28

If (for the purpose of collision detection) 3D objects are represented in a game by spheres, what is a good algorithm to detect a collision between spheres?

If each object has a position as of the last frame and a new (desired) position, what is a good algorithm that will identify collisions where the spheres didn't intersect in the previous frame, and they may not intersect in the second frame, but they did intersect somewhere in between?

kevin42
  • 4,506
  • 6
  • 27
  • 33
  • Here's another nice Gamasatura article. – Mateen Ulhaq Aug 27 '11 at 00:35
  • There is [article about deriving collision detection with math on Flipcode][1]. It has circle-cirle. There is how to detect precisely the point of collision and check if there is a collision at all. [1]:http://www.flipcode.com/archives/Theory_Practice-Issue_01_Collision_Detection.shtml – user712092 Jul 04 '11 at 15:39

6 Answers6

19

Basically you're looking for a trace.

This page will probably help you: http://www.realtimerendering.com/intersections.html

Moving Sphere/Sphere: (location) Add the radius of the moving sphere to the static sphere, and treat the moving sphere as a ray. Use this ray to perform ray/sphere intersection. See Gomez; Schroeder for code (article has bug in derivation, code is fine); and RTR2, p. 622.

Tetrad
  • 30,124
  • 12
  • 94
  • 143
  • 1
    That doesn't work if both spheres move, (not even if you do it twice). Seems to me that you'd have to first do a distance check between the lines spanning movement a and the one spanning movement b, and if that is less than radius a + radius b you have a possible collision. After that I would do a check to see where that point is in time for sphere a and where for sphere b to see if the times are close. If so I'd check speed against distance in time for that point, if it's still a possible collision I'd do a stepwise refinement. – Kaj Aug 19 '10 at 07:02
  • 18
    Actually it does, you just have to make the movement relative. So if both spheres are moving you just subtract the velocity of one of the spheres from both of them so you have one "moving" sphere and one "stationary" sphere. Then you can use the above. – Tetrad Nov 23 '10 at 17:37
8

Use a sweep test as demonstrated in this Gamasutra article. (Or the port to gamedeveloper.com...)

Vaillancourt
  • 16,325
  • 17
  • 55
  • 61
Firas Assaad
  • 3,544
  • 2
  • 32
  • 26
5

Off the top of my head:

  1. Create two line segments from the middle of each circle from where it started to where it moved to in that time step.
  2. Find the min distance between those two line segments; as is explained here.
  3. If that distance is less than or equal to the radius of the first circle plus the second then they collided; otherwise they did not.

And that is all there is to it, I would expect that to be pretty fast.

3

Answers here well explained the concept, but seems code answer was not posted yet:

// predicts collision time between two moving objects
// objects are spheres moving in 3D space with constant velocities
// returns PositiveInfinity if collision will never happen

float GetCollisionTime(WorldObject a, WorldObject b) { // relative velocity and position var rel_v = a.Velocity - b.Velocity; var rel_pos = a.Position - b.Position;

float start_dist_squared = rel_pos.LengthSquared();
double need_dist_squared = M.Pow(a.Radius + b.Radius, 2);

// skip if already collide
if (start_dist_squared <= need_dist_squared)
    return 0;

float rel_dot = Vector3.Dot(rel_pos, rel_v);
float rel_v_squared = rel_v.LengthSquared();

// skip if they move away
if (rel_dot > 0 || rel_v_squared == 0)
    return float.PositiveInfinity;

float min_dist_t = -rel_dot / rel_v_squared;
float min_dist_squared = (rel_pos + rel_v * min_dist_t).LengthSquared();

// skip if they never touch
if (min_dist_squared > need_dist_squared)
    return float.PositiveInfinity;

double collide_dist_to_min_squared = need_dist_squared - min_dist_squared;
float collide_t_before_min = (float)M.Sqrt(collide_dist_to_min_squared / rel_v_squared);

return min_dist_t - collide_t_before_min;
}

Squared distances are used only to optimize out slow root calculations.

halt9k
  • 131
  • 3
0

Collision detection for moving object is typically called "Swept volume calculation", here are some codes / articles about this subject.

http://www.gpu-voxels.org/demos/ (Demo)

Source code libraries:

https://github.com/fzi-forschungszentrum-informatik/gpu-voxels

https://libigl.github.io/tutorial/#swept-volume

https://github.com/gradientspace/geometry3Sharp

Articles:

http://gamma.cs.unc.edu/SV/sm03.pdf

https://www.cs.columbia.edu/~allen/PAPERS/abrams.swept.pdf (No source code unfortunately)

http://www.realtimerendering.com/intersections.html (Rather heavy collection of links)

TarmoPikaro
  • 109
  • 3
-3

Speaking as someone who's done this: it's not worth the hassle. Unless your game design absolutely needs it, and it almost certainly doesn't, you'll spend far more effort getting sweeping working than you really expect. And it will be slower than you wanted it to be.

ZorbaTHut
  • 11,580
  • 1
  • 37
  • 44