機械学習基礎理論独習

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

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

glMatrixの使い方

はじめに

WebGLで使われる最もよく使われるであろうライブラリglMatrixについて解説します。
対象のバージョンは3.4.0です。
引数を省略して、メソッドを使うことは無いようです。その方が使いやすいですね。
私が良く使うものだけを紹介します。
ベクトルは3次元のベクトルvec3を、行列は4x4の行列mat4のメソッドを紹介します。
以下の説明で使われる \leftarrow は代入を意味します。アルゴリズムの説明の時に見かける記号です。

ベクトルの定義

\begin{eqnarray}
&&{\bf x}\in{\mathbb R}^3\\
\end{eqnarray}

const x = vec3.create(); // 0,0,0 と初期化されます。

ベクトルを特定の値で初期化

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
\end{eqnarray}

const x = vec3.clone([1, 2, 3]); // 実引数はArray<number>でもFloat32Arrayでも数値の配列なら何でもよい

ベクトルの和

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow\begin{pmatrix}4, & 5, & 6\end{pmatrix}^\top\\
&&{\bf z}\leftarrow{\bf x}+{\bf y} 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.clone([4, 5, 6]);
const z = vec3.create(); // 変数を定義しておく必要がある
vec3.add(z, x, y); // z = x + y

ベクトルの差

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow\begin{pmatrix}4, & 5, & 6\end{pmatrix}^\top\\
&&{\bf z}\leftarrow{\bf x}-{\bf y} 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.clone([4, 5, 6]);
const z = vec3.create(); // 変数を定義しておく必要がある
vec3.subtract(z, x, y); // z = x - y

ベクトルのスカラー

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow 3{\bf x} 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.create(); // 変数を定義しておく必要がある
vec3.scale(y, x, 3); // y = 3x

ベクトルの内積

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow\begin{pmatrix}4, & 5, & 6\end{pmatrix}^\top\\
&&z\leftarrow{\bf x}^\top{\bf y}\ (or\ {\bf x}\cdot{\bf y}) 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.clone([4, 5, 6]);
const z = vec3.dot(x, y); // z = dot(x, y) inner product

ベクトルの外積

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow\begin{pmatrix}4, & 5, & 6\end{pmatrix}^\top\\
&&{\bf z}\leftarrow{\bf x}\times{\bf y} 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.clone([4, 5, 6]);
const z = vec3.create(); // 変数を定義しておく必要がある
vec3.cross(z, x, y); // z = cross(x, y) outer product

ベクトルと行列の積

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf A}\leftarrow\begin{pmatrix}1 & 0 & 0 & 1\\ 0 & 1 & 0 & 2\\ 0 & 0 & 1 & 3\\ 0 & 0 & 0 & 1\end{pmatrix}^\top\\
&&{\bf y}\leftarrow{\bf A}{\bf x} 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const A = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1]);
const y = vec3.create(); // 変数を定義しておく必要がある
vec3.transformMat4(y, x, A); // y = Ax

{\bf x} は3次元で、{\bf A} は4x4で数学的に {\bf A}{\bf x} は計算できませんが、
ベクトルの第4成分に1を補って、演算後、xyz成分をwで割ることにより3次元ベクトルにしています。詳細はメソッドのソースを読んでください。
vec3.transformMat4の第二引数がベクトルであり、第三引数が行列であり、実際の計算の順番とは異なる(ソース見て確認しました)ので注意してください。

単位ベクトル化

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow \frac{1}{|| {\bf x} ||}{\bf x} 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec.create(); // 変数を定義しておく必要がある
vec3.normalize(y, x);

ベクトルの長さ

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&y\leftarrow || {\bf x} || 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.length(x)

ベクトルの長さの2乗はvec3.squaredLengthメソッドで計算できます。

ベクトルの距離

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow\begin{pmatrix}4, & 5, & 6\end{pmatrix}^\top\\
&&z\leftarrow || {\bf x} - {\bf y} || 
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.clone([4, 5, 6]);
const z = vec3.distance(x, y)

ベクトルの距離の2乗はvec3.squaredDistanceメソッドで計算できます。

