Mview を作成する

Tiny のプロジェクトをベースに X-FILE のビューア(Mview) を作成します。

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

プログラムの説明

  1. 2011年11月に DirectX を June 2010 にアップしました。
    時を同じくして X-FILE の Viewer(Mview.exe) がダブルクリックで起動出来なくなりました。
    DirectX10 からは X-FILE が sdkmesh に変わるとは言え、現時点で Mview が使えないのは非常に不便です。
    そこで Tiny のプロジェクト(SkinnedMesh)をベースに Mview を作成することにしました。
    Tiny のプロジェクトは Tiny のアニメーション を参照して下さい。
  2. SkinnedMesh をベースに Mview を作成する手順です。
    SkinnedMesh.cpp のソースコードを整理します。
    1. 入力する X-FILE が格納されているディレクトリをフルパスで指定します。
      プロジェクトのフォルダー(Media) が不要になるので削除します。
      //#define MESHFILENAME L"tiny\\tiny.x"
      #define MESHFILENAME L"C:\\DATA\\Model\\tiny.x"
    2. Dialog 関係の機能は必要が無いので削除して身軽にします。
      次の行と関連するソースを削除します。
      CDXUTDialogResourceManager g_DialogResourceManager;
      CD3DSettingsDlg g_SettingsDlg;
      CDXUTDialog g_HUD;
    3. デバッグ情報と長いコメントを削除してソースコードを読みやすくします。
    4. 整理が終わると、プログラムを実行してマウスでモデルが操作出来ることを確認します。
  3. メニューからの入力に備え、入力処理を LoadMesh() 関数として独立します。
    1. X-FILE の名前を WCHAR[] で定義します。
      WCHAR MESHFILENAME[MAX_PATH] = L"C:\\DATA\\Model\\tiny.x";
      //WCHAR MESHFILENAME[MAX_PATH] = L"C:\\DATA\\Model\\cone.x";
      //WCHAR MESHFILENAME[MAX_PATH];
    2. LoadMesh() 関数を独立します。
      古い Mesh を解放してから、新しい Mesh をロードします。
    3. Mesh がロードされていないときは、ウインドウだけを表示します。
      そのままではメッシュがロードされていないとエラーが発生するので修正して下さい。
      if (pFrame==NULL) return;
    4. tiny.x, cone.x, 空, の順に、正常に実行されることを確認します。
      MESHFILENAME[] が空の時でもプログラムが正常に終了することを確認して下さい。
  4. Shader が関係すると扱いが面倒なので削除します。
    DirectX9 では、Shader は必須ではありません。
    1. g_pEffect と関連するコードを削除します。
              ID3DXEffect*    g_pEffect = NULL;
              WCHAR g_wszShaderSource[4][30] =
              {   L"skinmesh1.vsh",
                  L"skinmesh2.vsh",
                  L"skinmesh3.vsh",
                  L"skinmesh4.vsh"
              };
              
    2. フォルダーに格納されている Shader 関係のファイルを全て削除します。
      SkinnedMesh では g_pEffect は描画に直接関係しないようで?、すんなりと動きました。
    3. Shader を削除して tiny.x が正常にアニメーションされることを確認します。
      Shader を使わない描画のサンプルは X-FILE(Tiny.x) でアニメーション を参照して下さい。
  5. Main() 関数のパラメータから X-FILE 名を受け取ります。
    DRAG & DROP や Mview に関連付けられた X-FILE をダブルクリックで起動すると、Main() のパラメータとして渡されます。
    1. wWinMain() の引数(lpCmdLine) に X-FILE 名が設定されているときは MESHFILENAME[] に格納します。
      Command Line を取得する を参照して下さい。
      リンクがエラーになるときは「超初心者のプログラム入門(C言語 Windows)」から辿って下さい。
      if (lpCmdLine!=NULL && *lpCmdLine > ' ')
      { wcscpy_s( MESHFILENAME, MAX_PATH, lpCmdLine ); }
    2. コンパイルして実行を確認します。
      SkinnedMesh.exe をデスクトップに置きます。
      X-FILE を DRAG & DROP して実行を確認します。
    3. SkinnedMesh.exe を X-FILE と関連付けます。
      X-FILE をダブルクリックで起動して実行を確認します。
      ファイル名が " " で囲まれているときは、これを取り除きます。
      DRAG & DROP したときも、空白が含まれていると " " で囲まれています。
  6. メニューを設定します。
    1. SkinnedMesh.rc にメニューの記述を追加します。
      "OPEN(&O)", "EXIT(&X)", "Version(&V)" を設定しました。
      メニューの説明は ファイル選択メニューを設定する を参照して下さい。
              IDR_MENU1 MENU 
              BEGIN
                  POPUP "FILE(&F)"
                  BEGIN
                      MENUITEM "OPEN(&O)",                      ID_OPEN
                      MENUITEM "EXIT(&X)",                      IDM_EXIT
                  END
                  POPUP "HELP(&F)"
                  BEGIN
                      MENUITEM "Version(&V)",                   ID_HELP
                  END
              END
              
    2. resource.h にIDを追加します。
              #define IDI_MAIN_ICON                   101
              #define IDR_MENU1                       102
              #define ID_OPEN                         40001
              #define IDM_EXIT                        40002
              #define ID_HELP                         40003
              
    3. メニューを設定した Window の生成は DXUT\Core\DXUT.cpp(.h) で定義されています。
      DXUT.h の宣言です。
              HRESULT WINAPI DXUTCreateWindow( const WCHAR* strWindowTitle = L"Direct3D Window",
                  HINSTANCE hInstance = NULL, HICON hIcon = NULL, HMENU hMenu = NULL,
                  int x = CW_USEDEFAULT, int y = CW_USEDEFAULT );
              
    4. ウインドウにメニューを設定します。
      //DXUTCreateWindow( L"Skinned Mesh" );
      DXUTCreateWindow(L"Mview",NULL,NULL,LoadMenu(hinst,(LPCTSTR)IDR_MENU1));
    5. プログラムを実行して、メニューが表示されることを確認します。
  7. メニューの機能(EXIT, HELP)を設定します。
    1. MsgProc() にメニューの機能(EXIT, HELP)を設定します。
              switch(uMsg)
              {   case WM_COMMAND:
                      switch(LOWORD(wParam))
                      {   case IDM_EXIT:
                              OnDestroyDevice( pUserContext );
                              PostMessage( hWnd, WM_CLOSE,0,0 );
                              return 0L;
                          case ID_HELP:
                              MessageBox(NULL,L"Mview Version 1.0",
                                  L"Maead Minoru",MB_OK);
                              break;
                      }
              
    2. 念のために、解放した Object に NULL を格納します。
      X-FILE のオープンを繰り返したときに、解放されたことを明確にするためです。
    3. HELP メニューを実行して、Version 表示を確認します。
      EXIT メニューを実行して、プログラムの終了を確認します。
  8. メニューの ID_OPEN 機能 をプログラムします。
    1. MsgProc() にメニューの ID_OPEN 処理を追加します。
              switch(uMsg)
              {   case WM_COMMAND:
                      switch(LOWORD(wParam))
                      {   case IDM_EXIT:
                                 ・・・
                          case ID_OPEN:
                              if (GetOpenFile()==TRUE)
                              {   LoadMesh();
                                  XSIZ ^= 0X000F;
                                  MoveWindow(hWnd,80,80,XSIZ,600,TRUE);
                              }
                              break;
                         case ID_HELP:
              
    2. GetOpenFile() を追加します。
      GetOpenFile() 関数は ファイル選択メニューを設定する を参照して下さい。
    3. LoadMesh() を実行しただけでは描画されないようで、DXUT のリセットが必要なようです。
      一番手軽な方法は、ウインドウサイズを変えることで、下記の方法で無事描画されました。
              int     XSIZ = 800; // XSIZ ^= 0X0008; で交互に設定
      
              XSIZ ^= 0X000F;
              MoveWindow(hWnd,80,80,XSIZ,600,TRUE);
              
    4. 先にも説明しましたが、X-FILE の名前が " " で囲まれているときは取り除いて下さい。
              WCHAR   wk[MAX_PATH];
              WCHAR*  pt;
      
              if (MESHFILENAME[0]=='\0')  return S_FALSE;
              // 両側の " " を取り除く
              if (MESHFILENAME[0]==L'"')
              {   pt = wcsrchr( MESHFILENAME+1, L'"' );
                  if ( pt )    *pt = 0;
                  wcscpy_s( wk, MAX_PATH, MESHFILENAME+1 );
              }
              else    wcscpy_s( wk, MAX_PATH, MESHFILENAME );
              
  9. Debug モードでコンパイルするとサイズが大きくなるので、Release モードでコンパイルします。
    SkinnedMesh.exe の名前を Mview.exe に変更して、適当なフォルダーに格納すれば完成です。
    Shader を削除したので Mview.exe 一本だけで動きます。
    X-FILE を Mview.exe と関連付けます。
    X-FILE をダブルクリックすると Mview.exe が起動して描画されます。
  10. DXUT メッシュ の Viewer は sdkmesh の Viewer を作成 を参照して下さい。
    OBJ モデルの Viewer は 自作の OBJ Loader を使う を参照して下さい。

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