diff --git a/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.h b/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.h index e055778e..a87b92a5 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.h +++ b/library/PolyVoxCore/include/PolyVoxCore/BaseVolume.h @@ -41,11 +41,15 @@ namespace PolyVox enum BoundsCheck { None = 0, - Full = 1 + Full = 1, + ClampPos = 2, + BorderPos = 3 }; } typedef BoundsChecks::BoundsCheck BoundsCheck; + // Required for a trick to implement specialization of template member + // functions in template classes. See http://stackoverflow.com/a/4951057 template struct BoundsCheckType{}; namespace WrapModes diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/Config.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/Config.h index e97e27af..b852d165 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/Config.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/Config.h @@ -24,7 +24,7 @@ freely, subject to the following restrictions: #ifndef __PolyVox_Config_H__ #define __PolyVox_Config_H__ -#define POLYVOX_ASSERTS_ENABLED +//#define POLYVOX_ASSERTS_ENABLED #define POLYVOX_THROW_ENABLED #endif diff --git a/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.inl b/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.inl index 4d942519..79329a7f 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/LowPassFilter.inl @@ -192,8 +192,8 @@ namespace PolyVox { for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) { - AccumulationType previousSum = static_cast(satVolume.getVoxelAt(x,y-1,z)); - AccumulationType currentSum = static_cast(satVolume.getVoxelAt(x,y,z)); + AccumulationType previousSum = static_cast(satVolume.getVoxel(x,y-1,z, BoundsChecks::BorderPos)); + AccumulationType currentSum = static_cast(satVolume.getVoxel(x,y,z, BoundsChecks::BorderPos)); satVolume.setVoxelAt(x,y,z,previousSum + currentSum); } @@ -206,8 +206,8 @@ namespace PolyVox { for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) { - AccumulationType previousSum = static_cast(satVolume.getVoxelAt(x,y,z-1)); - AccumulationType currentSum = static_cast(satVolume.getVoxelAt(x,y,z)); + AccumulationType previousSum = static_cast(satVolume.getVoxel(x,y,z-1, BoundsChecks::BorderPos)); + AccumulationType currentSum = static_cast(satVolume.getVoxel(x,y,z, BoundsChecks::BorderPos)); satVolume.setVoxelAt(x,y,z,previousSum + currentSum); } @@ -234,14 +234,14 @@ namespace PolyVox int32_t satUpperY = iSrcY + border; int32_t satUpperZ = iSrcZ + border; - AccumulationType a = satVolume.getVoxelAt(satLowerX,satLowerY,satLowerZ); - AccumulationType b = satVolume.getVoxelAt(satUpperX,satLowerY,satLowerZ); - AccumulationType c = satVolume.getVoxelAt(satLowerX,satUpperY,satLowerZ); - AccumulationType d = satVolume.getVoxelAt(satUpperX,satUpperY,satLowerZ); - AccumulationType e = satVolume.getVoxelAt(satLowerX,satLowerY,satUpperZ); - AccumulationType f = satVolume.getVoxelAt(satUpperX,satLowerY,satUpperZ); - AccumulationType g = satVolume.getVoxelAt(satLowerX,satUpperY,satUpperZ); - AccumulationType h = satVolume.getVoxelAt(satUpperX,satUpperY,satUpperZ); + AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ, BoundsChecks::BorderPos); + AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ, BoundsChecks::BorderPos); + AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ, BoundsChecks::BorderPos); + AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ, BoundsChecks::BorderPos); + AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ, BoundsChecks::BorderPos); + AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ, BoundsChecks::BorderPos); + AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ, BoundsChecks::BorderPos); + AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ, BoundsChecks::BorderPos); AccumulationType sum = h+c-d-g-f-a+b+e; uint32_t sideLength = border * 2 + 1; diff --git a/library/PolyVoxCore/include/PolyVoxCore/RawVolume.h b/library/PolyVoxCore/include/PolyVoxCore/RawVolume.h index d1b821ad..14091c92 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/RawVolume.h +++ b/library/PolyVoxCore/include/PolyVoxCore/RawVolume.h @@ -117,12 +117,12 @@ namespace PolyVox /// Gets a voxel at the position given by x,y,z coordinates template - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; + VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const; /// Gets a voxel at the position given by x,y,z coordinates - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheck eBoundsCheck = BoundsChecks::Full) const; + VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheck eBoundsCheck = BoundsChecks::Full, VoxelType tBorder = VoxelType()) const; /// Gets a voxel at the position given by a 3D vector - VoxelType getVoxel(const Vector3DInt32& v3dPos, BoundsCheck eBoundsCheck = BoundsChecks::Full) const; + VoxelType getVoxel(const Vector3DInt32& v3dPos, BoundsCheck eBoundsCheck = BoundsChecks::Full, VoxelType tBorder = VoxelType()) const; /// Gets a voxel at the position given by x,y,z coordinates VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; /// Gets a voxel at the position given by a 3D vector @@ -155,9 +155,11 @@ namespace PolyVox void initialise(const Region& regValidRegion); template - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType) const; + VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const; + VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const; + VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const; + VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const; + VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const; //The block data VoxelType* m_pData; diff --git a/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl index a81799ae..fa323173 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/RawVolume.inl @@ -84,10 +84,10 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// template template - VoxelType RawVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const + VoxelType RawVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const { // Simply call through to the real implementation - return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType()); + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); } //////////////////////////////////////////////////////////////////////////////// @@ -100,19 +100,29 @@ namespace PolyVox /// \return The voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType RawVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheck eBoundsCheck) const + VoxelType RawVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheck eBoundsCheck, VoxelType tBorder) const { // If bounds checking is enabled then we validate the // bounds, and throw an exception if they are violated. if(eBoundsCheck == BoundsChecks::Full) { // Call through to the real implementation - return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType()); + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); + } + else if(eBoundsCheck == BoundsChecks::None) + { + // Call through to the real implementation + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); + } + else if(eBoundsCheck == BoundsChecks::ClampPos) + { + // Call through to the real implementation + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); } else { // Call through to the real implementation - return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType()); + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); } } @@ -124,9 +134,9 @@ namespace PolyVox /// is inside the volume's enclosing region then you can skip this check to gain some performance. //////////////////////////////////////////////////////////////////////////////// template - VoxelType RawVolume::getVoxel(const Vector3DInt32& v3dPos, BoundsCheck eBoundsCheck) const + VoxelType RawVolume::getVoxel(const Vector3DInt32& v3dPos, BoundsCheck eBoundsCheck, VoxelType tBorder) const { - return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eBoundsCheck); + return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eBoundsCheck, tBorder); } //////////////////////////////////////////////////////////////////////////////// @@ -357,24 +367,24 @@ namespace PolyVox template template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType) const + VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const { POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!"); } template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType) const + VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const { if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) { POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); } - return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType()); + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); } template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType) const + VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const { const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner(); int32_t iLocalXPos = uXPos - v3dLowerCorner.getX(); @@ -388,5 +398,32 @@ namespace PolyVox iLocalZPos * this->getWidth() * this->getHeight() ]; } + + template + VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const + { + //Perform clamping + uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX()); + uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY()); + uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ()); + uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX()); + uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY()); + uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ()); + + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); + } + + template + VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType) const + { + if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) + { + return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType()); // No bounds checks as we've just validated the position. + } + else + { + return tBorder; //FIXME - Should return border value. + } + } }