ティーポットを ArcBall で操作

ティーポットを生成して ArcBall で操作します。

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

プログラムの説明

  1. Visual C++ 2010 Express & June2010 の環境で DXUTCreateTeapot() でティーポットを生成して、ArcBall で操作(回転/移動)します。
    DirectX10(+X9) のプロジェクトは DirectX10 と DirectX9 のソースファイルが格納されている EmptyProject10 を使っていました。
    今回は純粋な DirectX10 のアプリケーションを作成します。
    DirectX10 のプロジェクトは幾つかあるのですが、MultiMon10 を使うことにします。
    DirectX Sample Browser で MultiMon10 のプロジェクトを作成して下さい。
    MultiMon10 のプロジェクトをコンパイルして、正常に実行されることを確かめて下さい。
    エラーが発生するときや、正常に実行出来ないときは、残念ながら現在の構成は相性が悪いようです。
  2. MultiMon10 のプロジェクトを使ってティーポットを生成して自動回転しながらマウスで操作します。
    モデルの操作には ArcBall を使う方法と Camera を使う方法があります。
    Camera を使う方法は ティーポットを Camera で操作 を参照して下さい。
    ソースプログラムと Shader を圧縮形式で提供します。
    ファイル名 説明
    TeapotArc.zip 圧縮ファイル
  3. #include と領域の宣言です。
    CD3DArcBall を使うので "DXUTcamera.h" を include して下さい。
    g_pMesh がティーポットのメッシュです。
    World, View, Projection, Color を Shader に設定して描画します。
    モデルの色を g_Colors[2] で二色(黄色,赤)定義してみました。
    g_ArcBall がモデルを回転する CD3DArcBall です。
    #include "DXUT.h"
    #include "SDKmisc.h"
    #include "DXUTShapes.h"
    #include "DXUTcamera.h"
    
    ID3DX10Mesh*                g_pMesh = NULL;
    ID3D10InputLayout*          g_pLayout = NULL;
    ID3D10Effect*               g_pEffect = NULL;
    ID3D10EffectTechnique*      g_pRender = NULL;
    ID3D10EffectMatrixVariable* g_pWorldVariable = NULL;
    ID3D10EffectMatrixVariable* g_pViewVariable = NULL;
    ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL;
    ID3D10EffectVectorVariable* g_pColorVariable = NULL;
    D3DXMATRIX                  g_World;
    D3DXMATRIX                  g_View;
    D3DXMATRIX                  g_Projection;
    D3DXVECTOR4 g_Colors[2] = 
    {
        D3DXVECTOR4( 1.0f, 1.0f, 0.2f, 1.0f ),
        D3DXVECTOR4( 1.0f, 0.3f, 0.3f, 1.0f ),
    };
    CD3DArcBall                 g_ArcBall;
    
  4. OnD3D10FrameRender() では (float)fTime/2.0f でY軸で自動回転しながら、 ArcBall の Rotation と Translation を掛け合わせて g_World を求めます。
    g_World, g_View, g_Projection, g_Colors[0] を Shader に設定して描画します。
    g_Colors[1] にするとモデルの色が変わるので試して下さい。
    void CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
    {
            :
            :
        // Setup the effects
        D3DXMatrixRotationY( &g_World, (float)fTime/2.0f );
        D3DXMatrixMultiply( &g_World, &g_World, g_ArcBall.GetRotationMatrix() );
        D3DXMatrixMultiply( &g_World, &g_World, g_ArcBall.GetTranslationMatrix() );
    
        // Update variables
        g_pWorldVariable->SetMatrix( (float*)&g_World );
        g_pViewVariable->SetMatrix( (float*)&g_View );
        g_pProjectionVariable->SetMatrix( (float*)&g_Projection );
        g_pColorVariable->SetFloatVector( (float*)&g_Colors[0] );
            :
            :
    
  5. OnD3D10CreateDevice() はデバイスを生成するときに呼ばれます。
    D3DX10CreateEffectFromFile() で "Normal.fx" を入力して Shader を作成します。
    "World", "View", "Projection", "Color" は Normal.fx の中で定義されている領域です。
    ティーポットの頂点データは、三次元座標と法線ベクトルで構成されています。
    DXUTCreateTeapot() でティーポットを生成します。
    &vEye, &vLook, &vUp をパラメータとして &g_View を設定します。
    HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc,
                                          void* pUserContext )
    {
        HRESULT hr = S_OK;
    
        // Find the D3DX effect file
        WCHAR str[MAX_PATH];
        V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"Normal.fx" ) );
        DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
        #if defined( DEBUG ) || defined( _DEBUG )
        dwShaderFlags |= D3D10_SHADER_DEBUG;
        #endif
        V_RETURN( D3DX10CreateEffectFromFile( str, NULL, NULL, "fx_4_0", dwShaderFlags, 0, pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ) );
    
        // Obtain the technique
        g_pRender = g_pEffect->GetTechniqueByName( "Render" );
        // Obtain the variables
        g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix();
        g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix();
        g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix();
        g_pColorVariable = g_pEffect->GetVariableByName( "Color" )->AsVector();
    
        // Create an input layout
        const D3D10_INPUT_ELEMENT_DESC layout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
        };
        D3D10_PASS_DESC PassDesc;
        g_pRender->GetPassByIndex( 0 )->GetDesc( &PassDesc );
        V_RETURN( pd3dDevice->CreateInputLayout( layout, sizeof(layout)/sizeof(layout[0]), 
                              PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pLayout ) );
        DXUTCreateTeapot( pd3dDevice, &g_pMesh );
    
        D3DXVECTOR3 vEye(0,2,-3);
        D3DXVECTOR3 vLook(0,0,0);
        D3DXVECTOR3 vUp(0,1,0);
        D3DXMatrixLookAtLH( &g_View, &vEye, &vLook, &vUp );
    
        return S_OK;
    }
    
  6. OnD3D10ResizedSwapChain() では、縦横比を計算して &g_Projection を設定します。
    次に g_ArcBall を使ってティーポットをマウスで回転します。
    マウスで回転するプログラムは結構面倒なのですが、ArcBall を使うと g_ArcBall.SetWindow() を呼び出すだけです。
    マウスの左ドラッグで回転が、右ドラッグで移動が、中央ボタンで拡大/縮小が出来るので操作してみて下さい。
    HRESULT CALLBACK OnD3D10ResizedSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain *pSwapChain,
            const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
    {
        float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
        D3DXMatrixPerspectiveFovLH( &g_Projection, D3DX_PI/3.0f, fAspectRatio, 0.1f, 30.0f );
    
        // Setup the arcball parameters
        g_ArcBall.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 0.85f );
    
        return S_OK;
    }
    

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