Merge branch 'develop' into feature/cubiquity-version

This commit is contained in:
David Williams
2013-02-07 23:02:23 +01:00
50 changed files with 6138 additions and 430 deletions

View File

@ -298,14 +298,14 @@ namespace PolyVox
hVal = SixConnectedCost(a, b);
break;
default:
assert(false); //Invalid case.
POLYVOX_ASSERT(false, "Invalid case");
}
//Sanity checks in debug mode. These can come out eventually, but I
//want to make sure that the heuristics I've come up with make sense.
assert((a-b).length() <= TwentySixConnectedCost(a,b));
assert(TwentySixConnectedCost(a,b) <= EighteenConnectedCost(a,b));
assert(EighteenConnectedCost(a,b) <= SixConnectedCost(a,b));
POLYVOX_ASSERT((a-b).length() <= TwentySixConnectedCost(a,b), "A* heuristic error.");
POLYVOX_ASSERT(TwentySixConnectedCost(a,b) <= EighteenConnectedCost(a,b), "A* heuristic error.");
POLYVOX_ASSERT(EighteenConnectedCost(a,b) <= SixConnectedCost(a,b), "A* heuristic error.");
//Apply the bias to the computed h value;
hVal *= m_params.hBias;
@ -336,7 +336,7 @@ namespace PolyVox
}
// Robert Jenkins' 32 bit integer hash function
// http://www.concentric.net/~ttwang/tech/inthash.htm
// http://www.burtleburtle.net/bob/hash/integer.html
template<typename VolumeType>
uint32_t AStarPathfinder<VolumeType>::hash( uint32_t a)
{

View File

@ -39,9 +39,9 @@ namespace PolyVox
uint16_t uIndexIncreament;
//Make sure that the size of the volume is an exact multiple of the size of the array.
assert(volInput->getWidth() % arrayResult->getDimension(0) == 0);
assert(volInput->getHeight() % arrayResult->getDimension(1) == 0);
assert(volInput->getDepth() % arrayResult->getDimension(2) == 0);
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.
@ -116,7 +116,7 @@ namespace PolyVox
else
{
fVisibility = static_cast<float>(uVisibleDirections) / static_cast<float>(uNoOfSamplesPerOutputElement);
assert((fVisibility >= 0.0f) && (fVisibility <= 1.0f));
POLYVOX_ASSERT((fVisibility >= 0.0f) && (fVisibility <= 1.0f), "Visibility value out of range.");
}
(*arrayResult)[z / iRatioZ][y / iRatioY][x / iRatioX] = static_cast<uint8_t>(255.0f * fVisibility);

View File

@ -73,7 +73,7 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex)
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -91,7 +91,7 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
const SubArray<noOfDims-1, ElementType> Array<noOfDims, ElementType>::operator[](uint32_t uIndex) const
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -139,7 +139,7 @@ namespace PolyVox
m_uNoOfElements = 1;
for (uint32_t i = 0; i<noOfDims; i++)
{
assert(pDimensions[i] != 0);
POLYVOX_ASSERT(pDimensions[i] != 0, "Invalid dimension");
m_uNoOfElements *= pDimensions[i];
m_pDimensions[i] = pDimensions[i];
@ -186,7 +186,7 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
uint32_t Array<noOfDims, ElementType>::getDimension(uint32_t uDimension)
{
assert(uDimension < noOfDims);
POLYVOX_ASSERT(uDimension < noOfDims, "Dimension out of range");
return m_pDimensions[uDimension];
}
@ -198,14 +198,14 @@ namespace PolyVox
,m_uNoOfElements(0)
{
//Not implemented
assert(false);
POLYVOX_ASSERT(false, "Not implemented.");
}
template <uint32_t noOfDims, typename ElementType>
Array<noOfDims, ElementType>& Array<noOfDims, ElementType>::operator=(const Array<noOfDims, ElementType>& rhs)
{
//Not implemented
assert(false);
POLYVOX_ASSERT(false, "Not implemented.");
return *this;
}
@ -251,14 +251,14 @@ namespace PolyVox
template <typename ElementType>
ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex)
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return m_pElements[uIndex];
}
template <typename ElementType>
const ElementType& Array<1, ElementType>::operator[] (uint32_t uIndex) const
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return m_pElements[uIndex];
}
@ -307,14 +307,14 @@ namespace PolyVox
,m_pDimensions(0)
{
//Not implemented
assert(false);
POLYVOX_ASSERT(false, "Not implemented.");
}
template <typename ElementType>
Array<1, ElementType>& Array<1, ElementType>::operator=(const Array<1, ElementType>& rhs)
{
//Not implemented
assert(false);
POLYVOX_ASSERT(false, "Not implemented.");
return *this;
}

View File

@ -28,7 +28,6 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/Region.h"
#include "PolyVoxCore/Vector.h"
#include <cassert>
#include <limits>
namespace PolyVox

View File

