Is this sphere-capsule intersection?

Started by
5 comments, last by Narf the Mouse 13 years, 6 months ago
The internet knows not of such a thing, so I took a stab at it, adapting Box-Capsule intersection:
        public static bool Intersects(BoundingSphere boundingSphere, Capsule capsule, out Vector3 point)        {            point = Vector3.Zero;            double halfLength = capsule.Line.Vector.Length() / 2;            Vector3 To = boundingSphere.Center - capsule.Line.MidPoint;            double r1 = boundingSphere.Radius + halfLength * Math.Abs(capsule.Line.Vector.X) + capsule.Radius;            double r2 = boundingSphere.Radius + halfLength * Math.Abs(capsule.Line.Vector.Y) + capsule.Radius;            double r3 = boundingSphere.Radius + halfLength * Math.Abs(capsule.Line.Vector.Z) + capsule.Radius;            if (To.SquaredLength() > (r1 * r1 + r2 * r2 + r3 * r3))                return false;            r1 = boundingSphere.Radius * Math.Abs(capsule.Line.Vector.Z) + boundingSphere.Radius * Math.Abs(capsule.Line.Vector.Y);            r2 = boundingSphere.Radius * Math.Abs(capsule.Line.Vector.Z) + boundingSphere.Radius * Math.Abs(capsule.Line.Vector.X);            r3 = boundingSphere.Radius * Math.Abs(capsule.Line.Vector.Y) + boundingSphere.Radius * Math.Abs(capsule.Line.Vector.X);            double r4 = Math.Sqrt(r1 * r1 + r2 * r2 + r3 * r3);            if (Math.Abs(To.Y * capsule.Line.Vector.Z - To.Z * capsule.Line.Vector.Y) > r4 + capsule.Radius)                return false;            if (Math.Abs(To.X * capsule.Line.Vector.Z - To.Z * capsule.Line.Vector.X) > r4 + capsule.Radius)                return false;            if (Math.Abs(To.X * capsule.Line.Vector.Y - To.Y * capsule.Line.Vector.X) > r4 + capsule.Radius)                return false;            point.X = r1; point.Y = r2; point.Z = r3;            return true;        }
Advertisement
Then it occurred to me that this can be reduced down to the distance between lines and then a radius check:
        public static bool Intersects(BoundingSphere boundingSphere, Capsule capsule, out Vector3 point)        {            double line1Distance, line2Distance;            double distance = Line.distance(                new Line(boundingSphere.Center, boundingSphere.Center),                 capsule.Line,                 out point,                out line1Distance,                 out line2Distance                );            Vector3 capsulePoint = capsule.Line.Point1 + (capsule.Line.Vector * line2Distance);            return distance < boundingSphere.Radius + ((point - capsulePoint).Length() + capsule.Radius);        }

I've never written my own swept intersection code before (even if I got the Line-Line off the internet). Which is why I'm asking for help. :)
I am assuming the sphere and capsule are stationary. They intersect when the distance between the sphere center and the line-segment axis of the capsule is smaller or equal to the sum of sphere radius and capsule radius. So all you really need is a calculator of distance between a point and a line segment.
Quote:Original post by Dave Eberly
I am assuming the sphere and capsule are stationary. They intersect when the distance between the sphere center and the line-segment axis of the capsule is smaller or equal to the sum of sphere radius and capsule radius. So all you really need is a calculator of distance between a point and a line segment.

Thanks for the idea. That would be what I have, then, save that I'm using a line where the two ends are at the same location.
Did I get this right check:
        public static double Distance(            Line line1, Vector3 point,            out Vector3 midpoint, out double lineDistance            )        {            Vector3 pointToLine = point - line1.Point1;            Vector3 toNearestOnLine = Vector3.Dot(pointToLine, Vector3.Normalize(line1.Vector)) *                Vector3.Normalize(line1.Vector);            Vector3 distancePoint = pointToLine - toNearestOnLine;            lineDistance = toNearestOnLine.Length();            midpoint = Vector3.Lerp(point, line1.Point1 + toNearestOnLine, .05);            return distancePoint.Length();        }
Hi,

Just something to keep in mind: the intersection set between a sphere and a capsule is almost never a single point. That is really a degenerate case.
(yeah, sphere-sphere intersection set is also quite complex so its usually not
computed but either approximated or another compromise is done).
-----------------------------He moves in space with minimum waste and maximum joyGalactic Conflict demo reel -http://www.youtube.com/watch?v=hh8z5jdpfXY
Quote:Original post by voguemaster
Hi,

Just something to keep in mind: the intersection set between a sphere and a capsule is almost never a single point. That is really a degenerate case.
(yeah, sphere-sphere intersection set is also quite complex so its usually not
computed but either approximated or another compromise is done).

Thanks for the info. I think, however, for my first attempt at collision physics where I'm seeing success (and not just cramming knowledge into my head until it turns to pudding), I will just get it working and not worry about advanced features like intersections covering an area and not a single point. :)

This topic is closed to new replies.

Advertisement