クォータニオンが x 軸と y 軸でのみ移動するように制限する可能性はありますか (オイラーのヨーとピッチのように、ローリングなしで)? これを行うための方程式またはそれに似たものはありますか?
いくつかの例:
動きは次のように動作する必要があります: http://360.art.pl/experimental/1/
しかし、クォータニオンでプレーヤーを構築すると、制限がなく、http://360.art を修正する方法がわかりません。 pl/experimental/2/
クォータニオンが x 軸と y 軸でのみ移動するように制限する可能性はありますか (オイラーのヨーとピッチのように、ローリングなしで)? これを行うための方程式またはそれに似たものはありますか?
いくつかの例:
動きは次のように動作する必要があります: http://360.art.pl/experimental/1/
しかし、クォータニオンでプレーヤーを構築すると、制限がなく、http://360.art を修正する方法がわかりません。 pl/experimental/2/
ヨー/ピッチから直接クォータニオンを構築することができます。
q = quat_from_axis_angle(up_vector, yaw) * quat_from_axis_angle(local_right, pitch)
(回転行列に正確に変換する方法によっては、これらを逆の順序で乗算する必要がある場合があります)、または変更するたびに再調整する必要があります。
rotated_right = apply_rotation(q, local_right);
projected_right = rotated_right - dot(rotated_right, up_vector) * up_vector;
realign = quat_align_vector(rotated_right, normalized(projected_right));
q = realign * q
projected_right
rotated_right
これが水平面への投影です。ローリングしない場合、これら2つのベクトルは同じである必要があります。これはを意味しdot(rotated_right, up_vector) = 0
ます。最後の方程式は、満たさなければならない実際の制約です。で二次ですq
。たとえば、、、の場合local_right=(1,0,0)
は、にup_vector=(0,0,1)
なります。dot(q*(1i+0j+0k)*conj(q), 0i+0j+1k)=2*x*z-2*w*y=0
q=w+xi+yi+zk
http://en.wikipedia.org/wiki/Quaternionquat_from_axis_angle
およびhttp://en.wikipedia.org/wiki/Quaternions_and_spatial_rotationapply_rotation
の公式を見つけることができます。に関しては、1つの方法はquat_align_vector
quat_align_vector(src, dst) = sqrt([dot(src, dst), cross(src, dst)])
実数部と虚数部を持つ[a, b]
四元数を意味します。次のように計算できます(これらの関数もwikiにあります)。up-vectorをスムーズに復元するためにsqrtをに置き換えてみることもできます:)。または、逆の方法で式を少し単純化します。a
b
Sqrt(x)
exp(ln(x)/2)
exp(ln(x)/2*tick*realign_rate)
quat_align_vector(src, dst) = [dot(halfway, dst), cross(halfway, dst)],
halfway = normalized(normalized(src) + normalized(dst))
https://stackoverflow.com/a/1171995も参照してください。
編集:ベクトルを修正し、制約を追加しました。
まず、あなたが話している制約の種類について説明しましょう。ベクトルが与えられたworld_up
場合、カメラに対して垂直に見えるように回転を制限する必要があります。カメラビューの座標に、、、および:というラベルが付いcamera_up
てcamera_right
いるcamera_forward
場合
constrain rotation matrix R such that: dot(R*world_up, camera_right) == 0
これは、ビュー方向の関数として垂直座標ベクトルのセットを作成することにより、簡単に(たとえば、LookAt()
関数のように)実行できview_forward
ます。
given vectors: view_forward, world_up
Rot_forward = normalize(view_forward)
Rot_right = normalize( cross(view_forward, world_up) )
Rot_up = cross(Rot_right, Rot_forward)
質問に答えるには:私は間違っている可能性がありますが、この種の制約をクォータニオンの観点から実装するのは簡単ではないと思います。上記のように回転行列を生成し、それをクォータニオンに変換する方が簡単です。
ここでクォータニオンを使用してどのような問題を解決しようとしていますか?
view_forward
クォータニオンではなく、ベクトルを補間する方が自然です。