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

В 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.

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

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

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

(далее…)