4

Objective-C での質問「ボールからボールへの衝突 - 検出と処理」のコードを実装しました。ただし、ボールが斜めに衝突するたびに、その速度は劇的に増加します。ベクトル計算はすべてcocos2d-iphoneを使用して行われ、ヘッダーは CGPointExtension.h です。この望ましくない加速の原因は何ですか?

高速化の例を次に示します。

入力:
質量 == 12.56637
速度.x == 1.73199439
速度.y == -10.5695238

ボールの質量 == 12.56637
ボールの速度.x == 6.04341078 ボールの速度
.y == 14.2686739

出力:
質量 == 12.56637
速度.x == 110.004326
速度.y == -10.5695238

ボールの質量 == 12.56637
ボールの速度.x == -102.22892 ボールの速度
.y == -72.4030228

#import "CGPointExtension.h"
#define RESTITUTION_CONSTANT (0.75) //elasticity of the system

- (void) resolveCollision:(Ball*) ball
{
    // get the mtd (minimum translation distance)
    CGPoint delta = ccpSub(position, ball.position);
    float d = ccpLength(delta);
    // minimum translation distance to push balls apart after intersecting
    CGPoint mtd = ccpMult(delta, (((radius + ball.radius)-d)/d)); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / [self mass]; 
    float im2 = 1 / [ball mass];

    // push-pull them apart based off their mass
    position = ccpAdd(position, ccpMult(mtd, (im1 / (im1 + im2))));
    ball.position = ccpSub(ball.position, ccpMult(mtd, (im2 / (im1 + im2))));

    // impact speed
    CGPoint v = ccpSub(velocity, ball.velocity);
    float vn = ccpDot(v,ccpNormalize(mtd));

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / ([self mass] + [ball mass]);
    CGPoint impulse = ccpMult(mtd, i);


    // change in momentum
    velocity = ccpAdd(velocity, ccpMult(impulse, im1));
    ball.velocity = ccpSub(ball.velocity, ccpMult(impulse, im2));

}
4

3 に答える 3

5

元のコードと元の投稿者のコメントを確認したところ、コードは同じように見えます。そのため、元のコードが正しい実装である場合、ベクトル ライブラリが正しくないか、何らかの初期化されていない変数が疑われます。

なぜ反発係数に 1.0 を加えるのですか?

出典: http://en.wikipedia.org/wiki/Coefficient_of_restitution

COR は通常、範囲 [0,1] の数値です。定性的には、1 は完全に弾性的な衝突を表し、0 は完全に非弾性的な衝突を表します。1 より大きい COR は理論的には可能であり、地雷が一緒に投げられて爆発するなど、運動エネルギーを生成する衝突を表します。

別の問題はこれです:

/ (im1 + im2)

質量の逆数の合計で除算して、接触ベクトルに沿ったインパルスを取得します。おそらく、質量自体の合計で除算する必要があります。これはあなたの衝動を拡大しています(「彼女が言ったことです」)。

于 2009-05-21T20:28:54.107 に答える
3

あなたが参照したオリジナルのボール バウンス コードを書いたのは私です。そのコードをダウンロードして試してみると、問題なく動作することがわかります。

次のコードは正しいです (元のコードと同じです)。

// collision impulse
float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / (im1 + im2);
CGPoint impulse = ccpMult(mtd, i);

これは非常に一般的な物理コードであり、次の例でこのようにほぼ正確に実装されていることがわかります。

これは正しく、他の人が示唆したように 1.0 を超える CoR を作成することではありません。これは、質量と反発係数に基づいて相対衝撃ベクトルを計算しています。

摩擦を無視すると、単純な 1 次元の例は次のようになります。

J = -Vr(1+e) / {1/m1 + 1/m2}  

ここで、e は CoR、Vr は正規化された速度、J はインパルス速度のスカラー値です。

これよりも高度なことを計画している場合は、すでに存在する多くの物理ライブラリのいずれかを使用することをお勧めします。上記のコードを使用したときは、数個のボールには問題ありませんでしたが、数百個まで上げると、チョークし始めました。Box2D 物理エンジンを使用しましたが、そのソルバーはより多くのボールを処理でき、はるかに正確です。

とにかく、私はあなたのコードを調べましたが、一見問題ないように見えます (かなり忠実な翻訳です)。おそらく、間違った値が渡されたという小さな微妙なエラーか、ベクトル演算の問題です。

iPhone の開発については何も知りませんが、そのメソッドの先頭にブレークポイントを設定し、各ステップの結果の値を監視し、ブローアップがどこにあるかを見つけることをお勧めします。大きな増加が導入されている場所がわかるまで、MTD、衝撃速度などが正しく計算されていることを確認してください。

そのメソッドの各ステップの値を報告すると、何が得られるかがわかります。

于 2009-05-22T01:31:12.623 に答える
0

この行で:

CGPoint impulse = ccpMult(mtd, i);

mtd は正規化されている必要があります。元のコードでは mtd が前の行で正規化されていたが、コードでは正規化されていなかったため、エラーが発生しました。次のようにして修正できます。

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
于 2012-08-13T14:47:52.563 に答える