解决力量冲突


14

在我的2D物理引擎中,我可以检测到AABB与AABB碰撞,并通过找到最短的穿透矢量并将其添加到AABB的位置来解决它们。

这样做可以将“第一” AABB“推”到第二AABB之外,但根本不处理速度/加速度变化。

如果我在仿真中添加重力加速度,则即使第一动态ABB停在第二静态ABB的顶部,它的速度也会保持增长。最终,速度将变得太大而无法检测到碰撞(动态AABB将落入静态ABB)。

我尝试将分辨率后的速度设置为零,但显然效果不佳,并创建了不切实际的模拟。

我在线阅读了通过手动处理位置或速度不正确来解决冲突的信息。我尝试过实施力量(目前,质量是“硬编码” 1):

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

如果我在冲突解决期间将最短的穿透向量用作力,则动态AABB将从静态AABB中“弹出”,但在没有重力的情况下其速度永远不会降低,并且将永远移动。

有没有办法施加“临时”力量?一种将第一个ABB推出第二个ABB的力,然后在该AABB不再碰撞时停止作用?

完整的源代码在这里:https : //github.com/SuperV1234/SSVSCollision


1
我对此很感兴趣。您有解决方案了吗?
TravisG

@TravisG:不幸的是,还没有。如果我没有得到任何答复,我明天会增加一笔赏金。
维托里奥·罗密欧

首先,力不等于加速度。您需要质量来计算加速度。如果要修改位置以阻止两个物体穿透,则还应该使用质量并基于它移动两个物体。施加等于渗透矢量的力没有任何价值。Box2D是基于脉冲的,它可以直接作用于速度,它可能不是“正确的”,但是足够好了。在基于脉冲的发动机中处理速度变化非常简单,因此您可以指定是否要确定基于力的解决方案,还是要简单得多的基于脉冲的解决方案是否足够好。
dreta

就个人而言,我建议您读一本有关物理引擎的书,至少阅读有关牛顿物理学的前几章。您的假设是不正确的,尝试回答这个问题将意味着必须在解释解释解决碰撞的高级算法时,向您教授物理基础知识。
dreta 2013年

@dreta他的假设很好。他指出,目前所有对象的质量仅为1,这使他的代码段有效。顺便说一句,即使Box2D可以直接处理速度,它也必须以某种方式处理相同的问题。如果Box2D而不是施加力,而是施加脉冲,则它仍必须处理以下事实:一旦对象被分离,脉冲不会消失。虽然,实际上它可能根本不处理此问题,而只是让对象保持能量(毕竟在现实世界中就是这样)
TravisG 2013年

Answers:


13

首先,我建议使用像Box2D这样的免费开放源代码物理学库,并且只专注于使游戏与众不同的方面!如果您坚持要重新发明轮子,请继续阅读...请注意,所有物理引擎都是近似值,尽管我在下面概述的方法将比当前模型更准确,但Box2D的结果将更加逼真。


一种快速建模两个对象A和B的更精确碰撞解决方案的方法:

  1. 在碰撞之前找到位置。您已经通过:“找到最短的渗透向量并将其添加到AABB的位置中”来近似。
  2. 使用牛顿物理学找到碰撞后的速度
    • 对于质量被硬编码为1的情况,只需交换速度(这不适用于必须具有无限质量的静态对象):
      • Av = Bu
      • Bv =金
    • 如果对象A和B的质量不同:
      • Av =(Au *(Am-Bm)+(2 * Bm * Bu))/(Am + Bm)
      • Bv =(Bu *(Bm-Am)+(2 * Am * Au))/(Am + Bm)
    • 哪里:
      • v:碰撞后的速度
      • u:碰撞前的速度
      • m:质量(对固定的静态物体的质量使用尽可能大的数字)
  3. 将加速度设置为0:以上步骤2中的速度计算说明了碰撞产生的加速度。

请查看我的示例小行星程序,该程序演示了这些概念。


接下来,说明堆叠的对象:

正如您已经注意到的那样,使用速度模拟堆叠/静止的对象并不能很好地工作:速度是对象在移动的速度,因此,如果它静止在静止的对象上,则速度应该接近0。增加速度没有意义。使物体出现在静止状态的速度:

如果我在仿真中添加重力加速度,则即使第一动态ABB停在第二静态ABB的顶部,它的速度也会保持增长。最终,速度将变得太大而无法检测到碰撞(动态AABB将落入静态ABB)。

真正应该发生的是一个与重力相反的加速力,重力会抵消重力。(这称为法向接触力)。一种快捷方式是不对没有飞行的物体施加重力:

  • 实现此目的的一种方法是保持“接地”状态:
    • 请勿在接地状态下对物体施加重力。
    • 如果物体从下方与物体碰撞,并且其速度非常小,则会进入接地状态。
    • 当物体的垂直速度超过某个正值时,它会退出接地状态。

