回答:
簡潔な答え
まず、ビューマトリックスを反転します。次に、最後の行/列から翻訳をフェッチします。
長い答え
ビューマトリックスのコンテンツを推定する1つの方法は、カメラをワールド内の他のオブジェクトと見なし、そのワールドマトリックスを計算することから始めます。
RightX RightY RightZ 0
UpX UpY UpZ 0
LookX LookY LookZ 0
PosX PosY PosZ 1
ワールドマトリックスは、ローカル空間からワールド空間に座標を変換します。ただし、この場合、カメラのローカル空間とビュー空間はまったく同じなので、この行列は座標をビュー空間からワールド空間に変換するとも言えます。
反対方向の変換が必要なので、行列を反転させる必要があります。結果は、座標をワールド空間からビュー空間に変換するビューマトリックスと呼ばれるものです。
RightX UpX LookX 0
RightY UpY LookY 0
RightZ UpZ LookZ 0
-(Pos*Right) -(Pos*Up) -(Pos*Look) 1 // * = dot product
そして、それはあなたが持っている一種のマトリックスです。したがって、カメラの位置を元に戻すには、最初にカメラの位置を反転する必要があります。次に、最後の行(またはシステムによっては列)から平行移動を取得できます。
まず、位置をベクトルとして個別に保存することを強くお勧めします。これにより、計算がはるかに簡単になります。いずれかの方法...
[x (dot) right, y (dot) up, z (dot) look]
は実際のビューマトリックスではありません。マトリックス自体の形式は次のとおりです。
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
左上の3x3マトリックスは回転、スケールなどを表します。すべてのカメラの向きはそこで行われます。残りの行と列は、翻訳や、今は説明しないその他の複雑なパースペクティブに使用されます。
マトリックスを取得すると(4x4マトリックスであると想定)、マトリックスクラスが行優先か列優先かによって、変換は常に最後の行または最後の列に格納されます。
おそらく混乱しているのは、ドット積が必要であるという事実です。何が起こっているのかは行列の数学の単純化です、このスタックオーバーフローの質問にはより詳細な回答があります:https : //stackoverflow.com/questions/349050/calculating-a-lookat-matrix
解決策はここにあります、あなたは行列の逆を取り、その翻訳を得る必要があります:
Vector3 ViewTrans = Matrix.Invert(ViewMatrix).Translation;
Position = ViewTrans;
ここでの他の答えは、カメラ行列の逆からカメラの位置を取得する方法を説明しています。
カメラマトリックスの3x3部分が通常のように回転のみ(スケーリングやシアリングなし)である場合、カメラマトリックスの変換にカメラの回転の転置を乗算することにより、計算を最適化できます。カメラ位置は、変換された並進ベクトルに-1を掛けたものです。GLSLでは、これは次のとおりです。
vec3 cameraPosition = -transpose(mat3(worldToCameraMatrix)) * worldToCameraMatrix[3].xyz;
または
vec3 cameraPosition = -worldToCameraMatrix[3].xyz * mat3(worldToCameraMatrix);
これは、カメラの位置を計算してユニフォームとして渡したくない場合に、頂点シェーダーで使用していたものです。