IrrLicht引擎研究
鬼火引擎研究
posts - 22,  comments - 38,  trackbacks - 0

http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=7494&highlight=crash+course

posted @ 2008-05-06 11:00 安徽飞雪游戏工作室 阅读(412) | 评论 (0)编辑
1 使用工具将文件转为字节数组,这里用[bin2h.exe]
    比如准备个文件 testpng.png
    使用命令
        bin2h testpng.png
    将生成 testpng.h,内容如下
        unsigned int testpng_size=<size>;
        unsigned char testpng[]={...};
2 将文件加入到工程中
    使用如下代码获取ITextrue接口,env为IGUIEnvironment
    //包含文件
    #include "testpng.h"
    ....
    //获得文件系统
     IFileSystem * pFS = env->getFileSystem();
    //创建读文件接口,这里特别注意第3个参数,其后缀一定要和文件格式一致,如果用的是bmp,则应该是testpng.bmp
     IReadFile * pMFR = pFS->createMemoryReadFile(testpng,testpng_size,"testpng.png",false);
    //获取Texture
     ITexture * pTxtPng = driver->getTexture(pMFR);
3 使用pTxtPng

posted @ 2008-01-13 15:26 安徽飞雪游戏工作室 阅读(288) | 评论 (0)编辑
在工作室制作一个动作类休闲游戏的过程中经过比较选择了ms3d做为动画模型.这样我们就需要把美工制作的max文件转化为ms3d格式.下面是我们采用的方法.(基本引用燕尘的ogre模型导出的文章)

(1) 使用ActorX插件,将角色动画从 3dsmax 完整导出PSA,PSK文件;
(2) 使用 MilkShape 3D ,读入上一步导出的动画,转化为ms3d。


下面介绍一下详细步骤。


0. 使用的工具:

(1) 3dsmax 4, 5, 6, 7
主要是因为下面的 Unreal ActorX 插件的强大,拥有对应 3dsmax 4, 5, 6, 7 各个版本的全部输出插件,所以在这里, 3dsmax 的版本不是问题。
我用的是 3dsmax 6

(2) Unreal ActorX for 3dsmax plugin
(2-1) 插件下载
你可以去 UND (Unreal Developer Network) 下载对应你的 3dsmax 版本的 ActorX 插件。下载页面在这里:
http://udn.epicgames.com/Two/ActorX
这里还有 for Maya 4, 4.5, 5, 6 的 ActorX 插件。总之不管你使用 3dsmax 还是 Maya ,也不管你使用的是什么版本,这个插件的强大性可以保证你能够顺利输出,同时保证输出后的模型和动画文件遵守相同的规范,确保它们可以被 MilkShape 3D 顺利读取和最终输出。
(2-2) 插件安装
解压缩 ActorX_216_Max6.zip ,把里面的 ActorX.dlu 复制到 3dsmax 的 plugins 文件夹,例如 C:\3dsmax6\plugins
(2-3) 使用方法
插件的使用方法可以简单阅读一下这一页:
http://udn.epicgames.com/Two/ActorXMaxTutorial

(3) MilkShape 3D 1.7.0 或 1.7.1
这是一个共享软件,未经注册无法输出,考虑到燕尘小筑的国际影响,坚决不在这里放出注册机或注册码,诸君可以自己寻找各种适用版本。它的官方网站在这里:
http://www.milkshape3d.com



OK. 下面开始正式输出。

1. 第一步,使用 Unreal ActorX 插件,从 3dsmax 中输出角色模型 *.PSK 和骨骼动画 *.PSA 。

(1) 使用 3dsmax 打开原始角色动画文件 *.max 。

(2) 然后,你必须遵守一些必要的约束,对这个原始角色动画文件进行一些必要的预加工:
(2-1) 一次只能输出一个角色模型。如果你希望一次输出多个物体,比方说,你希望同时输出角色本身和角色手中拿着的武器,你需要先把角色本身转化为 Editable Mesh ,然后使用 Attach 功能将武器绑定为角色的子物体 (Sub Mesh) 。
(2-2) 角色的骨骼只能有一个根节点。如果需要输出的角色骨骼拥有多个根节点,你需要为它们新建一个共同的根节点。
(2-3) 最后是最重要的一点,忽略了这一点将会导致你输出的模型的法线和纹理产生严重的异常。你必须给你的模型的材质赋予一个“合法的”名字。这一条,是 Unreal ActorX 输出插件的一个严格规定,它要求所有的材质都必须带一个形如 “_Skin00” 、"_Skin01"、 "_Skin02" 这样的后缀。
例如,如果你的模型带有两个材质,原来的名字分别是 "MBody" 和 "MFace" ,那么,你需要把这两个材质分别改名为 "MBody_Skin00" 和 "MBody_Skin01" 。
更改材质的名字可以使用 Material Editor :

