The Python fit test now caps the glasses at 0.70x head width and requires a positive bag clearance on both the coat and dress. The Godot character suite loads head/back gear on six roles and checks attach parents, head width and brow bounds, and that back gear reaches beyond the 0.26 m body silhouette. Rebuilt and re-baked all 18 gear assets; no-op GLB export churn was reverted. Headless 229/229, Python 87/87.
7.6 KiB
TODO
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).
- Measure the fit in Blender, not by eye:
python3 tools/blender_assets.py fitprints 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). - Narrow
sunglassesfrom 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 samey=-0.152,z=0.035plane. Rebuilt GLB/AO: measured width 0.202 m (0.64x head), still inside the head band. Also fixedcapture_realism.gdso--portrait-type=Nis actually parsed (it was documented but ignored). - Fix
shoulder_bagclipping throughnpc_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.fitnow measures the bag body separately from the torso strap. - 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 --only <18 gear names>) and re-bake AO (tools/bake_ao.py --only <same>), thengodot --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. - Add a regression test:
tools/test_blender_assets.pylimits 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_silhouetteloads the gear on six roles and checks head-parent/width/brow bounds plus back-parent/0.26 m outer radius. - Re-capture the portrait (
--stages=day,portrait) and the gallery shots; record the before/after indocs/screens/realism/<date>-gear/. - Consider a second character close-up for a hoodie/winter NPC so headgear is covered too
(
--portrait-type=5already 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
concepts are only compared on lighting (noted in tools/scene_concepts.py SHOTS). They also
have no stage in the committed docs/screenshots/ gallery, only in capture_realism.gd.
- Extract a geometry spec per venue instead of branching inline: a
scenario.(orWorldBuilder) table of facade width/height, door style, window rows, awning/marquee flags, street furniture set, palette and props, defaulting to the Hollywood values so nothing regresses. - Joke Shop: narrow brick alley (10–12 m wide), one warm wall lantern as the key light, recessed door with a step, shuttered window, dumpster/AC clutter, no skyline ring — the alley concept has depth, not a horizon.
- TV Studio: granite/stone facade, bulb canopy instead of the marquee, glossy black car on the curb, stanchions and barrier line at the door, no palm trees.
- Keep navigation working: regenerate/verify the
NavigationRegion3Dbake per venue, update sidewalk/steps/door waypoints (Joke Shop and Studio already havesidewalkandsteps_end), and confirm NPCs still reach the door (smoke +test_venue_*). - Split the concept mapping so each venue is judged on its own frame (
joke_shop_*,studio_*) and drop the "shared geometry" caveat intools/scene_concepts.py. - Add both venues to the committed gallery: two new stages in
src/test/capture_screenshots.gd(12-joke-shop.png,13-studio-arrival.png) reusing the existingjoke_shop_queue/studio_arrivaldesigns, thencheck_screenshots.shand a fresh judge run. - Update
docs/architecture.md(venue geometry),README.md(gallery) and the screenshot table when the stages land.
Forward+ desktop preset and a volumetric flashlight (v0.7.0)
The Compatibility renderer has no volumetrics, so the flashlight is a tight pool of light with no visible shaft. A second desktop build can render it properly without touching the CI/default path.
- Write the preset as an
override.cfg(Godot reads it beside the binary/project) that setsrendering/renderer/rendering_method="forward_plus", enablesvolumetric_fog_*and SDFGI, and keeps the Compatibility build as the default (project.godotunchanged). - Gate the effect in code: only give the flashlight a volumetric component when the renderer
is Forward+ (
RenderingServer.get_rendering_device() != null), so Web/CI builds are untouched and the existing headless tests keep passing. - Tune
light_volumetric_fog_energy/fog_densityfor the LATE phase and re-check the entrance so the shaft does not wash the facade again (the reason the wide cone was cut). - A/B the two renderers with
capture_realism.gd(same stages, two--outdirs) and record the diff + judge scores indocs/screens/realism/<date>-forward-plus/. - Add the preset to
tools/build_releases.shanddocs/RELEASING.mdas an optional "desktop HQ" artifact, and note the runtime requirement (Vulkan driver) inREADME.md. - Test: a headless run must still boot when Forward+ is unavailable (the preset must degrade to Compatibility instead of failing to start).
Realism follow-ups (deferred)
- Human-authored tree/hedge silhouettes: the whole scene now reads well except the foliage,
which is still flat-shaded clumps (
_shrub()/_tree()intools/blender_assets.py). Only worth doing if a higher-poly organic builder is added to the library. - Camera height: the concept frames are shot at ~1.55 m with a slightly wider lens; the game camera sits at 1.7 m. Decide whether the first-person height should match the art direction or stay at the current gameplay value.
Future ideas (optional, not scheduled)
- Live 3D body-camera replay (the timeline is text-only today).
- Additional venues or seasonal events authored from the new
.tresfiles. - Real voice/dialogue audio (the crowd bed and radio crackle are procedural).
- Swap the primitive prop builder for an image-to-mesh model API behind the same
assets/models/generated/<prop>.glbcontract.