irrlicht引擎:实现天龙八部的RPG角色换装
看了看时间,已经3点过了,突然想写点什么,却又不知从何说起。
那就从今天这个用irrlicht做天龙八部的模型换装说起吧。
也不知道是为什么,最近又捣鼓起了OGRE和irrlicht. 并且,总想用irrlicht实现一些OGRE中的东西。
当然,这不是商业项目,也没有商业目的,纯属蛋疼而已。
一切行动的由来,都来自于vczh那天晚上的举动。
记得有一天晚上在群里聊天,大伙就称赞各位菊苣是多么的厉害。
最后vc发了一个自己的桌面截图说:让你们看看菊苣是如何练成的(这不是原话,和话的字眼有出入,在此不想负任何责任,如果真有想看的,去翻群的聊天记录)
那天晚上,我想了很久。想想自己自从转做页游以后,是如何虚渡光阴的。
终于忍不住了,翻开了自己的移动硬盘,看看自己曾经做过的小东西。90%是建好工程就没理了。
这才明白,我花在思考上的时间远远大于了行动。 于是,我决定改变自己,找回那个真的我。
3D游戏是我的真爱, 真爱到就算画面差一点,只要是3D,我也会很喜欢。
于是,我觉得自己还是应该接着先前的路走下去。 什么服务器,什么 AS3. 都是浮云, 不喜欢就是不喜欢。
私下又开始研究irrlicht了。
猛地一发现,自己是多么的搞笑, 从09年到11年,一直在做引擎开发, 也翻过irrlicht和ogre无数遍。 却从来就没有写完过一个完整的DEMO。
连功能测试用例都没有写过。突然觉得之前的一些设计似乎有些脱离了实际。没有真正使用过,又怎知如何是好,如何是坏呢?
这一次是真的玩irrlicht了, 中间也纠结过是不是OGRE更适合。 但在目前这个时间有限的空间下,我更愿意玩irrlicht.小巧,轻便。 当然,意味着更多东西要自己实现。 不过对于一个代码控来说,也反而更自得其乐。 正好可以在短路的时候,去参考一下其它引擎,用来扩充irrlicht.
我要做的不是把irrlicht整得牛B,而是想自己弄弄,加上移动平台的崛起,我觉得irrlicht更加适合吧。 据说gameloft也有使用(仅是据说)。
可能很多兄弟会说我这讲的东西,其实就是一坨屎了。 不过,我觉得再坏的评论,也表示一种关注。 批评好过于无视啊~~~~
----------------------------------------------------------下面说说我遇上的纠结------------------------------------------------
纠结1:换装需要场景节点配合
在irrlicht中,并没有提供普通引擎中的submesh或者bodypart这种东西,用于直接支持换装。 在irrlicht中,如果想要换装,最直接的方法就是依赖于场景结点
比如,在我的示例中,可以更换头发,帽子,衣服,护腕,靴子,面容。 那就需要7个场景节点,1个作为根节点,用于控制整个角色的世界坐标,平移,缩放,旋转等属性。另外6个场景节点则分别绑有各个部件的模型
贴一下我的角色类的代码,行数不多
class CCharactor
{
IrrlichtDevice* m_pDevice;
IAnimatedMeshSceneNode* m_pBodyParts[eCBPT_Num];
ISceneNode* m_pRoot;
public:
CCharactor(IrrlichtDevice* pDevice)
:m_pDevice(pDevice)
{
memset(m_pBodyParts,0,sizeof(m_pBodyParts));
m_pRoot = pDevice->getSceneManager()->addEmptySceneNode(NULL,12345);
}
void changeBodyPart(ECharactorBodyPartType ePartType,stringw& meshPath,stringw& metrialPath)
{
ISceneManager* smgr = m_pDevice->getSceneManager();
IAnimatedMeshSceneNode* pBpNode = m_pBodyParts[ePartType];
IAnimatedMesh* pMesh = smgr->getMesh(meshPath.c_str());
if(pMesh==NULL)
return;
if(pBpNode==NULL)
{
pBpNode = smgr->addAnimatedMeshSceneNode(pMesh,m_pRoot);
m_pBodyParts[ePartType] = pBpNode;
}
else
{
pBpNode->setMesh(pMesh);
}
ITexture* pTexture = m_pDevice->getVideoDriver()->getTexture(metrialPath.c_str());
if(pTexture)
pBpNode->setMaterialTexture(0,pTexture);
}
};
//然后,我用了一个结构体来构建部件信息
struct SBodyPartInfo
{
stringw Desc;
ECharactorBodyPartType Type;
stringw MeshPath;
stringw MeterialPath;
};
纠结2:共享骨骼
首先,irrlicht 1.8中对OGRE模型的格式支持在代码中,最高只看到了1.40版本的解析,更高的就会被无视。 天龙八部的模型有几个是1.30的,而用于换装和主角的,都是1.40的。 可能是解析不全的原因,导致1.40的骨骼动画无法正常播放。 这个问题整了几个小时,没有解决,明天继续
其次,多个模型共享骨骼只能通过场景节点的useAnimationFrom来完成,并且传入的是一个Mesh参数。这点让人蛋疼, 天龙八部的角色动作是分开了的,不同的攻击动作是一个skeleton文件。 想要实现共享,有点麻烦。
纠结3:模型文件格式
irrlicht不像OGRE那样有一个强大且成熟的模型文件格式,虽然提供了.irr格式,但仅是用于irrEdit的场景信息输出。先看一张图
这张图是irrlicht samples中的MeshViewer的提示框内容。 上面列出了可以支持的模型文件类型。 大家可以看看,又有多少模型格式是可以直接拿来放到项目上用的呢? mdl和ms3d可以考虑,dae的话,我在开源游戏0 A.D. 中见到使用过。 其它的话,就完全不熟悉了。 OGRE的 .mesh支持也不完全。 难道真要自己整一个。
我能想到的,就是选一个插件完整和模型和动画格式都比较好的作为与美术工具交互的格式。 自己再写一个工具,转换成自己的格式。
纠结4:硬件蒙皮
我以为像NIKO那样的技术狂,怎么会放掉这一个特性。 很高兴地在场景节点上发现了硬件蒙皮的函数接口。但一看注释,把我咽着了。
//! (This feature is not implemented in irrlicht yet)
virtual bool setHardwareSkinning(bool on);
其它地方,还没有去整,就先不发表言论了。 继续着这个很傻B,很天真的捣鼓之路。
上个图,纪念一下我的irrlicht产物。
布衣
换了身盔甲
换了帽子和靴子
PS:头发没有纹理,所以是白的。