小さく高速なオブジェクトの衝突:トンネリングの回避


13

編集/更新:私の今の最大の質問は、ステップ3の「t = ...」式が良いアイデアか、それを行うより良い方法かということです。他のほとんどの問題は部分的または完全に対処されていますが、この問題に関するコメントや回答はありません。繰り返しになりますが、分析ソリューションがおそらく必要であり、速度と距離が大きすぎ、オブジェクトが小さすぎるため、私が考えることができる反復/再帰ソリューション(コメントで以下にいくつかを提案します)この種の状況をうまく処理する特別な反復/再帰ソリューションであれば、私は間違いなくそれを受け入れます)。これまでのご協力に感謝します。皆さんはすばらしく、あなたの考えと助けに本当に感謝しています!

小さい高速オブジェクト間の衝突を検出しようとしています。これは、比較的低速であっても、トンネリングが非常に簡単に発生する可能性がある状況です。

レイキャスティングは機能しません。これは、1つのオブジェクトと静止した壁の間ではなく、2つの高速オブジェクト間の衝突を検出しているためです。(レイキャスティングを誤解していない限り?)パフォーマンスは非常に重要です。可能な限り、パフォーマンスの大幅な低下を避けたいと思います。機能的で非常に効果的なクアッドツリー(http://en.wikipedia.org/wiki/Quadtree)を既に実装しているので、以下に説明するように変更して使用します。

編集:時間間隔を短くしても機能しません。このソリューションには速度が高すぎます。つまり、トンネリング衝突の大部分を逃しながら、パフォーマンスヒットが大きすぎるということです。(たとえば、時間間隔ごとに数百万単位で測定される速度で移動する約1単位のサイズのオブジェクトがあるかもしれません...)

提案された解決策:

ステップ1:

各オブジェクトの動きを囲むボックスを作成し、それらのボックスを四分木に入力して、衝突の可能性のある初期リストを生成します。次の画像を参照してください(この画像は、ある位置から別の位置に移動する円形オブジェクトと、四角形を生成する動きを示しています。四角形は四分木に供給されます)。動きによって生成される長方形

ステップ2:(このステップをスキップしたいですか?)

四分木によって生成される可能性のある衝突のリストを調べます。起こりうる各衝突で長方形が交差するかどうかを確認します。その場合は、手順3に進みます。

編集:以下、ショーン・ミドルディッチは、掃引ボリューム/カプセルの交差点の使用を提案しました(オブジェクトが円の場合)。次の3つのオプションがあります。1)ステップ2を完全にスキップします。2)自分のやり方でステップ2を行います。3)ショーンのやり方でやる。ショーンの方法は私のボックスのアイデアよりも計算コストが高くなりますが、私の方法よりも多くの誤検知を排除し、最終ステップに到達できないようにします。

これらの3つの選択肢のうち、どれが最良であるかについて、経験からだれでも話すことができますか?(この物理エンジンをいくつかの異なる目的に使用するつもりなので、どのソリューションを簡単に測定できる特定のテストケースだけでなく、さまざまな状況で最速で動作する「一般的に最高の」ソリューションを探しています最速です)。

ステップ3:

判別式(つまり、平方根の下の部分)が負または0、衝突なし、正の場合、t =式を使用し、衝突の時間としてt値を使用します(その後、それに応じて位置を簡単に調整できます)。 ..衝突後も両方のオブジェクトが存在し続ける場合)。方程式:

t =(-1/2 sqrt((2 a w-2 a x + 2 b y-2 b z-2 c w + 2 c x-2 d y + 2 dz)^ 2-4(w ^ 2- 2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2)(a ^ 2-2 a c + b ^ 2-2 b d + c ^ 2 + d ^ 2-r ^ 2-2 r ss ^ 2))-a w + a xb y + b z + c wc x + d yd z)/(w ^ 2-2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2 )

ここで(1と2はオブジェクト1と2を示すために使用されます):

tは0〜-1の負の時間値です。0は現在のフレーム、-1は前のフレームです。

a = x位置1;

b = y位置1;

c = x位置2;

d = y位置2;

w = x速度1;

x = x速度2;

y = y速度1;

z = y速度2;

r =半径1;

s =半径2;

導出:(^ 2は二乗を意味します)

