Initial work on unclassing raycast.
This commit is contained in:
parent
ca66396631
commit
23184e6924
@ -23,3 +23,10 @@ Changes to CubicSurfaceExtractor
|
||||
The behaviour of the CubicSurfaceExtractor has been changed such that it no longer handles some edge cases. Because each generated quad lies between two voxels it can be unclear which region should 'own' a quad when the two voxels are from different regions. The previous version of the CubicSurfaceExtractor would attempt to handle this automatically, but as a result it was possible to get two quads existing at the same position in space. This can cause problems with transparency and with physics, as well as making it harder to decide which regions need to be updated when a voxel is changed.
|
||||
|
||||
The new system simplifies the behaviour of this surface extractor but does require a bit of care on the part of the user. You should be clear on the rules controlling when quads are generated and to which regions they will belong. To aid with this we have significantly improved the API documentation for the CubicSurfaceExtractor so be sure to have a look.
|
||||
|
||||
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?
|
@ -120,6 +120,90 @@ namespace PolyVox
|
||||
Vector3DFloat m_v3dDirectionAndLength;
|
||||
float m_fMaxDistance;
|
||||
};
|
||||
|
||||
template<typename VolumeType, typename Callback>
|
||||
void raycast(VolumeType* volData, /*const*/ Vector3DFloat/*&*/ v3dStart, const Vector3DFloat& v3dDirectionAndLength, Callback& callback)
|
||||
{
|
||||
VolumeType::Sampler sampler(volData);
|
||||
|
||||
//The doRaycast function is assuming that it is iterating over the areas defined between
|
||||
//voxels. We actually want to define the areas as being centered on voxels (as this is
|
||||
//what the CubicSurfaceExtractor generates). We add (0.5,0.5,0.5) here to adjust for this.
|
||||
v3dStart = v3dStart + Vector3DFloat(0.5f, 0.5f, 0.5f);
|
||||
|
||||
//Compute the end point
|
||||
Vector3DFloat v3dEnd = v3dStart + v3dDirectionAndLength;
|
||||
|
||||
float x1 = v3dStart.getX();
|
||||
float y1 = v3dStart.getY();
|
||||
float z1 = v3dStart.getZ();
|
||||
float x2 = v3dEnd.getX();
|
||||
float y2 = v3dEnd.getY();
|
||||
float z2 = v3dEnd.getZ();
|
||||
|
||||
int i = (int)floorf(x1);
|
||||
int j = (int)floorf(y1);
|
||||
int k = (int)floorf(z1);
|
||||
|
||||
int iend = (int)floorf(x2);
|
||||
int jend = (int)floorf(y2);
|
||||
int kend = (int)floorf(z2);
|
||||
|
||||
int di = ((x1 < x2) ? 1 : ((x1 > x2) ? -1 : 0));
|
||||
int dj = ((y1 < y2) ? 1 : ((y1 > y2) ? -1 : 0));
|
||||
int dk = ((z1 < z2) ? 1 : ((z1 > z2) ? -1 : 0));
|
||||
|
||||
float deltatx = 1.0f / std::abs(x2 - x1);
|
||||
float deltaty = 1.0f / std::abs(y2 - y1);
|
||||
float deltatz = 1.0f / std::abs(z2 - z1);
|
||||
|
||||
float minx = floorf(x1), maxx = minx + 1.0f;
|
||||
float tx = ((x1 > x2) ? (x1 - minx) : (maxx - x1)) * deltatx;
|
||||
float miny = floorf(y1), maxy = miny + 1.0f;
|
||||
float ty = ((y1 > y2) ? (y1 - miny) : (maxy - y1)) * deltaty;
|
||||
float minz = floorf(z1), maxz = minz + 1.0f;
|
||||
float tz = ((z1 > z2) ? (z1 - minz) : (maxz - z1)) * deltatz;
|
||||
|
||||
sampler.setPosition(i,j,k);
|
||||
//m_result.previousVoxel = Vector3DInt32(i,j,k);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(!callback(sampler))
|
||||
{
|
||||
//m_result.foundIntersection = true;
|
||||
//m_result.intersectionVoxel = Vector3DInt32(i,j,k);
|
||||
return;
|
||||
}
|
||||
//m_result.previousVoxel = Vector3DInt32(i,j,k);
|
||||
|
||||
if(tx <= ty && tx <= tz)
|
||||
{
|
||||
if(i == iend) break;
|
||||
tx += deltatx;
|
||||
i += di;
|
||||
|
||||
if(di == 1) sampler.movePositiveX();
|
||||
if(di == -1) sampler.moveNegativeX();
|
||||
} else if (ty <= tz)
|
||||
{
|
||||
if(j == jend) break;
|
||||
ty += deltaty;
|
||||
j += dj;
|
||||
|
||||
if(dj == 1) sampler.movePositiveY();
|
||||
if(dj == -1) sampler.moveNegativeY();
|
||||
} else
|
||||
{
|
||||
if(k == kend) break;
|
||||
tz += deltatz;
|
||||
k += dk;
|
||||
|
||||
if(dk == 1) sampler.movePositiveZ();
|
||||
if(dk == -1) sampler.moveNegativeZ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/Raycast.inl"
|
||||
|
@ -33,11 +33,33 @@ 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.
|
||||
class MyFunctor
|
||||
{
|
||||
public:
|
||||
bool operator()(const SimpleVolume<int8_t>::Sampler& sampler)
|
||||
{
|
||||
if(sampler.getVoxel() > 0)
|
||||
{
|
||||
foundIntersection = true;
|
||||
}
|
||||
return sampler.getVoxel() <= 0;
|
||||
}
|
||||
};
|
||||
|
||||
void TestRaycast::testExecute()
|
||||
{
|
||||
const int32_t uVolumeSideLength = 32;
|
||||
@ -62,20 +84,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);
|
||||
int hits = 0;
|
||||
for(int ct = 0; ct < 1000000; ct++)
|
||||
{
|
||||
RaycastResult result;
|
||||
/*RaycastResult result;
|
||||
Raycast< SimpleVolume<int8_t> > raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, result, isPassableByRay);
|
||||
raycast.execute();
|
||||
if(result.foundIntersection)
|
||||
{
|
||||
hits++;
|
||||
}*/
|
||||
|
||||
foundIntersection = false;
|
||||
MyFunctor myFunctor;
|
||||
raycast(&volData, start, randomUnitVectors[ct % 1024] * 1000.0f, myFunctor);
|
||||
|
||||
if(foundIntersection)
|
||||
{
|
||||
hits++;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Finished in " << timer.elapsed() << "ms" << std::endl;
|
||||
|
||||
//Check the number of hits.
|
||||
QCOMPARE(hits, 687494);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user