diff options
| author | Valentin Popov <valentin@popov.link> | 2026-07-18 15:25:20 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-07-18 15:25:20 +0300 |
| commit | 1a8e1eaed1de540367bad377e72d228153d8cec6 (patch) | |
| tree | ab1404daba8d6508a5a6a98d3653827fd60ebd74 /docs | |
| parent | 858dcd0d1de47cce5f04f959f239cff6aaa033f4 (diff) | |
| download | fparkan-1a8e1eaed1de540367bad377e72d228153d8cec6.tar.xz fparkan-1a8e1eaed1de540367bad377e72d228153d8cec6.zip | |
feat(animation): recover Node38 fallback hierarchy
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/reference/msh.md | 24 | ||||
| -rw-r--r-- | docs/tomes/05-render.md | 21 |
2 files changed, 25 insertions, 20 deletions
diff --git a/docs/reference/msh.md b/docs/reference/msh.md index 93250a5..774e388 100644 --- a/docs/reference/msh.md +++ b/docs/reference/msh.md @@ -45,18 +45,22 @@ struct Node38 { Validated `ModelAsset` также сохраняет decoded type 8 keys и type 19 map как `ModelAnimation`. `node38_fallback_pose` возвращает pose по `fallback_key`, -то есть доказанный static input. Значение `parent_or_link` сохраняется как raw -field, пока runtime evidence не подтверждает, является ли оно parent index или -другой link semantic. +то есть доказанный static input. `parent_or_link == 0xFFFF` означает root; +иначе это parent index, обязательно меньший индекса child. Этот контракт +подтверждён на licensed animation gates обеих частей и защищён fallback-ом: +модель с нарушенным порядком не получает придуманную hierarchy. В legacy-camera static preview стандартный узел уже получает свой fallback pose -до внешнего TMA/Iron3D transform: quaternion поворачивает local vertex, затем -добавляется node translation, после чего применяется `Rz * Ry * Rx`, scale и -mission translation. Геометрия намеренно дублируется на draw-range узла, потому -что один source vertex может быть нарисован разными node poses. Это local-pose -assembly, а не skeleton: `parent_or_link` по-прежнему не используется, поэтому -вложенные parent transforms и dynamic frame-map sampling остаются отдельной -задачей runtime recovery. +до внешнего TMA/Iron3D transform. Parent pose поворачивает child translation, +затем translation суммируется, а rotations умножаются; после полученной global +pose применяется `Rz * Ry * Rx`, scale и mission translation. Геометрия +намеренно дублируется на draw-range узла, потому что один source vertex может +быть нарисован разными node poses. Это static fallback hierarchy, а не полная +animation parity: dynamic type-19 frame-map sampling остаётся отдельной задачей. + +Для воспроизводимого исследования `fparkan-cli model inspect --root <game> +--archive <archive> --resource <model.msh>` выводит Node38 metadata, включая +parent index, fallback key и наличие LOD0/group0 geometry. ## Slot and batch diff --git a/docs/tomes/05-render.md b/docs/tomes/05-render.md index 8dd244f..45bb058 100644 --- a/docs/tomes/05-render.md +++ b/docs/tomes/05-render.md @@ -1601,24 +1601,25 @@ parent hierarchy и animation-key/fallback semantics. Модели без layout Чтобы следующий шаг не перечитывал raw NRes streams в renderer, validated `ModelAsset` теперь переносит `ModelAnimation` с decoded type-8 keys, type-19 map и declared frame count. `node38_fallback_pose` возвращает exact fallback -key pose, а offset `+2` остаётся именованным только как `parent_or_link_raw`. -Licensed gates Part 1/Part 2 повторно подтвердили 435/511 models, 157/200 -animated models, 3,469/5,233 node samples и утверждённые captures. Это -доказывает production handoff animation data, не семантику parent links и не -готовую model assembly. +key pose. Licensed gates Part 1/Part 2 подтвердили 435/511 models, 157/200 +animated models, 3,469/5,233 node samples и утверждённые captures. Следующий узкий шаг применяет этот уже декодированный `fallback_key` в legacy-camera static preview. Для каждого выбранного `Node38` bridge поворачивает вершины normalized quaternion, прибавляет local translation pose и только затем применяет доказанный TMA `Rz * Ry * Rx`, scale и mission translation. Вершины намеренно разворачиваются per node/draw range, чтобы один source vertex мог -получить разные poses. `parent_or_link_raw` не читается как parent, frame map не -семплируется, поэтому это не заявляет восстановленную hierarchy или animation. +получить разные poses. `parent_or_link_raw == 0xFFFF` теперь доказан как root, +а любое меньшее child значение — parent index: inspected `R_B_01.msh` содержит +34-node parent-before-child tree, а Part 1/Part 2 animation gate подтвердил +этот контракт для всех standard nodes. Parent rotation корректно поворачивает +child translation до суммирования. Frame map всё ещё не семплируется, поэтому +это static fallback hierarchy, а не full animation parity. На той же GOG `MISSIONS/Autodemo.00/data.tma` и offline Ngi32 camera capture full preview из 8 objects / 66 mesh components / 67 descriptors завершился за -один native Vulkan run с `clip_visible_vertices=2584`, `validation_warnings=0`, -`validation_errors=0` и readback hash `5769837558651835265`. Рост с 938 -видимых вершин подтверждает, что local source poses реально вошли в geometry +один native Vulkan run с `clip_visible_vertices=3415`, `validation_warnings=0`, +`validation_errors=0` и readback hash `1275533143935640133`. Рост с 2584 +видимых вершин подтверждает, что composed parent poses реально вошли в geometry path; он не является оценкой сходства с original frame. Параллельно bridge для legacy-camera path теперь переводит только высоту |
