Added meaningful raycast return values and improved tests.

This commit is contained in:
David Williams 2012-10-02 16:52:43 +02:00
parent 23184e6924
commit 7af38d83a3
3 changed files with 46 additions and 37 deletions

View File

@ -29,4 +29,7 @@ Changes to Raycast
It's been unclassed (makes sense, removes template parameters).
Switch from std::function to STL approach.
Note functor is passed by reference rather than by value.
Remove 0.5 offset?
Remove 0.5 offset?
Resolved endpoints vs direction confusion
Prevent short directions
Prevent infinite loops (by preventing long directions?

View File

@ -121,8 +121,18 @@ namespace PolyVox
float m_fMaxDistance;
};
namespace MyRaycastResults
{
enum MyRaycastResult
{
Completed,
Interupted
};
}
typedef MyRaycastResults::MyRaycastResult MyRaycastResult;
template<typename VolumeType, typename Callback>
void raycast(VolumeType* volData, /*const*/ Vector3DFloat/*&*/ v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
MyRaycastResult raycast(VolumeType* volData, /*const*/ Vector3DFloat/*&*/ v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
{
VolumeType::Sampler sampler(volData);
@ -173,7 +183,7 @@ namespace PolyVox
{
//m_result.foundIntersection = true;
//m_result.intersectionVoxel = Vector3DInt32(i,j,k);
return;
return MyRaycastResults::Interupted;
}
//m_result.previousVoxel = Vector3DInt32(i,j,k);
@ -203,6 +213,8 @@ namespace PolyVox
if(dk == -1) sampler.moveNegativeZ();
}
}
return MyRaycastResults::Completed;
}
}

View File

@ -33,31 +33,27 @@ freely, subject to the following restrictions:
using namespace PolyVox;
bool foundIntersection;
bool isPassableByRay(const SimpleVolume<int8_t>::Sampler& sampler)
{
if(sampler.getVoxel() > 0)
{
foundIntersection = true;
}
return sampler.getVoxel() <= 0;
}
// This is the callback functor which is called by the raycast() function for every voxel it touches.
// It's primary purpose is to tell the raycast whether or not to continue (i.e. it tests whether the
// ray has hit a solid voxel). Because the instance of this class is passed to the raycast() function by reference we can also use it to encapsulate some state.
// ray has hit a solid voxel). Because the instance of this class is passed to the raycast() function
// by reference we can also use it to encapsulate some state. We're testing this by counting the total
// number of voxels touched.
class MyFunctor
{
public:
MyFunctor()
:m_uTotalVoxelsTouched(0)
{
}
bool operator()(const SimpleVolume<int8_t>::Sampler& sampler)
{
if(sampler.getVoxel() > 0)
{
foundIntersection = true;
}
m_uTotalVoxelsTouched++;
return sampler.getVoxel() <= 0;
}
uint32_t m_uTotalVoxelsTouched;
};
void TestRaycast::testExecute()
@ -84,36 +80,34 @@ void TestRaycast::testExecute()
}
}
QTime timer;
timer.start();
//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.
MyFunctor myFunctor;
// 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;
// Cast a large number of random rays
for(int ct = 0; ct < 1000000; ct++)
{
/*RaycastResult result;
Raycast< SimpleVolume<int8_t> > raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, result, isPassableByRay);
raycast.execute();
if(result.foundIntersection)
{
hits++;
}*/
MyRaycastResult result = raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, myFunctor);
foundIntersection = false;
MyFunctor myFunctor;
raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, myFunctor);
if(foundIntersection)
if(result == MyRaycastResults::Interupted)
{
hits++;
}
}
std::cout << "Finished in " << timer.elapsed() << "ms" << std::endl;
//Check the number of hits.
// Check the number of hits.
QCOMPARE(hits, 687494);
// Check the total number of voxels touched
QCOMPARE(myFunctor.m_uTotalVoxelsTouched, static_cast<uint32_t>(486219343));
}
QTEST_MAIN(TestRaycast)