Tiger.x を描画する

Tiger.x を回転しながらマウスで操作する

EmptyProject10 をベースに X9 で Tiger.x を回転しながらマウスで操作します。

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

プロジェクトの説明

  1. DirectX June 2010 の Sample Brower を使って EmptyProject10 を生成すると EmptyProject9.cpp が組み込まれています。
    EmptyProject10.cpp と EmptyProject9.cpp が格納されていることを確認して、そのままプロジェクトを実行して下さい。
    エラーが発生するときや、正常に実行出来ないときは、残念ながら現在の構成は相性が悪いようです。
    Cone.x を回転しながら描画する では従来と同様にプログラムしましたが、今回は DXUT の便利な API を使います。
  2. EmptyProject10.cpp の 修正です。
    EmptyProject9 の関数を呼び出すので、次の宣言を追加して下さい。
    // EmptyProject9 で定義された関数の宣言です。
    void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
    LRESULT CALLBACK MsgProc( HWND, UINT, WPARAM, LPARAM, bool*, void* );
    
    EmptyProject10.cpp に定義されている次の関数を削除して下さい。
    OnFrameMove() 関数
    MsgProc() 関数
  3. EmptyProject10.cpp の wWinMain() 関数を表示して下さい。
    次の行をコメントアウト(または削除)します。
    関数の本体も含めて削除すると、プログラムがすっきりします。
        // Set the D3D10 DXUT callbacks. Remove these sets if the app doesn't need to support D3D10
    /*
        DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable );
        DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice );
        DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizedSwapChain );
        DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender );
        DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain );
        DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice );
    */
    
    EmptyProject10.cpp の修正はこれだけです。
  4. EmptyProject9.cpp を修正して Tiger.x を描画します。
    Tiger.x は古くから使われているサンプルモデルなので、そのへんに転がっているのを拾ってきて下さい。
    DXUT.h に続いて次の行を追加します。
    Cone.x では LPD3DXMESH を使いましたが、今回は CDXUTXFileMesh を使います。
    CDXUTXFileMesh は LPD3DXMESH(従来から使われている基本メッシュ)をラップした便利なクラスです。
    #include "DXUT.h"
    #include "DXUTcamera.h"
    #include "SDKmesh.h"
    
    CModelViewerCamera      g_Camera;
    CDXUTXFileMesh          g_Mesh;
    D3DMATERIAL9            material;
    D3DLIGHT9               light;
    
  5. OnD3D9CreateDevice() で DirectX とアプリケーションの初期化を行います。
    CDXUTXFileMesh を使うと X-FILE のロードは一行だけです。
    また tiger.x には法線ベクトルが設定されていないのですが、設定も g_Mesh.SetFVF() を呼び出すだけです。
    vecEye と vecAt を定義して g_Camera の ViewParams を設定します。
    HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice,
            const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
    {
        HRESULT     hr;
    
        V_RETURN( g_Mesh.Create( pd3dDevice, L"C:\\DATA\\Model\\tiger.x" ) );
    
        //法線ベクトルを設定
        DWORD   dwFVF;
        dwFVF= g_Mesh.m_pMesh->GetFVF();
        if ((dwFVF & D3DFVF_NORMAL)==0)
            g_Mesh.SetFVF(pd3dDevice, dwFVF | D3DFVF_NORMAL);
    
        // Setup the camera's view parameters
        D3DXVECTOR3 vecEye( 0.0f, 0.0f, -5.0f );
        D3DXVECTOR3 vecAt ( 0.0f, 0.0f, 0.0f );
        g_Camera.SetViewParams( &vecEye, &vecAt );
    
        return S_OK;
    }
    
  6. OnD3D9ResetDevice() で描画環境を設定します。
    今回は Shader を使っていないので、マテリアルと光源の設定も必要です。
    HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice,
            const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
    {
        float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
        g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
        g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
    
        pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);     //カリングを行う
        pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);            //ライティングする
    
        //マテリアルの設定
        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;
        pd3dDevice->SetMaterial(&material);
    
        //光源の設定
        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);
        pd3dDevice->SetLight(0,&light);
        pd3dDevice->LightEnable(0,TRUE);
    
        return S_OK;
    }
    
  7. OnD3D9FrameRender() は Rendering を行う CALLBACK 関数です。
    タイマを使ってY軸で自動的に回転しながら描画しています。
    マウスの操作で回転すると g_Camera.GetWorldMatrix() と g_Camera.GetViewMatrix() の座標が回転します。
    この情報を WORLD と VIEW に設定して描画します。
    CDXUTXFileMesh を使うと、描画は実質的に g_Mesh.Render(pd3dDevice) の一行だけです。
    void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime,
            float fElapsedTime, void* pUserContext )
    {
        HRESULT hr;
        D3DXMATRIXA16 matWorld;
    
        D3DXMatrixRotationY(&matWorld,timeGetTime()/1000.0f);
        matWorld = *g_Camera.GetWorldMatrix() * matWorld;
        pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);
        pd3dDevice->SetTransform(D3DTS_VIEW, &(*g_Camera.GetViewMatrix()));
        pd3dDevice->SetTransform(D3DTS_PROJECTION, &(*g_Camera.GetProjMatrix()));
    
        // 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() ) )
        {
            V( g_Mesh.Render( pd3dDevice ) );
            pd3dDevice->EndScene();
        }
    }
    
  8. OnD3D9DestroyDevice() で資源を解放します。
    void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
    {
        g_Mesh.Destroy();
    }
    
  9. OnFrameMove() では g_Camera.FrameMove() を呼んで下さい。
    void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
    {
        // Update the camera's position based on user input 
        g_Camera.FrameMove( fElapsedTime );
    }
    
  10. マウスでモデルを回転する処理は結構面倒なのですが、g_Camera を使うと HandleMessages() を呼び出すだけです。
    LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                              bool* pbNoFurtherProcessing, void* pUserContext )
    {
        g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
    
        return 0;
    }
    
  11. プロジェクトを実行すると Tiger.X が回転しながら描画されます。
    マウスの左ボタンで WORLD 座標が回転します。
    マウスの右ボタンで VIEW 座標が回転します。
    他の X-FILE も試してみて下さい。
    DirectX10 のプロジェクト(.sdkmesh)でも同様のプログラムを作成しています。
    Tiger.sdkmesh を描画 を参照して下さい。
    DirectX9 でも同様のプログラムを作成しています。
    マテリアルを設定して、虎のモデルを描画する を参照して下さい。

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