4

さまざまな半径と質量を持つボールが完全に弾力性があり摩擦のない環境で跳ね返る単純な物理シミュレーションを作成しようとしています。私はこのリソースに従って独自のコードを書きました: http://www.vobarian.com/collisions/2dcollisions2.pdfそして、ここからコードをテストしました:ボールからボールへの衝突 - 検出と処理

質問が編集されました

Rick Goldstein と Ralph の助けを借りて、コードを動作させることができました (タイプミスがありました..)。助けてくれてどうもありがとう。ただし、他のアルゴリズムが機能しない理由についてはまだ混乱しています。ボールは正しい方向に跳ね返りますが、システムの総エネルギーは決して保存されません。画面上の静的な位置でボールが点滅し始めるまで、速度はますます速くなります。私が書いたコードよりもはるかに簡潔なので、実際にこのコードを自分のプログラムで使用したいと思っています。

これが私が書いた関数型アルゴリズムです (ただし、最初のビットは別のソースから取得しました)。それはバブルクラスにあります:

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ます。

また、 と の間の衝突を計算しているので、 と の間でthisb同じ衝突を行っていないことを確認して、衝突に関与する各バブルに適用されるデルタを 2 倍にしていますか?bthis

于 2011-02-15T19:24:54.200 に答える
3

私は最初の推測を行います: getMass() は整数 (または int) を返します (float や double ではありません)?

これが真の場合、問題は1 / getMass()整数値になることです(1のみまたはほとんど0になる可能性があります))。これを修正するには11.0またはで置き換えます1.0f

一般的なルールは単純なので、数学演算 (+、-、​​、/) がある場合、両方のオペランドが浮動小数点データ構造 (double または float) でない場合、結果の型は整数になります。

とにかく: 2 つ目の問題が発生する可能性があります。計算が十分に正確でない可能性があります。次に、float の代わりに double を使用する必要があります。

于 2011-02-15T19:19:13.880 に答える
1

奇妙に見える部分があります:

2つの計算:

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

最後の操作を除いて対称であり、最初の操作で*は2番目の操作です+

于 2011-02-15T19:27:11.313 に答える