2

I want to load a model from an fbx file into my own graphic engine and render the meshes. But when I've load the file and try to render it, the meshes of some nodes did not display on the right position or with the correct rotation. Just like this: incorrect rendering

I have tried almost all methods to transform the control points of meshes, such as using the code from fbx_sdk sample code:

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

which works well in U3d: correct rendering in U3d

But in my engine there are still meshes of two or three nodes of incorrect transform. I've opened the fbx file in Autodesk Fbx Review and Unity3D and it works well. The problem has bothered me for a whole day, so it would be awesome if someone can help. Thanks

CaringDev
  • 8,391
  • 1
  • 24
  • 43
BruceZ
  • 43
  • 2
  • 7

2 Answers2

3

This happens because of node hierarchy. And your answer is not completely correct

rewrite yor function like this

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;}
Azamat Em
  • 46
  • 4
2

Today I've tried to get "Local Transform", "Global Transform" and "Geometric Transform" from all nodes of the FBX file, and I've found that some of the nodes hold a "Geometric Transform", which are the ones in wrong position. So I use the nodes' global transform to multiply its geometric transfom, which generated a new matrix. Then I use this matrix to transform all the vertices of the node's mesh, and finally I got the properiate model.

Here's the code to transform the vertices

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

And the model rendered in my engine enter image description here

BruceZ
  • 43
  • 2
  • 7