aboutsummaryrefslogtreecommitdiff
path: root/docs/tomes
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tomes')
-rw-r--r--docs/tomes/04-world.md24
-rw-r--r--docs/tomes/05-render.md72
-rw-r--r--docs/tomes/06-behavior.md22
3 files changed, 103 insertions, 15 deletions
diff --git a/docs/tomes/04-world.md b/docs/tomes/04-world.md
index f9c0e67..e486e18 100644
--- a/docs/tomes/04-world.md
+++ b/docs/tomes/04-world.md
@@ -430,6 +430,30 @@ full 00000040 -> compact 2000
full 00200000 -> compact 8000
```
+Бит `0x400` в маске грани рельефа управляет detail-текстурой. В `Terrain.dll`
+метод `CShade` по смещению `+0x10` таблицы `0x10065108` ведёт к `0x10028A50`:
+он читает `flags` по смещению `+0x3C` и проверяет бит в `0x10029191`. Ветка для
+очищенного бита обнуляет указатель detail-текстуры в `0x10029427`. Затем
+`Ngi32` применяет режим 1 или 7: для RGB stage 0 умножает текстуру на diffuse-
+цвет, а stage 1 отключён. Alpha режима 1 берётся из texture, режима 7 — из
+diffuse; на проверенных непрозрачных полосах основания это различие не меняет
+цвет фрагмента. Текущий код сохраняет выбор в каждой полосе отрисовки рельефа:
+
+```rust
+let terrain_base_only = first_face.flags.0 & 0x400 == 0;
+```
+
+Фрагментный шейдер пропускает умножение на detail-текстуру:
+
+```glsl
+bool terrain_base_only = (mode & 16) != 0;
+vec3 base_rgb = terrain_base_only ? base.rgb : 2.0 * base.rgb * detail.rgb;
+```
+
+В исходных картах бит установлен у всех 275 882 граней рельефа. У полос
+основания, которые создаются процедурно при загрузке миссии, бит очищен;
+именно поэтому им нужен этот вариант без detail-текстуры.
+
Для шестибитного material-поля используются full-биты `0x100`, `0x8000`,
`0x10000`, `0x40000`, `0x80000` и `0x80`; они переходят соответственно в
compact-биты `1`, `2`, `4`, `8`, `0x10`, `0x20`.
diff --git a/docs/tomes/05-render.md b/docs/tomes/05-render.md
index b04af31..545aa1a 100644
--- a/docs/tomes/05-render.md
+++ b/docs/tomes/05-render.md
@@ -362,12 +362,30 @@ local.set_translation(pose.position);
world[n] = world[parent(n)] * local;
```
-Статический Vulkan preview берёт начальный кадр узла из явной ссылки прототипа
-на CTLD `.ctl`. Используются только включённые строки, а при повторе node ID
-поздняя строка заменяет раннюю. Без `--static-animation-frame` preview применяет
-эти настройки узлов; узлы без настройки остаются на кадре `0`. Явный
-`--static-animation-frame N` переопределяет их и задаёт `N` всем узлам.
-Результат — одна статическая поза, не обновление анимации, Control или AI.
+Статический Vulkan preview берёт CTLD `.ctl` из явной ссылки прототипа.
+Поддерживаемые Control timeline с tag 21 сэмплируются при запуске на native
+clock `0`; разрешённые NDP providers передают конечные type-1 значения.
+Неподдерживаемый режим или variable mapping, а также отсутствующее или
+неразрешённое gate value оставляют компонент на статических CTLD bindings. В
+timeline участвуют только включённые строки; при повторном node ID поздняя
+строка заменяет раннюю.
+
+Без `--static-animation-frame` preview сохраняет экземпляр Control и при
+каждом redraw сэмплирует поддерживаемый timeline на текущем native clock.
+Обновлённая Node38-поза перепроецирует видимую геометрию в заранее выделенный
+vertex span, оставляя индексы и draw ranges неизменными. Если в пути Unit DAT
+компонента есть такой Control, заново вычисляется его EXTO mount socket и
+перепроецируется дочерняя геометрия; дочерний mount использует preorder-порядок
+Unit DAT. Внутренние INTO-компоненты здесь не считаются глобальными MSH
+socket mounts. Обновлённые вершины и shadow-треугольники попадают в общий
+mesh upload перед следующим кадром. Culling sphere восстанавливается от
+начальной native sphere и расширяется до текущих shadow-треугольников; это
+`shortcut:`, потому что native обновление bounding sphere для анимированной
+геометрии пока не установлено. Это путь сэмплирования Control-позы, не AI или
+анимация эффектов.
+
+Явный `--static-animation-frame N` переопределяет timeline и задаёт `N` всем
+узлам, пропуская runtime Control-сэмпл.
MSH sampler выбирает type 19 frame округлением `(time - 0.5)` к ближайшему
целому с ties-to-even, затем интерполирует выбранный type 8 key и следующий
key в исходном `time`; это portable-вариант native x87 conversion в default
@@ -625,15 +643,20 @@ Lightmap не является обычной diffuse texture. WEAR содерж
отдельным slot или texture stage. Замена lightmap предварительным умножением в
diffuse texture ломает LOD, atlas coordinates и динамическую модуляцию.
-Vulkan preview строит projected shadows для выбранных зданий и роботов,
-отбрасывает spheres вне шести clip-плоскостей с радиусом `sphere + 100` и
+Vulkan preview строит проецируемые тени для объектов, отбрасывающих тени,
+отбрасывает сферы вне шести clip-плоскостей с радиусом `sphere + 100` и
сохраняет порядок видимых кандидатов; frame builder обрабатывает не более 20
-casters. Текущая реализация выделяет страницы в atlas `256 x 256` с 28 page
-slots и использует одну smoothing pass. Вызов preview передаёт `fade = 1.0` и
-LOD defaults: minimum LOD `1` и detail multiplier `1.0` отдельно для зданий и
-роботов. Rust-путь не загружает `shade.cfg`: эти значения задаются кодом, а
-параметры файла пока не влияют на preview. Проекция учитывает вклад
-directional и point lights.
+объектов. Текущая реализация выделяет страницы в atlas `256 x 256` с 28 page
+slots и использует одно сглаживание. Preview применяет native defaults
+`RobShadowsOn = true` и `BldShadowsOn = false`: объект kind `4` проверяет
+первый флаг, остальные kinds — второй. Поэтому роботы BTLU остаются объектами,
+отбрасывающими тени, а объекты FORT и STAT их не создают. Preview пока не
+загружает `shade.cfg`, поэтому значения из пользовательского файла не меняют
+список объектов, отбрасывающих тени. Проверка действует только на проецируемые
+тени: отдельный список объектов для затенения солнца по-прежнему включает
+FORT, BTLU и STAT. Вызов preview передаёт `fade = 1.0` и LOD defaults:
+minimum LOD `1` и detail multiplier `1.0` отдельно для зданий и роботов.
+Проекция учитывает вклад directional и point lights.
Receiver projection обрезает projected quad по рёбрам треугольника. Native ray
query descriptor в `+0x10` требует наличия всех переданных bits, а descriptor
@@ -955,6 +978,23 @@ for (face, assignment) in mesh.faces.iter().zip(assignments.iter()) {
}
```
+Подготовка BAS вынесена в `fparkan-terrain::build_basement_foundations`.
+Функция получает внешние и внутренние кольца в порядке размещения, строит
+упорядоченные пересечения внешней границы с текущей поверхностью и возвращает
+исходные фрагменты рельефа вместе с треугольниками отмостки в одном наборе.
+`TerrainWorld::with_basement_foundation` принимает этот набор во владение и
+устанавливает те же координаты и маски в BVH высотных запросов и пересечений.
+Предпросмотр миссии на Vulkan пока строит только LOD0: связывание BAS-записей
+с этой подготовкой ещё не подключено, поэтому наличие API не означает, что
+геометрия миссии уже обрезана.
+
+Внешнее кольцо должно лежать на области LOD0, а каждый его сегмент — оставаться
+покрытым текущей поверхностью. Непокрытый сегмент или пересекающиеся контуры
+дают ошибку; карта не остаётся частично обрезанной. Первичная нормализация
+использует исходные грани и соседей LOD0, последующие пересечения и вырезания —
+канонические фрагменты после предыдущих размещений. Соответствие динамических
+соседей, создаваемых нативным движком, пока не моделируется.
+
## Материалы ландшафта
Рядом с `Land.msh` лежат `Land1.wea` и `Land2.wea`. Старший байт
@@ -996,7 +1036,9 @@ animation phase; object batches сохраняют их legacy blend/depth/alpha
После загрузки world path создаёт интерактивную free-flight камеру (`WASD`,
`E/Q`, `Shift`, `Ctrl`, RMB relative-look), обновляет listener и на каждом
-кадре собирает environment frame. Mission-local `sky.ske`/`sky.wea` выбирают
+кадре собирает environment frame. После шага движения камера проверяет высоту
+`TerrainWorld`: над конечной поверхностью сохраняется начальный просвет, а вне
+поверхности высота не ограничивается. Mission-local `sky.ske`/`sky.wea` выбирают
атмосферное расписание и sky materials, `effects.rlb/env_lightning` даёт
lightning visual; weather particles, flares, sun/moon, point lights,
projected shadows и audio events обновляются вместе с камерой и временем.
diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md
index e663389..d1af7ba 100644
--- a/docs/tomes/06-behavior.md
+++ b/docs/tomes/06-behavior.md
@@ -424,6 +424,15 @@ type 4, в том числе четыре `f_smalllight_y` с offsets 104–107
offsets 119–121. В `fr_l_gener.ctl` найдено 35 строк type 4, включая
`f_gener_ball` с offset 85.
+Control.dll `+0x8B10` передаёт указатель текущей записи диспетчеру `+0x2D4B0`.
+Теги 2 и 5 направляются в общий читатель `+0x21D50`: таблица виртуальных методов
+тега 2 (`+0x3CBD8`) вызывает его через обёртку `+0x29650`, а таблица тега 5
+(`+0x3CDF8`) указывает прямо на него в позиции `+0x1C`. Читатель потребляет
+заголовок размером `0xB0` байт со счётчиком `u32` по `+0xAC`, затем `count`
+значений `u32`, слово длины и, при ненулевой длине, строку с завершающим NUL;
+указатель возврата указывает на следующую запись. Поэтому для тегов 2 и 5 подтверждён общий
+структурный формат; смысл их полей пока не назначен.
+
Resolver прототипов хранит явную registry-ссылку на `.cpt` отдельно от ссылки
на `.ctl`. Если строки type 4 разобраны и явная ссылка на CPT есть, подготовка
читает ровно указанные archive/name; имя CPT не выводится из имени CTL. В CPT
@@ -445,6 +454,19 @@ C0 равен 0, поэтому найденные offsets 104–107, 119–121
условий, загрузка FX materials, activation, выполнение FX opcodes и видимый
рендер эффектов пока не реализованы.
+После типизированных записей CTLD хранит 21 ссылку на группу эффектов. В
+`fr_l_plant.ctl` первая ссылка равна `8`, остальные 20 содержат `u32::MAX`; за
+ними расположены 13 таблиц групп. При разборе по адресу `+0x8B10` к каждой
+ссылке, кроме `u32::MAX`, прибавляется число групп, зарегистрированных до
+таблиц этого CTL; получившиеся индексы сохраняются в control mapping. При
+событии `0x80000020` код по адресу `+0x7830` сразу выходит, если поле дескриптора
+`+0xC0` равно нулю. Разбор по адресу `+0x8B10` вызывает диспетчер групп `+0x2800`
+с индексом группы по умолчанию только при ненулевом `+0xC0`. Назначение поля
+дескриптора и условия его заполнения на стороне producer пока неизвестны.
+`initial_effect_group` хранит проверенную ссылку на группу по умолчанию. Это
+поле описывает данные CTL и не выполняет activation, загрузку FX materials,
+FX opcodes или рендер эффектов.
+
CPU-only обход `MISSIONS/Autodemo.00/data.tma` подготовил четыре CTL с 80
строками type 4 и четыре явных CPT-списка (всего 322 записи). Среди пар были
`fortif.rlb/fr_l_plant.ctl` и `fortif.rlb/fr_l_plant.cpt` (155 точек), а также