Sinking Your Shot:
Look at figure 13 to get an idea of the problem and the variables that
we are going to use. The red circle is circle1, the blue one circle2.
They each have a movement vector, movevec1 and movevec2,
and a mass, m1 and m2.
Now that you have determined that your circles collide, you want to have
them bounce off of each other in a realistic manner, taking into account
their relative mass and speed. To solve this, we are going to rely on
some simple laws of physics, specifically the conservation of momentum
and the conservation of energy.
Conservation of Momentum states that the total momentum of the system
before the collision is equal to the total momentum in the system after
the collision. If we represent the momentum of a circle to be P
= M * V, where M is the circles mass and V
is its movement vector, then we can derive the equation:
where v1'and v2' are the movement vectors of circle 1 and 2 respectively
after the collision. Since the second circle gains any momentum lost by
the first, we can represent the difference between the momentums of the
balls before and after by the same vector, deltaP.
here is where the difference between reality and simulation comes into
play. If these two spheres were the rubber balls we all used in gym class
in high school, when they hit they would deform. This deformation would
increase the area where the balls are touching, and some of the energy
would be lost in that deformation. Other amounts of it would be lost in
spin. But in this simulation, we are assuming the balls to be rigid, frictionless,
perfect spheres. A common real-world example of this type might be the
steel balls hanging from a frame that collide with each other to demonstrate
action-reaction; because they are so rigid, very little of their momentum
is lost when they collide, and so when you set one ball swinging it takes
some time for them all to stop.
So in our simulation of perfect rigid spheres, the only transference of
momentum can occur along the single point of contact, as illustrated in
figure 13. Therefore, we can break deltaP into a unit vector N
that points down the line of contact, and a scalar P representing
the magnitude of deltaP. So, if we apply this to the equations
above, we can solve for the new movement vectors of the circles and get:
So, if we
can solve for P, we can calculate the new movement vectors.
Now look back at figure 13, and notice that v1 and v2
can be represented by the sum of two vectors: one that is parallel to
the line along which momentum is exchanged, and one that is perpendicular
to it. Using this information, we can represent v1, v1', v2,
and v2' by:
a1, a2, b1, and b2 are scalars, N
is the same N as mentioned before, and Q is
the normalized vector perpendicular to the line along which momentum is
exchanged and on the same plane as N and the movement vector.
Substituting v1 in equation 1 for the value of v1
in equation 3, and v2 in equation 2 for the value of v2
in equation 3, we get:
since v1' = a1'*N + b1'*Q and v2' = a2'*N + b2'*Q, we can see that
Now we can use the Conservation of Energy to solve for P.
The equation for kinetic energy is:
energy is conserved, the total energy before the collision must equal
the total energy after the collision:
the movement vector as the hypotenuse of a right triangle, we can substitute:
equation 4 for a1', b1', a2' and b2', we get:
that the b1 and b2 terms in equation 7 drop out of the equation. With
an equation in terms of m1, m2, a1, a2, and P,
we have an equation with variables that are either given or can be calculated
from what was given, except for P. So if we solve for P,
we will be able to plug in the known variables, derive P,
and then use P to calculate the new movement vectors. Equation
8 shows equation 7 after solving for P.
So, plugging this into Equations 1 & 2:
Notice that for both v1' and v2' the term
in the () brackets is the same, so you only need to calculate that once.
With that done, you can calculate v1'and v2'.
Now that we've done the math for this, the code to implement the results
is very short and quick. The variable optimizedP in the
code refers to the term in brackets above.
find the normalized vector n from the center of
// circle1 to the center of circle2
Vector n = circle1.center - circle2.center;
// Find the length
of the component of each of the movement
// vectors along n.
// a1 = v1 . n
// a2 = v2 . n
float a1 = v1.dot(n);
float a2 = v2.dot(n);
// Using the optimized
// optimizedP = 2(a1 - a2)
float optimizedP = (2.0 * (a1 - a2)) / (circle1.mass + circle2.mass);
// Calculate v1',
the new movement vector of circle1
// v1' = v1 - optimizedP * m2 * n
Vector v1' = v1 - optimizedP * circle2.mass * n;
// Calculate v1',
the new movement vector of circle1
// v2' = v2 + optimizedP * m1 * n
Vector v2' = v2 + optimizedP * circle1.mass * n;
8 Ball, Corner
These techniques will allow you use spheres with a higher degree of accuracy
than is probably necessary if your spheres are all bounding spheres. Precise
collisions between spheres become important when simulating things likes
pool balls or marbles, or potentially rocks in a landslide. But for spheres
bounding characters, for example, you might not care what angle two colliding
characters would bounce away at. However, parts of these methods are fast
enough to be useful if only to determine that a collision was avoided.
But who knows; using a pumped-up space marine as a cue ball just might
be humorous enough to do…
Special thanks to Dave Baum for his help with collision response.