Data structures 移动对象的空间数据结构?

Data structures 移动对象的空间数据结构?,data-structures,geometry,collision-detection,spatial,neighbours,Data Structures,Geometry,Collision Detection,Spatial,Neighbours,我想知道处理大量移动对象(球体、三角形、长方体、点等)的最佳数据结构是什么?我试图回答两个问题,最近邻和冲突检测 我知道传统上,像R树这样的数据结构用于最近邻查询,Oct/Kd/BSP用于处理静态对象或很少移动对象的碰撞检测问题 我只是希望有其他更好的东西 非常感谢您的帮助。边界球体可能会帮助您处理许多移动的对象;计算对象的半径平方,并从其中心跟踪它。如果两个对象中心之间的平方距离小于两个对象的平方半径之和,则可能发生碰撞。用平方距离做的每件事;没有平方根 您可以按对象之间的最小平方距离对最近邻

我想知道处理大量移动对象(球体、三角形、长方体、点等)的最佳数据结构是什么?我试图回答两个问题,最近邻和冲突检测

我知道传统上,像R树这样的数据结构用于最近邻查询,Oct/Kd/BSP用于处理静态对象或很少移动对象的碰撞检测问题

我只是希望有其他更好的东西


非常感谢您的帮助。

边界球体可能会帮助您处理许多移动的对象;计算对象的半径平方,并从其中心跟踪它。如果两个对象中心之间的平方距离小于两个对象的平方半径之和,则可能发生碰撞。用平方距离做的每件事;没有平方根

您可以按对象之间的最小平方距离对最近邻进行排序。当然,碰撞检测可能会变得复杂,对于非球形对象,边界球体不一定能获得碰撞信息,但它可以很好地修剪需要比较碰撞的对象树

当然,您需要跟踪对象的中心;理想情况下,您希望每个对象都是刚性的,以避免必须重新计算边界球体大小(尽管重新计算并不特别困难,特别是如果您使用一个刚性对象树,每个刚性对象都有自己的边界球体,用于非刚性的对象,但这会变得复杂)

基本上,要回答有关数据结构的问题,可以将所有对象保留在主数组中;我有一组“区域”数组,其中包含对主数组中对象的引用,您可以根据对象的笛卡尔坐标快速对对象进行排序;“区域”阵列的重叠定义应至少为主对象阵列中最大对象半径的2倍(如果可行,则会出现对象边界球体缩放与对象数量对比的问题)

一旦你做到了这一点,你就可以通过比较一个区域内所有对象之间的距离来进行快速碰撞测试;同样,这也是区域定义变得重要的地方,因为你在区域数量和比较数量之间做了一个重要的权衡。然而,仅仅因为你的距离比较ome可以归结为简单的减法运算(当然还有abs()运算)

当然,您必须在非球形对象之间执行实际的碰撞检测,这是非常重要的,但是在这一点上,您已经大大减少了潜在比较的数量

基本上,它是一个两层的系统;第一层是区域数组,通过它可以对场景进行粗略排序。第二层是区域内距离比较;在这里,您将对发生碰撞的对象进行基本的碰撞检测和碰撞标记


这种算法可能有空间在动态区域确定中使用树来平衡区域大小,以确保区域大小不会因“拥挤”而增长过快“区域;然而,这类事情并非微不足道,因为对于不同大小的对象,您对密度的排序变得。。。至少可以说是复杂的。

进行碰撞检测的一种有趣方法是使用特殊八叉树结构中组织的轴向对齐边界框(AABB)。AABB提供了帮助,因为它们使粗略碰撞计算非常快速,因为您最多只需要执行6次比较

对于八叉树结构,您应该使用以下几个技巧:

1) 节点占用的边界区域应该是普通八叉树的两倍大(其中八叉树将空间分割而不重叠)。因为每个节点应重叠其相邻节点面积的一半。由于AABB只能属于一个节点,因此这种额外的大小和重叠允许它在一个节点中停留更长的时间

2) 此外,在每个节点中,可能在层次结构的每个级别中,都会保持与节点邻居的链接。这将涉及大量额外的代码,但它将允许您在接近O(1)的时间(而不是O(2logn)的时间)内在节点之间移动元素

如果八叉树占用太多内存,您可以将其更改为使用稀疏八叉树结构,只保留游戏世界中实际包含实体的部分的树。然而,这意味着当实体在世界中移动时,必须对每个帧执行更多的计算

您可能希望尝试使用kd树(我相信这是正确的名称)来代替八叉树,或者使用AABB从下到上构建结构

KD树(来自内存)使用轴向对齐的平面划分空间,因此非常适合与AABB一起使用

另一个想法是,不要强迫八叉树的生成自上而下(从一个环绕整个世界的盒子开始),而是从基本实体开始构建,然后构建更大的AABB,直到最大的一个包含整个世界。虽然我不确定它将如何与许多快速移动的实体一起工作

(我已经有一段时间没有做过这种空间游戏开发编码了。)

  • 可以在八叉树中分割场景,并利用场景一致性。您正在测试的移动对象将位于树的特定节点中,具体帧数取决于其速度。这意味着您可以假定它将位于节点中,因此可以快速剪切许多不在节点中的对象。当然,棘手的一点是,当对象靠近分区的边缘时,必须确保更新哪个节点