attachments/month_0411/jg9m_snap0138.jpg



(3) 然后,首先输出角色的静态模型,输出为 *.PSK 文件。这个模型文件中,包含了角色的皮肤和骨骼信息。

(3-1) 首先要打开 ActorX 工具箱。
(3-1-1) 到 3dsmax 右栏,点击小锤子图标切换到 Utilities 面板,点击 [More...] :

attachments/month_0411/1xp4_snap0139.jpg


(3-1-2) 在弹出的 Utilities 窗口中,双击 "ActorX" :

attachments/month_0411/52t9_snap0140.jpg


(3-2) 在 ActorX 面板中,点击 output folder (输出文件夹) 一栏旁边的 Browse 按钮选择模型文件的保存目录,这同时也是稍后输出动作文件的保存目录;然后在 mesh file name (模型文件名) 一栏中给你要输出的模型文件取个名字。

attachments/month_0411/41s8_snap0143.jpg


(3-3) 然后点击 Save mesh/refpose (保存模型/参考姿势) 按钮来保存角色模型。在保存过程中会相继弹出下面两个对话框:

attachments/month_0411/liao_snap0146.jpg


attachments/month_0411/63u9_snap0147.jpg


(3-4) 如果弹出错误信息,你需要根据错误提示做一些相应的纠正。很多情况下,可能是你的输出选项没有设置好,需要在 ActorX - Setup 面板中修改一些相应的选项:

attachments/month_0411/fc5i_snap0148.jpg


每一个具体选项不再具体讲解,详细请参考这一页的下半部:
http://udn.epicgames.com/Two/ActorXMaxTutorial

(3-5) 输出的模型文件为 *.PSK 。


(4) 最后就是骨骼动画文件 *.PSA 的输出。这个功能相当强大。

(4-1) 首先, ActorX - Epic Games 面板的上部是模型输出模块,下部就是骨骼动画输出模块。
(4-1-1) 在 animation file name (动画文件名) 一栏中,给你要输出的动作文件起个名字;
(4-1-2) 在 animation sequence name (动画序列名) 一栏中,给你要输出的这段动作起一个动作名,例如 dance 、 walk 、 run 、 attack 等等;
(4-1-3) 在 animation range (动画范围) 一栏中,给你要输出的这段动画序列指定一个输出的帧的范围,格式是 "开始帧-结束帧";
整个设置如下图:

attachments/month_0411/olds_snap0151.jpg


(4-2) 然后首先我们要做的,是动画的采集 (Digest Animation) 。点击 [Digest animation] 按钮,看状态栏的进度条走完,就完成了动画的采集,但是这时候,仅仅是完成了这个动作序列的动画的数据取样,并没有把它保存起来,所以还需要进行下一步,就是动画的管理。

(4-3) 点击 [Animation manager] 按钮,打开 AcoorX animation manager (动画管理器) 面板:

attachments/month_0411/52u9_snap0152.jpg


(4-3-1) 在这个面板的左栏,我们会看到已经有了一个动画序列,名字是 "dance" ,我们可以使用中间的 move [-->] 、 [<--] 按钮,把这个动画序列移动到右边的 Output Package 一栏,也就是准备输出这个动作;

(4-3-2) 然后点击右边的 [Save] 按钮,骨骼动画序列就会被保存到指定的动作文件中:

attachments/month_0411/rogv_snap0153.jpg


保存成功后会弹出如下对话框:

attachments/month_0411/52t8_snap0154.jpg


(4-4) 就这样,动作文件被保存为 *.PSA 。

