BoneModel

CreateModel2

CreateModel に Bone を追加した Ver 2.0 です。

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

プロジェクトの説明

  1. CreateModel Class に Bone を生成する CreateBone() を新しく追加します。
    多角錐の回転軸の中心はモデルの中央に設定されていますが、Bone では関節に相当する蓋の部分に設定されています。
    細長い Bone を骨に見立てて Bone を組み合わせてアニメーションすることを想定しています。
    Bone は5角形の多角錐で、一番目のパラメータは Bone の長さです。
            m_CreateModel = new CreateModel(m_deviceResources);
            m_CreateModel->CreateBone(4.0f, &m_vertexBuffer, &m_indexBuffer, &m_indexCount);
    
    また個々のモデルごとに設定していた共通の処理を void Create() としてまとめます。
  2. Windows10 で CreateModel を組み込んで、Bone を描画します。
    Create Model で詳しく説明されているので、プロジェクトの作成方法をかいつまんで説明します。
    また Win10 Normal Cone を参照してマウスで回転を設定して下さい。
    1. DirectX 11 および XAML アプリ(ユニバーサル Windows)を構築します。
      カラーキューブが回転しながら描画されます。
    2. Sample3DSceneRenderer に CreateModel をプロジェクトに組み込みます。
          #include "CreateModel.h"
          CreateModel     *m_CreateModel;
      
    3. カメラを引いてモデルサイズを調整して下さい。
          static const XMVECTORF32 eye = { 0.0f, 0.7f, 20.0f, 0.0f };
      
    4. CreateDeviceDependentResources() 関数の中で Bone のモデルを生成します。
      CreateBone が新しく追加された頂点データ+法線のモデルです。
      "COLOR" を "NORMAL" に修正してシェーダーを入れ替えて下さい。
      	// 両方のシェーダーの読み込みが完了したら、メッシュを作成します。
      	auto createCubeTask = (createPSTask && createVSTask).then([this]() {
      		m_CreateModel = new CreateModel(m_deviceResources);
      		//m_CreateModel->CreateCube(&m_vertexBuffer, &m_indexBuffer, &m_indexCount); 
      		m_CreateModel->CreateBone(4.0f, &m_vertexBuffer, &m_indexBuffer, &m_indexCount);
      	});
      
    5. Rotate() 関数ではモデルをY軸で自動的に回転します。
      void Sample3DSceneRenderer::Rotate(float radians)
      {
          XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationY(radians)));
      }
      
    6. TrackingUpdate() 関数ではマウスの操作でY軸およびX軸で回転します。
      void Sample3DSceneRenderer::TrackingUpdate(float positionX, float positionY)
      {
          XMMATRIX    mat;
          XMFLOAT4X4  f4x4;
          float       rx, ry;
      
          if (m_tracking)
          {   rx = XM_2PI*2.0f*positionX/m_deviceResources->GetOutputSize().Width;
              ry = XM_2PI*2.0f*positionY/m_deviceResources->GetOutputSize().Height;
              mat = XMMatrixRotationY(rx) * XMMatrixRotationX(ry);
              XMStoreFloat4x4(&f4x4, mat);
              m_constantBufferData.model = f4x4;
          }
      }
      

