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

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

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

(далее…)

Обновления

Вышли небольшие обновления моих биндингов: 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.

Обновления

Обновил битые ссылки на статьи по 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.

Музыкальный D: синтезатор в 100 строк

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

Библиотека dlib предоставляет базовые инструменты для работы с аудиоданными, которые позволяют написать синтезатор с сохранением полученных звуков в WAV. В этой статье я покажу, как с их помощью сгенерировать знаменитую мелодию «Popcorn» Гершона Кингсли, используя для этого всего три функции, умещающиеся в 100 строк кода.

(далее…)

Обновления

dlib 1.3.0

Вышла новая версия dlib. В библиотеке появился новый пакет dlib.math.random с реализацией генератора псевдослучайных чисел на основе C-функции rand. Проделан ряд улучшений в математическом пакете: добавлена поддержка компилятора GDC в модуль dlib.math.sse, появилась новая функция интерполяции bezierQuadratic.

Количество скачиваний dlib в реестре DUB достигло 1400 в месяц — рекордный показатель за все время существования проекта!

Подготовка к релизу Dagon 0.16

Новая версия Dagon планируется к выпуску совсем скоро — на днях внес ряд багфиксов и улучшений в физику Newton (в частности, исправлен прыжок контроллера персонажа на плоских поверхностях), а также добавил встроенную функцию создания скриншотов — Application.takeScreenshot.

Статус по проектам

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

К сожалению, далеко не все, что я делаю, имеет какие-либо перспективы серьезного развития. Некоторые из проектов остались на уровне любительских, другие я просто физически не успеваю развивать надлежащими темпами. Третьи — это своего рода эзотерика в сфере IT, понятная и интересная лишь единицам)

Dagon. Развивается, но медленно. В данный момент я работаю над версией 0.16, в которую войдут нововведения прошлого года: подповерхностное рассеивание и зонды освещения среды. Я планирую работать над движком и дальше, планы по нему довольно масштабные: так, я хочу сделать встроенный редактор на основе ImGUI — он будет генерировать исходники на D и вызывать DUB для сборки проектов, таким образом движок станет намного дружелюбнее для начинающих. Также в планах переписать стек постпроцессинга.

dlib. Понемногу развивается ветка 1.x, а вот 2.x пока заморожена. Исследую возможность поддержки прогрессивных JPEG.

Electronvolt (проект Atrium). Временно заморожен, но не исключено, что я к нему еще вернусь.

bindbc-wgpu, dusk и прочие наработки по WebGPU на D. Периодически обновляю, но для серьезного перехода на WebGPU пока нет мотивации и ресурса. Никаких особых планов на этот счет тоже нет.

dray. Новый проект — движок рейкастинга на основе dlib. Находится в разработке. Я в него переношу код из моего старого физ. движка dmech, а то пропадают даром хорошие алгоритмы) На сегодняшний день dray уже поддерживает пересечение луча с произвольной выпуклой геометрией, движок включает классы для таких стандартных тел, как сфера, параллелепипед, цилиндр, конус, эллипсоид. Тела могут быть произвольным образом трансформированы при помощи матриц 4×4.

Журнал FPS. Он жив-здоров, просто уже не имеет PDF-версии и существует в виде новостной странички. У меня есть идея окончательно объединить его с порталом Xtreme3D — думаю, это будет сайт или даже целая соцсеть по любительской разработке игр.

Этос Метамодерна. Telegram-канал для пространных философских рассуждений, которые по формату не подходят для других моих площадок.

Живопись и 3D-моделирование для стоков я окончательно забросил — коммерческий выхлоп там теперь уже нулевой, а времени работать для души совершенно перестало хватать.

Не упоминаю тут свои бизнес-процессы — это большая тема для отдельной статьи, и даже не одной.

