web-dev-qa-db-ja.com

3D衝突検出:凸包対凸包、位置と法線が必要

おおよその3D位置およびを知りたい2つの3D凸包間の衝突サイトの3D法線(A vs B)。

括弧内のCPUは、完成したプログラムに必要な相対的なCPU時間を示しています。

パート1:早期終了(CPU 1%)

最初のステップでは、非常に安価なアルゴリズムである 分離軸定理 を使用します。
たとえば、2つの立方体に 15 axis を使用します。 (実際のケースでは、形状はより複雑です。)
分離できる軸が少なくとも1つある場合、return "no-collide"
それ以外の場合は、次の部分を実行します。

パート2:頂点とボリューム(CPU 10%)

  • Aのすべての頂点を確認します-B内にあるかどうか。
  • Bのすべての頂点を確認します-A内にあるかどうか。

enter image description here

パート3:エッジvsエッジ(CPU> 20%)

奇妙なケースがあります。 https://gamedev.stackexchange.com/questions/75437/collision-detection-3d-rectangles-using-sat 。私はそこから画像を盗みました:-

enter image description here

したがって、EdgevsEdgeも必要です。

  • AとBのエッジのすべてのペア(12 * 12 = 144ペア)について、Aのエッジに対してBのエッジで最も近い点を見つけます。頂点がB内にあるかどうかを確認します。
  • (逆も同様)BとAのエッジのすべてのペアについて、そのような頂点がA内にあるかどうかを確認します。

うわー、それはたくさんの計算です。
しかし、まだ終わっていません。

問題

  1. 報告された衝突位置はあまり正確ではありません(左:現在、右:希望):-

    enter image description here

    それを解決するために、新しい凸形状を生成することを考えました= A intersect B
    C++フリーのライブラリがいくつかあります(例 OpenMesh )が、CPUに負荷がかかりすぎると思います。
    正確に正確である必要はないことに注意してください。

  2. それは時々間違った正常を報告します(左:現在、右:願い):-

    enter image description here

    ^この問題はEdge(of A)対face(Bの)チェックですが、衝突検出全体がさらに高価になります。

質問

それは私がコピーしたインターネットの一般的なアルゴリズムがマイクロ機能のみを認識するようです。
IMHO、頂点ボリューム/エッジエッジアルゴリズムは、両方の形状がsolidボリュームであるという事実ではなく、トポロジーに焦点を当てています。

より正確(最優先)でおそらく安価なアルゴリズムは何ですか?
私のアプローチは、財団レベルでは間違っているかもしれません。

物事をスピードアップするために、私はすでにいくつかの剪定をしました近接しているエッジAとBのペアのみを選択します。

参照:-

編集(10日後)

今、私はすべての交差する凸点を見つけることができます(凸はピンクの三角形/長方形として描かれています):- enter image description here

これが私が正常を見つける方法です。

それぞれの分離軸(すべて= 15軸)の場合、Iprojectピンクの凸面が軸に投影されます。
最短投影距離(ピンクの矢印)を生成する軸は、法線の方向である必要があります。

私の上記の仮定は、多くの場合正しい(左など)が、時には間違っている(右など)。
CPUを安価に改善するにはどうすればよいですか?

12
javaLover

ゲームエンジンは通常、一連の個別のステップで時間をシミュレートします。その結果、衝突システムは、相互侵入(あなたのケース)のため、またはAがステップNでBの片側にあり、Bの反対側に完全にあるトンネリングが高速で移動しているときに、困難(計算コストが高い)ケースに陥る可能性があります。ステップN + 1で。マルチボディ接触または連続接触または非凸型またはジョイント型またはソフトオブジェクトを処理する必要がある場合は、さらに困難になります。うわぁ!全世界をシミュレートしています。

「ゲームの物理学」を行い、概算を使用してフレームレートを買い戻したいとします。結局のところ、たくさんのエラーを煙のパフまたはライトフレアの束でカバーできます。 :-)

衝突システムを支援するためにシミュレートされた時間を明示的に考慮に入れるアルゴリズムのクラスがあります。 「継続的衝突検出」システムを実装する方法はたくさんあります。ここから始めることもできますが、コードにコミットする前に、最初に広く読む必要があります。幸い、衝突については多くの文献があります。ここから始めるのが良いでしょう https://docs.unity3d.com/Manual/ContinuousCollisionDetection.htmlhttps://pybullet.org/Bullet/phpBB3/viewtopic.php?t = 2

これは、既存のシステムで機能する可能性のある提案されたヒューリスティックです。このヒューリスティックな手法は、オブジェクトが空間に自由に浮遊するastroids 3dのようなゲームで機能します。これで十分です。

すべてのオブジェクトが現在の状態ベクトル(位置、方向、速度、加速度、回転...)と前のタイムステップからの前の状態ベクトルを格納するイメージ。

Time = currentでオブジェクトAとBの間の潜在的な衝突を検出したとします。

Time = previousの場合、AとBが接触していないと仮定します。

AとBの以前の状態ベクトルを使用して、それぞれtime = prevでAとBの表面上の最も近い点を計算します(closestA、closestB)。

線分(closestA、closestB)は、time = previousでゼロ以外の長さになります。あなたはあなたの位置と法線のためにnearestBを単に使うことができました、しかしそれはラインセグメントの長さに比例するいくらかのエラーを持っているでしょう。

したがって、時間内にバイナリ検索を実行し、AがBに任意に近い時間を見つけることにより、エラーを最小限に抑えます。検索の各パスで、検索時間のステップサイズを半分に減らします。 0.5、0.25、0.125 ..(closestA、closestB)の長さがエラーしきい値を下回るまで、またはあきらめるまで。

それはあなたに単純なケースのための許容可能な近似解を与えるはずです...

また、分離軸の定理を「最初のチェック」として使用していると述べました。それが本当に「最初のチェック」であるなら、それは実際に私には高価に思えます。

最速の計算は実行しない計算であるため、高速の衝突は多くの安価な事前テストを意味し、高価なケースを回避します。

粗い空間グリッドのような空間技術の使用を検討し、すでに近くにあることがわかっているオブジェクトのみをチェックできます。

また、sphere-sphereテストは、2つの凸状オブジェクトの境界球が重なり合っているかどうかを確認するための非常に高速な事前テストです。

1
VerdeCode