leatherback wrote:As the mass of a ball is the result of the volume of that sphere,
Well, it depends on the density too - I figure it would be easier to regard them as independent properties. But here are some notes I knocked together.
Two balls; I'll call them A and B. (I have a very good imagination.)
Ball A has a mass "ma", a radius "ra", a position "pa" represented in Cartesian coordinates as "pxa" and "pya", and finally a velocity "va" which is also represented by its Cartesian components.
Ball B has similar labels.
First thing to do is decide whether or not the two balls are in collision. If they're not colliding there's nothing to do. This will happen if the distance between the centres of the two balls is not more than the sum of their radii. (Ideally, if the collisions are purely elastic, you never want it to be less, but roundoff and model resolution errors may cause the balls to overlap slightly.)
For performance's sake, calculate the square of the two distances involved: if s and t are nonnegative (as distances are wont to be), then if s<t then sqrt(s)<sqrt(t). Only take the square root (you'll only need one of them) when you've decided you need it.
I'm going to call the distance sqrt((pxa-pxb)2+(pya-pyb)2) between the two balls' centres "d". If they're not colliding, d>ra+rb; if just touching, then d=ra+rb. If they're overlapping, d<ra+rb and we need to model the collision we just missed and tweak them apart. It's not physically kosher, but it wasn't physically kosher to allow them to overlap in the first place. We'll just move them away from each other by half the amount of overlap each. With luck the visible magnitude of the fraud will be less than a pixel. I guess it's not strictly necessary to do this bit, but we'll be using dpx and dpy quite a bit later, so seeing as we need them anyway:
$overlap = $ra + $rb - $d;
$dpx = ($pxb - $pxa)/$d;
$dpy = ($pyb - $pya)/$d;
$pxa -= $dpx*$overlap/2;
$pya -= $dpy*$overlap/2;
$pxb += $dpx*$overlap/2;
$pyb += $dpy*$overlap/2;
Now for the juicy stuff. dpx and dpy represent a change of position - a direction. To be precise, it's the direction to move in to get from the centre of A to the centre of B. This is call the "axis of collision" and all the action will be happening there; the axis of collision passes through the point where the balls touch and this of course is where all the exchange of momentum happens. At right angles to the axis at this point you can imagine a second line that represents the "wall" the two balls are bouncing off of. The wall may only consist of one point on the surface of the other ball, but one point of contact is all we have with the wall anyway.
Ultimately it boils down to the conservation of two quantities: momentum and kinetic energy. The momentum of the system beforehand is mava+mbvb before the collision and ma'va'+mb'vb' afterward. Since the masses don't change ma=ma' and mb=mb'. The kinetic energy of the system before the collision is (ma*va2)/2+(mb+vb2)/2, and that equals the kinetic energy afterwards - by the definition of "elastic collision".
Let's say for the moment that B is stationary and that A is doing all the moving before the collision.
mava = mava' + mbvb' (conservation of momentum)
and
(mava2)/2 = (mava' + mbvb2)/2 (conservation of kinetic energy)
Which can each be rearranged as
ma(va - va') = mbvb'
and
ma(va - va')(va + va') = mbvb'
respectively.
Dividing one by the other and a bit of tidying up we have
va' = va(ma - mb)/(ma + mb)
vb' = va(ma + ma)/(ma + mb)
The new velocities of A and B.
That was if B started out at rest, though. What if it had been moving? Well, the momentum and energy transfers will be the same as if B were not moving and A's initial velocity had been its own less B's. In effect we shift to a new coordinate system that's tracking B's motion; afterwards we shift back again by adding B's initial velocity back in to both final velocities.
All that was working with the velocity vectors va and vb directly, though, rather than their x and y components (vxa, vya, vxb and vyb). Fortunately, that principle that the angle of incidence equals the angle of reflection applies: it means that all the action happens along that axis. Any movement that is perpendicular to the axis is unchanged.
$vca = $vxa*$dpx + $vya*$dpy;
$vcb = $vxb*$dpx + $vyb*$dpy;
Now everything is happening along the axis of collision; the two dimensional problem has been reduced to a one-dimensional one, and those velocity vectors we were working with a moment ago are now just ordinary numbers. Noting the shifting of coordinate systems above, and (because we'll actually want the change in velocity) subtracting the initial velocities:
$dva = ($vca*($ma - $mb) + 2*$vcb*$mb)/($ma + $mb) - $vca;
$dvb = ($vcb*($mb - $ma) + 2*$vca*$ma)/($ma + $mb) - $vcb;
And finally rotate back into the original X-Y system:
$vxa += $dva*$dpx;
$vya += $dva*$dpy;
$vxb += $dvb*$dpx;
$vyb += $dvb*$dpy;
If you have N balls numbered [0..N-1], you'd loop A from [0..n-2] and inside that loop B from [A+1..n-1]. That way you'll compare each distinct pair of balls precisely once. Possibly you might want to store each ball's changes in velocity (there shouldn't be that many unless things are really crowded) in a separate array and then add them all to the initial velocities after they've all been calculated.