Итоги 2023 года

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

  • Можно считать, что я достиг своей цели — стать профессиональным разработчиком игр. На сегодняшний день солидную долю моих доходов составляют фрилансерские проекты по разработке рекламных мини-игр и интерактивных баннеров. И, хотя все они пишутся на JavaScript, я стал чаще по работе использовать D для создания различных утилит, что не может не радовать.
  • Выпустил Dagon 0.15, в котором появилась поддержка Hald CLUT, 1D и 3D-текстуры, новые параметры постобработки для ручного управления эффектом Depth of Field, новые методы для текстур, обновлен биндинг Newton.
  • В репозиторий с примерами Dagon добавлены примеры создания ландшафта и работы с пользовательскими шейдерами.
  • Выпустил dlib 1.2.0 и 1.2.1. Добавлены функции гомотетии (масштабирования относительно точки), функции конвертации радианов в обороты и обратно, медианный фильтр, а также функция отрисовки прямоугольника. Спасибо Олегу Бахареву aka aquaratixc, Aaron Nédélec aka ReactiveAlkali, Razvan Nitu aka RazvanN7, Nick Treleaven aka ntrel за багфиксы и новые фичи.
  • Я наконец-то дописал вводную статью о PBR для начинающих, она доступна на сайте журнала «FPS». Кстати в уходящем году журналу исполнилось уже 15 лет.
  • Начал изучать микроконтроллеры — Arduino и ESP32. Полным ходом иду к своей детской мечте — сделать своими руками радиоуправляемую машинку (как-нибудь напишу пост об этом проекте).

Ну и, конечно, не могу не назвать самые значимые для меня события в мире IT:

  • Выход Blender 4.0
  • Выход Godot 4
  • Смена ценовой политики Unity
  • Появление ChatGPT (хотя я не думаю, что нейросети в обозримом будущем кого-то заменят).

Обновления

Лето подошло к концу — это печально 🙁 Но при этом спешу порадовать читателей хорошими новостями: одновременно вышли новые версии dlib и Dagon.

dlib 1.2.1 — в основном, исправляющий релиз. Исправлены ошибки в dlib.filesystem.posix.common, предупреждения о депрекациях в dlib.core.thread и dlib.math.utils. В dlib.image добавлен медианный фильтр (модуль dlib.image.filters.median).

Dagon 0.15.0 — первый релиз за последний год. Добавлена поддержка 1D и 3D-текстур и новые методы для класса Texture (setFaceImage, setFaceBit, createFromImage3D). Шейдер цветовых таблиц (LUT) теперь поддерживает таблицы в формате Hald CLUT — нужно создать 3D-текстуру из изображения Hald CLUT и просто передать в game.postProcessingRenderer.colorLookupTable. Появились новые параметры шейдера глубины резкости (DoF) для ручного управления эффектом: dofManual, dofNearStart, dofNearDistance, dofFarStart, dofFarDistance. Загрузчик glTF теперь декодирует встроенные в JSON-файл текстуры. Менеджер событий обзавелся поддержкой относительного режима мыши (EventManager.setRelativeMouseMode) для более надежной реализации управления мышью в играх. Соответственно, компонент управления FirstPersonViewComponent теперь использует по умолчанию относительный режим.
Обновился биндинг Newton Dynamics до свежей версии библиотеки: функция NewtonUserJointSetRowSpringDamperAcceleration удалена в пользу NewtonUserJointSetRowMassDependentSpringDamperAcceleration и NewtonUserJointSetRowMassIndependentSpringDamperAcceleration. Добавлен новый метод для ньютоновских твердых тел: NewtonRigidBody.localPointVelocity.

dlib 1.2 и другие обновления

Несколько обновлений за последние месяцы:

dlib 1.2.0 — добавлены функции гомотетии (homothetyMatrix, homothetyMatrix2D) в модуль dlib.math.transformation, функции конвертации радианов в обороты и обратно (radtorev, revtorad) в модуль dlib.math.utils. В dlib.image.render.shapes появилась функция отрисовки прямоугольника (drawRect) — автор реализации ReactiveAlkali. Добавлен файл CODE_OF_CONDUCT.md — краткий кодекс поведения для сообщества dlib:

