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).
|
It's been unclassed (makes sense, removes template parameters).
|
||||||
Switch from std::function to STL approach.
|
Switch from std::function to STL approach.
|
||||||
Note functor is passed by reference rather than by value.
|
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;
|
float m_fMaxDistance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace MyRaycastResults
|
||||||
|
{
|
||||||
|
enum MyRaycastResult
|
||||||
|
{
|
||||||
|
Completed,
|
||||||
|
Interupted
|
||||||
|
};
|
||||||
|
}
|
||||||
|
typedef MyRaycastResults::MyRaycastResult MyRaycastResult;
|
||||||
|
|
||||||
template<typename VolumeType, typename Callback>
|
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);
|
VolumeType::Sampler sampler(volData);
|
||||||
|
|
||||||
@ -173,7 +183,7 @@ namespace PolyVox
|
|||||||
{
|
{
|
||||||
//m_result.foundIntersection = true;
|
//m_result.foundIntersection = true;
|
||||||
//m_result.intersectionVoxel = Vector3DInt32(i,j,k);
|
//m_result.intersectionVoxel = Vector3DInt32(i,j,k);
|
||||||
return;
|
return MyRaycastResults::Interupted;
|
||||||
}
|
}
|
||||||
//m_result.previousVoxel = Vector3DInt32(i,j,k);
|
//m_result.previousVoxel = Vector3DInt32(i,j,k);
|
||||||
|
|
||||||
@ -203,6 +213,8 @@ namespace PolyVox
|
|||||||
if(dk == -1) sampler.moveNegativeZ();
|
if(dk == -1) sampler.moveNegativeZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MyRaycastResults::Completed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,31 +33,27 @@ freely, subject to the following restrictions:
|
|||||||
|
|
||||||
using namespace PolyVox;
|
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.
|
// 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
|
// 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
|
class MyFunctor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
MyFunctor()
|
||||||
|
:m_uTotalVoxelsTouched(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool operator()(const SimpleVolume<int8_t>::Sampler& sampler)
|
bool operator()(const SimpleVolume<int8_t>::Sampler& sampler)
|
||||||
{
|
{
|
||||||
if(sampler.getVoxel() > 0)
|
m_uTotalVoxelsTouched++;
|
||||||
{
|
|
||||||
foundIntersection = true;
|
|
||||||
}
|
|
||||||
return sampler.getVoxel() <= 0;
|
return sampler.getVoxel() <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t m_uTotalVoxelsTouched;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TestRaycast::testExecute()
|
void TestRaycast::testExecute()
|
||||||
@ -84,36 +80,34 @@ void TestRaycast::testExecute()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTime timer;
|
|
||||||
timer.start();
|
|
||||||
|
|
||||||
//Cast rays from the centre. Roughly 2/3 should escape.
|
//Cast rays from the centre. Roughly 2/3 should escape.
|
||||||
Vector3DFloat start (uVolumeSideLength / 2, uVolumeSideLength / 2, uVolumeSideLength / 2);
|
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;
|
int hits = 0;
|
||||||
|
|
||||||
|
// Cast a large number of random rays
|
||||||
for(int ct = 0; ct < 1000000; ct++)
|
for(int ct = 0; ct < 1000000; ct++)
|
||||||
{
|
{
|
||||||
/*RaycastResult result;
|
MyRaycastResult result = raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, myFunctor);
|
||||||
Raycast< SimpleVolume<int8_t> > raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, result, isPassableByRay);
|
|
||||||
raycast.execute();
|
|
||||||
if(result.foundIntersection)
|
|
||||||
{
|
|
||||||
hits++;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
foundIntersection = false;
|
if(result == MyRaycastResults::Interupted)
|
||||||
MyFunctor myFunctor;
|
|
||||||
raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, myFunctor);
|
|
||||||
|
|
||||||
if(foundIntersection)
|
|
||||||
{
|
{
|
||||||
hits++;
|
hits++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Finished in " << timer.elapsed() << "ms" << std::endl;
|
// Check the number of hits.
|
||||||
|
|
||||||
//Check the number of hits.
|
|
||||||
QCOMPARE(hits, 687494);
|
QCOMPARE(hits, 687494);
|
||||||
|
|
||||||
|
// Check the total number of voxels touched
|
||||||
|
QCOMPARE(myFunctor.m_uTotalVoxelsTouched, static_cast<uint32_t>(486219343));
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestRaycast)
|
QTEST_MAIN(TestRaycast)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user