バックグラウンド:
私は現在、GLSL でスケルタル アニメーション シェーダーを実装しています。スペースと複雑さを節約するために、ボーンの回転にクォータニオンを使用し、(各ボーンの) 加重クォータニオン乗算を使用して、各頂点の「最終的な回転」を蓄積しています。
次のようなもの: (疑似コード、四元数の計算が期待どおりに機能すると仮定してください)
float weights[5];
int bones[5];
vec4 position;
uniform quaternion allBoneRotations[100];
uniform vec3 allBonePositions[100];
main(){
quaternion finalQuaternion;
for(i=0;i<5;i++){finalQuaternion *= allBoneRotations[bones[i]]*weights[i];}
gl_position = position.rotateByQuaternion(finalQuaternion);
}
実際のコードは複雑で、ずさんで、期待どおりに動作しますが、これは一般的な考え方を示しているはずです。とにかく、これは主に数学の問題であり、コードはあまり重要ではなく、わかりやすくするために提供されているだけです。
問題:
「ピボット ポイント」/「ジョイント位置」を各ボーンに追加する過程にありました (負の変換、「最終クォータニオン」による回転、逆変換)。「最終クォータニオン」が異なるピボット ポイントを取得していないことに気付きました。クォータニオン自体を組み合わせるときに考慮に入れます。この場合、各ボーンの回転は、ポイント (0,0,0) の周りにあるかのように処理されます。
クォータニオンが回転のみを表すことを考えると、(可能であれば) クォータニオンに位置を「追加」するか、単にすべてのクォータニオンを行列に変換し、行列の乗算を行って一連の平行移動と回転。比較的効率が悪いように見えるので、後者が必要ないことを本当に望んでいます。
mathoverflow、math.stackexchange、および Google が提供するその他の情報を検索し、自分で答えを見つけられることを期待して、これまでに次のリソースを読みました。
さらに、Google で見つけたさまざまな小さなディスカッション (リンクは 2 つしか投稿できません)
コンセンサスは、クォータニオンはいかなる意味でも「変換」または「位置」をエンコードせず、それをシミュレートする直感的な方法を提供しないように思われるため、純粋なクォータニオン数学は実行可能なソリューションではないようです.
ただし、ここでこれに対する決定的な答えがあるとよいでしょう。クォータニオンの位置コンポーネントを「偽造」する方法、クォータニオンの数学効率を維持する方法、または単に行列を計算するよりも効率的な異なる原点の周りの回転を「累積」する他の方法を知っている人はいますか?クォータニオンのすべてのクォータニオンに対して行列の変換と回転の乗算を行いますか? あるいは、異なるピボットポイントが実際には何の違いももたらさず、実際には後で適用できるという数学的な保証もあります (しかし、私はそれを疑っています)。
それとも、この状況でクォータニオンを使用するのは一見悪い考えですか?