力との衝突の解決


14

2D物理エンジンでは、AABBとAABBの衝突を検出し、最短の貫通ベクトルを見つけてAABBの位置に追加することでそれらを解決できます。

これを行うと、最初のAABBが2番目のAABBの外側に「プッシュ」されますが、速度/加速度の変化はまったく処理されません。

シミュレーションに重力加速度を追加すると、最初の動的AABBの速度は、2番目の静的AABBの上にある場合でも増加し続けます。最終的に、速度が大きくなりすぎて衝突が検出されなくなります(動的なAABBは静的なAABBを通過します)。

解像度後に速度をゼロに設定しようとしましたが、明らかにうまく機能せず、非現実的なシミュレーションを作成しました。

オンラインで読んだところ、位置を手動で操作して衝突を解決したり、速度が正しくなかった。私は力を実装しようとしました(今のところ、質量は「ハードコードされた」1です):

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

衝突の解決中に最短の貫通ベクトルを力として適用すると、動的なAABBは静的なものから「押し出され」ますが、その速度は重力のないシミュレーションでは決して低下せず、永遠に動き続けます。

「一時的な」力を適用する方法はありますか?最初のAABBを2番目のAABBから押し出し、その後AABBが衝突しなくなった時点で停止する力。

ここで利用可能なソースコード全体:https : //github.com/SuperV1234/SSVSCollision


1
私はこれに興味があります。まだ解決策を思いつきましたか?
TravisG

@TravisG:残念ながら、まだです。返信がなければ明日報奨金を追加します。
ヴィットリオロミオ

まず、力と加速は等しくありません。加速度を計算するには質量が必要です。2つのボディの貫通を停止するために位置を変更する場合は、質量も使用し、それに基づいて両方のボディを移動する必要があります。貫通ベクトルに等しい力を適用してもメリットはありません。Box2Dはインパルスベースで、速度に直接作用します。「正確」ではないかもしれませんが、十分です。インパルスベースのエンジンで速度の変化に対処するのは非常に簡単です。したがって、力ベースのソリューションが最終的に必要な場合、またはより単純なインパルスベースのソリューションで十分かどうかを指定できます。
-dreta

個人的には、少なくともニュートン物理学の最初の数章を読んで、物理エンジンに関する本を選ぶことをお勧めします。あなたの仮定は間違っており、この質問に答えようとすることは、衝突を解決するための高レベルのアルゴリズムを説明しようとしながら、物理学の基礎を教えなければならないことを意味します。
-dreta

@dreta彼の仮定は問題ありません。彼は、現在のところ、すべてのオブジェクトの質量は単に「1」であるため、コードセクションが有効になることを指摘しました。ちなみに、Box2Dは速度を直接処理しますが、どういうわけか同じ問題を処理する必要があります。力を適用する代わりに、Box2Dがインパルスを適用する場合、オブジェクトが分離されるとインパルスが消えないという事実に何らかの方法で対処する必要があります。ただし、実際にはこれをまったく処理せず、オブジェクトにエネルギーを保持させるだけである可能性があります(結局、現実の世界ではこのようになります)
TravisG

回答:


13

まず、Box2Dのような無料のオープンソースの物理ライブラリを使用し、ゲームのユニークな側面に注目することをお勧めします!車輪の再発明を主張する場合は、続きを読んでください...すべての物理エンジンは近似であり、以下で概説する方法は現在のモデルよりも正確ですが、Box2Dの結果ははるかに現実的です。


2つのオブジェクトAとBのより正確な衝突解決をすばやくモデル化する方法:

  1. 衝突直前の位置を見つけます。あなたはすでにこれを近似しています:「最短の侵入ベクトルを見つけ、AABBの位置に追加します。」
  2. ニュートン物理学を使用して、衝突直後の速度を見つけます
    • 質量が1としてハードコードされている場合、速度を入れ替えるだけです(無限質量を持たなければならない静的オブジェクトには適用されません)。
      • Av = Bu
      • Bv = Au
    • オブジェクトAとBの質量が異なる場合:
      • Av =(Au *(Am-Bm)+(2 * Bm * Bu))/(Am + Bm)
      • Bv =(Bu *(Bm-Am)+(2 * Am * Au))/(Am + Bm)
    • どこ:
      • v:衝突後の速度
      • u:衝突前の速度
      • m:質量(固定された静的オブジェクトの質量に可能な最大数を使用)
  3. 加速を0に設定します。衝突からの加速は、ステップ番号2の速度計算によって上記に考慮されました。

これらの概念を実証する私の小惑星プログラムのサンプルをご覧ください。


次に、積み上げオブジェクトを考慮します。

既に述べたように、速度を使用して積み上げ/静止オブジェクトをシミュレートすることはうまく機能しません。速度はオブジェクトの移動速度です。静止状態で表示するオブジェクトの速度:

シミュレーションに重力加速度を追加すると、最初の動的AABBの速度は、2番目の静的AABBの上にある場合でも増加し続けます。最終的に、速度が大きくなりすぎて衝突が検出されなくなります(動的なAABBは静的なAABBを通過します)。

本当に起こるべきことは、重力が重力を打ち消すように反対方向に進む加速力です。(これは通常の接触力と呼ばれます)。簡単な方法は、空中にない物体に重力をかけないことです。

  • これを行う1つの方法は、「接地」状態を維持することです。
    • 接地状態のオブジェクトに重力をかけないでください。
    • オブジェクトが下からオブジェクトと衝突し、その速度が非常に小さい場合、接地状態になります。
    • オブジェクトは、垂直速度が特定の正の値を超えると、接地状態を終了します。

