OBB対OBB衝突検出


20

2つのバウンディングボックスオブジェクトがあり、それぞれがボックス内の現在の頂点をベクトルに格納し、オブジェクトのすべての頂点が共通の軸に対して回転および変換されているとします。

ここに私の問題を説明するための画像があります:

2つのOBBがリンクをオーバーラップしている場合、どうすれば問題の解決策を説明するのに役立つのでしょうか。複雑すぎることはありません...

回答:


16

OBBは凸包です。凸包は、表面に「割れ目」のない3D形状です。凸包のすべての「バンプ」(頂点)は外側突き出ており、内側には突き出ていません。凸包を通る平面をスライスすると、(1つのみ)凸多角形が得られます。凸包の内側にいて、外側に向かってレーザーを発射すると、船体の表面を1回だけ(2回は)パンチしません。

軸分離定理テストを使用して、凸包の衝突を検出できます。SATテストは簡単です。2Dおよび3Dで動作します。以下の写真は2Dですが、3Dにも簡単に適用できます。

概念

これは、SATで使用している重要な概念です。

  • 2つの形状が交差するのは、両方の形状のすべての通常の軸に「投影」したときに重なりがある場合のみです。

1Dベクトルへの形状の「投影」は次のようになります(「クラッシュ」と呼びます)

赤い頂点のある形状と軸

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

「形状を軸に投影する」とは、形状の各点から垂線を落として軸に着地することを意味します。これは、すべてを集めて軸に垂直に押しつぶす手でポイントを「つぶす」と考えることができます。

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

残っているもの:軸上の点

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

SATより:

2つの凸包を交差させるには、すべての軸で重なり合う必要があります(いずれかの形状のすべての法線が軸としてカウントされる必要があるため)。

次の2つの形を取ります。

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

交差していないので、オーバーラップ発生しなかったことを示すために、いくつかの軸を試してみましょう。

五角形の一番上の法線を試す:

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

これらはエクステントです。それらは重なります。

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

長方形の左側を試してください。現在、これらはこの軸でオーバーラップしていないため、交差はありません。

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

アルゴリズム:

両方の形状の法線の各面に対して:

  • その軸への両方の形状のすべての頂点コーナーポイントの投影の最小および最大範囲(最大および最小値)を見つける
  • それらが重ならない場合、交差点はありません。

そしてそれは本当にそれです。SATを機能させるためのコードは非常に短くシンプルです。

以下は、SAT軸投影を行う方法を示すコードです。

void SATtest( const Vector3f& axis, const vector<Vector3f>& ptSet, float& minAlong, float& maxAlong )
{
  minAlong=HUGE, maxAlong=-HUGE;
  for( int i = 0 ; i < ptSet.size() ; i++ )
  {
    // just dot it to get the min/max along this axis.
    float dotVal = ptSet[i].dot( axis ) ;
    if( dotVal < minAlong )  minAlong=dotVal;
    if( dotVal > maxAlong )  maxAlong=dotVal;
  }
}

呼び出しコード:

// Shape1 and Shape2 must be CONVEX HULLS
bool intersects( Shape shape1, Shape shape2 )
{
  // Get the normals for one of the shapes,
  for( int i = 0 ; i < shape1.normals.size() ; i++ )
  {
    float shape1Min, shape1Max, shape2Min, shape2Max ;
    SATtest( normals[i], shape1.corners, shape1Min, shape1Max ) ;
    SATtest( normals[i], shape2.corners, shape2Min, shape2Max ) ;
    if( !overlaps( shape1Min, shape1Max, shape2Min, shape2Max ) )
    {
      return 0 ; // NO INTERSECTION
    }

    // otherwise, go on with the next test
  }

  // TEST SHAPE2.normals as well

  // if overlap occurred in ALL AXES, then they do intersect
  return 1 ;
}

bool overlaps( float min1, float max1, float min2, float max2 )
{
  return isBetweenOrdered( min2, min1, max1 ) || isBetweenOrdered( min1, min2, max2 ) ;
}

inline bool isBetweenOrdered( float val, float lowerBound, float upperBound ) {
  return lowerBound <= val && val <= upperBound ;
}

Hullinatorは凸包のSATテストを実装します
bobobobo

素晴らしい説明!ありがとう。行にタイプミスがあるかもしれないと思います:「だから、いくつかの軸を試して、重複が発生しなかったことを示してください」。再度、感謝します!

法線のすべての外積に対してもテストを行う必要はありませんか?この記事のgeometrictools.com/Documentation/DynamicCollisionDetection.pdfはそう言っています。
iNFINITEi

このSATの特定の方法は2Dでのみ機能することを述べる価値があります。3Dでは、各面の法線以上のものを取得する必要があります。ただし、正しい法線を取得したら、残りのプロセス(プロジェクト、比較)はまったく同じです。
ファンドモニカの訴訟

矢印がどの方向に向かっているのかを2D画像から判断するのは非常に困難です。
WDUK

7

あなたは間違いなく軸分離定理を調べるべきです。凸状オブジェクト用です。「2つの凸状オブジェクトが交差しない場合、これら2つのオブジェクトの投影が交差しない平面があります」というルールがあります。

wikiでいくつかの例を見つけることができます。しかし、それはあなたの場合よりも少し複雑です。

あなたの問題により適したものがここにあります(衝突する2台の車)。


1

その他のSATの記事。

このサイトの最後の記事には完全なコードが付属しています.FLASHにあると思いますが、私は知りませんが、SATを初めて使用する必要があったときにC ++に変換する際に問題がまったくありませんでした他の言語についても同じことを行います。追加する必要があるのは、各計算で変位ベクトルを保存することだけです(最小の場合はもちろん、SATについて学習するとこれを理解できます)。このチュートリアルのコードはそれを行いません。最終的に計算されたベクトルになります。

http://rocketmandevelopment.com/tag/separation-axis-theorem/

良い、古いNゲームチュートリアル。ウェブ上で最高のSAT理論。

http://www.metanetsoftware.com/technique/tutorialA.html


すべての必要なクラスを含む完全な作業ソースを投稿する人がいらいらすることはありません。彼のコードを自分のデモに移植しましたが、うまくいきません。:(これはこれまでのところ私のプロジェクトです。誰かがそれをデバッグするのを手伝うことができれば素晴らしいです。 リンク
ジョシュアバーネット

それが機能しないとはどういう意味ですか?頂点を格納する方法に注意してください。デカルト座標系でそれらを持っている画像で、チュートリアルでは、重心に相対的なベクトルとして頂点を格納します(あなたがしなければならないのは、自分の頂点から重心を引くか、彼が自分の頂点を変更する行を削除します)、あなたが自分で作成できるドット積のような機能、あなたはそれらのためのガイドを必要とせず、残りは簡単でなければなりません、それはコピーペースト材料ではなく、それを実装する前にSATを学びます
-dreta

これは私がそれを実装した方法です:SAT.asShape2D.as、セントロイドとはどういう意味ですか?(x、y)などの多角形の中心?
ジョシュアバーネット

現時点では、元の画像で詳述されているように頂点を返す関数getOBB()があります。これは、形状の頂点、角度変数、位置変数を含むVector <b2Vec2>から計算されます。
ジョシュアバーネット

はい、センター、この男がポリゴンを作成する方法は、idk AS3のセンターからのオフセットを与えることですが、ドット積を計算するとき、頂点から重心を減算しようとすると、頂点をそのまま投影します(ベクトルのサブトラクション) )、これに加えて、どの分離ベクトルがまだ最小であるかをチェックせず、最後に計算されたもののみを保存します
-dreta
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.