From e6a7174b53834da3781be2dcb8f3df4654982195 Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 24 Jun 2008 21:28:29 +0000 Subject: [PATCH] Initial version of mesh smoothing code. --- PolyVoxCore/include/BlockVolume.inl | 12 +- PolyVoxCore/include/BlockVolumeIterator.h | 2 +- PolyVoxCore/include/BlockVolumeIterator.inl | 38 +-- PolyVoxCore/include/GradientEstimators.inl | 20 +- PolyVoxCore/include/SurfaceAdjusters.h | 1 + PolyVoxCore/include/SurfaceExtractors.h | 3 - PolyVoxCore/include/Utility.h | 25 ++ PolyVoxCore/source/SurfaceAdjusters.cpp | 106 ++++++- PolyVoxCore/source/SurfaceExtractors.cpp | 332 +------------------- TODO.txt | 5 +- 10 files changed, 167 insertions(+), 377 deletions(-) diff --git a/PolyVoxCore/include/BlockVolume.inl b/PolyVoxCore/include/BlockVolume.inl index 61a40fe2..c43d1920 100644 --- a/PolyVoxCore/include/BlockVolume.inl +++ b/PolyVoxCore/include/BlockVolume.inl @@ -139,13 +139,13 @@ namespace PolyVox assert(uYPos < getSideLength()); assert(uZPos < getSideLength()); - const uint16_t blockX = uXPos >> m_uBlockSideLengthPower; - const uint16_t blockY = uYPos >> m_uBlockSideLengthPower; - const uint16_t blockZ = uZPos >> m_uBlockSideLengthPower; + const boost::uint16_t blockX = uXPos >> m_uBlockSideLengthPower; + const boost::uint16_t blockY = uYPos >> m_uBlockSideLengthPower; + const boost::uint16_t blockZ = uZPos >> m_uBlockSideLengthPower; - const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower); - const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); - const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); + const boost::uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower); + const boost::uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); + const boost::uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); const Block* block = m_pBlocks [ diff --git a/PolyVoxCore/include/BlockVolumeIterator.h b/PolyVoxCore/include/BlockVolumeIterator.h index 6e84fe9c..61a907c7 100644 --- a/PolyVoxCore/include/BlockVolumeIterator.h +++ b/PolyVoxCore/include/BlockVolumeIterator.h @@ -43,11 +43,11 @@ namespace PolyVox bool operator<=(const BlockVolumeIterator& rhs); bool operator>=(const BlockVolumeIterator& rhs); - float getAveragedVoxel(boost::uint16_t size) const; VoxelType getMaxedVoxel(boost::uint8_t uLevel) const; boost::uint16_t getPosX(void) const; boost::uint16_t getPosY(void) const; boost::uint16_t getPosZ(void) const; + const BlockVolume& getVolume(void) const; VoxelType getVoxel(void) const; void setPosition(const Vector3DInt16& v3dNewPos); diff --git a/PolyVoxCore/include/BlockVolumeIterator.inl b/PolyVoxCore/include/BlockVolumeIterator.inl index 2b840db1..6bf53227 100644 --- a/PolyVoxCore/include/BlockVolumeIterator.inl +++ b/PolyVoxCore/include/BlockVolumeIterator.inl @@ -104,38 +104,6 @@ namespace PolyVox #pragma endregion #pragma region Getters - template - float BlockVolumeIterator::getAveragedVoxel(boost::uint16_t size) const - { - assert(mXPosInVolume >= size); - assert(mYPosInVolume >= size); - assert(mZPosInVolume >= size); - assert(mXPosInVolume < mVolume.getSideLength() - (size + 1)); - assert(mYPosInVolume < mVolume.getSideLength() - (size + 1)); - assert(mZPosInVolume < mVolume.getSideLength() - (size + 1)); - - float sum = 0.0; - for(uint16_t z = mZPosInVolume-size; z <= mZPosInVolume+size; ++z) - { - for(uint16_t y = mYPosInVolume-size; y <= mYPosInVolume+size; ++y) - { - for(uint16_t x = mXPosInVolume-size; x <= mXPosInVolume+size; ++x) - { - if(mVolume.getVoxelAt(x,y,z) != 0) - { - sum += 1.0; - } - } - } - } - - uint16_t kernelSideLength = size * 2 + 1; - uint16_t kernelVolume = kernelSideLength * kernelSideLength * kernelSideLength; - - sum /= static_cast(kernelVolume); - return sum; - } - template VoxelType BlockVolumeIterator::getMaxedVoxel(boost::uint8_t uLevel) const { @@ -192,6 +160,12 @@ namespace PolyVox return mZPosInVolume; } + template + const BlockVolume& BlockVolumeIterator::getVolume(void) const + { + return mVolume; + } + template VoxelType BlockVolumeIterator::getVoxel(void) const { diff --git a/PolyVoxCore/include/GradientEstimators.inl b/PolyVoxCore/include/GradientEstimators.inl index 798691c6..3c93f1f6 100644 --- a/PolyVoxCore/include/GradientEstimators.inl +++ b/PolyVoxCore/include/GradientEstimators.inl @@ -19,6 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ #pragma endregion +#include "SurfaceAdjusters.h" + namespace PolyVox { template @@ -76,25 +78,25 @@ namespace PolyVox //FIXME - bitwise way of doing this? volIter.setPosition(initialX-1, initialY, initialZ); - float voxel1nx = volIter.getAveragedVoxel(1); + float voxel1nx = computeSmoothedVoxel(volIter); volIter.setPosition(initialX+1, initialY, initialZ); - float voxel1px = volIter.getAveragedVoxel(1); + float voxel1px = computeSmoothedVoxel(volIter); volIter.setPosition(initialX, initialY-1, initialZ); - float voxel1ny = volIter.getAveragedVoxel(1); + float voxel1ny = computeSmoothedVoxel(volIter); volIter.setPosition(initialX, initialY+1, initialZ); - float voxel1py = volIter.getAveragedVoxel(1); + float voxel1py = computeSmoothedVoxel(volIter); volIter.setPosition(initialX, initialY, initialZ-1); - float voxel1nz = volIter.getAveragedVoxel(1); + float voxel1nz = computeSmoothedVoxel(volIter); volIter.setPosition(initialX, initialY, initialZ+1); - float voxel1pz = volIter.getAveragedVoxel(1); + float voxel1pz = computeSmoothedVoxel(volIter); return Vector3DFloat ( - voxel1px - voxel1nx, - voxel1py - voxel1ny, - voxel1pz - voxel1nz + voxel1nx - voxel1px, + voxel1ny - voxel1py, + voxel1nz - voxel1pz ); } diff --git a/PolyVoxCore/include/SurfaceAdjusters.h b/PolyVoxCore/include/SurfaceAdjusters.h index dc96a564..b978a23b 100644 --- a/PolyVoxCore/include/SurfaceAdjusters.h +++ b/PolyVoxCore/include/SurfaceAdjusters.h @@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. namespace PolyVox { POLYVOX_API void smoothRegionGeometry(BlockVolume* volumeData, RegionGeometry& regGeom); + float computeSmoothedVoxel(BlockVolumeIterator& volIter); } #endif \ No newline at end of file diff --git a/PolyVoxCore/include/SurfaceExtractors.h b/PolyVoxCore/include/SurfaceExtractors.h index 5ac13811..18ae76fb 100644 --- a/PolyVoxCore/include/SurfaceExtractors.h +++ b/PolyVoxCore/include/SurfaceExtractors.h @@ -45,9 +45,6 @@ namespace PolyVox POLYVOX_API void generateRoughVerticesForSlice(BlockVolumeIterator& volIter, Region& regSlice, const Vector3DFloat& offset, boost::uint8_t* bitmask, IndexedSurfacePatch* singleMaterialPatch,boost::int32_t vertexIndicesX[],boost::int32_t vertexIndicesY[],boost::int32_t vertexIndicesZ[]); POLYVOX_API void generateReferenceMeshDataForRegion(BlockVolume* volumeData, Region region, IndexedSurfacePatch* singleMaterialPatch); - - POLYVOX_API void generateSmoothMeshDataForRegion(BlockVolume* volumeData, Region region, IndexedSurfacePatch* singleMaterialPatch); - POLYVOX_API Vector3DFloat computeSmoothNormal(BlockVolume* volumeData, const Vector3DFloat& position, NormalGenerationMethod normalGenerationMethod); } #endif diff --git a/PolyVoxCore/include/Utility.h b/PolyVoxCore/include/Utility.h index fd8c9ad9..8b9f4399 100644 --- a/PolyVoxCore/include/Utility.h +++ b/PolyVoxCore/include/Utility.h @@ -30,6 +30,31 @@ namespace PolyVox { POLYVOX_API boost::uint8_t logBase2(boost::uint32_t uInput); POLYVOX_API bool isPowerOf2(boost::uint32_t uInput); + + template + Type trilinearlyInterpolate( + const Type& v000,const Type& v100,const Type& v010,const Type& v110, + const Type& v001,const Type& v101,const Type& v011,const Type& v111, + const float x, const float y, const float z) + { + assert((x >= 0.0f) && (y >= 0.0f) && (z >= 0.0f) && + (x <= 1.0f) && (y <= 1.0f) && (z <= 1.0f)); + + //Interpolate along X + Type v000_v100 = (v100 - v000) * x + v000; + Type v001_v101 = (v101 - v001) * x + v001; + Type v010_v110 = (v110 - v010) * x + v010; + Type v011_v111 = (v111 - v011) * x + v011; + + //Interpolate along Y + Type v000_v100__v010_v110 = (v010_v110 - v000_v100) * y + v000_v100; + Type v001_v101__v011_v111 = (v011_v111 - v001_v101) * y + v001_v101; + + //Interpolate along Z + Type v000_v100__v010_v110____v001_v101__v011_v111 = (v001_v101__v011_v111 - v000_v100__v010_v110) * z + v000_v100__v010_v110; + + return v000_v100__v010_v110____v001_v101__v011_v111; + } } #endif diff --git a/PolyVoxCore/source/SurfaceAdjusters.cpp b/PolyVoxCore/source/SurfaceAdjusters.cpp index c953fe42..dacc3ebe 100644 --- a/PolyVoxCore/source/SurfaceAdjusters.cpp +++ b/PolyVoxCore/source/SurfaceAdjusters.cpp @@ -1,7 +1,10 @@ #include "SurfaceAdjusters.h" +#include "BlockVolumeIterator.h" +#include "GradientEstimators.h" #include "IndexedSurfacePatch.h" #include "RegionGeometry.h" +#include "Utility.h" #include @@ -9,13 +12,110 @@ namespace PolyVox { void smoothRegionGeometry(BlockVolume* volumeData, RegionGeometry& regGeom) { + const boost::uint8_t uSmoothingFactor = 2; + const float fThreshold = 0.5f; + + BlockVolumeIterator volIter(*volumeData); + std::vector& vecVertices = regGeom.m_patchSingleMaterial->m_vecVertices; std::vector::iterator iterSurfaceVertex = vecVertices.begin(); while(iterSurfaceVertex != vecVertices.end()) { - iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() + iterSurfaceVertex->getNormal()); - //iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() + Vector3DFloat(10.0f,0.0f,0.0f)); + for(int ct = 0; ct < uSmoothingFactor; ++ct) + { + const Vector3DFloat& v3dPos = iterSurfaceVertex->getPosition() + static_cast(regGeom.m_v3dRegionPosition); + const Vector3DInt32 v3dFloor = static_cast(v3dPos); + const Vector3DFloat& v3dRem = v3dPos - static_cast(v3dFloor); + + //Check all corners are within the volume, allowing a boundary for gradient estimation + bool lowerCornerInside = volumeData->containsPoint(v3dFloor,2); + bool upperCornerInside = volumeData->containsPoint(v3dFloor+Vector3DInt32(1,1,1),2); + + if(lowerCornerInside && upperCornerInside) //If this test fails the vertex will be left as it was + { + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,0,0))); + const float v000 = computeSmoothedVoxel(volIter); + Vector3DFloat grad000 = computeSmoothCentralDifferenceGradient(volIter); + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,0,0))); + const float v100 = computeSmoothedVoxel(volIter); + Vector3DFloat grad100 = computeSmoothCentralDifferenceGradient(volIter); + + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,1,0))); + const float v010 = computeSmoothedVoxel(volIter); + Vector3DFloat grad010 = computeSmoothCentralDifferenceGradient(volIter); + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,1,0))); + const float v110 = computeSmoothedVoxel(volIter); + Vector3DFloat grad110 = computeSmoothCentralDifferenceGradient(volIter); + + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,0,1))); + const float v001 = computeSmoothedVoxel(volIter); + Vector3DFloat grad001 = computeSmoothCentralDifferenceGradient(volIter); + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,0,1))); + const float v101 = computeSmoothedVoxel(volIter); + Vector3DFloat grad101 = computeSmoothCentralDifferenceGradient(volIter); + + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,1,1))); + const float v011 = computeSmoothedVoxel(volIter); + Vector3DFloat grad011 = computeSmoothCentralDifferenceGradient(volIter); + volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,1,1))); + const float v111 = computeSmoothedVoxel(volIter); + Vector3DFloat grad111 = computeSmoothCentralDifferenceGradient(volIter); + + float fInterVal = trilinearlyInterpolate(v000,v100,v010,v110,v001,v101,v011,v111,v3dRem.getX(),v3dRem.getY(),v3dRem.getZ()); + Vector3DFloat fInterGrad = trilinearlyInterpolate(grad000,grad100,grad010,grad110,grad001,grad101,grad011,grad111,v3dRem.getX(),v3dRem.getY(),v3dRem.getZ()); + + fInterGrad.normalise(); + float fDiff = fInterVal - fThreshold; + iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() + (fInterGrad * fDiff)); + iterSurfaceVertex->setNormal(fInterGrad); //This is actually the gradient for the previous position, but it won't have moved much. + } //if(lowerCornerInside && upperCornerInside) + } //for(int ct = 0; ct < uSmoothingFactor; ++ct) ++iterSurfaceVertex; - } + } //while(iterSurfaceVertex != vecVertices.end()) + } + + float computeSmoothedVoxel(BlockVolumeIterator& volIter) + { + assert(volIter.getPosX() >= 1); + assert(volIter.getPosY() >= 1); + assert(volIter.getPosZ() >= 1); + assert(volIter.getPosX() < volIter.getVolume().getSideLength() - 2); + assert(volIter.getPosY() < volIter.getVolume().getSideLength() - 2); + assert(volIter.getPosZ() < volIter.getVolume().getSideLength() - 2); + + float sum = 0.0; + + if(volIter.peekVoxel1nx1ny1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx1ny0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx1ny1pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx0py1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx0py0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx0py1pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx1py1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx1py0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1nx1py1pz() != 0) sum += 1.0f; + + if(volIter.peekVoxel0px1ny1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel0px1ny0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel0px1ny1pz() != 0) sum += 1.0f; + if(volIter.peekVoxel0px0py1nz() != 0) sum += 1.0f; + if(volIter.getVoxel() != 0) sum += 1.0f; + if(volIter.peekVoxel0px0py1pz() != 0) sum += 1.0f; + if(volIter.peekVoxel0px1py1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel0px1py0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel0px1py1pz() != 0) sum += 1.0f; + + if(volIter.peekVoxel1px1ny1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px1ny0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px1ny1pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px0py1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px0py0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px0py1pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px1py1nz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px1py0pz() != 0) sum += 1.0f; + if(volIter.peekVoxel1px1py1pz() != 0) sum += 1.0f; + + sum /= 27.0f; + return sum; } } \ No newline at end of file diff --git a/PolyVoxCore/source/SurfaceExtractors.cpp b/PolyVoxCore/source/SurfaceExtractors.cpp index a8ca4b4a..fd5a395c 100644 --- a/PolyVoxCore/source/SurfaceExtractors.cpp +++ b/PolyVoxCore/source/SurfaceExtractors.cpp @@ -32,9 +32,17 @@ namespace PolyVox generateDecimatedMeshDataForRegion(volume.getVolumeData(), 0, *iterChangedRegions, regionGeometry.m_patchSingleMaterial); - computeNormalsForVertices(volume.getVolumeData(), regionGeometry, CENTRAL_DIFFERENCE); + //generateReferenceMeshDataForRegion(volume.getVolumeData(), *iterChangedRegions, regionGeometry.m_patchSingleMaterial); + + //for(int ct = 0; ct < 2; ct++) + Vector3DInt32 temp = regionGeometry.m_v3dRegionPosition; + //temp /= 16; + if(temp.getX() % 32 == 0) + { + smoothRegionGeometry(volume.getVolumeData(), regionGeometry); + } - //smoothRegionGeometry(volume.getVolumeData(), regionGeometry); + //computeNormalsForVertices(volume.getVolumeData(), regionGeometry, CENTRAL_DIFFERENCE); //genMultiFromSingle(regionGeometry.m_patchSingleMaterial, regionGeometry.m_patchMultiMaterial); @@ -746,324 +754,4 @@ namespace PolyVox } }*/ } - - void generateSmoothMeshDataForRegion(BlockVolume* volumeData, Region region, IndexedSurfacePatch* singleMaterialPatch) - { - //When generating the mesh for a region we actually look one voxel outside it in the - // back, bottom, right direction. Protect against access violations by cropping region here - Region regVolume = volumeData->getEnclosingRegion(); - regVolume.setUpperCorner(regVolume.getUpperCorner() - Vector3DInt32(1,1,1)); - region.cropTo(regVolume); - - //Offset from lower block corner - const Vector3DFloat offset = static_cast(region.getLowerCorner()); - - Vector3DFloat vertlist[12]; - uint8_t vertMaterials[12]; - BlockVolumeIterator volIter(*volumeData); - volIter.setValidRegion(region); - - const float threshold = 0.5f; - - ////////////////////////////////////////////////////////////////////////// - //Get mesh data - ////////////////////////////////////////////////////////////////////////// - - //Iterate over each cell in the region - for(volIter.setPosition(region.getLowerCorner().getX(),region.getLowerCorner().getY(), region.getLowerCorner().getZ());volIter.isValidForRegion();volIter.moveForwardInRegionXYZ()) - { - //Current position - const uint16_t x = volIter.getPosX(); - const uint16_t y = volIter.getPosY(); - const uint16_t z = volIter.getPosZ(); - - //Voxels values - BlockVolumeIterator tempVolIter(*volumeData); - tempVolIter.setPosition(x,y,z); - const float v000 = tempVolIter.getAveragedVoxel(1); - tempVolIter.setPosition(x+1,y,z); - const float v100 = tempVolIter.getAveragedVoxel(1); - tempVolIter.setPosition(x,y+1,z); - const float v010 = tempVolIter.getAveragedVoxel(1); - tempVolIter.setPosition(x+1,y+1,z); - const float v110 = tempVolIter.getAveragedVoxel(1); - tempVolIter.setPosition(x,y,z+1); - const float v001 = tempVolIter.getAveragedVoxel(1); - tempVolIter.setPosition(x+1,y,z+1); - const float v101 = tempVolIter.getAveragedVoxel(1); - tempVolIter.setPosition(x,y+1,z+1); - const float v011 = tempVolIter.getAveragedVoxel(1); - tempVolIter.setPosition(x+1,y+1,z+1); - const float v111 = tempVolIter.getAveragedVoxel(1); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - uint8_t iCubeIndex = 0; - - if (v000 < threshold) iCubeIndex |= 1; - if (v100 < threshold) iCubeIndex |= 2; - if (v110 < threshold) iCubeIndex |= 4; - if (v010 < threshold) iCubeIndex |= 8; - if (v001 < threshold) iCubeIndex |= 16; - if (v101 < threshold) iCubeIndex |= 32; - if (v111 < threshold) iCubeIndex |= 64; - if (v011 < threshold) iCubeIndex |= 128; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - float a = v000; - float b = v100; - float val = (threshold-a)/(b-a); - vertlist[0].setX(x + val); - vertlist[0].setY(y); - vertlist[0].setZ(z); - vertMaterials[0] = 1;//v000 | v100; //Because one of these is 0, the or operation takes the max. - } - if (edgeTable[iCubeIndex] & 2) - { - float a = v100; - float b = v110; - float val = (threshold-a)/(b-a); - vertlist[1].setX(x + 1.0f); - vertlist[1].setY(y + val); - vertlist[1].setZ(z); - vertMaterials[1] = 1;//v100 | v110; - } - if (edgeTable[iCubeIndex] & 4) - { - float a = v010; - float b = v110; - float val = (threshold-a)/(b-a); - vertlist[2].setX(x + val); - vertlist[2].setY(y + 1.0f); - vertlist[2].setZ(z); - vertMaterials[2] = 1;//v010 | v110; - } - if (edgeTable[iCubeIndex] & 8) - { - float a = v000; - float b = v010; - float val = (threshold-a)/(b-a); - vertlist[3].setX(x); - vertlist[3].setY(y + val); - vertlist[3].setZ(z); - vertMaterials[3] = 1;//v000 | v010; - } - if (edgeTable[iCubeIndex] & 16) - { - float a = v001; - float b = v101; - float val = (threshold-a)/(b-a); - vertlist[4].setX(x + val); - vertlist[4].setY(y); - vertlist[4].setZ(z + 1.0f); - vertMaterials[4] = 1;//v001 | v101; - } - if (edgeTable[iCubeIndex] & 32) - { - float a = v101; - float b = v111; - float val = (threshold-a)/(b-a); - vertlist[5].setX(x + 1.0f); - vertlist[5].setY(y + val); - vertlist[5].setZ(z + 1.0f); - vertMaterials[5] = 1;//v101 | v111; - } - if (edgeTable[iCubeIndex] & 64) - { - float a = v011; - float b = v111; - float val = (threshold-a)/(b-a); - vertlist[6].setX(x + val); - vertlist[6].setY(y + 1.0f); - vertlist[6].setZ(z + 1.0f); - vertMaterials[6] = 1;//v011 | v111; - } - if (edgeTable[iCubeIndex] & 128) - { - float a = v001; - float b = v011; - float val = (threshold-a)/(b-a); - vertlist[7].setX(x); - vertlist[7].setY(y + val); - vertlist[7].setZ(z + 1.0f); - vertMaterials[7] = 1;//v001 | v011; - } - if (edgeTable[iCubeIndex] & 256) - { - float a = v000; - float b = v001; - float val = (threshold-a)/(b-a); - vertlist[8].setX(x); - vertlist[8].setY(y); - vertlist[8].setZ(z + val); - vertMaterials[8] = 1;//v000 | v001; - } - if (edgeTable[iCubeIndex] & 512) - { - float a = v100; - float b = v101; - float val = (threshold-a)/(b-a); - vertlist[9].setX(x + 1.0f); - vertlist[9].setY(y); - vertlist[9].setZ(z + val); - vertMaterials[9] = 1;//v100 | v101; - } - if (edgeTable[iCubeIndex] & 1024) - { - float a = v110; - float b = v111; - float val = (threshold-a)/(b-a); - vertlist[10].setX(x + 1.0f); - vertlist[10].setY(y + 1.0f); - vertlist[10].setZ(z + val); - vertMaterials[10] = 1;//v110 | v111; - } - if (edgeTable[iCubeIndex] & 2048) - { - float a = v010; - float b = v011; - float val = (threshold-a)/(b-a); - vertlist[11].setX(x); - vertlist[11].setY(y + 1.0f); - vertlist[11].setZ(z + val); - vertMaterials[11] = 1;//v010 | v011; - } - - for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) - { - //The three vertices forming a triangle - const Vector3DFloat vertex0 = vertlist[triTable[iCubeIndex][i ]] - offset; - const Vector3DFloat vertex1 = vertlist[triTable[iCubeIndex][i+1]] - offset; - const Vector3DFloat vertex2 = vertlist[triTable[iCubeIndex][i+2]] - offset; - - const uint8_t material0 = vertMaterials[triTable[iCubeIndex][i ]]; - const uint8_t material1 = vertMaterials[triTable[iCubeIndex][i+1]]; - const uint8_t material2 = vertMaterials[triTable[iCubeIndex][i+2]]; - - SurfaceVertex surfaceVertex0Alpha1(vertex0,material0 + 0.1f,1.0f); - SurfaceVertex surfaceVertex1Alpha1(vertex1,material1 + 0.1f,1.0f); - SurfaceVertex surfaceVertex2Alpha1(vertex2,material2 + 0.1f,1.0f); - singleMaterialPatch->addTriangle(surfaceVertex0Alpha1, surfaceVertex1Alpha1, surfaceVertex2Alpha1); - - }//For each triangle - }//For each cell - - //FIXME - can it happen that we have no vertices or triangles? Should exit early? - - - //for(std::map::iterator iterPatch = surfacePatchMapResult.begin(); iterPatch != surfacePatchMapResult.end(); ++iterPatch) - { - - std::vector::iterator iterSurfaceVertex = singleMaterialPatch->getVertices().begin(); - while(iterSurfaceVertex != singleMaterialPatch->getVertices().end()) - { - Vector3DFloat tempNormal = computeSmoothNormal(volumeData, static_cast(iterSurfaceVertex->getPosition() + offset), CENTRAL_DIFFERENCE); - const_cast(*iterSurfaceVertex).setNormal(tempNormal); - ++iterSurfaceVertex; - } - } - } - - Vector3DFloat computeSmoothNormal(BlockVolume* volumeData, const Vector3DFloat& position, NormalGenerationMethod normalGenerationMethod) - { - - - const float posX = position.getX(); - const float posY = position.getY(); - const float posZ = position.getZ(); - - const uint16_t floorX = static_cast(posX); - const uint16_t floorY = static_cast(posY); - const uint16_t floorZ = static_cast(posZ); - - //Check all corners are within the volume, allowing a boundary for gradient estimation - bool lowerCornerInside = volumeData->containsPoint(Vector3DInt32(floorX, floorY, floorZ),1); - bool upperCornerInside = volumeData->containsPoint(Vector3DInt32(floorX+1, floorY+1, floorZ+1),1); - if((!lowerCornerInside) || (!upperCornerInside)) - { - normalGenerationMethod = SIMPLE; - } - - Vector3DFloat result; - - BlockVolumeIterator volIter(*volumeData); //FIXME - save this somewhere - could be expensive to create? - - - if(normalGenerationMethod == SOBEL) - { - volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); - const Vector3DFloat gradFloor = computeSobelGradient(volIter); - if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(posX+1.0),static_cast(posY),static_cast(posZ)); - } - if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(posX),static_cast(posY+1.0),static_cast(posZ)); - } - if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ+1.0)); - } - const Vector3DFloat gradCeil = computeSobelGradient(volIter); - result = ((gradFloor + gradCeil) * -1.0f); - if(result.lengthSquared() < 0.0001) - { - //Operation failed - fall back on simple gradient estimation - normalGenerationMethod = SIMPLE; - } - } - if(normalGenerationMethod == CENTRAL_DIFFERENCE) - { - volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); - const Vector3DFloat gradFloor = computeSmoothCentralDifferenceGradient(volIter); - if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(posX+1.0),static_cast(posY),static_cast(posZ)); - } - if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(posX),static_cast(posY+1.0),static_cast(posZ)); - } - if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 - { - volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ+1.0)); - } - const Vector3DFloat gradCeil = computeSmoothCentralDifferenceGradient(volIter); - result = ((gradFloor + gradCeil) * -1.0f); - if(result.lengthSquared() < 0.0001) - { - //Operation failed - fall back on simple gradient estimation - normalGenerationMethod = SIMPLE; - } - } - if(normalGenerationMethod == SIMPLE) - { - volIter.setPosition(static_cast(posX),static_cast(posY),static_cast(posZ)); - const uint8_t uFloor = volIter.getVoxel() > 0 ? 1 : 0; - if((posX - floorX) > 0.25) //The result should be 0.0 or 0.5 - { - uint8_t uCeil = volIter.peekVoxel1px0py0pz() > 0 ? 1 : 0; - result = Vector3DFloat(static_cast(uFloor - uCeil),0.0,0.0); - } - else if((posY - floorY) > 0.25) //The result should be 0.0 or 0.5 - { - uint8_t uCeil = volIter.peekVoxel0px1py0pz() > 0 ? 1 : 0; - result = Vector3DFloat(0.0,static_cast(uFloor - uCeil),0.0); - } - else if((posZ - floorZ) > 0.25) //The result should be 0.0 or 0.5 - { - uint8_t uCeil = volIter.peekVoxel0px0py1pz() > 0 ? 1 : 0; - result = Vector3DFloat(0.0, 0.0,static_cast(uFloor - uCeil)); - } - } - return result; - } } diff --git a/TODO.txt b/TODO.txt index c5779f6b..417837d1 100644 --- a/TODO.txt +++ b/TODO.txt @@ -24,4 +24,7 @@ For Version 0.2 =============== Detect detatched regions. Handle mesh generation for detatched regions. -Generate ambient lighting from volume? \ No newline at end of file +Generate ambient lighting from volume? +Utility function for closing outside surfaces? +Consider how seperate surface should be generated for a single region. +Consider transparent materials like glass. \ No newline at end of file