Dagon на FOSDEM 2024

Классная новость: на прошедшей в феврале в Брюсселе FOSDEM ’24, европейской конференции по свободному программному обеспечению, американский профессор компьютерных наук Майк Шах (Mike Shah) представил доклад по языку D. В числе прочего, доклад включает информацию по Dagon. Отмечается, что это «существенный проект, который представляет интерес для графических разработчиков». Также упоминаются Dash, Hipreme Engine, BindBC и некоторые коммерческие игры, созданные с использованием D.

Ссылка на презентацию

Доклад представляет собой общее ознакомление с языком, обзор основных его особенностей и преимуществ в плане разработки СПО, а также некоторых библиотек и примечательных проектов, написанных на D.

Майк Шах — ученый в области компьютерной графики и визуализации, Ph.D. компьютерных наук, преподаватель Колледжа компьютерных наук Хури Северо-Восточного университета (Массачусетс).

Векторная графика в dlib

Моя статья 2017 года, изначально написанная для блога LightHouse Software. Приведенный код актуален и сегодня.

Коллекция библиотек dlib предоставляет функции для рисования отрезков и окружностей (см. dlib.image.render.shapes). Однако при построении сложной векторной графики не обойтись без рендеринга более интересных объектов – в этой статье я рассмотрел рисование закрашенных многоугольников и фигур Безье на их основе.

(далее…)

Dagon 0.17 и другие обновления

Выпустил новую версию движка Dagon. Релиз включает поддержку экранов с высокой частотой обновления, поддержку Wayland под Linux, новые методы класса Application для управления окном приложения и методы класса Game для управления сценами. Шейдер HUD-объектов теперь поддерживает прозрачность материала. Исправлен баг с неправильным удалением из памяти сцен GLTF, также исправлен прыжок в контроллере персонажей Newton. Движок и расширения теперь используют самые свежие версии всех BindBC-биндингов.

bindbc-soloud обновлен до версии 0.2 — биндинг теперь поддерживает SoLoud 20200207.

Обновлена демка механики игры Electronvolt: добавил главное меню, опции, паузу и множество других мелких улучшений.

Чем создавать res-файлы?

Если вы создаете софт под Windows, то наверняка сталкивались с файлами *.res — это бинарный формат ресурсов, который используется тулчейном от Microsoft. Такие файлы прилинковываются с программным кодом для встраивания в экзешник иконок, курсоров, а также информации о версии приложения и авторских правах. Утилита для компиляции ресурсных файлов (RC) входит в состав MSVS, но если вы по тем или иным причинам не хотите ее использовать, то вас ждет, мягко говоря, увлекательное приключение — какого-то стандартного общепринятого способа компилировать ресурсы нет.

Странно, что никто до сих пор не создал универсальный res-компилятор для любых языков — хотя свои компиляторы разной степени удобства включены во многие IDE и тулчейны. Например, в GNU Binutils есть для этого программа windres. Но чтобы ее использовать, вам, естественно, придется целиком установить виндовый порт GCC, например TDM-GCC или Winlibs, а это «могут не только лишь все», да и держать у себя такой громоздкий пакет ради одной утилиты как-то жирно. Я решил найти альтернативу, что-то простое и независимое — и вот вам на выбор два кандидата.

GoRC

http://www.godevtool.com/ResourceFrame.htm

К языку Go никакого отношения не имеет) Это freeware-компилятор res-файлов с синтаксисом, являющимся надмножеством RC от Microsoft. Поддерживает x64. Минимальный исходник для задания иконки приложения выглядит так:

100 ICON "app.ico"

Полученный файл можно включить в DUB-проект:

"sourceFiles-windows": ["resource.res"]

rcedit

https://github.com/electron/rcedit

