変換 (Direct3D 9)
Direct3D の機能の一部で、ジオメトリを固定機能ジオメトリ パイプラインに挿入する変換エンジンです。 変換エンジンは、モデルとビューアーをワールド座標に配置し、画面表示のために頂点を投影し、ビューポートに頂点をクリッピングします。 さらに変換エンジンは照明計算を実行し、各頂点における拡散成分および鏡面成分を決定します。
ジオメトリ パイプラインは、頂点を入力として受け取ります。 変換エンジンは、ワールド変換、ビュー変換、射影変換を頂点に適用し、結果をクリッピングして、すべてをラスタライザーに渡します。
パイプラインの最初の処理では、モデルの頂点はローカル座標系を基準として相対的に宣言されます。 これはローカルの原点と方向です。 この座標の向きは、多くの場合、モデル空間と呼ばれ、個々の座標はモデル座標と呼ばれます。
ジオメトリ パイプラインの最初のステージでは、モデルの頂点が、ローカル座標系からシーン内のすべてのオブジェクトで使われる座標系に変換されます。 頂点の方向を変更するプロセスは、ワールド変換と呼ばれます。 この新しい向きは、一般にワールド空間と呼ばれ、ワールド空間内の各頂点はワールド座標を使用して宣言されます。
次のステージでは、3D ワールドを記述する頂点が、カメラを基準とする方向に変換されます。 つまり、アプリケーションはシーンの視点を選択し、ワールド空間座標がカメラのビューを中心に再配置および回転され、ワールド空間がカメラ空間に変わります。 これはビュー変換です。
次のステージはプロジェクション変換です。 パイプラインのこの部分では、オブジェクトは通常、シーンに奥行きの錯覚を与えるために、ビューアーからの距離に関連してスケーリングされます。閉じるオブジェクトは、遠くのオブジェクトよりも大きく表示されます。 わかりやすくするために、このドキュメントでは、射影変換後に頂点が存在する空間を "射影空間" と呼びます。 グラフィックスの解説書によっては、射影空間を "透視射影変換後の同次空間" と呼ぶ場合もあります。 すべての射影変換でシーン内のオブジェクトのサイズが変更されるとは限りません。 このような射影は、"アフィン変換" や "直行変換" と呼ばれることがあります。
パイプラインの最後の部分では、画面に表示されない頂点がすべて削除されます。これにより、表示されないオブジェクトの色や影の計算にラスタライザーが時間を費やすことはなくなります。 このプロセスを "クリッピング" と呼びます。 クリッピング後、残りの頂点はビューポート パラメーターに従ってスケーリングされ、スクリーン座標に変換されます。 結果として得られる頂点は "スクリーン空間" に存在し、シーンがラスタライズされるときに画面に表示されます。
変換は、オブジェクト ジオメトリをある座標空間から別の座標空間に変換するために使われます。 Direct3D では、行列を使って 3D 変換を実行します。 このセクションでは、マトリックスが 3D 変換を作成する方法、変換の一般的な用途について説明し、複数の変換を含む単一の行列を生成するためにマトリックスを結合する方法について詳しく説明します。
- ワールド変換 (Direct3D 9) - モデル空間からワールド空間への変換
- ビュー変換 (Direct3D 9) - ワールド空間から表示空間への変換
- 投影変換 (Direct3D 9) - ビュー空間から投影空間への変換
行列変換
3D グラフィックスを使用するアプリケーションでは、幾何学変換を使って次の操作を実行できます。
- オブジェクトの位置を、別のオブジェクトからの相対的な位置で表現する。
- オブジェクトを回転し、サイズを変更する。
- 視点、向き、奥行きを変更する。
次の方程式に示すように、4x4 行列を使うことで任意の点 (x,y,z) を別の点 (x', y', z') に変換できます。
(x, y, z) と行列に対して次の方程式を実行すると、点 (x', y', z') が生成されます。
最も一般的な変換は、平行移動、回転、スケーリングです。 これらの効果を生成する行列を結合して 1 つの行列にすると、複数の変換を一度に計算できます。 たとえば、一連の点に平行移動と回転を適用する 1 つの行列を作成することができます。
行列は、行、列の順番に記述されます。 各軸に対して頂点を均等にスケーリングする処理は均等スケーリングと呼ばれ、これを実行する行列は数学的に次のように表記されます。
C++ では、Direct3D は D3DMATRIX 構造体を使用して、行列を 2 次元配列として宣言します。 次の例は、均一なスケーリング マトリックスとして機能するように D3DMATRIX 構造体を初期化する方法を示しています。
// In this example, s is a variable of type float.
D3DMATRIX scale = {
s, 0.0f, 0.0f, 0.0f,
0.0f, s, 0.0f, 0.0f,
0.0f, 0.0f, s, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
Translate
次の方程式は、点 (x, y, z) を新しい点 (x', y', z') に平行移動します。
C++ では、平行移動行列を手動で作成することができます。 次の例は、頂点を平行移動する行列を作成する関数のソース コードを示しています。
D3DXMATRIX Translate(const float dx, const float dy, const float dz) {
D3DXMATRIX ret;
D3DXMatrixIdentity(&ret);
ret(3, 0) = dx;
ret(3, 1) = dy;
ret(3, 2) = dz;
return ret;
} // End of Translate
便宜上、D3DX ユーティリティ ライブラリは D3DXMatrixTranslation 関数を提供 します。
スケール
次の方程式は、点 (x, y, z) を x 方向、y 方向、z 方向に任意の値でスケーリングして、新しい点 (x', y', z') を求めます。
Rotate
ここで説明する変換は左手座標系を想定しているため、他の場所に記述されている変換行列とは異なる場合があります。
次の方程式は、x 軸を中心に点 (x, y, z) を回転し、新しい点 (x', y', z') を求めます。
次の方程式は、y 軸を中心に点を回転します。
次の方程式は、z 軸を中心に点を回転します。
これらの行列の例において、ギリシャ文字シータはラジアン単位の回転角度を表しています。 角度は、回転軸に沿って原点を見た状態で時計回りに測定されます。
C++ アプリケーションでは、D3DX ユーティリティ ライブラリによって提供される D3DXMatrixRotationX、 D3DXMatrixRotationY、 および D3DXMatrixRotationZ 関数を使用して、回転行列を作成します。 D3DXMatrixRotationX 関数のコードを次に示します。
D3DXMATRIX* WINAPI D3DXMatrixRotationX
( D3DXMATRIX *pOut, float angle )
{
#if DBG
if(!pOut)
return NULL;
#endif
float sin, cos;
sincosf(angle, &sin, &cos); // Determine sin and cos of angle
pOut->_11 = 1.0f; pOut->_12 = 0.0f; pOut->_13 = 0.0f; pOut->_14 = 0.0f;
pOut->_21 = 0.0f; pOut->_22 = cos; pOut->_23 = sin; pOut->_24 = 0.0f;
pOut->_31 = 0.0f; pOut->_32 = -sin; pOut->_33 = cos; pOut->_34 = 0.0f;
pOut->_41 = 0.0f; pOut->_42 = 0.0f; pOut->_43 = 0.0f; pOut->_44 = 1.0f;
return pOut;
}
行列の連結
行列を使う利点の 1 つは、2 つ以上の行列を掛け合わせて、それらの効果を組み合わせることができる点にあります。 つまり、モデルを回転した後で別の場所へ平行移動する場合でも、2 つの行列を適用する必要はありません。 代わりに、回転行列と平行移動行列を掛け合わせて、両方の効果を含む合成行列を生成します。 このプロセスは行列の連結と呼ばれ、次の方程式によって記述できます。
この方程式では、C は作成される合成行列を表し、M ~ Mₙ は個々の行列を表します。 ほとんどの場合、連結される行列は 2 ~ 3 個だけですが、数に制限はありません。
行列乗算を実行するには 、D3DXMatrixMultiply 関数を使用します。
行列の乗算を実行する順序は非常に重要です。 上の式は、行列が左から右へ連結されることを示しています。 つまり、合成行列の作成に使われる各行列の視覚効果は、左から右へ順番に適用されます。 ここで、典型的なワールド行列の例を考えてみましょう。 たとえば、よくある空飛ぶ円盤を表すワールド行列を作成するとします。 空飛ぶ円盤に期待されるのは、その中心点 (モデル空間の y 軸) で回転しながら、シーン内の別の場所に平行移動するという動作です。 この効果を実現するには、まず回転行列を作成し、それに平行移動行列を掛け合わせます。この方程式を次に示します。
この式では、Ry は y 軸周りの回転行列を表し、Tw はワールド座標の別の場所への平行移動を表します。
2 つのスカラー値を乗算する場合とは異なり、行列の乗算は非可換であるため、行列を乗算する順序には重要な意味があります。 行列を逆の順序で乗算すると、空飛ぶ円盤をワールド空間の場所へ平行移動させてから、ワールド原点を中心に回転させるという視覚効果になります。
どのような種類の行列を作成する場合でも、期待どおりの効果を得るためには、左から右という規則を覚えておくことが重要です。
関連トピック