更新:

  • 素人の言葉で言えば、ニュートンの物理学は、衝突の前後の総エネルギーが一致しなければならないと言います。2つのオブジェクトが互いに衝突すると、エネルギーが再分配されます。エネルギーは速度と重量の組み合わせです。重くて速いものほどエネルギーが多くなります。それは直感的です。ただし、直感的ではないのは、重みがエネルギーの再配分に与える正確な方法です。
  • 速度の交換は、同じ質量を持つ2つの動的な固定されていないボディ(静的で固定されたオブジェクトには非常に大きな無限の質量があります)に対するショートカットです。
  • 一方の静的ボディが固定されている場合のショートカットは、もう一方の動的で固定されていないボディは同じ速度を維持します。角度のみが変更されます(ボールがレールに衝突したときにビリヤード台を想像してください。レールは本質的に非常に大きく、無限の質量を持っています)。
  • 3つ以上のオブジェクトのような他の場合、完全なニュートン運動方程式を解く必要があります(運動量の保存と運動エネルギーの保存)。
  • 運動のニュートン方程式が3つ以上の物体について解けるかどうかはわかりません。ただし、幸いなことに、3つのオブジェクトがまったく同時に衝突することはほとんどありません。衝突する最初の2つのボディを処理し、前の衝突解決からの新しい速度を使用して、後続の衝突を処理するだけで十分です。これは、物理タイムステップをできるだけ小さく保ち、侵入が発生する前に衝突を処理するための正当な理由です。
  • 私の小惑星のデモでは、大きな岩が小さな岩に分割されるため、多くのボディが作成されることに気付くでしょう。ただし、私は常にボディのペア間の衝突を処理します。3つ以上のボディとの衝突を明示的に処理することはありません。

詳細な返信をありがとう。理解できないことがあります:速度の交換は、2つのボディとの衝突でうまく機能します-ただし、複数のボディ(および静的なボディ)がすべて同時に衝突したときの動作はわかりません。重力がなくても、動的ボディが静的ボディと別の動的ボディと同時に衝突すると、問題が発生します。速度は交換されるため、衝突の順序にすべて依存します。静的ボディが最後に衝突した場合、ボディは動きを停止します。動的なものがあれば、身体は再び動​​きます。これはどのように修正されますか?
ヴィットリオロミオ

@Vee:良い質問です!3つ以上のボディと静的ボディは、2つの別個の問題です。アップデートで両方に対処しました。概要:一度に2つのオブジェクトの衝突を処理します。静的物体には非常に大きな無限の質量があります。
レフティウム

安静時のコンタクトのモデルは奇妙です。安静時の接触は重力だけでなく、どんな力でも機能するはずです。動作する最も簡単な方法は、接触時に前のフレームの加速により得られた速度を単に削除することです。また、小さな速度の場合、反発を計算で計算することはできませんが、反発を完全に削除できます。このアプローチはすべての力に対して機能します。実装は簡単で、見た目は十分です。
-dreta

16

この問題を解決するには、位置と速度を調整する必要があります。剛体物理エンジンには、ニュートンの運動法則を使用してオブジェクトを時間的に前方に移動させ、非貫通の制約と摩擦も解決するソルバーがあります。これらのエンジンは、直線運動と角運動の適切な組み合わせを計算して、もっともらしい軌道を作成できます。

オーバーラップのみを解決する場合は、勢いを増やさずに分離軌道を生成する擬似速度を使用できます。これは、Box2Dの位置ソルバーで行われます。

2006年と2007年からGDCプレゼンテーションを入手することをお勧めします。

http://code.google.com/p/box2d/downloads/list

また、簡単な実装については、Box2D Liteをご覧ください。


位置の調整にも必要であるという発言に対して+1。これに満足する人はほとんどいませんが、シミュレーションの安定性を高めるために、ほとんどのエンジンは位置を直接調整することでごまかしています。全体的に見て、もっともらしいのであれば、ゲームでも機能します。
テオドロン

答えてくれてありがとう。おそらくプレゼンテーションで見落としていたことを知りたかったのです。Box2Dでは静的ボディは特別な方法で処理されますか?つまり、動的な物体が静的な物体に衝突するとどうなりますか?
ヴィットリオロミオ

2

ここに画像の説明を入力してください

現実の世界では、オブジェクトが互いに浸透することはないため、あるボディを別のボディの外側に「押し付ける」力はありません。最も近いものは法線力です:実際の衝突で接触した瞬間に作成され、そもそも侵入を防ぎます。

この法線力の角度は、衝突する2つのオブジェクトの接触面に垂直です。大きさは、侵入を防ぐために必要な力に依存します。(摩擦力などの他の力もモデル化されていない限り、法線力のy成分のみを使用する必要があります)。

法線力を明示的にモデル化することは可能ですが、その効果のみをモデル化する方が簡単です:

  1. 次のいずれかの方法でオブジェクトの交差を防ぎます。
    • 衝突の瞬間の衝突を解決して速度を調整します。(ベスト)
    • ボディが交差しないように、ボディの位置を手動で調整します。(簡単)「最短の侵入ベクトルを見つけてAABBの位置に追加する」ことで、すでにこれを行っています。
  2. 重力を相殺する垂直力がある場所に重力をかけないでください。
    • その下にある別のオブジェクトと接触しているオブジェクトは、垂直力の影響を受けます。したがって、それらのオブジェクトを追跡する問題です。(実際には、接触しているオブジェクトには法線力を適用する必要がありますが、これらのすべてが重力に関して正味の効果を持つわけではありません。)
    • ある角度にある他のオブジェクトを下にスライドできるオブジェクトを追加する場合は、法線力の摩擦力とx成分を追加する必要があります。

私はこれを他の答えで少し異なって説明しました。それは一般的に衝突についてです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.