Как стать автором
Обновить

Изучение физического движка Bullet Physics. Часть 2. Примеры

Время на прочтение5 мин
Количество просмотров3.7K

Введение

Данная статья продолжает тему исследования библиотеки симуляции столкновений в Bullet Physics (Bullet). Предыдущая статья здесь.

Чтобы разбавить теоретические рассуждения, здесь будут приведены практические примеры, в которых освещено общее взаимодействие с объектами средствами Bullet.

В качестве системы визуализации используется Unreal Engine(UE), поскольку  хайповая штука и она мне знакома она бесплатна, имеет множество дополнений и, в целом, предоставляет красивую картинку “из коробки”.

Подопытные
Подопытные

Как подключить библиотеку Bullet к UE, можно посмотреть здесь. Это руководство(далее Руководство) дает указания как использовать Bullet. Они корректны для всех текущих версий UE.

В качестве подопытного объекта выступит обрезанная сфера, смоделированная средствами Blender. Были экспортированы два вида фигур, глобальные координаты которого смещены по оси OX, чтобы продемонстрировать некоторую специфику обработки объектов инструментами Bullet.

a) Исходная математическая модель b) Смещенная математическая модель объекта
a) Исходная математическая модель b) Смещенная математическая модель объекта

Процесс загрузки математической модели выглядит следующим образом:

  1. Создание модели в Blender;

  2. Экспорт в файл fbx;

  3. Загрузка в Static Mesh через редактор UE;

  4. В целевом объекте AActor добавляем модель в UStaticMeshComponent;

  5. Далее выгружаем в btCollisionShape, а точнее в btConvexHullShape;

  6. Далее мы ассоциируем btRigitBody с полученной формой.

Здесь обращу внимание на следующий момент: возникаю два разных, но совпадающих по координатам точек объекта, UStaticMeshComponent и btCollisionShape. Они совпадают в этом примере для наглядности, но остаются совершенно независимыми сущностями.

Я не нашел прямого указания, как изменить центр масс иначе, чем смещая сетку. Bullet воспринимает модель, отсчитывая все силы от фиксированной точки. Для такого объекта, который экспортирован моим способом – это будет глобальный ноль в Blender. Такой подход может привести к весьма странным результатам, если точка находится далеко за пределами модели.

Цель данной статьи – показать основные возможности на практике, которые заключаются в приложении силы и ограничителей к физическим объектам. Это перечень главных средств Bullet. Сила – наиболее понятный инструмент. Человек прикладывает ее руками и ногами к предметам, хотя можно и головой. Разительное отличие состоит в том, что Bullet позволяет приложить силу «внутри» объекта: физически пиная мяч, вы можете ударить только в место на поверхности его сферы. Bullet разрешает употребить силу прямо к центру мяча или сделать так, что точка приложения силы к мячу будет удалена на 100 км. Это не интуитивно понятно, но библиотеку не смутит ни каплю.

Еще непривычными для человеческого ощущения будут ограничители. Они описывают поведение объектов во взаимодействии. Когда нам надо описать колесо автомобиля, мы используем ограничитель, который заставляет вращаться вокруг оси и не перемещаться относительно ее. В Bullet это реализуется через один класс btHingeConstraint, а в реальности это целая механическая система. По сути, еще одно упрощение, хотя можно собрать набор объектов, который будет выполнять точно такие же функции. Но какой ценой: значительного увеличения количества вычислений. По факту мы имеем сведение большого пласта расчетов к одному элементу. 

Использование библиотеки

Нужно приложить силу, чтобы переместить объект:

body->applyForce(f , r ); // регистрируем значения силы и рычага

body->activate();     // сообщаем Bullet, что тело активно

Переменная body – это btRigidBody, базовый класс Bullet.

Зачем нужно сообщать Bullet о активности тела? Bullet отслеживает столкновения объектов и считает их перемещения только тогда, когда они сталкиваются. Это называется «Островами симуляции» и необходимо для уменьшения количества расчетов. В нашем случае, сила берется «из воздуха», поэтому мы должны уведомить библиотеку, что с телом произошло непредсказуемое.

Дополнительный момент, который хотелось бы отметить: центр масс объекта считается исходя из его однородности. Именно для этого экспортировались тела с разными глобальными координатами.

Чтобы еще более наглядно продемонстрировать способ изменения центра масс, будем «налету» смещать точки сетки модели объекта.

btConvexHullShape* convex = static_cast<btConvexHullShape*>(shape);

btConvexHullShape* in = new btConvexHullShape();

for (int i = 0; i < convex->getNumPoints(); i++)

{

btVector3 * pt = convex->getUnscaledPoints();

btVector3 pt2 = pt[i] + bt_shift_vec;

in->addPoint(pt2);

}

btVector3 r;

body->setCollisionShape(in); //К телу прикладывается новая форма

body->getCollisionShape()->calculateLocalInertia(mass, r); //Считается вектор локальной инерции

body->setMassProps(mass, r); //Устанавливаются новые инерциальные характеристики

body->updateInertiaTensor(); //Обновляются значения

body->applyGravity(); //Прикладывается вектор силы тяжести

body->activate(); //Активируется объект

В приведенном выше коде, shape – это текущая форма переменной body. Далее берутся точки исходной сетки и смещаются на известное расстояние.

Ограничители – это инструмент создания динамических объектов, таких как вращающееся колесо.

Например, самый простой btPoint2PointConstraint, которому не подобрать аналогов в реальном мире: он лишает предмет способности перемещаться.

PickedBody = body;

PickState = PickedBody->getActivationState();

PickedBody->setActivationState(DISABLE_DEACTIVATION);

btVector3 local_pivot = PickedBody->getCenterOfMassTransform().inverse() * BulletHelpers::ToBtSize(location);

btPoint2PointConstraint *p2p = new btPoint2PointConstraint(*PickedBody, local_pivot);

В приведенном выше коде, body – это уже упомянутая ранее переменная. Значение вектора location – координаты точки, к которой привязывается объект ограничителем.

Практические демонстрации

Теперь можно перейти к непосредственному показу работы, описанных выше инструментов.

В этом видео показано влияние положения центра масс (ЦМ) на поведение тела. В поле вводится смещение ЦМ относительно первоначальных координат. Точки сетки двигаются только по локальной оси OY, привязанной к объекту.

На ролике представлена упомянутая выше обрезанная сфера, центр масс которой находится посередине.

На трех кадрах последовательно, сверху вниз:

  1. На центр воздействует сила

  2. К телу прикладывается та же сила, но смещенная по оси OZ

  3. Та же сила используется на еще большем плече

На ролике представлена обрезанная сфера, центр масс которой намерено смещен.

На трех кадрах последовательно, сверху вниз:

  1. На центр воздействует сила

  2. К телу прикладывается та же сила, но смещенная по оси OZ

  3. Та же сила используется на еще большем плече

На ролике показано влияние массы на поведение объектов, к которым приложена одинаковая сила. Вектор действия смотрит строго вертикально вверх.

На ролике представлены сферы, массы которых равны, слева направо,  1 кг, 5 кг и 0,5 кг. К каждому телу прикладывается сила, смещенная вверх от центра масс. В результате возникает соответствующий момент.

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

Заключение

В этой статье продемонстрированы способы подключения Bullet к UE. Аналогично можно встроить  инструменты воздействия на объекты средствами Bullet к другому проекту на C++. Также показан способ загрузки сложной модели в среду Bullet.

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

Теги:
Хабы:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

Публикации

Истории

Работа

QT разработчик
8 вакансий
Программист C++
133 вакансии

Ближайшие события