2つの移動するAABBが交差するかどうかを確認する最も速い方法は何ですか?


12

移動している2つのAABBがありますが、フレームの下で交差するかどうかを確認する最も速い方法は何ですか?

移動するということは、通常の矩形交差法で確認するだけではなく、ブール値のみを返し、ヒット時間などを返さない、単純で簡単なスイープテストを意味します。

私が思うのは、単純に次のようにすることです。

この

しかし、その六角形は非常に複雑であり、AABB-ポリゴンの交差を計算する方法がわかりませんが、もっと簡単な方法はありますか?

あなたが最も気に入っているプログラミング言語であれば、簡単に移植できます。

ありがとう。


3
よくわかりません。「スイープテスト」について具体的に言及していますが、典型的なAABBスイープテストを試しましたか?それはまさにあなたが望むことをします。
SomeWritesReserved

1
上記のコメントに同意します-「クラシック」テストの何が問題になっていますか?さらに、ここで提案されているソリューションのほとんどは明らかにそれよりも明らかに遅いです...さらに、それらのいくつかは間違った結果を与える可能性があります(堅牢ではありません)。
ウォンドラ

回答:


8

ミンコフスキー和を使用する

この問題を解決するための良い方法は、運動の線との交点を考慮することである(V)の原点(に翻訳V「)とミンコフスキー和Aは、原点(で180度回転A」)とその障害物(単にBこの場合):A」B

次の図では、任意の座標系の原点にA smack-dabを配置しています。この180度の結果によりAを回転させるように理解簡素化A「及びVの原点に翻訳に等しいV」を

ミンコフスキー和は緑色の長方形であり、線AAA交差を行うことにより、移動Aと静止Bの交点を見つけることができます。これらのポイントには青い丸が付いています。

ミンコフスキー和-縮退ケース

次の図では、異なる原点が使用されており、同じ交差点が見つかりました。

ミンコフスキー和-より一般的な場合

複数の移動AABB

特定の期間中に直線的に移動する2つのAABBに対してこれを機能させるには、Aの速度ベクトルからBの速度ベクトルを減算し、それをラインとAAAB交差のラインセグメントとして使用します。

擬似コード

def normalize(aabb):
    return {x1: min(aabb.x1, aabb.x2), x2: max(aabb.x1, aabb.x2),
            y1: min(aabb.y1, aabb.y2), y2: max(aabb.y1, aabb.y2),

def rotate_about_origin(aabb):
    return normalize({x1: -aabb.x1, x2: -aabb.x2
                      y1: -aabb.y1, y2: -aabb.y2})

# given normalized aabb's
def minkowski_sum(aabb1, aabb2):
    return {x1: aabb1.x1+aabb2.x1, x2: aabb1.x2+aabb2.x2,
            y1: aabb1.y1+aabb2.y1, y2: aabb1.y2+aabb2.y2}

def get_line_segment_from_origin(v):
    return {x1: 0, y1: 0, x2: v.x, y2: v.y}

def moving_objects_with_aabb_intersection(object1, object2):
    A = object1.get_aabb()
    B = object2.get_aabb()

    # get A'⊕B
    rotated_A = rotate_about_origin(A)
    sum_aabb = minkowski_sum(rotated_A, B)

    # get v'
    total_relative_velocity = vector_subtract(object1.get_relative_velocity(), object2.get_relative_velocity())
    line_segment = get_line_segment_from_origin(total_relative_velocity)

    # call your favorite line clipping algorithm
    return line_aabb_intersection(line_segment, sum_aabb)

衝突応答

ゲームプレイに応じて、よりきめ細かい衝突検出を実行するか(AABBにメッシュが含まれる場合があります)、次のフェーズである衝突応答に進みます。

衝突がある場合、line-AABB-intersectionアルゴリズムは、AがB内での移動を終了するか、Bを通過するかによって、それぞれ1つまたは2つの交差点を返します。(これは、Aが側面またはそれぞれのコーナーの1つに沿ってBをかすめる縮退ケースを割引きます。)

いずれにせよ、線分に沿った最初の交点は衝突点です。これをワールド座標系の正しい位置に変換します(元のvに沿った2番目の画像の最初の水色の円、pと呼びます))そして、フレームの端でのAの実際の位置がどの位置になるか(At + 1)を決定します(例えば、pの衝突法線に沿ってvを反射することにより弾性衝突の場合)。

衝突応答

コライダーが2つ以上ある場合、vの 2番目の反射部分についても衝突検出を行いたいため、これはもう少し複雑になります。


ありがとう、最も興味深い。移動中にAとBが交差する場合の対処方法を説明してください。ただし、交差なしで移動を終了しますか?
GameAlchemist

