web-dev-qa-db-ja.com

LookAtマトリックスの計算

私は3Dエンジンを書いている最中で、DirectXのドキュメントで説明されているLookAtアルゴリズムに出会いました。

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

 xaxis.x           yaxis.x           zaxis.x          0
 xaxis.y           yaxis.y           zaxis.y          0
 xaxis.z           yaxis.z           zaxis.z          0
-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  l

回転側でどのように機能するかはわかりましたが、マトリックスの変換コンポーネントをそれらのドット積にする理由はわかりません。少し調べてみると、目/カメラの位置への新しい基底ベクトルの投影に基づいて、カメラの位置を少し調整しているようです。

問題は、なぜこれを行う必要があるのか​​ということです。それは何を達成しますか?

37
Daemin

ここで行ったように3x3回転マトリックスを作成し、右下隅にゼロと単一の1を含む4x4に展開することにより、look-atマトリックスを作成します。次に、負の視点の座標(ドット積なし)を使用して4x4の変換行列を作成し、2つの行列を乗算します。私の推測では、この乗算はあなたの例の一番下の行のドット積に相当しますが、紙の上でそれを確認して確認する必要があります。

3D回転は軸を変換します。したがって、アイポイントをこの新しい座標系に変換せずに直接使用することはできません。これが、行列の乗算(この場合は3つの内積値)が達成することです。

18
Judge Maygarden

指定された例は左利きの行主行列であることに注意してください

したがって、操作は次のとおりです。まず原点に移動し(-eyeで移動)、次に回転して、ベクトルがeyeからAt行上になるようにします+ zを使用:

基本的に、回転行列に平行移動-eyeを事前乗算すると、同じ結果が得られます。

 [1 0 0 0] [xaxis.x yaxis.x zaxis.x 0] 
 [0 1 0 0] * [xaxis.y yaxis.y zaxis.y 0] 
 [0 0 1 0] [xaxis.z yaxis.z zaxis.z 0] 
 [-eye.x -eye.y -eye.z 1] [0 0 0 1] 
 
 [xaxis.x yaxis.x zaxis.x 0] 
 = [xaxis.y yaxis.y zaxis.y 0] 
 [xaxis.z yaxis.z zaxis。 z 0] 
 [dot(xaxis、-eye)dot(yaxis、-eye)dot(zaxis、-eye)1] 

その他の注意事項:

表示変換は(意図的に)反転であることに注意してください。すべての頂点にこのマトリックスを掛けて「世界を移動」し、見たい部分が標準的なビューボリュームに収まるようにします。

また、LookAtマトリックスの回転マトリックス([〜#〜] r [〜#〜]と呼ばれる)コンポーネントは、基底の反転変化の行であることに注意してください。 of [〜#〜] r [〜#〜]は、古い基底ベクトルに関する新しい基底ベクトルです(したがって、変数名はxaxis.x、.. xaxisはnew基底の変更が発生した後のx軸)。ただし、反転のため、行と列は転置されます。

52
bobobobo

その翻訳コンポーネントは、Originでの「目」と、そのOrigin(「目」)と3つの軸で表現される他のすべてで 正規直交基底 を作成するのに役立ちます。

コンセプトは、マトリックスがカメラの位置を調整するほどではありません。むしろ、数学を単純化しようとしています。「目」の位置から見えるすべての画像をレンダリングしたい場合、目が宇宙の中心であるふりをするのが最も簡単です。

したがって、簡単な答えは、これにより数学がはるかに簡単になるということです。

コメントの質問に答える:すべてから「目」の位置を差し引くだけではない理由は、操作の順序に関係しています。このように考えてください:新しい参照フレーム(つまり、xaxis、yaxis、およびzaxisで表される頭の位置)に入ったら、この新しい(回転した)参照フレームの観点から距離を表現する必要があります。これが、新しい軸と目の位置のドット積を使用する理由です。これは、物を動かす必要があるのと同じ距離を表しますが、新しい座標系を使用します。

3
Bob Cross

一般的な情報:

Lookatマトリックスは、空間内の別のポイントから、空間内のポイントを指す(見る)ために何かを配置/回転させるマトリックスです。

このメソッドは、カメラビューの目的の「中心」、カメラの「上」方向を表す「上」ベクトルを取ります(上はほとんどの場合(0,1,0)ですが、そうである必要はありません)、およびカメラの位置である「目」ベクトル。

これは主にカメラに使用されますが、シャドウ、スポットライトなどの他の技術にも使用できます。

率直に言って、このメソッドのように翻訳コンポーネントが設定されている理由は完全にはわかりません。 gluLookAt(OpenGLから)では、カメラは常に0,0,0にあると見なされるため、変換コンポーネントは0,0,0に設定されます。

3
TM.

ドット積は、単純に点を軸に投影して、目のx、y、またはzコンポーネントを取得します。カメラを後方に移動しているため、(0、0、0)から(10、0、0)と(100000、0、0)を見ると効果が異なります。

2
Eugene Yokota

変換4x4マトリックスには、2〜3個のコンポーネントが含まれます。1。回転マトリックス2.追加する変換。 3.スケール(多くのエンジンがこれをマトリックスで直接使用しないでください)。

それらの組み合わせは、点を空間Aから空間Bに変換します。したがって、これは変換行列M_abです。

現在、カメラの位置はスペースAにあるため、スペースBの有効な変換ではないため、この位置に回転変換を乗算する必要があります。

唯一の未解決の問題は、なぜドットが発生するのかということです。さて、紙に3つのドットを書くと、X、Y、Zの3つのドットは、回転行列の乗算とまったく同じであることがわかります。

その4番目の行/列の例は、ゼロを取得することです-(0,0,0)ワールド空間で。カメラ空間のゼロ点ではないため、回転とスケールがゼロのままになるため、カメラ空間の表現を知る必要があります!

乾杯

1
Adi

Lookatマトリックスは、次の2つのステップを実行します。

  1. モデルをOriginに変換し、
  2. アップベクトルと見た目で設定された方向に従って回転します
    方向。

ドット積は、最初に翻訳を行ってから回転することを意味します。 2つの行列を乗算する代わりに、ドット積は行と列を乗算するだけです。

1
Kalle

ワールド空間ではなく、軸空間に視点を配置する必要があります。 x、y、zのいずれかの座標単位基底ベクトルでベクトルにドットを付けると、that空間の目の座標が得られます。最後の場所(この場合は最後の行)で3つの翻訳を適用することにより、場所を変換します。次に、負の値で目を後方に移動することは、スペースの残りすべてを前方に移動することと同じです。エレベーターで上に移動するのと同じように、他の世界があなたの下から落ちているように感じます。

最後の列の代わりに翻訳を最後の行として使用する左利きの行列を使用することは、答えとはまったく関係のない宗教的な違いです。しかし、それは絶対に避けるべき教義です。ツリースケッチを描画するときは、グローバルからローカル(フォワードキネマティック)変換を左から右に自然な読み取り順序で連鎖させるのが最適です。左利きの行列を使用すると、これらの右から左への記述が強制されます。

0
DragonLord