(4-5) 这个Animation manager 的动画管理功能十分强大,你可以做的不仅仅是保存单个动画序列,你还可以分别采集 (Digest) 多个动画序列然后把它们保存为一个动作文件,你还可以使用 [Load] 或 [Load As..] 按钮来读取一个现有的动作文件,对其添加或删除动作序列,然后再使用 [Save] 或 [Save As..] 按钮来保存修改过的动作文件。总之,这个动画管理器很强大,多多学习。


2. 使用 MilkShape 3D ,读取上一步生成的 *.PSK 和 *.PSA 文件,然后整合输出到 OGRE 。

(1) 打开 MilkShape 3D 。

(2) 使用菜单 [File] - [Import] - [Unreal/UT PSK/PSA ..] ,首先输入模型文件 *.PSK ,然后输入动作文件 *.PSA

attachments/month_0411/da3h_snap0158.jpg


(3) 你可能发现两处毛病:首先,骨骼可能错位了;其次,没有纹理贴图。这两个问题都不难解决:
(3-1) 首先你必须详细阅读 MilkShape 3D 的 Help ,学会各种简单操作;
(3-2) 纹理贴图的问题,在 Materials 面板点击这个按钮就可以选择贴图:

attachments/month_0411/b91f_snap0159.jpg


(3-3) 骨骼错位的问题,配合三视图,利用 Model 面板,首先使用 [Select] 按钮选择全部顶点,然后使用 [Move] 和 [Rotate] 工具来使角色的皮肤对齐角色的骨骼。
注意一!不要动骨骼;
注意二!在对齐时,必须确保下方的 Animation 栏处于未激活状态,也就是 [Anim] 按钮未被按下,一排动画播放键处于失效状态。
等一切搞定后再点击 [Anim] 按钮播放动画。

attachments/month_0411/fc5i_snap0161.jpg


(3-4) 调好的模型和骨骼:

attachments/month_0411/52t9_snap0165.jpg



(4) 现在就该输出了。

FILE->SAVE就可以保存为ms3d模型了.在irrlicht几乎支持所有常见的动画格式.ms3d支持的是比较好的.1.0版本有些问题,不过后来的版本更正了.希望irrlicht的明天会更好.也希望有更多的人来使用研究这个引擎.





posted @ 2007-06-01 22:24 安徽飞雪游戏工作室 阅读(2475) | 评论 (4)编辑

irrlicht1.3的中文支持补丁,需要的朋友可以下载,如何使用里面有说明./Files/flysnow/IrrlichtML-1.3-win32Linux.zip

posted @ 2007-06-01 21:44 安徽飞雪游戏工作室 阅读(990) | 评论 (5)编辑

Audiere: http://audiere.sourceforge.net/
     Platform: Windows, *nix
     Cost: Free (LGPL) ------ freely use Audiere in commercial products
  Support file format:  Ogg Vorbis, MP3, FLAC, uncompressed WAV, AIFF, MOD, S3M, XM, and IT files.  不支持MIDI
  features:
     Braindead easy API
    Supported file formats: Uncompressed WAV*, Uncompressed AIFF*, Ogg Vorbis*, FLAC*, MP3, MOD, S3M, IT, XM (* supports seeking)
    Streaming and buffered audio
    Volume, pan, and pitch shift modification
    Flat tone, square wave, white noise, and pink noise generation
    Runtime enumeration of audio devices and supported file formats
    Custom file streams
    Python, Delphi, Java, XPCOM (JavaScript in Mozilla) bindings
    
 Support 2D/3D:  2D, 不支持3D音效
 Link:  http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=1422
   http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?p=8853#8853
   http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=627&highlight=openal
   http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=6106&highlight=openal
   http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=7646&highlight=openal
   http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=8048&highlight=openal   
Comment:
 1. 3d sound made using audihere!!  http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=7549&highlight=openal    


OpenAL: http://www.openal.org
     Platform: Windows, Mac, Linux, BSD, Solaris, IRIX, PS2, XBox, GameCube
     Cost: Free (LGPL).
     Support file format: Ogg , wav
    
   Support 2D/3D:  3D(hardware supported) and SoundBlaster Live 5.1 compatible

Link:  http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=2891&highlight=sound
  http://www.devmaster.net/articles.php?catID=6
  http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=10267&highlight=openal
  3d stereo sound  http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=7335&highlight=openal
Comment:

