機械学習基礎理論独習

誤りがあればご指摘いただけると幸いです。数式が整うまで少し時間かかります。リンクフリーです。

勉強ログです。リンクフリーです
目次へ戻る

ビュー変換

ビュー変換とは


ワールド座標系からビュー座標系への変換のことで、4x4の行列で表現します。
イメージとしては、この変換により、ビュー座標系の原点が視点となるといった感じです。
この変換は、回転と平行移動を合わせたものです。
この変換にlookAt関数が使われることが多いですが、使わなくても問題ありません。
私は使わないことが多いです。
個人的には、lookAt関数を使うのは、投影変換が平行投影でないでないときで、
lookAt関数を使わないのは、投影変換が透視投影のときかなって思います。
「ビュー変換」は「視野変換」とも言います。というか、視野変換として書くべきでした。書き直すのが面倒なのでこのままにしておきます。

ビュー変換行列

ビュー変換行列に対応するプログラムにおける関数はlooAt関数と言います。(lookAt関数と命名されていることがとても多いです。)
lookAt関数というのは通称です。ビュー変換でこの変換が必ず紹介されます。なので、本記事でも取り上げます。
(旧)OpenGLのUtilityにgluLookAtという関数があるぐらいよく使われる手法です。

この変換を定めるには、「視点の位置」、「目標の位置」、「上方向のベクトル」の3つが必要です。
「視点の位置」を {\bf e}=(e_x,e_y,e_z)、「目標の位置」を {\bf g}=(g_x,g_y,g_z)、「上方向のベクトル」を {\bf u}=(u_x,u_y,u_z) とします。
強調しておきますが、{\bf e},{\bf g} は位置ベクトル、{\bf u} は方向ベクトルです。

平行移動行列 {\bf T}_v、回転行列 {\bf R}_v を掛け合わせたものが求める変換です。個別にそれを求めていきます。

まず、視点 {\bf e}=(e_x,e_y,e_z) を原点 {\bf O}=(0,0,0) に平行移動する変換行列 {\bf T}_v は以下のようになります。

\begin{eqnarray}
{\bf T}_v=\begin{pmatrix}1 & 0 & 0 &-e_x\\ 0 & 1 & 0 & -e_y\\ 0 & 0 & 1 & -e_z\\0 & 0 & 0 & 1\end{pmatrix}\tag{1}
\end{eqnarray}

次に、回転行列 {\bf R}_v を求めます。
ビュー座標系の基底を以下によって定めます。
ビュー座標系の z 軸に相当するベクトル {\bf t}=(t_x,t_y,t_z) は、視線方向の逆ベクトル {\bf e}-{\bf g} とします。
ビュー座標系の x 軸に相当するベクトル {\bf r}=(r_x,r_y,r_z) は、{\bf u}\times{\bf t} で求まります。
ビュー座標系の y 軸に相当するベクトル {\bf s}=(s_x,s_y,s_z) は、{\bf t}\times{\bf r} で求まります。
上記をまとめます。

\begin{eqnarray}
&&{\bf t}={\bf e}-{\bf g}\tag{2}\\
&&{\bf r}={\bf u}\times{\bf t}\tag{3}\\
&&{\bf s}={\bf t}\times{\bf r}\tag{4}\\
\end{eqnarray}
{\bf r}, {\bf s}, {\bf t} をそれぞれ単位ベクトル化します。
後は直交座標系同士の変換なので、求める回転行列は以下のようになります。
(こちらを参考にしてください。)
\begin{eqnarray}
{\bf R}_v=
\begin{pmatrix}
& \dfrac{{\bf r}^\top}{||{\bf r}||} & & 0\\
& \dfrac{{\bf s}^\top}{||{\bf s}||} & & 0\\
& \dfrac{{\bf t}^\top}{||{\bf t}||} & & 0\\
0 & 0 & 0 & 1\\
\end{pmatrix}
=
\begin{pmatrix}
\dfrac{r_x}{||{\bf r}||} & \dfrac{r_y}{||{\bf r}||} & \dfrac{r_z}{||{\bf r}||} & 0\\
\dfrac{s_x}{||{\bf s}||} & \dfrac{s_y}{||{\bf s}||} & \dfrac{s_z}{||{\bf s}||} & 0\\
\dfrac{t_x}{||{\bf t}||} & \dfrac{t_y}{||{\bf t}||} & \dfrac{t_z}{||{\bf t}||} & 0\\
0 & 0 & 0 & 1\\
\end{pmatrix}\tag{5}
\end{eqnarray}

最後に、平行移動行列 {\bf T}_v、回転行列 {\bf R}_v を掛けます。これが求めるビュー変換行列 {\bf M}_v です。

\begin{eqnarray}
{\bf M}_v={\bf R}_v{\bf T}_v\tag{6}
\end{eqnarray}

ベクトルsをわざわざ求めなくてもよいのではないのか?

私が引っ掛かった内容をメモします。
初めてこのアルゴリズムを知ったとき、{\bf s}={\bf t}\times{\bf r} なのだから、{\bf s}{\bf u} は同じ方向だから求めなくてよいのではないか、
という疑問が湧きました。
{\bf s} を求めているのは、{\bf u}{\bf t} と垂直とは限らない({\bf u}\not\perp{\bf t})ためであり、
{\bf s}={\bf t}\times{\bf r}外積を計算しているのは、新たな座標系(ビュー座標系)の基底とするためです。
お恥ずかしいですが、少しこのことにはまってしまいました。
ちなみに、{\bf u}\perp{\bf t} のときは、{\bf u}{\bf s} の方向は同じすなわち \frac{{\bf u}}{||{\bf u}||}=\frac{{\bf s}}{||{\bf s}||} が成り立つので、{\bf s} を計算する必要はありません。

視線の逆ベクトルをビュー座標系のz軸とする理由

レンダリングパイプラインによって最終的にデバイス座標系へ変換されるわけですが、
そのデバイス座標の右側をx+、上側をy+にしたいわけです。
そうすると、このビュー座標系を右手座標で考えると視点はz+にあるわけで、視線方向はz-になります。
よって、視線の逆をz+になるように、視線の逆ベクトルをビュー座標系のz+にしているんだと思います。
これは、あくまで個人的な考えですが、そんなに間違っていないと思います。。

モデルビュー変換

モデル変換とビュー変換を合わせて、モデルビュー変換といいます。
その行列は、モデル変換行列とビュー変換行列を掛けたものです。

別名

ビュー変換は、カメラ変換ということがあります。
ビュー座標系は、カメラ座標系ということがあります。

最後に

冒頭で、私はこの変換を使わないと書きましたが、いわゆるlookAt関数を使わないだけで、ビュー変換は勿論使います。
どのようにビュー変換を実現するかは別記事にしたいと思います。

参考リンク

直交座標系の変換

参考文献

コンピュータグラフィックスの基礎 p47-p50

目次へ戻る