C++ 如何旋转蒙皮模型&x27;c++;使用ASIMP?

C++ 如何旋转蒙皮模型&x27;c++;使用ASIMP?,c++,opengl,matrix,rotation,assimp,C++,Opengl,Matrix,Rotation,Assimp,我可以通过在关键帧之间插值,使用assimp加载蒙皮模型的动画。现在,我一直在尝试从用户定义的变换矩阵中确定骨骼的方向或位置,而不仅仅是从动画文件中加载骨骼。例如,将手臂旋转一定角度,该角度由用户指定。我以绑定姿势加载模型,如下所示: void recursion(aiNode* gNode) { std::string gNodeName(gNode->mName.data); if(boneMapping.find(gNodeName) != boneMapping.end())

我可以通过在关键帧之间插值,使用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]);
 }
}
void递归(aiNode*gNode)
{
std::字符串gNodeName(gNode->mName.data);
if(boneMapping.find(gNodeName)!=boneMapping.end()
{
//如果节点对应于骨骼,
Matrix4f boneMatrix=IdentityMatrix;
aiNode*tempNode=gNode;
//找到骨骼的组合变换
while(tempNode!=NULL)
{
Matrix4f节点矩阵(tempNode->MTTransformation);
boneMatrix=节点矩阵*boneMatrix;
tempNode=tempNode->mParent;
}
pBoneData[boneId].FinalTransform=GlobalInverseTransform*boneMatrix*pBoneData[boneId].OffsetMatrix;
}
对于(int i=0;imNumChildren;i++)
{//对子节点重复此过程
递归(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;
}
将局部变换与骨骼空间中的骨骼矩阵相乘,而不是与世界空间中的骨骼矩阵相乘。这就是为什么你的角色看起来变形了

我使用ASIMP和OpenGL为我的动画项目解决了这个问题。我使用了一种稍有不同的方法,将所有assimp信息保存到自己的数据结构中。(骨骼)。从你的代码和你正在使用的数据结构来看,我猜你的代码就是基于这个

这是我使用的代码,我相信您可以使用它与您的实现进行比较:

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

希望能有所帮助。

“boneId”是骨头的boneIndex,如果有人想知道它有什么好运气的话?如果有效,请将问题标记为已回答。谢谢您的回答。是的,我遵循了你上面提到的教程,它使用了与你类似的方法。但是assimp矩阵是行主矩阵,而opengl使用列主矩阵。你是否在两者之间进行了转换以生成相同类型的所有矩阵?是的,我进行了转换,我将编辑我的答案,添加来自assimp的转换矩阵,以便您可以进行比较,只是为了确保,你已将node->mTranformation更改为glm::mat4,对吗?是的,为了使用glm,我转换了assimp矩阵。虽然您使用相同的方法将矩阵转换为矩阵,但它不会将骨骼从当前“骨骼”转换到层次结构的底部。例如,如果“骨”靠近根骨的某个地方,它不会在继承权中变换它下面的所有骨骼。
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;
}