37 template <
typename VoxelType>
46 m_funcDataRequiredHandler = dataRequiredHandler;
47 m_funcDataOverflowHandler = dataOverflowHandler;
48 m_bPagingEnabled =
true;
62 template <
typename VoxelType>
73 ,m_pCompressor(pCompressor)
75 m_funcDataRequiredHandler = dataRequiredHandler;
76 m_funcDataOverflowHandler = dataOverflowHandler;
77 m_bPagingEnabled = bPagingEnabled;
80 initialise(regValid,uBlockSideLength);
90 template <
typename VoxelType>
99 template <
typename VoxelType>
112 template <
typename VoxelType>
124 template <
typename VoxelType>
129 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
130 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
131 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
133 const uint16_t xOffset =
static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
134 const uint16_t yOffset =
static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
135 const uint16_t zOffset =
static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
137 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
139 return pUncompressedBlock->
getVoxelAt(xOffset,yOffset,zOffset);
146 template <
typename VoxelType>
149 return getVoxel(v3dPos.
getX(), v3dPos.
getY(), v3dPos.
getZ());
158 template <
typename VoxelType>
161 if(this->m_regValidRegion.containsPoint(
Vector3DInt32(uXPos, uYPos, uZPos)))
163 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
164 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
165 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
167 const uint16_t xOffset =
static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
168 const uint16_t yOffset =
static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
169 const uint16_t zOffset =
static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
171 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
173 return pUncompressedBlock->
getVoxelAt(xOffset,yOffset,zOffset);
177 return this->getBorderValue();
185 template <
typename VoxelType>
188 return getVoxelAt(v3dPos.
getX(), v3dPos.
getY(), v3dPos.
getZ());
197 template <
typename VoxelType>
205 uXPos = (std::max)(uXPos, this->m_regValidRegion.getLowerX());
206 uYPos = (std::max)(uYPos, this->m_regValidRegion.getLowerY());
207 uZPos = (std::max)(uZPos, this->m_regValidRegion.getLowerZ());
208 uXPos = (std::min)(uXPos, this->m_regValidRegion.getUpperX());
209 uYPos = (std::min)(uYPos, this->m_regValidRegion.getUpperY());
210 uZPos = (std::min)(uZPos, this->m_regValidRegion.getUpperZ());
213 return getVoxel(uXPos, uYPos, uZPos);
218 if(this->m_regValidRegion.containsPoint(uXPos, uYPos, uZPos))
220 return getVoxel(uXPos, uYPos, uZPos);
241 template <
typename VoxelType>
244 return getVoxelWithWrapping(v3dPos.
getX(), v3dPos.
getY(), v3dPos.
getZ(), eWrapMode, tBorder);
253 template <
typename VoxelType>
258 m_uMaxNumberOfUncompressedBlocks = uMaxNumberOfUncompressedBlocks;
265 template <
typename VoxelType>
268 if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
272 m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
282 template <
typename VoxelType>
287 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
288 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
289 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
291 const uint16_t xOffset =
static_cast<uint16_t>(uXPos - (blockX << m_uBlockSideLengthPower));
292 const uint16_t yOffset =
static_cast<uint16_t>(uYPos - (blockY << m_uBlockSideLengthPower));
293 const uint16_t zOffset =
static_cast<uint16_t>(uZPos - (blockZ << m_uBlockSideLengthPower));
295 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
297 pUncompressedBlock->
setVoxelAt(xOffset,yOffset,zOffset, tValue);
308 template <
typename VoxelType>
311 return setVoxelAt(v3dPos.
getX(), v3dPos.
getY(), v3dPos.
getZ(), tValue);
319 template <
typename VoxelType>
323 for(
int i = 0; i < 3; i++)
329 for(
int i = 0; i < 3; i++)
336 if(numblocks > m_uMaxNumberOfBlocksInMemory)
339 numblocks = m_uMaxNumberOfBlocksInMemory;
347 Vector3DInt32 pos(x,y,z);
348 typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos);
350 if(itBlock != m_pBlocks.end())
367 getUncompressedBlock(x,y,z);
376 template <
typename VoxelType>
379 typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i;
382 while(m_pBlocks.size() > 0)
384 eraseBlock(m_pBlocks.begin());
391 template <
typename VoxelType>
395 for(
int i = 0; i < 3; i++)
401 for(
int i = 0; i < 3; i++)
413 typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(pos);
414 if(itBlock == m_pBlocks.end())
421 if(m_v3dLastAccessedBlockPos == pos)
423 m_pLastAccessedBlock = 0;
433 template <
typename VoxelType>
436 for(
uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
438 m_vecUncompressedBlockCache[ct]->block.compress(m_pCompressor);
440 m_vecUncompressedBlockCache.clear();
446 template <
typename VoxelType>
450 POLYVOX_ASSERT(uBlockSideLength > 0,
"Block side length cannot be zero.");
452 POLYVOX_ASSERT(m_pCompressor,
"You must provide a compressor for the LargeVolume to use.");
455 if(uBlockSideLength == 0)
457 POLYVOX_THROW(std::invalid_argument,
"Block side length cannot be zero.");
461 POLYVOX_THROW(std::invalid_argument,
"Block side length must be a power of two.");
465 POLYVOX_THROW(std::invalid_argument,
"You must provide a compressor for the LargeVolume to use.");
469 m_uMaxNumberOfUncompressedBlocks = 16;
470 m_uBlockSideLength = uBlockSideLength;
471 m_uMaxNumberOfBlocksInMemory = 1024;
473 m_pLastAccessedBlock = 0;
475 this->m_regValidRegion = regValidRegion;
478 m_uBlockSideLength = uBlockSideLength;
479 m_uBlockSideLengthPower =
logBase2(m_uBlockSideLength);
481 m_regValidRegionInBlocks.setLowerX(this->m_regValidRegion.getLowerX() >> m_uBlockSideLengthPower);
482 m_regValidRegionInBlocks.setLowerY(this->m_regValidRegion.getLowerY() >> m_uBlockSideLengthPower);
483 m_regValidRegionInBlocks.setLowerZ(this->m_regValidRegion.getLowerZ() >> m_uBlockSideLengthPower);
484 m_regValidRegionInBlocks.setUpperX(this->m_regValidRegion.getUpperX() >> m_uBlockSideLengthPower);
485 m_regValidRegionInBlocks.setUpperY(this->m_regValidRegion.getUpperY() >> m_uBlockSideLengthPower);
486 m_regValidRegionInBlocks.setUpperZ(this->m_regValidRegion.getUpperZ() >> m_uBlockSideLengthPower);
488 setMaxNumberOfUncompressedBlocks(m_uMaxNumberOfUncompressedBlocks);
497 this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
498 this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
499 this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
502 template <
typename VoxelType>
503 void LargeVolume<VoxelType>::eraseBlock(
typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock)
const
505 if(m_funcDataOverflowHandler)
508 Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
511 Region reg(v3dLower, v3dUpper);
512 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*
this, reg);
514 m_funcDataOverflowHandler(ConstVolumeProxy, reg);
518 for(
uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
521 if(m_vecUncompressedBlockCache[ct] == &(itBlock->second))
524 itBlock->second.block.compress(m_pCompressor);
526 m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back();
528 m_vecUncompressedBlockCache.resize(m_vecUncompressedBlockCache.size()-1);
533 m_pBlocks.erase(itBlock);
536 template <
typename VoxelType>
543 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
544 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
545 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
547 const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
548 const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
549 const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
551 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
553 pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
560 template <
typename VoxelType>
561 Block<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(
int32_t uBlockX,
int32_t uBlockY,
int32_t uBlockZ)
const
569 if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
571 POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData,
"Block has no uncompressed data");
572 return m_pLastAccessedBlock;
575 typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itBlock = m_pBlocks.find(v3dBlockPos);
577 if(itBlock == m_pBlocks.end())
585 if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory)
588 typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i;
589 typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator itUnloadBlock = m_pBlocks.begin();
590 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
592 if(i->second.timestamp < itUnloadBlock->second.timestamp)
597 eraseBlock(itUnloadBlock);
602 LoadedBlock newBlock(m_uBlockSideLength);
607 newBlock.block.compress(m_pCompressor);
609 itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
615 if(m_funcDataRequiredHandler)
620 Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower);
622 Region reg(v3dLower, v3dUpper);
623 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*
this, reg);
624 m_funcDataRequiredHandler(ConstVolumeProxy, reg);
630 LoadedBlock& loadedBlock = itBlock->second;
631 loadedBlock.timestamp = ++m_uTimestamper;
632 m_v3dLastAccessedBlockPos = v3dBlockPos;
633 m_pLastAccessedBlock = &(loadedBlock.block);
635 if(loadedBlock.block.m_bIsCompressed ==
false)
637 POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData,
"Block has no uncompressed data");
638 return m_pLastAccessedBlock;
642 if((m_pCompressor) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks))
644 int32_t leastRecentlyUsedBlockIndex = -1;
645 uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)();
650 for(
uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
652 if(m_vecUncompressedBlockCache[ct]->timestamp < uLeastRecentTimestamp)
654 uLeastRecentTimestamp = m_vecUncompressedBlockCache[ct]->timestamp;
655 leastRecentlyUsedBlockIndex = ct;
660 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress(m_pCompressor);
664 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex] = &loadedBlock;
668 m_vecUncompressedBlockCache.push_back(&loadedBlock);
671 loadedBlock.block.uncompress(m_pCompressor);
673 m_pLastAccessedBlock = &(loadedBlock.block);
674 POLYVOX_ASSERT(m_pLastAccessedBlock->m_tUncompressedData,
"Block has no uncompressed data");
675 return m_pLastAccessedBlock;
681 template <
typename VoxelType>
684 float fRawSize =
static_cast<float>(m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength *
sizeof(
VoxelType));
685 float fCompressedSize =
static_cast<float>(calculateSizeInBytes());
686 return fCompressedSize/fRawSize;
692 template <
typename VoxelType>
698 typename std::map<Vector3DInt32, LoadedBlock, BlockPositionCompare>::iterator i;
699 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
702 uSizeInBytes += i->second.block.calculateSizeInBytes();
706 uSizeInBytes += m_vecUncompressedBlockCache.capacity() *
sizeof(
LoadedBlock);
707 uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength *
sizeof(
VoxelType);