目前,我正在使用ASSIMP库在我的3D OpenGL游戏引擎中实现骨骼动画,但不幸的是,进展并不顺利。
我当前面临的问题是,仅在变换一个父对象时,级联的骨骼变换(骨骼之间的父子关系)才能正确执行。

发生的是thigh's bone transformation is carried out on global axes instead of the pelvis' local axes.

这是我的骨架类(class):

class Skeleton
{
public:
    Skeleton();

    unsigned int numBones;
    std::vector<std::string> names;
    std::vector<glm::mat4> offsets;


    std::vector<glm::mat4> transforms;
    std::vector<int> parents;

    std::string GetName(int bone);
    glm::mat4 GetWorldTransform(int bone);
    int GetID(std::string bone_name);
};

这是我用来计算每个骨骼的世界变换的函数:
glm::mat4 Skeleton::GetWorldTransform(int bone)
{
int p = parents[bone];
glm::mat4 result = glm::mat4(1.0);

result *= glm::inverse(offsets[bone]);
    result *= transforms[bone];
result *= offsets[bone];

while(p >= 0)   //The root bone has a parent of -1
{
    result *= glm::inverse(offsets[p]);
        result *= transforms[p];    //Apply The Parent's Transform
    result *= offsets[p];

    p = parents[p];
}
return result;
}

在我的Mesh类中,我具有以下功能UpdateSkeleton():
void Mesh::UpdateSkeleton(unsigned int shaderID)
{
std::vector<glm::mat4> mats;

for(int i = 0; i < skeleton->numBones; i++)
{
    glm::mat4 matrix = glm::mat4(1.0);
        matrix *= skeleton->GetWorldTransform(i);
    mats.push_back(matrix);
}

if(mats.size() > 0)
    glUniformMatrix4fv(glGetUniformLocation(shaderID,"gBones"),mats.size(),GL_FALSE,glm::value_ptr(mats[0]));
}

谢谢!

最佳答案

所以我修好了。

https://www.youtube.com/playlist?list=PLi9hkiiZDonvUcT_FRD8rJtuuGltL3xys

基本上问题是串联是以相反的顺序进行的,我最初是这样进行的:

void Bone::UpdateParentTransform()
{
    parent_transform = glm::mat4(1.0);

    Node* node_id = parent_node;

    while(node_id != nullptr)
    {
        Bone* bone = mesh->FindBone(node_id->name);

        if(bone != nullptr)
        {
            parent_transform *= glm::inverse(bone->offset_matrix);
                parent_transform *= node_id->transformation;
            parent_transform *= (bone->offset_matrix);
            node_id = bone->parent_node;
        }
        else
            node_id = nullptr;
    }
}

现在,我将它们按相反的顺序执行,如下所示:
void Bone::UpdateParentTransform()
{
    parent_transform = glm::mat4(1.0);

    Node* node_id = node;

    std::vector<Bone*> bones;
    std::vector<Node*> parents;

    while(node_id != nullptr)
    {
        Bone* bone = mesh->FindBone(node_id->name);

        if(bone != nullptr)
        {
            bones.push_back(bone);
            parents.push_back(node_id);

            node_id = bone->parent_node;
        }
        else
            node_id = nullptr;
    }


    for(int i = parents.size()-1; i > 0; i--)
    {
        parent_transform *= glm::inverse(bones.at(i)->offset_matrix);
            parent_transform *= parents.at(i)->transformation;
        parent_transform *= (bones.at(i)->offset_matrix);
    }

}

如果您对此有任何疑问,或者对使用ASSIMP的骨骼动画有其他疑问,请随时与我联系,您可以在这里或在我的YouTube channel 上与我联系:RealityMultiplied

我现在将开始制作有关如何使用ASSIMP进行骨骼动画的教程系列,因此我希望在今晚之前制作第一个视频。

我希望这对于刚开始的人们来说是一个容易理解的话题,因为它看起来令人生畏,而且总体而言太可怕了。

编辑:
因此,我开始研究这些教程,但是现在我生活中经历了很多艰难的时刻,我认为我无法完成这些教程。
我希望他们至少能有所帮助,对不起,我不能做更多的事情。

http://realitymultiplied.blogspot.mx/

关于c++ - Assimp蒙皮全局转换,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35952202/

10-13 06:11