Утилита от разработчиков Electron. Это не компилятор ресурсов — rcedit работает с экзешниками напрямую и позволяет добавить иконку или манифест уже собранному приложению. Очень удобно, если ваш язык не поддерживает линкинг ресурсов. Или, например, если вы используете какой-то готовый движок или рантайм, который не собираете самостоятельно (как, собственно, тот же Electron). Можно присобачить rcedit к DUB-проекту следующим образом:

"postBuildCommands-windows": [
    "$PACKAGE_DIR\\rcedit \"app.exe\" --set-file-version \"1.0.0.0\" --set-product-version \"1.0.0\" --set-icon \"$PACKAGE_DIR\\icon.ico\""
]

Обновления

bindbc-opencl обновлен до версии 0.1.1.

dlib по итогам марта преодолел рекордную отметку в 14000 скачиваний в месяц! Я уже давно отслеживаю этот показатель и понятия не имею, откуда такой невероятный ажиотаж — обычное количество скачиваний в месяц не превышает 1000. Если у вас есть информация, буду рад узнать.

Сдвинулась с мертвой точки работа над Xtreme3D 4.0 — реализовал многие недостающие фичи, в том числе систему LightFX, функции TextureEx для материалов, а также поддержку FBO. Напомню, что Xtreme3D — это классический 3D-движок для Game Maker, враппер GLScene, разработкой и поддержкой которого я занимаюсь с 2009 года.

Необычный паттерн: объект-самоубийца

В D, как известно, нет встроенного способа удалить объект — то есть, освободить занятую им память. Функция destroy лишь вызывает деструктор и помечает объект как недействительный, но фактически память высвобождается в следующем цикле сборки мусора. dlib, будучи библиотекой для разработки приложений реального времени, предоставляет альтернативные механизмы управления памятью с возможностью удалять объекты вручную — в моменты, явно определяемые программистом, а не логикой сборщика мусора. Это накладывает на программиста определенную степень ответственности, так как стопроцентно ручное управление памятью — занятие довольно хардкорное. Я написал на Medium статью на эту тему, где описал парадигму владения (ownership), рекомендуемую при работе с dlib. Суть ее в том, что удаление данных автоматически выполняет объект-владелец этих данных, когда кто-то — вы сами или его собственный владелец — удаляет его самого. Таким образом, вы у себя в коде расставляете единичные функции Delete только в ключевых местах, когда ваше приложение переходит из одного режима в другой, а вся рутинная работа по удалению данных ложится на иерархию объектов-владельцев. Например, если это игра, то вы можете удалить текущую сцену, когда пользователь завершает уровнень, проигрывает, выходит в главное меню или загружает сохранение. Если объект сцены является владельцем всех ее данных, то они будут автоматически удалены.

Но при этом может возникнуть неожиданная проблема. Допустим, у вас есть некий глобальный менеджер игры, который каждый раз передает управление загруженной сцене. Сцена формирует нужные ей структуры данных, обрабатывает входящие события, реагирует на пользовательский ввод, обновляет изменяемое состояние и рендерит графику — то есть, совершает довольно много задач в цикле, полагаясь на то, что все ее данные находятся в памяти. Если вам нужно завершить работу сцены, то это равносильно удалению объектом самого себя — то есть, сцена обращается к корневому менеджеру с запросом о переключении в другой режим, и он ее удаляет. Можно ли в dlib так делать?

(далее…)

Симуляция веревок

В 2013-2017 годах я писал собственный физический движок, в котором LCP решается через систему неравенств для скоростей: каждое неравенство вводит в систему ограничение свободы для пары столкнувшихся тел, солвер итеративно решает столкновения путем корректировки скоростей. Это универсальный, но вычислительно недешевый метод, к тому же подверженный эффектам нестабильности. Импульсная физика хороша для движущихся тел, но не очень стабильна в состояниях покоя — тела часто дрожат, и для их «успокаивания» приходится вводить различные уловки и хаки, которые неизбежно вводят в систему ошибки, понижая точность симуляции.

В импульсных движках используется интегрирование Эйлера:

