空間ハッシュと四分木に代わる2D空間分割


11

私はゲームに空間分割アルゴリズムを実装しようとしましたが、空間ハッシュと四分木の両方が私が探しているものではありません。

私のレベルサイズには制限がないことになっています(Int32制限のみ)。「レベル幅」と「レベル高さ」を必要としない空間分割アルゴリズムが必要です。

動いている物体がたくさんあります。500以上のオブジェクトをサポートできるほど高速なアルゴリズムが必要です。

代替案はありますか?

回答:


13

動的ツリー

Box2Dは、経験豊富な物理学/ゲームプログラマーによって設計された、最適化されたエンジンです。もともとBox2Dは、固定の高さと幅を必要とするハッシュグリッドを使用していました。

エリンがより優れたブロードフェーズアルゴリズムにアップグレードしたとき、彼はナタナエルプレッソンのbtDbvtを採用しました。これはBullet Physicsで使用されるブロードフェーズです。エリンは、2Dのアルゴリズムを変更および最適化しました。

Box2Dマニュアルで超高レベルの概要を読むことができます(§4.11、または動的ツリーを検索)。

コードのドキュメントからの例外を以下に示します(これはパブリックAPIの一部ではないことを考えると非常に便利です)。

ナタナエルプレッソンのbtDbvtに触発されたダイナミックなAABBツリーのブロードフェーズ。動的ツリーは、データをバイナリツリーに配置して、ボリュームクエリやレイキャストなどのクエリを高速化します。葉はAABBのプロキシです。ツリーでは、プロキシAABBをb2_fatAABBFactorで展開して、プロキシAABBがクライアントオブジェクトよりも大きくなるようにします。これにより、クライアントオブジェクトはツリーの更新をトリガーせずに少しずつ移動できます。

ノードはプールされ、再配置可能であるため、ポインターではなくノードインデックスを使用します。

動的ツリーのアルゴリズムについての私の理解はこれです。動的ツリーは、古典的なavlバイナリツリーとクワッドツリーのクロスです。最終的な効果は、各ノードを半分に分割するだけのクワッドツリーであり、分割線は固定されていません(2つの半分はクワッドツリーのように同じサイズではありません)。AVLが登場するのは、動的分割を備えたquadreeが本質的にリスト(O(n)ルックアップ速度)に退化する可能性があるためです。AVLは、O lg(N)ルックアップ速度を保証するためにサブツリーを再調整するために使用されます。

すべてのコードの中で最も優れているのはMITであるため、自由にコピー、派生、恥知らずに盗むなどを行ってください。


見えます...複雑です!しかし、私はそれを見てみましょう。誰かが「スイープとプルーン」または「ソートとスイープ」のテクニックを使用することを提案しましたが、C#または.NET実装について何も見つかりませんでした。c ++の例を見つけましたが、それは混乱を招き、機能しませんでした(とにかくそれを実装しようとしました)。SAPの方が実装が簡単だと思いますか?.NET実装はありますか?
Vittorio Romeo

8

これはGamedevでここで尋ねられた同様の質問に非常に近いですが、ファイルストレージではなくパフォーマンスに関心があるので、おそらく私の答えがもっと役立つでしょう。完全を期すために、ここではその大部分を含めますが、調べたい場合は、元の答えでもう少し深みがあります。

私は同様の問題に遭遇し、データを処理するために独自の構造を作成することにしました。それは大まかに四分木に基づいていますが、すべての方向に無限(少なくともIntと同じ大きさ)の拡張性を持っています。これは、Minecraftが現在行っているように、中央から拡張されたグリッドベースのデータを処理するように設計されています。それは、メモリのスペース効率がよく、非常に高速です。

私のコードはここにあります。コードは完全で、テスト済み(ユニットテストと負荷テスト)、そして非常に最適化されています。内部の仕組みはまだ十分に文書化されていませんが、すべてのパブリックメソッドは使用できるはずです。誰かが試してみることにした場合は、質問やコメントで私に連絡してください。


1

比較的少数(<数千)の小さめのオブジェクト(ほとんどのオブジェクトは他の多くのオブジェクトと衝突する可能性があるほど大きくない)を操作すると、軸方向に整列した境界ボックス(AABB)の単純なx順リストが機能することがわかりますかなりよく。オブジェクトをリストに配置し、オブジェクトを移動した後の各フレームで、リストをx値ですばやく並べ替え、リストを1回通過してAABBの近接性を確認します。各オブジェクトについて、リストの最後に到達するか、またはxの範囲外のオブジェクトに到達するまで、リスト内のそれより前のオブジェクトと照合します。つまり、左端のx値は、テストされるオブジェクトの右端のx値よりも大きくなります。基本的に、スペースを動的に、重複するAABB-x-widthサイズのスライスに分割します。それ'


0

たぶん、r-treeアルゴリズムがあなたが探しているものです。

私は静的なジオメトリに対しては非常にうまく機能しますが、オブジェクトを新しい位置で削除したり追加したりして、オブジェクトを移動するためにも使用できます。


私はC#実装を試しましたが、「オブジェクトを新しい位置に削除して追加する」と、パフォーマンスが非常に悪くなりました。
Vittorio Romeo

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