Close and archive the 0.9.9 milestone, record that the upstream clips stay unused, and harden the fallback test
This commit is contained in:
1 parent
fcbeee0db2
commit
c70a523f0f
6 files changed
+126
-108
No files matched your search
@@ -2192,3 +2192,105 @@ variants, the four crowd-variety characters and the per-role pools — as a **pa
|
||||
**Exit:** met — 0.9.7 ships the 12-character library (face realism + crowd variety) with the pose
|
||||
harness fixed; the runtime contract is unchanged. The Quaternius NPC base and the map rebuild are
|
||||
not in this patch (they target 0.10.0).
|
||||
|
||||
## Milestone 0.9.9 — Quaternius NPC base swap (patch)
|
||||
|
||||
Goal: make one Quaternius-derived NPC render and animate correctly in Godot and ship it as the
|
||||
pilot base, with the procedural library still selectable as the fallback. This is the first
|
||||
versioned character milestone; it contains the rig correction that has been blocking the
|
||||
ADR-0018 rollout.
|
||||
|
||||
**Why this is a patch:** it changes character presentation and animation quality but adds no new
|
||||
player-facing system. The 0.10.0 minor is reserved for the release gates (see below), so a
|
||||
blocked rig can no longer block the whole release.
|
||||
|
||||
**Completed 2026-11-06.** Shipped as `v0.9.9` (tagged, local release build with checksums)
|
||||
and accepted by the owner after the follow-up fixes. Durable evidence: `docs/3d-model-review.md`,
|
||||
`docs/blender-assets.md`, `docs/adr/0018-quaternius-stage2-runtime-rig.md`.
|
||||
|
||||
### Rig and export correction
|
||||
|
||||
- [x] Reproduce and record the failure: the `armature_apply` + `export_apply=True` bake wrote
|
||||
wrong inverse bind matrices (Godot rendered A-pose while the rest was arm-down). Recorded
|
||||
in `MEMORY.md`; `bake_armdown_clean.py` was the failing recipe.
|
||||
- [x] Fix the arm-down bake so the exported skin matches the rest. `tmp/npc-research/bake_armdown_v2.py`
|
||||
(pose-rotate → apply modifier → reset pose → edit-mode rotate arms → re-add modifier →
|
||||
export `export_apply=False`) now yields a correct arm-down base: Blender deformed x ±0.221
|
||||
and the rest bone tail points down. Still local (`tmp/`), not shipped.
|
||||
- [x] Re-derive the pose composition for a non-180° rest. Superseded by the rig-agnostic
|
||||
`_swing_bone()` below: the rest-relative `set_bone_pose_rotation` form was never exact,
|
||||
because `get_bone_rest()` is parent-relative and already carries the importer's axis
|
||||
conversion. Kept in `MEMORY.md` as a rejected approach.
|
||||
- [x] Fix the skinning/rest bake end to end (commit `cd285b3`):
|
||||
(1) the canonical base is **join-only** (`tmp/npc-research/build_base_minimal.py`: no
|
||||
`remove_doubles` weld, no scale/ground transform, keep the Armature modifiers) — the weld
|
||||
and the transform corrupted the Quaternius weights;
|
||||
(2) the arm-down bake (`tmp/npc-research/bake_armdown_v5.py` — pose, read pose matrices,
|
||||
apply modifier, **reset pose to identity**, set rest matrices, re-add modifier) bakes the
|
||||
rest correctly (DEFORMED x −0.228/0.228, Godot bind pose arm-down);
|
||||
(3) `NpcAvatar._swing_bone()` now writes the **global** bone pose from
|
||||
`get_bone_global_rest()`, so one formula drives both the 62-joint Quaternius rig and the
|
||||
13-core fallback (measured: posed bone axis matches the proxy pivot at dot 1.000 on the
|
||||
Quaternius, and the procedural rigs are unchanged);
|
||||
(4) `RIG_BONES` + `NpcAvatar.bone_name()` hold the only side mapping (the Quaternius labels
|
||||
`L`/`R` opposite the project), and the hand proxy is `global_wrist − global_elbow`.
|
||||
Verified in Godot: idle/sit/walk captures on npc_casual plus the unchanged procedural rigs.
|
||||
- [x] Add regression tests: `test_shipped_rig_resolves_the_animation_joints` covers the joint map,
|
||||
the baked arm-down rest, the down-pointing arm axis and the proxy side mapping; the Blender
|
||||
audit/`inspect` and `npc_proportions` now understand both rigs. Godot 278/278, Python
|
||||
167/167.
|
||||
- [x] Give the Quaternius base the five tint slots: `build_base_minimal.py` renames the upstream
|
||||
materials to `skin`/`cloth`/`pants`/`hair`/`accessory` and keeps `Eye`/`Eyebrows` as
|
||||
fixed-colour detail. The source UV map is degenerate (every loop at 0,0), so the build now
|
||||
Smart-UV-unwraps and repacks the layout — texel density went from an unmeasurable 0 to
|
||||
73–74 px/m on the 256² maps and the 256² AO bake works again.
|
||||
- [x] Idle and Walk verified on the 62-joint rig through the pose code, not the clips: the 24
|
||||
upstream clips stay authoring reference only, because `_animate()` + `_sync_skeleton()`
|
||||
already drive sitting, hand-raising and head turns, and playing clips would replace that
|
||||
state machine rather than supplement it. Recorded in ADR-0018 and `MEMORY.md`.
|
||||
- [x] Poses the clips do not cover are driven by the same proxy pivots (`_legs`, `_knees`,
|
||||
`_arms`, `_elbows`, `_head`), which is why no clip retarget was needed.
|
||||
- [x] Fallback stays tested: `_build_body()` still builds the 13-core rig, and
|
||||
`test_forced_fallback_still_builds_the_procedural_rig` now asserts the hip swings and a hand
|
||||
pivot exists on that path. No MPFB or Stage-1 proportion work reopened.
|
||||
- [x] Backpack straps re-fitted for the Quaternius torso (`fb3e75a`) and the back attach raised to
|
||||
shoulder-blade height; the camera kept its wrist strap.
|
||||
|
||||
### Silhouette and face gate (owner)
|
||||
|
||||
- [x] Re-run the silhouette gate at gameplay distance and in portrait against the current
|
||||
`npc_casual`, front / three-quarter / profile. ADR-0018 removed the proportion warp, so
|
||||
source proportions are accepted by definition (head 13.4 % of height, measured by
|
||||
`npc_proportions`).
|
||||
- [x] Owner visual signoff obtained (2026-11-06) on the roster, the faces, the head gear and the
|
||||
hand/back gear. The review page and its sheets were retired after acceptance; the measurements
|
||||
live on in `docs/3d-model-review.md` and `docs/blender-assets.md`.
|
||||
- [x] Face-fidelity comparison was made and the full swap chosen; the comparison sheets were
|
||||
retired with the review pages, and the decision is recorded in the follow-up section of
|
||||
[`docs/adr/0018-quaternius-stage2-runtime-rig.md`](docs/adr/0018-quaternius-stage2-runtime-rig.md).
|
||||
- [x] **Owner decision:** option (a) full swap (2026-11-05). Applied: all twelve characters are
|
||||
baked from the three Quaternius sources inside 24,000 tris / 24,000 glTF vertices
|
||||
(`a6ccd86`), and the gate was re-run.
|
||||
- [x] Record the decision and its consequence in `MEMORY.md`,
|
||||
`docs/npc-model-sourcing.md#shipped-roster-099-owner-chose-the-full-swap` and the
|
||||
follow-up decision section of
|
||||
[`docs/adr/0018-quaternius-stage2-runtime-rig.md`](docs/adr/0018-quaternius-stage2-runtime-rig.md).
|
||||
- [x] Owner visual signoff on the shipped roster (2026-11-06): accepted.
|
||||
|
||||
### Pilot rollout
|
||||
|
||||
- [x] Map the five tint slots onto the Quaternius materials and unwrap the degenerate source
|
||||
UV map; bake the 256² AO and check texel density (73–74 px/m).
|
||||
- [x] Re-fit every gear attach point against the Quaternius skeleton and test each piece on the
|
||||
character (the 0.9.10 *Prop and gear fit pass* below carries the measurements).
|
||||
- [x] Wired the approved base into all twelve roles, with the procedural library as the instant
|
||||
fallback; no runtime download or optional dependency.
|
||||
- [x] Ran `inspect` (clean), `audit` (12/12), `fit` (OK), `npc_proportions` (measured), the 24-NPC
|
||||
budget smoke (175,264 tris, 0.87 ms) and the capture gates before/after the fixes.
|
||||
- [x] Released `0.9.9`: `config/version` 0.9.9, `CHANGELOG.md` entry, local build with checksums,
|
||||
commit, tag `v0.9.9` and push. Owner accepted the roster on 2026-11-06.
|
||||
|
||||
**Exit:** one committed Quaternius GLB renders arm-down with correct skinning, plays Idle and
|
||||
Walk on the 62-joint rig, poses correctly under the new composition, passes the owner face and
|
||||
silhouette gate, fits the 18 gear pieces, stays inside budget, and ships as `0.9.9` with the
|
||||
procedural library still available as a fallback.
|
||||
Reference in new issue
Block a user