Tiny.x でアニメーション

EmptyProject10 をベースに X9 で Tiny.x のアニメーションを描画します。
DirectX10 では X-FILE を直接描画することが出来ないようです。 (^_^;)
そこで EmptyProject10 に組み込まれている DirectX9 の機能を使って X-FILE を描画してみます。
Tiny.x にはモデルデータだけでなく、モデルを動かす bone のデータも格納されています。

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

プロジェクトの設定

  1. DirectX June 2010 の Sample Brower を使って EmptyProject10 を生成すると EmptyProject9.cpp が組み込まれています。
    EmptyProject10.cpp と EmptyProject9.cpp が格納されていることを確認して、プロジェクトが正常に実行されることを確かめて下さい。
    エラーが発生するときや、正常に実行出来ないときは、残念ながら現在の構成は相性が悪いようです。
    ファイル名 説明
    XfileTiny.zip 圧縮ファイル
  2. EmptyProject10.cpp の修正です。
    1. 関数宣言の修正です。
      OnFrameMove は EmptyProject9.cpp で定義した関数を使います。
      EmptyProject10.cpp の OnFrameMove() は削除して下さい。
      終了時に DrawMeshContainer を再帰的に開放する ReleaseFrame() 関数を呼び出します。
      //extern bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat,
      //            D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext );
      extern HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice,
                    const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
      extern HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice,
                    const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
      extern void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime,
                    float fElapsedTime, void* pUserContext );
      //extern void CALLBACK OnD3D9LostDevice( void* pUserContext );
      extern void CALLBACK OnD3D9DestroyDevice( void* pUserContext );
      
      extern void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
      extern void ReleaseFrame();
      
    2. wWinMain() の修正です。
      DirectX10 に関係する次の行をコメントアウト(または削除)して下さい。
      関数の本体も含めて削除すると、プログラムがすっきりします。
      終了時に DrawMeshContainer を再帰的に開放する関数 ReleaseFrame() を呼び出します。
      int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
      {
          // Enable run-time memory check for debug builds.
      #if defined(DEBUG) | defined(_DEBUG)
          _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
      #endif
      
          // DXUT will create and use the best device (either D3D9 or D3D10) 
          // that is available on the system depending on which D3D callbacks are set below
      
          // Set general DXUT callbacks
          DXUTSetCallbackFrameMove( OnFrameMove );
          DXUTSetCallbackKeyboard( OnKeyboard );
          DXUTSetCallbackMouse( OnMouse );
          DXUTSetCallbackMsgProc( MsgProc );
          DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
          DXUTSetCallbackDeviceRemoved( OnDeviceRemoved );
      
          // Set the D3D9 DXUT callbacks. Remove these sets if the app doesn't need to support D3D9
          //DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
          DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
          DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );
          DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );
          //DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );
          DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
      
          // 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 );
      */
          // Perform any application-level initialization here
          
          DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
          DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
          DXUTCreateWindow( L"EmptyProject10" );
          DXUTCreateDevice( true, 640, 480 );  
          DXUTMainLoop(); // Enter into the DXUT render loop
      
          // Perform any application-level cleanup here
          ReleaseFrame();
      
          return DXUTGetExitCode();
      }
      
  3. EmptyProject9.cpp のソースコードです。
    1. ヘッダファイルの include と構造体と Object Class の宣言です。
      ソースコードが長いので、最初の部分だけを掲載しています。
      あとは EmptyProject9.cpp のソースコードを参照して下さい。
      #include "DXUT.h"
      #include "DXUTcamera.h"
      #include "resource.h"
      
      // enum for various skinning modes possible
      enum METHOD
      {
          D3DNONINDEXED,
              :
              :
      
    2. g_pAnimController はモデルのアニメーションを制御するオブジェクトです。
      Path[] に Tiny.x が格納されているパスを設定します。
      CD3DArcBall             g_ArcBall;              // Arcball for model control
      LPD3DXFRAME             g_pFrameRoot = NULL;
      ID3DXAnimationController* g_pAnimController = NULL;
      D3DXVECTOR3             g_vObjectCenter;        // Center of bounding sphere of object
      FLOAT                   g_fObjectRadius;        // Radius of bounding sphere of object
      D3DXMATRIXA16           g_matView;              // View matrix
      D3DXMATRIXA16           g_matProj;              // Projection matrix
      D3DXMATRIXA16           g_matProjT;             // Transpose of projection matrix (for asm shader)
      WCHAR     Path[MAX_PATH] = L"C:\\Data\\Model\\Tiny";
      
    3. OnD3D9CreateDevice() 関数を作成します。
      D3DXLoadMeshHierarchyFromX() で Tiny.x を入力して g_pFrameRoot に格納します。
      HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                           void* pUserContext )
      {
          HRESULT hr;
          CAllocateHierarchy Alloc;
      
          WCHAR strCWD[MAX_PATH];
          GetCurrentDirectory( MAX_PATH, strCWD );
          SetCurrentDirectory( Path );
      
          V_RETURN( D3DXLoadMeshHierarchyFromX( L"tiny.x", D3DXMESH_MANAGED, pd3dDevice,
                                                &Alloc, NULL, &g_pFrameRoot, &g_pAnimController ) );
          V_RETURN( SetupBoneMatrixPointers( g_pFrameRoot ) );
          V_RETURN( D3DXFrameCalculateBoundingSphere( g_pFrameRoot, &g_vObjectCenter, &g_fObjectRadius ) );
          SetCurrentDirectory( strCWD );
      
          // Obtain the behavior flags
          D3DDEVICE_CREATION_PARAMETERS cp;
          pd3dDevice->GetCreationParameters( &cp );
      
          return S_OK;
      }
      
    4. OnD3D9FrameRender() 関数で Light を設定して、DrawFrame() 関数を呼び出します。
      void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
      {
          HRESULT hr;
      
          // Clear the backbuffer
          pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                               D3DCOLOR_ARGB(0, 66, 75, 121), 1.0f, 0L );
      
          // ライトとマテリアルの設定
          D3DLIGHT9 light;
              :
              :
          // Begin the scene
          if( SUCCEEDED( pd3dDevice->BeginScene() ) )
          {
              DrawFrame( pd3dDevice, g_pFrameRoot );
              // End the scene.
              pd3dDevice->EndScene();
          }
      }
      
    5. DrawFrame() 関数でフレームを描画します。
      void DrawFrame( IDirect3DDevice9 *pd3dDevice, LPD3DXFRAME pFrame )
      {
          LPD3DXMESHCONTAINER pMeshContainer;
      
          pMeshContainer = pFrame->pMeshContainer;
          while (pMeshContainer != NULL)
          {
              DrawMeshContainer( pd3dDevice, pMeshContainer, pFrame );
              pMeshContainer = pMeshContainer->pNextMeshContainer;
          }
      
          if (pFrame->pFrameSibling != NULL)
              DrawFrame( pd3dDevice, pFrame->pFrameSibling);
      
          if (pFrame->pFrameFirstChild != NULL)
              DrawFrame( pd3dDevice, pFrame->pFrameFirstChild );
      }
      
    6. 後は全ソースコードを参照して下さい。
  4. プロジェクトを実行すると Tiny が歩くアニメーションが描画されます。
    プログラムの詳しい説明は「DirectX9 の X-FILE(Tiny.x) でアニメーション」を参照して下さい。

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