@GameAlchemistそれは衝突応答であり、衝突検出ではありません(質問の元の主題)。しかし、私はペイントが好きなので、編集をチェックしてください。:-)
エリック

(スキームのとHURRA :-))アップデートのおかげで、これは私の質問はなかったが、私はAが完全にB.を通過するときに、あなたのアルゴリズムは、既にケースを扱うことを理解して助けた
GameAlchemist

5

OBB-方向付けられた境界ボックス。これがチュートリアルです

事実上、オブジェクトAの速度ベクトルをy軸(上方向)に揃えた境界ボックス。幅と高さは、オブジェクトAの開始点と終了点によって計算できます。次に、これをオブジェクトBのAABB(OOBBとして扱う)、およびゴールデンと比較します。

交差する可能性があるかどうかを確認する簡単な交差テストを探している場合は、開始位置と終了位置の両方でオブジェクトAのAABBを囲むAABBを作成できます。AABBがAABBを含むこのすべてと交差しない場合、交差はありません。ただし、これにより誤検知が発生する可能性があるため、予備テストとしてのみ使用してください。


4

OOBは必要なく、タイムステップ衝突検出を使用する必要もありません。通常のAABBスイープテストを使用してくださいこのリンクを参照してください。本質的には、ダイアグラムにあるとおりに動作します。移動するAABBは開始点から終了点まで「掃引」され、他の静的AABBに対する衝突検出に使用されます。

この「掃引テスト」が「影響時間」を返すために費用がかかるのではないかと心配している場合は、時期尚早に最適化すると思います。

掃引テストについてのより詳細な情報は、すばらしい本:Christer EricsonによるReal-Time Collision Detectionにあります。


3

AABB近似エッジケースの弱点

最初に動きをより小さなステップに分解し、その情報を使用して高レベルのAABBを計算する必要があります。大きなAABBが交差する場合は、小さなステップをチェックしてより正確にすることができます。

開始位置と終了位置のみを使用してAABB(またはOOBB)をチェックすることで衝突の可能性があるかどうかを推定すると、いずれかのオブジェクトが高速で回転し、ある次元が別の次元よりも長い場合、衝突を見逃す可能性があります。

より正確な推定AABBを計算するには、動きをより小さなステップに分解し、初期AABB(オブジェクトメッシュではない)のみを使用して、オブジェクトが回転して移動するたびにAABB(軸だけではなくボックスのみ)を回転しますステップ。各軸の最大点と最小点は、オブジェクトの動き全体を囲むAABBを提供します。

大きなAABBと交差する場合は、すでに計算されている小さなAABBを使用して、衝突が発生した可能性のある場所を特定できます。他のオブジェクトと交差する小さいAABBのそれぞれについて、より高価なメッシュ交差検出を行うことができます。


2
または、BBが回転できる最大幅を事前に計算し、それを使用します
ラチェットフリーク

2

動きをより小さな動きのステップに分解する必要があります。例えば:

大きなコンポーネント(この場合はX軸)を使用して動きを分解し、各ステップで衝突をチェックします。

これは非常に高価に見えるかもしれませんが、各サイクルでオブジェクトがそれ自身の幅よりも速く移動することは非常に速くなることを考慮してください。したがって、このシナリオは最初に考えるほど一般的ではありません。


2
この方法は、一部のケース(たとえば、最初に描いたボックスと2番目に描いたボックスに近いボックス)をキャッチできず、サンプリングの増加が過剰になるため、悪いです。SATを使用した単純なポリゴンテストは、十分に高速で信頼できるものでなければなりません。
ソペル

1
ええ、これは大丈夫ですが、あまり良い解決策ではありません。衝突がオブジェクトの角に近づくと精度が急激に低下し、速度が上がるとパフォーマンスが低下し(実装によっては精度が低下します)、不必要にハッキングされます。
BWG

2

また、衝突チェックに相対速度を使用して、一方のAABBが「静的」で、もう一方のAABBがそれ自体の速度から「静的」速度を引いた速度で移動するようにする必要があります。

交差する可能性があるかどうかを確認する最も速い方法は、移動するAABBを速度で拡張することです。

たとえば、AABBは0.1 x / frameで右に移動し、左端が同じままで右端がさらに0.1になるように拡張します。その後、新しいAABBで確認できます。falseの場合、衝突はありません。(小さな速度で早く戻り、正確)。

その後、移動オブジェクトの終了AABBと開始AABBが交差するかどうかを確認できます。trueの場合、trueを返します。

それ以外の場合は、対角線が静的ABBと交差するかどうかを確認する必要があります。

これには、x =静的の左端と右端がyが下と上にあるかどうかを確認する対角座標の取得が含まれます。(逆に繰り返します)

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