Dolphin の Animation

3枚の X-File を入力して myd3d->BlendMeshes で Vertex Buffer を Blending しながら Animation を行います。
Microsoft のサンプルプログラムの中で、私が最も感動した「イルカが泳ぐサンプル」の基本部分のプログラムです。

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

プログラムの説明

  1. イルカのXファイル(Dolphin1.x Dolphin2.x Dolphin3.x)を DirectX の Sample\Media からコピーしてきて下さい。
  2. #include と #define と頂点データと DirectX オブジェクトの定義です。
    MyD3D Object Class のヘッダファイル(MyD3D.h)を取り込みます。
    ライブラリのリンクは #pragma で指示するので、特に操作は不要です。
    dolphin1.x の頂点データは D3DFVF_XYZ | D3DFVF_NORMAL になっています。
    頂点データの形式は MyD3D.h の中で定義されています。
    g_pMesh[4] などで四個分の Mesh(X-File) の領域を定義します。
    ゼロ番目が描画する Mesh で後の三個はイルカの姿勢を決めるキーとなるメッシュです。
    これらの X-File には、テクスチャは貼り付けられていないようです。
        #include    "MyD3D.h"
    
        // Global variables
        MyD3D               *myd3d      = NULL;    // MyD3D Object Class
        HWND                g_hWnd;
        LPDIRECT3DDEVICE9   g_pDEV      = NULL;
        LPD3DXMESH          g_pMesh[4]  = { NULL,NULL,NULL,NULL };
        D3DMATERIAL9*       g_pMat[4]   = { NULL,NULL,NULL,NULL };
        LPDIRECT3DTEXTURE9* g_pTex[4]   = { NULL,NULL,NULL,NULL };
        DWORD               g_Num       = 0L;
        char                XFile[4][24]= { "dolphin1.x", "dolphin1.x", "dolphin2.x", "dolphin3.x" };
        D3DXVECTOR3         ViewForm(0,-300,800);
        
  3. デバイスの初期化を行います。
    MyD3D Object Class をインスタンス化して、インターフェースを取得します。
    四個のXファイルを入力してメッシュを生成します。
    ゼロ番目の Mesh は描画用で、頂点データはキーフレームから計算するのでどのファイルでも良いのですが、 1番目と同じファイルを入力しています。
        HRESULT InitDevices()
        {
            myd3d= new MyD3D(g_hWnd);
            myd3d->InitD3D(&g_pDEV);
            for(DWORD j=0; j<4; j++)
            {   g_Num= myd3d->LoadXFile(XFile[j],&g_pMesh[j],&g_pMat[j],&g_pTex[j]);
                if (g_Num==0)       return FALSE;
            }
            return S_OK;
        }
        
  4. イルカのメッシュを描画します。
    座標原点を中心にして WORLD 座標をY軸で回転します。
    イルカのメッシュは三枚のキーフレームを fweight の割合で Blend して描画します。
    BlendMeshes() が頂点座標をブレンドする関数で、よりリアルに変化させるためにサイン関数を使って補完します。
    fweight が負のときは 三番と二番の間を補完します。
    fweight が正のときは 一番と二番の間を補完します。
    描画するのはゼロ番目のメッシュです。
        VOID Render()
        {   D3DXMATRIX  matWorld;
    
            if (!myd3d)    return;
            D3DXMatrixIdentity(&matWorld);
            D3DXMatrixRotationY(&matWorld,timeGetTime()/3000.0f);
            g_pDEV->SetTransform(D3DTS_WORLD,&matWorld);
    
            //イルカのアニメーション
            FLOAT   fweight = sinf(timeGetTime()/500.0f);
            if (fweight<0.0f)
                myd3d->BlendMeshes(g_pMesh[0],g_pMesh[3],g_pMesh[2],-fweight);
            else
                myd3d->BlendMeshes(g_pMesh[0],g_pMesh[1],g_pMesh[2],fweight);
    
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                            D3DCOLOR_XRGB(0,100,160),1.0f,0);
            //描画の開始
            g_pDEV->BeginScene();
            SetupMatrices();
            //イルカの描画
            for(DWORD i=0; i<g_Num; i++)
            {   g_pDEV->SetMaterial(&g_pMat[0][i]);
                g_pDEV->SetTexture(0,g_pTex[0][i]);
                g_pMesh[0]->DrawSubset(i);
            }
            g_pDEV->EndScene();
            g_pDEV->Present(NULL,NULL,NULL,NULL);
        }
        
  5. 描画環境の設定です。
    GetClientRect() で Window Size を取得して、モデルのアスペクト比を保ちます。
    マテリアルと光源で立体感を出しています。
        VOID SetupMatrices()
        {   RECT        rect;
            D3DXMATRIX  matView;
            D3DXMATRIX  matProj;
    
            GetClientRect(g_hWnd,&rect);
            D3DXMatrixLookAtLH(&matView,(D3DXVECTOR3*)&ViewForm,&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,1,0));
            g_pDEV->SetTransform(D3DTS_VIEW,&matView);
            D3DXMatrixPerspectiveFovLH(&matProj,D3DXToRadian(45.0f),(float)rect.right/(float)rect.bottom,1,10000);
            g_pDEV->SetTransform(D3DTS_PROJECTION,&matProj);
            myd3d->SetMaterial();
            myd3d->SetLight();
            g_pDEV->SetRenderState(D3DRS_AMBIENT,0x00404040);
        }
        
  6. Cleanup() です。
    割り当てたメッシュを開放して下さい。
        VOID Cleanup()
        {   DWORD   i,j;
    
            for(j=0; j<4; j++)
            {   SAFE_DELETE(g_pMat[j]);
                if (g_pTex[j])
                {   for(i=0; i<g_Num; i++)  SAFE_RELEASE(g_pTex[j][i]);
                    SAFE_DELETE(g_pTex[j]);
                }
                SAFE_RELEASE(g_pMesh[j]);
            }
            SAFE_DELETE(myd3d);
        }
        
  7. ページ先頭の画像が表示されて、イルカが泳ぐようになれば完成です。

超初心者の方のために全ソースコードを掲載します。 (^_^;)
全ソースコード

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

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

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