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

问题描述 投票:0回答:2

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

opengl 3d fbx
2个回答
3
投票

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

像这样重写你的函数

FbxVector4 CMeshLoader::multT(FbxNode* pNode, FbxVector4 vector)
{
  FbxAMatrix geoMatrix;
  if (pNode->GetNodeAttribute())
  {
    const FbxVector4 lT = pNode->GetGeometricTranslation(FbxNode::eSourcePivot);
    const FbxVector4 lR = pNode->GetGeometricRotation(FbxNode::eSourcePivot);
    const FbxVector4 lS = pNode->GetGeometricScaling(FbxNode::eSourcePivot);
    geoMatrix.SetTRS(lT, lR, lS);
  }

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

  FbxAMatrix localMatrix = pNode->EvaluateLocalTransform();
  FbxAMatrix matrix = parentMatrix * localMatrix * geoMatrix;
  return matrix.MultT(vector);
}

2
投票

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

这是变换顶点的代码

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

© www.soinside.com 2019 - 2024. All rights reserved.