2016-04-30 12 views
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% точными, точными, достаточно хорошими. Каков рекомендуемый способ представления бесконечности в таких расчетах? Я просто выбираю произвольно большое число?

+0

Полезного приближение было бы дать объект в «недвижимое» имущество, которое вы проверяете, прежде чем пытаться обновить его векторы. Кроме того, вы можете установить массу объекта 'std :: numeric_limits :: max()', чтобы помочь в вычислении векторов движимого объекта. Это будет работать достаточно хорошо, если вы захотите также переключиться на интегральные типы. –

ответ

1

С поплавками 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.

+0

Ваше объяснение бесконечности бесконечности с плавающей точкой помогло мне понять странные результаты, которые я получал от своего кода. В конце концов было проще просто удалить массу из расчетов. Я добавил ответ, чтобы объяснить, как я в конечном итоге решил проблему, но я принял ваше, потому что это было очень полезно. – Fibbles

0

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

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

1

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

Кроме того, если точность не вызывает большого беспокойства, используйте float s вместо double. :)

+0

В конце я добавил ветку к коду, чтобы иметь дело явно с недвижимыми объектами. Оказывается, вычисления фактически проще, чем для двух подвижных объектов с различной массой. Я не уверен, какая польза от переключения на float даст мне современное оборудование x86. Хотя я буду рассматривать это в будущем, я не спешу преждевременно оптимизировать вещи. – Fibbles

1

Код в вопросе должен был рассчитать скорость отскока для кругового движущегося объекта, когда он столкнулся с неподвижным объектом AABB. Совершенно неподвижный объект должен теоретически иметь бесконечную массу, но, как можно видеть, представление этого в плавающей точке приводит к вычислению для создания вектора (NaN, NaN).

В конце я выбрал явную проверку для бесконечной массы, которая упростила код.

Неподвижный объект не может набирать обороты от столкновения, а из-за Conservation of Momentum движущийся объект не может потерять ни одного импульса. Это означает, что масса обоих объектов не имеет отношения к вычислениям, поскольку величина скорости движущегося объекта не изменится, изменится только направление.

Понимания это позволило мне сократить код просто отражает вектор скорости о столкновении нормального:

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

 Смежные вопросы

  • Нет связанных вопросов^_^