Spin Button で Material を操作

Dialog Box の Spin Button で Material を操作して View 座標を回転しながら描画します。
material の設定と、その効果を確かめるプログラムです。

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

プログラムの説明

Spin Button で Material を操作しながら View 座標(カメラの座標)を回転しながら描画します。
material とはライティング係数やテクスチャなど、ポリゴンをどのように表示させるかという付加データのことを言います。
  1. Dialog Box のキャプションとIDの設定です。
    BOX キャプション ID
    DialogBox ダイアログ IDD_DIALOG1
    EditBox Diffuse R IDC_EDIT1
    Spin R IDC_SPIN1
    EditBox Diffuse G IDC_EDIT2
    Spin G IDC_SPIN2
    EditBox ・・・ ・・・
    Spin ・・・ ・・・
    EditBox Power IDC_EDIT17
    Spin IDC_SPIN17
    Button Clear IDCANCEL
    Button END IDOK
  2. Global Area の領域です。
    myd3d は MyD3D Object Class の定義です。
    g_pMesh はトーラスのメッシュです。
    ViewForm は View(カメラ)の座標です。
    最初 ViewForm はトーラスを正面から写すように -5.0f の距離を置いて配置します。
    この ViewForm をトーラスを中心にして回転しながら描画します。
    g_bAct1 は Window の、g_bAct2 は Dialog のアクティブ状態を示すフラグです。
    ww[32] は編集用の作業領域です。
        //Global Area
        MyD3D                   *myd3d   = NULL;     // MyD3D Object Class
        HWND                    g_hWnd   = NULL;     // ウインドウ・ハンドル
        HWND                    g_hDlg   = NULL;     // ウインドウ・ハンドル
    
        //Direct3D Area
        LPDIRECT3DDEVICE9       g_pDEV   = NULL;
        LPD3DXMESH              g_pMesh  = NULL;
        bool                    g_bAct1  = false;   // Window アクティブ状態
        bool                    g_bAct2  = false;   // Dialog アクティブ状態
        D3DXVECTOR3             ViewForm(0.0f,0.0f,-5.0f);
        D3DMATERIAL9            material;
        char                    ww[32];
        
  3. material を操作するための領域です。
    CT[17] に現在描画中の material が格納されています。
    SpinID[17] は操作された Spin Button を識別するためのID テーブルです。
    EditID[17] は material の値を表示する Edit Box を識別するための ID テーブルです。
        float       CT[17];
        int         SpinID[17] =            // Spin ID
        {   IDC_SPIN1,  IDC_SPIN2,  IDC_SPIN3,  IDC_SPIN4,
            IDC_SPIN5,  IDC_SPIN6,  IDC_SPIN7,  IDC_SPIN8,
            IDC_SPIN9,  IDC_SPIN10, IDC_SPIN11, IDC_SPIN12,
            IDC_SPIN13, IDC_SPIN14, IDC_SPIN15, IDC_SPIN16,
            IDC_SPIN17
        };
        int         EditID[17] =            // EditBox ID
        {   IDC_EDIT1,  IDC_EDIT2,  IDC_EDIT3,   IDC_EDIT4,
            IDC_EDIT5,  IDC_EDIT6,  IDC_EDIT7,   IDC_EDIT8,
            IDC_EDIT9,  IDC_EDIT10, IDC_EDIT11,  IDC_EDIT12,
            IDC_EDIT13, IDC_EDIT14, IDC_EDIT15,  IDC_EDIT16,
            IDC_EDIT17
        };
        
  4. 描画に関係するソースコードは MyD3D Class でティーポットを描画する を参照して下さい。
  5. SetupMatrices で描画環境を設定します。
    myd3d->Rotate() で View 座標を回転しながら描画します。
    アルファテストの閾値が 0x80 なので、Diffuse の A が 0.5 を割るとトーラスが表示されなくなります。
        void  SetupMatrices(void)
        {   RECT            rect;
            D3DXMATRIX      matView;
            D3DXMATRIX      matProj;
            D3DXVECTOR3     VF;
    
            GetClientRect(g_hWnd,&rect);
            //View 座標をY軸を中心にして自動回転
            VF= ViewForm;
            myd3d->Rotate(&VF,&D3DXVECTOR3(0.0f,0.0f,0.0f),(timeGetTime()/100)%360,1);
            //View 座標の設定
            D3DXMatrixLookAtLH(&matView,&VF,
                               &D3DXVECTOR3(0.0f,0.0f,0.0f),&D3DXVECTOR3(0.0f,1.0f,0.0f));
            g_pDEV->SetTransform(D3DTS_VIEW,&matView);
            //透視変換の設定
            D3DXMatrixPerspectiveFovLH(&matProj,D3DXToRadian(45.0f),(float)rect.right/(float)rect.bottom,1,50);
            g_pDEV->SetTransform(D3DTS_PROJECTION,&matProj);
            //★Render State の設定
            g_pDEV->SetRenderState(D3DRS_AMBIENT,0x000F0F0F);
            g_pDEV->SetRenderState(D3DRS_SPECULARENABLE,TRUE);      //スペキュラを使う
            // Set up the textures
            g_pDEV->SetTextureStageState(0,D3DTSS_COLOROP,  D3DTOP_MODULATE);
            g_pDEV->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
            g_pDEV->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
            g_pDEV->SetTextureStageState(0,D3DTSS_ALPHAOP,  D3DTOP_MODULATE);
            g_pDEV->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
            g_pDEV->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
            g_pDEV->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
            g_pDEV->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
            // Set miscellaneous render states
            g_pDEV->SetRenderState(D3DRS_DITHERENABLE,  FALSE);
            g_pDEV->SetRenderState(D3DRS_ZENABLE,       TRUE);
            g_pDEV->SetRenderState(D3DRS_AMBIENT,       0x000F0F0F);
            //カラーキー用アルファテスト
            g_pDEV->SetRenderState(D3DRS_ALPHATESTENABLE,TRUE);
            g_pDEV->SetRenderState(D3DRS_ALPHAREF,0x80);
            g_pDEV->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL);
            g_pDEV->SetMaterial(&material);
        }
        
  6. WinMain() では InitGraphics() に続いてモードレスダイアログを表示します。
        int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
        {   MSG     msg;
    
            WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst,
                              NULL,NULL,NULL,NULL,NAME,NULL };
            if (RegisterClassEx(&wc)==0)    return FALSE;
            g_hWnd = CreateWindowEx(0,NAME,NAME,WS_OVERLAPPEDWINDOW,
                                    CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
                                    NULL,NULL,hInst,NULL);
            if (FAILED(InitGraphics()))    return FALSE;
    
            g_hDlg = CreateDialog(hInst,MAKEINTRESOURCE(IDD_DIALOG1),g_hWnd,(DLGPROC)DlgProc);
            if (g_hDlg == NULL)    return FALSE;
            ShowWindow(g_hDlg, SW_SHOW);
            UpdateWindow(g_hDlg);
    
            ShowWindow(g_hWnd,SW_SHOWDEFAULT);
            UpdateWindow(g_hWnd);
            SetFocus(g_hDlg);
            ZeroMemory(&msg,sizeof(msg));
            while(msg.message!=WM_QUIT)
            {   if (PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
                {   TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else    Draw();
            }
            Cleanup();
            UnregisterClass(NAME,wc.hInstance);
            return 0;
        }
        
  7. CALLBACK 関数です。
    Main にフォーカスがあるとき ESCAPE キーが押されると終了します。
        LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,UINT wParam,LONG lParam)
        {
            switch(msg)
            {   case WM_ACTIVATE:
                    g_bAct1= (LOWORD(wParam)!=0);
                    break;
                case WM_KEYDOWN:
                    switch(wParam)
                    {   case VK_ESCAPE:     // [ESCAPE]キーでウインドウを閉じる
                            PostMessage(hWnd,WM_CLOSE,0,0);
                            break;
                    }
                    break;
                case WM_CLOSE:
                case WM_DESTROY:
                    PostQuitMessage(0);
                    return 0L;
            }
            return DefWindowProc(hWnd,msg,wParam,lParam);
        }
        
  8. このプログラムのメインとなる Dialog Box の CALLBACK 関数です。
    InitDlg() で Dialog Box の初期化を行います。
    Spin Button をクリックすると WM_VSCROLL: がポストされます。
    Spin の ID を比べてどのボタンが押されたかを調べます。
    Spin Button を操作すると自動的にアップ/ダウンされて、現在の設定値を取得することができます。
        LRESULT CALLBACK DlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
        {   int     pos,i;
            float   v;
    
            switch(msg)
            {   case WM_INITDIALOG:
                    InitDlg(hDlg);
                    break;
                case WM_ACTIVATE:
                    g_bAct2= (LOWORD(wParam)!=0);
                    break;
                case WM_COMMAND:
                    switch(LOWORD(wParam))
                    {   case IDCANCEL:
                            EndDialog(hDlg,LOWORD(wParam));
                            PostQuitMessage(0);
                            return TRUE;
                        case IDOK:
                            InitMaterial();
                            SetEbox(hDlg);
                            return TRUE;
                    }
                    break;
                case WM_VSCROLL:
                    pos= HIWORD(wParam);
                    for(i=0; i<17 && GetDlgItem(hDlg,SpinID[i])!=(HWND)lParam; i++);
                    if (i<16)   v= (float)pos/200.0f;
                    else        v= (float)pos/2.0f;
                    CT[i]= v;
                    sprintf(ww,"%f",v);
                    SetWindowText(GetDlgItem(hDlg,EditID[i]),ww);
                    SetMaterial();
                    return TRUE;
                case WM_CLOSE:
                    EndDialog(hDlg,TRUE);
                    PostQuitMessage(0);
                    return TRUE;
            }
            return FALSE;
        }
        
  9. DialogBox の初期化です。
    Spin Button の下限と上限を設定しています。
        void  InitDlg(HWND hdlg)
        {   int     i;
            HWND    hSpin;
    
            //Color 操作 Spin(0~200)
            for(i=0; i<17; i++)
            {   hSpin= GetDlgItem(hdlg,SpinID[i]);
                SendMessage(hSpin,UDM_SETRANGE,0,200);
            }
            SetEbox(hdlg);
        }
        
  10. Material 情報を Edit Box に表示する処理です。
        void  SetEbox(HWND hdlg)
        {   int     i,v;
            HWND    hSpin;
    
            for(i=0; i<17; i++)
            {   sprintf(ww,"%f",CT[i]);
                SetWindowText(GetDlgItem(hdlg,EditID[i]),ww);
                v= (int)(CT[i]*200);
                hSpin= GetDlgItem(hdlg,SpinID[i]);
                SendMessage(hSpin,UDM_SETPOS,0,v);
            }
        }
        

マテリアルの説明

マテリアルとは、ポリゴンの色を決める属性となるもので、反射特性、放射特性、反射係数、半透明特性などのことを言います。

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

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

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