More work combining WrapMode and BoundsCheck

This commit is contained in:
Daviw Williams 2013-06-06 16:26:55 +02:00
parent 2b03e84f83
commit 6bc379f0df
4 changed files with 77 additions and 71 deletions

View File

@ -56,12 +56,18 @@ namespace PolyVox
{ {
enum WrapMode enum WrapMode
{ {
Clamp = 0, None = 0,
Border = 1 Clamp = 1,
Border = 2,
DontCheck = 3
}; };
} }
typedef WrapModes::WrapMode WrapMode; 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 <WrapMode W> struct WrapModeType{};
template <typename _VoxelType> template <typename _VoxelType>
class BaseVolume class BaseVolume
{ {

View File

@ -192,8 +192,8 @@ namespace PolyVox
{ {
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
{ {
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y-1,z, BoundsChecks::BorderPos)); AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y-1,z, WrapModes::Border));
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, BoundsChecks::BorderPos)); AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border));
satVolume.setVoxelAt(x,y,z,previousSum + currentSum); satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
} }
@ -206,8 +206,8 @@ namespace PolyVox
{ {
for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++) for(int32_t x = satLowerCorner.getX(); x <= satUpperCorner.getX(); x++)
{ {
AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z-1, BoundsChecks::BorderPos)); AccumulationType previousSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z-1, WrapModes::Border));
AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, BoundsChecks::BorderPos)); AccumulationType currentSum = static_cast<AccumulationType>(satVolume.getVoxel(x,y,z, WrapModes::Border));
satVolume.setVoxelAt(x,y,z,previousSum + currentSum); satVolume.setVoxelAt(x,y,z,previousSum + currentSum);
} }
@ -234,14 +234,14 @@ namespace PolyVox
int32_t satUpperY = iSrcY + border; int32_t satUpperY = iSrcY + border;
int32_t satUpperZ = iSrcZ + border; int32_t satUpperZ = iSrcZ + border;
AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ, BoundsChecks::BorderPos); AccumulationType a = satVolume.getVoxel(satLowerX,satLowerY,satLowerZ, WrapModes::Border);
AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ, BoundsChecks::BorderPos); AccumulationType b = satVolume.getVoxel(satUpperX,satLowerY,satLowerZ, WrapModes::Border);
AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ, BoundsChecks::BorderPos); AccumulationType c = satVolume.getVoxel(satLowerX,satUpperY,satLowerZ, WrapModes::Border);
AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ, BoundsChecks::BorderPos); AccumulationType d = satVolume.getVoxel(satUpperX,satUpperY,satLowerZ, WrapModes::Border);
AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ, BoundsChecks::BorderPos); AccumulationType e = satVolume.getVoxel(satLowerX,satLowerY,satUpperZ, WrapModes::Border);
AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ, BoundsChecks::BorderPos); AccumulationType f = satVolume.getVoxel(satUpperX,satLowerY,satUpperZ, WrapModes::Border);
AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ, BoundsChecks::BorderPos); AccumulationType g = satVolume.getVoxel(satLowerX,satUpperY,satUpperZ, WrapModes::Border);
AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ, BoundsChecks::BorderPos); AccumulationType h = satVolume.getVoxel(satUpperX,satUpperY,satUpperZ, WrapModes::Border);
AccumulationType sum = h+c-d-g-f-a+b+e; AccumulationType sum = h+c-d-g-f-a+b+e;
uint32_t sideLength = border * 2 + 1; uint32_t sideLength = border * 2 + 1;

View File

@ -116,21 +116,21 @@ namespace PolyVox
~RawVolume(); ~RawVolume();
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates /// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
template <BoundsCheck eBoundsCheck> template <WrapMode eWrapMode>
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, VoxelType tBorder = VoxelType()) const;
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates /// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheck eBoundsCheck = BoundsChecks::Full, VoxelType tBorder = VoxelType()) const; VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode = WrapModes::None, VoxelType tBorder = VoxelType()) const;
/// Gets a voxel at the position given by a 3D vector /// Gets a voxel at the position given by a 3D vector
VoxelType getVoxel(const Vector3DInt32& v3dPos, BoundsCheck eBoundsCheck = BoundsChecks::Full, VoxelType tBorder = VoxelType()) const; VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::None, VoxelType tBorder = VoxelType()) const;
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates /// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const; VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
/// Gets a voxel at the position given by a 3D vector /// Gets a voxel at the position given by a 3D vector
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const;
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates /// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder = VoxelType()) const; //VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder = VoxelType()) const;
/// Gets a voxel at the position given by a 3D vector /// Gets a voxel at the position given by a 3D vector
VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder = VoxelType()) const; //VoxelType getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder = VoxelType()) const;
/// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates /// Sets the voxel at the position given by <tt>x,y,z</tt> coordinates
void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, BoundsCheck eBoundsCheck = BoundsChecks::Full); void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, BoundsCheck eBoundsCheck = BoundsChecks::Full);
@ -154,12 +154,12 @@ namespace PolyVox
private: private:
void initialise(const Region& regValidRegion); void initialise(const Region& regValidRegion);
template <BoundsCheck eBoundsCheck> template <WrapMode eWrapMode>
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<eBoundsCheck>) const; VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<eWrapMode>) const;
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::Full>) const; VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::None>) const;
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::None>) const; VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::Clamp>) const;
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::ClampPos>) const; VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::Border>) const;
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::BorderPos>) const; VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::DontCheck>) const;
//The block data //The block data
VoxelType* m_pData; VoxelType* m_pData;

