幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 4224|回复: 3

[3D编程] [gameres文章]让OGRE支持中文

[复制链接]

330

主题

3719

帖子

5万

积分

⑧专业

霄月破苍穹

积分
58690
QQ
发表于 2006-7-30 11:37:37 | 显示全部楼层 |阅读模式
说明:这个是根据ogre-win32-v0-13-1基础上改的
--------------------
作者:免费打工仔
.准备工作
  “bug王”已经通过WINAPI实现了OGRE在Direct7.0下的中文支持,也有高手说这样效率不高,更因为本人基本上是不怎么熟悉WINAPI的,所以就放弃了这种方法。企图直接通过贴图来实现中文显示,毕竟OGRE本身文字输出也是用的这种办法,更好的是OGRE引擎除了普通的“ttf”字体外还支持位图字体(其实“ttf”在引擎中也被Ogre::Font::createTextureFromFont()转换成位图了),基本上就是做一个很大很大的图片,然后上面画满汉字,直接读进去就可以了,问题也就变成了——如何找这个大图片。
  幸好GBA游戏的开发者们已经找到了很好的文字来源和取得方法,通过金山的16*16点阵字库得到接近9000个字模,然后通过程序读出并写到2048*2048的单色位图上,转换成“png”格式图片才221k。

2.基本知识
  修改引擎之前,我们先要知道OGRE是如何显示字体的。OGRE本身面向对象的设计和自带文档都做得非常规范漂亮,很容易就能找到关于显示文字的类以及相关函数。在这里主要看一下关于位图字体是如何显示在画面上。

(1)字体的读取。
  和这项功能相关的有两个类,一个是Ogre::FontManager类,负责分析字体信息(*.fontdef)文件。然后用builder模式构建一个Ogre::Font类。在Font类中最重要的数据莫过于mTexCoords_u1、mTexCoords_u2、mTexCoords_v1、mTexCoords_v2这四个数组,他们分别用来储存不同文字对应在图片上的纹理坐标。 不过数组大小明显不够储存9000个汉字的,一会儿要改的。

(2)字体的显示。
  好像字体显示中用得较多的是Ogre::TextAreaGuiElement类,不过好像还有其他的,我们在这里只看这个吧,估计其他的也大同小异。看了看好像唯一和显示字体有关的函数就是void TextAreaGuiElement::updateGeometry()了,基本上就是根据要写到屏幕上的字串,在Ogre::Font类中得到相应的贴图坐标和贴图,然后画上去,道理也不是很难。

3.动手术
  目标锁定到Ogre::Font,Ogre::FontManager,Ogre::TextAreaGuiElement三个类中,把所有文件备份一遍手术开始!

(1) Ogre::Font类。
  首先是储存文字贴图坐标的数组的大小不够,原来定义的是——宽字符集 (1024 - 32)、ASCII(256 - 32)。这点点大小怎么够我近9000字大军进入,索性都改成(9030 - 32)。还有就是set和get文字贴图的id都是char类型数据,256个id也不够分配给汉字,看来要都改成unsigned long形(其实大部分机器上int也是32位,不过long是固定32位的类型,感觉统用点)。

(2) Ogre::FontManager类。
  里面从脚本文件中解析贴图坐标的方法是根据单字符的方式,为支持汉字,改成同时可以分析int的。一个汉字对应数字是他的区位码+161(前160个留给了半角字)。

(3) Ogre::TextAreaGuiElement类。
  这个是相对比较麻烦的,他要从字串中分辨出到半角字和中文。在这里增加一个std::vector<unsigned long> caption,用来储存分辨的结果。增加以下几行:

    std::vector<unsigned long> caption;
    unsigned char nTemp;
    String::iterator it=mCaption.begin();
    for(;it!=mCaption.end();++it)
    {
        if(unsigned char(*it)<=160)//如果是半角
        {
            caption.push_back((unsigned char)*it);
        }
        else//处理全角字符
        {
            nTemp=(unsigned char)(*it);
            ++it;
            if(it==mCaption.end())
                break;
            //下面是得到区位码+161的公式。
            caption.push_back((94*(nTemp-0xa0-1)+((unsigned char)(*it)-0xa0-1))+161);
        }
    }

然后后面所有关于mCaption的地方都用caption代替就ok了。

4.结果。
  在OpenGL和DX9.0中成功的支持了中文,但是DX7.0中竟然出现了运行错误,具体问题还不清楚,还望各位高手指教。
  因为字体本身原因,文字很扁平的不好看,索性又改了改Ogre::Font,Ogre::FontManager两个类,实现脚本中支持修改文字纵横比例的系数的proportion,当这个值设置为0.8的时候比较好看了。
------------------------------------------
相关文件
chinese.fontdef//字体信息文件 放在资源文件加中
    font.png//字体图片 放在资源文件加中

    OgreFont.cpp
    OgreFont.h
    OgreFontManager.cpp
    OgreTextAreaGuiElement.cpp
    //上面文件覆盖同名文件 就可以 先备份
噩梦刃化
回复

使用道具 举报

9

主题

1512

帖子

9136

积分

荣誉群

Cod3r

积分
9136

终身成就奖

发表于 2006-7-30 17:13:04 | 显示全部楼层
我想用這理論在Blitz3D上試看看...雖然很少實際用到中文。
(\\__/) (O.o ) (> < ) This is Bunny.
回复 支持 反对

使用道具 举报

330

主题

3719

帖子

5万

积分

⑧专业

霄月破苍穹

积分
58690
QQ
 楼主| 发表于 2006-8-1 22:32:05 | 显示全部楼层
OGRE1.2我家过敏......继续用1.0...
噩梦刃化
回复 支持 反对

使用道具 举报

18

主题

428

帖子

5260

积分

⑦老手

在美工荒中挣扎的全能

积分
5260
QQ
发表于 2006-8-2 13:12:18 | 显示全部楼层
Ogre1.3预备加入Unicode支持……

之后就不必用那么猥琐的方法了……
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2024-4-20 22:49 , Processed in 0.026002 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表