Simple Sphere-Sphere Collision Detection and Collision Response

By , last updated April 23, 2017
ldv

Collision Detection

To determine if two spheres are colliding, we take the sum of the radiuses and compare it with the length from the centers of the spheres. If the length is smaller than the sum of the radiuses, we have a collision.

The difference vector (the length is the distance between those two spheres):
vec{d} = s1.pos - s2.pos

Then the length is computed:
distance = vec{d}.length = sqrt{vec{d}.x^2 + vec{d}.y^2 + vec{d}.z^2}

Sum of the radiuses:
sumradius = s1.radius + s2.radius

If distance < sumradius the we have a collision to take care of. This is an example of an elastic collision detection. More advanced algorithm includes calculations of collision time and direction.

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

Collision Response

This is a little bit trickier, but with some basics explained, it should be pretty straight forward.

First, find the vector which will serve as a basis vector (x-axis), in an arbitrary direction. It has to be normalized to get realistic results.

vec{x} = s1.pos - s2.pos
vec{x}.normalize()

Then we calculate the x-direction velocity vector and the perpendicular y-vector.
vec{v1} = s1.vel
x1 = x.dot(vec{v1})
vec{v1x} = vec{x} * x1
vec{v1y} = vec{v1} - vec{v1x}
m1 = s1.mass

Same procedure for the other sphere.
vec{x} = vec{x}*-1
vec{v2} = s2.vel
x2 = vec{x}.dot(vec{v2})
vec{v2x} = vec{x} * x2
vec{v2y} = vec{v2} - vec{v2x}
m2 = s2.mass

Then we mix and play around with some of Newton’s laws to obtain a formula for the speed (in vector format) after the collision.
s1.vel = vec{v1x}{(m1-m2)/(m1+m2)} + vec{v2x}{(2*m2)/(m1+m2)} + vec{v1y}
s2.vel = vec{v1x}{(2*m1)/(m1+m2)} + vec{v2x}{(m2-m1)/(m1+m2)} + vec{v2y}

And it actually works! 🙂

Sample application:

Source code in subversion repository.

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

Comments

  1. Marco January 6, 2009 Leave a Reply

    I was looking for a clear tutorial on collision response and i found it here.
    great post, very usefull!

    Thanks

  2. Jonas September 15, 2009 Leave a Reply

    I had to refresh my dusty brain, and this was perfect for that!

    Thanks!

  3. Edgar October 29, 2009 Leave a Reply

    This information was very usefull in a demo that i’m trying to build in XNA. Thanks

  4. Niklas Rother July 31, 2010 Leave a Reply

    I tried to adapt this in C#/XNA, but it seems that there is a mistake: x is a Vector3 (Vector with 3 Components) and v1 also. So x.dot(v1) is a float (scalar/normal number). But in the line you use the Cross product (or am I wrong?), and you can´t make a Crossproduct of a Vector3 (x) and a float (x1).
    Additional the SVN link seems down, so I couldt check the code…

  5. kent August 4, 2010 Leave a Reply

    Niklas: I think it should be “vector multiplied by a scalar”, not cross product.

    This goes without checking the code, which I’ll do later when I fix the repository.

  6. kent August 15, 2010 Leave a Reply

    @Niklas

    I have fixed the websvn interface (and svn interface).

  7. Nick Wiggill November 21, 2010 Leave a Reply

    This doesn’t actually appear to work when one of the circle-bodies is stationary — it will not impart any forces in this instance, at least in my use of this code.

  8. Nick Wiggill November 21, 2010 Leave a Reply

    No — ignore my prior comment — I am mistaken. There is something other bug in my application of your code.

  9. Nick Wiggill November 22, 2010 Leave a Reply

    I had issues with my vector rotation code. Your approach works fine. Many thanks.

  10. kent November 23, 2010 Leave a Reply

    @Nick

    I’m glad you found this useful!

    Thanks.

  11. Robert January 28, 2011 Leave a Reply

    Super! All I need to to calculate the two angles that describe how to draw the line between sphere centers.. Can you help me there? How do I correctly write the code to get the two angles?

  12. Chris March 23, 2011 Leave a Reply

    A very nice tutorial for the collision response between two spheres. Unfortunately it doesn’t hold up when more than two spheres can collide at once.

    Although I suppose the solution for that is seperate to this tutorial as you just figure out which collision occurs first in the current frame and then push the physics simulation back and forwards through the frame until all collisions have been resolved.

  13. Elena March 25, 2011 Leave a Reply

    Hi,

    This helped a lot! I have been tormenting myself with books and other theoretical stuff for four days now and without any results. I still have a question. Does this work even when one object is stationary?

  14. Julian May 31, 2011 Leave a Reply

    Thanks! I’ve been looking for a nice and clear tut and i finally found it! You’re awesome!

  15. pw September 7, 2011 Leave a Reply

    great stuff. have converted this to c# xna with little much to change. x.dot() is vector3.dot(x,v1) and the final 2 lines omit the vector3 bracket: s1.Velocity = v1x…blah;

  16. aram January 26, 2012 Leave a Reply

    hi
    i’m trying to write code of a game named peggle,maby you know it.
    now i want to have collision functoin in my code & i hope you help me for that problem.
    if it is possible for you send methis code as E-mail;
    thank you…….!!!!!!!!

  17. kent February 1, 2012 Leave a Reply

    aram: you can see the source code in subversion repository (link at the end of the article)

  18. AAS November 17, 2013 Leave a Reply

    ThankYou! That logic for collision was very helpful.

  19. Ghassan February 13, 2014 Leave a Reply

    Thank You, but i have a question. Is that elastic or inelastic collision ??? and what’s the difference between them in equations ??

  20. kent February 17, 2014 Leave a Reply

    This is an elastic collision. If you want inelastic, you would have to multiply the collision response with a number somewhere between 0.0 and up to 1.0.

  21. MXXIV April 12, 2016 Leave a Reply

    This actually doesn’t work. Heavy ball bounces off small ball. Also, the collision is hyper elastic. If you make row of balls and hit it with ball from one side, it acts as particle accelerator.

  22. TheRabbidLemming September 16, 2016 Leave a Reply

    Great first steps into the topic. Thanks. Now to calculate for balls colliding with other balls! lol

  23. Sean June 24, 2017 Leave a Reply

    I’m just considering spheres but if you are dealing with a lot of them (for example snooker) then how does a physics engine choose the order of testing, baring in mind that in a single itteration, a ball could have collided with more than one ball.
    The point is, I’ve yet to see a physics engine that addresses this issue totally.
    Back in the 80s, a snooker game came out for the Amiga and ST.
    Cleverly, the programmer animated the cue moving backwards and forwards several times to emulate someone mentally preparing to take the shot.
    Of course, in reality, the 8MHz 68000 was precalculating all of the physics – it took several seconds.
    Can it really be the case that this arcaine knowledge has been lost?

  24. Kent Fagerjord June 24, 2017 Leave a Reply

    Hi Sean.

    It’s been a while since i studied a physics engine, but they would partition adjacent objects and run a simulation among those to speed up calculations.

    For games with many spheres / objects touching, special consideration should be taken, or else it would be jittery. One way is to preserve the absolute kinetic energy before and after. In a system, the kinetic energy can not increase unless there are external forces applied.

    For the snooker game, it’s only 2D. It would then be circles. And a circle is only a point with a radius. It would simplify the physics calculations a lot. But for a snooker game from the 80s, the main selling point would be the feeling of playing snooker, not real life physics.

    There are also numerical methods like Runge-Kutta to get a better approximation of the moving bodies.

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>

*