XFILE 3

X-FILE を親子孫で回転する

2体のカラーモデル(X-FILE)と4面体を親子孫の関係で回転します。

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

プログラムの説明

  1. X-FILE から入力した2体のカラーモデルとプログラムで定義した4面体を親子孫の関係で回転します。
    X-FILE を親子で回転する を参照してプロジェクトを作成して下さい。
    このプロジェクトは X-FILE から入力した "CubeColor.x", "Ball.x" が親子関係で回転しています。
  2. Sample3DSceneRenderer.h で3体のモデルとカメラの領域を配列で定義します。
        Microsoft::WRL::ComPtr<ID3D11Buffer>        m_vertexBuffer[3];
        Microsoft::WRL::ComPtr<ID3D11Buffer>        m_indexBuffer[3];
        uint32      m_indexCount[3];
        Load_X      *model;
        MyCamera    *camera[3];
    
  3. Sample3DSceneRenderer.cpp の修正です。
    Constructor でカメラを生成します。
    Sample3DSceneRenderer::Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
        m_loadingComplete(false),
        m_degreesPerSecond(45),
        m_tracking(false),
        m_deviceResources(deviceResources)
    {
        CreateDeviceDependentResources();
        CreateWindowSizeDependentResources();
        for(int i=0; i<3; i++)  camera[i] = new MyCamera(m_deviceResources);
    }
    
  4. Rotate() 関数でモデルの回転を設定します。
    Model() 関数のパラメータ1に回転情報の配列を渡します。
    パラメータ2は関係する回転情報の個数で、モデル1では1を、モデル2では2を渡します。
    void Sample3DSceneRenderer::Rotate(float radians)
    {
        camera[0]->Model(0.0f, radians, 0.0f);
        float3 m_rot[] = {{ 0.0f, 0.8f, 0-radians },{ 0.0f, 0.3f, 0-radians }};
        camera[1]->Model(m_rot, 1);
        camera[2]->Model(m_rot, 2);
    }
    
  5. CreateDeviceDependentResources() 関数では、2体のモデルを読み込んだ後で4面体を生成します。
    void Sample3DSceneRenderer::CreateDeviceDependentResources()
    {
        // シェーダーを非同期で読み込みます。
        auto loadVSTask = DX::ReadDataAsync(L"SampleVertexShader.cso");
        auto loadPSTask = DX::ReadDataAsync(L"SamplePixelShader.cso");
    
        // 頂点シェーダー ファイルを読み込んだ後、シェーダーと入力レイアウトを作成します。
        auto createVSTask = loadVSTask.then([this](const std::vector<byte>& fileData) {
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreateVertexShader(
                    &fileData[0],
                    fileData.size(),
                    nullptr,
                    &m_vertexShader
                    )
                );
    
            static const D3D11_INPUT_ELEMENT_DESC vertexDesc [] =
            {
                { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
                { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            };
    
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreateInputLayout(
                    vertexDesc,
                    ARRAYSIZE(vertexDesc),
                    &fileData[0],
                    fileData.size(),
                    &m_inputLayout
                    )
                );
        });
    
        // ピクセル シェーダー ファイルを読み込んだ後、シェーダーと定数バッファーを作成します。
        auto createPSTask = loadPSTask.then([this](const std::vector<byte>& fileData) {
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreatePixelShader(
                    &fileData[0],
                    fileData.size(),
                    nullptr,
                    &m_pixelShader
                    )
                );
    
            CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelViewProjectionConstantBuffer) , D3D11_BIND_CONSTANT_BUFFER);
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreateBuffer(
                    &constantBufferDesc,
                    nullptr,
                    &m_constantBuffer
                    )
                );
        });
    
        // 両方のシェーダーの読み込みが完了したら、メッシュを作成します。
        auto createCubeTask = (createPSTask && createVSTask).then([this] () {
            model = new Load_X(m_deviceResources);
            model->Load("CubeColor.x", &m_vertexBuffer[0], &m_indexBuffer[0], &m_indexCount[0]);
            model->Load("Ball.x", &m_vertexBuffer[1], &m_indexBuffer[1], &m_indexCount[1]);
    
            static const VertexPositionColor cubeVertices[] = 
            {
                { XMFLOAT3(0.0f, 1.22474f, 0.0f), XMFLOAT3(1.0f, 1.0f, 1.0f) },
                { XMFLOAT3(0.0f, -0.40825f, -1.1547f), XMFLOAT3(1.0f, 0.0f, 0.0f) },
                { XMFLOAT3(-1.0f, -0.40825f, 0.57735f), XMFLOAT3(0.0f, 1.0f, 0.0f) },
                { XMFLOAT3(1.0f, -0.40825f, 0.57735f), XMFLOAT3(0.0f, 0.0f, 1.0f) },
            };
            D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
            vertexBufferData.pSysMem = cubeVertices;
            vertexBufferData.SysMemPitch = 0;
            vertexBufferData.SysMemSlicePitch = 0;
            CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(cubeVertices), D3D11_BIND_VERTEX_BUFFER);
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreateBuffer(
                    &vertexBufferDesc,
                    &vertexBufferData,
                    &m_vertexBuffer[2]
                    )
                );
    
            static const unsigned short cubeIndices [] =
            {
                0,1,3,
                0,2,1,
                0,3,2,
                1,2,3,
            };
            m_indexCount[2] = ARRAYSIZE(cubeIndices);
            D3D11_SUBRESOURCE_DATA indexBufferData = {0};
            indexBufferData.pSysMem = cubeIndices;
            indexBufferData.SysMemPitch = 0;
            indexBufferData.SysMemSlicePitch = 0;
            CD3D11_BUFFER_DESC indexBufferDesc(sizeof(cubeIndices), D3D11_BIND_INDEX_BUFFER);
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreateBuffer(
                    &indexBufferDesc,
                    &indexBufferData,
                    &m_indexBuffer[2]
                    )
                );
        });
    
        // キューブが読み込まれたら、オブジェクトを描画する準備が完了します。
        createCubeTask.then([this] () {  m_loadingComplete = true;  });
    }
    
  6. Render() 関数でモデルを描画します。
    void Sample3DSceneRenderer::Render()
    {
        ・・・
    
        // カリングを設定
        model->SetCullMode();
    
        //☆モデルを描画
        for(int i=0; i<3; i++)
        {   m_constantBufferData.projection = camera[i]->m_projection;
            m_constantBufferData.view = camera[i]->m_view;
            m_constantBufferData.model = camera[i]->m_model;
    
            context->UpdateSubresource(
                m_constantBuffer.Get(), 0, NULL, &m_constantBufferData, 0, 0);
            context->IASetVertexBuffers(
                0, 1, m_vertexBuffer[i].GetAddressOf(), &stride, &offset);
            context->IASetIndexBuffer(
                m_indexBuffer[i].Get(), DXGI_FORMAT_R16_UINT, 0);
    
            context->DrawIndexed(m_indexCount[i], 0, 0);
        }
    }
    
  7. パラメータ1で回転情報の配列を受け取る Model() 関数です。
    モデル2の回転は、モデル1の回転情報と掛け合わせます。
    // 回転配列のパラメータ
    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);
    }
    

[Previous Chapter ↑] X-FILE を親子で回転する

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