2

現在、ASSIMP ライブラリを使用して 3D OpenGL ゲーム エンジンにスケルタル アニメーションを実装していますが、残念ながらうまくいきません。私が現在直面している問題は、連結されたボーン トランスフォーム (ボーン間の親子関係) が、1 つの親のみがトランスフォームされている場合にのみ正しく動作することです。

何が起こるかというと、太もものボーンの変換が、骨盤のローカル軸ではなくグローバル軸で実行されるということです。

ここに私のスケルトンクラスがあります:

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

ありがとうございました!

4

1 に答える 1

1

だから私はそれを修正しました。

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 チャンネル: RealityMultiplied で私に連絡できます。

ASSIMP を使用してスケルトン アニメーションを行う方法に関するチュートリアル シリーズの作業を開始する予定です。そのため、今夜までに最初のビデオをアップしたいと考えています。

始めたばかりの人にとって、これが理解しやすいトピックになることを願っています.

編集: それで私はチュートリアルに取り組み始めましたが、私は今私の人生で多くの困難を経験しており、それらを完了することができるとは思いません. 少しでもお役に立てば幸いです。それ以上のことができず申し訳ありません。

http://realitymultiplied.blogspot.mx/

于 2016-03-18T23:18:14.463 に答える