我可以通过在关键帧之间进行插值来使用assimp加载外观模型的动画。现在,我一直在尝试从用户定义的变换矩阵定向或定位骨骼,而不是仅仅从动画文件中加载骨骼。就像将 ARM 旋转一定角度,该角度将由用户指定。我在绑定(bind)姿势中将模型加载为:

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度角来对其进行修改,但是如左图所示,它保持不变并且腿部变形了。因此,任何指向现有文章或答案的链接都将非常有帮助。

最佳答案

我认为乘法矩阵的顺序在这一行中是错误的:

boneMatrix =  NodeMatrix * boneMatrix;

它应该是:
boneMatrix = boneMatrix * NodeMatrix;

在OpenGL中,乘法顺序相反。

尽管这种方法对我来说听起来并不正确:
while(tempNode != NULL)
{
    Matrix4f NodeMatrix(tempNode->mTransformation);
    boneMatrix =  NodeMatrix * boneMatrix;
    tempNode = tempNode->mParent;
}

您正在将局部变换乘以骨骼空间而不是世界空间中的骨骼矩阵。这就是为什么您的角色看起来变形了的原因。

我使用assimp和OpenGL为动画项目解决了这个问题。我通过将所有asimp信息保存到自己的数据结构中使用了稍微不同的方法。 (骨骼和骨头)。从您的代码和所使用的数据结构的外观来看,我想您是基于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;
}

希望能帮助到你。

10-08 15:28