The way i see it, one finds the closest feature to a minimum ray bound, clips the ray with the result, and continues searching until the minimum bound:
* goes beyond the ray
* passes the convex shape
* gets within a tolerance to the shape
For the most part my implementation works.
In one test case, i have two lumpy convex hulls (rocks) overlapping each other and i cast a ray straight down into the intersection region.
Depending on the result, i move the ray up and down to be a fixed distance away from the intersection pt. (Basic raycast character behavior)
What i'm seeing is that the intersection results differ depending on the starting height of the ray. In one frame it will find rock A and move the ray up.
Then it misses rock A and finds rock B and moves the ray down. This oscillates back and forth every frame.
I suspect that the order of terminations conditions or another simple mistake was made. Any suggestions?
void tGJKRaycast::fCompute( )
{
const f32 cTolerance = 0.001f;
const f32 cToleranceSqr = cTolerance * cTolerance;
tVec3f lastNormal = tVec3f::cYAxis;
b32 hasStepped = false;
mIntersects = false;
mT = 0.f;
mRaySupport->mCenter = mRay.fEvaluate( mT );
mGJK.fReset( );
while( 1 )
{
mGJK.fResume( );
mGJK.fCompute( );
if( !hasStepped && mGJK.fIntersects( ) )
{
// origin is contained
// miss
return;
}
// points from shape to ray.
tVec3f diff = mRaySupport->mCenter - mGJK.fClosestPtA( );
if( diff.fLengthSquared( ) < cToleranceSqr )
{
mIntersects = true;
mNormal = lastNormal;
mPoint = mGJK.fClosestPtA( );
mT = fClipRay( mRay, lastNormal, mGJK.fClosestPtA( ) );
return;
}
if( diff.fDot( mRay.mExtent ) >= -cEpsilon )
{
//clip plane and ray are either coplanar or facing the same direction.
// miss.
return;
}
hasStepped = true;
lastNormal = diff;
lastNormal.fNormalize( );
// plane on convex shape.
mT = fClipRay( mRay, lastNormal, mGJK.fClosestPtA( ) );
if( mT > 1.f )
{
// beyond ray length.
// miss
return;
}
mRaySupport->mCenter = mRay.fEvaluate( mT );
}
}
My tolerance is 0.001f but any smaller number exhibits the same behavior.
mRaySupport is just a point support mapping, containing the location of the current minimum bound location.