feat(facades): 0.1.4 — module kit, textured materials, theatre trim #30

Merged
zwitschi merged 13 commits from facades-0.1.4 into main 2026-11-08 20:29:12 +01:00
Showing only changes of commit 567ca0e4c7 - Show all commits
+249
View File
@@ -0,0 +1,249 @@
# Review — `0.1.4` building façades
A consolidated review of the work on branch **`facades-0.1.4`**, written for the project owner. It states what changed, what is actually verified, what is only claimed, the defects found on the way, and the decisions that need a human.
Written 2026-11-09. Branch `facades-0.1.4`, 9 commits ahead of `main` (`ba68dcf`), tags `v0.1.0`–`v0.1.3` already released.
---
## 1. Executive summary
The façades went from **flat extruded boxes with flat colours** to **coursed, textured surfaces assembled from a reusable 16-piece module kit**, with a theatre that finally reads as the El Capitan Theatre (marquee, fascia, blade sign). All build and behaviour checks pass, and 67 tool tests pass.
**One thing this document cannot do:** tell you the buildings _look_ right. Every defect that survived more than one render in this cycle was a **placement** error that rendered convincingly — a 119 m frame shift, a kit 12 km off, a mirrored marquee. So the visual verdict below is explicitly marked as pending, and there is a toolchain section (§6) for turning it into measurements.
| Area | State |
| --- | --- |
| Build (editor + game targets, packaged) | **PASS** |
| Behaviour (`-qaselftest`: walk, reset, pause, transect, wall probe, façade probe) | **PASS** (see §7 on flakiness) |
| Tool tests | **67 pass** |
| Geometry placement (verified by coordinate probes) | **PASS** |
| Materials (graph + textures + per-slot) | **Implemented**, visual verdict pending |
| Module kit + assembly on 8 buildings | **Implemented**, visual verdict pending |
| Theatre marquee + blade sign | **Implemented**, visual verdict pending |
| Reference match | **NOT verified** — needs your eyes |
| Release | **Not tagged** — `v0.1.4` waits on review |
---
## 2. Where the project stands
| Version | Date | Content |
| --- | --- | --- |
| `v0.1.0` | 2026-11-08 | Walkable demo: hero façade, block frontage, first-person controls, ODbL HUD, all release checks |
| `v0.1.1` | 2026-11-08 | Collision patch: sidewalk edge flush, crossing ramps graded to 8 %, QA probes |
| `v0.1.2` | 2026-11-09 | Scale + façade: 3.1 m storey height (Mapbox-calibrated), colonnade 47.6 → 53.1 %, window plane, medallions, hero collision |
| `v0.1.3` | 2026-11-09 | Packaging/setup: importers clear the LFS read-only bit; docs match the pipeline |
| `0.1.4` | **in review** | Façade kit, materials, textures, theatre trim, visual loop |
---
## 3. What `0.1.4` changed
**89 files, +2 565 / −180.** Nine commits, in order:
1. **Materials** — masonry coursing and roughness variation in the material graphs; new `M_FacadeStoneShadow`, `M_FacadeGlass` (specular 0.62 ≈ IOR 1.5), `M_FacadeBanner`; **per-slot** material assignment (it was slot-0 only, which on the hero is the banner, so stone and glass were still flat).
2. **Texture maps** — `Tools/generate_facade_textures.py`: deterministic stdlib-only PNGs for ashlar, stucco, asphalt, concrete (base colour + roughness), sampled world-aligned with per-material tiling.
3. **Module kit** — `Tools/facade_kit_build.py`: 16 pieces at the measured **4.96 m bay** / **3.10 m storey**; `ue_import_facade_kit.py`, `ue_apply_facade_kit.py` assemble **625 pieces across 8 buildings**.
4. **Blockout frame correction** — the `0.1.2` regeneration had run without `--origin`; regenerated with the affine fit and re-verified every frontage span.
5. **Kit hygiene** — `SM_` asset naming, per-piece topology validation (all 16 manifold, 12 tris each), stale-asset removal.
6. **QA verdict** — `Docs/qa/0.1.4-facade-qa.md` with budgets, evidence, severities.
7. **Visual loop** — `Tools/visual_loop.py` + `visual_targets.json`: verify captures, measure against references, emit skill-addressed feedback. Iterations gitignored.
8. **Screenshots** — demo-map only; per-shot expectations and a verified column.
9. **Theatre trim** — marquee canopy, illuminated fascia, soffit, blade sign.
New tools: `facade_kit_build`, `generate_facade_textures`, `theatre_trim_build`, `ue_apply_facade_kit`, `ue_import_facade_kit`, `ue_stage_theatre_trim`, `visual_loop` (+ `visual_targets.json`). New test files: `test_visual_loop`, plus the earlier `test_fbx_export_preset`, `test_ue_common`, `test_mapbox_buildings`, `test_facade_detail_concepts`, `test_block_height_report`, `test_input_emulation`.
---
## 4. Evidence that holds up
### Behaviour — packaged build, `-qaselftest`
```
start XYZ=(-13336,-1150,600) → settled XYZ=(-13336,-1150,456)
walk moved 761 cm in 2 s PASS (Z 456 → 456)
reset returned 0 cm from spawn PASS
pause / unpause PASS
transect 1456 samples, 0 holes PASS
wall probe 0/35 blockers PASS
facade probe 0/9 missing walls PASS
RESULT PASS
```
### Placement — probed from the live map, not assumed
| Building | World X span | Verified against |
| --- | --- | --- |
| 6922 | −24276…−17700 | `Geo/verification/2026-11-06-el-capitan-block.md` |
| 6902 | −17749…−14591 | same |
| **6840 hero** | **−14644…−12028** | sits between 6902 and 6838 ✔ |
| 6838 theatre | −12082…−8210 | same |
| 6822 / 6806 / 6800 | −7854…−1437 | same |
| TCL / Tussaud's | −22889…−18442 / −27071…−22799 | same |
Blockout affine fit residual **0.0 cm**; kit pieces land inside their building's span (theatre pieces at −12082…−8694).
### Budgets
| Asset | Count | Cost |
| ------------- | --------------- | ------------ |
| Hero façade | 148 parts | 3 044 tris |
| Kit | 16 meshes | 12 tris each |
| Kit instances | 625 actors | ~7 500 tris |
| Theatre trim | 6 pieces | boxes |
| Textures | 8 × 512² | 196 KB total |
| Screenshots | 4 demo captures | 11 MB |
### Tests
67 tests across 7 files: input driver, height classification, Mapbox cross-check, concept generator, FBX preset, `ue_common`, visual loop (metrics on synthetic images, comparison scoring, feedback rules, target spec).
---
## 5. Defects found this cycle
Severity per the `qa-review` scale. **Every one of these rendered convincingly.**
| # | Sev | Defect | Root cause | Caught by |
| --- | --- | --- | --- | --- |
| 1 | Blocker | Frontage shifted ≈119 m X / 2.4 m Y; hero outside its gap | Blockout regenerated **without `--origin`** | Coordinate probe vs verification doc |
| 2 | Blocker | Kit pieces ~12 km from their buildings | Used mesh-local bbox; actors carry the offset | Coordinate probe |
| 3 | Blocker | Marquee on the **far side** of the boulevard | Blender +Y = Unreal −Y; used +10.01 not −10.01 | Coordinate probe |
| 4 | Major | Marquee canopy **5 cm above the pavement** | Absolute Z; pavement is 4.56 m above datum | QA wall probe |
| 5 | Major | Window bays invisible (inside the solid wall) | Piece modelled entirely at +Y | Edge-density flat in iteration metrics |
| 6 | Major | Kit had no materials — glazing wasn't glass | Grey `M_Kit_*` from FBX import, never overridden | QA review pass |
| 7 | Major | Windows floated 1.44 m in front of the wall | Wrong Y in the hero builder | Mesh measurement |
| 8 | Major | Medallions were pancakes on the coping | Built with the Z-axis cylinder helper | Mesh measurement |
| 9 | Major | Hero had **no usable collision** — walk through it | Complex-only; traces use simple | New façade probe |
| 10 | Minor | "No smoothing group information" on every import | `mesh_smooth_type="OFF"` in six exporters | Import logs |
| 11 | Minor | `save_map()` returning False silently | LFS `.umap` read-only; importers never chmod'd | Log read (`save_map: False`) |
| 12 | Minor | North-buildings import silently no-op (exit 255) | Missing `import sys` | Import result file |
| 13 | Minor | Kit folder held 24 assets (8 orphan materials) | No stale-asset sweep | Asset probe |
| 14 | Minor | Edge-density metric counted PIL's border ring | `FIND_EDGES` leaves a 128 ring | Unit test on a flat image |
| 15 | Minor | QA wall probe grazed the theatre wall | Scan row 1 cm from the building line | QA FAIL |
**Pattern worth keeping:** 3 of the 4 blockers were _coordinate_ errors caught by probes, not by pictures. The probes are now permanent (`-qaselftest`, kit/asset probes, `visual_loop --verify`).
---
## 6. The iteration toolchain (`Tools/visual_loop.py`)
```
reference photo ─┐
├─ compare ─► metrics + feedback ─► skill-named actions
demo capture ──┘ │
└─ next iteration (uncommitted)
```
- **`--verify`** — gates each capture against its expectation in `Tools/visual_targets.json`: missing, blank, tone-less or wrong-size shots fail.
- **`--compare`** — luminance, RMS contrast, **edge density**, palette distance and a 3×3 luma grid, scored 0–1.
- **`--iteration N`** — writes `Art/reference/iterations/N/{metrics.json,feedback.md}`. **Gitignored** until you confirm a shot; only confirmed shots reach `Screenshots/`.
- Feedback names the skill to consult (`blender-modeler`, `archviz`, `materials`, `lookdev`, `camera-cinematography`).
### Current measurements (iteration 4)
| Shot | Score | Δ luma | Contrast | Edges | Palette | Composition |
| --- | --: | --: | --: | --: | --: | --: |
| demo-spawn-view | **0.68** | −9 | ×0.85 | ×0.28 | 18.2 | r=0.54 |
| demo-street-level | 0.33 | +39 | ×0.70 | ×0.27 | 67.7 | r=−0.91 |
| demo-crossing | 0.42 | +32 | ×0.70 | ×0.34 | 22.2 | r=−0.33 |
| demo-north-buildings | 0.34 | −44 | ×0.77 | ×0.14 | 61.9 | r=−0.46 |
**Read this carefully.** Edge density is **0.14–0.34×** the reference everywhere — the render still carries a fraction of the relief in the photographs. The low scores are not a bug in the metric, but they are also **not a fair verdict on the buildings**: a wide block view compared with a tight façade crop will always report low edge similarity and poor composition correlation. Treat the scores as a _trend across iterations_, not as an absolute quality number.
---
## 7. Known limitations
1. **The QA self-test is time-based and can flake.** One run reported `walk 246 cm` and `pause FAIL`; an immediate re-run reported `761 cm` and `pause PASS` with identical content. Likely a starved process or a second instance. **Do not trust a single FAIL — re-run before acting**, and prefer two consecutive passes before calling a release good.
2. **The vision pre-check is unreliable on this content.** It has rejected shots you have since approved, and it disagreed with itself between runs. It stays advisory; it is never a gate.
3. **Kit pieces are boxes.** No reveals, sills or mouldings beyond the kit's bands. That is the intended fidelity for this patch — the kit is the vocabulary.
4. **`M_Kit_*` materials are deleted at import**; the Unreal material set is authoritative, the Blender materials carry no shading intent.
5. **Textures are generated, not authored.** They are deterministic and repeatable but generic: no decals, no signage text, no weathering maps.
6. **Cornice dentil spacing, abacus and plinth dimensions are assumptions** — the reference photography does not resolve them at our scale.
7. **`Screenshots/` holds 4 demo captures only** by design; the review staging map is no longer rendered for review.
---
## 8. What is _not_ verified (this is what needs you)
- **Does the block look like Hollywood Boulevard?** Compare `Screenshots/demo/*` against `Art/reference/hollywood/` and `Art/reference/el-capitan-*`. The metrics say the render is flatter and lighter than the photographs; only you can say whether it reads as the place.
- **Does the theatre read as the El Capitan?** Marquee proportions (12.0 × 2.6 m at a 4.6 m soffit) and blade sign (1.3 × 5.2 m) are assumptions from the reference set, not measurements.
- **Do the shopfronts and window rhythm look right at street level?**
- **Are the 4 shots in `Screenshots/README.md` approved?** Each row has a verified column for the mechanical check; approval is still yours.
---
## 9. Decisions taken
| Decision | Rationale |
| --- | --- |
| **Adopt Mapbox heights** (3.1 m per level + 3 overrides) | Second independent source; block now 66 matches, 0 disagreements |
| **Blosm `setupScript` style closed as superseded** | The module kit already gives every building an elevation; a second system would duplicate it with different assumptions |
| **Screenshots are demo-map only** | The review staging map is not what ships; a reviewer should see the game |
| **Iterations stay uncommitted** | Prevents unconfirmed geometry becoming "the record" |
| **Vision model advisory, never a gate** | Demonstrably unreliable on this content |
| **Textures generated, not committed** | Deterministic, reproducible, keeps the repo lean (196 KB regenerated on demand) |
---
## 10. Risks for the next cycle
1. **Placement drift is the dominant failure mode** (3 blockers in one patch). Any new asset should be probed for its world span before it reaches a render.
2. **The kit is not yet a _measured_ vocabulary.** Bay and storey are measured; the pilaster depth, sill projection and fascia height are assumptions. Scaling this to the remaining 7 buildings multiplies the assumption count.
3. **QA flakiness** (§7.1) could mask a real regression or manufacture a false one.
4. **Reference coverage is thin for the retail neighbours** — the 18-frame set is the El Capitan Theatre, not 6806/6822/6800.
5. **No performance measurement since `0.1.0`.** 625 kit actors and 8 textures have not been measured against the 60 fps budget (it had enormous headroom: 414 fps).
---
## 11. Recommended next steps
| # | Action | Why |
| --- | --- | --- |
| 1 | **Review `Screenshots/demo/*` and the 4 README rows** | The only unverified claim left |
| 2 | Decide whether to tag `v0.1.4` as-is (kit + materials + trim) and move the remaining geometry to `0.1.5`/`0.2.0` | The remaining items are scope, not fixes |
| 3 | Re-measure 1440p performance with the kit in place | 625 new actors, never measured |
| 4 | Retail neighbours from their own references (not the theatre's 18-frame set) | Prevents misattributed façades |
| 5 | Hero fluting + motto band as geometry | Last hero detail from `0.1.4` |
---
## 12. How to verify any of this yourself
```bash
# build + behaviour
cd /run/media/system/DATA/Engines/UE_5.8.4
Engine/Build/BatchFiles/Linux/Build.sh GigLine Linux Development \
-project=/run/media/system/DATA/Documents/06-games/gig-line/Game/GigLine/GigLine.uproject -WaitMutex
cd /run/media/system/DATA/Builds/GigLineQA/Linux
./GigLine.sh -windowed -ResX=1280 -ResY=720 -nosplash -qaselftest
grep "GigLine QA:" GigLine/Saved/Logs/GigLine.log
# tool tests
cd /run/media/system/DATA/Documents/06-games/gig-line
python3 -m unittest discover -s Tools/tests -t Tools -p 'test_*.py'
# screenshots + verification + measurements
Tools/render_screenshots.sh --verify
python3 Tools/visual_loop.py --compare --iteration 5
```
---
## 13. Appendix — tool inventory added this cycle
| Tool | Purpose |
| --- | --- |
| `facade_kit_build.py` | 16-piece module kit at the 4.96 m bay / 3.10 m storey, with topology validation and a part report |
| `ue_import_facade_kit.py` | Import to `/Game/Hollywood/Kit`, complex-as-simple collision, stale-asset sweep |
| `ue_apply_facade_kit.py` | Assemble the kit from each building's **world** bounds (625 pieces) |
| `generate_facade_textures.py` | Deterministic stdlib PNG generator for 4 surface sets |
| `theatre_trim_build.py` | Marquee, fascia, soffit, blade sign in world coordinates |
| `ue_stage_theatre_trim.py` | Import + stage the theatre trim with site materials |
| `visual_loop.py` / `visual_targets.json` | Verify captures, measure against references, emit skill-addressed feedback |
| `fbx_export_preset.py` | One export preset (was six copies); exports smoothing groups |
| `ue_common.py` | Clear the LFS read-only bit, make save failures loud |
Document written by the agent that did the work; it is deliberately blunt about what it could not check.