Work on volume iterators.

This commit is contained in:
David Williams 2008-05-23 22:41:02 +00:00
parent 180981293a
commit 634a6fc883
5 changed files with 77 additions and 118 deletions

View File

@ -35,7 +35,7 @@ namespace PolyVox
//Check the block size is sensible. This corresponds to a side length of 256 voxels //Check the block size is sensible. This corresponds to a side length of 256 voxels
if(uSideLengthPower > 8) if(uSideLengthPower > 8)
{ {
throw std::invalid_argument("Block side length must be less than or equal to eight"); throw std::invalid_argument("Block side length power must be less than or equal to eight");
} }
//Compute the side length //Compute the side length

View File

@ -51,13 +51,11 @@ namespace PolyVox
bool containsPoint(Vector3DFloat pos, float boundary) const; bool containsPoint(Vector3DFloat pos, float boundary) const;
bool containsPoint(Vector3DInt32 pos, boost::uint16_t boundary) const; bool containsPoint(Vector3DInt32 pos, boost::uint16_t boundary) const;
VolumeIterator<VoxelType> firstVoxel(void);
void idle(boost::uint32_t uAmount); void idle(boost::uint32_t uAmount);
void lock(const Vector3DUint16& v3dLowerCorner, const Vector3DUint16& v3dUpperCorner); VolumeIterator<VoxelType> lastVoxel(void);
void unlock(void);
private: private:
bool isVoxelLocked(boost::uint16_t uXPos, boost::uint16_t uYPos, boost::uint16_t uZPos);
Block<VoxelType>* getHomogenousBlock(VoxelType tHomogenousValue) const; Block<VoxelType>* getHomogenousBlock(VoxelType tHomogenousValue) const;
Block<VoxelType>** m_pBlocks; Block<VoxelType>** m_pBlocks;
@ -74,10 +72,6 @@ namespace PolyVox
boost::uint8_t m_uBlockSideLengthPower; boost::uint8_t m_uBlockSideLengthPower;
boost::uint16_t m_uBlockSideLength; boost::uint16_t m_uBlockSideLength;
Vector3DUint16 m_v3dLastLockedLowerCorner;
Vector3DUint16 m_v3dLastLockedUpperCorner;
bool m_bIsLocked;
}; };
//Some handy typedefs //Some handy typedefs

View File

@ -36,7 +36,7 @@ namespace PolyVox
//Check the volume size is sensible. This corresponds to a side length of 65536 voxels //Check the volume size is sensible. This corresponds to a side length of 65536 voxels
if(uSideLengthPower > 16) if(uSideLengthPower > 16)
{ {
throw std::invalid_argument("Block side length must be less than or equal to 65536"); throw std::invalid_argument("Volume side length power must be less than or equal to 16");
} }
//Compute the volume side length //Compute the volume side length
@ -183,74 +183,25 @@ namespace PolyVox
&& (pos.z() >= boundary); && (pos.z() >= boundary);
} }
template <typename VoxelType>
VolumeIterator<VoxelType> Volume<VoxelType>::firstVoxel(void)
{
VolumeIterator<VoxelType> iter(*this);
iter.setPosition(0,0,0);
return iter;
}
template <typename VoxelType> template <typename VoxelType>
void Volume<VoxelType>::idle(boost::uint32_t uAmount) void Volume<VoxelType>::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 <typename VoxelType> template <typename VoxelType>
void Volume<VoxelType>::lock(const Vector3DUint16& v3dLowerCorner, const Vector3DUint16& v3dUpperCorner) VolumeIterator<VoxelType> Volume<VoxelType>::lastVoxel(void)
{ {
//Check the volume isn't already locked VolumeIterator<VoxelType> iter(*this);
if(m_bIsLocked) iter.setPosition(m_uSideLength-1,m_uSideLength-1,m_uSideLength-1);
{ return iter;
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 <typename VoxelType>
void Volume<VoxelType>::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 endregion
@ -269,21 +220,4 @@ namespace PolyVox
return iterResult->second; return iterResult->second;
} }
#pragma endregion #pragma endregion
#pragma region Private Implementation
template <typename VoxelType>
bool Volume<VoxelType>::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
} }

View File

