# How do I calculate collision response between a sphere and a plane?

I'm trying to create a simple 3D game and need to constrain the player within the limits of the game world. When the player hits the sides of the world I want the player's ship to bounce off slightly.

In effect I'm trying to trap the player within a box, and stop them from escaping through the sides...

I've managed to define the limits of the gameworld as a collection of planes, with normals and distances from the origin. The player has a spherical bounding sphere and from following this website http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.php I have managed to detect collisions.

I now can't quite work out what to do when a collision is detected. The best I can manage is the player getting stuck in the plane, going straight through it, or bouncing repeatedly off it at a really fast rate.

Common sense tells me I need to calculate the reflected angle off the plane, using its normal and apply that to the player's velocity, however I think I need to first see if the player has gone through the plane which is the bit I can't work out.

You'll have to apply an impulse to your object, which is an immediate change in it's velocity. In the real world, a powerful force would be applied to the object over a very short timestep, reversing its acceleration and causing its velocity to change. However, since we're working in a discrete world, we have to cheat a bit to simulate this abrupt change in direction. For a sphere and a plane, it's pretty straightforward. The most basic collision response is to reflect the sphere's velocity around the plane's normal, and then the result is the sphere's new velocity. Pseudo-code would look something like this:

reflected = 2 * plane.normal * (plane.normal * sphere.velocity)
sphere.velocity -= reflected


From there, you can add some damping (multiply by some coefficient, like 0.9) to account for energy lost to heat or friction. If you want to get angular velocity involved (perhaps your sphere is rotating), then the equations get a little more complicated.

For more info, I'll refer you to Chris Hecker's articles on Rigid Body Dynamics. If you haven't heard of Chris Hecker before, he's well known for game physics as well as his work on the procedural character generation and animation in Spore.

• This is essentially the right way to go, however calculating the time of impact (TOI) can make things more accurate as framerates fluctuate or drop. Knowing, based on current velocity, how long ago the impact occurred can help you calculate a time of impact, and using that you can move the sphere back to its position at the moment of impact and adjust velocity from there. After adjusting position and velocity from the point of impact, at the time of impact, you then move along the new velocity by the amount of time you subtracted to get to the TOI. Feb 14 '12 at 5:20
• OK this seems to mostly work, but it's a bit ... strange. I think I might be doing this at the wrong point in my code. Should I loop through all my objects and test if they're going to collide before I move them (based on where they're going to be next frame) or move them and then test for collisions afterwards?
– Piku
Feb 14 '12 at 17:45
• @Piku, no don't detect if they will collide. If a collision happens remember there is a very good chance the two objects are now overlapping far beyond where the actual collision would have occurred. You essentially need to figure out where the collision occurred as if you have infinite framerate (which you don't) and move the object back to the position where the collision would have initially occurred. If you do not separate the objects like this you will continually react to the same collision and the object will get stuck. Mar 15 '12 at 11:58
• @Piku and to do that we figure out the time in the past where the collision occurred (called TOI/time of impact). Once we have that we can use the velocity of the object to move it back (distance = speed * time, usually with a extra tiny distance to avoid error) and then update its velocity to what the collision result is. Mar 15 '12 at 12:01
• @Piku also we don't figure out where we will be in the next frame (I have never seen that done personally), but, generally, we do collision detection and response: AFTER we calculate the new position for THIS frame, but BEFORE we apply the new position for THIS frame. Mar 15 '12 at 12:04

F = ma, or a = F/m. Calculate the collision point between the sphere and plane. This is usually Sphere centre - normal* radius. If you want more accuracy, calculate how far the sphere has penetrated the plane, and adjust your calculation. This is largely optional of course, unless you want really accurate physics. Now calculate the relative velocity along the normal. For a static plane this is: Vball Dot N. Then Multiply VballDotN by -1, and multiply by mass. In physics at this stage you would also multiply this by the coefficient of restitution (bounce factor). Multiply this scalar by N and you have your force.

When adjusting Vball, divide the force by mass again and you have the final acceleration, so just add this to the velocity and you have your final post collision velocity.

vec3 Vrel = Ball.getVelocity();
float vDotN = Vrel.Dot(CollisionNormal);
vec3 F = -(1.0f+Ball.getRestitution())*vDotN;
F*=Ball.getMass();
Ball.accelerate(F/Ball.getMass());


This method is accurate to the formulae of collision response. If you want even more accuracy, you will want to take friction into account, which will cause the ball to spin, but I don't know if you want that in your game. In case you do, this is how you calculate the tangential force:

vec3 Ft = -(Ball.getvelocity()+(vDotN*CollisionNormal));
Ft*=Ball.getKineticFriction()+Wall.getKineticFriction(); //you could fudge these numbers
Ft*=Ball.getMass();
vec3 vec2Centre = Ball.getPosition()-ContactPoint;
vec3 Torque = cross(vec2Centre,Ft);
Ball.AngularAccelerate(Torque/Ball.getMomentofInertia(glm::normalize(Torque)));


Make sure to calculate Ft before applying any linear effects, or the friction won't be accurate.

• Shouldn't line 3 be: vec3 F = -CollisionNormal * (1.0f+Ball.getRestitution())*vDotN;? Jan 3 '17 at 3:18
• Indeed yes, I missed that part. Thanks for pointing it out. Mar 24 '17 at 4:02

I would suggest calculating you distance from plane first; and then when the distance <= to the radius carry out the collision reaction.

You can then alter this to calculate distance and if the distance is less that radius( which mean the object is overlapping) shift the balls position and then carry out the collision reaction.