Sphere vs AABB collision detection test

By , last updated October 8, 2016

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

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 structures:

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.

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

    // Intersection if the distance from center is larger than the radius
    // of the sphere.

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

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>

*