diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/appendices/knowledge-boundaries.md | 24 | ||||
| -rw-r--r-- | docs/reference/msh.md | 58 |
2 files changed, 53 insertions, 29 deletions
diff --git a/docs/appendices/knowledge-boundaries.md b/docs/appendices/knowledge-boundaries.md index a9aaba1..bc8e999 100644 --- a/docs/appendices/knowledge-boundaries.md +++ b/docs/appendices/knowledge-boundaries.md @@ -16,15 +16,21 @@ state transitions и окончательный порядок части transp Локальный MSH-запрос `query_slot_segment` сверён с оригиналом на фабричной стене и дверном проёме. Runtime-адаптер `query_building_segment_world` теперь -переводит отрезок через переданные преобразования выбранных MSH-узлов, выбирает -ближайшее мировое попадание и повторяет запрос для helper batch bit `0x0008`. -Его синтетические тесты покрывают поворот, масштаб, отражение, helper-повтор и -ограничение в 200 пересечений; они не доказывают паритет с полным мировым -запросом оригинала. - -Открыты выбор нативной категории и состава узлов/слотов, получение актуальных -поз и component bindings из runtime-объектов, подключение адаптера к свободной -камере и сравнение мирового результата с оригиналом +повторяет helper batch bit `0x0008` через связанный узел, указанный raw-словом +`Batch20 +0x06`. При повторе он обходит Node38-поддерево: сначала допустимых +потомков, затем сам узел. Флаги ветвления сверены с оригиналом. Синтетические +тесты покрывают связи, отсутствие геометрии у промежуточного узла, маски, +равные попадания и предел в 200 пересечений. + +Игнорируемый тест на AutoDemo загружает настоящий объект PLANT 4 и подтверждает, +что сегмент пересекает геометрию Node3 в исходной закрытой позе, но не +пересекает её в открытой позе Node3 на frame `1`. В загруженных +Control-привязках корня PLANT нет tag-21 записи для этого перехода. Тест задаёт +frame `1` напрямую и не исполняет команду открытия из миссии. + +Открыты выбор первого корня и состава узлов/слотов нативного мирового запроса, +полный обход текущих runtime-поз и component bindings, подключение адаптера к +свободной камере и сравнение итогового результата мирового запроса с оригиналом ([MSH](../reference/msh.md)). Для MSH без потока цветов type 16 подтверждён только один постоянный alpha diff --git a/docs/reference/msh.md b/docs/reference/msh.md index 3cff999..945bdc4 100644 --- a/docs/reference/msh.md +++ b/docs/reference/msh.md @@ -153,7 +153,10 @@ struct Batch20 { ``` Byte `material_index` выбирает строку WEAR; high word at `+0x02` сохраняется -отдельно для native overrides. Loader проверяет, что +отдельно для native overrides. Слово `local_batch_index` остаётся raw-полем +`+0x06`: в пути CBuilding helper retry оно вместе с базой модели задаёт +связанный корень Node38, а у отдельной `ModelAsset` база равна нулю. Вне этого +пути слово сохраняется без вывода о его значении. Loader проверяет, что `index_start + index_count` остаётся внутри type 6, а каждый использованный индекс через `base_vertex` попадает в position stream. `vertex_count` и `local_batch_index` доступны renderer для исходного draw contract. @@ -200,11 +203,10 @@ Rust использует обычное деление `f32`, поэтому п ### Мировой отрезок по выбранным узлам Локальный запрос выше проверяет один узел и slot модели. Runtime-функция -`query_building_segment_world` принимает мировой отрезок и список выбранных -узлов со slot-ами и их преобразованиями `world_from_node`. Для каждого узла она -переводит оба конца отрезка обратной матрицей, вызывает `query_slot_segment`, а -найденную точку переносит назад в мир. Затем она выбирает ближайшее попадание -среди переданных узлов. +`query_building_segment_world` принимает мировой отрезок и исходный список +выбранных узлов со slot-ами и их преобразованиями `world_from_node`. Первый +проход сохраняет порядок этого списка, переводит концы отрезка обратной +матрицей и выбирает ближайшее попадание в мире. ```text segment_node = inverse(world_from_node) * segment_world @@ -213,20 +215,36 @@ distance² = dot(hit_world - original_start, hit_world - original_start) ``` `original_start` остаётся началом первоначального мирового отрезка, даже когда -запрос перезапускается. Нативный CBuilding query сохраняет raw -`Batch20.batch_flags & 0x0008`: если ближайшее попадание помечено этим bit, -следующий проход начинается в его мировой точке и идёт к исходному концу. -Первичный запрос исключает из batch только `0x0200`, а тип-7 треугольники — -`0x0024`. Счётчик ограничивает число всех пересечений: при посещении 200 -запрос завершается ошибкой до проверки bit `0x0008`. - -Эта схема восстановлена по GOG `Terrain.dll` SHA-256 -`af87d1b2e728a0be73c52be3b44cc196ab46da7799f25a15d40f8c9b0b425ead`: -мировой обход проходит через `FUN_10016a20` (RVA `0x16A20`), CBuilding выполняет -запрос и helper-перезапуски в `FUN_10035430` (RVA `0x35430`), а guard находится -в участке `0x358FC..0x35926`. Runtime-модуль проверен на синтетических -переносах, поворотах, масштабах и отражениях; подключение к текущим позам -объектов и камере приложения пока не выполнено. +запрос перезапускается. Если ближайший batch имеет bit `0x0008`, его ключ +`local_batch_index` выбирает новый корень Node38, а отрезок начинается в +мировой точке helper-попадания и идёт к исходному концу. Runtime обходит +метаданные этого поддерева даже у узлов без переданной геометрии; сами slot- +запросы выполняются только для узлов, присутствующих во входном списке. Обход +проверяет сначала допустимых потомков, затем сам узел. Header bit `0x0010` +прекращает обход его потомков; bit `0x0004` у дочернего узла исключает всю эту ветвь, но bit +`0x0004` у текущего корня не мешает запросу его собственной геометрии. Слово +родителя `0xFFFF` не связывает узел с дочерним корнем, а helper-ключ `0xFFFF` +считается ошибкой данных. + +В каждом проходе batch `0x0200` и type-7 triangle flags `0x0024` исключаются. +Ближайшее попадание и разрешение равных расстояний сохраняют правила локального +запроса; расстояние измеряется от первоначального начала. Счётчик ограничивает +все пересечения: при посещении 200 запрос завершается ошибкой до проверки bit +`0x0008`. + +Эта схема сверена с GOG `Terrain.dll` SHA-256 +`af87d1b2e728a0be73c52be3b44cc196ab46da7799f25a15d40f8c9b0b425ead` (RVA +`0x35430`, `0x35961`) и `AniMesh.dll` SHA-256 +`65659bf67f20e5be77d67a5b2f59968f61b94293143807fa59ca451c560c4f7e` (RVA +`0x134D0`, `0x10A50`). Игнорируемый тест загружает настоящий объект PLANT 4 +миссии AutoDemo и проверяет, что сегмент пересекает геометрию Node3 в исходной +закрытой позе, но проходит без попадания при явно заданной открытой позе frame +`1`. Это проверка запроса для двух поз, а не открытие двери игровой командой. +В загруженных Control-привязках корня PLANT нет tag-21 записи для перехода +Node3; тест задаёт frame `1` напрямую и не исполняет команду открытия из +миссии. +Нативный выбор первого корня и полный мировой обход ещё не сопоставлены с Rust; +app пока не передаёт этой функции живые runtime-позы и bindings. ## Сторона грани в цветовом проходе |
