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;
428 m_uBlockSideLength = uBlockSideLength;
429 m_uBlockSideLengthPower =
logBase2(m_uBlockSideLength);
433 m_regValidRegionInBlocks.setLowerCorner(
Vector3DInt32(this->m_regValidRegion.getLowerCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getLowerCorner().getZ() >> m_uBlockSideLengthPower));
437 m_regValidRegionInBlocks.setUpperCorner(
Vector3DInt32(this->m_regValidRegion.getUpperCorner().getX() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getY() >> m_uBlockSideLengthPower, this->m_regValidRegion.getUpperCorner().getZ() >> m_uBlockSideLengthPower));
439 setMaxNumberOfUncompressedBlocks(m_uMaxNumberOfUncompressedBlocks);
448 m_pUncompressedBorderData =
new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
449 std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType());
452 this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
453 this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
454 this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
457 template <
typename VoxelType>
458 void LargeVolume<VoxelType>::eraseBlock(
typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock)
const
460 if(m_funcDataOverflowHandler)
463 Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
466 Region reg(v3dLower, v3dUpper);
467 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*
this, reg);
469 m_funcDataOverflowHandler(ConstVolumeProxy, reg);
471 if(m_bCompressionEnabled) {
472 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
475 if(m_vecUncompressedBlockCache[ct] == &(itBlock->second))
478 itBlock->second.block.compress();
480 m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back();
482 m_vecUncompressedBlockCache.resize(m_vecUncompressedBlockCache.size()-1);
487 m_pBlocks.erase(itBlock);
490 template <
typename VoxelType>
491 bool LargeVolume<VoxelType>::setVoxelAtConst(
int32_t uXPos,
int32_t uYPos,
int32_t uZPos, VoxelType tValue)
const
497 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
498 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
499 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
501 const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
502 const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
503 const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
505 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
507 pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
514 template <
typename VoxelType>
515 Block<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(
int32_t uBlockX,
int32_t uBlockY,
int32_t uBlockZ)
const
523 if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
525 assert(m_pLastAccessedBlock->m_tUncompressedData);
526 return m_pLastAccessedBlock;
529 typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
531 if(itBlock == m_pBlocks.end())
539 if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory)
542 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
543 typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
544 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
546 if(i->second.timestamp < itUnloadBlock->second.timestamp)
551 eraseBlock(itUnloadBlock);
556 LoadedBlock newBlock(m_uBlockSideLength);
557 itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
563 if(m_funcDataRequiredHandler)
568 Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower);
570 Region reg(v3dLower, v3dUpper);
571 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*
this, reg);
572 m_funcDataRequiredHandler(ConstVolumeProxy, reg);
578 LoadedBlock& loadedBlock = itBlock->second;
579 loadedBlock.timestamp = ++m_uTimestamper;
580 m_v3dLastAccessedBlockPos = v3dBlockPos;
581 m_pLastAccessedBlock = &(loadedBlock.block);
583 if(loadedBlock.block.m_bIsCompressed ==
false)
585 assert(m_pLastAccessedBlock->m_tUncompressedData);
586 return m_pLastAccessedBlock;
590 if((m_bCompressionEnabled) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks))
592 int32_t leastRecentlyUsedBlockIndex = -1;
593 uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)();
598 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
600 if(m_vecUncompressedBlockCache[ct]->timestamp < uLeastRecentTimestamp)
602 uLeastRecentTimestamp = m_vecUncompressedBlockCache[ct]->timestamp;
603 leastRecentlyUsedBlockIndex = ct;
608 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress();
612 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex] = &loadedBlock;
616 m_vecUncompressedBlockCache.push_back(&loadedBlock);
619 loadedBlock.block.uncompress();
621 m_pLastAccessedBlock = &(loadedBlock.block);
622 assert(m_pLastAccessedBlock->m_tUncompressedData);
623 return m_pLastAccessedBlock;
629 template <
typename VoxelType>
632 float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength *
sizeof(
VoxelType);
633 float fCompressedSize = calculateSizeInBytes();
634 return fCompressedSize/fRawSize;
640 template <
typename VoxelType>
646 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
647 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
650 uSizeInBytes += i->second.block.calculateSizeInBytes();
654 uSizeInBytes += m_vecUncompressedBlockCache.capacity() *
sizeof(
LoadedBlock);
655 uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength *
sizeof(
VoxelType);
658 if(m_pUncompressedBorderData)
660 uSizeInBytes += m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength *
sizeof(
VoxelType);