Algorithm 碰撞检测中的优化

Algorithm 碰撞检测中的优化,algorithm,optimization,collision-detection,Algorithm,Optimization,Collision Detection,我正在搜索有关碰撞检测优化的信息 有一个物体(圆)正在从点a移动到点b。这个物体的半径为r,在这个区域也有很多障碍物(圆) 我有一个算法(函数)来检查圆和胶囊之间的碰撞,目前我为每个障碍物调用此函数: for-each (o : obstacles) if collide(o, Capsule(a,b,r)) return true; return false; 许多障碍物离运动物体很远,使用碰撞检测功能检查时可以忽略这些障碍物 我的问题是: 是否有一种解决方案可以忽略使用碰撞

我正在搜索有关碰撞检测优化的信息

有一个物体(圆)正在从点a移动到点b。这个物体的半径为r,在这个区域也有很多障碍物(圆)

我有一个算法(函数)来检查圆和胶囊之间的碰撞,目前我为每个障碍物调用此函数:

for-each (o : obstacles)
  if collide(o, Capsule(a,b,r))
    return true;

return false;
许多障碍物离运动物体很远,使用碰撞检测功能检查时可以忽略这些障碍物

我的问题是:

是否有一种解决方案可以忽略使用碰撞检测功能检查所有障碍物?类似于最近邻搜索
或KD树



编辑:所有障碍物都有相同的半径。

作为第一步,您可以忽略不在某一帧/框中的所有障碍物

例如,y坐标(障碍物形状的y-最低点)大于a和b的最大y坐标+移动物体半径相同距离的所有障碍物都可以忽略。对于较低的y边框和x边框类似。 代替一个盒子,您可以进一步将类似的分支分成两个(或更多)盒子。例如,将a-b的距离分成两个距离,并对(a,(b-a)/2),/(b-a)/2,b)中的每一个进行上述步骤


但这完全取决于与碰撞过程相比,比较这些值的效率。

您可以简单地使用一个网格,其中每个单元格容纳所有接触该单元格的障碍物。现在只检查你的胶囊接触到的细胞有无碰撞。
另外,你也可以使用四叉树,但根据我的经验,网格通常就足够了,而且它的优点是在障碍物移动的情况下可以轻松快速地更新

我可以推荐一条怪兽曲线,例如希尔伯特曲线。它是一种四叉树或类似kd树的数据结构,它将二维复杂性降低为一维问题。在每一帧中,你只需要从一开始构建怪物曲线,这样就不用在四叉树或kd树中删除或插入。它还有一些更好的二维平铺特性,但在您的情况下可能不需要这些特性

对马丁回答的评论:

我制作了一个类似于
的盒子(a.x-R,a.y-R,b.x+R,b.y+R)
其中
R
ObjectRadius+ObstacleRadius
,然后扔掉所有不在这个盒子里的障碍物。在图中,仅检查带有黄点的障碍物:

  • 将障碍物的中心放入KD树
  • 找到最近的中心
  • 检查它是否比ObstacleRadius更接近

  • 您可以尝试在代码中实现空间分区。通过将每个对象/障碍划分为覆盖整个空间或地图的每个框。这样做就是将障碍物分成若干部分。因此,只需在一小部分内检查碰撞,就可以大大减少碰撞检查。如果你的障碍物没有移动,你只需要对每个障碍物进行一次分区。如果它们正在移动,您必须每次更新每个障碍的分区[重新分组]

    空间分区技术已经存在了相当长的一段时间,这里有一个链接可以帮助您实现


    您有多少障碍?它们的密度有多大?碰撞是经常发生还是很少发生?想想100个障碍物,它们是稀疏分布的。算法每10毫秒调用一次。我认为我的程序的瓶颈是这个问题。你应该尝试分析你的程序,以确保你找到了瓶颈。另外,kd树似乎适合您的问题,如果它有帮助,您尝试过吗?我以前使用kd树查找到给定点的最近点。但在这种情况下我不知道如何使用kd树!这个看起来很漂亮。尽管您可能需要稍微扩展这个框,以便所有的粉红色路径(+security R)都包含在其中(上面我假设a和b通过一条线连接)。小黑线表示什么?这是没有R防护罩的盒子。它工作得很好,我不得不在几个地方编辑代码。