Cone.x を描画する

Cone.x を回転しながら描画する

EmptyProject10 をベースに X9 で Cone.x を回転しながら描画します。
DirectX10 では X-FILE を直接描画することが出来ないようです。 (^_^;)
そこで EmptyProject10 に組み込まれている DirectX9 の機能を使って X-FILE を描画してみます。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの説明

  1. DirectX June 2010 の Sample Brower を使って EmptyProject10 を生成すると EmptyProject9.cpp が組み込まれています。
    EmptyProject10.cpp と EmptyProject9.cpp が格納されていることを確認して、そのままプロジェクトを実行して下さい。
    エラーが発生するときや、正常に実行出来ないときは、残念ながら現在の構成は相性が悪いようです。
  2. EmptyProject10.cpp の wWinMain() 関数を表示して下さい。
    次の行をコメントアウト(または削除)します。
    関数の本体も含めて削除すると、プログラムがすっきりします。
    /*
        DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable );
        DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice );
        DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizedSwapChain );
        DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender );
        DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain );
        DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice );
    */
    
    EmptyProject10.cpp の修正はこれだけです。
  3. EmptyProject9.cpp を修正して Cone.x を描画します。
    Cone.x は X-FILE(Cone.x) の頂点データを定義する から取得することが出来ます。
    DXUT.h に続いて次の行を追加します。
    strsafe.h は MultiByteToWideChar() 関数で MultiByte を WideChar に変換するときに必要です。
    領域の説明は DirectX9 のメッシュの描画を参照して下さい。
    #include "DXUT.h"
    #include <strsafe.h>
    
    LPD3DXMESH              g_pMesh          = NULL; // Our mesh object in sysmem
    D3DMATERIAL9*           g_pMeshMaterials = NULL; // Materials for our mesh
    LPDIRECT3DTEXTURE9*     g_pMeshTextures  = NULL; // Textures for our mesh
    DWORD                   g_dwNumMaterials = 0L;   // Number of mesh materials
    D3DMATERIAL9            material;
    D3DLIGHT9               light;
    
  4. OnD3D9CreateDevice() で DirectX とアプリケーションの初期化を行います。
    MultiByte を WideChar(Unicode) に変更することを除いて、DirectX9 と同じ要領です。
    今回は Shader を使っていないので、マテリアルと光源の設定が必要です。
    HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                         void* pUserContext )
    {
        LPD3DXBUFFER pD3DXMtrlBuffer;
        WCHAR *wszName;
        WCHAR wszBuf[MAX_PATH];
        wszName = wszBuf;
    
        SetCurrentDirectory(L"C:\\DATA\\Model");
        if (FAILED(D3DXLoadMeshFromX(L"Cone.x",D3DXMESH_SYSTEMMEM,pd3dDevice,NULL,
                                    &pD3DXMtrlBuffer,NULL,&g_dwNumMaterials,&g_pMesh)))
        {   MessageBox(NULL,L"Could not find Cone.x",L"Meshes.exe",MB_OK);
            return E_FAIL;
        }
        D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
        g_pMeshMaterials= new D3DMATERIAL9[g_dwNumMaterials];
        if(g_pMeshMaterials==NULL)  return E_OUTOFMEMORY;
        g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];
        if(g_pMeshTextures==NULL)   return E_OUTOFMEMORY;
        for(DWORD i=0; i<g_dwNumMaterials; i++)
        {   g_pMeshMaterials[i]= d3dxMaterials[i].MatD3D;
            g_pMeshTextures[i] = NULL;
            if (d3dxMaterials[i].pTextureFilename!=NULL)
            {   MultiByteToWideChar( CP_ACP, 0, d3dxMaterials[i].pTextureFilename, -1, wszBuf, MAX_PATH );
                if (wszBuf[0]!=NULL)
                {   if(FAILED(D3DXCreateTextureFromFile(pd3dDevice,wszName,&g_pMeshTextures[i])))
                        MessageBox(NULL,L"Could not find texture map",L"Meshes.exe",MB_OK);
                }
            }
        }
        pD3DXMtrlBuffer->Release();
        //マテリアルの設定
        material.Diffuse.r= material.Diffuse.g= material.Diffuse.b= 1.0f;
        material.Ambient.r= material.Ambient.g= material.Ambient.b= 0.5f;
        material.Specular.r= material.Specular.g= material.Specular.b= 0.0f;
        material.Emissive.r= material.Emissive.g= material.Emissive.b= 0.0f;
        material.Power= 0;
        //光源の作成
        ZeroMemory(&light,sizeof(D3DLIGHT9));
        light.Type = D3DLIGHT_DIRECTIONAL;
        light.Diffuse.r= light.Diffuse.g= light.Diffuse.b= 1.0f;
        light.Specular.r= light.Specular.g= light.Specular.b= 0.2f;
        light.Ambient.r= light.Ambient.g= light.Ambient.b= 0.5f;
        light.Direction = D3DXVECTOR3(10,-20,10);
    
        return S_OK;
    }
    
  5. OnD3D9FrameRender 関数の直前に、SetupMatrices() 関数を追加します。
    timeGetTime() の値でY座標を軸に回転しながら描画します。
    // Matrices の設定
    VOID SetupMatrices( IDirect3DDevice9* pd3dDevice )
    {
        D3DXMATRIXA16 matWorld;
        D3DXMatrixRotationY(&matWorld,timeGetTime()/1000.0f);
        pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);
        D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
        D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
        D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
        D3DXMATRIXA16 matView;
        D3DXMatrixLookAtLH(&matView,&vEyePt,&vLookatPt,&vUpVec);
        pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
        D3DXMATRIXA16 matProj;
        D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,10000.0f);
        pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
    
        pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);     //カリングを行う
        pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);            //ライティングする
    
        pd3dDevice->SetLight(0,&light);
        pd3dDevice->LightEnable(0,TRUE);
        pd3dDevice->SetMaterial(&material);
    }
    
  6. OnD3D9FrameRender() は Rendering を行う CALLBACK 関数です。
    DirectX9 と同じ要領です。
    void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
    {
        HRESULT hr;
    
        // Clear the render target and the zbuffer 
        V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 150, 200, 200), 1.0f, 0) );
    
        // Render the scene
        if( SUCCEEDED( pd3dDevice->BeginScene() ) )
        {   SetupMatrices(pd3dDevice);
            for(DWORD i=0; i<g_dwNumMaterials; i++)
            {   pd3dDevice->SetMaterial(&g_pMeshMaterials[i]);
                pd3dDevice->SetTexture(0,g_pMeshTextures[i]);
                g_pMesh->DrawSubset(i);
            }
            pd3dDevice->EndScene();
        }
        pd3dDevice->Present(NULL,NULL,NULL,NULL);
    }
    
  7. OnD3D9DestroyDevice() で資源を解放します。
    void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
    {
        if(g_pMeshMaterials!=NULL)  delete[] g_pMeshMaterials;
        if(g_pMeshTextures)
        {   for( DWORD i=0; i<g_dwNumMaterials; i++)
            {   if(g_pMeshTextures[i])  g_pMeshTextures[i]->Release();
            }
            delete[] g_pMeshTextures;
        }
        if(g_pMesh!=NULL)       g_pMesh->Release();
    }
    
  8. プロジェクトを実行すると Cone.X が回転しながら描画されます。
    アニメーションしないのであれば "tiny.x" も同じように描画できます。
    ただし、モデルのサイズが Cone.X に比べてかなり大きいので注意して下さい。
    DirectX9 で同様のプログラムを作成しています。
    超初心者のプログラム入門(DirectX9)から Sample Brower で X-FILE を描画 を参照して下さい。

超初心者のプログラム入門(DirectX10 game program)