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

PolyVoxCore/include/PolyVoxCore/SimpleVolume.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 namespace PolyVox
00025 {
00029     template <typename VoxelType>
00030     SimpleVolume<VoxelType>::SimpleVolume
00031     (
00032         int32_t dont_use_this_constructor_1, int32_t dont_use_this_constructor_2, int32_t dont_use_this_constructor_3
00033     )
00034     {
00035         //In earlier verions of PolyVox the constructor took three values indicating width, height, and depth. However, this
00036         //causes confusion because these three parameters can be interpreted as two function pointers and a block size instead,
00037         //hence calling a different constructor. And simply removing this constructor will cause confusion because existing
00038         //code with three parameters will then always resolve to the constructor with two function pointers and a block size.
00039         //
00040         //Eventually this constructor will be removed, it's just here to make people change their code to the new version.
00041         //
00042         //IF YOU HIT THIS ASSERT/ABORT, CHANGE YOUR CODE TO USE THE CONSTRUCTOR TAKING A 'Region' INSTEAD.
00043         assert(false);
00044         abort();
00045     }
00046 
00055     template <typename VoxelType>
00056     SimpleVolume<VoxelType>::SimpleVolume
00057     (
00058         const Region& regValid,
00059         uint16_t uBlockSideLength
00060     )
00061     :BaseVolume<VoxelType>(regValid)
00062     {
00063         //Create a volume of the right size.
00064         resize(regValid,uBlockSideLength);
00065     }
00066 
00070     template <typename VoxelType>
00071     SimpleVolume<VoxelType>::~SimpleVolume()
00072     {
00073         delete[] m_pBlocks;
00074         delete[] m_pUncompressedBorderData;
00075     }
00076 
00082     template <typename VoxelType>
00083     VoxelType SimpleVolume<VoxelType>::getBorderValue(void) const
00084     {
00085         return *m_pUncompressedBorderData;
00086     }
00087 
00094     template <typename VoxelType>
00095     VoxelType SimpleVolume<VoxelType>::getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const
00096     {
00097         if(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)))
00098         {
00099             const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
00100             const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
00101             const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
00102 
00103             const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
00104             const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
00105             const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
00106 
00107             typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
00108 
00109             return pUncompressedBlock->getVoxelAt(xOffset,yOffset,zOffset);
00110         }
00111         else
00112         {
00113             return getBorderValue();
00114         }
00115     }
00116 
00121     template <typename VoxelType>
00122     VoxelType SimpleVolume<VoxelType>::getVoxelAt(const Vector3DInt32& v3dPos) const
00123     {
00124         return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
00125     }
00126 
00130     template <typename VoxelType>
00131     void SimpleVolume<VoxelType>::setBorderValue(const VoxelType& tBorder) 
00132     {
00133         /*Block<VoxelType>* pUncompressedBorderBlock = getUncompressedBlock(&m_pBorderBlock);
00134         return pUncompressedBorderBlock->fill(tBorder);*/
00135         std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, tBorder);
00136     }
00137 
00145     template <typename VoxelType>
00146     bool SimpleVolume<VoxelType>::setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue)
00147     {
00148         assert(this->m_regValidRegion.containsPoint(Vector3DInt32(uXPos, uYPos, uZPos)));
00149 
00150         const int32_t blockX = uXPos >> m_uBlockSideLengthPower;
00151         const int32_t blockY = uYPos >> m_uBlockSideLengthPower;
00152         const int32_t blockZ = uZPos >> m_uBlockSideLengthPower;
00153 
00154         const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
00155         const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
00156         const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
00157 
00158         typename SimpleVolume<VoxelType>::Block* pUncompressedBlock = getUncompressedBlock(blockX, blockY, blockZ);
00159 
00160         pUncompressedBlock->setVoxelAt(xOffset,yOffset,zOffset, tValue);
00161 
00162         //Return true to indicate that we modified a voxel.
00163         return true;
00164     }
00165 
00171     template <typename VoxelType>
00172     bool SimpleVolume<VoxelType>::setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue)
00173     {
00174         return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
00175     }
00176 
00180     template <typename VoxelType>
00181     void SimpleVolume<VoxelType>::resize(const Region& regValidRegion, uint16_t uBlockSideLength)
00182     {
00183         //Debug mode validation
00184         assert(uBlockSideLength > 0);
00185         
00186         //Release mode validation
00187         if(uBlockSideLength == 0)
00188         {
00189             throw std::invalid_argument("Block side length cannot be zero.");
00190         }
00191         if(!isPowerOf2(uBlockSideLength))
00192         {
00193             throw std::invalid_argument("Block side length must be a power of two.");
00194         }
00195 
00196         m_uBlockSideLength = uBlockSideLength;
00197         m_uNoOfVoxelsPerBlock = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength;
00198         m_pUncompressedBorderData = 0;
00199 
00200         this->m_regValidRegion = regValidRegion;
00201 
00202         m_regValidRegionInBlocks.setLowerCorner(this->m_regValidRegion.getLowerCorner()  / static_cast<int32_t>(uBlockSideLength));
00203         m_regValidRegionInBlocks.setUpperCorner(this->m_regValidRegion.getUpperCorner()  / static_cast<int32_t>(uBlockSideLength));
00204 
00205         //Compute the block side length
00206         m_uBlockSideLength = uBlockSideLength;
00207         m_uBlockSideLengthPower = logBase2(m_uBlockSideLength);
00208 
00209         //Compute the size of the volume in blocks (and note +1 at the end)
00210         m_uWidthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getX() - m_regValidRegionInBlocks.getLowerCorner().getX() + 1;
00211         m_uHeightInBlocks = m_regValidRegionInBlocks.getUpperCorner().getY() - m_regValidRegionInBlocks.getLowerCorner().getY() + 1;
00212         m_uDepthInBlocks = m_regValidRegionInBlocks.getUpperCorner().getZ() - m_regValidRegionInBlocks.getLowerCorner().getZ() + 1;
00213         m_uNoOfBlocksInVolume = m_uWidthInBlocks * m_uHeightInBlocks * m_uDepthInBlocks;
00214 
00215         //Allocate the data
00216         m_pBlocks = new Block[m_uNoOfBlocksInVolume];
00217         for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i)
00218         {
00219             m_pBlocks[i].initialise(m_uBlockSideLength);
00220         }
00221 
00222         //Create the border block
00223         m_pUncompressedBorderData = new VoxelType[m_uNoOfVoxelsPerBlock];
00224         std::fill(m_pUncompressedBorderData, m_pUncompressedBorderData + m_uNoOfVoxelsPerBlock, VoxelType());
00225 
00226         //Other properties we might find useful later
00227         this->m_uLongestSideLength = (std::max)((std::max)(this->getWidth(),this->getHeight()),this->getDepth());
00228         this->m_uShortestSideLength = (std::min)((std::min)(this->getWidth(),this->getHeight()),this->getDepth());
00229         this->m_fDiagonalLength = sqrtf(static_cast<float>(this->getWidth() * this->getWidth() + this->getHeight() * this->getHeight() + this->getDepth() * this->getDepth()));
00230     }
00231 
00232     template <typename VoxelType>
00233     typename SimpleVolume<VoxelType>::Block* SimpleVolume<VoxelType>::getUncompressedBlock(int32_t uBlockX, int32_t uBlockY, int32_t uBlockZ) const
00234     {
00235         //The lower left corner of the volume could be
00236         //anywhere, but array indices need to start at zero.
00237         uBlockX -= m_regValidRegionInBlocks.getLowerCorner().getX();
00238         uBlockY -= m_regValidRegionInBlocks.getLowerCorner().getY();
00239         uBlockZ -= m_regValidRegionInBlocks.getLowerCorner().getZ();
00240 
00241         //Compute the block index
00242         uint32_t uBlockIndex =
00243                 uBlockX + 
00244                 uBlockY * m_uWidthInBlocks + 
00245                 uBlockZ * m_uWidthInBlocks * m_uHeightInBlocks;
00246 
00247         //Return the block
00248         return &(m_pBlocks[uBlockIndex]);
00249     }
00250 
00254     template <typename VoxelType>
00255     uint32_t SimpleVolume<VoxelType>::calculateSizeInBytes(void)
00256     {
00257         uint32_t uSizeInBytes = sizeof(SimpleVolume);
00258         
00259         uint32_t uSizeOfBlockInBytes = m_uNoOfVoxelsPerBlock * sizeof(VoxelType);
00260 
00261         //Memory used by the blocks ( + 1 is for border)
00262         uSizeInBytes += uSizeOfBlockInBytes * (m_uNoOfBlocksInVolume + 1);
00263 
00264         return uSizeInBytes;
00265     }
00266 
00267 }
00268 

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