Vertices now know whether they are on the edge of an indexed surface patch. This allows improved smoothing.
This commit is contained in:
		| @@ -53,7 +53,7 @@ namespace PolyVox | |||||||
| 	   void clear(void); | 	   void clear(void); | ||||||
| 	   const bool isEmpty(void) const; | 	   const bool isEmpty(void) const; | ||||||
|  |  | ||||||
| 	   void smoothPositions(float fAmount, uint8_t uNoRequiredUses = 0); | 	   void smoothPositions(float fAmount, bool bIncludeEdgeVertices = false); | ||||||
| 	   void sumNearbyNormals(bool bNormaliseResult = true); | 	   void sumNearbyNormals(bool bNormaliseResult = true); | ||||||
|  |  | ||||||
| 	   POLYVOX_SHARED_PTR<IndexedSurfacePatch> extractSubset(std::set<uint8_t> setMaterials); | 	   POLYVOX_SHARED_PTR<IndexedSurfacePatch> extractSubset(std::set<uint8_t> setMaterials); | ||||||
|   | |||||||
| @@ -104,7 +104,7 @@ namespace PolyVox | |||||||
| 		//The surface patch we are currently filling. | 		//The surface patch we are currently filling. | ||||||
| 		IndexedSurfacePatch* m_ispCurrent; | 		IndexedSurfacePatch* m_ispCurrent; | ||||||
|  |  | ||||||
| 		//Information about the region we a re currently processing | 		//Information about the region we are currently processing | ||||||
| 		Region m_regInputCropped; | 		Region m_regInputCropped; | ||||||
| 		Region m_regInputUncropped; | 		Region m_regInputUncropped; | ||||||
| 		Region m_regVolumeCropped; | 		Region m_regVolumeCropped; | ||||||
|   | |||||||
| @@ -38,6 +38,9 @@ namespace PolyVox | |||||||
| 		const Vector3DFloat& getNormal(void) const; | 		const Vector3DFloat& getNormal(void) const; | ||||||
| 		const Vector3DFloat& getPosition(void) const;	 | 		const Vector3DFloat& getPosition(void) const;	 | ||||||
|  |  | ||||||
|  | 		bool isEdgeVertex(void) const; | ||||||
|  | 	 | ||||||
|  | 		void setEdgeVertex(bool isEdgeVertex); | ||||||
| 		void setMaterial(float materialToSet); | 		void setMaterial(float materialToSet); | ||||||
| 		void setNormal(const Vector3DFloat& normalToSet); | 		void setNormal(const Vector3DFloat& normalToSet); | ||||||
| 		void setPosition(const Vector3DFloat& positionToSet); | 		void setPosition(const Vector3DFloat& positionToSet); | ||||||
| @@ -46,6 +49,7 @@ namespace PolyVox | |||||||
| 		Vector3DFloat position; | 		Vector3DFloat position; | ||||||
| 		Vector3DFloat normal; | 		Vector3DFloat normal; | ||||||
| 		float material; | 		float material; | ||||||
|  | 		bool m_bIsEdgeVertex; | ||||||
| 			 | 			 | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -121,20 +121,16 @@ namespace PolyVox | |||||||
| 	/// normals must hve been set to something sensible before this functions is called. | 	/// normals must hve been set to something sensible before this functions is called. | ||||||
| 	/// \param fAmount A factor controlling how much the vertices move by. Find a good | 	/// \param fAmount A factor controlling how much the vertices move by. Find a good | ||||||
| 	/// value by experimentation, starting with something small such as 0.1f. | 	/// value by experimentation, starting with something small such as 0.1f. | ||||||
| 	/// \param uNoRequiredUses The minumum number of triangles which have to be using  | 	/// \param bIncludeEdgeVertices Indicates whether vertices on the edge of an | ||||||
| 	/// a vertex for that vertex to be modified. This is can be used to help prevent | 	/// IndexedSurfacePatch should be smoothed. This can cause dicontinuities between | ||||||
| 	/// the operation being carried out on edge vertices, which could cause discontinuities. | 	/// neighbouring patches. | ||||||
| 	//////////////////////////////////////////////////////////////////////////////// | 	//////////////////////////////////////////////////////////////////////////////// | ||||||
| 	void IndexedSurfacePatch::smoothPositions(float fAmount, uint8_t uNoRequiredUses) | 	void IndexedSurfacePatch::smoothPositions(float fAmount, bool bIncludeEdgeVertices) | ||||||
| 	{ | 	{ | ||||||
| 		if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... | 		if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... | ||||||
| 		{ | 		{ | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		//Used to count how many times a given vertex is used. This helps determine if it's on an edge. |  | ||||||
| 		std::vector<uint32_t> useCount(m_vecVertices.size()); |  | ||||||
| 		//Initialise all counts to zero. Should be ok as the vector should store all elements contiguously. |  | ||||||
| 		memset(&useCount[0], 0, useCount.size() * sizeof(uint32_t)); |  | ||||||
|  |  | ||||||
| 		//This will hold the new positions, and is initialised with the current positions. | 		//This will hold the new positions, and is initialised with the current positions. | ||||||
| 		std::vector<Vector3DFloat> newPositions(m_vecVertices.size()); | 		std::vector<Vector3DFloat> newPositions(m_vecVertices.size()); | ||||||
| @@ -149,15 +145,12 @@ namespace PolyVox | |||||||
| 			//Get the vertex data for the triangle | 			//Get the vertex data for the triangle | ||||||
| 			SurfaceVertex& v0 = m_vecVertices[*iterIndex]; | 			SurfaceVertex& v0 = m_vecVertices[*iterIndex]; | ||||||
| 			Vector3DFloat& v0New = newPositions[*iterIndex]; | 			Vector3DFloat& v0New = newPositions[*iterIndex]; | ||||||
| 			useCount[*iterIndex]++; |  | ||||||
| 			iterIndex++; | 			iterIndex++; | ||||||
| 			SurfaceVertex& v1 = m_vecVertices[*iterIndex]; | 			SurfaceVertex& v1 = m_vecVertices[*iterIndex]; | ||||||
| 			Vector3DFloat& v1New = newPositions[*iterIndex]; | 			Vector3DFloat& v1New = newPositions[*iterIndex]; | ||||||
| 			useCount[*iterIndex]++; |  | ||||||
| 			iterIndex++; | 			iterIndex++; | ||||||
| 			SurfaceVertex& v2 = m_vecVertices[*iterIndex]; | 			SurfaceVertex& v2 = m_vecVertices[*iterIndex]; | ||||||
| 			Vector3DFloat& v2New = newPositions[*iterIndex]; | 			Vector3DFloat& v2New = newPositions[*iterIndex]; | ||||||
| 			useCount[*iterIndex]++; |  | ||||||
| 			iterIndex++; | 			iterIndex++; | ||||||
|  |  | ||||||
| 			//Find the midpoint | 			//Find the midpoint | ||||||
| @@ -193,8 +186,7 @@ namespace PolyVox | |||||||
| 		//Update with the new positions | 		//Update with the new positions | ||||||
| 		for(uint32_t uIndex = 0; uIndex < newPositions.size(); uIndex++) | 		for(uint32_t uIndex = 0; uIndex < newPositions.size(); uIndex++) | ||||||
| 		{ | 		{ | ||||||
| 			//Check we have enough uses.  | 			if((bIncludeEdgeVertices) || (m_vecVertices[uIndex].isEdgeVertex() == false)) | ||||||
| 			if(useCount[uIndex] >= uNoRequiredUses) |  | ||||||
| 			{ | 			{ | ||||||
| 				m_vecVertices[uIndex].setPosition(newPositions[uIndex]); | 				m_vecVertices[uIndex].setPosition(newPositions[uIndex]); | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -554,17 +554,21 @@ namespace PolyVox | |||||||
|  |  | ||||||
| 	void SurfaceExtractor::generateVerticesForSlice() | 	void SurfaceExtractor::generateVerticesForSlice() | ||||||
| 	{ | 	{ | ||||||
|  | 		uint16_t uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); | ||||||
|  | 		const uint16_t uZRegSpace = uZVolSpace - m_regInputCropped.getLowerCorner().getZ(); | ||||||
|  | 		bool isZEdge = ((uZVolSpace == m_regInputCropped.getLowerCorner().getZ()) || (uZVolSpace == m_regInputCropped.getUpperCorner().getZ())); | ||||||
|  |  | ||||||
| 		//Iterate over each cell in the region | 		//Iterate over each cell in the region | ||||||
| 		for(uint16_t uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); uYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); uYVolSpace += m_uStepSize) | 		for(uint16_t uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); uYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); uYVolSpace += m_uStepSize) | ||||||
| 		{ | 		{ | ||||||
|  | 			const uint16_t uYRegSpace = uYVolSpace - m_regInputCropped.getLowerCorner().getY(); | ||||||
|  | 			bool isYEdge = ((uYVolSpace == m_regInputCropped.getLowerCorner().getY()) || (uYVolSpace == m_regInputCropped.getUpperCorner().getY())); | ||||||
|  |  | ||||||
| 			for(uint16_t uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); uXVolSpace += m_uStepSize) | 			for(uint16_t uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); uXVolSpace += m_uStepSize) | ||||||
| 			{		 | 			{		 | ||||||
| 				uint16_t uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); |  | ||||||
|  |  | ||||||
| 				//Current position | 				//Current position | ||||||
| 				const uint16_t uXRegSpace = uXVolSpace - m_regInputCropped.getLowerCorner().getX(); | 				const uint16_t uXRegSpace = uXVolSpace - m_regInputCropped.getLowerCorner().getX(); | ||||||
| 				const uint16_t uYRegSpace = uYVolSpace - m_regInputCropped.getLowerCorner().getY(); | 				bool isXEdge = ((uXVolSpace == m_regInputCropped.getLowerCorner().getX()) || (uXVolSpace == m_regInputCropped.getUpperCorner().getX())); | ||||||
| 				const uint16_t uZRegSpace = uZVolSpace - m_regInputCropped.getLowerCorner().getZ(); |  | ||||||
|  |  | ||||||
| 				//Determine the index into the edge table which tells us which vertices are inside of the surface | 				//Determine the index into the edge table which tells us which vertices are inside of the surface | ||||||
| 				uint8_t iCubeIndex = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace)]; | 				uint8_t iCubeIndex = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace)]; | ||||||
| @@ -575,6 +579,9 @@ namespace PolyVox | |||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				//Check whether the generated vertex will lie on the edge of the region | ||||||
|  |  | ||||||
|  |  | ||||||
| 				m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace); | 				m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace); | ||||||
| 				const uint8_t v000 = m_sampVolume.getSubSampledVoxel(m_uLodLevel); | 				const uint8_t v000 = m_sampVolume.getSubSampledVoxel(m_uLodLevel); | ||||||
|  |  | ||||||
| @@ -587,6 +594,7 @@ namespace PolyVox | |||||||
| 					const Vector3DFloat v3dNormal(v000 > v100 ? 1.0f : -1.0f,0.0,0.0); | 					const Vector3DFloat v3dNormal(v000 > v100 ? 1.0f : -1.0f,0.0,0.0); | ||||||
| 					const uint8_t uMaterial = v000 | v100; //Because one of these is 0, the or operation takes the max. | 					const uint8_t uMaterial = v000 | v100; //Because one of these is 0, the or operation takes the max. | ||||||
| 					SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); | 					SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); | ||||||
|  | 					surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge); | ||||||
| 					uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); | 					uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); | ||||||
| 					m_pCurrentVertexIndicesX[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; | 					m_pCurrentVertexIndicesX[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; | ||||||
| 				} | 				} | ||||||
| @@ -598,6 +606,7 @@ namespace PolyVox | |||||||
| 					const Vector3DFloat v3dNormal(0.0,v000 > v010 ? 1.0f : -1.0f,0.0); | 					const Vector3DFloat v3dNormal(0.0,v000 > v010 ? 1.0f : -1.0f,0.0); | ||||||
| 					const uint8_t uMaterial = v000 | v010; //Because one of these is 0, the or operation takes the max. | 					const uint8_t uMaterial = v000 | v010; //Because one of these is 0, the or operation takes the max. | ||||||
| 					SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); | 					SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); | ||||||
|  | 					surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge); | ||||||
| 					uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); | 					uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); | ||||||
| 					m_pCurrentVertexIndicesY[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; | 					m_pCurrentVertexIndicesY[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; | ||||||
| 				} | 				} | ||||||
| @@ -608,7 +617,8 @@ namespace PolyVox | |||||||
| 					const Vector3DFloat v3dPosition(uXVolSpace - m_regInputCropped.getLowerCorner().getX(), uYVolSpace - m_regInputCropped.getLowerCorner().getY(), uZVolSpace - m_regInputCropped.getLowerCorner().getZ() + 0.5f * m_uStepSize); | 					const Vector3DFloat v3dPosition(uXVolSpace - m_regInputCropped.getLowerCorner().getX(), uYVolSpace - m_regInputCropped.getLowerCorner().getY(), uZVolSpace - m_regInputCropped.getLowerCorner().getZ() + 0.5f * m_uStepSize); | ||||||
| 					const Vector3DFloat v3dNormal(0.0,0.0,v000 > v001 ? 1.0f : -1.0f); | 					const Vector3DFloat v3dNormal(0.0,0.0,v000 > v001 ? 1.0f : -1.0f); | ||||||
| 					const uint8_t uMaterial = v000 | v001; //Because one of these is 0, the or operation takes the max. | 					const uint8_t uMaterial = v000 | v001; //Because one of these is 0, the or operation takes the max. | ||||||
| 					const SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); | 					SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); | ||||||
|  | 					surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge); | ||||||
| 					uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); | 					uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); | ||||||
| 					m_pCurrentVertexIndicesZ[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; | 					m_pCurrentVertexIndicesZ[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -58,6 +58,16 @@ namespace PolyVox | |||||||
| 		return position; | 		return position; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	bool SurfaceVertex::isEdgeVertex(void) const | ||||||
|  | 	{ | ||||||
|  | 		return m_bIsEdgeVertex; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void SurfaceVertex::setEdgeVertex(bool isEdgeVertex) | ||||||
|  | 	{ | ||||||
|  | 		m_bIsEdgeVertex = isEdgeVertex; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	void SurfaceVertex::setMaterial(float materialToSet) | 	void SurfaceVertex::setMaterial(float materialToSet) | ||||||
| 	{ | 	{ | ||||||
| 		material = materialToSet; | 		material = materialToSet; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user