Some refactoring of the volume.
This commit is contained in:
parent
ef185d79a0
commit
3cc2e4383f
@ -64,9 +64,6 @@ namespace PolyVox
|
|||||||
|
|
||||||
//---------- Volume ----------
|
//---------- Volume ----------
|
||||||
template <typename VoxelType> class Volume;
|
template <typename VoxelType> class Volume;
|
||||||
typedef Volume<float> FloatVolume;
|
|
||||||
typedef Volume<uint8_t> UInt8Volume;
|
|
||||||
typedef Volume<uint16_t> UInt16Volume;
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
|
||||||
//---------- Mesh ----------
|
//---------- Mesh ----------
|
||||||
|
@ -70,9 +70,6 @@ namespace PolyVox
|
|||||||
uint8_t m_uSideLengthPower;
|
uint8_t m_uSideLengthPower;
|
||||||
bool m_bIsCompressed;
|
bool m_bIsCompressed;
|
||||||
bool m_bIsUncompressedDataModified;
|
bool m_bIsUncompressedDataModified;
|
||||||
uint32_t m_uTimestamp;
|
|
||||||
uint32_t m_uUncompressedIndex;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,6 @@ namespace PolyVox
|
|||||||
,m_tUncompressedData(NULL)
|
,m_tUncompressedData(NULL)
|
||||||
,m_bIsCompressed(true)
|
,m_bIsCompressed(true)
|
||||||
,m_bIsUncompressedDataModified(true)
|
,m_bIsUncompressedDataModified(true)
|
||||||
,m_uTimestamp(0)
|
|
||||||
,m_uUncompressedIndex((std::numeric_limits<uint32_t>::max)())
|
|
||||||
{
|
{
|
||||||
if(uSideLength != 0)
|
if(uSideLength != 0)
|
||||||
{
|
{
|
||||||
|
@ -116,11 +116,19 @@ namespace PolyVox
|
|||||||
// Make the ConstVolumeProxy a friend
|
// Make the ConstVolumeProxy a friend
|
||||||
friend class ConstVolumeProxy<VoxelType>;
|
friend class ConstVolumeProxy<VoxelType>;
|
||||||
|
|
||||||
struct UncompressedBlock
|
struct LoadedBlock
|
||||||
{
|
{
|
||||||
Vector3DInt32 v3dBlockIndex;
|
public:
|
||||||
VoxelType* data;
|
LoadedBlock(uint16_t uSideLength = 0)
|
||||||
|
:block(uSideLength)
|
||||||
|
,uncompressedData(0)
|
||||||
|
,timestamp(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Block<VoxelType> block;
|
||||||
|
VoxelType* uncompressedData;
|
||||||
|
uint32_t timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -182,22 +190,21 @@ namespace PolyVox
|
|||||||
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler;
|
polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler;
|
||||||
private:
|
private:
|
||||||
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
Block<VoxelType>* getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const;
|
||||||
void eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const;
|
void eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const;
|
||||||
/// this function can be called by dataRequiredHandler without causing any weird effects
|
/// this function can be called by dataRequiredHandler 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;
|
||||||
|
|
||||||
//The block data
|
//The block data
|
||||||
mutable std::map<Vector3DInt32, Block<VoxelType> > m_pBlocks;
|
mutable std::map<Vector3DInt32, LoadedBlock > m_pBlocks;
|
||||||
|
|
||||||
//The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
|
//The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather
|
||||||
//than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
|
//than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache
|
||||||
//of blocks. However, this could mean the same block data is uncompressed and modified in more than one
|
//of blocks. However, this could mean the same block data is uncompressed and modified in more than one
|
||||||
//location in memory... could be messy with threading.
|
//location in memory... could be messy with threading.
|
||||||
mutable std::vector< UncompressedBlock > m_vecUncompressedBlockCache;
|
mutable std::vector< LoadedBlock* > m_vecUncompressedBlockCache;
|
||||||
mutable std::vector<uint32_t> m_pUncompressedTimestamps;
|
|
||||||
mutable uint32_t m_uTimestamper;
|
mutable uint32_t m_uTimestamper;
|
||||||
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
|
||||||
mutable Block<VoxelType>* m_pLastAccessedBlock;
|
mutable LoadedBlock* m_pLastAccessedBlock;
|
||||||
uint32_t m_uMaxUncompressedBlockCacheSize;
|
uint32_t m_uMaxUncompressedBlockCacheSize;
|
||||||
uint32_t m_uMaxBlocksLoaded;
|
uint32_t m_uMaxBlocksLoaded;
|
||||||
|
|
||||||
@ -220,11 +227,6 @@ namespace PolyVox
|
|||||||
int32_t m_uShortestSideLength;
|
int32_t m_uShortestSideLength;
|
||||||
float m_fDiagonalLength;
|
float m_fDiagonalLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
//Some handy typedefs
|
|
||||||
typedef Volume<float> FloatVolume;
|
|
||||||
typedef Volume<uint8_t> UInt8Volume;
|
|
||||||
typedef Volume<uint16_t> UInt16Volume;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "Volume.inl"
|
#include "Volume.inl"
|
||||||
|
@ -99,7 +99,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
Volume<VoxelType>::~Volume()
|
Volume<VoxelType>::~Volume()
|
||||||
{
|
{
|
||||||
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i = m_pBlocks.begin()) {
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i = m_pBlocks.begin()) {
|
||||||
eraseBlock(i);
|
eraseBlock(i);
|
||||||
}
|
}
|
||||||
@ -255,11 +255,14 @@ namespace PolyVox
|
|||||||
if(uMaxBlocks < m_pBlocks.size()) {
|
if(uMaxBlocks < m_pBlocks.size()) {
|
||||||
std::cout << uMaxBlocks << ", " << m_pBlocks.size() << ", " << m_pBlocks.size() - uMaxBlocks << std::endl;
|
std::cout << uMaxBlocks << ", " << m_pBlocks.size() << ", " << m_pBlocks.size() - uMaxBlocks << std::endl;
|
||||||
// we need to unload some blocks
|
// we need to unload some blocks
|
||||||
for(int j = 0; j < m_pBlocks.size() - uMaxBlocks; j++) {
|
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();
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
|
||||||
if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp) {
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||||
|
{
|
||||||
|
if(i->second.timestamp < itUnloadBlock->second.timestamp)
|
||||||
|
{
|
||||||
itUnloadBlock = i;
|
itUnloadBlock = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,8 +327,8 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
||||||
{
|
{
|
||||||
m_pBlocks[m_vecUncompressedBlockCache[ct].v3dBlockIndex].compress();
|
m_vecUncompressedBlockCache[ct]->block.compress();
|
||||||
delete[] m_vecUncompressedBlockCache[ct].data;
|
delete[] m_vecUncompressedBlockCache[ct]->uncompressedData;
|
||||||
}
|
}
|
||||||
m_vecUncompressedBlockCache.clear();
|
m_vecUncompressedBlockCache.clear();
|
||||||
}
|
}
|
||||||
@ -375,7 +378,6 @@ namespace PolyVox
|
|||||||
|
|
||||||
//Clear the previous data
|
//Clear the previous data
|
||||||
m_pBlocks.clear();
|
m_pBlocks.clear();
|
||||||
m_pUncompressedTimestamps.clear();
|
|
||||||
|
|
||||||
//Compute the block side length
|
//Compute the block side length
|
||||||
m_uBlockSideLength = uBlockSideLength;
|
m_uBlockSideLength = uBlockSideLength;
|
||||||
@ -383,9 +385,6 @@ namespace PolyVox
|
|||||||
|
|
||||||
//Clear the previous data
|
//Clear the previous data
|
||||||
m_pBlocks.clear();
|
m_pBlocks.clear();
|
||||||
m_pUncompressedTimestamps.clear();
|
|
||||||
|
|
||||||
m_pUncompressedTimestamps.resize(m_uMaxUncompressedBlockCacheSize, 0);
|
|
||||||
|
|
||||||
//Create the border block
|
//Create the border block
|
||||||
m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
||||||
@ -398,7 +397,7 @@ namespace PolyVox
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void Volume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock) const
|
void Volume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const
|
||||||
{
|
{
|
||||||
if(dataOverflowHandler)
|
if(dataOverflowHandler)
|
||||||
{
|
{
|
||||||
@ -449,10 +448,10 @@ namespace PolyVox
|
|||||||
//This check should also provide a significant speed boost as usually it is true.
|
//This check should also provide a significant speed boost as usually it is true.
|
||||||
if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
|
if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
|
||||||
{
|
{
|
||||||
return m_pLastAccessedBlock;
|
return &(m_pLastAccessedBlock->block);
|
||||||
}
|
}
|
||||||
|
|
||||||
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
|
||||||
// check whether the block is already loaded
|
// check whether the block is already loaded
|
||||||
if(itBlock == m_pBlocks.end())
|
if(itBlock == m_pBlocks.end())
|
||||||
{
|
{
|
||||||
@ -461,11 +460,11 @@ namespace PolyVox
|
|||||||
if(m_pBlocks.size() == m_uMaxBlocksLoaded)
|
if(m_pBlocks.size() == m_uMaxBlocksLoaded)
|
||||||
{
|
{
|
||||||
// find the least recently used block
|
// find the least recently used block
|
||||||
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||||
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator itUnloadBlock = m_pBlocks.begin();
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
|
||||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||||
{
|
{
|
||||||
if(i->second.m_uTimestamp < itUnloadBlock->second.m_uTimestamp)
|
if(i->second.timestamp < itUnloadBlock->second.timestamp)
|
||||||
{
|
{
|
||||||
itUnloadBlock = i;
|
itUnloadBlock = i;
|
||||||
}
|
}
|
||||||
@ -476,7 +475,7 @@ namespace PolyVox
|
|||||||
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
|
Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
|
||||||
|
|
||||||
// create the new block
|
// create the new block
|
||||||
Block<VoxelType> newBlock(m_uBlockSideLength);
|
LoadedBlock newBlock(m_uBlockSideLength);
|
||||||
itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
|
itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
|
||||||
|
|
||||||
// fill it with data (well currently fill it with nothingness)
|
// fill it with data (well currently fill it with nothingness)
|
||||||
@ -494,16 +493,15 @@ namespace PolyVox
|
|||||||
m_v3dLastAccessedBlockPos = v3dBlockPos;
|
m_v3dLastAccessedBlockPos = v3dBlockPos;
|
||||||
|
|
||||||
//Get the block
|
//Get the block
|
||||||
Block<VoxelType>* block = &(itBlock->second);
|
LoadedBlock* block = &(itBlock->second);
|
||||||
|
|
||||||
m_uTimestamper++;
|
m_uTimestamper++;
|
||||||
block->m_uTimestamp = m_uTimestamper;
|
block->timestamp = m_uTimestamper;
|
||||||
|
|
||||||
if(block->m_bIsCompressed == false)
|
if(block->block.m_bIsCompressed == false)
|
||||||
{
|
{
|
||||||
m_pUncompressedTimestamps[block->m_uUncompressedIndex] = m_uTimestamper;
|
|
||||||
m_pLastAccessedBlock = block;
|
m_pLastAccessedBlock = block;
|
||||||
return block;
|
return &(block->block);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Currently we find the oldest block by iterating over the whole array. Of course we could store the blocks sorted by
|
//Currently we find the oldest block by iterating over the whole array. Of course we could store the blocks sorted by
|
||||||
@ -517,31 +515,27 @@ namespace PolyVox
|
|||||||
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)(); // you said not int64 ;)
|
uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)(); // you said not int64 ;)
|
||||||
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
|
||||||
{
|
{
|
||||||
if(m_pUncompressedTimestamps[ct] < uLeastRecentTimestamp)
|
if(m_vecUncompressedBlockCache[ct]->timestamp < uLeastRecentTimestamp)
|
||||||
{
|
{
|
||||||
uLeastRecentTimestamp = m_pUncompressedTimestamps[ct];
|
uLeastRecentTimestamp = m_vecUncompressedBlockCache[ct]->timestamp;
|
||||||
leastRecentlyUsedBlockIndex = ct;
|
leastRecentlyUsedBlockIndex = ct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uUncompressedBlockIndex = leastRecentlyUsedBlockIndex;
|
uUncompressedBlockIndex = leastRecentlyUsedBlockIndex;
|
||||||
m_pBlocks[m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex].compress();
|
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress();
|
||||||
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex].v3dBlockIndex = v3dBlockPos;
|
m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->uncompressedData = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UncompressedBlock uncompressedBlock;
|
block->uncompressedData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
||||||
//uncompressedBlock.block = block;
|
m_vecUncompressedBlockCache.push_back(block);
|
||||||
uncompressedBlock.v3dBlockIndex = v3dBlockPos;
|
|
||||||
uncompressedBlock.data = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
|
|
||||||
m_vecUncompressedBlockCache.push_back(uncompressedBlock);
|
|
||||||
uUncompressedBlockIndex = m_vecUncompressedBlockCache.size() - 1;
|
uUncompressedBlockIndex = m_vecUncompressedBlockCache.size() - 1;
|
||||||
}
|
}
|
||||||
block->m_uUncompressedIndex = uUncompressedBlockIndex;
|
block->block.uncompress(block->uncompressedData);
|
||||||
block->uncompress(m_vecUncompressedBlockCache[uUncompressedBlockIndex].data);
|
|
||||||
|
|
||||||
m_pLastAccessedBlock = block;
|
m_pLastAccessedBlock = block;
|
||||||
return block;
|
return &(block->block);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
@ -558,15 +552,16 @@ namespace PolyVox
|
|||||||
uint32_t uSizeInBytes = sizeof(Volume);
|
uint32_t uSizeInBytes = sizeof(Volume);
|
||||||
|
|
||||||
//Memory used by the blocks
|
//Memory used by the blocks
|
||||||
typename std::map<Vector3DInt32, Block<VoxelType> >::iterator i;
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) {
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||||
i->second.calculateSizeInBytes();
|
{
|
||||||
|
//Inaccurate - account for rest of loaded block.
|
||||||
|
uSizeInBytes += i->second.block.calculateSizeInBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Memory used by the block cache.
|
//Memory used by the block cache.
|
||||||
uSizeInBytes += m_vecUncompressedBlockCache.capacity() * sizeof(UncompressedBlock);
|
uSizeInBytes += m_vecUncompressedBlockCache.capacity() * sizeof(LoadedBlock);
|
||||||
uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||||
uSizeInBytes += m_pUncompressedTimestamps.capacity() * sizeof(uint32_t);
|
|
||||||
|
|
||||||
//Memory used by border data.
|
//Memory used by border data.
|
||||||
if(m_pUncompressedBorderData)
|
if(m_pUncompressedBorderData)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user