如何在 Bullet 中找到投射光线以避免碰撞的位置?

Posted

技术标签:

【中文标题】如何在 Bullet 中找到投射光线以避免碰撞的位置?【英文标题】:How to find where to cast a ray to avoid collision in Bullet? 【发布时间】:2012-12-28 21:32:23 【问题描述】:

假设我们在 A 点有一个物体。它想知道它是否可以移动到 B 点。它的速度有限,所以它只能一步一步地移动。它向其移动的方向投射光线。射线与物体碰撞,我们检测到它。如何获得一种安全地通过我们的光线(避免碰撞)的方法?

顺便说一句,在物体投射的情况下,有没有办法让这种事情起作用,它会像简单的光线投射一样/几乎快吗?

有没有办法在某些不同的路径中找到最佳路径?

【问题讨论】:

是要避免一个对象还是任意数量的对象?它是在平面空间还是 3 维空间中? A 在路上时障碍物会移动吗? 什么衡量一个逃避选择的成功? 是要避免一个对象还是任意数量的对象?是的 - 10 k 的物体,3 维空间,A 在路上时障碍物会移动吗?没有。 什么衡量逃跑选择的成功与否?在(物体)中,光线投射在给定的步距内不得与任何障碍物发生碰撞。 【参考方案1】:

您所问的实际上是一个寻路问题;更具体地说,它是“任意角度寻路问题”。

如果您可以将障碍物的边缘限制为网格,那么一个流行的解决方案是在该网格上使用 A*,然后应用路径平滑。但是,有一个 (相当新的) 算法,它既易于实现/理解,又比路径平滑提供更好的结果。它被称为Theta*。

有一篇很好的文章解释了 Theta*(我从中偷了上面的图片)here


如果您不能将障碍物限制在网格中,则必须为您的地图生成navigation mesh:

有很多方法可以做到这一点,复杂程度各不相同;参见例如here、here 或here。快速的 google 搜索还可以找到大量可用的库,例如 this one 或 this one。

【讨论】:

【参考方案2】:

一种方法可能是使用一根绳子或几根绳子,其中一根绳子由几个线性连接的点组成。可以在空间的任意位置初始化点,但第一个点是A的初始位置,最后一个点是A的最终位置。

最初,绳索将是一条非常糟糕的路线。为了优化,沿着能量梯度移动点。在您的情况下,能量函数非常简单,即绳索的总长度。

这不是一个新想法,但在计算机视觉中用于检测物体的边界,尽管能量函数要复杂得多。然而,看看“蛇”,让您了解如何在给定两个邻居的情况下移动每个点:http://en.wikipedia.org/wiki/Snake_(computer_vision)

然而,在你的情况下,简单地从相邻点施加的力推导出每个点的方向就可以了。

您的问题是您考虑碰撞的受限问题。我真的会在这里使用@paddy 的想法来使用凸包,甚至只是为每个对象使用一个球体。在后一种情况下,不要将一个点移动到它到B的距离小于A的半径加上B的半径的地方strong> 考虑到你没有无限多的点,再加上一个软糖因素。

一个有效的解决方案要求任何邻居之间的最长距离小于一个阈值,否则,两点之间的连接线将与障碍物相交。

【讨论】:

绳索/蛇快吗? (比如 10 000 个物体(简单的盒子和金字塔)在 i7 核心上以随机方向移动) 如果您正在规划 10,000 个对象的路线,将彼此视为障碍物,恐怕这种方法可能不适合您。【参考方案3】:

从一个简单的方法开始怎么样......

如果这只是一个对象,您可以计算障碍物所有顶点的凸包,以及起点和终点。然后,您将通过顺时针和逆时针穿过船体来检查从 A 到 B 的两个方向。选择最短路径。

它有点复杂,因为你移动的形状不仅仅是一个点。你不能只是盲目地移动它的中心,否则它会发生碰撞。当它经过一个顶点时,它会变得更加复杂,因为您必须将对象的边缘擦过障碍物的顶点。

但希望这能给你一个思考的想法,这在概念上并不难理解。

【讨论】:

我有 10k 个物体,还有更多……都在移动……而且所有物体都不应该碰撞并保持速度……(【参考方案4】:

我制作这张图片是为了告诉我将物体到达 B 点的想法。 图像中的对象:- 深蓝色的点代表对象。红线是障碍物。灰色的点和线是可以到达的区域。紫色箭头是 B 点的方向。对象的灰色线是可见范围。 了解图像:- 该对象将具有一定的视野范围。这是二维情况,所以我假设能见度为 180 度。 (对于人的视野,请参考http://en.wikipedia.org/wiki/Human_eye#Field_of_view)对象将使用声纳的思想来测量距离。在声纳的帮助下,物体可以找到它可以到达的区域。使用 BACKTRACKING,对象可以找到到达对象的路径。如果无路可走,则该对象必须更改其可见范围

【讨论】:

【参考方案5】:

看待这个问题的一种方法是作为阴影投射问题。将A 设为“光源”,然后决定场景中的每个点是在阴影中还是阴影中。那些不在阴影中的人可以通过来自A 的光线访问。其他地区则不然。如果你发现B 在阴影中,那么你只需要找到场景中最近的光照点。

如果您将此问题离散为“像素”,那么上述方法在有关阴影渲染的大量计算机图形学文献中具有非常著名的解决方案。例如,您可以使用Shadow Map 为每个像素绘制一个布尔标志,指示它是否处于阴影中。找到最近的发光像素只是简单地搜索围绕B 不断增长的同心圆。通过利用 GPU 硬件,这两个操作都可以变得非常快。

另一个注意事项:您可以将一般对象路径查找问题视为点路径问题。秘诀是使用 Minkowski 差异将障碍“增加”适当的数量。参见例如this work on robot path planning。

【讨论】:

以上是关于如何在 Bullet 中找到投射光线以避免碰撞的位置?的主要内容,如果未能解决你的问题,请参考以下文章

使用光线投射和实例化对象问题检查与多边形碰撞器的碰撞(统一)

Unity3D 5.x 交互功能 - 光线投射碰撞设置

Three.js 用于碰撞检测的光线投射

Hololens 2 的光线投射问题

光线投射中的方向向量

使用光线投射的对象拾取