35 template <
typename VoxelType>
40 uint16_t uBlockSideLength
44 m_funcDataRequiredHandler = dataRequiredHandler;
45 m_funcDataOverflowHandler = dataOverflowHandler;
46 m_bPagingEnabled =
true;
59 template <
typename VoxelType>
66 uint16_t uBlockSideLength
70 m_funcDataRequiredHandler = dataRequiredHandler;
71 m_funcDataOverflowHandler = dataOverflowHandler;
72 m_bPagingEnabled = bPagingEnabled;
75 initialise(regValid,uBlockSideLength);
85 template <
typename VoxelType>
94 template <
typename VoxelType>
98 delete[] m_pUncompressedBorderData;
108 template <
typename VoxelType>
119 template <
typename VoxelType>
122 return *m_pUncompressedBorderData;
131 template <
typename VoxelType>
134 if(this->m_regValidRegion.containsPoint(
Vector3DInt32(uXPos, uYPos, uZPos)))
136 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
137 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
138 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
140 const uint16_t xOffset =
static_cast<uint16_t
>(uXPos - (blockX << m_uBlockSideLengthPower));
141 const uint16_t yOffset =
static_cast<uint16_t
>(uYPos - (blockY << m_uBlockSideLengthPower));
142 const uint16_t zOffset =
static_cast<uint16_t
>(uZPos - (blockZ << m_uBlockSideLengthPower));
144 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
146 return pUncompressedBlock->
getVoxelAt(xOffset,yOffset,zOffset);
150 return getBorderValue();
158 template <
typename VoxelType>
161 return getVoxelAt(v3dPos.
getX(), v3dPos.
getY(), v3dPos.
getZ());
168 template <
typename VoxelType>
172 if(m_bCompressionEnabled == bCompressionEnabled)
177 m_bCompressionEnabled = bCompressionEnabled;
179 if(m_bCompressionEnabled)
194 template <
typename VoxelType>
199 m_uMaxNumberOfUncompressedBlocks = uMaxNumberOfUncompressedBlocks;
206 template <
typename VoxelType>
209 if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
213 m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
219 template <
typename VoxelType>
224 std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder);
234 template <
typename VoxelType>
237 assert(this->m_regValidRegion.containsPoint(
Vector3DInt32(uXPos, uYPos, uZPos)));
239 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
240 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
241 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
243 const uint16_t xOffset =
static_cast<uint16_t
>(uXPos - (blockX << m_uBlockSideLengthPower));
244 const uint16_t yOffset =
static_cast<uint16_t
>(uYPos - (blockY << m_uBlockSideLengthPower));
245 const uint16_t zOffset =
static_cast<uint16_t
>(uZPos - (blockZ << m_uBlockSideLengthPower));
247 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
249 pUncompressedBlock->
setVoxelAt(xOffset,yOffset,zOffset, tValue);
260 template <
typename VoxelType>
263 return setVoxelAt(v3dPos.
getX(), v3dPos.
getY(), v3dPos.
getZ(), tValue);
271 template <
typename VoxelType>
275 for(
int i = 0; i < 3; i++)
281 for(
int i = 0; i < 3; i++)
287 uint32_t numblocks =
static_cast<uint32_t
>(v3dSize.
getX() * v3dSize.
getY() * v3dSize.
getZ());
288 if(numblocks > m_uMaxNumberOfBlocksInMemory)
291 numblocks = m_uMaxNumberOfBlocksInMemory;
299 Vector3DInt32 pos(x,y,z);
300 typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
302 if(itBlock != m_pBlocks.end())
319 getUncompressedBlock(x,y,z);
328 template <
typename VoxelType>
331 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
334 while(m_pBlocks.size() > 0)
336 eraseBlock(m_pBlocks.begin());
343 template <
typename VoxelType>
347 for(
int i = 0; i < 3; i++)
353 for(
int i = 0; i < 3; i++)
365 typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
366 if(itBlock == m_pBlocks.end())
373 if(m_v3dLastAccessedBlockPos == pos)
375 m_pLastAccessedBlock = 0;
385 template <
typename VoxelType>
388 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
390 m_vecUncompressedBlockCache[ct]->block.compress();
392 m_vecUncompressedBlockCache.clear();
398 template <
typename VoxelType>
402 assert(uBlockSideLength > 0);
405 if(uBlockSideLength == 0)
407 throw std::invalid_argument(
"Block side length cannot be zero.");
411 throw std::invalid_argument(
"Block side length must be a power of two.");
415 m_uMaxNumberOfUncompressedBlocks = 16;
416 m_uBlockSideLength = uBlockSideLength;
417 m_pUncompressedBorderData = 0;
418 m_uMaxNumberOfBlocksInMemory = 1024;
420 m_pLastAccessedBlock = 0;
421 m_bCompressionEnabled =
true;
423 this->m_regValidRegion = regValidRegion;
425 m_regValidRegionInBlocks.
setLowerCorner(this->m_regValidRegion.getLowerCorner() /
static_cast<int32_t>(uBlockSideLength));
426 m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner() /
static_cast<int32_t>(uBlockSideLength));
428 setMaxNumberOfUncompressedBlocks(m_uMaxNumberOfUncompressedBlocks);
434 m_uBlockSideLength = uBlockSideLength;
435 m_uBlockSideLengthPower =
logBase2(m_uBlockSideLength);
441 m_pUncompressedBorderData =
new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
442 std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType());
445 this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
446 this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
447 this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
450 template <
typename VoxelType>
451 void LargeVolume<VoxelType>::eraseBlock(
typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock)
const
453 if(m_funcDataOverflowHandler)
456 Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
459 Region reg(v3dLower, v3dUpper);
460 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*
this, reg);
462 m_funcDataOverflowHandler(ConstVolumeProxy, reg);
464 if(m_bCompressionEnabled) {
465 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
468 if(m_vecUncompressedBlockCache[ct] == &(itBlock->second))
471 itBlock->second.block.compress();
473 m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back();
475 m_vecUncompressedBlockCache.resize(m_vecUncompressedBlockCache.size()-1);
480 m_pBlocks.erase(itBlock);
483 template <
typename VoxelType>
484 bool LargeVolume<VoxelType>::setVoxelAtConst(
int32_t uXPos,
int32_t uYPos,
int32_t uZPos, VoxelType tValue)
const
490 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
491 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
492 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
494 const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
495 const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
496 const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
498 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
500 pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
507 template <
typename VoxelType>
508 Block<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(
int32_t uBlockX,
int32_t uBlockY,
int32_t uBlockZ)
const
516 if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
518 assert(m_pLastAccessedBlock->m_tUncompressedData);
519 return m_pLastAccessedBlock;
522 typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
524 if(itBlock == m_pBlocks.end())
532 if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory)
535 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
536 typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
537 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
539 if(i->second.timestamp < itUnloadBlock->second.timestamp)
544 eraseBlock(itUnloadBlock);
549 LoadedBlock newBlock(m_uBlockSideLength);
550 itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
556 if(m_funcDataRequiredHandler)
561 Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower);
563 Region reg(v3dLower, v3dUpper);
564 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*
this, reg);
565 m_funcDataRequiredHandler(ConstVolumeProxy, reg);
571 LoadedBlock& loadedBlock = itBlock->second;
572 loadedBlock.timestamp = ++m_uTimestamper;
573 m_v3dLastAccessedBlockPos = v3dBlockPos;
574 m_pLastAccessedBlock = &(loadedBlock.block);
576 if(loadedBlock.block.m_bIsCompressed ==
false)
578 assert(m_pLastAccessedBlock->m_tUncompressedData);
579 return m_pLastAccessedBlock;
583 if((m_bCompressionEnabled) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks))
585 int32_t leastRecentlyUsedBlockIndex = -1;
586 uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)();
591 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
593 if(m_vecUncompressedBlockCache[ct]->timestamp < uLeastRecentTimestamp)
595 uLeastRecentTimestamp = m_vecUncompressedBlockCache[ct]->timestamp;
596 leastRecentlyUsedBlockIndex = ct;
601 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress();
605 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex] = &loadedBlock;
609 m_vecUncompressedBlockCache.push_back(&loadedBlock);
612 loadedBlock.block.uncompress();
614 m_pLastAccessedBlock = &(loadedBlock.block);
615 assert(m_pLastAccessedBlock->m_tUncompressedData);
616 return m_pLastAccessedBlock;
622 template <
typename VoxelType>
625 float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength *
sizeof(
VoxelType);
626 float fCompressedSize = calculateSizeInBytes();
627 return fCompressedSize/fRawSize;
633 template <
typename VoxelType>
639 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
640 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
643 uSizeInBytes += i->second.block.calculateSizeInBytes();
647 uSizeInBytes += m_vecUncompressedBlockCache.capacity() *
sizeof(
LoadedBlock);
648 uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength *
sizeof(
VoxelType);
651 if(m_pUncompressedBorderData)
653 uSizeInBytes += m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength *
sizeof(
VoxelType);