オブジェクトの動きのパラメトリック方程式(たとえば、newxpos1 = a + t w)を取り、それらを距離の式に差し込みます(両側を二乗):距離の式の2乗=(a + t w-(c + t x))^ 2 +(b + t y-(d + t * z))^ 2。tが負になることを忘れないでください。2つの円形オブジェクトの衝突時間を見つけるには、左側を(r + s)^ 2に設定します。二次方程式(および非常に退屈な代数)を使用してtを解くと、上記の「t = ...」方程式が得られます。

私の質問:

1)これは良い方法ですか?それはまったく機能しますか?予期しない問題が発生しますか?(一度に3つ以上のオブジェクトが衝突すると問題が発生することはわかっていますが、実際に反対するのは、相対速度が低い場合のみです(相対速度が高い場合は、アルゴリズムが提供する「グーフィー」ソリューションは「十分」であり、人間がエラーを見ることは不可能です)、同じタイムステップで2つ以上が低い相対速度で衝突する場合、ほとんどのソリューションはとにかく十分に近づいてください、私はたくさんの非弾性衝突を持つつもりはないので)

2)パフォーマンスは大きく低下しますか?そうなるとは思いませんが、もしそうなら、もっと良い方法はありますか?

3)ステップ2をスキップして、ステップ1から3に直接進む必要がありますか?明らかにステップ2は重要ではありませんが、パフォーマンスを向上させる可能性があります(または、保存するよりも多くのCPU時間を要する場合があります)。

他のすべてのコメント、提案、または批判は大歓迎です。ご協力ありがとうございました!


1
Christer Ericsonは、彼のオレンジブックで、掃引された球体/球体のテストに関する情報を持っています。問題を解決する方法はかなりありますが、間隔を半分にするのが一番好きだと思います。このようなものを自分で派生させてみるのは良いことですが、本当に良い検出ルーチンを取得して詳細を知るには、オレンジ色の本を見て比較するだけです。
ランディゴール

あなたはすでに計画を立てているように聞こえます..それを試してみて、それがどのように機能するかを見てください?
トレバーパウエル

「通常の」方法は、デルタ時間の最大間隔を小さくすることだと思います。したがって、1000ms経過した場合は、10x 100ms(または100x 10ms、または33x 30ms、または同様のもの)をシミュレートしてください。
ashes999

@RandyGaul 215-218ページ、特に218ページ(Googleプレビュー)で説明されているアルゴリズムを見ました。私はまだその意味、長所、短所をすべて熟考していませんが、非常にエレガントです。それは私のものよりはるかに速いでしょうか?もしそうなら、私のアルゴリズムのどの部分がエリクソンの再帰に比べて遅いのですか?ステップ3の式は遅すぎるのでしょうか?一部のオブジェクトは非常に高速に移動している可能性があるため、再帰はheします。したがって、場合によっては大量の再帰が必要になることがあります。(また、その本のために70ドル...)
マインドシーカー

1
@MindSeeker私はあなたの派生物を調べる時間はありませんが、エリクソンの本のアルゴリズムはどれも本当にうまく機能し、おそらくあなたのものよりも速くて堅牢になると確信しています。他のページをデモしたい場合は、PDFバージョンをオンラインで無料で見つけることができます。また、衝突検出を頻繁に行う場合は、オレンジ色の本が主流です。
ランディゴール

回答:


9

基本的に、スイープボリュームのやや熱狂的なバージョンを作成しました。

オブジェクトの2つの位置を取ります。オブジェクトを最初から最後まで「スイープ」します。球体の場合、これはカプセルを作成します。ボックスの場合、これは六角形を作成します(または、より長いボックスは単一軸に沿った動きです)。一般的な凸多角形の場合、これは異なる凸多角形を作成します。

これで、このスイープボリュームを使用して交差テスト(クアッドツリークエリを含む)を実行できます。衝突がいつ発生したかを計算し、開始時間から衝突時間までシミュレーションをロールフォワードして、繰り返すことができます。

もう少しシンプルな別のオプションは、@ ashes999が述べたことを実行し、単純に短い時間間隔または小さい速度を使用することです。単一の物理的相互作用の中で最も狭い側面よりも遠くにオブジェクトが移動できない間隔から得られる理想的な最大速度があります。特に小さいオブジェクトや特に高速なオブジェクトの場合、適切に機能する適度に小さい間隔を見つけることができない場合があります。

