feat(facades): 0.1.5 — hero detail, scene audit, material orphaning fixed #32

Merged
zwitschi merged 5 commits from facade-finishing-0.1.5 into main 2026-11-08 22:56:08 +01:00
Owner

Summary

The 0.1.5 façade-finishing patch.

The find that mattered

The "blockout cleaning" task needed material and placement hygiene, not more geometry. A new scene audit found the map was rendering with 604 of 620 mesh actors unmaterialed — every kit piece and all theatre trim — because ensure_material deleted and recreated the site materials on every run, orphaning every reference. Nothing errored; the map looked only slightly flat.

Added

  • Tools/ue_audit_scene.py — gate: every mesh actor has a material, every verified frontage span within ±1 m, no duplicate actor labels. Wired into render_screenshots.sh, which now runs the full chain in the required order and stops on failure.
  • Tools/ue_placement.py — one source of truth for staged positions and verified spans, with validators and tests that fail if a stale literal returns.
  • Hero fluting — 20 grooves per column as shallow shadow-tone cylinders (120 pieces) instead of boolean cuts.

Changed

  • Motto band is a real recess (surround 6 cm proud, panel 12 cm behind) instead of an 8 cm dark stripe. Hero 148 parts/3 044 tris → 271/5 492, still 14.50 m.
  • Kit layout fixed for wide/tall buildings — bays capped at 9 (6922 had 13 across 65.8 m, a window every 4.96 m on a 37 m block), storey spread derived from available height.

Fixed

  • 604 unmaterialed actors (materials updated in place).
  • Hero could be teleported 13 m east onto the north side — the importer carried its own copy of the pre-0.1.0 position. Placement now has one definition; the import asserts the staged span.
  • 53 duplicated kit actor labels.

Verified

Scene audit 0 failures · packaged -qaselftest all PASS · 1440p re-measured: 2.76 ms / 363 fps, p99 3.64 ms (≈12 % more than 0.1.0, ~6× the 60 fps floor) · 78 tool tests · screenshots verified 4/4.

Carried forward

Retail neighbours 6822 / 6806–6820 / 6800 move to a 0.1.6 patch: Commons holds no usable reference for two of the three, and substituting the theatre's photographs would misattribute those façades.

## Summary The `0.1.5` façade-finishing patch. ### The find that mattered The "blockout cleaning" task needed **material and placement hygiene, not more geometry**. A new scene audit found the map was rendering with **604 of 620 mesh actors unmaterialed** — every kit piece and all theatre trim — because `ensure_material` deleted and recreated the site materials on every run, orphaning every reference. Nothing errored; the map looked only slightly flat. ### Added - **`Tools/ue_audit_scene.py`** — gate: every mesh actor has a material, every verified frontage span within ±1 m, no duplicate actor labels. Wired into `render_screenshots.sh`, which now runs the full chain in the required order and stops on failure. - **`Tools/ue_placement.py`** — one source of truth for staged positions and verified spans, with validators and tests that fail if a stale literal returns. - **Hero fluting** — 20 grooves per column as shallow shadow-tone cylinders (120 pieces) instead of boolean cuts. ### Changed - **Motto band is a real recess** (surround 6 cm proud, panel 12 cm behind) instead of an 8 cm dark stripe. Hero 148 parts/3 044 tris → 271/5 492, still 14.50 m. - **Kit layout fixed for wide/tall buildings** — bays capped at 9 (6922 had 13 across 65.8 m, a window every 4.96 m on a 37 m block), storey spread derived from available height. ### Fixed - 604 unmaterialed actors (materials updated in place). - **Hero could be teleported 13 m east onto the north side** — the importer carried its own copy of the pre-`0.1.0` position. Placement now has one definition; the import asserts the staged span. - 53 duplicated kit actor labels. ### Verified Scene audit **0 failures** · packaged `-qaselftest` all PASS · **1440p re-measured: 2.76 ms / 363 fps, p99 3.64 ms** (≈12 % more than `0.1.0`, ~6× the 60 fps floor) · 78 tool tests · screenshots verified 4/4. ### Carried forward Retail neighbours 6822 / 6806–6820 / 6800 move to a `0.1.6` patch: Commons holds no usable reference for two of the three, and substituting the theatre's photographs would misattribute those façades.
zwitschi added 5 commits 2026-11-08 22:54:46 +01:00
Kit layout, found while starting the retail pass:
- Bays were round(width / 4.96), so 6922 (65.8 m wide) got 13 bays - a window every
  4.96 m across a 37 m block. Capped at MAX_BAYS = 9, widening the module instead.
