在OGRE中使用Cal3D

Kevin Lynx

2007-7-17

      要将Cal3D这个动画库结合进OGRE,最重要的就是关于渲染方面。Cal3D在渲染时,提供了顶点信息给外部世界,然后外部世界根据具体的渲染API来渲染这些顶点。要在OGRE中使用Cal3D,就需要在OGRE中直接渲染顶点。

       首先我看到的是OGRE支持Hardware Buffer,似乎可以直接填充顶点进去。但是其使用似乎有点复杂。(1st way)后来又看到ManualObject这个类,该类创建对象时支持直接填充顶点信息,估计也可以实现这里的要求。(2nd way)

       ManualObject创建的对象可以直接attach到一个SceneNode上。

 

       看了Cal3D的例子,渲染时大致就是填充顶点信息,设置材质material和纹理texture。接下来我需要去了解D3D中顶点填充渲染方面的信息。

 

       ManualObject最基本的使用方法,如下代码所示:

ManualObject* manual = mSceneMgr->createManualObject("manual");

manual->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);

 

manual->position(-100.0, -100.0, 0.0);

manual->position( 100.0, -100.0, 0.0);

manual->position( 100.0,  100.0, 0.0);

manual->position(-100.0,  100.0, 0.0);

 

manual->index(0);

manual->index(1);

manual->index(2);

manual->index(3);

manual->index(0);

 

manual->end();

mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(manual);

 

       begin的第二个参数表示顶点的类型(可以参看D3D),OT_LINE_STRIP表示线带,罗列顶点时,前两个顶点构成一条线,然后第二个顶点又和第三个顶点构成一条线(所以是线带)。同理,OT_LINE_LIST即为线的列表,需要罗列每一条线的两个顶点。这里的类型决定了OGRE如何处理顶点数据,如果是线表,则每两个顶点构成一条线;如果是三角形表,则每三个点构成一个三角形。规则同D3D里一样。

       position则是放置顶点数据。根据文档,在设置每个顶点数据时,需要在position后马上设置该点的属性。

       index确定索引,一旦使用该函数,则表示该处将使用索引顶点的方式。当不使用该函数时,默认情况是直接使用顶点来渲染的。If you don't do this, the class will assume you want triangles drawn directly as defined by the vertex list, ie non-indexed geometry.

       顶点定义的顺序是按照逆时钟方向来定义的。

 

       ManualObject指定一种材质,包括纹理:

MaterialPtr myManualObjectMaterial = MaterialManager::getSingleton().create("manual1Material","General");

myManualObjectMaterial->setReceiveShadows(false);

myManualObjectMaterial->getTechnique(0)->setLightingEnabled(true);

myManualObjectMaterial->getTechnique(0)->getPass(0)->setDiffuse(1,1,1,1);

myManualObjectMaterial->getTechnique(0)->getPass(0)->setAmbient(1,1,1);

//myManualObjectMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1,1,1);

myManualObjectMaterial->getTechnique(0)->getPass(0)->createTextureUnitState( "1.jpg" );

       因为该材质名为manual1Material,在ManualObject::begin时,指定该材质名即可。要指定一个纹理,只需要加上最后一句:createTextureUnitState。然后在ManualObject设置顶点数据时设置好纹理坐标即可。

       注意,纹理图片将会根据该材质资源所在组来寻找。例如以上资源组为General

 

       到目前为止,基本上掌握了把Cal3D结合进OGRE的信息,接下来准备稍微了解下Cal3D的信息。然后写写实验代码。

 

2007-7-18

       动态改变ManulaObject的顶点数据,只需要保存该object的引用以及其使用的材质的引用。然后动态改变材质属性,以及顶点数据即可。

       注意,默认情况下,调用ManualObject::begin不会把之前的顶点数据擦出,而是继续添加新的顶点数据进去。(看到帧数越来越低,屏幕上的多边形越来越多就知道了)要清除之前的顶点数据,可以调用ManualObject::clear

 

       现在可以动态改变一个ManualObject的顶点数据了,那么就可以开始把Cal3D用进来了。(目前已成功)

       整个过程的大致原理,就是根据Cal3D而得到模型动画本身的顶点数据(构成三角形列),以及材质信息。然后用ManualObject来渲染顶点数据,而用Material来反应材质信息。这些材质信息被设置后,再结合进ManualObject,从而达到最终的渲染目的。Cal3d本身对于渲染的要求也就是这些。(可以参看Cal3D的一些例子)

       首先提一下Cal3D整个的使用过程,包括从初始化,渲染,到销毁。

       首先是初始化,Cal3D为每一个模型建立一个Core Model,以及很多Model InstanceCore Model用于保存共享数据,而Model Instance则是各个模型实例特有的数据。这主要用于,用一种模型在程序中创建多个模型实例。(例如有多个相同样子的怪物),初始化过程大致如下:

