Xファイルの表示


~いちいちポリゴンでなんてやってられません ~




■はじめに

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





もどる

imagire@gmail.com