• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

PolyVoxCore/include/PolyVoxCore/LargeVolume.inl

Go to the documentation of this file.
00001 /*******************************************************************************
00002 Copyright (c) 2005-2009 David Williams
00003 
00004 This software is provided 'as-is', without any express or implied
00005 warranty. In no event will the authors be held liable for any damages
00006 arising from the use of this software.
00007 
00008 Permission is granted to anyone to use this software for any purpose,
00009 including commercial applications, and to alter it and redistribute it
00010 freely, subject to the following restrictions:
00011 
00012     1. The origin of this software must not be misrepresented; you must not
00013     claim that you wrote the original software. If you use this software
00014     in a product, an acknowledgment in the product documentation would be
00015     appreciated but is not required.
00016 
00017     2. Altered source versions must be plainly marked as such, and must not be
00018     misrepresented as being the original software.
00019 
00020     3. This notice may not be removed or altered from any source
00021     distribution.   
00022 *******************************************************************************/
00023 
00024 //Included here rather than in the .h because it refers to LargeVolume (avoids forward declaration)
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         //Create a volume of the right size.
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         //In earlier verions of PolyVox the constructor took three values indicating width, height, and depth. However, this
00061         //causes confusion because these three parameters can be interpreted as two function pointers and a block size instead,
00062         //hence calling a different constructor. And simply removing this constructor will cause confusion because existing
00063         //code with three parameters will then always resolve to the constructor with two function pointers and a block size.
00064         //
00065         //Eventually this constructor will be removed, it's just here to make people change their code to the new version.
00066         //
00067         //IF YOU HIT THIS ASSERT/ABORT, CHANGE YOUR CODE TO USE THE CONSTRUCTOR TAKING A 'Region' INSTEAD.
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         //Create a volume of the right size.
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         //Early out - nothing to do
00167         if(m_bCompressionEnabled == bCompressionEnabled)
00168         {
00169             return;
00170         }
00171         
00172         m_bCompressionEnabled = bCompressionEnabled;
00173 
00174         if(m_bCompressionEnabled)
00175         {
00176             //If compression has been enabled then we need to start honouring the max number of
00177             //uncompressed blocks. Because compression has been disabled for a while we might have
00178             //gone above that limit. Easiest solution is just to clear the cache and start again.
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         /*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
00218         return pUncompressedBorderBlock->fill(tBorder);*/
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         //Return true to indicate that we modified a voxel.
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             // cannot support the amount of blocks... so only load the maximum possible
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                         // If the block is already loaded then we don't load it again. This means it does not get uncompressed,
00300                         // whereas if we were to call getUncompressedBlock() regardless then it would also get uncompressed.
00301                         // This might be nice, but on the prefetch region could be bigger than the uncompressed cache size.
00302                         // This would limit the amount of prefetching we could do.
00303                         continue;
00304                     }
00305 
00306                     if(numblocks == 0)
00307                     {
00308                         // Loading any more blocks would attempt to overflow the memory and therefore erase blocks
00309                         // we loaded in the beginning. This wouldn't cause logic problems but would be wasteful.
00310                         return;
00311                     }
00312                     // load a block
00313                     numblocks--;
00314                     getUncompressedBlock(x,y,z);
00315                 } // for z
00316             } // for y
00317         } // for x
00318     }
00319 
00323     template <typename VoxelType>
00324     void LargeVolume<VoxelType>::flushAll()
00325     {
00326         typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
00327         //Replaced the for loop here as the call to
00328         //eraseBlock was invalidating the iterator.
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                         // not loaded, not unloading
00364                         continue;
00365                     }
00366                     eraseBlock(itBlock);
00367                     // eraseBlock might cause a call to getUncompressedBlock, which again sets m_pLastAccessedBlock
00368                     if(m_v3dLastAccessedBlockPos == pos)
00369                     {
00370                         m_pLastAccessedBlock = 0;
00371                     }
00372                 } // for z
00373             } // for y
00374         } // for x
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         //Debug mode validation
00397         assert(uBlockSideLength > 0);
00398         
00399         //Release mode validation
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); //There are no invalid positions, but initially the m_pLastAccessedBlock pointer will be null;
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         //Clear the previous data
00426         m_pBlocks.clear();
00427 
00428         //Compute the block side length
00429         m_uBlockSideLength = uBlockSideLength;
00430         m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
00431 
00432         //Clear the previous data
00433         m_pBlocks.clear();
00434 
00435         //Create the border block
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         //Other properties we might find useful later
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                 // find the block in the uncompressed cache
00463                 if(m_vecUncompressedBlockCache[ct] == &(itBlock->second))
00464                 {
00465                     // TODO: compression is unneccessary? or will not compressing this cause a memleak?
00466                     itBlock->second.block.compress();
00467                     // put last object in cache here
00468                     m_vecUncompressedBlockCache[ct] = m_vecUncompressedBlockCache.back();
00469                     // decrease cache size by one since last element is now in here twice
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         //We don't have any range checks in this function because it
00482         //is a private function only called by the ConstVolumeProxy. The
00483         //ConstVolumeProxy takes care of ensuring the range is appropriate.
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         //Return true to indicate that we modified a voxel.
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         //Check if we have the same block as last time, if so there's no need to even update
00508         //the time stamp. If we updated it everytime then that would be every time we touched
00509         //a voxel, which would overflow a uint32_t and require us to use a uint64_t instead.
00510         //This check should also provide a significant speed boost as usually it is true.
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         // check whether the block is already loaded
00519         if(itBlock == m_pBlocks.end())
00520         {
00521             //The block is not in the map, so we will have to create a new block and add it.
00522             //Before we do so, we might want to dump some existing data to make space. We 
00523             //Only do this if paging is enabled.
00524             if(m_bPagingEnabled)
00525             {
00526                 // check wether another block needs to be unloaded before this one can be loaded
00527                 if(m_pBlocks.size() == m_uMaxNumberOfBlocksInMemory)
00528                 {
00529                     // find the least recently used block
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             // create the new block
00544             LoadedBlock newBlock(m_uBlockSideLength);
00545             itBlock = m_pBlocks.insert(std::make_pair(v3dBlockPos, newBlock)).first;
00546 
00547             //We have created the new block. If paging is enabled it should be used to
00548             //fill in the required data. Otherwise it is just left in the default state.
00549             if(m_bPagingEnabled)
00550             {
00551                 if(m_funcDataRequiredHandler)
00552                 {
00553                     // "load" will actually call setVoxel, which will in turn call this function again but the block will be found
00554                     // so this if(itBlock == m_pBlocks.end()) never is entered      
00555                     //FIXME - can we pass the block around so that we don't have to find  it again when we recursively call this function?
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         //Get the block and mark that we accessed it
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         //If we are allowed to compress then check whether we need to
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             //Currently we find the oldest block by iterating over the whole array. Of course we could store the blocks sorted by
00584             //timestamp (set, priority_queue, etc) but then we'll need to move them around as the timestamp changes. Can come back 
00585             //to this if it proves to be a bottleneck (compraed to the cost of actually doing the compression/decompression).
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             //Compress the least recently used block.
00596             m_vecUncompressedBlockCache[leastRecentlyUsedBlockIndex]->block.compress();
00597 
00598             //We don't actually remove any elements from this vector, we
00599             //simply change the pointer to point at the new uncompressed bloack.            
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         //Memory used by the blocks
00634         typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
00635         for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
00636         {
00637             //Inaccurate - account for rest of loaded block.
00638             uSizeInBytes += i->second.block.calculateSizeInBytes();
00639         }
00640 
00641         //Memory used by the block cache.
00642         uSizeInBytes += m_vecUncompressedBlockCache.capacity() * sizeof(LoadedBlock);
00643         uSizeInBytes += m_vecUncompressedBlockCache.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
00644 
00645         //Memory used by border data.
00646         if(m_pUncompressedBorderData)
00647         {
00648             uSizeInBytes += m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
00649         }
00650 
00651         return uSizeInBytes;
00652     }
00653 
00654 }
00655 

Generated on Sat Nov 19 2011 00:27:30 for PolyVox by  doxygen 1.7.1