2d point collision problem: no energy conservation

I am trying to write a simple physical simulation in which balls with varying radii and masses bounce in a completely elastic and frictionless environment. I wrote my own code following this resource: http://www.vobarian.com/collisions/2dcollisions2.pdf , and I also checked the code here: Ball to Ball Collision - detection and processing

QUESTION EDITED

With the help of Rick Goldstein and Ralph, I got my code for work (there was a typo ..). Thank you for help. However, I'm still confused about why another algorithm is not working for me. The balls bounce in the right direction, but the full energy of the system is never conserved. Speeds are getting faster and faster until the balls begin to flash in static positions on the screen. I really want to use this code in my program because it is much more concise than the one I wrote.

Here is a functional algorithm that I wrote (although I took the first bit from this other source). Its in the 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 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 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

+4
source share
3 answers

Is there a typo in the line that sets v1nPost? It looks like the denominator should be this.mass + b.mass , not this.mass * b.mass .

Also, since you are calculating the collision between this and b , do you verify that you are also not doing the same collision between b and this , thereby doubling the applied delta for each bubble involved in the collision?

+6
source

I guess first: getMass () returns an integer (or int) (and not a float or double)?

If so, then the problem is that 1 / getMass() will result in an integer value (and there can only be 1 or more time 0)). To fix this, replace 1 with 1.0 or 1.0f

Since the general rule is simple: If you have a mathematical operation (+, -, *, /), the resulting type will be integer if neither of the two operands is a floating-point data structure (double or float)

Anyway: there may be a second problem, whether your assessment may not be accurate enougth. Then you should use double instead of float.

+3
source

There is a part that looks weird:

Two calculations:

 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); 

are symmetric, with the exception of the last operation, in the first - * , in the second - +

+1
source

Source: https://habr.com/ru/post/1339878/


All Articles