247 lines
11 KiB
Markdown
247 lines
11 KiB
Markdown
# RuneWaker evaluated-pose audit
|
|
|
|
`audit-animated-poses.mjs` checks the actual evaluated, skinned vertices of the
|
|
RuneWaker actors shipped by HealerMan. It is intentionally separate from the
|
|
clip-name/readiness audit: an animation can have the right name and duration
|
|
while applying bone rotations in the wrong coordinate basis.
|
|
|
|
## What is audited
|
|
|
|
The batch runner can discover packaged GLBs under `public/assets/creatures`, but
|
|
the authoritative full-game input is the 322 runtime-referenced shipping paths
|
|
in `artifacts/animation-audit/runtime-clip-coverage.json`. Discovery can include
|
|
unused or non-combat assets and must not be substituted for that exact list in a
|
|
release verdict. Each Meshopt shipping GLB is copied through glTF Transform to a
|
|
temporary, uncompressed GLB because Blender does not import
|
|
`EXT_meshopt_compression`. Blender then evaluates:
|
|
|
|
- the armature rest/bind pose;
|
|
- the first, middle, and final frame of every action by default;
|
|
- finite and non-finite skinned vertices;
|
|
- posed AABB, axis extents, diagonal, centroid, maximum radius, and RMS radius;
|
|
- bind-relative size, radius, and centroid-shift ratios;
|
|
- connected-topology component movement, resizing, and separation from the
|
|
bind envelope.
|
|
|
|
The temporary decompressed file is removed after each actor. The report hashes
|
|
and identifies the original packaged GLB, not the temporary copy.
|
|
|
|
## Commands
|
|
|
|
Run from `D:\Projects\HealerMan`. First regenerate the inventory and runtime
|
|
selector plan from the same shipping build that will be pose-audited:
|
|
|
|
```powershell
|
|
npm run runewaker:audit:animation-inventory
|
|
npm run runewaker:audit:runtime-clips
|
|
```
|
|
|
|
The package aliases pass additional CLI arguments through to the batch runner
|
|
and regenerate the deterministic all-dungeon report:
|
|
|
|
```powershell
|
|
npm run runewaker:audit:pose-batch -- --input-list <inputs.json> --jobs 2
|
|
npm run runewaker:audit:pose-master
|
|
```
|
|
|
|
The expected mapping is 436 entity templates to 268 base actor configurations
|
|
to 322 runtime-referenced shipping variants. Do not continue if the inventory
|
|
contract fails. Create the exact input list from the runtime plan, assert its
|
|
size, and run the complete numeric audit plus semantic-family render pass:
|
|
|
|
```powershell
|
|
$projectRoot = (Resolve-Path '.').Path
|
|
$coverageFile = 'artifacts/animation-audit/runtime-clip-coverage.json'
|
|
$coverage = Get-Content -Raw -LiteralPath $coverageFile | ConvertFrom-Json
|
|
$inputs = @(
|
|
foreach ($dungeon in $coverage.samplePlanByDungeonAndAsset.PSObject.Properties) {
|
|
foreach ($asset in $dungeon.Value.PSObject.Properties) {
|
|
(Join-Path $projectRoot $asset.Value.glb).Replace('\', '/')
|
|
}
|
|
}
|
|
) | Sort-Object -Unique
|
|
if ($inputs.Count -ne 322) {
|
|
throw "Expected 322 runtime shipping variants; found $($inputs.Count)."
|
|
}
|
|
$inputList = Join-Path $projectRoot 'artifacts/animation-audit/v5-pose-inputs.json'
|
|
$inputJson = @{ inputs = @($inputs) } | ConvertTo-Json -Depth 3
|
|
[System.IO.File]::WriteAllText(
|
|
$inputList,
|
|
$inputJson + [Environment]::NewLine,
|
|
[System.Text.UTF8Encoding]::new($false)
|
|
)
|
|
node scripts/runewaker-pipeline/audit-animated-poses.mjs `
|
|
--root public/assets/creatures `
|
|
--input-list $inputList `
|
|
--output-dir artifacts/animation-audit/batches/v5-full `
|
|
--summary artifacts/animation-audit/batches/v5-full/summary.json `
|
|
--jobs 2 `
|
|
--sample-mode all `
|
|
--render-mode families `
|
|
--render-limit 24 `
|
|
--contact-sheets
|
|
node scripts/runewaker-pipeline/make-pose-audit-review-pages.mjs `
|
|
artifacts/animation-audit/batches/v5-full
|
|
```
|
|
|
|
`--sample-mode all` numerically evaluates first, middle, and final samples from
|
|
every action. `--render-mode families` renders a bounded representative
|
|
semantic-family set for every shipping variant; it does not reduce the numeric
|
|
action plan. Preserve the runtime coverage JSON, input list, pose reports,
|
|
contact sheets, and review pages together. Their hashes identify the exact
|
|
shipping build under review.
|
|
|
|
Running discovery without an input list remains useful as a broader diagnostic,
|
|
but its count is not the runtime contract:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/audit-animated-poses.mjs --jobs 2
|
|
```
|
|
|
|
Audit one dungeon and keep a deterministic report for each packaged variant:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/audit-animated-poses.mjs `
|
|
--include '^paspers-shrine/' `
|
|
--jobs 2 `
|
|
--output-dir runewaker-export-work/pose-audit-paspers
|
|
```
|
|
|
|
Render one representative middle frame per detected semantic family and make a
|
|
contact sheet:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/audit-animated-poses.mjs `
|
|
--input public/assets/creatures/paspers-shrine/fog-ferocity-03.glb `
|
|
--render-mode families `
|
|
--contact-sheets
|
|
```
|
|
|
|
Use `--render-mode flagged` to render only numeric outliers, or
|
|
`--render-mode all` for every sampled frame. `--render-limit` bounds disk and
|
|
rendering cost. Reports can be reused only when the shipping SHA-256 still
|
|
matches by adding `--resume`.
|
|
|
|
An inventory job can supply the exact runtime-used variant set as a JSON array
|
|
or an object containing an `inputs` array:
|
|
|
|
```json
|
|
{
|
|
"inputs": [
|
|
"D:/Projects/HealerMan/public/assets/creatures/paspers-shrine/fog-ferocity-03.glb",
|
|
{ "file": "D:/Projects/HealerMan/public/assets/creatures/paspers-shrine/fog-loster-03.glb" }
|
|
]
|
|
}
|
|
```
|
|
|
|
Pass it with `--input-list inventory.json`. Relative paths are resolved from
|
|
the inventory file's directory. Input and Blender paths are converted to
|
|
absolute paths before subprocesses start, so Blender changing its working
|
|
directory cannot redirect a source or report.
|
|
|
|
## Required human visual review
|
|
|
|
Numeric status is triage, not acceptance. A wrong quaternion basis can keep all
|
|
values finite and leave the GLB Khronos-clean. A reviewer must inspect the
|
|
contact sheet for every one of the 322 variant paths, including numeric passes,
|
|
and compare warnings with their per-sample metrics. Any folded or inverted
|
|
limb, exploded skin, detached equipment, discontinuity, or ambiguous extreme
|
|
pose must be rerun with `--render-mode all` and, when necessary, compared with
|
|
the original-client animation.
|
|
|
|
After actual inspection, create a review input using
|
|
`batch-a-visual-review-input.json` as the schema reference. Its
|
|
`reviewedVariants` must exactly match `summary.json`; include both
|
|
`demon-stronghold-125` and `zurhidon-stronghold-124` in
|
|
`explicitEmptyDungeons`, and record a reason for each. The compiler verifies
|
|
inventory equality but cannot perform or infer the visual review:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/compile-pose-audit-review.mjs `
|
|
artifacts/animation-audit/batches/v5-full `
|
|
artifacts/animation-audit/batches/v5-full/v5-visual-review-input.json `
|
|
artifacts/animation-audit/batches/v5-full/v5-review.json `
|
|
artifacts/animation-audit/batches/v5-full/v5-review.md
|
|
```
|
|
|
|
## Completed v5 disposition
|
|
|
|
`artifacts/animation-audit/post-v5/summary.json` contains all 322 runtime paths
|
|
and 44,305 evaluated poses: 282 actors passed numerically, 40 are
|
|
accepted-warning candidates, and there were zero errors and zero
|
|
Blender/decompression/report failures. The 634 flagged samples exactly match
|
|
the totals from the visually reviewed v4 batches; no new numeric deformation
|
|
signature appeared after the v5 cast-semantics rebuild. Mantarick accounts for
|
|
the expected static-pose warning, and Sardo's red Rune Warning Device retains
|
|
its intentional native no-locomotion exception.
|
|
|
|
The rebuilt inventory is green at 30/436/268/322 with zero blockers, and the
|
|
runtime selector reports zero semantic near misses. The packaged/offline browser
|
|
showed all 30 dungeons Ready and loaded both Pasper's Shrine and Hall of
|
|
Survivors with no animation or WebGL errors. Only an unrelated library
|
|
deprecation warning appeared. These results complete the v5 pose disposition;
|
|
the sampling and original-client comparison limits below still apply.
|
|
|
|
All 19 focused RuneWaker animation tests pass. The unfinished RoM class catalog
|
|
and missing Manastorm fixtures remain unrelated repo-wide build/test blockers.
|
|
|
|
## Report contract
|
|
|
|
Every `<actor>.pose-audit.json` is timestamp-free and deterministically ordered.
|
|
`variantId` is the stable packaged path below the selected discovery root, so
|
|
actors with the same basename in different dungeons remain distinct.
|
|
Its `sampling.actionPlan` is the machine-readable audit plan: action index,
|
|
exact action name, semantic family, action frame range, and every frame label
|
|
and value selected for evaluation. `samples` records the resulting metrics,
|
|
bind comparisons, and issue codes. `summary.status` is one of `pass`, `warning`,
|
|
or `error`.
|
|
|
|
The batch `summary.json` records one row per packaged input path. Numeric
|
|
warnings do not fail the command because unusual animations can intentionally
|
|
detach weapons or body parts. A Blender/decompression/report failure does fail
|
|
the command.
|
|
|
|
The documented Mantarick exception (Hall of Survivors template `102452`, asset
|
|
`judgement-light-pose`) contains static posed meshes without an armature. It is
|
|
still checked for finite geometry and bounds, and is reported as
|
|
`static-pose-only` with a `pose-only-no-armature` warning rather than failing the
|
|
batch. It is the only approved pose-only runtime variant.
|
|
|
|
Sardo Castle template `105758` (`rune-device-red`, Rune Warning Device) is a
|
|
native stationary device, not pose-only. Its source animation set intentionally
|
|
has no locomotion. A missing-moving warning is acceptable only for this asset;
|
|
its idle, configured combat, wound, and death actions still require numeric and
|
|
visual review.
|
|
|
|
## Regression proof for the Pasper goatmen
|
|
|
|
The preserved pre-fix v3 cache files and the shipping v4 files captured for the
|
|
quaternion repair were audited with all actions:
|
|
|
|
| Actor | Source | Poses | Flagged samples |
|
|
| --- | --- | ---: | ---: |
|
|
| Giant Assassin | pre-fix cache `2dd9e271a1296f39cb35864b.glb` | 61 | 51 |
|
|
| Blackhorn Silencer | pre-fix cache `921ccbe5f2225bf2f02a3136.glb` | 61 | 51 |
|
|
| Giant Assassin | v4 `paspers-shrine/fog-ferocity-03.glb` capture | 61 | 0 |
|
|
| Blackhorn Silencer | v4 `paspers-shrine/fog-loster-03.glb` capture | 61 | 0 |
|
|
|
|
The old poses were caught by connected-component movement even though their
|
|
whole-character AABB diagonal stayed near the bind size. This is why global
|
|
bounds alone are not sufficient for this regression. The v4 comparison proves
|
|
the quaternion repair, while the completed 322-variant post-v5 audit proves the
|
|
cast-semantics rebuild did not change the aggregate evaluated-pose result.
|
|
|
|
## Limits
|
|
|
|
- Numeric shape checks cannot prove semantic correctness, timing quality,
|
|
attack impact alignment, or that a clip is the intended RuneWaker clip.
|
|
- Start/middle/end sampling can miss a defect isolated between those frames.
|
|
- Family contact sheets render representative frames, not every frame of every
|
|
action. Use `--render-mode all` for suspicious actors, then test timing and
|
|
transitions in the browser.
|
|
- Deliberately detached parts, projectiles, trails, and extreme attacks may
|
|
require visual review rather than automatic rejection.
|
|
- Component metrics require the evaluated modifier stack to preserve vertex
|
|
count and ordering.
|
|
- Contact sheets are evidence aids, not replacements for an in-game playtest.
|