我导入了一个由多个网格组成的FBX模型。不幸的是,我无法将每个网格显示在正确的位置。对于每个网格,我将网格的几何变换与网格的局部变换相乘,然后将其传递给着色器。我该如何解决这个问题?
gl_Position = modelViewProjectionMatrix *TransformationMatrix*vertexPositionsOfMesh;
GLKMatrix4 LcLTransformation = createTransformationMatrix(
Mesh->LclRotation,
Mesh->LclScaling,
Mesh->LclTranslation);
GLKMatrix4 GeoTransformation = createTransformationMatrix(
Mesh->GeometricRotation,
Mesh->GeometricScaling,
Mesh->GeometricTranslation);
TransformationMatrix=GLKMatrix4Transpose(GLKMatrix4Multiply(LcLTransformation,
GeoTransformation));
GLKMatrix4 createTransformationMatrix(float* _rotation, float* _scaling, float* _translation)
{
GLKMatrix4 Rx = GLKMatrix4Make(1, 0, 0, 0,
0, cos(_rotation[0]), -sin(_rotation[0]), 0,
0, sin(_rotation[0]), cos(_rotation[0]), 0,
0, 0, 0, 1
);
GLKMatrix4 Ry = GLKMatrix4Make(cos(_rotation[1]), 0, sin(_rotation[1]), 0,
0, 1, 0, 0,
-sin(_rotation[1]), 0, cos(_rotation[1]), 0,
0, 0, 0, 1
);
GLKMatrix4 Rz = GLKMatrix4Make(cos(_rotation[2]), -sin(_rotation[2]), 0, 0,
sin(_rotation[2]), cos(_rotation[2]), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
GLKMatrix4 Translation = GLKMatrix4Make(1, 0, 0, _translation[0],
0, 1, 0, _translation[1],
0, 0, 1, _translation[2],
0, 0, 0, 1
);
GLKMatrix4 Scaling = GLKMatrix4Identity;
Scaling.m00 = _scaling[0];
Scaling.m11 = _scaling[1];
Scaling.m22 = _scaling[2];
GLKMatrix4 Rotation = GLKMatrix4Multiply(GLKMatrix4Multiply(Rx, Ry), Rz);
Transformation = GLKMatrix4Multiply(Scaling, GLKMatrix4Multiply(Rotation, Translation));
return Transformation;
}
答案 0 :(得分:144)
我在引擎中正确地从MAX导入了fbx。
你必须:
WorldMatrix= [ParentWorldMatrix * ModelMatrix] * GeometricMatrix
你只需要将几何矩阵 AFTER 相乘,即可获得层次结构的世界。 " ParentMatrix" 不包含GEOM。
所以模型应该是:
World = GrandGrandParentModel * [...] * GrandParentModel * ParentModel * Model * CurrentModelGeometric。
请记住旋转是ZYX。
代码:
void GRPNODE::UpdateWorldMatrix(bool * mustUpdate)
{
if (!parent)
return;
parent->UpdateWorldMatrix(mustUpdate);
if (worldmatrix_is_pending)
*mustUpdate = true;
if (*mustUpdate)
this->worldmatrix.GetMulplicationMatrix(parent->GetWorldMatrixPointer(), &modelmatrix);
}
然后我得到节点的世界矩阵,当我转换顶点时,我做了:
void GRPELEMENT::ComputeMatrices(GRPMATRIX* viewmatrix, GRPMATRIX* viewprojection, GRPMATRIX* projection)
{
modelmatrix=node->GetWorldMatrix();
if (node->UsesGeometric)
modelmatrix.GetMulplicationMatrix(modelmatrix, (*node->GetGeometricMatrix()));
modelviewmatrix.GetMulplicationMatrix((*viewmatrix), modelmatrix);
modelviewprojectionmatrix.GetMulplicationMatrix(projection, &modelviewmatrix);
}
void GRPNODE::MaxUpdate()
{
// 1.0 Create Scale matrix
scalematrix.BuildScaleMatrix(scale.vector[0], scale.vector[1], scale.vector[2]);
// 1.1 Create current Rotation Translation Matrix
Rx.BuildRotationMatrixX (this->rotation.vector[0]);
Ry.BuildRotationMatrixY (this->rotation.vector[1]);
Rz.BuildRotationMatrixZ (this->rotation.vector[2]);
if (UsesPreRotation)
{
Rpre.GetMulplicationMatrix(&prerotationmatrix, &Rz);
Rt.GetMulplicationMatrix(&Rpre, &Ry);
rotationmatrix.GetMulplicationMatrix(&Rt, &Rx);
}
else
{
Rt.GetMulplicationMatrix(&Rz, &Ry);
rotationmatrix.GetMulplicationMatrix(&Rt, &Rx);
}
if (UsesPostRotation)
{
Rpost.GetMulplicationMatrix(&rotationmatrix, &postrotationmatrix);
rotationmatrix = Rpost;
}
translationmatrix.BuildTranslationMatrix(position);
//1.2. Create current model matrix (from stored matrix with rotation/translation)
m.GetMulplicationMatrix(translationmatrix, rotationmatrix);
modelmatrix.GetMulplicationMatrix(m, scalematrix);
}
答案 1 :(得分:-27)
根据Autodesk官方SDK中的the Transformations example code,节点在世界空间中的全局位置由CalculateGlobalTransform(FbxNode * pNode)函数递归计算,如下面的示例代码所示。需要注意的重要事项是,此功能不仅考虑旋转前后旋转,还考虑枢轴位置和偏移。 此外,根据节点的转换继承类型,转换公式也会更改。
如果从3ds Max导入模型,在计算节点的全局变换信息后,仍然必须将其与几何变换相乘,以便在全局坐标中找到节点属性的位置。
/*
Copyright (C) 2013 Autodesk, Inc.
Terminology:
Suffix "M" means this is a matrix, suffix "V" means it is a vector.
T is translation.
R is rotation.
S is scaling.
SH is shear.
GlobalRM(x) means the Global Rotation Matrix of node "x".
GlobalRM(P(x)) means the Global Rotation Matrix of the parent node of node "x".
All other transforms are described in the similar way.
The algorithm description:
To calculate global transform of a node x according to different InheritType,
we need to calculate GlobalTM(x) and [GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x))] separately.
GlobalM(x) = GlobalTM(x) * [GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x))];
InhereitType = RrSs:
GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x)) = GlobalRM(P(x)) * LocalRM(x) * [GlobalSHM(P(x)) * GlobalSM(P(x))] * LocalSM(x);
InhereitType = RSrs:
GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x)) = GlobalRM(P(x)) * [GlobalSHM(P(x)) * GlobalSM(P(x))] * LocalRM(x) * LocalSM(x);
InhereitType = Rrs:
GlobalRM(x) * (GlobalSHM(x) * GlobalSM(x)) = GlobalRM(P(x)) * LocalRM(x) * LocalSM(x);
LocalM(x)= TM(x) * RoffsetM(x) * RpivotM(x) * RpreM(x) * RM(x) * RpostM(x) * RpivotM(x)^-1 * SoffsetM(x) *SpivotM(x) * SM(x) * SpivotM(x)^-1
LocalTWithAllPivotAndOffsetInformationV(x) = Local(x).GetT();
GlobalTV(x) = GlobalM(P(x)) * LocalTWithAllPivotAndOffsetInformationV(x);
Notice: FBX SDK does not support shear yet, so all local transform won't have shear.
However, global transform might bring in shear by combine the global transform of node in higher hierarchy.
For example, if you scale the parent by a non-uniform scale and then rotate the child node, then a shear will
be generated on the child node's global transform.
In this case, we always compensates shear and store it in the scale matrix too according to following formula:
Shear*Scaling = RotationMatrix.Inverse * TranslationMatrix.Inverse * WholeTranformMatrix
*/
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;
}