1

キーフレームの代わりにトラック(カーブ)を使用して、スケルタルアニメーションシステムを最適化しようとしています。各曲線は特定のコンポーネントを処理し、(今のところ)値を線形補間します。私の骨の位置はうまく機能しますが、クォータニオンコンポーネント補間の「ジャジー」を取り除くのに苦労しています...

基本的に、各ボーンクォータニオンの各コンポーネント(XYおよびZ)に1つのカーブがあり、次のコードを使用してXYカーブとZカーブを個別に補間します。

// Simple lerp... (f is always a value between 0.0f and 1.0f)
return ( curve->data_array[ currentframe ].value * ( 1.0f - f ) ) +
       ( curve->data_array[ nextframe ].value * f );

クォータニオンXYZを補間するときは、次のコードを使用して、クォータニオンのWコンポーネントを再構築してから、正規化し、描画する前にボーンに影響を与えます。

Quaternion QuaternionW( const Quaternion q )
{
    Quaternion t = { q.x, q.y, q.z };

    float l = 1.0f - ( q.x * q.x ) - ( q.y * q.y ) - ( q.z * q.z );

    t.w = ( l < 0.0f ) ? 0.0f : -sqrtf( l );

    return t;
}

ボーンがときどきぎくしゃくすることを除いて、描画はきれいに見えますが、それは浮動小数点の精度によるものでしょうか?または、Wコンポーネントの再計算ですか?または、この方法でクォータニオンの各コンポーネントを線形補間する方法は絶対にありませんか?

ps:ちなみに、上記のコードを次のように置き換えると、曲線補間関数で次のようになります。

return curve->data_array[ currentframe ].value;

代わりに、または線形補間すると、すべてが正常です...したがって、データは明らかに正しいです...私は困惑しています...

[ 編集 ]

さらに調査した結果、問題はフレームデータに起因することがわかりました...つまり、次のようになりました。

Frame0:quat.x = 0.950497

フレーム1:quat.x = -0.952190

フレーム2:quat.x = 0.953192

これが反転とジャギーの原因です...私はこのケースを検出してデータの符号を反転しようとしましたが、一部のフレームが(描画時に視覚的に)単に奇妙に見えるため、問題を完全に修正することはできません。

曲線を適切に修正する方法はありますか?

4

2 に答える 2

2

あなたのデータはおそらく間違っていません。オリエンテーションのクォータニオン表現には、2倍冗長であるという面白い特性があります。クォータニオンの4つの要素すべてを無効にすると、同じ方向になります。クォータニオンを軸/角度表現と考えると、これは簡単にわかります。軸aを中心にΘだけ回転することは、軸-aを中心にだけ回転することと同じです。

それで、あなたはそれについて何をすべきです?前に述べたように、slerpは正しいことです。クォータニオンの向きは、ユニットの超球上に存在します。球上の点間を線形補間すると、球を離れます。ただし、ポイントが互いに接近している場合、それは大したことではないことがよくあります(ただし、後で再正規化する必要があります)。絶対に行う必要があるのは、2つのクォータニオンを補間する前に、それらの内積をチェックすることです。

k=q0[0]*q1[0] + q0[1]*q1[1] + q0[2]*q1[2] + q0[3]*q1[3];

の場合k<0、クォータニオンの1つを否定for (ii=0;ii<4;++ii) q1[ii]=-q1[ii]; します。これにより、円の周りの長い道のりを補間しようとしていないことが確認されます。ただし、これは、クォータニオンを部分的にではなく全体として処理する必要があることを意味します。クォータニオンがあいまいにならないようにサインが必要なため、1つのコンポーネントを完全に破棄することは特に問題があります。

于 2012-11-20T17:38:11.393 に答える
0

素朴な考慮事項

線形補間は、加法的に動作するもの、つまり、対応する操作を実行するたびに何かを追加するものには適しています。ただし、Queternionsは乗法性があります。つまり、Queternionsを乗算して連鎖させます。

このため、私は当初、次の計算を提案しました。

pow(secondQuaternion, f)*pow(firstQuaternion, 1. - f)

ウィキペディアには、とりわけ、クォータニオンの計算能力に関するセクションがあります。以下のコメントはこれは機能しないと述べているので、上記は参照用です。

適切な補間

この投稿を書いてから、slerp(球面線形補間)についてもう少し読んで、ウィキペディアにクォータニオンslerpに関するセクションがあることがわかりました。上記のあなたのコメントは、その用語がすでにあなたに馴染みがあることを示唆しています。公式は私が上で書いたものより少し複雑ですが、それでも力を使う方法のためにかなり関連しています。その式の利用可能な実装を適応または移植することによって、あなたが最善を尽くすと思います。たとえば、このページには少しのコードが含まれています。

データの修正

あなたの更新された質問に関して

曲線を適切に修正する方法はありますか?

正しいデータを維持しながらエラーを修正するには、どのような種類のエラーが発生するかをある程度理解する必要があります。したがって、可能であれば、そのエラーの原因を突き止めることから始めます。それを修正して正しいデータを生成できるのであれば、それで問題ありません。そうでない場合でも、何をいつ期待するかについてのより良いアイデアが得られるはずです。

于 2012-11-15T18:26:35.700 に答える