[数学] 線形代数と3D空間における行列の役割

はじめに

線形代数は、3Dプログラミングにおいて不可欠な分野です。

特に、行列を理解することで、座標変換、カメラの視点変更、回転、スケーリングなどの操作が可能になります。

これらの操作は、3D空間でのオブジェクトの位置や形状を自由に制御するために重要です。

この記事では、4x4行列が3D空間でどのように使われるかを簡単に説明し、特に以下のポイントに焦点を当てます:

  • 行列とは何か?
  • 4x4行列の構造とその用途
  • 3D空間での座標変換、回転、スケーリングの基本
  • カメラの視点変換や射影行列の役割

行列の理解は、3Dプログラミングにおいて、カメラワークやアニメーション、物体の配置、さらにはリアルタイムレンダリングに至るまで、非常に重要な技術です。初心者でも分かりやすく説明していきますので、ぜひ一緒に学びましょう。

1. 行列とは?

行列とは、数を格納した2次元配列で、一般的に数式や計算で使われる数学的なツールです。行列は、主に複数のベクトルを効率よく操作するために使います。特に3Dプログラミングにおいて、行列は座標やオブジェクトの変換を行うために不可欠な要素となります。

行列の基本構造

行列は、通常、以下のように数値が格納された長方形の配列として表されます:

| a11, a12, a13, a14 |
| a21, a22, a23, a24 |
| a31, a32, a33, a34 |
| a41, a42, a43, a44 |

ここで、aij(i行j列)は、行列の各要素を表しています。行列の行と列を使って、ベクトルの変換を行います。

ベクトルと行列の関係

  • ベクトルは、3D空間内での位置や方向を表現するために使われます。例えば、(x, y, z)という三つの数値を使って、空間内の特定の位置を示します。

  • 行列は、ベクトルに対して操作を加えるために使います。具体的には、位置を移動する(平行移動)、物体を回転させる(回転行列)、物体の大きさを変更する(スケーリング)などの変換を行うために使用されます。

行列を使う理由

行列を使う主な理由は、複雑な変換を一度にまとめて計算できることです。例えば、3D空間において、物体を回転させてから移動させる、またはスケーリングした後に回転させるといった一連の操作を、行列を使うことで効率的に計算できます。

2. 4x4行列の構造

4x4行列は、3D空間での複雑な変換を一度に計算できる非常に強力なツールです。以下はその基本的な形です:

| m11, m12, m13, m14 |
| m21, m22, m23, m24 |
| m31, m32, m33, m34 |
| m41, m42, m43, m44 |

この行列は、4つの行と4つの列を持ち、16個の要素(m11からm44)から成り立っています。それぞれの成分が、3D空間での変換(回転、スケーリング、平行移動など)を担当します。

行列の役割

  • 3x3部分(m11, m12, m13, m21, m22, m23, m31, m32, m33): この部分は、主に回転やスケーリングに関係します。例えば、物体を回転させたり、拡大縮小したりする際に使われます。

  • 4x1部分(m14, m24, m34): これらの成分は、平行移動(位置の変更)を担当します。3D空間内で、物体を別の位置に移動させるために使います。

  • m44(行列の右下隅): 通常、この値は1に設定され、その他の行列計算におけるスケーリングや視点変換を補完するために使われます。例えば、カメラ変換や投影行列で重要な役割を果たします。

行列の使い方

4x4行列を使うことで、次のような変換をまとめて行うことができます:

  • 回転:物体を特定の軸を中心に回転させます。回転行列は、m11からm33の部分で計算されます。
  • スケーリング:物体の大きさを変更します。スケーリング行列は、m11、m22、m33に影響を与えます。
  • 平行移動(位置変更):物体を新しい位置に移動させます。平行移動は、m14、m24、m34の成分で調整されます。

これにより、1つの行列で、回転、スケーリング、平行移動を同時に適用できるようになります。これが、行列を使う大きな利点です。

3. 4x4行列の使い方

4x4行列は、3D空間での変換をまとめて効率よく計算するために使われます。以下の3つの基本的な変換が、4x4行列を使って一度に行うことができます。

1. 回転(Rotation)

回転行列は、3D空間で物体を特定の軸を中心に回転させるために使います。例えば、物体をX軸、Y軸、またはZ軸を中心に回転させることができます。

  • 回転行列は、m11からm33の成分に関係します。これらの要素によって、物体が回転する軸と角度が決まります。
  • 回転行列を使うことで、物体の向きを変更することができます。

例:Z軸回りの回転行列

| cos(θ), -sin(θ), 0, 0 |
| sin(θ), cos(θ),  0, 0 |
| 0,        0,       1, 0 |
| 0,        0,       0, 1 |

この行列は、物体をZ軸を中心にθ度回転させます。

2. スケーリング(Scaling)