- Storeys were assumed exactly 310 cm apart, leaving ~1.6 m of bare wall under the
  cornice on a tall building. The spread is now derived from the available height
  (usable / storeys), so the top band lands inside the volume.
  Result: 6922 9x11 (was 13x11), theatre 8x6, 6806 7x3, 6800 4x3, TCL 9x5.

Retail references: fetched Art/reference/retail-neighbours/01-lee-drug-and-neighbor.jpg
(Gb321, CC BY-SA 4.0) - 6800 and its neighbour at street level, confirmed to show
shopfronts and parapets. Commons has nothing for 6822 or 6806-6820, so those two
remain blocked on reference photography; recorded in TODO.

Re-applied the kit, repackaged, screenshots re-rendered and verified 4/4, packaged
QA all PASS.
Hero detail:
- Fluting: 20 grooves per column as thin shadow-tone cylinders set into the shaft
  (120 pieces) rather than boolean cuts - readable in silhouette and grazing light
  at a fraction of the cost.
- Motto band: real recess with a moulded surround 6 cm proud and the panel 12 cm
  behind, replacing the 8 cm dark stripe.
  Hero 148 parts/3044 tris -> 271/5492, still 14.50 m.

Placement bug this exposed (a real one, invisible in a render):
- ue_hero_facade_import.py carried its own hero position (-12024.5, -1450) from
  before the 0.1.0 frontage fix, so running the importer alone moved the hero 13 m
  east and onto the north side of the boulevard. Only symptom: the reference score
  fell 0.69 -> 0.56 and the 3x3 composition correlation flipped +0.54 -> -0.08.
- New Tools/ue_placement.py is the single source of truth (hero position, verified
  frontage spans, span validators). Both the importer and the demo builder use it;
  the import asserts the staged span and logs PLACEMENT ERROR otherwise.
- 11 new tests, including one that fails if the stale literal returns. 78 total.

Spawn-view score recovered to 0.72 (best yet); screenshots verified 4/4, packaged QA
all PASS.
Closes the 0.1.5 performance task. Same route and preset as 0.1.0 (packaged
Development, Epic scalability, TSR, VSync off, no frame generation, 2560x1440):

  0.1.0                2.42 ms (414 fps)  p99 3.01
  0.1.5 (kit)          2.76 ms (363 fps)  p99 3.64

The 625 kit actors and 8 generated textures cost about 12% of frame time and still
leave roughly six times the 60 fps floor. Frame-time series committed at
Docs/perf/0.1.5-kit-walk-frametimes.csv; comparison table added to
Docs/release-checks.md.

Records the measurement trap once more: runs showing ~105 fps were two overlapping
game instances, not the build - 363 fps reproduced twice on a clean single instance.
The blockout cleaning pass found the map was rendering with 604 of 620 mesh actors
unmaterialed - every kit piece and all theatre trim.

Cause: ensure_material() deleted and recreated each /Game/Hollywood/Site/M_* asset on
every run, so actors staged by other tools kept references to deleted assets and fell
back to the default material. Nothing errored; the map looked merely slightly flat.

- Materials are now updated IN PLACE (load, delete_all_material_expressions, rebuild
  the graph, recompile, save). Material.expressions is protected from Python, so the
  editing library's deleter is used.
- 53 duplicated kit actor labels fixed (both shop piers of a bay shared one name).
- New Tools/ue_audit_scene.py gates the scene: every mesh actor has a material, every
  verified frontage span is within +/-1 m (via ue_placement), no duplicate labels.
- render_screenshots.sh now runs the chain in the required order (demo map -> kit ->
  theatre -> audit -> cameras -> capture) and exits non-zero on an audit failure,
  because the demo builder rebuilds materials and later staging must follow it.

Scene audit: 0 failures. Packaged QA PASS. Spawn-view reference score 0.72.
- CHANGELOG: full 0.1.5 entry (scene audit, ue_placement, hero fluting, recessed
  motto band, kit layout fix, the 604-unmaterialed-actors fix, the 13 m hero
  placement drift, 363 fps re-measure, limitations).
- TODO: 0.1.5 section removed; blocked retail frontage carried into a new 0.1.6
  patch with the reason recorded, rather than letting the release wait on missing
  reference photography.
- ROADMAP status updated.
zwitschi merged commit 73aca9db80 into main 2026-11-08 22:56:08 +01:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: zwitschi/gig-line#32