简体   繁体   English

如何使用assimp在c ++中旋转蒙皮模型的骨骼?

[英]How to rotate a skinned model's bones in c++ using assimp?

I could load an animation of a skinned model using assimp by interpolating between key-frames. 我可以通过在关键帧之间插值来使用assimp加载皮肤模型的动画。 Now, I have been trying to orient or position bones from a user defined transformation matrix instead of just loading it from an animation file. 现在,我一直试图从用户定义的转换矩阵中定向或定位骨骼,而不是仅仅从动画文件中加载骨骼。 Like, rotating an arm by a certain angle in which the angle would be specified by the user. 比如,将手臂旋转一定角度,其中角度将由用户指定。 I loaded the model in it's bind pose as: 我将模型加载到它的绑定姿势中:

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]);
 }
}

To orient one of the meshes of a model using transformation matrix, I tried searching for name of the bone that corresponds to the parent-bone of the mesh and then replace it's node matrix with the required matrix. 为了使用变换矩阵定向模型的一个网格,我尝试搜索与网格的父骨相对应的骨骼名称,然后用所需的矩阵替换它的节点矩阵。 However, that didn't work at all as it deformed a bone at a different mesh. 然而,这根本不起作用,因为它在不同的网格处使骨骼变形。

在此输入图像描述

The model to the right is in T pose and I intended to modify it by rotating the bone at the neck by a 45 deg angle, but it remained the same and the leg portion got deformed as seen in model to the left. 右边的模型是T姿势,我打算通过将颈部的骨头旋转45度角来修改它,但它保持不变,腿部变形,如左侧模型所示。 So, any links to existing articles or answers could be really helpful. 因此,任何现有文章或答案的链接都可能非常有用。

I think the order of the multiplication matrix is wrong in this line: 我认为乘法矩阵的顺序在这一行是错误的:

boneMatrix =  NodeMatrix * boneMatrix;

it should be: 它应该是:

boneMatrix = boneMatrix * NodeMatrix;

In OpenGL the order of multiplication is reversed. 在OpenGL中,乘法的顺序是相反的。

Although this approach doesn't sound right to me: 虽然这种方法对我来说听起来不对:

while(tempNode != NULL)
{
    Matrix4f NodeMatrix(tempNode->mTransformation);
    boneMatrix =  NodeMatrix * boneMatrix;
    tempNode = tempNode->mParent;
}

you are multiplying your local transformation by the bone matrix in bone space and not in world space. 您将局部变换乘以骨骼空间中的骨骼矩阵而不是世界空间。 This is why your character appears deformed. 这就是你的角色出现变形的原因。

I solved this problem for my animation project, using assimp and OpenGL. 我使用assimp和OpenGL为我的动画项目解决了这个问题。 I used a slightly different approach by saving all assimp information into my own data structure. 通过将所有assimp信息保存到我自己的数据结构中,我使用了稍微不同的方法。 (skeleton and bones). (骨架和骨头)。 By the look of your code and the data structure you are using I guess you are basing your code upon this tutorial . 通过您的代码和您正在使用的数据结构的外观,我猜您将基于本教程的代码。

Here is the code I used, I'm sure you can use it to compare with your implementation: 这是我使用的代码,我相信你可以用它来与你的实现进行比较:

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]);
    }
}

EDIT: 编辑:

For matrix conversion from Assimp to glm I used this function: 对于从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;
}

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM