Win10 Texture Cylinder

シリンダーの座標をプログラムで計算して、テクスチャを張り付けて描画します。

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

プロジェクトの作成

  1. Windows10 DirectX3D でシリンダーの座標をプログラムで計算して、テクスチャを張り付けて描画します。
    Win10 TextureBox では BOX の座標をテーブルで定義しましたが、今回はプログラムで計算します。
    Win10 Template を参照して DirectX 11 アプリ(ユニバーサル Windows)を構築して下さい。
    カラーキューブが回転しながら描画され、FPS が表示されます。
    プロジェクトの名前は App1 になっています。
  2. テクスチャを貼り付けたシリンダーを描画するので Win10 Shader から「頂点座標+法線+テクスチャ」を参照してシェーダーを設定して下さい。
  3. 次のファイルを Content\ に格納して下さい。
    これらのファイルはテクスチャを貼り付ける為に使用します。
    ソースコードは Win10 TextureBox に掲載されています。
    Content\BasicReaderWriter.h
    Content\BasicReaderWriter.cpp
    Content\TextureLoader.h
    Content\TextureLoader.cpp
  4. テクスチャ画像は何でも良いのですが、今回は ayu.jpg を使うことにします。
    プロジェクトのフォルダーに ayu.jpg を格納してプロジェクトに加えて下さい。
  5. Sample3DSceneRenderer.h の修正です。
    今回は m_modelVertices, m_modelIndices を vector で定義してみました。
    #include <vector>
    using namespace std;
    
            vector<VertexPosition> m_modelVertices;
            vector<unsigned short> m_modelIndices;
    
    Win10 Norm Cone のように配列で定義する方法もあります。
        static VertexPositionNorm modelVertices[KAKU * 2];
        static unsigned short modelIndices[KAKU*6];
    
  6. Content\Sample3DSceneRenderer.cpp を修正します。
    ヘッダーの追加です。
    #include "TextureLoader.h"
    #define  KAKU  20       //(Cylinder の画数)
    
    プログラムでシリンダーを生成します。
    VertexPosition modelVertices[] の古いソースコードは削除して下さい。
        auto createCubeTask = (createPSTask && createVSTask).then([this] ()
        {
            int i;
            static VertexPosition VP[2];
            for(i=0; i<KAKU; i++)
            {   float v = (float)i / (float)(KAKU - 1);
                float theta = v * 3.14f * 2;
                VP[0].pos = XMFLOAT3(sinf(theta), -1.5f, cosf(theta));
                VP[0].norm = XMFLOAT3(sinf(theta), 1.0f, cosf(theta));
                VP[0].tex.x = (float)i / (KAKU - 1);
                VP[0].tex.y = 1.0f;
                VP[1].pos = XMFLOAT3(sinf(theta), 1.5f, cosf(theta));
                VP[1].norm = XMFLOAT3(sinf(theta), 1.0f, cosf(theta));
                VP[1].tex.x = (float)i / (KAKU - 1);
                VP[1].tex.y = 0.0f;
                m_modelVertices.push_back(VP[0]);
                m_modelVertices.push_back(VP[1]);
            }
    
    頂点Index の計算です。
    short modelIndices[] の古いソースコードは削除して下さい。
            for(i=0; i<KAKU; i++)
            {   m_modelIndices.push_back(i*2+0);
                m_modelIndices.push_back(i*2+1);
                m_modelIndices.push_back(i*2+2);
            }
            for(i=0; i<KAKU; i++)
            {   m_modelIndices.push_back(i*2+3);
                m_modelIndices.push_back(i*2+2);
                m_modelIndices.push_back(i*2+1);
            }
    
    モデルのデータを参照してメッシュを生成します。
            int VTnum = m_modelVertices.size();
            int IDXnum = m_modelIndices.size();
            m_indexCount = IDXnum;
            VertexPosition *Vertices = new VertexPosition[VTnum];
            unsigned short *Indices = new unsigned short[IDXnum];
            for(int i=0; i<VTnum; i++) Vertices[i] = m_modelVertices[i];
            for(int i=0; i<IDXnum; i++) Indices[i] = m_modelIndices[i];
    
            D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
            vertexBufferData.pSysMem = Vertices;
            vertexBufferData.SysMemPitch = 0;
            vertexBufferData.SysMemSlicePitch = 0;
            CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(VertexPosition)*VTnum, D3D11_BIND_VERTEX_BUFFER);
    
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreateBuffer(
                    &vertexBufferDesc, &vertexBufferData, &m_vertexBuffer ));
    
            D3D11_SUBRESOURCE_DATA indexBufferData = {0};
            indexBufferData.pSysMem = Indices;
            indexBufferData.SysMemPitch = 0;
            indexBufferData.SysMemSlicePitch = 0;
            CD3D11_BUFFER_DESC indexBufferDesc(sizeof(unsigned short)*IDXnum, D3D11_BIND_INDEX_BUFFER);
    
            DX::ThrowIfFailed(
                m_deviceResources->GetD3DDevice()->CreateBuffer(
                    &indexBufferDesc, &indexBufferData, &m_indexBuffer ));
    
            // 領域の解放
            if (Vertices)   delete Vertices;
            if (Indices)    delete Indices;
        });
    
  7. コンパイルして実行すると、テクスチャを張り付けたモデルが描画されます。

【NOTE】

vector 領域からモデルデータを直接参照することも出来るようです。
但し、領域が配列と同様に連続していることが条件で、あまりお勧めはできません。
直接転送する場合は、次のようになります。
    D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
    vertexBufferData.pSysMem = m_modelVertices.data();
    vertexBufferData.SysMemPitch = 0;
    vertexBufferData.SysMemSlicePitch = 0;
    CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(VertexPosition)*KAKU*2, D3D11_BIND_VERTEX_BUFFER);

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