私はイライラするほど、WebGL での骨格アニメーションの作業に近づいています。
バックグラウンド
無料で入手したゾンビウォークアニメーションのモデルがあります。すべてを 1 つの Collada ファイルにまとめてダウンロードしました。すべての頂点、法線、ジョイント インフルエンス インデックス/ウェイト、およびジョイント マトリックスを取得するためのパーサーを作成しました。次のようにして、キャラクターをバインド ポーズでレンダリングできます。
joints[i].skinning_matrix = MatrixMultiply(joints[i].inverse_bind_pose_matrix, joints[i].world_matrix);
ここで、ジョイントのワールド マトリックスは、ジョイントの bind_pose_matrix に親のワールド マトリックスを掛けたものです。次のようにして、inverse_bind_pose_matrix を取得しました。
joints[i].inverse_bind_pose_matrix = MatrixInvert(joints[i].world_matrix);
つまり、キャラクターをバインド ポーズでレンダリングすることは、アイデンティティ マトリックスをシェーダーに渡すだけなので、その部分をまったく正しく行っていない可能性があります。しかし、私が計算した逆バインド ポーズ マトリックスは、Collada ファイルによって提供されたものとほぼ同じであるため、それらが適切であると確信しています。
バインド ポーズのモデルは次のとおりです。
問題
先に進み、アニメーションの 1 つのフレームを使用してスキニング マトリックスを計算しようとすると (フレーム 10 をランダムに選択しました)、それでも男性に似ていますが、何かが明らかに間違っています。
最初に計算したのと同じ inverse_bind_pose_matrix を使用しています。代わりに、各ジョイントのキーフレーム/アニメーション マトリックスをその親の新しいワールド マトリックスで乗算することによって計算された、新しいワールド マトリックスを使用しています。
コードベース全体のどこでも転置を行っていませんが、マトリックスのほとんどすべての組み合わせを転置しようとしても無駄でした。
これが彼のアニメーション フレーム 10 ポーズの私のモデルです。
関連するコード
頂点シェーダー:
attribute float aBoneIndex1;
// up to aBoneIndex5
attribute float aBoneWeight1;
// up to aBoneWeight5
uniform mat4 uBoneMatrices[52];
void main(void) {
vec4 vertex = vec4(0.0, 0.0, 0.0, 0.0);
vertex += aBoneWeight1 * vec4(uBoneMatrices[int(aBoneIndex1)] * aPosition);
vertex += aBoneWeight2 * vec4(uBoneMatrices[int(aBoneIndex2)] * aPosition);
vertex += aBoneWeight3 * vec4(uBoneMatrices[int(aBoneIndex3)] * aPosition);
vertex += aBoneWeight4 * vec4(uBoneMatrices[int(aBoneIndex4)] * aPosition);
vertex += aBoneWeight5 * vec4(uBoneMatrices[int(aBoneIndex5)] * aPosition);
// normal/lighting part
// the "/ 90.0" simply scales the model down, problem persists without it.
gl_Position = uPMatrix * uMVMatrix * vec4(vertex.xyz / 90.0, 1.0);
}
私のパーサー全体をGitHubで見ることができます (本当に必要な場合は...) 。モデルはここでライブで見ることができます。