ベクトルの相等

\begin{eqnarray}
&&{\bf x}\leftarrow\begin{pmatrix}1, & 2, & 3\end{pmatrix}^\top\\
&&{\bf y}\leftarrow\begin{pmatrix}4, & 5, & 6\end{pmatrix}^\top\\
&&z\leftarrow\left\{
\begin{array}{l}
true\ ({\bf x}={\bf y})\\
false\ ({\bf x}\not={\bf y})
\end{array}
\right.
\end{eqnarray}

const x = vec3.clone([1, 2, 3]);
const y = vec3.clone([4, 5, 6]);
const z = vec3.equals(x, y); // false

vec3.equalsメソッドは、各成分の差が glMatrix.EPSILON(=0.000001)以下の場合にtrueを返します。
厳密な相等を判定する場合、vec3.exactEqualsを使いましょう。

行列の定義

\begin{eqnarray}
&&{\bf A}\in{\mathbb R}^{4\times 4}\\
\end{eqnarray}

const A = mat4.create(); // 全成分 0 で初期化されます。

単位行列

\begin{eqnarray}
&&{\bf A}\leftarrow\begin{pmatrix}1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1\end{pmatrix}\\
\end{eqnarray}

const A = mat4.create();
mat4.identity(A);

行列を特定の値で初期化

\begin{eqnarray}
&&{\bf A}\leftarrow\begin{pmatrix}1 & 0 & 0 & 1\\ 0 & 1 & 0 & 2\\ 0 & 0 & 1 & 3\\ 0 & 0 & 0 & 1\end{pmatrix}\\
\end{eqnarray}

const A = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1]); // 実引数はArray<number>でもFloat32Arrayでも数値の配列なら何でもよい

任意軸回りの回転(演算)

Aに右からX軸回りに45度回転する行列をかけた行列を取得する例

const A = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1]); 
const B = mat4.create(); // 変数を定義しておく必要がある
mat4.rotate(B, A, 45 / 180 * Math.PI, [1, 0, 0]);

X,Y,Z軸回りのメソッドとして、mat4.rotateX,mat4.rotateY,mat4.rotateZがありますが、使う必要はないと思います。

平行移動(演算)

AにX軸方向に+4平行移動する行列をかけた行列を取得する例

const A = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1]); 
const B = mat4.create(); // 変数を定義しておく必要がある
mat4.translate(B, A, [4, 0, 0]);

拡大縮小(演算)

AにX軸方向に+4倍、Y軸方向に+1倍、Z軸方向に+1倍、拡大縮小する行列をかけた行列を取得する例

const A = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1]); 
const B = mat4.create(); // 変数を定義しておく必要がある
mat4.scale(B, A, [4, 1, 1]);

行列同士の掛け算

\begin{eqnarray}
{\bf A, B}\in{\mathbb R}^{4\times 4}\\
{\bf C}\leftarrow{\bf A}{\bf B}
\end{eqnarray}

const A = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1]); 
const B = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 5, 6, 1]); 
const C = mat4.create(); // 変数を定義しておく必要がある
mat4.multiply(C, A, B);

行列の積は非可換ですので、掛ける順番に注意しましょう。

逆行列

\begin{eqnarray}
{\bf A}\in{\mathbb R}^{4\times 4}\\
{\bf B}\leftarrow{\bf A}^{-1}
\end{eqnarray}

const A = mat4.clone([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1]);
const B = mat4.create(); // 変数を定義しておく必要がある
mat4.invert(B, A);

視野変換

const A = mat4.create(); // 変数を定義しておく必要がある
mat4.lookAt(A, left, right, bottom, top, near, far);

正射影

const A = mat4.create(); // 変数を定義しておく必要がある
mat4.ortho(A, eye, center, up);

透視投影

const A = mat4.create(); // 変数を定義しておく必要がある
mat4.frustum(A, left, right, bottom, top, near, far);

画角を指定した透視投影

const A = mat4.create(); // 変数を定義しておく必要がある
mat4.perspective(A, fovy, aspect, near, far);
目次へ戻る