Work on new getVoxel() functions.

This commit is contained in:
Daviw Williams 2013-05-29 16:07:27 +02:00
parent de8c69456f
commit 073c415a38
6 changed files with 82 additions and 26 deletions

View File

@ -46,6 +46,8 @@ namespace PolyVox
} }
typedef BoundsChecks::BoundsCheck BoundsCheck; typedef BoundsChecks::BoundsCheck BoundsCheck;
template <BoundsCheck B> struct BoundsCheckType{};
namespace WrapModes namespace WrapModes
{ {
enum WrapMode enum WrapMode

View File

@ -374,8 +374,9 @@ namespace PolyVox
} }
default: default:
{ {
//Should never happen. We don't log because this hurts performance (preventing inlining?). //Should never happen. However, this assert appears to hurt performance (logging prevents inlining?).
POLYVOX_THROW_DONT_LOG(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); POLYVOX_ASSERT(false, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
} }
} }
} }

View File

@ -241,8 +241,9 @@ namespace PolyVox
} }
default: default:
{ {
//Should never happen. We don't log because this hurts performance (preventing inlining?). //Should never happen. However, this assert appears to hurt performance (logging prevents inlining?).
POLYVOX_THROW_DONT_LOG(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); POLYVOX_ASSERT(false, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
} }
} }
} }

View File

@ -115,6 +115,10 @@ namespace PolyVox
/// Destructor /// Destructor
~RawVolume(); ~RawVolume();
/// Gets a voxel at the position given by <tt>x,y,z</tt> coordinates
template <BoundsCheck eBoundsCheck>
VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) 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) const; VoxelType getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheck eBoundsCheck = BoundsChecks::Full) const;
/// Gets a voxel at the position given by a 3D vector /// Gets a voxel at the position given by a 3D vector
@ -150,6 +154,11 @@ namespace PolyVox
private: private:
void initialise(const Region& regValidRegion); void initialise(const Region& regValidRegion);
template <BoundsCheck eBoundsCheck>
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType<eBoundsCheck>) const;
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType<BoundsChecks::Full>) const;
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType<BoundsChecks::None>) const;
//The block data //The block data
VoxelType* m_pData; VoxelType* m_pData;
}; };

View File

@ -73,6 +73,23 @@ namespace PolyVox
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons."); POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
} }
////////////////////////////////////////////////////////////////////////////////
/// \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 eBoundsCheck Controls whether bounds checking is performed on voxel access. It's safest to
/// set this to BoundsChecks::Full (the default), but if you are certain that the voxel you are accessing
/// is inside the volume's enclosing region then you can skip this check to gain some performance.
/// \return The voxel value
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
template <BoundsCheck eBoundsCheck>
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
// Simply call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType<eBoundsCheck>());
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \param uXPos The \c x position of the voxel /// \param uXPos The \c x position of the voxel
/// \param uYPos The \c y position of the voxel /// \param uYPos The \c y position of the voxel
@ -89,25 +106,16 @@ namespace PolyVox
// bounds, and throw an exception if they are violated. // bounds, and throw an exception if they are violated.
if(eBoundsCheck == BoundsChecks::Full) if(eBoundsCheck == BoundsChecks::Full)
{ {
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false) // Call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType<BoundsChecks::Full>());
}
else
{ {
POLYVOX_THROW(std::out_of_range, "Position is outside valid region"); // Call through to the real implementation
return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType<BoundsChecks::None>());
} }
} }
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();
return m_pData
[
iLocalXPos +
iLocalYPos * this->getWidth() +
iLocalZPos * this->getWidth() * this->getHeight()
];
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \param v3dPos The 3D position of the voxel /// \param v3dPos The 3D position of the voxel
/// \return The voxel value /// \return The voxel value
@ -182,14 +190,14 @@ namespace PolyVox
uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ()); uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
//Get the voxel value //Get the voxel value
return getVoxel(uXPos, uYPos, uZPos, BoundsChecks::None); // No bounds checks as we've just validated the position. return getVoxel<BoundsChecks::None>(uXPos, uYPos, uZPos); // No bounds checks as we've just validated the position.
//No need to break as we've returned //No need to break as we've returned
} }
case WrapModes::Border: case WrapModes::Border:
{ {
if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos)) if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
{ {
return getVoxel(uXPos, uYPos, uZPos, BoundsChecks::None); // No bounds checks as we've just validated the position. return getVoxel<BoundsChecks::None>(uXPos, uYPos, uZPos); // No bounds checks as we've just validated the position.
} }
else else
{ {
@ -199,8 +207,9 @@ namespace PolyVox
} }
default: default:
{ {
//Should never happen. We don't log because this hurts performance (preventing inlining?). //Should never happen. However, this assert appears to hurt performance (logging prevents inlining?).
POLYVOX_THROW_DONT_LOG(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); POLYVOX_ASSERT(false, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
} }
} }
} }
@ -346,5 +355,38 @@ namespace PolyVox
return this->getWidth() * this->getHeight() * this->getDepth() * sizeof(VoxelType); return this->getWidth() * this->getHeight() * this->getDepth() * sizeof(VoxelType);
} }
template <typename VoxelType>
template <BoundsCheck eBoundsCheck>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType<eBoundsCheck>) const
{
POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!");
}
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType<BoundsChecks::Full>) const
{
if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)) == false)
{
POLYVOX_THROW(std::out_of_range, "Position is outside valid region");
}
return getVoxelImpl(uXPos, uYPos, uZPos, BoundsCheckType<BoundsChecks::None>());
}
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, BoundsCheckType<BoundsChecks::None>) const
{
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();
return m_pData
[
iLocalXPos +
iLocalYPos * this->getWidth() +
iLocalZPos * this->getWidth() * this->getHeight()
];
}
} }

View File

@ -199,8 +199,9 @@ namespace PolyVox
} }
default: default:
{ {
//Should never happen. We don't log because this hurts performance (preventing inlining?). //Should never happen. However, this assert appears to hurt performance (logging prevents inlining?).
POLYVOX_THROW_DONT_LOG(std::invalid_argument, "Wrap mode parameter has an unrecognised value."); POLYVOX_ASSERT(false, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
} }
} }
} }