Win10 CameraRot

Windows10 Direct3D で Camera を組み込んでモデルを回転します。

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

プロジェクトの作成

  1. Win10 Template を参照して「DirectX 11 および XAML アプリ(ユニバーサル Windows)」を構築して下さい。
    コンパイルして実行するとカラーキューブが回転し、FPS と TextBox に XAML! が表示されます。
  2. 最初にY軸だけでなく、X軸でも回転するようにプログラムを修正します。
    詳細は Win10 MouseRot を参照して下さい。
  3. DirectXPage.xaml.cpp の OnPointerMoved() から X と Y を渡して下さい。
    void DirectXPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e)
    {   if (m_main->IsTracking())
        {   m_main->TrackingUpdate(e->CurrentPoint->Position.X, e->CurrentPoint->Position.Y);
        }
    }
    
  4. App1Main.h に m_pointerLocationY を追加して、TrackingUpdate() 関数で positionX と positionY を保存します。
        float m_pointerLocationX;
        float m_pointerLocationY;
    
        void TrackingUpdate(float positionX, float positionY)
        {   m_pointerLocationX = positionX;
            m_pointerLocationY = positionY;
        }
    
  5. App1Main.cpp の ProcessInput() 関数で X と Y を渡します。
    void App1Main::ProcessInput()
    {   m_sceneRenderer->TrackingUpdate(m_pointerLocationX, m_pointerLocationY);
    }
    
  6. Sample3DSceneRenderer.cpp を修正してX軸とY軸で回転します。
    void Sample3DSceneRenderer::TrackingUpdate(float positionX, float positionY)
    {
        XMMATRIX    mat;
        XMFLOAT4X4  f4x4;
        float       rx, ry;
    
        if (m_tracking)
        {   ry = XM_2PI*2.0f*positionX/m_deviceResources->GetOutputSize().Width;
            rx = XM_2PI*2.0f*positionY/m_deviceResources->GetOutputSize().Height;
            mat = XMMatrixRotationX(rx) * XMMatrixRotationY(ry);
            XMStoreFloat4x4(&f4x4, mat);
            m_constantBufferData.model = f4x4;
        }
    }
    

