2d球碰撞问题:没有能量守恒

我正在尝试编写一个简单的物理模拟,其中具有不同半径和质量的球在完全弹性和无摩擦的环境中反弹。 我按照以下资源编写了自己的代码: http : //www.vobarian.com/collisions/2dcollisions2.pdf ,我也从这里测试了代码: Ball to Ball Collision – 检测和处理

编辑问题

在Rick Goldstein和Ralph的帮助下,我得到了我的代码(有一个错字……)。 非常感谢你的帮助。 但是我仍然感到困惑,为什么其他算法不适合我。 球以正确的方向反弹,但系统的总能量永远不会被保存。 速度越来越快,直到球刚开始在屏幕上的静态位置闪烁。 我实际上想在我的程序中使用这个代码,因为它比我写的那个简洁得多。

这是我写的function算法(虽然我确实从其他来源获取了第一位)。 它在泡泡类中:

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

这是一个不起作用的

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

如果你发现任何事情,请告诉我。 谢谢

设置v1nPost的行中是否有拼写错误? 看起来分母应该是this.mass + b.mass ,而不是this.mass * b.mass

另外,因为你计算了thisb之间的碰撞,你是否在检查以确保你没有在bb之间进行相同的碰撞,从而使碰撞中每个参与气泡的增量加倍?

我做了第一个猜测:getMass()返回一个整数(或int)(而不是float或double)?

如果这是真的,那么问题是1 / getMass()将导致整数值(并且可以只有1或大部分时间为0))。 要解决此问题,请将1.0替换为1.01.0f

因为一般规则很简单:如果你有数学运算(+, – ,*,/),如果两个操作数都不是浮点数据结构(double或float),结果类型将是整数

无论如何:可能存在第二个问题,可能你的计算不准确。 然后你应该使用double而不是float。

有一部分看起来很奇怪:

两个计算:

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

是对称的,除了最后一个操作,第一个是* ,在第二个是+