我正在开发一个2D物理引擎,希望添加广义相撞检测,但我只知道2或3种方法:
- 对每个物体都进行相互检测 (O(n^2) 复杂度)
- 扫描和修剪(排序和扫描)
- 关于二进制空间分割的某些内容(不确定如何实现)
但是肯定还有更多选项,对吗?它们是什么?每个算法可以提供基本描述或指向其描述的链接吗?
我看过这个,但我想要的是可用算法列表,而不是最适合我的需求的算法。
在这种情况下,“广义相撞检测”是物理引擎用来确定模拟中哪些物体足够接近以需要进一步调查和可能进行碰撞解决的方法。
我正在开发一个2D物理引擎,希望添加广义相撞检测,但我只知道2或3种方法:
但是肯定还有更多选项,对吗?它们是什么?每个算法可以提供基本描述或指向其描述的链接吗?
我看过这个,但我想要的是可用算法列表,而不是最适合我的需求的算法。
在这种情况下,“广义相撞检测”是物理引擎用来确定模拟中哪些物体足够接近以需要进一步调查和可能进行碰撞解决的方法。
SphereTrees(在2D中为CircleTrees,实现方式或多或少相同)是四叉树或二叉空间划分树的替代方案。SphereTrees的优点是它们能够很好地处理大量动态对象的负载。如果您的对象经常移动,则BSPTrees和QuadTrees在更新时比Sphere/Circle Tree要慢得多。
如果您有良好的静态和动态对象混合,一个相当好的解决方案是使用QuadTree/BSPTree来处理静态对象,使用Sphere/Circle Tree来处理动态对象。只需记住,对于任何给定的对象,您都需要检查它是否与两棵树相交。
一种替代方案是使用简单的网格,比如20x20或100x100(取决于您的世界和内存大小)。这种实现比递归结构(如四叉/bsp树,或球形树)要简单。
在这种情况下,穿过单元格边界的物体会更加简单,并且不像bsp / quad / oct-tree的naive实现那样退化。
使用这种(或其他)技术,您应该能够快速剔除许多对并获得需要进一步研究的潜在碰撞集。
我刚想出了一个解决方案,它不依赖于网格大小,可能是O(nlogn)(当没有碰撞时是最优的),但最坏情况下为O(nnlogn)(当所有东西都发生碰撞时)。
我还实现并测试了它,这里是源代码的链接。但我还没有将其与暴力解决方案进行比较。
它的工作原理描述如下: (我正在寻找矩形之间的碰撞)
在x轴上,我根据矩形的右边缘进行排序(O(nlogn))
对于排序后列表中的每个矩形,我取左边缘并进行二分查找,直到找到左边缘左侧最右边的边缘,并将这些矩形插入到可能发生碰撞的X轴集合的这些索引之间(这些是n个矩形,二分查找需要logn,每次插入集合需要O(log n))
在y轴上,我也是同样的操作
现在,在每个集合中,我都有可能在x轴上发生碰撞(在一个集合中)和在y轴上发生碰撞(在另一个集合中),我相交这些集合,现在我有了x轴和y轴上的碰撞(也就是我取公共元素)(O(n))
很抱歉描述不太清楚,希望您能从源代码中更好地理解,这里还有一个示例:image
如果你的物体在一个有边界的空间内移动,那么你可以使用网格来将物体分割。将每个物体放入物体完全或部分占据的每个网格单元中。要检查A对象是否与其他对象发生碰撞,请确定A对象覆盖的网格单元格,然后获取这些单元格中唯一对象的列表,并最终测试A对象与每个唯一对象。如果大多数对象通常包含在单个网格单元格中,则此方法效果最佳。
如果你的空间没有边界,则需要实现某种动态网格,在2D中可以根据需要向四个方向扩展。
与更适应性算法(即BSP、Quadtree、Circletree)相比,这种方法的优点是单元格可以在O(1)时间(即常量时间)内访问,而不是O(log N)时间(即对数时间)。但是后者能够自适应于对象密度的大变化。当物体密度在整个空间中相当恒定时,网格方法效果最佳。