マウス操作で View 座標を回転する

長方体のそれぞれの面に異なる色を設定して、マウス操作で View 座標を回転します。
WM_MOUSEMOVE でマウスの移動を検出して、自作の Rotate 関数で回転します。

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

プロジェクトの作成

  1. 空の新規プロジェクト(BoxDx9)を作成して下さい。
  2. 前回のプログラムが理解できると、このプログラムは独力で作成できるはずです。
    この後の説明を参考にプログラムを作成して、プロジェクトに追加して下さい。
    ファイル名 ファイルの説明
    BoxDx9.cpp この後の説明を参考にして作成
  3. ライブラリのリンクは #pragma で指示するので、特別な操作は不要です。
  4. ビルドから実行を選ぶと、コンパイルに続いて実行が行われます。
    マウスを左右にドラッグすると View 座標が回転します。

プログラムの説明

  1. #include と #pragma と Direct3D の領域です。
    g_pD3D は Direct3D のオブジェクトです。
    g_p3DDev は Direct3D のデバイスです。
    ViewForm は View の座標で、基準を X=0, Y=0, Z=400 に設定しています。
    4面体のときは X=0, Y=-5, Z=-30 に設定していたことを確認して下さい。
    View 座標はオブジェクトのサイズや描画する大きさにより変わります。
    viewRot はマウスで操作する View 座標の回転データです。
        #include    <d3d9.h>
        #include    <d3dx9.h>
        #pragma once
        #pragma comment(lib,"dxguid.lib")
        #pragma comment(lib,"d3d9.lib")
        #pragma comment(lib,"d3dx9.lib")
    
        #define SAFE_DELETE(p)  { if (p) { delete (p);     (p)=NULL; } }
        #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
        #define EMSG(x)         MessageBox(NULL,x,"DirectX D3D",MB_OK);
    
        //Global Area
        D3DXVECTOR3             ViewForm(0,0,400);
        float                   viewRot= 0;
    
        //DirectXオブジェクト
        LPDIRECT3D9             g_pD3D;
        LPDIRECT3DDEVICE9       g_p3DDev;
        
  2. 頂点フォーマットの設定です。
    6個の面を三角形を組み合わせた矩形(TRIANGLESTRIP)として、個別に定義します。
        //頂点フォーマット
        #define D3DFVF_VERTEX  (D3DFVF_XYZ | D3DFVF_DIFFUSE)
        typedef struct _D3DVERTEXCOR_
        {   float   x,y,z;
            DWORD   color;
        }   D3DVERTEXCOR;
    
        D3DVERTEXCOR v1[]=     //前面赤の矩形 
        { { -50, -50,  50, 0xffff0000  },
          {  50, -50,  50, 0xffff0000  },
          { -50,  50,  50, 0xffff0000  },
          {  50,  50,  50, 0xffff0000  } };
        D3DVERTEXCOR v2[]=     //右側面緑の矩形
        { {  50, -50,  50, 0xff00ff00  },
          {  50, -50, -50, 0xff00ff00  },
          {  50,  50,  50, 0xff00ff00  },
          {  50,  50, -50, 0xff00ff00  } };
              :
        D3DVERTEXCOR v3[]=     //上面青の矩形
              :
        D3DVERTEXCOR v4[]=     //左側面黄の矩形
              :
        D3DVERTEXCOR v5[]=     //裏面紫の矩形 
              :
        D3DVERTEXCOR v6[]=     //下面白の矩形
              :
        
  3. 長方体を描画する関数です。
    Clear() で画面をクリアします。
    BeginScene() でシーンの開始を設定します。
    SetupMatrices() は描画環境を設定する関数です。
    SetFVF() で頂点フォーマットをセットします。
    DrawPrimitiveUP() で6個の面を描画します。
    それぞれの面は三角形を2枚組み合わせた(TRIANGLESTRIP)で構成しています。
    EndScene() でシーンの処理を終了します。
    Present() で作成したシーンを描画します。
        void Draw(void)
        {
            if (!g_pD3D || !g_p3DDev)   return;
                :
            //描画環境の設定
            SetupMatrices();
            //デバイスに使用する頂点フォーマットをセットする
            g_p3DDev->SetFVF(D3DFVF_VERTEX);
            //ストリームを使わないで直接データを渡して描画する
            g_p3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v1,sizeof(D3DVERTEXCOR));
            g_p3DDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v2,sizeof(D3DVERTEXCOR));
                :
        }
        
  4. 描画環境を設定する関数です。
    ViewForm は View の初期座標で viewRot はマウスで操作した回転データです。
    今回は座標の回転を実感するために自作した Rotate() 関数を使っています。
    最後尾の引数を 0 にするとX軸を中心に回転します。
    バックフェース・カリングとは「ポリゴンの裏側」を描画しないようにする設定です。
    左手座標系では「反時計回りの面」を消去します。
        void  SetupMatrices(void)
        {   D3DXMATRIX      matView;
            D3DXMATRIX      matProj;
            D3DXVECTOR3     v;
    
            //View 座標の設定
            v= ViewForm;
            Rotate(&v,&D3DXVECTOR3(0,0,0),viewRot,1);
            //Rotate(&v,&D3DXVECTOR3(0,0,0),viewRot,0);
            D3DXMatrixLookAtLH(&matView,(D3DXVECTOR3*)&v,&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,-1,0));
            g_p3DDev->SetTransform(D3DTS_VIEW,&matView);
            //透視変換の設定
            D3DXMatrixPerspectiveFovLH(&matProj,D3DXToRadian(45.0),1.0f,-300,300);
            g_p3DDev->SetTransform(D3DTS_PROJECTION,&matProj);
            //描画設定
            g_p3DDev->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);   //カリングの設定
            g_p3DDev->SetRenderState(D3DRS_LIGHTING,FALSE);         //ライティングしない
            g_p3DDev->SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE);    //Zバッファ使わない
        }
        
  5. MainWndProc() でマウスをキャプチャーして回転情報を設定します。
        LRESULT CALLBACK MainWndProc(HWND hWnd,UINT msg,UINT wParam,LONG lParam)
        {   static int  prevX=0, prevY=0;
            int         x,y,dy;
            float       dx;
    
            switch(msg)
            {   case WM_LBUTTONDOWN:
                    prevX = LOWORD(lParam);
                    prevY = HIWORD(lParam);
                    SetCapture(hWnd);
                    return 0L;
                case WM_LBUTTONUP:
                    ReleaseCapture();
                    return 0L;
                case WM_MOUSEMOVE:
                    if ((wParam&MK_LBUTTON)==0)     break;
                    y = HIWORD(lParam);
                    dy= prevY-y;
                    if (dy!=0)  ViewForm.y+= dy;
                    x = LOWORD(lParam);
                    dx= float((x-prevX)/3);
                    if (dx!=0)  viewRot+= dx;
                    prevX= x;
                    prevY= y;
                    return 0L;
                        :
        
  6. 私が作成した Rotate() 関数のパラメータの説明です。
    引数 説明
    &v 回転前の3次元ベクトル、回転後の値が格納される
    (0,0,0) 回転軸の中心点
    viewRot 回転角度
    1 回転軸(0:X, 1:Y, 2:Z)

【課題】

  1. バックフェース・カリングとは「ポリゴンの裏側」を描画しないようにする設定です。
    左手座標系では「反時計回りの面」を、右手座標系では「時計回りの面」を消去します。
    カリングの意味を理解するためにも、次の設定で実行してみて下さい。
  2. 反時計回りの面を消去する
    g_p3DDev->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
  3. 時計回りの面を消去する
    g_p3DDev->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);
  4. カリングを行わない
    g_p3DDev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);

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

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

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