https://www.siggraph.org/education/mate ... inter3.htm
Algorithm is quite simple, requires a little geometry. Anyways, after I understood the algorithm mentioned in the link, I wanted to see an implementation of this and since the book uses the XNA collision library (which doesn't exist anymore since XNA became DirectXMath), I decided to take a look at the XNA::IntersectRayAxisAlignedBox() method. I'm trying to decipher this shit and I'm having difficulty understanding some parts of it.
This is the function :
Code: Select all
//-----------------------------------------------------------------------------
// Compute the intersection of a ray (Origin, Direction) with an axis aligned
// box using the slabs method.
//-----------------------------------------------------------------------------
BOOL IntersectRayAxisAlignedBox( FXMVECTOR Origin, FXMVECTOR Direction, const AxisAlignedBox* pVolume, FLOAT* pDist )
{
XMASSERT( pVolume );
XMASSERT( pDist );
XMASSERT( XMVector3IsUnit( Direction ) );
static const XMVECTOR Epsilon =
{
1e-20f, 1e-20f, 1e-20f, 1e-20f
};
static const XMVECTOR FltMin =
{
-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX
};
static const XMVECTOR FltMax =
{
FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX
};
// Load the box.
XMVECTOR Center = XMLoadFloat3( &pVolume->Center );
XMVECTOR Extents = XMLoadFloat3( &pVolume->Extents );
// Adjust ray origin to be relative to center of the box.
XMVECTOR TOrigin = Center - Origin;
// Compute the dot product againt each axis of the box.
// Since the axii are (1,0,0), (0,1,0), (0,0,1) no computation is necessary.
XMVECTOR AxisDotOrigin = TOrigin;
XMVECTOR AxisDotDirection = Direction;
// if (fabs(AxisDotDirection) <= Epsilon) the ray is nearly parallel to the slab.
XMVECTOR IsParallel = XMVectorLessOrEqual( XMVectorAbs( AxisDotDirection ), Epsilon );
// Test against all three axii simultaneously.
XMVECTOR InverseAxisDotDirection = XMVectorReciprocal( AxisDotDirection );
XMVECTOR t1 = ( AxisDotOrigin - Extents ) * InverseAxisDotDirection;
XMVECTOR t2 = ( AxisDotOrigin + Extents ) * InverseAxisDotDirection;
// Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't
// use the results from any directions parallel to the slab.
XMVECTOR t_min = XMVectorSelect( XMVectorMin( t1, t2 ), FltMin, IsParallel );
XMVECTOR t_max = XMVectorSelect( XMVectorMax( t1, t2 ), FltMax, IsParallel );
// t_min.x = maximum( t_min.x, t_min.y, t_min.z );
// t_max.x = minimum( t_max.x, t_max.y, t_max.z );
t_min = XMVectorMax( t_min, XMVectorSplatY( t_min ) ); // x = max(x,y)
t_min = XMVectorMax( t_min, XMVectorSplatZ( t_min ) ); // x = max(max(x,y),z)
t_max = XMVectorMin( t_max, XMVectorSplatY( t_max ) ); // x = min(x,y)
t_max = XMVectorMin( t_max, XMVectorSplatZ( t_max ) ); // x = min(min(x,y),z)
// if ( t_min > t_max ) return FALSE;
XMVECTOR NoIntersection = XMVectorGreater( XMVectorSplatX( t_min ), XMVectorSplatX( t_max ) );
// if ( t_max < 0.0f ) return FALSE;
NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( XMVectorSplatX( t_max ), XMVectorZero() ) );
// if (IsParallel && (-Extents > AxisDotOrigin || Extents < AxisDotOrigin)) return FALSE;
XMVECTOR ParallelOverlap = XMVectorInBounds( AxisDotOrigin, Extents );
NoIntersection = XMVectorOrInt( NoIntersection, XMVectorAndCInt( IsParallel, ParallelOverlap ) );
if( !XMVector3AnyTrue( NoIntersection ) )
{
// Store the x-component to *pDist
XMStoreFloat( pDist, t_min );
return TRUE;
}
return FALSE;
}
Like this, kind of :
If the v is not a unit vector then the projected vector u is given with a slightly different method. Anyways, getting off topic here.
Question is : What are these lines of code accomplishing to do ?
Code: Select all
// Compute the dot product againt each axis of the box.
// Since the axii are (1,0,0), (0,1,0), (0,0,1) no computation is necessary.
XMVECTOR AxisDotOrigin = TOrigin;
XMVECTOR AxisDotDirection = Direction;
Code: Select all
// Test against all three axii simultaneously.
XMVECTOR InverseAxisDotDirection = XMVectorReciprocal( AxisDotDirection );
XMVECTOR t1 = ( AxisDotOrigin - Extents ) * InverseAxisDotDirection;
XMVECTOR t2 = ( AxisDotOrigin + Extents ) * InverseAxisDotDirection;
I managed to understand the other parts of it but I'm stuck on these two. Does anybody have an idea ?
EDIT : By the way XNA Collision library is under Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\C++\Misc\Collision