Найти тему

Разбираем код на примере физического движка Bullet Engine

#ИскусствоВзлома #BulletEngine #cpp

Bullet Engine -- это современный физический движок, работающий в трехмерном пространстве. Он предоставляется с открытым исходным кодом, что позволяет его легко анализировать и изучать.

Примеры использования движка
Примеры использования движка

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

Для рассмотрения будем использовать пример, находящийся по пути

examples/HelloWorld/HelloWorld.cpp.

В нем приведен минимальный набор действий для запуска физики.

Первоначально создается мир и два объекта в нем: земля(btBoxShape) и сфера на ней (btSphereShape).

На картинке приведенной ниже описаны основные действия выполняемые движком. Мир обновляется через команду stepSimulation. Сама команда проверяет частоту обновления мира через средства ОС, затем определяет кинематические положение и скорость всех объектов, применяет гравитацию, после чего определяет СубШаги, которые необходимо выполнить для корректной работы Bullet.

Общий алгоритм работы
Общий алгоритм работы

СубШаги равны количеству заданных промежутков времени, умешенные в шаг Симуляции. Иначе говоря, у нас есть бесконечный цикл (шаг) симуляции, внутри которого проворачивается свои небольшие СубШаги. Таким образом, производится кусочная симуляция, базирующаяся на неком тике системы.

В рамках каждого СубШага производится набор действий, которые определят положение объекта. Демпфирование объектов необходимо отчасти из-за дискретности симуляции: необходимо разрешить проблемы бесконечно малых скоростей, например. Прогноз перемещения точек производится с помощью интегрирования скорости точек сетки объекта, в дальнейшем, данный прогноз используется для последующих вычислений.

Алгоритм дискретного поиска столкновений (ДПС) приведен на картинке ниже. Разными цветами выделены отдельные классы, участвующие в работе алгоритма.

Дискретный поиск столкновений
Дискретный поиск столкновений

На ДПС мы познакомимся с первыми классами. Базовый класс btCollisionWorld -- это основа Bullet. Поверх этого класса реализован класс btDiscreteDynamicsWorld, который описывает конкретную реализацию всей физики коллизий. Внутри Дискретного Мира реализованы вспомогательные классы btClosestNotMeConvexResultCallback и btSingleSweepCallback, реализующие взаимодействие между ДМ и другими объектами. При первоначальном рассмотрении они изучаться не будут.

Класс btDbvtBroadphase реализует основные ступени взаимодействия, используя две динамические иерархии/дерева объемного ограничения по алгоритму AABB( прямоугольным параллелепипедом). Одно дерево используется для статических объектов, второе -- для динамических: объекты могут перемещаться из одной иерархии в другую.

Класс btDbvt неотрывно связан с предыдущим: он представляет быстродействующее дерево ограничения объема взаимодействия, основанное на параллелепипеде, выровненном по осям Мира. Он может быстро вставлять, удалять или обновлять узлы. Узлы могут динамично вращаться вокруг, изменяя структуру основной топологии.

Класс btContinuousConvexCollision выполняет оценку времени соударения при угловом и линейном движении. Его основная задача выдерживать согласованность движения. Сейчас использует идею консервативного движения Brian Mirtich, в дальнейшем предполагается добавление Minkowski.

Алгоритм Расчета Областей Взаимодействия выполняется следующим, а сам он представлен на картинке ниже. В нем задействованы уже известные классы btCollisionWorld и btDbvtBroadphase, а также несколько новых.

Алгоритм расчета областей взаимодействия
Алгоритм расчета областей взаимодействия

Класс btCollisionDispatcher выполняет процедуры обработки пар взаимодействия типа ConvexConvex, ConvexConcave (Выпуклый-Выпуклый, Выпуклый-Вогнутый типы): вычисляет время взаимодействия, ближайшие точки и степень проникновения.

Класс btDefaultCollisionConfiguration определяет набор функций для алгоритмов коллизий, например btSphereSphereCollisionAlgorithm. Эти функции используются при расчете классом btCollisionDispatcher. Таким образом можно имплементировать различное количество функций.

Класс btHashedOverlappingPairCache предоставляет интерфейс управления перекрывающими парами. Он используется btBroadphaseInterface, в данном случае его имплементацией btDbvtBroadphase.

Дальнейшие функции СубШагов будут рассмотрены в следующих частях.