从FBX加载皮肤信息

Mr *_*ace 10 3d animation skinning fbx

我正在尝试将FBX文件的解析器编写为我的自定义模型格式,可以在我的游戏引擎中使用,但我目前只是在提取每个骨骼所需的矩阵.我想我也可能会在皮肤理论中迷失...

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

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

// BoneID

// ParentBoneID

//矩阵1

//矩阵2

现在,对于矩阵......我是否正确地假设它们中至少有一个应该是"绑定姿势矩阵",即我骨架的默认位置?如何从FBX中提取此内容?整个网格的矩阵是否均匀?

至于第二个,我真的不知道,我已经尝试过查看ViewScene和ImportScene示例,但是我没有得到它.我读了一些关于"局部空间矩阵"的东西,我猜这是每个骨骼的个别位置,旋转和比例?

任何帮助或建议都表示赞赏,我现在感到很茫然,可能是因为我对此视而不见.几乎在放弃FBX而转向COLLADA的时候.

编辑1:引擎没有绘图功能,因为我想在继续之前完成这项工作.我找到了一个我认为理解的例子,也许这里有人可以确认它是否正确.

//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;
Run Code Online (Sandbox Code Playgroud)

所以基本上,当我想要计算我的动画时,我得到网格的世界矩阵的逆,将它与表示我的动画帧的矩阵相乘,乘以我的绑定矩阵的倒数,该骨骼的父绑定矩阵和最终的父变换矩阵?

Sea*_*tar 9

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

骨架树的所有变换节点也会发生同样的事情.这意味着,即使只有一个带有单位矩阵的骨骼,网格也需要通过FBX场景的根节点转换,然后是骨骼节点的局部矩阵.(因为根节点也是骨节点的父节点),

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

要正确计算顶点的位置,需要找到网格所属的FbxNode,然后调用其EvaluateGlobalTransform()函数来获取全局变换矩阵,并使用它来变换网格顶点的位置.(反向转置矩阵表示正常.)

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

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

为了检索骨骼的节点,我也使用FbxNode* pBoneNode = pCluster->GetLink(),并调用pBoneNode->EvaluateLocalTransform( CurrentTime )以获取当前骨骼的局部变换矩阵.但是我做了一件特别的事情:记得我用根节点的全局变换矩阵转换了网格吗?所以对于骨架的根节点,我需要通过调用得到它的全局变换矩阵 FbxAMatrix BoneInitPoseGlobalTransform = pBoneRootNode->EvaluateGlobalTransform(),然后反转它.我的根骨的局部变换矩阵将是:BoneLocalTransform = InvBoneInitPoseGlobalTransform * BoneLocalTransform;我们只需要为骨根节点做这个.

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

就是这样,上面的代码在D3D和OpenGL下都能很好地工作.我希望它可以帮到你.:d

  • 对不起,我可能误解了这个问题.是的,你可以自己计算局部变换,但它非常复杂.首先,您需要检索与下面列出的节点属性绑定的所有动画曲线:LclTranslation,LclRotation,PreRotation,PostRotation,RotationPivot,RotationOffset,LclScaling,ScalingPivot,ScalingOffset. (2认同)
  • 然后你需要把它们变成矩阵,并按顺序乘以:InvScalPivot*Scal*ScalPivot*ScalOffset*InvRotaPivot*PostRota*Rota*PreRota*RotaPivot*RotaOffset*Translation.您可以搜索类FbxProperty和FbxAnimCurve以获取更多信息. (2认同)