@ -38,14 +38,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(const BaseVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -66,7 +66,7 @@ namespace PolyVox
template <typename VoxelType>
BaseVolume<VoxelType>& BaseVolume<VoxelType>::operator=(const BaseVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -162,7 +162,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType BaseVolume<VoxelType>::getVoxel(int32_t /*uXPos*/, int32_t /*uYPos*/, int32_t /*uZPos*/) const
{
assert(false);
POLYVOX_ASSERT(false, "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
{
assert(false);
POLYVOX_ASSERT(false, "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
{
assert(false);
POLYVOX_ASSERT(false, "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
{
assert(false);
POLYVOX_ASSERT(false, "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
{
assert(false);
POLYVOX_ASSERT(false, "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
{
assert(false);
POLYVOX_ASSERT(false, "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*/)
{
assert(false);
POLYVOX_ASSERT(false, "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*/)
{
assert(false);
POLYVOX_ASSERT(false, "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
assert(false);
POLYVOX_ASSERT(false, "Invalid case.");
return VoxelType(0);
}
}

View File

@ -0,0 +1,49 @@
/*******************************************************************************
Copyright (c) 2005-2009 David Williams
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*******************************************************************************/
#ifndef __PolyVox_Compressor_H__
#define __PolyVox_Compressor_H__
#include "PolyVoxCore/Impl/TypeDef.h"
namespace PolyVox
{
class Compressor
{
public:
Compressor() {};
virtual ~Compressor() {};
// Computes a worst-case scenario for how big the output can be for a given input size. If
// necessary you can use this as a destination buffer size, though it may be somewhat wasteful.
virtual uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize) = 0;
// Compresses the data.
virtual uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0;
// Decompresses the data.
virtual uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength) = 0;
};
}
#endif //__PolyVox_Compressor_H__

View File

@ -37,25 +37,25 @@ namespace PolyVox
public:
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
assert(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
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
{
assert(m_regValid.containsPoint(v3dPos));
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
{
assert(m_regValid.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
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
{
assert(m_regValid.containsPoint(v3dPos));
POLYVOX_ASSERT(m_regValid.containsPoint(v3dPos), "Position is outside valid region");
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
}
private:

View File

@ -26,13 +26,12 @@ namespace PolyVox
// We try to avoid duplicate vertices by checking whether a vertex has already been added at a given position.
// However, it is possible that vertices have the same position but different materials. In this case, the
// vertices are not true duplicates and both must be added to the mesh. As far as I can tell, it is possible to have
// at most six vertices with the same position but different materials. This worst-case scenario happens when we
// have a 2x2x2 group of voxels (all with different materials) and then we delete two voxels from opposing corners.
// The vertex position at the center of this group is then going to be used by six quads all with different materials.
// One futher note - we can actually have eight quads sharing a vertex position (imagine two 1x1x10 rows of voxels
// sharing a common edge) but in this case all eight quads will not have different materials.
// at most eight vertices with the same position but different materials. For example, this worst-case scenario
// happens when we have a 2x2x2 group of voxels, all with different materials and some/all partially transparent.
// The vertex position at the center of this group is then going to be used by all eight voxels all with different
// materials.
template<typename VolumeType, typename IsQuadNeeded>
const uint32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::MaxVerticesPerPosition = 6;
const uint32_t CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::MaxVerticesPerPosition = 8;
template<typename VolumeType, typename IsQuadNeeded>
CubicSurfaceExtractor<VolumeType, IsQuadNeeded>::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh<PositionMaterial<typename VolumeType::VoxelType> >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded)
@ -228,7 +227,7 @@ 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!
assert(false);
POLYVOX_ASSERT(false, "All slots full but no matches.");
return -1; //Should never happen.
}

View File

@ -28,7 +28,6 @@ freely, subject to the following restrictions:
#include "Impl/TypeDef.h"
#include <cassert>
#include <limits>
#undef min

View File

@ -25,6 +25,8 @@ freely, subject to the following restrictions:
#define __PolyVox_Block_H__
#include "PolyVoxCore/Impl/TypeDef.h"
#include "PolyVoxCore/PolyVoxForwardDeclarations.h"
#include "PolyVoxCore/Vector.h"
#include <limits>
@ -56,15 +58,15 @@ namespace PolyVox
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
void fill(VoxelType tValue);
void initialise(uint16_t uSideLength);
uint32_t calculateSizeInBytes(void);
public:
void compress(void);
void uncompress(void);
void compress(Compressor* pCompressor);
void uncompress(Compressor* pCompressor);
std::vector< RunlengthEntry<uint16_t> > m_vecCompressedData;
void* m_pCompressedData;
uint32_t m_uCompressedDataLength;
VoxelType* m_tUncompressedData;
uint16_t m_uSideLength;
uint8_t m_uSideLengthPower;

View File

@ -24,9 +24,11 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/Impl/ErrorHandling.h"
#include "PolyVoxCore/Impl/Utility.h"
#include "PolyVoxCore/Compressor.h"
#include "PolyVoxCore/Vector.h"
#include <cassert>
#include "PolyVoxCore/Impl/ErrorHandling.h"
#include <cstring> //For memcpy
#include <limits>
#include <stdexcept> //for std::invalid_argument
@ -35,10 +37,12 @@ namespace PolyVox
{
template <typename VoxelType>
Block<VoxelType>::Block(uint16_t uSideLength)
:m_tUncompressedData(0)
:m_pCompressedData(0)
,m_uCompressedDataLength(0)
,m_tUncompressedData(0)
,m_uSideLength(0)
,m_uSideLengthPower(0)
,m_bIsCompressed(true)
,m_bIsCompressed(false)
,m_bIsUncompressedDataModified(true)
{
if(uSideLength != 0)
@ -56,11 +60,11 @@ namespace PolyVox
template <typename VoxelType>
VoxelType Block<VoxelType>::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
{
assert(uXPos < m_uSideLength);
assert(uYPos < m_uSideLength);
assert(uZPos < m_uSideLength);
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");
assert(m_tUncompressedData);
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels.");
return m_tUncompressedData
[
@ -79,11 +83,11 @@ namespace PolyVox
template <typename VoxelType>
void Block<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
{
assert(uXPos < m_uSideLength);
assert(uYPos < m_uSideLength);
assert(uZPos < m_uSideLength);
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");
assert(m_tUncompressedData);
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data - block must be decompressed before accessing voxels.");
m_tUncompressedData
[
@ -101,33 +105,11 @@ namespace PolyVox
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
}
template <typename VoxelType>
void Block<VoxelType>::fill(VoxelType tValue)
{
if(!m_bIsCompressed)
{
//The memset *may* be faster than the std::fill(), but it doesn't compile nicely
//in 64-bit mode as casting the pointer to an int causes a loss of precision.
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, tValue);
m_bIsUncompressedDataModified = true;
}
else
{
RunlengthEntry<uint16_t> rle;
rle.length = m_uSideLength*m_uSideLength*m_uSideLength;
rle.value = tValue;
m_vecCompressedData.clear();
m_vecCompressedData.push_back(rle);
}
}
template <typename VoxelType>
void Block<VoxelType>::initialise(uint16_t uSideLength)
{
//Debug mode validation
assert(isPowerOf2(uSideLength));
POLYVOX_ASSERT(isPowerOf2(uSideLength), "Block side length must be a power of two.");
//Release mode validation
if(!isPowerOf2(uSideLength))
@ -139,55 +121,86 @@ namespace PolyVox
m_uSideLength = uSideLength;
m_uSideLengthPower = logBase2(uSideLength);
Block<VoxelType>::fill(VoxelType());
//Create the block data
m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];
//Clear it (should we bother?)
const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, VoxelType());
m_bIsUncompressedDataModified = true;
}
template <typename VoxelType>
uint32_t Block<VoxelType>::calculateSizeInBytes(void)
{
//FIXME - This function is incomplete.
uint32_t uSizeInBytes = sizeof(Block<VoxelType>);
uSizeInBytes += m_vecCompressedData.capacity() * sizeof(RunlengthEntry<uint16_t>);
return uSizeInBytes;
}
template <typename VoxelType>
void Block<VoxelType>::compress(void)
void Block<VoxelType>::compress(Compressor* pCompressor)
{
assert(m_bIsCompressed == false);
assert(m_tUncompressedData != 0);
POLYVOX_ASSERT(pCompressor, "Compressor is not valid");
POLYVOX_ASSERT(m_bIsCompressed == false, "Attempted to compress block which is already flagged as compressed.");
POLYVOX_ASSERT(m_tUncompressedData != 0, "No uncompressed data is present.");
//If the uncompressed data hasn't actually been
//modified then we don't need to redo the compression.
if(m_bIsUncompressedDataModified)
{
uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
m_vecCompressedData.clear();
// Delete the old compressed data as we'll create a new one
delete[] m_pCompressedData;
m_pCompressedData = 0;
RunlengthEntry<uint16_t> entry;
entry.length = 1;
entry.value = m_tUncompressedData[0];
void* pSrcData = reinterpret_cast<void*>(m_tUncompressedData);
uint32_t uSrcLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
for(uint32_t ct = 1; ct < uNoOfVoxels; ++ct)
{
VoxelType value = m_tUncompressedData[ct];
if((value == entry.value) && (entry.length < entry.maxRunlength()))
{
entry.length++;
}
else
{
m_vecCompressedData.push_back(entry);
entry.value = value;
entry.length = 1;
}
uint8_t tempBuffer[10000];
void* pDstData = reinterpret_cast<void*>( tempBuffer );
uint32_t uDstLength = 10000;
uint32_t uCompressedLength = 0;
try
{
uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength);
// Create new compressed data and copy across
m_pCompressedData = reinterpret_cast<void*>( new uint8_t[uCompressedLength] );
memcpy(m_pCompressedData, pDstData, uCompressedLength);
m_uCompressedDataLength = uCompressedLength;
}
catch(std::exception&)
{
// It is possible for the compression to fail. A common cause for this would be if the destination
// buffer is not big enough. So now we try again using a buffer that is definitely big enough.
// Note that ideally we will choose our earlier buffer size so that this almost never happens.
uint32_t uMaxCompressedSize = pCompressor->getMaxCompressedSize(uSrcLength);
uint8_t* buffer = new uint8_t[ uMaxCompressedSize ];
m_vecCompressedData.push_back(entry);
pDstData = reinterpret_cast<void*>( buffer );
uDstLength = uMaxCompressedSize;
//Shrink the vectors to their contents (maybe slow?):
//http://stackoverflow.com/questions/1111078/reduce-the-capacity-of-an-stl-vector
//C++0x may have a shrink_to_fit() function?
std::vector< RunlengthEntry<uint16_t> >(m_vecCompressedData).swap(m_vecCompressedData);
try
{
uCompressedLength = pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength);
// Create new compressed data and copy across
m_pCompressedData = reinterpret_cast<void*>( new uint8_t[uCompressedLength] );
memcpy(m_pCompressedData, pDstData, uCompressedLength);
m_uCompressedDataLength = uCompressedLength;
}
catch(std::exception&)
{
// At this point it didn't work even with a bigger buffer.
// Not much more we can do so just rethrow the exception.
delete[] buffer;
POLYVOX_THROW(std::runtime_error, "Failed to compress block data");
}
delete[] buffer;
}
}
//Flag the uncompressed data as no longer being used.
@ -197,18 +210,26 @@ namespace PolyVox
}
template <typename VoxelType>
void Block<VoxelType>::uncompress(void)
void Block<VoxelType>::uncompress(Compressor* pCompressor)
{
assert(m_bIsCompressed == true);
assert(m_tUncompressedData == 0);
POLYVOX_ASSERT(pCompressor, "Compressor is not valid");
POLYVOX_ASSERT(m_bIsCompressed == true, "Attempted to uncompress block which is not flagged as compressed.");
POLYVOX_ASSERT(m_tUncompressedData == 0, "Uncompressed data already exists.");
m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength];
VoxelType* pUncompressedData = m_tUncompressedData;
for(uint32_t ct = 0; ct < m_vecCompressedData.size(); ++ct)
{
std::fill(pUncompressedData, pUncompressedData + m_vecCompressedData[ct].length, m_vecCompressedData[ct].value);
pUncompressedData += m_vecCompressedData[ct].length;
}
void* pSrcData = reinterpret_cast<void*>(m_pCompressedData);
void* pDstData = reinterpret_cast<void*>(m_tUncompressedData);
uint32_t uSrcLength = m_uCompressedDataLength;
uint32_t uDstLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
//MinizCompressor compressor;
//RLECompressor<VoxelType, uint16_t> compressor;
uint32_t uUncompressedLength = pCompressor->decompress(pSrcData, uSrcLength, pDstData, uDstLength);
POLYVOX_ASSERT(uUncompressedLength == m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType), "Destination length has changed.");
//m_tUncompressedData = reinterpret_cast<VoxelType*>(uncompressedResult.ptr);
m_bIsCompressed = false;
m_bIsUncompressedDataModified = false;

View File

@ -21,14 +21,14 @@ misrepresented as being the original software.
distribution.
*******************************************************************************/
#include <cassert>
#include "PolyVoxCore/Impl/ErrorHandling.h"
namespace PolyVox
{
template <uint32_t noOfDims, typename ElementType>
SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex)
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -37,7 +37,7 @@ namespace PolyVox
template <uint32_t noOfDims, typename ElementType>
const SubArray<noOfDims-1, ElementType> SubArray<noOfDims, ElementType>::operator[](uint32_t uIndex) const
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return
SubArray<noOfDims-1, ElementType>(&m_pElements[uIndex*m_pOffsets[0]],
m_pDimensions+1, m_pOffsets+1);
@ -56,14 +56,14 @@ namespace PolyVox
template <typename ElementType>
ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex)
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return m_pElements[uIndex];
}
template <typename ElementType>
const ElementType& SubArray<1, ElementType>::operator[] (uint32_t uIndex) const
{
assert(uIndex<m_pDimensions[0]);
POLYVOX_ASSERT(uIndex < m_pDimensions[0], "Index out of range");
return m_pElements[uIndex];
}

View File

@ -26,8 +26,6 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/Impl/TypeDef.h"
#include <cassert>
namespace PolyVox
{
POLYVOX_API uint8_t logBase2(uint32_t uInput);

File diff suppressed because it is too large Load Diff

View File

@ -24,8 +24,6 @@ freely, subject to the following restrictions:
#ifndef __PolyVox_Interpolation_H__
#define __PolyVox_Interpolation_H__
#include <cassert>
namespace PolyVox
{
template <typename Type>
@ -33,7 +31,7 @@ namespace PolyVox
const Type& v0,const Type& v1,
const float x)
{
assert((x >= 0.0f) && (x <= 1.0f));
POLYVOX_ASSERT((x >= 0.0f) && (x <= 1.0f), "Interpolation input out of 0.0 to 1.0 range.");
//Interpolate along X
Type v0_1 = (v1 - v0) * x + v0;
@ -46,8 +44,8 @@ namespace PolyVox
const Type& v00,const Type& v10,const Type& v01,const Type& v11,
const float x, const float y)
{
assert((x >= 0.0f) && (y >= 0.0f) &&
(x <= 1.0f) && (y <= 1.0f));
POLYVOX_ASSERT((x >= 0.0f) && (y >= 0.0f) &&
(x <= 1.0f) && (y <= 1.0f), "Interpolation input out of 0.0 to 1.0 range.");
// Linearly interpolate along x
Type v00_10 = lerp(v00, v10, x);
@ -65,8 +63,8 @@ namespace PolyVox
const Type& v001,const Type& v101,const Type& v011,const Type& v111,
const float x, const float y, const float z)
{
assert((x >= 0.0f) && (y >= 0.0f) && (z >= 0.0f) &&
(x <= 1.0f) && (y <= 1.0f) && (z <= 1.0f));
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.");
// Bilinearly interpolate along Y
Type v000_v100__v010_v110 = bilerp(v000, v100, v010, v110, x, y);

View File

@ -26,12 +26,12 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/BaseVolume.h"
#include "Impl/Block.h"
#include "PolyVoxCore/Compressor.h"
#include "PolyVoxCore/Log.h"
#include "PolyVoxCore/Region.h"
#include "PolyVoxCore/Vector.h"
#include <limits>
#include <cassert>
#include <cstdlib> //For abort()
#include <cstring> //For memcpy
#include <list>
@ -257,6 +257,7 @@ namespace PolyVox
LargeVolume
(
const Region& regValid,
Compressor* pCompressor = 0,
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler = 0,
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler = 0,
bool bPagingEnabled = false,
@ -278,8 +279,6 @@ namespace PolyVox
/// Gets a voxel at the position given by a 3D vector
VoxelType getVoxelWithWrapping(const Vector3DInt32& v3dPos, WrapMode eWrapMode = WrapModes::Border, VoxelType tBorder = VoxelType(0)) const;
//Sets whether or not blocks are compressed in memory
void setCompressionEnabled(bool bCompressionEnabled);
/// Sets the number of blocks for which uncompressed data is stored
void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks);
/// Sets the number of blocks which can be in memory before the paging system starts unloading them
@ -313,7 +312,7 @@ namespace PolyVox
struct BlockPositionCompare
{
bool operator() (const PolyVox::Vector3DInt32& a, const PolyVox::Vector3DInt32& b)
bool operator() (const PolyVox::Vector3DInt32& a, const PolyVox::Vector3DInt32& b) const
{
const uint32_t size = 3;
for(uint32_t ct = 0; ct < size; ++ct)
@ -364,7 +363,9 @@ namespace PolyVox
uint16_t m_uBlockSideLength;
uint8_t m_uBlockSideLengthPower;
bool m_bCompressionEnabled;
//The compressor used by the Blocks to compress their data if required.
Compressor* m_pCompressor;
bool m_bPagingEnabled;
};
}

View File

@ -53,6 +53,7 @@ namespace PolyVox
////////////////////////////////////////////////////////////////////////////////
/// This constructor creates a volume with a fixed size which is specified as a parameter. By default this constructor will not enable paging but you can override this if desired. If you do wish to enable paging then you are required to provide the call back function (see the other LargeVolume constructor).
/// \param regValid Specifies the minimum and maximum valid voxel positions.
/// \param pCompressor An implementation of the Compressor interface which is used to compress blocks in memory.
/// \param dataRequiredHandler The callback function which will be called when PolyVox tries to use data which is not currently in momory.
/// \param dataOverflowHandler The callback function which will be called when PolyVox has too much data and needs to remove some from memory.
/// \param bPagingEnabled Controls whether or not paging is enabled for this LargeVolume.
@ -62,12 +63,14 @@ namespace PolyVox
LargeVolume<VoxelType>::LargeVolume
(
const Region& regValid,
Compressor* pCompressor,
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
bool bPagingEnabled,
uint16_t uBlockSideLength
)
:BaseVolume<VoxelType>(regValid)
,m_pCompressor(pCompressor)
{
m_funcDataRequiredHandler = dataRequiredHandler;
m_funcDataOverflowHandler = dataOverflowHandler;
@ -80,14 +83,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>
LargeVolume<VoxelType>::LargeVolume(const LargeVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -109,7 +112,7 @@ namespace PolyVox
template <typename VoxelType>
LargeVolume<VoxelType>& LargeVolume<VoxelType>::operator=(const LargeVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -121,7 +124,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType LargeVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region");
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
@ -225,7 +228,7 @@ namespace PolyVox
default:
{
//Should never happen
assert(false);
POLYVOX_ASSERT(false, "Invlaid case.");
return VoxelType(0);
}
}
@ -241,30 +244,6 @@ namespace PolyVox
return getVoxelWithWrapping(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), eWrapMode, tBorder);
}
////////////////////////////////////////////////////////////////////////////////
/// Enabling compression allows significantly more data to be stored in memory.
/// \param bCompressionEnabled Specifies whether compression is enabled.
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
void LargeVolume<VoxelType>::setCompressionEnabled(bool bCompressionEnabled)
{
//Early out - nothing to do
if(m_bCompressionEnabled == bCompressionEnabled)
{
return;
}
m_bCompressionEnabled = bCompressionEnabled;
if(m_bCompressionEnabled)
{
//If compression has been enabled then we need to start honouring the max number of
//uncompressed blocks. Because compression has been disabled for a while we might have
//gone above that limit. Easiest solution is just to clear the cache and start again.
clearBlockCache();
}
}
////////////////////////////////////////////////////////////////////////////////
/// Increasing the size of the block cache will increase memory but may improve performance.
/// You may want to set this to a large value (e.g. 1024) when you are first loading your
@ -303,7 +282,7 @@ namespace PolyVox
template <typename VoxelType>
bool LargeVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
{
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region");
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
@ -456,7 +435,7 @@ namespace PolyVox
{
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
{
m_vecUncompressedBlockCache[ct]->block.compress();
m_vecUncompressedBlockCache[ct]->block.compress(m_pCompressor);
}
m_vecUncompressedBlockCache.clear();
}
@ -468,7 +447,9 @@ namespace PolyVox
void LargeVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength)
{
//Debug mode validation
assert(uBlockSideLength > 0);
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
if(uBlockSideLength == 0)
@ -479,6 +460,10 @@ namespace PolyVox
{
POLYVOX_THROW(std::invalid_argument, "Block side length must be a power of two.");
}
if(!m_pCompressor)
{
POLYVOX_THROW(std::invalid_argument, "You must provide a compressor for the LargeVolume to use.");
}
m_uTimestamper = 0;
m_uMaxNumberOfUncompressedBlocks = 16;
@ -486,7 +471,6 @@ namespace PolyVox
m_uMaxNumberOfBlocksInMemory = 1024;
m_v3dLastAccessedBlockPos = Vector3DInt32(0,0,0); //There are no invalid positions, but initially the m_pLastAccessedBlock pointer will be null;
m_pLastAccessedBlock = 0;
m_bCompressionEnabled = true;
this->m_regValidRegion = regValidRegion;
@ -529,14 +513,15 @@ namespace PolyVox
m_funcDataOverflowHandler(ConstVolumeProxy, reg);
}
if(m_bCompressionEnabled) {
if(m_pCompressor)
{
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
{
// find the block in the uncompressed cache
if(m_vecUncompressedBlockCache[ct] == &(itBlock->second))
{
// TODO: compression is unneccessary? or will not compressing this cause a memleak?
itBlock->second.block.compress();
itBlock->second.block.compress(m_pCompressor);
// put last object in cache here
m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back();
// decrease cache size by one since last element is now in here twice
@ -583,7 +568,7 @@ namespace PolyVox
//This check should also provide a significant speed boost as usually it is true.
if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
{
assert(m_pLastAccessedBlock->m_tUncompressedData);
POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data");
return m_pLastAccessedBlock;
}
@ -615,6 +600,12 @@ namespace PolyVox
// create the new block
LoadedBlock newBlock(m_uBlockSideLength);
// Blocks start out compressed - should we change this?
// Or maybe we should just 'seed' them with compressed data,
// rather than creating an empty block and then compressing?
newBlock.block.compress(m_pCompressor);
itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
//We have created the new block. If paging is enabled it should be used to
@ -643,12 +634,12 @@ namespace PolyVox
if(loadedBlock.block.m_bIsCompressed == false)
{
assert(m_pLastAccessedBlock->m_tUncompressedData);
POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data");
return m_pLastAccessedBlock;
}
//If we are allowed to compress then check whether we need to
if((m_bCompressionEnabled) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks))
if((m_pCompressor) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks))
{
int32_t leastRecentlyUsedBlockIndex = -1;
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)();
@ -666,7 +657,7 @@ namespace PolyVox
}
//Compress the least recently used block.
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress();
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress(m_pCompressor);
//We don't actually remove any elements from this vector, we
//simply change the pointer to point at the new uncompressed bloack.
@ -677,10 +668,10 @@ namespace PolyVox
m_vecUncompressedBlockCache.push_back(&loadedBlock);
}
loadedBlock.block.uncompress();
loadedBlock.block.uncompress(m_pCompressor);
m_pLastAccessedBlock = &(loadedBlock.block);
assert(m_pLastAccessedBlock->m_tUncompressedData);
POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData, "Block has no uncompressed data");
return m_pLastAccessedBlock;
}

View File

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

View File

@ -39,11 +39,11 @@ namespace PolyVox
,m_uKernelSize(uKernelSize)
{
//Kernel size must be at least three
assert(m_uKernelSize >= 3);
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
//Kernel size must be odd
assert(m_uKernelSize % 2 == 1);
POLYVOX_ASSERT(m_uKernelSize % 2 == 1, "Kernel size must be odd");
if(m_uKernelSize % 2 == 0) //For release builds
{
m_uKernelSize++;

View File

@ -570,62 +570,50 @@ namespace PolyVox
if (edgeTable[iCubeIndex] & 1)
{
indlist[0] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace];
//assert(indlist[0] != -1);
}
if (edgeTable[iCubeIndex] & 2)
{
indlist[1] = m_pPreviousVertexIndicesY[uXRegSpace+1][uYRegSpace];
//assert(indlist[1] != -1);
}
if (edgeTable[iCubeIndex] & 4)
{
indlist[2] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace+1];
//assert(indlist[2] != -1);
}
if (edgeTable[iCubeIndex] & 8)
{
indlist[3] = m_pPreviousVertexIndicesY[uXRegSpace][uYRegSpace];
//assert(indlist[3] != -1);
}
if (edgeTable[iCubeIndex] & 16)
{
indlist[4] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace];
//assert(indlist[4] != -1);
}
if (edgeTable[iCubeIndex] & 32)
{
indlist[5] = m_pCurrentVertexIndicesY[uXRegSpace+1][uYRegSpace];
//assert(indlist[5] != -1);
}
if (edgeTable[iCubeIndex] & 64)
{
indlist[6] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace+1];
//assert(indlist[6] != -1);
}
if (edgeTable[iCubeIndex] & 128)
{
indlist[7] = m_pCurrentVertexIndicesY[uXRegSpace][uYRegSpace];
//assert(indlist[7] != -1);
}
if (edgeTable[iCubeIndex] & 256)
{
indlist[8] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace];
//assert(indlist[8] != -1);
}
if (edgeTable[iCubeIndex] & 512)
{
indlist[9] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace];
//assert(indlist[9] != -1);
}
if (edgeTable[iCubeIndex] & 1024)
{
indlist[10] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace+1];
//assert(indlist[10] != -1);
}
if (edgeTable[iCubeIndex] & 2048)
{
indlist[11] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace+1];
//assert(indlist[11] != -1);
}
for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3)

View File

@ -28,8 +28,6 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/DefaultIsQuadNeeded.h" //we'll specialise this function for this voxel type
#include <cassert>
namespace PolyVox
{
///This class represents a voxel storing only a material.

View File

@ -0,0 +1,20 @@
#ifndef __PolyVox_MinizCompressor_H__
#define __PolyVox_MinizCompressor_H__
#include "PolyVoxCore/Compressor.h"
namespace PolyVox
{
class MinizCompressor : public Compressor
{
public:
MinizCompressor();
~MinizCompressor();
uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize);
uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength);
uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength);
};
}
#endif //__PolyVox_MinizCompressor_H__

View File

@ -60,6 +60,11 @@ namespace PolyVox
typedef Array<3,int32_t> Array3DInt32;
typedef Array<3,uint32_t> Array3DUint32;
////////////////////////////////////////////////////////////////////////////////
// Compressor
////////////////////////////////////////////////////////////////////////////////
class Compressor;
////////////////////////////////////////////////////////////////////////////////
// CubicSurfaceExtractor
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,28 @@
#ifndef __PolyVox_RLECompressor_H__
#define __PolyVox_RLECompressor_H__
#include "PolyVoxCore/Compressor.h"
namespace PolyVox
{
template<typename ValueType, typename LengthType>
class RLECompressor : public Compressor
{
struct Run
{
ValueType value;
LengthType length;
};
public:
RLECompressor();
~RLECompressor();
uint32_t getMaxCompressedSize(uint32_t uUncompressedInputSize);
uint32_t compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength);
uint32_t decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength);
};
}
#include "RLECompressor.inl"
#endif //__PolyVox_RLECompressor_H__

View File

@ -0,0 +1,126 @@
#include <algorithm>
#include <cassert>
#include <limits>
namespace PolyVox
{
template<typename ValueType, typename LengthType>
RLECompressor<ValueType, LengthType>::RLECompressor()
{
}
template<typename ValueType, typename LengthType>
RLECompressor<ValueType, LengthType>::~RLECompressor()
{
}
template<typename ValueType, typename LengthType>
uint32_t RLECompressor<ValueType, LengthType>::getMaxCompressedSize(uint32_t uUncompressedInputSize)
{
// In the worst case we will have a seperate Run (of length one) for each element of the input data.
return uUncompressedInputSize * sizeof(Run);
}
template<typename ValueType, typename LengthType>
uint32_t RLECompressor<ValueType, LengthType>::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
{
if(uSrcLength % sizeof(ValueType) != 0)
{
POLYVOX_THROW(std::length_error, "Source length must be a integer multiple of the ValueType size");
}
// Lengths provided are in bytes, so convert them to be in terms of our types.
uSrcLength /= sizeof(ValueType);
uDstLength /= sizeof(Run);
// Get data pointers in the appropriate type
ValueType* pSrcDataAsType = reinterpret_cast<ValueType*>(pSrcData);
Run* pDstDataAsRun = reinterpret_cast<Run*>(pDstData);
// Pointers to just past the end of the data
ValueType* pSrcDataEnd = pSrcDataAsType + uSrcLength;
Run* pDstDataEnd = pDstDataAsRun + uDstLength;
//Counter for the output length
uint32_t uDstLengthInBytes = 0;
// Read the first element of the source and set up the first run based on it.
pDstDataAsRun->value = *pSrcDataAsType;
pSrcDataAsType++;
pDstDataAsRun->length = 1;
uDstLengthInBytes += sizeof(Run);
//Now process all remaining elements of the source.
while(pSrcDataAsType < pSrcDataEnd)
{
// If the value is the same as the current run (and we have not
// reached the maximum run length) then extend the current run.
if((*pSrcDataAsType == pDstDataAsRun->value) && (pDstDataAsRun->length < (std::numeric_limits<LengthType>::max)()))
{
pDstDataAsRun->length++;
}
// Otherwise we need to start a new Run.
else
{
pDstDataAsRun++;
// Check if we have enough space in the destination buffer.
if(pDstDataAsRun >= pDstDataEnd)
{
POLYVOX_THROW(std::runtime_error, "Insufficient space in destination buffer.");
}
// Create the new run.
pDstDataAsRun->value = *pSrcDataAsType;
pDstDataAsRun->length = 1;
uDstLengthInBytes += sizeof(Run);
}
pSrcDataAsType++;
}
return uDstLengthInBytes;
}
template<typename ValueType, typename LengthType>
uint32_t RLECompressor<ValueType, LengthType>::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
{
if(uSrcLength % sizeof(Run) != 0)
{
POLYVOX_THROW(std::length_error, "Source length must be a integer multiple of the Run size");
}
// Lengths provided are in bytes, so convert them to be in terms of our types.
uSrcLength /= sizeof(Run);
uDstLength /= sizeof(ValueType);
// Get data pointers in the appropriate type
Run* pSrcDataAsRun = reinterpret_cast<Run*>(pSrcData);
ValueType* pDstDataAsType = reinterpret_cast<ValueType*>(pDstData);
// Pointers to just past the end of the data
Run* pSrcDataEnd = pSrcDataAsRun + uSrcLength;
ValueType* pDstDataEnd = pDstDataAsType + uDstLength;
//Counter for the output length
uint32_t uDstLengthInBytes = 0;
while(pSrcDataAsRun < pSrcDataEnd)
{
// Check if we have enough space in the destination buffer.
if(pDstDataAsType + pSrcDataAsRun->length > pDstDataEnd)
{
POLYVOX_THROW(std::runtime_error, "Insufficient space in destination buffer.");
}
// Write the run into the destination
std::fill(pDstDataAsType, pDstDataAsType + pSrcDataAsRun->length, pSrcDataAsRun->value);
pDstDataAsType += pSrcDataAsRun->length;
uDstLengthInBytes += pSrcDataAsRun->length * sizeof(ValueType);
pSrcDataAsRun++;
}
return uDstLengthInBytes;
}
}

View File

@ -29,7 +29,6 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/Region.h"
#include "PolyVoxCore/Vector.h"
#include <cassert>
#include <cstdlib> //For abort()
#include <limits>
#include <memory>

View File

@ -47,7 +47,7 @@ namespace PolyVox
template <typename VoxelType>
RawVolume<VoxelType>::RawVolume(const RawVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -70,7 +70,7 @@ namespace PolyVox
template <typename VoxelType>
RawVolume<VoxelType>& RawVolume<VoxelType>::operator=(const RawVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -82,7 +82,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region");
const Vector3DInt32& v3dLowerCorner = this->m_regValidRegion.getLowerCorner();
int32_t iLocalXPos = uXPos - v3dLowerCorner.getX();
@ -186,7 +186,7 @@ namespace PolyVox
default:
{
//Should never happen
assert(false);
POLYVOX_ASSERT(false, "Invalid case.");
return VoxelType(0);
}
}
@ -255,9 +255,9 @@ namespace PolyVox
this->m_regValidRegion = regValidRegion;
//Ensure dimensions of the specified Region are valid
assert(this->getWidth() > 0);
assert(this->getHeight() > 0);
assert(this->getDepth() > 0);
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.");
//Create the data
m_pData = new VoxelType[this->getWidth() * this->getHeight()* this->getDepth()];

View File

@ -31,7 +31,6 @@ freely, subject to the following restrictions:
#include "PolyVoxCore/Region.h"
#include "PolyVoxCore/Vector.h"
#include <cassert>
#include <cstdlib> //For abort()
#include <cstring> //For memcpy
#include <limits>

View File

@ -48,7 +48,7 @@ namespace PolyVox
template <typename VoxelType>
SimpleVolume<VoxelType>::SimpleVolume(const SimpleVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Copy constructor not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -70,7 +70,7 @@ namespace PolyVox
template <typename VoxelType>
SimpleVolume<VoxelType>& SimpleVolume<VoxelType>::operator=(const SimpleVolume<VoxelType>& /*rhs*/)
{
assert(false); // See function comment above.
POLYVOX_ASSERT(false, "Assignment operator not implemented."); // See function comment above.
}
////////////////////////////////////////////////////////////////////////////////
@ -82,7 +82,7 @@ namespace PolyVox
template <typename VoxelType>
VoxelType SimpleVolume<VoxelType>::getVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region");
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
@ -186,7 +186,7 @@ namespace PolyVox
default:
{
//Should never happen
assert(false);
POLYVOX_ASSERT(false, "Invalid case.");
return VoxelType(0);
}
}
@ -212,7 +212,7 @@ namespace PolyVox
template <typename VoxelType>
bool SimpleVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
{
assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
POLYVOX_ASSERT(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)), "Position is outside valid region");
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
@ -248,9 +248,9 @@ namespace PolyVox
void SimpleVolume<VoxelType>::initialise(const Region& regValidRegion, uint16_t uBlockSideLength)
{
//Debug mode validation
assert(uBlockSideLength >= 8);
assert(uBlockSideLength <= 256);
assert(isPowerOf2(uBlockSideLength));
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)
@ -308,9 +308,9 @@ namespace PolyVox
uBlockY -= m_regValidRegionInBlocks.getLowerCorner().getY();
uBlockZ -= m_regValidRegionInBlocks.getLowerCorner().getZ();
assert(uBlockX >= 0);
assert(uBlockY >= 0);
assert(uBlockZ >= 0);
POLYVOX_ASSERT(uBlockX >= 0, "Block coordinate must not be negative.");
POLYVOX_ASSERT(uBlockY >= 0, "Block coordinate must not be negative.");
POLYVOX_ASSERT(uBlockZ >= 0, "Block coordinate must not be negative.");
//Compute the block index
uint32_t uBlockIndex =

View File

@ -52,11 +52,11 @@ namespace PolyVox
template <typename VoxelType>
VoxelType SimpleVolume<VoxelType>::Block::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
{
assert(uXPos < m_uSideLength);
assert(uYPos < m_uSideLength);
assert(uZPos < m_uSideLength);
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.");
assert(m_tUncompressedData);
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data available");
return m_tUncompressedData
[
@ -75,11 +75,11 @@ namespace PolyVox
template <typename VoxelType>
void SimpleVolume<VoxelType>::Block::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
{
assert(uXPos < m_uSideLength);
assert(uYPos < m_uSideLength);
assert(uZPos < m_uSideLength);
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.");
assert(m_tUncompressedData);
POLYVOX_ASSERT(m_tUncompressedData, "No uncompressed data available");
m_tUncompressedData
[
@ -106,7 +106,7 @@ namespace PolyVox
void SimpleVolume<VoxelType>::Block::initialise(uint16_t uSideLength)
{
//Debug mode validation
assert(isPowerOf2(uSideLength));
POLYVOX_ASSERT(isPowerOf2(uSideLength), "Block side length must be a power of two.");
//Release mode validation
if(!isPowerOf2(uSideLength))

View File

@ -21,8 +21,6 @@ freely, subject to the following restrictions:
distribution.
*******************************************************************************/
#include <cassert>
namespace PolyVox
{
template <typename VertexType>
@ -103,9 +101,9 @@ namespace PolyVox
void SurfaceMesh<VertexType>::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2)
{
//Make sure the specified indices correspond to valid vertices.
assert(index0 < m_vecVertices.size());
assert(index1 < m_vecVertices.size());
assert(index2 < m_vecVertices.size());
POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex.");
POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex.");
POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex.");
m_vecTriangleIndices.push_back(index0);
m_vecTriangleIndices.push_back(index1);
@ -116,9 +114,9 @@ namespace PolyVox
void SurfaceMesh<VertexType>::addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2)
{
//Make sure the specified indices correspond to valid vertices.
assert(index0 < m_vecVertices.size());
assert(index1 < m_vecVertices.size());
assert(index2 < m_vecVertices.size());
POLYVOX_ASSERT(index0 < m_vecVertices.size(), "Index points at an invalid vertex.");
POLYVOX_ASSERT(index1 < m_vecVertices.size(), "Index points at an invalid vertex.");
POLYVOX_ASSERT(index2 < m_vecVertices.size(), "Index points at an invalid vertex.");
m_vecTriangleIndices.push_back(index0);
m_vecTriangleIndices.push_back(index1);
@ -408,7 +406,7 @@ namespace PolyVox
return result;
}
assert(inputMesh.m_vecLodRecords.size() == 1);
POLYVOX_ASSERT(inputMesh.m_vecLodRecords.size() == 1, "Number of LOD records must equal one.");
if(inputMesh.m_vecLodRecords.size() != 1)
{
//If we have done progressive LOD then it's too late to split into subsets.