王朝网络
分享
 
 
 

讲解如何让OGRE支持中文(二)

王朝other·作者佚名  2008-05-19
宽屏版  字体: |||超大  

0.还是前言

如果你希望能看懂这篇文章,请先确定你已经看到了《让OGRE支持中文》(http://www.gameres.com/Articles/Program/Visual/3D/OgreSupChn.htm),因为本文是在上一篇文章的基础上写的,并且假设文件都已经按照上一篇文章进行了手术。但是如果你只想简单的使用TTF字体,只要下载本文附带的文件,重新编译就可以了。

1.检讨

正如上回说的,我们已经实现了一个位图的字体。但是当冷静下来思考时,就能发现这种方法的诸多缺陷。读入一个2048*2048的位图,等于在显存中保存一个2048*2048的贴图,不说是否所有显卡都支持这么大的贴图,单是每个Font字体类吃显存的胃口,就足以令人心惊肉跳。如果定义足够多的字体类,我想你的游戏的配置要求,在某些方面足以超过《DOOM3》了。

而且这并不是唯一的缺陷,文字大小相对于位图大小比例相差太大,导致浮点数的文字位置误差很大,你可以在一个文字旁边看到其他文字的影子。(虽然可以通过增加文字间距来解决。)还有点阵字体本身的缺陷,就是字形单一,不适合放大缩小,一些文字边缘的马赛克,足以熄灭任何玩家的投入感。

似乎TTF是唯一的解决之道。

2.基本知识

(1)TTF字体。

TTF是一种矢量字库。我们经常可以听到矢量这个词,像是FLASH中的矢量图形,在100*100分辨率下制作的flash,就算它放大为全屏,显示出的画面也不会出现马赛克。所谓矢量,其实说白了就是用点和线来描述图形,这样,在图形需要放大的时候,只要把所有这个图形的点和线放大相应的倍数就可以了。而且,在网站上有很多的TTF字库可以下载,或者你可以去买一些专门的字库光盘。然后在你发行你精心制作的游戏时,可以顺便捎上这些后缀为。ttf的文件就行了。包括Quake这样的惊世之作,也都是用的TTF字库。

(2)FreeType2库

在http://www.freetype.org,有一个FreeType的免费库,而且是OpenSource的。它目前有2个版本:1.0和2.0.其区别在于,1.0只能读取TTF格式的,而2.0支持更多的文件格式,在使用它之前请详细阅读所要遵循的Licence,以下是摘自FreeType2.0对字库的支持列表:

TrueType fonts (and collections)

Type 1 fonts

CID-keyed Type 1 fonts

CFF fonts

OpenType fonts (both TrueType and CFF variants)

SFNT-based bitmap fonts

X11 PCF fonts

Windows FNT fonts

(3)“主体思想”

请参照炎龙工作室的《游戏中汉字显示的实现与技巧》这篇文章,可惜使用的是Windows API,作者千里马肝,上网上搜一下吧。

附带说一句,上面两条都是直接从这文章中剪切下来的,_<;

不要骂我啊,不知道算不算侵权呢。

3.动手术――比你想象的要麻烦

(1)

首先要告诉字体类,我们下一次渲染需要哪些字。以便字体类可以在需要的时候释放不使用的字体。

在Font类中~

a.增加数据 bool mUsing[OGRE_NUM_GLYPHS]; 用来标记文字是否使用。

b.增加函数

inline void setUsing(std::vector<;unsigned long& caption)

{

memset(this-mUsing,0,sizeof(this-mUsing));

std::vector<;unsigned long::iterator it;

for(it=caption.begin();it!=caption.end();++it)

{

if(OGRE_GLYPH_INDEX(*it)<;OGRE_NUM_GLYPHS)

this-mUsing[OGRE_GLYPH_INDEX(*it)]=1;//标记文字为使用

}

}

并在 void TextAreaGuiElement::updateGeometry() 中调用这个函数。

(2)

然后是修改void Font::createTextureFromFont(void);

Font类是通过void Font::createTextureFromFont(void)来把通过FreeType2分析好的英文字画在一个2^n*2^n的贴图上,然后再保存英文字的位置。

我们需要修改的是:

a.从函数中分离并保存画字的FreeType2和辅助变量。我们通过一个类来保存和处理这些变量。

class TTFMsg

{

class Max//类中类,用来保存几个"最大",

{

int nothing;//这个是用来占位的,没意义,反正没他就运行出错,可能和数据对齐有关吧。

public:

int height;//文字最大高度

int width;//最大宽度

int bear;//最大空隙?

};

public:

FT_Library ftLibrary;//FreeType2用

FT_Face face;//FreeType2接口?

uint char_spacer;//文字空隙

SDDataChunk ttfchunk;//数据块,用来保存ttf信息

FT_F26Dot6 ftSize;//FreeType2字体大小

std::pair<;uint,uint point;//在位图上画字的点

SDDataChunk imgchunk;//数据块,用来保存位图信息

bool dirty;//标记,看是否需要更新贴图

Max max;//几个最大

inline bool init(Font*

font) //这个是初始化函数在void Font::createTextureFromFont(void);中调用。

{

//以下都是初始化,大部分都是从void Font::createTextureFromFont(void);移植过来的

dirty=false;

if( FT_Init_FreeType( &ftLibrary ) )

Except( Exception::ERR_INTERNAL_ERROR, "Could not init FreeType library!",

"Font::Font");

char_spacer= 5;

FontManager::getSingleton()。_findResourceData(font-mSource,ttfchunk);

if( FT_New_Memory_Face( ftLibrary, ttfchunk.getPtr(), (FT_Long)ttfchunk.getSize() , 0, &face ) )

Except( Exception::ERR_INTERNAL_ERROR,

"Could not open font face!", "Font::createTextureFromFont" );

ftSize = (FT_F26Dot6)(font-mTtfSize * (1 <;<; 6));

if( FT_Set_Char_Size( face, ftSize, 0, font-mTtfResolution, 0 ) )

Except( Exception::ERR_INTERNAL_ERROR,

"Could not set char size!", "Font::createTextureFromFont" );

return true;

}

inline bool done()

{

//在Font的解构函数中调用的,本来应该调用下面两个函数,但是不知道为什么一调用就出错,不用倒没事。

//FT_Done_Face(face);

//FT_Done_FreeType(ftLibrary);

return true;

}

inline bool getRect(Image::Rect & rect)//这个函数以后用的,是用来找到可以画字的贴图的空的位置

{

if(511<;point.second+max.height+char_spacer)

{

rect.right=rect.top=rect.left=rect.bottom=-1;

return false;

}

if(511<;point.first+max.width+char_spacer)

{

point.second+=max.width+char_spacer;

point.first=0;

if(511<;point.second+max.height+char_spacer)

{

rect.right=rect.top=rect.left=rect.bottom=-1;

return false;

}

}

rect.left=point.first;

rect.top=point.second;

rect.bottom=max.height;

rect.right=max.width;

point.first+=max.width+char_spacer;

return true;

}

};

上面的类定义在Font类中,在Font中增加 TTFMsg * mTTFMsg 数据,并在构造函数中 mTTFMsg=new TTFMsg;

正是修改void Font::createTextureFromFont(void);函数,主要几点,首先是分离出很多变量和构造到TTFMsg类中了,然后是贴图从2^n*2^n变成固定的512*512,为什么要这个数字呢,因为256太小(废话了)。能保证512*512大小的文本区不会出现不够画字的情况(所有英文+符号+没有重复的汉字),这个安全区域基本上是够用的。(什么,你要画满屏幕的汉字?哪你自己看着改吧。)还有一个重要功能是,要找100个汉字,找出最高和最宽和最大空隙作参考。修改完成这个样子了~

void Font::createTextureFromFont(void)

{

mTTFMsg-init(this);//初始化FreeType2

uint i, l, m, n;

int j, k;

FILE *fo_def = stdout;//啥意思?我看不明白

int max_height = 0, max_width = 0, max_bear = 0;

uint startGlyph = 33;

uint endGlyph = 167;

// 找英文的找出最高和最宽和最大空

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有