2017-02-06 6 views
2

私は新しいビデオゲームを開発しており、骨格アニメーションで約5週間ブロックされています。私は問題を絞り込んだと信じていますが、私が実際に間違っていることを理解することはできません。骨格アニメーションの頂点を変換するにはどうすればよいですか?

私は内部に4本の骨を持つ単純な12頂点の長方形のオブジェクトを持っています。 This imageは、バインドポーズでオブジェクトがどのように見えるか、オブジェクトがY軸の周りに90度回転したトップボーンで好きなものを示します。私のアプリケーションで骨重量をテストするには、私が使っている簡単な例です。私のアプリケーションでは、プログラム上、トップボーンを90度回転させ、シェーダにレンダリングさせます。

残念ながら、私のアプリケーションでは同じ結果が得られません。バインドポーズは正しく表示されますが、トップボーントランスフォームが適用されると、トランスフォームは誇張され、矩形の上部は単にボーンを回転させる方向に伸びます。

私は次のことを確認しました:

  • 骨は、相対的な変換としてシェーダ均一に送信されます。これは、上の骨を90°回転させると、骨1〜3はすべて同一性であり、骨4はY軸に沿って90度だけ回転する行列であることを意味します。
  • ボーンは任意の頂点に対して適切に重み付けされています(少なくとも、私のアプリケーションではBlenderが報告したものと同じに重み付けされています)。

私はこの単一の健全性チェックに問題を減らしました。上の最初のスクリーンショットを参照して、私は私の骨の方法を使用して変換する頂点を選択しました。 1つの小さな頂点:-0.5、-0.5、4.0。すべてを適切に適用すると仮定すると、骨はこの頂点を-0.95638、-0.5、2.63086に変換する必要があります。デバッグを容易にするために、私は私の頂点シェーダ...

#version 330 core 
layout (location = 0) in vec3 position; // The position variable has attribute position 0 
layout (location = 1) in vec3 normal; // This is currently unused 
layout (location = 2) in vec2 texture; 
layout (location = 3) in ivec4 boneIDs; 
layout (location = 4) in vec4 boneWeights; 

out vec2 fragTexture; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 

uniform mat4 bones[ 16 ]; 

void main() 
{ 
    mat4 boneTransform = 
    (bones[ boneIDs[ 0 ] ] * boneWeights[ 0 ]) + 
    (bones[ boneIDs[ 1 ] ] * boneWeights[ 1 ]) + 
    (bones[ boneIDs[ 2 ] ] * boneWeights[ 2 ]) + 
    (bones[ boneIDs[ 3 ] ] * boneWeights[ 3 ]); 

    mat4 mvp = projection * view * model; 
    gl_Position = mvp * boneTransform * vec4(position, 1.0f); 

    fragTexture = texture; 
} 

を取り...そしてちょうど私のテスト頂点を変換するために作られた以下のこの単純なユニットテスト形式の関数、にそれを入れています。

glm::mat4 id(1.0f); // ID 0 
glm::mat4 bone(1.0f); // ID 1 
glm::mat4 bone002(1.0f); // ID 2 
glm::mat4 bone003(1.0f); // ID 3 

// Keyframe is set to rotate bone003 -89.113 degrees along Y 
bone003 *= glm::toMat4(glm::angleAxis((float)glm::radians(-89.113), glm::vec3(0.0f, 1.0f, 0.0f))); 

glm::mat4 xform = 
    (bone002 * 0.087f) + 
    (bone003 * 0.911f) + 
    (id * 0) + 
    (id * 0); 

glm::vec4 point = xform * glm::vec4(glm::vec3(-0.5f, -0.5f, 4.0f), 1.0f); 

このコードは、上記の4つのmat4sは骨である私の頂点シェーダの状態、[0]の骨を介して[3]をシミュレートします。 bone003は、Bone.003を変換してその逆バインドを削除した後、シェーダに送信されるものです。私の現在の骨格アニメーションの理解と、Blenderからの関連するすべてのウェイト/値のマッチングに合わせて正確にはですが、頂点(-0.5、-0.5,4.0)はナンセンス値(-3.694115、-0.499000、 -0.051035)。数学は正しいです、値は一致しますが、答えはすべて間違っています。

私の実際の質問には、ここで私は骨変換の影響によってメッシュの頂点を変えるのが間違っていますか?ここで私の骨格アニメーションの理解は間違っていますか?

答えて

1

これは私には間違っているようだ:

mat4 boneTransform = 
    (bones[ boneIDs[ 0 ] ] * boneWeights[ 0 ]) + 
    (bones[ boneIDs[ 1 ] ] * boneWeights[ 1 ]) + 
    (bones[ boneIDs[ 2 ] ] * boneWeights[ 2 ]) + 
    (bones[ boneIDs[ 3 ] ] * boneWeights[ 3 ]); 

あなたはとすべての骨基質を(骨空間での)頂点を乗算し、そのように、重みの世話をして一緒に結果のベクトルを追加する必要があります

vec4 temp = vec4(0.0f, 0.0f, 0.0f, 0.0f); 
vec4 v = vec4(position, 1.0f); 
temp += (bones[boneIDs[0]] * v) * boneWeights[0]; 
temp += (bones[boneIDs[1]] * v) * boneWeights[1]; 
temp += (bones[boneIDs[2]] * v) * boneWeights[2]; 
temp += (bones[boneIDs[3]] * v) * boneWeights[3]; 

// temp is now the vector in local space that you 
// transform with MVP to clip space, or whatever 

この機能が動作するかどうか教えてください。

EDIT:そうは思わない。よし:

頂点(-0.5、-0.5、4.0)は(-3.694115、-0.499000、-0.051035)

のナンセンス値に変換されて、本当にナンセンスということですか? Y軸の周りに時計回りに90度回転すると、私はちょうどそれを目玉にするとその値を与えます。あなたのテストは「正しい」です。この時点で、私は骨の階層に問題があると思ったり、キーフレームの補間に問題があると考え始めています。

+0

残念ながら、これは同じ(不正確な)結果を生成します。 – ne0ndrag0n

関連する問題