Improved raycast unit test so that it exits early if the ray leaves the volume.

This commit is contained in:
David Williams 2012-12-02 17:33:59 +01:00
parent c37997bfe2
commit 47e8f4a86d
3 changed files with 33 additions and 18 deletions

View File

@ -65,6 +65,8 @@ namespace PolyVox
Vector3DInt32 getPosition(void) const;
inline VoxelType getVoxel(void) const;
bool isCurrentPositionValid(void) const;
void setPosition(const Vector3DInt32& v3dNewPos);
void setPosition(int32_t xPos, int32_t yPos, int32_t zPos);
inline bool setVoxel(VoxelType tValue);
@ -110,7 +112,6 @@ namespace PolyVox
protected:
VoxelType getVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos) const;
bool isCurrentPositionValid(void) const;
DerivedVolumeType* mVolume;

View File

@ -60,6 +60,13 @@ namespace PolyVox
return mVolume->getVoxelAt(mXPosInVolume, mYPosInVolume, mZPosInVolume);
}
template <typename VoxelType>
template <typename DerivedVolumeType>
bool inline BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::isCurrentPositionValid(void) const
{
return m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ;
}
template <typename VoxelType>
template <typename DerivedVolumeType>
void BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::setPosition(const Vector3DInt32& v3dNewPos)
@ -374,11 +381,4 @@ namespace PolyVox
}
}
}
template <typename VoxelType>
template <typename DerivedVolumeType>
bool inline BaseVolume<VoxelType>::Sampler<DerivedVolumeType>::isCurrentPositionValid(void) const
{
return m_bIsCurrentPositionValidInX && m_bIsCurrentPositionValidInY && m_bIsCurrentPositionValidInZ;
}
}

View File

@ -42,18 +42,30 @@ class RaycastTestFunctor
{
public:
RaycastTestFunctor()
:m_uTotalVoxelsTouched(0)
:m_uVoxelsTouched(0)
,m_bRayLeftVolume(false)
{
}
bool operator()(const SimpleVolume<int8_t>::Sampler& sampler)
{
m_uTotalVoxelsTouched++;
m_uVoxelsTouched++;
// For this particular test we know that we are always starting a ray inside the volume,
// so if it ever leaves the volume we know it can't go back in and so we can terminate early.
// This optimisation is worthwhile because samplers get slow once outside the volume.
if(!sampler.isCurrentPositionValid())
{
m_bRayLeftVolume = true;
return false;
}
// We are in the volume, so decide whether to continue based on the voxel value.
return sampler.getVoxel() <= 0;
}
uint32_t m_uTotalVoxelsTouched;
uint32_t m_uVoxelsTouched;
bool m_bRayLeftVolume;
};
void TestRaycast::testExecute()
@ -83,21 +95,23 @@ void TestRaycast::testExecute()
//Cast rays from the centre. Roughly 2/3 should escape.
Vector3DFloat start (uVolumeSideLength / 2, uVolumeSideLength / 2, uVolumeSideLength / 2);
// For demonstration purposes we are using the same function object for all raycasts.
// Therefore, the state it maintains (total voxels touched) is accumulated over all raycsts.
RaycastTestFunctor raycastTestFunctor;
// We could have counted the total number of hits in the same way as the total number of voxels
// touched, but for demonstration and testing purposes we are making use of the raycast return value
// and counting them seperatly in this variable.
int hits = 0;
uint32_t uTotalVoxelsTouched = 0;
// Cast a large number of random rays
for(int ct = 0; ct < 1000000; ct++)
{
RaycastTestFunctor raycastTestFunctor;
RaycastResult result = raycastWithDirection(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, raycastTestFunctor);
if(result == RaycastResults::Interupted)
uTotalVoxelsTouched += raycastTestFunctor.m_uVoxelsTouched;
// If the raycast completed then we know it did not hit anything.If it was interupted then it
// probably hit something, unless we noted that the reason it was interupted was that it left the volume.
if((result == RaycastResults::Interupted) && (raycastTestFunctor.m_bRayLeftVolume == false))
{
hits++;
}
@ -107,7 +121,7 @@ void TestRaycast::testExecute()
QCOMPARE(hits, 687494);
// Check the total number of voxels touched
QCOMPARE(raycastTestFunctor.m_uTotalVoxelsTouched, static_cast<uint32_t>(486219343));
QCOMPARE(uTotalVoxelsTouched, static_cast<uint32_t>(29783248));
}
QTEST_MAIN(TestRaycast)