有没有人做过从3DMAX的CS动画中导出动画数据?做过的话请进来看看,谢谢!

lyzcom 2004-04-15 01:07:55
我在做从MAX的CS中导出动画数据出现了问题,以下是我的导出动画矩阵关键帧的代码。

我的基本思路是:从MAX中直接导出最终用来渲染的矩阵而不再做实时的运算了。所以我的导出插件使用了d3dx9.lib,直接就是最后渲染用的矩阵。另外,我目前能100%的确定我的权重数据导出是没有任何问题的,问题就出在动画矩阵的数据上!

for(int iBone = 0; iBone < iTotalBones; ++ iBone)
{
INode* pBoneNode = pBoneList->Get(iBone)->GetMaxNode();
//获取0时间矩阵
Matrix3 initMat = pBoneNode->GetNodeTM(0);
initMat.NoScale();
initMat.Invert();
//保存
pBoneList->Get(iBone)->SetInitMat(initMat);
}

for(int iTime = 0; iTime < iTotalTimes; ++ iTime)
{
for(iBone = 0; iBone < iTotalBones; ++ iBOne)
{
//BoneInfo结构是一个骨头的数据结构,其中包含了这个骨头所对应的MAX节点、顶点数量、子骨头等
BoneInfo* pBoneInfo = pBoneList->Get(iBone);
//使用0时间的反转矩阵乘以当前时间的变换矩阵
Matrix3 finalMat = pBoneInfo->GetInitMat() * pBoneInfo->GetMaxNode()->GetNodeTM(iTime);

//在这里转换到D3DXMATRIX成为最终渲染用矩阵
D3DXMATRIX rotateMat;

Point3 offset = finalMat.GetTrans();

Quat rotateQuat(finalMat);
D3DXQUATERNION d3dQuat;
d3dQuat.x = rotateQuat.x;
d3dQuat.y = rotateQuat.y;
d3dQuat.z = rotateQuat.z;
d3dQuat.w = rotateQuat.w;

D3DXQuaternionRotationMatrix(&d3dQuat, &rotateMat);

D3DXMATRIX d3dMatFinal;
memcpy(&d3dMatFinal, &rotateMat, sizeof(D3DXMATRIX));
d3dMatFinal._41 = offset.x;
d3dMatFinal._42 = offset.y;
d3dMatFinal._43 = offset.z;

//现在得到的d3dMat就是最终渲染用的矩阵,渲染的时候,我就直接拿这个矩阵和他所拥有的权重去转换他所影响的顶点了。
}
}


但是现在,动画总是会出现问题,问题出得小的,就是很多的地方出现过份运动,比如人的走路动作,走起来像个跛子一样,而MAX中并不是这样的。问题出得大一点的,那就完全不知道是什么东西了,网格的顶点被拉扯得一蹋糊涂。

我已经郁闷了好几天了,实在是弄不出来为什么会这样。各位高手,帮帮我吧!!哪怕是谈谈经验也好啊。
...全文
198 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
KingofMagic 2004-05-12
  • 打赏
  • 举报
回复
应该是MAX和Directx的世界坐标系不同造成的
因为一个是左手一个是右手
kypck 2004-04-17
  • 打赏
  • 举报
回复
我看了下以前的的代码,发现你的代码是有几个严重的问题。
1、GetNodeTM得到的是此节点相对于其父节点的变换,就是说NodeTM矩阵的作用就是把子骨骼坐标系下的坐标变换到其父骨骼下面,所以当计算initMat时,要使用GetObjectTM,另外你的骨骼最好别用affect pivot(object) only功能,否则offset matrix就不为单位阵了(可能会出错);
2、你的initMat的功能应该是把皮肤mesh上顶点的建模坐标转换为每块骨骼的局部坐标,而得到最后的finalMat时,initMat却在左边与骨骼的NodeMat相乘,我的做法是先把mesh的建模坐标转换为骨骼的局部坐标(通过initMat),然后在通过乘上每块骨骼的ObjectTM,就可以得到皮肤mesh跟随骨骼一起运动的效果了;
所以说,你的那两个用NodeTM的地方都应该用ObjectTM。关于插值的问题,我觉得还是用到点好,因为它能产生“要多平滑有多平滑”的动画,每秒30帧似乎很高,但如果需要要把1秒内的动作按慢镜头方式播放个10秒呢?
另外如果只保存最后的矩阵,那么你的骨架系统的动画就完全是预置的了,如果需要做出象Max Payne 2里的那样的人物效果,每块骨骼的NodeTM必须实时计算,然后得到ObjectTM再与initMat相乘。
lyzcom 2004-04-16
  • 打赏
  • 举报
回复
有没有人帮帮我?
kypck 2004-04-15
  • 打赏
  • 举报
回复
多半会是插值时产生的问题,也还有可能是这行
“Matrix3 finalMat = pBoneInfo->GetInitMat() * pBoneInfo->GetMaxNode()->GetNodeTM(iTime);”
后得到某一帧时刻的NodeTM没有经过NoScale操作,要知道在对齐骨骼时,会经常用到缩放操作的,如果不去掉缩放就会出错。
lyzcom 2004-04-15
  • 打赏
  • 举报
回复
谢谢楼上兄弟的回答。

NoScale函数我加上了,还是无效。

但是关于您所说的多半是插值的问题,我有些不明白:

因为从MAX中获取出来的变换矩阵,已经是很平滑的,因为我是使用每秒钟采样30帧的速度来获取矩阵的,MAX中每秒应该含有200个以上的矩阵,所以,我从来想不通为什么还要进行插值。

为什么呢?

8,303

社区成员

发帖
与我相关
我的任务
社区描述
游戏开发相关内容讨论专区
社区管理员
  • 游戏开发
  • 呆呆敲代码的小Y
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