Рельеф и места
Рельеф — это не просто «гора из шума»: под ним настоящие высоты конкретного места на Земле, настоящая карта земного покрова (лес, луг, поле, вода) и настоящие дома, дороги и провода из OpenStreetMap. Можно взлететь на одном из встроенных мест или ввести координаты — и полетать там, куда данные вообще дотягиваются.
Встроенные места
| Место | Что это | Старты |
|---|---|---|
ongudai | Алтай, долина Урсула у Онгудая, хребет с перевалом Каянча (полёты с 1980-х) | южный склон у Онгудайского ретранслятора, 1870 м, курс 151° |
askarovo | Башкирия, хребет Биягода у Идяш-Кускарово (дельтадром, Чемпионат России 2025) | запад у верхнего лагеря 294°, восток 94°, южная вершина 285° |
aushkul | Башкирия, озеро Аушкуль: гора Ауштау («пупырь») и хребет у Старобайрамгулово | Ауштау восток 119°, Ауштау юг 170°, хребет запад 273° |
altai | Манжерок, Малая Синюха (дополнительное место) | 3 старта |
Источники и допущения по каждому месту — в _sources_doc конфига места, например
configs/locations/ongudai.json.
Полёт по координатам
Кроме встроенных мест, можно ввести любые координаты (широта, долгота) на карте выбора места — рельеф и карта поверхности подгружаются по сети:
terrain.load_location_latlon(43.25, 42.45, 40.0) # lat, lon, размер стороны в км
await terrain.loadedКарта выбора точки рисуется отмывкой (hillshade) прямо из тех же тайлов высот, что грузятся для полёта —
без внешних картографических сервисов и ключей (scripts/terrain/map_picker.gd).
Источники высот
Для встроенных мест высоты — Copernicus DEM GLO-30 (разрешение 1″, ≈30 м, облачный
GeoTIFF, бесплатно, без ключа): лучшее открытое качество, новее и чище SRTM. Данные конвертируются в
плоский формат заранее (tools/terrain/fetch_dem.py), в игру попадают уже готовым слоем.
Для рантайм-мест (по координатам) — AWS Terrain Tiles (Mapzen/Tilezen): на суше в основе тот же SRTM (≈30 м), для отдельных регионов точнее (Европа — EU-DEM, США — 3DEP 10 м, выше 60° с. ш. — ArcticDEM). Открытый HTTPS без ключа и без лимитов, PNG-тайлы декодирует сам движок.
И Copernicus, и SRTM — модель поверхности (DSM), а не земли (DTM): в лесу «высота» — это верх крон (+15…25 м), на опушках и вырубках получаются ступеньки высотой с дерево. Поэтому детальный слой слегка сглаживается (σ = 0,8 клетки), а 3D-деревья утоплены в поверхность. Открытых моделей без леса для Алтая нет: FABDEM лицензирован под CC-BY-NC (не подходит для некоммерческого, но свободно раздаваемого проекта), национальные лидарные DTM закрывают только отдельные страны.
Каждое встроенное место хранит два вложенных слоя высот: детальный (40 км, шаг 25 м) и фоновый (160 км, шаг 100 м, Terrarium); узлы выровнены, на стыке нет ступеньки. Загрузка Алтая — 0,2–0,3 с.
Карта земного покрова
Класс поверхности (лес, луг, пашня, кустарник, скалы, вода, застройка, снег) — из ESA WorldCover 2021
(10 м, лицензия CC-BY 4.0). Из этой же карты берётся и цвет земли, и то, где стоят деревья, и сила
источников термиков — три вещи из одного файла. fetch_landcover.py читает только нужные тайлы COG
(HTTP range-запросы, без GDAL) и записывает класс узла как моду 3×3 подвыборок.
Дополнительно для детального слоя строится маска «деталь 10 м» (два канала: R — доля леса, G — доля воды в клетке 10 м): по ней кромка леса и берега рек выглядят гладкими, а не «лесенкой» из клеток 25 м. Вода в этой маске дополнена реками, каналами и ручьями из OpenStreetMap (ширина по типу: река 25 м, канал 6 м, ручей 4 м) и озёрами (полигоны OSM). Ручьи уже самой клетки в шейдере остаются берегом, а не сплошной водой; реки и каналы — сплошная вода. Данные всей локации, включая эту маску, — не больше 15 МБ.
Для рантайм-мест (по координатам) этой маски нет — вода определяется классом WorldCover, как раньше;
если нет ни сети, ни данных — запасная процедурная карта по высоте, уклону, экспозиции и шуму
(SurfaceClassifier), той же формы, что настоящая.
OSM-объекты: дома, дороги, провода, заборы
Для встроенных мест поверх рельефа стоят настоящие объекты из OpenStreetMap
(data/osm/<id>.json, © OpenStreetMap contributors, лицензия ODbL): дороги (лента по рельефу, шаг
12 м на главных / 20 м на прочих, видимость 25 км / 4 км), здания (коробки стен + крыша, по контуру
из OSM), линии электропередачи (решётчатые опоры 110 кВ / столбы 10 кВ, провод — парабола с провисанием
3 % пролёта, реальной толщины 2 см, но не тоньше пикселя; вблизи — линия, дальше 500 м не рисуется — как
в жизни), заборы у посадочных площадок. С проводами есть столкновение.
Реки и озёра не рисуются из OSM отдельно — вода уже есть в раскраске рельефа (маска 10 м выше);
данные OSM о воде лежат в файле и при желании terrain-модуль может заменить ими маски рек, построенные
по стоку. Данные OSM выгружаются через Overpass API (tools/osm/fetch_osm.py) и хранятся в репозитории,
а не запрашиваются игрой в реальном времени.
Для рантайм-мест (по координатам) OSM-данных нет — ставятся только ветроуказатели на стартах, без домов, дорог и проводов.
Вода
Класс «вода» задаёт не только цвет, но и поведение: над водой источники термиков слабые (0,05 из 1 по силе, против ≈0,87 у ровного поля). Визуально вода реагирует на ветер: в штиль — зеркало, к скорости ветра ≈ полная шероховатость («матовая рябь») — шероховатость и направление нормалей ряби идут поперёк ветра; в пятнах порывов рябь темнее («кошачьи лапы» — меньше отражённого неба), против солнца искрится. Со стороны, откуда дует ветер, вода гасится сушей и остаётся гладкой полосой (4 выборки маски воды против ветра). Вдоль берега — тонкая полоса мокрого грунта. Подробнее о ветре на воде и суше — на странице Облака и тени и в разделе трав ниже.
Лес и растительность
Три плана леса с высоты:
- Полог рельефа (на самом классе «лес» в шейдере) — кроны-ячейки Вороного ≈6 м, освещение по солнцу, тень от соседней кроны, тёмные просветы; на расстоянии, где отдельная крона мельче пикселя, — плавный переход к среднему тону полога с пятнами древостоев.
- Средний план (0,35–3,5 км) — билборды деревьев из атласа импостеров на сетке 12 м.
- Ближний план (до ≈0,7 радиуса видимости моделей) — 3D-модели: 5 пород (берёза, лиственница, кедр, ель, сосна) × 3 LOD, порода зависит от высотного пояса и экспозиции склона (ель на северных, сосна на южных сухих), локация может переопределить веса пород.
Деревья стоят только там, где маска «деталь 10 м» показывает лес (доля ≥ 0,5), и не стоят в воде (доля
воды маски < 0,35). У кромки леса деревья гуще и меньше утоплены — опушка выглядит объёмнее, а не
обрывается стеной. Просеки (дороги, коридор ЛЭП, здания, поля посадок) вырезают деревья явной маской
(WorldClearings) — ни модель, ни импостер туда не попадают.
Травинки вокруг камеры, их прореживание и качание от ветра — отдельная механика, читайте docs/guide/vegetation.md (параметры и графические пресеты) и раздел «Ветер на земле» ниже.
Как рельеф строится и подгружается
Меш. Каждый слой высот режется на чанки; у всех чанков слоя общие плоские сетки нескольких LOD
(шаг 1, 2, 4… клетки) — высоту в них добавляет вершинный шейдер выборкой из текстуры высот, поэтому
построение меша мгновенное. LOD переключается по расстоянию камеры до чанка; щели между уровнями
закрывает «юбка». Коллизии как таковой нет — полёт и посадка используют функцию height_at
(билинейная интерполяция самого детального слоя, покрывающего точку; ≈1,6 мкс на вызов).
Рантайм-загрузка (полёт по координатам) не подвешивает главный поток: тайлы высот и карты покрова
качаются через HTTPRequest в фоновых потоках, сборка меша, деревьев и травы идёт по кадрам в рабочем
потоке, пока экран загрузки показывает этапы и долю прогресса. На высоких широтах пиксель
веб-меркатора мельчает как cos(широты) — уровень тайлов автоматически понижается, чтобы сетка не
раздувалась (например, у Гренландии на 72° с. ш.).
Ошибки возвращают в меню с понятным сообщением: нет связи с сервером рельефа, для точки нет данных (тайл 403/404), точка — море (высота ниже уровня моря без карты покрова с сушей рядом), сервер рельефа не отвечает (таймаут по неизменному прогрессу).
Границы модели
- Разрешение. Высоты — 25 м у встроенных мест (30 м у рантайм-мест), карта покрова — 10 м у детальной маски / 25 м у общей карты классов. Мельче этого рельеф ничего не различает — камни, тропинки и отдельные кусты на карте не «настоящие», а процедурный рисунок по статистике.
- DSM, а не DTM. Высота в лесу — верх крон, а не земля под ними; посадка в лес — это столкновение с кронами, а не спуск сквозь них до земли.
- Из OSM берётся не всё. Рисуются дороги, здания, ЛЭП и заборы у посадок; реки и озёра берутся не из OSM-геометрии, а из общей карты воды (маска 10 м/класс WorldCover). Другие объекты OSM (мосты, малые формы, дворы) не отображаются.
- Рантайм-места беднее встроенных: без OSM (нет домов, дорог, проводов, заборов), без маски воды 10 м (вода — только по классу WorldCover), без специально расставленных посадочных площадок — только выбранная точка и курс вниз по склону.
- Бюджет данных — не больше 15 МБ на встроенное место (высоты + карта покрова + маски), поэтому часть деталей (например, ширина ручья по тегу OSM) намеренно не учитывается.
- Термики завязаны на ту же карту, что и цвет земли: если WorldCover ошибся с классом (типичная ошибка спутниковой классификации — спутать пойму с лесом), это отражается и в термиках, и в картинке одинаково — модель не «подглядывает» правильный ответ отдельно от того, что видно пилоту.
Что рассматривали и почему так
- Тайлы карты для экрана выбора места. Стандартные тайлы
tile.openstreetmap.orgпо политике использования — только для умеренного, некоммерческого трафика с атрибуцией и без массовой предзагрузки; для распространяемой игры без гарантированного лимита это не подходит. Платные сервисы (MapTiler, Thunderforest) потребовали бы зашить API-ключ в открытый код. Свой сервер тайлов из OSM — вариант на будущее, но требует инфраструктуры. Выбрана отмывка рельефа (hillshade) из тех же тайлов высот, что и так нужны для полёта: без внешних сервисов и ключей, горы и долины читаются пилоту лучше дорог. - DEM для рантайма. Coperniсus DEM лучше по качеству, но в игру его для рантайм-точек по всему миру не зашить (весь земной шар — не 15 МБ). OpenTopography даёт удобный API, но требует ключ и ограничен по площади и числу запросов в сутки — не годится для игры у случайного пользователя. AWS Terrain Tiles — открытые PNG-тайлы без ключа и без лимитов, декодируются самим движком; качество немного ниже Copernicus (местами ступеньки SRTM), но для полёта достаточно.
- DTM без леса не нашли с подходящей лицензией (FABDEM — CC-BY-NC), поэтому вместо попытки убрать лес из высот выбрано простое сглаживание + утопление 3D-моделей деревьев в поверхность.
- Одна карта на три задачи. Цвет земли, расстановка деревьев и сила термиков раньше могли бы жить в трёх разных структурах; решили держать одну карту поверхности как единственный источник истины — это и проще, и не даёт картинке разойтись с моделью термиков.
Подробнее
- docs/guide/terrain.md — полное устройство модуля рельефа (файлы, формулы, параметры).
- docs/research/terrain_sources.md — сравнение источников высот и картографических подложек.
- docs/guide/world-objects.md — OSM-объекты, посадочные площадки, ветроуказатели, лагерь и костёр у старта.
- docs/guide/vegetation.md — травинки и деревья по кромке леса.
- Код: scripts/terrain/, scripts/world_objects/.
- Подготовка данных места: tools/terrain/fetch_dem.py, tools/terrain/fetch_landcover.py, tools/osm/fetch_osm.py.


