3DCGの世界において、キャラクターやオブジェクトを移動させたり、回転させたり、大きさを変えたりする操作は欠かせない要素です。
これらの操作を数学的に支えているのが「アフィン変換」と呼ばれる手法であり、現代のコンピュータグラフィックスにおけるもっとも基本的な理論の一つとされています。
アフィン変換を理解することは、プログラミングやモデリングソフトの内部挙動を把握するだけでなく、より高度な表現を可能にするための第一歩となります。
本記事では、アフィン変換の基礎概念から、行列計算の具体的な仕組み、そして実際の3DCG制作でどのように活用されているのかを詳しく解き明かしていきます。
アフィン変換の定義と基本的な概念
アフィン変換とは、幾何学における写像の一種であり、線形変換と平行移動を組み合わせたものを指します。
数学的な定義では、点やベクトルの直線性や平行関係を保ったまま別の状態へと移し替える操作のことです。
3DCGの文脈では、3次元空間上に配置されたモデルの頂点座標を、数式を用いて効率的に変換するために利用されます。
アフィン変換には大きな特徴があり、変換後も「直線は直線のまま」「平行な線は平行なまま」という性質が維持されます。
この性質があるおかげで、物体を移動させたり回転させたりしても、形状が不自然に歪んだり崩れたりすることはありません。
私たちが普段目にしているゲームや映画の3Dモデルは、このアフィン変換が1秒間に何十回、何百回と計算されることで滑らかに動いています。
アフィン変換の語源と歴史
「アフィン(Affine)」という言葉は、ラテン語の「affinis」に由来しており、「密接な」「関連のある」といった意味を持っています。
18世紀の数学者レオンハルト・オイラーなどによって研究が進められ、幾何学の分野で重要な地位を確立しました。
現代ではコンピュータの計算能力向上に伴い、グラフィックス処理ユニット(GPU)内で高速に処理される計算の基盤となっています。
アフィン変換を構成する4つの要素
アフィン変換は、主に4つの基本的な幾何学的操作を組み合わせて構築されます。
これらの要素を理解することで、複雑な物体の動きを単純な計算の積み重ねとして捉えることができるようになります。
1. 平行移動(Translation)
平行移動は、物体の形状や向きを変えずに、位置だけを特定の方向へ動かす操作です。
3次元空間のX軸、Y軸、Z軸のそれぞれに対して、移動させたい距離を加算することで実現します。
純粋な線形変換の行列(3×3行列)だけでは表現できない操作であるため、アフィン変換において非常に重要な役割を担います。
2. 拡大縮小(Scaling)
拡大縮小は、物体の大きさを変化させる操作であり、各軸の座標値に倍率を掛け合わせることで行われます。
中心点からの距離を調整することで、物体を大きくしたり、逆に小さく押しつぶしたりすることが可能です。
すべての軸に対して同じ倍率を適用すれば均等な拡大縮小になり、軸ごとに異なる倍率を適用すれば歪んだ形状を作ることができます。
3. 回転(Rotation)
回転は、特定の軸を基準にして物体を回す操作です。
3DCGでは、X軸周り、Y軸周り、Z軸周りの3方向の回転を組み合わせることで、自由な向きを作り出します。
回転の計算には三角関数(sin、cos)が用いられ、アフィン変換の中でも計算負荷が比較的高い部類に含まれます。
4. せん断(Shearing)
せん断は、物体をある方向に押しつぶすように歪ませる操作です。
たとえば、正方形を平行四辺形に変形させるような動きを指します。
3DCGの制作現場で直接「せん断」を指定することは少ないですが、特殊な視覚効果やアニメーションの演出で使用されることがあります。
行列計算の仕組みと数学的背景
アフィン変換がなぜこれほどまでに重宝されるのか、その理由は行列(Matrix)による一括計算が可能だからです。
複数の変換を一つにまとめることで、コンピュータは極めて効率的に座標計算を行うことができます。
なぜ行列を使うのか
例えば、物体を「30度回転させ、2倍に拡大し、右に10移動させる」という処理を行うとします。
これらを一つずつ順番に計算していくと、膨大な頂点数を持つモデルでは多大な時間がかかってしまいます。
しかし、行列計算を用いれば、回転行列、拡大行列、移動行列を事前に掛け合わせて「合成行列」を作ることができます。
一度合成行列を作ってしまえば、各頂点に対してその行列を1回掛けるだけで、すべての変換が同時に完了します。
行列計算の基本ルール
行列同士の掛け算には順序があり、掛ける順番を変えると結果が変わってしまうという性質があります。
一般的に、3DCGでは「拡大縮小 → 回転 → 平行移動」の順序で計算を組み立てるのが標準的です。
この順番を間違えると、意図しない場所を中心に回転してしまったり、移動してから拡大されたりと、結果が大きく崩れる原因となります。
同次座標系:4×4行列の魔法
アフィン変換を語る上で避けて通れないのが、「同次座標系」という考え方です。
通常、3次元の座標は(x, y, z)の3つの数値で表されますが、アフィン変換ではあえて(x, y, z, w)という4つ目の成分を追加します。
3×3行列の限界と解決策
拡大縮小、回転、せん断は、3×3の行列で数学的に表現することができます。
しかし、前述した「平行移動」だけは、3×3の行列の掛け算では表現できず、足し算が必要になってしまいます。
「掛け算」と「足し算」が混ざると、行列を合成して一つにまとめるというメリットが失われてしまいます。
そこで、座標に4つ目の要素「w」を追加し、4×4の正方行列を用いることで、移動も含めたすべての変換を掛け算だけで表現できるようにしたのです。
w成分の意味
多くの場合、このw成分には「1」が代入されます。
wが1であるとき、そのデータは「点(位置)」を表し、wが0であるときは「ベクトル(方向)」を表すと定義されます。
この仕組みにより、点は移動の影響を受け、ベクトルは移動の影響を受けないという、物理的に正しい計算が自動的に行われます。
3DCG制作における実用的な応用
アフィン変換は、ソフトウェアの内部だけで閉じている理論ではありません。
実際の制作フローやプログラミングにおいても、その仕組みを意識する場面は多々あります。
座標系の変換(ローカル・ワールド・ビュー)
3DCGには、オブジェクト自身が持つ「ローカル座標」、世界全体の中心からの位置を示す「ワールド座標」、カメラから見た「ビュー座標」が存在します。
これらの座標系を行き来する際にも、すべてアフィン変換による行列計算が使われています。
UnityやUnreal Engineといったゲームエンジンでは、「Transform」コンポーネントを操作することで、内部的にこの行列が更新されています。
スケルタルアニメーション(スキニング)
キャラクターが腕を曲げたり歩いたりするアニメーションも、アフィン変換の応用です。
骨格(ボーン)の動きを行列として計算し、それに追従するようにモデルの各頂点を変形させています。
複雑な関節の動きを再現するために、複数のボーンの影響度(ウェイト)を加味したアフィン変換の合成が行われています。
プログラミングにおける実装例
ここでは、アフィン変換行列を扱うための擬似的なコード例を紹介します。
多くのライブラリでは、開発者が自分で行列の要素を書き換える必要はなく、専用の関数を呼び出すだけで計算が可能です。
// GLMライブラリを想定した行列計算の例
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
void transformObject() {
// 単位行列(初期状態)の作成
glm::mat4 modelMatrix = glm::mat4(1.0f);
// 1. スケーリング(2倍に拡大)
modelMatrix = glm::scale(modelMatrix, glm::vec3(2.0f, 2.0f, 2.0f));
// 2. 回転(Y軸を中心に45度回転)
modelMatrix = glm::rotate(modelMatrix, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// 3. 平行移動(X軸方向に10移動)
modelMatrix = glm::translate(modelMatrix, glm::vec3(10.0f, 0.0f, 0.0f));
// このmodelMatrixをシェーダーに送り、各頂点に掛け合わせる
}
このコードで注目すべきは、関数の呼び出し順序がそのまま行列の合成順序になる点です。
プログラム内部では、各関数の戻り値として新しい4×4行列が生成され、次々に掛け合わされていきます。
行列の各要素が持つ意味
4×4のアフィン変換行列の中身を詳しく見ると、どの要素が何に影響しているのかが一目でわかります。
行列の構成を知っておくことで、デバッグ作業やシェーダー開発の際に役立ちます。
| 行列の範囲 | 役割 | 詳細 |
|---|---|---|
| 左上3×3の領域 | 線形変換 | 回転、拡大縮小、せん断を担当する。 |
| 右側の縦3列(または下側の横3列) | 平行移動 | X, Y, Z軸への移動量を格納する。 |
| 右下の1要素 | w成分 | 同次座標系におけるスケール値(通常は1)。 |
※行列の列優先・行優先の定義により、移動成分の格納場所はライブラリ(DirectX系かOpenGL系か)によって異なります。
アフィン変換を扱う際の注意点
非常に便利なアフィン変換ですが、扱う際にはいくつか注意すべきポイントがあります。
特に初心者の方が陥りやすい罠を知っておくことで、制作のトラブルを未然に防ぐことができます。
逆行列の存在
特定の変換を元に戻したい場合、「逆行列」を計算する必要があります。
たとえば、カメラを移動させる処理は、実は「世界全体を逆方向に移動させる」という逆行列の処理と同じです。
ただし、拡大率を0に設定してしまうと逆行列が計算できなくなる(行列式が0になる)ため、極端な値の設定には注意が必要です。
浮動小数点数の精度誤差
行列計算を何度も繰り返すと、計算精度の限界からわずかな誤差が蓄積することがあります。
特に回転計算を数千回繰り返すと、オブジェクトの形が微妙に歪んでしまう「ドリフト現象」が起きることがあります。
これを防ぐために、定期的に行列を正規化したり、回転の表現に「クォータニオン」を併用したりするのが一般的です。
まとめ
アフィン変換は、3DCGの根幹を支える極めて強力で合理的な仕組みです。
平行移動、拡大縮小、回転、せん断という4つの要素を組み合わせ、それを行列という数学的ツールで一括処理することによって、現代のリアルタイムグラフィックスは成り立っています。
特に「同次座標系」を導入して4×4行列で計算するというアイデアは、エンジニアリングにおける大きなブレイクスルーと言えるでしょう。
数学的な背景を知ることは一見遠回りに思えますが、アフィン変換の原理を理解していれば、モデルが意図しない動きをした際の原因特定や、より効率的な描画処理の実装が可能になります。
これから3DCGプログラミングやテクニカルアートを目指す方は、ぜひこのアフィン変換の仕組みをマスターし、自在な空間表現へと繋げてください。
