Win10 CameraKey

Windows10 で MyCamera を組み込んでモデルをキーで操作します。

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

プロジェクトの作成

  1. キーを検出してモデルを回転プロジェクトは Win10 KeyRot を参照して下さい。
    今回はこのプロジェクトに MyCamera を組み込んでモデルを平行移動(回転移動)します。
    モデルの回転は MyCamera の m_model に変換行列を設定すれば良いのですが、何故か移動情報を設定するとモデルが変形します。
    そこでモデルを平行移動(回転移動)する方法を調べました。
    モデルの回転は Win10 MyCamera を参照して下さい。
  2. プロジェクトの Content\ に MyCamera.h(.cpp) を格納して組み込んで下さい。
    MyCamera に m_view(カメラの座標と向き)を設定する View() 関数を追加します。
    void MyCamera::View(float dx, float dy, float dz)
    {   XMMATRIX    view, mat;
        view = XMMatrixTranspose(XMMatrixLookAtRH(m_eye, m_at, m_up));
        mat = XMMatrixRotationView(dx, dy, dz);
        XMStoreFloat4x4(&m_view, mat * view);
    }
    
  3. Sample3DSceneRenderer.h に my_camera と移動(回転)情報を設定する領域を定義します。
    #include "MyCamera.h"
    
        MyCamera    *my_camera = nullptr;
        float       m_x, m_y, m_z;
    
  4. Sample3DSceneRenderer.cpp で my_camera を生成します。
    my_camera->Camera() は無くても支障は無いのですが、モデルが大きく描画されるのでカメラを引いてみました。
    Sample3DSceneRenderer::Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources,
                Windows::UI::Core::CoreWindow^ window) :
        m_loadingComplete(false),
        m_degreesPerSecond(45),
        m_indexCount(0),
        m_tracking(false),
        m_deviceResources(deviceResources),
        m_window(window)
    {
        CreateDeviceDependentResources();
        CreateWindowSizeDependentResources();
        my_camera = new MyCamera(m_deviceResources);
        m_x = 0;
        m_y = 0;
        m_z = 0;
        my_camera->Camera(XMVECTORF32{ 0.0f, 0.7f, 5.0f, 0.0f },
            XMVECTORF32{ -1.0f, -0.1f, 0.0f, 0.0f }, XMVECTORF32{ 0.0f, 1.0f, 0.0f, 0.0f });
    }
    
  5. CreateWindowSizeDependentResources() からは Projection() を呼ぶだけです。
    void Sample3DSceneRenderer::CreateWindowSizeDependentResources()
    {   if (my_camera!=nullptr) my_camera->Projection();  }
    
  6. Update() 関数でキーを検出して、m_x, m_y, m_z を設定します。
    ←→ キーで m_x を設定します(Y軸で回転)。
    ↑↓ キーで m_y を設定します(X軸で回転)。
    Space,Enter キーで m_z を設定します(Z軸回転)。
    回転軸に合わせて m_y, m_x, m_z の順序で View() 関数を呼び出します。
    void Sample3DSceneRenderer::Update(DX::StepTimer const& timer)
    {
        Windows::UI::Core::CoreVirtualKeyStates KeyState;
        KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Left);
        if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
        {   m_x -= 0.01f;  }
        KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Right);
        if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
        {   m_x += 0.01f;  }
        KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Up);
        if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
        {   m_y -= 0.01f;  }
        KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Down);
        if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
        {   m_y += 0.01f;  }
        KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Space);
        if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
        {   m_z -= 0.01f;  }
        KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Enter);
        if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
        {   m_z += 0.01f;  }
        //my_camera->Trans(m_x, m_y, m_z);  // View に代えて Trans を試します
        my_camera->View(m_y, m_x, m_z);
    }
    
  7. 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;
    
  8. プログラムを実行して上下左右の矢印キー及び Space, Enter キーをタイプして下さい。
    モデルが三次元座標上で平行移動します。
    正確には XMMatrixRotationView() で m_view を回転しているのですが、平行移動のように見えます。
    Space, Enter キーをタイプすると、正味Z軸で回転します。
    回転と平行移動はアニメーションの基本で、複数のモデル(またはパーツ)を組み合わせてアニメーションを組み立てます。
  9. View() に代えて Trans() 関数を呼び出してみます。
    こちらは XMMatrixTranslation() で座標を平行移動しているのですが、何故かモデルが変形するので試してみて下さい。
    m_model には移動情報は設定できないようです。
    void MyCamera::Trans(float tx, float ty, float tz)
    {
        XMMATRIX    mat;
        mat = XMMatrixTranslation(tx, ty, tz);
        XMStoreFloat4x4(&m_model, mat);
    }
    

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