Где Δx — скорость частицы — интегрируется аналогичным образом на основе ускорения:

Таким образом, «физично» подействовать на частицу можно только через скорости и силы. Все ограничения в систему вводятся только через скорости — модифицировать позиции тел вручную нельзя, что делает импульсную физику в играх менее удобной для определенных геймплейных задач. Однако существует альтернативный подход на основе интегрирования Верле:

Из формулы получается, что для частицы не нужно хранить скорость, но нужна позиция с предыдущего шага интегрирования.

for (size_t i = 0; i < positions.length; i++)
{
    Vector3f currentPos = positions[i];
    positions[i] += (currentPos - oldPositions[i]) + freeFallAcceleration * (dt * dt);
    oldPositions[i] = currentPos;
}

Метод Верле позволяет легко вводить в систему ограничения: чтобы их решить, нужно итеративно скорректировать позиции частиц. Например, в случае с веревкой — то есть, набором последовательно соединенных частиц — расстояние между ними делается таким, каким оно должно быть (то есть, позиции частиц корректируются так, чтобы расстояние между ними не увеличивалось и не уменьшалось):

for (size_t i = 0; i < positions.length - 1; i++)
{
    Vector3f pos1 = positions[i];
    Vector3f pos2 = positions[i + 1];
    
    if (i == 0)
        positions[i] = attachPosition;
    
    Vector3f diffVec = pos1 - pos2;
    float dist = distance(pos1, pos2);
    float difference = 0;
     
    if (dist > 0.0f)
        difference = (nodeDistance - dist) / dist;
    
    Vector3f translation = diffVec * (0.5f * difference) * stiffness;
     
    positions[i] += translation;
    positions[i + 1] -= translation;
}

Аналогичным образом разрешаются столкновения: для частиц вводится объемная оболочка (например, сфера), взаимопроникшие тела перемещаются в кратчайшем направлении так, чтобы их оболочки не пересекались. Алгоритмы проверки столкновений обычно дают необходимую для этого информацию — нормаль и глубину проникновения. Преимущество перед импульсным подходом в том, что для этого не нужно составлять систему для скоростей — вы можете напрямую корректировать позиции и, таким образом, легко реализовать любую модель столкновений.

Обновления

Вышли небольшие обновления моих биндингов: bindbc-wgpu 0.19.1, bindbc-newton 0.3.1, bindbc-soloud 0.1.4. Все биндинги теперь используют bindbc-loader 1.1.

dlib достиг очередной рекордной отметки в 6000 скачиваний в месяц — это уже 4 место в каталоге DUB.

В Dagon добавлена базовая функциональность для переключения сцен: к выходу следующей версии опубликую пример, реализующий главное меню на ImGui с возможностью задавать настройки игры. Также Dagon теперь использует актуальные версии bindbc-opengl и bindbc-sdl.

Физика Верле

Попытка написать для Dagon физику веревки на основе интегрирования Верле увенчалась успехом! Добавил даже поддержку столкновений с боксами. В скором времени выложу эту демку в публичный доступ. Не исключено и добавление веревки в качестве встроенного объекта в движок.

Upd 06.03.2024: исходник демки можно скачать тут.

Обновления

Обновил битые ссылки на статьи по dlib в блоге LHS — у блога сменился домен на blog.lhs.su. Также решил постепенно выложить здесь все свои гостевые статьи оттуда.

Обновил сайты Dagon и dlib: https://gecko0307.github.io/dagon/, https://gecko0307.github.io/dlib/. Также все примеры Dagon теперь используют версию 0.16.0.

dlib бьет очередной рекорд по скачиваниям — 3400 в месяц, что выводит библиотеку на 6 место в каталоге DUB с рейтингом 5.0.

В Dagon появилась функция для управления кадровой частотой — Cadencer.setFrequency, а также хелперы для автоматической адаптации кадровой частоты к частоте обновления экрана: Application.displayRefreshRate, Application.frequencyToRefreshRate.