void GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData) { meshData.Vertices.clear(); meshData.Indices.clear(); // // Build Stacks. // float stackHeight = height / stackCount; // Amount to increment radius as we move up each stack level from bottom to top. float radiusStep = (topRadius - bottomRadius) / stackCount; UINT ringCount = stackCount+1; // Compute vertices for each stack ring starting at the bottom and moving up. for(UINT i = 0; i < ringCount; ++i) { float y = -0.5f*height + i*stackHeight; float r = bottomRadius + i*radiusStep; // vertices of ring float dTheta = 2.0f*XM_PI/sliceCount; for(UINT j = 0; j <= sliceCount; ++j) { Vertex vertex; float c = cosf(j*dTheta); float s = sinf(j*dTheta); vertex.Position = XMFLOAT3(r*c, y, r*s); vertex.TexC.x = (float)j/sliceCount; vertex.TexC.y = 1.0f - (float)i/stackCount; // Cylinder can be parameterized as follows, where we introduce v // parameter that goes in the same direction as the v tex-coord // so that the bitangent goes in the same direction as the v tex-coord. // Let r0 be the bottom radius and let r1 be the top radius. // y(v) = h - hv for v in [0,1]. // r(v) = r1 + (r0-r1)v // // x(t, v) = r(v)*cos(t) // y(t, v) = h - hv // z(t, v) = r(v)*sin(t) // // dx/dt = -r(v)*sin(t) // dy/dt = 0 // dz/dt = +r(v)*cos(t) // // dx/dv = (r0-r1)*cos(t) // dy/dv = -h // dz/dv = (r0-r1)*sin(t) // This is unit length. vertex.TangentU = XMFLOAT3(-s, 0.0f, c); float dr = bottomRadius-topRadius; XMFLOAT3 bitangent(dr*c, -height, dr*s); XMVECTOR T = XMLoadFloat3(&vertex.TangentU); XMVECTOR B = XMLoadFloat3(&bitangent); XMVECTOR N = XMVector3Normalize(XMVector3Cross(T, B)); XMStoreFloat3(&vertex.Normal, N); meshData.Vertices.push_back(vertex); } } // Add one because we duplicate the first and last vertex per ring // since the texture coordinates are different. UINT ringVertexCount = sliceCount+1; // Compute indices for each stack. for(UINT i = 0; i < stackCount; ++i) { for(UINT j = 0; j < sliceCount; ++j) { meshData.Indices.push_back(i*ringVertexCount + j); meshData.Indices.push_back((i+1)*ringVertexCount + j); meshData.Indices.push_back((i+1)*ringVertexCount + j+1); meshData.Indices.push_back(i*ringVertexCount + j); meshData.Indices.push_back((i+1)*ringVertexCount + j+1); meshData.Indices.push_back(i*ringVertexCount + j+1); } } BuildCylinderTopCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData); BuildCylinderBottomCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData); }
void GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData) { meshData.Vertices.clear(); meshData.Indices.clear(); float stackHeight = height / stackCount; float radiusStep = (topRadius - bottomRadius) / stackCount; UINT ringCount = stackCount+1; for(UINT i = 0; i < ringCount; ++i) { float y = -0.5f*height + i*stackHeight; float r = bottomRadius + i*radiusStep; float dTheta = 2.0f*XM_PI/sliceCount; for(UINT j = 0; j <= sliceCount; ++j) { Vertex vertex; float c = cosf(j*dTheta); float s = sinf(j*dTheta); vertex.Position = glm::vec3(r*c, y, r*s); vertex.TexC.x = (float)j/sliceCount; vertex.TexC.y = 1.0f - (float)i/stackCount; vertex.TangentU = glm::vec3(-s, 0.0f, c); float dr = bottomRadius-topRadius; glm::vec3 bitangent(dr*c, -height, dr*s); glm::vec3 T = vertex.TangentU; glm::vec3 B = bitangent; glm::vec3 N = glm::normalize(glm::cross(T, B)); vertex.Normal = N; meshData.Vertices.push_back(vertex); } } UINT ringVertexCount = sliceCount+1; for(UINT i = 0; i < stackCount; ++i) { for(UINT j = 0; j < sliceCount; ++j) { meshData.Indices.push_back(i*ringVertexCount + j); meshData.Indices.push_back((i+1)*ringVertexCount + j); meshData.Indices.push_back((i+1)*ringVertexCount + j+1); meshData.Indices.push_back(i*ringVertexCount + j); meshData.Indices.push_back((i+1)*ringVertexCount + j+1); meshData.Indices.push_back(i*ringVertexCount + j+1); } } BuildCylinderTopCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData); BuildCylinderBottomCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData); }