骨骼动画貌似很简单的原理的理解

上传人:小** 文档编号:83455816 上传时间:2019-02-27 格式:DOCX 页数:4 大小:15.41KB
返回 下载 相关 举报
骨骼动画貌似很简单的原理的理解_第1页
第1页 / 共4页
骨骼动画貌似很简单的原理的理解_第2页
第2页 / 共4页
骨骼动画貌似很简单的原理的理解_第3页
第3页 / 共4页
骨骼动画貌似很简单的原理的理解_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

《骨骼动画貌似很简单的原理的理解》由会员分享,可在线阅读,更多相关《骨骼动画貌似很简单的原理的理解(4页珍藏版)》请在金锄头文库上搜索。

1、先说一下我对骨骼动画貌似很简单的原理的理解。下面的阐述也能看得出我对这些概念的把握其实很混乱,都是模模糊糊的。骨骼像一棵树形结构那样,有父骨骼、子骨骼。每个骨骼保存的都是相对于父骨骼的转换矩阵,因此他们的世界矩阵都需要把自己的矩阵乘上父骨骼的世界矩阵才能得到(这是在d3d的情况。opengl的程序往往是反过来的,父骨骼的世界矩阵乘上本骨骼的矩阵,好像跟opengl使用矩阵的方式有关(压入堆栈)。Mesh的每一个顶点都可以受多根骨骼的影响,使用权重值来决定影响的程度。在程序里面,可以先对一个顶点使用骨骼转换到正确的动作姿态(这时仍然只是在模型空间),再用该游戏物体的世界矩阵转换到游戏世界的正确位

2、置上现在先不考虑游戏物体的世界矩阵,只考虑模型空间。这就有了一个问题:对顶点应当使用什么矩阵才能把它转换到正确的动作姿态上?想象一个简单的人物模型,裸模,身体各部位都是连贯的一个mesh。那么这些顶点都是在模型空间里定义的,而每个骨骼的那些缩放、旋转和位置信息都是在父骨骼的空间里定义的,这就不能拿骨骼的世界矩阵直接转换顶点。我认为,只有顶点是在骨骼的本地空间里定义的才可以使用骨骼的世界矩阵转换它。确实,有一个bind pose的概念,它其实就是矩阵,是骨骼初始的世界矩阵。矩阵是把坐标从空间A转换到空间B,那么这个矩阵的逆矩阵就能把坐标从空间B转换回空间A。所以bind pose矩阵的逆矩阵就应

3、当能把模型空间的顶点转换到骨骼的本地空间去,然后在某一时刻,使用骨骼的世界矩阵转换这些在骨骼空间中的顶点,应该就能把它们转换到正确的动作姿态了。在3DSMAX导出插件,使用IGame。如何得到各骨骼的bind pose呢?由于在游戏里,骨骼的空间信息仍然是相对于父骨骼定义的,所以这里求Bind pose,也是一样。而且一般bind pose取第0帧时即可。使用IGameNode:GetWorldTM()函数(参数应该传0,也就相当于第0帧了),得到一个GMatrix结构,在调用GMatrix的ExtractMatrix3()函数就能得到一个Matrix3结构(它是以列为主的,跟d3d不一样)t

4、m,这就是该IGameNode在第0帧时的世界矩阵了。本来tm应该就是该骨骼的bind pose矩阵的,但因为要保存相对于父骨骼的值,所以还要先使用同样方法得到父骨骼在第0帧时的世界矩阵ptm,让tm乘上ptm的逆矩阵。接下来,实际保存的时候,由于我的Bone结构实际存储的是缩放、旋转、位置,所以要把这个tm矩阵拆开来。那么在游戏里要得到一个Bone的Bind pose矩阵,就是从这3个值构造一个矩阵,再乘上父骨骼的bind pose矩阵。这里,我发现我和Ogre引擎的一个非常显著的分歧。我的做法,如上所述Matrix IBone:GetBindPoseMatrix() Matrix mtxS

5、cale = MtxScale(m_BindPoseScale); / m_BindPoseScale是一个三维向量,代表了bind pose的xyz方向上的缩放 Matrix mtxRot = MtxRotFromQuaternion(m_BindPoseRot); / m_BindPoseRot是一个Quaternion,MtxRotFromQuaternion函数可以根据一个Quaternion创建一个旋转矩阵 Matrix mtxTrans = MtxTranslation(m_BindPoseTrans); m_BindPoseMatrix = mtxScale * mtxRot *

6、 mtxTrans; / 保存一下计算出的bind pose矩阵,如果愿意,使用一点技巧,可以使此函数不必每次都计算,这里省掉了 if(m_pParent) m_BindPoseMatrix *= m_pParent-GetBindPoseMatrix(); return m_BindPoseMatrix;可以看到,我先把本骨骼相对于父骨骼的bindpose缩放、旋转、平移合并为一个矩阵,再乘上父骨骼的bind pose矩阵,得到本骨骼的在世界空间的bind pose矩阵。可是ogre,是先把本骨骼的bindpose缩放乘上父骨骼的bindpose缩放,本骨骼的bindpose旋转乘上父骨骼的

7、bindpose旋转,本骨骼的bindpose位置加上父骨骼的bindpose位置,得出三个新的缩放、旋转、位置,再合并为一个矩阵。这两种方法得出来的结果是不一样的。这就是我的困惑。ogre的运行效果是没错的,我的运行效果是错误的,不过我之前用过ogre的方式,也不对。我想不对的原因不仅仅在bind pose矩阵的重新合并上,还在于动作的导出上。因为ogre的导出插件用的INode借口,没用IGame的IGameNode。INode有GetNodeTM函数,文档上说能得到合并了父结点矩阵的矩阵,而IGameNode有三个函数:GetWorldTM、GetLocalTM、GetObjectTM,

8、文档也没有说明哪个函数对应INode的GetNodeTM,我想当然的认为是GetWorldTM。下面是我导出动作的做法。很羞愧,我其实不知道control、modifier到底是干什么的。但是要导出骨骼的每一帧动作,似乎必须通过control。首先IGameNode-GetIGameControl()得到一个IGameControl指针,然后调用IGameControl的GetFullSampledKeys函数就可以得到各帧的转换。这个函数也很让我困惑,我认为把参数Type设为IGAME_TM,就可以得到矩阵形式的转换,参数Relative,我不知道是相对于谁,相对于父骨骼?相对于前一帧?相对

9、于第0帧?相对于bind pose?由于这个函数是计算各帧的转换,所以我倾向于认为是相对于前一帧的。那么我要的是绝对值,所以这个就设为falseIGameKeyTab selfKeys; / 在每一帧,本骨骼的世界转换IGameKeyTab parentKeys; / 在每一帧,父骨骼的世界转换IGameNode* pParent = pGameNode-GetNodeParent(); / pGameNode就是当前正在处理的骨骼, pParent是父骨骼IGameControl* pControl = pGameNode-GetIGameControl();pControl-GetFull

10、SampledKeys(selfKeys, frameRate, TGAME_TM, false);if(pParent) pControl = pParent-GetIGameControl(); pControl-GetFullSampledKeys(parentKeys, frameRate, TGAME_TM, false);for(uint k = startKeyFrame; k GetWorldMatrix(); return m_WorldMatrix;至此,我对骨骼动画的导出及渲染就是这样做的了,遗憾的是,运行结果是错误的。这两个多星期以来,我尝试修改了很多方式,都没有成功。也有参考Ogre的源代码,可是它坐标系不一样,它使用max sdk api而不是IGame,所以结果也不对。有谁能帮我看看是怎么回事?有谁曾经实现过,能指点一下吗?谢谢了。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 商业/管理/HR > 管理学资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号