Shoot

Shoot

カラーキューブを弾丸に見立てて発射します。

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

プロジェクトの説明

  1. DirectX 11 および XAML アプリ(ユニバーサル Windows)を構築します。
    カラーキューブが回転しながら描画されます。
    詳細は「Page 検索」から DirectX 11 アプリ(ユニバーサル Windows) を参照して下さい。
  2. プロジェクトのフォルダー(App1\Content\)に Shoot.h と Shoot.cpp を格納してプロジェクトに組み込みます。
    Shoot のソースコードはページの後半に掲載します。
  3. Sample3DSceneRenderer に Shoot Class を組み込みます。
    Sample3DSceneRenderer.h に Shoot.h を取り込んで領域を定義して下さい。
    float3 mov; はカラーキューブの現在の座標です。
    #include "Shoot.h"
    
        Shoot       *shoot = nullptr;
        float3      mov;
    
  4. Sample3DSceneRenderer.cpp の修正です。
    Constructor で Shoot Class を生成して mov に初期座標(左下)を設定します。
    座標が大きくなる方向は「左(X座標), 下(Y座標), 手前(Z座標)」のようです。
    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();
        shoot= new Shoot(m_deviceResources);
        mov = shoot->f3(16.0f, 10.0f, 0.0f);
    }
    
  5. CreateWindowSizeDependentResources() 関数では Projection() を呼ぶだけです。
    void Sample3DSceneRenderer::CreateWindowSizeDependentResources()
    {    if (shot!=nullptr) shot->Projection();  }
    
  6. Rotate() ではキューブを弾丸に見立てて移動します。
    mov は現在の弾丸の座標で、右上に向かって移動します。
    mov の座標を XMMatrixTranslation() で変換行列 shot->m_mat に格納します。
    void Sample3DSceneRenderer::Rotate(float radians)
    {
        mov.x -= 0.2f;
        mov.y -= 0.1f;
        shoot->m_mat = XMMatrixTranslation(mov.x, mov.y, mov.z);
    }
    
  7. Render() 関数でモデルを描画します。
    SetEnv() が XMMATRIX m_mat で指定されたモデルの姿勢データを m_projection, m_view, m_model に設定する関数です。
    void Sample3DSceneRenderer::Render()
    {   if (!m_loadingComplete) {   return;  }
    
        auto context = m_deviceResources->GetD3DDeviceContext();
        shot->SetEnv();
        m_constantBufferData.projection = shot->m_projection;
        m_constantBufferData.view = shot->m_view;
        m_constantBufferData.model = shot->m_model;
        context->UpdateSubresource(m_constantBuffer.Get(), 0, NULL,
            &m_constantBufferData, 0, 0);
    
        UINT stride = sizeof(VertexPositionColor);
        UINT offset = 0;
        context->IASetVertexBuffers(
            0,1, m_vertexBuffer.GetAddressOf(), &stride, &offset);
        context->IASetIndexBuffer(
            m_indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);
        context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        context->IASetInputLayout(m_inputLayout.Get());
    
        context->VSSetShader(m_vertexShader.Get(), nullptr, 0);
        context->VSSetConstantBuffers(0, 1, m_constantBuffer.GetAddressOf());
        context->PSSetShader(m_pixelShader.Get(), nullptr, 0);
    
        context->DrawIndexed(m_indexCount, 0, 0);
    }
    
  8. マウスをクリックすると弾丸を元の座標に戻します。
    今回は Tracking は使いません。
    void Sample3DSceneRenderer::StartTracking()
    {   mov = shot->f3(16.0f, 10.0f, 0.0f);
    }
    
  9. プログラムを実行すると弾丸に見立てたカラーキューブが左下から右上に向かって発射されることを確認して下さい。
    マウスをクリックすると弾丸が元の座標に戻り、また右上に向かって移動します。
    モデルの位置とサイズの説明は Win10 Position を参照して下さい。