1.  建立CalCoreModel对象。(在Cal3D 0.10.0 中不需要调用create

2.  装载骨骼资源csf文件,此步骤必须在以下步骤之前,装载其他数据(动画,材质)则不讲究顺序。

3.  装载动画文件caf,装载mesh文件cmf,装载material文件crf

4.  其他一些非必须步骤,虽然这些步骤不是必须的,但是通常情况下为了让material正常,都需要做。首先需要装载纹理,OGRE中将直接根据文件名(来自于material里)来创建TextureUnitState对象并放进OGREmaterial里。这样创建后,该纹理就会一直在该material里,在后面的渲染过程中,除非要改变该纹理,否则根本不需要再去管纹理部分。(对于有些开发包,需要临时设置材质,那么就需要临时地设置TextureUnitState对象,该对象在装载纹理时被创建,然后把其引用保存进Cal3D里,这通过调用setMapUserData实现)

 

在该一步,比较值得注意的是,需要创建material thread(目前我还不了解这个的具体意义),这关系到后面渲染时是否可以得到正确的材质颜色信息。

5.  创建model instance。也就是创建CalModel之类的对象。

6.  把所有的mesh attach到上一步创建的model

7.  可选步骤,但是为了实现后面渲染时正确地读取材质信息,还是必须的。只有一句代码:mCalModel->setMaterialSet( 0 );

8.  设置初始动画状态。Cal3D有两种动画:Action, Circle。也就是只播放一次和循环播放。Cal3D通过一个整数ID值来标识一种动画状态(例如跑)。

 

对于circle动画,则调用mCalModel->getMixer()->blendCycle;对于action动画,则调用mCalModel->getMixer()->executeAction。无论调用哪个函数,都将激活该动画状态。被激活的动画状态会在调用mCalModel->update时被自动更新。渲染动画时,也是渲染的这个激活状态。(目前对于那两个函数的具体参数还不是很明白)

 

9.  游戏循环中更新动画就调用CalModel::update

10.  渲染。渲染时由CalRenderer获得各个mesh以及其submesh,然后逐个获取材质颜色(ambient, diffuse, specular等),由这些信息更新ManuablObject使用的Material;然后逐个获取顶点,发现,纹理坐标,以及索引顶点,由这些信息更新ManualObject的顶点信息。

 

 

大部分情况下,得到的mesh数量都是1,且其sub mesh数量也是1。在填充ManualObject的顶点数据时,必须先把所有顶点放置完了,再处理索引信息。索引信息必须以 0-1-2 的顺序放入,否则位置会不正确:

for( size_t i = 0; i < indexCount; ++ i )

          {

              /// 必须是这样的顺序:0->1->2,否则不正确

              mManualCal->index( meshFaces[i][0] );

              mManualCal->index( meshFaces[i][1] );

              mManualCal->index( meshFaces[i][2] );

     }

 

其他实验事项:

1.  CalMixer::clearCycle会在指定时间内停止指定的动画。第一个参数指定动画ID,第二个参数指定时间。当调用该函数后,动画会在指定时间间隔内停止(动画速度不变)

2.  CalCoreAnimation::getDuration返回的是该动画所持续的时间,该时间被记录在动画文件中,Cal3D会自动读取其值。完全可以根据这个时间来转换动画状态。

3.  对于action动画,当其结束时会自动回复到该动画初始状态。

4.  对于executeAction以及blendCycle,包括clearCycle的一些参数,经过一些组合可以实现不同动画状态间的平滑过渡。例如:

mCalModel->getMixer()->executeAction( 1, 1, 0 );

     mCalModel->getMixer()->clearCycle( 2, 2.0f );

 

 

 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值