CreateModel

  1. CreateBone() を追加した CreateModel.h のソースコードです。
    // Create Normal Model  Ver 2.0  前田 稔
    #pragma once
    
    #include "..\Common\DeviceResources.h"
    #define  KAKU  21  // (多角錐の数は最大20まで)
    
    struct VertexNorm
    {
        DirectX::XMFLOAT3 pos;
        DirectX::XMFLOAT3 norm;
    };
    
    class CreateModel
    {
    public:
        CreateModel(std::shared_ptr<DX::DeviceResources>& deviceResources);
        void Create(
            _Out_ ID3D11Buffer **vertexBuffer,
            _Out_ ID3D11Buffer **indexBuffer,
            _Out_ uint32 *indexCount,
            _In_  VertexNorm *Vertices,
            _In_  unsigned short *Indices,
            _In_  uint32 Size);
        void CreateCube(
            _Out_ ID3D11Buffer **vertexBuffer,
            _Out_ ID3D11Buffer **indexBuffer,
            _Out_ uint32 *indexCount);
        void CreateCone(
            _In_  uint32 kaku,
            _Out_ ID3D11Buffer **vertexBuffer,
            _Out_ ID3D11Buffer **indexBuffer,
            _Out_ uint32 *indexCount);
        void CreateBone(
            _In_  float len,
            _Out_ ID3D11Buffer **vertexBuffer,
            _Out_ ID3D11Buffer **indexBuffer,
            _Out_ uint32 *indexCount);
    
        void Debug(uint16 *ary, uint32 siz);
        void DebugVert(VertexNorm *Vert, uint32 siz);
        void DebugVert(VertexNorm Vert, uint32 num);
        void DebugVert(VertexNorm *Vert, uint16 *ary, uint32 siz);
    
    private:
        std::shared_ptr<DX::DeviceResources> m_deviceResources;
    };
    
  2. CreateModel.cpp です。
    Debug() 関係の関数は必要無ければ削除して下さい。
    個々のモデルごとに設定していた共通の処理を void Create() としてまとめます。
    CreateBone() の回転軸の中心は多角錐の蓋の部分に設定されています。
    // Create Normal Model  Ver 2.0  前田 稔
    #pragma once
    
    #include "pch.h"
    #include "..\Common\DirectXHelper.h"
    #include "CreateModel.h"
    using namespace DirectX;
    
    void CreateModel::Debug(uint16 *ary, uint32 siz)
    {
        wchar_t str[80];
        swprintf(str, 80, L"Array[%d]\r\n", siz);
        OutputDebugString(str);
        for (uint32 i = 0; i<siz; i++)
        {
            swprintf(str, 80, L"%d\r\n", ary[i]);
            OutputDebugString(str);
        }
    }
    void CreateModel::DebugVert(VertexNorm *Vert, uint32 siz)
    {
        for (uint32 i = 0; i<siz; i++)
        {
            DebugVert(Vert[i], i);
        }
    }
    void CreateModel::DebugVert(VertexNorm Vert, uint32 num)
    {
        wchar_t str[120];
        swprintf(str, 120, L"Vert-%d(%f, %f, %f) (%f, %f, %f)\r\n",
            num, Vert.pos.x, Vert.pos.y, Vert.pos.z, Vert.norm.x, Vert.norm.y, Vert.norm.z);
        OutputDebugString(str);
    }
    
    void CreateModel::DebugVert(VertexNorm *Vert, uint16 *ary, uint32 siz)
    {
        for(uint32 i=0; i<siz; i++)
        {   if (i%3==0) OutputDebugString(L"(");
            DebugVert(Vert[ary[i]], i);
            if (i%3==2) OutputDebugString(L")\r\n");
        }
    }
    
    CreateModel::CreateModel(std::shared_ptr<DX::DeviceResources>& deviceResources) :
        m_deviceResources(deviceResources)
    {
    }
    
    void CreateModel::Create(
        _Out_ ID3D11Buffer **vertexBuffer,
        _Out_ ID3D11Buffer **indexBuffer,
        _In_  uint32 *indexCount,
        _In_  VertexNorm *Vertices,
        _In_  uint16 *Indices,
        _In_  uint32 Size)
    {
        D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
        vertexBufferData.pSysMem = Vertices;
        vertexBufferData.SysMemPitch = 0;
        vertexBufferData.SysMemSlicePitch = 0;
        CD3D11_BUFFER_DESC vertexBufferDesc(Size, D3D11_BIND_VERTEX_BUFFER);
        DX::ThrowIfFailed(
            m_deviceResources->GetD3DDevice()->CreateBuffer(
                &vertexBufferDesc,
                &vertexBufferData,
                vertexBuffer
            ));
    
        D3D11_SUBRESOURCE_DATA indexBufferData = {0};
        indexBufferData.pSysMem = Indices;
        indexBufferData.SysMemPitch = 0;
        indexBufferData.SysMemSlicePitch = 0;
        CD3D11_BUFFER_DESC indexBufferDesc(*indexCount * 2, D3D11_BIND_INDEX_BUFFER);
        DX::ThrowIfFailed(
            m_deviceResources->GetD3DDevice()->CreateBuffer(
                &indexBufferDesc,
                &indexBufferData,
                indexBuffer));
    }
    
    void CreateModel::CreateCube(
        _Out_ ID3D11Buffer **vertexBuffer,
        _Out_ ID3D11Buffer **indexBuffer,
        _Out_ uint32 *indexCount)
    {
        static VertexNorm cubeVertices[] = 
        {
            { XMFLOAT3(-0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f) },   // +Y (top face)
            { XMFLOAT3( 0.5f, 0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f) },
            { XMFLOAT3( 0.5f, 0.5f,  0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f) },
            { XMFLOAT3(-0.5f, 0.5f,  0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f) },
    
            { XMFLOAT3(-0.5f, -0.5f,  0.5f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, // -Y (bottom face)
            { XMFLOAT3( 0.5f, -0.5f,  0.5f), XMFLOAT3(0.0f, -1.0f, 0.0f) },
            { XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, -1.0f, 0.0f) },
            { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, -1.0f, 0.0f) },
    
            { XMFLOAT3(0.5f,  0.5f,  0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f) },   // +X (right face)
            { XMFLOAT3(0.5f,  0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f) },
            { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f) },
            { XMFLOAT3(0.5f, -0.5f,  0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f) },
    
            { XMFLOAT3(-0.5f,  0.5f, -0.5f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, // -X (left face)
            { XMFLOAT3(-0.5f,  0.5f,  0.5f), XMFLOAT3(-1.0f, 0.0f, 0.0f) },
            { XMFLOAT3(-0.5f, -0.5f,  0.5f), XMFLOAT3(-1.0f, 0.0f, 0.0f) },
            { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(-1.0f, 0.0f, 0.0f) },
    
            { XMFLOAT3(-0.5f,  0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f) },   // +Z (front face)
            { XMFLOAT3( 0.5f,  0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f) },
            { XMFLOAT3( 0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f) },
            { XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f) },
    
            { XMFLOAT3( 0.5f,  0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, // -Z (back face)
            { XMFLOAT3(-0.5f,  0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, -1.0f) },
            { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, -1.0f) },
            { XMFLOAT3( 0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, -1.0f) },
        };
    
        static uint16 cubeIndices [] =
        {
            0, 1, 2,      0, 2, 3,
            4, 5, 6,      4, 6, 7,
            8, 9, 10,     8, 10, 11,
            12, 13, 14,   12, 14, 15,
            16, 17, 18,   16, 18, 19,
            20, 21, 22,   20, 22, 23
        };
    
        *indexCount = ARRAYSIZE(cubeIndices);   // 36
        Create(vertexBuffer, indexBuffer, indexCount, cubeVertices, cubeIndices, sizeof(cubeVertices));
    }
    
    void CreateModel::CreateCone(
        _In_  uint32 kaku,
        _Out_ ID3D11Buffer **vertexBuffer,
        _Out_ ID3D11Buffer **indexBuffer,
        _Out_ uint32 *indexCount)
    {
        static VertexNorm coneVertex[KAKU * 4];
        // 辺の座標, 頂点座標, 蓋の座標, 蓋の中心
        for (uint32 slice = 0; slice<kaku; slice++)
        {
            float v = (float)slice / (float)(kaku - 1);
            float theta = v * 3.14f * 2;
            coneVertex[slice * 4 + 0].pos = XMFLOAT3(sinf(theta), -0.7f, cosf(theta));
            coneVertex[slice * 4 + 1].pos = XMFLOAT3(0.0f, 0.7f, 0.0f);
            coneVertex[slice * 4 + 2].pos = XMFLOAT3(sinf(theta), -0.7f, cosf(theta));
            coneVertex[slice * 4 + 3].pos = XMFLOAT3(0.0f, -0.7f, 0.0f);
            coneVertex[slice * 4 + 0].norm = XMFLOAT3(sinf(theta), 0.7f, cosf(theta));
            coneVertex[slice * 4 + 1].norm = XMFLOAT3(sinf(theta), 0.7f, cosf(theta));
            coneVertex[slice * 4 + 2].norm = XMFLOAT3(0.0f, -1.0f, 0.0f);
            coneVertex[slice * 4 + 3].norm = XMFLOAT3(0.0f, -1.0f, 0.0f);
        }
        // 最後の座標は先頭と同じ(誤差を修正)
        coneVertex[(kaku-1) * 4 + 0].pos = coneVertex[0].pos;
        coneVertex[(kaku-1) * 4 + 2].pos = coneVertex[2].pos;
    
        static uint16 coneIndex[KAKU * 6];
        for (uint32 slice = 0; slice<(kaku - 1); slice++)
        {   // 辺の座標, 頂点座標, 蓋の座標, 蓋の中心
            coneIndex[6 * slice + 0] = slice * 4 + 0;
            coneIndex[6 * slice + 1] = slice * 4 + 1;
            coneIndex[6 * slice + 2] = slice * 4 + 4;
            coneIndex[6 * slice + 3] = slice * 4 + 6;
            coneIndex[6 * slice + 4] = slice * 4 + 3;
            coneIndex[6 * slice + 5] = slice * 4 + 2;
        }
    
        *indexCount = (kaku - 1) * 12;
        Create(vertexBuffer, indexBuffer, indexCount, coneVertex, coneIndex, sizeof(coneVertex));
    }
    
    void CreateModel::CreateBone(
        _In_  float len,
        _Out_ ID3D11Buffer **vertexBuffer,
        _Out_ ID3D11Buffer **indexBuffer,
        _Out_ uint32 *indexCount)
    {
        static VertexNorm coneVertex[KAKU * 4];
        // 辺の座標, 頂点座標, 蓋の座標, 蓋の中心
        for (uint32 slice = 0; slice<6; slice++)
        {
            float v = (float)slice / 5.0f;
            float theta = v * 3.14f * 2;
            coneVertex[slice * 4 + 0].pos = XMFLOAT3(sinf(theta), 0.0f, cosf(theta));
            coneVertex[slice * 4 + 1].pos = XMFLOAT3(0.0f, len, 0.0f);
            coneVertex[slice * 4 + 2].pos = XMFLOAT3(sinf(theta), 0.0f, cosf(theta));
            coneVertex[slice * 4 + 3].pos = XMFLOAT3(0.0f, 0.0f, 0.0f);
            coneVertex[slice * 4 + 0].norm = XMFLOAT3(sinf(theta), len, cosf(theta));
            coneVertex[slice * 4 + 1].norm = XMFLOAT3(sinf(theta), len, cosf(theta));
            coneVertex[slice * 4 + 2].norm = XMFLOAT3(0.0f, -1.0f, 0.0f);
            coneVertex[slice * 4 + 3].norm = XMFLOAT3(0.0f, -1.0f, 0.0f);
        }
        // 最後の座標は先頭と同じ(誤差を修正)
        coneVertex[5 * 4 + 0].pos = coneVertex[0].pos;
        coneVertex[5 * 4 + 2].pos = coneVertex[2].pos;
    
        static uint16 coneIndex[6 * 6];
        for (uint32 slice = 0; slice<5; slice++)
        {   // 辺の座標, 頂点座標, 蓋の座標, 蓋の中心
            coneIndex[slice * 6 + 0] = slice * 4 + 0;
            coneIndex[slice * 6 + 1] = slice * 4 + 1;
            coneIndex[slice * 6 + 2] = slice * 4 + 4;
            coneIndex[slice * 6 + 3] = slice * 4 + 6;
            coneIndex[slice * 6 + 4] = slice * 4 + 3;
            coneIndex[slice * 6 + 5] = slice * 4 + 2;
        }
    
        *indexCount = 5 * 12;
        Create(vertexBuffer, indexBuffer, indexCount, coneVertex, coneIndex, sizeof(coneVertex));
    }
    

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