diff --git a/include/PolyVox/CubicSurfaceExtractor.h b/include/PolyVox/CubicSurfaceExtractor.h index 2879a630..e7728ae7 100644 --- a/include/PolyVox/CubicSurfaceExtractor.h +++ b/include/PolyVox/CubicSurfaceExtractor.h @@ -225,31 +225,8 @@ namespace PolyVox public: CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), bool bMergeQuads = true); - void execute(); - private: - IsQuadNeeded m_funcIsQuadNeededCallback; - - //The volume data and a sampler to access it. - VolumeType* m_volData; - - //Information about the region we are currently processing - Region m_regSizeInVoxels; - - //The surface patch we are currently filling. - MeshType* 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 > 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; + }; // This version of the function performs the extraction into a user-provided mesh rather than allocating a mesh automatically. @@ -269,7 +246,7 @@ namespace PolyVox void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), bool bMergeQuads = true) { CubicSurfaceExtractor extractor(volData, region, result, isQuadNeeded, bMergeQuads); - extractor.execute(); + //extractor.execute(); } /// The CubicSurfaceExtractor creates a mesh in which each voxel appears to be rendered as a cube diff --git a/include/PolyVox/CubicSurfaceExtractor.inl b/include/PolyVox/CubicSurfaceExtractor.inl index 12f1f795..a5556f76 100644 --- a/include/PolyVox/CubicSurfaceExtractor.inl +++ b/include/PolyVox/CubicSurfaceExtractor.inl @@ -27,61 +27,52 @@ namespace PolyVox { template CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded, bool bMergeQuads) - :m_volData(volData) - ,m_regSizeInVoxels(region) - ,m_meshCurrent(result) - ,m_previousSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition) - ,m_currentSliceVertices(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2, m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2, MaxVerticesPerPosition) - ,m_bMergeQuads(bMergeQuads) { - m_funcIsQuadNeededCallback = isQuadNeeded; - // This extractor has a limit as to how large the extracted region can be, because the vertex positions are encoded with a single byte per component. int32_t maxReionDimension = 256; POLYVOX_THROW_IF(region.getWidthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions"); POLYVOX_THROW_IF(region.getHeightInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions"); POLYVOX_THROW_IF(region.getDepthInVoxels() > maxReionDimension, std::invalid_argument, "Requested extraction region exceeds maximum dimensions"); - } - template - void CubicSurfaceExtractor::execute() - { Timer timer; - m_meshCurrent->clear(); + result->clear(); + + //Used to avoid creating duplicate vertices. + Array<3, IndexAndMaterial > m_previousSliceVertices(region.getUpperX() - region.getLowerX() + 2, region.getUpperY() - region.getLowerY() + 2, MaxVerticesPerPosition); + Array<3, IndexAndMaterial > m_currentSliceVertices(region.getUpperX() - region.getLowerX() + 2, region.getUpperY() - region.getLowerY() + 2, MaxVerticesPerPosition); + + //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 > m_vecQuads[NoOfFaces]; - //uint32_t uArrayWidth = m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2; - //uint32_t uArrayHeight = m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2; - //uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxVerticesPerPosition}; - //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)); - m_vecQuads[NegativeX].resize(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2); - m_vecQuads[PositiveX].resize(m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 2); + m_vecQuads[NegativeX].resize(region.getUpperX() - region.getLowerX() + 2); + m_vecQuads[PositiveX].resize(region.getUpperX() - region.getLowerX() + 2); - m_vecQuads[NegativeY].resize(m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2); - m_vecQuads[PositiveY].resize(m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 2); + m_vecQuads[NegativeY].resize(region.getUpperY() - region.getLowerY() + 2); + m_vecQuads[PositiveY].resize(region.getUpperY() - region.getLowerY() + 2); - m_vecQuads[NegativeZ].resize(m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ() + 2); - m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ() + 2); + m_vecQuads[NegativeZ].resize(region.getUpperZ() - region.getLowerZ() + 2); + m_vecQuads[PositiveZ].resize(region.getUpperZ() - region.getLowerZ() + 2); - typename VolumeType::Sampler volumeSampler(m_volData); - - for(int32_t z = m_regSizeInVoxels.getLowerZ(); z <= m_regSizeInVoxels.getUpperZ(); z++) + typename VolumeType::Sampler volumeSampler(volData); + + for (int32_t z = region.getLowerZ(); z <= region.getUpperZ(); z++) { - uint32_t regZ = z - m_regSizeInVoxels.getLowerZ(); + uint32_t regZ = z - region.getLowerZ(); - for(int32_t y = m_regSizeInVoxels.getLowerY(); y <= m_regSizeInVoxels.getUpperY(); y++) + for (int32_t y = region.getLowerY(); y <= region.getUpperY(); y++) { - uint32_t regY = y - m_regSizeInVoxels.getLowerY(); + uint32_t regY = y - region.getLowerY(); - volumeSampler.setPosition(m_regSizeInVoxels.getLowerX(),y,z); + volumeSampler.setPosition(region.getLowerX(), y, z); - for(int32_t x = m_regSizeInVoxels.getLowerX(); x <= m_regSizeInVoxels.getUpperX(); x++) + for (int32_t x = region.getLowerX(); x <= region.getUpperX(); x++) { - uint32_t regX = x - m_regSizeInVoxels.getLowerX(); + uint32_t regX = x - region.getLowerX(); typename VolumeType::VoxelType material; //Filled in by callback typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel(); @@ -90,64 +81,64 @@ namespace PolyVox typename VolumeType::VoxelType negZVoxel = volumeSampler.peekVoxel0px0py1nz(); // X - if(m_funcIsQuadNeededCallback(currentVoxel, negXVoxel, material)) + if (isQuadNeeded(currentVoxel, negXVoxel, material)) { - uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v1 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices, m_meshCurrent); - uint32_t v2 = addVertex(regX , regY + 1, regZ + 1, material, m_currentSliceVertices, m_meshCurrent); - uint32_t v3 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices, m_meshCurrent); + uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v1 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); + uint32_t v2 = addVertex(regX, regY + 1, regZ + 1, material, m_currentSliceVertices, result); + uint32_t v3 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); m_vecQuads[NegativeX][regX].push_back(Quad(v0, v1, v2, v3)); } - if(m_funcIsQuadNeededCallback(negXVoxel, currentVoxel, material)) + if (isQuadNeeded(negXVoxel, currentVoxel, material)) { - uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v1 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices, m_meshCurrent); - uint32_t v2 = addVertex(regX , regY + 1, regZ + 1, material, m_currentSliceVertices, m_meshCurrent); - uint32_t v3 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices, m_meshCurrent); + uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v1 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); + uint32_t v2 = addVertex(regX, regY + 1, regZ + 1, material, m_currentSliceVertices, result); + uint32_t v3 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); m_vecQuads[PositiveX][regX].push_back(Quad(v0, v3, v2, v1)); } // Y - if(m_funcIsQuadNeededCallback(currentVoxel, negYVoxel, material)) + if (isQuadNeeded(currentVoxel, negYVoxel, material)) { - uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v1 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v2 = addVertex(regX + 1, regY , regZ + 1, material, m_currentSliceVertices, m_meshCurrent); - uint32_t v3 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices, m_meshCurrent); + uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v1 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v2 = addVertex(regX + 1, regY, regZ + 1, material, m_currentSliceVertices, result); + uint32_t v3 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); m_vecQuads[NegativeY][regY].push_back(Quad(v0, v1, v2, v3)); } - if(m_funcIsQuadNeededCallback(negYVoxel, currentVoxel, material)) + if (isQuadNeeded(negYVoxel, currentVoxel, material)) { - uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v1 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v2 = addVertex(regX + 1, regY , regZ + 1, material, m_currentSliceVertices, m_meshCurrent); - uint32_t v3 = addVertex(regX , regY , regZ + 1, material, m_currentSliceVertices, m_meshCurrent); + uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v1 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v2 = addVertex(regX + 1, regY, regZ + 1, material, m_currentSliceVertices, result); + uint32_t v3 = addVertex(regX, regY, regZ + 1, material, m_currentSliceVertices, result); m_vecQuads[PositiveY][regY].push_back(Quad(v0, v3, v2, v1)); } // Z - if(m_funcIsQuadNeededCallback(currentVoxel, negZVoxel, material)) + if (isQuadNeeded(currentVoxel, negZVoxel, material)) { - uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v1 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v2 = addVertex(regX + 1, regY + 1, regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v3 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices, m_meshCurrent); + uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v1 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); + uint32_t v2 = addVertex(regX + 1, regY + 1, regZ, material, m_previousSliceVertices, result); + uint32_t v3 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); m_vecQuads[NegativeZ][regZ].push_back(Quad(v0, v1, v2, v3)); } - if(m_funcIsQuadNeededCallback(negZVoxel, currentVoxel, material)) + if (isQuadNeeded(negZVoxel, currentVoxel, material)) { - uint32_t v0 = addVertex(regX , regY , regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v1 = addVertex(regX , regY + 1, regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v2 = addVertex(regX + 1, regY + 1, regZ , material, m_previousSliceVertices, m_meshCurrent); - uint32_t v3 = addVertex(regX + 1, regY , regZ , material, m_previousSliceVertices, m_meshCurrent); + uint32_t v0 = addVertex(regX, regY, regZ, material, m_previousSliceVertices, result); + uint32_t v1 = addVertex(regX, regY + 1, regZ, material, m_previousSliceVertices, result); + uint32_t v2 = addVertex(regX + 1, regY + 1, regZ, material, m_previousSliceVertices, result); + uint32_t v3 = addVertex(regX + 1, regY, regZ, material, m_previousSliceVertices, result); m_vecQuads[PositiveZ][regZ].push_back(Quad(v0, v3, v2, v1)); } @@ -160,33 +151,33 @@ namespace PolyVox memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial)); } - for(uint32_t uFace = 0; uFace < NoOfFaces; uFace++) + for (uint32_t uFace = 0; uFace < NoOfFaces; uFace++) { std::vector< std::list >& vecListQuads = m_vecQuads[uFace]; - for(uint32_t slice = 0; slice < vecListQuads.size(); slice++) + for (uint32_t slice = 0; slice < vecListQuads.size(); slice++) { std::list& listQuads = vecListQuads[slice]; - if(m_bMergeQuads) + if (bMergeQuads) { //Repeatedly call this function until it returns //false to indicate nothing more can be done. - while (performQuadMerging(listQuads, m_meshCurrent)){} + while (performQuadMerging(listQuads, result)){} } typename std::list::iterator iterEnd = listQuads.end(); - for(typename std::list::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++) + for (typename std::list::iterator quadIter = listQuads.begin(); quadIter != iterEnd; quadIter++) { - Quad& quad = *quadIter; - m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[1],quad.vertices[2]); - m_meshCurrent->addTriangle(quad.vertices[0], quad.vertices[2],quad.vertices[3]); - } + Quad& quad = *quadIter; + result->addTriangle(quad.vertices[0], quad.vertices[1], quad.vertices[2]); + result->addTriangle(quad.vertices[0], quad.vertices[2], quad.vertices[3]); + } } } - m_meshCurrent->setOffset(m_regSizeInVoxels.getLowerCorner()); - m_meshCurrent->removeUnusedVertices(); + result->setOffset(region.getLowerCorner()); + result->removeUnusedVertices(); POLYVOX_LOG_TRACE("Cubic surface extraction took ", timer.elapsedTimeInMilliSeconds(), "ms (Region size = ", m_regSizeInVoxels.getWidthInVoxels(), "x", m_regSizeInVoxels.getHeightInVoxels(),