Record the Quaternius pilot fixes and remaining 0.9.9 work in MEMORY.md
Full build / Import + headless tests (push) Successful in 42s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-06 13:19:42 +01:00
1 parent b012c6a675
commit 68f49253fe
1 file changed
+26 -17
+26 -17
View File
@@ -119,10 +119,10 @@ canonical implemented-features list in `docs/development-status.md`.
library with a sculpted realistic face, so the 0.9.9 gate is a product decision, not just an
art check. Owner picks full swap / crowd-only / extra head detail. Do not lower character
fidelity silently.
- **Pose composition is rest-relative (2026-11-05, hypothesis to verify at 0.9.9):** Godot's
`set_bone_pose_rotation` offsets from the bone rest, so `rest * Quaternion(axis, angle)` only
equals the target when the rest is ±identity (the old 180° rig). The candidate fix is
`rest.inverse() * target`, proven with measured global bone transforms.
- **Pose composition is rest-relative (resolved 2026-11-05):** Godot's `set_bone_pose_rotation`
offsets from the bone rest, so the correct swing around a world axis is
`rest * Quaternion(rest.inverse() * axis, angle)`. For the old 180° rest this reduces to the
legacy `rest * Quaternion(axis, angle)`, so the 13-core fallback is unchanged (commit `8b1bf73`).
- **One character source, one fallback:** no new NPC source without an ADR. MPFB body work stays
closed, the Stage-1 proportion warp is not reopened, and the procedural `npc_base` + MakeHuman
head stay tested until the Quaternius base passes its gate.
@@ -147,13 +147,19 @@ canonical implemented-features list in `docs/development-status.md`.
out of a portrait frame (park the rest of the crowd away instead).
- Blender: `bisect_plane` and thin bevels leave zero-area triangles (Godot "non-finite normal in
LOD generation"); `_clean()` + a weld after bisect fixes them and the audit rejects them.
- Quaternius arm-down bake: pose-rotate `UpperArm.L/R` −90° local X → apply Armature modifier →
`armature_apply` → re-add modifier bakes the rest, but `export_apply=True` writes wrong inverse
bind matrices (Godot renders A-pose even though the rest is arm-down). The runtime `_pose_bone`
`rest * Quaternion(axis, angle)` only cancels when `rest² = identity` (old rig's 180° rest); the
Quaternius ~76° rest does not, so the pose formula must be re-derived for a non-180° rest.
Godot's bone pose rotation is relative to the bone rest, not absolute: treat
`rest.inverse() * target` as the candidate and verify with measured global bone transforms.
- Quaternius arm-down bake (working recipe, `tmp/npc-research/bake_armdown_v5.py`): pose-rotate
`UpperArm.L/R` −90° local X → read the pose matrices → apply the Armature modifier → **reset the
pose to identity** → set each arm bone's rest matrix from its pose matrix → re-add the modifier →
export `export_apply=False`. Missing the pose reset double-applies the arm-down (mesh ±0.53
instead of ±0.23). `armature_apply` in Blender 5.2 is broken (deforms the mesh but does not bake
the rest). The canonical base must be **join-only** (`build_base_minimal.py`: no `remove_doubles`
weld, no scale/ground transform, keep the Armature modifiers) — the weld and the scale/ground
transform corrupt the skin weights (arm poses to ±0.51 instead of −0.23).
- Quaternius `NpcAvatar` wiring (commit `2a6f29f`): the Quaternius labels `L`/`R` opposite the
project, so the dot-suffixed bone names are looked up with a **swapped suffix** (proxy `L` →
`UpperLeg.R`/`UpperArm.R`, proxy `R` → `.L`). The arm/elbow swing axis is `Vector3.LEFT` (legs
stay `RIGHT`). The hand proxy position is `global_wrist − global_elbow` (subtracting the relative
`elbow.position` misplaces handheld gear). Old 13-core names fall back unchanged.
- Image models have per-model size floors/caps (Seedream needs 1920+; `GEN_SIZE=2048`, do not
lower; gpt-5-image-mini caps lower). `generate_image` applies model-specific sizing; concept
generation defaults to `--request-size 1536`.
@@ -242,12 +248,15 @@ realism asset pipeline (see `DONE.md` and `CHANGELOG.md`). The 12-character proc
**Planning pivot (2026-11-05, owner):** the character and map work was re-sequenced into
patches (`0.9.9`–`0.9.12`) with `0.10.0` as the public-readiness minor. The gap analysis and the
three release roadmaps now live in `PLAN.md`; `TODO.md` is the executable task list. ADR-0017
Stage 1 (proportion warp) is dead; ADR-0018 option 2 (62-joint runtime) is accepted. The
`quaternius_base.glb`, joint map, slot map and `NpcAvatar` name mapping exist, but the arm-down
skin export and the pose composition are still wrong — no Quaternius character has rendered
correctly in Godot yet, and no character GLB has been rebuilt since the pivot.
Stage 1 (proportion warp) is dead; ADR-0018 option 2 (62-joint runtime) is accepted.
Test counts as of 2026-11-05: Python 167/167 (last run), Godot 277/277 (last run before the
docs-only pivot), `check_docs` OK.
**Quaternius pilot (2026-11-05):** the arm-down skin export and pose composition are now fixed
(`bake_armdown_v5.py`, `2a6f29f`). The join-only `quaternius_base.glb` renders arm-down in Godot;
idle/sit/walk were vision-verified (coherent humanoid, seated arms on thighs, contralateral walk).
Remaining before 0.9.9: handheld-gear fitting (the 0.43 m camera reads shoulder-mounted on the
0.42 m arm), five-slot mapping + AO bake, the owner face/silhouette gate, then the rollout.
No character GLB has been rebuilt since the pivot.
Test counts as of 2026-11-05: Python 167/167, Godot 277/277, `check_docs` OK.
<!-- b64: RWFzdGVyIGVnZzogYSByYXJlIHJhZGlvIHRyYW5zbWlzc2lvbiAiwr9Ew7NuZGUgZXN0w6EgbGEgbW90YT8iIGZpcmVzIHZpYSBHYW1lTWFuYWdlci5fbWF5YmVfcmFkaW9fZWFzdGVyX2VnZyAoMi41JSBjaGFuY2UgYWZ0ZXIgYSBzdWNjZXNzZnVsIHJhZGlvIGNhbGwpLiBTdHJpbmcga2V5IHJhZGlvLmVhc3Rlcl9lZ2cgaW4gY29udGVudC9zdHJpbmdzLmVuLmpzb24uIERvIG5vdCByZW1vdmUu -->