コード例 #1
0
ファイル: Polyhedron.cpp プロジェクト: KeckCAVES/3DVisualizer
inline
Polyhedron<ScalarParam>*
Polyhedron<ScalarParam>::clip(
	const typename Polyhedron<ScalarParam>::Plane& plane) const
	{
	typedef Misc::HashTable<Card,void> IndexSet;
	typedef Misc::HashTable<Card,Card> IndexMapper;
	
	/* Find the indices of all half edges that intersect the plane: */
	IndexMapper indexMapper(101);
	Card nextIndex=0;
	Card numIntersectedEdges=0;
	Card intersectedEdgeIndex=0;
	IndexSet ioEdges(17);
	Card numEdges=edges.size();
	for(Card i=0;i<numEdges;++i)
		{
		/* Get the plane distance of start and end points of edge i: */
		Scalar d0=plane.calcDistance(edges[i].start);
		Scalar d1=plane.calcDistance(edges[edges[i].next].start);
		
		/* Classify the edge: */
		if(d0<Scalar(0)&&d1<Scalar(0))
			{
			/* Keep the edge: */
			indexMapper.setEntry(typename IndexMapper::Entry(i,nextIndex));
			++nextIndex;
			}
		else if(d0<Scalar(0)||d1<Scalar(0))
			{
			/* Keep the edge: */
			indexMapper.setEntry(typename IndexMapper::Entry(i,nextIndex));
			++nextIndex;
			
			if(d0<Scalar(0))
				{
				/* Mark the edge as intersected: */
				++numIntersectedEdges;
				intersectedEdgeIndex=i;
				}
			else
				{
				/* Mark the edge as the opposite of an intersected edge: */
				ioEdges.setEntry(typename IndexSet::Entry(i));
				}
			}
		}
	
	/* Remember the number of retained edges: */
	Card newNumEdges=nextIndex;
	
	/* Check for trivial cases: */
	if(newNumEdges==0)
		return new Polyhedron; // Return an empty polyhedron
	else if(numIntersectedEdges==0)
		return new Polyhedron(*this); // Return an identical copy of the polyhedron
	
	/* Sort the list of intersected edges to form a loop: */
	IndexMapper newFaceEdges(17);
	EdgeList newFace;
	while(newFace.size()<numIntersectedEdges)
		{
		Edge newEdge;
		
		/* Calculate the new edge's starting point: */
		const Point& p0=edges[intersectedEdgeIndex].start;
		Scalar d0=plane.calcDistance(p0);
		const Point& p1=edges[edges[intersectedEdgeIndex].next].start;
		Scalar d1=plane.calcDistance(p1);
		newEdge.start=Geometry::affineCombination(p0,p1,(Scalar(0)-d0)/(d1-d0));
		
		/* Find the next intersected edge around the same face as the current last edge: */
		Card edgeIndex;
		for(edgeIndex=edges[intersectedEdgeIndex].next;!ioEdges.isEntry(edgeIndex);edgeIndex=edges[edgeIndex].next)
			;
		newEdge.next=indexMapper.getEntry(edgeIndex).getDest();
		newEdge.opposite=newNumEdges+numIntersectedEdges+newFace.size();
		
		/* Store the index of the new face edge: */
		newFaceEdges.setEntry(IndexMapper::Entry(intersectedEdgeIndex,newFace.size()));
		
		/* Store the new face edge: */
		newFace.push_back(newEdge);
		
		/* Go to the next intersected face: */
		intersectedEdgeIndex=edges[edgeIndex].opposite;
		}
	
	/* Create the result polyhedron: */
	Polyhedron* result=new Polyhedron;
	
	/* Create the edges of the result polyhedron: */
	for(Card i=0;i<numEdges;++i)
		{
		/* Get the plane distance of start and end points of edge i: */
		Scalar d0=plane.calcDistance(edges[i].start);
		Scalar d1=plane.calcDistance(edges[edges[i].next].start);
		
		/* Classify the edge: */
		if(d0<Scalar(0)&&d1<Scalar(0))
			{
			/*****************************************************************
			If an edge is completely inside, its opposite edge must be as
			well, and its next edge must at least be partially inside.
			Therefore, indexMapper will contain the new indices for both
			edges.
			*****************************************************************/
			
			/* Keep the edge: */
			result->edges.push_back(Edge(edges[i].start,indexMapper.getEntry(edges[i].next).getDest(),indexMapper.getEntry(edges[i].opposite).getDest()));
			}
		else if(d0<Scalar(0))
			{
			/*****************************************************************
			If an edge's start point is inside, its opposite edge's index will
			be contained in indexMapper, and its next edge is a new face edge
			whose index can be calculated from newFaceEdges.
			*****************************************************************/
			
			/* Find the index of the next edge from the new face loop: */
			Card next=newNumEdges+newFaceEdges.getEntry(i).getDest();
			
			/* Retain the edge: */
			result->edges.push_back(Edge(edges[i].start,next,indexMapper.getEntry(edges[i].opposite).getDest()));
			}
		else if(d1<Scalar(0))
			{
			/*****************************************************************
			If an edge's end point is inside, its start point must be
			calculated by clipping, and its next edge and opposite edge will
			both be contained in indexMapper.
			*****************************************************************/
			
			/* Calculate the new start point: */
			Point newStart=Geometry::affineCombination(edges[edges[i].next].start,edges[i].start,(Scalar(0)-d1)/(d0-d1));
			
			/* Retain the clipped edge: */
			result->edges.push_back(Edge(newStart,indexMapper.getEntry(edges[i].next).getDest(),indexMapper.getEntry(edges[i].opposite).getDest()));
			}
		}
	
	/* Add the closing edges for all clipped faces to the polyhedron: */
	for(typename EdgeList::const_iterator nfIt=newFace.begin();nfIt!=newFace.end();++nfIt)
		result->edges.push_back(*nfIt);
	
	/* Add the edges of the closing face to the polyhedron: */
	for(Card i=0;i<newFace.size();++i)
		{
		Edge newEdge;
		newEdge.start=newFace[(i+1)%newFace.size()].start;
		newEdge.next=newNumEdges+numIntersectedEdges+(i+newFace.size()-1)%newFace.size();
		newEdge.opposite=newNumEdges+i;
		result->edges.push_back(newEdge);
		}
	
	// DEBUGGING
	// result->check();
	
	return result;
	}
コード例 #2
0
ファイル: Mesh.cpp プロジェクト: GigAnon/NazaraEngine
	SubMesh* Mesh::BuildSubMesh(const Primitive& primitive, const MeshParams& params)
	{
		#if NAZARA_UTILITY_SAFE
		if (!m_impl)
		{
			NazaraError("Mesh not created");
			return nullptr;
		}

		if (m_impl->animationType != AnimationType_Static)
		{
			NazaraError("Mesh must be static");
			return nullptr;
		}

		if (!params.IsValid())
		{
			NazaraError("Parameters must be valid");
			return nullptr;
		}
		#endif

		Boxf aabb;
		IndexBufferRef indexBuffer;
		VertexBufferRef vertexBuffer;

		Matrix4f matrix(primitive.matrix);
		matrix.ApplyScale(params.scale);

		VertexDeclaration* declaration = VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent);

		switch (primitive.type)
		{
			case PrimitiveType_Box:
			{
				unsigned int indexCount;
				unsigned int vertexCount;
				ComputeBoxIndexVertexCount(primitive.box.subdivision, &indexCount, &vertexCount);

				indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), indexCount, params.storage, BufferUsage_Static);
				vertexBuffer = VertexBuffer::New(declaration, vertexCount, params.storage, BufferUsage_Static);

				VertexMapper vertexMapper(vertexBuffer, BufferAccess_WriteOnly);

				VertexPointers pointers;
				pointers.normalPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
				pointers.positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
				pointers.tangentPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Tangent);
				pointers.uvPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);

				IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
				GenerateBox(primitive.box.lengths, primitive.box.subdivision, matrix, primitive.textureCoords, pointers, indexMapper.begin(), &aabb);
				break;
			}

			case PrimitiveType_Cone:
			{
				unsigned int indexCount;
				unsigned int vertexCount;
				ComputeConeIndexVertexCount(primitive.cone.subdivision, &indexCount, &vertexCount);

				indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), indexCount, params.storage, BufferUsage_Static);
				vertexBuffer = VertexBuffer::New(declaration, vertexCount, params.storage, BufferUsage_Static);

				VertexMapper vertexMapper(vertexBuffer, BufferAccess_WriteOnly);

				VertexPointers pointers;
				pointers.normalPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
				pointers.positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
				pointers.tangentPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Tangent);
				pointers.uvPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);

				IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
				GenerateCone(primitive.cone.length, primitive.cone.radius, primitive.cone.subdivision, matrix, primitive.textureCoords, pointers, indexMapper.begin(), &aabb);
				break;
			}

			case PrimitiveType_Plane:
			{
				unsigned int indexCount;
				unsigned int vertexCount;
				ComputePlaneIndexVertexCount(primitive.plane.subdivision, &indexCount, &vertexCount);

				indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), indexCount, params.storage, BufferUsage_Static);
				vertexBuffer = VertexBuffer::New(declaration, vertexCount, params.storage, BufferUsage_Static);

				VertexMapper vertexMapper(vertexBuffer, BufferAccess_WriteOnly);

				VertexPointers pointers;
				pointers.normalPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
				pointers.positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
				pointers.tangentPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Tangent);
				pointers.uvPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);

				IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
				GeneratePlane(primitive.plane.subdivision, primitive.plane.size, matrix, primitive.textureCoords, pointers, indexMapper.begin(), &aabb);
				break;
			}

			case PrimitiveType_Sphere:
			{
				switch (primitive.sphere.type)
				{
					case SphereType_Cubic:
					{
						unsigned int indexCount;
						unsigned int vertexCount;
						ComputeCubicSphereIndexVertexCount(primitive.sphere.cubic.subdivision, &indexCount, &vertexCount);

						indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), indexCount, params.storage, BufferUsage_Static);
						vertexBuffer = VertexBuffer::New(declaration, vertexCount, params.storage, BufferUsage_Static);

						VertexMapper vertexMapper(vertexBuffer, BufferAccess_ReadWrite);

						VertexPointers pointers;
						pointers.normalPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
						pointers.positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
						pointers.tangentPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Tangent);
						pointers.uvPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);

						IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
						GenerateCubicSphere(primitive.sphere.size, primitive.sphere.cubic.subdivision, matrix, primitive.textureCoords, pointers, indexMapper.begin(), &aabb);
						break;
					}

					case SphereType_Ico:
					{
						unsigned int indexCount;
						unsigned int vertexCount;
						ComputeIcoSphereIndexVertexCount(primitive.sphere.ico.recursionLevel, &indexCount, &vertexCount);

						indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), indexCount, params.storage, BufferUsage_Static);
						vertexBuffer = VertexBuffer::New(declaration, vertexCount, params.storage, BufferUsage_Static);

						VertexMapper vertexMapper(vertexBuffer, BufferAccess_WriteOnly);

						VertexPointers pointers;
						pointers.normalPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
						pointers.positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
						pointers.tangentPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Tangent);
						pointers.uvPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);

						IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
						GenerateIcoSphere(primitive.sphere.size, primitive.sphere.ico.recursionLevel, matrix, primitive.textureCoords, pointers, indexMapper.begin(), &aabb);
						break;
					}

					case SphereType_UV:
					{
						unsigned int indexCount;
						unsigned int vertexCount;
						ComputeUvSphereIndexVertexCount(primitive.sphere.uv.sliceCount, primitive.sphere.uv.stackCount, &indexCount, &vertexCount);

						indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), indexCount, params.storage, BufferUsage_Static);
						vertexBuffer = VertexBuffer::New(declaration, vertexCount, params.storage, BufferUsage_Static);

						VertexMapper vertexMapper(vertexBuffer, BufferAccess_WriteOnly);

						VertexPointers pointers;
						pointers.normalPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
						pointers.positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
						pointers.tangentPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Tangent);
						pointers.uvPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);

						IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
						GenerateUvSphere(primitive.sphere.size, primitive.sphere.uv.sliceCount, primitive.sphere.uv.stackCount, matrix, primitive.textureCoords, pointers, indexMapper.begin(), &aabb);
						break;
					}
				}
				break;
			}
		}

		StaticMeshRef subMesh = StaticMesh::New(this);
		if (!subMesh->Create(vertexBuffer))
		{
			NazaraError("Failed to create StaticMesh");
			return nullptr;
		}

		if (params.optimizeIndexBuffers)
			indexBuffer->Optimize();

		subMesh->SetAABB(aabb);
		subMesh->SetIndexBuffer(indexBuffer);

		AddSubMesh(subMesh);
		return subMesh;
	}
コード例 #3
0
ファイル: Mesh.cpp プロジェクト: BigFax/NazaraEngine
NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams& params)
{
	#if NAZARA_UTILITY_SAFE
	if (!m_impl)
	{
		NazaraError("Mesh not created");
		return nullptr;
	}

	if (m_impl->animationType != nzAnimationType_Static)
	{
		NazaraError("Mesh must be static");
		return nullptr;
	}

	if (!params.IsValid())
	{
		NazaraError("Parameters must be valid");
		return nullptr;
	}
	#endif

	NzBoxf aabb;
	std::unique_ptr<NzIndexBuffer> indexBuffer;
	std::unique_ptr<NzVertexBuffer> vertexBuffer;

	NzMatrix4f matrix(primitive.matrix);
	matrix.ApplyScale(params.scale);

	NzVertexDeclaration* declaration = NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent);

	switch (primitive.type)
	{
		case nzPrimitiveType_Box:
		{
			unsigned int indexCount;
			unsigned int vertexCount;
			NzComputeBoxIndexVertexCount(primitive.box.subdivision, &indexCount, &vertexCount);

			indexBuffer.reset(new NzIndexBuffer(vertexCount > std::numeric_limits<nzUInt16>::max(), indexCount, params.storage, nzBufferUsage_Static));
			indexBuffer->SetPersistent(false);

			vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
			vertexBuffer->SetPersistent(false);

			NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
			NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_WriteOnly);

			NzGenerateBox(primitive.box.lengths, primitive.box.subdivision, matrix, primitive.textureCoords, static_cast<NzMeshVertex*>(vertexMapper.GetPointer()), indexMapper.begin(), &aabb);
			break;
		}

		case nzPrimitiveType_Cone:
		{
			unsigned int indexCount;
			unsigned int vertexCount;
			NzComputeConeIndexVertexCount(primitive.cone.subdivision, &indexCount, &vertexCount);

			indexBuffer.reset(new NzIndexBuffer(vertexCount > std::numeric_limits<nzUInt16>::max(), indexCount, params.storage, nzBufferUsage_Static));
			indexBuffer->SetPersistent(false);

			vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
			vertexBuffer->SetPersistent(false);

			NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
			NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_WriteOnly);

			NzGenerateCone(primitive.cone.length, primitive.cone.radius, primitive.cone.subdivision, matrix, primitive.textureCoords, static_cast<NzMeshVertex*>(vertexMapper.GetPointer()), indexMapper.begin(), &aabb);
			break;
		}

		case nzPrimitiveType_Plane:
		{
			unsigned int indexCount;
			unsigned int vertexCount;
			NzComputePlaneIndexVertexCount(primitive.plane.subdivision, &indexCount, &vertexCount);

			indexBuffer.reset(new NzIndexBuffer(vertexCount > std::numeric_limits<nzUInt16>::max(), indexCount, params.storage, nzBufferUsage_Static));
			indexBuffer->SetPersistent(false);

			vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
			vertexBuffer->SetPersistent(false);

			NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
			NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_WriteOnly);

			NzGeneratePlane(primitive.plane.subdivision, primitive.plane.size, matrix, primitive.textureCoords, static_cast<NzMeshVertex*>(vertexMapper.GetPointer()), indexMapper.begin(), &aabb);
			break;
		}

		case nzPrimitiveType_Sphere:
		{
			switch (primitive.sphere.type)
			{
				case nzSphereType_Cubic:
				{
					unsigned int indexCount;
					unsigned int vertexCount;
					NzComputeCubicSphereIndexVertexCount(primitive.sphere.cubic.subdivision, &indexCount, &vertexCount);

					indexBuffer.reset(new NzIndexBuffer(vertexCount > std::numeric_limits<nzUInt16>::max(), indexCount, params.storage, nzBufferUsage_Static));
					indexBuffer->SetPersistent(false);

					vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
					vertexBuffer->SetPersistent(false);

					NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
					NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_WriteOnly);

					NzGenerateCubicSphere(primitive.sphere.size, primitive.sphere.cubic.subdivision, matrix, primitive.textureCoords, static_cast<NzMeshVertex*>(vertexMapper.GetPointer()), indexMapper.begin(), &aabb);
					break;
				}

				case nzSphereType_Ico:
				{
					unsigned int indexCount;
					unsigned int vertexCount;
					NzComputeIcoSphereIndexVertexCount(primitive.sphere.ico.recursionLevel, &indexCount, &vertexCount);

					indexBuffer.reset(new NzIndexBuffer(vertexCount > std::numeric_limits<nzUInt16>::max(), indexCount, params.storage, nzBufferUsage_Static));
					indexBuffer->SetPersistent(false);

					vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
					vertexBuffer->SetPersistent(false);

					NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
					NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_WriteOnly);

					NzGenerateIcoSphere(primitive.sphere.size, primitive.sphere.ico.recursionLevel, matrix, primitive.textureCoords, static_cast<NzMeshVertex*>(vertexMapper.GetPointer()), indexMapper.begin(), &aabb);
					break;
				}

				case nzSphereType_UV:
				{
					unsigned int indexCount;
					unsigned int vertexCount;
					NzComputeUvSphereIndexVertexCount(primitive.sphere.uv.sliceCount, primitive.sphere.uv.stackCount, &indexCount, &vertexCount);

					indexBuffer.reset(new NzIndexBuffer(vertexCount > std::numeric_limits<nzUInt16>::max(), indexCount, params.storage, nzBufferUsage_Static));
					indexBuffer->SetPersistent(false);

					vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static));
					vertexBuffer->SetPersistent(false);

					NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly);
					NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_WriteOnly);

					NzGenerateUvSphere(primitive.sphere.size, primitive.sphere.uv.sliceCount, primitive.sphere.uv.stackCount, matrix, primitive.textureCoords, static_cast<NzMeshVertex*>(vertexMapper.GetPointer()), indexMapper.begin(), &aabb);
					break;
				}
			}
			break;
		}
	}

	std::unique_ptr<NzStaticMesh> subMesh(new NzStaticMesh(this));
	if (!subMesh->Create(vertexBuffer.get()))
	{
		NazaraError("Failed to create StaticMesh");
		return nullptr;
	}
	vertexBuffer.release();

	if (params.optimizeIndexBuffers)
		indexBuffer->Optimize();

	subMesh->SetIndexBuffer(indexBuffer.get());
	indexBuffer.release();

	subMesh->SetAABB(aabb);
	AddSubMesh(subMesh.get());

	return subMesh.release();
}