# Is this the simplest Sphere-AABB collision test?

This topic is 5073 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey all, After trying -numerous- possible solutions (most of which didn't work), I finally came up with this to detect a collision between a sphere and an axis aligned bounding box (AABB). The sphere is defined by a center and a radius, and the AABB is defined by a minimum and maxiumum point:
// First, compute the distance between the centers
Vec3 SepAxis = Sphere.Center - AABB.Center;
float Dist = Vec3Length( SepAxis );

// then, find the unit vector that points from the box center to the sphere center
Vec3Normalize( SepAxis );

// divide each component of the unit vector by the maximum component, effectively "normalizing" the unit vector
if( SepAxis.x >= SepAxis.y && SepAxis.x >= SepAxis.z )
SepAxis /= SepAxis.x;
else if( SepAxis.y >= SepAxis.x && SepAxis.y >= SepAxis.z )
SepAxis /= SepAxis.y;
else
SepAxis /= SepAxis.z;

// Now, find the effective radius of the box along the "normalized" unit vector pointing to the sphere
SepAxis.x *= Box.GetWidth() / 2.0f;
SepAxis.y *= Box.GetHeight() / 2.0f;
SepAxis.z *= Box.GetLength() / 2.0f;

if( Dist <= (Sphere.Radius + Vec3Length( SepAxis ) )
Collision true!
else
Collision false


Where the box width is defined as Max.x - Min.x, height is Max.y - Min.y, and length is Max.z - Min.z. This seems to work with some preliminary testing. Is this the most efficient way to perform such a collision check? How does everyone else do it?

##### Share on other sites
I didn't really follow what you do but an easy way for non a continous test is to clamp the sphere center to the AABB boundaries. You get the closest point from AABB to sphere. From there it's rather easy to find if they collide or not.

##### Share on other sites
Hmm, looks reasonable enough. Can't say for sure wether it would work just from a quick read of it, but if it does, it does.

Here's my sphere-AABB test. It's a bit longer, but doesn't have any square roots or divides.

The idea behind it is to look at each of the 3 axes of the box individually to find the closest point on the box to the center of the sphere. Then it's just a distance check.

// Get the center of the sphere relative to the center of the boxVec3 sphereCenterRelBox = Sphere.center - Box.center;// Point on surface of box that is closest to the center of the sphereVec3 boxPoint;// Check sphere center against box along the X axis alone. // If the sphere is off past the left edge of the box, // then the left edge is closest to the sphere. // Similar if it's past the right edge. If it's between // the left and right edges, then the sphere's own X // is closest, because that makes the X distance 0, // and you can't get much closer than that :)if (sphereCenterRelBox.x < -Box.GetWidth()/2.0)    boxPoint.x = -Box.GetWidth()/2.0;else if (sphereCenterRelBox.x > Box.GetWidth()/2.0)    boxPoint.x = Box.GetWidth()/2.0;else    boxPoint.x = sphereCenterRelBox.x;// ...same for Y axisif (sphereCenterRelBox.y < -Box.GetHeight()/2.0)    boxPoint.y = -Box.GetHeight()/2.0;else if (sphereCenterRelBox.y > Box.GetHeight()/2.0)    boxPoint.y = Box.GetHeight()/2.0;else    boxPoint.y = sphereCenterRelBox.y;// ... same for Z axisif (sphereCenterRelBox.z < -Box.GetLength()/2.0)    boxPoint.z = -Box.GetLength()/2.0;else if (sphereCenterRelBox.x > Box.GetLength()/2.0)    boxPoint.z = Box.GetLength()/2.0;else    boxPoint.z = sphereCenterRelBox.z;// Now we have the closest point on the box, so get the distance from // that to the sphere center, and see if it's less than the radiusVec3 dist = sphereCenterRelBox - boxPoint;if (dist.x*dist.x + dist.y*dist.y + distz*dist.z < Sphere.radius*Sphere.radius)    return true;else    return false;

EDIT: Dangit, b34r beat me to it and explained my whole function in one sentence...

##### Share on other sites
Quote:
 Original post by b34rI didn't really follow what you do but an easy way for non a continous test is to clamp the sphere center to the AABB boundaries. You get the closest point from AABB to sphere. From there it's rather easy to find if they collide or not.

seconded. Although this won't quite work if the sphere centre is inside the box. THen you have to do a special case, and find the cosest face to the sphere centre and use that.

simple code. Although it doesn't check if the sphere centre is inside teh box.

Vector ClosestPointOnAABB(Vector Point, CAABBox xBox){    Vector xClosestPoint;    xClosestPoint.x = (Point.x < xBox.Min.x)? xBox.Min.x : (Point.x > xBox.Max.x)? xBox.Max.x : Point.x;    xClosestPoint.y = (Point.y < xBox.Min.y)? xBox.Min.y : (Point.y > xBox.Max.y)? xBox.Max.y : Point.y;    xClosestPoint.z = (Point.z < xBox.Min.z)? xBox.Min.z : (Point.z > xBox.Max.z)? xBox.Max.z : Point.z;    return xClosestPoint;}bool Intersect(CSphere xSphere, CAABBox xBox, Vector& xNcoll, float& fDcoll){    if(xBox.Contains(xSphere.Centre))    {         // Do special code.         // here, for now don't do a collision, until the centre is         // outside teh box         fDcoll = 0.0f;         xNcoll = Vector(0, 0, 0);         return true;    }    // get closest point on box from sphere centre    Vector xClosest = ClosestPointOnAABB(xSphere.Centre, xBox);        // find the separation    Vector xDiff = xSphere.Centre - xClosest;    // check if points are far enough    float fDistSquared = xDiff.GetLengthSquared();    if (fDistSquared > xSphere.RadiusSquared())    {        return false;    }    float fDist = sqrt(fDistSquared);    // collision depth    fDcoll = xSphere.GetRadius() - fDist;       // normal of collision (going towards the sphere centre)    xNcoll = xDiff  / fDist;    return true;    }

• 9
• 16
• 9
• 10
• 16