如何获得 fbx 网格的正确位置?

Posted

技术标签:

【中文标题】如何获得 fbx 网格的正确位置?【英文标题】:How can I get the correct position of fbx mesh? 【发布时间】:2016-03-30 21:47:12 【问题描述】:

我想将一个 fbx 文件中的模型加载到我自己的图形引擎中并渲染网格。但是当我加载文件并尝试渲染它时,某些节点的网格没有显示在正确的位置或正确的旋转。就像这样:

我已经尝试了几乎所有方法来转换网格的控制点,例如使用 fbx_sdk 示例代码中的代码:

FbxAMatrix CalculateGlobalTransform(FbxNode* pNode) 

    FbxAMatrix lTranlationM, lScalingM, lScalingPivotM, lScalingOffsetM, lRotationOffsetM, lRotationPivotM, lPreRotationM, lRotationM, lPostRotationM, lTransform;

    FbxAMatrix lParentGX, lGlobalT, lGlobalRS;

    if(!pNode)
    
        lTransform.SetIdentity();
        return lTransform;
    

    // Construct translation matrix
    FbxVector4 lTranslation = pNode->LclTranslation.Get();
    lTranlationM.SetT(lTranslation);

    // Construct rotation matrices
    FbxVector4 lRotation = pNode->LclRotation.Get();
    FbxVector4 lPreRotation = pNode->PreRotation.Get();
    FbxVector4 lPostRotation = pNode->PostRotation.Get();
    lRotationM.SetR(lRotation);
    lPreRotationM.SetR(lPreRotation);
    lPostRotationM.SetR(lPostRotation);

    // Construct scaling matrix
    FbxVector4 lScaling = pNode->LclScaling.Get();
    lScalingM.SetS(lScaling);

    // Construct offset and pivot matrices
    FbxVector4 lScalingOffset = pNode->ScalingOffset.Get();
    FbxVector4 lScalingPivot = pNode->ScalingPivot.Get();
    FbxVector4 lRotationOffset = pNode->RotationOffset.Get();
    FbxVector4 lRotationPivot = pNode->RotationPivot.Get();
    lScalingOffsetM.SetT(lScalingOffset);
    lScalingPivotM.SetT(lScalingPivot);
    lRotationOffsetM.SetT(lRotationOffset);
    lRotationPivotM.SetT(lRotationPivot);

    // Calculate the global transform matrix of the parent node
    FbxNode* lParentNode = pNode->GetParent();
    if(lParentNode)
    
        lParentGX = CalculateGlobalTransform(lParentNode);
    
    else
    
        lParentGX.SetIdentity();
    

    //Construct Global Rotation
    FbxAMatrix lLRM, lParentGRM;
    FbxVector4 lParentGR = lParentGX.GetR();
    lParentGRM.SetR(lParentGR);
    lLRM = lPreRotationM * lRotationM * lPostRotationM;

    //Construct Global Shear*Scaling
    //FBX SDK does not support shear, to patch this, we use:
    //Shear*Scaling = RotationMatrix.Inverse * TranslationMatrix.Inverse * WholeTranformMatrix
    FbxAMatrix lLSM, lParentGSM, lParentGRSM, lParentTM;
    FbxVector4 lParentGT = lParentGX.GetT();
    lParentTM.SetT(lParentGT);
    lParentGRSM = lParentTM.Inverse() * lParentGX;
    lParentGSM = lParentGRM.Inverse() * lParentGRSM;
    lLSM = lScalingM;

    //Do not consider translation now
    FbxTransform::EInheritType lInheritType = pNode->InheritType.Get();
    if(lInheritType == FbxTransform::eInheritRrSs)
    
        lGlobalRS = lParentGRM * lLRM * lParentGSM * lLSM;
    
    else if(lInheritType == FbxTransform::eInheritRSrs)
    
        lGlobalRS = lParentGRM * lParentGSM * lLRM * lLSM;
    
    else if(lInheritType == FbxTransform::eInheritRrs)
    
        FbxAMatrix lParentLSM;
        FbxVector4 lParentLS = lParentNode->LclScaling.Get();
        lParentLSM.SetS(lParentLS);

        FbxAMatrix lParentGSM_noLocal = lParentGSM * lParentLSM.Inverse();
        lGlobalRS = lParentGRM * lLRM * lParentGSM_noLocal * lLSM;
    
    else
    
        FBXSDK_printf("error, unknown inherit type! \n");
    

    // Construct translation matrix
    // Calculate the local transform matrix
    lTransform = lTranlationM * lRotationOffsetM * lRotationPivotM * lPreRotationM * lRotationM * lPostRotationM * lRotationPivotM.Inverse()\
        * lScalingOffsetM * lScalingPivotM * lScalingM * lScalingPivotM.Inverse();
    FbxVector4 lLocalTWithAllPivotAndOffsetInfo = lTransform.GetT();
    // Calculate global translation vector according to: 
    // GlobalTranslation = ParentGlobalTransform * LocalTranslationWithPivotAndOffsetInfo
    FbxVector4 lGlobalTranslation = lParentGX.MultT(lLocalTWithAllPivotAndOffsetInfo);
    lGlobalT.SetT(lGlobalTranslation);

    //Construct the whole global transform
    lTransform = lGlobalT * lGlobalRS;

    return lTransform;

