Exemple #1
0
VOID Bound::Merge( const Bound& Other )
{
    Sphere OtherSphere;
    OtherSphere.Center = Other.GetCenter();
    OtherSphere.Radius = Other.GetMaxRadius();

    if( m_Type == Bound::No_Bound )
    {
        SetSphere( OtherSphere );
        return;
    }

    Sphere ThisSphere;
    if( m_Type != Bound::Sphere_Bound )
    {
        // convert this bound into a sphere
        ThisSphere.Center = GetCenter();
        ThisSphere.Radius = GetMaxRadius();
    }
    else
    {
        ThisSphere = GetSphere();
    }

    XMVECTOR vThisCenter = XMLoadFloat3( &ThisSphere.Center );
    XMVECTOR vOtherCenter = XMLoadFloat3( &OtherSphere.Center );
    XMVECTOR vThisToOther = XMVectorSubtract( vOtherCenter, vThisCenter );
    XMVECTOR vDistance = XMVector3LengthEst( vThisToOther );

    FLOAT fCombinedDiameter = XMVectorGetX( vDistance ) + ThisSphere.Radius + OtherSphere.Radius;
    if( fCombinedDiameter <= ( ThisSphere.Radius * 2 ) )
    {
        SetSphere( ThisSphere );
        return;
    }
    if( fCombinedDiameter <= ( OtherSphere.Radius * 2 ) )
    {
        SetSphere( OtherSphere );
        return;
    }

    XMVECTOR vDirectionNorm = XMVector3Normalize( vThisToOther );

    XMVECTOR vRadius = XMVectorSet( ThisSphere.Radius, OtherSphere.Radius, 0, 0 );
    XMVECTOR vThisRadius = XMVectorSplatX( vRadius );
    XMVECTOR vOtherRadius = XMVectorSplatY( vRadius );
    XMVECTOR vCombinedDiameter = vThisRadius + vDistance + vOtherRadius;
    XMVECTOR vMaxDiameter = XMVectorMax( vCombinedDiameter, vThisRadius * 2 );
    vMaxDiameter = XMVectorMax( vMaxDiameter, vOtherRadius * 2 );
    XMVECTOR vMaxRadius = vMaxDiameter * 0.5f;
    ThisSphere.Radius = XMVectorGetX( vMaxRadius );
    vMaxRadius -= vThisRadius;
    XMVECTOR vCombinedCenter = vThisCenter + vMaxRadius * vDirectionNorm;
    XMStoreFloat3( &ThisSphere.Center, vCombinedCenter );
    SetSphere( ThisSphere );
}
Exemple #2
0
//-----------------------------------------------------------------------------
// Compute the intersection of a ray (Origin, Direction) with an axis aligned 
// box using the slabs method.
//-----------------------------------------------------------------------------
BOOL GLibIntersectRayAxisAlignedBox( FXMVECTOR Origin, FXMVECTOR Direction, const XNA::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(!GLibXMVector3AnyTrue( NoIntersection ) )
	{
		// Store the x-component to *pDist
		XMStoreFloat( pDist, t_min );
		return TRUE;
	}

	return FALSE;
}