1. The main reason why it doesn't work is to use stereo waves !!!
Stereo waves will cause OpenAl to play the sound as background music (like Audiere) !!!
If you use a mono wave it works: the nearer the player to the sounds position, the louder the sound is played. If the player left or right of the sound, the sound will played on left/right speaker...

2. 一般使用OpenAL..音效部分就是用wav格式, 背景音樂部份就是用ogg..

posted @ 2006-08-21 20:46 安徽飞雪游戏工作室 阅读(568) | 评论 (0)编辑

测试过irrlicht中ms3d模型的朋友可能发现了这样的现象,如果ms3d模型只有一个贴图,则无论贴图文件放到和demo可执行程序同一目录下或者调用setMaterialTexture()函数都可以让模型正常被正常渲染,而当模型拥有两个或以上贴图时,则只有贴图和可执行程序在同一目录被自动加载时才能正确渲染,而用setMaterialTexture(0,。。。),setMaterialTexture(1,。。。)时似乎只有第一个贴图起作用。仔细查看引擎的代码发现,这不是偶然的现象,也可以算是引擎对ms3d模型支持的一个bug吧。在说到具体的解决方案之前,我们先来说一下ms3d模型中组的概念。“组”顾名思义应该是拥有一些共同属性的事物集合了。在ms3d中,一个组内的三角形就拥有同一个贴图文件。在引擎装载ms3d模型数据时,已经记下了组对应的贴图文件名,因此自动贴图不会出错。而在用setMaterialTexture函数指定时却并没有指定是哪个组的贴图,因此就会出现只有一个贴图起效果的现像,其实从代码中可以看出,它是遍历了所有组,但都用了setMaterialTexture(0,...)指定的这一个贴图。
好了,知道原因后,我们大概就可以想到解决办法了。就是在setMaterialTexture时也指定是哪个组。对就是这样。我们提供了另外两个针对MS3D的setMaterialTexture函数,分别是:
void  CAnimatedMeshSceneNode::setMS3DMaterialTexture(const c8 * groupName,s32 textureLayer, video::ITexture* texture)
{
  if (textureLayer<0 || textureLayer>= video::MATERIAL_MAX_TEXTURES)
    return;

  // 根据组名得到MeshBuffer
  IMesh * pMesh = Mesh->getMesh(0,0);
  
  for(s32 i = 0; i<pMesh->getMeshBufferCount();i++)
  {
   IMeshBuffer* pMeshBuf = pMesh->getMeshBuffer(i);
   if(strcmp(pMeshBuf->getGroupName(),groupName) == 0){
    irr::video::SMaterial & mat = pMeshBuf->getMaterial();
    mat.Textures[textureLayer] = texture;
    Materials[i].Texture1 = texture;
    break;
   }
  }

}
void  CAnimatedMeshSceneNode::setMS3DMaterialTexture(s32 groupIndex,s32 textureLayer, video::ITexture* texture)
{
  if (textureLayer<0 || textureLayer>= video::MATERIAL_MAX_TEXTURES)
    return;
  
 
  // 根据组名得到MeshBuffer
  IMesh * pMesh = Mesh->getMesh(0,0);
  
  if(groupIndex < 0 || groupIndex > pMesh->getMeshBufferCount())
   return;

  
  IMeshBuffer* pMeshBuf = pMesh->getMeshBuffer(groupIndex);
  // yfxu
  irr::video::SMaterial & mat = pMeshBuf->getMaterial();
  mat.Textures[textureLayer] = texture;
  if(textureLayer == 0) mat.Texture1 = texture; 
  Materials[groupIndex].Texture1 = texture;

}
一个是根据组名设贴图,一个是根据组索引设贴图。
值得一起的是 引擎在载如ms3d模型数据在取组名时也有一点问题,原来的代码如下:
for (i=0; i<numGroups; ++i)
 {
  Groups.push_back(SGroup());
  SGroup& grp = Groups.getLast();
  // 组名称
  grp.Name = (const c8*)pPt;
。。。

参考ms3d的文件格式可知改为:
 grp.Name = (const c8*)(pPt+1);
才能正确取到组名。
到此为止,加上动画模型旋转bug,和无效帧问题的解决。irrlicht对ms3d模型的支持基本就完美了。

下图中的美女,身体和头发是分开的贴图:


posted @ 2006-07-28 13:25 安徽飞雪游戏工作室 阅读(561) | 评论 (1)编辑
这是Irrlicht SDK中给的一个例子,用来演示如何在Irricht中冲突检测与响应,其它的例子还有十三个,俺会陆续翻译出来。自己英语水平很洼,但对翻译又有点瘾,所以就帖到这里来,有译错或表达不好的地方请指正。

 

 例7,碰撞检测与响应
  这一节,我将演示如何在Irrlicht引擎里进行碰撞检测。有三种方法:自动的碰撞检测,例如上下楼梯时移动全局坐标;手工拾取三角形和场景结点。
  演示程序效果图:

  开始吧!
  简单起见,我们拿那个加载并显示Quake3地图的例2开刀:在里面四处走动并从中拾取三角形。另外,为了说明场景结点的拾取我们再放三个精灵在里面。下面的代码启动引擎并加载Quake3地图。不再多加解释(详情参见例2)。

#include <irrlicht.h>
#include <iostream>
using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

int main()
{
  // let user select driver type
  video::E_DRIVER_TYPE driverType;  printf("Please select the driver you want for this example:\n"\    " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\    " (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\    " (f) NullDevice\n (otherKey) exit\n\n");  char i;  std::cin >> i;  switch(i)  {  case 'a': driverType = video::EDT_DIRECT3D9;break;  case 'b': driverType = video::EDT_DIRECT3D8;break;  case 'c': driverType = video::EDT_OPENGL;   break;  case 'd': driverType = video::EDT_SOFTWARE; break;  case 'e': driverType = video::EDT_SOFTWARE2;break;    case 'f': driverType = video::EDT_NULL;     break;  default: return 0;  }
  // create device
  IrrlichtDevice *device = createDevice(driverType,
     core::dimension2d<s32>(640, 480), 16, false);
  if (device == 0)    return 1; // could not create selected driver.  video::IVideoDriver* driver = device->getVideoDriver();  scene::ISceneManager* smgr = device->getSceneManager();  device->getFileSystem()->addZipFileArchive      ("../../media/map-20kdm2.pk3");


scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* q3node = 0;

if (q3levelmesh)
q3node = smgr->addOctTreeSceneNode(q3levelmesh->getMesh(0));

 
  到此为止,我们已经像例2那样加载了Quake3地图。接下来的情况有所不同:我们创建了一个三角形的选择器。这是一个类,你可以用它来从场景结点中拾取三角形,以用作各种不同的用途,比如碰撞检测。引擎里有几种三角选择器,它们都可以用ISceneManager来创建。在这个例子中我们创建OctTreeTriangleSelector,你可以照字面意思理解,是的,这是个树状的选择器,“树”就是数据结构里面的树,我们以此来对三角形数目的输出做些优化。这样对像Quake3之类大的地图是很有用的。
  创建完三角形选择器就把它“系”到场景结点上去,此处是q3node。并不是必需这么做,这是“懒汉”式做法,不用再考虑选择器了,比如到底什么时候用不着了才好释放它。
  Code..................................
  还是像例2,为了能在Quake3地图里面移动,我们添加一个FPS(First Person Shooter第一人称射击游戏)相机。但这一次,还要给相机加个特殊的animator:带冲突响应的animator(注3)。它会调整与自己关联的场景结点,使它看起来受重力影响并且不会穿墙而过。对于animator,我们要做的唯一的事情就是告诉它世界是个什么样子,场景结点有多大,重力有多大等等。把带冲突响应的animator加到相机上后,就不必再做任何关于碰撞检测的事――一切都是自动的!。下面有关碰撞检测的代码是是用来拾取的。还有一个令人高兴的、很酷的特性:可以把带冲突响应的animator的事附加到任何场景结点上,不只是相机。另外,它也可以与别的场景结点animator混合使用。如此以来,在Irrlicht引擎中使用冲突检测与响应就非常、非常地简单。
  好了,来看一下createCollisionResponseAnimator() 的参数。第一个参数是TriangleSelector,指明碰撞检测完成后世界看起来是个什么样子。 第二个参数是场景结点,指定受碰撞检测影响的对象,在我们的例子中就是相机。第三个定义对象的大小,即椭球半径。试一试:把半径改小后是不是能够靠墙更近呢?下一个参数是重力的大小和方向。你可以将方向设为(0,0,0)以消除重力。最后一个仅用于转换:否则的话,计算好碰撞检测的椭球会包住相机,而相机位于椭球的中央。但是从人的角度,我们习惯于“眼睛在身体的上方”,而眼睛在身体中间是同我们的现实世界相抵触的。所以我们用这个参数把场景结点从椭球中央上移50个单位。好,现在碰撞检测可以起作用了。
  Code………………………….
  因为在Irrlicht里碰撞检测并不是很大的一块(引擎要做的事多着呢,译注)。下一节我将描述如何使用两种不同类型的拾取。但在这之前我会为场景稍作准备。需要三个用来拾取的角色:精灵,一个动态光源以照亮它们,一个用来指出交叉点的白板,还有,噢,我得把光标去掉。 :)
  Code………………………..
  为了不致太复杂,我会在渲染循环里进行拾取。我们先定义两个指针用来保存当前和最后一个场景结点,然后进入循环。
  Code…………………
  用smgr->drawAll()绘制完全部场景后,开始第一次拾取:我们想知道自己正瞧着整个世界坐标中的哪个三角形。另外,准确一些,还想知道这是在Quake3地图中的哪个点。为此我们创建一个三维的射线:从相机位置开始,穿过目标点。
  然后向碰撞管理器询问:这条射线是否同存储在三角选择器里的三角形发生碰撞?如果是,我们画一个三维的三角形并把白板位置设在交叉点上。
  Code……………….
  Irrlicht引擎支持的另一种拾取方法是基于包围盒的节点拾取。每个场景结点已有一个包围盒包着,正因如此,拾取速度非常快,例如在拾取相机看到的场景结点时。再说明一次,我们是向碰撞管理器询问得到这个结果的,如果得到了一个场景结点,就通过取消它材质的光照特性而加亮它,当然,如果它不是白板或Quake3地图的话。
  Code……………….
  就这些,下面要做的只是完成绘制。
  Code…………………
  ――――――――End―――Of―――File ―――――――――
注:
  1.虽然是科技文,但为了便于理解采用意译。
  2.原文见:Irrlicht手册

posted @ 2006-07-28 09:48 安徽飞雪游戏工作室 阅读(593) | 评论 (1)编辑

试验过在IrrLicht中导入播放骨骼动画模型的朋友可能会发现,引擎存在下列问题:一, 当一次循环结束时会产生无效帧,在原模型不远的位置出现一片不规则的图片,严重影响显示效果。二,当模型包含旋转动作时发现模型在旋转过程中方向会突然反向,猜想也是计算错误。针对这两个问题,可以采用如下解决办法。
针对出现无效帧的问题,代码做如下修改:
在类SMS3DMeshBuffer的loadFile方法中(请对照原代码)
 // 获得旋转的关键帧
  //>>rxue add
  s32 j;
  SKeyframe k;
  MS3DKeyframe* eka = NULL; // this contains data of first keyframe
  f32 first = 0; // this is time of first keyframe
  //<<rxue add end

  for (j=0; j<pJoint->NumRotationKeyframes; ++j)
  {
   MS3DKeyframe* kf = (MS3DKeyframe*)pPtr;
   pPtr += sizeof(MS3DKeyframe);
   //>>rxue add
   if(j==0)
   {
    eka = kf;
    first = kf->Time;
   }
   k.timeindex = (kf->Time-first) * 1000.0f;
   //<<rxue add end
   k.data.X = kf->Parameter[0];
   k.data.Y = kf->Parameter[1];
   k.data.Z = kf->Parameter[2];
   jnt.RotationKeys.push_back(k);
  }
  //>>rxue add
  totalTime -= first;
  if(eka)
  {
   k.timeindex = totalTime;
   k.data.X = eka->Parameter[0];
   k.data.Y = eka->Parameter[1];
   k.data.Z = eka->Parameter[2];
   jnt.RotationKeys.push_back(k);
  }
  eka = NULL;
  //<<rxue add end


  // 获得变换的关键帧
  first = 0; //rxue add
  for (j=0; j<pJoint->NumTranslationKeyframes; ++j)
  {
   MS3DKeyframe* kf = (MS3DKeyframe*)pPtr;
   pPtr += sizeof(MS3DKeyframe);
   
   //>>rxue add
   if(j==0)
   {
    eka = kf;
    first = kf->Time;
   }
   
   k.timeindex = (kf->Time-first) * 1000.0f;
   //<<rxue add end   
   k.data.X = kf->Parameter[0];
   k.data.Y = kf->Parameter[1];
   k.data.Z = kf->Parameter[2];
   jnt.TranslationKeys.push_back(k);
  }
  //>> rxue add Let's add one keyframe to the end
  if(eka)
  {
   k.timeindex = totalTime;
   k.data.X = eka->Parameter[0];
   k.data.Y = eka->Parameter[1];
   k.data.Z = eka->Parameter[2];
   jnt.TranslationKeys.push_back(k);
  }
  //<<rxue add end
旋转反向的问题:
修改SMS3DMeshBuffer类的getKeyframeData方法如下:(注意:s32type为增加的参数,所以函数声明也要做相应修改
void CAnimatedMeshMS3D::getKeyframeData(core::array<SKeyframe>& keys, f32 time, core::vector3df& outdata,s32 type)
{
 if(type == 0)
 {
  for (s32 i=0; i<(s32)keys.size()-1; ++i)
  {
   if (keys[i].timeindex <= time && keys[i+1].timeindex >= time)
   {    
    f32 interpolate = (time - keys[i].timeindex)/(keys[i+1].timeindex - keys[i].timeindex);    
    outdata = keys[i].data + ((keys[i+1].data - keys[i].data) * interpolate);   
    return;
   }
  }
 }
 else
 {
  for (s32 i=0; i<(s32)keys.size()-1; ++i)
  {
   if (keys[i].timeindex <= time && keys[i+1].timeindex >= time)
   {
    irr::core::quaternion q1(keys[i].data.X,keys[i].data.Y,keys[i].data.Z);
    irr::core::quaternion q2(keys[i+1].data.X,keys[i+1].data.Y,keys[i+1].data.Z);     
    f32 interpolate = (time - keys[i].timeindex)/(keys[i+1].timeindex - keys[i].timeindex);
    q2 = q1.slerp(q1,q2,interpolate);
    q2.toEuler(outdata);
    return;
   }
  }
 }
}

SMS3DMeshBuffer类animate方法修改如下:
//find keyframe translation and roation
//getKeyframeData(Joints[i].TranslationKeys, time, translation);
//getKeyframeData(Joints[i].RotationKeys, time, rotation);
  
  getKeyframeData(Joints[i].TranslationKeys, time, translation,0);//rxue
  getKeyframeData(Joints[i].RotationKeys, time, rotation,1);//rxue 重新计算
至此,解决了模型动画的播放问题。在我们这里测试正常,有问题的朋友可以留言讨论。

posted @ 2006-07-28 09:23 安徽飞雪游戏工作室 阅读(789) | 评论 (0)编辑
MS3D model 的Frame count
通常在载入ms3d动画序列后, 无法播放动画或动得极缓慢,调用IAnimatedMesh::getFrameCount()取得的FrameCount也比MilkShape里的FrameCount大很多, 这是为什么呢? 请看"niko"的原话:The reason why the frame number is multiplied is because using only 300 frames, your animation would not be smooth at all. By multiplying the frame number with (for example here 40), it is getting smoother. By the factor 40, in this case. I should add a comment on this in the documentation.
 
 
float fFactor = getFrameCount()/effective number of frames of your animation;
所以在setFrameLoop时必须在1*fFactor~RealFrameCounts*fFactor之间, 要不然就有各种怪异的现象.
e.g.
If get total numbers of frames with getFrameCount (ex : 12000)
divide the getFrameCount by the effective number of frames of your animation (ex : 12000/300 = 40)
multiply this factor (40) by the number of the frame you want to display (in your example : 40*1 and 40*31) and you'll get :
Code:
model1->setFrameLoop(40,1240);
 
That's all...

[Ref Link] Ms3d and MD2
http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=154&start=0&postdays=0&postorder=asc&highlight=ms3d+texture
posted @ 2006-07-23 21:42 安徽飞雪游戏工作室 阅读(180) | 评论 (0)编辑

<2009年7月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

与我联系

搜索

 

常用链接

留言簿

随笔档案

文章分类

常用地址

最新评论

阅读排行榜

评论排行榜