スケーリング行列は、物体の大きさを変更するために使用します。例えば、物体を拡大または縮小することができます。

  • スケーリング行列は、m11、m22、m33の成分でスケール因子を指定します。
  • これにより、物体のX軸、Y軸、Z軸方向に対してスケーリングを適用できます。

例:スケーリング行列

| sx,  0,  0,  0 |
| 0,  sy,  0,  0 |
| 0,  0,  sz,  0 |
| 0,  0,  0,  1 |

ここで、sx、sy、szはそれぞれX軸、Y軸、Z軸のスケーリング因子です。例えば、sx=2、sy=0.5、sz=1に設定すると、物体がX方向に2倍、Y方向に0.5倍、Z方向には変化なしでスケーリングされます。

3. 平行移動(Translation)

平行移動行列は、物体を3D空間内で移動させるために使います。物体の位置を変えることができます。

  • 平行移動行列は、m14、m24、m34の成分で位置を変更します。これにより、物体を新しい位置に移動できます。

例:平行移動行列

| 1,  0,  0,  tx |
| 0,  1,  0,  ty |
| 0,  0,  1,  tz |
| 0,  0,  0,  1 |

ここで、tx、ty、tzはそれぞれ物体のX軸、Y軸、Z軸方向への移動量です。例えば、tx=3、ty=-2、tz=5に設定すると、物体はX方向に3、Y方向に-2、Z方向に5の位置に移動します。

まとめ

回転、スケーリング、平行移動といった基本的な変換は、4x4行列を使って一度に計算することができます。これにより、3D空間内での物体の位置や向きを効率よく変更することが可能になります。行列を使った計算は、これらの操作を組み合わせて行うことができるため、非常に強力で汎用性の高いツールです。

次は、これらの変換をどう組み合わせて使うか、さらに実践的な応用例を見ていきましょう。

4. カメラ変換(ビュー行列と射影行列)

3Dグラフィックスでは、カメラの位置や向きによってシーンがどのように表示されるかが決まります。このカメラ変換にも、4x4行列が重要な役割を果たします。カメラの位置や向きに応じて、シーンをどう描画するかを決定するために、ビュー行列と射影行列が使用されます。

1. ビュー行列(View Matrix)

ビュー行列は、カメラの位置、向き、上方向に基づいて、シーンをカメラ視点からどのように見えるかを決定します。簡単に言うと、ビュー行列は「カメラがどこにあり、どの方向を見ているのか」を表現する行列です。

  • ビュー行列は、物体をカメラの視点に合わせて「逆転させる」ために使われます。物体をカメラに合わせて正しく描画するために、シーンの全てをカメラの視点に変換する操作を行います。
  • カメラの向きや位置を変えることで、シーン内での物体の位置も変化します。

ビュー行列の例:

ビュー行列はカメラの位置と視点を考慮して、物体がカメラからどう見えるかを決めます。例えば、カメラを原点に配置し、視線がZ軸方向を向いている場合、ビュー行列は次のように構成されることがあります:

| 1,  0,  0,  -cx |
| 0,  1,  0,  -cy |
| 0,  0,  1,  -cz |
| 0,  0,  0,  1  |

ここで、(cx, cy, cz) はカメラの位置です。ビュー行列は、シーン全体をカメラの視点に合わせて移動させる(逆行列の役割)ために使われます。

2. 射影行列(Projection Matrix)

射影行列は、3D空間の座標を2Dスクリーンに投影するために使われます。これによって、実際に3Dで描かれた物体を2D画面に表示することができます。射影行列は、カメラから見た物体の遠近感やサイズを調整します。

  • 透視投影行列(Perspective Projection Matrix): 透視投影は、遠くの物体が小さく見える効果を持っています。通常のカメラのレンズで見るような視覚効果を作るために使用されます。

  • 直交投影行列(Orthographic Projection Matrix): 直交投影では、物体がどんな距離にあっても、サイズが変わりません。エンタープライズ向けのCADシステムなど、物体の相対的な位置を保ちながら視覚的に誤差なく描写するために使われます。

透視投影行列の例:

透視投影行列は、遠くの物が小さく、近くの物が大きく見えるように調整します。例えば、次のような形で表されます:

| 1/tan(fov/2),  0,                 0,                   0 |
| 0,               1/tan(fov/2),  0,                   0 |
| 0,               0,               far/(far-near),  -far*near/(far-near) |
| 0,               0,               -1,                   0 |

ここで、fovは視野角、nearとfarはカメラが描画する最短距離と最長距離を示します。

直交投影行列の例:

直交投影行列では、物体がどの距離にあってもサイズが一定に保たれます。例えば、次のような形です:

| 2/(right-left), 0,                 0,           -(right+left)/(right-left) |
| 0,               2/(top-bottom),  0,           -(top+bottom)/(top-bottom) |
| 0,               0,               -2/(far-near), -(far+near)/(far-near) |
| 0,               0,               0,           1 |

