feat(render): integrate Control effects and animated world scene
Docs Deploy / Build and Deploy MkDocs (push) Successful in 37s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 37s
This commit is contained in:
7 files changed
+8364
-2601
No files matched your search
@@ -5,8 +5,10 @@
|
|||||||
интерактивную сцену выбранной карты: terrain, все доступные MSH-компоненты
|
интерактивную сцену выбранной карты: terrain, все доступные MSH-компоненты
|
||||||
объектов, материалы, динамические тени, небо, погоду, lightning FX и звуковые
|
объектов, материалы, динамические тени, небо, погоду, lightning FX и звуковые
|
||||||
события. Это просмотр карты с полной графической сценой; прохождение миссии и
|
события. Это просмотр карты с полной графической сценой; прохождение миссии и
|
||||||
игровое поведение юнитов пока не запускаются, а модели показываются в статической
|
игровое поведение юнитов пока не запускаются. Модели начинают с настроек узлов
|
||||||
позе, заданной сохранёнными настройками узлов прототипа.
|
прототипа, а поддерживаемые Control-анимации и эффекты обновляются по общим
|
||||||
|
часам сцены. Неподдерживаемые Control-треки остаются на сохранённой начальной
|
||||||
|
позе.
|
||||||
|
|
||||||
## Запуск
|
## Запуск
|
||||||
|
|
||||||
@@ -46,23 +48,21 @@ cargo run --release -p fparkan-game -- `
|
|||||||
луна, flares, молнии, дождь и снег, point lights, динамические тени и связанные
|
луна, flares, молнии, дождь и снег, point lights, динамические тени и связанные
|
||||||
звуковые события обновляются в каждом кадре.
|
звуковые события обновляются в каждом кадре.
|
||||||
|
|
||||||
`--frames N` ограничивает запуск числом представленных кадров для
|
`--frames N` ограничивает запуск числом кадров для smoke/readback-проверок;
|
||||||
smoke/readback-проверок;
|
значение `0` означает бесконечный интерактивный запуск. `--legacy-camera-capture`
|
||||||
значение `0` означает бесконечный интерактивный запуск. `--control-clock-ms N`
|
читает сохранённый захват камеры и запускает воспроизводимый режим без
|
||||||
воспроизводит общий clock анимации MSH и материалов вместе с окружением от нуля
|
free-flight управления. В обычном запуске накопленный runtime clock обновляет
|
||||||
до `N` за `--frames` кадров и требует не менее двух кадров. Пересоздание
|
MSH Control-анимацию, поддержанные Control FX и анимацию материалов.
|
||||||
swapchain повторяет текущий sample времени и состояние мира; перед повторной
|
`--control-clock-ms <u32>` вместе с `--frames N` (не меньше двух) воспроизводит
|
||||||
отправкой обновляются camera projection и viewport-зависимая геометрия. Это не
|
этот clock от нуля до заданного миллисекундного значения за выбранные кадры.
|
||||||
продвигает сцену или replay clock. Счётчик и replay clock переходят дальше
|
|
||||||
после представленного кадра.
|
`--static-animation-frame <u16>` задаёт один кадр для всех MSH-узлов и
|
||||||
`--legacy-camera-capture` читает сохранённый захват камеры и запускает
|
выключает выбор MSH-позы из Control clock. Без override приложение берёт
|
||||||
воспроизводимый режим без
|
начальные настройки узлов из явных `.ctl` bindings, затем применяет
|
||||||
free-flight управления. `--static-animation-frame <u16>` задаёт один кадр для
|
поддержанные Control-треки. Узлы без настройки остаются на кадре `0`. Это не
|
||||||
всех узлов. Если параметр не указан, приложение берёт сохранённые настройки
|
запускает AI, миссионные события или полное поведение юнитов.
|
||||||
узлов из явной ссылки прототипа на `.ctl`; для узлов без такой настройки
|
`--static-material-phase <u16>` фиксирует фазу MSH и terrain материалов; фаза
|
||||||
используется кадр `0`. Статическая поза не запускает игровой Control, AI или
|
материала Control FX остаётся частью его normalized command timeline.
|
||||||
полное поведение юнитов.
|
|
||||||
`--static-material-phase <u16>` выбирает фиксированную фазу материала.
|
|
||||||
`--readback-out target/frame.raw` сохраняет последний кадр GPU. `--validation`
|
`--readback-out target/frame.raw` сохраняет последний кадр GPU. `--validation`
|
||||||
включает Vulkan validation layers и завершает запуск с ошибкой при предупреждении
|
включает Vulkan validation layers и завершает запуск с ошибкой при предупреждении
|
||||||
или ошибке. Readback сохраняет байты в формате surface без преобразования;
|
или ошибке. Readback сохраняет байты в формате surface без преобразования;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ fparkan-resource = { path = "../../crates/fparkan-resource" }
|
|||||||
fparkan-render = { path = "../../crates/fparkan-render" }
|
fparkan-render = { path = "../../crates/fparkan-render" }
|
||||||
fparkan-platform-winit = { path = "../../adapters/fparkan-platform-winit" }
|
fparkan-platform-winit = { path = "../../adapters/fparkan-platform-winit" }
|
||||||
fparkan-msh = { path = "../../crates/fparkan-msh" }
|
fparkan-msh = { path = "../../crates/fparkan-msh" }
|
||||||
|
fparkan-material = { path = "../../crates/fparkan-material" }
|
||||||
fparkan-prototype = { path = "../../crates/fparkan-prototype" }
|
fparkan-prototype = { path = "../../crates/fparkan-prototype" }
|
||||||
fparkan-render-vulkan = { path = "../../adapters/fparkan-render-vulkan" }
|
fparkan-render-vulkan = { path = "../../adapters/fparkan-render-vulkan" }
|
||||||
fparkan-runtime = { path = "../../crates/fparkan-runtime" }
|
fparkan-runtime = { path = "../../crates/fparkan-runtime" }
|
||||||
@@ -24,6 +25,3 @@ rodio = { version = "0.23.0", default-features = false, features = ["playback",
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
winit = { version = "0.30", default-features = false, features = ["rwh_06"] }
|
winit = { version = "0.30", default-features = false, features = ["rwh_06"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
fparkan-material = { path = "../../crates/fparkan-material" }
|
|
||||||
+8075
-2436
File diff suppressed because it is too large.
Load diff
@@ -236,11 +236,19 @@ packed: [key.colors[10], key.colors[14]],
|
|||||||
`AtmosphereFrame` пока не несёт этот бит обновления, поэтому sampler
|
`AtmosphereFrame` пока не несёт этот бит обновления, поэтому sampler
|
||||||
выдаёт интерполированный цвет при каждом запросе.
|
выдаёт интерполированный цвет при каждом запросе.
|
||||||
|
|
||||||
## Экранная геометрия солнца и луны
|
## Отрисовка солнца, луны и бликов
|
||||||
|
|
||||||
`CSun::Render` сначала переводит направление небесного тела в пиксели текущего
|
`CSun::Render` получает текущий viewport, проецирует направление солнца или
|
||||||
viewport, затем собирает quad с native XYZRHW-позицией. При положительной высоте
|
луны и собирает quad уже в его пикселях. `Terrain.dll` VA `0x1004AA40` передаёт
|
||||||
viewport Vulkan пиксели переводятся в clip-space так:
|
эту геометрию через shade callback; native FVF `0x1c4` задаёт
|
||||||
|
`XYZRHW | DIFFUSE | SPECULAR | TEX1`. Конвертер `0x10020700` сохраняет входные
|
||||||
|
`x`, `y` и `z`, а в `RHW` записывает `1.0`; исходный `z` равен `0.999`. Callback
|
||||||
|
включает depth test и выключает запись depth, поэтому более близкая поверхность
|
||||||
|
может закрыть спрайт, а сам спрайт не меняет глубину для последующих слоёв.
|
||||||
|
|
||||||
|
В Vulkan ряды 3 и 4 сохраняют этот contract отдельным bit 8 material mode.
|
||||||
|
CPU каждый кадр преобразует viewport-пиксели к clip space текущего размера
|
||||||
|
swapchain:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
position = [
|
position = [
|
||||||
@@ -250,13 +258,17 @@ position = [
|
|||||||
];
|
];
|
||||||
```
|
```
|
||||||
|
|
||||||
Vertex shader пропускает `clip_from_world` для строк солнца и луны. CPU каждый
|
Положительная высота Vulkan viewport отображает эти координаты в тот же
|
||||||
кадр пересчитывает центр и размер quad по текущему viewport; старые пиксельные
|
top-down экран. Vertex shader пропускает мировую матрицу только для этого
|
||||||
координаты не переносятся на новый размер. World-space billboards бликов
|
режима:
|
||||||
остаются отдельным путём. Материал экранного quad не освещается, vertex fog
|
|
||||||
отключён, а sky far-depth bit к нему не применяется.
|
|
||||||
|
|
||||||
Для мировой геометрии
|
```glsl
|
||||||
|
vec4 clip_position = screen_tl
|
||||||
|
? vec4(in_position, 1.0)
|
||||||
|
: frame.clip_from_world * vec4(in_position, 1.0);
|
||||||
|
```
|
||||||
|
|
||||||
|
Материал остаётся unlit, fog factor равен нулю. Для мировой геометрии
|
||||||
оригинал задаёт viewport `MinZ = 0.1`, `MaxZ = 0.99`: после отсечения
|
оригинал задаёт viewport `MinZ = 0.1`, `MaxZ = 0.99`: после отсечения
|
||||||
проекционная глубина отображается в этот диапазон:
|
проекционная глубина отображается в этот диапазон:
|
||||||
|
|
||||||
@@ -280,35 +292,39 @@ RVA `0x7170`, участок `0x71E7–0x723C`, копирует MinZ/MaxZ в re
|
|||||||
[таблице бинарников](original-binaries.md). Нативные значения этих двух полей
|
[таблице бинарников](original-binaries.md). Нативные значения этих двух полей
|
||||||
имеют биты `0x3DCCCCCD` и `0x3F7D70A4`.
|
имеют биты `0x3DCCCCCD` и `0x3F7D70A4`.
|
||||||
|
|
||||||
|
Sky-background bit 4 продолжает помещать слои на дальнюю плоскость. Отдельные
|
||||||
|
flare rows 5 и 6 пока используют world-space billboard builder: для них не
|
||||||
|
подтверждён этот же native TL путь.
|
||||||
|
|
||||||
## Геометрия визуальных FX-команд
|
## Эффекты Control
|
||||||
|
|
||||||
`fparkan-fx::fx_visual` формирует кадры для двух подтверждённых вариантов
|
Погодное расписание `sky.ske` — только один источник эффектов. У объектов
|
||||||
`f_gener_ball`. Op4 принимает mode 0 с положительным знаменателем в `body+0xC4`
|
миссии таблица Control (`.ctl`) связывает строки с FXID-командами. Текущий
|
||||||
и выдаёт camera-facing quad; расстояние камеры считается через native
|
preview выбирает начальную группу Control и исполняет только строки без
|
||||||
component-wise projection родительской матрицы. Op9 принимает mode 2:
|
predicate, chain и state gate. Условия игровых событий и переходы между
|
||||||
селектор `body+0xC4` со значением 0, 1 или 2 отображается в native flag base
|
группами принадлежат полному игровому Control runtime и здесь не моделируются.
|
||||||
3, 5 или 6 и выбирает одну из трёх сеток; категория render flags выбирает её
|
|
||||||
детализацию. `body+0xC8` выбирает UV path:
|
|
||||||
нулевое значение проецирует позицию вершины на XY, ненулевое использует
|
|
||||||
фиксированные координаты quad и cap. Кадр сохраняет MAT0 resource, фазу,
|
|
||||||
opacity, вершины и triangle indices для renderer.
|
|
||||||
|
|
||||||
Evaluator получает готовые command body, phase, camera point и внешнюю
|
Type 4 row задаёт локальную basis эффекта через три точки CTL point list. Для
|
||||||
матрицу. Выбор Control row, manager gates, owner attachment, header jitter и
|
валидной привязки первая точка также задаёт owner node. Путь MSH выбирает позу
|
||||||
global RNG остаются задачей владельца. `fparkan-game` пока использует для Op9
|
этого узла из текущей pose hierarchy; для внешнего mounted-компонента к ней
|
||||||
категорию 0 с наибольшей детализацией; выбор категории по projected size ещё
|
добавляется поза socket. После этого применяются object transform, header
|
||||||
не реализован.
|
scale и локальная матрица FX. Подробнее о порядке матриц см.
|
||||||
|
[описание MSH](msh.md#control-fx-и-owner-transform).
|
||||||
|
|
||||||
Для Op3 поддерживаются body-типы 0, 1 и 2. Поля отсчитываются от
|
Renderer preview поддерживает FXID-команды Op3 modes 0–2, Op4, Op7, Op8 и Op9.
|
||||||
`FxCommand.raw_body`, то есть после 4-байтового command word. Типы 0 и 1
|
Op3 mode0 строит camera-facing поверхность из анимируемых локальных позиции и
|
||||||
используют общие position/scale/phase/opacity tracks и camera-facing основу;
|
масштаба; Op7/Op8 обновляют отдельные элементы particle pool; Op9 создаёт
|
||||||
тип 1 и тип 2 также интерполируют ось, а тип 2 строит basis через native
|
индексированную полусферическую сетку. Op1 вычисляется отдельно как список
|
||||||
D110-порядок. Все три evaluator-а принимают уже собранную матрицу владельца и
|
point lights: selector 1 и записи без `flags & 0x80000000` входят в общий
|
||||||
не выбирают Control row или attachment. Текущий путь для типов 0 и 1
|
diffuse light set. Записи с этим битом сохраняют native flags для специальных
|
||||||
предполагает native render context 0: `Effect.dll` проверяет общий gate
|
путей и projected shadows, но не добавляются в общий diffuse список.
|
||||||
`context + 0x60 < 8`, а API этих evaluator-ов не выбирает другой context.
|
|
||||||
Evaluator типа 2 принимает индекс context явно и учитывает этот gate в `active`.
|
Body discriminator Op3 читается из первого DWORD `FxCommand.raw_body`; offsets
|
||||||
|
в evaluator-е относительны к данным после четырёхбайтового command word. Mode 1
|
||||||
|
добавляет анимируемую ось к camera-facing basis, mode 2 использует native
|
||||||
|
D110 basis. Для modes 0 и 1 preview предполагает render context 0, который
|
||||||
|
проходит общий gate `Effect.dll` `0x106C0`; их API не выбирает другой context.
|
||||||
|
Evaluator mode 2 принимает индекс context и учитывает gate при расчёте `active`.
|
||||||
|
|
||||||
У Op3 mode 1 ось задаёт длину прямоугольника, а не его нормаль. Для
|
У Op3 mode 1 ось задаёт длину прямоугольника, а не его нормаль. Для
|
||||||
локального вектора к камере `v` и анимируемой оси `a` столбцы базиса имеют
|
локального вектора к камере `v` и анимируемой оси `a` столбцы базиса имеют
|
||||||
@@ -359,27 +375,66 @@ RVA `0x93D0`, ветка mode 1 с `0x9739`, сборка столбцов `0x97
|
|||||||
семена отдельных экземпляров лишь детерминированно заменяют process-global
|
семена отдельных экземпляров лишь детерминированно заменяют process-global
|
||||||
состояние и не воспроизводят общий порядок вызовов.
|
состояние и не воспроизводят общий порядок вызовов.
|
||||||
|
|
||||||
|
`f_gener_ball` evaluator покрывает Op4 mode 0 с положительным знаменателем в
|
||||||
|
`body+0xC4` и Op9 mode 2. Для Op9 selectors `body+0xC4` со значениями 0, 1 и 2
|
||||||
|
отображаются в native flag bases 3, 5 и 6. Нулевой `body+0xC8` проецирует UV на
|
||||||
|
XY, ненулевой выбирает статические quad/cap координаты. Op4 вычисляет локальное
|
||||||
|
расстояние камеры тем же component-wise projection, что использует native path.
|
||||||
|
|
||||||
|
FX-команды используют общий preview clock и ограниченный набор time modes:
|
||||||
|
mode 0 оставляет фазу равной нулю, mode 1 вычисляет `elapsed / duration` без
|
||||||
|
зажатия, mode 2 повторяет цикл. Header flags `0x200` и `0x20` преобразуют эту
|
||||||
|
фазу; command path `0x8120` зажимает результат только после преобразований.
|
||||||
|
Effect renderer проверяет header bit `0x800` только при
|
||||||
|
render selector 0; native AniMesh component path был захвачен с selector 1,
|
||||||
|
поэтому preview использует selector 1 и не подавляет такие visual commands.
|
||||||
|
Этот capture также показал `0xD00` FX entries в 53-entry manager. Динамическое
|
||||||
|
состояние manager `A8`, связанное с header gate и фактической FX phase, пока не
|
||||||
|
моделируется. Header bit `0x10` относится к activation lifecycle и сам по себе
|
||||||
|
не отключает draw.
|
||||||
|
Header jitter и random shift хранятся один раз на Control row и совместно
|
||||||
|
применяются к его sibling-командам; отдельный детерминированный поток каждой
|
||||||
|
строки сохраняет эту связь, но не повторяет порядок глобального native RNG.
|
||||||
|
Неразобранные группы, event predicates и неразрешённые owner attachments
|
||||||
|
пропускаются.
|
||||||
|
|
||||||
|
Для visual FX material берётся из resource reference команды. MAT0 выбирает
|
||||||
|
фазу по normalized FX phase, независимо от wall-clock анимации world materials.
|
||||||
|
Command opacity передаётся vertex alpha, а FX MAT0 alpha не умножает её второй
|
||||||
|
раз; texture alpha продолжает участвовать в shader. Текущая preview-ветка
|
||||||
|
использует SourceAlpha и read-only depth state и допускает только MAT0-фазы,
|
||||||
|
проходящие локальный predicate additive-RGB approximation. Семантика native
|
||||||
|
`flag40` и directional-light ветки остаётся открытой.
|
||||||
|
|
||||||
|
Generated Op9 mesh разделяется на отдельный draw range для каждого native
|
||||||
|
quad и cap. Каждый range получает ключ по камере до первой индексированной
|
||||||
|
вершины, в порядке убывания расстояния. Равные ключи используют midpoint
|
||||||
|
insertion из native queue, поэтому их порядок не является стабильным по
|
||||||
|
первоначальному времени поступления. Preview использует category 0 как
|
||||||
|
highest-detail mesh; projected-size LOD и полное визуальное совпадение размера
|
||||||
|
и формы пока не реализованы.
|
||||||
|
|
||||||
## Частицы Op8
|
## Частицы Op8
|
||||||
|
|
||||||
`fparkan-fx::smoke` разбирает body Op8, хранит кольцевой пул команды и выдаёт
|
`fparkan-fx::smoke` разбирает body Op8, хранит кольцевой пул команды и выдаёт
|
||||||
quad-ы с ориентацией к камере для активных слотов. Нативная нормализованная
|
quad-ы с ориентацией к камере для активных слотов. Нативная нормализованная
|
||||||
фаза окна ограничивается диапазоном 0–1 и задаёт интервал проверки следующего события;
|
фаза окна ограничивается диапазоном 0–1 и задаёт интервал проверки следующего
|
||||||
сравнение строгое (`schedule_base + interval < update_clock`). Все события
|
события; сравнение строгое (`schedule_base + interval < update_clock`). Все
|
||||||
catch-up в одном обновлении проверяются по тому же нормализованному интервалу;
|
события catch-up в одном обновлении проверяются по тому же нормализованному
|
||||||
после события нативный код продвигает базу расписания интервалом, вычисленным
|
интервалу; после события нативный код продвигает базу расписания интервалом,
|
||||||
по сырой фазе эффекта, а возраст слота считает по нормализованному интервалу.
|
вычисленным по сырой фазе эффекта, а возраст слота считает по нормализованному
|
||||||
Когда фаза равна единственной границе окна, деление `0/0` даёт NaN, который
|
интервалу. Когда фаза равна единственной границе окна, деление `0/0` даёт NaN,
|
||||||
нативный unordered-путь сравнения ограничивает нулём.
|
который нативный unordered-путь сравнения ограничивает нулём.
|
||||||
|
|
||||||
Нулевая база расписания служит признаком начального состояния: обновление
|
Нулевая база расписания служит признаком начального состояния: обновление
|
||||||
сохраняет текущую опору эмиттера и базу времени, не создавая частицу. Если
|
сохраняет текущую опору эмиттера и базу времени, не создавая частицу. Если
|
||||||
первое время равно нулю, следующее обновление повторно захватывает опору. При
|
первое время равно нулю, следующее обновление повторно захватывает опору. При
|
||||||
событии скорость опоры считается от сохранённой позиции до текущей за время
|
событии скорость опоры считается от сохранённой позиции до текущей за время
|
||||||
от базы расписания; слот смещает сохранённую опору на `скорость * due_interval`.
|
от базы расписания; слот смещает сохранённую опору на `скорость * due_interval`.
|
||||||
Обновление без событий не переносит сохранённую опору к текущему владельцу.
|
При нулевой скорости оригинал подставляет ось X владельца и для направления,
|
||||||
Откат часов корректирует только базу расписания до текущего времени: слоты,
|
и для этого смещения. Обновление без событий не переносит сохранённую опору к
|
||||||
опора и три потока случайных
|
текущему владельцу. Откат часов корректирует только базу расписания до текущего
|
||||||
чисел не сбрасываются.
|
времени: слоты, опора и три потока случайных чисел не сбрасываются.
|
||||||
|
|
||||||
Evaluator принимает отдельные начальные состояния для эмиттера, знаковых
|
Evaluator принимает отдельные начальные состояния для эмиттера, знаковых
|
||||||
отклонений и материала. Переход каждого потока совпадает с общим native LFSR,
|
отклонений и материала. Переход каждого потока совпадает с общим native LFSR,
|
||||||
|
|||||||
@@ -95,6 +95,51 @@ translation суммируется, а rotations умножаются; посл
|
|||||||
запускает игровой Control/AI и не обещает полного совпадения с runtime или
|
запускает игровой Control/AI и не обещает полного совпадения с runtime или
|
||||||
всеми x87 rounding modes.
|
всеми x87 rounding modes.
|
||||||
|
|
||||||
|
## Control clock и pose компонентов
|
||||||
|
|
||||||
|
Статический Vulkan preview начинает с позы, вычисленной из сохранённых `.ctl`
|
||||||
|
bindings. Пока не задан `--static-animation-frame`, при каждом новом сэмпле
|
||||||
|
сцены приложение сэмплирует поддержанные tag 21 записи для каждого экземпляра
|
||||||
|
компонента и заново строит его MSH node hierarchy; time и transition используют
|
||||||
|
общий runtime clock. Динамический sampler принимает tag 21 mode `0`,
|
||||||
|
controller flags `5` (raw value `0xFFFFFFFF` трактуется как `5`),
|
||||||
|
разрешённый gate provider и static row mapping: оба
|
||||||
|
variable index равны `0xFFFFFFFF`, previous-row flag не установлен, transition
|
||||||
|
rate конечен и положителен.
|
||||||
|
|
||||||
|
Fallback к статической CTLD-позе всего экземпляра компонента срабатывает только
|
||||||
|
при следующих ошибках sampler: `UnsupportedTag21Mode`,
|
||||||
|
`UnsupportedVariableMapping`, `MissingGateProvider`,
|
||||||
|
`GateProviderKeyOutOfRange`, `MissingGateProviderValue` и
|
||||||
|
`GateProviderCountMismatch`. Он заменяет весь динамический результат экземпляра,
|
||||||
|
а не одну запись. Остальные sampling errors завершают обновление сцены; например,
|
||||||
|
`UnsupportedPreviousRowMapping` и `InvalidTransitionRate` не включают fallback.
|
||||||
|
|
||||||
|
`--control-clock-ms <u32>` воспроизводит общий MSH/FX clock линейно: первый из
|
||||||
|
`--frames` успешно представленных кадров получает `0`, последний — заданное
|
||||||
|
время. Replay clock привязан к числу представленных кадров: повторная подготовка
|
||||||
|
того же кадра, включая swapchain recreation, использует прежний sample.
|
||||||
|
`--static-animation-frame <u16>` отключает динамическую MSH выборку и задаёт один
|
||||||
|
frame всем компонентам. Этот override не включает AI и не превращает preview
|
||||||
|
в полный игровой Control runtime.
|
||||||
|
|
||||||
|
## Control FX и owner transform
|
||||||
|
|
||||||
|
Для выбранной Control effect group runtime берёт строки без predicate, chain и
|
||||||
|
state gate. Type 4 row offsets выбирают три точки из CTL point list; позиции
|
||||||
|
точек задают локальное начало, а их направления — локальную basis. К basis
|
||||||
|
применяются FX header scale и локальные random shifts. Затем матрица проходит
|
||||||
|
через mission rotation/translation и object scale, optional mounted-component
|
||||||
|
pose, owner-node pose и локальную матрицу эффекта. Поэтому FX mounted-компонента
|
||||||
|
следует её текущему MSH owner pose, а не остаётся привязанным к mission root.
|
||||||
|
|
||||||
|
Когда point record задаёт допустимый owner node, его pose разрешается из MSH
|
||||||
|
hierarchy. Для mounted external components node pose вычисляется относительно
|
||||||
|
component root и применяется вместе с уже рассчитанным mount pose. Internal
|
||||||
|
`INTO` child controller/equipment links пока не интерпретируются как MSH socket;
|
||||||
|
если owner pose нельзя разрешить, его FX пропускается. Нативное сочетание child
|
||||||
|
component scale, equipment attachment и CPT basis остаётся неустановленным.
|
||||||
|
|
||||||
## Vertex streams
|
## Vertex streams
|
||||||
|
|
||||||
Основные vertex streams имеют фиксированный source index. У type 3 `attr1`
|
Основные vertex streams имеют фиксированный source index. У type 3 `attr1`
|
||||||
|
|||||||
@@ -24,22 +24,22 @@
|
|||||||
затенения, вызывается завершение рендерера, снимается `in_render`, затем
|
затенения, вызывается завершение рендерера, снимается `in_render`, затем
|
||||||
рассылается `end-of-render`.
|
рассылается `end-of-render`.
|
||||||
|
|
||||||
При retry кадра после пересоздания swapchain сохраняется прежний pending
|
В интерактивном preview часы материалов и окружения прибавляют полное время
|
||||||
sample, включая уже вычисленные позы и состояния FX и материалов. Для нового
|
между обновлениями. Ограничение шага в 100 мс остаётся у движения свободной
|
||||||
drawable обновляются aspect, проекция и геометрия, зависящая от viewport; pose
|
камеры и не обрезает эти часы. В режиме replay окружение получает разницу
|
||||||
берётся из pending camera. Новые события управления камерой остаются в
|
последних применённых значений общего control clock.
|
||||||
input controller и применяются следующим sample. Экранные billboards погоды
|
|
||||||
повторно проецируются из закэшированных мировых головы и хвоста, без второго
|
|
||||||
шага симуляции окружения и повторной отправки звуковых событий. Пауза нулевого
|
|
||||||
drawable не добавляет время.
|
|
||||||
|
|
||||||
Pending frame хранит пакет MAT0 для мира и, при наличии GPU-окружения, отдельный
|
Если swapchain просит повторить ещё не представленный кадр, preview сохраняет
|
||||||
пакет неба. Пакеты содержат выбранные селектор и категорию конвейера, фазовые
|
его общий clock, уже вычисленные позы, FX/RNG и фазы материалов. При изменении
|
||||||
коэффициенты материала, четыре UV-преобразования и кортеж фаз дополнительных
|
drawable обновляются камера, aspect и viewport, после чего sky, environment
|
||||||
текстур. Повторное применение пакета при retry или нескольких resize не выбирает
|
geometry и projected shadows пересобираются для нового размера.
|
||||||
фазу заново и не продвигает RNG. Перед отрисовкой сначала применяются материалы
|
Положение и ориентация камеры берутся из сохранённого состояния
|
||||||
мира и их порядок прозрачности, затем MAT0 неба, после чего viewport-зависимый
|
ожидающего кадра; новый ввод мыши применяется при следующем сэмпле. Сэмпл
|
||||||
проход неба записывает свои переопределения.
|
погоды остаётся прежним: экранные billboards дождя и снега повторно
|
||||||
|
проецируются из закэшированных мировых головы и хвоста, без второго шага
|
||||||
|
симуляции окружения или повторной отправки звуковых событий. Следующий такт
|
||||||
|
выбирается после успешного представления кадра; пауза нулевого drawable не
|
||||||
|
добавляет время.
|
||||||
|
|
||||||
## Элемент отрисовки
|
## Элемент отрисовки
|
||||||
|
|
||||||
@@ -117,6 +117,10 @@ RVA `0x13D90`. Эти данные подтверждают только пор
|
|||||||
путь превью принимает входные данные с матрицей `selector0_words`, полученные через
|
путь превью принимает входные данные с матрицей `selector0_words`, полученные через
|
||||||
[процедуру захвата нативного кадра](../../tools/native-frame-capture/README.md).
|
[процедуру захвата нативного кадра](../../tools/native-frame-capture/README.md).
|
||||||
|
|
||||||
|
Формат захвата сохраняет локальную матрицу `selector0_words` и, когда она
|
||||||
|
доступна, записывает `effective_world_matrix_words` с маркером пространства
|
||||||
|
`world`.
|
||||||
|
|
||||||
Процедура захвата записывает наблюдавшийся путь миссии и значение
|
Процедура захвата записывает наблюдавшийся путь миссии и значение
|
||||||
`atmosphere_seconds`, если проверка потока, поколения и часов прошла успешно.
|
`atmosphere_seconds`, если проверка потока, поколения и часов прошла успешно.
|
||||||
В превью с фиксированной камерой эта абсолютная фаза расписания используется,
|
В превью с фиксированной камерой эта абсолютная фаза расписания используется,
|
||||||
@@ -163,14 +167,26 @@ RVA `0x4EBE0` использует соглашение о вызовах `__std
|
|||||||
события, слушателю задаются захваченные позиция, направление вперёд и верхняя
|
события, слушателю задаются захваченные позиция, направление вперёд и верхняя
|
||||||
ось; начальная сортировка диапазонов мира использует ту же позицию.
|
ось; начальная сортировка диапазонов мира использует ту же позицию.
|
||||||
|
|
||||||
|
Если в JSON присутствует пара `effective_world_matrix_space: "world"` и
|
||||||
|
`effective_world_matrix_words`, превью использует мировую матрицу. Матрица
|
||||||
|
`selector0_words` остаётся локальной и используется как запасной вариант только
|
||||||
|
при отсутствии мировых полей, если `parented_camera` не равно `true`. Для
|
||||||
|
родительской камеры без эффективной мировой матрицы вход отклоняется.
|
||||||
|
|
||||||
Захват может содержать наблюдавшийся путь миссии и проверенное значение
|
Захват может содержать наблюдавшийся путь миссии и проверенное значение
|
||||||
`atmosphere_seconds`; последнее используется только при отсутствии явного
|
`atmosphere_seconds`; последнее используется только при отсутствии явного
|
||||||
параметра командной строки. Это значение фиксирует фазу расписания атмосферы
|
параметра командной строки. Это значение фиксирует фазу расписания атмосферы
|
||||||
при сравнении с неподвижной камерой, тогда как FX продолжает получать реальное
|
при сравнении с неподвижной камерой, тогда как FX по умолчанию получает реальное
|
||||||
время кадра. `simulation_time_seconds`, погода, RNG и полное состояние миссии
|
время кадра. `simulation_time_seconds`, погода, RNG и полное состояние миссии
|
||||||
остаются неизвестными, поэтому совпадение камеры и фазы не подтверждает
|
остаются неизвестными, поэтому совпадение камеры и фазы не подтверждает
|
||||||
визуального совпадения с нативным кадром.
|
визуального совпадения с нативным кадром.
|
||||||
|
|
||||||
|
Параметр `--control-clock-ms` воспроизводит единые часы MSH/FX от нуля до
|
||||||
|
выбранного значения в миллисекундах за указанное число кадров. Без этого
|
||||||
|
параметра часы идут в реальном времени. Для `--readback-sequence-out` этот
|
||||||
|
управляемый режим обязателен. Он не восстанавливает
|
||||||
|
`simulation_time_seconds`, погоду, RNG или полное состояние миссии.
|
||||||
|
|
||||||
Для неба превью вычисляет направление как `atan2(forward.x, forward.y)`. Оно
|
Для неба превью вычисляет направление как `atan2(forward.x, forward.y)`. Оно
|
||||||
совпадает со вторым выходным значением, вычисляемым в `Terrain.dll` по RVA
|
совпадает со вторым выходным значением, вычисляемым в `Terrain.dll` по RVA
|
||||||
`0x4F9C0`; при выборе сектора экранного градиента `CSky` добавляет π по RVA
|
`0x4F9C0`; при выборе сектора экранного градиента `CSky` добавляет π по RVA
|
||||||
@@ -183,15 +199,9 @@ RVA `0x4EBE0` использует соглашение о вызовах `__std
|
|||||||
`1.3` рад — параметры, наблюдавшиеся в проверенном контексте GOG Ngi32
|
`1.3` рад — параметры, наблюдавшиеся в проверенном контексте GOG Ngi32
|
||||||
([формула native projection](../tomes/05-render.md#камера-и-размещение-в-оригинале)).
|
([формула native projection](../tomes/05-render.md#камера-и-размещение-в-оригинале)).
|
||||||
Для отношения ширины к высоте `a` превью вычисляет вертикальный угол
|
Для отношения ширины к высоте `a` превью вычисляет вертикальный угол
|
||||||
```rust
|
`2 * atan(tan(horizontal_fov / 2) / a)`. Поэтому горизонтальный угол остаётся
|
||||||
fn vertical_fov(self, aspect: f32) -> f32 {
|
`1.3` рад после изменения размера окна; новый viewport и матрица камеры
|
||||||
2.0 * ((self.horizontal_fov * 0.5).tan() / aspect).atan()
|
применяются при следующей отрисовке.
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Код заменяет невалидный `aspect` на отношение 16:9; горизонтальный угол
|
|
||||||
остаётся `1.3` рад после изменения размера окна, а новый viewport и матрица
|
|
||||||
камеры применяются при следующей отрисовке.
|
|
||||||
|
|
||||||
Проекция направления не сравнивает косинус угла с ближней дистанцией: она
|
Проекция направления не сравнивает косинус угла с ближней дистанцией: она
|
||||||
отбрасывает только лучи за камерой и почти параллельные плоскости изображения
|
отбрасывает только лучи за камерой и почти параллельные плоскости изображения
|
||||||
@@ -254,6 +264,11 @@ D3D7 в `fparkan-render`, а затем один раз меняет знак в
|
|||||||
- переход на запасной набор возможностей устройства;
|
- переход на запасной набор возможностей устройства;
|
||||||
- квантование времени симуляции.
|
- квантование времени симуляции.
|
||||||
|
|
||||||
Для отладки требуется детерминированный захват кадра: состояние камеры,
|
Параметр `--readback-sequence-out` сохраняет необработанные байты каждого
|
||||||
идентификаторы видимых объектов, список элементов отрисовки, ключи конвейера,
|
отправленного кадра; в имя файла записываются индекс кадра, значение общих
|
||||||
матрицы и хэши промежуточных буферов.
|
управляемых часов и размер изображения. Байты соответствуют выбранному формату
|
||||||
|
изображения swapchain Vulkan и не гарантируют порядок каналов R, G, B, A. Числовое
|
||||||
|
формат выводится как `readback_format`; расширение `.rgba` само по себе порядок
|
||||||
|
каналов не определяет. Последовательность не содержит структурированных ID
|
||||||
|
видимых объектов, списка элементов отрисовки, ключей конвейера, матриц или
|
||||||
|
хэшей промежуточных буферов.
|
||||||
+80
-69
@@ -362,30 +362,14 @@ local.set_translation(pose.position);
|
|||||||
world[n] = world[parent(n)] * local;
|
world[n] = world[parent(n)] * local;
|
||||||
```
|
```
|
||||||
|
|
||||||
Статический Vulkan preview берёт CTLD `.ctl` из явной ссылки прототипа.
|
Статический Vulkan preview сначала строит начальную позу по CTLD `.ctl`.
|
||||||
Поддерживаемые Control timeline с tag 21 сэмплируются при запуске на native
|
В ней участвуют только включённые строки; при повторе node ID поздняя строка
|
||||||
clock `0`; разрешённые NDP providers передают конечные type-1 значения.
|
заменяет раннюю, а узлы без настройки остаются на кадре `0`. Без
|
||||||
Неподдерживаемый режим или variable mapping, а также отсутствующее или
|
`--static-animation-frame` preview сэмплирует поддержанные Control timelines
|
||||||
неразрешённое gate value оставляют компонент на статических CTLD bindings. В
|
при каждом новом сэмпле сцены. Флаг `--static-animation-frame N` задаёт `N`
|
||||||
timeline участвуют только включённые строки; при повторном node ID поздняя
|
всем узлам и пропускает runtime Control sample. Это визуальный preview позы,
|
||||||
строка заменяет раннюю.
|
а не полный Control/AI runtime.
|
||||||
|
|
||||||
Без `--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)` к ближайшему
|
MSH sampler выбирает type 19 frame округлением `(time - 0.5)` к ближайшему
|
||||||
целому с ties-to-even, затем интерполирует выбранный type 8 key и следующий
|
целому с ties-to-even, затем интерполирует выбранный type 8 key и следующий
|
||||||
key в исходном `time`; это portable-вариант native x87 conversion в default
|
key в исходном `time`; это portable-вариант native x87 conversion в default
|
||||||
@@ -646,15 +630,15 @@ diffuse texture ломает LOD, atlas coordinates и динамическую
|
|||||||
Vulkan preview строит проецируемые тени для объектов, отбрасывающих тени,
|
Vulkan preview строит проецируемые тени для объектов, отбрасывающих тени,
|
||||||
отбрасывает сферы вне шести clip-плоскостей с радиусом `sphere + 100` и
|
отбрасывает сферы вне шести clip-плоскостей с радиусом `sphere + 100` и
|
||||||
сохраняет порядок видимых кандидатов; frame builder обрабатывает не более 20
|
сохраняет порядок видимых кандидатов; frame builder обрабатывает не более 20
|
||||||
объектов. Текущая реализация выделяет страницы в atlas `256 x 256` с 28 page
|
объектов, отбрасывающих тени. Текущая реализация выделяет страницы в atlas
|
||||||
slots и использует одно сглаживание. Preview применяет native defaults
|
`256 x 256` с 28 page slots и использует одно сглаживание. Preview применяет
|
||||||
`RobShadowsOn = true` и `BldShadowsOn = false`: объект kind `4` проверяет
|
native defaults `RobShadowsOn = true` и `BldShadowsOn = false`: объект kind `4`
|
||||||
первый флаг, остальные kinds — второй. Поэтому роботы BTLU остаются объектами,
|
проверяет первый флаг, остальные kinds — второй. Поэтому роботы BTLU остаются
|
||||||
отбрасывающими тени, а объекты FORT и STAT их не создают. Preview пока не
|
объектами, отбрасывающими тени, а объекты FORT и STAT их не создают. Preview
|
||||||
загружает `shade.cfg`, поэтому значения из пользовательского файла не меняют
|
пока не загружает `shade.cfg`, поэтому значения из пользовательского файла не
|
||||||
список объектов, отбрасывающих тени. Проверка действует только на проецируемые
|
меняют список объектов, отбрасывающих тени. Проверка действует только на
|
||||||
тени: отдельный список объектов для затенения солнца по-прежнему включает
|
проецируемые тени: отдельный список объектов для затенения солнца по-прежнему
|
||||||
FORT, BTLU и STAT. Вызов preview передаёт `fade = 1.0` и LOD defaults:
|
включает FORT, BTLU и STAT. Вызов preview передаёт `fade = 1.0` и LOD defaults:
|
||||||
minimum LOD `1` и detail multiplier `1.0` отдельно для зданий и роботов.
|
minimum LOD `1` и detail multiplier `1.0` отдельно для зданий и роботов.
|
||||||
Проекция учитывает вклад directional и point lights.
|
Проекция учитывает вклад directional и point lights.
|
||||||
|
|
||||||
@@ -823,6 +807,39 @@ emit не должен повторно менять игровое состоя
|
|||||||
типизировать header и resource references, а body редких commands сохранять raw
|
типизировать header и resource references, а body редких commands сохранять raw
|
||||||
до подтверждения field-level semantics.
|
до подтверждения field-level semantics.
|
||||||
|
|
||||||
|
В `fparkan-game` выбранные Control FX проходят отдельный transparent path.
|
||||||
|
Начальная CTL group запускает только строки без predicates, chain или state
|
||||||
|
gate. Type 4 point list задаёт локальную матрицу; текущие MSH owner и mounted
|
||||||
|
node poses входят в transform до локальной FX basis. Реализованные visuals
|
||||||
|
охватывают Op3 modes 0–2, Op4, Op7/8 particle pools и Op9 generated mesh. Op1
|
||||||
|
selector 1 добавляет point lights без native flag `0x80000000` в общий diffuse
|
||||||
|
список; остальные active records сохраняют flags для специальных путей и
|
||||||
|
projected shadows. Effect renderer подавляет header bit `0x800` только при
|
||||||
|
render selector 0. Native AniMesh component path захвачен с selector 1, а в
|
||||||
|
его 53-entry manager присутствуют FX entries с header `0xD00`; preview
|
||||||
|
использует selector 1 и пропускает такие visual commands. Изменения manager
|
||||||
|
`A8`, которые задают runtime phase/header gate, пока не моделируются. Header
|
||||||
|
bit `0x10` относится к activation lifecycle и не выключает draw.
|
||||||
|
|
||||||
|
Для visual effect renderer использует MAT0, указанный самой командой. Его
|
||||||
|
phase выбирается по normalized FX phase, а не по wall-clock clock материала
|
||||||
|
мира. FX opacity остаётся в vertex alpha, MAT0 alpha для этой FX binding
|
||||||
|
фиксируется на единице, texture alpha остаётся в shader. Preview передаёт FX
|
||||||
|
через SourceAlpha/read-only-depth state. MAT0 phases проходят локальный
|
||||||
|
eligibility predicate additive-RGB approximation; native `flag40` и
|
||||||
|
directional-light branch остаются неразрешёнными.
|
||||||
|
|
||||||
|
Op9 генерирует индексированную полусферу с отдельными vertex и UV данными и
|
||||||
|
отправляет каждый quad и cap как отдельный draw range. Native packet distance
|
||||||
|
callback берёт первую индексированную вершину (`Terrain.dll:0x246A0` через
|
||||||
|
`0x247B0`), преобразует её согласно режиму packet и использует евклидово
|
||||||
|
расстояние до камеры. Queue размещает большие расстояния раньше меньших;
|
||||||
|
равный ключ вставляется в найденный binary-search midpoint, поэтому порядок
|
||||||
|
равных packets не стабилен по времени поступления. Preview повторяет этот ключ
|
||||||
|
и insertion order. Renderer category 0 остаётся highest-detail mesh; native
|
||||||
|
category вычисляется из projected sphere size и quality table, поэтому
|
||||||
|
фиксированная категория не является native LOD parity.
|
||||||
|
|
||||||
## Полный кадр
|
## Полный кадр
|
||||||
|
|
||||||
Крупный вход в world render проходит через `World3D::stdRenderGame`. Доказан
|
Крупный вход в world render проходит через `World3D::stdRenderGame`. Доказан
|
||||||
@@ -1035,54 +1052,48 @@ WEAR и MAT0 до объединения геометрии. Индексы GPU
|
|||||||
animation phase; object batches сохраняют их legacy blend/depth/alpha state.
|
animation phase; object batches сохраняют их legacy blend/depth/alpha state.
|
||||||
|
|
||||||
После загрузки world path создаёт интерактивную free-flight камеру (`WASD`,
|
После загрузки world path создаёт интерактивную free-flight камеру (`WASD`,
|
||||||
`E/Q`, `Shift`, `Ctrl`, RMB relative-look), обновляет listener и собирает
|
`E/Q`, `Shift`, `Ctrl`, RMB relative-look), обновляет listener и на каждом
|
||||||
environment frame для каждого подготовленного кадра. Event loop один раз
|
кадре собирает environment frame. Для каждого отрисовываемого строения
|
||||||
сэмплирует камеру, общий animation clock, геометрию и окружение перед запросом
|
(корневого объекта класса `FORT`) и для каждого его отрисовываемого компонента
|
||||||
redraw; redraw потребляет это состояние. Если surface требует пересоздать
|
создаётся отдельная запись проверки. Она использует те же текущие матрицы узлов
|
||||||
swapchain, тот же sample времени и состояние мира отправляются повторно.
|
и присоединённых компонентов, что и геометрия. После ограничения целевой
|
||||||
Перед повторной отправкой projection камеры и viewport-зависимые environment
|
позиции по TerrainWorld камера проверяет непрерывный отрезок от прежней позиции
|
||||||
и shadow geometry обновляются для нового размера без продвижения сцены.
|
до цели; при пересечении
|
||||||
Счётчик и replay clock продвигаются только после результата `Presented`.
|
она остаётся в прежней позиции, сохраняя новый поворот. Повторная отправка
|
||||||
После шага движения камера проверяет высоту
|
ожидающего кадра не применяет движение второй раз. Это ограничение
|
||||||
`TerrainWorld`: над конечной поверхностью сохраняется начальный просвет, а вне
|
диагностической свободной камеры, а не правило игрового или следящего режима
|
||||||
поверхности высота не ограничивается.
|
оригинала.
|
||||||
|
|
||||||
Для каждого отрисовываемого строения (корневого объекта класса `FORT`) и для
|
|
||||||
каждого его отрисовываемого компонента создаётся отдельная запись проверки. Она
|
|
||||||
использует те же текущие матрицы узлов и присоединённых компонентов, что и
|
|
||||||
геометрия.
|
|
||||||
После ограничения целевой позиции по TerrainWorld камера проверяет непрерывный
|
|
||||||
отрезок от прежней позиции до цели; при пересечении она остаётся в прежней
|
|
||||||
позиции, сохраняя новый поворот. Повторная отправка ожидающего кадра не
|
|
||||||
применяет движение второй раз. Это ограничение диагностической свободной
|
|
||||||
камеры, а не правило игрового или следящего режима оригинала.
|
|
||||||
|
|
||||||
Mission-local `sky.ske`/`sky.wea` выбирают
|
Mission-local `sky.ske`/`sky.wea` выбирают
|
||||||
атмосферное расписание и sky materials, `effects.rlb/env_lightning` даёт
|
атмосферное расписание и sky materials, `effects.rlb/env_lightning` даёт
|
||||||
lightning visual; weather particles, flares, sun/moon, point lights,
|
lightning visual; weather particles, flares, sun/moon, point lights,
|
||||||
projected shadows и audio events обновляются вместе с камерой и временем.
|
projected shadows и audio events обновляются вместе с камерой и временем.
|
||||||
`--atmosphere-seconds` задаёт старт времени, `--frames 0` оставляет цикл
|
`--atmosphere-seconds` задаёт старт времени, `--frames 0` оставляет цикл
|
||||||
бесконечным, `--control-clock-ms N` воспроизводит общий clock анимации MSH и
|
бесконечным, а `--preview-roots` служит только диагностическим ограничителем.
|
||||||
материалов вместе с окружением от нуля до `N` за заданное число кадров и требует
|
|
||||||
как минимум два кадра.
|
|
||||||
`--preview-roots` служит только диагностическим ограничителем.
|
|
||||||
`--legacy-camera-capture` выбирает воспроизводимую камеру без free-flight
|
`--legacy-camera-capture` выбирает воспроизводимую камеру без free-flight
|
||||||
управления: запись selector 0 задаёт D3D7 transform, clip параметры и native
|
управления. `selector0_words` содержит локальную матрицу камеры. Если запись
|
||||||
viewport RECT `[left, top, right, bottom]`. Путь сохраняет оси basis из view
|
содержит `effective_world_matrix_words` с маркером
|
||||||
matrix вместе с roll, переносит полученный `clip_from_world` в preview camera,
|
`effective_world_matrix_space="world"`, preview использует эту мировую
|
||||||
переводит RECT в физический drawable размер `(right - left) × (bottom - top)`
|
матрицу. При `parented_camera=true` отсутствие мировой матрицы — ошибка;
|
||||||
и отклоняет несовпадение размера при
|
локальный selector 0 остаётся legacy fallback только для записей без признака
|
||||||
создании или resize вместо растягивания кадра. Результат нужно сравнивать с
|
parented и без мировой матрицы.
|
||||||
тем же crop исходного PNG `[left, top, right, bottom]`. Контроллер
|
Если native helper явно применяет выбранную мировую камеру, setter работает в
|
||||||
`FreeFlightCamera` в этом режиме не создаётся. Подготовка кадра обновляет
|
mode 2, а restore возвращает исходную локальную матрицу в mode 1. Clip
|
||||||
|
параметры и native viewport RECT `[left, top, right, bottom]` идут из той же
|
||||||
|
записи. Путь сохраняет оси basis из view matrix вместе с roll, переносит
|
||||||
|
полученный `clip_from_world` в preview camera, переводит RECT в физический
|
||||||
|
drawable размер `(right - left) × (bottom - top)` и отклоняет несовпадение
|
||||||
|
размера при создании или resize вместо растягивания кадра. Результат нужно
|
||||||
|
сравнивать с тем же crop исходного PNG `[left, top, right, bottom]`. Контроллер
|
||||||
|
`FreeFlightCamera` в этом режиме не создаётся, но redraw продолжает обновлять
|
||||||
environment и projected shadows от captured camera. Перед environment update и
|
environment и projected shadows от captured camera. Перед environment update и
|
||||||
его audio events listener получает position, forward и up captured camera;
|
его audio events listener получает position, forward и up captured camera;
|
||||||
начальная сортировка world draw использует её же position. Phase capture может
|
начальная сортировка world draw использует её же position. Phase capture может
|
||||||
содержать наблюдаемый mission path и проверенный `atmosphere_seconds`; viewer
|
содержать наблюдаемый mission path и проверенный `atmosphere_seconds`; viewer
|
||||||
использует эту абсолютную фазу по умолчанию, если не указан явный CLI override,
|
использует эту абсолютную фазу по умолчанию, если не указан явный CLI override,
|
||||||
и удерживает sample атмосферы на ней через readback frames. Без
|
и удерживает sample атмосферы на ней через readback frames. Фазы FX следуют
|
||||||
`--control-clock-ms` FX получает реальный frame time; с параметром environment
|
выбранному control clock: без `--control-clock-ms` он обновляется по elapsed
|
||||||
и материалы используют replay clock. Это не полное simulation time: `weather`, RNG и
|
time, а с явным значением readback frames переигрывают заданный clock. Это не
|
||||||
|
полное simulation time: `weather`, RNG и
|
||||||
остальное mission state остаются неизвестными, поэтому совпадение камеры и
|
остальное mission state остаются неизвестными, поэтому совпадение камеры и
|
||||||
фазы не доказывает visual parity с native frame.
|
фазы не доказывает visual parity с native frame.
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user