From a657f4d4d0b06d351dbce4c4272887256591b60e Mon Sep 17 00:00:00 2001 From: David Williams Date: Fri, 23 May 2008 20:59:27 +0000 Subject: [PATCH] Mostly refactoring and tidying up the code. --- include/Block.h | 4 +- include/Block.inl | 18 ++-- include/Volume.h | 27 ++++-- include/Volume.inl | 180 +++++++++++++++++++++++++------------ include/VolumeIterator.h | 25 +++--- include/VolumeIterator.inl | 141 +++++++++++++++-------------- 6 files changed, 247 insertions(+), 148 deletions(-) diff --git a/include/Block.h b/include/Block.h index 52ad4b48..0f876f17 100644 --- a/include/Block.h +++ b/include/Block.h @@ -47,10 +47,12 @@ namespace PolyVox void setVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos, VoxelType tValue); + void fill(VoxelType tValue); + private: boost::uint8_t m_uSideLengthPower; boost::uint16_t m_uSideLength; - VoxelType* m_tData; + VoxelType* m_tData; }; } diff --git a/include/Block.inl b/include/Block.inl index d113b1a0..545f2263 100644 --- a/include/Block.inl +++ b/include/Block.inl @@ -106,11 +106,19 @@ namespace PolyVox assert(uZPos < m_uSideLength); m_tData - [ - uXPos + - uYPos * m_uSideLength + - uZPos * m_uSideLength * m_uSideLength - ] = tValue; + [ + uXPos + + uYPos * m_uSideLength + + uZPos * m_uSideLength * m_uSideLength + ] = tValue; + } + #pragma endregion + + #pragma region Other + template + void Block::fill(VoxelType tValue) + { + memset(m_tData, tValue, m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType)); } #pragma endregion } diff --git a/include/Volume.h b/include/Volume.h index d6507ce7..e85ac65c 100644 --- a/include/Volume.h +++ b/include/Volume.h @@ -26,6 +26,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "PolyVoxForwardDeclarations.h" #include "boost/cstdint.hpp" + +#include #pragma endregion namespace PolyVox @@ -43,26 +45,39 @@ namespace PolyVox Volume& operator=(const Volume& rhs); - boost::uint16_t getSideLength(void); + boost::uint16_t getSideLength(void) const; VoxelType getVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos) const; VoxelType getVoxelAt(const Vector3DUint16& v3dPos) const; - void setVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos, VoxelType tValue); - void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); - bool containsPoint(Vector3DFloat pos, float boundary) const; bool containsPoint(Vector3DInt32 pos, boost::uint16_t boundary) const; + void idle(boost::uint32_t uAmount); + void lock(const Vector3DUint16& v3dLowerCorner, const Vector3DUint16& v3dUpperCorner); + void unlock(void); private: - Block** mBlocks; + bool isVoxelLocked(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos); + + Block* getHomogenousBlock(VoxelType tHomogenousValue) const; + + Block** m_pBlocks; + bool* m_pIsShared; + bool* m_pIsPotentiallySharable; + VoxelType* m_pHomogenousValue; + mutable std::map*> m_pHomogenousBlocks; + boost::uint32_t m_uNoOfBlocksInVolume; boost::uint16_t m_uSideLengthInBlocks; boost::uint8_t m_uSideLengthPower; boost::uint16_t m_uSideLength; - boost::uint16_t m_uBlockSideLengthPower; + boost::uint8_t m_uBlockSideLengthPower; boost::uint16_t m_uBlockSideLength; + + Vector3DUint16 m_v3dLastLockedLowerCorner; + Vector3DUint16 m_v3dLastLockedUpperCorner; + bool m_bIsLocked; }; //Some handy typedefs diff --git a/include/Volume.inl b/include/Volume.inl index 3df00af3..d78d9ac8 100644 --- a/include/Volume.inl +++ b/include/Volume.inl @@ -31,7 +31,7 @@ namespace PolyVox #pragma region Constructors/Destructors template Volume::Volume(boost::uint8_t uSideLengthPower, boost::uint8_t uBlockSideLengthPower) - :mBlocks(0) + :m_pBlocks(0) { //Check the volume size is sensible. This corresponds to a side length of 65536 voxels if(uSideLengthPower > 16) @@ -53,15 +53,17 @@ namespace PolyVox //Compute number of blocks in the volume m_uNoOfBlocksInVolume = m_uSideLengthInBlocks * m_uSideLengthInBlocks * m_uSideLengthInBlocks; - mBlocks = new Block*[m_uNoOfBlocksInVolume]; + //Create the blocks + m_pBlocks = new Block*[m_uNoOfBlocksInVolume]; + m_pIsShared = new bool[m_uNoOfBlocksInVolume]; + m_pIsPotentiallySharable = new bool[m_uNoOfBlocksInVolume]; + m_pHomogenousValue = new VoxelType[m_uNoOfBlocksInVolume]; for(boost::uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i) { - mBlocks[i] = 0; - } - - for(boost::uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i) - { - mBlocks[i] = new Block(uBlockSideLengthPower); + m_pBlocks[i] = getHomogenousBlock(0); //new Block(uBlockSideLengthPower); + m_pIsShared[i] = true; + m_pIsPotentiallySharable[i] = false; + m_pHomogenousValue[i] = 0; } } @@ -76,7 +78,7 @@ namespace PolyVox { for(boost::uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i) { - delete mBlocks[i]; + delete m_pBlocks[i]; } } #pragma endregion @@ -93,21 +95,21 @@ namespace PolyVox /*for(uint16_t i = 0; i < POLYVOX_NO_OF_BLOCKS_IN_VOLUME; ++i) { //FIXME - Add checking... - mBlocks[i] = SharedPtr(new Block); + m_pBlocks[i] = SharedPtr(new Block); }*/ for(uint32_t i = 0; i < m_uNoOfBlocksInVolume; ++i) { //I think this is OK... If a block is in the homogeneous array it's ref count will be greater //than 1 as there will be the pointer in the volume and the pointer in the static homogeneous array. - /*if(rhs.mBlocks[i].unique()) + /*if(rhs.m_pBlocks[i].unique()) { - mBlocks[i] = SharedPtr(new Block(*(rhs.mBlocks[i]))); + m_pBlocks[i] = SharedPtr(new Block(*(rhs.m_pBlocks[i]))); } else {*/ //we have a block in the homogeneous array - just copy the pointer. - mBlocks[i] = rhs.mBlocks[i]; + m_pBlocks[i] = rhs.m_pBlocks[i]; //} } @@ -117,7 +119,7 @@ namespace PolyVox #pragma region Getters template - boost::uint16_t Volume::getSideLength(void) + boost::uint16_t Volume::getSideLength(void) const { return m_uSideLength; } @@ -125,9 +127,9 @@ namespace PolyVox template VoxelType Volume::getVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos) const { - assert(uXPos < mVolume.getSideLength()); - assert(uYPos < mVolume.getSideLength()); - assert(uZPos < mVolume.getSideLength()); + assert(uXPos < getSideLength()); + assert(uYPos < getSideLength()); + assert(uZPos < getSideLength()); const uint16_t blockX = uXPos >> m_uBlockSideLengthPower; const uint16_t blockY = uYPos >> m_uBlockSideLengthPower; @@ -137,7 +139,7 @@ namespace PolyVox const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); - const Block* block = mBlocks + const Block* block = m_pBlocks [ blockX + blockY * m_uSideLengthInBlocks + @@ -156,44 +158,7 @@ namespace PolyVox return getVoxelAt(v3dPos.x(), v3dPos.y(), v3dPos.z()); } - #pragma endregion - - #pragma region Setters - template - void Volume::setVoxelAt(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos, VoxelType tValue) - { - assert(uXPos < mVolume.getSideLength()); - assert(uYPos < mVolume.getSideLength()); - assert(uZPos < mVolume.getSideLength()); - - const uint16_t blockX = uXPos >> m_uBlockSideLengthPower; - const uint16_t blockY = uYPos >> m_uBlockSideLengthPower; - const uint16_t blockZ = uZPos >> m_uBlockSideLengthPower; - - const uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower); - const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower); - const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower); - - const Block* block = mBlocks - [ - blockX + - blockY * m_uSideLengthInBlocks + - blockZ * m_uSideLengthInBlocks * m_uSideLengthInBlocks - ]; - - return block->setVoxelAt(xOffset,yOffset,zOffset, tValue); - } - - template - void Volume::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue) - { - assert(v3dPos.x() < m_uSideLength); - assert(v3dPos.y() < m_uSideLength); - assert(v3dPos.z() < m_uSideLength); - - setVoxelAt(v3dPos.x(), v3dPos.y(), v3dPos.z(), tValue); - } - #pragma endregion + #pragma endregion #pragma region Other template @@ -217,5 +182,108 @@ namespace PolyVox && (pos.y() >= boundary) && (pos.z() >= boundary); } + + template + void Volume::idle(boost::uint32_t uAmount) + { + //Check the volume isn't locked + if(m_bIsLocked) + { + throw std::logic_error("Cannot perform idle tasks on a locked volume"); + } + } + + template + void Volume::lock(const Vector3DUint16& v3dLowerCorner, const Vector3DUint16& v3dUpperCorner) + { + //Check the volume isn't already locked + if(m_bIsLocked) + { + throw std::logic_error("Cannot lock an already locked volume"); + } + + //Find the block corresponding to the lower corner + Vector3DUint16 v3dBlockLowerCorner + ( + v3dLowerCorner.x() >> m_uBlockSideLengthPower, + v3dLowerCorner.y() >> m_uBlockSideLengthPower, + v3dLowerCorner.z() >> m_uBlockSideLengthPower + ); + + //Find the block corresponding to the upper corner + Vector3DUint16 v3dBlockUpperCorner + ( + v3dUpperCorner.x() >> m_uBlockSideLengthPower, + v3dUpperCorner.y() >> m_uBlockSideLengthPower, + v3dUpperCorner.z() >> m_uBlockSideLengthPower + ); + + //Set all covered blocks to be potentially sharable + for(boost::uint16_t z = v3dBlockLowerCorner.z(); z <= v3dBlockUpperCorner.z(); ++z) + { + for(boost::uint16_t y = v3dBlockLowerCorner.y(); y <= v3dBlockUpperCorner.y(); ++y) + { + for(boost::uint16_t x = v3dBlockLowerCorner.x(); x <= v3dBlockUpperCorner.x(); ++x) + { + const boost::uint32_t uBlockIndex = + blockX + + blockY * m_uSideLengthInBlocks + + blockZ * m_uSideLengthInBlocks * m_uSideLengthInBlocks; + m_pIsPotentiallySharable[uBlockIndex] = true; + } + } + } + + //Store the values so that we can verify voxels are locked before writing to them + m_v3dLastLockedLowerCorner = v3dLowerCorner; + m_v3dLastLockedUpperCorner = v3dUpperCorner; + m_bIsLocked = true; + } + + template + void Volume::unlock(void) + { + //Check the volume isn't already locked. + if(!m_bIsLocked) + { + throw std::logic_error("Cannot unlock an already unlocked volume"); + } + + //Unlock it + m_bIsLocked = false; + } + #pragma endregion + + #pragma region Private Implementation + template + Block* Volume::getHomogenousBlock(VoxelType tHomogenousValue) const + { + std::map*>::iterator iterResult = m_pHomogenousBlocks.find(tHomogenousValue); + if(iterResult == m_pHomogenousBlocks.end()) + { + Block* pBlock = new Block(m_uBlockSideLengthPower); + pBlock->fill(tHomogenousValue); + m_pHomogenousBlocks.insert(std::make_pair(tHomogenousValue, pBlock)); + return pBlock; + } + return iterResult->second; + } + #pragma endregion + + #pragma region Private Implementation + template + bool Volume::isVoxelLocked(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos) + { + return + ( + (uXPos >= m_v3dLastLockedLowerCorner.x()) && + (uYPos >= m_v3dLastLockedLowerCorner.y()) && + (uZPos >= m_v3dLastLockedLowerCorner.z()) && + (uXPos <= m_v3dLastLockedUpperCorner.x()) && + (uYPos <= m_v3dLastLockedUpperCorner.y()) && + (uZPos <= m_v3dLastLockedUpperCorner.z()) && + (m_bIsLocked) + ); + } #pragma endregion } diff --git a/include/VolumeIterator.h b/include/VolumeIterator.h index 55c68ba0..97822f31 100644 --- a/include/VolumeIterator.h +++ b/include/VolumeIterator.h @@ -22,11 +22,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef __VolumeIterator_H__ #define __VolumeIterator_H__ -#include "boost/cstdint.hpp" - +#pragma region Headers #include "PolyVoxForwardDeclarations.h" -#include "TypeDef.h" -#include "Vector.h" + +#include "boost/cstdint.hpp" +#pragma endregion namespace PolyVox { @@ -35,24 +35,22 @@ namespace PolyVox { public: VolumeIterator(Volume& volume); - ~VolumeIterator(); + ~VolumeIterator(); - void setVoxel(VoxelType value); - VoxelType getVoxel(void); + bool operator==(const VolumeIterator& rhs); float getAveragedVoxel(boost::uint16_t size) const; - - - boost::uint16_t getPosX(void) const; boost::uint16_t getPosY(void) const; boost::uint16_t getPosZ(void) const; + VoxelType getVoxel(void) const; void setPosition(boost::uint16_t xPos, boost::uint16_t yPos, boost::uint16_t zPos); void setValidRegion(boost::uint16_t xFirst, boost::uint16_t yFirst, boost::uint16_t zFirst, boost::uint16_t xLast, boost::uint16_t yLast, boost::uint16_t zLast); - void moveForwardInRegion(void); + void setVoxel(VoxelType tValue); - bool isValidForRegion(void); + bool isValidForRegion(void) const; + void moveForwardInRegion(void); VoxelType peekVoxel1nx1ny1nz(void) const; VoxelType peekVoxel1nx1ny0pz(void) const; @@ -85,9 +83,6 @@ namespace PolyVox VoxelType peekVoxel1px1py1pz(void) const; private: - - //VoxelType getVoxelAt(const boost::uint16_t xPosition, const boost::uint16_t yPosition, const boost::uint16_t zPosition) const; - //The current volume Volume& mVolume; diff --git a/include/VolumeIterator.inl b/include/VolumeIterator.inl index f8809d1d..e6e2ea26 100644 --- a/include/VolumeIterator.inl +++ b/include/VolumeIterator.inl @@ -19,13 +19,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ******************************************************************************/ #pragma endregion +#pragma region Headers #include "Block.h" +#include "Vector.h" #include "Volume.h" - -using namespace boost; +#pragma endregion namespace PolyVox { + #pragma region Constructors/Destructors template VolumeIterator::VolumeIterator(Volume& volume) :mVolume(volume) @@ -51,8 +53,7 @@ namespace PolyVox ,mYPosInBlock(0) ,mZPosInBlock(0) ,mIsValidForRegion(true) - ,mCurrentVoxel(volume.mBlocks[0]->m_tData) - //,mCurrentBlock(volume->mBlocks[0]) + ,mCurrentVoxel(volume.m_pBlocks[0]->m_tData) ,mVoxelIndexInBlock(0) ,mBlockIndexInVolume(0) { @@ -61,58 +62,26 @@ namespace PolyVox template VolumeIterator::~VolumeIterator() { - } - - template - void VolumeIterator::setVoxel(VoxelType value) - { - Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; - - /*if(!currentBlock.unique()) - { - Block* copy(new Block(*currentBlock)); - currentBlock = copy; - - mCurrentVoxel = currentBlock->mData + mVoxelIndexInBlock; - }*/ - - *mCurrentVoxel = value; } + #pragma endregion + #pragma region Operators template - VoxelType VolumeIterator::getVoxel(void) + bool VolumeIterator::operator==(const VolumeIterator& rhs) { - //return getVoxelAt(mXPosInVolume,mYPosInVolume,mZPosInVolume); - return *mCurrentVoxel; + //We could just check whether the two mCurrentVoxel pointers are equal, but this may not + //be safe in the future if we decide to allow blocks to be shared between volumes + //So we really check whether the volumes and positions are the same + /*return + ( + mVolume. + );*/ } + #pragma endregion - /*template - VoxelType VolumeIterator::getVoxelAt(const uint16_t xPosition, const uint16_t yPosition, const uint16_t zPosition) const - { - assert(xPosition < mVolume.getSideLength()); - assert(yPosition < mVolume.getSideLength()); - assert(zPosition < mVolume.getSideLength()); - - const uint16_t blockX = xPosition >> mVolume.m_uBlockSideLengthPower; - const uint16_t blockY = yPosition >> mVolume.m_uBlockSideLengthPower; - const uint16_t blockZ = zPosition >> mVolume.m_uBlockSideLengthPower; - - const uint16_t xOffset = xPosition - (blockX << mVolume.m_uBlockSideLengthPower); - const uint16_t yOffset = yPosition - (blockY << mVolume.m_uBlockSideLengthPower); - const uint16_t zOffset = zPosition - (blockZ << mVolume.m_uBlockSideLengthPower); - - const Block* block = mVolume.mBlocks - [ - blockX + - blockY * mVolume.m_uSideLengthInBlocks + - blockZ * mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks - ]; - - return block->getVoxelAt(xOffset,yOffset,zOffset); - }*/ - + #pragma region Getters template - float VolumeIterator::getAveragedVoxel(uint16_t size) const + float VolumeIterator::getAveragedVoxel(boost::uint16_t size) const { assert(mXPosInVolume >= size); assert(mYPosInVolume >= size); @@ -144,25 +113,33 @@ namespace PolyVox } template - uint16_t VolumeIterator::getPosX(void) const + boost::uint16_t VolumeIterator::getPosX(void) const { return mXPosInVolume; } template - uint16_t VolumeIterator::getPosY(void) const + boost::uint16_t VolumeIterator::getPosY(void) const { return mYPosInVolume; } template - uint16_t VolumeIterator::getPosZ(void) const + boost::uint16_t VolumeIterator::getPosZ(void) const { return mZPosInVolume; } template - void VolumeIterator::setPosition(uint16_t xPos, uint16_t yPos, uint16_t zPos) + VoxelType VolumeIterator::getVoxel(void) const + { + return *mCurrentVoxel; + } + #pragma endregion + + #pragma region Setters + template + void VolumeIterator::setPosition(boost::uint16_t xPos, boost::uint16_t yPos, boost::uint16_t zPos) { mXPosInVolume = xPos; mYPosInVolume = yPos; @@ -179,7 +156,7 @@ namespace PolyVox mBlockIndexInVolume = mXBlock + mYBlock * mVolume.m_uSideLengthInBlocks + mZBlock * mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks; - Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; + Block* currentBlock = mVolume.m_pBlocks[mBlockIndexInVolume]; mVoxelIndexInBlock = mXPosInBlock + mYPosInBlock * mVolume.m_uBlockSideLength + @@ -189,7 +166,7 @@ namespace PolyVox } template - void VolumeIterator::setValidRegion(uint16_t xFirst, uint16_t yFirst, uint16_t zFirst, uint16_t xLast, uint16_t yLast, uint16_t zLast) + void VolumeIterator::setValidRegion(boost::uint16_t xFirst, boost::uint16_t yFirst, boost::uint16_t zFirst, boost::uint16_t xLast, boost::uint16_t yLast, boost::uint16_t zLast) { mXRegionFirst = xFirst; mYRegionFirst = yFirst; @@ -208,6 +185,43 @@ namespace PolyVox mZRegionLastBlock = mZRegionLast >> mVolume.m_uBlockSideLengthPower; } + template + void VolumeIterator::setVoxel(VoxelType tValue) + { + assert(mVolume.isVoxelLocked(mXPosInVolume,mYPosInVolume,mZPosInVolume)); + + const boost::uint32_t uBlockIndex = + mXBlock + + mYBlock * mVolume.m_uSideLengthInBlocks + + mZBlock * mVolume.m_uSideLengthInBlocks * mVolume.m_uSideLengthInBlocks; + + const bool bIsShared = mVolume.m_pIsShared[uBlockIndex]; + const VoxelType tHomogenousValue = mVolume.m_pHomogenousValue[uBlockIndex]; + if(bIsShared) + { + if(tHomogenousValue != tValue) + { + mVolume.m_pBlocks[uBlockIndex] = new Block(mVolume.m_uBlockSideLengthPower); + mVolume.m_pIsShared[uBlockIndex] = false; + mVolume.m_pBlocks[uBlockIndex]->fill(tHomogenousValue); + mCurrentVoxel = mVolume.m_pBlocks[uBlockIndex]->m_tData + mVoxelIndexInBlock; + *mCurrentVoxel = tValue; + } + } + else + { + *mCurrentVoxel = tValue; + } + } + #pragma endregion + + #pragma region Other + template + bool VolumeIterator::isValidForRegion(void) const + { + return mIsValidForRegion; + } + template void VolumeIterator::moveForwardInRegion(void) { @@ -221,7 +235,7 @@ namespace PolyVox mVoxelIndexInBlock = mXPosInBlock + mYPosInBlock * mVolume.m_uBlockSideLength + mZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; - Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; + Block* currentBlock = mVolume.m_pBlocks[mBlockIndexInVolume]; mCurrentVoxel = currentBlock->m_tData + mVoxelIndexInBlock; mYPosInBlock++; @@ -234,7 +248,7 @@ namespace PolyVox mVoxelIndexInBlock = mXPosInBlock + mYPosInBlock * mVolume.m_uBlockSideLength + mZPosInBlock * mVolume.m_uBlockSideLength * mVolume.m_uBlockSideLength; - Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; + Block* currentBlock = mVolume.m_pBlocks[mBlockIndexInVolume]; mCurrentVoxel = currentBlock->m_tData + mVoxelIndexInBlock; mZPosInBlock++; @@ -273,8 +287,8 @@ namespace PolyVox } } - Block* currentBlock = mVolume.mBlocks[mBlockIndexInVolume]; - //mCurrentBlock = mVolume->mBlocks[mBlockIndexInVolume]; + Block* currentBlock = mVolume.m_pBlocks[mBlockIndexInVolume]; + //mCurrentBlock = mVolume->m_pBlocks[mBlockIndexInVolume]; mXPosInVolume = (std::max)(mXRegionFirst,uint16_t(mXBlock * mVolume.m_uBlockSideLength)); mYPosInVolume = (std::max)(mYRegionFirst,uint16_t(mYBlock * mVolume.m_uBlockSideLength)); @@ -293,13 +307,9 @@ namespace PolyVox } } } + #pragma endregion - template - bool VolumeIterator::isValidForRegion(void) - { - return mIsValidForRegion; - } - + #pragma region Peekers template VoxelType VolumeIterator::peekVoxel1nx1ny1nz(void) const { @@ -569,4 +579,5 @@ namespace PolyVox } return mVolume.getVoxelAt(mXPosInVolume+1,mYPosInVolume+1,mZPosInVolume+1); } + #pragma endregion }