空间散列和四叉树的2D空间分区替代方案


11

我一直在尝试在游戏中实现空间分区算法,但是空间散列和四叉树都不是我想要的。

我的级别大小不应该有限制(只有Int32限制)。我需要一个不需要“水平宽度”和“水平高度”的空间分区算法。

我有许多移动的物理对象。我需要算法足够快以支持500多个对象。

还有其他选择吗?

Answers:


13

动态树

Box2D是由经验丰富的物理/游戏程序员设计的经过良好优化的引擎。最初,Box2D使用的哈希网格要求高度和宽度固定。

当Erin升级到更好的广相算法时,他选择了Nathanael Presson的btDbvt。这是Bullet Physics使用的主要阶段。Erin修改并优化了2d算法。

您可以在Box2D手册(第4.11节,或搜索“动态树”)中阅读最高级别的概述。

这是in 代码文档中的一个例外(考虑到它不是公共API的一部分,所以非常好)。

受Nathanael Presson的btDbvt启发,动态AABB树处于宽相状态。动态树将数据排列在二叉树中,以加速诸如体积查询和射线投射之类的查询。叶子是带有AABB的代理。在树中,我们通过b2_fatAABBFactor扩展代理AABB,以使代理AABB大于客户端对象。这允许客户端对象少量移动而不会触发树更新。

节点是可合并和可重定位的,因此我们使用节点索引而不是指针。

我对动态树算法的理解是这样的。动态树是经典avl二叉树和四叉之间的交叉。最终效果是四叉树,该四叉树仅将每个节点分成两半,并且分割线不是固定的(两半的大小不像四叉树一样)。AVL之所以出现,是因为具有动态拆分的四边形可以退化为一个列表(O(n)查找速度)。AVL用于重新平衡子树,以确保O lg(N)查找速度。

最好的代码是MIT,因此可以随意复制/派生/无耻窃取/等等。


看起来...复杂!我会看一下。有人建议我使用“扫描和修剪”或“分类和扫描”技术,但我找不到有关C#或.NET实现的任何信息。我找到了一个c ++示例,但它很混乱,而且没有用(无论如何,我还是试图实现它)。您认为SAP实施起来会更容易吗?是否有.NET实现?
罗密欧

8

在Gamedev上询问的类似问题非常接近,但是由于您关注性能而不是文件存储,也许我的回答对您会有更多用处。为了完整起见,我将在此处包括大部分内容,但是如果您想对其进行深入研究,原始答案会提供更多的深度。

我遇到了类似的问题,并决定创建自己的结构来处理数据。它松散地基于四叉树,但是在所有方向上都具有无限的(至少与Int一样大)可扩展性。它旨在处理从中心点扩展的基于网格的数据,就像现在的Minecraft一样。它在内存中节省空间,而且速度非常快。

我的代码可以在这里找到。该代码是完整的,经过测试的(单元测试和负载测试),并且经过了优化。但是,内部工作方式还没有得到很好的记录,但是所有公共方法都可以使用。如果有人决定尝试,请随时向我提出问题或评论。


1

当使用相对较少(小于几千个)的小物体(大多数物体的大小不足以与许多其他物体发生碰撞)时,我发现一个简单的轴向排列的包围盒(AABB)的x顺序列表有效很不错。我只是将对象放入列表中,然后在移动对象后的每一帧中,按x值对列表进行快速排序,然后一次遍历列表以检查AABB邻近度。对于每个对象,我都将其与列表中前面的对象进行比较,直到到达列表的末尾或超出x范围的对象为止。也就是说,它的左边缘的x值>被测试对象的右边缘的x值。它基本上将空间动态地划分为有时重叠的,AABB-x宽度大小的切片。它'


0

也许您正在寻找r树算法

我在静态几何体上确实工作得很好,但是您也可以通过在新位置移除和添加对象来将其用于移动对象。


我尝试了C#实现,并且“在新位置删除和添加对象”时性能太差了。
罗密欧

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.