ここで、left, right, top, bottom は投影される範囲の座標、near と far はカメラの視距離です。

3. ビュー行列と射影行列の組み合わせ

ビュー行列と射影行列は、カメラの位置とシーン内の物体の投影方法を組み合わせて、最終的にスクリーンに描画される映像を作り上げます。これらの行列を連続して掛け算することで、3D空間の座標がスクリーン上に正しく投影されます。

  1. ビュー行列:カメラの視点に合わせてシーンを変換。
  2. 射影行列:シーンを2Dスクリーンに投影。

これらを組み合わせることで、カメラの位置や向きに関係なく、シーン全体を正しく描画することができます。

まとめ

ビュー行列と射影行列は、カメラ視点の変換と物体の投影を効率よく行うために不可欠です。これらの行列を適切に使用することで、どんなカメラ位置でもシーンを正しく描画することができ、3Dグラフィックスをリアルに表現できます。次に、これらの変換を実際にどのように組み合わせて使用するか、さらに詳しく見ていきましょう。

5. 行列と実際のプログラム

実際のプログラミングでは、行列を使った計算は非常に重要です。特に、3Dグラフィックスのライブラリ(Three.jsやWebGLなど)を使うと、行列を直接操作せずとも、裏でこれらの計算が自動的に行われます。たとえば、カメラを動かすためにビュー行列が計算され、物体を回転させるために回転行列が使われるなど、さまざまな変換操作が行われています。

1. Three.jsでの行列の利用

Three.jsは、WebGLを簡単に扱えるJavaScriptライブラリで、3Dグラフィックスの描画を手軽に実現できます。内部では、行列を使ってシーン内のオブジェクトを動かしたり、カメラ視点を変更したりします。たとえば、カメラを動かすためには、ビュー行列を使ってカメラの位置や方向を決定し、物体を回転させるためには、回転行列を使ってオブジェクトの向きを調整します。

ビュー行列の自動計算

Three.jsでは、Cameraオブジェクトを使って、ビュー行列を自動的に計算します。ユーザーがカメラを移動したり回転させたりすると、Three.jsが内部でビュー行列を更新して、シーンを正しく描画します。

const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 5);  // カメラ位置を(0, 0, 5)に設定
camera.lookAt(new THREE.Vector3(0, 0, 0));  // カメラの視点を原点に向ける

上記のコードでは、カメラの位置と向きを設定することで、ビュー行列が自動的に計算され、シーンが適切に描画されます。

回転行列の使用

物体を回転させるためには、Three.jsでオブジェクトの回転行列が自動的に適用されます。たとえば、rotationプロパティを使うことで、オブジェクトを回転させることができます。

const cube = new THREE.Mesh(geometry, material);
cube.rotation.x = Math.PI / 4;  // X軸回りに45度回転
cube.rotation.y = Math.PI / 4;  // Y軸回りに45度回転

これにより、cubeオブジェクトはX軸とY軸で回転します。Three.js内部で回転行列が適用され、描画時にオブジェクトが回転したように見えます。

2. 行列の直接操作(低レベルでの利用)

Three.jsや他のグラフィックスライブラリでは、行列を直接操作することもできます。たとえば、オブジェクトに対してスケーリングや回転、平行移動を行いたい場合、行列を自分で作成して操作することができます。

// 3Dオブジェクトに対してスケーリングを適用する
const matrix = new THREE.Matrix4();
matrix.makeScale(2, 2, 2);  // オブジェクトを2倍に拡大
object.applyMatrix4(matrix);  // 行列を適用

ここでは、Matrix4を使ってスケーリング行列を作成し、それをオブジェクトに適用しています。これにより、オブジェクトの大きさを変更できます。

3. ビュー行列と射影行列の自動計算

Three.jsでは、ビュー行列や射影行列も自動的に計算してくれます。例えば、カメラの投影行列は、PerspectiveCameraOrthographicCameraのインスタンスを作成すると、内部で自動的に計算されます。

const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
const projectionMatrix = camera.projectionMatrix;  // 射影行列を取得

このように、Three.jsでは多くの行列計算を自動で行ってくれるので、プログラマは行列を直接操作せずに、シーンの設定に集中することができます。

4. 自分で行列を操作する必要があるケース

しかし、場合によっては、ライブラリが提供する機能では足りないこともあります。その際には、行列を手動で操作する必要があります。たとえば、カスタムな回転や変換を行いたいときには、行列を直接作成し、適用することが求められます。

const matrix = new THREE.Matrix4();
matrix.identity();  // 単位行列にリセット
matrix.rotateX(Math.PI / 2);  // X軸回りに90度回転
matrix.translate(new THREE.Vector3(1, 0, 0));  // X軸方向に1単位移動

このように、行列の操作を手動で行うこともできますが、Three.jsや他のライブラリが提供する高レベルの機能を利用することで、多くの計算は裏で処理され、開発効率を高めることができます。