diff options
Diffstat (limited to 'docs/reference')
| -rw-r--r-- | docs/reference/environment-effects.md | 43 | ||||
| -rw-r--r-- | docs/reference/msh.md | 39 |
2 files changed, 74 insertions, 8 deletions
diff --git a/docs/reference/environment-effects.md b/docs/reference/environment-effects.md index 42e203c..799a969 100644 --- a/docs/reference/environment-effects.md +++ b/docs/reference/environment-effects.md @@ -256,14 +256,30 @@ Vertex shader пропускает `clip_from_world` для строк солнÑ остаются отдельным путём. Материал экранного quad не освещается, vertex fog отключён, а sky far-depth bit к нему не применяется. -Native `z = 0.999` не означает, что спрайт гарантированно лежит за любой -поверхностью. Vulkan использует `LESS_OR_EQUAL` и не записывает depth для -прозрачного ряда. При near `0.5`, far `700` мировая поверхность на расстоянии -`320` получает depth -`700 / (700 - 0.5) * (1 - 0.5 / 320) ≈ 0.999151`; поэтому экранный `0.999` -чуть ближе этой поверхности и проходит depth test перед ней. Это фиксированное -native значение сохраняется для совместимости, но само по себе не обещает -окклюзию солнца всей геометрией местности. +Для мировой геометрии +оригинал задаёт viewport `MinZ = 0.1`, `MaxZ = 0.99`: после отсечения +проекционная глубина отображается в этот диапазон: + +```text +world_depth = 0.1 + (0.99 - 0.1) * (clip_z / clip_w) +``` + +Даже дальняя гора получает глубину не больше `0.99` и закрывает экранный +диск с `z = 0.999`. Если оставить мировой диапазон `0–1`, при near `0.5` +и far `700` поверхность дальше примерно `292` единиц окажется позади диска: +солнце начнёт просвечивать сквозь неё при движении камеры. Одного переноса +нативного `z` в экранные вершины недостаточно. + +В Vulkan диапазон задаётся динамическим viewport отдельно для мировых +пакетов; экранные TL и фоновые sky-пакеты сохраняют диапазон `0–1`. +Матрица проекции и плоскости отсечения при этом не меняются. Константы +мирового профиля записывает GOG `Terrain.dll` RVA `0x27422–0x27452` из таблицы +`0x65088/0x6508C/0x650A0/0x650A4` (near, far, MinZ, MaxZ). GOG `Ngi32.dll` +RVA `0x7170`, участок `0x71E7–0x723C`, копирует MinZ/MaxZ в renderer +`+0x30/+0x34` и передаёт их `IDirect3DDevice7::SetViewport`; сборки указаны в +[таблице бинарников](original-binaries.md). Нативные значения этих двух полей +имеют биты `0x3DCCCCCD` и `0x3F7D70A4`. + ## Геометрия визуальных FX-команд @@ -312,6 +328,17 @@ RVA `0x93D0`, ветка mode 1 с `0x9739`, сборка столбцов `0x97 двух столбцов могут немного отличаться от единицы из-за приближённой нормализации выбранного `g_FastProc`; порядок осей от этого не меняется. +У сооружения `s_tree_58` в миссии «Конструктор» FXID `tree_ray_58` задаёт два +слоя жёлтого луча: команды Op3 mode 1 с ресурсами `defl_y_add` и `defl_y1_add`. +Их геометрию сверили с CPU-вызовом GOG `Effect.dll` `0x93D0`. На семи временных +фазах и трёх направлениях камеры для каждой команды (42 выборки) вершины +совпали с Rust evaluator с максимальной покомпонентной разницей `0.0001373291`. +Оракул получает уже выбранные Rust позицию, ось и масштаб, а world-camera +переводится в `cameraLocal` тем же component-wise projection, что и native +`FastProc + 0x68`. Поэтому это подтверждает только геометрию Type 1 helper-а на +этих входах: обновление и расписание эффекта, UV/material и пиксельное +совпадение здесь не проверялись. + ## Частицы Op7 `fparkan-fx::op7` вычисляет фиксированный набор частиц Op7 по body команды, diff --git a/docs/reference/msh.md b/docs/reference/msh.md index a28514d..7c6eca7 100644 --- a/docs/reference/msh.md +++ b/docs/reference/msh.md @@ -154,6 +154,45 @@ Byte `material_index` выбирает строку WEAR; high word at `+0x02` Ñ индекс через `base_vertex` попадает в position stream. `vertex_count` и `local_batch_index` доступны renderer для исходного draw contract. +## Type 7 и сегментный запрос + +Type 7 необязателен для обычного MSH preview. Если stream есть, каждые 16 bytes +описывают одну грань: `tri_flags` находится по `+0`, четыре неинтерпретируемых +слова — по `+2`, `+4`, `+6` и `+14`, а signed `normal[3]` — по `+8`, `+0xA` и +`+0xC`. `ModelAsset.triangle_descriptors` сохраняет декодированную таблицу как +`Option`; отсутствие Type 7 не делает статическую модель недействительной. + +`query_slot_segment` использует Node38 header mask, Batch20 leading DWORD +`batch_flags | (material_index_hi << 16)` и `tri_flags`. Для каждого поля +include mask требует все установленные биты, exclude mask пропускает запись при +любом совпавшем бите. Descriptor cursor начинается с `Slot68.tri_start` и +сдвигается на `Batch20.index_count / 3` после каждой записи, даже если batch +или грань отфильтрованы. Индексы грани читаются из type 6 с учётом +`base_vertex`. + +Правило восстановлено для GOG-бинарей `AniMesh.dll` +(`65659bf67f20e5be77d67a5b2f59968f61b94293143807fa59ca451c560c4f7e`) и +`Ngi32.dll` (`bab9840d94f4e4e74ffc26677724fa896cf4823845504d09a9e025f80016edf5`). +Callback `AniMesh.dll+0x11090` переводит signed type-7 normal множителем +`1 / 32767`; функция `AniMesh.dll+0x11EB0` записывает этот scale в глобальное +поле. Callback вызывает FastProc slot `+0xB4`: в этой сборке он указывает на +`Ngi32.dll+0x1D560`. После обычной загрузки DLL порог `Ngi32.dll+0x37224` +равен нулю, поэтому plane test принимает только переход от положительного +расстояния к неположительному (`dot(normal, end - start) < 0`, расстояние в +начале `> 0`, в конце `<= 0`). `Batch20.batch_flags & 0x0002` разрешает повторный +plane test в обратном направлении, только если прямой plane test не пересёк +плоскость. Пересечение проверяется export ordinal 202 +(`Ngi32.dll+0x1E60`, `mrnPointInPoly`): проекция выбирает ось с наибольшим по +модулю normal component, а точка проходит грань, пока ни одно edge expression +не меньше нуля. Равенство нулю принимается, поэтому попадание на ребро или +вершину считается попаданием. Поздний кандидат с тем же squared distance +заменяет предыдущий; расстояние считается от исходного первого endpoint. + +Native helper получает точку пересечения через `RCPSS` и один шаг уточнения; +Rust использует обычное деление `f32`, поэтому последние биты координат могут +отличаться. Игнорируемый тест с ресурсами проверяет исходную стену, дверной +проём и обратное направление на `fortif.rlb/fr_l_plant.msh`. + ## Сторона грани в цветовом проходе В цветном проходе `Terrain.dll`, функция `0x100296F0`, сравнивает камеру с |
