小型高速物体碰撞:避免隧道效应


14

编辑/更新:我现在最大的问题是步骤3的“ t = ...”等式是一个好主意还是有更好的方法来做到这一点。大多数其他问题已得到部分或完全解决,但没有任何评论或答案真正涉及此问题。同样,对于我可以想到的任何迭代/递归解决方案(下面的注释中有一些建议),可能都需要解析解决方案,速度和距离太大,对象也太小(尽管有一种特殊的迭代/递归解决方案,可以很好地处理此类情况,那么我肯定会接受)。到目前为止,非常感谢您的帮助,你们都很棒,我非常感谢您的想法和帮助!

我正在尝试检测小型高速物体之间的碰撞。在这种情况下,即使以相对较低的速度,也可能非常容易发生隧穿。

射线投射将不起作用,因为这将检测两个高速物体之间的碰撞,而不是一个物体与固定墙之间的碰撞。(除非我误解了射线投射?)性能是一个非常重要的考虑因素。如果可能的话,我想避免对性能造成重大影响。我已经实现了一个功能强大且非常有效的四叉树(http://en.wikipedia.org/wiki/Quadtree),因此,我将按如下所述对其进行修改和使用。

编辑:减少时间间隔将不起作用。此解决方案的速度太高,这意味着性能损失会太大,同时仍会丢失绝大多数隧道碰撞。(例如,我可能有一个大小约为1个单位的对象,其移动速度在每个时间间隔中以百万个单位为单位...)

建议的解决方案:

步骤1:

在每个对象的运动周围创建一个框,然后将这些框输入四叉树以生成可能发生碰撞的初始列表。参见下图(此图显示了一个圆形对象从一个位置移动到另一个位置,并且该移动生成一个矩形,该矩形将被馈送到四叉树中):运动产生的矩形

步骤2 :(可能要跳过此步骤吗?)

浏览四叉树可能产生的碰撞列表。查看矩形是否在每次可能的碰撞中相交。如果是这样,请继续执行步骤3。

编辑:在下面,肖恩·米德里奇(Sean Middleditch)建议使用扫掠体/胶囊的交点(如果对象是圆形的话)。剩下三个选项:1)完全跳过步骤2。2)按我的方式执行步骤2。3)按肖恩的方式做。肖恩的方法在计算上比我的盒子想法要昂贵,但是它会比我的方法消除更多的误报,从而阻止他们进入最后一步。

任何人都可以根据经验谈谈这三种选择中哪一种是最佳的吗?(我打算将此物理引擎用于其他一些事情,因此我正在寻找一种“一般最佳”的解决方案,该解决方案在各种各样的情况下都能最快地工作,而不仅仅是一个可以轻松衡量哪种解决方案的特定测试用例。是最快的)。

第三步:

使用下面的t =方程,如果判别式(即,平方根下的部分)为负或0,则无碰撞;如果为正,则将t值用作碰撞时间(在此之后,很容易相应地调整位置)。 ..如果两个对象在碰撞后仍继续存在)。方程:

t =(-1/2 sqrt((2 a w-2 a x + 2 b y-2 b z-2 c w + 2 c x-2 d y + 2 dz)^ 2-4(w ^ 2- 2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2)(a ^ 2-2 a c + b ^ 2-2 b d + c ^ 2 + d ^ 2-r ^ 2-2 r ss ^ 2))-a w + a xb y + b z + c wc x + d yd z)/(w ^ 2-2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2 )

其中(1和2用于表示对象1和2):

t是介于0和-1之间的负时间值,其中0是当前帧,而-1是前一帧;

a = x位置1;

b = y位置1;

c = x位置2;

d = y位置2;

w = x速度1;

x = x速度2;

y = y速度1;

z = y速度2;

r =半径1;

s =半径2;

导数:(^ 2表示平方)

对象运动的参数方程式为例(例如,newxpos1 = a + t w),并将其插入距离公式中(对边进行平方):距离公式的平方=(a + t w-(c + t x))^ 2 +(b + t y-(d + t * z))^ 2。请记住,t将为负。为了找到两个圆形物体的碰撞时间,我们将左侧设置为(r + s)^ 2。使用二次方程式(以及大量非常繁琐的代数)求解t,我们得到上面的“ t = ...”方程式。

我的问题:

1)这是一个好方法吗?会起作用吗?我会遇到任何无法预料的问题吗?(我知道当一次有两个以上的物体碰撞时我会遇到麻烦,但我不在乎,因为我真正反对的唯一情况是当它们的相对速度较低时(如果相对速度较高)那么算法给出的“愚蠢”解决方案将“足够好”,并且人类将不可能看到错误),并且如果在同一时间步长内有两个以上的碰撞且相对速度较低,大多数解决方案将无论如何都要足够近,因为我不打算发生一堆无弹性的碰撞)

2)我的表现会受到很大影响吗?我认为这不会,但是如果有的话,还有更好的方法吗?

3)我应该跳过第2步,直接从第1步转到第3步吗?显然,步骤2并不是至关重要的,但是它可能会提高性能(或者它可能花费比所节省的CPU时间更多的时间)。

所有其他评论,建议或批评都非常欢迎。谢谢您的帮助!


1
克里斯特·埃里克森(Christer Ericson)在橙皮书中提供了一些有关扫掠球体/球体测试的信息。有很多解决问题的方法,但是我想您会喜欢将间隔减半最多。最好自己尝试派生这些东西,但是您真的应该只是看看橙皮书并进行比较,以获得真正好的检测程序并了解更多信息。
RandyGaul

