00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "PolyVoxCore/ConstVolumeProxy.h"
00026
00027 namespace PolyVox
00028 {
00035 template <typename VoxelType>
00036 LargeVolume<VoxelType>::LargeVolume
00037 (
00038 polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
00039 polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
00040 uint16_t uBlockSideLength
00041 )
00042 :BaseVolume<VoxelType>(Region::MaxRegion)
00043 {
00044 m_funcDataRequiredHandler = dataRequiredHandler;
00045 m_funcDataOverflowHandler = dataOverflowHandler;
00046 m_bPagingEnabled = true;
00047
00048 resize(Region::MaxRegion,uBlockSideLength);
00049 }
00050
00054 template <typename VoxelType>
00055 LargeVolume<VoxelType>::LargeVolume
00056 (
00057 int32_t dont_use_this_constructor_1, int32_t dont_use_this_constructor_2, int32_t dont_use_this_constructor_3
00058 )
00059 {
00060
00061
00062
00063
00064
00065
00066
00067
00068 assert(false);
00069 abort();
00070 }
00071
00080 template <typename VoxelType>
00081 LargeVolume<VoxelType>::LargeVolume
00082 (
00083 const Region& regValid,
00084 polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataRequiredHandler,
00085 polyvox_function<void(const ConstVolumeProxy<VoxelType>&, const Region&)> dataOverflowHandler,
00086 bool bPagingEnabled,
00087 uint16_t uBlockSideLength
00088 )
00089 :BaseVolume<VoxelType>(regValid)
00090 {
00091 m_funcDataRequiredHandler = dataRequiredHandler;
00092 m_funcDataOverflowHandler = dataOverflowHandler;
00093 m_bPagingEnabled = bPagingEnabled;
00094
00095
00096 resize(regValid,uBlockSideLength);
00097 }
00098
00102 template <typename VoxelType>
00103 LargeVolume<VoxelType>::~LargeVolume()
00104 {
00105 flushAll();
00106 delete[] m_pUncompressedBorderData;
00107 }
00108
00114 template <typename VoxelType>
00115 VoxelType LargeVolume<VoxelType>::getBorderValue(void) const
00116 {
00117 return *m_pUncompressedBorderData;
00118 }
00119
00126 template <typename VoxelType>
00127 VoxelType LargeVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
00128 {
00129 if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
00130 {
00131 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
00132 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
00133 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
00134
00135 const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
00136 const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
00137 const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
00138
00139 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
00140
00141 return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
00142 }
00143 else
00144 {
00145 return getBorderValue();
00146 }
00147 }
00148
00153 template <typename VoxelType>
00154 VoxelType LargeVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
00155 {
00156 return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
00157 }
00158
00163 template <typename VoxelType>
00164 void LargeVolume<VoxelType>::setCompressionEnabled(bool bCompressionEnabled)
00165 {
00166
00167 if(m_bCompressionEnabled == bCompressionEnabled)
00168 {
00169 return;
00170 }
00171
00172 m_bCompressionEnabled = bCompressionEnabled;
00173
00174 if(m_bCompressionEnabled)
00175 {
00176
00177
00178
00179 clearBlockCache();
00180 }
00181 }
00182
00189 template <typename VoxelType>
00190 void LargeVolume<VoxelType>::setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks)
00191 {
00192 clearBlockCache();
00193
00194 m_uMaxNumberOfUncompressedBlocks = uMaxNumberOfUncompressedBlocks;
00195 }
00196
00201 template <typename VoxelType>
00202 void LargeVolume<VoxelType>::setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory)
00203 {
00204 if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
00205 {
00206 flushAll();
00207 }
00208 m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
00209 }
00210
00214 template <typename VoxelType>
00215 void LargeVolume<VoxelType>::setBorderValue(const VoxelType& tBorder)
00216 {
00217
00218
00219 std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, tBorder);
00220 }
00221
00229 template <typename VoxelType>
00230 bool LargeVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
00231 {
00232 assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
00233
00234 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
00235 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
00236 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
00237
00238 const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
00239 const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
00240 const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
00241
00242 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
00243
00244 pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
00245
00246
00247 return true;
00248 }
00249
00255 template <typename VoxelType>
00256 bool LargeVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
00257 {
00258 return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
00259 }
00260
00261
00266 template <typename VoxelType>
00267 void LargeVolume<VoxelType>::prefetch(Region regPrefetch)
00268 {
00269 Vector3DInt32 v3dStart;
00270 for(int i = 0; i < 3; i++)
00271 {
00272 v3dStart.setElement(i, regPrefetch.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
00273 }
00274
00275 Vector3DInt32 v3dEnd;
00276 for(int i = 0; i < 3; i++)
00277 {
00278 v3dEnd.setElement(i, regPrefetch.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
00279 }
00280
00281 Vector3DInt32 v3dSize = v3dEnd - v3dStart + Vector3DInt32(1,1,1);
00282 uint32_t numblocks = static_cast<uint32_t>(v3dSize.getX() * v3dSize.getY() * v3dSize.getZ());
00283 if(numblocks > m_uMaxNumberOfBlocksInMemory)
00284 {
00285
00286 numblocks = m_uMaxNumberOfBlocksInMemory;
00287 }
00288 for(int32_t x = v3dStart.getX(); x <= v3dEnd.getX(); x++)
00289 {
00290 for(int32_t y = v3dStart.getY(); y <= v3dEnd.getY(); y++)
00291 {
00292 for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
00293 {
00294 Vector3DInt32 pos(x,y,z);
00295 typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
00296
00297 if(itBlock != m_pBlocks.end())
00298 {
00299
00300
00301
00302
00303 continue;
00304 }
00305
00306 if(numblocks == 0)
00307 {
00308
00309
00310 return;
00311 }
00312
00313 numblocks--;
00314 getUncompressedBlock(x,y,z);
00315 }
00316 }
00317 }
00318 }
00319
00323 template <typename VoxelType>
00324 void LargeVolume<VoxelType>::flushAll()
00325 {
00326 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
00327
00328
00329 while(m_pBlocks.size() > 0)
00330 {
00331 eraseBlock(m_pBlocks.begin());
00332 }
00333 }
00334
00338 template <typename VoxelType>
00339 void LargeVolume<VoxelType>::flush(Region regFlush)
00340 {
00341 Vector3DInt32 v3dStart;
00342 for(int i = 0; i < 3; i++)
00343 {
00344 v3dStart.setElement(i, regFlush.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
00345 }
00346
00347 Vector3DInt32 v3dEnd;
00348 for(int i = 0; i < 3; i++)
00349 {
00350 v3dEnd.setElement(i, regFlush.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
00351 }
00352
00353 for(int32_t x = v3dStart.getX(); x <= v3dEnd.getX(); x++)
00354 {
00355 for(int32_t y = v3dStart.getY(); y <= v3dEnd.getY(); y++)
00356 {
00357 for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
00358 {
00359 Vector3DInt32 pos(x,y,z);
00360 typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
00361 if(itBlock == m_pBlocks.end())
00362 {
00363
00364 continue;
00365 }
00366 eraseBlock(itBlock);
00367
00368 if(m_v3dLastAccessedBlockPos == pos)
00369 {
00370 m_pLastAccessedBlock = 0;
00371 }
00372 }
00373 }
00374 }
00375 }
00376
00380 template <typename VoxelType>
00381 void LargeVolume<VoxelType>::clearBlockCache(void)
00382 {
00383 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
00384 {
00385 m_vecUncompressedBlockCache[ct]->block.compress();
00386 }
00387 m_vecUncompressedBlockCache.clear();
00388 }
00389
00393 template <typename VoxelType>
00394 void LargeVolume<VoxelType>::resize(const Region& regValidRegion, uint16_t uBlockSideLength)
00395 {
00396
00397 assert(uBlockSideLength > 0);
00398
00399
00400 if(uBlockSideLength == 0)
00401 {
00402 throw std::invalid_argument("Block side length cannot be zero.");
00403 }
00404 if(!isPowerOf2(uBlockSideLength))
00405 {
00406 throw std::invalid_argument("Block side length must be a power of two.");
00407 }
00408
00409 m_uTimestamper = 0;
00410 m_uMaxNumberOfUncompressedBlocks = 16;
00411 m_uBlockSideLength = uBlockSideLength;
00412 m_pUncompressedBorderData = 0;
00413 m_uMaxNumberOfBlocksInMemory = 1024;
00414 m_v3dLastAccessedBlockPos = Vector3DInt32(0,0,0);
00415 m_pLastAccessedBlock = 0;
00416 m_bCompressionEnabled = true;
00417
00418 this->m_regValidRegion = regValidRegion;
00419
00420 m_regValidRegionInBlocks.setLowerCorner(this->m_regValidRegion.getLowerCorner() / static_cast<int32_t>(uBlockSideLength));
00421 m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner() / static_cast<int32_t>(uBlockSideLength));
00422
00423 setMaxNumberOfUncompressedBlocks(m_uMaxNumberOfUncompressedBlocks);
00424
00425
00426 m_pBlocks.clear();
00427
00428
00429 m_uBlockSideLength = uBlockSideLength;
00430 m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
00431
00432
00433 m_pBlocks.clear();
00434
00435
00436 m_pUncompressedBorderData = new VoxelType[m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength];
00437 std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength, VoxelType());
00438
00439
00440 this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
00441 this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
00442 this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
00443 }
00444
00445 template <typename VoxelType>
00446 void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock) const
00447 {
00448 if(m_funcDataOverflowHandler)
00449 {
00450 Vector3DInt32 v3dPos = itBlock->first;
00451 Vector3DInt32 v3dLower(v3dPos.getX() << m_uBlockSideLengthPower, v3dPos.getY() << m_uBlockSideLengthPower, v3dPos.getZ() << m_uBlockSideLengthPower);
00452 Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
00453
00454 Region reg(v3dLower, v3dUpper);
00455 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*this, reg);
00456
00457 m_funcDataOverflowHandler(ConstVolumeProxy, reg);
00458 }
00459 if(m_bCompressionEnabled) {
00460 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
00461 {
00462
00463 if(m_vecUncompressedBlockCache[ct] == &(itBlock->second))
00464 {
00465
00466 itBlock->second.block.compress();
00467
00468 m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back();
00469
00470 m_vecUncompressedBlockCache.resize(m_vecUncompressedBlockCache.size()-1);
00471 break;
00472 }
00473 }
00474 }
00475 m_pBlocks.erase(itBlock);
00476 }
00477
00478 template <typename VoxelType>
00479 bool LargeVolume<VoxelType>::setVoxelAtConst(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue) const
00480 {
00481
00482
00483
00484
00485 const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
00486 const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
00487 const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
00488
00489 const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
00490 const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
00491 const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
00492
00493 Block<VoxelType>* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
00494
00495 pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
00496
00497
00498 return true;
00499 }
00500
00501
00502 template <typename VoxelType>
00503 Block<VoxelType>* LargeVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
00504 {
00505 Vector3DInt32 v3dBlockPos(uBlockX, uBlockY, uBlockZ);
00506
00507
00508
00509
00510
00511 if((v3dBlockPos == m_v3dLastAccessedBlockPos) && (m_pLastAccessedBlock != 0))
00512 {
00513 assert(m_pLastAccessedBlock->m_tUncompressedData);
00514 return m_pLastAccessedBlock;
00515 }
00516
00517 typename std::map<Vector3DInt32, LoadedBlock >::iterator itBlock = m_pBlocks.find(v3dBlockPos);
00518
00519 if(itBlock == m_pBlocks.end())
00520 {
00521
00522
00523
00524 if(m_bPagingEnabled)
00525 {
00526
00527 if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory)
00528 {
00529
00530 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
00531 typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
00532 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
00533 {
00534 if(i->second.timestamp < itUnloadBlock->second.timestamp)
00535 {
00536 itUnloadBlock = i;
00537 }
00538 }
00539 eraseBlock(itUnloadBlock);
00540 }
00541 }
00542
00543
00544 LoadedBlock newBlock(m_uBlockSideLength);
00545 itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
00546
00547
00548
00549 if(m_bPagingEnabled)
00550 {
00551 if(m_funcDataRequiredHandler)
00552 {
00553
00554
00555
00556 Vector3DInt32 v3dLower(v3dBlockPos.getX() << m_uBlockSideLengthPower, v3dBlockPos.getY() << m_uBlockSideLengthPower, v3dBlockPos.getZ() << m_uBlockSideLengthPower);
00557 Vector3DInt32 v3dUpper = v3dLower + Vector3DInt32(m_uBlockSideLength-1, m_uBlockSideLength-1, m_uBlockSideLength-1);
00558 Region reg(v3dLower, v3dUpper);
00559 ConstVolumeProxy<VoxelType> ConstVolumeProxy(*this, reg);
00560 m_funcDataRequiredHandler(ConstVolumeProxy, reg);
00561 }
00562 }
00563 }
00564
00565
00566 LoadedBlock& loadedBlock = itBlock->second;
00567 loadedBlock.timestamp = ++m_uTimestamper;
00568 m_v3dLastAccessedBlockPos = v3dBlockPos;
00569 m_pLastAccessedBlock = &(loadedBlock.block);
00570
00571 if(loadedBlock.block.m_bIsCompressed == false)
00572 {
00573 assert(m_pLastAccessedBlock->m_tUncompressedData);
00574 return m_pLastAccessedBlock;
00575 }
00576
00577
00578 if((m_bCompressionEnabled) && (m_vecUncompressedBlockCache.size() == m_uMaxNumberOfUncompressedBlocks))
00579 {
00580 int32_t leastRecentlyUsedBlockIndex = -1;
00581 uint32_t uLeastRecentTimestamp = (std::numeric_limits<uint32_t>::max)();
00582
00583
00584
00585
00586 for(uint32_t ct = 0; ct < m_vecUncompressedBlockCache.size(); ct++)
00587 {
00588 if(m_vecUncompressedBlockCache[ct]->timestamp < uLeastRecentTimestamp)
00589 {
00590 uLeastRecentTimestamp = m_vecUncompressedBlockCache[ct]->timestamp;
00591 leastRecentlyUsedBlockIndex = ct;
00592 }
00593 }
00594
00595
00596 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress();
00597
00598
00599
00600 m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex] = &loadedBlock;
00601 }
00602 else
00603 {
00604 m_vecUncompressedBlockCache.push_back(&loadedBlock);
00605 }
00606
00607 loadedBlock.block.uncompress();
00608
00609 m_pLastAccessedBlock = &(loadedBlock.block);
00610 assert(m_pLastAccessedBlock->m_tUncompressedData);
00611 return m_pLastAccessedBlock;
00612 }
00613
00617 template <typename VoxelType>
00618 float LargeVolume<VoxelType>::calculateCompressionRatio(void)
00619 {
00620 float fRawSize = m_pBlocks.size() * m_uBlockSideLength * m_uBlockSideLength* m_uBlockSideLength * sizeof(VoxelType);
00621 float fCompressedSize = calculateSizeInBytes();
00622 return fCompressedSize/fRawSize;
00623 }
00624
00628 template <typename VoxelType>
00629 uint32_t LargeVolume<VoxelType>::calculateSizeInBytes(void)
00630 {
00631 uint32_t uSizeInBytes = sizeof(LargeVolume);
00632
00633
00634 typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
00635 for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
00636 {
00637
00638 uSizeInBytes += i->second.block.calculateSizeInBytes();
00639 }
00640
00641
00642 uSizeInBytes += m_vecUncompressedBlockCache.capacity() * sizeof(LoadedBlock);
00643 uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
00644
00645
00646 if(m_pUncompressedBorderData)
00647 {
00648 uSizeInBytes += m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
00649 }
00650
00651 return uSizeInBytes;
00652 }
00653
00654 }
00655