aboutsummaryrefslogtreecommitdiff
path: root/docs/specs/terrain-map-loading.md
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-06-22 00:58:51 +0300
committerValentin Popov <valentin@popov.link>2026-06-22 00:58:51 +0300
commit78fc5f1debf1395d5df0bab7cc0dde54351205cb (patch)
treeef8f7c72a183723fcbea0b2d1fefd7c28ca7bc18 /docs/specs/terrain-map-loading.md
parent50c2cf4686b53ebd2b76318223096660e92305a4 (diff)
downloadfparkan-78fc5f1debf1395d5df0bab7cc0dde54351205cb.tar.xz
fparkan-78fc5f1debf1395d5df0bab7cc0dde54351205cb.zip
docs: rewrite MkDocs documentation
Diffstat (limited to 'docs/specs/terrain-map-loading.md')
-rw-r--r--docs/specs/terrain-map-loading.md291
1 files changed, 0 insertions, 291 deletions
diff --git a/docs/specs/terrain-map-loading.md b/docs/specs/terrain-map-loading.md
deleted file mode 100644
index a511799..0000000
--- a/docs/specs/terrain-map-loading.md
+++ /dev/null
@@ -1,291 +0,0 @@
-# Terrain + ArealMap
-
-Документ описывает подсистему ландшафта и ареалов мира в движке Parkan: Iron Strategy:
-
-- `Land.msh` (terrain-геометрия и вспомогательные таблицы);
-- `Land.map` (ареалы и навигационные связи);
-- `BuildDat.lst` (категории объектных зон).
-
-Описание дано в высокоуровневом переносимом виде, без ссылок на внутренние адреса и имена из дизассемблера.
-
-Связанные страницы:
-
-- [NRes](nres.md)
-- [RsLi](rsli.md)
-- [MSH core](msh-core.md)
-- [Render pipeline](render.md)
-
-## 1. End-to-End загрузка уровня
-
-Для каждой карты движок загружает пару файлов:
-
-- `.../Land.msh`
-- `.../Land.map`
-
-Высокоуровневый порядок:
-
-1. Открыть `Land.msh` как `NRes`.
-2. Прочитать обязательные terrain-chunk'и.
-3. Построить runtime-структуры terrain (slots, faces, spatial grid).
-4. Открыть `Land.map` как `NRes`.
-5. Найти единственный chunk `type=12`.
-6. Прочитать ареалы, их связи и cell-grid.
-7. Применить инициализацию объектных категорий из `BuildDat.lst`.
-
-## 2. Формат `Land.msh`
-
-`Land.msh` — обычный `NRes` архив с фиксированным набором terrain-ресурсов.
-
-## 2.1. Состав chunk'ов
-
-Обязательные типы:
-
-- `1`, `2`, `3`, `4`, `5`, `11`, `18`, `21`
-
-Опциональные типы:
-
-- `14`
-
-Наблюдаемый retail-порядок chunk'ов:
-
-```text
-[1, 2, 3, 4, 5, 18, 14, 11, 21]
-```
-
-## 2.2. Stride и атрибуты
-
-| Type | Назначение | Stride |
-|---:|---|---:|
-| 1 | node/slot матрица | 38 |
-| 3 | позиции вершин | 12 |
-| 4 | нормали (packed) | 4 |
-| 5 | UV (packed) | 4 |
-| 11 | cell-ускоритель | 4 |
-| 14 | доп. поток | 4 |
-| 18 | доп. поток | 4 |
-| 21 | terrain face | 28 |
-
-Общее правило для этих chunk'ов:
-
-- `attr1 == size / stride`
-- `attr3 == stride`
-
-## 2.3. Type `2`: slot table
-
-`type=2` содержит:
-
-- заголовок `0x8C` байт;
-- затем таблицу slots по `68` байт.
-
-Инварианты:
-
-- `size >= 0x8C`
-- `(size - 0x8C) % 68 == 0`
-- `attr1 == (size - 0x8C) / 68`
-- `attr3 == 68`
-
-## 2.4. Type `21`: terrain face (28 байт)
-
-Высокоуровневая структура face:
-
-- флаги face;
-- индексы треугольника (`i0, i1, i2`);
-- индексы соседей (`n0, n1, n2`, значение `0xFFFF` = нет соседа);
-- служебные поля (материал/класс/edge-поля и др.).
-
-Критичные проверки:
-
-- `i0/i1/i2 < vertex_count` (`type=3`);
-- `nX == 0xFFFF` или `nX < face_count`.
-
-## 2.5. Маски face и compact-представления
-
-В рантайме используются:
-
-- полная 32-битная маска (`full`);
-- компактные представления (`compactMain16`, `compactMaterial6`).
-
-Подтвержденный remap `full -> compactMain16`:
-
-| Full bit | Compact bit |
-|---:|---:|
-| `0x00000001` | `0x0001` |
-| `0x00000008` | `0x0002` |
-| `0x00000010` | `0x0004` |
-| `0x00000020` | `0x0008` |
-| `0x00001000` | `0x0010` |
-| `0x00004000` | `0x0020` |
-| `0x00000002` | `0x0040` |
-| `0x00000400` | `0x0080` |
-| `0x00000800` | `0x0100` |
-| `0x00020000` | `0x0200` |
-| `0x00002000` | `0x0400` |
-| `0x00000200` | `0x0800` |
-| `0x00000004` | `0x1000` |
-| `0x00000040` | `0x2000` |
-| `0x00200000` | `0x8000` |
-
-Подтвержденный remap `full -> compactMaterial6`:
-
-| Full bit | Compact bit |
-|---:|---:|
-| `0x00000100` | `0x01` |
-| `0x00008000` | `0x02` |
-| `0x00010000` | `0x04` |
-| `0x00040000` | `0x08` |
-| `0x00080000` | `0x10` |
-| `0x00000080` | `0x20` |
-
-Для 1:1 реализации нужно поддерживать оба представления и обратное восстановление `compact -> full`.
-
-## 2.6. Type `11` и cell-ускоритель terrain
-
-`type=11` служит источником cell-ускорителя для terrain-запросов.
-
-Практические требования для editor/toolchain:
-
-- не переупорядочивать содержимое без полного пересчета зависимых таблиц;
-- сохранять служебные/неизвестные поля побайтно;
-- выполнять валидацию диапазонов face/slot после любых правок.
-
-## 3. Формат `Land.map` (chunk `type=12`)
-
-`Land.map` — `NRes`, содержащий ровно один ресурс `type=12`.
-
-Контракт верхнего уровня:
-
-- `entry.attr1` = `areal_count`;
-- payload включает:
- - `areal_count` переменных записей ареалов;
- - затем grid-секцию cell-попаданий.
-
-## 3.1. Запись ареала
-
-Старт записи:
-
-```c
-float anchor_x; // +0
-float anchor_y; // +4
-float anchor_z; // +8
-float reserved_12; // +12
-float area_metric; // +16
-float normal_x; // +20
-float normal_y; // +24
-float normal_z; // +28
-uint32_t logic_flag; // +32
-uint32_t reserved_36; // +36
-uint32_t class_id; // +40
-uint32_t reserved_44; // +44
-uint32_t vertex_count; // +48
-uint32_t poly_count; // +52
-```
-
-Далее:
-
-1. `float3 vertices[vertex_count]`
-2. `EdgeLink8 links[vertex_count + 3 * poly_count]`, где
- `EdgeLink8 = { int32 area_ref; int32 edge_ref; }`
-3. для каждого полигона block:
- - `uint32 n`
- - `4 * (3*n + 1)` байт данных полигона
-
-## 3.2. Семантика edge-link
-
-Для `links[0 .. vertex_count-1]`:
-
-- `(-1, -1)` означает «соседа нет»;
-- иначе `area_ref` указывает на индекс соседнего ареала, `edge_ref` — на ребро в соседнем ареале.
-
-## 3.3. Grid-секция после ареалов
-
-Формат:
-
-```c
-uint32 cellsX;
-uint32 cellsY;
-for (x=0; x<cellsX; x++) {
- for (y=0; y<cellsY; y++) {
- uint16 hitCount;
- uint16 areaIds[hitCount];
- }
-}
-```
-
-В runtime существует упакованное cell-meta представление:
-
-- high 10 бит: `hitCount`;
-- low 22 бита: `startIndex` (в общем `areaIds` пуле).
-
-## 3.4. Валидация целостности chunk 12
-
-Обязательные проверки:
-
-- `areal_count > 0`;
-- `cellsX > 0 && cellsY > 0`;
-- каждый `area_id` из cell-списков `< areal_count`;
-- все `area_ref/edge_ref` валидны относительно целевых ареалов;
-- полный объем прочитанных байт должен точно совпасть с размером payload.
-
-## 4. `BuildDat.lst`
-
-Используются 12 объектных категорий ареалов:
-
-| Имя | Маска |
-|---|---:|
-| `Bunker_Small` | `0x80010000` |
-| `Bunker_Medium` | `0x80020000` |
-| `Bunker_Large` | `0x80040000` |
-| `Generator` | `0x80000002` |
-| `Mine` | `0x80000004` |
-| `Storage` | `0x80000008` |
-| `Plant` | `0x80000010` |
-| `Hangar` | `0x80000040` |
-| `MainTeleport` | `0x80000200` |
-| `Institute` | `0x80000400` |
-| `Tower_Medium` | `0x80100000` |
-| `Tower_Large` | `0x80200000` |
-
-Файл должен парситься строго секционно; поврежденный формат считается ошибкой.
-
-## 5. Требования к reader/writer/editor
-
-1. Сохранять порядок и бинарную форму chunk'ов, если не выполняется осознанная нормализация.
-2. Все неизвестные поля хранить и писать побайтно (`preserve-as-is`).
-3. После правок пересчитывать только вычислимые поля, не «чистить» opaque-данные.
-4. Проверять диапазоны индексов между связанными таблицами (`nodes/slots/faces/vertices/areas/cells`).
-5. Для неизмененных ресурсов обеспечивать byte-identical roundtrip.
-
-## 6. Эмпирическая верификация (retail)
-
-Валидация на `testdata/Parkan - Iron Strategy`:
-
-- карт: `33`
-- `Land.msh`: `33/33` валидны
-- `Land.map`: `33/33` валидны
-- `issues_total = 0`, `errors_total = 0`, `warnings_total = 0`
-
-Подтвержденные наблюдения:
-
-- `Land.msh` порядок chunk'ов стабилен: `[1,2,3,4,5,18,14,11,21]`;
-- `Land.map` всегда содержит один chunk `type=12`;
-- `cellsX == cellsY == 128` во всех retail-картах;
-- `poly_count == 0` во всем проверенном retail-корпусе;
-- `normal` имеет длину ~1.0;
-- `reserved_12`, `reserved_36`, `reserved_44` в retail наблюдаются как `0`.
-
-Проверено legacy-валидатором terrain/map форматов.
-
-## 7. Статус покрытия и что осталось до 100%
-
-Закрыто:
-
-- бинарный контракт `Land.msh` и `Land.map`;
-- диапазонные и структурные инварианты;
-- remap масок `full/compact`;
-- валидация на полном retail-корпусе карт.
-
-Осталось до полного 100% архитектурного покрытия движка:
-
-1. Полная доменная семантика `class_id` и `logic_flag` (игровые значения/поведенческие правила).
-2. Полная спецификация ветки `poly_count > 0` на живых данных (в retail не встречена).
-3. Полная field-level семантика части битов `TerrainFace28.flags` (бинарный контракт и remap закрыты, но не все биты имеют документированные геймплейные имена).