MyCamera

  1. Win10 MyCamera を参照して class MyCamera を組み込んで下さい。
    MyCamera に新しい関数を追加します。
    Camera() は、カメラのビュー座標を設定する関数です。
    Model() はモデルの回転情報を m_model に設定して、X, Y, Zで回転する関数です。
  2. class MyCamera Version-1.1 の Header File です。
    // MyCamera Header File  Ver-1.1  前田 稔
    #pragma once
    #include "..\Common\DeviceResources.h"
    using namespace DirectX;
    
    class MyCamera
    { public:
        MyCamera(std::shared_ptr<DX::DeviceResources>& deviceResources);
        void Projection();
        void Camera(XMVECTOR eye, XMVECTOR at, XMVECTOR up);
        void Model(float rx, float ry, float rz);
    
        XMVECTOR    m_eye = { 0.0f, 0.7f, 1.5f, 0.0f };
        XMVECTOR    m_at = { 0.0f, -0.1f, 0.0f, 0.0f };
        XMVECTOR    m_up = { 0.0f, 1.0f, 0.0f, 0.0f };
    
        XMFLOAT4X4 m_projection;
        XMFLOAT4X4 m_view;
        XMFLOAT4X4 m_model;
    
      private:
        std::shared_ptr<DX::DeviceResources> m_deviceResources;
    };
    
  3. class MyCamera Version-1.1 の Program File です。
    掲載されていない関数は Windows10 DirectX Library を参照して下さい。
    /*******************************************/
    /* MyCamera Program File  Ver-1.1  前田 稔 */
    /*******************************************/
    #pragma once
    
    #include "pch.h"
    #include "..\Common\DirectXHelper.h"
    #include "MyCamera.h"
    using namespace Windows::Foundation;
    
    MyCamera::MyCamera(std::shared_ptr<DX::DeviceResources>& deviceResources)
    {
        m_deviceResources = deviceResources;
        Projection();
        XMStoreFloat4x4(&m_view, XMMatrixTranspose(XMMatrixLookAtRH(m_eye, m_at, m_up)));
        XMStoreFloat4x4(&m_model, XMMatrixIdentity());
    }
    
  4. Sample3DSceneRenderer.cpp の Constructor で MyCamera を生成します。
    Sample3DSceneRenderer::Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
        m_loadingComplete(false),
        m_degreesPerSecond(45),
        m_indexCount(0),
        m_tracking(false),
        m_deviceResources(deviceResources)
    {
        CreateDeviceDependentResources();
        CreateWindowSizeDependentResources();
        my_camera = new MyCamera(m_deviceResources);
    }
    
  5. CreateWindowSizeDependentResources() では Projection() を呼ぶだけです。
    void Sample3DSceneRenderer::CreateWindowSizeDependentResources()
    {   if (my_camera!=nullptr) my_camera->Projection();  }
    
  6. Rotate() 関数では Model() のパラメータに radians を渡してY軸で回転します。
    先頭からX軸, Y軸, Z軸の回転係数です。
    void Sample3DSceneRenderer::Rotate(float radians)
    {
        my_camera->Model(0.0f, radians, 0.0f);
    }
    
  7. TrackingUpdate() 関数からはマウスの操作でX軸とY軸で回転する関数を呼び出します。
    横方向の移動量(Y軸回転)を ry に設定します。
    縦方向の移動量(X軸回転)を rx に設定します。
    Model() 関数では、X軸の回転方向を反転してマウスの操作に合わせています。
    void Sample3DSceneRenderer::TrackingUpdate(float positionX, float positionY)
    {   float       rx, ry;
        if (m_tracking)
        {   ry = XM_2PI*2.0f*positionX/m_deviceResources->GetOutputSize().Width;
            rx = XM_2PI*2.0f*positionY/m_deviceResources->GetOutputSize().Height;
            my_camera->Model(-rx, ry, 0.0f);
        }
    }
    
  8. Render() では MyCamera のデータを m_constantBufferData に設定して描画します。
        // 定数バッファーを準備して、グラフィックス デバイスに送信します。
        m_constantBufferData.projection = my_camera->m_projection;
        m_constantBufferData.view = my_camera->m_view;
        m_constantBufferData.model = my_camera->m_model;
        context->UpdateSubresource(
            m_constantBuffer.Get(),
            0,
            NULL,
            &m_constantBufferData,
            0,
            0
            );
    
  9. カメラを引いてモデルを小さく描画してみましょう。
    Constructor で設定される eye の値は z = 1.5f ですが、z = 3.0f に設定します。
    Sample3DSceneRenderer::Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
        m_loadingComplete(false),
        m_degreesPerSecond(45),
        m_indexCount(0),
        m_tracking(false),
        m_deviceResources(deviceResources)
    {
        CreateDeviceDependentResources();
        CreateWindowSizeDependentResources();
        my_camera = new MyCamera(m_deviceResources);
        my_camera->Camera(XMVECTORF32{ 0.0f,0.7f,3.0f,0.0f }, XMVECTORF32{ 0.0f,-0.1f,0.0f,0.0f }, XMVECTORF32{ 0.0f,1.0f,0.0f,0.0f });
    }
    

  1. 3D画像の描画環境は m_constantBufferData の projection, view, model で管理されます。
    projection にはプロジェクション(縦横比や遠近感)が格納されます。
    view にはカメラの座標や向きが格納されます。
    model にはモデルの姿勢(回転情報など)が格納されます。
  2. m_constantBufferData はモデルを操作(回転や移動)する必要がなければ、ウインドウサイズが変更されたときに設定すれば十分です。
    自動生成のプロジェクトでは Sample3DSceneRenderer の CeateWindowSizeDependentResources() 関数で設定されています。
    void Sample3DSceneRenderer::CreateWindowSizeDependentResources()
    {
        Size outputSize = m_deviceResources->GetOutputSize();
        float aspectRatio = outputSize.Width / outputSize.Height;
        float fovAngleY = 70.0f * XM_PI / 180.0f;
    
        if (aspectRatio < 1.0f)
        {
            fovAngleY *= 2.0f;
        }
    
        XMMATRIX perspectiveMatrix = XMMatrixPerspectiveFovRH(
            fovAngleY,
            aspectRatio,
            0.01f,
            100.0f
            );
    
        XMFLOAT4X4 orientation = m_deviceResources->GetOrientationTransform3D();
    
        XMMATRIX orientationMatrix = XMLoadFloat4x4(&orientation);
    
        XMStoreFloat4x4(
            &m_constantBufferData.projection,
            XMMatrixTranspose(perspectiveMatrix * orientationMatrix)
            );
    
        // 視点は (0,0.7,1.5) の位置にあり、y 軸に沿って上方向のポイント (0,-0.1,0) を見ています。
        static const XMVECTORF32 eye = { 0.0f, 0.7f, 1.5f, 0.0f };
        static const XMVECTORF32 at = { 0.0f, -0.1f, 0.0f, 0.0f };
        static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0f };
    
        XMStoreFloat4x4(&m_constantBufferData.view, XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up)));
    }
    
  3. 回転情報は Sample3DSceneRenderer の Rotate() 関数で設定されます。
    void Sample3DSceneRenderer::Rotate(float radians)
    {
        //更新されたモデル マトリックスをシェーダーに渡す準備をします
        XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationY(radians)));
    }
    
  4. Class MyCamera では、これらの領域を m_projection, m_view, m_model で管理します。
        XMFLOAT4X4 m_projection;
        XMFLOAT4X4 m_view;
        XMFLOAT4X4 m_model;
    
  5. そして Render() 関数でフレームごとに m_projection, m_view, m_model を設定し直すことでアニメーションなどに対応します。
        //☆モデルを描画
        m_constantBufferData.projection = camera->m_projection;
        m_constantBufferData.view = camera->m_view;
        m_constantBufferData.model = camera->m_model;
    

超初心者のプログラム入門(DirectX Store)