Shoot のソースコード

  1. Shoot.h です。
    DirectX::XMMATRIX m_mat; がモデルを描画する座標です。
    m_eye のZ座標を 20.0f にしてモデルの移動が良くわかるようにしています。
    // Shoot Class Header File  前田 稔
    #pragma once
    #include "..\Common\DeviceResources.h"
    struct float3
    {
        float   x;
        float   y;
        float   z;
    };
    
    class Shoot
    { public:
        float3 f3(float x, float y, float z);
        Shoot(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 SetEnv();
    
        // 3Dモデルの描画環境
        DirectX::XMFLOAT4X4 m_projection;
        DirectX::XMFLOAT4X4 m_view;
        DirectX::XMFLOAT4X4 m_model;
    
        // カメラの姿勢(Camera で規定値から修正)
        DirectX::XMVECTOR   m_eye = { 0.0f, 0.7f, 20.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::XMMATRIX   m_mat;
    
    private:
        std::shared_ptr<DX::DeviceResources> m_deviceResources;
    };
    
  2. Shoot.cpp です。
    SetEnv() が XMMATRIX *m_mat で指定されたモデルの姿勢データを m_projection, m_view, m_model に設定する関数です。
    移動情報を含んだ Matrix をそのまま m_model に代入出来れば苦労は無いのですが、移動情報を含めるとモデルが大きく変形してしまいます。
    そこで回転情報と移動情報を分けて処理します。
    移動情報は XMMATRIX の4行目の1列目から3列目に格納されています。
    モデルの移動は m_view のカメラの座標と向きを変更して対応します。
    モデルの回転は、移動情報を外して m_model に代入します。
    /*************************************/
    /* Shoot Class Program File  前田 稔 */
    /*************************************/
    #pragma once
    
    #include "pch.h"
    #include "..\Common\DirectXHelper.h"
    #include "Shoot.h"
    
    using namespace DirectX;
    using namespace Windows::Foundation;
    
    float3 Shoot::f3(float x, float y, float z)
    {
        float3 wf3;
        wf3.x = x;
        wf3.y = y;
        wf3.z = z;
        return wf3;
    }
    
    // Constructor で規定値に設定
    Shoot::Shoot(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_mat = XMMatrixIdentity();
    }
    
    // カメラの Projection を設定
    void Shoot::Projection()
    {
        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_projection, XMMatrixTranspose(perspectiveMatrix * orientationMatrix));
    }
    
    // m_eye, m_at, m_up を規定値から変更
    void Shoot::Camera(DirectX::XMVECTOR eye, DirectX::XMVECTOR at, DirectX::XMVECTOR up)
    {
        m_eye = eye;
        m_at = at;
        m_up = up;
        XMStoreFloat4x4(&m_view, XMMatrixTranspose(XMMatrixLookAtRH(eye, at, up)));
    }
    
    // 規定値からカメラを操作してモデルを平行移動
    void Shoot::Camera(float dx, float dy, float dz)
    {
        DirectX::XMVECTOR   eye;
        DirectX::XMVECTOR   at;
        eye = m_eye;
        at = m_at;
        eye.m128_f32[0] += dx;
        eye.m128_f32[1] += dy;
        eye.m128_f32[2] += dz;
        at.m128_f32[0] += dx;
        at.m128_f32[1] += dy;
        at.m128_f32[2] += dz;
        XMStoreFloat4x4(&m_view, XMMatrixTranspose(XMMatrixLookAtRH(eye, at, m_up)));
    }
    
    // モデルの描画環境を設定
    void Shoot::SetEnv()
    {
        Camera(m_mat.r->m128_f32[12], m_mat.r->m128_f32[13], m_mat.r->m128_f32[14]);
        m_mat.r->m128_f32[12] = 0.0f;
        m_mat.r->m128_f32[13] = 0.0f;
        m_mat.r->m128_f32[14] = 0.0f;
        XMStoreFloat4x4(&m_model, m_mat);
    }
    

RollPitchYaw を使う

  1. 弾丸の移動に XMMatrixRotationRollPitchYaw を使ってみましょう。
    RollPitchYaw は本来回転を設定する関数ですが、今回の場合はこちらの方が簡単かも知れません。
  2. SetEnv() 関数を次のように修正します。
    XMMATRIX *m_mat で指定されたモデルの回転情報は、view と乗算して m_view に格納することが出来ます。
    void Shoot::SetEnv()
    {
        XMMATRIX    view;
        view = XMMatrixTranspose(XMMatrixLookAtRH(m_eye, m_at, m_up));
        XMStoreFloat4x4(&m_view, m_mat * view);
    }
    
  3. 後は Sample3DSceneRenderer.cpp の Rotate() 関数を修正すればOKです。
    プログラムを実行すると弾丸に見立てたカラーキューブが左下から右上に向かって発射されることを確認して下さい。
    マウスをクリックすると弾丸が元の座標に戻り、また右上に向かって移動します。
    void Sample3DSceneRenderer::Rotate(float radians)
    {
        mov.x -= 0.003f;
        mov.y -= 0.005f;
        shoot->m_mat = XMMatrixRotationRollPitchYaw(mov.x, mov.y, mov.z);
    }
    

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