3x3 回転行列に問題があります。任意の既存の回転行列を調整して、回転を水平線にロックすることは可能ですか (ロールなし、ピッチとジョーのみ)? たとえば、一部のFPSのカメラのように、地平線を常に「水平」にする必要があります。
1 に答える
既存の回転行列を、必要に応じて制約された回転行列に変換することはできません (つまり、回転行列の右ベクトルは、常にワールド座標系の上軸に垂直な平面にあります)。変換方法を指定する必要があります。行うべきですか?既存の回転行列は、一連のベクトルを中心に回転して、必要な制約を取得できますが、それらはすべて異なる結果をもたらす可能性があります。
おそらく最も自然に回転するベクトルは、既存の回転行列の前方ベクトルですが、ワールド座標系の前方ベクトルまたは右ベクトルである可能性もあります。
既存の回転行列の前方ベクトルを中心に回転する例を示します。Xが右、Yが上、Zが後ろのデフォルトのOpenGL座標系のような座標系を使用していると仮定します。座標系が異なる場合は、調整する必要があります。
次のようにワールドからオブジェクトへの回転行列を作成します。
[r1 u1 b1]
[r2 u2 b2]
[r3 u3 b3]
、r*
、u*
およびb*
は、ワールド座標系で表された回転オブジェクト座標系のそれぞれ直交する右、上、および後方のベクトルです。
前述のように、ワールド座標系の上軸に垂直な平面に右ベクトルを拘束したいということr2
は、常に0
. に設定r2
する0
と、きれいな回転ではなく、非常に奇妙な変形が得られます。適切な平面で適切なベクトルを取得するために、回転する角度を見つける必要があります。
調整は次のようになります。
[nr1 nu1 nb1] [r1 u1 b1] [ar1 au1 ab1]
[nr2 nu2 nb2] = [r2 u2 b2] * [ar2 au2 ab2]
[nr3 nu3 nb3] [r3 u3 b3] [ar3 au3 ab3]
はa*
あなたの調整でn*
あり、あなたの新しい回転行列です。
a*
回転行列は基本的に、角度シータの前方ベクトル (Z 軸) を中心とした回転であり、ベクトルr*
をワールド座標系のアップ ベクトルに直交する平面に戻します。<r1, r2, r3>
そのシータは、との間のドット積によって計算できます<r1, 0, r3>
。
dotproduct(<r1, r2, r3>, <r1, 0, r3>) == length(<r1, r2, r3>) * length(<r1, 0, r3>) * cos(theta)
theta = acos(dotproduct(<r1, r2, r3>, <r1, 0, r3>) / (length(<r1, r2, r3>) * length(<r1, 0, r3>)))
次に、回転行列は、 Ora*
によって適用される単なる回転行列です。おそらく、最後の引数については、疲れすぎて今は考えられません。glRotate3f(theta, 0, 0, 1)
-1
ユーザー入力に対して独自のピッチおよびヨー アプリケーションを実行する場合は、インクリメンタル変換マトリックスを維持する代わりに、オブジェクトをレンダリングするフレームごとにワールドからオブジェクトへの回転マトリックスを計算する方がはるかに簡単であることに注意してください。 ) その場合、使用入力時にピッチとヨーの数値を調整してから、ピッチとヨーを正しい順序で適用するようにしてください。最初にヨーを行ってからピッチを適用します。逆にすると、副作用としてロールが発生します。