Moved Block into SimpleVolume class.
This commit is contained in:
parent
bc9f1e8ac5
commit
032accd915
@ -24,7 +24,6 @@ freely, subject to the following restrictions:
|
|||||||
#ifndef __PolyVox_SimpleVolume_H__
|
#ifndef __PolyVox_SimpleVolume_H__
|
||||||
#define __PolyVox_SimpleVolume_H__
|
#define __PolyVox_SimpleVolume_H__
|
||||||
|
|
||||||
#include "PolyVoxImpl/Block.h"
|
|
||||||
#include "Region.h"
|
#include "Region.h"
|
||||||
#include "PolyVoxForwardDeclarations.h"
|
#include "PolyVoxForwardDeclarations.h"
|
||||||
|
|
||||||
@ -40,6 +39,47 @@ namespace PolyVox
|
|||||||
class SimpleVolume
|
class SimpleVolume
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
class Block
|
||||||
|
{
|
||||||
|
template <typename LengthType>
|
||||||
|
struct RunlengthEntry
|
||||||
|
{
|
||||||
|
LengthType length;
|
||||||
|
VoxelType value;
|
||||||
|
|
||||||
|
//We can parametise the length on anything up to uint32_t.
|
||||||
|
//This lets us experiment with the optimal size in the future.
|
||||||
|
static uint32_t maxRunlength(void) {return (std::numeric_limits<LengthType>::max)();}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Make Sampler a friend
|
||||||
|
friend class LargeVolume<VoxelType>::Sampler;
|
||||||
|
public:
|
||||||
|
Block(uint16_t uSideLength = 0);
|
||||||
|
|
||||||
|
uint16_t getSideLength(void) const;
|
||||||
|
VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||||
|
VoxelType getVoxelAt(const Vector3DUint16& v3dPos) const;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
std::vector< RunlengthEntry<uint16_t> > m_vecCompressedData;
|
||||||
|
VoxelType* m_tUncompressedData;
|
||||||
|
uint16_t m_uSideLength;
|
||||||
|
uint8_t m_uSideLengthPower;
|
||||||
|
bool m_bIsCompressed;
|
||||||
|
bool m_bIsUncompressedDataModified;
|
||||||
|
};
|
||||||
|
|
||||||
class Sampler
|
class Sampler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -110,9 +150,6 @@ namespace PolyVox
|
|||||||
VoxelType* mCurrentVoxel;
|
VoxelType* mCurrentVoxel;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make the ConstVolumeProxy a friend
|
|
||||||
friend class ConstVolumeProxy<VoxelType>;
|
|
||||||
|
|
||||||
struct LoadedBlock
|
struct LoadedBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -122,7 +159,7 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Block<VoxelType> block;
|
Block block;
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -194,7 +231,7 @@ private:
|
|||||||
/// is absolutely unsafe
|
/// is absolutely unsafe
|
||||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataOverflowHandler;
|
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> m_funcDataOverflowHandler;
|
||||||
|
|
||||||
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
Block* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||||
void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const;
|
void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const;
|
||||||
/// this function can be called by m_funcDataRequiredHandler without causing any weird effects
|
/// this function can be called by m_funcDataRequiredHandler without causing any weird effects
|
||||||
bool setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const;
|
bool setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const;
|
||||||
@ -209,7 +246,7 @@ private:
|
|||||||
mutable std::vector< LoadedBlock* > m_vecUncompressedBlockCache;
|
mutable std::vector< LoadedBlock* > m_vecUncompressedBlockCache;
|
||||||
mutable uint32_t m_uTimestamper;
|
mutable uint32_t m_uTimestamper;
|
||||||
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
||||||
mutable Block<VoxelType>* m_pLastAccessedBlock;
|
mutable Block* m_pLastAccessedBlock;
|
||||||
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
||||||
|
|
||||||
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
//We don't store an actual Block for the border, just the uncompressed data. This is partly because the border
|
||||||
@ -235,6 +272,7 @@ private:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "SimpleVolumeBlock.inl"
|
||||||
#include "SimpleVolume.inl"
|
#include "SimpleVolume.inl"
|
||||||
#include "SimpleVolumeSampler.inl"
|
#include "SimpleVolumeSampler.inl"
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ namespace PolyVox
|
|||||||
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
||||||
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
||||||
|
|
||||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||||
|
|
||||||
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
|
||||||
}
|
}
|
||||||
@ -276,7 +276,7 @@ namespace PolyVox
|
|||||||
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
||||||
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
||||||
|
|
||||||
Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
|
||||||
|
|
||||||
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ namespace PolyVox
|
|||||||
|
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
Block<VoxelType>* SimpleVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
typename SimpleVolume<VoxelType>::Block* SimpleVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
|
||||||
{
|
{
|
||||||
Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
|
Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
|
||||||
|
|
||||||
|
214
library/PolyVoxCore/include/SimpleVolumeBlock.inl
Normal file
214
library/PolyVoxCore/include/SimpleVolumeBlock.inl
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "PolyVoxImpl/Utility.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring> //For memcpy
|
||||||
|
#include <limits>
|
||||||
|
#include <stdexcept> //for std::invalid_argument
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
template <typename VoxelType>
|
||||||
|
SimpleVolume<VoxelType>::Block::Block(uint16_t uSideLength)
|
||||||
|
:m_uSideLength(0)
|
||||||
|
,m_uSideLengthPower(0)
|
||||||
|
,m_tUncompressedData(0)
|
||||||
|
,m_bIsCompressed(true)
|
||||||
|
,m_bIsUncompressedDataModified(true)
|
||||||
|
{
|
||||||
|
if(uSideLength != 0)
|
||||||
|
{
|
||||||
|
initialise(uSideLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
uint16_t SimpleVolume<VoxelType>::Block::getSideLength(void) const
|
||||||
|
{
|
||||||
|
return m_uSideLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
assert(m_tUncompressedData);
|
||||||
|
|
||||||
|
return m_tUncompressedData
|
||||||
|
[
|
||||||
|
uXPos +
|
||||||
|
uYPos * m_uSideLength +
|
||||||
|
uZPos * m_uSideLength * m_uSideLength
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
VoxelType SimpleVolume<VoxelType>::Block::getVoxelAt(const Vector3DUint16& v3dPos) const
|
||||||
|
{
|
||||||
|
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
assert(m_tUncompressedData);
|
||||||
|
|
||||||
|
m_tUncompressedData
|
||||||
|
[
|
||||||
|
uXPos +
|
||||||
|
uYPos * m_uSideLength +
|
||||||
|
uZPos * m_uSideLength * m_uSideLength
|
||||||
|
] = tValue;
|
||||||
|
|
||||||
|
m_bIsUncompressedDataModified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
void SimpleVolume<VoxelType>::Block::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||||
|
{
|
||||||
|
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
void SimpleVolume<VoxelType>::Block::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 SimpleVolume<VoxelType>::Block::initialise(uint16_t uSideLength)
|
||||||
|
{
|
||||||
|
//Debug mode validation
|
||||||
|
assert(isPowerOf2(uSideLength));
|
||||||
|
|
||||||
|
//Release mode validation
|
||||||
|
if(!isPowerOf2(uSideLength))
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Block side length must be a power of two.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Compute the side length
|
||||||
|
m_uSideLength = uSideLength;
|
||||||
|
m_uSideLengthPower = logBase2(uSideLength);
|
||||||
|
|
||||||
|
SimpleVolume<VoxelType>::Block::fill(VoxelType());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
uint32_t SimpleVolume<VoxelType>::Block::calculateSizeInBytes(void)
|
||||||
|
{
|
||||||
|
uint32_t uSizeInBytes = sizeof(Block<VoxelType>);
|
||||||
|
uSizeInBytes += m_vecCompressedData.capacity() * sizeof(RunlengthEntry<uint16_t>);
|
||||||
|
return uSizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
void SimpleVolume<VoxelType>::Block::compress(void)
|
||||||
|
{
|
||||||
|
assert(m_bIsCompressed == false);
|
||||||
|
assert(m_tUncompressedData != 0);
|
||||||
|
|
||||||
|
//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();
|
||||||
|
|
||||||
|
RunlengthEntry<uint16_t> entry;
|
||||||
|
entry.length = 1;
|
||||||
|
entry.value = m_tUncompressedData[0];
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vecCompressedData.push_back(entry);
|
||||||
|
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Flag the uncompressed data as no longer being used.
|
||||||
|
delete[] m_tUncompressedData;
|
||||||
|
m_tUncompressedData = 0;
|
||||||
|
m_bIsCompressed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VoxelType>
|
||||||
|
void SimpleVolume<VoxelType>::Block::uncompress(void)
|
||||||
|
{
|
||||||
|
assert(m_bIsCompressed == true);
|
||||||
|
assert(m_tUncompressedData == 0);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bIsCompressed = false;
|
||||||
|
m_bIsUncompressedDataModified = false;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user