void GeometryGenerator::CreateSphere(float radius, UINT sliceCount, UINT stackCount, MeshData& meshData) { meshData.Vertices.clear(); meshData.Indices.clear(); // // Compute the vertices stating at the top pole and moving down the stacks. // // Poles: note that there will be texture coordinate distortion as there is // not a unique point on the texture map to assign to the pole when mapping // a rectangular texture onto a sphere. Vertex topVertex(0.0f, +radius, 0.0f, 0.0f, +1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); Vertex bottomVertex(0.0f, -radius, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); meshData.Vertices.push_back( topVertex ); float phiStep = XM_PI/stackCount; float thetaStep = 2.0f*XM_PI/sliceCount; // Compute vertices for each stack ring (do not count the poles as rings). for(UINT i = 1; i <= stackCount-1; ++i) { float phi = i*phiStep; // Vertices of ring. for(UINT j = 0; j <= sliceCount; ++j) { float theta = j*thetaStep; Vertex v; // spherical to cartesian v.Position.x = radius*sinf(phi)*cosf(theta); v.Position.y = radius*cosf(phi); v.Position.z = radius*sinf(phi)*sinf(theta); // Partial derivative of P with respect to theta v.TangentU.x = -radius*sinf(phi)*sinf(theta); v.TangentU.y = 0.0f; v.TangentU.z = +radius*sinf(phi)*cosf(theta); XMVECTOR T = XMLoadFloat3(&v.TangentU); XMStoreFloat3(&v.TangentU, XMVector3Normalize(T)); XMVECTOR p = XMLoadFloat3(&v.Position); XMStoreFloat3(&v.Normal, XMVector3Normalize(p)); v.TexC.x = theta / XM_2PI; v.TexC.y = phi / XM_PI; meshData.Vertices.push_back( v ); } } meshData.Vertices.push_back( bottomVertex ); // // Compute indices for top stack. The top stack was written first to the vertex buffer // and connects the top pole to the first ring. // for(UINT i = 1; i <= sliceCount; ++i) { meshData.Indices.push_back(0); meshData.Indices.push_back(i+1); meshData.Indices.push_back(i); } // // Compute indices for inner stacks (not connected to poles). // // Offset the indices to the index of the first vertex in the first ring. // This is just skipping the top pole vertex. UINT baseIndex = 1; UINT ringVertexCount = sliceCount+1; for(UINT i = 0; i < stackCount-2; ++i) { for(UINT j = 0; j < sliceCount; ++j) { meshData.Indices.push_back(baseIndex + i*ringVertexCount + j); meshData.Indices.push_back(baseIndex + i*ringVertexCount + j+1); meshData.Indices.push_back(baseIndex + (i+1)*ringVertexCount + j); meshData.Indices.push_back(baseIndex + (i+1)*ringVertexCount + j); meshData.Indices.push_back(baseIndex + i*ringVertexCount + j+1); meshData.Indices.push_back(baseIndex + (i+1)*ringVertexCount + j+1); } } // // Compute indices for bottom stack. The bottom stack was written last to the vertex buffer // and connects the bottom pole to the bottom ring. // // South pole vertex was added last. UINT southPoleIndex = (UINT)meshData.Vertices.size()-1; // Offset the indices to the index of the first vertex in the last ring. baseIndex = southPoleIndex - ringVertexCount; for(UINT i = 0; i < sliceCount; ++i) { meshData.Indices.push_back(southPoleIndex); meshData.Indices.push_back(baseIndex+i); meshData.Indices.push_back(baseIndex+i+1); } }
void CreateSphere(float radius, UINT sliceCount, UINT stackCount, std::vector<XMFLOAT3>* Positions, std::vector<WORD>* Indices, std::vector<XMFLOAT2>* UVs) //From Frank D. Luna's book but edited a little bit { // // Compute the vertices stating at the top pole and moving down the stacks. // // Poles: note that there will be texture coordinate distortion as there is // not a unique point on the texture map to assign to the pole when mapping // a rectangular texture onto a sphere. XMFLOAT3 topVertex(0.0f, +radius, 0.0f); XMFLOAT3 bottomVertex(0.0f, -radius, 0.0f); Positions->push_back(topVertex); float phiStep = XM_PI / stackCount; float thetaStep = 2.0f*XM_PI / sliceCount; // Compute vertices for each stack ring (do not count the poles as rings). for (UINT i = 1; i <= stackCount - 1; ++i) { float phi = i*phiStep; // Vertices of ring. for (UINT j = 0; j <= sliceCount; ++j) { float theta = j*thetaStep; XMFLOAT3 v; // spherical to cartesian v.x = radius*sinf(phi)*cosf(theta); v.y = radius*cosf(phi); v.z = radius*sinf(phi)*sinf(theta); //// Partial derivative of P with respect to theta //v.TangentU.x = -radius*sinf(phi)*sinf(theta); //v.TangentU.y = 0.0f; //v.TangentU.z = +radius*sinf(phi)*cosf(theta); //XMVECTOR T = XMLoadFloat3(&v.TangentU); //XMStoreFloat3(&v.TangentU, XMVector3Normalize(T)); //XMVECTOR p = XMLoadFloat3(&v.Position); //XMStoreFloat3(&v.Normal, XMVector3Normalize(p)); XMFLOAT2 uv; uv.x = theta / XM_2PI; uv.y = phi / XM_PI; Positions->push_back(v); UVs->push_back(uv); } } Positions->push_back(bottomVertex); // // Compute indices for top stack. The top stack was written first to the vertex buffer // and connects the top pole to the first ring. // for (UINT i = 1; i <= sliceCount; ++i) { Indices->push_back(0); Indices->push_back(i + 1); Indices->push_back(i); } // // Compute indices for inner stacks (not connected to poles). // // Offset the indices to the index of the first vertex in the first ring. // This is just skipping the top pole vertex. UINT baseIndex = 1; UINT ringVertexCount = sliceCount + 1; for (UINT i = 0; i < stackCount - 2; ++i) { for (UINT j = 0; j < sliceCount; ++j) { Indices->push_back(baseIndex + i*ringVertexCount + j); Indices->push_back(baseIndex + i*ringVertexCount + j + 1); Indices->push_back(baseIndex + (i + 1)*ringVertexCount + j); Indices->push_back(baseIndex + (i + 1)*ringVertexCount + j); Indices->push_back(baseIndex + i*ringVertexCount + j + 1); Indices->push_back(baseIndex + (i + 1)*ringVertexCount + j + 1); } } // // Compute indices for bottom stack. The bottom stack was written last to the vertex buffer // and connects the bottom pole to the bottom ring. // // South pole vertex was added last. UINT southPoleIndex = (UINT)Positions->size() - 1; // Offset the indices to the index of the first vertex in the last ring. baseIndex = southPoleIndex - ringVertexCount; for (UINT i = 0; i < sliceCount; ++i) { Indices->push_back(southPoleIndex); Indices->push_back(baseIndex + i); Indices->push_back(baseIndex + i + 1); } }
void GeometryGenerator::CreateSphere(float radius, UINT sliceCount, UINT stackCount, MeshData& meshData) { meshData.Vertices.clear(); meshData.Indices.clear(); Vertex topVertex(0.0f, +radius, 0.0f, 0.0f, +1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); Vertex bottomVertex(0.0f, -radius, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); meshData.Vertices.push_back( topVertex ); float phiStep = XM_PI/stackCount; float thetaStep = 2.0f*XM_PI/sliceCount; for(UINT i = 1; i <= stackCount-1; ++i) { float phi = i*phiStep; for(UINT j = 0; j <= sliceCount; ++j) { float theta = j*thetaStep; Vertex v; v.Position.x = radius*sinf(phi)*cosf(theta); v.Position.y = radius*cosf(phi); v.Position.z = radius*sinf(phi)*sinf(theta); v.TangentU.x = -radius*sinf(phi)*sinf(theta); v.TangentU.y = 0.0f; v.TangentU.z = +radius*sinf(phi)*cosf(theta); v.TangentU = glm::normalize(v.TangentU); v.Normal = glm::normalize(v.Position); v.TexC.x = theta / (2.0f * glm::pi<float>()); v.TexC.y = phi / XM_PI; meshData.Vertices.push_back( v ); } } meshData.Vertices.push_back( bottomVertex ); for(UINT i = 1; i <= sliceCount; ++i) { meshData.Indices.push_back(0); meshData.Indices.push_back(i+1); meshData.Indices.push_back(i); } UINT baseIndex = 1; UINT ringVertexCount = sliceCount+1; for(UINT i = 0; i < stackCount-2; ++i) { for(UINT j = 0; j < sliceCount; ++j) { meshData.Indices.push_back(baseIndex + i*ringVertexCount + j); meshData.Indices.push_back(baseIndex + i*ringVertexCount + j+1); meshData.Indices.push_back(baseIndex + (i+1)*ringVertexCount + j); meshData.Indices.push_back(baseIndex + (i+1)*ringVertexCount + j); meshData.Indices.push_back(baseIndex + i*ringVertexCount + j+1); meshData.Indices.push_back(baseIndex + (i+1)*ringVertexCount + j+1); } } UINT southPoleIndex = (UINT)meshData.Vertices.size()-1; baseIndex = southPoleIndex - ringVertexCount; for(UINT i = 0; i < sliceCount; ++i) { meshData.Indices.push_back(southPoleIndex); meshData.Indices.push_back(baseIndex+i); meshData.Indices.push_back(baseIndex+i+1); } }
void Geometry::createSphere(float radius, UINT sliceCount, UINT stackCount, OGLMeshData& meshData) { // // Compute the vertices stating at the top pole and moving down the stacks. // // Poles: note that there will be texture coordinate distortion as there is // not a unique point on the texture map to assign to the pole when mapping // a rectangular texture onto a sphere. OGLVertex topVertex(0.0f, +radius, 0.0f, 0.0f, +1.0f, 0.0f, 0.0f, 0.0f); OGLVertex bottomVertex(0.0f, -radius, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f); meshData.VertexData.push_back(topVertex); float phiStep = XM_PI / stackCount; float thetaStep = 2.0f*XM_PI / sliceCount; // Compute vertices for each stack ring (do not count the poles as rings). for (UINT i = 1; i <= stackCount - 1; ++i) { float phi = i*phiStep; // Vertices of ring. for (UINT j = 0; j <= sliceCount; ++j) { float theta = j*thetaStep; OGLVertex v; // spherical to cartesian v.position.x = radius * sinf(phi) * cosf(theta); v.position.y = radius * cosf(phi); v.position.z = radius * sinf(phi) * sinf(theta); v.normal = v.position; glm::normalize(v.normal); v.texcoord.x = theta / XM_2PI; v.texcoord.y = phi / XM_PI; meshData.VertexData.push_back(v); } } // Compute indices for top stack. The top stack was written first to the vertex buffer // and connects the top pole to the first ring. // for (UINT i = 1; i <= sliceCount; ++i) { meshData.IndexData.push_back(0); meshData.IndexData.push_back(i + 1); meshData.IndexData.push_back(i); } // // Compute indices for inner stacks (not connected to poles). // // Offset the indices to the index of the first vertex in the first ring. // This is just skipping the top pole vertex. UINT baseIndex = 1; UINT ringVertexCount = sliceCount + 1; for (UINT i = 0; i < stackCount - 2; ++i) { for (UINT j = 0; j < sliceCount; ++j) { meshData.IndexData.push_back(baseIndex + i*ringVertexCount + j); meshData.IndexData.push_back(baseIndex + i*ringVertexCount + j + 1); meshData.IndexData.push_back(baseIndex + (i + 1)*ringVertexCount + j); meshData.IndexData.push_back(baseIndex + (i + 1)*ringVertexCount + j); meshData.IndexData.push_back(baseIndex + i*ringVertexCount + j + 1); meshData.IndexData.push_back(baseIndex + (i + 1)*ringVertexCount + j + 1); } } // // Compute indices for bottom stack. The bottom stack was written last to the vertex buffer // and connects the bottom pole to the bottom ring. // // South pole vertex was added last. UINT southPoleIndex = (UINT)meshData.VertexData.size() - 1; // Offset the indices to the index of the first vertex in the last ring. baseIndex = southPoleIndex - ringVertexCount; for (UINT i = 0; i < sliceCount; ++i) { meshData.IndexData.push_back(southPoleIndex); meshData.IndexData.push_back(baseIndex + i); meshData.IndexData.push_back(baseIndex + i + 1); } }
// // Create a sphere with the given radius and center point. 'numStacks' is // the number of layers along the Z axis and 'numSlices' is the number // of radial divisions. // STShape* CreateSphere( float radius, const STPoint3& center, unsigned int numSlices, unsigned int numStacks) { STShape* result = new STShape(); float PI_Stacks = float(M_PI) / float(numStacks); float PI2_Slices = 2.0f * float(M_PI) / float(numSlices); // // Add the interior vertices // for (unsigned int ii = 1; ii < numStacks; ++ii) { float phi = float(ii) * PI_Stacks; float cosPhi = cosf(phi); float sinPhi = sinf(phi); for(unsigned int jj = 0; jj < numSlices; ++jj) { float theta = float(jj) * PI2_Slices; STPoint3 position = center + STVector3(radius * cosf(theta) * sinPhi, radius * sinf(theta) * sinPhi, radius * cosPhi); result->AddVertex(STShape::Vertex( position, STVector3::Zero, STPoint2::Origin)); } } // // Add the pole vertices // STShape::Vertex topVertex( center + STVector3(0,0,radius), STVector3::Zero, STPoint2::Origin); STShape::Index topVertexIndex = result->AddVertex(topVertex); STShape::Vertex bottomVertex( center + STVector3(0,0,-radius), STVector3::Zero, STPoint2::Origin); STShape::Index bottomVertexIndex = result->AddVertex(bottomVertex); // // Add the top and bottom triangles (all triangles involving the pole vertices) // for( unsigned int ii = 0; ii < numSlices; ii++) { unsigned int iiPlus1 = (ii + 1) % numSlices; result->AddFace( STShape::Face(ii, iiPlus1, topVertexIndex)); result->AddFace(STShape::Face( iiPlus1 + (numStacks - 2) * numSlices, ii + (numStacks - 2) * numSlices, bottomVertexIndex)); } // // Add all the interior triangles // for(unsigned int ii = 0; ii < numStacks - 2; ++ii) { for(unsigned int jj = 0; jj < numSlices; ++jj) { unsigned int jjPlus1 = (jj + 1) % numSlices; result->AddFace(STShape::Face( (ii + 1)*numSlices + jj, (ii + 0)*numSlices + jjPlus1, (ii + 0)*numSlices + jj)); result->AddFace(STShape::Face( (ii + 1)*numSlices + jj, (ii + 1)*numSlices + jjPlus1, (ii + 0)*numSlices + jjPlus1)); } } result->GenerateNormals(); return result; }