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);
	}
}
Exemple #4
0
		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);
			}
		}
Exemple #5
0
    //
    // 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;
    }