diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 2627cd7b..5de989ae 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -26,14 +26,14 @@ freely, subject to the following restrictions: #include "PolyVox/CubicSurfaceExtractor.h" #include "PolyVox/MarchingCubesSurfaceExtractor.h" #include "PolyVox/Mesh.h" -#include "PolyVox/PagedVolume.h" +#include "PolyVox/RawVolume.h" #include //Use the PolyVox namespace using namespace PolyVox; -void createSphereInVolume(PagedVolume& volData, float fRadius) +void createSphereInVolume(RawVolume& volData, float fRadius) { //This vector hold the position of the center of the volume Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2); @@ -60,7 +60,7 @@ void createSphereInVolume(PagedVolume& volData, float fRadius) } //Wrte the voxel value into the volume - volData.setVoxelAt(x, y, z, uVoxelValue); + volData.setVoxel(x, y, z, uVoxelValue); } } } @@ -78,7 +78,7 @@ protected: void initializeExample() override { // Create an empty volume and then place a sphere in it - PagedVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63))); + RawVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63))); createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index 158bcfec..f61bd242 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -26,14 +26,14 @@ freely, subject to the following restrictions: #include "PolyVox/CubicSurfaceExtractor.h" #include "PolyVox/MarchingCubesSurfaceExtractor.h" #include "PolyVox/Mesh.h" -#include "PolyVox/PagedVolume.h" +#include "PolyVox/RawVolume.h" #include //Use the PolyVox namespace using namespace PolyVox; -void createSphereInVolume(PagedVolume& volData, float fRadius) +void createSphereInVolume(RawVolume& volData, float fRadius) { //This vector hold the position of the center of the volume Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2); @@ -60,7 +60,7 @@ void createSphereInVolume(PagedVolume& volData, float fRadius) } //Wrte the voxel value into the volume - volData.setVoxelAt(x, y, z, uVoxelValue); + volData.setVoxel(x, y, z, uVoxelValue); } } } @@ -94,7 +94,7 @@ protected: setShader(shader); //Create an empty volume and then place a sphere in it - PagedVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63))); + RawVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63))); createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. diff --git a/examples/OpenGL/Shapes.cpp b/examples/OpenGL/Shapes.cpp index 1ebe6e58..8821e7fb 100644 --- a/examples/OpenGL/Shapes.cpp +++ b/examples/OpenGL/Shapes.cpp @@ -27,7 +27,7 @@ freely, subject to the following restrictions: using namespace PolyVox; -void createSphereInVolume(PagedVolume& volData, float fRadius, uint8_t uValue) +void createSphereInVolume(RawVolume& volData, float fRadius, uint8_t uValue) { //This vector hold the position of the center of the volume Vector3DInt32 v3dVolCenter = (volData.getEnclosingRegion().getUpperCorner() - volData.getEnclosingRegion().getLowerCorner()) / static_cast(2); @@ -48,14 +48,14 @@ void createSphereInVolume(PagedVolume& volData, float fRa //then we make it solid, otherwise we make it empty space. if(fDistToCenter <= fRadius) { - volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? MaterialDensityPair88::getMaxDensity() : MaterialDensityPair88::getMinDensity())); + volData.setVoxel(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? MaterialDensityPair88::getMaxDensity() : MaterialDensityPair88::getMinDensity())); } } } } } -void createCubeInVolume(PagedVolume& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue) +void createCubeInVolume(RawVolume& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue) { uint8_t maxDen = MaterialDensityPair88::getMaxDensity(); uint8_t minDen = MaterialDensityPair88::getMinDensity(); @@ -66,7 +66,7 @@ void createCubeInVolume(PagedVolume& volData, Vector3DInt { for (int x = lowerCorner.getX() ; x <= upperCorner.getX(); x++) { - volData.setVoxelAt(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? maxDen : minDen)); + volData.setVoxel(x,y,z, MaterialDensityPair88(uValue, uValue > 0 ? maxDen : minDen)); } } } diff --git a/examples/OpenGL/Shapes.h b/examples/OpenGL/Shapes.h index f2f5b193..4ff84883 100644 --- a/examples/OpenGL/Shapes.h +++ b/examples/OpenGL/Shapes.h @@ -24,10 +24,10 @@ freely, subject to the following restrictions: #ifndef __OpenGLExample_Shapes_H__ #define __OpenGLExample_Shapes_H__ -#include "PolyVox/PagedVolume.h" +#include "PolyVox/RawVolume.h" #include "PolyVox/MaterialDensityPair.h" -void createSphereInVolume(PolyVox::LargeVolume& volData, float fRadius, uint8_t uValue); -void createCubeInVolume(PolyVox::LargeVolume& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue); +void createSphereInVolume(PolyVox::RawVolume& volData, float fRadius, uint8_t uValue); +void createCubeInVolume(PolyVox::RawVolume& volData, PolyVox::Vector3DInt32 lowerCorner, PolyVox::Vector3DInt32 upperCorner, uint8_t uValue); #endif //__OpenGLExample_Shapes_H__ \ No newline at end of file diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index e39249f0..f73a1b8e 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -58,8 +58,7 @@ public: protected: void initializeExample() override { - FilePager* pager = new FilePager("."); - PagedVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1)), pager); + RawVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1))); //Make our volume contain a sphere in the center. int32_t minPos = 0; diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 415a466d..3cb5415c 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -67,7 +67,7 @@ void createSphereInVolume(PagedVolume& volData, Vector3DF voxel.setDensity(uDensity); //Wrte the voxel value into the volume - volData.setVoxelAt(x, y, z, voxel); + volData.setVoxel(x, y, z, voxel); } } } @@ -127,7 +127,7 @@ public: // Voxel position within a chunk always start from zero. So if a chunk represents region (4, 8, 12) to (11, 19, 15) // then the valid chunk voxels are from (0, 0, 0) to (7, 11, 3). Hence we subtract the lower corner position of the // region from the volume space position in order to get the chunk space position. - pChunk->setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel); + pChunk->setVoxel(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel); } } } @@ -151,8 +151,7 @@ protected: void initializeExample() override { PerlinNoisePager* pager = new PerlinNoisePager(); - PagedVolume volData(PolyVox::Region::MaxRegion(), pager, 64); - volData.setMemoryUsageLimit(8 * 1024 * 1024); // 8Mb + PagedVolume volData(pager, 8 * 1024 * 1024, 64); //createSphereInVolume(volData, 30); //createPerlinTerrain(volData); diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index 57cfcd90..7279f0c7 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -27,7 +27,6 @@ freely, subject to the following restrictions: #include "PolyVox/MarchingCubesSurfaceExtractor.h" #include "PolyVox/Mesh.h" #include "PolyVox/RawVolume.h" -#include "PolyVox/PagedVolume.h" #include "PolyVox/VolumeResampler.h" #include @@ -35,7 +34,7 @@ freely, subject to the following restrictions: //Use the PolyVox namespace using namespace PolyVox; -void createSphereInVolume(PagedVolume& volData, float fRadius) +void createSphereInVolume(RawVolume& volData, float fRadius) { //This vector hold the position of the center of the volume Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2); @@ -58,11 +57,11 @@ void createSphereInVolume(PagedVolume& volData, float fRadius) uint8_t uDensity = std::numeric_limits::max(); //Wrte the voxel value into the volume - volData.setVoxelAt(x, y, z, uDensity); + volData.setVoxel(x, y, z, uDensity); } //144 in the middle, (144 - 32) at the edges. Threshold of 128 is between these - //volData.setVoxelAt(x, y, z, 144 - fDistToCenter); + //volData.setVoxel(x, y, z, 144 - fDistToCenter); } } } @@ -80,7 +79,7 @@ protected: void initializeExample() override { //Create an empty volume and then place a sphere in it - PagedVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63))); + RawVolume volData(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(63, 63, 63))); createSphereInVolume(volData, 28); //Smooth the data - should reimplement this using LowPassFilter @@ -90,7 +89,7 @@ protected: RawVolume volDataLowLOD(PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(15, 31, 31))); - VolumeResampler< PagedVolume, RawVolume > volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion()); + VolumeResampler< RawVolume, RawVolume > volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0, 0, 0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion()); volumeResampler.execute(); //Extract the surface diff --git a/include/PolyVox/AmbientOcclusionCalculator.h b/include/PolyVox/AmbientOcclusionCalculator.h index 2560127d..bdd10de7 100644 --- a/include/PolyVox/AmbientOcclusionCalculator.h +++ b/include/PolyVox/AmbientOcclusionCalculator.h @@ -33,7 +33,7 @@ freely, subject to the following restrictions: //These two should not be here! #include "PolyVox/Material.h" -#include "PolyVox/PagedVolume.h" +#include "PolyVox/RawVolume.h" #include @@ -53,7 +53,7 @@ namespace PolyVox { } - bool operator()(const PagedVolume::Sampler& sampler) + bool operator()(const RawVolume::Sampler& sampler) { uint8_t sample = sampler.getVoxel(); bool func = mIsVoxelTransparentCallback(sample); diff --git a/include/PolyVox/Array.h b/include/PolyVox/Array.h index 68f54db5..2a34bc4f 100644 --- a/include/PolyVox/Array.h +++ b/include/PolyVox/Array.h @@ -98,7 +98,7 @@ namespace PolyVox return m_pElements[z * m_uDimensions[0] * m_uDimensions[1] + y * m_uDimensions[0] + x]; } - uint32_t getDimension(uint32_t dimension) + uint32_t getDimension(uint32_t dimension) const { return m_uDimensions[dimension]; } diff --git a/include/PolyVox/BaseVolume.h b/include/PolyVox/BaseVolume.h index 57898ffb..b0a0c8cc 100644 --- a/include/PolyVox/BaseVolume.h +++ b/include/PolyVox/BaseVolume.h @@ -36,23 +36,6 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// More details to come... //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - namespace WrapModes - { - enum WrapMode - { - Validate = 0, - Clamp = 1, - Border = 2, - AssumeValid = 3 - }; - } - typedef WrapModes::WrapMode WrapMode; - - // Required for a trick to implement specialization of template member - // functions in template classes. See http://stackoverflow.com/a/4951057 - template struct WrapModeType{}; - template class BaseVolume { @@ -70,12 +53,9 @@ namespace PolyVox Vector3DInt32 getPosition(void) const; inline VoxelType getVoxel(void) const; - bool isCurrentPositionValid(void) const; - void setPosition(const Vector3DInt32& v3dNewPos); void setPosition(int32_t xPos, int32_t yPos, int32_t zPos); inline bool setVoxel(VoxelType tValue); - void setWrapMode(WrapMode eWrapMode, VoxelType tBorder = VoxelType()); void movePositiveX(void); void movePositiveY(void); @@ -116,7 +96,6 @@ namespace PolyVox inline VoxelType peekVoxel1px1py1pz(void) const; protected: - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; DerivedVolumeType* mVolume; @@ -124,70 +103,26 @@ namespace PolyVox int32_t mXPosInVolume; int32_t mYPosInVolume; int32_t mZPosInVolume; - - WrapMode m_eWrapMode; - VoxelType m_tBorder; - - //Whether the current position is inside the volume - //FIXME - Replace these with flags - bool m_bIsCurrentPositionValidInX; - bool m_bIsCurrentPositionValidInY; - bool m_bIsCurrentPositionValidInZ; }; #endif public: - /// Gets the value used for voxels which are outside the volume - VoxelType getBorderValue(void) const; - /// Gets a Region representing the extents of the Volume. - const Region& getEnclosingRegion(void) const; - /// Gets the width of the volume in voxels. - int32_t getWidth(void) const; - /// Gets the height of the volume in voxels. - int32_t getHeight(void) const; - /// Gets the depth of the volume in voxels. - int32_t getDepth(void) const; - /// Gets the length of the longest side in voxels - int32_t getLongestSideLength(void) const; - /// Gets the length of the shortest side in voxels - int32_t getShortestSideLength(void) const; - /// Gets the length of the diagonal in voxels - float getDiagonalLength(void) const; - /// Gets a voxel at the position given by x,y,z coordinates - template - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const; + VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; /// Gets a voxel at the position given by a 3D vector - template - VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const; + VoxelType getVoxel(const Vector3DInt32& v3dPos) const; - /// Gets a voxel at the position given by x,y,z coordinates - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; - /// Gets a voxel at the position given by a 3D vector - VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; - - /// Gets a voxel at the position given by x,y,z coordinates - POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; - /// Gets a voxel at the position given by a 3D vector - POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; - - /// Sets the value used for voxels which are outside the volume - void setBorderValue(const VoxelType& tBorder); /// Sets the voxel at the position given by x,y,z coordinates - void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); + void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue); /// Sets the voxel at the position given by a 3D vector - void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); - /// Sets the voxel at the position given by x,y,z coordinates - bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue); - /// Sets the voxel at the position given by a 3D vector - bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue); + void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue); /// Calculates approximatly how many bytes of memory the volume is currently using. uint32_t calculateSizeInBytes(void); protected: - /// Constructor for creating a fixed size volume. - BaseVolume(const Region& regValid); + /// Constructor for creating a volume. + BaseVolume(); /// Copy constructor BaseVolume(const BaseVolume& rhs); @@ -197,17 +132,6 @@ namespace PolyVox /// Assignment operator BaseVolume& operator=(const BaseVolume& rhs); - - //The size of the volume - Region m_regValidRegion; - - //Some useful sizes - int32_t m_uLongestSideLength; - int32_t m_uShortestSideLength; - float m_fDiagonalLength; - - //The border value - VoxelType m_tBorderValue; }; } diff --git a/include/PolyVox/BaseVolume.inl b/include/PolyVox/BaseVolume.inl index 4f2d8121..f3fcfd06 100644 --- a/include/PolyVox/BaseVolume.inl +++ b/include/PolyVox/BaseVolume.inl @@ -29,9 +29,7 @@ namespace PolyVox /// \sa RawVolume, PagedVolume //////////////////////////////////////////////////////////////////////////////// template - BaseVolume::BaseVolume(const Region& regValid) - :m_regValidRegion(regValid) - ,m_tBorderValue() + BaseVolume::BaseVolume() { } @@ -45,7 +43,7 @@ namespace PolyVox template BaseVolume::BaseVolume(const BaseVolume& /*rhs*/) { - POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons."); + POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented to prevent accidental copying."); } //////////////////////////////////////////////////////////////////////////////// @@ -66,127 +64,7 @@ namespace PolyVox template BaseVolume& BaseVolume::operator=(const BaseVolume& /*rhs*/) { - POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons."); - } - - //////////////////////////////////////////////////////////////////////////////// - /// The border value is returned whenever an attempt is made to read a voxel which - /// is outside the extents of the volume. - /// \return The value used for voxels outside of the volume - //////////////////////////////////////////////////////////////////////////////// - template - VoxelType BaseVolume::getBorderValue(void) const - { - return m_tBorderValue; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \return A Region representing the extent of the volume. - //////////////////////////////////////////////////////////////////////////////// - template - const Region& BaseVolume::getEnclosingRegion(void) const - { - return m_regValidRegion; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \return The width of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the width is 64. - /// \sa getHeight(), getDepth() - //////////////////////////////////////////////////////////////////////////////// - template - int32_t BaseVolume::getWidth(void) const - { - return m_regValidRegion.getUpperX() - m_regValidRegion.getLowerX() + 1; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \return The height of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the height is 64. - /// \sa getWidth(), getDepth() - //////////////////////////////////////////////////////////////////////////////// - template - int32_t BaseVolume::getHeight(void) const - { - return m_regValidRegion.getUpperY() - m_regValidRegion.getLowerY() + 1; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \return The depth of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the depth is 64. - /// \sa getWidth(), getHeight() - //////////////////////////////////////////////////////////////////////////////// - template - int32_t BaseVolume::getDepth(void) const - { - return m_regValidRegion.getUpperZ() - m_regValidRegion.getLowerZ() + 1; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \return The length of the shortest side in voxels. For example, if a volume has - /// dimensions 256x512x1024 this function will return 256. - /// \sa getLongestSideLength(), getDiagonalLength() - //////////////////////////////////////////////////////////////////////////////// - template - int32_t BaseVolume::getShortestSideLength(void) const - { - return m_uShortestSideLength; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \return The length of the longest side in voxels. For example, if a volume has - /// dimensions 256x512x1024 this function will return 1024. - /// \sa getShortestSideLength(), getDiagonalLength() - //////////////////////////////////////////////////////////////////////////////// - template - int32_t BaseVolume::getLongestSideLength(void) const - { - return m_uLongestSideLength; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \return The length of the diagonal in voxels. For example, if a volume has - /// dimensions 256x512x1024 this function will return sqrt(256*256+512*512+1024*1024) - /// = 1173.139. This value is computed on volume creation so retrieving it is fast. - /// \sa getShortestSideLength(), getLongestSideLength() - //////////////////////////////////////////////////////////////////////////////// - template - float BaseVolume::getDiagonalLength(void) const - { - return m_fDiagonalLength; - } - - //////////////////////////////////////////////////////////////////////////////// - /// This version of the function requires the wrap mode to be specified as a - /// template parameter, which can provide better performance. - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - template - VoxelType BaseVolume::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tBorder*/) const - { - POLYVOX_ASSERT(false, "You should never call the base class version of this function."); - return VoxelType(); - } - - //////////////////////////////////////////////////////////////////////////////// - /// This version of the function requires the wrap mode to be specified as a - /// template parameter, which can provide better performance. - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - template - VoxelType BaseVolume::getVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tBorder*/) const - { - POLYVOX_ASSERT(false, "You should never call the base class version of this function."); - return VoxelType(); + POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented to prevent accidental copying."); } //////////////////////////////////////////////////////////////////////////////// @@ -195,12 +73,10 @@ namespace PolyVox /// \param uXPos The \c x position of the voxel /// \param uYPos The \c y position of the voxel /// \param uZPos The \c z position of the voxel - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. /// \return The voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType BaseVolume::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const + VoxelType BaseVolume::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const { POLYVOX_ASSERT(false, "You should never call the base class version of this function."); return VoxelType(); @@ -210,50 +86,15 @@ namespace PolyVox /// This version of the function is provided so that the wrap mode does not need /// to be specified as a template parameter, as it may be confusing to some users. /// \param v3dPos The 3D position of the voxel - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. /// \return The voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType BaseVolume::getVoxel(const Vector3DInt32& /*v3dPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const + VoxelType BaseVolume::getVoxel(const Vector3DInt32& /*v3dPos*/) const { POLYVOX_ASSERT(false, "You should never call the base class version of this function."); return VoxelType(); } - //////////////////////////////////////////////////////////////////////////////// - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - VoxelType BaseVolume::getVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const - { - POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); - return VoxelType(); - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param v3dPos The 3D position of the voxel - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - VoxelType BaseVolume::getVoxelAt(const Vector3DInt32& /*v3dPos*/) const - { - POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); - return VoxelType(); - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param tBorder The value to use for voxels outside the volume. - //////////////////////////////////////////////////////////////////////////////// - template - void BaseVolume::setBorderValue(const VoxelType& tBorder) - { - m_tBorderValue = tBorder; - } - //////////////////////////////////////////////////////////////////////////////// /// \param uXPos the \c x position of the voxel /// \param uYPos the \c y position of the voxel @@ -261,7 +102,7 @@ namespace PolyVox /// \param tValue the value to which the voxel will be set //////////////////////////////////////////////////////////////////////////////// template - void BaseVolume::setVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/) + void BaseVolume::setVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/) { POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); } @@ -271,37 +112,11 @@ namespace PolyVox /// \param tValue the value to which the voxel will be set //////////////////////////////////////////////////////////////////////////////// template - void BaseVolume::setVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/, WrapMode /*eWrapMode*/) + void BaseVolume::setVoxel(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/) { POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); } - //////////////////////////////////////////////////////////////////////////////// - /// \param uXPos the \c x position of the voxel - /// \param uYPos the \c y position of the voxel - /// \param uZPos the \c z position of the voxel - /// \param tValue the value to which the voxel will be set - /// \return whether the requested position is inside the volume - //////////////////////////////////////////////////////////////////////////////// - template - bool BaseVolume::setVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/) - { - POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); - return false; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param v3dPos the 3D position of the voxel - /// \param tValue the value to which the voxel will be set - /// \return whether the requested position is inside the volume - //////////////////////////////////////////////////////////////////////////////// - template - bool BaseVolume::setVoxelAt(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/) - { - POLYVOX_THROW(not_implemented, "You should never call the base class version of this function."); - return false; - } - //////////////////////////////////////////////////////////////////////////////// /// Note: This function needs reviewing for accuracy... //////////////////////////////////////////////////////////////////////////////// diff --git a/include/PolyVox/BaseVolumeSampler.inl b/include/PolyVox/BaseVolumeSampler.inl index 993113a3..ccd14410 100644 --- a/include/PolyVox/BaseVolumeSampler.inl +++ b/include/PolyVox/BaseVolumeSampler.inl @@ -32,11 +32,6 @@ namespace PolyVox ,mXPosInVolume(0) ,mYPosInVolume(0) ,mZPosInVolume(0) - ,m_eWrapMode(WrapModes::Border) - ,m_tBorder() - ,m_bIsCurrentPositionValidInX(false) - ,m_bIsCurrentPositionValidInY(false) - ,m_bIsCurrentPositionValidInZ(false) { } @@ -57,14 +52,7 @@ namespace PolyVox template VoxelType BaseVolume::Sampler::getVoxel(void) const { - return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume, WrapModes::Validate); // FIXME - Use templatised version instead but watch for Linux compile errors. - } - - template - template - bool inline BaseVolume::Sampler::isCurrentPositionValid(void) const - { - return m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ; + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume); } template @@ -81,25 +69,13 @@ namespace PolyVox mXPosInVolume = xPos; mYPosInVolume = yPos; mZPosInVolume = zPos; - - m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(xPos); - m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(yPos); - m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(zPos); } template template bool BaseVolume::Sampler::setVoxel(VoxelType tValue) { - return mVolume->setVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume, tValue); - } - - template - template - void BaseVolume::Sampler::setWrapMode(WrapMode eWrapMode, VoxelType tBorder) - { - m_eWrapMode = eWrapMode; - m_tBorder = tBorder; + return mVolume->setVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume, tValue); } template @@ -107,7 +83,6 @@ namespace PolyVox void BaseVolume::Sampler::movePositiveX(void) { mXPosInVolume++; - m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume); } template @@ -115,7 +90,6 @@ namespace PolyVox void BaseVolume::Sampler::movePositiveY(void) { mYPosInVolume++; - m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume); } template @@ -123,7 +97,6 @@ namespace PolyVox void BaseVolume::Sampler::movePositiveZ(void) { mZPosInVolume++; - m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume); } template @@ -131,7 +104,6 @@ namespace PolyVox void BaseVolume::Sampler::moveNegativeX(void) { mXPosInVolume--; - m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume); } template @@ -139,7 +111,6 @@ namespace PolyVox void BaseVolume::Sampler::moveNegativeY(void) { mYPosInVolume--; - m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume); } template @@ -147,70 +118,69 @@ namespace PolyVox void BaseVolume::Sampler::moveNegativeZ(void) { mZPosInVolume--; - m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx1ny1nz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx1ny0pz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx1ny1pz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume - 1, mZPosInVolume + 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx0py1nz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx0py0pz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx0py1pz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume , mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume, mZPosInVolume + 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx1py1nz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx1py0pz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel1nx1py1pz(void) const { - return getVoxelImpl(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume - 1, mYPosInVolume + 1, mZPosInVolume + 1); } ////////////////////////////////////////////////////////////////////////// @@ -219,63 +189,63 @@ namespace PolyVox template VoxelType BaseVolume::Sampler::peekVoxel0px1ny1nz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume - 1, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel0px1ny0pz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume - 1, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel0px1ny1pz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume - 1, mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume - 1, mZPosInVolume + 1); } template template VoxelType BaseVolume::Sampler::peekVoxel0px0py1nz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel0px0py0pz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel0px0py1pz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume , mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume, mZPosInVolume + 1); } template template VoxelType BaseVolume::Sampler::peekVoxel0px1py1nz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume + 1, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel0px1py0pz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume + 1, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel0px1py1pz(void) const { - return getVoxelImpl(mXPosInVolume , mYPosInVolume + 1, mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume, mYPosInVolume + 1, mZPosInVolume + 1); } ////////////////////////////////////////////////////////////////////////// @@ -284,83 +254,62 @@ namespace PolyVox template VoxelType BaseVolume::Sampler::peekVoxel1px1ny1nz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1px1ny0pz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel1px1ny1pz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume - 1, mZPosInVolume + 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1px0py1nz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1px0py0pz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel1px0py1pz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume , mZPosInVolume + 1); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume, mZPosInVolume + 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1px1py1nz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume - 1); } template template VoxelType BaseVolume::Sampler::peekVoxel1px1py0pz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume ); + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume); } template template VoxelType BaseVolume::Sampler::peekVoxel1px1py1pz(void) const { - return getVoxelImpl(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1); - } - - template - template - VoxelType BaseVolume::Sampler::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos) const - { - switch(m_eWrapMode) - { - case WrapModes::Validate: - return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Validate, m_tBorder); - case WrapModes::Clamp: - return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Clamp, m_tBorder); - case WrapModes::Border: - return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::Border, m_tBorder); - case WrapModes::AssumeValid: - return mVolume->getVoxel(uXPos, uYPos, uZPos, WrapModes::AssumeValid, m_tBorder); - default: - // Should never happen - POLYVOX_ASSERT(false, "Invalid wrap mode"); - return VoxelType(); - } + return mVolume->getVoxel(mXPosInVolume + 1, mYPosInVolume + 1, mZPosInVolume + 1); } } diff --git a/include/PolyVox/CubicSurfaceExtractor.h b/include/PolyVox/CubicSurfaceExtractor.h index b0855061..19f726b7 100644 --- a/include/PolyVox/CubicSurfaceExtractor.h +++ b/include/PolyVox/CubicSurfaceExtractor.h @@ -112,7 +112,7 @@ namespace PolyVox }; public: - CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true); + CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), bool bMergeQuads = true); void execute(); @@ -147,10 +147,6 @@ namespace PolyVox //This constant defines the maximum number of quads which can share a //vertex in a cubic style mesh. See the initialisation for more details. static const uint32_t MaxVerticesPerPosition; - - //The wrap mode - WrapMode m_eWrapMode; - typename VolumeType::VoxelType m_tBorderValue; }; // This version of the function performs the extraction into a user-provided mesh rather than allocating a mesh automatically. @@ -167,9 +163,9 @@ namespace PolyVox // are provided (would the third parameter be a controller or a mesh?). It seems this can be fixed by using enable_if/static_assert to emulate concepts, // but this is relatively complex and I haven't done it yet. Could always add it later as another overload. template > - void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true) + void extractCubicMeshCustom(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), bool bMergeQuads = true) { - CubicSurfaceExtractor extractor(volData, region, result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads); + CubicSurfaceExtractor extractor(volData, region, result, isQuadNeeded, bMergeQuads); extractor.execute(); } @@ -215,10 +211,10 @@ namespace PolyVox /// Another scenario which sometimes results in confusion is when you wish to extract a region which corresponds to the whole volume, partcularly when solid voxels extend right to the edge of the volume. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template > - Mesh > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true) + Mesh > extractCubicMesh(VolumeType* volData, Region region, IsQuadNeeded isQuadNeeded = IsQuadNeeded(), bool bMergeQuads = true) { Mesh< CubicVertex > result; - extractCubicMeshCustom(volData, region, &result, isQuadNeeded, eWrapMode, tBorderValue, bMergeQuads); + extractCubicMeshCustom(volData, region, &result, isQuadNeeded, bMergeQuads); return result; } } diff --git a/include/PolyVox/CubicSurfaceExtractor.inl b/include/PolyVox/CubicSurfaceExtractor.inl index 6eefe3ec..24ea0609 100644 --- a/include/PolyVox/CubicSurfaceExtractor.inl +++ b/include/PolyVox/CubicSurfaceExtractor.inl @@ -36,15 +36,13 @@ namespace PolyVox const uint32_t CubicSurfaceExtractor::MaxVerticesPerPosition = 8; template - CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, IsQuadNeeded isQuadNeeded, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads) + 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_eWrapMode(eWrapMode) - ,m_tBorderValue(tBorderValue) { m_funcIsQuadNeededCallback = isQuadNeeded; @@ -80,7 +78,6 @@ namespace PolyVox m_vecQuads[PositiveZ].resize(m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ() + 2); typename VolumeType::Sampler volumeSampler(m_volData); - volumeSampler.setWrapMode(m_eWrapMode, m_tBorderValue); for(int32_t z = m_regSizeInVoxels.getLowerZ(); z <= m_regSizeInVoxels.getUpperZ(); z++) { diff --git a/include/PolyVox/FilePager.h b/include/PolyVox/FilePager.h index 19c8ca62..04eb3b04 100644 --- a/include/PolyVox/FilePager.h +++ b/include/PolyVox/FilePager.h @@ -117,6 +117,11 @@ namespace PolyVox else { POLYVOX_LOG_TRACE("No data found for " << region << " during paging in."); + + // Just fill with zeros. This feels hacky... perhaps we should just throw + // an exception and let the calling code handle it and fill with zeros. + uint32_t noOfVoxels = region.getWidthInVoxels() * region.getHeightInVoxels() * region.getDepthInVoxels(); + std::fill(pChunk->getData(), pChunk->getData() + noOfVoxels, VoxelType()); } } diff --git a/include/PolyVox/Impl/Config.h b/include/PolyVox/Impl/Config.h index 4a39a615..1959a6d2 100644 --- a/include/PolyVox/Impl/Config.h +++ b/include/PolyVox/Impl/Config.h @@ -25,13 +25,13 @@ freely, subject to the following restrictions: #define __PolyVox_Config_H__ //#define POLYVOX_LOG_TRACE_ENABLED -#define POLYVOX_LOG_DEBUG_ENABLED +//#define POLYVOX_LOG_DEBUG_ENABLED #define POLYVOX_LOG_INFO_ENABLED #define POLYVOX_LOG_WARNING_ENABLED #define POLYVOX_LOG_ERROR_ENABLED #define POLYVOX_LOG_FATAL_ENABLED -#define POLYVOX_ASSERTS_ENABLED +//#define POLYVOX_ASSERTS_ENABLED #define POLYVOX_THROW_ENABLED #endif diff --git a/include/PolyVox/Impl/Timer.h b/include/PolyVox/Impl/Timer.h index 9ad25bc6..20d3a36b 100644 --- a/include/PolyVox/Impl/Timer.h +++ b/include/PolyVox/Impl/Timer.h @@ -52,13 +52,13 @@ namespace PolyVox return elapsed_seconds.count(); } - uint32_t elapsedTimeInMilliSeconds(void) + float elapsedTimeInMilliSeconds(void) { std::chrono::duration elapsed_milliseconds = clock::now() - m_start; return elapsed_milliseconds.count(); } - uint32_t elapsedTimeInMicroSeconds(void) + float elapsedTimeInMicroSeconds(void) { std::chrono::duration elapsed_microseconds = clock::now() - m_start; return elapsed_microseconds.count(); diff --git a/include/PolyVox/LowPassFilter.inl b/include/PolyVox/LowPassFilter.inl index d4211f44..b79cd69a 100644 --- a/include/PolyVox/LowPassFilter.inl +++ b/include/PolyVox/LowPassFilter.inl @@ -114,7 +114,7 @@ namespace PolyVox tSrcVoxel /= 27; //tSrcVoxel.setDensity(uDensity); - m_pVolDst->setVoxelAt(iSrcX, iSrcY, iSrcZ, static_cast(tSrcVoxel)); + m_pVolDst->setVoxel(iSrcX, iSrcY, iSrcZ, static_cast(tSrcVoxel)); } } } @@ -141,7 +141,7 @@ namespace PolyVox { for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) { - satVolume.setVoxelAt(x,y,z,0); + satVolume.setVoxel(x,y,z,0); } } } @@ -178,10 +178,10 @@ namespace PolyVox { for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) { - AccumulationType previousSum = static_cast(satVolume.getVoxelAt(x-1,y,z)); - AccumulationType currentVal = static_cast(m_pVolSrc->getVoxelAt(x,y,z)); + AccumulationType previousSum = static_cast(satVolume.getVoxel(x-1,y,z)); + AccumulationType currentVal = static_cast(m_pVolSrc->getVoxel(x,y,z)); - satVolume.setVoxelAt(x,y,z,previousSum + currentVal); + satVolume.setVoxel(x,y,z,previousSum + currentVal); } } }*/ @@ -192,10 +192,10 @@ namespace PolyVox { for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) { - AccumulationType previousSum = static_cast(satVolume.getVoxel(x,y-1,z, WrapModes::Border)); - AccumulationType currentSum = static_cast(satVolume.getVoxel(x,y,z, WrapModes::Border)); + AccumulationType previousSum = static_cast(satVolume.getVoxel(x,y-1,z)); + AccumulationType currentSum = static_cast(satVolume.getVoxel(x,y,z)); - satVolume.setVoxelAt(x,y,z,previousSum + currentSum); + satVolume.setVoxel(x,y,z,previousSum + currentSum); } } } @@ -206,10 +206,10 @@ namespace PolyVox { for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) { - AccumulationType previousSum = static_cast(satVolume.getVoxel(x,y,z-1, WrapModes::Border)); - AccumulationType currentSum = static_cast(satVolume.getVoxel(x,y,z, WrapModes::Border)); + AccumulationType previousSum = static_cast(satVolume.getVoxel(x,y,z-1)); + AccumulationType currentSum = static_cast(satVolume.getVoxel(x,y,z)); - satVolume.setVoxelAt(x,y,z,previousSum + currentSum); + satVolume.setVoxel(x,y,z,previousSum + currentSum); } } } @@ -234,20 +234,20 @@ namespace PolyVox int32_t satUpperY = iSrcY + border; int32_t satUpperZ = iSrcZ + border; - AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ, WrapModes::Border); - AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ, WrapModes::Border); - AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ, WrapModes::Border); - AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ, WrapModes::Border); - AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ, WrapModes::Border); - AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ, WrapModes::Border); - AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ, WrapModes::Border); - AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ, WrapModes::Border); + AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ); + AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ); + AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ); + AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ); + AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ); + AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ); + AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ); + AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ); AccumulationType sum = h+c-d-g-f-a+b+e; uint32_t sideLength = border * 2 + 1; AccumulationType average = sum / (sideLength*sideLength*sideLength); - m_pVolDst->setVoxelAt(iDstX, iDstY, iDstZ, static_cast(average)); + m_pVolDst->setVoxel(iDstX, iDstY, iDstZ, static_cast(average)); } } } diff --git a/include/PolyVox/MarchingCubesSurfaceExtractor.h b/include/PolyVox/MarchingCubesSurfaceExtractor.h index 69ec0569..565034ff 100644 --- a/include/PolyVox/MarchingCubesSurfaceExtractor.h +++ b/include/PolyVox/MarchingCubesSurfaceExtractor.h @@ -157,7 +157,7 @@ namespace PolyVox class MarchingCubesSurfaceExtractor { public: - MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, ControllerType controller, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType()); + MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, ControllerType controller); void execute(); @@ -338,17 +338,17 @@ namespace PolyVox // are provided (would the third parameter be a controller or a mesh?). It seems this can be fixed by using enable_if/static_assert to emulate concepts, // but this is relatively complex and I haven't done it yet. Could always add it later as another overload. template< typename VolumeType, typename MeshType, typename ControllerType = DefaultMarchingCubesController > - void extractMarchingCubesMeshCustom(VolumeType* volData, Region region, MeshType* result, ControllerType controller = ControllerType(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType()) + void extractMarchingCubesMeshCustom(VolumeType* volData, Region region, MeshType* result, ControllerType controller = ControllerType()) { - MarchingCubesSurfaceExtractor extractor(volData, region, result, controller, eWrapMode, tBorderValue); + MarchingCubesSurfaceExtractor extractor(volData, region, result, controller); extractor.execute(); } template< typename VolumeType, typename ControllerType = DefaultMarchingCubesController > - Mesh > extractMarchingCubesMesh(VolumeType* volData, Region region, ControllerType controller = ControllerType(), WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType()) + Mesh > extractMarchingCubesMesh(VolumeType* volData, Region region, ControllerType controller = ControllerType()) { Mesh > result; - extractMarchingCubesMeshCustom, DefaultIndexType > >(volData, region, &result, controller, eWrapMode, tBorderValue); + extractMarchingCubesMeshCustom, DefaultIndexType > >(volData, region, &result, controller); return result; } } diff --git a/include/PolyVox/MarchingCubesSurfaceExtractor.inl b/include/PolyVox/MarchingCubesSurfaceExtractor.inl index 4fb98272..1d81e3f0 100644 --- a/include/PolyVox/MarchingCubesSurfaceExtractor.inl +++ b/include/PolyVox/MarchingCubesSurfaceExtractor.inl @@ -26,7 +26,7 @@ freely, subject to the following restrictions: namespace PolyVox { template - MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, ControllerType controller, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue) + MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, MeshType* result, ControllerType controller) :m_volData(volData) ,m_sampVolume(volData) ,m_meshCurrent(result) @@ -38,8 +38,6 @@ namespace PolyVox //m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion()); m_regSizeInCells = m_regSizeInVoxels; m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1)); - - m_sampVolume.setWrapMode(eWrapMode, tBorderValue); } template diff --git a/include/PolyVox/PagedVolume.h b/include/PolyVox/PagedVolume.h index e5ca536f..6bdf6331 100644 --- a/include/PolyVox/PagedVolume.h +++ b/include/PolyVox/PagedVolume.h @@ -130,8 +130,8 @@ namespace PolyVox VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const; VoxelType getVoxel(const Vector3DUint16& v3dPos) const; - void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); - void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); + void setVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); + void setVoxel(const Vector3DUint16& v3dPos, VoxelType tValue); private: /// Private copy constructor to prevent accisdental copying @@ -187,7 +187,7 @@ namespace PolyVox #if defined(_MSC_VER) class Sampler : public BaseVolume::Sampler< PagedVolume > //This line works on VS2010 #else - class Sampler : public BaseVolume::template Sampler< PagedVolume > //This line works on GCC + class Sampler : public BaseVolume::template Sampler< PagedVolume > //This line works on GCC #endif { public: @@ -249,42 +249,20 @@ namespace PolyVox public: /// Constructor for creating a fixed size volume. - PagedVolume - ( - const Region& regValid, - Pager* pPager = nullptr, - uint16_t uChunkSideLength = 32 - ); + PagedVolume(Pager* pPager, uint32_t uTargetMemoryUsageInBytes = 256 * 1024 * 1024, uint16_t uChunkSideLength = 32); /// Destructor ~PagedVolume(); /// Gets a voxel at the position given by x,y,z coordinates - template - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const; + VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; /// Gets a voxel at the position given by a 3D vector - template - VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const; + VoxelType getVoxel(const Vector3DInt32& v3dPos) const; - /// Gets a voxel at the position given by x,y,z coordinates - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; - /// Gets a voxel at the position given by a 3D vector - VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; - - /// Gets a voxel at the position given by x,y,z coordinates - POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; - /// Gets a voxel at the position given by a 3D vector - POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; - - /// Sets the number of chunks for which uncompressed data is stored - void setMemoryUsageLimit(uint32_t uMemoryUsageInBytes); /// Sets the voxel at the position given by x,y,z coordinates - void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); + void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue); /// Sets the voxel at the position given by a 3D vector - void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); - /// Sets the voxel at the position given by x,y,z coordinates - bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue); - /// Sets the voxel at the position given by a 3D vector - bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue); + void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue); + /// Tries to ensure that the voxels within the specified Region are loaded into memory. void prefetch(Region regPrefetch); /// Ensures that any voxels within the specified Region are removed from memory. @@ -302,19 +280,7 @@ namespace PolyVox /// Assignment operator PagedVolume& operator=(const PagedVolume& rhs); - private: - - // FIXME - We can probably ove this into the constructor - void initialise(); - - // A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057 - template - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - + private: std::shared_ptr getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const; void purgeNullPtrsFromAllChunks(void) const; @@ -338,24 +304,20 @@ namespace PolyVox typedef std::unordered_map > SharedPtrChunkMap; mutable SharedPtrChunkMap m_pRecentlyUsedChunks; - mutable uint32_t m_uTimestamper; - mutable Vector3DInt32 m_v3dLastAccessedChunkPos; - mutable std::shared_ptr m_pLastAccessedChunk; - uint32_t m_uChunkCountLimit; + mutable uint32_t m_uTimestamper = 0; + mutable Vector3DInt32 m_v3dLastAccessedChunkPos = Vector3DInt32(0, 0, 0); //There are no invalid positions, but initially the m_pLastAccessedChunk pointer will be null + mutable std::shared_ptr m_pLastAccessedChunk = nullptr; + uint32_t m_uChunkCountLimit = 0; // The size of the volume - Region m_regValidRegionInChunks; + //Region m_regValidRegionInChunks; // The size of the chunks uint16_t m_uChunkSideLength; uint8_t m_uChunkSideLengthPower; + int32_t m_iChunkMask; - Pager* m_pPager; - - // Enough to make sure a chunks and it's neighbours can be loaded, with a few to spare. - const uint32_t uMinPracticalNoOfChunks = 32; - // Should prevent multi-gigabyte volumes when chunk sizes are reasonable. - const uint32_t uMaxPracticalNoOfChunks = 32768; + Pager* m_pPager = nullptr; }; } diff --git a/include/PolyVox/PagedVolume.inl b/include/PolyVox/PagedVolume.inl index e6c5b04b..50841c48 100644 --- a/include/PolyVox/PagedVolume.inl +++ b/include/PolyVox/PagedVolume.inl @@ -30,62 +30,43 @@ namespace PolyVox { //////////////////////////////////////////////////////////////////////////////// /// This constructor creates a volume with a fixed size which is specified as a parameter. By default this constructor will not enable paging but you can override this if desired. If you do wish to enable paging then you are required to provide the call back function (see the other PagedVolume constructor). - /// \param regValid Specifies the minimum and maximum valid voxel positions. - /// \param dataRequiredHandler The callback function which will be called when PolyVox tries to use data which is not currently in momory. - /// \param dataOverflowHandler The callback function which will be called when PolyVox has too much data and needs to remove some from memory. - /// \param bPagingEnabled Controls whether or not paging is enabled for this PagedVolume. + /// \param pPager Called by PolyVox to load and unload data on demand. + /// \param uTargetMemoryUsageInBytes The upper limit to how much memory this PagedVolume should aim to use. /// \param uChunkSideLength The size of the chunks making up the volume. Small chunks will compress/decompress faster, but there will also be more of them meaning voxel access could be slower. //////////////////////////////////////////////////////////////////////////////// template - PagedVolume::PagedVolume - ( - const Region& regValid, - Pager* pPager, - uint16_t uChunkSideLength - ) - :BaseVolume(regValid) + PagedVolume::PagedVolume(Pager* pPager, uint32_t uTargetMemoryUsageInBytes, uint16_t uChunkSideLength) + :BaseVolume() + , m_pPager(pPager) + , m_uChunkSideLength(uChunkSideLength) { - m_uChunkSideLength = uChunkSideLength; - m_pPager = pPager; + // Validation of parameters + POLYVOX_THROW_IF(!pPager, std::invalid_argument, "You must provide a valid pager when constructing a PagedVolume"); + POLYVOX_THROW_IF(uTargetMemoryUsageInBytes < 1 * 1024 * 1024, std::invalid_argument, "Target memory usage is too small to be practical"); + POLYVOX_THROW_IF(m_uChunkSideLength == 0, std::invalid_argument, "Chunk side length cannot be zero."); + POLYVOX_THROW_IF(m_uChunkSideLength > 256, std::invalid_argument, "Chunk size is too large to be practical."); + POLYVOX_THROW_IF(!isPowerOf2(m_uChunkSideLength), std::invalid_argument, "Chunk side length must be a power of two."); - if (m_pPager) - { - // If the user is creating a vast (almost infinite) volume then we can bet they will be - // expecting a high memory usage and will want a fair number of chunks to play around with. - if (regValid == Region::MaxRegion()) - { - m_uChunkCountLimit = 1024; - } - else - { - // Otherwise we try to choose a chunk count to avoid too much thrashing, particularly when iterating - // over the whole volume. This means at least enough chunks to cover one edge of the volume, and ideally - // enough for a whole face. Which face? Longest edge by shortest edge seems like a reasonable guess. - uint32_t longestSide = (std::max)(regValid.getWidthInVoxels(), (std::max)(regValid.getHeightInVoxels(), regValid.getDepthInVoxels())); - uint32_t shortestSide = (std::min)(regValid.getWidthInVoxels(), (std::min)(regValid.getHeightInVoxels(), regValid.getDepthInVoxels())); + // Used to perform multiplications and divisions by bit shifting. + m_uChunkSideLengthPower = logBase2(m_uChunkSideLength); + // Use to perform modulo by bit operations + m_iChunkMask = m_uChunkSideLength - 1; - longestSide /= m_uChunkSideLength; - shortestSide /= m_uChunkSideLength; + // Calculate the number of chunks based on the memory limit and the size of each chunk. + uint32_t uChunkSizeInBytes = PagedVolume::Chunk::calculateSizeInBytes(m_uChunkSideLength); + m_uChunkCountLimit = uTargetMemoryUsageInBytes / uChunkSizeInBytes; - m_uChunkCountLimit = longestSide * shortestSide; - } - } - else - { - // If there is no pager provided then we set the chunk limit to the maximum - // value to ensure the system never attempts to page chunks out of memory. - m_uChunkCountLimit = (std::numeric_limits::max)(); - } - - // Make sure the calculated chunk limit is within practical bounds + // Enforce sensible limits on the number of chunks. + const uint32_t uMinPracticalNoOfChunks = 32; // Enough to make sure a chunks and it's neighbours can be loaded, with a few to spare. + const uint32_t uMaxPracticalNoOfChunks = 32768; // Should prevent multi-gigabyte volumes when chunk sizes are reasonable. + POLYVOX_LOG_WARNING_IF(m_uChunkCountLimit < uMinPracticalNoOfChunks, "Requested memory usage limit of " + << uTargetMemoryUsageInBytes / (1024 * 1024) << "Mb is too low and cannot be adhered to."); m_uChunkCountLimit = (std::max)(m_uChunkCountLimit, uMinPracticalNoOfChunks); m_uChunkCountLimit = (std::min)(m_uChunkCountLimit, uMaxPracticalNoOfChunks); - uint32_t uChunkSizeInBytes = PagedVolume::Chunk::calculateSizeInBytes(m_uChunkSideLength); - POLYVOX_LOG_DEBUG("Memory usage limit for volume initially set to " << (m_uChunkCountLimit * uChunkSizeInBytes) / (1024 * 1024) + // Inform the user about the chosen memory configuration. + POLYVOX_LOG_DEBUG("Memory usage limit for volume now set to " << (m_uChunkCountLimit * uChunkSizeInBytes) / (1024 * 1024) << "Mb (" << m_uChunkCountLimit << " chunks of " << uChunkSizeInBytes / 1024 << "Kb each)."); - - initialise(); } //////////////////////////////////////////////////////////////////////////////// @@ -98,7 +79,7 @@ namespace PolyVox template PagedVolume::PagedVolume(const PagedVolume& /*rhs*/) { - POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons."); + POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented to prevent accidental copying."); } //////////////////////////////////////////////////////////////////////////////// @@ -120,43 +101,7 @@ namespace PolyVox template PagedVolume& PagedVolume::operator=(const PagedVolume& /*rhs*/) { - POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons."); - } - - //////////////////////////////////////////////////////////////////////////////// - /// This version of the function requires the wrap mode to be specified as a - /// template parameter, which can provide better performance. - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - template - VoxelType PagedVolume::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, WrapModeType(), tBorder); - } - - //////////////////////////////////////////////////////////////////////////////// - /// This version of the function requires the wrap mode to be specified as a - /// template parameter, which can provide better performance. - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - template - VoxelType PagedVolume::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const - { - // Simply call through to the real implementation - return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder); + POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented to prevent accidental copying."); } //////////////////////////////////////////////////////////////////////////////// @@ -165,139 +110,43 @@ namespace PolyVox /// \param uXPos The \c x position of the voxel /// \param uYPos The \c y position of the voxel /// \param uZPos The \c z position of the voxel - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. /// \return The voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType PagedVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const + VoxelType PagedVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const { - switch(eWrapMode) - { - case WrapModes::Validate: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - case WrapModes::Clamp: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - case WrapModes::Border: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - case WrapModes::AssumeValid: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - default: - // Should never happen - POLYVOX_ASSERT(false, "Invalid wrap mode"); - return VoxelType(); - } + const int32_t chunkX = uXPos >> m_uChunkSideLengthPower; + const int32_t chunkY = uYPos >> m_uChunkSideLengthPower; + const int32_t chunkZ = uZPos >> m_uChunkSideLengthPower; + + const uint16_t xOffset = static_cast(uXPos & m_iChunkMask); + const uint16_t yOffset = static_cast(uYPos & m_iChunkMask); + const uint16_t zOffset = static_cast(uZPos & m_iChunkMask); + + auto pChunk = getChunk(chunkX, chunkY, chunkZ); + return pChunk->getVoxel(xOffset, yOffset, zOffset); } //////////////////////////////////////////////////////////////////////////////// /// This version of the function is provided so that the wrap mode does not need /// to be specified as a template parameter, as it may be confusing to some users. /// \param v3dPos The 3D position of the voxel - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. /// \return The voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType PagedVolume::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const + VoxelType PagedVolume::getVoxel(const Vector3DInt32& v3dPos) const { - return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - VoxelType PagedVolume::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const - { - if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos))) - { - const int32_t chunkX = uXPos >> m_uChunkSideLengthPower; - const int32_t chunkY = uYPos >> m_uChunkSideLengthPower; - const int32_t chunkZ = uZPos >> m_uChunkSideLengthPower; - - const uint16_t xOffset = static_cast(uXPos - (chunkX << m_uChunkSideLengthPower)); - const uint16_t yOffset = static_cast(uYPos - (chunkY << m_uChunkSideLengthPower)); - const uint16_t zOffset = static_cast(uZPos - (chunkZ << m_uChunkSideLengthPower)); - - auto pChunk = getChunk(chunkX, chunkY, chunkZ); - - return pChunk->getVoxel(xOffset, yOffset, zOffset); - } - else - { - return this->getBorderValue(); - } - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param v3dPos The 3D position of the voxel - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - VoxelType PagedVolume::getVoxelAt(const Vector3DInt32& v3dPos) const - { - return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); - } - - //////////////////////////////////////////////////////////////////////////////// - /// Increasing the size of the chunk cache will increase memory but may improve performance. - /// You may want to set this to a large value (e.g. 1024) when you are first loading your - /// volume data and then set it to a smaller value (e.g.64) for general processing. - /// \param uMaxNumberOfChunks The number of chunks for which uncompressed data can be cached. - //////////////////////////////////////////////////////////////////////////////// - template - void PagedVolume::setMemoryUsageLimit(uint32_t uMemoryUsageInBytes) - { - POLYVOX_THROW_IF(!m_pPager, invalid_operation, "You cannot limit the memory usage of the volume because it was created without a pager attached."); - - // Calculate the number of chunks based on the memory limit and the size of each chunk. - uint32_t uChunkSizeInBytes = PagedVolume::Chunk::calculateSizeInBytes(m_uChunkSideLength); - m_uChunkCountLimit = uMemoryUsageInBytes / uChunkSizeInBytes; - - // We need at least a few chunks available to avoid thrashing, and in pratice there will probably be hundreds. - POLYVOX_LOG_WARNING_IF(m_uChunkCountLimit < uMinPracticalNoOfChunks, "Requested memory usage limit of " - << uMemoryUsageInBytes / (1024 * 1024) << "Mb is too low and cannot be adhered to."); - m_uChunkCountLimit = (std::max)(m_uChunkCountLimit, uMinPracticalNoOfChunks); - m_uChunkCountLimit = (std::min)(m_uChunkCountLimit, uMaxPracticalNoOfChunks); - - // If the new limit is less than the number of chunks already loaded then the easiest solution is to flush and start loading again. - if (m_pRecentlyUsedChunks.size() > m_uChunkCountLimit) - { - flushAll(); - } - - POLYVOX_LOG_DEBUG("Memory usage limit for volume now set to " << (m_uChunkCountLimit * uChunkSizeInBytes) / (1024 * 1024) - << "Mb (" << m_uChunkCountLimit << " chunks of " << uChunkSizeInBytes / 1024 << "Kb each)."); + return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); } //////////////////////////////////////////////////////////////////////////////// /// \param uXPos the \c x position of the voxel /// \param uYPos the \c y position of the voxel /// \param uZPos the \c z position of the voxel - /// \param tValue the value to which the voxel will be set - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. //////////////////////////////////////////////////////////////////////////////// template - void PagedVolume::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode) + void PagedVolume::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) { - if((eWrapMode != WrapModes::Validate) && (eWrapMode != WrapModes::AssumeValid)) - { - POLYVOX_THROW(std::invalid_argument, "Invalid wrap mode in call to setVoxel(). It must be 'None' or 'DontCheck'."); - } - - // This validation is skipped if the wrap mode is 'DontCheck' - if(eWrapMode == WrapModes::Validate) - { - if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) - { - POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); - } - } - const int32_t chunkX = uXPos >> m_uChunkSideLengthPower; const int32_t chunkY = uYPos >> m_uChunkSideLengthPower; const int32_t chunkZ = uZPos >> m_uChunkSideLengthPower; @@ -307,62 +156,19 @@ namespace PolyVox const uint16_t zOffset = static_cast(uZPos - (chunkZ << m_uChunkSideLengthPower)); auto pChunk = getChunk(chunkX, chunkY, chunkZ); - pChunk->setVoxelAt(xOffset, yOffset, zOffset, tValue); + pChunk->setVoxel(xOffset, yOffset, zOffset, tValue); } //////////////////////////////////////////////////////////////////////////////// /// \param v3dPos the 3D position of the voxel /// \param tValue the value to which the voxel will be set - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. //////////////////////////////////////////////////////////////////////////////// template - void PagedVolume::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode) + void PagedVolume::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue) { - setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue, eWrapMode); + setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } - //////////////////////////////////////////////////////////////////////////////// - /// \param uXPos the \c x position of the voxel - /// \param uYPos the \c y position of the voxel - /// \param uZPos the \c z position of the voxel - /// \param tValue the value to which the voxel will be set - /// \return whether the requested position is inside the volume - //////////////////////////////////////////////////////////////////////////////// - template - bool PagedVolume::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) - { - // PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual. - POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region"); - - const int32_t chunkX = uXPos >> m_uChunkSideLengthPower; - const int32_t chunkY = uYPos >> m_uChunkSideLengthPower; - const int32_t chunkZ = uZPos >> m_uChunkSideLengthPower; - - const uint16_t xOffset = static_cast(uXPos - (chunkX << m_uChunkSideLengthPower)); - const uint16_t yOffset = static_cast(uYPos - (chunkY << m_uChunkSideLengthPower)); - const uint16_t zOffset = static_cast(uZPos - (chunkZ << m_uChunkSideLengthPower)); - - auto pChunk = getChunk(chunkX, chunkY, chunkZ); - - pChunk->setVoxelAt(xOffset, yOffset, zOffset, tValue); - - //Return true to indicate that we modified a voxel. - return true; - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param v3dPos the 3D position of the voxel - /// \param tValue the value to which the voxel will be set - /// \return whether the requested position is inside the volume - //////////////////////////////////////////////////////////////////////////////// - template - bool PagedVolume::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue) - { - return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); - } - - //////////////////////////////////////////////////////////////////////////////// /// Note that if the memory usage limit is not large enough to support the region this function will only load part of the region. In this case it is undefined which parts will actually be loaded. If all the voxels in the given region are already loaded, this function will not do anything. Other voxels might be unloaded to make space for the new voxels. /// \param regPrefetch The Region of voxels to prefetch into memory. @@ -386,7 +192,7 @@ namespace PolyVox // Ensure we don't page in more chunks than the volume can hold. Region region(v3dStart, v3dEnd); uint32_t uNoOfChunks = static_cast(region.getWidthInVoxels() * region.getHeightInVoxels() * region.getDepthInVoxels()); - POLYVOX_LOG_WARNING_IF(uNoOfChunks > m_uChunkCountLimit, "Attempting to prefetch more than the maximum number of chunks."); + POLYVOX_LOG_WARNING_IF(uNoOfChunks > m_uChunkCountLimit, "Attempting to prefetch more than the maximum number of chunks (this will cause thrashing)."); uNoOfChunks = (std::min)(uNoOfChunks, m_uChunkCountLimit); // Loops over the specified positions and touch the corresponding chunks. @@ -408,8 +214,6 @@ namespace PolyVox template void PagedVolume::flushAll() { - POLYVOX_LOG_WARNING_IF(!m_pPager, "Data discarded by flush operation as no pager is attached."); - // Clear this pointer so it doesn't hang on to any chunks. m_pLastAccessedChunk = nullptr; @@ -429,8 +233,6 @@ namespace PolyVox template void PagedVolume::flush(Region regFlush) { - POLYVOX_LOG_WARNING_IF(!m_pPager, "Data discarded by flush operation as no pager is attached."); - // Clear this pointer so it doesn't hang on to any chunks. m_pLastAccessedChunk = nullptr; @@ -465,48 +267,6 @@ namespace PolyVox purgeNullPtrsFromAllChunks(); } - //////////////////////////////////////////////////////////////////////////////// - /// This function should probably be made internal... - //////////////////////////////////////////////////////////////////////////////// - template - void PagedVolume::initialise() - { - //Validate parameters - if(m_uChunkSideLength == 0) - { - POLYVOX_THROW(std::invalid_argument, "Chunk side length cannot be zero."); - } - - if(!isPowerOf2(m_uChunkSideLength)) - { - POLYVOX_THROW(std::invalid_argument, "Chunk side length must be a power of two."); - } - - m_uTimestamper = 0; - m_v3dLastAccessedChunkPos = Vector3DInt32(0,0,0); //There are no invalid positions, but initially the m_pLastAccessedChunk pointer will be null; - m_pLastAccessedChunk = nullptr; - - //Compute the chunk side length - m_uChunkSideLengthPower = logBase2(m_uChunkSideLength); - - m_regValidRegionInChunks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uChunkSideLengthPower); - m_regValidRegionInChunks.setLowerY(this->m_regValidRegion.getLowerY() >> m_uChunkSideLengthPower); - m_regValidRegionInChunks.setLowerZ(this->m_regValidRegion.getLowerZ() >> m_uChunkSideLengthPower); - m_regValidRegionInChunks.setUpperX(this->m_regValidRegion.getUpperX() >> m_uChunkSideLengthPower); - m_regValidRegionInChunks.setUpperY(this->m_regValidRegion.getUpperY() >> m_uChunkSideLengthPower); - m_regValidRegionInChunks.setUpperZ(this->m_regValidRegion.getUpperZ() >> m_uChunkSideLengthPower); - - //setMaxNumberOfChunks(m_uChunkCountLimit); - - //Clear the previous data - m_pRecentlyUsedChunks.clear(); - - //Other properties we might find useful later - this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth()); - this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth()); - this->m_fDiagonalLength = sqrtf(static_cast(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth())); - } - template std::shared_ptr::Chunk> PagedVolume::getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const { @@ -566,10 +326,6 @@ namespace PolyVox bool erasedChunk = false; while (m_pRecentlyUsedChunks.size() + 1 > m_uChunkCountLimit) // +1 ready for new chunk we will add next. { - // This should never hit, because it should not have been possible for - // the user to limit the number of chunks if they did not provide a pager. - POLYVOX_ASSERT(m_pPager, "A valid pager is required to limit number of chunks"); - // Find the least recently used chunk. Hopefully this isn't too slow. typename SharedPtrChunkMap::iterator itUnloadChunk = m_pRecentlyUsedChunks.begin(); for (typename SharedPtrChunkMap::iterator i = m_pRecentlyUsedChunks.begin(); i != m_pRecentlyUsedChunks.end(); i++) @@ -633,66 +389,5 @@ namespace PolyVox } } } - - template - template - VoxelType PagedVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const - { - // This function should never be called because one of the specialisations should always match. - POLYVOX_ASSERT(false, "This function is not implemented and should never be called!"); - } - - template - VoxelType PagedVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) 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, WrapModeType(), tBorder); // No wrapping as we've just validated the position. - } - - template - VoxelType PagedVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) 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, WrapModeType(), tBorder); // No wrapping as we've just validated the position. - } - - template - VoxelType PagedVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const - { - if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) - { - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); // No wrapping as we've just validated the position. - } - else - { - return tBorder; - } - } - - template - VoxelType PagedVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType /*tBorder*/) const - { - const int32_t chunkX = uXPos >> m_uChunkSideLengthPower; - const int32_t chunkY = uYPos >> m_uChunkSideLengthPower; - const int32_t chunkZ = uZPos >> m_uChunkSideLengthPower; - - const uint16_t xOffset = static_cast(uXPos - (chunkX << m_uChunkSideLengthPower)); - const uint16_t yOffset = static_cast(uYPos - (chunkY << m_uChunkSideLengthPower)); - const uint16_t zOffset = static_cast(uZPos - (chunkZ << m_uChunkSideLengthPower)); - - auto pChunk = getChunk(chunkX, chunkY, chunkZ); - return pChunk->getVoxel(xOffset, yOffset, zOffset); - } } diff --git a/include/PolyVox/PagedVolumeChunk.inl b/include/PolyVox/PagedVolumeChunk.inl index 7a51c79b..b21ca9f1 100644 --- a/include/PolyVox/PagedVolumeChunk.inl +++ b/include/PolyVox/PagedVolumeChunk.inl @@ -35,30 +35,24 @@ namespace PolyVox ,m_pPager(pPager) ,m_v3dChunkSpacePosition(v3dPosition) { + POLYVOX_ASSERT(m_pPager, "No valid pager supplied to chunk constructor."); + // Compute the side length m_uSideLength = uSideLength; m_uSideLengthPower = logBase2(uSideLength); // Allocate the data const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength; - m_tData = new VoxelType[uNoOfVoxels]; + m_tData = new VoxelType[uNoOfVoxels]; // Pass the chunk to the Pager to give it a chance to initialise it with any data - if (m_pPager) - { - // From the coordinates of the chunk we deduce the coordinates of the contained voxels. - Vector3DInt32 v3dLower = m_v3dChunkSpacePosition * static_cast(m_uSideLength); - Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uSideLength - 1, m_uSideLength - 1, m_uSideLength - 1); - Region reg(v3dLower, v3dUpper); + // From the coordinates of the chunk we deduce the coordinates of the contained voxels. + Vector3DInt32 v3dLower = m_v3dChunkSpacePosition * static_cast(m_uSideLength); + Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uSideLength - 1, m_uSideLength - 1, m_uSideLength - 1); + Region reg(v3dLower, v3dUpper); - // Page the data in - m_pPager->pageIn(reg, this); - } - else - { - // Just fill with zeros - std::fill(m_tData, m_tData + uNoOfVoxels, VoxelType()); - } + // Page the data in + m_pPager->pageIn(reg, this); // We'll use this later to decide if data needs to be paged out again. m_bDataModified = false; @@ -67,7 +61,7 @@ namespace PolyVox template PagedVolume::Chunk::~Chunk() { - if (m_pPager && m_bDataModified) + if (m_bDataModified) { // From the coordinates of the chunk we deduce the coordinates of the contained voxels. Vector3DInt32 v3dLower = m_v3dChunkSpacePosition * static_cast(m_uSideLength); @@ -118,7 +112,7 @@ namespace PolyVox } template - void PagedVolume::Chunk::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue) + void PagedVolume::Chunk::setVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue) { // This code is not usually expected to be called by the user, with the exception of when implementing paging // of uncompressed data. It's a performance critical code path so we use asserts rather than exceptions. @@ -138,9 +132,9 @@ namespace PolyVox } template - void PagedVolume::Chunk::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue) + void PagedVolume::Chunk::setVoxel(const Vector3DUint16& v3dPos, VoxelType tValue) { - setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); + setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } template diff --git a/include/PolyVox/PagedVolumeSampler.inl b/include/PolyVox/PagedVolumeSampler.inl index 90909cb7..3de9ca10 100644 --- a/include/PolyVox/PagedVolumeSampler.inl +++ b/include/PolyVox/PagedVolumeSampler.inl @@ -21,12 +21,12 @@ freely, subject to the following restrictions: distribution. *******************************************************************************/ -#define CAN_GO_NEG_X(val) ((val > this->mVolume->getEnclosingRegion().getLowerX()) && (val % this->mVolume->m_uChunkSideLength != 0)) -#define CAN_GO_POS_X(val) ((val < this->mVolume->getEnclosingRegion().getUpperX()) && ((val + 1) % this->mVolume->m_uChunkSideLength != 0)) -#define CAN_GO_NEG_Y(val) ((val > this->mVolume->getEnclosingRegion().getLowerY()) && (val % this->mVolume->m_uChunkSideLength != 0)) -#define CAN_GO_POS_Y(val) ((val < this->mVolume->getEnclosingRegion().getUpperY()) && ((val + 1) % this->mVolume->m_uChunkSideLength != 0)) -#define CAN_GO_NEG_Z(val) ((val > this->mVolume->getEnclosingRegion().getLowerZ()) && (val % this->mVolume->m_uChunkSideLength != 0)) -#define CAN_GO_POS_Z(val) ((val < this->mVolume->getEnclosingRegion().getUpperZ()) && ((val + 1) % this->mVolume->m_uChunkSideLength != 0)) +#define CAN_GO_NEG_X(val) ((val % this->mVolume->m_uChunkSideLength != 0)) +#define CAN_GO_POS_X(val) (((val + 1) % this->mVolume->m_uChunkSideLength != 0)) +#define CAN_GO_NEG_Y(val) ((val % this->mVolume->m_uChunkSideLength != 0)) +#define CAN_GO_POS_Y(val) (((val + 1) % this->mVolume->m_uChunkSideLength != 0)) +#define CAN_GO_NEG_Z(val) ((val % this->mVolume->m_uChunkSideLength != 0)) +#define CAN_GO_POS_Z(val) (((val + 1) % this->mVolume->m_uChunkSideLength != 0)) namespace PolyVox { @@ -71,7 +71,7 @@ namespace PolyVox { for(uint8_t x = 0; x < uSize; ++x) { - tValue = (std::min)(tValue, this->mVolume->getVoxelAt(this->mXPosInVolume + x, this->mYPosInVolume + y, this->mZPosInVolume + z)); + tValue = (std::min)(tValue, this->mVolume->getVoxel(this->mXPosInVolume + x, this->mYPosInVolume + y, this->mZPosInVolume + z)); } } } @@ -82,14 +82,7 @@ namespace PolyVox template VoxelType PagedVolume::Sampler::getVoxel(void) const { - if(this->isCurrentPositionValid()) - { - return *mCurrentVoxel; - } - else - { - return this->getVoxelImpl(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); - } + return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); } template @@ -105,43 +98,26 @@ namespace PolyVox BaseVolume::template Sampler< PagedVolume >::setPosition(xPos, yPos, zPos); // Then we update the voxel pointer - if(this->isCurrentPositionValid()) - { - const int32_t uXChunk = this->mXPosInVolume >> this->mVolume->m_uChunkSideLengthPower; - const int32_t uYChunk = this->mYPosInVolume >> this->mVolume->m_uChunkSideLengthPower; - const int32_t uZChunk = this->mZPosInVolume >> this->mVolume->m_uChunkSideLengthPower; + const int32_t uXChunk = this->mXPosInVolume >> this->mVolume->m_uChunkSideLengthPower; + const int32_t uYChunk = this->mYPosInVolume >> this->mVolume->m_uChunkSideLengthPower; + const int32_t uZChunk = this->mZPosInVolume >> this->mVolume->m_uChunkSideLengthPower; - const uint16_t uXPosInChunk = static_cast(this->mXPosInVolume - (uXChunk << this->mVolume->m_uChunkSideLengthPower)); - const uint16_t uYPosInChunk = static_cast(this->mYPosInVolume - (uYChunk << this->mVolume->m_uChunkSideLengthPower)); - const uint16_t uZPosInChunk = static_cast(this->mZPosInVolume - (uZChunk << this->mVolume->m_uChunkSideLengthPower)); + const uint16_t uXPosInChunk = static_cast(this->mXPosInVolume - (uXChunk << this->mVolume->m_uChunkSideLengthPower)); + const uint16_t uYPosInChunk = static_cast(this->mYPosInVolume - (uYChunk << this->mVolume->m_uChunkSideLengthPower)); + const uint16_t uZPosInChunk = static_cast(this->mZPosInVolume - (uZChunk << this->mVolume->m_uChunkSideLengthPower)); - const uint32_t uVoxelIndexInChunk = uXPosInChunk + - uYPosInChunk * this->mVolume->m_uChunkSideLength + - uZPosInChunk * this->mVolume->m_uChunkSideLength * this->mVolume->m_uChunkSideLength; + const uint32_t uVoxelIndexInChunk = uXPosInChunk + + uYPosInChunk * this->mVolume->m_uChunkSideLength + + uZPosInChunk * this->mVolume->m_uChunkSideLength * this->mVolume->m_uChunkSideLength; - auto pCurrentChunk = this->mVolume->getChunk(uXChunk, uYChunk, uZChunk); + auto pCurrentChunk = this->mVolume->getChunk(uXChunk, uYChunk, uZChunk); - mCurrentVoxel = pCurrentChunk->m_tData + uVoxelIndexInChunk; - } - else - { - mCurrentVoxel = 0; - } + mCurrentVoxel = pCurrentChunk->m_tData + uVoxelIndexInChunk; } template bool PagedVolume::Sampler::setVoxel(VoxelType tValue) { - /*if(m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ) - { - *mCurrentVoxel = tValue; - return true; - } - else - { - return false; - }*/ - //Need to think what effect this has on any existing iterators. POLYVOX_THROW(not_implemented, "This function cannot be used on PagedVolume samplers."); return false; @@ -150,14 +126,11 @@ namespace PolyVox template void PagedVolume::Sampler::movePositiveX(void) { - // We'll need this in a moment... - bool bIsOldPositionValid = this->isCurrentPositionValid(); - // Base version updates position and validity flags. BaseVolume::template Sampler< PagedVolume >::movePositiveX(); // Then we update the voxel pointer - if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mXPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) + if(((this->mXPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) { //No need to compute new chunk. ++mCurrentVoxel; @@ -172,14 +145,11 @@ namespace PolyVox template void PagedVolume::Sampler::movePositiveY(void) { - // We'll need this in a moment... - bool bIsOldPositionValid = this->isCurrentPositionValid(); - // Base version updates position and validity flags. BaseVolume::template Sampler< PagedVolume >::movePositiveY(); // Then we update the voxel pointer - if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mYPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) + if(((this->mYPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) { //No need to compute new chunk. mCurrentVoxel += this->mVolume->m_uChunkSideLength; @@ -194,14 +164,11 @@ namespace PolyVox template void PagedVolume::Sampler::movePositiveZ(void) { - // We'll need this in a moment... - bool bIsOldPositionValid = this->isCurrentPositionValid(); - // Base version updates position and validity flags. BaseVolume::template Sampler< PagedVolume >::movePositiveZ(); // Then we update the voxel pointer - if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mZPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) + if(((this->mZPosInVolume) % this->mVolume->m_uChunkSideLength != 0)) { //No need to compute new chunk. mCurrentVoxel += this->mVolume->m_uChunkSideLength * this->mVolume->m_uChunkSideLength; @@ -216,14 +183,11 @@ namespace PolyVox template void PagedVolume::Sampler::moveNegativeX(void) { - // We'll need this in a moment... - bool bIsOldPositionValid = this->isCurrentPositionValid(); - // Base version updates position and validity flags. BaseVolume::template Sampler< PagedVolume >::moveNegativeX(); // Then we update the voxel pointer - if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mXPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) + if(((this->mXPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) { //No need to compute new chunk. --mCurrentVoxel; @@ -238,14 +202,11 @@ namespace PolyVox template void PagedVolume::Sampler::moveNegativeY(void) { - // We'll need this in a moment... - bool bIsOldPositionValid = this->isCurrentPositionValid(); - // Base version updates position and validity flags. BaseVolume::template Sampler< PagedVolume >::moveNegativeY(); // Then we update the voxel pointer - if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mYPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) + if(((this->mYPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) { //No need to compute new chunk. mCurrentVoxel -= this->mVolume->m_uChunkSideLength; @@ -260,14 +221,11 @@ namespace PolyVox template void PagedVolume::Sampler::moveNegativeZ(void) { - // We'll need this in a moment... - bool bIsOldPositionValid = this->isCurrentPositionValid(); - // Base version updates position and validity flags. BaseVolume::template Sampler< PagedVolume >::moveNegativeZ(); // Then we update the voxel pointer - if((this->isCurrentPositionValid()) && bIsOldPositionValid && ((this->mZPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) + if(((this->mZPosInVolume + 1) % this->mVolume->m_uChunkSideLength != 0)) { //No need to compute new chunk. mCurrentVoxel -= this->mVolume->m_uChunkSideLength * this->mVolume->m_uChunkSideLength; @@ -282,91 +240,91 @@ namespace PolyVox template VoxelType PagedVolume::Sampler::peekVoxel1nx1ny1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel1nx1ny0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) ) { return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel1nx1ny1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1); } template VoxelType PagedVolume::Sampler::peekVoxel1nx0py1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - 1 - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel1nx0py0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) ) { return *(mCurrentVoxel - 1); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel1nx0py1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1); } template VoxelType PagedVolume::Sampler::peekVoxel1nx1py1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel1nx1py0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) ) { return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel1nx1py1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - 1 + this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1); } ////////////////////////////////////////////////////////////////////////// @@ -374,91 +332,87 @@ namespace PolyVox template VoxelType PagedVolume::Sampler::peekVoxel0px1ny1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel0px1ny0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) ) + if(CAN_GO_NEG_Y(this->mYPosInVolume) ) { return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel0px1ny1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1); } template VoxelType PagedVolume::Sampler::peekVoxel0px0py1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel0px0py0pz(void) const { - if((this->isCurrentPositionValid())) - { - return *mCurrentVoxel; - } - return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return *mCurrentVoxel; } template VoxelType PagedVolume::Sampler::peekVoxel0px0py1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1); } template VoxelType PagedVolume::Sampler::peekVoxel0px1py1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel0px1py0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) ) + if(CAN_GO_POS_Y(this->mYPosInVolume) ) { return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel0px1py1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1); } ////////////////////////////////////////////////////////////////////////// @@ -466,91 +420,91 @@ namespace PolyVox template VoxelType PagedVolume::Sampler::peekVoxel1px1ny1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel1px1ny0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) ) { return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel1px1ny1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1); } template VoxelType PagedVolume::Sampler::peekVoxel1px0py1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + 1 - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel1px0py0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) ) { return *(mCurrentVoxel + 1); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel1px0py1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1); } template VoxelType PagedVolume::Sampler::peekVoxel1px1py1nz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_NEG_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength - this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1); } template VoxelType PagedVolume::Sampler::peekVoxel1px1py0pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) ) { return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume); } template VoxelType PagedVolume::Sampler::peekVoxel1px1py1pz(void) const { - if((this->isCurrentPositionValid()) && CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) + if(CAN_GO_POS_X(this->mXPosInVolume) && CAN_GO_POS_Y(this->mYPosInVolume) && CAN_GO_POS_Z(this->mZPosInVolume) ) { return *(mCurrentVoxel + 1 + this->mVolume->m_uChunkSideLength + this->mVolume->m_uChunkSideLength*this->mVolume->m_uChunkSideLength); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1); } } diff --git a/include/PolyVox/RawVolume.h b/include/PolyVox/RawVolume.h index 73a2f1e5..4b05f7d5 100644 --- a/include/PolyVox/RawVolume.h +++ b/include/PolyVox/RawVolume.h @@ -57,7 +57,9 @@ namespace PolyVox Sampler(RawVolume* volume); ~Sampler(); - inline VoxelType getVoxel(void) const; + inline VoxelType getVoxel(void) const; + + bool isCurrentPositionValid(void) const; void setPosition(const Vector3DInt32& v3dNewPos); void setPosition(int32_t xPos, int32_t yPos, int32_t zPos); @@ -105,6 +107,12 @@ namespace PolyVox //Other current position information VoxelType* mCurrentVoxel; + + //Whether the current position is inside the volume + //FIXME - Replace these with flags + bool m_bIsCurrentPositionValidInX; + bool m_bIsCurrentPositionValidInY; + bool m_bIsCurrentPositionValidInZ; }; #endif @@ -115,31 +123,29 @@ namespace PolyVox /// Destructor ~RawVolume(); - /// Gets a voxel at the position given by x,y,z coordinates - template - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const; - /// Gets a voxel at the position given by a 3D vector - template - VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const; + /// Gets the value used for voxels which are outside the volume + VoxelType getBorderValue(void) const; + /// Gets a Region representing the extents of the Volume. + const Region& getEnclosingRegion(void) const; + + /// Gets the width of the volume in voxels. + int32_t getWidth(void) const; + /// Gets the height of the volume in voxels. + int32_t getHeight(void) const; + /// Gets the depth of the volume in voxels. + int32_t getDepth(void) const; /// Gets a voxel at the position given by x,y,z coordinates - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; + VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; /// Gets a voxel at the position given by a 3D vector - VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const; - - /// Gets a voxel at the position given by x,y,z coordinates - POLYVOX_DEPRECATED VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; - /// Gets a voxel at the position given by a 3D vector - POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; + VoxelType getVoxel(const Vector3DInt32& v3dPos) const; + /// Sets the value used for voxels which are outside the volume + void setBorderValue(const VoxelType& tBorder); /// Sets the voxel at the position given by x,y,z coordinates - void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); + void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue); /// Sets the voxel at the position given by a 3D vector - void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); - /// Sets the voxel at the position given by x,y,z coordinates - bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue); - /// Sets the voxel at the position given by a 3D vector - bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue); + void setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue); /// Calculates approximatly how many bytes of memory the volume is currently using. uint32_t calculateSizeInBytes(void); @@ -154,13 +160,11 @@ namespace PolyVox private: void initialise(const Region& regValidRegion); - // A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057 - template - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; - VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; + //The size of the volume + Region m_regValidRegion; + + //The border value + VoxelType m_tBorderValue; //The voxel data VoxelType* m_pData; diff --git a/include/PolyVox/RawVolume.inl b/include/PolyVox/RawVolume.inl index 3dd0ef5d..efca9982 100644 --- a/include/PolyVox/RawVolume.inl +++ b/include/PolyVox/RawVolume.inl @@ -29,7 +29,9 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// template RawVolume::RawVolume(const Region& regValid) - :BaseVolume(regValid) + :BaseVolume() + , m_regValidRegion(regValid) + , m_tBorderValue() { this->setBorderValue(VoxelType()); @@ -74,39 +76,53 @@ namespace PolyVox } //////////////////////////////////////////////////////////////////////////////// - /// This version of the function requires the wrap mode to be specified as a - /// template parameter, which can provide better performance. - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. - /// \return The voxel value + /// The border value is returned whenever an attempt is made to read a voxel which + /// is outside the extents of the volume. + /// \return The value used for voxels outside of the volume //////////////////////////////////////////////////////////////////////////////// template - template - VoxelType RawVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const + VoxelType RawVolume::getBorderValue(void) const { - // Simply call through to the real implementation - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); + return m_tBorderValue; } //////////////////////////////////////////////////////////////////////////////// - /// This version of the function requires the wrap mode to be specified as a - /// template parameter, which can provide better performance. - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \tparam eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. - /// \return The voxel value + /// \return A Region representing the extent of the volume. //////////////////////////////////////////////////////////////////////////////// template - template - VoxelType RawVolume::getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder) const + const Region& RawVolume::getEnclosingRegion(void) const { - // Simply call through to the real implementation - return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder); + return m_regValidRegion; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The width of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the width is 64. + /// \sa getHeight(), getDepth() + //////////////////////////////////////////////////////////////////////////////// + template + int32_t RawVolume::getWidth(void) const + { + return m_regValidRegion.getUpperX() - m_regValidRegion.getLowerX() + 1; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The height of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the height is 64. + /// \sa getWidth(), getDepth() + //////////////////////////////////////////////////////////////////////////////// + template + int32_t RawVolume::getHeight(void) const + { + return m_regValidRegion.getUpperY() - m_regValidRegion.getLowerY() + 1; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The depth of the volume in voxels. Note that this value is inclusive, so that if the valid range is e.g. 0 to 63 then the depth is 64. + /// \sa getWidth(), getHeight() + //////////////////////////////////////////////////////////////////////////////// + template + int32_t RawVolume::getDepth(void) const + { + return m_regValidRegion.getUpperZ() - m_regValidRegion.getLowerZ() + 1; } //////////////////////////////////////////////////////////////////////////////// @@ -115,81 +131,50 @@ namespace PolyVox /// \param uXPos The \c x position of the voxel /// \param uYPos The \c y position of the voxel /// \param uZPos The \c z position of the voxel - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. /// \return The voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType RawVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const + VoxelType RawVolume::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const { - switch(eWrapMode) + if (this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) { - case WrapModes::Validate: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - case WrapModes::Clamp: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - case WrapModes::Border: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - case WrapModes::AssumeValid: - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); - default: - // Should never happen - POLYVOX_ASSERT(false, "Invalid wrap mode"); - return VoxelType(); - } - } - - //////////////////////////////////////////////////////////////////////////////// - /// This version of the function is provided so that the wrap mode does not need - /// to be specified as a template parameter, as it may be confusing to some users. - /// \param v3dPos The 3D position of the voxel - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// \param tBorder The border value to use if the wrap mode is set to 'Border'. - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - VoxelType RawVolume::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const - { - return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param uXPos The \c x position of the voxel - /// \param uYPos The \c y position of the voxel - /// \param uZPos The \c z position of the voxel - /// \return The voxel value - //////////////////////////////////////////////////////////////////////////////// - template - VoxelType RawVolume::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const - { - if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos))) - { - const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner(); - int32_t iLocalXPos = uXPos - v3dLowerCorner.getX(); - int32_t iLocalYPos = uYPos - v3dLowerCorner.getY(); - int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ(); + const Region& regValidRegion = this->m_regValidRegion; + int32_t iLocalXPos = uXPos - regValidRegion.getLowerX(); + int32_t iLocalYPos = uYPos - regValidRegion.getLowerY(); + int32_t iLocalZPos = uZPos - regValidRegion.getLowerZ(); return m_pData [ - iLocalXPos + - iLocalYPos * this->getWidth() + + iLocalXPos + + iLocalYPos * this->getWidth() + iLocalZPos * this->getWidth() * this->getHeight() ]; } else { - return this->getBorderValue(); + return m_tBorderValue; } } //////////////////////////////////////////////////////////////////////////////// + /// This version of the function is provided so that the wrap mode does not need + /// to be specified as a template parameter, as it may be confusing to some users. /// \param v3dPos The 3D position of the voxel /// \return The voxel value //////////////////////////////////////////////////////////////////////////////// template - VoxelType RawVolume::getVoxelAt(const Vector3DInt32& v3dPos) const + VoxelType RawVolume::getVoxel(const Vector3DInt32& v3dPos) const { - return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); + return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param tBorder The value to use for voxels outside the volume. + //////////////////////////////////////////////////////////////////////////////// + template + void RawVolume::setBorderValue(const VoxelType& tBorder) + { + m_tBorderValue = tBorder; } //////////////////////////////////////////////////////////////////////////////// @@ -197,24 +182,13 @@ namespace PolyVox /// \param uYPos the \c y position of the voxel /// \param uZPos the \c z position of the voxel /// \param tValue the value to which the voxel will be set - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. //////////////////////////////////////////////////////////////////////////////// template - void RawVolume::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode) + void RawVolume::setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) { - if((eWrapMode != WrapModes::Validate) && (eWrapMode != WrapModes::AssumeValid)) + if (this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) { - POLYVOX_THROW(std::invalid_argument, "Invalid wrap mode in call to setVoxel(). It must be 'None' or 'DontCheck'."); - } - - // This validation is skipped if the wrap mode is 'DontCheck' - if(eWrapMode == WrapModes::Validate) - { - if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) - { - POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); - } + POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); } const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner(); @@ -233,57 +207,11 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// /// \param v3dPos the 3D position of the voxel /// \param tValue the value to which the voxel will be set - /// \param eWrapMode Specifies the behaviour when the requested position is outside of the volume. - /// This must be set to 'None' or 'DontCheck'. Other wrap modes cannot be used when writing to volume data. //////////////////////////////////////////////////////////////////////////////// template - void RawVolume::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue, WrapMode eWrapMode) + void RawVolume::setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue) { - setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue, eWrapMode); - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param uXPos the \c x position of the voxel - /// \param uYPos the \c y position of the voxel - /// \param uZPos the \c z position of the voxel - /// \param tValue the value to which the voxel will be set - /// \return whether the requested position is inside the volume - //////////////////////////////////////////////////////////////////////////////// - template - bool RawVolume::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) - { - if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos))) - { - const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner(); - int32_t iLocalXPos = uXPos - v3dLowerCorner.getX(); - int32_t iLocalYPos = uYPos - v3dLowerCorner.getY(); - int32_t iLocalZPos = uZPos - v3dLowerCorner.getZ(); - - m_pData - [ - iLocalXPos + - iLocalYPos * this->getWidth() + - iLocalZPos * this->getWidth() * this->getHeight() - ] = tValue; - - //Return true to indicate that we modified a voxel. - return true; - } - else - { - return false; - } - } - - //////////////////////////////////////////////////////////////////////////////// - /// \param v3dPos the 3D position of the voxel - /// \param tValue the value to which the voxel will be set - /// \return whether the requested position is inside the volume - //////////////////////////////////////////////////////////////////////////////// - template - bool RawVolume::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue) - { - return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); + setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } //////////////////////////////////////////////////////////////////////////////// @@ -310,10 +238,8 @@ namespace PolyVox //Create the data m_pData = new VoxelType[this->getWidth() * this->getHeight()* this->getDepth()]; - //Other properties we might find useful later - this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth()); - this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth()); - this->m_fDiagonalLength = sqrtf(static_cast(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth())); + // Clear to zeros + std::fill(m_pData, m_pData + this->getWidth() * this->getHeight()* this->getDepth(), VoxelType()); } //////////////////////////////////////////////////////////////////////////////// @@ -324,67 +250,5 @@ namespace PolyVox { return this->getWidth() * this->getHeight() * this->getDepth() * sizeof(VoxelType); } - - template - template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const - { - // This function should never be called because one of the specialisations should always match. - POLYVOX_ASSERT(false, "This function is not implemented and should never be called!"); - } - - template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) 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, WrapModeType(), tBorder); // No wrapping as we've just validated the position. - } - - template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) 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, WrapModeType(), tBorder); // No wrapping as we've just validated the position. - } - - template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const - { - if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) - { - return getVoxelImpl(uXPos, uYPos, uZPos, WrapModeType(), tBorder); // No wrapping as we've just validated the position. - } - else - { - return tBorder; - } - } - - template - VoxelType RawVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType /*tBorder*/) const - { - const Region& regValidRegion = this->m_regValidRegion; - int32_t iLocalXPos = uXPos - regValidRegion.getLowerX(); - int32_t iLocalYPos = uYPos - regValidRegion.getLowerY(); - int32_t iLocalZPos = uZPos - regValidRegion.getLowerZ(); - - return m_pData - [ - iLocalXPos + - iLocalYPos * this->getWidth() + - iLocalZPos * this->getWidth() * this->getHeight() - ]; - } } diff --git a/include/PolyVox/RawVolumeSampler.inl b/include/PolyVox/RawVolumeSampler.inl index 9da44077..16766c2f 100644 --- a/include/PolyVox/RawVolumeSampler.inl +++ b/include/PolyVox/RawVolumeSampler.inl @@ -34,6 +34,9 @@ namespace PolyVox RawVolume::Sampler::Sampler(RawVolume* volume) :BaseVolume::template Sampler< RawVolume >(volume) ,mCurrentVoxel(0) + , m_bIsCurrentPositionValidInX(false) + , m_bIsCurrentPositionValidInY(false) + , m_bIsCurrentPositionValidInZ(false) { } @@ -51,10 +54,16 @@ namespace PolyVox } else { - return this->getVoxelImpl(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); + return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); } } + template + bool inline RawVolume::Sampler::isCurrentPositionValid(void) const + { + return m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ; + } + template void RawVolume::Sampler::setPosition(const Vector3DInt32& v3dNewPos) { @@ -67,6 +76,10 @@ namespace PolyVox // Base version updates position and validity flags. BaseVolume::template Sampler< RawVolume >::setPosition(xPos, yPos, zPos); + m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(xPos); + m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(yPos); + m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(zPos); + // Then we update the voxel pointer if(this->isCurrentPositionValid()) { @@ -111,6 +124,8 @@ namespace PolyVox // Base version updates position and validity flags. BaseVolume::template Sampler< RawVolume >::movePositiveX(); + m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume); + // Then we update the voxel pointer if(this->isCurrentPositionValid() && bIsOldPositionValid ) { @@ -131,6 +146,8 @@ namespace PolyVox // Base version updates position and validity flags. BaseVolume::template Sampler< RawVolume >::movePositiveY(); + m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume); + // Then we update the voxel pointer if(this->isCurrentPositionValid() && bIsOldPositionValid ) { @@ -151,6 +168,8 @@ namespace PolyVox // Base version updates position and validity flags. BaseVolume::template Sampler< RawVolume >::movePositiveZ(); + m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume); + // Then we update the voxel pointer if(this->isCurrentPositionValid() && bIsOldPositionValid ) { @@ -171,6 +190,8 @@ namespace PolyVox // Base version updates position and validity flags. BaseVolume::template Sampler< RawVolume >::moveNegativeX(); + m_bIsCurrentPositionValidInX = mVolume->getEnclosingRegion().containsPointInX(mXPosInVolume); + // Then we update the voxel pointer if(this->isCurrentPositionValid() && bIsOldPositionValid ) { @@ -191,6 +212,8 @@ namespace PolyVox // Base version updates position and validity flags. BaseVolume::template Sampler< RawVolume >::moveNegativeY(); + m_bIsCurrentPositionValidInY = mVolume->getEnclosingRegion().containsPointInY(mYPosInVolume); + // Then we update the voxel pointer if(this->isCurrentPositionValid() && bIsOldPositionValid ) { @@ -211,6 +234,8 @@ namespace PolyVox // Base version updates position and validity flags. BaseVolume::template Sampler< RawVolume >::moveNegativeZ(); + m_bIsCurrentPositionValidInZ = mVolume->getEnclosingRegion().containsPointInZ(mZPosInVolume); + // Then we update the voxel pointer if(this->isCurrentPositionValid() && bIsOldPositionValid ) { @@ -229,7 +254,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume-1); } template @@ -239,7 +264,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 - this->mVolume->getWidth()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume); } template @@ -249,7 +274,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume-1,this->mZPosInVolume+1); } template @@ -259,7 +284,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume-1); } template @@ -269,7 +294,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume); } template @@ -279,7 +304,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume,this->mZPosInVolume+1); } template @@ -289,7 +314,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume-1); } template @@ -299,7 +324,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 + this->mVolume->getWidth()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume); } template @@ -309,7 +334,7 @@ namespace PolyVox { return *(mCurrentVoxel - 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume-1,this->mYPosInVolume+1,this->mZPosInVolume+1); } ////////////////////////////////////////////////////////////////////////// @@ -321,7 +346,7 @@ namespace PolyVox { return *(mCurrentVoxel - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume-1); } template @@ -331,7 +356,7 @@ namespace PolyVox { return *(mCurrentVoxel - this->mVolume->getWidth()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume); } template @@ -341,7 +366,7 @@ namespace PolyVox { return *(mCurrentVoxel - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume-1,this->mZPosInVolume+1); } template @@ -351,7 +376,7 @@ namespace PolyVox { return *(mCurrentVoxel - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume-1); } template @@ -361,7 +386,7 @@ namespace PolyVox { return *mCurrentVoxel; } - return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume, this->mYPosInVolume, this->mZPosInVolume); } template @@ -371,7 +396,7 @@ namespace PolyVox { return *(mCurrentVoxel + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume,this->mZPosInVolume+1); } template @@ -381,7 +406,7 @@ namespace PolyVox { return *(mCurrentVoxel + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume-1); } template @@ -391,7 +416,7 @@ namespace PolyVox { return *(mCurrentVoxel + this->mVolume->getWidth()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume); } template @@ -401,7 +426,7 @@ namespace PolyVox { return *(mCurrentVoxel + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume,this->mYPosInVolume+1,this->mZPosInVolume+1); } ////////////////////////////////////////////////////////////////////////// @@ -413,7 +438,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 - this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume-1); } template @@ -423,7 +448,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 - this->mVolume->getWidth()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume); } template @@ -433,7 +458,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 - this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume-1,this->mZPosInVolume+1); } template @@ -443,7 +468,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume-1); } template @@ -453,7 +478,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume); } template @@ -463,7 +488,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume,this->mZPosInVolume+1); } template @@ -473,7 +498,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 + this->mVolume->getWidth() - this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume-1); } template @@ -483,7 +508,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 + this->mVolume->getWidth()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume); } template @@ -493,7 +518,7 @@ namespace PolyVox { return *(mCurrentVoxel + 1 + this->mVolume->getWidth() + this->mVolume->getWidth() * this->mVolume->getHeight()); } - return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1,this->m_eWrapMode, this->m_tBorder); + return this->mVolume->getVoxel(this->mXPosInVolume+1,this->mYPosInVolume+1,this->mZPosInVolume+1); } } diff --git a/include/PolyVox/VolumeResampler.inl b/include/PolyVox/VolumeResampler.inl index 3360d54b..2170f8b9 100644 --- a/include/PolyVox/VolumeResampler.inl +++ b/include/PolyVox/VolumeResampler.inl @@ -72,9 +72,9 @@ namespace PolyVox { for(int32_t sx = m_regSrc.getLowerX(), dx = m_regDst.getLowerX(); dx <= m_regDst.getUpperX(); sx++,dx++) { - const typename SrcVolumeType::VoxelType& tSrcVoxel = m_pVolSrc->getVoxel(sx,sy,sz, WrapModes::AssumeValid); // FIXME use templatised version of getVoxel(), but watch out for Linux compile issues. + const typename SrcVolumeType::VoxelType& tSrcVoxel = m_pVolSrc->getVoxel(sx,sy,sz); const typename DstVolumeType::VoxelType& tDstVoxel = static_cast(tSrcVoxel); - m_pVolDst->setVoxelAt(dx,dy,dz,tDstVoxel); + m_pVolDst->setVoxel(dx,dy,dz,tDstVoxel); } } } @@ -130,7 +130,7 @@ namespace PolyVox typename SrcVolumeType::VoxelType tInterpolatedValue = trilerp(voxel000,voxel100,voxel010,voxel110,voxel001,voxel101,voxel011,voxel111,sx,sy,sz); typename DstVolumeType::VoxelType result = static_cast(tInterpolatedValue); - m_pVolDst->setVoxelAt(dx,dy,dz,result); + m_pVolDst->setVoxel(dx,dy,dz,result); } } } diff --git a/tests/TestAStarPathfinder.cpp b/tests/TestAStarPathfinder.cpp index c6c52da0..36cbfb82 100644 --- a/tests/TestAStarPathfinder.cpp +++ b/tests/TestAStarPathfinder.cpp @@ -40,7 +40,7 @@ bool testVoxelValidator(const VolumeType* volData, const Vector3DInt32& v3dPos) return false; } - typename VolumeType::VoxelType voxel = volData->getVoxel(v3dPos, WrapModes::Validate); // FIXME use templatised version of getVoxel(), but watch out for Linux compile issues. + typename VolumeType::VoxelType voxel = volData->getVoxel(v3dPos); if(voxel != 0) { return false; @@ -92,7 +92,7 @@ void TestAStarPathfinder::testExecute() for(int x = 0; x < uVolumeSideLength; x++) { uint8_t solidVoxel(0); - volData.setVoxelAt(x,y,z,solidVoxel); + volData.setVoxel(x,y,z,solidVoxel); } } } @@ -105,7 +105,7 @@ void TestAStarPathfinder::testExecute() for(int x = 4; x < 12; x++) { uint8_t solidVoxel(1); - volData.setVoxelAt(x,y,z,solidVoxel); + volData.setVoxel(x,y,z,solidVoxel); } } } diff --git a/tests/TestAmbientOcclusionGenerator.cpp b/tests/TestAmbientOcclusionGenerator.cpp index 253af603..683d5c98 100644 --- a/tests/TestAmbientOcclusionGenerator.cpp +++ b/tests/TestAmbientOcclusionGenerator.cpp @@ -24,7 +24,7 @@ freely, subject to the following restrictions: #include "TestAmbientOcclusionGenerator.h" #include "PolyVox/AmbientOcclusionCalculator.h" -#include "PolyVox/PagedVolume.h" +#include "PolyVox/RawVolume.h" #include @@ -49,7 +49,7 @@ void TestAmbientOcclusionGenerator::testExecute() const int32_t g_uVolumeSideLength = 64; //Create empty volume - PagedVolume volData(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1))); + RawVolume volData(Region(0, 0, 0, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1, g_uVolumeSideLength - 1)); //Create two solid walls at opposite sides of the volume for (int32_t z = 0; z < g_uVolumeSideLength; z++) @@ -60,7 +60,7 @@ void TestAmbientOcclusionGenerator::testExecute() { for (int32_t x = 0; x < g_uVolumeSideLength; x++) { - volData.setVoxelAt(x, y, z, 1); + volData.setVoxel(x, y, z, 1); } } } diff --git a/tests/TestCubicSurfaceExtractor.cpp b/tests/TestCubicSurfaceExtractor.cpp index df821f30..a38b5326 100644 --- a/tests/TestCubicSurfaceExtractor.cpp +++ b/tests/TestCubicSurfaceExtractor.cpp @@ -24,6 +24,7 @@ freely, subject to the following restrictions: #include "TestCubicSurfaceExtractor.h" #include "PolyVox/Density.h" +#include "PolyVox/FilePager.h" #include "PolyVox/Material.h" #include "PolyVox/MaterialDensityPair.h" #include "PolyVox/RawVolume.h" @@ -60,11 +61,8 @@ public: // Runs the surface extractor for a given type. template -VolumeType* createAndFillVolumeWithNoise(int32_t iVolumeSideLength, typename VolumeType::VoxelType minValue, typename VolumeType::VoxelType maxValue) +void createAndFillVolumeWithNoise(VolumeType& volData, int32_t iVolumeSideLength, typename VolumeType::VoxelType minValue, typename VolumeType::VoxelType maxValue) { - //Create empty volume - VolumeType* volData = new VolumeType(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(iVolumeSideLength - 1, iVolumeSideLength - 1, iVolumeSideLength - 1))); - // Set up a random number generator std::mt19937 rng; @@ -78,7 +76,7 @@ VolumeType* createAndFillVolumeWithNoise(int32_t iVolumeSideLength, typename Vol if (minValue == maxValue) { // In this case we are filling the whole volume with a single value. - volData->setVoxelAt(x, y, z, minValue); + volData.setVoxel(x, y, z, minValue); } else { @@ -86,13 +84,11 @@ VolumeType* createAndFillVolumeWithNoise(int32_t iVolumeSideLength, typename Vol // We can't use std distributions because they vary between platforms (breaking tests). int voxelValue = (rng() % (maxValue - minValue + 1)) + minValue; // +1 for inclusive bounds - volData->setVoxelAt(x, y, z, static_cast(voxelValue)); + volData.setVoxel(x, y, z, static_cast(voxelValue)); } } } } - - return volData; } // Runs the surface extractor for a given type. @@ -100,7 +96,8 @@ template VolumeType* createAndFillVolumeRealistic(int32_t iVolumeSideLength) { //Create empty volume - VolumeType* volData = new VolumeType(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(iVolumeSideLength - 1, iVolumeSideLength - 1, iVolumeSideLength - 1))); + FilePager* filePager = new FilePager(); + VolumeType* volData = new VolumeType(filePager); //Fill the volume with data for (int32_t z = 0; z < iVolumeSideLength; z++) @@ -113,11 +110,11 @@ VolumeType* createAndFillVolumeRealistic(int32_t iVolumeSideLength) // that it's not empty/random data, and should allow significant decimation to be performed. if ((x ^ y) & 0x01) { - volData->setVoxelAt(x, y, z, 0); + volData->setVoxel(x, y, z, 0); } else { - volData->setVoxelAt(x, y, z, 1); + volData->setVoxel(x, y, z, 1); } } } @@ -128,38 +125,46 @@ VolumeType* createAndFillVolumeRealistic(int32_t iVolumeSideLength) void TestCubicSurfaceExtractor::testBehaviour() { + int32_t iVolumeSideLength = 32; + // Test with default mesh and contoller types. - auto uint8Vol = createAndFillVolumeWithNoise< PagedVolume >(32, 0, 2); - auto uint8Mesh = extractCubicMesh(uint8Vol, uint8Vol->getEnclosingRegion()); + RawVolume uint8Vol(Region(0, 0, 0, iVolumeSideLength - 1, iVolumeSideLength - 1, iVolumeSideLength - 1)); + createAndFillVolumeWithNoise(uint8Vol, 32, 0, 2); + auto uint8Mesh = extractCubicMesh(&uint8Vol, uint8Vol.getEnclosingRegion()); QCOMPARE(uint8Mesh.getNoOfVertices(), uint32_t(57544)); QCOMPARE(uint8Mesh.getNoOfIndices(), uint32_t(215304)); // Test with default mesh type but user-provided controller. - auto int8Vol = createAndFillVolumeWithNoise< PagedVolume >(32, 0, 2); - auto int8Mesh = extractCubicMesh(int8Vol, int8Vol->getEnclosingRegion(), CustomIsQuadNeeded()); + RawVolume int8Vol(Region(0, 0, 0, iVolumeSideLength - 1, iVolumeSideLength - 1, iVolumeSideLength - 1)); + createAndFillVolumeWithNoise(int8Vol, 32, 0, 2); + auto int8Mesh = extractCubicMesh(&int8Vol, int8Vol.getEnclosingRegion(), CustomIsQuadNeeded()); QCOMPARE(int8Mesh.getNoOfVertices(), uint32_t(29106)); QCOMPARE(int8Mesh.getNoOfIndices(), uint32_t(178566)); // Test with default controller but user-provided mesh. - auto uint32Vol = createAndFillVolumeWithNoise< PagedVolume >(32, 0, 2); + RawVolume uint32Vol(Region(0, 0, 0, iVolumeSideLength - 1, iVolumeSideLength - 1, iVolumeSideLength - 1)); + createAndFillVolumeWithNoise(uint32Vol, 32, 0, 2); Mesh< CubicVertex< uint32_t >, uint16_t > uint32Mesh; - extractCubicMeshCustom(uint32Vol, uint32Vol->getEnclosingRegion(), &uint32Mesh); + extractCubicMeshCustom(&uint32Vol, uint32Vol.getEnclosingRegion(), &uint32Mesh); QCOMPARE(uint32Mesh.getNoOfVertices(), uint16_t(57544)); QCOMPARE(uint32Mesh.getNoOfIndices(), uint32_t(215304)); // Test with both mesh and controller being provided by the user. - auto int32Vol = createAndFillVolumeWithNoise< PagedVolume >(32, 0, 2); + RawVolume int32Vol(Region(0, 0, 0, iVolumeSideLength - 1, iVolumeSideLength - 1, iVolumeSideLength - 1)); + createAndFillVolumeWithNoise(int32Vol, 32, 0, 2); Mesh< CubicVertex< int32_t >, uint16_t > int32Mesh; - extractCubicMeshCustom(int32Vol, int32Vol->getEnclosingRegion(), &int32Mesh, CustomIsQuadNeeded()); + extractCubicMeshCustom(&int32Vol, int32Vol.getEnclosingRegion(), &int32Mesh, CustomIsQuadNeeded()); QCOMPARE(int32Mesh.getNoOfVertices(), uint16_t(29106)); QCOMPARE(int32Mesh.getNoOfIndices(), uint32_t(178566)); } void TestCubicSurfaceExtractor::testEmptyVolumePerformance() { - auto emptyVol = createAndFillVolumeWithNoise< PagedVolume >(128, 0, 0); + FilePager* filePager = new FilePager(); + PagedVolume emptyVol(filePager); + createAndFillVolumeWithNoise(emptyVol, 128, 0, 0); Mesh< CubicVertex< uint32_t >, uint16_t > emptyMesh; - QBENCHMARK{ extractCubicMeshCustom(emptyVol, Region(32, 32, 32, 63, 63, 63), &emptyMesh); } + QBENCHMARK{ extractCubicMeshCustom(&emptyVol, Region(32, 32, 32, 63, 63, 63), &emptyMesh); } QCOMPARE(emptyMesh.getNoOfVertices(), uint16_t(0)); } @@ -173,9 +178,11 @@ void TestCubicSurfaceExtractor::testRealisticVolumePerformance() void TestCubicSurfaceExtractor::testNoiseVolumePerformance() { - auto noiseVol = createAndFillVolumeWithNoise< PagedVolume >(128, 0, 2); + FilePager* filePager = new FilePager(); + PagedVolume noiseVol(filePager); + createAndFillVolumeWithNoise(noiseVol, 128, 0, 2); Mesh< CubicVertex< uint32_t >, uint16_t > noiseMesh; - QBENCHMARK{ extractCubicMeshCustom(noiseVol, Region(32, 32, 32, 63, 63, 63), &noiseMesh); } + QBENCHMARK{ extractCubicMeshCustom(&noiseVol, Region(32, 32, 32, 63, 63, 63), &noiseMesh); } QCOMPARE(noiseMesh.getNoOfVertices(), uint16_t(57905)); } diff --git a/tests/TestLowPassFilter.cpp b/tests/TestLowPassFilter.cpp index 849cf927..b6263115 100644 --- a/tests/TestLowPassFilter.cpp +++ b/tests/TestLowPassFilter.cpp @@ -50,7 +50,7 @@ void TestLowPassFilter::testExecute() if(x % 2 == 0) { Density8 voxel(32); - volData.setVoxelAt(x, y, z, voxel); + volData.setVoxel(x, y, z, voxel); } } } diff --git a/tests/TestPicking.cpp b/tests/TestPicking.cpp index 78f2b5c6..748b31e2 100644 --- a/tests/TestPicking.cpp +++ b/tests/TestPicking.cpp @@ -24,7 +24,7 @@ freely, subject to the following restrictions: #include "TestPicking.h" #include "PolyVox/Picking.h" -#include "PolyVox/PagedVolume.h" +#include "PolyVox/RawVolume.h" #include @@ -34,7 +34,7 @@ void TestPicking::testExecute() { const int32_t uVolumeSideLength = 32; - PagedVolume volData(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(uVolumeSideLength - 1, uVolumeSideLength - 1, uVolumeSideLength - 1))); + RawVolume volData(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(uVolumeSideLength - 1, uVolumeSideLength - 1, uVolumeSideLength - 1))); for (int32_t z = 0; z < uVolumeSideLength; z++) { for (int32_t y = 0; y < uVolumeSideLength; y++) @@ -43,11 +43,11 @@ void TestPicking::testExecute() { if((x > uVolumeSideLength/2)) //x > 16 is filled { - volData.setVoxelAt(x, y, z, 100); + volData.setVoxel(x, y, z, 100); } else { - volData.setVoxelAt(x, y, z, 0); + volData.setVoxel(x, y, z, 0); } } } diff --git a/tests/TestRaycast.cpp b/tests/TestRaycast.cpp index 655d2b0b..1ea9c9e0 100644 --- a/tests/TestRaycast.cpp +++ b/tests/TestRaycast.cpp @@ -25,7 +25,7 @@ freely, subject to the following restrictions: #include "PolyVox/Density.h" #include "PolyVox/Raycast.h" -#include "PolyVox/PagedVolume.h" +#include "PolyVox/RawVolume.h" #include "PolyVox/Impl/RandomUnitVectors.h" @@ -47,7 +47,7 @@ public: { } - bool operator()(const PagedVolume::Sampler& sampler) + bool operator()(const RawVolume::Sampler& sampler) { m_uVoxelsTouched++; @@ -73,7 +73,7 @@ void TestRaycast::testExecute() const int32_t uVolumeSideLength = 32; //Create a hollow volume, with solid sides on x and y but with open ends in z. - PagedVolume volData(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(uVolumeSideLength - 1, uVolumeSideLength - 1, uVolumeSideLength - 1))); + RawVolume volData(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(uVolumeSideLength - 1, uVolumeSideLength - 1, uVolumeSideLength - 1))); for (int32_t z = 0; z < uVolumeSideLength; z++) { for (int32_t y = 0; y < uVolumeSideLength; y++) @@ -82,11 +82,11 @@ void TestRaycast::testExecute() { if((x == 0) || (x == uVolumeSideLength-1) || (y == 0) || (y == uVolumeSideLength-1)) { - volData.setVoxelAt(x, y, z, 100); + volData.setVoxel(x, y, z, 100); } else { - volData.setVoxelAt(x, y, z, -100); + volData.setVoxel(x, y, z, -100); } } } diff --git a/tests/TestSurfaceExtractor.cpp b/tests/TestSurfaceExtractor.cpp index 6be9aa2d..56c61092 100644 --- a/tests/TestSurfaceExtractor.cpp +++ b/tests/TestSurfaceExtractor.cpp @@ -103,10 +103,8 @@ VolumeType* createAndFillVolume(void) { const int32_t uVolumeSideLength = 64; - FilePager* pager = new FilePager("."); - //Create empty volume - VolumeType* volData = new VolumeType(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(uVolumeSideLength - 1, uVolumeSideLength - 1, uVolumeSideLength - 1)), pager); + VolumeType* volData = new VolumeType(Region(0, 0, 0, uVolumeSideLength - 1, uVolumeSideLength - 1, uVolumeSideLength - 1)); // Fill for (int32_t z = 0; z < uVolumeSideLength; z++) @@ -120,7 +118,7 @@ VolumeType* createAndFillVolume(void) typename VolumeType::VoxelType voxelValue; writeDensityValueToVoxel(x + y + z, voxelValue); writeMaterialValueToVoxel(z > uVolumeSideLength / 2 ? 42 : 79, voxelValue); - volData->setVoxelAt(x, y, z, voxelValue); + volData->setVoxel(x, y, z, voxelValue); } } } @@ -134,7 +132,7 @@ VolumeType* createAndFillVolumeWithNoise(int32_t iVolumeSideLength, float minVal FilePager* pager = new FilePager("."); //Create empty volume - VolumeType* volData = new VolumeType(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(iVolumeSideLength - 1, iVolumeSideLength - 1, iVolumeSideLength - 1)), pager); + VolumeType* volData = new VolumeType(pager); // Set up a random number generator std::mt19937 rng; @@ -150,7 +148,7 @@ VolumeType* createAndFillVolumeWithNoise(int32_t iVolumeSideLength, float minVal float voxelValue = static_cast(rng()) / static_cast(std::numeric_limits::max()); // Float in range 0.0 to 1.0 voxelValue = voxelValue * (maxValue - minValue) + minValue; // Float in range minValue to maxValue - volData->setVoxelAt(x, y, z, voxelValue); + volData->setVoxel(x, y, z, voxelValue); } } } @@ -168,7 +166,7 @@ void TestSurfaceExtractor::testBehaviour() // Of course, the use of a custom controller will also make a significant diference, but this probably does need investigating further in the future. // This basic test just uses the default controller and automatically generates a mesh of the appropriate type. - auto uintVol = createAndFillVolume< PagedVolume >(); + auto uintVol = createAndFillVolume< RawVolume >(); auto uintMesh = extractMarchingCubesMesh(uintVol, uintVol->getEnclosingRegion()); QCOMPARE(uintMesh.getNoOfVertices(), uint32_t(12096)); // Verifies size of mesh and that we have 32-bit indices QCOMPARE(uintMesh.getNoOfIndices(), uint32_t(35157)); // Verifies size of mesh @@ -176,7 +174,7 @@ void TestSurfaceExtractor::testBehaviour() QCOMPARE(uintMesh.getVertex(100).data, uint8_t(1)); // Not really meaningful for a primative type // This test makes use of a custom controller - auto floatVol = createAndFillVolume< PagedVolume >(); + auto floatVol = createAndFillVolume< RawVolume >(); CustomMarchingCubesController floatCustomController; auto floatMesh = extractMarchingCubesMesh(floatVol, floatVol->getEnclosingRegion(), floatCustomController); QCOMPARE(floatMesh.getNoOfVertices(), uint32_t(16113)); // Verifies size of mesh and that we have 32-bit indices @@ -186,7 +184,7 @@ void TestSurfaceExtractor::testBehaviour() // This test makes use of a user provided mesh. It uses the default controller, but we have to explicitly provide this because C++ won't let us // use a default for the second-to-last parameter but noot use a default for the last parameter. - auto intVol = createAndFillVolume< PagedVolume >(); + auto intVol = createAndFillVolume< RawVolume >(); Mesh< MarchingCubesVertex< int8_t >, uint16_t > intMesh; extractMarchingCubesMeshCustom(intVol, intVol->getEnclosingRegion(), &intMesh); QCOMPARE(intMesh.getNoOfVertices(), uint16_t(11718)); // Verifies size of mesh and that we have 16-bit indices @@ -195,7 +193,7 @@ void TestSurfaceExtractor::testBehaviour() QCOMPARE(intMesh.getVertex(100).data, int8_t(1)); // Not really meaningful for a primative type // This test makes use of a user-provided mesh and also a custom controller. - auto doubleVol = createAndFillVolume< PagedVolume >(); + auto doubleVol = createAndFillVolume< RawVolume >(); CustomMarchingCubesController doubleCustomController; Mesh< MarchingCubesVertex< double >, uint16_t > doubleMesh; extractMarchingCubesMeshCustom(doubleVol, doubleVol->getEnclosingRegion(), &doubleMesh, doubleCustomController); @@ -205,7 +203,7 @@ void TestSurfaceExtractor::testBehaviour() QCOMPARE(doubleMesh.getVertex(100).data, double(1.0f)); // Not really meaningful for a primative type // This test ensures the extractor works on a non-primitive voxel type. - auto materialVol = createAndFillVolume< PagedVolume >(); + auto materialVol = createAndFillVolume< RawVolume >(); auto materialMesh = extractMarchingCubesMesh(materialVol, materialVol->getEnclosingRegion()); QCOMPARE(materialMesh.getNoOfVertices(), uint32_t(12096)); // Verifies size of mesh and that we have 32-bit indices QCOMPARE(materialMesh.getNoOfIndices(), uint32_t(35157)); // Verifies size of mesh diff --git a/tests/TestVolumeSubclass.cpp b/tests/TestVolumeSubclass.cpp index 0a301e3e..eb5238ca 100644 --- a/tests/TestVolumeSubclass.cpp +++ b/tests/TestVolumeSubclass.cpp @@ -62,8 +62,8 @@ public: /// Constructor for creating a fixed size volume. VolumeSubclass(const Region& regValid) - :BaseVolume(regValid) - , mVolumeData(this->getWidth(), this->getHeight(), this->getDepth()) + :BaseVolume() + , mVolumeData(regValid.getWidthInVoxels(), regValid.getHeightInVoxels(), regValid.getDepthInVoxels()) { //mVolumeData.resize(ArraySizes(this->getWidth())(this->getHeight())(this->getDepth())); } @@ -71,83 +71,30 @@ public: ~VolumeSubclass() {}; /// Gets a voxel at the position given by x,y,z coordinates - template - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder = VoxelType()) const + VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const { - // FIXME: This templatised version is implemented in terms of the not template version. This is strange - // from a peformance point of view but it's just because we were encountering some compile issues on GCC. - return getVoxel(uXPos, uYPos, uZPos, eWrapMode, tBorder); - } - - /// Gets a voxel at the position given by a 3D vector - template - VoxelType getVoxel(const Vector3DInt32& v3dPos, VoxelType tBorder = VoxelType()) const - { - // Simply call through to the real implementation - return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tBorder); - } - - /// Gets a voxel at the position given by x,y,z coordinates - VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const - { - switch(eWrapMode) + if ((uXPos < mVolumeData.getDimension(0)) && (uYPos < mVolumeData.getDimension(1)) && (uZPos < mVolumeData.getDimension(2))) { - case WrapModes::Validate: - { - if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) - { - POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); - } - - return mVolumeData(uXPos, uYPos, uZPos); - } - case WrapModes::Clamp: - { - //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 mVolumeData(uXPos, uYPos, uZPos); - } - case WrapModes::Border: - { - if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) - { - return mVolumeData(uXPos, uYPos, uZPos); - } - else - { - return tBorder; - } - } - case WrapModes::AssumeValid: - { - return mVolumeData(uXPos, uYPos, uZPos); - } - default: - { - // Should never happen - POLYVOX_ASSERT(false, "Invalid wrap mode"); - return VoxelType(); - } + return mVolumeData(uXPos, uYPos, uZPos); + } + else + { + return VoxelType(); } } /// Gets a voxel at the position given by a 3D vector - VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Validate, VoxelType tBorder = VoxelType()) const + VoxelType getVoxel(const Vector3DInt32& v3dPos) const { - return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); + return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); } /// Sets the value used for voxels which are outside the volume void setBorderValue(const VoxelType& tBorder) { } /// Sets the voxel at the position given by x,y,z coordinates - bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) + bool setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) { - if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos))) + if ((uXPos < mVolumeData.getDimension(0)) && (uYPos < mVolumeData.getDimension(1)) && (uZPos < mVolumeData.getDimension(2))) { mVolumeData(uXPos, uYPos, uZPos) = tValue; return true; @@ -158,7 +105,7 @@ public: } } /// Sets the voxel at the position given by a 3D vector - bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue) { return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } + bool setVoxel(const Vector3DInt32& v3dPos, VoxelType tValue) { return setVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } /// Calculates approximatly how many bytes of memory the volume is currently using. uint32_t calculateSizeInBytes(void) { return 0; } @@ -172,21 +119,22 @@ private: void TestVolumeSubclass::testExtractSurface() { - VolumeSubclass volumeSubclass(Region(0,0,0,16,16,16)); + Region region(0, 0, 0, 16, 16, 16); + VolumeSubclass volumeSubclass(region); - for(int32_t z = 0; z < volumeSubclass.getDepth() / 2; z++) + for (int32_t z = 0; z < region.getDepthInVoxels() / 2; z++) { - for(int32_t y = 0; y < volumeSubclass.getHeight(); y++) + for (int32_t y = 0; y < region.getHeightInVoxels(); y++) { - for(int32_t x = 0; x < volumeSubclass.getWidth(); x++) + for (int32_t x = 0; x < region.getWidthInVoxels(); x++) { Material8 mat(1); - volumeSubclass.setVoxelAt(Vector3DInt32(x,y,z),mat); + volumeSubclass.setVoxel(Vector3DInt32(x,y,z),mat); } } } - auto result = extractCubicMesh(&volumeSubclass, volumeSubclass.getEnclosingRegion()); + auto result = extractCubicMesh(&volumeSubclass, region); QCOMPARE(result.getNoOfVertices(), static_cast(8)); } diff --git a/tests/testvolume.cpp b/tests/testvolume.cpp index df2a3a97..27d10a57 100644 --- a/tests/testvolume.cpp +++ b/tests/testvolume.cpp @@ -46,18 +46,15 @@ inline int32_t cantorTupleFunction(int32_t previousResult, int32_t value) // We allow user provided offset in this function so we can test the case when all samples are inside a volume and also the case when some samples are outside. // This is important because samplers are often slower when outside the volume as they have to fall back on directly accessing the volume data. template -int32_t testDirectAccessWithWrappingForwards(const VolumeType* volume, int lowXOffset, int lowYOffset, int lowZOffset, int highXOffset, int highYOffset, int highZOffset) +int32_t testDirectAccessWithWrappingForwards(const VolumeType* volume, Region region) { int32_t result = 0; - // If we know that we are only iterating over voxels internal to the volume then we can avoid calling the 'wrapping' function. This should be faster. - bool bAllVoxelsInternal = (lowXOffset > 0) && (lowYOffset > 0) && (lowZOffset > 0) && (highXOffset < 0) && (highYOffset < 0) && (highZOffset < 0); - - for(int z = volume->getEnclosingRegion().getLowerZ() + lowZOffset; z <= volume->getEnclosingRegion().getUpperZ() + highZOffset; z++) + for (int z = region.getLowerZ(); z <= region.getUpperZ(); z++) { - for(int y = volume->getEnclosingRegion().getLowerY() + lowYOffset; y <= volume->getEnclosingRegion().getUpperY() + highYOffset; y++) + for (int y = region.getLowerY(); y <= region.getUpperY(); y++) { - for(int x = volume->getEnclosingRegion().getLowerX() + lowXOffset; x <= volume->getEnclosingRegion().getUpperX() + highXOffset; x++) + for (int x = region.getLowerX(); x <= region.getUpperX(); x++) { //Three level loop now processes 27 voxel neighbourhood for(int innerZ = -1; innerZ <=1; innerZ++) @@ -66,16 +63,7 @@ int32_t testDirectAccessWithWrappingForwards(const VolumeType* volume, int lowXO { for(int innerX = -1; innerX <=1; innerX++) { - // Deeply nested 'if', but this is just a unit test and we should still - // see some performance improvement by skipping the wrapping versions. - if(bAllVoxelsInternal) - { - result = cantorTupleFunction(result, volume->getVoxel(x + innerX, y + innerY, z + innerZ)); - } - else - { - result = cantorTupleFunction(result, volume->getVoxel(x + innerX, y + innerY, z + innerZ, WrapModes::Border, 3)); - } + result = cantorTupleFunction(result, volume->getVoxel(x + innerX, y + innerY, z + innerZ)); } } } @@ -88,7 +76,7 @@ int32_t testDirectAccessWithWrappingForwards(const VolumeType* volume, int lowXO } template -int32_t testSamplersWithWrappingForwards(VolumeType* volume, int lowXOffset, int lowYOffset, int lowZOffset, int highXOffset, int highYOffset, int highZOffset) +int32_t testSamplersWithWrappingForwards(VolumeType* volume, Region region) { int32_t result = 0; @@ -97,18 +85,14 @@ int32_t testSamplersWithWrappingForwards(VolumeType* volume, int lowXOffset, int typename VolumeType::Sampler ySampler(volume); typename VolumeType::Sampler zSampler(volume); - xSampler.setWrapMode(WrapModes::Border, 3); - ySampler.setWrapMode(WrapModes::Border, 3); - zSampler.setWrapMode(WrapModes::Border, 3); - - zSampler.setPosition(volume->getEnclosingRegion().getLowerX() + lowXOffset, volume->getEnclosingRegion().getLowerY() + lowYOffset, volume->getEnclosingRegion().getLowerZ() + lowZOffset); - for(int z = volume->getEnclosingRegion().getLowerZ() + lowZOffset; z <= volume->getEnclosingRegion().getUpperZ() + highZOffset; z++) + zSampler.setPosition(region.getLowerX(), region.getLowerY(), region.getLowerZ()); + for (int z = region.getLowerZ(); z <= region.getUpperZ(); z++) { ySampler = zSampler; - for(int y = volume->getEnclosingRegion().getLowerY() + lowYOffset; y <= volume->getEnclosingRegion().getUpperY() + highYOffset; y++) + for (int y = region.getLowerY(); y <= region.getUpperY(); y++) { xSampler = ySampler; - for(int x = volume->getEnclosingRegion().getLowerX() + lowXOffset; x <= volume->getEnclosingRegion().getUpperX() + highXOffset; x++) + for (int x = region.getLowerX(); x <= region.getUpperX(); x++) { xSampler.setPosition(x, y, z); // HACK - Accessing a volume through multiple samplers currently breaks the PagedVolume. @@ -159,18 +143,15 @@ int32_t testSamplersWithWrappingForwards(VolumeType* volume, int lowXOffset, int // We allow user provided offset in this function so we can test the case when all samples are inside a volume and also the case when some samples are outside. // This is important because samplers are often slower when outside the volume as they have to fall back on directly accessing the volume data. template -int32_t testDirectAccessWithWrappingBackwards(const VolumeType* volume, int lowXOffset, int lowYOffset, int lowZOffset, int highXOffset, int highYOffset, int highZOffset) +int32_t testDirectAccessWithWrappingBackwards(const VolumeType* volume, Region region) { int32_t result = 0; - // If we know that we are only iterating over voxels internal to the volume then we can avoid calling the 'wrapping' function. This should be faster. - bool bAllVoxelsInternal = (lowXOffset > 0) && (lowYOffset > 0) && (lowZOffset > 0) && (highXOffset < 0) && (highYOffset < 0) && (highZOffset < 0); - - for(int z = volume->getEnclosingRegion().getUpperZ() + highZOffset; z >= volume->getEnclosingRegion().getLowerZ() + lowZOffset; z--) + for (int z = region.getUpperZ(); z >= region.getLowerZ(); z--) { - for(int y = volume->getEnclosingRegion().getUpperY() + highYOffset; y >= volume->getEnclosingRegion().getLowerY() + lowYOffset; y--) + for (int y = region.getUpperY(); y >= region.getLowerY(); y--) { - for(int x = volume->getEnclosingRegion().getUpperX() + highXOffset; x >= volume->getEnclosingRegion().getLowerX() + lowXOffset; x--) + for (int x = region.getUpperX(); x >= region.getLowerX(); x--) { //Three level loop now processes 27 voxel neighbourhood for(int innerZ = -1; innerZ <=1; innerZ++) @@ -179,16 +160,7 @@ int32_t testDirectAccessWithWrappingBackwards(const VolumeType* volume, int lowX { for(int innerX = -1; innerX <=1; innerX++) { - // Deeply nested 'if', but this is just a unit test and we should still - // see some performance improvement by skipping the wrapping versions. - if(bAllVoxelsInternal) - { - result = cantorTupleFunction(result, volume->getVoxel(x + innerX, y + innerY, z + innerZ)); - } - else - { - result = cantorTupleFunction(result, volume->getVoxel(x + innerX, y + innerY, z + innerZ, WrapModes::Border, 3)); - } + result = cantorTupleFunction(result, volume->getVoxel(x + innerX, y + innerY, z + innerZ)); } } } @@ -201,7 +173,7 @@ int32_t testDirectAccessWithWrappingBackwards(const VolumeType* volume, int lowX } template -int32_t testSamplersWithWrappingBackwards(VolumeType* volume, int lowXOffset, int lowYOffset, int lowZOffset, int highXOffset, int highYOffset, int highZOffset) +int32_t testSamplersWithWrappingBackwards(VolumeType* volume, Region region) { int32_t result = 0; @@ -210,18 +182,14 @@ int32_t testSamplersWithWrappingBackwards(VolumeType* volume, int lowXOffset, in typename VolumeType::Sampler ySampler(volume); typename VolumeType::Sampler zSampler(volume); - xSampler.setWrapMode(WrapModes::Border, 3); - ySampler.setWrapMode(WrapModes::Border, 3); - zSampler.setWrapMode(WrapModes::Border, 3); - - zSampler.setPosition(volume->getEnclosingRegion().getUpperX() + highXOffset, volume->getEnclosingRegion().getUpperY() + highYOffset, volume->getEnclosingRegion().getUpperZ() + highZOffset); - for(int z = volume->getEnclosingRegion().getUpperZ() + highZOffset; z >= volume->getEnclosingRegion().getLowerZ() + lowZOffset; z--) + zSampler.setPosition(region.getUpperX(), region.getUpperY(), region.getUpperZ()); + for (int z = region.getUpperZ(); z >= region.getLowerZ(); z--) { ySampler = zSampler; - for(int y = volume->getEnclosingRegion().getUpperY() + highYOffset; y >= volume->getEnclosingRegion().getLowerY() + lowYOffset; y--) + for (int y = region.getUpperY(); y >= region.getLowerY(); y--) { xSampler = ySampler; - for(int x = volume->getEnclosingRegion().getUpperX() + highXOffset; x >= volume->getEnclosingRegion().getLowerX() + lowXOffset; x--) + for (int x = region.getUpperX(); x >= region.getLowerX(); x--) { xSampler.setPosition(x, y, z); // HACK - Accessing a volume through multiple samplers currently breaks the PagedVolume. @@ -267,26 +235,32 @@ int32_t testSamplersWithWrappingBackwards(VolumeType* volume, int lowXOffset, in TestVolume::TestVolume() { - Region region(-57, -31, 12, 64, 96, 131); // Deliberatly awkward size + m_regVolume = Region(-57, -31, 12, 64, 96, 131); // Deliberatly awkward size + + m_regInternal = m_regVolume; + m_regInternal.shiftLowerCorner(4, 2, 2); + m_regInternal.shiftUpperCorner(-3, -1, -2); + + m_regExternal = m_regVolume; + m_regExternal.shiftLowerCorner(-1, -3, -2); + m_regExternal.shiftUpperCorner(2, 5, 4); m_pFilePager = new FilePager("."); //Create the volumes - m_pRawVolume = new RawVolume(region); - m_pPagedVolume = new PagedVolume(region, m_pFilePager, 32); - - m_pPagedVolume->setMemoryUsageLimit(1 * 1024 * 1024); + m_pRawVolume = new RawVolume(m_regVolume); + m_pPagedVolume = new PagedVolume(m_pFilePager, 1 * 1024 * 1024, 32); //Fill the volume with some data - for(int z = region.getLowerZ(); z <= region.getUpperZ(); z++) + for (int z = m_regVolume.getLowerZ(); z <= m_regVolume.getUpperZ(); z++) { - for(int y = region.getLowerY(); y <= region.getUpperY(); y++) + for (int y = m_regVolume.getLowerY(); y <= m_regVolume.getUpperY(); y++) { - for(int x = region.getLowerX(); x <= region.getUpperX(); x++) + for (int x = m_regVolume.getLowerX(); x <= m_regVolume.getUpperX(); x++) { int32_t value = x + y + z; - m_pRawVolume->setVoxelAt(x, y, z, value); - m_pPagedVolume->setVoxelAt(x, y, z, value); + m_pRawVolume->setVoxel(x, y, z, value); + m_pPagedVolume->setVoxel(x, y, z, value); } } } @@ -310,7 +284,7 @@ void TestVolume::testRawVolumeDirectAccessAllInternalForwards() QBENCHMARK { - result = testDirectAccessWithWrappingForwards(m_pRawVolume, 4, 2, 2, -3, -1, -2); + result = testDirectAccessWithWrappingForwards(m_pRawVolume, m_regInternal); } QCOMPARE(result, static_cast(1004598054)); } @@ -321,7 +295,7 @@ void TestVolume::testRawVolumeSamplersAllInternalForwards() QBENCHMARK { - result = testSamplersWithWrappingForwards(m_pRawVolume, 4, 2, 2, -3, -1, -2); + result = testSamplersWithWrappingForwards(m_pRawVolume, m_regInternal); } QCOMPARE(result, static_cast(1004598054)); } @@ -332,9 +306,9 @@ void TestVolume::testRawVolumeDirectAccessWithExternalForwards() QBENCHMARK { - result = testDirectAccessWithWrappingForwards(m_pRawVolume, -1, -3, -2, 2, 5, 4); + result = testDirectAccessWithWrappingForwards(m_pRawVolume, m_regExternal); } - QCOMPARE(result, static_cast(-928601007)); + QCOMPARE(result, static_cast(337227750)); } void TestVolume::testRawVolumeSamplersWithExternalForwards() @@ -343,9 +317,9 @@ void TestVolume::testRawVolumeSamplersWithExternalForwards() QBENCHMARK { - result = testSamplersWithWrappingForwards(m_pRawVolume, -1, -3, -2, 2, 5, 4); + result = testSamplersWithWrappingForwards(m_pRawVolume, m_regExternal); } - QCOMPARE(result, static_cast(-928601007)); + QCOMPARE(result, static_cast(337227750)); } void TestVolume::testRawVolumeDirectAccessAllInternalBackwards() @@ -354,7 +328,7 @@ void TestVolume::testRawVolumeDirectAccessAllInternalBackwards() QBENCHMARK { - result = testDirectAccessWithWrappingBackwards(m_pRawVolume, 4, 2, 2, -3, -1, -2); + result = testDirectAccessWithWrappingBackwards(m_pRawVolume, m_regInternal); } QCOMPARE(result, static_cast(-269366578)); } @@ -365,7 +339,7 @@ void TestVolume::testRawVolumeSamplersAllInternalBackwards() QBENCHMARK { - result = testSamplersWithWrappingBackwards(m_pRawVolume, 4, 2, 2, -3, -1, -2); + result = testSamplersWithWrappingBackwards(m_pRawVolume, m_regInternal); } QCOMPARE(result, static_cast(-269366578)); } @@ -376,9 +350,9 @@ void TestVolume::testRawVolumeDirectAccessWithExternalBackwards() QBENCHMARK { - result = testDirectAccessWithWrappingBackwards(m_pRawVolume, -1, -3, -2, 2, 5, 4); + result = testDirectAccessWithWrappingBackwards(m_pRawVolume, m_regExternal); } - QCOMPARE(result, static_cast(-769775893)); + QCOMPARE(result, static_cast(-993539594)); } void TestVolume::testRawVolumeSamplersWithExternalBackwards() @@ -387,9 +361,9 @@ void TestVolume::testRawVolumeSamplersWithExternalBackwards() QBENCHMARK { - result = testSamplersWithWrappingBackwards(m_pRawVolume, -1, -3, -2, 2, 5, 4); + result = testSamplersWithWrappingBackwards(m_pRawVolume, m_regExternal); } - QCOMPARE(result, static_cast(-769775893)); + QCOMPARE(result, static_cast(-993539594)); } /* @@ -401,7 +375,7 @@ void TestVolume::testPagedVolumeDirectAccessAllInternalForwards() int32_t result = 0; QBENCHMARK { - result = testDirectAccessWithWrappingForwards(m_pPagedVolume, 4, 2, 2, -3, -1, -2); + result = testDirectAccessWithWrappingForwards(m_pPagedVolume, m_regInternal); } QCOMPARE(result, static_cast(1004598054)); } @@ -411,7 +385,7 @@ void TestVolume::testPagedVolumeSamplersAllInternalForwards() int32_t result = 0; QBENCHMARK { - result = testSamplersWithWrappingForwards(m_pPagedVolume, 4, 2, 2, -3, -1, -2); + result = testSamplersWithWrappingForwards(m_pPagedVolume, m_regInternal); } QCOMPARE(result, static_cast(1004598054)); } @@ -421,9 +395,9 @@ void TestVolume::testPagedVolumeDirectAccessWithExternalForwards() int32_t result = 0; QBENCHMARK { - result = testDirectAccessWithWrappingForwards(m_pPagedVolume, -1, -3, -2, 2, 5, 4); + result = testDirectAccessWithWrappingForwards(m_pPagedVolume, m_regExternal); } - QCOMPARE(result, static_cast(-928601007)); + QCOMPARE(result, static_cast(337227750)); } void TestVolume::testPagedVolumeSamplersWithExternalForwards() @@ -431,9 +405,9 @@ void TestVolume::testPagedVolumeSamplersWithExternalForwards() int32_t result = 0; QBENCHMARK { - result = testSamplersWithWrappingForwards(m_pPagedVolume, -1, -3, -2, 2, 5, 4); + result = testSamplersWithWrappingForwards(m_pPagedVolume, m_regExternal); } - QCOMPARE(result, static_cast(-928601007)); + QCOMPARE(result, static_cast(337227750)); } void TestVolume::testPagedVolumeDirectAccessAllInternalBackwards() @@ -441,7 +415,7 @@ void TestVolume::testPagedVolumeDirectAccessAllInternalBackwards() int32_t result = 0; QBENCHMARK { - result = testDirectAccessWithWrappingBackwards(m_pPagedVolume, 4, 2, 2, -3, -1, -2); + result = testDirectAccessWithWrappingBackwards(m_pPagedVolume, m_regInternal); } QCOMPARE(result, static_cast(-269366578)); } @@ -451,7 +425,7 @@ void TestVolume::testPagedVolumeSamplersAllInternalBackwards() int32_t result = 0; QBENCHMARK { - result = testSamplersWithWrappingBackwards(m_pPagedVolume, 4, 2, 2, -3, -1, -2); + result = testSamplersWithWrappingBackwards(m_pPagedVolume, m_regInternal); } QCOMPARE(result, static_cast(-269366578)); } @@ -461,9 +435,9 @@ void TestVolume::testPagedVolumeDirectAccessWithExternalBackwards() int32_t result = 0; QBENCHMARK { - result = testDirectAccessWithWrappingBackwards(m_pPagedVolume, -1, -3, -2, 2, 5, 4); + result = testDirectAccessWithWrappingBackwards(m_pPagedVolume, m_regExternal); } - QCOMPARE(result, static_cast(-769775893)); + QCOMPARE(result, static_cast(-993539594)); } void TestVolume::testPagedVolumeSamplersWithExternalBackwards() @@ -471,9 +445,9 @@ void TestVolume::testPagedVolumeSamplersWithExternalBackwards() int32_t result = 0; QBENCHMARK { - result = testSamplersWithWrappingBackwards(m_pPagedVolume, -1, -3, -2, 2, 5, 4); + result = testSamplersWithWrappingBackwards(m_pPagedVolume, m_regExternal); } - QCOMPARE(result, static_cast(-769775893)); + QCOMPARE(result, static_cast(-993539594)); } QTEST_MAIN(TestVolume) diff --git a/tests/testvolume.h b/tests/testvolume.h index 41ec64dd..79bab98d 100644 --- a/tests/testvolume.h +++ b/tests/testvolume.h @@ -25,6 +25,7 @@ freely, subject to the following restrictions: #define __PolyVox_TestVolume_H__ #include "PolyVox/PolyVoxForwardDeclarations.h" +#include "PolyVox/Region.h" #include @@ -56,6 +57,9 @@ private slots: void testPagedVolumeSamplersWithExternalBackwards(); private: + PolyVox::Region m_regVolume; + PolyVox::Region m_regInternal; + PolyVox::Region m_regExternal; PolyVox::FilePager* m_pFilePager; PolyVox::RawVolume* m_pRawVolume;