Share via


行列スタック

行列スタック

Direct3D エクステンション (D3DX) ユーティリティ ライブラリは、ID3DXMatrixStack インターフェイスを備えている。このインターフェイスは、行列を行列スタックにプッシュしたり、行列スタックからポップ オフしたりするためのメカニズムを提供する。行列スタックを実装すると、トランスフォーム階層内を移動する際に、行列を効率よく管理できる。

D3DX ユーティリティ ライブラリは、行列スタックを使ってトランスフォームを行列として格納する。ID3DXMatrixStack インターフェイスのさまざまなメソッドを使って、現在の行列 (行列の最上部にある行列) を操作できる。現在の行列をクリアするには、ID3DXMatrixStack::LoadIdentity メソッドを使う。特定の行列を現在のトランスフォーム行列としてロードするよう明示的に指定するには、ID3DXMatrixStack::LoadMatrix メソッドを使う。その後 ID3DXMatrixStack::MultMatrix メソッドまたは ID3DXMatrixStack::MultMatrixLocal メソッドを呼び出して、現在の行列を指定した行列で乗算することができる。

ID3DXMatrixStack::Pop メソッドを使うと、前のトランスフォーム行列に戻り、ID3DXMatrixStack::Push メソッドを使うと、スタックにトランスフォーム行列が追加される。

行列スタック上の個々の行列は、D3DX ユーティリティ ライブラリの D3DXMATRIX 構造体によって定義された 4 × 4 の同次行列として表現される。

D3DX ユーティリティ ライブラリは、コンポーネント オブジェクト モデル (COM) オブジェクトを使った行列スタックを提供している。

シーンの階層の実装

一連の単純なオブジェクトから複雑なオブジェクトが構築される階層モデルは、行列スタックを使うことで簡単に構築できるようになる。

シーンやトランスフォームでは、階層は通常ツリー データ構造として表現される。ツリー データ構造内の各ノードには行列が含まれる。特定の行列は、ノードの親からノードへの座標系の変化を表す。たとえば、人間の腕をモデリングしている場合、次のような階層を実装する場合がある。

人間の腕のモデルの階層

この階層では、Body 行列が胴体をワールド内に配置する。UpperArm 行列には肩の回転、LowerArm 行列にはひじの回転、Hand 行列には手首の回転がそれぞれ含まれる。手がどこでワールドと関連するかを決定するには、Body から Hand までの行列をすべて乗算する。

前の階層は、各ノードに子が 1 つずつしかなかったので、非常に単純であった。より詳細に手をモデリングする場合は、指を追加することになる。5 本の指はすべて、Hand の子として階層に追加できる。

人間の手のモデルの階層

腕の完全なグラフ内を深度優先の順序 (単一のパスをできるだけ深く移動してから次のパスに移る) で移動する場合は、分断された一連のレンダリングを実行することになる。たとえば、手と指をレンダリングする場合は、次の手順を実行する。

  1. Hand 行列を行列スタックにプッシュする。
  2. 手を描画する。
  3. Thumb 行列を行列スタックにプッシュする。
  4. 親指を描画する。
  5. Thumb 行列をスタックからポップ オフする。
  6. Finger 1 行列を行列スタックにプッシュする。
  7. 最初の指を描画する。
  8. Finger 1 行列をスタックからポップ オフする。
  9. Finger 2 行列を行列スタックにプッシュする。すべての指がレンダリングされるまで、この手順を繰り返す。

指のレンダリングが終わったら、Hand 行列をスタックからポップ オフする。

次の例を使って、この基本的なプロセスをコード内で実行できる。ツリー データ構造の深度優先検索中にノードが見つかったら、行列を行列スタックの最上部にプッシュする。

MatrixStack->Push();

MatrixStack->MultMatrix(pNode->matrix);

ノードの操作が終了したら、行列を行列スタックの最上部からポップ オフする。

MatrixStack->Pop();

つまり、スタックの最上部にある行列は、常に現在のノードのワールド トランスフォームを表す。このため、各ノードの描画前に、Microsoft® Direct3D® 行列を設定する必要がある。

pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(0), *MatrixStack->GetTop());

D3DX 行列スタックで実行できるさまざまなメソッドについての詳細は、「ID3DXMatrixStack」を参照すること。