6

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

変換マトリックスを使用してモデルのメッシュの 1 つを方向付けるために、メッシュの親ボーンに対応するボーンの名前を検索して、そのノード マトリックスを必要なマトリックスに置き換えてみました。しかし、別のメッシュでボーンを変形させたため、まったく機能しませんでした。

ここに画像の説明を入力

右のモデルは T ポーズで、首のボーンを 45 度回転させて修正するつもりでしたが、そのままで左のモデルのように脚の部分が変形してしまいました。そのため、既存の記事や回答へのリンクは非常に役立ちます。

4

1 に答える 1

10

この行では、乗算行列の順序が間違っていると思います。

boneMatrix =  NodeMatrix * boneMatrix;

そのはず:

boneMatrix = boneMatrix * NodeMatrix;

OpenGL では、乗算の順序が逆になります。

このアプローチは私には正しく聞こえませんが:

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

ローカル変換に、ワールド空間ではなくボーン空間のボーン マトリックスを乗算しています。これが、キャラクターが変形して見える理由です。

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

編集:

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

それが役に立てば幸い。

于 2015-03-21T15:37:45.273 に答える