Spin Button で3Dモデルの姿勢を操作

Dialog Box の Spin Button でティーポットの姿勢(座標と回転)を操作して描画します。

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

プログラムの説明

  1. Dialog Box のキャプションとIDの設定です。
    BOX キャプション ID
    DialogBox Dialog View IDD_DIALOG1
    EditBox メッシュ座標(X) IDC_MX
    Spin IDC_SMX
    EditBox メッシュ座標(Y) IDC_MY
    Spin IDC_SMY
    EditBox メッシュ座標(Z) IDC_MZ
    Spin IDC_SMZ
    EditBox 回転係数(X) IDC_RX
    Spin IDC_SRX
    EditBox 回転係数(Y) IDC_RY
    Spin IDC_SRY
    EditBox 回転係数(Z) IDC_RZ
    Spin IDC_SRZ
    Button 終了 IDC_END
  2. myd3d は MyD3D Object Class の定義です。
    g_pMesh はティーポットのメッシュです。
    viewForm, tergForm はカメラの座標と注視点ですが、今回は操作できません。
    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;
        D3DXVECTOR3             viewForm;
        D3DXVECTOR3             tergForm;
        char                    ww[32];
        
  3. Dialog Box のボタンを操作するためのIDの定義です。
    SpinID[] が Spin Button で、EditID[] が EditBox の ID です。
    Sens[] は Spin Button がクリックされたときの感度の調整です。
    VT[12] はモデルの姿勢データで、この値を Soin Button で操作します。
        int         SpinID[12] =         // Spin ID
        {   IDC_SVX, IDC_SVY, IDC_SVZ,   IDC_STX, IDC_STY, IDC_STZ,
            IDC_SMX, IDC_SMY, IDC_SMZ,   IDC_SRX, IDC_SRY, IDC_SRZ
        };
        int         EditID[12] =         // EditBox ID
        {   IDC_VX, IDC_VY, IDC_VZ,   IDC_TX, IDC_TY, IDC_TZ,
            IDC_MX, IDC_MY, IDC_MZ,   IDC_RX, IDC_RY, IDC_RZ
        };
    
        //View, Terg, 移動, 回転の感度。移動と回転のみ操作可能
        float       Sens[4]= { 1.0f, 1.0f, 0.5f, 0.1f };
        //View(XYZ), Terg(XYZ), 移動(XYZ), 回転(XYZ)。移動と回転のみ操作可能
        float   VT[12]=
        {  0.00f, 0.00f, -10.00f,  0.00f, 0.00f, 0.00f,  0.00f, 0.00f, 0.00f,  -0.40f, 2.50f, 0.00f  };
        
  4. 描画に関係するソースコードはティーポットのメッシュを表示したときと同じです。
  5. WinMain() では InitGraphics() に続いてモードレスダイアログを表示します。
        int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
        {   MSG     msg;
                    :
            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);
                    :
        
  6. CALLBACK 関数です。
    Main にフォーカスがあるとき ESCAPE キーが押されると終了します。
        //CALLBACK Procedure
        LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,UINT wParam,LONG lParam)
        {
            switch(msg)
            {   case WM_PAINT:
                    Draw();
                    break;
                case WM_KEYDOWN:
                    switch(wParam)
                    {   case VK_ESCAPE: //Main にフォーカスがあるとき ESCAPE で終了
                            PostMessage(hWnd,WM_CLOSE,0,0);
                            break;
                    }
                    break;
                        :
        
  7. このプログラムのメインとなる Dialog Box の CALLBACK 関数です。
    InitDlg() で Dialog Box の初期化を行います。
    Spin Button をクリックすると WM_VSCROLL: がポストされます。
    Spin の ID を比べてどのボタンが押されたかを調べます。
    Spin Button を操作すると自動的にアップ/ダウンされて、現在の設定値を取得することができます。
        //DialogBox CALLBACK
        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_COMMAND:
                    switch(LOWORD(wParam))
                    {   case IDC_END:
                            EndDialog(hDlg,LOWORD(wParam));
                            PostQuitMessage(0);
                            return TRUE;
                    }
                    break;
                case WM_VSCROLL:
                    pos= HIWORD(wParam);
                    for(i=0; i<12 && GetDlgItem(hDlg,SpinID[i])!=(HWND)lParam; i++);
                    if (i>=12)  break;
                    v= (pos-100)*Sens[i/3];
                    VT[i]= v;
                    sprintf(ww,"%f",v);
                    SetWindowText(GetDlgItem(hDlg,EditID[i]),ww);
                    return TRUE;
                case WM_CLOSE:
                    EndDialog(hDlg,TRUE);
                    PostQuitMessage(0);
                    return TRUE;
            }
            return FALSE;
        }
        
  8. DialogBox の初期化です。
    Spin Button の下限と上限を設定しています。
        void  InitDlg(HWND hdlg)
        {   int     i;
            HWND    hSpin;
    
            //メッシュ 操作 Spin(0~200)
            for(i=0; i<12; i++)
            {   hSpin= GetDlgItem(hdlg,SpinID[i]);
                SendMessage(hSpin,UDM_SETRANGE,0,200);
                SendMessage(hSpin,UDM_SETPOS,0,0);
            }
            SetEbox(hdlg);
        }
        
  9. View 情報を Edit Box に表示する処理です。
        void  SetEbox(HWND hdlg)
        {   int     i,v;
            HWND    hSpin;
    
            for(i=0; i<12; i++)
            {   sprintf(ww,"%f",VT[i]);
                SetWindowText(GetDlgItem(hdlg,EditID[i]),ww);
                v= (int)(VT[i]/Sens[i/3]);
                hSpin= GetDlgItem(hdlg,SpinID[i]);
                SendMessage(hSpin,UDM_SETPOS,0,v+100);
            }
        }
        

【補足説明】

Spin Button の補足説明です。
UDM_SETRANGE で Spin Button の下限と上限を 0~200 に設定します。
WM_VSCROLL: がポストされたとき pos= HIWORD(wParam) には Spin Button の現在の値(0~200)が格納されます。
この値をそのまま使えるのであれば変換の必要はありませんが、多くの場合には変換が必要です。
このプログラムでも (pos-100) でゼロを中心にマイナスとプラスの値(-100~100)に変換しています。
さらに -0.12 のような実数値が必要な項目には Sens[i/3] を乗じて目標の数値に変換します。
    float       Sens[4]= { 1.0f, 1.0f, 0.5f, 0.1f };

    for(i=0; i<12; i++)
    {   hSpin= GetDlgItem(hdlg,SpinID[i]);
        SendMessage(hSpin,UDM_SETRANGE,0,200);
        SendMessage(hSpin,UDM_SETPOS,0,0);
    }

    case WM_VSCROLL:
        pos= HIWORD(wParam);
        for(i=0; i<12 && GetDlgItem(hDlg,SpinID[i])!=(HWND)lParam; i++);
        if (i>=12)  break;
        v= (pos-100)*Sens[i/3];
        VT[i]= v;

Spin Button の初期値は UDM_SETPOS で設定します。
例えば 100 に設定する場合は次のように書きます。
    SendMessage(hSpin,UDM_SETPOS,100,0);

float から TEXT 形式に変換する方法です。
wsprintf() では何故か %f が使えないようです。
    #include    <stdio.h>
    float   val;
    char    w[16];
    sprintf(w,"%8.2f",val);

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

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

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