Renamed ImprovedCubicSurfaceExtractor back to CubicSurfaceExtractor.
This commit is contained in:
		| @@ -33,8 +33,6 @@ SET(CORE_INC_FILES | ||||
| 	include/PolyVoxCore/Filters.inl | ||||
| 	include/PolyVoxCore/GradientEstimators.h | ||||
| 	include/PolyVoxCore/GradientEstimators.inl | ||||
| 	include/PolyVoxCore/ImprovedCubicSurfaceExtractor.h | ||||
| 	include/PolyVoxCore/ImprovedCubicSurfaceExtractor.inl | ||||
| 	include/PolyVoxCore/LargeVolume.h | ||||
| 	include/PolyVoxCore/LargeVolume.inl | ||||
| 	include/PolyVoxCore/LargeVolumeSampler.inl | ||||
|   | ||||
| @@ -32,26 +32,43 @@ freely, subject to the following restrictions: | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	struct IndexAndMaterial | ||||
| 	{ | ||||
| 		int32_t iIndex    : 24; | ||||
| 		int32_t uMaterial : 8; | ||||
| 	}; | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	class CubicSurfaceExtractor | ||||
| 	{ | ||||
| 		struct IndexAndMaterial | ||||
| 		{ | ||||
| 			int32_t iIndex; | ||||
| 			int32_t uMaterial; //Should actually use the material type here, but this is ok for now. | ||||
| 		}; | ||||
|  | ||||
| 		enum FaceNames | ||||
| 		{ | ||||
| 			PositiveX, | ||||
| 			PositiveY, | ||||
| 			PositiveZ, | ||||
| 			NegativeX, | ||||
| 			NegativeY, | ||||
| 			NegativeZ, | ||||
| 			NoOfFaces | ||||
| 		}; | ||||
|  | ||||
| 		struct Quad | ||||
| 		{ | ||||
| 			uint32_t vertices[4]; | ||||
| 		}; | ||||
|  | ||||
| 	public: | ||||
| 		CubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result); | ||||
| 		CubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads = true); | ||||
|  | ||||
| 		void execute(); | ||||
|  | ||||
| 		int32_t addVertex(float fX, float fY, float fZ, uint8_t uMaterial, Array<3, IndexAndMaterial>& existingVertices); | ||||
| 		void execute();		 | ||||
|  | ||||
| 	private: | ||||
| 		int32_t addVertex(float fX, float fY, float fZ, uint8_t uMaterial, Array<3, IndexAndMaterial>& existingVertices); | ||||
| 		bool performQuadMerging(std::list<Quad>& quads); | ||||
| 		bool mergeQuads(Quad& q1, Quad& q2); | ||||
|  | ||||
| 		//The volume data and a sampler to access it. | ||||
| 		VolumeType<VoxelType>* m_volData; | ||||
| 		typename VolumeType<VoxelType>::Sampler m_sampVolume; | ||||
|  | ||||
| 		//Information about the region we are currently processing | ||||
| 		Region m_regSizeInVoxels; | ||||
| @@ -59,14 +76,22 @@ namespace PolyVox | ||||
| 		//The surface patch we are currently filling. | ||||
| 		SurfaceMesh<PositionMaterial>* m_meshCurrent; | ||||
|  | ||||
| 		//Array<4, IndexAndMaterial> m_vertices; | ||||
| 		//Used to avoid creating duplicate vertices. | ||||
| 		Array<3, IndexAndMaterial> m_previousSliceVertices; | ||||
| 		Array<3, IndexAndMaterial> m_currentSliceVertices; | ||||
|  | ||||
| 		//During extraction we create a number of different lists of quads. All the  | ||||
| 		//quads in a given list are in the same plane and facing in the same direction. | ||||
| 		std::vector< std::list<Quad> > m_vecQuads[NoOfFaces]; | ||||
|  | ||||
| 		//Controls whether quad merging should be performed. This might be undesirable | ||||
| 		//is the user needs per-vertex attributes, or to perform per vertex lighting. | ||||
| 		bool m_bMergeQuads; | ||||
|  | ||||
| 		//Although we try to avoid creating multiple vertices at the same location, sometimes this is unavoidable | ||||
| 		//if they have different materials. For example, four different materials next to each other would mean | ||||
| 		//four quads (though more triangles) sharing the vertex. As far as I can tell, four is the worst case scenario. | ||||
| 		static const uint32_t MaxQuadsSharingVertex; | ||||
| 		static const uint32_t MaxQuadsSharingVertex;		 | ||||
| 	}; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -33,11 +33,11 @@ namespace PolyVox | ||||
| 	const uint32_t CubicSurfaceExtractor<VolumeType, VoxelType>::MaxQuadsSharingVertex = 4; | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	CubicSurfaceExtractor<VolumeType, VoxelType>::CubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result) | ||||
| 	CubicSurfaceExtractor<VolumeType, VoxelType>::CubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads) | ||||
| 		:m_volData(volData) | ||||
| 		,m_sampVolume(volData) | ||||
| 		,m_regSizeInVoxels(region) | ||||
| 		,m_meshCurrent(result) | ||||
| 		,m_bMergeQuads(bMergeQuads) | ||||
| 	{ | ||||
| 		m_meshCurrent->clear(); | ||||
| 	} | ||||
| @@ -53,60 +53,81 @@ namespace PolyVox | ||||
| 		m_currentSliceVertices.resize(arraySize); | ||||
| 		memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); | ||||
| 		memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); | ||||
| 		 | ||||
|  | ||||
| 		uint32_t uRegionWidth  = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1; | ||||
| 		uint32_t uRegionHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1; | ||||
| 		uint32_t uRegionDepth  = m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 1; | ||||
|  | ||||
| 		m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2); | ||||
| 		m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2); | ||||
|  | ||||
| 		m_vecQuads[NegativeY].resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2); | ||||
| 		m_vecQuads[PositiveY].resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2); | ||||
|  | ||||
| 		m_vecQuads[NegativeZ].resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2); | ||||
| 		m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2); | ||||
|  | ||||
| 		VolumeType<VoxelType>::Sampler volumeSampler(m_volData);	 | ||||
| 		Quad quad; | ||||
| 		 | ||||
| 		for(int32_t z = m_regSizeInVoxels.getLowerCorner().getZ(); z <= m_regSizeInVoxels.getUpperCorner().getZ() + 1; z++) | ||||
| 		{ | ||||
| 			uint32_t regZ = z - m_regSizeInVoxels.getLowerCorner().getZ(); | ||||
| 			bool finalZ = (z == m_regSizeInVoxels.getUpperCorner().getZ() + 1); | ||||
|  | ||||
| 			for(int32_t y = m_regSizeInVoxels.getLowerCorner().getY(); y <= m_regSizeInVoxels.getUpperCorner().getY() + 1; y++) | ||||
| 			{ | ||||
| 				uint32_t regY = y - m_regSizeInVoxels.getLowerCorner().getY(); | ||||
| 				bool finalY = (y == m_regSizeInVoxels.getUpperCorner().getY() + 1); | ||||
|  | ||||
| 				for(int32_t x = m_regSizeInVoxels.getLowerCorner().getX(); x <= m_regSizeInVoxels.getUpperCorner().getX() + 1; x++) | ||||
| 				{ | ||||
| 					// these are always positive anyway | ||||
| 					uint32_t regX = x - m_regSizeInVoxels.getLowerCorner().getX(); | ||||
| 					uint32_t regY = y - m_regSizeInVoxels.getLowerCorner().getY(); | ||||
| 					uint32_t regZ = z - m_regSizeInVoxels.getLowerCorner().getZ(); | ||||
| 					bool finalX = (x == m_regSizeInVoxels.getUpperCorner().getX() + 1);					 | ||||
|  | ||||
| 					bool finalX = (x == m_regSizeInVoxels.getUpperCorner().getX() + 1); | ||||
| 					bool finalY = (y == m_regSizeInVoxels.getUpperCorner().getY() + 1); | ||||
| 					bool finalZ = (z == m_regSizeInVoxels.getUpperCorner().getZ() + 1); | ||||
| 					volumeSampler.setPosition(x,y,z); | ||||
|  | ||||
| 					VoxelType currentVoxel = m_volData->getVoxelAt(x,y,z); | ||||
| 					VoxelType currentVoxel = volumeSampler.getVoxel(); | ||||
| 					bool currentVoxelIsSolid = currentVoxel.getDensity() >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					VoxelType negXVoxel = m_volData->getVoxelAt(x-1,y,z); | ||||
| 					VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz(); | ||||
| 					bool negXVoxelIsSolid = negXVoxel.getDensity()  >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					if((currentVoxelIsSolid != negXVoxelIsSolid) && (finalY == false) && (finalZ == false)) | ||||
| 					{ | ||||
| 						int material = (std::max)(currentVoxel.getMaterial(), negXVoxel.getMaterial()); | ||||
|  | ||||
| 						/*uint32_t v0 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ - 0.5f), material)); | ||||
| 						uint32_t v1 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), material)); | ||||
| 						uint32_t v2 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), material)); | ||||
| 						uint32_t v3 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), material));*/ | ||||
|  | ||||
| 						// Check to ensure that when a voxel solid/non-solid change is right on a region border, the vertices are generated on the solid side of the region border | ||||
| 						if(((currentVoxelIsSolid > negXVoxelIsSolid) && finalX == false) || ((currentVoxelIsSolid < negXVoxelIsSolid) && regX != 0)) | ||||
| 						{ | ||||
| 							uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices); | ||||
| 							uint32_t v2 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v3 = addVertex(regX - 0.5f, regY + 0.5f, regZ + 0.5f, material, m_currentSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);	 | ||||
| 							uint32_t v2 = addVertex(regX - 0.5f, regY + 0.5f, regZ + 0.5f, material, m_currentSliceVertices);							 | ||||
| 							uint32_t v3 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
|  | ||||
| 							if(currentVoxelIsSolid > negXVoxelIsSolid) | ||||
| 							{ | ||||
| 								m_meshCurrent->addTriangleCubic(v0,v1,v2); | ||||
| 								m_meshCurrent->addTriangleCubic(v1,v3,v2); | ||||
| 							{								 | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v1; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v3; | ||||
|  | ||||
| 								m_vecQuads[NegativeX][regX].push_back(quad); | ||||
| 							} | ||||
| 							else											 | ||||
| 							{ | ||||
| 								m_meshCurrent->addTriangleCubic(v0,v2,v1); | ||||
| 								m_meshCurrent->addTriangleCubic(v1,v2,v3); | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v3; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v1; | ||||
|  | ||||
| 								m_vecQuads[PositiveX][regX].push_back(quad); | ||||
| 							} | ||||
|  | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					VoxelType negYVoxel = m_volData->getVoxelAt(x,y-1,z); | ||||
| 					VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz(); | ||||
| 					bool negYVoxelIsSolid = negYVoxel.getDensity()  >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					if((currentVoxelIsSolid != negYVoxelIsSolid) && (finalX == false) && (finalZ == false)) | ||||
| @@ -116,24 +137,34 @@ namespace PolyVox | ||||
| 						if(((currentVoxelIsSolid > negYVoxelIsSolid) && finalY == false) || ((currentVoxelIsSolid < negYVoxelIsSolid) && regY != 0)) | ||||
| 						{ | ||||
| 							uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices); | ||||
| 							uint32_t v2 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v3 = addVertex(regX + 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);							 | ||||
| 							uint32_t v2 = addVertex(regX + 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices); | ||||
| 							uint32_t v3 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
|  | ||||
| 							if(currentVoxelIsSolid > negYVoxelIsSolid) | ||||
| 							{ | ||||
| 								m_meshCurrent->addTriangleCubic(v0,v2,v1); | ||||
| 								m_meshCurrent->addTriangleCubic(v1,v2,v3); | ||||
| 								//NOTE: For some reason y windong is opposite of X and Z. Investigate this... | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v3; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v1; | ||||
|  | ||||
| 								m_vecQuads[NegativeY][regY].push_back(quad); | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| 								m_meshCurrent->addTriangleCubic(v0,v1,v2); | ||||
| 								m_meshCurrent->addTriangleCubic(v1,v3,v2); | ||||
| 								//NOTE: For some reason y windong is opposite of X and Z. Investigate this... | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v1; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v3; | ||||
|  | ||||
| 								m_vecQuads[PositiveY][regY].push_back(quad); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					VoxelType negZVoxel = m_volData->getVoxelAt(x,y,z-1); | ||||
| 					VoxelType negZVoxel = volumeSampler.peekVoxel0px0py1nz(); | ||||
| 					bool negZVoxelIsSolid = negZVoxel.getDensity()  >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					if((currentVoxelIsSolid != negZVoxelIsSolid) && (finalX == false) && (finalY == false)) | ||||
| @@ -144,18 +175,26 @@ namespace PolyVox | ||||
| 						{ | ||||
| 							uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v2 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v3 = addVertex(regX + 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v2 = addVertex(regX + 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v3 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);							 | ||||
| 	 | ||||
| 							if(currentVoxelIsSolid > negZVoxelIsSolid) | ||||
| 							{ | ||||
| 								m_meshCurrent->addTriangleCubic(v0,v1,v2); | ||||
| 								m_meshCurrent->addTriangleCubic(v1,v3,v2); | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v1; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v3; | ||||
|  | ||||
| 								m_vecQuads[NegativeZ][regZ].push_back(quad); | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| 								m_meshCurrent->addTriangleCubic(v0,v2,v1); | ||||
| 								m_meshCurrent->addTriangleCubic(v1,v2,v3); | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v3; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v1; | ||||
|  | ||||
| 								m_vecQuads[PositiveZ][regZ].push_back(quad); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| @@ -166,7 +205,33 @@ namespace PolyVox | ||||
| 			memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); | ||||
| 		} | ||||
|  | ||||
| 		for(uint32_t uFace = 0; uFace < NoOfFaces; uFace++) | ||||
| 		{ | ||||
| 			std::vector< std::list<Quad> >& vecListQuads = m_vecQuads[uFace]; | ||||
|  | ||||
| 			for(uint32_t slice = 0; slice < vecListQuads.size(); slice++) | ||||
| 			{ | ||||
| 				std::list<Quad>& listQuads = vecListQuads[slice]; | ||||
|  | ||||
| 				if(m_bMergeQuads) | ||||
| 				{ | ||||
| 					//Repeatedly call this function until it returns | ||||
| 					//false to indicate nothing more can be done. | ||||
| 					while(performQuadMerging(listQuads)){} | ||||
| 				} | ||||
|  | ||||
| 				std::list<Quad>::iterator iterEnd = listQuads.end(); | ||||
| 				for(std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++) | ||||
| 				{ | ||||
| 					Quad& quad = *quadIter;				 | ||||
| 					m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]); | ||||
| 					m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]); | ||||
| 				}			 | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		m_meshCurrent->m_Region = m_regSizeInVoxels; | ||||
| 		m_meshCurrent->removeUnusedVertices(); | ||||
|  | ||||
| 		m_meshCurrent->m_vecLodRecords.clear(); | ||||
| 		LodRecord lodRecord; | ||||
| @@ -185,25 +250,19 @@ namespace PolyVox | ||||
| 		{ | ||||
| 			IndexAndMaterial& rEntry = existingVertices[uX][uY][ct]; | ||||
|  | ||||
| 			int32_t iIndex = static_cast<int32_t>(rEntry.iIndex); | ||||
| 			uint8_t uMaterial = static_cast<uint8_t>(rEntry.uMaterial); | ||||
|  | ||||
| 			//If we have an existing vertex and the material matches then we can return it. | ||||
| 			if((iIndex != -1) && (uMaterial == uMaterialIn)) | ||||
| 			{ | ||||
| 				return iIndex; | ||||
| 			} | ||||
| 			else | ||||
| 			if(rEntry.iIndex == -1) | ||||
| 			{ | ||||
| 				//No vertices matched and we've now hit an empty space. Fill it by creating a vertex. | ||||
| 				uint32_t temp = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(fX, fY, fZ), uMaterialIn)); | ||||
|  | ||||
| 				//Note - Slightly dodgy casting taking place here. No proper way to convert to 24-bit int though? | ||||
| 				//If problematic in future then fix IndexAndMaterial to contain variables rather than bitfield. | ||||
| 				rEntry.iIndex = temp; | ||||
| 				rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(fX, fY, fZ), uMaterialIn)); | ||||
| 				rEntry.uMaterial = uMaterialIn; | ||||
|  | ||||
| 				return temp; | ||||
| 				return rEntry.iIndex; | ||||
| 			} | ||||
|  | ||||
| 			//If we have an existing vertex and the material matches then we can return it. | ||||
| 			if(rEntry.uMaterial == uMaterialIn) | ||||
| 			{ | ||||
| 				return rEntry.iIndex; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -212,4 +271,74 @@ namespace PolyVox | ||||
| 		assert(false); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	bool CubicSurfaceExtractor<VolumeType, VoxelType>::performQuadMerging(std::list<Quad>& quads) | ||||
| 	{ | ||||
| 		bool bDidMerge = false; | ||||
| 		for(std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++) | ||||
| 		{ | ||||
| 			std::list<Quad>::iterator innerIter = outerIter; | ||||
| 			innerIter++; | ||||
| 			while(innerIter != quads.end()) | ||||
| 			{ | ||||
| 				Quad& q1 = *outerIter; | ||||
| 				Quad& q2 = *innerIter; | ||||
|  | ||||
| 				bool result = mergeQuads(q1,q2); | ||||
|  | ||||
| 				if(result) | ||||
| 				{ | ||||
| 					bDidMerge = true; | ||||
| 					innerIter = quads.erase(innerIter); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					innerIter++; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return bDidMerge; | ||||
| 	} | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	bool CubicSurfaceExtractor<VolumeType, VoxelType>::mergeQuads(Quad& q1, Quad& q2) | ||||
| 	{ | ||||
| 		//All four vertices of a given quad have the same material, | ||||
| 		//so just check that the first pair or vertices match. | ||||
| 		if(fabs(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() - m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) < 0.001) | ||||
| 		{ | ||||
| 			//Now check whether quad 2 is adjacent to quad one by comparing vertices. | ||||
| 			//Adjacent quads must share two vertices, and the second quad could be to the | ||||
| 			//top, bottom, left, of right of the first one. This gives four combinations to test. | ||||
| 			if((q1.vertices[0] == q2.vertices[1]) && ((q1.vertices[3] == q2.vertices[2]))) | ||||
| 			{ | ||||
| 				q1.vertices[0] = q2.vertices[0]; | ||||
| 				q1.vertices[3] = q2.vertices[3]; | ||||
| 				return true; | ||||
| 			} | ||||
| 			else if((q1.vertices[3] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[1]))) | ||||
| 			{ | ||||
| 				q1.vertices[3] = q2.vertices[3]; | ||||
| 				q1.vertices[2] = q2.vertices[2]; | ||||
| 				return true; | ||||
| 			} | ||||
| 			else if((q1.vertices[1] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[3]))) | ||||
| 			{ | ||||
| 				q1.vertices[1] = q2.vertices[1]; | ||||
| 				q1.vertices[2] = q2.vertices[2]; | ||||
| 				return true; | ||||
| 			} | ||||
| 			else if((q1.vertices[0] == q2.vertices[3]) && ((q1.vertices[1] == q2.vertices[2]))) | ||||
| 			{ | ||||
| 				q1.vertices[0] = q2.vertices[0]; | ||||
| 				q1.vertices[1] = q2.vertices[1]; | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		//Quads cannot be merged. | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| @@ -1,100 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2009 David Williams | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied | ||||
| warranty. In no event will the authors be held liable for any damages | ||||
| arising from the use of this software. | ||||
|  | ||||
| Permission is granted to anyone to use this software for any purpose, | ||||
| including commercial applications, and to alter it and redistribute it | ||||
| freely, subject to the following restrictions: | ||||
|  | ||||
|     1. The origin of this software must not be misrepresented; you must not | ||||
|     claim that you wrote the original software. If you use this software | ||||
|     in a product, an acknowledgment in the product documentation would be | ||||
|     appreciated but is not required. | ||||
|  | ||||
|     2. Altered source versions must be plainly marked as such, and must not be | ||||
|     misrepresented as being the original software. | ||||
|  | ||||
|     3. This notice may not be removed or altered from any source | ||||
|     distribution. | ||||
| *******************************************************************************/ | ||||
|  | ||||
| #ifndef __PolyVox_ImprovedCubicSurfaceExtractor_H__ | ||||
| #define __PolyVox_ImprovedCubicSurfaceExtractor_H__ | ||||
|  | ||||
| #include "PolyVoxCore/Array.h" | ||||
| #include "PolyVoxCore/PolyVoxForwardDeclarations.h" | ||||
| #include "PolyVoxCore/LargeVolume.h" | ||||
|  | ||||
| #include "PolyVoxImpl/TypeDef.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	class ImprovedCubicSurfaceExtractor | ||||
| 	{ | ||||
| 		struct IndexAndMaterial | ||||
| 		{ | ||||
| 			int32_t iIndex; | ||||
| 			int32_t uMaterial; //Should actually use the material type here, but this is ok for now. | ||||
| 		}; | ||||
|  | ||||
| 		enum FaceNames | ||||
| 		{ | ||||
| 			PositiveX, | ||||
| 			PositiveY, | ||||
| 			PositiveZ, | ||||
| 			NegativeX, | ||||
| 			NegativeY, | ||||
| 			NegativeZ, | ||||
| 			NoOfFaces | ||||
| 		}; | ||||
|  | ||||
| 		struct Quad | ||||
| 		{ | ||||
| 			uint32_t vertices[4]; | ||||
| 		}; | ||||
|  | ||||
| 	public: | ||||
| 		ImprovedCubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads = true); | ||||
|  | ||||
| 		void execute();		 | ||||
|  | ||||
| 	private: | ||||
| 		int32_t addVertex(float fX, float fY, float fZ, uint8_t uMaterial, Array<3, IndexAndMaterial>& existingVertices); | ||||
| 		bool performQuadMerging(std::list<Quad>& quads); | ||||
| 		bool mergeQuads(Quad& q1, Quad& q2); | ||||
|  | ||||
| 		//The volume data and a sampler to access it. | ||||
| 		VolumeType<VoxelType>* m_volData; | ||||
|  | ||||
| 		//Information about the region we are currently processing | ||||
| 		Region m_regSizeInVoxels; | ||||
|  | ||||
| 		//The surface patch we are currently filling. | ||||
| 		SurfaceMesh<PositionMaterial>* m_meshCurrent; | ||||
|  | ||||
| 		//Used to avoid creating duplicate vertices. | ||||
| 		Array<3, IndexAndMaterial> m_previousSliceVertices; | ||||
| 		Array<3, IndexAndMaterial> m_currentSliceVertices; | ||||
|  | ||||
| 		//During extraction we create a number of different lists of quads. All the  | ||||
| 		//quads in a given list are in the same plane and facing in the same direction. | ||||
| 		std::vector< std::list<Quad> > m_vecQuads[NoOfFaces]; | ||||
|  | ||||
| 		//Controls whether quad merging should be performed. This might be undesirable | ||||
| 		//is the user needs per-vertex attributes, or to perform per vertex lighting. | ||||
| 		bool m_bMergeQuads; | ||||
|  | ||||
| 		//Although we try to avoid creating multiple vertices at the same location, sometimes this is unavoidable | ||||
| 		//if they have different materials. For example, four different materials next to each other would mean | ||||
| 		//four quads (though more triangles) sharing the vertex. As far as I can tell, four is the worst case scenario. | ||||
| 		static const uint32_t MaxQuadsSharingVertex;		 | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| #include "PolyVoxCore/ImprovedCubicSurfaceExtractor.inl" | ||||
|  | ||||
| #endif | ||||
| @@ -1,344 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| Copyright (c) 2005-2009 David Williams | ||||
|  | ||||
| This software is provided 'as-is', without any express or implied | ||||
| warranty. In no event will the authors be held liable for any damages | ||||
| arising from the use of this software. | ||||
|  | ||||
| Permission is granted to anyone to use this software for any purpose, | ||||
| including commercial applications, and to alter it and redistribute it | ||||
| freely, subject to the following restrictions: | ||||
|  | ||||
|     1. The origin of this software must not be misrepresented; you must not | ||||
|     claim that you wrote the original software. If you use this software | ||||
|     in a product, an acknowledgment in the product documentation would be | ||||
|     appreciated but is not required. | ||||
|  | ||||
|     2. Altered source versions must be plainly marked as such, and must not be | ||||
|     misrepresented as being the original software. | ||||
|  | ||||
|     3. This notice may not be removed or altered from any source | ||||
|     distribution. | ||||
| *******************************************************************************/ | ||||
|  | ||||
| #include "PolyVoxCore/Array.h" | ||||
| #include "PolyVoxCore/MaterialDensityPair.h" | ||||
| #include "PolyVoxCore/SurfaceMesh.h" | ||||
| #include "PolyVoxImpl/MarchingCubesTables.h" | ||||
| #include "PolyVoxCore/VertexTypes.h" | ||||
|  | ||||
| namespace PolyVox | ||||
| { | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	const uint32_t ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::MaxQuadsSharingVertex = 4; | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::ImprovedCubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result, bool bMergeQuads) | ||||
| 		:m_volData(volData) | ||||
| 		,m_regSizeInVoxels(region) | ||||
| 		,m_meshCurrent(result) | ||||
| 		,m_bMergeQuads(bMergeQuads) | ||||
| 	{ | ||||
| 		m_meshCurrent->clear(); | ||||
| 	} | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	void ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::execute() | ||||
| 	{ | ||||
| 		uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2; | ||||
| 		uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2; | ||||
|  | ||||
| 		uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxQuadsSharingVertex}; | ||||
| 		m_previousSliceVertices.resize(arraySize); | ||||
| 		m_currentSliceVertices.resize(arraySize); | ||||
| 		memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); | ||||
| 		memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); | ||||
|  | ||||
| 		uint32_t uRegionWidth  = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1; | ||||
| 		uint32_t uRegionHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1; | ||||
| 		uint32_t uRegionDepth  = m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 1; | ||||
|  | ||||
| 		m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2); | ||||
| 		m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2); | ||||
|  | ||||
| 		m_vecQuads[NegativeY].resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2); | ||||
| 		m_vecQuads[PositiveY].resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2); | ||||
|  | ||||
| 		m_vecQuads[NegativeZ].resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2); | ||||
| 		m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2); | ||||
|  | ||||
| 		VolumeType<VoxelType>::Sampler volumeSampler(m_volData);	 | ||||
| 		Quad quad; | ||||
| 		 | ||||
| 		for(int32_t z = m_regSizeInVoxels.getLowerCorner().getZ(); z <= m_regSizeInVoxels.getUpperCorner().getZ() + 1; z++) | ||||
| 		{ | ||||
| 			uint32_t regZ = z - m_regSizeInVoxels.getLowerCorner().getZ(); | ||||
| 			bool finalZ = (z == m_regSizeInVoxels.getUpperCorner().getZ() + 1); | ||||
|  | ||||
| 			for(int32_t y = m_regSizeInVoxels.getLowerCorner().getY(); y <= m_regSizeInVoxels.getUpperCorner().getY() + 1; y++) | ||||
| 			{ | ||||
| 				uint32_t regY = y - m_regSizeInVoxels.getLowerCorner().getY(); | ||||
| 				bool finalY = (y == m_regSizeInVoxels.getUpperCorner().getY() + 1); | ||||
|  | ||||
| 				for(int32_t x = m_regSizeInVoxels.getLowerCorner().getX(); x <= m_regSizeInVoxels.getUpperCorner().getX() + 1; x++) | ||||
| 				{ | ||||
| 					uint32_t regX = x - m_regSizeInVoxels.getLowerCorner().getX(); | ||||
| 					bool finalX = (x == m_regSizeInVoxels.getUpperCorner().getX() + 1);					 | ||||
|  | ||||
| 					volumeSampler.setPosition(x,y,z); | ||||
|  | ||||
| 					VoxelType currentVoxel = volumeSampler.getVoxel(); | ||||
| 					bool currentVoxelIsSolid = currentVoxel.getDensity() >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz(); | ||||
| 					bool negXVoxelIsSolid = negXVoxel.getDensity()  >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					if((currentVoxelIsSolid != negXVoxelIsSolid) && (finalY == false) && (finalZ == false)) | ||||
| 					{ | ||||
| 						int material = (std::max)(currentVoxel.getMaterial(), negXVoxel.getMaterial()); | ||||
|  | ||||
| 						// Check to ensure that when a voxel solid/non-solid change is right on a region border, the vertices are generated on the solid side of the region border | ||||
| 						if(((currentVoxelIsSolid > negXVoxelIsSolid) && finalX == false) || ((currentVoxelIsSolid < negXVoxelIsSolid) && regX != 0)) | ||||
| 						{ | ||||
| 							uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);	 | ||||
| 							uint32_t v2 = addVertex(regX - 0.5f, regY + 0.5f, regZ + 0.5f, material, m_currentSliceVertices);							 | ||||
| 							uint32_t v3 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
|  | ||||
| 							if(currentVoxelIsSolid > negXVoxelIsSolid) | ||||
| 							{								 | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v1; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v3; | ||||
|  | ||||
| 								m_vecQuads[NegativeX][regX].push_back(quad); | ||||
| 							} | ||||
| 							else											 | ||||
| 							{ | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v3; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v1; | ||||
|  | ||||
| 								m_vecQuads[PositiveX][regX].push_back(quad); | ||||
| 							} | ||||
|  | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz(); | ||||
| 					bool negYVoxelIsSolid = negYVoxel.getDensity()  >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					if((currentVoxelIsSolid != negYVoxelIsSolid) && (finalX == false) && (finalZ == false)) | ||||
| 					{ | ||||
| 						int material = (std::max)(currentVoxel.getMaterial(),negYVoxel.getMaterial()); | ||||
|  | ||||
| 						if(((currentVoxelIsSolid > negYVoxelIsSolid) && finalY == false) || ((currentVoxelIsSolid < negYVoxelIsSolid) && regY != 0)) | ||||
| 						{ | ||||
| 							uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);							 | ||||
| 							uint32_t v2 = addVertex(regX + 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices); | ||||
| 							uint32_t v3 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
|  | ||||
| 							if(currentVoxelIsSolid > negYVoxelIsSolid) | ||||
| 							{ | ||||
| 								//NOTE: For some reason y windong is opposite of X and Z. Investigate this... | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v3; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v1; | ||||
|  | ||||
| 								m_vecQuads[NegativeY][regY].push_back(quad); | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| 								//NOTE: For some reason y windong is opposite of X and Z. Investigate this... | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v1; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v3; | ||||
|  | ||||
| 								m_vecQuads[PositiveY][regY].push_back(quad); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					VoxelType negZVoxel = volumeSampler.peekVoxel0px0py1nz(); | ||||
| 					bool negZVoxelIsSolid = negZVoxel.getDensity()  >= VoxelType::getThreshold(); | ||||
|  | ||||
| 					if((currentVoxelIsSolid != negZVoxelIsSolid) && (finalX == false) && (finalY == false)) | ||||
| 					{ | ||||
| 						int material = (std::max)(currentVoxel.getMaterial(), negZVoxel.getMaterial()); | ||||
|  | ||||
| 						if(((currentVoxelIsSolid > negZVoxelIsSolid) && finalZ == false) || ((currentVoxelIsSolid < negZVoxelIsSolid) && regZ != 0)) | ||||
| 						{ | ||||
| 							uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v1 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v2 = addVertex(regX + 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices); | ||||
| 							uint32_t v3 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);							 | ||||
| 	 | ||||
| 							if(currentVoxelIsSolid > negZVoxelIsSolid) | ||||
| 							{ | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v1; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v3; | ||||
|  | ||||
| 								m_vecQuads[NegativeZ][regZ].push_back(quad); | ||||
| 							} | ||||
| 							else | ||||
| 							{ | ||||
| 								quad.vertices[0] = v0; | ||||
| 								quad.vertices[1] = v3; | ||||
| 								quad.vertices[2] = v2; | ||||
| 								quad.vertices[3] = v1; | ||||
|  | ||||
| 								m_vecQuads[PositiveZ][regZ].push_back(quad); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			m_previousSliceVertices.swap(m_currentSliceVertices); | ||||
| 			memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); | ||||
| 		} | ||||
|  | ||||
| 		for(uint32_t uFace = 0; uFace < NoOfFaces; uFace++) | ||||
| 		{ | ||||
| 			std::vector< std::list<Quad> >& vecListQuads = m_vecQuads[uFace]; | ||||
|  | ||||
| 			for(uint32_t slice = 0; slice < vecListQuads.size(); slice++) | ||||
| 			{ | ||||
| 				std::list<Quad>& listQuads = vecListQuads[slice]; | ||||
|  | ||||
| 				if(m_bMergeQuads) | ||||
| 				{ | ||||
| 					//Repeatedly call this function until it returns | ||||
| 					//false to indicate nothing more can be done. | ||||
| 					while(performQuadMerging(listQuads)){} | ||||
| 				} | ||||
|  | ||||
| 				std::list<Quad>::iterator iterEnd = listQuads.end(); | ||||
| 				for(std::list<Quad>::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++) | ||||
| 				{ | ||||
| 					Quad& quad = *quadIter;				 | ||||
| 					m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]); | ||||
| 					m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]); | ||||
| 				}			 | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		m_meshCurrent->m_Region = m_regSizeInVoxels; | ||||
| 		m_meshCurrent->removeUnusedVertices(); | ||||
|  | ||||
| 		m_meshCurrent->m_vecLodRecords.clear(); | ||||
| 		LodRecord lodRecord; | ||||
| 		lodRecord.beginIndex = 0; | ||||
| 		lodRecord.endIndex = m_meshCurrent->getNoOfIndices(); | ||||
| 		m_meshCurrent->m_vecLodRecords.push_back(lodRecord); | ||||
| 	} | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	int32_t ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::addVertex(float fX, float fY, float fZ, uint8_t uMaterialIn, Array<3, IndexAndMaterial>& existingVertices) | ||||
| 	{ | ||||
| 		uint32_t uX = static_cast<uint32_t>(fX + 0.75f); | ||||
| 		uint32_t uY = static_cast<uint32_t>(fY + 0.75f); | ||||
|  | ||||
| 		for(uint32_t ct = 0; ct < MaxQuadsSharingVertex; ct++) | ||||
| 		{ | ||||
| 			IndexAndMaterial& rEntry = existingVertices[uX][uY][ct]; | ||||
|  | ||||
| 			if(rEntry.iIndex == -1) | ||||
| 			{ | ||||
| 				//No vertices matched and we've now hit an empty space. Fill it by creating a vertex. | ||||
| 				rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(fX, fY, fZ), uMaterialIn)); | ||||
| 				rEntry.uMaterial = uMaterialIn; | ||||
|  | ||||
| 				return rEntry.iIndex; | ||||
| 			} | ||||
|  | ||||
| 			//If we have an existing vertex and the material matches then we can return it. | ||||
| 			if(rEntry.uMaterial == uMaterialIn) | ||||
| 			{ | ||||
| 				return rEntry.iIndex; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		//If we exit the loop here then apparently all the slots were full but none of | ||||
| 		//them matched. I don't think this can happen so let's put an assert to make sure. | ||||
| 		assert(false); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	bool ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::performQuadMerging(std::list<Quad>& quads) | ||||
| 	{ | ||||
| 		bool bDidMerge = false; | ||||
| 		for(std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++) | ||||
| 		{ | ||||
| 			std::list<Quad>::iterator innerIter = outerIter; | ||||
| 			innerIter++; | ||||
| 			while(innerIter != quads.end()) | ||||
| 			{ | ||||
| 				Quad& q1 = *outerIter; | ||||
| 				Quad& q2 = *innerIter; | ||||
|  | ||||
| 				bool result = mergeQuads(q1,q2); | ||||
|  | ||||
| 				if(result) | ||||
| 				{ | ||||
| 					bDidMerge = true; | ||||
| 					innerIter = quads.erase(innerIter); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					innerIter++; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return bDidMerge; | ||||
| 	} | ||||
|  | ||||
| 	template< template<typename> class VolumeType, typename VoxelType> | ||||
| 	bool ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::mergeQuads(Quad& q1, Quad& q2) | ||||
| 	{ | ||||
| 		//All four vertices of a given quad have the same material, | ||||
| 		//so just check that the first pair or vertices match. | ||||
| 		if(fabs(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() - m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) < 0.001) | ||||
| 		{ | ||||
| 			//Now check whether quad 2 is adjacent to quad one by comparing vertices. | ||||
| 			//Adjacent quads must share two vertices, and the second quad could be to the | ||||
| 			//top, bottom, left, of right of the first one. This gives four combinations to test. | ||||
| 			if((q1.vertices[0] == q2.vertices[1]) && ((q1.vertices[3] == q2.vertices[2]))) | ||||
| 			{ | ||||
| 				q1.vertices[0] = q2.vertices[0]; | ||||
| 				q1.vertices[3] = q2.vertices[3]; | ||||
| 				return true; | ||||
| 			} | ||||
| 			else if((q1.vertices[3] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[1]))) | ||||
| 			{ | ||||
| 				q1.vertices[3] = q2.vertices[3]; | ||||
| 				q1.vertices[2] = q2.vertices[2]; | ||||
| 				return true; | ||||
| 			} | ||||
| 			else if((q1.vertices[1] == q2.vertices[0]) && ((q1.vertices[2] == q2.vertices[3]))) | ||||
| 			{ | ||||
| 				q1.vertices[1] = q2.vertices[1]; | ||||
| 				q1.vertices[2] = q2.vertices[2]; | ||||
| 				return true; | ||||
| 			} | ||||
| 			else if((q1.vertices[0] == q2.vertices[3]) && ((q1.vertices[1] == q2.vertices[2]))) | ||||
| 			{ | ||||
| 				q1.vertices[0] = q2.vertices[0]; | ||||
| 				q1.vertices[1] = q2.vertices[1]; | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		//Quads cannot be merged. | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user