在 U3d 中运行良好:

但是在我的引擎中仍然有两三个不正确变换节点的网格。 我已经在 Autodesk Fbx Review 和 Unity3D 中打开了 fbx 文件,它运行良好。这个问题困扰了我一整天,所以如果有人可以提供帮助,那就太棒了。谢谢

【问题讨论】:

您的代码似乎缺少的一件事是网格的“几何”变换。你可以用 GetGeometric[Rotation/Translation/Scaling] 得到它 是的,这就是重点。谢谢! 【参考方案1】:

发生这种情况是因为节点层次结构。而且你的答案并不完全正确

像这样重写你的函数

FbxVector4 CMeshLoader::multT(FbxNode* pNode, FbxVector4 vector) 

FbxAMatrix matrixGeo;
matrixGeo.SetIdentity();
if (pNode->GetNodeAttribute())

    const FbxVector4 lT = pNode->GetGeometricTranslation(FbxNode::eSourcePivot);
    const FbxVector4 lR = pNode->GetGeometricRotation(FbxNode::eSourcePivot);
    const FbxVector4 lS = pNode->GetGeometricScaling(FbxNode::eSourcePivot);
    matrixGeo.SetT(lT);
    matrixGeo.SetR(lR);
    matrixGeo.SetS(lS);

FbxAMatrix localMatrix = pNode->EvaluateLocalTransform();

FbxNode* pParentNode = pNode->GetParent();
FbxAMatrix parentMatrix = pParentNode->EvaluateLocalTransform();
while ((pParentNode = pParentNode->GetParent()) != NULL) 

    parentMatrix = pParentNode->EvaluateLocalTransform() * parentMatrix;


FbxAMatrix matrix = parentMatrix * localMatrix * matrixGeo;
FbxVector4 result = matrix.MultT(vector);
return result;

【讨论】:

【参考方案2】:

今天我尝试从 FBX 文件的所有节点中获取“局部变换”、“全局变换”和“几何变换”,我发现其中一些节点持有“几何变换”,这是那些处于错误位置的人。所以我使用节点的全局变换来乘以它的几何变换,从而生成一个新的矩阵。然后我用这个矩阵对节点网格的所有顶点进行变换,最后得到了properiate模型。

这是转换顶点的代码

FbxVector4 multT(FbxNode node, FbxVector4 vector)

FbxAMatrix matrixGeo;
matrixGeo.SetIdentity();
if (node->GetNodeAttribute())

    const FbxVector4 lT = node->GetGeometricTranslation(FbxNode::eSourcePivot);
    const FbxVector4 lR = node->GetGeometricRotation(FbxNode::eSourcePivot);
    const FbxVector4 lS = node->GetGeometricScaling(FbxNode::eSourcePivot);
    matrixGeo.SetT(lT);
    matrixGeo.SetR(lR);
    matrixGeo.SetS(lS);

FbxAMatrix globalMatrix = node->EvaluateLocalTransform();

FbxAMatrix matrix = globalMatrix*matrixGeo;
FbxVector4 result = matrix.MultT(vector);
return result;

在我的引擎中渲染的模型 enter image description here

【讨论】:

你的回答中的错字:EvaluateLocalTransform,你的意思肯定是 EvaluateGlobalTransform

以上是关于如何获得 fbx 网格的正确位置?的主要内容,如果未能解决你的问题,请参考以下文章

FBX 导出:对象枢轴设置为场景中心

如何正确读取 DirectX 的 FBX 2014 索引?

如何获得旋转的 UIView 的正确框架(包括正确的位置)

如何调整 Azure Maps 以获得正确的位置?

如何获得 SKShapeNode 的准确触摸位置?

在 Unity 中导入 Blender,如何生成正确的网格对撞机?