Представляя бесконечность в физических расчетах

В настоящее время я пишу некоторые функции для решения упругих столкновений в 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% физически точными, просто «достаточно хорошими». Каков рекомендуемый способ представления бесконечности в таких вычислениях? Я просто выбираю произвольно большое число?

2

Решение

При использовании чисел с плавающей запятой IEEE эти две бесконечности уже специально обрабатываются аппаратными средствами вместе со значениями Not-A-Number (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 будет распространяться через другие операции, давая circle_obj->velocity = NAN,

1

Другие решения

Если бы я был тобой, я бы сделал так, чтобы некоторые объекты были неподвижны в моем коде. Например, вместо того, чтобы вставлять значения в одну общую формулу, должен предотвращать перемещение некоторых объектов, иметь разные ветви выполнения для столкновения двух движущихся объектов против столкновения подвижного и неподвижного объекта.

Кроме того, если точность не является большой проблемой, используйте floatс вместо doubles. 🙂

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;
}
1

насколько я знаю, это просто максимальное число, возможное в представлении с плавающей запятой.

Конечно, это так, потому что числа с плавающей точкой IEEE не могут представлять ничего больше, чем бесконечность. В то же время, это действительно бесконечность, и вы можете использовать его безопасно.

0
По вопросам рекламы [email protected]