← На главную

Curveball на Rust обходит ограничения curve.c для Neverball в браузере

04.07.2026 16:15 · hackernews

Разработчик написал инструмент Curveball для генерации кривых в игре Neverball. Curveball написан на Rust, работает прямо в браузере, а исходники лежат на GitHub. Можно скачать десктопную версию или собрать самому.

Зачем это вообще понадобилось? Автор делает набор уровней для Neverball и столкнулся с ограничениями старой утилиты curve.c. Та умела создавать только один тип кривой — круговую дугу. Хотя настроек там было много, нужных форм curve.c не выдавал. Пришлось писать собственные скрипты, а потом склеить их в один инструмент с визуализатором. Получился Curveball.

Теперь о технической кухне. Уровни Neverball собираются из «кистей» (brushes) — маленьких кусков геометрии. Каждая кисть задаётся через пересечение полупространств. Звучит дико, но так сделано, чтобы упростить обработку коллизий. Суть: берётся вся вселенная, и от неё отсекают лишнее плоскостями, пока не останется нужный кусочек. Эти плоскости описываются тремя точками в формате Quake map — ошибиться с порядком точек легко, и тогда отрежешь не ту половину.

Главная проблема: каждая кисть обязана быть выпуклой (convex), а кривые выпуклыми не бывают. Поэтому кривую приходится лепить из кучи маленьких выпуклых кусочков. Старый curve.c и ранние скрипты автора просто вручную подбирали точки — муторно и с ошибками. Решение нашлось в виде convex hull алгоритма: кидаешь кучу точек, а библиотека chull (на Rust сама собирает из них форму. Текстуры на грани автор решил не назначать в коде — проще покрасить их потом в редакторе Trenchbroom.

Ключевая идея Curveball — экструзия (extrusion), позаимствованная у CAD-систем вроде Solidworks. Ты задаёшь 2D-профиль и экструдируешь его вдоль 3D-пути. Программа копирует профиль вдоль пути, берёт вершины соседних копий, прогоняет через chull и получает готовую кисть. Так можно собрать сколько угодно кривых, комбинируя профили и пути. Если закодить m профилей и n путей, получится m × n разных кривых — вручную такое не перебрать.

С ориентацией профиля вдоль пути возникла проблема. Оказалось, что знать точку и направление мало — есть ещё кручение (torsion). Решение — Frenet frame: векторы T, N, B в каждой точке пути. Остаётся просто умножить матрицу из этих векторов на точку профиля. Для простых путей векторы задаются напрямую, без сложных формул. Поворот профиля сделали опциональным.

Кроме экструзии, Curveball умеет генерировать три дополнительных типа кривых: Curve Classic (для совместимости со старым curve.c), Curve Slope (единственная, которую экструзией не сделать — там кисти треугольные) и Rayto. Curve Classic и Rayto технически можно получить экструзией, но проще реализовать отдельно.

Автор собирается наконец доделать приостановленные уровни и ждёт, что придумает сообщество Neverball.

Читать оригинал →