0からのゲームプログラミング > 行列

Back Next
更新日 2004.04.24
行列

 前回まではヘリコプターのみを表示させていましたが、今回は地面を新たに追加してみることにします。下のような地面を作成し、Xファイルで保存するときには 20 倍に拡大しています。


ダウンロード Ground.zip [ 16.8 KB ]

地面 (左:全体像 右:中央を拡大)
全体像 中央を拡大


 ZIPファイルを解凍して出来た Ground フォルダごと DataForWork フォルダ内に入れておき、以下のように、地面のコードを追加します。


Screen.h

//====================================================================
//			CScreenStage クラスの定義
//====================================================================
class CScreenStage : public CScreen{
	CXFile		m_xHeli;		// ヘリ本体
	CXFile		m_xProp;		// プロペラ
	CXFile		m_xGround;		// 地面

	・
	・
	・
};


ScreenStage.cpp

// コンストラクタ
CScreenStage::CScreenStage()
{
	・
	・
	・


	// Xファイルを読み込む
	m_xHeli.Load(g_pD3DDevice, "DataForWork/Heli/Heli.x");
	m_xProp.Load(g_pD3DDevice, "DataForWork/Heli/Prop.x");
	m_xGround.Load(g_pD3DDevice, "DataForWork/Ground/Ground.x");


	・
	・
	・
}


// 描画
// 引数、戻値なし。
void CScreenStage::Draw(void)
{
	・
	・
	・


	// Xファイルを描画する
	m_xHeli.Draw(g_pD3DDevice);
	m_xProp.Draw(g_pD3DDevice);
	m_xGround.Draw(g_pD3DDevice);


	・
	・
	・
}


 これで実行してみると、以下のようになります。

スクリーンショット


 はい、ヘリが地面に埋まっています。(笑)イメージして頂いた通りになっていると思います。ヘリと地面を重ね合わせて描画しただけですから、このような結果になりますよね。


◆ 行列

 このヘリを移動させたりする為に、行列マトリックスmatrix)を使います。2D編でも触れましたが、ここでは行列について深く考えず、DirectX で用意されている D3DXMATRIX 構造体 を使っていきます。


 行列を使う準備として、以下のようにコードを加えます。


Screen.h

//====================================================================
//			CScreenStage クラスの定義
//====================================================================
class CScreenStage : public CScreen{
	// Xファイル
	CXFile		m_xHeli;		// ヘリ本体
	CXFile		m_xProp;		// プロペラ
	CXFile		m_xGround;		// 地面

	// マトリックス(行列)
	D3DXMATRIX	m_MtrxHeli;		// ヘリ本体
	D3DXMATRIX	m_MtrxProp;		// プロペラ
	D3DXMATRIX	m_MtrxGround;		// 地面

	・
	・
	・
};


ScreenStage.cpp

// コンストラクタ
CScreenStage::CScreenStage()
{
	// ファイルパック開始
	g_pFilePack->Begin("Data/Pack0.dat");


	// Xファイルを読み込む
	m_xHeli.Load(g_pD3DDevice, "DataForWork/Heli/Heli.x");
	m_xProp.Load(g_pD3DDevice, "DataForWork/Heli/Prop.x");


	// ファイルパック終了
	g_pFilePack->End();


	// 単位行列作成
	D3DXMatrixIdentity(&m_MtrxHeli);
	m_MtrxProp = m_MtrxGround = m_MtrxHeli;


	// 描画の初期設定等
	InitRender();
}


// 描画
// 引数、戻値なし。
void CScreenStage::Draw(void)
{
	// 画面クリア
	g_pD3DDevice->Clear(0, NULL, g_pFormat->GetFlags(), D3DCOLOR_XRGB(0, 255, 0), 1, 0);

	// 描画開始
	g_pD3DDevice->BeginScene();


	// ワールド・トランスフォームを行い、Xファイルを描画する

	// ヘリ本体
	g_pD3DDevice->SetTransform(D3DTS_WORLD, &m_MtrxHeli);
	m_xHeli.Draw(g_pD3DDevice);

	// プロペラ
	g_pD3DDevice->SetTransform(D3DTS_WORLD, &m_MtrxProp);
	m_xProp.Draw(g_pD3DDevice);

	// 地面
	g_pD3DDevice->SetTransform(D3DTS_WORLD, &m_MtrxGround);
	m_xGround.Draw(g_pD3DDevice);


	// 描画終了
	g_pD3DDevice->EndScene();

	// 画面更新
	g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}


 ヘリ本体、プロペラ、地面、それぞれに対して D3DXMATRIX 構造体 を用意しています。コンストラクタでは、それぞれの変数に初期値として単位行列を格納しています。そして、描画するときには、ワールド・トランスフォームを行い、Xファイルを描画するように変更しています。


 単位行列とは、行列の対角線上の成分がすべて 1 で、他の成分は 0 である正方行列であり、・・・云々かんぬん。とありますが、詳しくは数学の教科書等を参照して下さい。D3DXMATRIX 構造体の初期値は、単位行列を入れておけば問題ないです。D3DXMatrixIdentity 関数は、単位行列を作成する関数です。


 ワールド・トランスフォームとは、モデル空間からワールド空間へ座標を変換する [ トランスフォーム、transform ] ことです。トランスフォームするには、IDirect3DDevice9::SetTransform メソッド を使います。

 第1引数には、D3DTS_WORLD (ワールド・トランスフォーム) をセットし、第2引数には、D3DMATRIX 構造体へのポインタを渡します。


参考(順番にトランスフォームしていきます。)

ワールド・トランスフォームモデル座標ワールド座標

ビュー・トランスフォームワールド座標ビュー座標

射影・トランスフォームビュー座標射影座標

ビューポート変換射影座標スクリーン座標

【スポンサード リンク】


Back Next

0からのゲームプログラミング > 行列