关于fbx转化为md5

2者都是模型格式,不要问我为什么要这么转,也不要问我为什么不走插件,有些情况我也说不清楚

Fbx转化为md5

简述:

fbxmd5都是3d模型格式就不多作介绍了,直接进入主题;我们的目标是把fbx转化为md5md5meshanimator是分开的,meshanimator会分别介绍。

既然要解析fbx,那么就必须先对其足够的了解,才能对解析出来的数据做正确的处理,少走弯路。

FBX(这里转载翻译后的fbx简单说明):

fbx是一种封闭的模型格式,这不仅说它通常作为二进制文件出现,而且是目前只能使用Autodesk提供的FBX SDK来操控这种文件。事实上,无论是3DS Max还是其SDK内置的Converter工具,都可以把其转换成ASCII的文本格式,虽然看上去有点JSON的样子,可事实上是全自给的“仅供观赏”的数据堆,也没有spec,通常也不会有人使用这种方式输出模型。好了,看来是必须借助其SDK了,所以首先要做的一件不太让人愉快的事情:加入这个SDK的库(lib&dll)。现在我用的是最新的fbxsdk-2013.3,下文仅就这版本兼容的模型而言。(注意,在预处理器选项中加入FBXSDK_NEW_API和FBXSDK_SHARED,如果你不想编译器抱怨一大堆的话。)

这里首先说一下,对于Fbx,它保存的最大集合是一个Scene(场景),跟很多的游戏引擎所使用的概念是一致的,就是用场景节点树来组织成一个场景。以前的3ds虽然也是树状地组织数据,但它是把不同类型数据堆抽象成节点,而Fbx/Dae则是纯粹地表述场景节点。所以对于后者们来说,即使把场景中多个物体/模型保存到同一个模型文件里,也是可以的,只不过是不同名字的节点而已,甚至把灯光、相机也可以抽象成节点而已。当然,对于我们编程者来说,一个模型文件仅仅对应一个模型是最自然的。所以接下来我只会谈及抽取模型和动画本身信息(事实上动画信息并非必须的——fbx和dae文件在没有动画或骨骼信息时,也就是静态模型了),不相关的部分则不涉及也不关心。

因为有其自身的SDK帮我们分析fbx文件,所以对于fbx,只要去获取SDK的FbxImporter读取的结果来为我们所用就可以了——问题是要知道怎么获取我们需要的数据,你要让它直接告诉你每个网格数据的各个直接可用的顶点属性数组,那可为难了。我们还是必须把它分析出来的数据,转换成我们需要的数据的。所以还是先想清楚我们需要什么数据:1.动画信息(如果有的话);2.网格信息;3.关联前两者的骨骼信息(如果有的话)。在导入MD5模型时,其实也是一个寻找这些信息的过程(不过MD5可是把动画信息另外封成一个md5anim文件而已)。

C++代码

1. FbxScene *pScene = FbxScene::Create(pFbxManager, "ImporterScene");  

2.   

3. pSdkImporter->Import(pScene);  

4.   

5. PrepareAnimationInfo((Scene*)pScene);  

6.   

7. FbxNode *pRootNode = pScene->GetRootNode();  

8.   

9. if (pRootNode)  

10. {  

11.     for (int i = 0; i < pRootNode->GetChildCount(); ++i)  

12.     {  

13.         FbxNode *pNode = pRootNode->GetChild(i);  

14.   

15.         ProcessNode((Node*)pNode, szResDirectory);  

16.     }  

17. }  

18.   

19. SetupJointKeyFrameInfo();  

在这里,我首先获取到这个场景(Scene),然后用PrepareAnimationInfo来预先查找场景中存在的动画信息(这里只简单查询动画的基本信息,通过Scene内的各FbxAnimStack下查各FbxAnimLayer,每个Anim Layer保存着一个动画,这里是把这些Layer的地址先存起来),然后获取场景的根节点,逐个处理其下属节点( ProcessNode函数里再轮询处理该节点的下属节点,递归调用 ProcessNode,完成整棵场景树的深度遍历),最后就是SetupJointKeyFrameInfo,获取具体的动画数据并把前两者的信息结合起来。

场景节点除了网格对象(FbxNodeAttribute::eMesh)外还有其他多种类型,前面说过了,省略。对于每个Mesh网格对象,我们要得到它的几个顶点属性数组:位置、纹理坐标、影响的骨骼点(Joint)个数,以及这些骨骼点的索引(Index)和影响因子(Bias),另外对于法线切线这些,也可以顺便获取也可以自行计算。注意除了位置(和顶点属性索引)外其余属性并非每个mesh都有,注意判断了。其中,获取骨骼蒙皮信息(也就是这个Mesh的Skin)还是很值得注意的:

C++代码

1. FbxSkin *pSkinDeformer = (FbxSkin *)pMesh->GetDeformer(0, FbxDeformer::eSkin);  

2.   

3. for (int i = 0; i < pSkinDeformer->GetClusterCount(); ++i)  

4. {  

5.     FbxCluster *pCluster = pSkinDeformer->GetCluster(i);  

6.   

7.     int nInfluencedPointIndexCount = pCluster->GetControlPointIndicesCount();  

8.     int *pInfluencedPointIndice = pCluster->GetControlPointIndices();  

9.     double *pInfluencedPointWeights = pCluster->GetControlPointWeights();  

10.   

11.     if (pLinkingBoneNode && pInfluencedPointIndice && pInfluencedPointWeights)  

12.     {  

13.         t3DJoint *pJoint = new t3DJoint((pCluster->GetLink()->GetName());       

14.   

15.         pCluster->GetTransformMatrix(transMatrix);  

16.         pCluster->GetTransformLinkMatrix(transLinkMatrix);  

17.   

18.         GetMatrixValue(transMatrix.Inverse(), &pJoint->mtPreFramePosed);  

19.         GetMatrixValue(transLinkMatrix, &pJoint->mtBindPose);  

20.  

21.         transLinkMatrix = transLinkMatrix.Inverse() * transMatrix;  

22.         GetMatrixValue(transLinkMatrix, &pJoint->mtPostFramePosed);  

23.   

24.         AddJoint(pJoint);  

25.   

26.         for (int iPtIndex = 0; iPtIndex < nInfluencedPointIndexCount; ++iPtIndex)  

27.         {  

28.             int nVertIndex = pInfluencedPointIndice[iPtIndex];  

29.                       

30.             tVertWeights.nAttachJointIndex = GetJointCount() - 1;  

31.             tVertWeights.fWeightBias = (float)pInfluencedPointWeights[iPtIndex];  

32.   

33.             std::map<int, std::vector<t3DVertWeights>>::iterator pFind = VertJointInfo.find(nVertIndex);  

34.   

35.             if (VertJointInfo.end() != pFind)  

36.                 pFind->second.push_back(tVertWeights);  

37.             else  

38.    

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值