2011-02-15 77 views
4

我想写一个简单的物理模拟,其中半球和质量不同的球在完美弹性和无摩擦的环境中弹跳。我写我自己的代码下面这个资源:http://www.vobarian.com/collisions/2dcollisions2.pdf,我也测试了从这里代码:Ball to Ball Collision - Detection and Handling二维球碰撞问题:没有能量守恒

问题EDITED

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

这里是我写的功能算法(虽然我没有从其他来源获得第一位)。它在气泡类别:

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

我们,如果你发现任何我知道的一个。谢谢

回答

6

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

而且,因为你计算thisb之间的碰撞,你检查,以确保你不是也做bthis之间的相同的碰撞,从而加倍三角洲应用到每一个参与泡沫的碰撞?

+0

雅这是错字...我一直在电脑前呆了太久,我多次查了一遍数学。谢谢。看看我的编辑虽然,我真的想让其他算法的工作和它绝对不是同一个问题 – Cbas 2011-02-16 02:51:26

+0

至于你的第二点,我不检查,看看我是否已经通过气泡解决了我的循环中的碰撞,但我不认为这很重要,因为我在这个resolveCollision方法中做的第一件事是将它们拉开。当循环在碰撞中找到另一个球时,它不会再发生碰撞并且不会再次调用这个方法 – Cbas 2011-02-16 02:56:36

3

我做了第一个猜测:getMass()返回一个整数(或整数)(而不是一个浮点数或双)?

如果这是真的,比你的问题是1/getMass()将导致一个整数值(并且可能只有1或大多数时间0))。要解决由1.01.0f

这种替换1因为一般的规则很简单: 如果你有一个数学运算(+, - ,*,/)所产生的类型将是整数,如果没有这两个operants的是浮点数据结构(双精度或浮点)

无论如何:可能会有第二个问题,可能您的计算结果不准确。那么你应该使用double而不是float。

+0

这是一个很好的观点。 getMass()实际上返回一个字节,在我的代码中,到目前为止,所有的气泡的质量都是1.如果质量不同,我发现我会遇到问题。我会改变它,非常感谢。 – Cbas 2011-02-16 03:00:50

1

有看起来奇怪的一部分:

两个计算:

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

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