sdkmesh の Viewer を作成

sdkmesh の Viewer を作成

DXUT メッシュ形式 (.sdkmesh) の Viewer の作成に挑戦します。

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

プロジェクトの説明

  1. DirectX10 でプログラムを開発する上で、sdkmesh のビューアが無いのは非常に不便です。
    サンプルフォルダーやネット上で探したのですが、どうしても見つかりません。
    仕方が無いので、自前でビューアを作成することにしました。
    X-FILE の Viewer は Mview を作成する を参照して下さい。
    OBJ モデルの Viewer は 自作の OBJ Loader を使う を参照して下さい。
  2. sdkmesh のビューアを開発する上で最も困るのが、頂点データの形式と Shader の組み合わせです。
    頂点データの形式によって Shader(Normal.fx, Color.fx, Texture.fx など)を使い分けなければなりません。
    DirectX9 では GetFVF() 関数で頂点データの形式を取得出来たのですが、sdkmesh には見当たりません。
    そこで .sdkmesh のファイルを直接調べれば解るだろうと、バイナリ形式のヘッダーをダンプしてみました。
    ところがヘッダーを調べても違いが解りません。
    (sdkmesh のヘッダーは DXUT\Optional\SDKmesh.cpp(SDKmesh.h) を参照して下さい)。
  3. 仕方が無いので最初のステップとして、Shader ごとに Viewer を作成してみました。
    次のプログラムをベースに wWinMain() でコマンドラインから sdkmesh の名前を取得して描画して下さい。
    sdkmesh に関連付けて、ダブルクリックで起動すれば描画されます。
    コマンドラインから sdkmesh の名前を取得する方法は Mview を作成する を参照して下さい。
    「Tiger.sdkmesh を描画」で説明している「モデルサイズ&中心座標」を利用して、描画サイズを調整して下さい。
  4. これで一応 sdkmesh の描画を確認できたのですが、三種類のプログラムを使い分けるのはかなり面倒です。
    そこで、三種類(またはそれ以上)の Shader を用意しておいて、キーの操作で順番に切り替えることにしました。
    sdkmesh のビューアは一本だけで、sdkmesh に関連付けて、ダブルクリックで起動します。
    そして Enter キーで Shader を切り替えて正常に描画されるモードを確認する方法です。
    現在のところ、一応重宝しているようです。
    1. Shader 専用の Object Class を用意します。
      //★ Shader Class
      class Shader
      {
        protected:
          ID3D10Device*                   Device;
          int                             Type;
          WCHAR                           FxName[64];
          ID3D10Effect*                   Effect;
          ID3D10EffectTechnique*          Render;
          ID3D10EffectShaderResourceVariable* DiffuseVariable;
          ID3D10EffectMatrixVariable*     WorldVariable;
          ID3D10EffectMatrixVariable*     ViewVariable;
          ID3D10EffectMatrixVariable*     ProjectionVariable;
          ID3D10EffectVectorVariable*     ColorVariable;
      
        public:
          ID3D10InputLayout*              Layout;
      
          Shader(ID3D10Device*, int);     //Constructor
          ~Shader();                      //Destructor
          void    View(CDXUTSDKMesh*, CModelViewerCamera*);   //View Mesh
          void    View(CDXUTSDKMesh*, CModelViewerCamera*, float[]);
      };
      
    2. Shader ごとの Layout を定義します。
      // Define the input layout
      // "Normal.fx"
      const D3D10_INPUT_ELEMENT_DESC T_Layout0[] =
      {
          { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D10_INPUT_PER_VERTEX_DATA, 0 },
          { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
      };
      // "Color.fx"
      const D3D10_INPUT_ELEMENT_DESC T_Layout1[] =
      {
          { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
          { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
          { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
      };
      // "Texture.fx"
      const D3D10_INPUT_ELEMENT_DESC T_Layout2[] =
      {
          { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
          { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
          { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
      };
      
    3. 三種類の Shader を配列で定義します。
      sn は現在使用中の Shader です。
      Shader*                 shader[3] = { NULL, NULL, NULL };
      CDXUTSDKMesh            g_Mesh;
      CModelViewerCamera      g_Camera;
      D3DXVECTOR3             g_vCenter;        // Object の中心
      D3DXVECTOR3             g_vExtents;       // Object の大きさ
      D3DXMATRIXA16           g_mWorld;         // World matrix to center the mesh
      int                     sn = 0;
      ID3D10Device*           D10Device;
      
    4. Enter キーで Shader を切り替えます。
      void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
      {
          if( bKeyDown )
          {
              switch( nChar )
              {
                  case VK_RETURN:
                      sn = (sn+1)%3;
                      D10Device->IASetInputLayout(shader[sn]->Layout);
                      break;
              }
          }
      }
      
    5. キー操作のついでに、拡大・縮小やモデルの移動が出来るともっと便利です。
  5. sdkmesh の頂点データの形式が解れば、もっとスマートなビューアが作成出来るのですが。 (^_^;)
    どなたかご存じの方がおられましたら、メールして下さい。

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