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

How can I get the correct position of fbx mesh?

我想将模型从 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 文件,它运行良好。这个问题困扰了我一整天,所以如果有人能提供帮助就太棒了。谢谢

今天我尝试从 FBX 文件的所有节点获取 "Local Transform"、"Global Transform" 和 "Geometric Transform",我发现一些节点持有 "Geometric Transform",这是错误的位置。所以我使用节点的全局变换乘以它的几何变换,生成一个新的矩阵。然后我用这个矩阵来变换节点网格的所有顶点,最后我得到了合适的模型。

这是转换顶点的代码

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

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

像这样重写你的函数

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;}