3DsMax导出插件编写(四)——导出骨骼动画的帧信息

接下来讲一下怎样导出骨骼动画。

首先我们要收集蒙皮信息。常规方法我们已经介绍过怎样获取蒙皮信息了,这里只介绍一些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模型插件导出的介绍就结束了,接下来,就是你自己来写导出插件,然后自己解析模型的过程了。相信自己导出的数据,自己再解析起来,将会是非常非常简单的事情了。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值