2

我目前正在编写一些函数来处理 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% 物理准确,只要“足够好”即可。在此类计算中表示无穷大的推荐方法是什么?我只是选择一个任意高的数字吗?

4

4 回答 4

1

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

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

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

于 2016-04-30T16:36:44.103 回答
1

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

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

于 2016-04-30T16:22:22.670 回答
1

问题中的代码应该计算圆形运动物体与不可移动的 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;
}
于 2016-05-01T15:19:54.770 回答
0

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

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

于 2016-04-30T14:39:42.567 回答