View File

@ -83,11 +83,11 @@ namespace PolyVox
/// \return The voxel value /// \return The voxel value
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template <typename VoxelType>
template <BoundsCheck eBoundsCheck> template <WrapMode eWrapMode>
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder) const
{ {
// Simply call through to the real implementation // Simply call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<eBoundsCheck>()); return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<eWrapMode>());
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -100,29 +100,29 @@ namespace PolyVox
/// \return The voxel value /// \return The voxel value
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheck eBoundsCheck, VoxelType tBorder) const VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const
{ {
// If bounds checking is enabled then we validate the // If bounds checking is enabled then we validate the
// bounds, and throw an exception if they are violated. // bounds, and throw an exception if they are violated.
if(eBoundsCheck == BoundsChecks::Full) if(eWrapMode == WrapModes::None)
{ {
// Call through to the real implementation // Call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<BoundsChecks::Full>()); return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<WrapModes::None>());
} }
else if(eBoundsCheck == BoundsChecks::None) else if(eWrapMode == WrapModes::Clamp)
{ {
// Call through to the real implementation // Call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<BoundsChecks::None>()); return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<WrapModes::Clamp>());
} }
else if(eBoundsCheck == BoundsChecks::ClampPos) else if(eWrapMode == WrapModes::Border)
{ {
// Call through to the real implementation // Call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<BoundsChecks::ClampPos>()); return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<WrapModes::Border>());
} }
else else
{ {
// Call through to the real implementation // Call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<BoundsChecks::BorderPos>()); return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<WrapModes::DontCheck>());
} }
} }
@ -134,9 +134,9 @@ namespace PolyVox
/// is inside the volume's enclosing region then you can skip this check to gain some performance. /// is inside the volume's enclosing region then you can skip this check to gain some performance.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, BoundsCheck eBoundsCheck, VoxelType tBorder) const VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const
{ {
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eBoundsCheck, tBorder); return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -184,7 +184,7 @@ namespace PolyVox
/// \param uZPos The \c z position of the voxel /// \param uZPos The \c z position of the voxel
/// \return The voxel value /// \return The voxel value
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType> /*template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapMode eWrapMode, VoxelType tBorder) const
{ {
switch(eWrapMode) switch(eWrapMode)
@ -232,7 +232,7 @@ namespace PolyVox
VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const VoxelType RawVolume<VoxelType>::getVoxel(const Vector3DInt32& v3dPos, WrapMode eWrapMode, VoxelType tBorder) const
{ {
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder); return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
} }*/
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \param uXPos the \c x position of the voxel /// \param uXPos the \c x position of the voxel
@ -366,25 +366,52 @@ namespace PolyVox
} }
template <typename VoxelType> template <typename VoxelType>
template <BoundsCheck eBoundsCheck> template <WrapMode eWrapMode>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<eBoundsCheck>) const VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<eWrapMode>) const
{ {
POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!"); POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!");
} }
template <typename VoxelType> template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::Full>) const VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::None>) const
{ {
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) 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");
} }
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<BoundsChecks::None>()); return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<WrapModes::DontCheck>());
} }
template <typename VoxelType> template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::None>) const VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::Clamp>) const
{
//Perform clamping
uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<WrapModes::DontCheck>());
}
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::Border>) const
{
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
{
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, WrapModeType<WrapModes::DontCheck>()); // No bounds checks as we've just validated the position.
}
else
{
return tBorder; //FIXME - Should return border value.
}
}
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, WrapModeType<WrapModes::DontCheck>) const
{ {
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner(); const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX(); int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
@ -398,32 +425,5 @@ namespace PolyVox
iLocalZPos * this->getWidth() * this->getHeight() iLocalZPos * this->getWidth() * this->getHeight()
]; ];
} }
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::ClampPos>) const
{
//Perform clamping
uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<BoundsChecks::None>());
}
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tBorder, BoundsCheckType<BoundsChecks::BorderPos>) const
{
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
{
return getVoxelImpl(uXPos, uYPos, uZPos, tBorder, BoundsCheckType<BoundsChecks::None>()); // No bounds checks as we've just validated the position.
}
else
{
return tBorder; //FIXME - Should return border value.
}
}
} }