Code of Conduct

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

1. Мы не приемлем нецензурные выражения, грубые и/или пренебрежительные сообщения, использование сексуальной, жестокой и иной оскорбительной лексики и изображений.

2. Любая критика должна быть конструктивной и разумной. Простого личного недовольства без каких-либо объективных причин недостаточно, чтобы делать критические заявления и влиять на развитие dlib.

3. Этот проект держится в стороне от нетехнологических вопросов и тем. Мы приветствуем всех, независимо от возраста, гендерной идентичности, религии, этнической принадлежности, гражданства или культурного происхождения, и наше сообщество не придерживается какой-либо определенной идеологии. Сайты, репозитории, каналы связи и прочие ресурсы, связанные с dlib, не должны использоваться как площадка для пропаганды.

Также добавлена поддержка Doxygen для генерирования документации.

bindbc-wgpu 0.16.0 — синхронизация с wgpu-native 0.16.0.1. Кстати, также обновил демку wgpu-dlang, добавил поддержку мипмаппинга и перевел на dlib 1.2.0.

Dagon 0.15 пока, к сожалению, откладывается на неопределенный срок — не доходят руки сделать поддержку 1D-текстур, которой не хватает для того, чтобы реализовать загрузчик KTX. В марте добавил новые параметры постобработки для ручного управления эффектом Depth of Field (dofManual, dofNearStart, dofNearDistance, dofFarStart, dofFarDistance) — это нужно, если необходимо реализовать кастомную расфокусированность, труднодостижимую стандартными параметрами focalDepth, focalLength и fStop.

Обращение к пользователям dlib, Dagon и других моих публичных проектов в связи с происходящими событиями

Я, Тимур Гафаров, создатель и мэйнтейнер dlib, Dagon, bindbc-wgpu, bindbc-newton, bindbc-soloud и др., в настоящее время живу в России без возможности в обозримом будущем покинуть эту страну.

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

Тем не менее, реальность такова, что разработчики из России в любой момент могут оказаться отрезанными от мирового сообщества СПО. Это серьезно повлияет на проекты, в которых они принимают участие. Я искренне надеюсь, что этого не произойдет. В противном случае я, к моему огромному сожалению, не смогу управлять разработкой dlib, Dagon и других моих пакетов в реестре Dub. В отсутствие сопровождения эти пакеты будут постепенно терять актуальность. Также у меня пока нет уверенности, что я смогу получать финансирование через Patreon и PayPal.

До ухудшения ситуации, пока у меня есть доступ к GitHub и реестру пакетов, я продолжаю сопровождение dlib и Dagon, в настоящее время уделяя этому минимум своего свободного времени. Я на неопределенный срок приостанавливаю разработку dlib 2.0 и новых версий Dagon из-за негативного психологического фона и неясной картины будущего. В случае катастрофического развития событий я не обещаю, что смогу посвящать проектам даже минимальные время и силы.

В связи с этим, я с сегодняшнего дня не рекомендую использовать dlib, Dagon и другие мои пакеты в качестве критических зависимостей в важных программных продуктах. Кто хочет взять активную разработку на себя, создать форк — буду только рад. Пожалуйста, не делайте pull request’ы с большим количеством коммитов, существенными изменениями и новыми фичами, которые мне придется читать и проверять — у меня для этого может физически не оказаться возможности. Если у меня сохранится доступ к GitHub, я, скорее всего, увижу ваш форк и сам сделаю слияние, как только смогу.

P.S. Я в срочном порядке выпустил Dagon 0.13.0.

P.P.S. Облачная папка с примерами Dagon (Sponsor Folder), которая была ранее доступна только для подписчиков на Patreon, теперь открыта для всех.