Applying ker's patch unmodified.

This commit is contained in:
David Williams
2011-03-10 20:31:11 +00:00
parent d7cea1b72e
commit 8e6b1a3b7e
14 changed files with 300 additions and 378 deletions

View File

@ -48,17 +48,19 @@ namespace PolyVox
/// the default if you are not sure what to choose here.
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
Volume<VoxelType>::Volume(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength)
:m_uTimestamper(0)
Volume<VoxelType>::Volume(uint16_t uBlockSideLength)
:
m_uTimestamper(0)
,m_uMaxUncompressedBlockCacheSize(256)
,m_uMaxBlocksLoaded(4096)
,m_uBlockSideLength(uBlockSideLength)
,m_pUncompressedBorderData(0)
,m_ulastAccessedBlockIndex((std::numeric_limits<uint32_t>::max)()) //An invalid index
,m_v3dLastAccessedBlockPos((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)()) //An invalid index
{
setBlockCacheSize(m_uMaxUncompressedBlockCacheSize);
//Create a volume of the right size.
resize(uWidth, uHeight, uDepth, uBlockSideLength);
resize(uBlockSideLength);
}
////////////////////////////////////////////////////////////////////////////////
@ -67,95 +69,10 @@ namespace PolyVox
template <typename VoxelType>
Volume<VoxelType>::~Volume()
{
}
////////////////////////////////////////////////////////////////////////////////
/// The border value is returned whenever an atempt is made to read a voxel which
/// is outside the extents of the volume.
/// \return The value used for voxels outside of the volume
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
VoxelType Volume<VoxelType>::getBorderValue(void) const
{
/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(const_cast<Block<VoxelType>*>(&m_pBorderBlock));
return pUncompressedBorderBlock->getVoxelAt(0,0,0);*/
return *m_pUncompressedBorderData;
}
////////////////////////////////////////////////////////////////////////////////
/// The result will always have a lower corner at (0,0,0) and an upper corner at one
/// less than the side length. For example, if a volume has dimensions 256x512x1024
/// then the upper corner of the enclosing region will be at (255,511,1023).
/// \return A Region representing the extent of the volume.
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
Region Volume<VoxelType>::getEnclosingRegion(void) const
{
return Region(Vector3DInt32(0,0,0), Vector3DInt32(m_uWidth-1,m_uHeight-1,m_uDepth-1));
}
////////////////////////////////////////////////////////////////////////////////
/// \return The width of the volume in voxels
/// \sa getHeight(), getDepth()
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
int32_t Volume<VoxelType>::getWidth(void) const
{
return m_uWidth;
}
////////////////////////////////////////////////////////////////////////////////
/// \return The height of the volume in voxels
/// \sa getWidth(), getDepth()
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
int32_t Volume<VoxelType>::getHeight(void) const
{
return m_uHeight;
}
////////////////////////////////////////////////////////////////////////////////
/// \return The depth of the volume in voxels
/// \sa getWidth(), getHeight()
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
int32_t Volume<VoxelType>::getDepth(void) const
{
return m_uDepth;
}
////////////////////////////////////////////////////////////////////////////////
/// \return The length of the shortest side in voxels. For example, if a volume has
/// dimensions 256x512x1024 this function will return 256.
/// \sa getLongestSideLength(), getDiagonalLength()
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
int32_t Volume<VoxelType>::getShortestSideLength(void) const
{
return m_uShortestSideLength;
}
////////////////////////////////////////////////////////////////////////////////
/// \return The length of the longest side in voxels. For example, if a volume has
/// dimensions 256x512x1024 this function will return 1024.
/// \sa getShortestSideLength(), getDiagonalLength()
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
int32_t Volume<VoxelType>::getLongestSideLength(void) const
{
return m_uLongestSideLength;
}
////////////////////////////////////////////////////////////////////////////////
/// \return The length of the diagonal in voxels. For example, if a volume has
/// dimensions 256x512x1024 this function will return sqrt(256*256+512*512+1024*1024)
/// = 1173.139. This value is computed on volume creation so retrieving it is fast.
/// \sa getShortestSideLength(), getLongestSideLength()
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
float Volume<VoxelType>::getDiagonalLength(void) const
{
return m_fDiagonalLength;
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i = m_pBlocks.begin()) {
eraseBlock(i);
}
}
////////////////////////////////////////////////////////////////////////////////
@ -167,26 +84,17 @@ namespace PolyVox
template <typename VoxelType>
VoxelType Volume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
{
//We don't use getEnclosingRegion here because we care
//about speed
if((uXPos >=0) && (uYPos >=0) && (uZPos >=0) && (uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth()))
{
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
}
else
{
return getBorderValue();
}
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
}
////////////////////////////////////////////////////////////////////////////////
@ -214,14 +122,27 @@ namespace PolyVox
}
////////////////////////////////////////////////////////////////////////////////
/// \param tBorder The value to use for voxels outside the volume.
/// Increasing the number of blocks in memory causes fewer calls to load/unload
/// \param uMaxBlocks The number of blocks
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
void Volume<VoxelType>::setBorderValue(const VoxelType& tBorder)
void Volume<VoxelType>::setMaxBlocksLoaded(uint16_t uMaxBlocks)
{
/*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
return pUncompressedBorderBlock->fill(tBorder);*/
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder);
if(uMaxBlocks < m_pBlocks.size()) {
std::cout << uMaxBlocks << ", " << m_pBlocks.size() << ", " << m_pBlocks.size() - uMaxBlocks << std::endl;
// we need to unload some blocks
for(int j = 0; j < m_pBlocks.size() - uMaxBlocks; j++) {
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itUnloadBlock = m_pBlocks.begin();
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp) {
itUnloadBlock = i;
}
}
eraseBlock(itUnloadBlock);
}
}
m_uMaxBlocksLoaded = uMaxBlocks;
}
////////////////////////////////////////////////////////////////////////////////
@ -234,30 +155,20 @@ namespace PolyVox
template <typename VoxelType>
bool Volume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
{
//We don't use getEnclosingRegion here because we care
//about speed
if((uXPos >=0) && (uYPos >=0) && (uZPos >=0) && (uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth()))
{
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
//Return true to indicate that we modified a voxel.
return true;
}
else
{
//Return false to indicate that no voxel was modified.
return false;
}
//Return true to indicate that we modified a voxel.
return true;
}
////////////////////////////////////////////////////////////////////////////////
@ -276,7 +187,7 @@ namespace PolyVox
{
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
{
m_pBlocks[m_vecUncompressedBlockCache[ct].uBlockIndex].compress();
m_pBlocks[m_vecUncompressedBlockCache[ct].v3dBlockIndex].compress();
delete[] m_vecUncompressedBlockCache[ct].data;
}
m_vecUncompressedBlockCache.clear();
@ -284,9 +195,6 @@ namespace PolyVox
////////////////////////////////////////////////////////////////////////////////
/// Note: Calling this function will destroy all existing data in the volume.
/// \param uWidth The desired width in voxels. This must be a power of two.
/// \param uHeight The desired height in voxels. This must be a power of two.
/// \param uDepth The desired depth in voxels. This must be a power of two.
/// \param uBlockSideLength The size of the blocks which make up the volume. Small
/// blocks are more likely to be homogeneous (so more easily shared) and have better
/// cache behaviour. However, there is a memory overhead per block so if they are
@ -295,17 +203,11 @@ namespace PolyVox
/// the default if you are not sure what to choose here.
////////////////////////////////////////////////////////////////////////////////
template <typename VoxelType>
void Volume<VoxelType>::resize(int32_t uWidth, int32_t uHeight, int32_t uDepth, uint16_t uBlockSideLength)
void Volume<VoxelType>::resize(uint16_t uBlockSideLength)
{
//Debug mode validation
assert(uBlockSideLength > 0);
assert(isPowerOf2(uBlockSideLength));
assert(uBlockSideLength <= uWidth);
assert(uBlockSideLength <= uHeight);
assert(uBlockSideLength <= uDepth);
assert(0 < uWidth);
assert(0 < uHeight);
assert(0 < uDepth);
//Release mode validation
if(uBlockSideLength == 0)
@ -316,103 +218,112 @@ namespace PolyVox
{
throw std::invalid_argument("Block side length must be a power of two.");
}
if(uBlockSideLength > uWidth)
{
throw std::invalid_argument("Block side length cannot be greater than volume width.");
}
if(uBlockSideLength > uHeight)
{
throw std::invalid_argument("Block side length cannot be greater than volume height.");
}
if(uBlockSideLength > uDepth)
{
throw std::invalid_argument("Block side length cannot be greater than volume depth.");
}
if(0 >= uWidth)
{
throw std::invalid_argument("Volume width cannot be smaller than 1.");
}
if(0 >= uHeight)
{
throw std::invalid_argument("Volume height cannot be smaller than 1.");
}
if(0 >= uDepth)
{
throw std::invalid_argument("Volume depth cannot be smaller than 1.");
}
//Clear the previous data
m_pBlocks.clear();
m_pUncompressedTimestamps.clear();
//Compute the volume side lengths
m_uWidth = uWidth;
m_uHeight = uHeight;
m_uDepth = uDepth;
m_pUncompressedTimestamps.resize(m_uMaxUncompressedBlockCacheSize, 0);
//Compute the block side length
m_uBlockSideLength = uBlockSideLength;
m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
}
//Compute the side lengths in blocks
m_uWidthInBlocks = m_uWidth / m_uBlockSideLength;
m_uHeightInBlocks = m_uHeight / m_uBlockSideLength;
m_uDepthInBlocks = m_uDepth / m_uBlockSideLength;
template <typename VoxelType>
void Volume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const
{
Vector3DInt32 v3dPos = itBlock->first;
Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
Region reg(v3dLower, v3dUpper);
if(m_UnloadCallback) {
m_UnloadCallback(std::ref(*this), reg);
}
m_pBlocks.erase(itBlock);
}
//Compute number of blocks in the volume
m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
//Create the blocks
m_pBlocks.resize(m_uNoOfBlocksInVolume);
for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
{
m_pBlocks[i].initialise(m_uBlockSideLength);
template <typename VoxelType>
bool Volume<VoxelType>::load_setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const
{
const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
assert(blockX == m_v3dLoadBlockPos.getX());
assert(blockY == m_v3dLoadBlockPos.getY());
assert(blockZ == m_v3dLoadBlockPos.getZ());
if(blockX != m_v3dLoadBlockPos.getX() && blockY != m_v3dLoadBlockPos.getY() && blockZ != m_v3dLoadBlockPos.getZ()) {
throw(std::invalid_argument("you are not allowed to write to any voxels outside the designated region"));
}
m_pUncompressedTimestamps.resize(m_uNoOfBlocksInVolume);
std::fill(m_pUncompressedTimestamps.begin(), m_pUncompressedTimestamps.end(), 0);
const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
//Create the border block
m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType());
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
//Other properties we might find useful later
m_uLongestSideLength = (std::max)((std::max)(m_uWidth,m_uHeight),m_uDepth);
m_uShortestSideLength = (std::min)((std::min)(m_uWidth,m_uHeight),m_uDepth);
m_fDiagonalLength = sqrtf(static_cast<float>(m_uWidth * m_uWidth + m_uHeight * m_uHeight + m_uDepth * m_uDepth));
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
//Return true to indicate that we modified a voxel.
return true;
}
template <typename VoxelType>
Block<VoxelType>* Volume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
{
assert(uBlockX >= 0);
assert(uBlockY >= 0);
assert(uBlockZ >= 0);
assert(uBlockX < m_uWidthInBlocks);
assert(uBlockY < m_uHeightInBlocks);
assert(uBlockZ < m_uDepthInBlocks);
//Compute the block's index from it's position.
const int32_t uBlockIndex =
uBlockX +
uBlockY * m_uWidthInBlocks +
uBlockZ * m_uWidthInBlocks * m_uHeightInBlocks;
assert(uBlockIndex < m_uNoOfBlocksInVolume);
assert(uBlockIndex >= 0);
Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
// check whether the block is already loaded
if(itBlock == m_pBlocks.end()) {
// it is not loaded
// check wether another block needs to be unloaded before this one can be loaded
if(m_pBlocks.size() == m_uMaxBlocksLoaded) {
// find the least recently used block
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itUnloadBlock = m_pBlocks.begin();
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp) {
itUnloadBlock = i;
}
}
eraseBlock(itUnloadBlock);
}
Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower);
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
Region reg(v3dLower, v3dUpper);
// create the new block
m_pBlocks[v3dBlockPos] = Block<VoxelType>(m_uBlockSideLength);
itBlock = m_pBlocks.find(v3dBlockPos);
// fill it with data (well currently fill it with nothingness)
// "load" will actually call setVoxel, which will in turn call this function again but the block will be found
// so this if(itBlock == m_pBlocks.end()) never is entered
m_v3dLoadBlockPos = v3dBlockPos;
if(m_LoadCallback) {
m_LoadCallback(std::ref(*this), reg);
}
m_v3dLoadBlockPos = Vector3DInt32((std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)(), (std::numeric_limits<int32_t>::max)());
}
//Get the block
Block<VoxelType>* block = &(m_pBlocks[uBlockIndex]);
Block<VoxelType>* block = &(itBlock->second);
//Check if we have the same block as last time, if so there's no need to even update
//the time stamp. If we updated it everytime then that would be every time we touched
//a voxel, which would overflow a uint32_t and require us to use a uint64_t instead.
if(uBlockIndex == m_ulastAccessedBlockIndex)
if(v3dBlockPos == m_v3dLastAccessedBlockPos)
{
return block;
}
m_v3dLastAccessedBlockPos = v3dBlockPos;
m_pUncompressedTimestamps[uBlockIndex] = ++m_uTimestamper;
m_uTimestamper++;
block->m_uTimestamp = m_uTimestamper;
if(block->m_bIsCompressed == false)
{
m_pUncompressedTimestamps[block->m_uUncompressedIndex] = m_uTimestamper;
return block;
}
@ -427,28 +338,27 @@ namespace PolyVox
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)(); // you said not int64 ;)
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
{
if(m_pUncompressedTimestamps[m_vecUncompressedBlockCache[ct].uBlockIndex] < uLeastRecentTimestamp)
if(m_pUncompressedTimestamps[ct] < uLeastRecentTimestamp)
{
uLeastRecentTimestamp = m_pUncompressedTimestamps[m_vecUncompressedBlockCache[ct].uBlockIndex];
uLeastRecentTimestamp = m_pUncompressedTimestamps[ct];
leastRecentlyUsedBlockIndex = ct;
}
}
uUncompressedBlockIndex = leastRecentlyUsedBlockIndex;
m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex].compress();
m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex].m_tUncompressedData = 0;
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].uBlockIndex = uBlockIndex;
m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex].compress();
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex = v3dBlockPos;
}
else
{
UncompressedBlock uncompressedBlock;
//uncompressedBlock.block = block;
uncompressedBlock.uBlockIndex = uBlockIndex;
uncompressedBlock.v3dBlockIndex = v3dBlockPos;
uncompressedBlock.data = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
m_vecUncompressedBlockCache.push_back(uncompressedBlock);
uUncompressedBlockIndex = m_vecUncompressedBlockCache.size() - 1;
}
block->m_uUncompressedIndex = uUncompressedBlockIndex;
block->uncompress(m_vecUncompressedBlockCache[uUncompressedBlockIndex].data);
return block;
@ -457,7 +367,7 @@ namespace PolyVox
template <typename VoxelType>
float Volume<VoxelType>::calculateCompressionRatio(void)
{
float fRawSize = m_uWidth * m_uHeight * m_uDepth * sizeof(VoxelType);
float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType);
float fCompressedSize = calculateSizeInBytes();
return fCompressedSize/fRawSize;
}
@ -468,9 +378,9 @@ namespace PolyVox
uint32_t uSizeInBytes = sizeof(Volume);
//Memory used by the blocks
for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
{
uSizeInBytes += m_pBlocks[i].calculateSizeInBytes();
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
i->second.calculateSizeInBytes();
}
//Memory used by the block cache.
@ -487,20 +397,4 @@ namespace PolyVox
return uSizeInBytes;
}
template <typename VoxelType>
void Volume<VoxelType>::useCompatibilityMode(void)
{
setBlockCacheSize(m_uNoOfBlocksInVolume * 2); //Times two gives space to spare
for(int32_t z = 0; z < m_uDepthInBlocks; z++)
{
for(int32_t y = 0; y < m_uHeightInBlocks; y++)
{
for(int32_t x = 0; x < m_uWidthInBlocks; x++)
{
getUncompressedBlock(x,y,z);
}
}
}
}
}