Narrow the pose-capture discrepancy to the harness and lock bone posing
Full build / Import + headless tests (push) Successful in 45s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-03 11:24:44 +01:00
1 parent 7a5b902797
commit 1d4f718376
5 files changed
+63 -26

No files matched your search

+19 -18
View File
@@ -165,26 +165,27 @@ for presence, not re-reviewed for art quality.
## Pose evidence is blocked (2026-11-03)
The weights/pose column cannot be filled yet. A pose harness was added
(`src/test/capture_npc_pose.gd`, staged in `tmp/model-pose*`), and its output does not match the
state it reports:
The weights/pose column cannot be filled yet. The pose logic is verified; the *capture* is not.
`src/test/capture_npc_pose.gd` stages idle / walk-contact / walk-pass / seated for all eight
variants (full-body + shoulder views) and its output does not match the state it reports.
- `_animate()` applies the seated pose (logged `rig_y=-0.339`, `leg0=-1.357`) and
`Skeleton3D.get_bone_pose_rotation()` returns the rotated quaternion at capture time, yet the
saved frame shows the rest pose.
- Ruled out: missing skeleton (one `Skeleton3D`, mesh bound to it, `same=true`), hidden mesh
(hiding `npc_base` removes the body), pose not applied (proxies and bone poses verified),
and unbound skinning: writing a single bone rotation directly (`HipL`, `KneeL`, `Spine`,
`ShoulderL`, `ElbowL`, `Head`) changes the rendered pixels, and a bone *position* offset moves
the head. A standalone probe that calls the same `_animate()` sequence renders the crouch.
- Also observed: a staged in-game `film` pose frame showed the arms down, so this may affect the
live game rather than only the harness. That is why it is a P0/P1 candidate rather than a QA
tooling nit.
| Check | Result |
| --- | --- |
| Pose reaches proxies | Seated pose logs `rig_y=-0.339`, `leg0=-1.357` |
| Pose reaches skeleton bones | `Skeleton3D.get_bone_pose_rotation(HipL/KneeL)` differs from rest; new headless test `test_pose_reaches_the_skeleton_bones` locks it (suite 273/273) |
| Idle restores rest | Same test asserts the hip returns to its rest orientation |
| Skinning bound | One `Skeleton3D`, mesh bound to it (`same=true`); hiding `npc_base` removes the body |
| Bone rotations deform the mesh | Direct writes change rendered pixels: Spine 1,719 / HipL 1,052 / KneeL 810 / ElbowL 745 / Head 671 / ShoulderL 640 sampled pixels |
| Bone translation deforms the mesh | A +0.5 m Head offset moves the head in frame |
| Standalone probes render the pose | Three variants (avatar under `root`, under a `Node3D` stage, created mid-`_process`) all render the seated crouch (`posed` vs rest diff ≈ 2,200–2,360 samples) |
| The harness renders the pose | **No.** All 8 variants × 4 poses save the rest pose while the logged state and bone poses are posed |
Next step is a focused diagnosis: compare the harness/venue staging with the standalone probe
(SceneTree lifetime, node parents, first-frame skin bind, capture timing) and add a scene test
that asserts a posed avatar renders differently from its rest frame. Do not mark the pose/weight
scorecard row until that test exists.
The cause is therefore in the harness's capture path, not in the rig or the animation math. Two
leads are left and both are cheap: reproduce the stage inside a harness that is known to render
correctly (`capture_npc_review.gd` already produces 96 valid frames), or capture through a
`SubViewport` with `RenderingServer.force_draw()` so the frame cannot lag the state. Until a
scene test asserts that a posed avatar renders differently from its rest frame, do not treat pose
sheets as evidence and do not claim rig deformation in the review.
## Ranked candidate gaps