Work on error handling. I replaced some asserts with exceptions and also added basic error handling documentation.

This commit is contained in:
David Williams
2013-05-11 10:05:08 +02:00
parent 62d164ef8a
commit ee299a45f0
22 changed files with 213 additions and 90 deletions

View File

@ -298,7 +298,7 @@ namespace PolyVox
hVal = SixConnectedCost(a, b);
break;
default:
POLYVOX_ASSERT(false, "Invalid case");
POLYVOX_THROW(std::invalid_argument, "Connectivity parameter has an unrecognised value.");
}
//Sanity checks in debug mode. These can come out eventually, but I

View File

@ -34,15 +34,24 @@ namespace PolyVox
template<typename VolumeType, typename IsVoxelTransparentCallback>
void calculateAmbientOcclusion(VolumeType* volInput, Array<3, uint8_t>* arrayResult, Region region, float fRayLength, uint8_t uNoOfSamplesPerOutputElement, IsVoxelTransparentCallback isVoxelTransparentCallback)
{
//Make sure that the size of the volume is an exact multiple of the size of the array.
if(volInput->getWidth() % arrayResult->getDimension(0) != 0)
{
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array width.");
}
if(volInput->getHeight() % arrayResult->getDimension(1) != 0)
{
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array height.");
}
if(volInput->getDepth() % arrayResult->getDimension(2) != 0)
{
POLYVOX_THROW(std::invalid_argument, "Volume width must be an exact multiple of array depth.");
}
uint16_t uRandomUnitVectorIndex = 0;
uint16_t uRandomVectorIndex = 0;
uint16_t uIndexIncreament;
//Make sure that the size of the volume is an exact multiple of the size of the array.
POLYVOX_ASSERT(volInput->getWidth() % arrayResult->getDimension(0) == 0, "Volume width must be an exact multiple of array width.");
POLYVOX_ASSERT(volInput->getHeight() % arrayResult->getDimension(1) == 0, "Volume height must be an exact multiple of array height.");
POLYVOX_ASSERT(volInput->getDepth() % arrayResult->getDimension(2) == 0, "Volume depth must be an exact multiple of array depth.");
//Our initial indices. It doesn't matter exactly what we set here, but the code below makes
//sure they are different for different regions which helps reduce tiling patterns in the results.
uRandomUnitVectorIndex += region.getLowerX() + region.getLowerY() + region.getLowerZ();

View File

@ -73,7 +73,11 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex)
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -91,7 +95,11 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
const SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex) const
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -139,7 +147,10 @@ namespace PolyVox
m_uNoOfElements = 1;
for (uint32_t i = 0; i<noOfDims; i++)
{
POLYVOX_ASSERT(pDimensions[i] != 0, "Invalid dimension");
if(pDimensions[i] == 0)
{
POLYVOX_THROW(std::out_of_range, "Invalid array dimension");
}
m_uNoOfElements *= pDimensions[i];
m_pDimensions[i] = pDimensions[i];
@ -186,7 +197,11 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
uint32_t Array<noOfDims, ElementType>::getDimension(uint32_t uDimension)
{
POLYVOX_ASSERT(uDimension < noOfDims, "Dimension out of range");
if(uDimension >= noOfDims)
{
POLYVOX_THROW(std::out_of_range, "Array dimension out of range");
}
return m_pDimensions[uDimension];
}
@ -198,14 +213,14 @@ namespace PolyVox
,m_uNoOfElements(0)
{
//Not implemented
POLYVOX_ASSERT(false, "Not implemented.");
POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!");
}
template <uint32_t noOfDims, typename ElementType>
Array<noOfDims, ElementType>& Array<noOfDims, ElementType>::operator=(const Array<noOfDims, ElementType>& rhs)
{
//Not implemented
POLYVOX_ASSERT(false, "Not implemented.");
POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!");
return *this;
}
@ -251,14 +266,22 @@ namespace PolyVox
template <typename ElementType>
ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex)
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return m_pElements[uIndex];
}
template <typename ElementType>
const ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) const
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return m_pElements[uIndex];
}
@ -307,14 +330,14 @@ namespace PolyVox
,m_pDimensions(0)
{
//Not implemented
POLYVOX_ASSERT(false, "Not implemented.");
POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!");
}
template <typename ElementType>
Array<1, ElementType>& Array<1, ElementType>::operator=(const Array<1, ElementType>& rhs)
{
//Not implemented
POLYVOX_ASSERT(false, "Not implemented.");
POLYVOX_THROW(not_implemented, "This function is not implemented and should never be called!");
return *this;
}

