Bounds check added to get/setVoxelAt.
This commit is contained in:
parent
d0ebd53407
commit
29928b774d
8
TODO.txt
8
TODO.txt
@ -1,3 +1,11 @@
|
||||
Short term
|
||||
==========
|
||||
Sort awkward use of 'offset'
|
||||
Replace float with uchar for material.
|
||||
Mesh smoothing (surface nets?)
|
||||
Mesh filters/modifiers - A 'translate' modifier?
|
||||
|
||||
|
||||
For Version 1.0
|
||||
===============
|
||||
Implement Memory Pool
|
||||
|
@ -132,11 +132,11 @@ namespace PolyVox
|
||||
uint16_t getShortestSideLength(void) const;
|
||||
///Gets the length of the diagonal in voxels
|
||||
float getDiagonalLength(void) const;
|
||||
VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||
VoxelType getVoxelAt(const Vector3DUint16& v3dPos) const;
|
||||
VoxelType getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tDefault = 0) const;
|
||||
VoxelType getVoxelAt(const Vector3DUint16& v3dPos, VoxelType tDefault = 0) const;
|
||||
|
||||
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||
bool setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||
bool setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||
|
||||
void tidyUpMemory(uint32_t uNoOfBlocksToProcess = (std::numeric_limits<uint32_t>::max)());
|
||||
|
||||
|
@ -224,82 +224,99 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Volume<VoxelType>::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
|
||||
VoxelType Volume<VoxelType>::getVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tDefault) const
|
||||
{
|
||||
assert(uXPos < getWidth());
|
||||
assert(uYPos < getHeight());
|
||||
assert(uZPos < getDepth());
|
||||
//We don't use getEnclosingRegion here because we care
|
||||
//about speed and don't need to check the lower bound.
|
||||
if((uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth()))
|
||||
{
|
||||
const uint16_t blockX = uXPos >> m_uBlockSideLengthPower;
|
||||
const uint16_t blockY = uYPos >> m_uBlockSideLengthPower;
|
||||
const uint16_t blockZ = uZPos >> m_uBlockSideLengthPower;
|
||||
|
||||
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 uint16_t xOffset = uXPos - (blockX << m_uBlockSideLengthPower);
|
||||
const uint16_t yOffset = uYPos - (blockY << m_uBlockSideLengthPower);
|
||||
const uint16_t zOffset = uZPos - (blockZ << m_uBlockSideLengthPower);
|
||||
const std::shared_ptr< Block< VoxelType > >& block = m_pBlocks
|
||||
[
|
||||
blockX +
|
||||
blockY * m_uWidthInBlocks +
|
||||
blockZ * m_uWidthInBlocks * m_uHeightInBlocks
|
||||
];
|
||||
|
||||
const std::shared_ptr< Block< VoxelType > >& block = m_pBlocks
|
||||
[
|
||||
blockX +
|
||||
blockY * m_uWidthInBlocks +
|
||||
blockZ * m_uWidthInBlocks * m_uHeightInBlocks
|
||||
];
|
||||
|
||||
return block->getVoxelAt(xOffset,yOffset,zOffset);
|
||||
return block->getVoxelAt(xOffset,yOffset,zOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tDefault;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Volume<VoxelType>::getVoxelAt(const Vector3DUint16& v3dPos) const
|
||||
VoxelType Volume<VoxelType>::getVoxelAt(const Vector3DUint16& v3dPos, VoxelType tDefault) const
|
||||
{
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tDefault);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Setters
|
||||
template <typename VoxelType>
|
||||
void Volume<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
bool Volume<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
{
|
||||
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);
|
||||
|
||||
uint32_t uBlockIndex =
|
||||
blockX +
|
||||
blockY * m_uWidthInBlocks +
|
||||
blockZ * m_uWidthInBlocks * m_uHeightInBlocks;
|
||||
|
||||
std::shared_ptr< Block<VoxelType> >& block = m_pBlocks[uBlockIndex];
|
||||
|
||||
//It's quite possible that the user might attempt to set a voxel to it's current value.
|
||||
//We test for this case firstly because it could help performance, but more importantly
|
||||
//because it lets us avoid unsharing blocks unnecessarily.
|
||||
if(block->getVoxelAt(xOffset, yOffset, zOffset) != tValue)
|
||||
//We don't use getEnclosingRegion here because we care
|
||||
//about speed and don't need to check the lower bound.
|
||||
if((uXPos < getWidth()) && (uYPos < getHeight()) && (uZPos < getDepth()))
|
||||
{
|
||||
if(block.unique())
|
||||
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);
|
||||
|
||||
uint32_t uBlockIndex =
|
||||
blockX +
|
||||
blockY * m_uWidthInBlocks +
|
||||
blockZ * m_uWidthInBlocks * m_uHeightInBlocks;
|
||||
|
||||
std::shared_ptr< Block<VoxelType> >& block = m_pBlocks[uBlockIndex];
|
||||
|
||||
//It's quite possible that the user might attempt to set a voxel to it's current value.
|
||||
//We test for this case firstly because it could help performance, but more importantly
|
||||
//because it lets us avoid unsharing blocks unnecessarily.
|
||||
if(block->getVoxelAt(xOffset, yOffset, zOffset) != tValue)
|
||||
{
|
||||
block->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
//There is a chance that setting this voxel makes the block homogenous and therefore shareable.
|
||||
//But checking this will take some time, so for now just set a flag.
|
||||
m_vecBlockIsPotentiallyHomogenous[uBlockIndex] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr< Block<VoxelType> > pNewBlock(new Block<VoxelType>(*(block)));
|
||||
block = pNewBlock;
|
||||
m_vecBlockIsPotentiallyHomogenous[uBlockIndex] = false;
|
||||
block->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
if(block.unique())
|
||||
{
|
||||
block->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
//There is a chance that setting this voxel makes the block homogenous and therefore shareable.
|
||||
//But checking this will take some time, so for now just set a flag.
|
||||
m_vecBlockIsPotentiallyHomogenous[uBlockIndex] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr< Block<VoxelType> > pNewBlock(new Block<VoxelType>(*(block)));
|
||||
block = pNewBlock;
|
||||
m_vecBlockIsPotentiallyHomogenous[uBlockIndex] = false;
|
||||
block->setVoxelAt(xOffset,yOffset,zOffset, tValue);
|
||||
}
|
||||
}
|
||||
//Return true to indicate that we modified a voxel.
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Return false to indicate that no voxel was modified.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Volume<VoxelType>::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
bool Volume<VoxelType>::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
{
|
||||
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
return setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
@ -33,6 +33,18 @@ void TestVolume::testSize()
|
||||
{
|
||||
const uint16_t g_uVolumeSideLength = 128;
|
||||
Volume<uint8_t> volData(g_uVolumeSideLength, g_uVolumeSideLength, g_uVolumeSideLength);
|
||||
|
||||
//Note: Deliberatly go past each edge by one to test if the bounds checking works.
|
||||
for (uint16_t z = 0; z < g_uVolumeSideLength + 1; z++)
|
||||
{
|
||||
for (uint16_t y = 0; y < g_uVolumeSideLength + 1; y++)
|
||||
{
|
||||
for (uint16_t x = 0; x < g_uVolumeSideLength + 1; x++)
|
||||
{
|
||||
volData.setVoxelAt(x,y,z,255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
volData.tidyUpMemory(0);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user