@ -38,6 +38,10 @@ namespace PolyVox
~VolumeIterator(); ~VolumeIterator();
bool operator==(const VolumeIterator& rhs); bool operator==(const VolumeIterator& rhs);
bool operator<(const VolumeIterator& rhs);
bool operator>(const VolumeIterator& rhs);
bool operator<=(const VolumeIterator& rhs);
bool operator>=(const VolumeIterator& rhs);
float getAveragedVoxel(boost::uint16_t size) const; float getAveragedVoxel(boost::uint16_t size) const;
boost::uint16_t getPosX(void) const; boost::uint16_t getPosX(void) const;
@ -83,6 +87,7 @@ namespace PolyVox
VoxelType peekVoxel1px1py1pz(void) const; VoxelType peekVoxel1px1py1pz(void) const;
private: private:
//The current volume //The current volume
Volume<VoxelType>& mVolume; Volume<VoxelType>& mVolume;

View File

@ -31,31 +31,6 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
VolumeIterator<VoxelType>::VolumeIterator(Volume<VoxelType>& volume) VolumeIterator<VoxelType>::VolumeIterator(Volume<VoxelType>& volume)
:mVolume(volume) :mVolume(volume)
,mXRegionFirst(0)
,mYRegionFirst(0)
,mZRegionFirst(0)
,mXRegionLast(volume.getSideLength()-1)
,mYRegionLast(volume.getSideLength()-1)
,mZRegionLast(volume.getSideLength()-1)
,mXRegionFirstBlock(0)
,mYRegionFirstBlock(0)
,mZRegionFirstBlock(0)
,mXRegionLastBlock(volume.m_uSideLengthInBlocks-1)
,mYRegionLastBlock(volume.m_uSideLengthInBlocks-1)
,mZRegionLastBlock(volume.m_uSideLengthInBlocks-1)
,mXPosInVolume(0)
,mYPosInVolume(0)
,mZPosInVolume(0)
,mXBlock(0)
,mYBlock(0)
,mZBlock(0)
,mXPosInBlock(0)
,mYPosInBlock(0)
,mZPosInBlock(0)
,mIsValidForRegion(true)
,mCurrentVoxel(volume.m_pBlocks[0]->m_tData)
,mVoxelIndexInBlock(0)
,mBlockIndexInVolume(0)
{ {
} }
@ -71,11 +46,60 @@ namespace PolyVox
{ {
//We could just check whether the two mCurrentVoxel pointers are equal, but this may not //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 //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 //So we really check whether the positions are the same.
/*return //NOTE: With all iterator comparisons it is the users job to ensure they at least point
//to the same volume. Otherwise they are not comparible.
assert(&mVolume == &rhs.mVolume);
return
( (
mVolume. (mXPosInVolume == rhs.mXPosInVolume) &&
);*/ (mYPosInVolume == rhs.mYPosInVolume) &&
(mZPosInVolume == rhs.mZPosInVolume)
);
}
template <typename VoxelType>
bool VolumeIterator<VoxelType>::operator<(const VolumeIterator<VoxelType>& rhs)
{
assert(&mVolume == &rhs.mVolume);
if(mZPosInVolume < rhs.mZPosInVolume)
return true;
if(mZPosInVolume > rhs.mZPosInVolume)
return false;
if(mYPosInVolume < rhs.mYPosInVolume)
return true;
if(mYPosInVolume > rhs.mYPosInVolume)
return false;
if(mXPosInVolume < rhs.mXPosInVolume)
return true;
if(mXPosInVolume > rhs.mXPosInVolume)
return false;
return false;
}
template <typename VoxelType>
bool VolumeIterator<VoxelType>::operator>(const VolumeIterator<VoxelType>& rhs)
{
assert(&mVolume == &rhs.mVolume);
return (rhs < *this);
}
template <typename VoxelType>
bool VolumeIterator<VoxelType>::operator<=(const VolumeIterator<VoxelType>& rhs)
{
assert(&mVolume == &rhs.mVolume);
return (rhs > *this);
}
template <typename VoxelType>
bool VolumeIterator<VoxelType>::operator>=(const VolumeIterator<VoxelType>& rhs)
{
assert(&mVolume == &rhs.mVolume);
return (rhs < *this);
} }
#pragma endregion #pragma endregion
@ -210,6 +234,8 @@ namespace PolyVox
} }
else else
{ {
//There is a chance that setting this voxel makes the block homogenous and therefore shareable.
mVolume.m_pIsPotentiallySharable[uBlockIndex] = true;
*mCurrentVoxel = tValue; *mCurrentVoxel = tValue;
} }
} }