接下来讲一下怎样导出骨骼动画。
首先我们要收集蒙皮信息。常规方法我们已经介绍过怎样获取蒙皮信息了,这里只介绍一些IGame的方法:
IGameSkin* skin;
bool meshSkin = false;
int mods = iObj->GetNumModifiers();
if(mods>0)
{
for(i = 0;i<mods;i++)
{
IGameModifier * im = iObj->GetIGameModifier(i);
if(im->IsSkin())
{
skin = (IGameSkin*)im;
meshSkin = true;
break;
}
}
}
我们用上面的方法先判断一下节点身上有多少个修改器,然后逐个遍历一下,假如有蒙皮的信息,就把修改器存下来。Igame的一个方便地方,就是它的通用,这里的IsSkin已经包含了3dsmax的两种蒙皮方式了,所以美术可以使用自己喜欢的蒙皮修改器来做蒙皮了。
int vertSum = iMesh->GetNumberOfVerts();
for(i = 0;i<vertSum;i++)
{
if(meshSkin)
{
int type = skin->GetVertexType(i);
if(type==IGameSkin::IGAME_RIGID)
{
SkinInfo subSkinInfo;
INode* bNode = skin->GetBone(i,0);
//subSkinInfo 是我记录信息的类,里面可以保存骨骼名称和权重
subSkinInfo.boneName = bNode->GetName();
subSkinInfo.weight = 1;
vInfo.skinInfo.push_back(subSkinInfo);
}
else //blended
{
for(j=0;j<skin->GetNumberOfBones(i);j++)
{
SkinInfo subSkinInfo;
INode* bNode = skin->GetBone(i,j);
float weight = skin->GetWeight(i,j);
subSkinInfo.boneName = bNode->GetName();
subSkinInfo.weight = weight;
vInfo.skinInfo.push_back(subSkinInfo);
}
}
}
objList.vert.push_back(vInfo);
}
好了,蒙皮信息已经记录完了,那么下面就来开始导出动画:
在之前我们已经介绍过怎样去获取场景里面所有骨骼的节点,这里就不重复。接下来我们先要获取一下当前场景的动画长度,然后遍历动画的长度,遍历所有获取到的骨骼,然后获取它们在每一帧的信息,下面是用IGame,其实用常规方法也是一样的做法,只是使用的函数不一样而已:
void GetAllFrame(Interface *itf)
{
Interval ARange = itf->GetAnimRange();
TimeValue tAniTime = ARange.End()-ARange.Start();
TimeValue tTime = ARange.Start();
int gpf = GetTicksPerFrame();
frameCount = tAniTime/gpf;
int i;
int j;
for(i =0;i<frameCount;i++)
{
BoneFrame tempFrame;
tempFrame.frameIndex = i;
for(j = 0;j<bones.size();j++)
{
BoneKey bKey;
GMatrix gm = bones[j].node->GetWorldTM(i*gpf);
Point3 pos = gm.Translation();
Point3 rota = gm.Rotation().Vector();
bKey.x = pos.x;
bKey.y = pos.y;
bKey.z = pos.z;
bKey.rx = rota.x;
bKey.ry = rota.y;
bKey.rz = rota.z;
bKey.gm = gm;
tempFrame.keys.push_back(bKey);
}
frames.push_back(tempFrame);
}
}
说明:上面我们记录了很多信息,其实只是一个示范,具体需要什么信息,可以根据个人的需要来定。比如上面我获取的是GetWorldTM世界坐标的矩阵,这是方便后期计算,却不利于文件的容量,我们可以改成GetLocalTM获取相对的坐标,这样做,保存的文件容量可以减少到原来的三分之一以下。然后我们可以选择保存整个矩阵GMatrix ,也可以选择保存单独的位移旋转的数据。最后,我们甚至可以连单独的位移旋转数据都不用每一帧保存,只需要记录它相对于第一帧时候的增量来保存。经过层层的优化,你的保存动画的文件就可以很小很小了。比如我的一个跑步的动画,如果是直接获取世界坐标然后保存矩阵,文件的大小大概在90几k左右。但如果最后各种优化,最终的文件大小只有9k。
当然了,在我们减少了文件容量的同时,我们是相应的增大了文件应用时候解析的难度和计算量的,这个优劣就自己去衡量了。
好了,到这里,阿赵我的3dsMax模型插件导出的介绍就结束了,接下来,就是你自己来写导出插件,然后自己解析模型的过程了。相信自己导出的数据,自己再解析起来,将会是非常非常简单的事情了。