衝突の検出のトピックに関する入門書/中間書の1つについては、リアルタイム衝突検出を参照してください。


素晴らしい入力をありがとう!答えを分解して、質問について質問できるようにします。「オブジェクトを最初から最後までスイープ」。これまでのところ、私は追跡しています。間違いなく私のボックス方式よりも改善されています。これらのシェイプをクアッドツリーでフィードし、より正確な衝突をチェックします。「衝突がいつ発生したかを計算できます。」母はやったよりも簡単に言った:)あなたは私がステップのためにステップ3からの私の方程式に固執することを推奨していますか?または、より良い方法はありますか?これは本当に重要な部分です。
マインドシーカー

[続き]「別のオプション...」そのオプションについて考えましたが、残念ながら速度が高すぎます。詳細については、@ ashes999への私のコメント応答を参照し、上記を編集してください。手伝ってくれてありがとうございます!
マインドシーカー

パフォーマンスについて知る唯一の方法は、それを試し、測定し、見ることです。私は以前、非常に非直感的な理由で、「明らかに」非効率的なコードが効率的なバージョンを大幅に上回ることを見てきました。最速のものを聞かないでください。テストして調べてください。
ショーンミドルディッチ

案の定、私は先に進み、あなたが提案したように修正された私の方法を試します。コメント内の私の質問は、「衝突がいつ発生したかを計算できます。」ステップ3の式をそのステップに固執することを推奨していますか?または、より良い方法はありますか?これは私が考える問題の中で最も難しい部分です。スイープボリュームは、それらを正しく理解している場合、オブジェクトのパスが交差することを教えてくれますが、オブジェクト自体が衝突するかどうか/いつ衝突するかを教えてくれません。
マインドシーカー

1
@MindSeeker Sweptジオメトリは、レイの代わりにシェイプをキャストすることを除いて、レイキャスティングです。したがって、この方法は、1つのレイと静止オブジェクトではなく、高速で移動するすべてのオブジェクトに対して「レイ」を使用したレイキャスティングを使用するのと同じように見えるはずです。「光線」から潜在的な衝突を特定した後、両方の「光線」で時間をかけて、それらが同時に同じ場所にあることを確認する必要があります。
ストーンメタル

2

質問で提案されたアルゴリズムは非常にうまく機能します。オブジェクトが極端な速度で進んでいる場合でも、高速で完全に正確です。私は四分木を実装しているので、ステップ1からボックスを四分木に入力した後、ステップ2は不要であることがわかりました。私のプログラムは以前とほぼ同じ速度で実行されていました。

私はこのアルゴリズムを数か月間使用していますが、衝突の時間tを決定するのに完全に正確であるようです。Web上にはより良いものはないように思われるので、これを使用することを強くお勧めします。(上記の他の回答とコメントの回答のいくつかは素晴らしいですが、質問で述べられているようにニーズを完全に満たしていないか、著者が何かについて非常に曖昧で、曖昧さについて質問されたときに返事をしませんでした)。


1

まだコメントするほどの評判はありませんが、上記のショーン・ミドルディッチがあなたの「t」を計算することを可能にするものを使用して追加したいと思います。少なくとも私が彼の答えを理解し、あなたが正しく質問した場合。

ここに私が見つけた最高の説明を提供するsam hocevarによる素晴らしい答えへのリンクがあります(彼も絵を描いた、ばか!)

/gamedev//a/55991/112940

それがあなた自身の方法よりも速い場合、私は言うことはできませんが、彼は確かにあなたがそれを実装してあなたのものと比較するためにあなたに必要なすべてを提供します。

「リンクのみの回答」を残さないようにするために、彼のアイデアを簡単に要約します。

  1. 2つの境界ボックス間のミンコフスキー差を計算する
  2. その間の相対速度を使用して、交点を取得するために、原点からミンコフスキー差分によって作成されたボックスに光線/線分セグメントをキャストします
  3. 光線が当たった場合、光線を移動した距離を相対速度を表すベクトルの長さで除算すると、「t」
  4. 上記で提供したリンクをクリックすると、たくさんの写真とともに、これらすべての美しい説明が表示されます。すばらしい。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.