View File

@ -45,7 +45,7 @@ namespace PolyVox
template <typename VoxelType>
BaseVolume<VoxelType>::BaseVolume(const BaseVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -59,14 +59,14 @@ namespace PolyVox
////////////////////////////////////////////////////////////////////////////////
/// This function should never be called. Copying volumes by value would be expensive, and we want to prevent users from doing
/// it by accident (such as when passing them as paramenters to functions). That said, there are times when you really do want to
/// make a copy of a volume and in this case you should look at the Volumeresampler.
/// make a copy of a volume and in this case you should look at the VolumeResampler.
///
/// \sa VolumeResampler
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
BaseVolume<VoxelType>& BaseVolume<VoxelType>::operator=(const BaseVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -162,7 +162,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType BaseVolume<VoxelType>::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.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return VoxelType();
}
@ -173,7 +173,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType BaseVolume<VoxelType>::getVoxel(const Vector3DInt32& /*v3dPos*/) const
{
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return VoxelType();
}
@ -186,7 +186,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType BaseVolume<VoxelType>::getVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const
{
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return VoxelType();
}
@ -197,7 +197,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType BaseVolume<VoxelType>::getVoxelAt(const Vector3DInt32& /*v3dPos*/) const
{
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return VoxelType();
}
@ -210,7 +210,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType BaseVolume<VoxelType>::getVoxelWithWrapping(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
{
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return VoxelType();
}
@ -221,7 +221,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType BaseVolume<VoxelType>::getVoxelWithWrapping(const Vector3DInt32& /*v3dPos*/, WrapMode /*eWrapMode*/, VoxelType /*tBorder*/) const
{
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return VoxelType();
}
@ -244,7 +244,7 @@ namespace PolyVox
template <typename VoxelType>
bool BaseVolume<VoxelType>::setVoxelAt(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/, VoxelType /*tValue*/)
{
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return false;
}
@ -256,7 +256,7 @@ namespace PolyVox
template <typename VoxelType>
bool BaseVolume<VoxelType>::setVoxelAt(const Vector3DInt32& /*v3dPos*/, VoxelType /*tValue*/)
{
POLYVOX_ASSERT(false, "You should never call the base class version of this function.");
POLYVOX_THROW(not_implemented, "You should never call the base class version of this function.");
return false;
}

View File

@ -375,7 +375,7 @@ namespace PolyVox
default:
{
//Should never happen
POLYVOX_ASSERT(false, "Invalid case.");
POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
}
}

View File

@ -37,24 +37,28 @@ namespace PolyVox
public:
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual.
POLYVOX_ASSERT(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region");
return m_pVolume.getVoxelAt(uXPos, uYPos, uZPos);
}
VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const
{
// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual.
POLYVOX_ASSERT(m_regValid.containsPoint(v3dPos), "Position is outside valid region");
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
}
void setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const
{
// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual.
POLYVOX_ASSERT(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region");
m_pVolume.setVoxelAtConst(uXPos, uYPos, uZPos, tValue);
}
void setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue) const
{
// PolyVox does not throw an exception when a voxel is out of range. Please see 'Error Handling' in the User Manual.
POLYVOX_ASSERT(m_regValid.containsPoint(v3dPos), "Position is outside valid region");
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
}

View File

@ -220,9 +220,9 @@ namespace PolyVox
}
}
// If we exit the loop here then apparently all the slots were full but none of them matched. I don't think
// this can happen so let's put an assert to make sure. If you hit this assert then please report it to us!
POLYVOX_ASSERT(false, "All slots full but no matches.");
// If we exit the loop here then apparently all the slots were full but none of them matched.
// This shouldn't ever happen, so if it does it is probably a bug in PolyVox. Please report it to us!
POLYVOX_THROW(std::runtime_error, "All slots full but no matches during cubic surface extraction. This is probably a bug in PolyVox");
return -1; //Should never happen.
}

