機械学習基礎理論独習

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

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

WebGLは列優先で行列の右側から列ベクトルを掛ける

はじめに

WebGL/OpenGLは列優先だから」という説明を見受けますがそれはいったい何なんだってことを説明します。
ちなみに「列優先だから」というだけでは何もわかりません。

行列のメモリレイアウト

行列として4x4を考えます。
そうすると、スカラーが4x4=16個必要なわけです。
メモリの効率を考えて、この16個の数値を1次元配列に持ちます。
この数値が、列を優先して配置されるとき、列優先といい
行を優先して配置されるとき、行優先といいます。

\begin{eqnarray}
{\bf M}_c&=&
\begin{pmatrix}
{\rm m}_0 & {\rm m}_4 & {\rm m}_8 & {\rm m}_{12}\\ 
{\rm m}_1 & {\rm m}_5 & {\rm m}_9 & {\rm m}_{13}\\ 
{\rm m}_2 & {\rm m}_6 & {\rm m}_{10} & {\rm m}_{14}\\ 
{\rm m}_3 & {\rm m}_7 & {\rm m}_{11} & {\rm m}_{15}\\ 
\end{pmatrix}\\
{\bf M}_r&=&
\begin{pmatrix}
{\rm m}_0 & {\rm m}_1 & {\rm m}_2 & {\rm m}_3\\ 
{\rm m}_4 & {\rm m}_5 & {\rm m}_6 & {\rm m}_7\\ 
{\rm m}_8 & {\rm m}_9 & {\rm m}_{10} & {\rm m}_{11}\\ 
{\rm m}_{12} & {\rm m}_{13} & {\rm m}_{14} & {\rm m}_{15}\\ 
\end{pmatrix}\\
\end{eqnarray}

{\bf M}_c が列優先で、{\bf M}_r が行優先です。
列優先、行優先をを変換する場合転置すればよいことが分かります。

行列とベクトルを掛けるとき

普通、ベクトルは列ベクトルで定義するので、行列の右側に掛けます。
ベクトルが行ベクトルの場合、行列の左側に掛けます。
なので、行列が2種類、ベクトルとの演算で2種類あるので2x2=4種類あります。
列優先行列、行優先行列にそれぞれ、左右からベクトルを掛けてみます。

