Math 实时计算碰撞-处理时间延迟
假设:Math 实时计算碰撞-处理时间延迟,math,real-time,physics,Math,Real Time,Physics,假设: 您正在编写一个程序,其中3个(或更多)圆(或其他几何体)以不同的速度在屏幕上实时移动,由于物理计算,在某些时间可能会发生变化 计算只能在每一帧上进行 在每一帧中,您必须确保在这一帧和最后一帧之间发生“碰撞”/“碰撞”的圆将通过物理计算“反弹” 假设在帧x和帧x+1之间的时间内,三个圆将相互碰撞。但是,在第x帧期间,没有一个圆与另一个圆接触。在帧x+1中,应用相同的内容(无碰撞) 我将尝试用一幅图像更好地说明这一点: 问题: 有什么好方法可以像这样跟踪碰撞,这样碰撞就不会因为
- 您正在编写一个程序,其中3个(或更多)圆(或其他几何体)以不同的速度在屏幕上实时移动,由于物理计算,在某些时间可能会发生变化
- 计算只能在每一帧上进行
- 在每一帧中,您必须确保在这一帧和最后一帧之间发生“碰撞”/“碰撞”的圆将通过物理计算“反弹”
- 假设在帧x和帧x+1之间的时间内,三个圆将相互碰撞。但是,在第x帧期间,没有一个圆与另一个圆接触。在帧x+1中,应用相同的内容(无碰撞) 我将尝试用一幅图像更好地说明这一点:
对所有认为这篇文章是OT的人来说:在投票结束之前先看一看。只在“框架”中评估事物的想法可能是不正确的 最古老的OO模式之一是“”——它鼓励将查看的内容(模型)与查看方式(视图)分离
物理引擎在模型对象上运行,因此将始终跟踪它们之间的交互作用。因此,当视图出现并询问“x+1帧”场景中每个圆的位置和方向时,它可以轻松回答,基于上次查看请求后经过的实时时间。我知道您的问题指出,物理只能在每一帧进行评估,但我不知道什么时候会出现这种情况。在足够小的步骤中以增量方式更新物理,以避免对象完全绕过彼此,每一步一次,这将是非常简单的 但是,坚持显式更新方案(速度乘以时间步长)只适用于低速。正如在许多基于物理的游戏中所看到的,提高速度通常会导致穿透物体。 大多数简单的物理引擎选择只考虑这些bug,因为健壮性是众所周知的困难和昂贵的 如果将适用范围限制在圆形,那么可以做一些事情。书写对象的距离,作为时间的函数(在时间步长上) 如果距离函数
d_ab
等于时间步长内任何t
的半径r_a+r_b
之和,则发生碰撞。因此,首先检查哪些对象发生碰撞(如果有),然后从该点继续并重新进行分析,直到到达时间步长的末尾。非常复杂,仍然只适用于圆/球体。要正确执行此操作:
- 计算圆的精确碰撞时间,而不是舍入到下一帧:
- 如果对象的移动距离超过1D,则需要查找根
- 按如下顺序解决冲突:
- 在上述精确碰撞时间停止模拟
- 在第一次碰撞中解析圆的物理特性
- 重新计算以确定由新轨迹引起的任何碰撞
- 重新启动模拟
- 重复此操作,直到到达帧的末尾而不发生碰撞为止
- 物理上任何其他计划外的变化也需要更新即将发生的碰撞
更新,回应评论:我想明确我的回答忽略了你的一个假设——如果你假装帧边界之间没有时间,你就无法准确地处理碰撞。碰撞不会发生在帧边界处;通常,碰撞将发生在帧边界之间,因此您的计算需要反映这一点 如果假设帧之间的所有运动都是线性的(即,模拟在帧边界上进行所有加速),那么确定是否发生碰撞、发生碰撞的位置和时间实际上非常简单。它将帧间“模拟”减少到几乎为零——即使模拟是二维或三维的,也可以以闭合形式求解方程:
posAB = posA - posB [relative vector between circles A and B]
velAB = velA - velB [relative velocity between circles A and B]
posAB(t) = posAB(0) + t * velAB [relative vector as a function of time]
rAB = rA + rB [sum of radii of the two circles]
collision happens when distance(t) = abs(posAB(t)) == rAB
-> rAB^2 = | posAB(t) |^2 = | posAB(0) + t * velAB |^2
-> t^2 * |velAB|^2 + t * 2*posAB(0).velAB + |posAB(0)|^2 - rAB^2 == 0
solve quadratic equation for t:
- if discriminant is negative, there is no collision.
- if collision times are outside current timestep, there is no current collision.
- otherwise, smallest t should be the correct collision time.
- watch out for cases like 2 circles coming *out* of collision...
最后,听起来你好像在尝试进行过早的优化。最好是让事情正常运转,然后让它们快速运转;在运行代码之前,您不会知道实际的瓶颈。我还认为你实际上低估了现代计算机的能力。当然,你总是可以添加足够多的对象来让你的计算机陷入困境,但我想你会惊讶地发现需要这么多的对象……这里碰撞检测的关键词是“连续”或“不连续” 正如其他一些答案所述,大多数现代碰撞库都使用非连续版本,因为分析许多碰撞形状的精确碰撞时间成本很高。这意味着让对象相互穿透,检测到这一点,然后调整它们的速度以对抗相互穿透。正如已经指出的,这允许快速移动的物体相互通过。这可以通过增加运行物理的频率来解决,本质上需要将物理与渲染分离(使用更快的计时器运行)。解决穿透分辨率的实际方法
posAB = posA - posB [relative vector between circles A and B]
velAB = velA - velB [relative velocity between circles A and B]
posAB(t) = posAB(0) + t * velAB [relative vector as a function of time]
rAB = rA + rB [sum of radii of the two circles]
collision happens when distance(t) = abs(posAB(t)) == rAB
-> rAB^2 = | posAB(t) |^2 = | posAB(0) + t * velAB |^2
-> t^2 * |velAB|^2 + t * 2*posAB(0).velAB + |posAB(0)|^2 - rAB^2 == 0
solve quadratic equation for t:
- if discriminant is negative, there is no collision.
- if collision times are outside current timestep, there is no current collision.
- otherwise, smallest t should be the correct collision time.
- watch out for cases like 2 circles coming *out* of collision...