山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他立方体を描画(DirectX 9 32/64bit)
概要
ソースコードの説明
WinMain
最初に実行される関数です。
          最初にウィンドウを作成し、Init3DDev関数でDirect Xの初期化を行います。
          その後通常のWinMain関数と同じ様にメッセージループを構成しますが、メッセージの取り出しにGetMessage関数ではなく、PeekMessage関数を使用し、メッセージがないときもループが回るようにします。メッセージがないときにDraw関数を呼び出し描画を行います。
          プログラム終了前にInit3DDevで作成したデバイスを開放します。
WndProc
ウィンドウプロシージャーです。ウィンドウ関係のメッセージを処理します。通常WM_PAINTメッセージにより再描画を行いますが、スピードが要求される場合は、前期のとおり別の場所で処理しています。
Init3DDev
Direct Xの初期化を行います。
SetupMatrices
draw関数から呼び出されます。
          ポリゴン等をどの向きにどの位置に表示させるかを設定します。
          まずここで表示させたいポリゴンの頂点座標を定義します。
          グローバルの構造体 TLVERTX v1[]からV6[]が該当します。
          ポリゴンは、3角形が基本ですので四角形なら6個の座標を定義しなければいけませんが、、DrawPrimitiveUP関数の第1引数の定義によっては、4個の頂点のみで描画できます。
ローカル座標を任意に回転させるD3DXMatrixRotationAxis
ポリゴンを ローカル座標の原点(0,0,0)と第2引数で指定される点と結ぶ軸を中心に 原点方向を向いた右回りに第3引数の角度回転させる行列を作成し第1引数に保存します。
行列を移動させる D3DXMatrixTranslation
ローカル座標をワールド座標へ移動させるのに使用しています。
          x,y,zで移動させる距離を指定します。
デバイスにワールド座標への変換方法を設定する SetTransform
D3DXMatrixPerspectiveFovLH
ワールド座標をビュー座標に変換する。ワールド座標のどの方向からどの範囲を見るか(描画するか)を設定する。この関数は、左手座標(Xが右、Yが上、Zが奥行方向で奥 左手で手のひらを上側がにし人差し指をX方向に向けた時における親指のさしている方向がZ値が増える方向である。)においてワールド座標をビュー座標に変換する。
          描画する遠近それぞれのZ値、画面の縦横比(アスペクト)、Y方向の視野角を指定する。
          
ビュー座標への変換行列を設定する SetTransform
レンタリングステートの設定 SetRenderState
カーニング方法 反時計周りの面を消去
          ライディングをしない
          Zバッファを使わない
draw
画面のクリア Clear
レンタリング開始 BeginScene
レンタリングを行う DrawPrimitiveUP
レンタリング終了 EndScene
バッファの内容を表示 Present
コンパイル方法
Visual C++ 2008
          Microsoft DirectX SDK June 2010をインストールをあらかじめ行っておく
          プロジェクトに下記のパスを追加(64bit Windowsで64bitの実行ファイルを作成する場合)
          includeパスにC:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include
          LibパスにC:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64
          を追加
ソースコード
//      Direct X 9 Sample Program 
//  立方体4個が回転する
//      32bit/64bit マルチバイト/Unicode対応 Visual C++ 2008
#define     szClassName TEXT("3D Box Rotate")
#include <windows.h>
#include <d3dx9.h>
#include <dxerr.h>
#include <tchar.h>
#pragma once
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
//頂点フォーマット
#define D3DFVF_VERTEX  (D3DFVF_XYZ | D3DFVF_DIFFUSE)    //トランスフォームされていない頂点の位置座標+ディフューズ カラー成分
typedef struct _D3DVERTEXCOR_ {
        float   x,y,z;  // トランスフォームされていない頂点の位置座標
    DWORD   color;      // ディフューズ カラー成分
}   D3DVERTEXCOR;
#define TIME_SET 500.0f //      立方体を回転させるスピード 1/1000秒単位
HWND                    hWnd;
LPDIRECT3DDEVICE9       g_pDEV = 0;
LPDIRECT3D9             pD3D;
D3DPRESENT_PARAMETERS   D3DPPWin;
//      立方体の頂点座標を定義(座標は立方体の中心を原点とする)
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[]=     //上面青の矩形
{ { -50, -50, -50, 0xff0000ff  },
  {  50, -50, -50, 0xff0000ff  },
  { -50, -50,  50, 0xff0000ff  },
  {  50, -50,  50, 0xff0000ff  } };
D3DVERTEXCOR v4[]=     //左側面黄の矩形
{ { -50,  50,  50, 0xffffff00  },
  { -50,  50, -50, 0xffffff00  },
  { -50, -50,  50, 0xffffff00  },
  { -50, -50, -50, 0xffffff00  } };
D3DVERTEXCOR v5[]=     //裏面紫の矩形 
{ { -50,  50, -50, 0xffff00ff  },
  {  50,  50, -50, 0xffff00ff  },
  { -50, -50, -50, 0xffff00ff  },
  {  50, -50, -50, 0xffff00ff  } };
