Sphere vs AABB collision detection test

By , last updated April 23, 2017

As the sphere is being the simplest primitive there is, the test for Sphere and AABB intersection is easy. This solution works also for Sphere Cube intersection tests.

Given the following C++ structures of Point, cube (AABB) and a Sphere:

struct Point
{
    Point() {}
    Point( double x, double y, double z )
        : x(x)
        , y(y)
        , z(z)
    {}
    double x = 0.0;
    double y = 0.0;
    double z = 0.0;
    double w = 0.0;
};

struct AABB
{
    AABB() : min(), max() {}
    AABB( const Point & min, const Point & max )
        : min(min)
        , max(max)
    {}

    Point min;
    Point max;
};

struct Sphere
{
    Sphere() : center(), radius() {}
    Sphere( const Point & center, double radius )
        : center(center)
        , radius(radius)
    {}

    Point center;
    double radius = 0;
};

And this test for determining the closest Point on AABB to a certain Point.

double SquaredDistPointAABB( const Point & p, const AABB & aabb )
{
    auto check = [&](
        const double pn,
        const double bmin,
        const double bmax ) -> double
    {
        double out = 0;
        double v = pn;

        if ( v < bmin ) 
		{             
			double val = (bmin - v);             
			out += val * val;         
		}         
		
		if ( v > bmax )
        {
            double val = (v - bmax);
            out += val * val;
        }

        return out;
    };

    // Squared distance
    double sq = 0.0;

    sq += check( p.x, aabb.min.x, aabb.max.x );
    sq += check( p.y, aabb.min.y, aabb.max.y );
    sq += check( p.z, aabb.min.z, aabb.max.z );

    return sq;
}

This test becomes easier. There is an intersection if the distance from center is larger than the radius of the sphere.

// True if the Sphere and AABB intersects
bool TestSphereAABB( const Sphere & sphere, const AABB & aabb )
{
    double squaredDistance = SquaredDistPointAABB( sphere.center, aabb );

    return squaredDistance <= (sphere.radius * sphere.radius);
}

Related:
Simple AABB vs AABB collision detection
Simple Sphere-Sphere collision detection

Here is a test program testing the algorithm.

int main()
{
    // AABB
    AABB aabb( Point(-1, -1, -1), Point(1,1,1) );

    // Sphere 1 in the center with radius 1
    Sphere s1( Point(0, 0, 0), 1 );

    // Sphere 2 at x=1 with radious 1
    Sphere s2( Point(1, 0, 0), 1 );

    // Sphere 3 at x=3 with radious 1
    Sphere s3( Point(3, 0, 0), 1 );

    bool t1 = TestSphereAABB( s1, aabb );
    bool t2 = TestSphereAABB( s2, aabb );
    bool t3 = TestSphereAABB( s3, aabb );

    std::cout << " Test 1 " << ( t1 ? "succeeded" : "failed" ) << std::endl;
    std::cout << " Test 2 " << ( t2 ? "succeeded" : "failed" ) << std::endl;
    std::cout << " Test 3 " << ( t3 ? "succeeded" : "failed" ) << std::endl;



    return 0;
}

The output should then be:

 Test 1 succeeded
 Test 2 succeeded
 Test 3 failed

All code is published at Github.

Professional Software Developer, doing mostly C++. Connect with Kent on Twitter.

Comments

Be the first to comment.

Leave a Reply


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*