在物理计算中表示无穷大

Representing infinity in physics calculations

本文关键字:表示 无穷大 计算      更新时间:2023-10-16

我目前正在编写一些函数来处理C++中的弹性碰撞。在处理移动物体与不可移动物体碰撞时,我遇到了绊脚石,因为计算要求不可移动物体具有无限的质量。

我知道std::numeric_limits提供了infinity()但我不确定它在这种情况下是否完全有用,因为据我所知,这只是浮点表示中可能的最大数量。在下面的代码中,如果aabb_obj的质量等于 std::numeric_limits<double>::max() 似乎使用它的每个计算都会导致 std::numeric_limits<double>::max()0 .

double t;
if (intersect_moving_circle_aabb(circle_obj, aabb_obj, t))
{
    circle_obj->position += circle_obj->velocity * t;
    vec2 closest_point;
    closest_pt_point_aabb(circle_obj->position, aabb_obj, closest_point);
    vec2 n = (closest_point - circle_obj->position).normalized();
    double a = dot_product(circle_obj->velocity, n);
    double p = (2.0 * a) / (circle_obj->mass + aabb_obj->mass);
    circle_obj->velocity = circle_obj->velocity - p * aabb_obj->mass * n;
}

这是针对游戏的,因此结果不需要 100% 物理准确,只需"足够好"。在此类计算中表示无穷大的推荐方法是什么?我只是选择一个任意高的数字吗?

对于 IEEE 浮点数,硬件已经对两个无穷大以及非数字值 (NAN( 进行了特殊处理。他们遵守正常的数学规则:

1/0 = +inf
+inf + x = +inf
-inf + +inf = NAN
x/+inf = 0
0*+inf = NAN
...

现在,您可以检查代码,看看如果为其中一个质量块插入+inf会发生什么情况: 这将产生 p = 0 的值,在下一行中,如果aabb_obj->mass是有限的,则p * aabb_obj->mass将产生0,如果它是无限的,则NAN。后一种情况是您需要避免的情况,因为NAN将通过其他操作传播,从而产生circle_obj->velocity = NAN

如果我

是你,我会在我的代码中明确某些对象是不移动的事实。例如,与其将值代入一个防止某些对象移动的通用公式中,不如对两个可移动对象碰撞与可移动和不可移动对象碰撞具有不同的执行分支。

此外,如果准确性不是一个大问题,请使用 float s 而不是 double s:)。

问题中的代码应该计算圆形运动物体与不可移动的AABB物体碰撞时的反弹速度。理论上,一个完全不可移动的物体应该有无限的质量,但可以看出,用浮点表示会导致计算产生(NaN,NaN(的向量。

最后,我选择了对无限质量的显式检查,从而简化了代码。

不可移动的物体

不能从碰撞中获得动量,并且由于动量守恒,移动的物体不会失去任何动量。这意味着两个物体的质量与计算无关,因为移动物体速度的大小不会改变,只有方向会改变。

理解了这一点,我可以将代码简化为简单地反映关于碰撞法线的速度矢量:

double t;
if (aabb_obj->mass == std::numeric_limits<double>::infinity()
    && intersect_moving_circle_aabb(circle_obj, aabb_obj, t))
{
    circle_obj->position += circle_obj->velocity * t;
    vec2 closest_point;
    closest_pt_point_aabb(circle_obj->position, aabb_obj, closest_point);
    vec2 n = (closest_point - circle_obj->position).normalized();
    circle_obj->velocity = circle_obj->velocity - 2.0 * dot_product(circle_obj->velocity, n) * n;
}

据我所知,这只是浮点表示中可能的最大数量。

当然是这样,因为IEEE浮点数不能代表大于无穷大的任何内容。同时,这确实是无限的,您可以安全地使用它。