Jolt Physics включает не только готовый контроллер персонажа, но и полнофункциональный raycast vehicle — причем, это не экспериментальная поделка-бонус, как часто бывает в физдвижках, а серьезный такой префаб, который с минимальными усовершенствованиями можно брать для создания симкейда коммерческого уровня. Достаточно сказать, что он безо всякой доработки напильником уже выглядит лучше, чем, скажем, печально известная физика авто в Cyberpunk 2077. А если еще подобрать реалистичные параметры подвески и инерцию шасси, заменить встроенную модель трения шин на свою, то вообще идеально!
На видео — демка 4×4, которую я накидал буквально за день, изучив VehicleController в Jolt:
Пока в Dagon нет соответствующей объектной обертки, но это не проблема, так как можно использовать любые функции joltc напрямую. Исходники и сборку планирую выпустить одновременно с Dagon 0.42, где будет несколько важных улучшений в dagon:jolt и dagon:audio.
В новой версии движка дебютирует физический движок Jolt Physics, в виде расширения dagon:jolt. Он предоставляет примерно тот же набор возможностей, что и Newton, при этом он лучше оптимизирован под многоядерные процессоры, а также имеет встроенный контроллер персонажа, который работает более стабильно, чем старый NewtonCharacterController. Newton, однако, в обозримом будущем никуда не денется, оба расширения будут развиваться параллельно. Я планирую также добавить поддержку встроенного симулятора автомобиля Jolt — об экспериментах с ним напишу как-нибудь в отдельном посте.
Исправлен микростаттеринг, связанный с неверной работой главного таймера. Визуально это проявлялось в виде периодических скачков изображения, заметных при движении камеры. Свойство stepFrequency переименовано в updatesPerSecond, в классе Application и в settings.conf.
Добавлены новые цветовые профили вывода: линейный (gl.outputColorProfile = "Linear") и Gamma 2.4 (gl.outputColorProfile = "Gamma24").
Добавлено новое свойство Entity.autoUpdateTransformation. Если его отключить, то Dagon не будет автоматически обновлять матрицы трансформации Entity. Это нужно, главным образом, в компонентах, которые заменяют встроенную трансформацию своей собственной математикой.
Реализована поддержка кинематических тел в dagon:newton. С их помощью можно реализовать, например, движущиеся платформы. Также добавлены новые свойства NewtonRigidBody: bodyType, collisionShape, angularVelocity, acceleration, linearDamping, angularDamping, simulationState, collidable, sleepState, autoSleep, freezeState, gyroscopicTorque и новые методы setMassMatrix, setMassProperties. В контроллере персонажа исправлено застревание в стенах при прыжке.
В dagon:audio добавлены новый метод AudioManager.setPlaySpeed и опциональный параметр громкости в методах SoundComponent.play.
Как я уже не раз отмечал, игровая физика — это крайне недооцененный вид софта. Люди много говорят о графике, обыватель в играх вообще ничего, кроме графона, не замечает. А между тем, проверка столкновений и физика — вот что по-настоящему важно. Устаревший визуал и любительский уровень моделей игре можно простить, но проваливание персонажа сквозь пол и стены — нет. Я видел множество инди-проектов, потенциал которых был загублен именно плохой физикой (и, как следствие, неудобным управлением), а не графической или геймплейной составляющими. В мире инди и СПО вообще редко связываются с «физичными» жанрами типа экшнов, гонок, симуляторов и т.д. Свободные игры — это в основном стратегии, песочницы, 2D-аркады, рогалики. Физика довольно устойчиво ассоциируется с AAA и колоссальными бюджетами крупных издателей. Причина, конечно, в том, что она непредсказуема и плохо программируется. Она хороша в «чистом» виде — скажем, в симуляторе бильярда, где простая геометрия и нет вычислительно сложных ситуаций. Но если физика должна быть подчинена игровой логике, а не наоборот, то решения «по учебнику» резко перестают работать, приходится изобретать невиданные хаки и решать дичайшие корнер-кейсы. Это и отличает AAA от любительского геймдева — там коммерческие секреты, ноу-хау, огромный опыт. Я вот давно уже пишу контроллеры персонажа и не понаслышке знаю, как это непросто. А ведь хочется получить этот священный Грааль — чтобы персонаж свободно двигался по карте, не застревал, правильно сталкивался с препятствиями, поднимался по склонам и лестницам. Сегодня это необходимая база для 3D-игр любого жанра, кроме совсем уж простеньких.
Я пробовал писать собственный физдвижок (dmech). Это был очень полезный опыт, но, взвесив все «за» и «против», я все-таки решил использовать то, что сделано профессионалами — я ведь не физик, а графический разработчик. Пусть каждый занимается тем, что лучше всего получается. Я выбрал Newton Game Dynamics, который долгое время был, пожалуй, самым оптимизированным и точным среди всех, что имеют C-интерфейс. Это отличный физический движок, и я очень благодарен Хулио Хересу за этот проект, Newton много лет был прекрасным дополнением к Dagon. Я долго не хотел его менять, но технологии не стоят на месте. Newton 3 заметно устаревает, а Newton 4 — это уже чистый C++ без C-враппера, поэтому настало время переходить на что-то альтернативное. Есть серьезные основания полагать, что новым стандартом индустрии станет Jolt Physics от Guerrilla Games. Jolt используется в их движке Decima, лежащем в основе серий Horizon и Death Stranding — редкий случай, когда технология AAA-уровня сразу переходит в Open Source! Jolt — это реальный конкурент PhysX и Bullet, многие бесплатные и свободные игровые движки уже переходят на него один за другим: Godot, NeoAxis, Dagor. И, что самое замечательное, к Jolt есть полноценный C-враппер, позволяющий использовать его не только в C++.
Итак, что же там такого уникального? Во-первых, отличная оптимизация под SIMD и поддержка многопоточности (правда, это имеет значение лишь при каких-то редко встречающихся высоких CPU-нагрузках). Во-вторых, изначальная ориентация на игры — дизайн и набор фич показывают, что Jolt разработан игроделами для игроделов, для реального продакшна, а не академических публикаций. Движок ощущается, как некий «бесплатный Havok» из закромов энтерпрайза. У него много архитектурных особенностей, но в целом с ним очень приятно работать. Например, очень понравилось, что структуры векторов и кватернионов в Jolt бинарно совместимы с моими родными Vector3f и Quaternionf. Да и сама синхронизация через позиции и кватернионы вместо матриц 4×4 — это мудро, так как матрицы требуют декомпозиции.
Я, пока писал этот пост, уже успел написать для Dagon базовую обертку над Jolt (расширение dagon:jolt), концептуально весьма близкую с dagon:newton. Движки во многом похожи — используется классическая схема с разделением на тела и полиморфные шейпы. Многие функции имеют более удобный API, чем в Newton — например, рейкастинг. В данный момент обертка поддерживает создание статических и динамических тел, шейпов всех видов, включая меши, а также базовый контроллер персонажа, который я планирую довести, как минимум, до уровня NewtonCharacterController. К релизу Dagon 0.41 будут добавлены сочленения.
Контроллер персонажа CharacterVirtual особенно порадовал: я решил сразу попробовать его в деле. Шикарно, что управление контроллером (включая гравитацию и прыжок) осуществляется путем произвольного изменения вектора скорости — можно реализовать любую механику. Контроллер стабильный и точный, встроенный ground-тест работает надежно — основа для игры от первого лица пишется буквально за один вечер.
В Jolt есть поддержка мягких тел и даже встроенный симулятор автомобиля! Очень надеюсь, что когда-нибудь все это тоже получится перенести в dagon:jolt.
Использовать расширение не сложнее, чем dagon:newton, а в чем-то даже проще. Сначала нужно вызвать joltInit для инициализации: