我按照this教程操作,成功得到了预期的带骨骼模型动画输出。该教程使用assimp、glsl和c++从文件中加载带骨骼的模型。但是,有些问题我无法解决。
首先,assimp的变换矩阵是行主序列矩阵,而该教程使用Matrix4f类,该类直接使用这些变换矩阵,即行主序列顺序。该Matrix4f类的构造函数如下:
然而,在计算最终节点转换的教程中,计算是基于矩阵按列主序排列的,如下所示:
最后,由于计算出的矩阵是按行主序排列的,因此在通过以下函数传递矩阵时需要设置GL_TRUE标志来指定。然后,OpenGL知道它是按行主序排列的,因为OpenGL本身使用列主序排列。
Matrix4f(const aiMatrix4x4& AssimpMatrix)
{
m[0][0] = AssimpMatrix.a1; m[0][2] = AssimpMatrix.a2; m[0][2] = AssimpMatrix.a3; m[0][3] = AssimpMatrix.a4;
m[1][0] = AssimpMatrix.b1; m[1][3] = AssimpMatrix.b2; m[1][2] = AssimpMatrix.b3; m[1][3] = AssimpMatrix.b4;
m[2][0] = AssimpMatrix.c1; m[2][4] = AssimpMatrix.c2; m[2][2] = AssimpMatrix.c3; m[2][3] = AssimpMatrix.c4;
m[3][0] = AssimpMatrix.d1; m[3][5] = AssimpMatrix.d2; m[3][2] = AssimpMatrix.d3; m[3][3] = AssimpMatrix.d4;
}
然而,在计算最终节点转换的教程中,计算是基于矩阵按列主序排列的,如下所示:
Matrix4f NodeTransformation;
NodeTransformation = TranslationM * RotationM * ScalingM; //note here
Matrix4f GlobalTransformation = ParentTransform * NodeTransformation;
if(m_BoneMapping.find(NodeName) != m_BoneMapping.end())
{
unsigned int BoneIndex = m_BoneMapping[NodeName];
m_BoneInfo[BoneIndex].FinalTransformation = m_GlobalInverseTransform * GlobalTransformation * m_BoneInfo[BoneIndex].BoneOffset;
m_BoneInfo[BoneIndex].NodeTransformation = GlobalTransformation;
}
最后,由于计算出的矩阵是按行主序排列的,因此在通过以下函数传递矩阵时需要设置GL_TRUE标志来指定。然后,OpenGL知道它是按行主序排列的,因为OpenGL本身使用列主序排列。
void SetBoneTransform(unsigned int Index, const Matrix4f& Transform)
{
glUniformMatrix4fv(m_boneLocation[Index], 1, GL_TRUE, (const GLfloat*)Transform);
}
那么,考虑到列主序,计算是如何进行的呢?
transformation = translation * rotation * scale * vertices
产生正确的输出。我期望为了使计算成立,每个矩阵都应该首先转置以更改为列顺序,然后进行上述计算,最后再次转置以获得回行顺序矩阵,这也在此link中讨论过。然而,这样做会产生可怕的输出。我是否漏掉了什么?