diff --git a/MEMORY.md b/MEMORY.md index e7458f1..360eb17 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -15,7 +15,10 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o (7 match / 4 review / 0 diff); `--model` remains available. - `capture_realism.gd` parses `--portrait-type=N`; it was documented but ignored before the gear pass. Portrait captures need the requested NPC type to have spawned, otherwise the stage can - finish with an empty frame; use the Blender `npc_coat` preview for a deterministic gear check. + finish with an empty frame; use the Blender character previews (`render --only npc_coat`) for + deterministic gear checks. +- Headgear: the firefighter helmet was lifted 2 cm after the brow/face pass; cap and hood were + visually checked on `npc_vest`/`npc_hoodie`. The beanie is unused and shares the cap shell. - Gear fit is measured with `python3 tools/blender_assets.py fit` (stdlib, reads the GLBs): head width uses skin vertices weighted to Head in y 1.55–1.81; clothing radius is the cloth skirt in y 0.30–0.52 with a pants hip fallback. The command reports per-character gear boxes, diff --git a/TODO.md b/TODO.md index 1cf9303..6b3d6c3 100644 --- a/TODO.md +++ b/TODO.md @@ -25,8 +25,11 @@ live in `tools/blender_assets.py` (`_build_gear()`), the contract in `docs/blend moved it outboard (centre x=0.292); the body's inner face is now 0.262 m, clearing the coat (0.225) by 0.037 m and the dress (0.260) by 0.002 m. The strap's lower attach points sit on the same outboard line. `fit` now measures the bag body separately from the torso strap. -- [ ] Same pass for `cap`/`beanie`/`hood`/`firefighter_helmet`: they must not clip the new - brow/ear geometry, and `hood` must still leave the face readable for hoodie avatars. +- [x] Same pass for `cap`/`beanie`/`hood`/`firefighter_helmet`: rendered the cap (vest), hood + (hoodie), and firefighter helmet on their characters. Cap and hood clear the brow/ears and + the hood leaves the face readable; the helmet brim sat on the brow, so the whole helmet was + lifted 2 cm and rebuilt/re-baked. Beanie uses the same capped-shell sizing as the cap and is + currently unused; it is covered by the upcoming headgear regression check. - [ ] Rebuild the gear (`build`) and re-bake AO (`tools/bake_ao.py`), then `godot --headless --path . --import`. - [ ] Add a regression test: `tools/test_blender_assets.py` checks the glasses width against the diff --git a/assets/models/blender/manifest.json b/assets/models/blender/manifest.json index 0b3e278..9c4106a 100644 --- a/assets/models/blender/manifest.json +++ b/assets/models/blender/manifest.json @@ -287,12 +287,12 @@ "bounds_godot": { "max": [ 0.26, - 0.225, + 0.245, 0.26 ], "min": [ -0.26, - 0.015, + 0.035, -0.351 ] }, diff --git a/assets/models/blender/npc_gear/firefighter_helmet.glb b/assets/models/blender/npc_gear/firefighter_helmet.glb index f1a3bdc..b7477a0 100644 Binary files a/assets/models/blender/npc_gear/firefighter_helmet.glb and b/assets/models/blender/npc_gear/firefighter_helmet.glb differ diff --git a/assets/models/blender/npc_gear/firefighter_helmet_ao.png b/assets/models/blender/npc_gear/firefighter_helmet_ao.png index 1177375..cf982e8 100644 Binary files a/assets/models/blender/npc_gear/firefighter_helmet_ao.png and b/assets/models/blender/npc_gear/firefighter_helmet_ao.png differ diff --git a/tools/blender_assets.py b/tools/blender_assets.py index 1ba60d3..241da5f 100644 --- a/tools/blender_assets.py +++ b/tools/blender_assets.py @@ -996,6 +996,10 @@ def build_gear(name): scale=(1.0, 1.08, 1.0))) p.append(box("Ridge", (0.03, 0.34, 0.05), (0, 0.0, 0.2), M("helmet"), bevel=0.01)) p.append(box("Shield", (0.09, 0.012, 0.09), (0, -0.2, 0.11), M("brass"), bevel=0.01)) + # The 2026-11-01 face pass added a brow ridge; lift the helmet 2 cm so + # the brim sits above the eyes instead of cutting into the brow. + for obj in p: + obj.data.transform(Matrix.Translation((0, 0, 0.02))) # Back gear: origin = spine centre (Godot 0, 1.10, 0); +Y Blender = behind. elif name == "backpack": p.append(box("Pack", (0.30, 0.15, 0.40), (0, 0.20, 0.08), M("pack_nylon"),