text: //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  //// PARTICULAR PURPOSE.
  ////
  //// Copyright (c) Microsoft Corporation. All rights reserved
  
  #include "pch.h"
  #include "CylinderMesh.h"
  #include "DirectXSample.h"
  #include "ConstantBuffers.h"
  
  using namespace Microsoft::WRL;
  using namespace DirectX;
  
  CylinderMesh::CylinderMesh(_In_ ID3D11Device *device, uint32 segments)
  {
      D3D11_BUFFER_DESC bd = {0};
      D3D11_SUBRESOURCE_DATA initData = {0};
  
      uint32 numVertices = 6 * (segments + 1) + 1;
      uint32 numIndices = 3 * segments * 3 * 2;
  
      std::vector<PNTVertex> point(numVertices);
      std::vector<uint16> index(numIndices);
  
      uint32 p = 0;
      // Top center point (multiple points for texture coordinates).
      for (uint32 a = 0; a <= segments; a++)
      {
          point[p].position = XMFLOAT3(0.0f, 0.0f, 1.0f);
          point[p].normal = XMFLOAT3(0.0f, 0.0f, 1.0f);
          point[p].textureCoordinate = XMFLOAT2(static_cast<float>(a) / static_cast<float>(segments), 0.0f);
          p++;
      }
      // Top edge of cylinder: Normals point up for lighting of top surface.
      for (uint32 a = 0; a <= segments; a++)
      {
          float angle = static_cast<float>(a) / static_cast<float>(segments) * XM_2PI;
          point[p].position = XMFLOAT3(cos(angle), sin(angle), 1.0f);
          point[p].normal = XMFLOAT3(0.0f, 0.0f, 1.0f);
          point[p].textureCoordinate = XMFLOAT2(static_cast<float>(a) / static_cast<float>(segments), 0.0f);
          p++;
      }
      // Top edge of cylinder: Normals point out for lighting of the side surface.
      for (uint32 a = 0; a <= segments; a++)
      {
          float angle = static_cast<float>(a) / static_cast<float>(segments) * XM_2PI;
          point[p].position = XMFLOAT3(cos(angle), sin(angle), 1.0f);
          point[p].normal = XMFLOAT3(cos(angle), sin(angle), 0.0f);
          point[p].textureCoordinate = XMFLOAT2(static_cast<float>(a) / static_cast<float>(segments), 0.0f);
          p++;
      }
      // Bottom edge of cylinder: Normals point out for lighting of the side surface.
      for (uint32 a = 0; a <= segments; a++)
      {
          float angle = static_cast<float>(a) / static_cast<float>(segments) * XM_2PI;
          point[p].position = XMFLOAT3(cos(angle), sin(angle), 0.0f);
          point[p].normal = XMFLOAT3(cos(angle), sin(angle), 0.0f);
          point[p].textureCoordinate = XMFLOAT2(static_cast<float>(a) / static_cast<float>(segments), 1.0f);
          p++;
      }
      // Bottom edge of cylinder: Normals point down for lighting of the bottom surface.
      for (uint32 a = 0; a <= segments; a++)
      {
          float angle = static_cast<float>(a) / static_cast<float>(segments) * XM_2PI;
          point[p].position = XMFLOAT3(cos(angle), sin(angle), 0.0f);
          point[p].normal = XMFLOAT3(0.0f, 0.0f, -1.0f);
          point[p].textureCoordinate = XMFLOAT2(static_cast<float>(a) / static_cast<float>(segments), 1.0f);
          p++;
      }
      // Bottom center of cylinder: Normals point down for lighting on the bottom surface.
      for (uint32 a = 0; a <= segments; a++)
      {
          point[p].position = XMFLOAT3(0.0f, 0.0f, 0.0f);
          point[p].normal = XMFLOAT3(0.0f, 0.0f, -1.0f);
          point[p].textureCoordinate = XMFLOAT2(static_cast<float>(a) / static_cast<float>(segments), 1.0f);
          p++;
      }
      m_vertexCount = p;
  
      p = 0;
      for (uint16 a = 0; a < 6; a += 2)
      {
          uint16 p1 = a*(segments + 1);
          uint16 p2 = (a+1)*(segments + 1);
          for (uint16 b = 0; b < segments; b++)
          {
              if (a < 4)
              {
                  index[p] = b + p1;
                  index[p+1] = b + p2;
                  index[p+2] = b + p2 + 1;
                  p = p + 3;
              }
              if (a > 0)
              {
                  index[p] = b + p1;
                  index[p+1] = b + p2 + 1;
                  index[p+2] = b + p1 + 1;
                  p = p + 3;
              }
          }
      }
      m_indexCount = p;
  
      bd.Usage = D3D11_USAGE_DEFAULT;
      bd.ByteWidth = sizeof(PNTVertex) * m_vertexCount;
      bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
      bd.CPUAccessFlags = 0;
      initData.pSysMem = point.data();
      DX::ThrowIfFailed(
          device->CreateBuffer(&bd, &initData, &m_vertexBuffer)
          );
  
      bd.Usage = D3D11_USAGE_DEFAULT;
      bd.ByteWidth = sizeof(uint16) * m_indexCount;
      bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
      bd.CPUAccessFlags = 0;
      initData.pSysMem = index.data();
      DX::ThrowIfFailed(
          device->CreateBuffer(&bd, &initData, &m_indexBuffer)
          );
  }
  