全动态KD树与四叉树?


11

在开发游戏时,我正处于需要跟踪世界上所有单位的地步,以便可以进行最近邻检查以进行战斗。这是一款类似于RTS的游戏,可能有成千上万的小型自动化单位在移动。

我一直在研究KD树和四叉树(尤其是点四叉树)。我仍在尝试了解它们如何工作的详细信息,但是到目前为止,Point Quadtree对我来说最有意义。但是,我的印象是KD-Trees的搜索速度更快,这对我在树中拥有的点数很重要。

另一方面,就我而言,我将跟踪大量始终在移动的单元。从一帧到另一帧,它们的位置将始终不同。四叉树显然比KD-Trees重平衡更快,但是我不知道当您重新平衡树中的每个点时是否适用。

我想知道在这种情况下,最好只是逐帧废弃树并从头开始重建它,而不是尝试重新平衡树中的每个点?如果Quadtree重新平衡的速度更快,是否也意味着从头开始构建的速度更快?如果是这样,那对性能而言可能比KD-Tree的搜索速度更重要,这取决于创建树的负担,但我不知道...

Answers:


12

老实说,KD树绝对不够动态。移动几个单元很容易需要您重建整个KD-Tree。另外,KD树对于查询非常有效,但对于邻居搜索则不是那么有效。

随着时间的推移,四叉树会更加灵活,因为修改会保留在本地。缺点是,如果您在一个位置上有很多经常移动的设备,则可能细分太多,并且由于设备的移动而需要进行大量更新。您可以设置一个阈值,在该阈值下不能进行细分。但是要提防,这意味着很多单元可能都位于同一叶正方形中。

但是,如果您只想查找恒定半径r内的所有单位,则不需要立即使用四叉树和kd树。您可以简单地创建长度为r的单元格的2D数组,然后根据其位置将单元堆叠在每个单元格中。这样一来,您至少要搜索9个单元格。仅当您的地图很大时,此类网格才会太大而无法实现。

我们没有讲过另外两种完全不同的结构:层次AABB和本地敏感哈希表。如果相对于父级ABB来描述每个层次AABB的起源,那么它的优点是,如果一大群单位保持其形成,那么您无需更新较小的AABB,因为它们保持相同的相对位置。当然,旋转地层可能会导致许多更新,在这种情况下,使用其他边界体积(例如球体或定向边界框(OBB))可能会更有效。

本地敏感的哈希表只能有效地提供近似的解决方案,因此我不会理会它们。

我该怎么办?我可能会从一个简单的网格开始,并在需要时将其升级为四叉树,如果需要,我将其与某个阈值以下的边界体积层次结构结合使用:四叉树在较大范围内运行良好相对边界体积在小范围内效果很好。逐步进行操作,我不必从一开始就花费数小时立即获得最佳数据结构。


谢谢!我还没有听说过AABB分层结构和本地敏感的哈希表,我将在将来对其进行研究。现在,我将使用一个简单的网格,并且如您所提到的,将在需要时进行扩展。:)
Nairou

4

Lærne的建议很好,但我也建议使用AABB的动态边界体积树。从概念上讲,动态边界体积树保持节点的平衡树,可以通过传入AABB并检索重叠对来随时查询附近元素。并非每帧都重建树。取而代之的是,每个节点的AABB在放入树中时都会稍微膨胀,并且仅在膨胀的ABB不再包含节点的实际ABB时才重建树。我在物理引擎中使用了它,效果很好。

Box2D源代码可以很好地实现它。

https://github.com/erincatto/Box2D/blob/master/Box2D/Box2D/Collision/b2DynamicTree.h

这是对其实施的良好回顾:

http://www.randygaul.net/2013/08/06/dynamic-aabb-tree/


是的,这或多或少是我所说的AABB分层系统的意思,我不是很精确。哦,在RTSes中,单位通常是可移动的,但在编队中。因此,使用相对于父AABB节点的坐标可能会非常有效,并具有“通胀”误差幅度。
Lærne

您可以更新Google代码链接吗?
kolenda '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.