\begin{eqnarray}
&&{\bf M}_c,{\bf M}_r\in{\mathbb R}^{4\times 4},{\bf v}=\begin{pmatrix}x,&y,&z,&w\end{pmatrix}^\top\in{\mathbb R}^4\\
&&{\bf M}_c{\bf v}=\begin{pmatrix}
{\rm m}_0 & {\rm m}_4 & {\rm m}_8 & {\rm m}_{12}\\ 
{\rm m}_1 & {\rm m}_5 & {\rm m}_9 & {\rm m}_{13}\\ 
{\rm m}_2 & {\rm m}_6 & {\rm m}_{10} & {\rm m}_{14}\\ 
{\rm m}_3 & {\rm m}_7 & {\rm m}_{11} & {\rm m}_{15}\\ 
\end{pmatrix}
\begin{pmatrix}x\\ y\\ z\\ w\end{pmatrix}
=\begin{pmatrix}
{\rm m}_0 x + {\rm m}_4 y + {\rm m}_8 z + {\rm m}_{12} w\\
{\rm m}_1 x + {\rm m}_5 y + {\rm m}_9 z + {\rm m}_{13} w\\
{\rm m}_2 x + {\rm m}_6 y + {\rm m}_{10} z + {\rm m}_{14} w\\
{\rm m}_3 x + {\rm m}_7 y + {\rm m}_{11} z + {\rm m}_{15} w\\
\end{pmatrix}\tag{1}\\
&&{\bf v}^\top{\bf M}_c=
\begin{pmatrix}x,& y,& z,& w\end{pmatrix}
\begin{pmatrix}
{\rm m}_0 & {\rm m}_4 & {\rm m}_8 & {\rm m}_{12}\\ 
{\rm m}_1 & {\rm m}_5 & {\rm m}_9 & {\rm m}_{13}\\ 
{\rm m}_2 & {\rm m}_6 & {\rm m}_{10} & {\rm m}_{14}\\ 
{\rm m}_3 & {\rm m}_7 & {\rm m}_{11} & {\rm m}_{15}\\ 
\end{pmatrix}
=\begin{pmatrix}
{\rm m}_0 x + {\rm m}_1 y + {\rm m}_2 z + {\rm m}_3 w\\
{\rm m}_4 x + {\rm m}_5 y + {\rm m}_6 z + {\rm m}_7 w\\
{\rm m}_8 x + {\rm m}_9 y + {\rm m}_{10} z + {\rm m}_{11} w\\
{\rm m}_{12} x + {\rm m}_{13} y + {\rm m}_{14} z + {\rm m}_{15} w\\
\end{pmatrix}^\top\tag{2}\\
&&{\bf M}_r{\bf v}=\begin{pmatrix}
{\rm m}_0 & {\rm m}_1 & {\rm m}_2 & {\rm m}_3\\ 
{\rm m}_4 & {\rm m}_5 & {\rm m}_6 & {\rm m}_7\\ 
{\rm m}_8 & {\rm m}_9 & {\rm m}_{10} & {\rm m}_{11}\\ 
{\rm m}_{12} & {\rm m}_{13} & {\rm m}_{14} & {\rm m}_{15}\\ 
\end{pmatrix}
\begin{pmatrix}x\\ y\\ z\\ w\end{pmatrix}
=\begin{pmatrix}
{\rm m}_0 x + {\rm m}_1 y + {\rm m}_2 z + {\rm m}_3 w\\
{\rm m}_4 x + {\rm m}_5 y + {\rm m}_6 z + {\rm m}_7 w\\
{\rm m}_8 x + {\rm m}_9 y + {\rm m}_{10} z + {\rm m}_{11} w\\
{\rm m}_{12} x + {\rm m}_{13} y + {\rm m}_{14} z + {\rm m}_{15} w\\
\end{pmatrix}\tag{3}\\
&&{\bf v}^\top{\bf M}_c=
\begin{pmatrix}x,& y,& z,& w\end{pmatrix}
\begin{pmatrix}
{\rm m}_0 & {\rm m}_1 & {\rm m}_2 & {\rm m}_3\\ 
{\rm m}_4 & {\rm m}_5 & {\rm m}_6 & {\rm m}_7\\ 
{\rm m}_8 & {\rm m}_9 & {\rm m}_{10} & {\rm m}_{11}\\ 
{\rm m}_{12} & {\rm m}_{13} & {\rm m}_{14} & {\rm m}_{15}\\ 
\end{pmatrix}
=\begin{pmatrix}
{\rm m}_0 x + {\rm m}_4 y + {\rm m}_8 z + {\rm m}_{12} w\\
{\rm m}_1 x + {\rm m}_5 y + {\rm m}_9 z + {\rm m}_{13} w\\
{\rm m}_2 x + {\rm m}_6 y + {\rm m}_{10} z + {\rm m}_{14} w\\
{\rm m}_3 x + {\rm m}_7 y + {\rm m}_{11} z + {\rm m}_{15} w\\
\end{pmatrix}^\top\tag{4}\\
\end{eqnarray}

(1)(4) の成分を比較してみると、(1)(4) が等しく、(2)(3) が等しいことが分かります。
ベクトルを掛ける方向を入れ替えても、計算結果が変わらないようにするには、入れ替えるたびに転置すればよいことが分かります。
OpenGL/WebGLは式 (1) の「行優先」かつ「ベクトルを右から掛ける」です。
他のグラフィックスライブラリの優先とベクトルをどちらから掛けるかについては、リンクを参照してください。

最後に

CGで行列を扱うときは「優先」と「ベクトルをどちらから掛けるか」の両方気にしないといけないことがわかりました。
ちなみに上記と「右手座標系、左手座標系」は無関係です。ここもごっちゃになっている人が多い気がします。

目次へ戻る