Win10 Pair

Windows10 DirectX3D で2体のモデルを並べて描画します。
2016/05/24 Windows10 が不安定になり再セットアップした所、従来のプロジェクトが起動出来なくなりました。
詳細は Windows Guid から Windows10 ガイドを参照して下さい。

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

プログラムの説明

  1. Windows10 で CreateModel と MyCamera を組み込んで、2体のモデルを並べて描画します。
    3Dアニメーションの基本は、複数のモデル(パーツ)を組み合わせて回転(移動)することです。
    人体の場合でも「腰,首,腕,手,手首,指,足など」の関節を回転して飛んだり跳ねたりします。
    最初の課題として2体のモデルを横に並べて、Y軸とX軸で回転しながら描画してみます。
  2. Win10 Template を参照して DirectX 11 アプリ(ユニバーサル Windows) を生成して下さい。
    生成したアプリは「頂点+カラー」のモデルを描画するプロジェクトです。
    [DirectX Page 検索]を参照して「頂点+法線」のモデルを描画出来るように修正して下さい。
    次に Class CreateModel を組み込んで、多角錐のモデルを描画します。
  3. Sample3DSceneRenderer.h に CreateModel と MyCamera を組み込んで、2体のモデル領域を定義します。
    CreateModel は Win10 Create Model に掲載しています。
    MyCamera はこのページの後部に掲載します。
    #include "CreateModel.h"
    #include "MyCamera.h"
    
        Microsoft::WRL::ComPtr<ID3D11Buffer>        m_vertexBuffer1;
        Microsoft::WRL::ComPtr<ID3D11Buffer>        m_vertexBuffer2;
        Microsoft::WRL::ComPtr<ID3D11Buffer>        m_indexBuffer1;
        Microsoft::WRL::ComPtr<ID3D11Buffer>        m_indexBuffer2;
    
        uint32          m_indexCount1;
        uint32          m_indexCount2;
        CreateModel     *m_CreateModel;
        MyCamera        *my_camera1 = nullptr;
        MyCamera        *my_camera2 = nullptr;
    
  4. Sample3DSceneRenderer.cpp で2体のモデルを生成して描画します。
    1. Constructor でモデル1とモデル2の MyCamera を生成します。
      Camera() 関数でX座標をずらして2体のモデルを横に並べます。
      Sample3DSceneRenderer::Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
          m_loadingComplete(false),
          m_degreesPerSecond(45),
          m_tracking(false),
          m_deviceResources(deviceResources)
      {
          CreateDeviceDependentResources();
          CreateWindowSizeDependentResources();
          my_camera1 = new MyCamera(m_deviceResources);
          my_camera2 = new MyCamera(m_deviceResources);
          my_camera1->Camera(1.0f, 0.0f, 0.0f);
          my_camera2->Camera(-1.0f, 0.0f, 0.0f);
      }
      
    2. Rotate() 関数では、モデル1をY軸で,モデル2をX軸で回転します。
      void Sample3DSceneRenderer::Rotate(float radians)
      {
          my_camera1->Model(0.0f, radians, 0.0f);
          my_camera2->Model(radians, 0.0f, 0.0f);
      }
      
    3. Render() 関数ではモデル1に続いてモデル2を描画します。
      void Sample3DSceneRenderer::Render()
      {
          // 読み込みは非同期です。読み込みが完了した後にのみ描画してください。
          if (!m_loadingComplete) {  return;  }
      
          auto context = m_deviceResources->GetD3DDeviceContext();
          // 頂点シェーダーをアタッチします。
          context->VSSetShader(
              m_vertexShader.Get(), nullptr, 0);
          // ピクセル シェーダーをアタッチします。
          context->PSSetShader(
              m_pixelShader.Get(), nullptr, 0);
          // 定数バッファーをグラフィックス デバイスに送信します。
          context->VSSetConstantBuffers(
              0, 1, m_constantBuffer.GetAddressOf());
          context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
          context->IASetInputLayout(m_inputLayout.Get());
      
          //☆モデル1を描画
          m_constantBufferData.projection = my_camera1->m_projection;
          m_constantBufferData.view = my_camera1->m_view;
          m_constantBufferData.model = my_camera1->m_model;
          context->UpdateSubresource(
              m_constantBuffer.Get(), 0, NULL, &m_constantBufferData, 0, 0);
          // 各頂点は、VertexPositionColor 構造体の 1 つのインスタンスです。
          UINT stride = sizeof(VertexPositionColor);
          UINT offset = 0;
          context->IASetVertexBuffers(
              0, 1, m_vertexBuffer1.GetAddressOf(), &stride, &offset);
          context->IASetIndexBuffer(
              m_indexBuffer1.Get(), DXGI_FORMAT_R16_UINT, 0);
          // オブジェクトを描画します。
          context->DrawIndexed(
              m_indexCount1, 0, 0);
      
          //☆モデル2を描画
          m_constantBufferData.projection = my_camera2->m_projection;
          m_constantBufferData.view = my_camera2->m_view;
          m_constantBufferData.model = my_camera2->m_model;
          context->UpdateSubresource(
              m_constantBuffer.Get(), 0, NULL, &m_constantBufferData, 0, 0);
          context->IASetVertexBuffers(
              0, 1, m_vertexBuffer2.GetAddressOf(), &stride, &offset);
          context->IASetIndexBuffer(
              m_indexBuffer2.Get(), DXGI_FORMAT_R16_UINT, 0);
          // オブジェクトを描画します。
          context->DrawIndexed(
              m_indexCount2, 0, 0);
      }
      
    4. カラーモデルでは "COLOR" になっていますが "NORMAL" に修正します。
          static const D3D11_INPUT_ELEMENT_DESC vertexDesc [] =
          {
              {"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0},
              {"NORMAL",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0},
          };
      
    5. CreateModel で2体のモデルを生成します。
          // 両方のシェーダーの読み込みが完了したら、メッシュを作成します。
          auto createCubeTask = (createPSTask && createVSTask).then([this] () {
              m_CreateModel = new CreateModel(m_deviceResources);
              m_CreateModel->CreateCube(&m_vertexBuffer1, &m_indexBuffer1, &m_indexCount1);
              m_CreateModel->CreateCone(4, &m_vertexBuffer2, &m_indexBuffer2, &m_indexCount2);
          });
      
          // キューブが読み込まれたら、オブジェクトを描画する準備が完了します。
          createCubeTask.then([this] () {
              m_loadingComplete = true;
          });
      
  5. MyCamera.h です。
    void Camera() 関数と void Model() 関数が追加されています。
    float3 がバッティングするときは "BasicMath.h" を使って下さい。
    // MyCamera Header File  Ver-1.2  前田 稔
    #pragma once
    #include "..\Common\DeviceResources.h"
    //#include "BasicMath.h"
    struct float3
    {
        float   x;
        float   y;
        float   z;
    };
    
    class MyCamera
    { public:
        MyCamera(std::shared_ptr<DX::DeviceResources>& deviceResources);
        void Projection();
        void Camera(DirectX::XMVECTOR eye, DirectX::XMVECTOR at, DirectX::XMVECTOR up);
        void Camera(float dx, float dy, float dz);
        void View(float dx, float dy, float dz);
        void Model(float rx, float ry, float rz);
        void Model(float r, float rx, float ry, float rz);
        void Model(float3 *f3, int n);
    
        DirectX::XMVECTOR   m_eye = { 0.0f, 0.7f, 10.0f, 0.0f };
        DirectX::XMVECTOR   m_at = { 0.0f, -0.1f, 0.0f, 0.0f };
        DirectX::XMVECTOR   m_up = { 0.0f, 1.0f, 0.0f, 0.0f };
    
        DirectX::XMFLOAT4X4 m_projection;
        DirectX::XMFLOAT4X4 m_view;
        DirectX::XMFLOAT4X4 m_model;
    
      private:
        std::shared_ptr<DX::DeviceResources> m_deviceResources;
    };
    
  6. MyCamera.cpp です。
    掲載されていない関数は Windows10 DirectX Library を参照して下さい。
    Camera(float dx, float dy, float dz) は規定値から m_eye, m_at を補正してカメラを設定する関数です。
    Model(float r, float rx, float ry, float rz) は半径 r で Model を回転する関数です。
    Model(float3 *f3, int n) は回転情報を配列で渡す関数です。
    /*******************************************/
    /* MyCamera Program File  Ver-1.2  前田 稔 */
    /*******************************************/
    #pragma once
    
    #include "pch.h"
    #include "..\Common\DirectXHelper.h"
    #include "MyCamera.h"
    using namespace DirectX;
    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());
    }
    
    // 規定値から m_eye, m_at を補正してカメラを設定
    void MyCamera::Camera(float dx, float dy, float dz)
    {
        m_eye.m128_f32[0] += dx;
        m_eye.m128_f32[1] += dy;
        m_eye.m128_f32[2] += dz;
        m_at.m128_f32[0] += dx;
        m_at.m128_f32[1] += dy;
        m_at.m128_f32[2] += dz;
        XMStoreFloat4x4(&m_view, XMMatrixTranspose(XMMatrixLookAtRH(m_eye, m_at, m_up)));
    }
    
    // 半径 r で Model を回転する
    void MyCamera::Model(float r, float rx, float ry, float rz)
    {
        XMMATRIX    mat, view;
        XMVECTOR    eyew = { 0.0f, 0.0f, r, 0.0f };
    
        view = XMMatrixTranspose(XMMatrixLookAtRH(eyew, XMVECTOR{0.0f, 0.0f, 0.0f, 0.0f}, XMVECTOR{0.0f, 1.0f, 0.0f, 0.0f}));
        mat = XMMatrixRotationRollPitchYaw(rx, ry, rz);
        XMStoreFloat4x4(&m_model, mat * view);
    }
    
    // 回転配列のパラメータ
    void MyCamera::Model(float3 *f3, int n)
    {
        XMMATRIX    view, mat, w;
        view = XMMatrixTranspose(XMMatrixLookAtRH(m_eye, m_at, m_up));
        mat = XMMatrixIdentity();
        for (int i = 0; i<n; i++)
        {
            w = XMMatrixRotationRollPitchYaw(f3[i].y, f3[i].x, f3[i].z);
            mat = mat * (w * view);
        }
        XMStoreFloat4x4(&m_model, mat);
    }
    
  7. コンパイル&実行すると2体のモデルが横に並んで回転しながら描画されます。
    モデル1はY軸で、モデル2はX軸で回転しながら描画されます。
    より簡単な二体の4面体(頂点+カラー)を描画するプロジェクトは Win10 Men4 2Model を参照して下さい。

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