Animation 从FBX加载蒙皮信息

Animation 从FBX加载蒙皮信息,animation,3d,skinning,fbx,Animation,3d,Skinning,Fbx,我正试图为FBX文件编写一个解析器,使其符合我的自定义模型格式,可以在我的游戏引擎中使用,但我目前一直在提取每个骨骼所需的矩阵。我想我可能也迷失在剥皮理论中了 我已设法提取网格的骨骼层次,并将变形簇的权重和索引附加到顶点。现在我需要提取(两个?)矩阵,以便在引擎中进行蒙皮 基本上,在我的格式中,我也希望它看起来像这样: //博奈德 //亲本 //Matrix1 //Matrix2 现在,关于矩阵。。。 我假设其中至少有一个应该是“绑定姿势矩阵”(即骨骼的默认位置)对吗?我如何从FBX中提取这个?

我正试图为FBX文件编写一个解析器,使其符合我的自定义模型格式,可以在我的游戏引擎中使用,但我目前一直在提取每个骨骼所需的矩阵。我想我可能也迷失在剥皮理论中了

我已设法提取网格的骨骼层次,并将变形簇的权重和索引附加到顶点。现在我需要提取(两个?)矩阵,以便在引擎中进行蒙皮

基本上,在我的格式中,我也希望它看起来像这样:

//博奈德

//亲本

//Matrix1

//Matrix2

现在,关于矩阵。。。 我假设其中至少有一个应该是“绑定姿势矩阵”(即骨骼的默认位置)对吗?我如何从FBX中提取这个?整个网格的矩阵是否一致

至于第二个,我真的不知道,我试过查看ViewScene和ImportScene示例,但我不明白。我读了一些关于“局部空间矩阵”的东西,我猜这是每个骨骼的单独位置、旋转和比例

任何帮助或建议都是很感激的,我现在不知所措,可能是因为我对这件事视而不见。几乎到了放弃FBX转而支持COLLADA的时候

Edit1:引擎还没有绘图功能,因为我想在继续之前完成这项工作。我找到了一个我想我能理解的例子,也许这里有人能证实它是否正确

//TEST CODE
        //This lFbxLinkMatrix is the skeleton's transform when the binding happened. 
        //It is the same as the matrix in bindpose if the bindpose is complete.
        // Multiply lClusterGlobalInitPosition by Geometric Transformation
        FbxAMatrix clusterGlobalInitPosition;
        cluster->GetTransformLinkMatrix(clusterGlobalInitPosition);

        FbxAMatrix clusterGeometry = GetGeometry(cluster->GetLink());
        clusterGlobalInitPosition *= clusterGeometry;

        skeleton->at(boneListPosition).bindMatrix = clusterGlobalInitPosition;

        // Compute the shift of the link relative to the reference.
        //lVertexTransformMatrix = RGCP.Inverse() * CGCP * CGIP.Inverse() * RGIP * RG;
        // CGCP = position of bone
        // RGCP = mesh position
        FbxAMatrix offsetMatrix;
        FbxNode* boneNode = cluster->GetLink();

        FbxAMatrix CGIP, RGIP, vertexTransformMatrix;

        cluster->GetTransformLinkMatrix(CGIP);
        cluster->GetTransformMatrix(RGIP);

        vertexTransformMatrix = CGIP.Inverse() * RGIP;

        skeleton->at(boneListPosition).localBoneMatrix = vertexTransformMatrix;

所以基本上,当我想计算我的动画时,我得到网格世界矩阵的逆矩阵,乘以代表我动画帧的矩阵,乘以我绑定矩阵的逆矩阵,骨骼的父绑定矩阵和最终的父变换矩阵?

首先,您需要知道网格的原始顶点位置不在世界空间中。(例如:您将看到角色在3ds max中竖立,但如果直接导出网格数据,则角色会躺下。)

骨骼树的所有变换节点也会发生同样的情况。这意味着,即使只有一块骨骼具有单位矩阵,网格也需要先通过FBX场景的根节点进行变换,然后再通过骨骼节点的局部矩阵进行变换。(因为根节点也是骨骼节点的父节点)

顺便说一下,如果使用函数FbxAxisSystem::ConvertScene()转换网格的轴系统,则该操作也仅应用于根节点的变换矩阵,而不应用于网格的顶点

要正确计算顶点的位置,需要找到网格所属的FBX节点,然后调用其EvaluateGlobalTransform()函数以获取全局变换矩阵,并使用它变换网格顶点的位置。(正常情况下的逆转置矩阵。)

我不知道您在代码的函数GetGeometry()中到底做了什么:
FbxAMatrix clusterGeometry=GetGeometry(cluster->GetLink())

但这是我获取骨骼绑定姿势矩阵的方法:
FbxAMatrix-BoneBindPoseMatrix;
pCluster->GetTransferorMLinkMatrix(BoneBindPoseMatrix)。

为了检索骨骼的节点,我还使用了
FbxNode*pBoneNode=pCluster->GetLink()
,并调用
pBoneNode->EvaluateLocalTransform(CurrentTime)
来获取骨骼在当前时间的局部变换矩阵。但我做了一件特别的事:记得我用根节点的全局变换矩阵来转换网格吗?所以对于骨架的根节点,我需要通过调用
FbxAMatrix BoneInitPoseGlobalTransform=pBoneRootNode->EvaluateGlobalTransform()
, 然后倒过来。我的根骨的局部变换矩阵是:
BoneLocalTransform=InvBoneInitPoseGlobalTransform*BoneLocalTransform我们只需要对骨骼的根节点执行此操作

设置蒙皮动画时,我遍历整个骨骼树,对于每个骨骼节点,我通过以下方式计算其全局变换矩阵:
BoneGlobalTransform=BoneLocalTransform*ParentBoneGlobalTransform但在将矩阵传递到着色器之前,我需要执行以下操作:
BlendMatrix=Bone.InvBindPoseMatrix*BoneGlobalTransform不要忘记,我已经通过根节点转换了顶点的位置


以上代码在D3D和OpenGL下都运行良好。我希望它能帮助你虽然这个答案很有用;它没有回答提取原始转换信息的问题。调用EvaluateLocalTransform(currentTime)需要FBX SDK,但作者想知道是否可以检索原始的“皮肤”信息,以便他们能够编写自己的EvaluateLocalTransform函数。你知道FBX SDK是否可以这样做吗?对不起,我可能误解了这个问题。是的,你可以自己计算局部变换,但它相当复杂。首先,您需要检索与下列节点属性绑定的所有动画曲线:LCL平移、LCL旋转、预旋转、后旋转、旋转枢轴、旋转偏移、LCL缩放、缩放枢轴、缩放偏移。然后您需要将它们转换为矩阵,然后将它们乘以以下顺序:invscapivot*Scal*scapivot*scalpoffset*InvRotaPivot*PostRota*Rota*PreRota*RotaPivot*RotaOffset*Translation。您可以搜索类FbxProperty和FbxAnimCurve以获取更多信息。这个答案对我帮助很大(搜索轴转换),fbx的文档记录非常糟糕!!找到正确的方法是一件痛苦的事情。@SeaStar似乎在描述Maya风格的FBX矩阵([Sp]x[S]x[Sh]x[Sp]x[St]x[Rp]x[Ro]x[R]x[Rp]x[Rt]x[T]),但在其他3d建模工具(如3DS Max)中,世界变换只是(ParentWorldTransform*T*R*S*OT*或*OS)。