2012-02-02 6 views
5

私のカメラは、向きを変えようとするとポイントを中心に回転します。私のカメラを回転させると、Y軸で30度のように、カメラが右に30度の角度を向くのではなく、見ていたポイントを中心にカメラが回転します。カメラがこの数式でポイントを中心に回転するのはなぜですか?

o is the camera, A and B are 3D models. The lines show line-of-sight. 
This is what I expect: 
    A B 
    | >/
    |/
    |/
    |/ 
    o 

This is what actually happens: 
    A B 
    |\ 
    | \ 
    | \ 
    | > \ 
      o 

私の理解から、カメラを動かすためには、その量の逆数で世界を動かす必要があります。ですから、私がZ軸で+1を動かしたいのであれば、私はZ軸の世界-1を変換します。私は方位を表現するために四元数を使用しているので、カメラの四元数の逆数を使います(方位は常に単位四元数であるため、逆数を計算する代わりに共役を使って最適化します)。ここで

私はqが反転四元で行列に四元数を変換する方法である:

[... ... ... -x] 
|... ... ... -y| 
|... ... ... -z| 
[0  0  0  1] 

そして最後に:その後

[1 - 2 * (q.y * q.y + q.z * q.z) 2 * (q.x * q.y - q.w * q.z)  2 * (q.x * q.z + q.w * q.y)   0] 
|2 * (q.x * q.y + q.w * q.z)  1 - 2 * (q.x * q.x + q.z * q.z) 2 * (q.y * q.z - q.w * q.x)   0| 
|2 * (q.x * q.z - q.w * q.y)  2 * (q.y * q.z + q.w * q.z)  1 - 2 * (q.x * q.x + q.y * q.y)  0| 
[0         0         0         1] 

、私は行列の変換コンポーネントを設定しますこれをモデルビューの行列スタックに乗算し、すべてのオブジェクトをレンダリングします。 私はこの数学が正しいと確信していますが、私が期待していた結果は得られません。明らかに前方ベクトルと右側ベクトルが問題なので、私の唯一の疑問はなぜ彼らが間違っているのか、そして私が期待している結果を得るためにはどうすればそれらを設定すべきかということです。ありがとう。

編集: 解決策はthis guy's quaternion camera classです。まず、私が前に行っていたような回転行列を作成しますが、その後、最初、2番目、3番目の列(xa、ya、za)から行列の列ベクトルを取り出します。

次に、結果の行列をmodelview行列スタックに乗算すると、完全に動作します。

+0

編集を行い、それを受け入れます。それがここで解決された質問に印を付ける方法です。また、あなたは何が起こっているのか説明するに値すると思います。私はこれに対する答えを書くだろう。 – datenwolf

答えて

1

編集:私はこの男のクォータニオンカメラクラスから解決策を見つけました。まず、前に行っていたように 回転行列を作成しますが、その後、最初の列、2番目の列、3番目の列(xa、、ya、za)から行列のベクトル を取り出します。

[... ... ... -xa.dotProduct(cameraPos)] 
|... ... ... -ya.dotProduct(cameraPos)| 
|... ... ... -za.dotProduct(cameraPos)| 
[... ... ... ...      ] 

次いで、得られたマトリックスは、モデルビュー行列 スタックに乗算することができ、それが完璧に動作:次に、私はこのような 行列の並進成分を設定します。

はい、これはまさに私が示唆したものであり、ちょっと違います。あなたは、OpenGLにはカメラがないことを理解する必要がありますが、代わりに世界を逆方向に移動するだけで、逆変換行列を見つける必要があります。

カメラはちょうど回転して動きます。これは物事を非常に簡単にします。平行移動の逆は逆符号のベクトルと同じであり、回転行列の逆数は転置行列(列と行の入れ替え)です。 OpenGLは、それらを使用するようになりました均一な変換マトリックスを見:

R t 
0 1 

3×3の左上は、回転部分である、右端の列は並進ベクトルです。私は残りの部分はすでにあなた自身を考え出したと思います。

0

実際、モジュールビューの行列に掛ける行列を見つけることは、実際には複雑で非常にエラーを起こしやすいです。混乱と特殊なケースがたくさんあります。たとえば、90度上を見ていると、2つの軸が同じになります。論理的な問題はこれです:あなたが頭を後ろに回しているなら、上の点を通過するので、あなたの上のベクトルは反転されなければなりません、そうですか?しかし、あなたが0.0001度それを見逃したら?あなたのアップベクトルがまだ上になるようにその点の周りにあなたの頭を回す必要があります。

私の意見では、最良の方法は別の観点から問題にアプローチすることです。 2つのケースを想定してみましょう:

  • 逆さま不可能:
    • お使いのカメラの位置と方向のための緯度/経度のためにポイントをおいてください。 シンプルなsin/cos演算で方向ベクトルを得ることができます。カメラ位置のほか
      • 、両方アップし、ターゲットベクトル保つ:あなたのアップベクトルは、(0、1、0)
      • 旋削は、単に緯度と経度逆さま可能
    • を変えることです。
    • 右回りにtarget xを計算し、次にtargetをx * right + y * upに変更します。
    • ターゲットベクトルを正規化して新たに計算する必要があります。しかし、多くの場合は を扱うケースがあります。これらのすべての後

、あなたは単にgluLookAtを呼び出します。

+0

"正直言って、行列をモジュールビュー行列に掛け合わせるのは本当に複雑でエラーが起こりやすいです。"いいえ、ちがいます。行列は、相対的な座標の方向性について考える最も明白な方法です。最初の3つの列のそれぞれは、変換された座標系の基底ベクトルの1つです。第4列は相対的な翻訳です。視点ベクトルとターゲットベクトルからカメラマトリックを書き留めておき、その間の三角関数を使って、はるかに簡単です。 – datenwolf

+0

私はそれを知っています。私が言っていることは、たとえば、次のフレームまで3種類の動き(移動、ねじれ、ロール)がある場合は、位置/緯度/経度でそれを行うのがずっと簡単で、各操作を前の行列に適用しようとするよりも、 – Shahbaz

関連する問題