D3DVERTEXCOR v6[]=     //下面白の矩形
{ {  50,  50, -50, 0xffffffff  },
  { -50,  50, -50, 0xffffffff  },
  {  50,  50,  50, 0xffffffff  },
  { -50,  50,  50, 0xffffffff  } };
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
HRESULT Init3DDev(HWND hwnd);
void  SetupMatrices(float x,float y,float z=0);
void Draw(void);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int){
        MSG     msg;
    WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst,
                      NULL,NULL,NULL,NULL,szClassName,NULL };
    if (RegisterClassEx(&wc)==0)
                return FALSE;
    HWND  hWnd = CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT,CW_USEDEFAULT,600,600,
                            NULL,NULL,hInst,NULL);
    if (FAILED(Init3DDev(hWnd)))        return FALSE;
    ShowWindow(hWnd,SW_SHOWDEFAULT);
    UpdateWindow(hWnd);
    ZeroMemory(&msg,sizeof(msg));
    while(msg.message != WM_QUIT){
                if (PeekMessage(&msg,NULL,0U,0U,PM_REMOVE)){
                        TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
                        Draw();
    }
        g_pDEV->Release();
        pD3D->Release();
    UnregisterClass(szClassName,wc.hInstance);
    return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam){
    switch(msg){
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0L;
    }
    return DefWindowProc(hWnd,msg,wParam,lParam);
}
//デバイス/モード等の初期化
HRESULT Init3DDev(HWND hwnd){
        hWnd= hwnd;
    pD3D= NULL;
        HRESULT     hr;
        D3DDISPLAYMODE          dmode;
        // デバイス/モード等の初期化
        if (pD3D==NULL)
                pD3D = Direct3DCreate9(D3D_SDK_VERSION);
        if (pD3D==NULL)
                return E_FAIL;
        //現在のディスプレイモードを得る
        if (FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&dmode)))
                return E_FAIL;
        // D3DDeviceオブジェクトの作成
        ZeroMemory(&D3DPPWin, sizeof(D3DPPWin));
        D3DPPWin.BackBufferFormat           = dmode.Format;
        D3DPPWin.BackBufferCount            = 1;
        D3DPPWin.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
        D3DPPWin.Windowed                   = TRUE;
        D3DPPWin.EnableAutoDepthStencil     = TRUE;
        D3DPPWin.AutoDepthStencilFormat     = D3DFMT_D16;
        D3DPPWin.Flags                      = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                D3DCREATE_HARDWARE_VERTEXPROCESSING, &D3DPPWin, &g_pDEV);
        if (FAILED(hr)){
        hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPPWin, &g_pDEV);
                if (FAILED(hr)){
            hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPPWin, &g_pDEV);
                        if (FAILED(hr)){
              MessageBox(NULL,TEXT("Create Device Error"),TEXT("Surface Error"),MB_OK);
                          return E_FAIL;
                        }
        }
    }
        return S_OK;
}
//描画環境の設定
void  SetupMatrices(float x,float y,float z){
        D3DXMATRIX      matView;
    D3DXMATRIX      matProj;
    D3DXMATRIX      w;
        D3DXVECTOR3 v;
        v.x=-x;
        v.y=-z;
        v.z=-y;
        D3DXMatrixRotationAxis(&w,&v, timeGetTime()/TIME_SET); // 任意の軸を回転軸にして回転する行列を作成する。 システム時刻をミリ秒単位で取得
    D3DXMatrixTranslation(&matView,x,y,z); // オフセットを指定して行列を作成する。
    matView= w*matView;
    g_pDEV->SetTransform(D3DTS_VIEW,&matView);
        //透視変換の設定
    D3DXMatrixPerspectiveFovLH(&matProj,D3DXToRadian(45.0f),1.0f,-300,300); // 視野に基づいて、左手座標系パースペクティブ射影行列を作成する
    g_pDEV->SetTransform(D3DTS_PROJECTION,&matProj);
    //描画設定
    g_pDEV->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);              //反時計回りの面を消去
    g_pDEV->SetRenderState(D3DRS_LIGHTING,FALSE);            //ライティングしない
    g_pDEV->SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE);       //Zバッファ使わない
}
//描画処理
void Draw(void){
    if (!g_pDEV)
                return;
    //黒で塗りつぶして消去
    g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0,0);
    //描画の開始
    g_pDEV->BeginScene();
        //描画環境の設定
        SetupMatrices(80,80,400);
        //デバイスに使用する頂点フォーマットをセットする
        g_pDEV->SetFVF(D3DFVF_VERTEX);
        //ストリームを使わないで直接データを渡して描画する
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v1,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v2,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v3,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v4,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v5,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v6,sizeof(D3DVERTEXCOR));
        SetupMatrices(80,-80,400);
        //ストリームを使わないで直接データを渡して描画する
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v1,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v2,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v3,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v4,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v5,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v6,sizeof(D3DVERTEXCOR));
        SetupMatrices(-80,80,400);
        //ストリームを使わないで直接データを渡して描画する
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v1,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v2,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v3,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v4,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v5,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v6,sizeof(D3DVERTEXCOR));
        SetupMatrices(-80,-80,400);
        //ストリームを使わないで直接データを渡して描画する
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v1,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v2,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v3,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v4,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v5,sizeof(D3DVERTEXCOR));
        g_pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,v6,sizeof(D3DVERTEXCOR));
        g_pDEV->EndScene();
    g_pDEV->Present(NULL,NULL,NULL,NULL);
}
 
 