起こっている可能性のあることがいくつかあります。あなたはその四元数を再正規化することについて言及していません。あなたがそれをやっていないなら、間違ったことは間違いなく起こります。また、元の四元数に加算する前に、デルタ四元数のコンポーネントにdt
が合格した時間を乗算したとは言いません。あなたの角速度が毎秒ラジアンですが、ほんの一瞬だけ前へ進んでいるならば、あまりにも遠くに歩きます。しかし、そうであっても、あなたは離散的な時間を踏んで、それが極微量であるとふりそそうとしているので、特にあなたのタイムステップや角速度が大きい場合、奇妙なことが起こります。
物理エンジンは、ODEは、それが微小ステップを取っていたかのようにその角速度から体の回転を更新するか、有限の大きさのステップを使用して更新するためのオプションを提供します。有限のステップははるかに正確ですが、いくつかのトリグが必要です。関数は少し遅くなります。関連するODEのソースコードはhere, lines 300-321で、デルタクォータニオンのコードはhere, line 310です。これは、ゼロ除算の問題を回避するためにあなたを可能にし、まだ非常に正確である
if (fabs(x) < 1.0e-4) return (1.0) - x*x*(0.166666666666666666667);
else return sin(x)/x;
:sinc(x)
がある
float wMag = sqrt(wx*wx + wy*wy + wz*wz);
float theta = 0.5f*wMag*dt;
q[0] = cos(theta); // Scalar component
float s = sinc(theta)*0.5f*dt;
q[1] = wx * s;
q[2] = wy * s;
q[3] = wz * s;
。
q
四元は次に身体の向きの既存の四元数表現に予め乗算されます。次に、再正規化します。
編集 - この式から来ている:
初期四元q0
と時間の量dt
する角速度w
で回転させた後、その結果、最終的な四元q1
を考えます。ここでは、角速度ベクトルを四元数に変更し、その四元数で最初の方向を回転させるだけです。四元数および角速度は両方とも軸 - 角度表現の変化である。 q0 = [cos(theta/2) sin(theta/2)x sin(theta/2)y sin(theta/2)z]
:を[x,y,z]
軸部周りtheta
により、その正規の向きからを回転させて本体は、その向きの次の四元数表現を有することになります。 [x,y,z]
軸部の周囲にtheta/s
回転ある 体は、角速度w=[theta*x theta*y theta*z]
を有するであろう。したがって、どの回転がdt
秒を超えて発生するかを決めるために、最初に角速度の大きさを抽出します:theta/s = sqrt(w[0]^2 + w[1]^2 + w[2]^2)
。次に、実際の角度はdt
を掛けて(これを四元数に変換する際の便宜のために2で割ります)。軸[x y z]
を正規化する必要があるため、theta
で除算します。それはsinc(theta)
部分の由来です。 (theta
には、その大きさから余分な0.5*dt
があるので、それを増やします)。 sinc(x)
関数は、数値安定してより正確であるため、x
が小さい場合、関数のテイラー級数近似を使用しています。この便利な機能を使用する能力は、実際の大きさであるwMag
で除算しただけではありません。非常に速く回転しない物体は、非常に小さい角速度を有する。これがかなり一般的であると予想しているので、安定したソリューションが必要です。私たちが最終的に終わるのは、回転の単一のステップタイムステップdt
を表す四元数です。
期待どおりの結果が得られていないと言います。何がうまくいかないようですか? – JCooper
私は追跡にモデルを使用しており、安定していません –
"w"ベクトルに "delta time"がすでに乗算されていますか?この式は「デルタタイム」が小さい場合にのみ正しく動作します。 – minorlogic