4

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

问题已编辑

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

这是我编写的函数算法(尽管我确实从其他来源获取了第一部分)。它在 Bubble 类中:

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

如果你发现什么,请告诉我。谢谢

4

3 回答 3

6

设置 v1nPost 的行中有错字吗?看起来分母应该是this.mass + b.mass,不是this.mass * b.mass

this另外,因为您正在计算and之间的碰撞b,您是否正在检查以确保您没有在 and 之间进行相同的碰撞bthis从而将应用于碰撞中每个参与气泡的增量加倍?

于 2011-02-15T19:24:54.200 回答
3

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

如果这是真的,那么你的问题是这1 / getMass()将导致一个整数值(并且只能是 1 或大多数时候为 0))。要解决此问题,请替换11.01.0f

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

无论如何:可能还有第二个问题,可能你的计算不够精确。那么你应该使用双精度而不是浮点数。

于 2011-02-15T19:19:13.880 回答
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);

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

于 2011-02-15T19:27:11.313 回答