animation - 从 FBX 加载蒙皮信息

标签 animation 3d skinning fbx

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

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

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

//骨骼ID

//父骨骼ID

//矩阵1

//矩阵2

现在,到矩阵...
我是否正确假设其中至少一个应该是“绑定(bind)姿势矩阵”,即我的骨架的默认位置?如何从 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;

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

最佳答案

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

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

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

要正确计算顶点的位置,需要找到网格所在的FbxNode,然后调用其EvaluateGlobalTransform()函数得到全局变换矩阵,并用它来变换网格顶点的位置。 (法线的逆转置矩阵。)

我不知道您在代码的函数 GetGeometry() 中究竟做了什么:FbxAMatrix clusterGeometry = GetGeometry(cluster->GetLink());
但这是我获取骨骼绑定(bind)姿势矩阵的方法: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

关于animation - 从 FBX 加载蒙皮信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13566608/

相关文章:

Android 自定义弹出窗口/对话框

image - 通过在自定义单元格内进行修饰来制作基本的动画/翻译

silverlight - 删除 Silverlight 动画

javascript - 如何将 ASCII JSON 3D 模型文件转换为二进制文件?

inheritance - SceneKit Swift 3 继承不起作用

c# - 在 WPF 中为整个应用程序设置皮肤的推荐方法是什么?

java - 如何减慢行星在轨道上的移动速度?

ios动画旋转效果

python - 存储 3d 空间中点的信息

使背景可点击的jquery脚本