我可以通过在关键帧之间插值来使用assimp加载蒙皮模型的动画。现在,我一直试图从用户定义的转换矩阵中定向或定位骨骼,而不是仅仅从动画文件中加载骨骼。比如,将手臂旋转一定角度,其中角度将由用户指定。我将模型加载到它的绑定姿势中:
void recursion(aiNode* gNode)
{
std::string gNodeName(gNode->mName.data);
if(boneMapping.find(gNodeName) != boneMapping.end())
{
//if node corresponds to a bone,
Matrix4f boneMatrix = IdentityMatrix;
aiNode* tempNode = gNode;
//find combined transform of a bone
while(tempNode != NULL)
{
Matrix4f NodeMatrix(tempNode->mTransformation);
boneMatrix = NodeMatrix * boneMatrix;
tempNode = tempNode->mParent;
}
pBoneData[boneId].FinalTransform = GlobalInverseTransform * boneMatrix * pBoneData[boneId].OffsetMatrix;
}
for(int i = 0; i < gNode->mNumChildren; i++)
{ //repeat this process for child nodes
recursion(gNode->mChildren[i]);
}
}
为了使用变换矩阵定向模型的一个网格,我尝试搜索与网格的父骨相对应的骨骼名称,然后用所需的矩阵替换它的节点矩阵。然而,这根本不起作用,因为它使不同网格的骨骼变形。
右边的模型处于T姿势,我打算通过将颈部的骨骼旋转45度角来修改它,但它保持不变,腿部变形,如左侧模型所示。因此,任何指向现有文章或答案的链接都可能非常有用。
答案 0 :(得分:7)
我认为乘法矩阵的顺序在这一行中是错误的:
boneMatrix = NodeMatrix * boneMatrix;
它应该是:
boneMatrix = boneMatrix * NodeMatrix;
在OpenGL中,乘法的顺序是相反的。
虽然这种方法对我来说听起来不对:
while(tempNode != NULL)
{
Matrix4f NodeMatrix(tempNode->mTransformation);
boneMatrix = NodeMatrix * boneMatrix;
tempNode = tempNode->mParent;
}
您将局部变换乘以骨骼空间中的骨骼矩阵而不是世界空间。这就是你的角色出现变形的原因。
我使用assimp和OpenGL为我的动画项目解决了这个问题。通过将所有assimp信息保存到我自己的数据结构中,我使用了稍微不同的方法。 (骨架和骨头)。通过您的代码和您正在使用的数据结构,我猜您的代码基于此tutorial。
以下是我使用的代码,我确定您可以将其用于与您的实施进行比较:
glm::mat4 getParentTransform()
{
if (this->parent)
return parent->globalTransform;
else
return glm::mat4(1.0f);
}
void updateSkeleton(Bone* bone = NULL)
{
bone->globalTransform = bone->getParentTransform() // This retrieve the transformation one level above in the tree
* bone->transform //bone->transform is the assimp matrix assimp_node->mTransformation
* bone->localTransform; //this is your T * R matrix
bone->finalTransform = inverseGlobal // which is scene->mRootNode->mTransformation from assimp
* bone->globalTransform //defined above
* bone->boneOffset; //which is ai_mesh->mBones[i]->mOffsetMatrix
for (int i = 0; i < bone->children.size(); i++) {
updateSkeleton (&bone->children[i]);
}
}
编辑:
对于从Assimp到glm的矩阵转换,我使用了这个函数:
inline glm::mat4 aiMatrix4x4ToGlm(const aiMatrix4x4* from)
{
glm::mat4 to;
to[0][0] = (GLfloat)from->a1; to[0][1] = (GLfloat)from->b1; to[0][2] = (GLfloat)from->c1; to[0][3] = (GLfloat)from->d1;
to[1][0] = (GLfloat)from->a2; to[1][1] = (GLfloat)from->b2; to[1][2] = (GLfloat)from->c2; to[1][3] = (GLfloat)from->d2;
to[2][0] = (GLfloat)from->a3; to[2][1] = (GLfloat)from->b3; to[2][2] = (GLfloat)from->c3; to[2][3] = (GLfloat)from->d3;
to[3][0] = (GLfloat)from->a4; to[3][1] = (GLfloat)from->b4; to[3][2] = (GLfloat)from->c4; to[3][3] = (GLfloat)from->d4;
return to;
}
希望它有所帮助。