更新:

  • 用外行的术语来说,牛顿物理学说碰撞前后的总能量必须匹配。当两个对象相互碰撞时,它们的能量将重新分配。能量是速度和重量的结合:较重,较快的事物具有更多的能量。这很直观。但是,不直观的是权重影响能量重新分配的确切方式。
  • 交换速度仅是质量相同的两个动态未固定实体(静态的固定对象具有非常大的无限质量)的快捷方式。
  • 固定一个静态物体时的捷径是:另一个动态的未固定物体保持相同的速度;仅角度会发生变化(想象一下,当球撞击铁轨时撞球台。铁轨本质上具有非常大的无限质量)。
  • 对于其他情况,例如三个或更多对象,必须求解完整的牛顿运动方程(动量守恒和动能守恒)。
  • 我不确定牛顿运动方程是否可以解决两个以上的物体。幸运的是,三个物体几乎从未在同一时间发生碰撞。处理前两个碰撞的实体就足够了,然后使用以前的碰撞分辨率中的新速度来处理任何后续的碰撞。这是使物理时间步长尽可能小并在发生任何穿透之前处理碰撞的一个很好的理由。
  • 您会在我的小行星演示中注意到,随着较大的岩石分裂成较小的岩石,会创建许多物体。但是,我总是处理成对的物体之间的碰撞。从不明确处理与两个以上物体之间的碰撞。

感谢您的详细答复。但是,有些事情我还是不明白:交换速度在与2个物体碰撞时能很好地工作-但是,我看不到当多个物体(也包括静态物体)同时碰撞时它如何工作。即使没有重力,将动态物体同时与静态物体和另一个动态物体碰撞也会产生问题。由于速度是交换的,所以一切都取决于碰撞的顺序。如果最后碰撞静态物体,则该物体将停止移动。如果是动态的,身体将再次移动。如何解决?
维托里奥·罗密欧

@Vee:好问题!三+物体和静态物体是两个独立的问题。我在更新中解决了这两个问题。简介:一次处理两个对象的碰撞;静态物体具有非常大的无限质量。
Leftium

您的静态联系人模型很奇怪。静触头不仅是靠重力作用,还应该在任何力下起作用。最简单的方法是消除接触时由于前一帧的加速度而获得的速度。同样,对于小速度,您可以完全取消赔偿,尽管您的计算并未考虑赔偿。这种方法适用于所有部队,易于实施并且看起来足够好。
dreta

16

解决此问题需要调整位置,并可能调整速度。刚体物理引擎具有一个求解器,该求解器使用牛顿运动定律及时将物体向前移动,同时还解决了非渗透约束和摩擦。这些引擎可以计算线性运动和角运动的正确组合,以创建合理的轨迹。

如果只想解决重叠问题,则可以使用伪速度来生成分离的轨迹,而不会增加动量。这是在Box2D的位置求解器中完成的。

我建议从这里获得2006和2007年的GDC演示文稿:

http://code.google.com/p/box2d/downloads/list

另外,您可以查看Box2D Lite的简化实现。


+1也表示必须调整位置。很少有人沉迷于此,但是为了增加仿真稳定性,大多数引擎通过直接调整位置来作弊。总而言之,如果可行的话,它适用于游戏。
teodron

感谢您的回答。我想知道在演示中可能错过的一些东西:Box2D是否以特殊方式处理了静态物体?我的意思是-当动态物体撞击静态物体时会发生什么?
维托里奥·罗密欧

2

在此处输入图片说明

在现实世界中,没有力将一个物体“推”到另一个物体之外,因为物体永远不会相互穿透。最接近的是法向力:它是在现实世界中的碰撞瞬间产生的,它首先阻止了穿透。

该法向力的角度垂直于两个碰撞对象的接触表面。大小取决于防止穿透所需的力。(请注意,除非使用其他力(例如摩擦力)进行建模,否则仅应使用法向力的y分量)。

虽然可以显式建模法向力,但仅建模其作用会更简单:

  1. 通过以下任一方法防止对象相交:
    • 通过解决碰撞时的碰撞来调整速度。(最好)
    • 手动调整主体的位置,以免它们相交。(更简单)您已经在“通过找到最短的渗透向量并将其添加到AABB的位置中”。
  2. 不要在会有法向力抵消重力的地方施加重力。
    • 与下面的另一个物体接触的物体承受法向力。因此,这是跟踪那些对象的问题。(实际上,任何接触的物体都应施加法向力,但并非所有这些物体都会对重力产生净作用。)
    • 如果要添加可以向下倾斜的其他对象滑动的对象,则必须添加摩擦力和法向力的x分量。

我在其他答案中稍稍不同地描述了这一点,后者更多地是关于碰撞的

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.