View File

@ -60,10 +60,10 @@ namespace PolyVox
template <typename VoxelType>
VoxelType Block<VoxelType>::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
{
// This is internal code not directly called by the user. For efficiency we assert rather than throwing.
POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block");
POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block");
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block");
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels.");
return m_tUncompressedData
@ -83,10 +83,10 @@ namespace PolyVox
template <typename VoxelType>
void Block<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
{
// This is internal code not directly called by the user. For efficiency we assert rather than throwing.
POLYVOX_ASSERT(uXPos < m_uSideLength, "Supplied position is outside of the block");
POLYVOX_ASSERT(uYPos < m_uSideLength, "Supplied position is outside of the block");
POLYVOX_ASSERT(uZPos < m_uSideLength, "Supplied position is outside of the block");
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels.");
m_tUncompressedData
@ -108,9 +108,6 @@ namespace PolyVox
template <typename VoxelType>
void Block<VoxelType>::initialise(uint16_t uSideLength)
{
//Debug mode validation
POLYVOX_ASSERT(isPowerOf2(uSideLength), "Block side length must be a power of two.");
//Release mode validation
if(!isPowerOf2(uSideLength))
{
@ -141,8 +138,16 @@ namespace PolyVox
template <typename VoxelType>
void Block<VoxelType>::compress(Compressor* pCompressor)
{
POLYVOX_ASSERT(pCompressor, "Compressor is not valid");
POLYVOX_ASSERT(m_bIsCompressed == false, "Attempted to compress block which is already flagged as compressed.");
if(m_bIsCompressed)
{
POLYVOX_THROW(invalid_operation, "Attempted to compress block which is already flagged as compressed.");
}
if(!pCompressor)
{
POLYVOX_THROW(std::invalid_argument, "A valid compressor must be provided");
}
POLYVOX_ASSERT(m_tUncompressedData != 0, "No uncompressed data is present.");
//If the uncompressed data hasn't actually been
@ -212,8 +217,16 @@ namespace PolyVox
template <typename VoxelType>
void Block<VoxelType>::uncompress(Compressor* pCompressor)
{
POLYVOX_ASSERT(pCompressor, "Compressor is not valid");
POLYVOX_ASSERT(m_bIsCompressed == true, "Attempted to uncompress block which is not flagged as compressed.");
if(!m_bIsCompressed)
{
POLYVOX_THROW(invalid_operation, "Attempted to uncompress block which is not flagged as compressed.");
}
if(!pCompressor)
{
POLYVOX_THROW(std::invalid_argument, "A valid compressor must be provided");
}
POLYVOX_ASSERT(m_tUncompressedData == 0, "Uncompressed data already exists.");
m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];

View File

@ -26,9 +26,10 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/Impl/Config.h"
#include <cstdlib> //For std::exit
#include <iostream> //For std::cerr
#include <cstdlib> // For std::exit
#include <iostream> // For std::cerr
#include <stdexcept>
#include <string.h> // Exception constuctors take strings.
#if defined(_MSC_VER)
// In Visual Studio we can use this function to go into the debugger.
@ -148,4 +149,32 @@ freely, subject to the following restrictions:
getThrowHandler()((except), __FILE__, __LINE__)
#endif
namespace PolyVox
{
/// A general purpose exception to indicate that an operation cannot be peformed.
class invalid_operation : public std::logic_error
{
public:
explicit invalid_operation(const std::string& message)
: logic_error(message.c_str()) {}
explicit invalid_operation(const char *message)
: logic_error(message) {}
};
/// Thrown to indicate that a function is deliberatly not implmented. For example, perhaps you called a function
/// in a base class whereas you are supposed to use a derived class which implements the function, or perhaps the
/// function is not defined for a particular template parameter. It may be that the function is required to
/// compile sucessfully but it should not be called.
class not_implemented : public std::logic_error
{
public:
explicit not_implemented(const std::string& message)
: logic_error(message.c_str()) {}
explicit not_implemented(const char *message)
: logic_error(message) {}
};
}
#endif //__PolyVox_ErrorHandling_H__

View File

@ -28,7 +28,11 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex)
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -37,7 +41,11 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
const SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex) const
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -56,14 +64,22 @@ namespace PolyVox
template <typename ElementType>
ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex)
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return m_pElements[uIndex];
}
template <typename ElementType>
const ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex) const
{
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
if(uIndex >= m_pDimensions[0])
{
POLYVOX_THROW(std::out_of_range, "Array index out of range");
}
return m_pElements[uIndex];
}

