diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/Utility.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/Utility.h index 7d243c79..915c20ab 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/Utility.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/Utility.h @@ -32,6 +32,19 @@ namespace PolyVox { POLYVOX_API uint8_t logBase2(uint32_t uInput); POLYVOX_API bool isPowerOf2(uint32_t uInput); + + int32_t roundTowardsNegInf(float r); + int32_t roundToInteger(float r); + + inline int32_t roundTowardsNegInf(float r) + { + return (r > 0.0) ? static_cast(r) : static_cast(r - 1.0f); + } + + inline int32_t roundToNearestInteger(float r) + { + return (r > 0.0) ? static_cast(r + 0.5f) : static_cast(r - 0.5f); + } } #endif diff --git a/library/PolyVoxCore/include/PolyVoxCore/Region.h b/library/PolyVoxCore/include/PolyVoxCore/Region.h index 3c937ca5..564bd0b1 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Region.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Region.h @@ -30,21 +30,25 @@ freely, subject to the following restrictions: namespace PolyVox { - /** - Represents a part of a Volume. - - Many operations in PolyVox are constrained to only part of a volume. For example, when running the surface extractors - it is unlikely that you will want to run it on the whole volume at once, as this will give a very large mesh which may - be too much to render. Instead you will probably want to run a surface extractor a number of times on different parts - of the volume, there by giving a number of meshes which can be culled and rendered seperately. - - The Region class is used to define these parts (regions) of the volume. Essentially it consists of an upper and lower - bound which specify the range of voxels positions considered to be part of the region. Note that these bounds are - inclusive. The class also provides functions for modifying the regions in a variety of ways. - - \Note The dimensions of a region can be measured either in voxels or in cells. See the manual for more information - about these definitions. - */ + /// Represents a part of a Volume. + //////////////////////////////////////////////////////////////////////////////// + /// Many operations in PolyVox are constrained to only part of a volume. For example, when running the surface extractors + /// it is unlikely that you will want to run it on the whole volume at once, as this will give a very large mesh which may + /// be too much to render. Instead you will probably want to run a surface extractor a number of times on different parts + /// of the volume, there by giving a number of meshes which can be culled and rendered seperately. + /// + /// The Region class is used to define these parts (regions) of the volume. Essentially it consists of an upper and lower + /// bound which specify the range of voxels positions considered to be part of the region. Note that these bounds are + /// inclusive. + /// + /// As well as the expected set of getters and setters, this class also provide utility functions for increasing and decresing + /// the size of the Region, shifting the Region in 3D space, testing whether it contains a given position, enlarging it so that + /// it does contain a given position, croppng it to another Region, and various other utility functions. + /// + /// \Note The dimensions of a region can be measured either in voxels or in cells. See the manual for more information + /// about these definitions. + /// + //////////////////////////////////////////////////////////////////////////////// #ifdef SWIG class Region #else @@ -53,11 +57,16 @@ namespace PolyVox { public: + /// A Region with the lower corner set as low as possible and the upper corner set as high as possible. static const Region MaxRegion; + /// A Region with the lower corner set as high as possible and the upper corner set as low as possible. static const Region InvertedRegion; + /// Constructor Region(); + /// Constructor Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner); + /// Constructor Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ); /// Equality Operator. @@ -65,65 +74,117 @@ namespace PolyVox /// Inequality Operator. bool operator!=(const Region& rhs) const; + /// Gets the 'x' position of the lower corner. int32_t getLowerX(void) const; + /// Gets the 'y' position of the lower corner. int32_t getLowerY(void) const; + /// Gets the 'z' position of the lower corner. int32_t getLowerZ(void) const; + /// Gets the 'x' position of the upper corner. int32_t getUpperX(void) const; + /// Gets the 'y' position of the upper corner. int32_t getUpperY(void) const; + /// Gets the 'z' position of the upper corner. int32_t getUpperZ(void) const; + /// Gets the position of the lower corner. Vector3DInt32 getLowerCorner(void) const; + /// Gets the position of the upper corner. Vector3DInt32 getUpperCorner(void) const; - /// Gets the width of the region measured in voxels + /// Gets the width of the region measured in voxels. int32_t getWidthInVoxels(void) const; - /// Gets the height of the region measured in voxels + /// Gets the height of the region measured in voxels. int32_t getHeightInVoxels(void) const; - /// Gets the depth of the region measured in voxels + /// Gets the depth of the region measured in voxels. int32_t getDepthInVoxels(void) const; - /// Gets the dimensions of the region measured in voxels + /// Gets the dimensions of the region measured in voxels. Vector3DInt32 getDimensionsInVoxels(void) const; - /// Gets the width of the region measured in cells + /// Gets the width of the region measured in cells. int32_t getWidthInCells(void) const; - /// Gets the height of the region measured in cells + /// Gets the height of the region measured in cells. int32_t getHeightInCells(void) const; - /// Gets the depth of the region measured in cells + /// Gets the depth of the region measured in cells. int32_t getDepthInCells(void) const; - /// Gets the dimensions of the region measured in cells + /// Gets the dimensions of the region measured in cells. Vector3DInt32 getDimensionsInCells(void) const; - bool isValid(void); - + /// Sets the 'x' position of the lower corner. void setLowerX(int32_t iX); + /// Sets the 'y' position of the lower corner. void setLowerY(int32_t iY); + /// Sets the 'z' position of the lower corner. void setLowerZ(int32_t iZ); + /// Sets the 'x' position of the upper corner. void setUpperX(int32_t iX); + /// Sets the 'y' position of the upper corner. void setUpperY(int32_t iY); + /// Sets the 'z' position of the upper corner. void setUpperZ(int32_t iZ); + /// Sets the position of the lower corner. void setLowerCorner(const Vector3DInt32& v3dLowerCorner); + /// Sets the position of the upper corner. void setUpperCorner(const Vector3DInt32& v3dUpperCorner); + /// Tests whether the given point is contained in this Region. bool containsPoint(const Vector3DFloat& pos, float boundary = 0.0f) const; + /// Tests whether the given point is contained in this Region. bool containsPoint(const Vector3DInt32& pos, uint8_t boundary = 0) const; - //FIXME - Don't like these. Make containsPoint take flags indicating which axes to check? + /// Tests whether the given position is contained in the 'x' range of this Region. bool containsPointInX(float pos, float boundary = 0.0f) const; + /// Tests whether the given position is contained in the 'x' range of this Region. bool containsPointInX(int32_t pos, uint8_t boundary = 0) const; + /// Tests whether the given position is contained in the 'y' range of this Region. bool containsPointInY(float pos, float boundary = 0.0f) const; + /// Tests whether the given position is contained in the 'y' range of this Region. bool containsPointInY(int32_t pos, uint8_t boundary = 0) const; + /// Tests whether the given position is contained in the 'z' range of this Region. bool containsPointInZ(float pos, float boundary = 0.0f) const; + /// Tests whether the given position is contained in the 'z' range of this Region. bool containsPointInZ(int32_t pos, uint8_t boundary = 0) const; - void cropTo(const Region& other); - - void shift(const Vector3DInt32& amount); - void shiftLowerCorner(const Vector3DInt32& amount); - void shiftUpperCorner(const Vector3DInt32& amount); - //FIXME - Add dilate and erode functions? - void dilate(int32_t amount); - void erode(int32_t amount); - + /// Enlarges the Region so that it contains the specified position. + void accumulate(int32_t iX, int32_t iY, int32_t iZ); + /// Enlarges the Region so that it contains the specified position. + void accumulate(const Vector3DInt32& v3dPos); + /// Enlarges the Region so that it contains the specified Region. + void accumulate(const Region& reg); + + /// Crops the extents of this Region accoring to another Region. + void cropTo(const Region& other); + + /// Enlarges this region by the amount specified. + void dilate(int32_t iAmount); + /// Enlarges this region by the amounts specified. + void dilate(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ); + /// Enlarges this region by the amounts specified. + void dilate(const Vector3DInt32& v3dAmount); + + /// Shrinks this region by the amount specified. + void erode(int32_t iAmount); + /// Shrinks this region by the amounts specified. + void erode(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ); + /// Shrinks this region by the amounts specified. + void erode(const Vector3DInt32& v3dAmount); + + /// Tests whether all components of the upper corner are at least + /// as great as the corresponding components of the lower corner. + bool isValid(void) const; + + /// Moves the Region by the amount specified. + void shift(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ); + /// Moves the Region by the amount specified. + void shift(const Vector3DInt32& v3dAmount); + /// Moves the lower corner of the Region by the amount specified. + void shiftLowerCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ); + /// Moves the lower corner of the Region by the amount specified. + void shiftLowerCorner(const Vector3DInt32& v3dAmount); + /// Moves the upper corner of the Region by the amount specified. + void shiftUpperCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ); + /// Moves the upper corner of the Region by the amount specified. + void shiftUpperCorner(const Vector3DInt32& v3dAmount); private: int32_t m_iLowerX; @@ -133,6 +194,214 @@ namespace PolyVox int32_t m_iUpperY; int32_t m_iUpperZ; }; + + // Functions to be inlined to to be in the header rather than the .cpp. + // 'inline' keyword is used for the definition rather than the declaration. + // See also http://www.parashift.com/c++-faq-lite/inline-functions.html + + //////////////////////////////////////////////////////////////////////////////// + /// \return The 'x' position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getLowerX(void) const + { + return m_iLowerX; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The 'y' position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getLowerY(void) const + { + return m_iLowerY; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The 'z' position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getLowerZ(void) const + { + return m_iLowerZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The 'x' position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getUpperX(void) const + { + return m_iUpperX; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The 'y' position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getUpperY(void) const + { + return m_iUpperY; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The 'z' position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getUpperZ(void) const + { + return m_iUpperZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline Vector3DInt32 Region::getLowerCorner(void) const + { + return Vector3DInt32(m_iLowerX, m_iLowerY, m_iLowerZ); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline Vector3DInt32 Region::getUpperCorner(void) const + { + return Vector3DInt32(m_iUpperX, m_iUpperY, m_iUpperZ); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The width of the region measured in voxels. + /// \sa getWidthInCells() + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getWidthInVoxels(void) const + { + return getWidthInCells() + 1; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The height of the region measured in voxels. + /// \sa getHeightInCells() + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getHeightInVoxels(void) const + { + return getHeightInCells() + 1; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The depth of the region measured in voxels. + /// \sa getDepthInCells() + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getDepthInVoxels(void) const + { + return getDepthInCells() + 1; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The dimensions of the region measured in voxels. + /// \sa getDimensionsInCells() + //////////////////////////////////////////////////////////////////////////////// + inline Vector3DInt32 Region::getDimensionsInVoxels(void) const + { + return getDimensionsInCells() + Vector3DInt32(1, 1, 1); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The width of the region measured in cells. + /// \sa getWidthInVoxels() + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getWidthInCells(void) const + { + return m_iUpperX - m_iLowerX; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The height of the region measured in cells. + /// \sa getHeightInVoxels() + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getHeightInCells(void) const + { + return m_iUpperY - m_iLowerY; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The depth of the region measured in cells. + /// \sa getDepthInVoxels() + //////////////////////////////////////////////////////////////////////////////// + inline int32_t Region::getDepthInCells(void) const + { + return m_iUpperZ - m_iLowerZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \return The dimensions of the region measured in cells. + /// \sa getDimensionsInVoxels() + //////////////////////////////////////////////////////////////////////////////// + inline Vector3DInt32 Region::getDimensionsInCells(void) const + { + return Vector3DInt32(getWidthInCells(), getHeightInCells(), getDepthInCells()); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iX The new 'x' position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setLowerX(int32_t iX) + { + m_iLowerX = iX; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iY The new 'y' position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setLowerY(int32_t iY) + { + m_iLowerY = iY; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iZ The new 'z' position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setLowerZ(int32_t iZ) + { + m_iLowerZ = iZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iX The new 'x' position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setUpperX(int32_t iX) + { + m_iUpperX = iX; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iY The new 'y' position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setUpperY(int32_t iY) + { + m_iUpperY = iY; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iZ The new 'z' position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setUpperZ(int32_t iZ) + { + m_iUpperZ = iZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dLowerCorner The new position of the lower corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner) + { + m_iLowerX = v3dLowerCorner.getX(); + m_iLowerY = v3dLowerCorner.getY(); + m_iLowerZ = v3dLowerCorner.getZ(); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dUpperCorner The new position of the upper corner. + //////////////////////////////////////////////////////////////////////////////// + inline void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner) + { + m_iUpperX = v3dUpperCorner.getX(); + m_iUpperY = v3dUpperCorner.getY(); + m_iUpperZ = v3dUpperCorner.getZ(); + } } #endif diff --git a/library/PolyVoxCore/source/Region.cpp b/library/PolyVoxCore/source/Region.cpp index e3c9a4ba..ea79ced2 100644 --- a/library/PolyVoxCore/source/Region.cpp +++ b/library/PolyVoxCore/source/Region.cpp @@ -23,22 +23,75 @@ freely, subject to the following restrictions: #include "PolyVoxCore/Region.h" +#include #include namespace PolyVox { + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// const Region Region::MaxRegion ( Vector3DInt32((std::numeric_limits::min)(), (std::numeric_limits::min)(), (std::numeric_limits::min)()), Vector3DInt32((std::numeric_limits::max)(), (std::numeric_limits::max)(), (std::numeric_limits::max)()) ); + //////////////////////////////////////////////////////////////////////////////// + /// This Region is not considered valid as defined by isValid(). It's main application + /// is to initialise a Region to this value and then() accumulate positions. The result + /// of this will be a Region which encompasses all positions specified. + //////////////////////////////////////////////////////////////////////////////// const Region Region::InvertedRegion ( Vector3DInt32((std::numeric_limits::max)(), (std::numeric_limits::max)(), (std::numeric_limits::max)()), Vector3DInt32((std::numeric_limits::min)(), (std::numeric_limits::min)(), (std::numeric_limits::min)()) ); + //////////////////////////////////////////////////////////////////////////////// + /// \param iX The 'x' component of the position to accumulate. + /// \param iY The 'y' component of the position to accumulate. + /// \param iZ The 'z' component of the position to accumulate. + //////////////////////////////////////////////////////////////////////////////// + void Region::accumulate(int32_t iX, int32_t iY, int32_t iZ) + { + m_iLowerX = ((std::min)(m_iLowerX, iX)); + m_iLowerY = ((std::min)(m_iLowerY, iY)); + m_iLowerZ = ((std::min)(m_iLowerZ, iZ)); + m_iUpperX = ((std::max)(m_iUpperX, iX)); + m_iUpperY = ((std::max)(m_iUpperY, iY)); + m_iUpperZ = ((std::max)(m_iUpperZ, iZ)); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dPos The position to accumulate. + //////////////////////////////////////////////////////////////////////////////// + void Region::accumulate(const Vector3DInt32& v3dPos) + { + accumulate(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); + } + + //////////////////////////////////////////////////////////////////////////////// + /// Note that this is not the same as computing the union of two Regions (as the result of + /// such a union may not be a shape which can be exactly represented by a Region). Instead, + /// the result is simply big enough to contain both this Region and the one passed as a parameter. + /// \param reg The Region to accumulate. This must be valid as defined by the isValid() function. + /// \sa isValid() + //////////////////////////////////////////////////////////////////////////////// + void Region::accumulate(const Region& reg) + { + assert(reg.isValid(), "The result of accumulating an invalid region is not defined."); + + m_iLowerX = ((std::min)(m_iLowerX, reg.getLowerX())); + m_iLowerY = ((std::min)(m_iLowerY, reg.getLowerY())); + m_iLowerZ = ((std::min)(m_iLowerZ, reg.getLowerZ())); + m_iUpperX = ((std::max)(m_iUpperX, reg.getUpperX())); + m_iUpperY = ((std::max)(m_iUpperY, reg.getUpperY())); + m_iUpperZ = ((std::max)(m_iUpperZ, reg.getUpperZ())); + } + + //////////////////////////////////////////////////////////////////////////////// + /// Constructs a Region and clears all extents to zero. + //////////////////////////////////////////////////////////////////////////////// Region::Region() :m_iLowerX(0) ,m_iLowerY(0) @@ -49,6 +102,11 @@ namespace PolyVox { } + //////////////////////////////////////////////////////////////////////////////// + /// Constructs a Region and sets the lower and upper corners to the specified values. + /// \param v3dLowerCorner The desired lower corner of the Region. + /// \param v3dUpperCorner The desired upper corner of the Region. + //////////////////////////////////////////////////////////////////////////////// Region::Region(const Vector3DInt32& v3dLowerCorner, const Vector3DInt32& v3dUpperCorner) :m_iLowerX(v3dLowerCorner.getX()) ,m_iLowerY(v3dLowerCorner.getY()) @@ -59,6 +117,15 @@ namespace PolyVox { } + //////////////////////////////////////////////////////////////////////////////// + /// Constructs a Region and sets the extents to the specified values. + /// \param iLowerX The desired lower 'x' extent of the Region. + /// \param iLowerY The desired lower 'y' extent of the Region. + /// \param iLowerZ The desired lower 'z' extent of the Region. + /// \param iUpperX The desired upper 'x' extent of the Region. + /// \param iUpperY The desired upper 'y' extent of the Region. + /// \param iUpperZ The desired upper 'z' extent of the Region. + //////////////////////////////////////////////////////////////////////////////// Region::Region(int32_t iLowerX, int32_t iLowerY, int32_t iLowerZ, int32_t iUpperX, int32_t iUpperY, int32_t iUpperZ) :m_iLowerX(iLowerX) ,m_iLowerY(iLowerY) @@ -69,158 +136,36 @@ namespace PolyVox { } - /** - Checks whether two Regions are equal. - \param rhs The Region to compare to. - \return true if the Regions match. - \see operator!= - */ + //////////////////////////////////////////////////////////////////////////////// + /// Two regions are considered equal if all their extents match. + /// \param rhs The Region to compare to. + /// \return true if the Regions match. + /// \sa operator!= + //////////////////////////////////////////////////////////////////////////////// bool Region::operator==(const Region& rhs) const { return ((m_iLowerX == rhs.m_iLowerX) && (m_iLowerY == rhs.m_iLowerY) && (m_iLowerZ == rhs.m_iLowerZ) && (m_iUpperX == rhs.m_iUpperX) && (m_iUpperY == rhs.m_iUpperY) && (m_iUpperZ == rhs.m_iUpperZ)); } - /** - Checks whether two Regions are not equal. - \param rhs The Region to compare to. - \return true if the Regions do not match. - \see operator== - */ + //////////////////////////////////////////////////////////////////////////////// + /// Two regions are considered different if any of their extents differ. + /// \param rhs The Region to compare to. + /// \return true if the Regions are different. + /// \sa operator== + //////////////////////////////////////////////////////////////////////////////// bool Region::operator!=(const Region& rhs) const { return !(*this == rhs); } - int32_t Region::getLowerX(void) const - { - return m_iLowerX; - } - - int32_t Region::getLowerY(void) const - { - return m_iLowerY; - } - - int32_t Region::getLowerZ(void) const - { - return m_iLowerZ; - } - - int32_t Region::getUpperX(void) const - { - return m_iUpperX; - } - - int32_t Region::getUpperY(void) const - { - return m_iUpperY; - } - - int32_t Region::getUpperZ(void) const - { - return m_iUpperZ; - } - - Vector3DInt32 Region::getLowerCorner(void) const - { - return Vector3DInt32(m_iLowerX, m_iLowerY, m_iLowerZ); - } - - Vector3DInt32 Region::getUpperCorner(void) const - { - return Vector3DInt32(m_iUpperX, m_iUpperY, m_iUpperZ); - } - - int32_t Region::getWidthInVoxels(void) const - { - return getWidthInCells() + 1; - } - - int32_t Region::getHeightInVoxels(void) const - { - return getHeightInCells() + 1; - } - - int32_t Region::getDepthInVoxels(void) const - { - return getDepthInCells() + 1; - } - - Vector3DInt32 Region::getDimensionsInVoxels(void) const - { - return getDimensionsInCells() + Vector3DInt32(1, 1, 1); - } - - int32_t Region::getWidthInCells(void) const - { - return m_iUpperX - m_iLowerX; - } - - int32_t Region::getHeightInCells(void) const - { - return m_iUpperY - m_iLowerY; - } - - Vector3DInt32 Region::getDimensionsInCells(void) const - { - return Vector3DInt32(getWidthInCells(), getHeightInCells(), getDepthInCells()); - } - - int32_t Region::getDepthInCells(void) const - { - return m_iUpperZ - m_iLowerZ; - } - - bool Region::isValid(void) - { - return (m_iUpperX >= m_iLowerX) && (m_iUpperY >= m_iLowerY) && (m_iUpperZ >= m_iLowerZ); - } - - void Region::setLowerX(int32_t iX) - { - m_iLowerX = iX; - } - - void Region::setLowerY(int32_t iY) - { - m_iLowerY = iY; - } - - void Region::setLowerZ(int32_t iZ) - { - m_iLowerZ = iZ; - } - - void Region::setUpperX(int32_t iX) - { - m_iUpperX = iX; - } - - void Region::setUpperY(int32_t iY) - { - m_iUpperY = iY; - } - - void Region::setUpperZ(int32_t iZ) - { - m_iUpperZ = iZ; - } - - void Region::setLowerCorner(const Vector3DInt32& v3dLowerCorner) - { - m_iLowerX = v3dLowerCorner.getX(); - m_iLowerY = v3dLowerCorner.getY(); - m_iLowerZ = v3dLowerCorner.getZ(); - } - - void Region::setUpperCorner(const Vector3DInt32& v3dUpperCorner) - { - m_iUpperX = v3dUpperCorner.getX(); - m_iUpperY = v3dUpperCorner.getY(); - m_iUpperZ = v3dUpperCorner.getZ(); - } - + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in all directions. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPoint(const Vector3DFloat& pos, float boundary) const { return (pos.getX() <= m_iUpperX - boundary) @@ -231,6 +176,13 @@ namespace PolyVox && (pos.getZ() >= m_iLowerZ + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in all directions. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPoint(const Vector3DInt32& pos, uint8_t boundary) const { return (pos.getX() <= m_iUpperX - boundary) @@ -241,42 +193,89 @@ namespace PolyVox && (pos.getZ() >= m_iLowerZ + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in the 'x' direction. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPointInX(float pos, float boundary) const { return (pos <= m_iUpperX - boundary) && (pos >= m_iLowerX + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in the 'x' direction. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPointInX(int32_t pos, uint8_t boundary) const { return (pos <= m_iUpperX - boundary) && (pos >= m_iLowerX + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in the 'y' direction. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPointInY(float pos, float boundary) const { return (pos <= m_iUpperY - boundary) && (pos >= m_iLowerY + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in the 'y' direction. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPointInY(int32_t pos, uint8_t boundary) const { return (pos <= m_iUpperY - boundary) && (pos >= m_iLowerY + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in the 'z' direction. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPointInZ(float pos, float boundary) const { return (pos <= m_iUpperZ - boundary) && (pos >= m_iLowerZ + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// The boundary value can be used to ensure a position is only considered to be inside + /// the Region if it is that far in in the 'z' direction. Also, the test is inclusive such + /// that positions lying exactly on the edge of the Region are considered to be inside it. + /// \param pos The position to test. + /// \param boundary The desired boundary value. + //////////////////////////////////////////////////////////////////////////////// bool Region::containsPointInZ(int32_t pos, uint8_t boundary) const { return (pos <= m_iUpperZ - boundary) && (pos >= m_iLowerZ + boundary); } + //////////////////////////////////////////////////////////////////////////////// + /// After calling this functions, the extents of this Region are given by the intersection + /// of this Region and the one it was cropped to. + /// \param other The Region to crop to. + //////////////////////////////////////////////////////////////////////////////// void Region::cropTo(const Region& other) { m_iLowerX = ((std::max)(m_iLowerX, other.m_iLowerX)); @@ -287,45 +286,158 @@ namespace PolyVox m_iUpperZ = ((std::min)(m_iUpperZ, other.m_iUpperZ)); } - void Region::shift(const Vector3DInt32& amount) + //////////////////////////////////////////////////////////////////////////////// + /// The same amount of dilation is applied in all directions. Negative dilations + /// are possible but you should prefer the erode() function for clarity. + /// \param iAmount The amount to dilate by. + //////////////////////////////////////////////////////////////////////////////// + void Region::dilate(int32_t iAmount) { - shiftLowerCorner(amount); - shiftUpperCorner(amount); + m_iLowerX -= iAmount; + m_iLowerY -= iAmount; + m_iLowerZ -= iAmount; + + m_iUpperX += iAmount; + m_iUpperY += iAmount; + m_iUpperZ += iAmount; } - void Region::shiftLowerCorner(const Vector3DInt32& amount) + //////////////////////////////////////////////////////////////////////////////// + /// The dilation can be specified seperatly for each direction. Negative dilations + /// are possible but you should prefer the erode() function for clarity. + /// \param iAmountX The amount to dilate by in 'x'. + /// \param iAmountY The amount to dilate by in 'y'. + /// \param iAmountZ The amount to dilate by in 'z'. + //////////////////////////////////////////////////////////////////////////////// + void Region::dilate(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ) { - m_iLowerX += amount.getX(); - m_iLowerY += amount.getY(); - m_iLowerZ += amount.getZ(); + m_iLowerX -= iAmountX; + m_iLowerY -= iAmountY; + m_iLowerZ -= iAmountZ; + + m_iUpperX += iAmountX; + m_iUpperY += iAmountY; + m_iUpperZ += iAmountZ; } - void Region::shiftUpperCorner(const Vector3DInt32& amount) + //////////////////////////////////////////////////////////////////////////////// + /// The dilation can be specified seperatly for each direction. Negative dilations + /// are possible but you should prefer the erode() function for clarity. + /// \param v3dAmount The amount to dilate by (one components for each direction). + //////////////////////////////////////////////////////////////////////////////// + void Region::dilate(const Vector3DInt32& v3dAmount) { - m_iUpperX += amount.getX(); - m_iUpperY += amount.getY(); - m_iUpperZ += amount.getZ(); + dilate(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ()); } - void Region::dilate(int32_t amount) + //////////////////////////////////////////////////////////////////////////////// + /// The same amount of erosion is applied in all directions. Negative erosions + /// are possible but you should prefer the dilate() function for clarity. + /// \param iAmount The amount to erode by. + //////////////////////////////////////////////////////////////////////////////// + void Region::erode(int32_t iAmount) { - m_iLowerX -= amount; - m_iLowerY -= amount; - m_iLowerZ -= amount; + m_iLowerX += iAmount; + m_iLowerY += iAmount; + m_iLowerZ += iAmount; - m_iUpperX += amount; - m_iUpperY += amount; - m_iUpperZ += amount; + m_iUpperX -= iAmount; + m_iUpperY -= iAmount; + m_iUpperZ -= iAmount; } - void Region::erode(int32_t amount) + //////////////////////////////////////////////////////////////////////////////// + /// The erosion can be specified seperatly for each direction. Negative erosions + /// are possible but you should prefer the dilate() function for clarity. + /// \param iAmountX The amount to erode by in 'x'. + /// \param iAmountY The amount to erode by in 'y'. + /// \param iAmountZ The amount to erode by in 'z'. + //////////////////////////////////////////////////////////////////////////////// + void Region::erode(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ) { - m_iLowerX += amount; - m_iLowerY += amount; - m_iLowerZ += amount; + m_iLowerX += iAmountX; + m_iLowerY += iAmountY; + m_iLowerZ += iAmountZ; - m_iUpperX -= amount; - m_iUpperY -= amount; - m_iUpperZ -= amount; + m_iUpperX -= iAmountX; + m_iUpperY -= iAmountY; + m_iUpperZ -= iAmountZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// The erosion can be specified seperatly for each direction. Negative erosions + /// are possible but you should prefer the dilate() function for clarity. + /// \param v3dAmount The amount to erode by (one components for each direction). + //////////////////////////////////////////////////////////////////////////////// + void Region::erode(const Vector3DInt32& v3dAmount) + { + erode(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ()); + } + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + bool Region::isValid(void) const + { + return (m_iUpperX >= m_iLowerX) && (m_iUpperY >= m_iLowerY) && (m_iUpperZ >= m_iLowerZ); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iAmountX The amount to move the Region by in 'x'. + /// \param iAmountY The amount to move the Region by in 'y'. + /// \param iAmountZ The amount to move the Region by in 'z'. + //////////////////////////////////////////////////////////////////////////////// + void Region::shift(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ) + { + shiftLowerCorner(iAmountX, iAmountY, iAmountZ); + shiftUpperCorner(iAmountX, iAmountY, iAmountZ); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dAmount The amount to move the Region by. + //////////////////////////////////////////////////////////////////////////////// + void Region::shift(const Vector3DInt32& v3dAmount) + { + shiftLowerCorner(v3dAmount); + shiftUpperCorner(v3dAmount); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iAmountX The amount to move the lower corner by in 'x'. + /// \param iAmountY The amount to move the lower corner by in 'y'. + /// \param iAmountZ The amount to move the lower corner by in 'z'. + //////////////////////////////////////////////////////////////////////////////// + void Region::shiftLowerCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ) + { + m_iLowerX += iAmountX; + m_iLowerY += iAmountY; + m_iLowerZ += iAmountZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dAmount The amount to move the lower corner by. + //////////////////////////////////////////////////////////////////////////////// + void Region::shiftLowerCorner(const Vector3DInt32& v3dAmount) + { + shiftLowerCorner(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ()); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param iAmountX The amount to move the upper corner by in 'x'. + /// \param iAmountY The amount to move the upper corner by in 'y'. + /// \param iAmountZ The amount to move the upper corner by in 'z'. + //////////////////////////////////////////////////////////////////////////////// + void Region::shiftUpperCorner(int32_t iAmountX, int32_t iAmountY, int32_t iAmountZ) + { + m_iUpperX += iAmountX; + m_iUpperY += iAmountY; + m_iUpperZ += iAmountZ; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \param v3dAmount The amount to move the upper corner by. + //////////////////////////////////////////////////////////////////////////////// + void Region::shiftUpperCorner(const Vector3DInt32& v3dAmount) + { + shiftUpperCorner(v3dAmount.getX(), v3dAmount.getY(), v3dAmount.getZ()); } }