diff --git a/library/PolyVoxCore/include/SurfaceExtractor.inl b/library/PolyVoxCore/include/SurfaceExtractor.inl index bda57d04..24024324 100644 --- a/library/PolyVoxCore/include/SurfaceExtractor.inl +++ b/library/PolyVoxCore/include/SurfaceExtractor.inl @@ -91,7 +91,7 @@ namespace PolyVox m_regSliceCurrent.shift(Vector3DInt16(0,0,1)); //Process the other slices (previous slice is available) - for(int16_t uSlice = 1; uSlice < m_regSizeInVoxels.depth(); uSlice++) + for(int16_t uSlice = 1; uSlice <= m_regSizeInVoxels.depth(); uSlice++) { computeBitmaskForSlice(pPreviousBitmask, pCurrentBitmask); uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells; @@ -119,15 +119,6 @@ namespace PolyVox m_regSliceCurrent.shift(Vector3DInt16(0,0,1)); } - //A final slice just to close of the volume - if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0)) - { - memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4); - memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4); - memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4); - generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ); - } - m_meshCurrent->m_Region = m_regSizeInVoxels; m_meshCurrent->m_vecLodRecords.clear(); @@ -416,14 +407,14 @@ namespace PolyVox bool isPosZEdge = (uZVolSpace == m_regSizeInVoxels.getUpperCorner().getZ()); //Iterate over each cell in the region - for(uint16_t uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); uYVolSpace <= m_regSliceCurrent.getUpperCorner().getY()-1; uYVolSpace++) + for(uint16_t uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); uYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); uYVolSpace++) { const uint16_t uYRegSpace = uYVolSpace - m_regSizeInVoxels.getLowerCorner().getY(); //bool isYEdge = ((uYVolSpace == m_regSizeInVoxelsCropped.getLowerCorner().getY()) || (uYVolSpace == m_regSizeInVoxelsCropped.getUpperCorner().getY())); bool isNegYEdge = (uYVolSpace == m_regSizeInVoxels.getLowerCorner().getY()); bool isPosYEdge = (uYVolSpace == m_regSizeInVoxels.getUpperCorner().getY()); - for(uint16_t uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXVolSpace <= m_regSliceCurrent.getUpperCorner().getX()-1; uXVolSpace++) + for(uint16_t uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); uXVolSpace++) { //Current position const uint16_t uXRegSpace = uXVolSpace - m_regSizeInVoxels.getLowerCorner().getX(); @@ -655,9 +646,9 @@ namespace PolyVox indlist[i] = -1; } - for(uint16_t uYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); uYVolSpace < m_regSizeInVoxels.getUpperCorner().getY(); uYVolSpace++) + for(uint16_t uYVolSpace = m_regSlicePrevious.getLowerCorner().getY(); uYVolSpace <= m_regSizeInCells.getUpperCorner().getY(); uYVolSpace++) { - for(uint16_t uXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); uXVolSpace < m_regSizeInVoxels.getUpperCorner().getX(); uXVolSpace++) + for(uint16_t uXVolSpace = m_regSlicePrevious.getLowerCorner().getX(); uXVolSpace <= m_regSizeInCells.getUpperCorner().getX(); uXVolSpace++) { uint16_t uZVolSpace = m_regSlicePrevious.getLowerCorner().getZ(); m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace); diff --git a/library/PolyVoxCore/include/Volume.h b/library/PolyVoxCore/include/Volume.h index 1c64dbb6..0b0c8c12 100644 --- a/library/PolyVoxCore/include/Volume.h +++ b/library/PolyVoxCore/include/Volume.h @@ -32,8 +32,8 @@ freely, subject to the following restrictions: #include #include -#include #include +#include #pragma endregion @@ -128,6 +128,8 @@ namespace PolyVox ///Destructor ~Volume(); + ///Gets the value used for voxels which are outside the volume + VoxelType getBorderValue(void) const; ///Gets a Region representing the extents of the Volume. Region getEnclosingRegion(void) const; ///Gets the width of the volume in voxels. @@ -143,10 +145,12 @@ namespace PolyVox ///Gets the length of the diagonal in voxels float getDiagonalLength(void) const; ///Gets a voxel by x,y,z position - VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tDefault = VoxelType()) const; + VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const; ///Gets a voxel by 3D vector position VoxelType getVoxelAt(const Vector3DUint16& v3dPos, VoxelType tDefault = VoxelType()) const; + ///Sets the value used for voxels which are outside the volume + void setBorderValue(const VoxelType& tBorder); ///Sets the voxel at an x,y,z position bool setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); ///Sets the voxel at a 3D vector position @@ -157,6 +161,7 @@ namespace PolyVox private: std::shared_ptr< Block > getHomogenousBlock(VoxelType tHomogenousValue); + std::shared_ptr< Block > m_pBorderBlock; std::vector< std::shared_ptr< Block > > m_pBlocks; std::vector m_vecBlockIsPotentiallyHomogenous; @@ -174,20 +179,14 @@ namespace PolyVox uint16_t m_uDepthInBlocks; uint16_t m_uWidth; - uint8_t m_uWidthPower; - - uint16_t m_uHeight; - uint8_t m_uHeightPower; - + uint16_t m_uHeight; uint16_t m_uDepth; - uint8_t m_uDepthPower; uint8_t m_uBlockSideLengthPower; uint16_t m_uBlockSideLength; uint16_t m_uLongestSideLength; uint16_t m_uShortestSideLength; - float m_fDiagonalLength; uint32_t m_uCurrentBlockForTidying; diff --git a/library/PolyVoxCore/include/Volume.inl b/library/PolyVoxCore/include/Volume.inl index c92030f6..b220491a 100644 --- a/library/PolyVoxCore/include/Volume.inl +++ b/library/PolyVoxCore/include/Volume.inl @@ -66,19 +66,12 @@ namespace PolyVox } //Debug mode validation - assert(isPowerOf2(uWidth)); - assert(isPowerOf2(uHeight)); - assert(isPowerOf2(uDepth)); assert(isPowerOf2(uBlockSideLength)); assert(uBlockSideLength <= uWidth); assert(uBlockSideLength <= uHeight); assert(uBlockSideLength <= uDepth); //Release mode validation - if(!(isPowerOf2(uWidth) && isPowerOf2(uHeight) && isPowerOf2(uDepth))) - { - throw std::invalid_argument("Volume width, height, and depth must all be a power of two."); - } if(!isPowerOf2(uBlockSideLength)) { throw std::invalid_argument("Block side length must be a power of two."); @@ -98,20 +91,19 @@ namespace PolyVox //Compute the volume side lengths m_uWidth = uWidth; - m_uWidthPower = logBase2(m_uWidth); + //m_uWidthPower = logBase2(m_uWidth); m_uHeight = uHeight; - m_uHeightPower = logBase2(m_uHeight); + //m_uHeightPower = logBase2(m_uHeight); m_uDepth = uDepth; - m_uDepthPower = logBase2(m_uDepth); + //m_uDepthPower = logBase2(m_uDepth); //Compute the block side length m_uBlockSideLength = uBlockSideLength; m_uBlockSideLengthPower = logBase2(m_uBlockSideLength); - //Compute the side length in blocks - //m_uSideLengthInBlocks = m_uSideLength / m_uBlockSideLength; + //Compute the side lengths in blocks m_uWidthInBlocks = m_uWidth / m_uBlockSideLength; m_uHeightInBlocks = m_uHeight / m_uBlockSideLength; m_uDepthInBlocks = m_uDepth / m_uBlockSideLength; @@ -128,6 +120,11 @@ namespace PolyVox m_vecBlockIsPotentiallyHomogenous[i] = false; } + //Create the border block + std::shared_ptr< Block > pTempBlock(new Block(m_uBlockSideLength)); + pTempBlock->fill(VoxelType()); + m_pBorderBlock = pTempBlock; + //Other properties we might find useful later m_uLongestSideLength = (std::max)((std::max)(m_uWidth,m_uHeight),m_uDepth); m_uShortestSideLength = (std::min)((std::min)(m_uWidth,m_uHeight),m_uDepth); @@ -147,6 +144,18 @@ namespace PolyVox #pragma endregion #pragma region Getters + + template + //////////////////////////////////////////////////////////////////////////////// + /// The border value is returned whenever an atempt is made to read a voxel which + /// is outside the extents of the volume. + /// \return The value used for voxels outside of the volume + //////////////////////////////////////////////////////////////////////////////// + VoxelType Volume::getBorderValue(void) const + { + return m_pBorderBlock->getVoxelAt(0,0,0); + } + //////////////////////////////////////////////////////////////////////////////// /// The result will always have a lower corner at (0,0,0) and an upper corner at one /// less than the side length. For example, if a volume has dimensions 256x512x1024 @@ -231,7 +240,7 @@ namespace PolyVox /// \return the voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType Volume::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tDefault) const + VoxelType Volume::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const { //We don't use getEnclosingRegion here because we care //about speed and don't need to check the lower bound. @@ -256,7 +265,7 @@ namespace PolyVox } else { - return tDefault; + return getBorderValue(); } } @@ -273,6 +282,15 @@ namespace PolyVox #pragma endregion #pragma region Setters + //////////////////////////////////////////////////////////////////////////////// + /// \param tBorder The value to use for voxels outside the volume. + //////////////////////////////////////////////////////////////////////////////// + template + void Volume::setBorderValue(const VoxelType& tBorder) + { + return m_pBorderBlock->fill(tBorder); + } + //////////////////////////////////////////////////////////////////////////////// /// \param uXPos the \c x position of the voxel /// \param uYPos the \c y position of the voxel diff --git a/library/PolyVoxCore/include/VolumeSampler.inl b/library/PolyVoxCore/include/VolumeSampler.inl index 3143176d..8f03c466 100644 --- a/library/PolyVoxCore/include/VolumeSampler.inl +++ b/library/PolyVoxCore/include/VolumeSampler.inl @@ -156,15 +156,23 @@ namespace PolyVox const uint16_t uYPosInBlock = mYPosInVolume - (uYBlock << mVolume->m_uBlockSideLengthPower); const uint16_t uZPosInBlock = mZPosInVolume - (uZBlock << mVolume->m_uBlockSideLengthPower); - const uint32_t uBlockIndexInVolume = uXBlock + - uYBlock * mVolume->m_uWidthInBlocks + - uZBlock * mVolume->m_uWidthInBlocks * mVolume->m_uHeightInBlocks; - const std::shared_ptr< Block >& currentBlock = mVolume->m_pBlocks[uBlockIndexInVolume]; - const uint32_t uVoxelIndexInBlock = uXPosInBlock + - uYPosInBlock * mVolume->m_uBlockSideLength + - uZPosInBlock * mVolume->m_uBlockSideLength * mVolume->m_uBlockSideLength; - mCurrentVoxel = currentBlock->m_tData + uVoxelIndexInBlock; + uYPosInBlock * mVolume->m_uBlockSideLength + + uZPosInBlock * mVolume->m_uBlockSideLength * mVolume->m_uBlockSideLength; + + if((uXBlock < mVolume->m_uWidthInBlocks) && (uYBlock < mVolume->m_uHeightInBlocks) && (uZBlock < mVolume->m_uDepthInBlocks)) + { + const uint32_t uBlockIndexInVolume = uXBlock + + uYBlock * mVolume->m_uWidthInBlocks + + uZBlock * mVolume->m_uWidthInBlocks * mVolume->m_uHeightInBlocks; + const std::shared_ptr< Block >& currentBlock = mVolume->m_pBlocks[uBlockIndexInVolume]; + + mCurrentVoxel = currentBlock->m_tData + uVoxelIndexInBlock; + } + else + { + mCurrentVoxel = mVolume->m_pBorderBlock->m_tData + uVoxelIndexInBlock; + } } #pragma endregion @@ -172,8 +180,6 @@ namespace PolyVox template void VolumeSampler::movePositiveX(void) { - assert(mXPosInVolume < mVolume->m_uWidth - 1); - //Note the *pre* increament here if((++mXPosInVolume) % mVolume->m_uBlockSideLength != 0) { @@ -190,8 +196,6 @@ namespace PolyVox template void VolumeSampler::movePositiveY(void) { - assert(mYPosInVolume < mVolume->m_uHeight - 1); - //Note the *pre* increament here if((++mYPosInVolume) % mVolume->m_uBlockSideLength != 0) { @@ -208,8 +212,6 @@ namespace PolyVox template void VolumeSampler::movePositiveZ(void) { - assert(mZPosInVolume < mVolume->m_uDepth - 1); - //Note the *pre* increament here if((++mZPosInVolume) % mVolume->m_uBlockSideLength != 0) { @@ -226,8 +228,6 @@ namespace PolyVox template void VolumeSampler::moveNegativeX(void) { - assert(mXPosInVolume > 0); - //Note the *post* increament here if((mXPosInVolume--) % mVolume->m_uBlockSideLength != 0) { @@ -244,8 +244,6 @@ namespace PolyVox template void VolumeSampler::moveNegativeY(void) { - assert(mYPosInVolume > 0); - //Note the *post* increament here if((mYPosInVolume--) % mVolume->m_uBlockSideLength != 0) { @@ -262,8 +260,6 @@ namespace PolyVox template void VolumeSampler::moveNegativeZ(void) { - assert(mZPosInVolume > 0); - //Note the *post* increament here if((mZPosInVolume--) % mVolume->m_uBlockSideLength != 0) {