View File

@ -31,6 +31,7 @@ namespace PolyVox
const Type& v0,const Type& v1,
const float x)
{
//This function is called frequently and is very short, so assert rather than exceptions.
POLYVOX_ASSERT((x >= 0.0f) && (x <= 1.0f), "Interpolation input out of 0.0 to 1.0 range.");
//Interpolate along X
@ -44,6 +45,7 @@ namespace PolyVox
const Type& v00,const Type& v10,const Type& v01,const Type& v11,
const float x, const float y)
{
//This function is called frequently and is very short, so assert rather than exceptions.
POLYVOX_ASSERT((x >= 0.0f) && (y >= 0.0f) &&
(x <= 1.0f) && (y <= 1.0f), "Interpolation input out of 0.0 to 1.0 range.");
@ -63,6 +65,7 @@ namespace PolyVox
const Type& v001,const Type& v101,const Type& v011,const Type& v111,
const float x, const float y, const float z)
{
//This function is called frequently and is very short, so assert rather than exceptions.
POLYVOX_ASSERT((x >= 0.0f) && (y >= 0.0f) && (z >= 0.0f) &&
(x <= 1.0f) && (y <= 1.0f) && (z <= 1.0f), "Interpolation input out of 0.0 to 1.0 range.");

View File

@ -90,7 +90,7 @@ namespace PolyVox
template <typename VoxelType>
LargeVolume<VoxelType>::LargeVolume(const LargeVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -112,7 +112,7 @@ namespace PolyVox
template <typename VoxelType>
LargeVolume<VoxelType>& LargeVolume<VoxelType>::operator=(const LargeVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -124,6 +124,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType LargeVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
// 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 blockX = uXPos >> m_uBlockSideLengthPower;
@ -228,7 +229,7 @@ namespace PolyVox
default:
{
//Should never happen
POLYVOX_ASSERT(false, "Invlaid case.");
POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
}
}
@ -282,6 +283,7 @@ namespace PolyVox
template <typename VoxelType>
bool LargeVolume<VoxelType>::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 blockX = uXPos >> m_uBlockSideLengthPower;
@ -445,13 +447,8 @@ namespace PolyVox
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
void LargeVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength)
{
//Debug mode validation
POLYVOX_ASSERT(uBlockSideLength > 0, "Block side length cannot be zero.");
POLYVOX_ASSERT(isPowerOf2(uBlockSideLength), "Block side length must be a power of two.");
POLYVOX_ASSERT(m_pCompressor, "You must provide a compressor for the LargeVolume to use.");
//Release mode validation
{
//Validate parameters
if(uBlockSideLength == 0)
{
POLYVOX_THROW(std::invalid_argument, "Block side length cannot be zero.");

View File

@ -143,7 +143,7 @@ namespace PolyVox
}*/
//Need to think what effect this has on any existing iterators.
POLYVOX_ASSERT(false, "This function cnnot be used on LargeVolume samplers.");
POLYVOX_THROW(not_implemented, "This function cannot be used on LargeVolume samplers.");
return false;
}

View File

@ -39,14 +39,15 @@ namespace PolyVox
,m_uKernelSize(uKernelSize)
{
//Kernel size must be at least three
POLYVOX_ASSERT(m_uKernelSize >= 3, "Kernel size must be at least three");
m_uKernelSize = std::max(m_uKernelSize, static_cast<uint32_t>(3)); //For release builds
if(m_uKernelSize < 3)
{
POLYVOX_THROW(std::invalid_argument, "Kernel size must be at least three");
}
//Kernel size must be odd
POLYVOX_ASSERT(m_uKernelSize % 2 == 1, "Kernel size must be odd");
if(m_uKernelSize % 2 == 0) //For release builds
if(m_uKernelSize % 2 == 0)
{
m_uKernelSize++;
POLYVOX_THROW(std::invalid_argument, "Kernel size must be odd");
}
}

View File

@ -47,7 +47,7 @@ namespace PolyVox
template <typename VoxelType>
RawVolume<VoxelType>::RawVolume(const RawVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -70,7 +70,7 @@ namespace PolyVox
template <typename VoxelType>
RawVolume<VoxelType>& RawVolume<VoxelType>::operator=(const RawVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -82,6 +82,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
// 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 Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
@ -186,7 +187,7 @@ namespace PolyVox
default:
{
//Should never happen
POLYVOX_ASSERT(false, "Invalid case.");
POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
}
}
@ -254,10 +255,18 @@ namespace PolyVox
{
this->m_regValidRegion = regValidRegion;
//Ensure dimensions of the specified Region are valid
POLYVOX_ASSERT(this->getWidth() > 0, "Volume width must be greater than zero.");
POLYVOX_ASSERT(this->getHeight() > 0, "Volume width must be greater than zero.");
POLYVOX_ASSERT(this->getDepth() > 0, "Volume width must be greater than zero.");
if(this->getWidth() <= 0)
{
POLYVOX_THROW(std::invalid_argument, "Volume width must be greater than zero.");
}
if(this->getHeight() <= 0)
{
POLYVOX_THROW(std::invalid_argument, "Volume height must be greater than zero.");
}
if(this->getDepth() <= 0)
{
POLYVOX_THROW(std::invalid_argument, "Volume depth must be greater than zero.");
}
//Create the data
m_pData = new VoxelType[this->getWidth() * this->getHeight()* this->getDepth()];

View File

@ -48,7 +48,7 @@ namespace PolyVox
template <typename VoxelType>
SimpleVolume<VoxelType>::SimpleVolume(const SimpleVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume copy constructor not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -70,7 +70,7 @@ namespace PolyVox
template <typename VoxelType>
SimpleVolume<VoxelType>& SimpleVolume<VoxelType>::operator=(const SimpleVolume<VoxelType>& /*rhs*/)
{
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
POLYVOX_THROW(not_implemented, "Volume assignment operator not implemented for performance reasons.");
}
////////////////////////////////////////////////////////////////////////////////
@ -82,6 +82,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType SimpleVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
// 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 blockX = uXPos >> m_uBlockSideLengthPower;
@ -186,7 +187,7 @@ namespace PolyVox
default:
{
//Should never happen
POLYVOX_ASSERT(false, "Invalid case.");
POLYVOX_THROW(std::invalid_argument, "Wrap mode parameter has an unrecognised value.");
return VoxelType();
}
}
@ -212,6 +213,7 @@ namespace PolyVox
template <typename VoxelType>
bool SimpleVolume<VoxelType>::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 blockX = uXPos >> m_uBlockSideLengthPower;
@ -246,12 +248,7 @@ namespace PolyVox
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
void SimpleVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength)
{
//Debug mode validation
POLYVOX_ASSERT(uBlockSideLength >= 8, "Block side length should be at least 8");
POLYVOX_ASSERT(uBlockSideLength <= 256, "Block side length should not be more than 256");
POLYVOX_ASSERT(isPowerOf2(uBlockSideLength), "Block side length must be a power of two.");
{
//Release mode validation
if(uBlockSideLength < 8)
{

View File

@ -52,10 +52,10 @@ namespace PolyVox
template <typename VoxelType>
VoxelType SimpleVolume<VoxelType>::Block::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
{
// This is internal code not directly called by the user. For efficiency we assert rather than throwing.
POLYVOX_ASSERT(uXPos < m_uSideLength, "Position is outside of the block.");
POLYVOX_ASSERT(uYPos < m_uSideLength, "Position is outside of the block.");
POLYVOX_ASSERT(uZPos < m_uSideLength, "Position is outside of the block.");
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data available");
return m_tUncompressedData
@ -75,10 +75,10 @@ namespace PolyVox
template <typename VoxelType>
void SimpleVolume<VoxelType>::Block::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
{
// This is internal code not directly called by the user. For efficiency we assert rather than throwing.
POLYVOX_ASSERT(uXPos < m_uSideLength, "Position is outside of the block.");
POLYVOX_ASSERT(uYPos < m_uSideLength, "Position is outside of the block.");
POLYVOX_ASSERT(uZPos < m_uSideLength, "Position is outside of the block.");
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data available");
m_tUncompressedData
@ -105,9 +105,6 @@ namespace PolyVox
template <typename VoxelType>
void SimpleVolume<VoxelType>::Block::initialise(uint16_t uSideLength)
{
//Debug mode validation
POLYVOX_ASSERT(isPowerOf2(uSideLength), "Block side length must be a power of two.");
//Release mode validation
if(!isPowerOf2(uSideLength))
{

View File

@ -414,7 +414,11 @@ namespace PolyVox
template <uint32_t Size, typename StorageType, typename OperationType>
inline StorageType Vector<Size, StorageType, OperationType>::getElement(uint32_t index) const
{
POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element.");
if(index >= Size)
{
POLYVOX_THROW(std::out_of_range, "Attempted to access invalid vector element.");
}
return m_tElements[index];
}
@ -465,7 +469,11 @@ namespace PolyVox
template <uint32_t Size, typename StorageType, typename OperationType>
inline void Vector<Size, StorageType, OperationType>::setElement(uint32_t index, StorageType tValue)
{
POLYVOX_ASSERT(index < Size, "Attempted to access invalid vector element.");
if(index >= Size)
{
POLYVOX_THROW(std::out_of_range, "Attempted to access invalid vector element.");
}
m_tElements[index] = tValue;
}
@ -645,10 +653,17 @@ namespace PolyVox
inline void Vector<Size, StorageType, OperationType>::normalise(void)
{
float fLength = this->length();
if(fLength <= 0.0)
{
POLYVOX_THROW(invalid_operation, "Cannot normalise a vector with a length of zero");
}
for(uint32_t ct = 0; ct < Size; ++ct)
{
// Standard float rules apply for divide-by-zero
m_tElements[ct] /= fLength;
//This shouldn't happen as we had the length check earlier. So it's probably a bug if it does happen.
POLYVOX_ASSERT(m_tElements[ct] == m_tElements[ct], "Obtained NAN during vector normalisation. Perhaps the input vector was too short?");
}
}

View File

@ -30,10 +30,6 @@ namespace PolyVox
//If this is not the case then the output is undefined.
uint8_t logBase2(uint32_t uInput)
{
//Debug mode validation
POLYVOX_ASSERT(uInput != 0, "Cannot compute the log of zero.");
POLYVOX_ASSERT(isPowerOf2(uInput), "Input must be a power of two in order to compute the log.");
//Release mode validation
if(uInput == 0)
{

View File

@ -78,7 +78,10 @@ namespace PolyVox
*/
void Region::accumulate(const Region& reg)
{
POLYVOX_ASSERT(reg.isValid(), "You cannot accumulate an invalid region."); //The result of accumulating an invalid region is not defined.
if(!reg.isValid())
{
POLYVOX_THROW(invalid_operation, "You cannot accumulate an invalid region."); //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()));