さて、いままでのところで、ポリゴンはあらかた表示できるようになったと思います。
ですが、実際にゲームを作るようになると、全部ポリゴンで表示するなんてやってられません。
実際には自分でフォーマットを作って、コンバートを作るのがいいのでしょうが、
考えたり、作ったりに時間もかかりますし、パフォーマンスが出る方法を考えるのは大変です。
さらに、動きが速いこの業界では、一年前にパフォーマンスがある仕様が現在では効率が悪いのはざらです。
ということで、すでにあるフォーマットを利用します。
DirectX で有名なフォーマットは、Xファイルです。このファイルを表示します。
いつも通り、以下のファイルをダウンロードしてください。
今回は、さらに car.x というファイルが入っています。
これが X ファイルです。
この X ファイルは、LightWave6.5 でつくったファイルを、D-STORM さんから落とした DirectX Export プラグインで出力しました。
さて、draw.cpp です。
今回は新しいオブジェクトだらけです。
X ファイルのモデルは、『メッシュ』で管理されます。
メッシュ自体の情報が、pMesh に入ります。
pMeshMaterials は、ライトに対する応答について格納されます。
pMeshTextures は、テクスチャーの情報です。
dwNumMaterials は、Xファイルのモデルがいくつに分かれているか収まっています。
LPD3DXMESH pMesh = NULL; // メッシュ D3DMATERIAL8 *pMeshMaterials = NULL; // メッシュの質感 LPDIRECT3DTEXTURE8 *pMeshTextures = NULL; // メッシュのテクスチャー DWORD dwNumMaterials = 0L; // マテリアルの数
次が初期化部分です。
HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDEV)
{
HRESULT hr;
LPD3DXBUFFER pD3DXMtrlBuffer;
// X ファイルのロード
hr = D3DXLoadMeshFromX( "car.x", D3DXMESH_SYSTEMMEM,
lpD3DDEV, NULL,
&pD3DXMtrlBuffer, &dwNumMaterials,
&pMesh );
if(FAILED(hr)) return E_FAIL;
// pD3DXMtrlBuffer から、質感やテクスチャーの情報を読み取る
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
pMeshMaterials = new D3DMATERIAL8[dwNumMaterials];
pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials];
for( DWORD i=0; i < dwNumMaterials; i++ ){
pMeshMaterials[i] = d3dxMaterials[i].MatD3D;// 質感のコピー
pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;// マテリアルの環境色を設定する
hr = D3DXCreateTextureFromFile( lpD3DDEV,
d3dxMaterials[i].pTextureFilename,
&pMeshTextures[i] );
if(FAILED(hr)) pMeshTextures[i] = NULL;
}
RELEASE(pD3DXMtrlBuffer);
lpD3DDEV->SetRenderState( D3DRS_ZENABLE, TRUE);
lpD3DDEV->SetRenderState( D3DRS_AMBIENT, 0xffffffff);
return S_OK;
}
D3DXLoadMeshFromX で、ファイルをロードします。 そのあと、X ファイルの情報を元に、 d3dxMaterials に質感の情報を設定したり、 D3DXCreateTextureFromFile でテクスチャーをロードします。
あと、Z バッファーを有効にして、アンビエントライト(環境色:周りから一様にあたるライト)を設定します。
表示です。最初のほうは、3D ポリゴンを表示したときと同じように、 表示マトリックスの設定です。 最後の for ループがモデルの表示です。 マテリアルごとに、質感やテクスチャーを設定してから表示します。
void Render(LPDIRECT3DDEVICE8 lpD3DDEV)
{
D3DXMATRIX mWorld;
D3DXMatrixRotationY( &mWorld, timeGetTime()/1000.0f );
D3DXMATRIX mView, mProj;
D3DXMatrixLookAtLH( &mView, &D3DXVECTOR3( 0.0f, 3.0f, 4.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
D3DXMatrixPerspectiveFovLH(&mProj
,60.0f*PI/180.0f // 視野角
,1.0f // アスペクト比
,0.01f // 最近接距離
,100.0f // 最遠方距離
);
lpD3DDEV->SetTransform(D3DTS_WORLD, &mWorld);
lpD3DDEV->SetTransform(D3DTS_VIEW, &mView);
lpD3DDEV->SetTransform(D3DTS_PROJECTION, &mProj);
for( DWORD i=0; i < dwNumMaterials; i++ ){
lpD3DDEV->SetMaterial( &pMeshMaterials[i] );
lpD3DDEV->SetTexture( 0, pMeshTextures[i] );
pMesh->DrawSubset( i );
}
}
後始末は、作成したオブジェクトを開放します。
void CleanRender()
{
if( pMeshMaterials != NULL ) delete[] pMeshMaterials;
if( pMeshTextures ){
for( DWORD i = 0; i < dwNumMaterials; i++ ){
RELEASE(pMeshTextures[i]);
}
delete[] pMeshTextures;
}
RELEASE(pMesh);
}
今回の X ファイルは、テクスチャーが張っていませんが、プログラムは、テクスチャーに対応しています。 他の X ファイルを読み込んでも、きちんと表示できるはずです。