简体   繁体   English

用于2D碰撞检测的四叉树

[英]Quadtree for 2D collision detection

I'm trying to use a quadtree for 2D collision detection, but I'm a little stumped on how to implement it. 我正在尝试使用四叉树进行二维碰撞检测,但我对如何实现它感到有点困惑。 First of all, I'd have a quadtree which contains four subtrees (one representing each quadrant), as well as a collection of objects which don't fit into a single subtree. 首先,我有一个四叉树,其中包含四个子树(一个代表每个象限),以及一个不适合单个子树的对象集合。

When checking an object for collisions in the tree, I would do something like this (thanks to QuadTree for 2D collision detection ): 当检查对象在树中的碰撞时,我会做这样的事情(感谢QuadTree用于2D碰撞检测 ):

  1. Check the object for collisions with any objects in the current node. 检查对象是否与当前节点中的任何对象发生冲突。
  2. For any subtree whose space overlaps the object, recurse. 对于其空间与对象重叠的任何子树,递归。

To find all collisions within a quadtree tree: 要查找四叉树中的所有碰撞:

  1. Check each object in the current node against each other object in the current node. 检查当前节点中的每个对象与当前节点中的每个其他对象。
  2. Check each object in the current node against each subtree. 根据每个子树检查当前节点中的每个对象。

To insert into a quadtree: 要插入四叉树:

  1. If the object fits into multiple subtrees, then add it to the current node, and return. 如果对象适合多个子树,则将其添加到当前节点,然后返回。
  2. Otherwise, recurse into whichever subtree contains it. 否则,递归到包含它的子树。

To update a quadtree: 要更新四叉树:

  1. Recurse into each subtree. 递归到每个子树。
  2. If any element in the current node no longer fits completely in the current tree, move it to the parent. 如果当前节点中的任何元素不再完全适合当前树,请将其移动到父节点。
  3. If any element in the current node fits into a subtree, insert it into the subtree. 如果当前节点中的任何元素适合子树,请将其插入子树中。

Is this alright? 这好吗? Can it be improved? 可以改进吗?

Your quadtree structure isn't optimal. 您的四叉树结构不是最佳的。 You're right to store 4 subtrees per node, but actual objects should only be stored inside the leaves, not inner nodes. 您每个节点存储4个子树是正确的,但实际对象应该只存储在叶子内部,而不是内部节点。 Therefore the collection holding the actual objects needs to be moved to the leaves. 因此,需要将保存实际对象的集合移动到叶子上。

Let's have a look at the implementation of the operations : 我们来看看操作的实现:

  1. Insert an object into the quadtree : 将对象插入到四叉树中
    Check if the object intersects the current node. 检查对象是否与当前节点相交。 If so, recurse. 如果是这样,递归。 If you've reached the leaf level, insert the object into the collection. 如果已达到叶级别,请将对象插入集合中。
  2. Delete an object from the quadtree : 从四叉树中删除一个对象
    Execute the exact same steps as if inserting the object, but when you've reached the leaf level delete it from the collection. 执行与插入对象完全相同的步骤,但是当您到达叶级别时,将其从集合中删除。
  3. Test if an object intersects any object inside the quadtree : 测试对象是否与四叉树内的任何对象相交
    Execute the exact same steps as if inserting the object, but when you've reached the leaf level check for collision with all the objects in the collection. 执行与插入对象完全相同的步骤,但是当您到达叶级别时检查是否与集合中的所有对象发生冲突。
  4. Test for all collisions between all objects inside the quadtree : 测试四叉树内所有对象之间的所有碰撞
    For every object in the quadtree execute the single object collision test. 对于四叉树中的每个对象,执行单个对象碰撞测试。
  5. Update the quadtree : 更新四叉树
    Delete all objects from the quadtree whose position has been modified and insert them again. 从位置已被修改的四叉树中删除所有对象并再次插入。

This has several advantages : 这有几个好处

  • By only storing objects in the leaves it is very easy to handle operations on the quadtree (fewer special cases) 通过仅在叶子中存储对象,可以很容易地处理四叉树上的操作(更少的特殊情况)
  • The quadtree can have leaves with different depth, thus allowing you to adapt the density of the quadtree depending on the spatial region it covers. 四叉树可以具有不同深度的叶子,因此您可以根据其覆盖的空间区域调整四叉树的密度。 This adaption can happen at runtime, thus keeping the object/node ratio optimal. 这种适应可以在运行时发生,从而保持对象/节点比率最佳。

Only disatvantage : 只有不利条件

  • Objects can belong to several collections inside the quadtree. 对象可以属于四叉树内的多个集合。 You're going to need an extra linear collection outside the quadtree to enumerate every object without duplicates. 您将需要在四叉树外部使用额外的线性集合来枚举每个对象而不重复。

Quad trees are not always the best data structure for collision detection. 四叉树并不总是用于碰撞检测的最佳数据结构。 The overhead of a quadtree can potentially be unbounded (if you don't limit the depth of the tree), and in the worst case don't give any speed up at all. 四叉树的开销可能是无限的(如果你不限制树的深度),并且在最坏的情况下根本不提供任何加速。 Instead, you might want to consider using a sparse grid, which gives better performance than a quadtree only without the extra overhead of traversing multiple tree levels. 相反,您可能需要考虑使用稀疏网格,这样可以提供比四叉树更好的性能,而无需遍历多个树级别的额外开销。

There are also other completely different approaches which might be even better. 还有其他完全不同的方法甚至可能更好。 For example, you could try implementing Zomorodian and Edelsbrunner's algorithm, as I did in the following module: 例如,您可以尝试实现Zomorodian和Edelsbrunner的算法,就像我在以下模块中所做的那样:

Here are also some articles which I wrote that discuss these issues in more detail: 以下是我写的一些文章,更详细地讨论了这些问题:

In particular, if you look at the benchmarks in the last section you will see that of all the libraries surveyed, quadtrees tended to perform quite poorly compared to other collision detection methods like R-Trees, grids or segment trees. 特别是,如果你看一下上一节中的基准测试,你将看到所有被调查的图书馆,与其他碰撞检测方法(如R-Trees,网格或细分树)相比,四叉树往往表现不佳。

I am not sure how cpu effective it is yet, but it seems to be working fine on my core duo in eclipse, still runs at over 2400 fps lol.. 我不确定它是如何有效的cpu,但它似乎在我的核心二重奏在eclipse中工作正常,仍然运行超过2400 fps大声笑..

basically, I added one list to collidable objects to store references to quadtree node objects that I have associated the object with (via inserting into the quadtree). 基本上,我向可碰撞对象添加了一个列表,用于存储我已将对象与之关联的四叉树节点对象的引用(通过插入到四叉树中)。 I also added a list to each quadtree node, that stores references to any objects deemed within the bounds of that node. 我还为每个四叉树节点添加了一个列表,该列表存储对该节点范围内的任何对象的引用。 So each node will only have one occurrence of each object. 因此每个节点只有一个对象出现。 each node also stores a reference to its parent node, for navigation to nearby nodes if I want to check any of them after the inital node for further collision accuracy. 每个节点还存储对其父节点的引用,用于导航到附近的节点,如果我想在初始节点之后检查它们中的任何一个以获得进一步的冲突准确性。

it's very easy to get references to all other objects in one cell: 在一个单元格中引用所有其他对象非常容易:

list temp_checklist = object.cells[cell_index].objects
//('objects' being some sort of array or list of object references as described above)

hope that helps someone ;) 希望能帮到某人;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM