Close the NPC gear-fit section
Move the completed gear section to DONE.md and record the hooded-portrait follow-up. An explicit --portrait-type now overrides the hooded-subject skip, though the day roster has no types 5-7 yet. Headless 229/229.
This commit is contained in:
1 parent
151630e957
commit
26d64baa01
4 files changed
+58
-44
No files matched your search
@@ -1196,3 +1196,49 @@ Web deployment and release artifact list were brought up to date. `MEMORY.md` wa
|
||||
obsolete uncommitted/active-pass claims and now points at the current follow-ups.
|
||||
|
||||
- [x] Re-check `PLAN.md`/`MEMORY.md` against the current build, update `README.md` and `docs/architecture.md`, and compact the historical PLAN sections.
|
||||
|
||||
## NPC gear fit (v0.6.1)
|
||||
|
||||
Completed 2026-11-01. Eyes, bag and helmet now fit the measured body silhouette; portrait staging and gallery shots are refreshed.
|
||||
|
||||
The 2026-11-01 detail pass fixed the bodies but not the props worn on them. In the portrait
|
||||
capture (`--stages=day,portrait`, see the report in `docs/screens/realism/2026-11-01-npc/`) the
|
||||
sunglasses span the whole upper face and the shoulder bag cuts through `npc_coat`'s skirt. Blender sources for gear
|
||||
live in `tools/blender_assets.py` (`_build_gear()`), the contract in `docs/blender-assets.md`
|
||||
(gear budget 1500 tris, `GEAR_ATTACH` points in `NpcAvatar`).
|
||||
|
||||
- [x] Measure the fit in Blender, not by eye: `python3 tools/blender_assets.py fit` prints each
|
||||
character's measured head width and hip/skirt radius, then every head/back/chest gear
|
||||
bounding box with head-band status or skirt clearance. Current measurements: head width
|
||||
0.315 m; coat skirt 0.225 m, dress 0.260 m; sunglasses 0.282 m (0.90x head); shoulder-bag
|
||||
x-clearance -0.025 m on the coat (radial -0.031 m on the dress).
|
||||
- [x] Narrow `sunglasses` from 0.28 m to ~0.20 m. The hinges moved to ±0.075 (0.035 box), the
|
||||
arms to ±0.098, and the lenses are 0.024 m radius at the same `y=-0.152`, `z=0.035` plane.
|
||||
Rebuilt GLB/AO: measured width **0.202 m** (0.64x head), still inside the head band.
|
||||
Also fixed `capture_realism.gd` so `--portrait-type=N` is actually parsed (it was documented
|
||||
but ignored).
|
||||
- [x] Fix `shoulder_bag` clipping through `npc_coat`/`npc_dress`: narrowed the bag to 0.06 m and
|
||||
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.
|
||||
- [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.
|
||||
- [x] Rebuild the gear (`build --only <18 gear names>`) and re-bake AO (`tools/bake_ao.py --only
|
||||
<same>`), then `godot --headless --path . --import` (clean). Blender's GLB export is
|
||||
byte-nondeterministic for unchanged assets (padding/index order changes), so the no-op churn
|
||||
was reverted; only the intended sunglasses, bag, and helmet assets are committed.
|
||||
- [x] Add a regression test: `tools/test_blender_assets.py` limits the glasses to 0.70x head
|
||||
width and requires positive bag clearance on both coat and dress;
|
||||
`test_npc_character.test_head_and_back_gear_clear_the_body_silhouette` loads the gear on
|
||||
six roles and checks head-parent/width/brow bounds plus back-parent/0.26 m outer radius.
|
||||
- [x] Re-capture the portrait (`--stages=day,portrait`) and the gallery shots; record the
|
||||
before/after in `docs/screens/realism/2026-11-01-gear/`. The portrait staging now turns the
|
||||
rig toward the camera (the old yaw was 180° out) and hides the blue focus disc, which was
|
||||
covering the face in close-ups. `check_screenshots.sh` is 11 good / 0 bad; the judge went
|
||||
from overall 2 / characters 1 to overall 3 / characters 2.
|
||||
- [x] Consider a second character close-up for a hoodie/winter NPC so headgear is covered too.
|
||||
`--portrait-type=N` now overrides the hooded-subject skip, but the day roster does not spawn
|
||||
types 5-7, so no hooded subject was available; deferred as a scenario-spawn follow-up.
|
||||
@@ -246,6 +246,10 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o
|
||||
helmet is lifted 2 cm above the brow. `test_npc_character` guards head/back gear in Godot.
|
||||
Blender's GLB export is byte-nondeterministic for unchanged assets (padding/index order), so do
|
||||
not commit a full no-op rebuild; rebuild only the assets whose geometry changed.
|
||||
- **Portrait capture:** `capture_realism.gd` faces the **Rig** toward the camera (using the
|
||||
inverse look direction) and hides the blue `FocusCircle`; the old code used the wrong yaw and
|
||||
left the focus disc over the face. An explicit `--portrait-type=N` now overrides the hooded
|
||||
skip, but the day roster spawns none of types 5-7, so a hooded close-up is deferred.
|
||||
- **v0.6.0 environment pass:** `tools/bake_ao.py` bakes 256² AO maps per library asset
|
||||
(`<name>_ao.png`, red channel) and `Materials.apply_ao()`/`SurfaceMaterials` wire them in;
|
||||
`tools/make_normal_maps.py` derives tangent normals for the 1024² brick/concrete/asphalt
|
||||
|
||||
@@ -3,49 +3,6 @@
|
||||
Work is grouped by theme. Each item should be small enough to complete and verify on its own;
|
||||
see `AGENTS.md` for the workflow and `MEMORY.md` for the decisions behind these plans.
|
||||
|
||||
## NPC gear fit (v0.6.1)
|
||||
|
||||
The 2026-11-01 detail pass fixed the bodies but not the props worn on them. In the portrait
|
||||
capture (`--stages=day,portrait`, see the report in `docs/screens/realism/2026-11-01-npc/`) the
|
||||
sunglasses span the whole upper face and the shoulder bag cuts through `npc_coat`'s skirt. Blender sources for gear
|
||||
live in `tools/blender_assets.py` (`_build_gear()`), the contract in `docs/blender-assets.md`
|
||||
(gear budget 1500 tris, `GEAR_ATTACH` points in `NpcAvatar`).
|
||||
|
||||
- [x] Measure the fit in Blender, not by eye: `python3 tools/blender_assets.py fit` prints each
|
||||
character's measured head width and hip/skirt radius, then every head/back/chest gear
|
||||
bounding box with head-band status or skirt clearance. Current measurements: head width
|
||||
0.315 m; coat skirt 0.225 m, dress 0.260 m; sunglasses 0.282 m (0.90x head); shoulder-bag
|
||||
x-clearance -0.025 m on the coat (radial -0.031 m on the dress).
|
||||
- [x] Narrow `sunglasses` from 0.28 m to ~0.20 m. The hinges moved to ±0.075 (0.035 box), the
|
||||
arms to ±0.098, and the lenses are 0.024 m radius at the same `y=-0.152`, `z=0.035` plane.
|
||||
Rebuilt GLB/AO: measured width **0.202 m** (0.64x head), still inside the head band.
|
||||
Also fixed `capture_realism.gd` so `--portrait-type=N` is actually parsed (it was documented
|
||||
but ignored).
|
||||
- [x] Fix `shoulder_bag` clipping through `npc_coat`/`npc_dress`: narrowed the bag to 0.06 m and
|
||||
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.
|
||||
- [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.
|
||||
- [x] Rebuild the gear (`build --only <18 gear names>`) and re-bake AO (`tools/bake_ao.py --only
|
||||
<same>`), then `godot --headless --path . --import` (clean). Blender's GLB export is
|
||||
byte-nondeterministic for unchanged assets (padding/index order changes), so the no-op churn
|
||||
was reverted; only the intended sunglasses, bag, and helmet assets are committed.
|
||||
- [x] Add a regression test: `tools/test_blender_assets.py` limits the glasses to 0.70x head
|
||||
width and requires positive bag clearance on both coat and dress;
|
||||
`test_npc_character.test_head_and_back_gear_clear_the_body_silhouette` loads the gear on
|
||||
six roles and checks head-parent/width/brow bounds plus back-parent/0.26 m outer radius.
|
||||
- [x] Re-capture the portrait (`--stages=day,portrait`) and the gallery shots; record the
|
||||
before/after in `docs/screens/realism/2026-11-01-gear/`. The portrait staging now turns the
|
||||
rig toward the camera (the old yaw was 180° out) and hides the blue focus disc, which was
|
||||
covering the face in close-ups. `check_screenshots.sh` is 11 good / 0 bad; the judge went
|
||||
from overall 2 / characters 1 to overall 3 / characters 2.
|
||||
- [ ] Consider a second character close-up for a hoodie/winter NPC so headgear is covered too
|
||||
(`--portrait-type=5` already forces a hooded role for comparison).
|
||||
|
||||
## Venue geometry and the committed gallery (v0.6.1)
|
||||
|
||||
Today all three venues share the Hollywood `WorldBuilder` geometry, so the Joke Shop and studio
|
||||
@@ -96,6 +53,8 @@ path.
|
||||
|
||||
## Realism follow-ups (deferred)
|
||||
|
||||
- [ ] Capture a hooded/winter NPC close-up once a scenario spawns types 5-7 (the explicit
|
||||
`--portrait-type` override is already in `capture_realism.gd`).
|
||||
- [ ] Human-authored tree/hedge silhouettes: the whole scene now reads well except the foliage,
|
||||
which is still flat-shaded clumps (`_shrub()`/`_tree()` in `tools/blender_assets.py`).
|
||||
Only worth doing if a higher-poly organic builder is added to the library.
|
||||
|
||||
@@ -318,7 +318,12 @@ func _faces_covered(npc: Node3D) -> bool:
|
||||
var profile = brain.get("profile")
|
||||
if profile == null:
|
||||
return false
|
||||
return int(profile.get("npc_type")) in HOODED_TYPES
|
||||
var npc_type := int(profile.get("npc_type"))
|
||||
# An explicit --portrait-type is a deliberate request to inspect headgear,
|
||||
# including a hood; the default crowd selection still avoids covered faces.
|
||||
if _portrait_type >= 0 and npc_type == _portrait_type:
|
||||
return false
|
||||
return npc_type in HOODED_TYPES
|
||||
|
||||
## Apply swaps, tints and normals to every material whose original albedo path
|
||||
## matches. Called once per stage; materials are visited through the tree.
|
||||
|
||||
Reference in new issue
Block a user