さて、いままでのところで、ポリゴンはあらかた表示できるようになったと思います。
ですが、実際にゲームを作るようになると、全部ポリゴンで表示するなんてやってられません。
実際には自分でフォーマットを作って、コンバートを作るのがいいのでしょうが、
考えたり、作ったりに時間もかかりますし、パフォーマンスが出る方法を考えるのは大変です。
さらに、動きが速いこの業界では、一年前にパフォーマンスがある仕様が現在では効率が悪いのはざらです。
ということで、すでにあるフォーマットを利用します。
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 ファイルを読み込んでも、きちんと表示できるはずです。