I am trying to write a simple physics simulation where balls with varying radii and masses bounce around in a perfectly elastic and frictionless environment. I wrote my own code following this resource: http://www.vobarian.com/collisions/2dcollisions2.pdf and I also tested the code from here: Ball to Ball Collision - Detection and Handling
QUESTION EDITED
With the help of Rick Goldstein and Ralph, I have gotten my code to work (there was a typo..). Thanks so much for you help. However I am still confused as to why the other algorithm isn't working for me. The balls bounce off in the correct directions, but the total energy of the system is never conserved. The velocities get faster and faster until the balls just start blinking in static positions on the screen. I actually want to use this code in my program, because it is a lot more concise than the one I wrote.
Here is the functional algorithm that I wrote (although I did take the first bit from that other source). Its in a Bubble class:
public void resolveCollision(Bubble b)
{
// get the minimum translation distance
Vector2 delta = (position.subtract(b.position));
float d = delta.getMagnitude();
// minimum translation distance to push balls apart after intersecting
Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / b.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
b.position = b.position.subtract(mtd.multiply(im2 / (im1 + im2)));
//get the unit normal and unit tanget vectors
Vector2 uN = b.position.subtract(this.position).normalize();
Vector2 uT = new Vector2(-uN.Y, uN.X);
//project ball 1 & 2 's velocities onto the collision axis
float v1n = uN.dot(this.velocity);
float v1t = uT.dot(this.velocity);
float v2n = uN.dot(b.velocity);
float v2t = uT.dot(b.velocity);
//calculate the post collision normal velocities (tangent velocities don't change)
float v1nPost = (v1n*(this.mass-b.mass) + 2*b.mass*v2n)/(this.mass+b.mass);
float v2nPost = (v2n*(b.mass-this.mass) + 2*this.mass*v1n)/(this.mass+b.mass);
//convert scalar velocities to vectors
Vector2 postV1N = uN.multiply(v1nPost);
Vector2 postV1T = uT.multiply(v1t);
Vector2 postV2N = uN.multiply(v2nPost);
Vector2 postV2T = uT.multiply(v2t);
//change the balls velocities
this.velocity = postV1N.add(postV1T);
b.velocity = postV2N.add(postV2T);
}
And here is the one that doesn't work
public void resolveCollision(Bubble b)
{
// get the minimum translation distance
Vector2 delta = (position.subtract(b.position));
float d = delta.getMagnitude();
// minimum translation distance to push balls apart after intersecting
Vector2 mtd = delta.multiply(((getRadius() + b.getRadius())-d)/d);
// resolve intersection --
// inverse mass quantities
float im1 = 1 / getMass();
float im2 = 1 / b.getMass();
// push-pull them apart based off their mass
position = position.add(mtd.multiply(im1 / (im1 + im2)));
b.position = b.position.subtract(mtd.multiply(im2 / (im1 + im2)));
// impact speed
Vector2 v = (this.velocity.subtract(b.velocity));
float vn = v.dot(mtd.normalize());
// sphere intersecting but moving away from each other already
if (vn > 0.0f) return;
// collision impulse (1f is the coefficient of restitution)
float i = (-(1.0f + 1f) * vn) / (im1 + im2);
Vector2 impulse = mtd.multiply(i);
// change in momentum
this.velocity = this.velocity.add(impulse.multiply(im1));
b.velocity = b.velocity.subtract(impulse.multiply(im2));
}
Let me know if you find anything. Thanks
Is there a typo in the line that sets v1nPost? Looks like the denominator should be this.mass + b.mass
, not this.mass * b.mass
.
Also, because you're computing a collision between this
and b
, are you checking to make sure you're not also doing the same collision between b
and this
, thus doubling the delta applied to each participating bubble in the collision?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With