Added meaningful raycast return values and improved tests.
This commit is contained in:
parent
23184e6924
commit
7af38d83a3
@ -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?
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user