听起来您已经有一个计划。尝试一下,看看它如何运作?
Trevor Powell

我认为“通常”的方法是在增量时间上设置一个小的最大间隔。因此,如果经过1000毫秒,则只需模拟10倍100毫秒(或100倍10毫秒或33倍30毫秒或类似的时间)。
ashes999

@RandyGaul我查看了第215-218页,尤其是第218页(Google预览)中描述的算法。尽管我尚未仔细考虑其所有含义,优点和缺点,但它还是很优雅的。它会比我的快很多吗?如果是这样,与Ericson的递归相比,我算法的哪一部分比较慢?步骤3中的方程会太慢吗?递归让我有些犹豫,因为某些对象的移动速度可能非常快,因此在某些情况下可能需要进行大量递归。(另外,这本书的价格是70美元……)
MindSeeker 2013年

1
@MindSeeker我没有时间研究您的推导,但是我很肯定Ericson的书中的算法(其中任何一种)都可以很好地工作,并且可能比您的东西更快,更健壮。如果要演示其他页面,可以免费在线找到PDF版本。另外,如果您经常要进行碰撞检测,则橙皮书是必不可少的。
RandyGaul

Answers:


9

本质上,您已经创建了一些过分热情的扫描卷版本。

采取对象的两个位置。从对象的开始到结束“扫描”对象。对于球体,这将创建一个胶囊。对于一个盒子,这将创建一个六边形(或者更长的盒子是沿着单个轴的运动)。对于一般的凸多边形,这将创建一个不同的凸多边形。

现在,您可以使用此扫描量进行交集测试(包括四叉树查询)。您可以计算发生碰撞的时间,将模拟从开始时间前移到碰撞时间,然后重复进行。

另一个更简单的选择是执行@ ashes999所述的操作,并简单地使用较小的时间间隔或较小的速度。有一个理想的最大速度是从一个间隔得出的,在该间隔中,没有一个对象可以在单个物理交互中移动得比最窄的一侧更远。对于特别小的物体或特别快的物体,您可能无法找到运行良好的较小间隔。

有关检测冲突的主题,请参阅《实时冲突检测》以获取更好的入门/中级书籍之一。


感谢您的大力支持!分解您的答案,以便我可以提出以下问题:“从对象的开始到结束,对其进行“扫描”。到目前为止,我正在跟踪;绝对比我的box方法有所改进。我将这些形状输入四叉树,然后检查更精确的碰撞。“您可以计算发生碰撞的时间。” 哈哈说起来容易做起来难:)您是否建议我坚持步骤3的公式?或者,还有更好的方法?这是真正关键的部分。
MindSeeker 2013年

[续]“另一个选项...”我考虑了该选项,但不幸的是速度太高。请参阅我对@ ashes999的评论回复,并在上方进行编辑以获取更多信息。非常感谢您的帮助!
MindSeeker 2013年

了解性能的唯一方法是尝试,衡量和观察。我已经看到一些“明显”低效率的代码在很大程度上超出了高效版本,通常是出于非直观的原因。不要问最快的是什么。测试并找出答案。
肖恩·米德迪奇

公平地说,我将继续尝试按照您的建议进行修改的方法。我在评论中的问题仍然存在:“您可以计算发生碰撞的时间。” 您是否建议我坚持从第3步开始的方程式?或者,还有更好的方法?这是我认为问题中最困难的部分。如果我正确理解了扫掠体,它们可以告诉我对象的路径相交,但是不能告诉我对象本身是否/何时碰撞。
MindSeeker 2013年

1
@MindSeeker扫掠几何体是光线投射的,除了要投射形状而不是光线。因此,该方法应类似于对所有快速移动的对象使用带有“射线”的射线投射,而不是仅对静止对象使用一束射线。在确定“射线”的潜在碰撞之后,您需要解决两个“射线”上的时间,以确保它们同时位于同一地点。
stonemetal

2

问题中提出的算法效果很好:即使物体以极高的速度行驶,它也快速且完全准确。我实现了一个四叉树,因此将步骤1中的框输入四叉树后,我发现不需要第二步:我的程序运行速度几乎和以前一样。

我已经使用这种算法几个月了,在确定碰撞时间t方面似乎非常准确。由于网络上似乎没有什么比这更好,因此我强烈建议您使用此工具。(以上其他答案和评论中的某些答案很棒,但它们要么不能完全满足问题所指出的需求,要么作者对某些事情含糊不清,并且在被问及歧义性时从未回过头来回答)。


1

我尚无足够的声誉发表评论,但我想补充一点,即使用上面提到的Sean Middleditch来计算“ t”成为可能。至少如果我理解他的回答并且您正确地提出了问题。

这是sam hocevar的一个很棒的答案的链接,它提供了我所发现的最好的解释(他也画了照片,欢呼!)

/gamedev//a/55991/112940

如果那比您自己的方法快,我不能说,但是他一定会为您提供实现它并与您进行比较所需的一切。

为了避免留下“仅链接的答案”,我将简要总结一下他的想法:

  1. 计算两个边界框之间的Minkowski差
  2. 然后使用之间的相对速度,从原点到由Minkowski差创建的框投射射线/线段,以获取相交点
  3. 如果射线命中,将射线行进的距离除以代表相对速度的矢量的长度,您将得到“ t”
  4. 单击我在上面提供的链接,并用大量图片查看sam对所有这些的漂亮解释。太棒了。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.