Collision & spatial queries

Axis-Aligned Bounding Box / AABB

軸平行包囲箱

軸に平行な箱で衝突候補を絞る。

3 / 10

Interactive demo

Preparing the demo…

Axis-Aligned Bounding Box / AABB

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

物体を、座標軸に平行な辺だけでできた箱で囲んだものです。「x の最小と最大」「y の最小と最大」「z の最小と最大」の 6 つの数だけで表せ、2 つの箱が重なるかは、軸ごとに区間が重なるかを比べる 6 回の比較で決まります。形が複雑な物体どうしの正確な判定は重いので、まず AABB どうしで「重なっていない組」を安く捨て、残った組だけを正確に調べます。

ゲームでの使いどころ

  • 衝突の候補を絞る:物理エンジンの広域判定は、ほぼ必ず AABB を使う。
  • 木構造の箱:BVH や四分木・八分木の節の範囲。
  • 画面外の判定・カリング:物体の AABB が視錐台の外なら描かない。
  • 2D ゲームの当たり判定:回転しないキャラクターやタイルなら、AABB どうしの判定だけで十分なことが多い。

しくみ

AABB は最小の角 min\mathbf{min} と最大の角 max\mathbf{max} で表します。2 つの箱 A、B が重なるのは、すべての軸で区間が重なるときです。

Amin⁡,x≤Bmax⁡,x  ∧  Amax⁡,x≥Bmin⁡,x  ∧  (y と z も同様)A_{\min,x} \le B_{\max,x} \;\land\; A_{\max,x} \ge B_{\min,x} \;\land\; (\text{y と z も同様})

1 つの軸でも重ならなければ、その時点で「重なっていない」と決まります(分離軸定理の、軸が座標軸に固定された特別な場合)。

回転する物体の AABB:物体が回転すると、囲む箱の大きさが変わります。作り方は主に 3 つです。

  • 頂点から作り直す:物体の頂点(箱なら 8 つの角)をすべて変換し、最小と最大を取ります。ぴったりですが、頂点の多いメッシュでは重くなります。
  • 元の箱を回して囲む:物体の元の AABB の 8 つの角だけを変換して囲みます。速いですが、少し大きめになります。中心と半分の大きさ e\mathbf{e} を使えば、回転行列の各成分の絶対値 ∣R∣|R| を掛けるだけで求まります(e′=∣R∣ e\mathbf{e}' = |R|\,\mathbf{e})。
  • 回転しても変わらない箱:物体を囲む球の半径で立方体を作ります。回転のたびに作り直す必要はありませんが、大きすぎて候補が増えます。

実装のポイント

  • 少し太らせる:動く物体の AABB を毎フレーム作り直す代わりに、少し大きめ(ファット AABB)にしておき、中身がはみ出したときだけ作り直すと、木構造の更新が減ります(Box2D の動的 AABB 木)。
  • 速度の分だけ伸ばす:速い物体は、次のフレームまでの移動分を含むように伸ばしておくと、連続衝突判定の候補も拾えます。
  • 中心と半分の大きさで持つ:重なりの判定は ∣ca−cb∣≤ea+eb|c_a - c_b| \le e_a + e_b を軸ごとに比べる形でも書けます。こちらの方が変換には便利です。

つまずきやすい点

  • 細長い物体を斜めにすると大きくなる:棒を 45° 回すと、AABB は棒の何倍もの面積になり、候補が大量に増えます。そういう物体には、回転に合わせた箱(OBB)やBVH を使います。
  • 等号の扱い:辺がちょうど接している場合を重なりとするかどうかを、全体でそろえます。
  • AABB の重なり=衝突ではない:箱が重なっても、中の物体が接触しているとは限りません。正確な判定と混同しないようにします。

デモで試すこと

  1. 回転しながら飛び回る 16 個の箱に、白い線の AABB が付いています。AABB がほかと重なると黄色になり、中の箱が本当に接触すると箱が赤くなります。
  2. 左下で、120 組のうち AABB が重なった組(候補)と、本当に接触した組の数を比べてください。正確な判定は候補の組だけで済みます。
  3. 「回転しても変わらない立方体」にすると、箱がずっと大きくなり、候補の数と「AABB の体積 / 箱の体積」が増えます。
  4. 「動く速さ」を 0 にして、止まった状態でじっくり比べることもできます。

References

Box2D Collision ↗

A general reference for this subcategory.