From 8851b2272e1d95aa57ef2134440bff43c973f435 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 16:46:30 +0100 Subject: [PATCH 1/9] fix(hero): lift the colonnade into the photographed 50-60% band Measured from the built mesh, the colonnade (columns + capitals) was 6.90 m of the 14.50 m elevation = 47.6 %: the entablature (3.40 m) and parapet (2.20 m) were using 5.60 m of the height. Thinned both to 3.00 m and 1.80 m in hero_facade_build.py, which lifts the colonnade to 7.70 m = 53.1 % - inside the 50-60 % band - with the envelope, motto band and medallions unchanged relative to the parapet. Hero rebuilt, re-imported (bounds 2604 x 1257 x 1450 cm), DemoMap rebuilt and the screenshot set re-rendered for review. Hero part report updated (columns 7.45 -> 8.25 m, entablature 3.40 -> 3.00 m). TODO: colonnade item closed. MEMORY records the FBX-vs-blend --out gotcha. --- Art/blender/hero/hero-facade-2026-11-07.blend | 4 ++-- Art/blender/hero/hero-facade-2026-11-07.json | 6 +++--- Game/GigLine/Content/Hollywood/DemoMap.umap | 2 +- .../Hollywood/ElCapitan/SM_HeroFacade.uasset | 4 ++-- .../Content/Hollywood/Site/M_Asphalt.uasset | 2 +- .../Content/Hollywood/Site/M_Concrete.uasset | 2 +- .../Hollywood/Site/M_FacadeStone.uasset | 2 +- .../Content/Hollywood/Site/M_Ground.uasset | 2 +- .../Hollywood/Site/M_KerbConcrete.uasset | 2 +- .../Content/Hollywood/Site/M_RoadPaint.uasset | 2 +- .../Content/Hollywood/Site/M_Stucco.uasset | 2 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 2 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- MEMORY.md | 18 ++++++++++++++++++ Screenshots/demo/review-demo-crossing.png | 4 ++-- .../demo/review-demo-north-buildings.png | 4 ++-- Screenshots/demo/review-demo-spawn-view.png | 4 ++-- Screenshots/demo/review-demo-street-level.png | 4 ++-- Screenshots/review-character.png | 4 ++-- Screenshots/review-ground-contact.png | 4 ++-- Screenshots/review-hero-facade-front.png | 4 ++-- Screenshots/review-hero-facade-oblique.png | 4 ++-- Screenshots/review-hero-portals.png | 4 ++-- Screenshots/review-npc-prefab.png | 4 ++-- Screenshots/review-overview.png | 4 ++-- Screenshots/review-player-placement.png | 4 ++-- Screenshots/review-scale-cubes.png | 4 ++-- Screenshots/review-shadow-compare.png | 4 ++-- TODO.md | 2 +- Tools/hero_facade_build.py | 8 ++++++-- 30 files changed, 70 insertions(+), 48 deletions(-) diff --git a/Art/blender/hero/hero-facade-2026-11-07.blend b/Art/blender/hero/hero-facade-2026-11-07.blend index 771f2b9..d09f55d 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.blend +++ b/Art/blender/hero/hero-facade-2026-11-07.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eba62eb9928ddc52ca895280168f9db2b1627a86b777e7d34175c49ab0f8034f -size 134203 +oid sha256:efd64c3868efddfc1b7dcf8a4a6e5a04b3e993f2742f6543cee68e6f4424b37f +size 134196 diff --git a/Art/blender/hero/hero-facade-2026-11-07.json b/Art/blender/hero/hero-facade-2026-11-07.json index b56c429..61169ff 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.json +++ b/Art/blender/hero/hero-facade-2026-11-07.json @@ -33,7 +33,7 @@ "dims_m": [ 0.95, 0.95, - 7.45 + 8.25 ], "evidence": "6 columns at 4.96 m centres (sibling notes x measured frontage)" }, @@ -60,7 +60,7 @@ "dims_m": [ 25.75, 1.5, - 3.4 + 3.0 ], "evidence": "assumption: entablature depth" }, @@ -69,7 +69,7 @@ "dims_m": [ 25.75, 1.2, - 2.2 + 1.8 ], "evidence": "assumption: parapet carries the motto band" }, diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 1822e71..cbb508e 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1d90ad9f218d9f1e29f78b600b19a42cc63e99753f74da94adcbec8e32c7d2f +oid sha256:16d5f4ee60297154f7e8125f6af47c30593961ae74462ebc4658b5b582df1e62 size 54508 diff --git a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset index d66dd6f..3240b57 100644 --- a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset +++ b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce9572e7344bb02ea61c2cc1a3b0966125c4a2a01d99acd012a658519df037ac -size 117081 +oid sha256:97c39662ded14a52d89e194c8e566d3bc2c1dbbdf89d739070c001f5c198c884 +size 117002 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index 9c2c426..dcf7844 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:188cf5bd1547c1bec869a194b79ba60548ac28e8414289bf9ea32b827f8eaecc +oid sha256:36ce1de545cf43c1ed8f19ed2dc3499fc8e1e2efca547e9fb971d3261db486d0 size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index 77fa9fc..cfdd0b2 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2313642be9c8dfcdd0439527b0b6f031887d61598f34511be1bd75182a9e855 +oid sha256:85c127d9f7e6a5a5a35dbd114fc9bb43620db84bd04650a0625d827d9499e484 size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index 7ba9917..5843bbe 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9385d8c1460375dd52aee6106a8802457c9c8e6bab63277229c0b094d2528a0 +oid sha256:3c0c6efaa601235b1719752a017cf062001eaf859249af3428e1a133efb21ab3 size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 5a7a5f0..a0c15ad 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22ef2675f4979297f9cf77f75ab1d94ddf064fa51d89af2006686b154802b8be +oid sha256:5e4eab78c46b101565591b6de1ca002fa0f3d63e64ca669c686d363f27518a45 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index 9bea9fe..580af1e 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff080d67c3e222453f879666e18a8ae74f1332f4f5f34159c58d61c06f09c1d5 +oid sha256:f0e2e423bc6324a211bd44976653b5129d11edda6d401588c0e42724b00f3614 size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index 7e06e1f..7cfa980 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ea19c5e9e2399de65497b46afc2b0d0453e85e230e719f4c3b134a3254e01b7 +oid sha256:5a256f29ac54323c4c5efe6fe80d3932381ad0c9d35115dd396d830d6fe9b17f size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index b586dd8..088c0d3 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01438cb78cf286d3a097fbcdb5406c8a37c872d9eafe5211d9755fb420371fad +oid sha256:2a3a70892aca278b313e2f90d53f404f05e8df2cdb40f7a1b81fd1513d216413 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index 5e04895..d628366 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d12a66df59e4d32dc19240ff025aa156569c6c6c7290f4a076211c1728044ad6 +oid sha256:a2f46d8184e1d8a9f580404be92d3721bb11098d2585548551a161f42532498e size 335528 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index ad8ae57..9df8f2b 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df31c3e291c05b111ad898efcf9aba0acf70866210aff82c981aa896c2adc63c +oid sha256:4fdb42865c9fd632ec28a96b3eebfd03fdab611c57512a54323fb93beb7ded8a size 28706 diff --git a/MEMORY.md b/MEMORY.md index a890e0f..8e5c2b3 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -400,3 +400,21 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. height error; the table is the tagged height, the mesh is storey + roof. - Gotcha: regenerating the blockout is safe for names, but any future change to the import must re-verify the 6/6 frontage export and the `element.*` mapping. + +## 2026-11-09 — hero colonnade proportion fixed (47.6 % → 53.1 %) + +- The hero's colonnade (columns 2.00–7.95 + capitals 7.95–8.90) was 6.90 m of the + 14.50 m elevation = **47.6 %**, below the photographed 50–60 %, because the + entablature (3.40 m) and parapet (2.20 m) used 5.60 m of the height. +- Thinned ENTABLATURE_H 3.40 → 3.00 and PARAPET_H 2.20 → 1.80 in + `Tools/hero_facade_build.py`; the colonnade grows to **7.70 m = 53.1 %** while the + envelope, motto band and medallions keep their relationships (all positioned + relative to those two constants). +- **Gotcha (cost a bad build):** `hero_facade_build.py` takes `--out` for the + **FBX** and `--save-blend` for the `.blend`. Passing `--out .blend` writes + FBX bytes over the blend and Blender then reports "File format is not supported". + Correct invocation: `--out /tmp/gigline/hero-facade.fbx --save-blend Art/...blend + --report Art/...json`. +- Rebuilt hero → re-imported (`SM_HeroFacade`, bounds 2604 × 1257 × 1450 cm) → + DemoMap rebuilt → screenshots re-rendered. Note `ue_hero_facade_import.py` saves + the map, so `chmod u+w` the `.umap` first or the import silently does not persist. diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index d207434..ea864e4 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed6b566b47e6332461dea5f1c786e458ae6a7a83e9f77fde960ab516be860707 -size 2625467 +oid sha256:da23e9657ac70d9b07b992d80ba1125ea1c37e4341e972a85cc125e2d0fc55d2 +size 2666878 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index d2a2eef..240a795 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a668af9982a5237f8b1212a42e75762522e5fda2cbd81c3dda41e6e1f2c08dbf -size 2472516 +oid sha256:b22b2d96e338664960053deef545e7f6c6484b268f7132072f97853066a45960 +size 2503609 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 59d4675..73bdea9 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3dea97c4a2b1e5055585f5d185ad3726a45009c98bb17c04a11734222015570 -size 2583278 +oid sha256:4769b99211089f11b7c6a2d69af8169038a62fd76eb218c0092782af6c600202 +size 2607575 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index fc6b0da..995d628 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30d2432eb2dbe611761ecf756c819fc03d56a9b672dd2ef937cc395b0446688f -size 2406661 +oid sha256:bf2ceebd60382c94a0b66fae1da93554023172ff88c6daa65bacc09059776dd5 +size 2442205 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index ed80072..09d2570 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b94be4fb2264ba612a3ff697e3fab6b328965eff86478a352c043890b226197 -size 2755469 +oid sha256:284c94b4932504c8b6dad7faaa8ed4e83293ec90aa572a08810f374c6ac3f776 +size 2536672 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 86fb8b0..a3dafeb 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:784d70d8ecdf66e2ec254510b2ea44dee2e738b2788e3c0310d2bc95a2413a59 -size 1805142 +oid sha256:454940ab353bd4cf9cc6d15c19581def8cba85551f17f917d835656073fed2d5 +size 1756594 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index ac578a8..102caf9 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d20f402ee2f0adbb5ddfff3532f9f2fd3b8a4101bd235a1211a9ad7772761d4 -size 1744237 +oid sha256:f193afde4e5becdfa0d8c22b9f2b3d5808492a8e84d04645d2593509e5eec64e +size 1548752 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index 904f152..dd7405f 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08f49feb0e7fa2bb39dda28aef933173fa4b89a5e8280d5353ed7d26a7410d90 -size 1402754 +oid sha256:bfeabf9ecd2ecba7e5fa9906a5e4753aa369cfe8338dc644661cd3084a62b6ef +size 1305603 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 21fac11..5b9857d 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b87d31270f6233b9bd345041e9a63be274a2843405139d5c6e629c429aca0529 -size 1364154 +oid sha256:2fcae54c0d176c60251718e28a05bb3e605eafc084698256995d08a65498fdc3 +size 1321708 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index d120ac8..50a8a9f 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:204920e7d8ab884d47848fa6a811ca7cc17f9cdc6a84cdccc6d3889cd773ab80 -size 1797175 +oid sha256:fd2016a49dc035945fa350b51fbcba3ddce3f95d723bebe2c42702d3ee3f377f +size 1735461 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index c494541..18e53e7 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aec644b1926c6bf7333de00c22e34d44e18e2dbcdc061b7be9c006dbdb160c60 -size 2416002 +oid sha256:ddaadc5a847a281a95ef99c31d6aa60a35c62b5b0e794cd6ef04d8dbbbc351c6 +size 2589945 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index 84ed21d..aaee19a 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85c4cb94ddcdf1fa214b267e4b3e11add02af22224e4a3b7ea5a918725b72963 -size 2205324 +oid sha256:65dceafdc4a716eb1900e1b7f08e9cb48dd0619ea8245b17c159e27aaf60cf89 +size 2025575 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 09645eb..38c14ef 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc335d11b76a319eac8528f5fe0a5ac03945e69739f49f9339f5572a22aa3faf -size 2134125 +oid sha256:09584a3e4c2ee4931671f9e71c0991feea9acbc7dfed7b8f2cdaa2169e6e008e +size 1943609 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index 3ecc241..08c6c6e 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81e9ffc8ff8f124f9b5f9c57595e399444adca2614fb424a48f51fdbca9bc741 -size 1853523 +oid sha256:bdc59ffde57459024b5af56d66e489e9522908662e63984b4c27ac6b960392de +size 1715031 diff --git a/TODO.md b/TODO.md index 64a68eb..c00ee99 100644 --- a/TODO.md +++ b/TODO.md @@ -18,7 +18,7 @@ Suggested blender skills: **references** (reference-image-match and visual-match - [x] Correct building scale and street proportions flagged against references. **Mapbox adopted 2026-11-09.** `Geo/tools/mapbox_buildings.py` merges our OSM heights with Mapbox's building data for the same footprints; after adopting its two findings the cross-check reports **66 match, 6 non-building, 0 disagreements**. Adopted: **`LEVEL_HEIGHT` 3.2 → 3.1 m** (`block_height_report.py`, and the Blosm `--level-height` default), plus explicit `HEIGHT_OVERRIDES` (3.0 m) for the three rear `building=yes`/`apartments` structures Mapbox gives as single-storey. Blockout regenerated, frontage re-exported/re-imported, DemoMap rebuilt; packaged `-qaselftest` all PASS. Measured effect: 6922 42.1 → 39.1 m, El Capitan Theatre 20.0 → 20.5 m (both now ~1.9 m above their table height = roof mass). - [ ] Refine hero façade details where reference photography shows discrepancies. - [x] **Replace the placeholder heights.** **Resolved 2026-11-08 — they were never unknown buildings.** The three "guessed" ways are not building volumes at all: `1360755125` and `1360755126` are `building=roof` at `layer=1` (elevated canopies) and `1417995292` is `amenity=shelter` / `shelter_type=public_transport` (a transit shelter). The report defaulted them to "2 levels × 3.2 m" and produced the bogus 6.4 m. `Geo/tools/block_height_report.py` now classifies roof/shelter explicitly and reports **0 guessed heights**: all 15 block volumes have a real `height` tag, a `building:levels` derivation, or are correctly excluded as non-building volumes. No photograph measurement was needed, and no frontage building was affected. -- [ ] Resolve the remaining unknown on the hero: the colonnade currently occupies about 45 % of the height against roughly 50–60 % in the photographs. Fix the vertical proportions. **Measured 2026-11-08 from the built mesh** (`Art/blender/hero/hero-facade-2026-11-07.blend`): envelope 0–14.50 m; stylobate 0–2.00; columns 2.00–7.95; capitals 7.95–8.90; entablature 8.90–12.30; parapet 12.30–14.50. So the colonnade (columns + capitals) is **6.90 m = 47.6 %** of the height — inside the range only at the low end. Bringing it to ~55 % needs ~+1.0 m of colonnade taken from the attic/parapet zone, which also carries the motto band and medallions, so it is a **design decision that needs the reference photographs side by side** — left open for owner visual review rather than guessed. +- [x] Resolve the remaining unknown on the hero: the colonnade currently occupies about 45 % of the height against roughly 50–60 % in the photographs. Fix the vertical proportions. **Fixed 2026-11-09.** Measured baseline: colonnade (columns + capitals) 6.90 m of the 14.50 m envelope = **47.6 %**, because the entablature (3.40 m) and parapet (2.20 m) left only 7.90 m for the order. Thinned both to **3.00 m** and **1.80 m** (`Tools/hero_facade_build.py`), which lifts the colonnade to **7.70 m = 53.1 %** — inside the photographed 50–60 % band, with the 14.50 m envelope, the motto band and the medallions unchanged in position relative to the parapet. Hero rebuilt, re-imported (bounds 2604 × 1257 × 1450 cm) and re-rendered. - [ ] Tag `v0.1.2` and write `CHANGELOG.md` entry; then remove this section. ## 0.1.3 — Packaging and setup fixes (patch) diff --git a/Tools/hero_facade_build.py b/Tools/hero_facade_build.py index 4003a98..c3c670f 100644 --- a/Tools/hero_facade_build.py +++ b/Tools/hero_facade_build.py @@ -50,8 +50,12 @@ FRONTAGE_Y = 0.0 # front plane sits at the building line of the block fra PEDESTAL_H = 1.45 # column pedestal top; entrance platform sits on it COLUMN_D = 0.95 # Ionic shaft diameter at the base CAPITAL_H = 0.95 -ENTABLATURE_H = 3.40 # band between the capitals and the motto panel -PARAPET_H = 2.20 # motto panel and cornice above the entablature +ENTABLATURE_H = 3.00 # band between the capitals and the motto panel + # 3.40 -> 3.00 on 2026-11-09: the photographs put the + # colonnade at 50-60 % of the 14.5 m elevation, and our + # 3.40/2.20 entablature+parapet left it at 47.6 %. Thinning + # both lifts the colonnade to 7.70 m = 53.1 %, inside the band. +PARAPET_H = 1.80 # motto panel and cornice above the entablature (see above) PORTAL_W = 3.10 # each of the three door openings PORTAL_H = 3.40 STEP_TREAD = 0.34 -- 2.47.3 From abace2ad055038cbbbedcc0c482c43b9761a1c11 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 17:27:27 +0100 Subject: [PATCH 2/9] feat(tools): AI detail plates from the reference photography; fix floating windows Adds Tools/facade_detail_concepts.py: generates architectural detail plates from a local reference photograph through OpenRouter's image models. Spec-driven (eight studies: door recess, entrance, column order, entablature/cornice, parapet/motto, window rhythm, street wall, banner), never overwrites (writes -vN), writes a .refgen.json sidecar (model, prompt, source photo, SHA-256) per image, and keeps all output under the gitignored Art/reference/facade-details/ - local only, never shipped. Stdlib only; http 429/5xx back-off; refuses to write a sidecar containing the token. 11 tests cover the study table, prompt assembly, next-free naming, data-URL decoding (both response shapes plus a refusal) and the local-only rule. Measurement pass on the plates: the hero window panes were at Y -1.98, i.e. 1.44 m in FRONT of the wall (Y -0.50) and ahead of the column line, so the glazing floated in the colonnade instead of reading as openings behind it. Moved to Y -0.56; hero rebuilt, re-imported, DemoMap rebuilt, full screenshot set re-rendered. Docs: Tools/README row, Screenshots README known-issues entry now records the fix. --- Art/blender/hero/hero-facade-2026-11-07.blend | 4 +- Game/GigLine/Content/Hollywood/DemoMap.umap | 2 +- .../Hollywood/ElCapitan/SM_HeroFacade.uasset | 4 +- .../Content/Hollywood/Site/M_Asphalt.uasset | 2 +- .../Content/Hollywood/Site/M_Concrete.uasset | 2 +- .../Hollywood/Site/M_FacadeStone.uasset | 2 +- .../Content/Hollywood/Site/M_Ground.uasset | 2 +- .../Hollywood/Site/M_KerbConcrete.uasset | 2 +- .../Content/Hollywood/Site/M_RoadPaint.uasset | 2 +- .../Content/Hollywood/Site/M_Stucco.uasset | 2 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 2 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- Screenshots/README.md | 3 +- Screenshots/demo/review-demo-crossing.png | 4 +- .../demo/review-demo-north-buildings.png | 4 +- Screenshots/demo/review-demo-spawn-view.png | 4 +- Screenshots/demo/review-demo-street-level.png | 4 +- Screenshots/review-character.png | 4 +- Screenshots/review-ground-contact.png | 4 +- Screenshots/review-hero-facade-front.png | 4 +- Screenshots/review-hero-facade-oblique.png | 4 +- Screenshots/review-hero-portals.png | 4 +- Screenshots/review-npc-prefab.png | 4 +- Screenshots/review-overview.png | 4 +- Screenshots/review-player-placement.png | 4 +- Screenshots/review-scale-cubes.png | 4 +- Screenshots/review-shadow-compare.png | 4 +- TODO.md | 2 +- Tools/README.md | 7 + Tools/facade_detail_concepts.py | 319 ++++++++++++++++++ Tools/hero_facade_build.py | 9 +- Tools/tests/test_facade_detail_concepts.py | 108 ++++++ 32 files changed, 487 insertions(+), 45 deletions(-) create mode 100644 Tools/facade_detail_concepts.py create mode 100644 Tools/tests/test_facade_detail_concepts.py diff --git a/Art/blender/hero/hero-facade-2026-11-07.blend b/Art/blender/hero/hero-facade-2026-11-07.blend index d09f55d..b88fd9b 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.blend +++ b/Art/blender/hero/hero-facade-2026-11-07.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efd64c3868efddfc1b7dcf8a4a6e5a04b3e993f2742f6543cee68e6f4424b37f -size 134196 +oid sha256:fe3a08cdf4ca196cd59fe52a7ba9edc140d0e11391dff970a93b883410b415a6 +size 134198 diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index cbb508e..56e6a99 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16d5f4ee60297154f7e8125f6af47c30593961ae74462ebc4658b5b582df1e62 +oid sha256:58339d354b5afeb8fddefdd2c463eda6d45cd5379ff80f8eb644a33c17599e3f size 54508 diff --git a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset index 3240b57..01f38d5 100644 --- a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset +++ b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97c39662ded14a52d89e194c8e566d3bc2c1dbbdf89d739070c001f5c198c884 -size 117002 +oid sha256:d3831a508ced9e573ab9db083672c1e16ba46f9f052ceb53665853f6198cc64b +size 117009 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index dcf7844..3899d1d 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36ce1de545cf43c1ed8f19ed2dc3499fc8e1e2efca547e9fb971d3261db486d0 +oid sha256:9525922eca9e99a50f97b0c44ede1b908e1d97fa8c0fbddf928ffa3fbc960c4b size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index cfdd0b2..5eab245 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85c127d9f7e6a5a5a35dbd114fc9bb43620db84bd04650a0625d827d9499e484 +oid sha256:906f52dcc949ac7dfeae7f60e250434af3d2e57d5d6e23a6deb565d3a138a39e size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index 5843bbe..ccecc9c 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c0c6efaa601235b1719752a017cf062001eaf859249af3428e1a133efb21ab3 +oid sha256:0323b2b2ee3023cadb09d8bc3f3a7c024ef2c2a0de53db8442070ef404a3b434 size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index a0c15ad..ea094ac 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e4eab78c46b101565591b6de1ca002fa0f3d63e64ca669c686d363f27518a45 +oid sha256:ebc3cbc40452389f0ae078dad79949653612c5c300fa5644807344dbb6aa97bb size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index 580af1e..00b980c 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0e2e423bc6324a211bd44976653b5129d11edda6d401588c0e42724b00f3614 +oid sha256:4f311cc222d4f215b3163841c111e526b09874d5ee8845ea5720e4556babd387 size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index 7cfa980..dba2aed 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a256f29ac54323c4c5efe6fe80d3932381ad0c9d35115dd396d830d6fe9b17f +oid sha256:4b4e25f5d61346ae996c1ad43c889fdabbe0576f306fba83b67f2918e778d675 size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index 088c0d3..c4b8fa9 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a3a70892aca278b313e2f90d53f404f05e8df2cdb40f7a1b81fd1513d216413 +oid sha256:720902f570fb87a38e3847d2645b057e71f8971a82000ca39af3652349349ce7 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index d628366..c175268 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2f46d8184e1d8a9f580404be92d3721bb11098d2585548551a161f42532498e +oid sha256:17d9fe3b1ce4589e610f0027c91f361eb73b09c7442b5c4a763b5419aba47040 size 335528 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index 9df8f2b..ec501e9 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fdb42865c9fd632ec28a96b3eebfd03fdab611c57512a54323fb93beb7ded8a +oid sha256:e94a0743d2dfd379b4011e69d79f0fe156a8d2158727b8fc5f3d1395f854e2aa size 28706 diff --git a/Screenshots/README.md b/Screenshots/README.md index 2a5f6fc..73e033f 100644 --- a/Screenshots/README.md +++ b/Screenshots/README.md @@ -58,5 +58,6 @@ Rebuilds `Game/GigLine/Content/Test/ReviewMap.umap` from current content, runs t - Floor speckle from the `Constant3Vector` wiring in `Tools/ue_build_review_map.py`. - Hero façade renders pale — Blender flat colours with no normal/roughness, so it reads as untextured stone (the `0.1.4` façade patch, not a lighting bug). -- Banners and window panels float detached from the colonnade wall (next modelling pass). +- Banners sit on the column line rather than the wall (acceptable: they hang on the columns in the photographs). +- ~~Banners and window panels float detached from the colonnade wall~~ — **window panes fixed 2026-11-09**: they sat at Y −1.98, 1.44 m in *front* of the wall and ahead of the column line; they now sit on the wall plane at Y −0.56, behind the columns, and read as dark openings (see `review-hero-facade-front`). - Between kerb and building line, the walkable surface is the terrain mesh, not a modelled pavement. diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index ea864e4..dd16d77 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da23e9657ac70d9b07b992d80ba1125ea1c37e4341e972a85cc125e2d0fc55d2 -size 2666878 +oid sha256:33e7e224081d4b0a44752a42e93b944f1f41172c85978c8f4f9a20169c4b7502 +size 2666539 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index 240a795..deb86a3 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b22b2d96e338664960053deef545e7f6c6484b268f7132072f97853066a45960 -size 2503609 +oid sha256:cd7a116c05c31584187d6dd05fb94f69d6ff540737cb212b8a860931f360666b +size 2506551 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 73bdea9..880f199 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4769b99211089f11b7c6a2d69af8169038a62fd76eb218c0092782af6c600202 -size 2607575 +oid sha256:f1cbf3b285c04f9c851ede43f5aa97585facf966f5e7e8cdb20d7ef074f71193 +size 2619015 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 995d628..9f8899d 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf2ceebd60382c94a0b66fae1da93554023172ff88c6daa65bacc09059776dd5 -size 2442205 +oid sha256:bba4637c4fb2a60f629def61edc61d231389576a77bd4a02dbe569ceb13ae036 +size 2441194 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index 09d2570..6035512 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:284c94b4932504c8b6dad7faaa8ed4e83293ec90aa572a08810f374c6ac3f776 -size 2536672 +oid sha256:874d3a55f9f369c07bb266619550a0ddb6608e60bca03b61e92c5c84172899a2 +size 2533314 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index a3dafeb..36fd3d6 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:454940ab353bd4cf9cc6d15c19581def8cba85551f17f917d835656073fed2d5 -size 1756594 +oid sha256:5e03e459828414a20d22cf82bab6ff2101e2d252e05892d6353de72c0bfcafb7 +size 1751574 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index 102caf9..eca1075 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f193afde4e5becdfa0d8c22b9f2b3d5808492a8e84d04645d2593509e5eec64e -size 1548752 +oid sha256:8d43265c7371293f51d3097ac0b64231bb744a8968c34fea6059bda4bf338a94 +size 1552429 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index dd7405f..0519f5e 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bfeabf9ecd2ecba7e5fa9906a5e4753aa369cfe8338dc644661cd3084a62b6ef -size 1305603 +oid sha256:46c18a8e4a04e87f9c5bfe0d485e012ca320ea258d01d2bbf04fb81e8366cdd0 +size 1306107 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 5b9857d..2443cb5 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2fcae54c0d176c60251718e28a05bb3e605eafc084698256995d08a65498fdc3 -size 1321708 +oid sha256:fa0eedb216ff40fd04886f3848de4ed614e57b2cdc376a2881a3869c8b2027f9 +size 1326324 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index 50a8a9f..ae36cee 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd2016a49dc035945fa350b51fbcba3ddce3f95d723bebe2c42702d3ee3f377f -size 1735461 +oid sha256:77b89f510d5bdbc5a894a65e7244713d055b9e0c5ef365a52c31f5e8886946cc +size 1732427 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index 18e53e7..1b8ef3b 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddaadc5a847a281a95ef99c31d6aa60a35c62b5b0e794cd6ef04d8dbbbc351c6 -size 2589945 +oid sha256:5bfd21b670e27b2d9642083bc25460023d8acf4d788981b750ad7cc7d74d13ed +size 2482062 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index aaee19a..b44ffde 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65dceafdc4a716eb1900e1b7f08e9cb48dd0619ea8245b17c159e27aaf60cf89 -size 2025575 +oid sha256:11933b0e8fe721cd9f785f15d99438dd8c632e814a7fe86b053e855b909673d4 +size 2022340 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 38c14ef..3bb9a2a 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09584a3e4c2ee4931671f9e71c0991feea9acbc7dfed7b8f2cdaa2169e6e008e -size 1943609 +oid sha256:c54621f64bd890182f04755154156a74b735ad1a839b712c6c48bd9d60f1afe6 +size 1936777 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index 08c6c6e..c980a6b 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bdc59ffde57459024b5af56d66e489e9522908662e63984b4c27ac6b960392de -size 1715031 +oid sha256:01f3443e4163ec9e3e45f1612c8357f1b05dd6bb87043095b8aa9e8a1ceaddab +size 1721917 diff --git a/TODO.md b/TODO.md index c00ee99..c4e5599 100644 --- a/TODO.md +++ b/TODO.md @@ -16,7 +16,7 @@ Suggested blender skills: **references** (reference-image-match and visual-match ### Patch tasks - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `scale-facade-0.1.2`) - [x] Correct building scale and street proportions flagged against references. **Mapbox adopted 2026-11-09.** `Geo/tools/mapbox_buildings.py` merges our OSM heights with Mapbox's building data for the same footprints; after adopting its two findings the cross-check reports **66 match, 6 non-building, 0 disagreements**. Adopted: **`LEVEL_HEIGHT` 3.2 → 3.1 m** (`block_height_report.py`, and the Blosm `--level-height` default), plus explicit `HEIGHT_OVERRIDES` (3.0 m) for the three rear `building=yes`/`apartments` structures Mapbox gives as single-storey. Blockout regenerated, frontage re-exported/re-imported, DemoMap rebuilt; packaged `-qaselftest` all PASS. Measured effect: 6922 42.1 → 39.1 m, El Capitan Theatre 20.0 → 20.5 m (both now ~1.9 m above their table height = roof mass). -- [ ] Refine hero façade details where reference photography shows discrepancies. +- [ ] Refine hero façade details where reference photography shows discrepancies. **Started 2026-11-09:** built `Tools/facade_detail_concepts.py`, which generates architectural detail plates from the local reference photographs with an image model (`--list` free, `--all` generates, sidecars + `-vN` no-overwrite, output gitignored). Eight studies generated locally under `Art/reference/facade-details/`: door recess, entrance, column order, entablature/cornice, parapet/motto, window rhythm, street wall, banner. **First fix from the measurement pass:** window panes were 1.44 m in front of the wall (ahead of the columns) and now sit on the wall plane behind the colonnade. Remaining: use the plates to correct the capital/base profiles and the medallion/cornice detail. - [x] **Replace the placeholder heights.** **Resolved 2026-11-08 — they were never unknown buildings.** The three "guessed" ways are not building volumes at all: `1360755125` and `1360755126` are `building=roof` at `layer=1` (elevated canopies) and `1417995292` is `amenity=shelter` / `shelter_type=public_transport` (a transit shelter). The report defaulted them to "2 levels × 3.2 m" and produced the bogus 6.4 m. `Geo/tools/block_height_report.py` now classifies roof/shelter explicitly and reports **0 guessed heights**: all 15 block volumes have a real `height` tag, a `building:levels` derivation, or are correctly excluded as non-building volumes. No photograph measurement was needed, and no frontage building was affected. - [x] Resolve the remaining unknown on the hero: the colonnade currently occupies about 45 % of the height against roughly 50–60 % in the photographs. Fix the vertical proportions. **Fixed 2026-11-09.** Measured baseline: colonnade (columns + capitals) 6.90 m of the 14.50 m envelope = **47.6 %**, because the entablature (3.40 m) and parapet (2.20 m) left only 7.90 m for the order. Thinned both to **3.00 m** and **1.80 m** (`Tools/hero_facade_build.py`), which lifts the colonnade to **7.70 m = 53.1 %** — inside the photographed 50–60 % band, with the 14.50 m envelope, the motto band and the medallions unchanged in position relative to the parapet. Hero rebuilt, re-imported (bounds 2604 × 1257 × 1450 cm) and re-rendered. - [ ] Tag `v0.1.2` and write `CHANGELOG.md` entry; then remove this section. diff --git a/Tools/README.md b/Tools/README.md index d11e50f..fc8e18f 100644 --- a/Tools/README.md +++ b/Tools/README.md @@ -60,6 +60,13 @@ Geographic tools live in [`Geo/tools/`](../Geo/README.md) and the Blender-side b | `-qaselftest` phases | Walk, reset, pause/unpause, a 16-row seam transect (0 holes) and a ground-referenced wall probe (0/35), plus a frame-time capture writing `Saved/Profiling/perf-walk-frametimes.csv` and logging `GigLine PERF:`. | | `gigline.SetupLogs` cvar | Spawn/input setup logging, **off by default** (`DefaultEngine.ini [ConsoleVariables]`); enable at runtime with `gigline.SetupLogs 1`. | +## Reference and concept generation + +| Tool | Purpose | +| --- | --- | +| `facade_detail_concepts.py` | Generates architectural detail plates from a local reference photograph with an image model (OpenRouter). `--list` is free and shows which studies have their reference present; `--all`/`--only ` generates. Never overwrites (writes `-v2`, `-v3`), writes a `.refgen.json` sidecar per image (model, prompt, source photo, SHA-256), and puts everything under `Art/reference/facade-details/` — gitignored, local-only, never shipped. Costs money per image, so it is never automatic. | +| `judge_screenshot.py` | (see Visual review) | + ## Input injection | Tool | Purpose | diff --git a/Tools/facade_detail_concepts.py b/Tools/facade_detail_concepts.py new file mode 100644 index 0000000..a6e1c60 --- /dev/null +++ b/Tools/facade_detail_concepts.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python3 +"""Generate architectural detail studies from the local reference photography. + +Each study takes one photograph we already hold (`Art/reference/`, gitignored) as +the geometric anchor and asks an image model to re-stage it as a clean +architectural detail plate — no crowd, no staging, straight-on, evenly lit — so +the modelling pass has something to measure against instead of a tourist photo. + + python3 Tools/facade_detail_concepts.py --list + python3 Tools/facade_detail_concepts.py --only door-recess,parapet-motto + python3 Tools/facade_detail_concepts.py --all + python3 Tools/facade_detail_concepts.py --all --model google/gemini-2.5-flash-image + +Output: `Art/reference/facade-details/.png` plus a `.refgen.json` +sidecar recording the model, the source photograph, the prompt and the SHA-256 of +the result. `Art/reference/` is gitignored, so **neither the images nor the +sidecars are committed** — they are local working material. The study list and +the tool are the committed part. + +Design notes +------------ +* Standard library only: the OpenRouter chat-completions call is `urllib`, and + the returned `data:` URL is decoded with `base64` and written straight to disk. +* An existing output is never overwritten; `-v2`, `-v3` … are used instead, so + re-running after a prompt edit keeps both studies comparable. +* Generation costs money, so it is never automatic: `--list` is free, and every + generating run prints the model and the study count first. +* The token is read from `OPENROUTER_API_KEY` or the ignored `.env` and is never + written to a sidecar or a log line. +""" + +from __future__ import annotations + +import argparse +import base64 +import json +import os +import re +import sys +import time +import urllib.error +import urllib.request + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +REFERENCE_DIR = os.path.join(ROOT, "Art", "reference") +OUT_DIR = os.path.join(REFERENCE_DIR, "facade-details") +API_URL = "https://openrouter.ai/api/v1/chat/completions" +DEFAULT_MODEL = "google/gemini-2.5-flash-image" + +# The instruction appended to every study. Kept identical to the sibling +# project's convention so the two sets stay comparable: the photograph fixes the +# geometry, the prompt only restages light, weather, people and surface. +ANCHOR_SUFFIX = ( + "Use the attached reference photograph as the fixed source of geometry and " + "composition: keep the building's proportions, column rhythm, band heights, " + "signage placement and camera angle exactly as photographed. Only restage " + "lighting, weather, people and surface condition where the request asks for " + "it. Do not invent extra storeys, wings or ornaments that the photo does not " + "show." +) + +# name -> (reference photo relative to Art/reference/, what the study must show) +STUDIES: dict[str, tuple[str, str]] = { + "door-recess": ( + "el-capitan-entrance/01-hollywood-el-capitan-entrance-detail.jpg", + "A clean architectural detail plate of exactly the subject in the " + "reference photograph. Render it as an even-daylight stone study: crisp " + "surface carving, readable depth of every recess and moulding, no people, " + "no signage or banners in front of it, no shop clutter, straight-on to the " + "subject.", + ), + "entrance-wide": ( + "el-capitan-entrance/01-hollywood-el-capitan-entrance.jpg", + "A straight-on architectural study of the street entrance in the " + "reference photograph, the portal group centred and filling the frame, " + "threshold and pavement readable, no pedestrians or vehicles, even " + "overcast daylight, stone surface legible.", + ), + "column-order": ( + "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", + "A close architectural study of the column order visible in the " + "reference photograph: the base, shaft and capital read clearly, " + "neighbouring columns framing it. Straight-on, evenly lit, stone surface " + "and carving legible, no people or banners.", + ), + "entablature-cornice": ( + "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", + "An architectural detail study of the horizontal stone bands above the " + "columns in the reference photograph: every band edge and the projecting " + "cornice with its shadow line. The layered depth of the stone must be " + "readable, flat even light, no people.", + ), + "parapet-motto": ( + "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", + "An architectural study of the parapet above the colonnade in the " + "reference photograph: the inset panel, any round medallions beside it " + "and the coping at the top. Lettering on the panel is blocked out as " + "unreadable texture. Flat even light, no people.", + ), + "window-rhythm": ( + "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", + "An architectural study of the wall surface behind and between the " + "columns in the reference photograph: the opening or window rhythm and " + "the reveal depth. Straight-on, no people, no banners covering the wall.", + ), + "street-wall": ( + "hollywood/el-capitan-theatre-blade-sign-day-wikimedia-2008-10.jpg", + "A clean street-wall study from the opposite pavement, as framed in the " + "reference photograph: the building line, the parapet heights of the " + "neighbouring buildings, the shopfront line and the pavement depth. No " + "crowd, even daylight.", + ), + "banner-detail": ( + "el-capitan-premiere/02-premiere-of-spielberg-s-west-side-story---el-capitan---holly.jpg", + "An architectural study of the vertical banner in the reference " + "photograph: how it is fixed, its proportions against the column behind " + "it, and how it sits against the stone. Daylight, no crowd.", + ), +} + + +def load_token() -> str: + token = os.environ.get("OPENROUTER_API_KEY") + if token: + return token.strip() + env_path = os.path.join(ROOT, ".env") + if os.path.exists(env_path): + with open(env_path, encoding="utf-8") as handle: + for line in handle: + line = line.strip() + if line.startswith("OPENROUTER_API_KEY="): + return line.split("=", 1)[1].strip().strip('"').strip("'") + raise SystemExit("no OpenRouter key: set OPENROUTER_API_KEY or add it to .env") + + +def build_prompt(study: str) -> str: + """The full prompt for a study: its request plus the fixed anchor suffix.""" + if study not in STUDIES: + raise KeyError(f"unknown study {study!r}; known: {sorted(STUDIES)}") + return f"{STUDIES[study][1]}\n\n{ANCHOR_SUFFIX}" + + +def reference_path(study: str) -> str: + return os.path.join(REFERENCE_DIR, STUDIES[study][0]) + + +def missing_references() -> list[str]: + """Studies whose source photograph is not present locally.""" + return [name for name in STUDIES if not os.path.isfile(reference_path(name))] + + +def next_free_path(study: str, directory: str = OUT_DIR) -> str: + """`.png`, or `-v2.png`, `-v3` … if the name is taken.""" + base = os.path.join(directory, f"{study}.png") + if not os.path.exists(base): + return base + index = 2 + while True: + candidate = os.path.join(directory, f"{study}-v{index}.png") + if not os.path.exists(candidate): + return candidate + index += 1 + + +def data_url(path: str) -> str: + suffix = os.path.splitext(path)[1].lower() + mime = {".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png"}.get(suffix) + if not mime: + raise SystemExit(f"unsupported reference type: {path}") + with open(path, "rb") as handle: + return f"data:{mime};base64,{base64.b64encode(handle.read()).decode('ascii')}" + + +def decode_image(payload: dict) -> bytes: + """Extract the returned image bytes from a chat-completions payload.""" + message = (payload.get("choices") or [{}])[0].get("message", {}) + urls = [item.get("image_url", {}).get("url", "") + for item in (message.get("images") or []) if isinstance(item, dict)] + if not urls: + match = re.search(r"data:image/[a-z]+;base64,[A-Za-z0-9+/=]+", + str(message.get("content") or "")) + if match: + urls.append(match.group(0)) + if not urls or not urls[0]: + raise SystemExit(f"model returned no image data: {json.dumps(payload)[:400]}") + url = urls[0] + if url.startswith("data:"): + return base64.b64decode(url.split(",", 1)[1]) + with urllib.request.urlopen(urllib.request.Request(url), timeout=120) as response: + return response.read() + + +def generate(study: str, token: str, model: str, force: bool = False) -> str: + """Generate one study; returns the written path. Never overwrites by default.""" + path = next_free_path(study) + if force and os.path.exists(os.path.join(OUT_DIR, f"{study}.png")): + path = os.path.join(OUT_DIR, f"{study}.png") + # Write to a temp name then replace, so a failed call cannot destroy the + # previous result. + target = path + ".new" + else: + target = path + + body = { + "model": model, + "messages": [{ + "role": "user", + "content": [ + {"type": "text", "text": build_prompt(study)}, + {"type": "image_url", "image_url": {"url": data_url(reference_path(study))}}, + ], + }], + } + request = urllib.request.Request( + API_URL, + data=json.dumps(body).encode("utf-8"), + headers={ + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + "HTTP-Referer": "https://git.allucanget.biz/zwitschi/gig-line", + "X-Title": "gig-line facade details", + }, + method="POST", + ) + + payload = None + for attempt in range(3): + try: + with urllib.request.urlopen(request, timeout=180) as response: + payload = json.load(response) + break + except urllib.error.HTTPError as exc: + if exc.code == 429 or exc.code >= 500: + wait = 5 * (attempt + 1) + sys.stderr.write(f" HTTP {exc.code}; retrying in {wait}s\n") + time.sleep(wait) + continue + detail = exc.read().decode("utf-8", "replace")[:300] + raise SystemExit(f"{study}: HTTP {exc.code} — {detail}") + except urllib.error.URLError as exc: + sys.stderr.write(f" network error ({exc.reason}); retrying\n") + time.sleep(5 * (attempt + 1)) + if payload is None: + raise SystemExit(f"{study}: no response after retries") + + image = decode_image(payload) + os.makedirs(OUT_DIR, exist_ok=True) + with open(target, "wb") as handle: + handle.write(image) + if target != path: + os.replace(target, path) + + import hashlib + sidecar = { + "study": study, + "generated": os.path.basename(path), + "generated_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), + "model": model, + "prompt": build_prompt(study), + "reference": { + "file": STUDIES[study][0], + "note": "local reference photography; Art/reference is gitignored and never shipped", + }, + "sha256": hashlib.sha256(image).hexdigest(), + "bytes": len(image), + "redistribution": "local development reference only; not committed, not shipped", + } + sidecar_path = os.path.splitext(path)[0] + ".refgen.json" + with open(sidecar_path, "w", encoding="utf-8") as handle: + json.dump(sidecar, handle, indent=2) + if token in json.dumps(sidecar): + raise SystemExit("refusing to write a sidecar containing the token") + return path + + +def main(argv=None) -> int: + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--list", action="store_true", help="list studies and exit (free)") + ap.add_argument("--all", action="store_true", help="generate every study") + ap.add_argument("--only", help="comma-separated study names") + ap.add_argument("--model", default=DEFAULT_MODEL) + ap.add_argument("--force", action="store_true", + help="replace the existing .png instead of writing a -vN") + args = ap.parse_args(argv) + + if args.list or not (args.all or args.only): + missing = set(missing_references()) + print(f"{len(STUDIES)} studies; model {args.model}") + for name, (ref, _prompt) in STUDIES.items(): + state = "MISSING reference" if name in missing else "ready" + print(f" {name:22} {state:18} <- {ref}") + if missing: + print(f"\n{len(missing)} study(ies) cannot run without their reference photograph.") + return 0 + + names = list(STUDIES) if args.all else [s.strip() for s in args.only.split(",") if s.strip()] + unknown = [n for n in names if n not in STUDIES] + if unknown: + raise SystemExit(f"unknown study(ies): {unknown}; known: {sorted(STUDIES)}") + blocked = [n for n in names if n in set(missing_references())] + if blocked: + raise SystemExit(f"missing reference photograph for: {blocked}") + token = load_token() + + print(f"generating {len(names)} study(ies) with {args.model} -> {OUT_DIR}") + for index, name in enumerate(names, 1): + print(f"[{index}/{len(names)}] {name}") + try: + path = generate(name, token, args.model, force=args.force) + except SystemExit as exc: + sys.stderr.write(f" FAILED: {exc}\n") + continue + print(f" wrote {os.path.relpath(path, ROOT)}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Tools/hero_facade_build.py b/Tools/hero_facade_build.py index c3c670f..c75015a 100644 --- a/Tools/hero_facade_build.py +++ b/Tools/hero_facade_build.py @@ -245,10 +245,17 @@ def build(): # --- windows ----------------------------------------------------------- # Two ranks of windows between the columns and behind the colonnade. + # Y must sit on the wall plane: the mass front face is at Y -0.50 and the + # columns stand proud to -1.02. These were at -1.98, i.e. 1.44 m in FRONT of + # the wall and ahead of the column line, so the glazing floated in the + # colonnade instead of reading as openings behind it (visible in the + # review-hero-facade-* shots). WINDOW_Y puts the pane 6 cm proud of the wall, + # safely behind the columns. + WINDOW_Y = -0.56 for rank, z in enumerate((4.4, 8.2), start=1): for i, x in enumerate(col_xs[:-1], start=1): wx = x + COLUMN_BAY / 2.0 - cube(f"Hero_Window_{rank}_{i}", wx, -1.98, z, 2.0, 0.08, 1.9, glass) + cube(f"Hero_Window_{rank}_{i}", wx, WINDOW_Y, z, 2.0, 0.08, 1.9, glass) note("Hero_Window_x10", (2.0, 0.08, 1.9), "photographs: window bands behind the colonnade") return parts, lines diff --git a/Tools/tests/test_facade_detail_concepts.py b/Tools/tests/test_facade_detail_concepts.py new file mode 100644 index 0000000..fae36ca --- /dev/null +++ b/Tools/tests/test_facade_detail_concepts.py @@ -0,0 +1,108 @@ +"""Tests for Tools/facade_detail_concepts.py — the pure parts. + +No network calls: the OpenRouter request and the image bytes are represented as +the small structures the API uses. Generation itself is manual and paid. +""" + +import base64 +import json +import os +import sys +import unittest + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +sys.path.insert(0, os.path.join(ROOT, "Tools")) + +import facade_detail_concepts as fc # noqa: E402 + + +class StudyTableTest(unittest.TestCase): + def test_every_study_has_a_reference_and_a_prompt(self): + self.assertTrue(fc.STUDIES) + for name, (ref, prompt) in fc.STUDIES.items(): + self.assertTrue(ref, f"{name} has no reference") + self.assertTrue(prompt.strip(), f"{name} has no prompt") + # References are relative to Art/reference and never escape it. + self.assertFalse(os.path.isabs(ref), f"{name} reference is absolute") + self.assertNotIn("..", ref, f"{name} reference escapes the directory") + + def test_prompt_always_carries_the_anchor_suffix(self): + for name in fc.STUDIES: + prompt = fc.build_prompt(name) + self.assertIn(fc.ANCHOR_SUFFIX, prompt) + self.assertIn(fc.STUDIES[name][1], prompt) + + def test_unknown_study_raises(self): + with self.assertRaises(KeyError): + fc.build_prompt("no-such-study") + + +class NextFreePathTest(unittest.TestCase): + def test_uses_the_plain_name_when_free(self): + import tempfile + with tempfile.TemporaryDirectory() as tmp: + self.assertEqual(os.path.basename(fc.next_free_path("x", tmp)), "x.png") + + def test_never_overwrites(self): + import tempfile + with tempfile.TemporaryDirectory() as tmp: + open(os.path.join(tmp, "x.png"), "w").close() + self.assertEqual(os.path.basename(fc.next_free_path("x", tmp)), "x-v2.png") + open(os.path.join(tmp, "x-v2.png"), "w").close() + self.assertEqual(os.path.basename(fc.next_free_path("x", tmp)), "x-v3.png") + + +class DecodeImageTest(unittest.TestCase): + PAYLOAD_BYTES = b"\x89PNG\r\n\x1a\nfake" + + def _data_url(self): + return "data:image/png;base64," + base64.b64encode(self.PAYLOAD_BYTES).decode() + + def test_reads_message_images(self): + payload = {"choices": [{"message": { + "images": [{"image_url": {"url": self._data_url()}}]}}]} + self.assertEqual(fc.decode_image(payload), self.PAYLOAD_BYTES) + + def test_reads_a_data_url_embedded_in_content(self): + payload = {"choices": [{"message": {"content": f"here: {self._data_url()}"}}]} + self.assertEqual(fc.decode_image(payload), self.PAYLOAD_BYTES) + + def test_refusal_raises_with_the_text(self): + payload = {"choices": [{"message": {"content": "I cannot do that."}}]} + with self.assertRaises(SystemExit): + fc.decode_image(payload) + + +class DataUrlTest(unittest.TestCase): + def test_encodes_a_jpeg(self): + import tempfile + with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as handle: + handle.write(b"jpegbytes") + path = handle.name + try: + url = fc.data_url(path) + self.assertTrue(url.startswith("data:image/jpeg;base64,")) + finally: + os.unlink(path) + + def test_rejects_an_unsupported_type(self): + import tempfile + with tempfile.NamedTemporaryFile(suffix=".gif", delete=False) as handle: + path = handle.name + try: + with self.assertRaises(SystemExit): + fc.data_url(path) + finally: + os.unlink(path) + + +class SidecarShapeTest(unittest.TestCase): + def test_studies_and_outputs_are_local_only(self): + # The output directory lives under the gitignored Art/reference tree, so + # neither the images nor the sidecars can be committed. + self.assertIn(os.path.join("Art", "reference"), fc.OUT_DIR) + self.assertIn("gitignored", fc.__doc__) + + +if __name__ == "__main__": + unittest.main() -- 2.47.3 From bbb373ec062587af4f0a97d787f2e5cf42711cb9 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 17:27:32 +0100 Subject: [PATCH 3/9] memory: detail-plate toolchain, prompt-refusal gotcha, floating-window fix --- MEMORY.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/MEMORY.md b/MEMORY.md index 8e5c2b3..adfec09 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -418,3 +418,25 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. - Rebuilt hero → re-imported (`SM_HeroFacade`, bounds 2604 × 1257 × 1450 cm) → DemoMap rebuilt → screenshots re-rendered. Note `ue_hero_facade_import.py` saves the map, so `chmod u+w` the `.umap` first or the import silently does not persist. + +## 2026-11-09 — AI detail plates from reference photos; floating windows fixed + +- `Tools/facade_detail_concepts.py` generates architectural detail plates from one + local reference photograph via OpenRouter image models (default + `google/gemini-2.5-flash-image`; the sibling project uses the same route in + `tools/generate_textures.py` — chat/completions with a text + image_url content + part, image returned as `message.images[].image_url.url`). Eight studies, + `--list` free, `--all` generates, `-vN` never overwrites, `.refgen.json` sidecar + per image, all output under gitignored `Art/reference/facade-details/`. +- **Prompt gotcha:** the model refuses when the prompt describes features the + reference photograph does not show ("the image you sent appears to be a + decorative architectural detail, not an entrance with steps"). Prompts must + describe the *reference subject* and only restage light/people/surface. +- **Output is real:** 1184×864 to 1344×768 PNGs, ~2 MB each. +- **Measured defect found and fixed:** hero window panes sat at Y −1.98 while the + mass front is Y −0.50 and the columns reach −1.02 — i.e. glazing floating 1.44 m + in front of the wall and ahead of the colonnade. Now `WINDOW_Y = −0.56` + (6 cm proud of the wall, behind the columns). Visible as dark openings in + `review-hero-facade-front`. +- Reminder: `.blend` is LFS read-only on checkout — `chmod u+w` or Blender fails + with "Cannot save blend file … not writable" (this bit again here). -- 2.47.3 From fe8a23e5eed246b30175ad62953aecb81431fd80 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 17:35:20 +0100 Subject: [PATCH 4/9] feat(tools): rephrase the concept studies as frontal building views Owner instruction: show the building, its entrance, the neighbouring buildings, front-on, and drop the close-up detail framing. - Studies replaced: door-recess / entrance-wide / column-order / entablature-cornice / parapet-motto / window-rhythm / street-wall / banner-detail -> building-front, building-entrance, building-with-neighbours, building-street-front, building-front-oblique, theatre-front-with-neighbours. - ANCHOR_SUFFIX now permits REFRAMING (step back, zoom out, widen the view) so the whole building can fit, while the architecture stays fixed; previously it pinned the camera angle to the reference, which forced cropped results. - Prompts state 'exterior' explicitly (the entrance study otherwise produced an interior) and require sky above the roofline and nothing cut off. Vision pre-check on the regenerated set: building-entrance and building-street-front read as full-elevation frontal plates; the studies anchored on the tightly cropped 2009 facade photo stay cropped, because the model will not invent the parapet and sky the photograph does not contain. That limitation is recorded in the study table comment - a full 6840 plate needs a full-elevation photograph we do not hold. Tests: 40 pass (study table assertions unchanged). --- TODO.md | 2 +- Tools/README.md | 2 +- Tools/facade_detail_concepts.py | 129 +++++++++++++++++--------------- 3 files changed, 71 insertions(+), 62 deletions(-) diff --git a/TODO.md b/TODO.md index c4e5599..9966973 100644 --- a/TODO.md +++ b/TODO.md @@ -16,7 +16,7 @@ Suggested blender skills: **references** (reference-image-match and visual-match ### Patch tasks - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `scale-facade-0.1.2`) - [x] Correct building scale and street proportions flagged against references. **Mapbox adopted 2026-11-09.** `Geo/tools/mapbox_buildings.py` merges our OSM heights with Mapbox's building data for the same footprints; after adopting its two findings the cross-check reports **66 match, 6 non-building, 0 disagreements**. Adopted: **`LEVEL_HEIGHT` 3.2 → 3.1 m** (`block_height_report.py`, and the Blosm `--level-height` default), plus explicit `HEIGHT_OVERRIDES` (3.0 m) for the three rear `building=yes`/`apartments` structures Mapbox gives as single-storey. Blockout regenerated, frontage re-exported/re-imported, DemoMap rebuilt; packaged `-qaselftest` all PASS. Measured effect: 6922 42.1 → 39.1 m, El Capitan Theatre 20.0 → 20.5 m (both now ~1.9 m above their table height = roof mass). -- [ ] Refine hero façade details where reference photography shows discrepancies. **Started 2026-11-09:** built `Tools/facade_detail_concepts.py`, which generates architectural detail plates from the local reference photographs with an image model (`--list` free, `--all` generates, sidecars + `-vN` no-overwrite, output gitignored). Eight studies generated locally under `Art/reference/facade-details/`: door recess, entrance, column order, entablature/cornice, parapet/motto, window rhythm, street wall, banner. **First fix from the measurement pass:** window panes were 1.44 m in front of the wall (ahead of the columns) and now sit on the wall plane behind the colonnade. Remaining: use the plates to correct the capital/base profiles and the medallion/cornice detail. +- [ ] Refine hero façade details where reference photography shows discrepancies. **Started 2026-11-09:** built `Tools/facade_detail_concepts.py`, which generates architectural detail plates from the local reference photographs with an image model (`--list` free, `--all` generates, sidecars + `-vN` no-overwrite, output gitignored). Six **frontal building** studies generated locally under `Art/reference/facade-details/` (whole elevation, entrance in its facade, building with neighbours, pavement view, three-quarter, theatre frontage) — rephrased on owner instruction to show the building/entrance/neighbours rather than close-up detail crops. **First fix from the measurement pass:** window panes were 1.44 m in front of the wall (ahead of the columns) and now sit on the wall plane behind the colonnade. Remaining: use the plates to correct the capital/base profiles and the medallion/cornice detail. - [x] **Replace the placeholder heights.** **Resolved 2026-11-08 — they were never unknown buildings.** The three "guessed" ways are not building volumes at all: `1360755125` and `1360755126` are `building=roof` at `layer=1` (elevated canopies) and `1417995292` is `amenity=shelter` / `shelter_type=public_transport` (a transit shelter). The report defaulted them to "2 levels × 3.2 m" and produced the bogus 6.4 m. `Geo/tools/block_height_report.py` now classifies roof/shelter explicitly and reports **0 guessed heights**: all 15 block volumes have a real `height` tag, a `building:levels` derivation, or are correctly excluded as non-building volumes. No photograph measurement was needed, and no frontage building was affected. - [x] Resolve the remaining unknown on the hero: the colonnade currently occupies about 45 % of the height against roughly 50–60 % in the photographs. Fix the vertical proportions. **Fixed 2026-11-09.** Measured baseline: colonnade (columns + capitals) 6.90 m of the 14.50 m envelope = **47.6 %**, because the entablature (3.40 m) and parapet (2.20 m) left only 7.90 m for the order. Thinned both to **3.00 m** and **1.80 m** (`Tools/hero_facade_build.py`), which lifts the colonnade to **7.70 m = 53.1 %** — inside the photographed 50–60 % band, with the 14.50 m envelope, the motto band and the medallions unchanged in position relative to the parapet. Hero rebuilt, re-imported (bounds 2604 × 1257 × 1450 cm) and re-rendered. - [ ] Tag `v0.1.2` and write `CHANGELOG.md` entry; then remove this section. diff --git a/Tools/README.md b/Tools/README.md index fc8e18f..414542f 100644 --- a/Tools/README.md +++ b/Tools/README.md @@ -64,7 +64,7 @@ Geographic tools live in [`Geo/tools/`](../Geo/README.md) and the Blender-side b | Tool | Purpose | | --- | --- | -| `facade_detail_concepts.py` | Generates architectural detail plates from a local reference photograph with an image model (OpenRouter). `--list` is free and shows which studies have their reference present; `--all`/`--only ` generates. Never overwrites (writes `-v2`, `-v3`), writes a `.refgen.json` sidecar per image (model, prompt, source photo, SHA-256), and puts everything under `Art/reference/facade-details/` — gitignored, local-only, never shipped. Costs money per image, so it is never automatic. | +| `facade_detail_concepts.py` | Generates **frontal building plates** (whole elevation, entrance in its facade, or building with neighbours) from a local reference photograph with an image model (OpenRouter); close-up detail crops are deliberately not requested because they cannot be measured for proportion. `--list` is free and shows which studies have their reference present; `--all`/`--only ` generates. Never overwrites (writes `-v2`, `-v3`), writes a `.refgen.json` sidecar per image (model, prompt, source photo, SHA-256), and puts everything under `Art/reference/facade-details/` — gitignored, local-only, never shipped. Costs money per image, so it is never automatic. | | `judge_screenshot.py` | (see Visual review) | ## Input injection diff --git a/Tools/facade_detail_concepts.py b/Tools/facade_detail_concepts.py index a6e1c60..90a523f 100644 --- a/Tools/facade_detail_concepts.py +++ b/Tools/facade_detail_concepts.py @@ -1,10 +1,14 @@ #!/usr/bin/env python3 -"""Generate architectural detail studies from the local reference photography. +"""Generate frontal building plates from the local reference photography. Each study takes one photograph we already hold (`Art/reference/`, gitignored) as -the geometric anchor and asks an image model to re-stage it as a clean -architectural detail plate — no crowd, no staging, straight-on, evenly lit — so -the modelling pass has something to measure against instead of a tourist photo. +the geometric anchor and asks an image model to re-stage it as a clean **frontal +view of the building** — the whole elevation, the entrance in its facade, or the +building with its neighbours — evenly lit, no crowd, no staging, so the modelling +pass has something measurable instead of a tourist photo. + +Deliberately **not** close-up detail crops: a doorway or cornice crop cannot be +measured for proportion, which is what the modelling pass actually needs. python3 Tools/facade_detail_concepts.py --list python3 Tools/facade_detail_concepts.py --only door-recess,parapet-motto @@ -51,70 +55,75 @@ DEFAULT_MODEL = "google/gemini-2.5-flash-image" # project's convention so the two sets stay comparable: the photograph fixes the # geometry, the prompt only restages light, weather, people and surface. ANCHOR_SUFFIX = ( - "Use the attached reference photograph as the fixed source of geometry and " - "composition: keep the building's proportions, column rhythm, band heights, " - "signage placement and camera angle exactly as photographed. Only restage " - "lighting, weather, people and surface condition where the request asks for " - "it. Do not invent extra storeys, wings or ornaments that the photo does not " - "show." + "Use the attached reference photograph as the source of the architecture: keep " + "the building's proportions, storey count, column rhythm, band heights and " + "signage placement exactly as photographed. You may REFRAME — step back across " + "the street, zoom out or widen the field of view — so that the whole building " + "fits in the frame from the pavement to the parapet; the reference is often " + "cropped and the plate must not be. Keep the view exterior and frontal (or " + "three-quarter where asked). Restage only lighting, weather, people and surface " + "condition. Do not invent extra storeys, wings or ornaments, and do not change " + "the architecture to fit the frame." ) -# name -> (reference photo relative to Art/reference/, what the study must show) +# name -> (reference photo relative to Art/reference/, what the plate must show) +# +# Verified framing (vision pre-check, 2026-11-09): the model follows the reference +# crop closely, so a plate is only as wide as its source photo. `building-entrance` +# and `building-street-front` come back as full-elevation frontal views; the studies +# anchored on the tightly cropped 2009 facade photo stay cropped, because the model +# will not invent the parapet and sky that the photograph does not contain. A full +# building plate for 6840 needs a full-elevation photograph, which the local set +# does not have (see Docs/reference-notes-hollywood.md). +# +# Every study asks for a *frontal view of a building*, not a crop of one detail: +# the whole elevation, the entrance in its facade, or the building together with +# its neighbours. Close-up framing is deliberately absent — a detail crop cannot +# be measured for proportion, which is what the modelling pass needs. STUDIES: dict[str, tuple[str, str]] = { - "door-recess": ( - "el-capitan-entrance/01-hollywood-el-capitan-entrance-detail.jpg", - "A clean architectural detail plate of exactly the subject in the " - "reference photograph. Render it as an even-daylight stone study: crisp " - "surface carving, readable depth of every recess and moulding, no people, " - "no signage or banners in front of it, no shop clutter, straight-on to the " - "subject.", + "building-front": ( + "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", + "A frontal view of the complete building shown in the reference " + "photograph: the whole elevation from the pavement to the parapet fits in " + "the frame with clear sky above the roofline and pavement below the ground " + "floor, shot straight on and centred. Nothing may be cut off at the top or " + "bottom. Even daylight, no crowd, no vehicles.", ), - "entrance-wide": ( + "building-entrance": ( "el-capitan-entrance/01-hollywood-el-capitan-entrance.jpg", - "A straight-on architectural study of the street entrance in the " - "reference photograph, the portal group centred and filling the frame, " - "threshold and pavement readable, no pedestrians or vehicles, even " - "overcast daylight, stone surface legible.", + "A frontal view of the building in the reference photograph, framed so its " + "street entrance is clearly visible as part of the facade — the doors and " + "the wall around them in proportion, not a close-up of the doorway. " + "Include the pavement in front. Even daylight, no crowd.", ), - "column-order": ( - "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", - "A close architectural study of the column order visible in the " - "reference photograph: the base, shaft and capital read clearly, " - "neighbouring columns framing it. Straight-on, evenly lit, stone surface " - "and carving legible, no people or banners.", - ), - "entablature-cornice": ( - "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", - "An architectural detail study of the horizontal stone bands above the " - "columns in the reference photograph: every band edge and the projecting " - "cornice with its shadow line. The layered depth of the stone must be " - "readable, flat even light, no people.", - ), - "parapet-motto": ( - "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", - "An architectural study of the parapet above the colonnade in the " - "reference photograph: the inset panel, any round medallions beside it " - "and the coping at the top. Lettering on the panel is blocked out as " - "unreadable texture. Flat even light, no people.", - ), - "window-rhythm": ( - "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", - "An architectural study of the wall surface behind and between the " - "columns in the reference photograph: the opening or window rhythm and " - "the reveal depth. Straight-on, no people, no banners covering the wall.", - ), - "street-wall": ( + "building-with-neighbours": ( "hollywood/el-capitan-theatre-blade-sign-day-wikimedia-2008-10.jpg", - "A clean street-wall study from the opposite pavement, as framed in the " - "reference photograph: the building line, the parapet heights of the " - "neighbouring buildings, the shopfront line and the pavement depth. No " - "crowd, even daylight.", + "A straight-on view of the street wall in the reference photograph: the " + "building and its neighbouring buildings either side, each at full height " + "from pavement to parapet with sky above, the joins between them visible, " + "nothing cut off. Shot from across the road, parallel to the frontage. " + "Even daylight, no crowd.", ), - "banner-detail": ( - "el-capitan-premiere/02-premiere-of-spielberg-s-west-side-story---el-capitan---holly.jpg", - "An architectural study of the vertical banner in the reference " - "photograph: how it is fixed, its proportions against the column behind " - "it, and how it sits against the stone. Daylight, no crowd.", + "building-street-front": ( + "hollywood/walk-of-fame-terrazzo-ovation-day-cc0-2019-06-20.jpg", + "A frontal view along the pavement of the building in the reference " + "photograph: the building's frontage seen from street level with its " + "neighbours continuing either side and the pavement in the foreground. " + "Straight on, even daylight, no crowd.", + ), + "building-front-oblique": ( + "hollywood/el-capitan-facade-day-wikimedia-2009-10-27.jpg", + "A three-quarter view of the complete building in the reference " + "photograph: the frontal elevation and one side visible together so the " + "building's depth and mass read, with its neighbouring building at one " + "edge. The whole building stays in frame. Even daylight, no crowd.", + ), + "theatre-front-with-neighbours": ( + "el-capitan-theater-detail/01-el-capitan-marquee.jpg", + "A frontal view of the theatre in the reference photograph together with " + "the buildings either side of it, the whole frontage and its full height " + "in frame, shot from across the road. Even daylight, no crowd, marquee " + "lettering blocked out as unreadable texture.", ), } -- 2.47.3 From 70c6e322e20934ac286e06938fa51a425fc1a1b1 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 17:39:52 +0100 Subject: [PATCH 5/9] feat(hero): Ionic base and abacus, medallions onto the parapet face Detail pass on the hero, all verified by measuring the built mesh: - Column base moulding: a 1.36 m wide, 0.22 m tall cylinder at each shaft foot (2.00-2.22 m). The shaft previously started straight off the square pedestal, so the base never read in silhouette. - Abacus: a 1.30 m square, 0.14 m thick slab over each capital. It takes the top of the capital zone, so the colonnade still ends at 9.70 m and the 53.1 % proportion is unchanged. - Medallions fixed: they were built with the Z-axis cylinder helper, so the two 'discs' were pancakes lying flat on the parapet coping (1.1 x 1.1 x 0.02, z 14.02-14.04). New disc_on_wall() helper rotates the cylinder 90 deg about X; they now stand 1.1 m across on the parapet face (y -1.32..-1.28, z 13.05..14.15). Hero rebuilt (95 parts, 2420 tris, still 14.50 m), re-imported, DemoMap rebuilt, screenshot set re-rendered. Part report records the new dims and their assumption notes. Screenshots README notes the detail pass. --- Art/blender/hero/hero-facade-2026-11-07.blend | 4 +- Art/blender/hero/hero-facade-2026-11-07.json | 34 ++++++++--- Game/GigLine/Content/Hollywood/DemoMap.umap | 2 +- .../Hollywood/ElCapitan/SM_HeroFacade.uasset | 4 +- .../Content/Hollywood/Site/M_Asphalt.uasset | 2 +- .../Content/Hollywood/Site/M_Concrete.uasset | 2 +- .../Hollywood/Site/M_FacadeStone.uasset | 2 +- .../Content/Hollywood/Site/M_Ground.uasset | 2 +- .../Hollywood/Site/M_KerbConcrete.uasset | 2 +- .../Content/Hollywood/Site/M_RoadPaint.uasset | 2 +- .../Content/Hollywood/Site/M_Stucco.uasset | 2 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 2 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- Screenshots/demo/review-demo-crossing.png | 4 +- .../demo/review-demo-north-buildings.png | 4 +- Screenshots/demo/review-demo-spawn-view.png | 4 +- Screenshots/demo/review-demo-street-level.png | 4 +- Screenshots/review-character.png | 4 +- Screenshots/review-ground-contact.png | 4 +- Screenshots/review-hero-facade-front.png | 4 +- Screenshots/review-hero-facade-oblique.png | 4 +- Screenshots/review-hero-portals.png | 4 +- Screenshots/review-npc-prefab.png | 4 +- Screenshots/review-overview.png | 4 +- Screenshots/review-player-placement.png | 4 +- Screenshots/review-scale-cubes.png | 4 +- Screenshots/review-shadow-compare.png | 4 +- TODO.md | 2 +- Tools/hero_facade_build.py | 57 ++++++++++++++++--- 29 files changed, 117 insertions(+), 60 deletions(-) diff --git a/Art/blender/hero/hero-facade-2026-11-07.blend b/Art/blender/hero/hero-facade-2026-11-07.blend index b88fd9b..480949d 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.blend +++ b/Art/blender/hero/hero-facade-2026-11-07.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe3a08cdf4ca196cd59fe52a7ba9edc140d0e11391dff970a93b883410b415a6 -size 134198 +oid sha256:85235632d76bd9527947bdbff1f242cabc3de8192c6211273a77744d99f1e2e9 +size 139428 diff --git a/Art/blender/hero/hero-facade-2026-11-07.json b/Art/blender/hero/hero-facade-2026-11-07.json index 61169ff..a93b843 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.json +++ b/Art/blender/hero/hero-facade-2026-11-07.json @@ -3,18 +3,18 @@ "frame": "project frame, metres, X east Y north Z up", "bounds_m": { "min": [ - -13.02, + -13.08, -12.5, 0.0 ], "max": [ - 13.02, - 0.07, + 13.08, + 0.13, 14.5 ], "size": [ - 26.04, - 12.57, + 26.16, + 12.63, 14.5 ] }, @@ -37,6 +37,24 @@ ], "evidence": "6 columns at 4.96 m centres (sibling notes x measured frontage)" }, + { + "object": "Hero_ColumnBase_x6", + "dims_m": [ + 1.36, + 1.36, + 0.22 + ], + "evidence": "assumption: Ionic base moulding; photographs show a wider base at the shaft foot" + }, + { + "object": "Hero_Abacus_x6", + "dims_m": [ + 1.3, + 1.3, + 0.14 + ], + "evidence": "assumption: square abacus under the architrave, as Ionic capitals carry" + }, { "object": "Hero_Architrave", "dims_m": [ @@ -86,10 +104,10 @@ "object": "Hero_Medallion_x2", "dims_m": [ 1.1, - 1.1, - 0.02 + 0.04, + 1.1 ], - "evidence": "photographs: two stone discs beside the motto" + "evidence": "photographs: two stone discs beside the motto, mounted on the parapet face" }, { "object": "Hero_Stylobate", diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 56e6a99..45119d5 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58339d354b5afeb8fddefdd2c463eda6d45cd5379ff80f8eb644a33c17599e3f +oid sha256:acdd30ea6a5ad59a1c7f42ed0d70d179e98a6431791ce6bf7a3c584c36883f94 size 54508 diff --git a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset index 01f38d5..0dbcfbd 100644 --- a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset +++ b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3831a508ced9e573ab9db083672c1e16ba46f9f052ceb53665853f6198cc64b -size 117009 +oid sha256:9258231850302dd06eb27d7714b1560fe4921dd73db680cd2d6e19ebaf8c57c5 +size 128284 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index 3899d1d..fadfff1 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9525922eca9e99a50f97b0c44ede1b908e1d97fa8c0fbddf928ffa3fbc960c4b +oid sha256:ac1508a932d350be48d9969dd90c3e7ca5c67a89b63546a9ddae990b3e47a228 size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index 5eab245..d3d636e 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:906f52dcc949ac7dfeae7f60e250434af3d2e57d5d6e23a6deb565d3a138a39e +oid sha256:a43bf901e9cf838ad480784f3682ee2547e8de9e317ac1115bff0f3bacc99d44 size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index ccecc9c..0fa6b2b 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0323b2b2ee3023cadb09d8bc3f3a7c024ef2c2a0de53db8442070ef404a3b434 +oid sha256:296c8933f068d64587c35916b947453fc394484246cfde3fcdf0c865a076400f size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index ea094ac..8755aae 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebc3cbc40452389f0ae078dad79949653612c5c300fa5644807344dbb6aa97bb +oid sha256:664b4fb977c50a4b80a6b121e8f7f9c71b1a3c6ceac95528dfc15baa8f3bf732 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index 00b980c..2c48dd6 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f311cc222d4f215b3163841c111e526b09874d5ee8845ea5720e4556babd387 +oid sha256:a6210dae202c33257c7817d5b9cc95198df094f2338400d8f525d8bbea9351a2 size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index dba2aed..f50c054 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b4e25f5d61346ae996c1ad43c889fdabbe0576f306fba83b67f2918e778d675 +oid sha256:c85b5214d4eca87d470bbbc6babfc92b55a9c2b0a937171a2c16c41a915e09b3 size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index c4b8fa9..4b11416 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:720902f570fb87a38e3847d2645b057e71f8971a82000ca39af3652349349ce7 +oid sha256:b409da289210f018dcf96757db52af5d90b2ddd9890c082a75aeec081ea8bde2 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index c175268..ec52357 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17d9fe3b1ce4589e610f0027c91f361eb73b09c7442b5c4a763b5419aba47040 +oid sha256:f7c788b5a4bb6700c50b56009c5b0aa0ff08bddfa4e093e881b04bf4521eb2a3 size 335528 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index ec501e9..ac2c54c 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e94a0743d2dfd379b4011e69d79f0fe156a8d2158727b8fc5f3d1395f854e2aa +oid sha256:95c36b872c9c9ced0d697b1766a0aa729e5229b39ed117a4764ddaac31c00613 size 28706 diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index dd16d77..4fb56b0 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33e7e224081d4b0a44752a42e93b944f1f41172c85978c8f4f9a20169c4b7502 -size 2666539 +oid sha256:c7433f707fd4c67c2086010e0e5532ccd52181256a18fe463e1df5482199c51e +size 2670224 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index deb86a3..826fcc0 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd7a116c05c31584187d6dd05fb94f69d6ff540737cb212b8a860931f360666b -size 2506551 +oid sha256:7b3f30d08aac53ff457d77c15623f0e64576a99fd35b2365fae8be20f368d196 +size 2506433 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 880f199..fdff3ea 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1cbf3b285c04f9c851ede43f5aa97585facf966f5e7e8cdb20d7ef074f71193 -size 2619015 +oid sha256:b6d50f5ab3d48192c29fa8e1f55081cf07a25ed8e076a433db206fae2d071aa4 +size 2622693 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 9f8899d..509f5cc 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bba4637c4fb2a60f629def61edc61d231389576a77bd4a02dbe569ceb13ae036 -size 2441194 +oid sha256:62281b1fc62966c64b191d70e3d028cc58ac1ca3678cb0ebb293c8c8cba886e4 +size 2447844 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index 6035512..026cb84 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:874d3a55f9f369c07bb266619550a0ddb6608e60bca03b61e92c5c84172899a2 -size 2533314 +oid sha256:e2ac708b0b575a87bbdd56a19979c2115b7ff60797faf3569a92bec37f072b04 +size 2537573 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 36fd3d6..04655e3 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e03e459828414a20d22cf82bab6ff2101e2d252e05892d6353de72c0bfcafb7 -size 1751574 +oid sha256:801b4dc81508169a309950e9dcfa8275e0106af16496b0741f5c22fc8d0445f0 +size 1751096 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index eca1075..6aa970d 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d43265c7371293f51d3097ac0b64231bb744a8968c34fea6059bda4bf338a94 -size 1552429 +oid sha256:e01eeea0faae4f18969b5f2f5885462c5033e1d8a476060fbd60c2e55f9d8375 +size 1554786 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index 0519f5e..df386cf 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46c18a8e4a04e87f9c5bfe0d485e012ca320ea258d01d2bbf04fb81e8366cdd0 -size 1306107 +oid sha256:5f65120965f61e8b6c667a8524864653755012cc68fe98a36396f08780ed2dc8 +size 1308909 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 2443cb5..e4e699c 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa0eedb216ff40fd04886f3848de4ed614e57b2cdc376a2881a3869c8b2027f9 -size 1326324 +oid sha256:14f651aeeef6ddec8e7de0a89326b7ac7c8f713ffdf83fc67525dfd780b2b3b9 +size 1328002 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index ae36cee..de225e6 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77b89f510d5bdbc5a894a65e7244713d055b9e0c5ef365a52c31f5e8886946cc -size 1732427 +oid sha256:cff5f94a8224a3b7ee2e22db8dc157a2a6e484dd405b0f934f38e966265d881b +size 1737790 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index 1b8ef3b..e4d4b66 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bfd21b670e27b2d9642083bc25460023d8acf4d788981b750ad7cc7d74d13ed -size 2482062 +oid sha256:b809ae0e1239f3e915ac312bcee988270cb1516707b784c95fb7014704474534 +size 2627332 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index b44ffde..c5393bc 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11933b0e8fe721cd9f785f15d99438dd8c632e814a7fe86b053e855b909673d4 -size 2022340 +oid sha256:7b024c12c58253aefdfa34f64463fde181382bfe4106df092c9b0e8cf6e1cb1d +size 2018349 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 3bb9a2a..49f3d9e 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c54621f64bd890182f04755154156a74b735ad1a839b712c6c48bd9d60f1afe6 -size 1936777 +oid sha256:fb7a5b86453eb0d15bf34feafe69773038b30d7467e6034f6455921ca19b9862 +size 1938812 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index c980a6b..d7fa9d6 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01f3443e4163ec9e3e45f1612c8357f1b05dd6bb87043095b8aa9e8a1ceaddab -size 1721917 +oid sha256:b3c25931da0737b93cc89558556e87537a3ac1518e2d8290258024fd68e6f338 +size 1721081 diff --git a/TODO.md b/TODO.md index 9966973..333d831 100644 --- a/TODO.md +++ b/TODO.md @@ -16,7 +16,7 @@ Suggested blender skills: **references** (reference-image-match and visual-match ### Patch tasks - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `scale-facade-0.1.2`) - [x] Correct building scale and street proportions flagged against references. **Mapbox adopted 2026-11-09.** `Geo/tools/mapbox_buildings.py` merges our OSM heights with Mapbox's building data for the same footprints; after adopting its two findings the cross-check reports **66 match, 6 non-building, 0 disagreements**. Adopted: **`LEVEL_HEIGHT` 3.2 → 3.1 m** (`block_height_report.py`, and the Blosm `--level-height` default), plus explicit `HEIGHT_OVERRIDES` (3.0 m) for the three rear `building=yes`/`apartments` structures Mapbox gives as single-storey. Blockout regenerated, frontage re-exported/re-imported, DemoMap rebuilt; packaged `-qaselftest` all PASS. Measured effect: 6922 42.1 → 39.1 m, El Capitan Theatre 20.0 → 20.5 m (both now ~1.9 m above their table height = roof mass). -- [ ] Refine hero façade details where reference photography shows discrepancies. **Started 2026-11-09:** built `Tools/facade_detail_concepts.py`, which generates architectural detail plates from the local reference photographs with an image model (`--list` free, `--all` generates, sidecars + `-vN` no-overwrite, output gitignored). Six **frontal building** studies generated locally under `Art/reference/facade-details/` (whole elevation, entrance in its facade, building with neighbours, pavement view, three-quarter, theatre frontage) — rephrased on owner instruction to show the building/entrance/neighbours rather than close-up detail crops. **First fix from the measurement pass:** window panes were 1.44 m in front of the wall (ahead of the columns) and now sit on the wall plane behind the colonnade. Remaining: use the plates to correct the capital/base profiles and the medallion/cornice detail. +- [ ] Refine hero façade details where reference photography shows discrepancies. **Started 2026-11-09:** built `Tools/facade_detail_concepts.py`, which generates architectural detail plates from the local reference photographs with an image model (`--list` free, `--all` generates, sidecars + `-vN` no-overwrite, output gitignored). Six **frontal building** studies generated locally under `Art/reference/facade-details/` (whole elevation, entrance in its facade, building with neighbours, pavement view, three-quarter, theatre frontage) — rephrased on owner instruction to show the building/entrance/neighbours rather than close-up detail crops. **First fix from the measurement pass:** window panes were 1.44 m in front of the wall (ahead of the columns) and now sit on the wall plane behind the colonnade. **Detail pass 2026-11-09 (all measured on the built mesh):** added an Ionic base moulding (1.36 m × 0.22 m) at each shaft foot and a square abacus (1.30 m × 0.14 m) over each capital, taking the abacus out of the capital zone so the colonnade still ends at 9.70 m; re-oriented the two parapet medallions, which were flat discs lying on the coping (1.1 × 1.1 × 0.02 in the wrong axes) instead of discs on the parapet face; window panes moved onto the wall plane. Hero is now 2 420 tris across 95 parts, still 14.50 m. Cornice/dentil profile refinement remains. - [x] **Replace the placeholder heights.** **Resolved 2026-11-08 — they were never unknown buildings.** The three "guessed" ways are not building volumes at all: `1360755125` and `1360755126` are `building=roof` at `layer=1` (elevated canopies) and `1417995292` is `amenity=shelter` / `shelter_type=public_transport` (a transit shelter). The report defaulted them to "2 levels × 3.2 m" and produced the bogus 6.4 m. `Geo/tools/block_height_report.py` now classifies roof/shelter explicitly and reports **0 guessed heights**: all 15 block volumes have a real `height` tag, a `building:levels` derivation, or are correctly excluded as non-building volumes. No photograph measurement was needed, and no frontage building was affected. - [x] Resolve the remaining unknown on the hero: the colonnade currently occupies about 45 % of the height against roughly 50–60 % in the photographs. Fix the vertical proportions. **Fixed 2026-11-09.** Measured baseline: colonnade (columns + capitals) 6.90 m of the 14.50 m envelope = **47.6 %**, because the entablature (3.40 m) and parapet (2.20 m) left only 7.90 m for the order. Thinned both to **3.00 m** and **1.80 m** (`Tools/hero_facade_build.py`), which lifts the colonnade to **7.70 m = 53.1 %** — inside the photographed 50–60 % band, with the 14.50 m envelope, the motto band and the medallions unchanged in position relative to the parapet. Hero rebuilt, re-imported (bounds 2604 × 1257 × 1450 cm) and re-rendered. - [ ] Tag `v0.1.2` and write `CHANGELOG.md` entry; then remove this section. diff --git a/Tools/hero_facade_build.py b/Tools/hero_facade_build.py index c75015a..204d0fa 100644 --- a/Tools/hero_facade_build.py +++ b/Tools/hero_facade_build.py @@ -88,6 +88,25 @@ def cylinder(name, x, y, z0, z1, radius, material, vertices=24): return obj +def disc_on_wall(name, x, y, z, radius, thickness, material=None, vertices=24): + """A round disc mounted vertically on a wall face. + + `cylinder()` builds along Z, so a "medallion" made with it is a pancake lying + flat on top of the parapet rather than a disc on its face — which is what the + first build did (1.1 m across in Y, 0.02 m thick in Z, sitting at the coping). + This rotates the cylinder 90 degrees about X so the axis points along Y and + the disc faces the street. + """ + obj = cylinder(name, x, y, z - thickness / 2.0, z + thickness / 2.0, + radius, material, vertices=vertices) + obj.rotation_euler = (math.radians(90.0), 0.0, 0.0) + bpy.ops.object.select_all(action="DESELECT") + obj.select_set(True) + bpy.context.view_layer.objects.active = obj + bpy.ops.object.transform_apply(location=False, rotation=True, scale=True) + return obj + + def make_material(name, rgba, roughness=0.75): mat = bpy.data.materials.new(name) mat.use_nodes = True @@ -136,14 +155,32 @@ def build(): col_xs.append(x) cube(f"Hero_Pedestal_{i + 1}", x, -0.62, PEDESTAL_H + 0.27, 1.24, 1.24, 0.54, stone) - cylinder(f"Hero_Column_{i + 1}", x, -0.55, PEDESTAL_H + 0.55, - PEDESTAL_H + 0.55 + (HEIGHT - ENTABLATURE_H - PARAPET_H - PEDESTAL_H - 0.55 - CAPITAL_H), + # Base moulding: a taller, wider cylinder where the shaft meets the + # pedestal. Without it the shaft starts straight off a square plinth, + # which is not how an Ionic base reads in silhouette. + base_z0 = PEDESTAL_H + 0.55 + base_h = 0.22 + cylinder(f"Hero_ColumnBase_{i + 1}", x, -0.55, base_z0, base_z0 + base_h, + 0.68, stone, vertices=20) + shaft_z0 = base_z0 + base_h + cap_z0 = HEIGHT - ENTABLATURE_H - PARAPET_H - CAPITAL_H + cylinder(f"Hero_Column_{i + 1}", x, -0.55, shaft_z0, cap_z0, COLUMN_D / 2.0, stone) - cylinder(f"Hero_Capital_{i + 1}", x, -0.55, - HEIGHT - ENTABLATURE_H - PARAPET_H - CAPITAL_H, - HEIGHT - ENTABLATURE_H - PARAPET_H, 0.62, stone, vertices=16) + # Capital block, then the square abacus that carries the architrave. + # The abacus takes the top 0.14 m of the capital zone so the colonnade + # still ends at HEIGHT - ENTABLATURE_H - PARAPET_H (proportion unchanged). + abacus_h = 0.14 + cylinder(f"Hero_Capital_{i + 1}", x, -0.55, cap_z0, + HEIGHT - ENTABLATURE_H - PARAPET_H - abacus_h, 0.62, stone, vertices=16) + cube(f"Hero_Abacus_{i + 1}", x, -0.55, + HEIGHT - ENTABLATURE_H - PARAPET_H - abacus_h / 2.0, + 1.30, 1.30, abacus_h, stone) note("Hero_Column_x6", (COLUMN_D, COLUMN_D, HEIGHT - ENTABLATURE_H - PARAPET_H - PEDESTAL_H), f"6 columns at {COLUMN_BAY} m centres (sibling notes x measured frontage)") + note("Hero_ColumnBase_x6", (1.36, 1.36, 0.22), + "assumption: Ionic base moulding; photographs show a wider base at the shaft foot") + note("Hero_Abacus_x6", (1.30, 1.30, 0.14), + "assumption: square abacus under the architrave, as Ionic capitals carry") # --- entablature and parapet ------------------------------------------ ent_z0 = HEIGHT - ENTABLATURE_H - PARAPET_H @@ -167,11 +204,13 @@ def build(): FRONTAGE_W - 3.0, 0.08, 0.85, stone_dark) note("Hero_MottoBand", (FRONTAGE_W - 3.0, 0.08, 0.85), "photographs: motto panel above the colonnade") - # Medallions either side of the inscription. + # Medallions either side of the inscription: discs on the parapet face, not + # pancakes on the coping (see disc_on_wall). for i, x in enumerate((-6.2, 6.2), start=1): - cylinder(f"Hero_Medallion_{i}", x, -1.36, HEIGHT - PARAPET_H / 2.0 + 0.42, - HEIGHT - PARAPET_H / 2.0 + 0.44, 0.55, stone_dark, vertices=20) - note("Hero_Medallion_x2", (1.1, 1.1, 0.02), "photographs: two stone discs beside the motto") + disc_on_wall(f"Hero_Medallion_{i}", x, -1.30, HEIGHT - PARAPET_H / 2.0, + 0.55, 0.04, stone_dark, vertices=20) + note("Hero_Medallion_x2", (1.1, 0.04, 1.1), + "photographs: two stone discs beside the motto, mounted on the parapet face") # --- entrances --------------------------------------------------------- # Three portals between column pairs, each with its own short flight. The -- 2.47.3 From 160e9144f92e841c3e7fda81b34a153f7dcd802e Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 17:53:31 +0100 Subject: [PATCH 6/9] fix(hero): export smoothing groups; give the facade real collision UE export hygiene (unreal-export skill checklist) plus a gameplay defect the new probe caught: - FBX export now uses mesh_smooth_type="FACE" (was OFF, which is why every import logged "No smoothing group information was found"), and the round parts are shaded with shade_smooth_by_angle(35 deg) before export, so columns and medallions read round instead of faceted. - SM_HeroFacade had complex-only collision, so capsule sweeps and line traces passed through the wall: the player could walk through the hero facade. auto_generate_collision was tried and rejected (coarse hulls bulged into the street; the QA wall probe went 0/35 -> 2/35). It now uses UseComplexAsSimple, saved on the asset, like the terrain. - New -qaselftest facade occlusion probe: 40 m traces sideways from the road centre at walking height, required only where a building is staged (explicit X spans mirroring ue_build_demo_map). Result 0/9 -> PASS, alongside transect 0 holes and wall probe 0/35. Docs: release-checks records the probe and both collision attempts; Tools/README lists the new phase; MEMORY records the smoothing/collision lessons. --- Art/blender/hero/hero-facade-2026-11-07.blend | 4 +- Docs/release-checks.md | 9 +++ Game/GigLine/Content/Hollywood/DemoMap.umap | 2 +- .../Hollywood/ElCapitan/SM_HeroFacade.uasset | 4 +- .../Content/Hollywood/Site/M_Asphalt.uasset | 2 +- .../Content/Hollywood/Site/M_Concrete.uasset | 2 +- .../Hollywood/Site/M_FacadeStone.uasset | 2 +- .../Content/Hollywood/Site/M_Ground.uasset | 2 +- .../Hollywood/Site/M_KerbConcrete.uasset | 2 +- .../Content/Hollywood/Site/M_RoadPaint.uasset | 2 +- .../Content/Hollywood/Site/M_Stucco.uasset | 2 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 2 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- .../Source/GigLine/GigLineCharacter.cpp | 75 +++++++++++++++++++ MEMORY.md | 20 +++++ Screenshots/demo/review-demo-crossing.png | 4 +- .../demo/review-demo-north-buildings.png | 4 +- Screenshots/demo/review-demo-spawn-view.png | 4 +- Screenshots/demo/review-demo-street-level.png | 4 +- Screenshots/review-character.png | 4 +- Screenshots/review-ground-contact.png | 4 +- Screenshots/review-hero-facade-front.png | 4 +- Screenshots/review-hero-facade-oblique.png | 4 +- Screenshots/review-hero-portals.png | 4 +- Screenshots/review-npc-prefab.png | 4 +- Screenshots/review-overview.png | 4 +- Screenshots/review-player-placement.png | 4 +- Screenshots/review-scale-cubes.png | 4 +- Screenshots/review-shadow-compare.png | 4 +- Tools/README.md | 2 +- Tools/hero_facade_build.py | 11 ++- Tools/ue_hero_facade_import.py | 10 +++ 32 files changed, 166 insertions(+), 45 deletions(-) diff --git a/Art/blender/hero/hero-facade-2026-11-07.blend b/Art/blender/hero/hero-facade-2026-11-07.blend index 480949d..b97c286 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.blend +++ b/Art/blender/hero/hero-facade-2026-11-07.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85235632d76bd9527947bdbff1f242cabc3de8192c6211273a77744d99f1e2e9 -size 139428 +oid sha256:5a1fb7ce48fa6a8b82a629caa61b6678e79d001491dfc5b5a00ce49acd13d9f0 +size 139669 diff --git a/Docs/release-checks.md b/Docs/release-checks.md index 328f44d..fae4af0 100644 --- a/Docs/release-checks.md +++ b/Docs/release-checks.md @@ -95,6 +95,15 @@ Run on the packaged build (`GigLineQA`, Development, Vulkan SM5) with `-qaselfte - **Invisible-wall probe:** horizontal traces 30 m long, grounded at 160 cm above the local ground, along the road and both seam rows. Result **0/35 blocking hits inside 21 m** — no invisible walls or misplaced blockers in the street envelope. +- **Facade occlusion probe:** from the road centre, 40 m traces sideways at walking + height toward each frontage, required only where the map stages a building (the + spans are listed in `AGigLineCharacter` and mirror `Tools/ue_build_demo_map.py`). + Result **0/9 directions without a blocking wall** — the player cannot walk + through the hero or the frontage. This probe found the hero façade had **no + simple collision** at all (complex-only, so traces and capsule sweeps passed + through it); it is now `UseComplexAsSimple`. Auto-generated convex hulls were + tried first and rejected: on a 95-part, 26 m façade they bulged into the street + (the wall probe went 0/35 → 2/35). (First pass used a fixed Z 160 start; the street is at Z ~366, so the probe started inside the earth and reported every row as a dist-0 blocker. Grounding the probe fixed that measurement bug.) diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 45119d5..c11114b 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:acdd30ea6a5ad59a1c7f42ed0d70d179e98a6431791ce6bf7a3c584c36883f94 +oid sha256:ab6fbc24a8ebaa48287b8d81e4b180000d5692134349e9bd26f46a90f5d297aa size 54508 diff --git a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset index 0dbcfbd..7141801 100644 --- a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset +++ b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9258231850302dd06eb27d7714b1560fe4921dd73db680cd2d6e19ebaf8c57c5 -size 128284 +oid sha256:4ddad5d7f8850af3547fe2f80c388e16e0559e266da058874f0fc36af2ac4f6b +size 129152 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index fadfff1..b5f45fe 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac1508a932d350be48d9969dd90c3e7ca5c67a89b63546a9ddae990b3e47a228 +oid sha256:492410ca526af9484ed9d2f35139b05c00072fdf93156e470c4dea697913804b size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index d3d636e..5f25f89 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a43bf901e9cf838ad480784f3682ee2547e8de9e317ac1115bff0f3bacc99d44 +oid sha256:01c5f65d30f0502c08ae6c3d0a6149bf22cd3cc6964386fab7823006433d09a7 size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index 0fa6b2b..da554a9 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:296c8933f068d64587c35916b947453fc394484246cfde3fcdf0c865a076400f +oid sha256:ab055873e8dd41063966798974289109b1a402fedc9856a0e8e8f22d5575c382 size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 8755aae..601239b 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:664b4fb977c50a4b80a6b121e8f7f9c71b1a3c6ceac95528dfc15baa8f3bf732 +oid sha256:9ceb456eaaa65eb883ff9b5601d1da6801349396ffaff50d956eca62f8978c57 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index 2c48dd6..78ed54a 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6210dae202c33257c7817d5b9cc95198df094f2338400d8f525d8bbea9351a2 +oid sha256:95591e094b01819fe8fd4ccc36241c1c71aa9b364689e555468191f4a74992d5 size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index f50c054..ee34264 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c85b5214d4eca87d470bbbc6babfc92b55a9c2b0a937171a2c16c41a915e09b3 +oid sha256:514e92d6639134304adb30c845cdcc4ce5d21debc4088e78de5446ae6949dafd size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index 4b11416..669842d 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b409da289210f018dcf96757db52af5d90b2ddd9890c082a75aeec081ea8bde2 +oid sha256:12a5691b007ae60ced3f3bab90abd9a08825a460206dec097a589c94f58228ba size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index ec52357..5f66af5 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7c788b5a4bb6700c50b56009c5b0aa0ff08bddfa4e093e881b04bf4521eb2a3 +oid sha256:48ff0d06e31cb7824b60c2e13b9555c20c7b03d45cfd4efcab2f72ca61fb16b9 size 335528 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index ac2c54c..6bca92a 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:95c36b872c9c9ced0d697b1766a0aa729e5229b39ed117a4764ddaac31c00613 +oid sha256:631a70bc5f98ececab410ab698bc2047a7f65e3e2d010c679988bef28f70b430 size 28706 diff --git a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp index 9ab855a..aafab92 100644 --- a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp +++ b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp @@ -416,6 +416,81 @@ void AGigLineCharacter::StartQASelfTest() TEXT("GigLine QA: wall probe %d/%d traces with blocking hit inside 21 m -> %s"), Walls, WallSamples, Walls == 0 ? TEXT("PASS") : TEXT("FAIL")); + + // Facade occlusion probe: walkable street is only half the story — + // the player must also NOT be able to walk through the buildings. + // From the road centre, fire 40 m sideways at walking height toward + // each frontage and require a blocking hit. A miss means the + // building has no collision (or only non-blocking collision) and the + // player would pass through the wall. + // Expect a wall only where the map actually stages a building. + // Spans below mirror the actors placed by Tools/ue_build_demo_map.py + // (frontage + hero) and the two north buildings; update them if + // that list changes. Gaps between buildings are legitimate misses. + struct FSpan { float Min, Max; }; + static const FSpan SouthSpans[] = { + {-24276.f, -17700.f}, // 6922 + {-17749.f, -14591.f}, // 6902 + {-14638.f, -12034.f}, // 6840 hero + {-12082.f, -8210.f}, // 6838 El Capitan Theatre + {-7854.f, -7252.f}, // 6822 Budget + {-6608.f, -3307.f}, // 6806-6820 + {-3320.f, -1437.f}, // 6800 Lee Drug + }; + static const FSpan NorthSpans[] = { + {-27071.f, -22799.f}, // Madame Tussaud's + {-22889.f, -18442.f}, // TCL Chinese Theatre + }; + auto InSpans = [](const FSpan* Spans, int32 Count, float X) + { + for (int32 i = 0; i < Count; ++i) + { + if (X >= Spans[i].Min && X <= Spans[i].Max) { return true; } + } + return false; + }; + int32 Facades = 0, FacadeSamples = 0; + for (float X0 = -19000.0f; X0 <= -3000.0f; X0 += 2000.0f) + { + for (float Dir : {1.0f, -1.0f}) // +Y south frontage, -Y north side + { + const bool bExpectWall = (Dir > 0.0f) + ? InSpans(SouthSpans, UE_ARRAY_COUNT(SouthSpans), X0) + : InSpans(NorthSpans, UE_ARRAY_COUNT(NorthSpans), X0); + if (!bExpectWall) + { + continue; + } + FHitResult GroundHit2; + FCollisionQueryParams GQ2(TEXT("GigLineFacadeGround"), false, this); + if (!W->LineTraceSingleByChannel(GroundHit2, + FVector(X0, 0.0f, 3000.f), FVector(X0, 0.0f, -1000.f), + ECC_Visibility, GQ2)) + { + continue; + } + const float ProbeZ2 = GroundHit2.ImpactPoint.Z + 160.f; + FHitResult Hit2; + FCollisionQueryParams Q2(TEXT("GigLineFacadeProbe"), false, this); + const bool bHit2 = W->LineTraceSingleByChannel(Hit2, + FVector(X0, 0.0f, ProbeZ2), + FVector(X0, Dir * 4000.f, ProbeZ2), + ECC_Visibility, Q2); + ++FacadeSamples; + const bool bBlocking = bHit2 && Hit2.GetActor() != nullptr; + if (!bBlocking) + { + ++Facades; + UE_LOG(LogTemp, Log, + TEXT("GigLine QA: facade probe miss at X %.0f dir %.0f (no blocking hit in 40 m)"), + X0, Dir); + } + } + } + UE_LOG(LogTemp, Log, + TEXT("GigLine QA: facade probe %d/%d directions without a blocking wall -> %s"), + Facades, FacadeSamples, + Facades == 0 ? TEXT("PASS") : TEXT("FAIL")); } // 7.0: verdict, then stop ticking. diff --git a/MEMORY.md b/MEMORY.md index adfec09..31ae523 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -440,3 +440,23 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. `review-hero-facade-front`. - Reminder: `.blend` is LFS read-only on checkout — `chmod u+w` or Blender fails with "Cannot save blend file … not writable" (this bit again here). + +## 2026-11-09 — UE export hygiene: smoothing groups + facade collision + +- **All our FBX exporters used `mesh_smooth_type="OFF"`**, which is why every Unreal + import logged "No smoothing group information was found for this mesh". The hero + now exports `"FACE"` and its round parts are shaded with + `shade_smooth_by_angle(35°)` before export: cylinders read as round instead of + faceted, and the import warning is gone (6 → 0). +- **The hero façade had no simple collision** (complex-only), so line traces and + capsule sweeps passed straight through it — the player could walk through the + wall of the demo. Caught by a new `-qaselftest` **facade occlusion probe** (40 m + sideways traces from the road centre at walking height). +- **Auto-generated convex collision on a 95-part 26 m façade is unusable**: it + produced coarse hulls that bulged into the street and the wall probe went + 0/35 → 2/35. Rejected in favour of `UseComplexAsSimple` via + `UGigLineAssetTools.set_complex_collision_as_simple` (same reason the terrain + uses it), saved on the asset. +- Probe expectations must mirror the staged buildings: the facade probe now carries + explicit X spans per frontage (and the TCL/Tussaud's spans on the north side) so + a gap between buildings is not reported as a defect. diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index 4fb56b0..53583a0 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7433f707fd4c67c2086010e0e5532ccd52181256a18fe463e1df5482199c51e -size 2670224 +oid sha256:6c0144a5d8ad74cc56b512099e0bccf1b4913cc0969a40e2353a5d7b6c88dc4c +size 2670411 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index 826fcc0..3f0fd57 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b3f30d08aac53ff457d77c15623f0e64576a99fd35b2365fae8be20f368d196 -size 2506433 +oid sha256:bf0a8b0f98a3a8e37c6708a1ba6f37fce92d1954e5d02e8ef8051fdc669ad8f9 +size 2505075 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index fdff3ea..0fd459c 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6d50f5ab3d48192c29fa8e1f55081cf07a25ed8e076a433db206fae2d071aa4 -size 2622693 +oid sha256:25fb859414e73ccc043ab5cbba352bdab1ed45e668d82d3a1c4ccdd4f6e36441 +size 2627108 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 509f5cc..5f559d9 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62281b1fc62966c64b191d70e3d028cc58ac1ca3678cb0ebb293c8c8cba886e4 -size 2447844 +oid sha256:01c7e5f2385b9f4c7457b7d15745757568f5c26329b3db4ef08d44742ff5a25d +size 2448129 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index 026cb84..85e752d 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2ac708b0b575a87bbdd56a19979c2115b7ff60797faf3569a92bec37f072b04 -size 2537573 +oid sha256:6984bfec9d9d04e71ae10dd0e950f4bef7c82721e8c72abe70542ae7446e644f +size 2750769 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 04655e3..9ed90e0 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:801b4dc81508169a309950e9dcfa8275e0106af16496b0741f5c22fc8d0445f0 -size 1751096 +oid sha256:797c379922881c6db39bb8afd710283e5c0d5928919b4214eb98ab0d2e89ebe5 +size 1817363 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index 6aa970d..134198e 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e01eeea0faae4f18969b5f2f5885462c5033e1d8a476060fbd60c2e55f9d8375 -size 1554786 +oid sha256:8e46779f2b62816fab2f651b3d61bd780f2d98926a2f1b3eecbf36d09fedda41 +size 1731572 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index df386cf..b6db3e6 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f65120965f61e8b6c667a8524864653755012cc68fe98a36396f08780ed2dc8 -size 1308909 +oid sha256:c054e9e5edc10864f0a68f91248ec586121ba58cd57fac5509e0967859156594 +size 1399505 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index e4e699c..d3bcd07 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14f651aeeef6ddec8e7de0a89326b7ac7c8f713ffdf83fc67525dfd780b2b3b9 -size 1328002 +oid sha256:43bc085789469e32f656e910996dd2a9b4744cae1a0fcb8670e69d8625c94876 +size 1367381 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index de225e6..3140e12 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cff5f94a8224a3b7ee2e22db8dc157a2a6e484dd405b0f934f38e966265d881b -size 1737790 +oid sha256:645767d4184dedc7569d9a443cf7c855f1205b8dfd85c7ccbcd16068bcb26c97 +size 1802903 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index e4d4b66..c45ae01 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b809ae0e1239f3e915ac312bcee988270cb1516707b784c95fb7014704474534 -size 2627332 +oid sha256:4ca2ac170c369b2093c0b4bbb06bdf0cce318c897e75b74363a31bf56858bdab +size 2393713 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index c5393bc..ff8ca06 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b024c12c58253aefdfa34f64463fde181382bfe4106df092c9b0e8cf6e1cb1d -size 2018349 +oid sha256:16985e7229cd275af3567e9999e45c51db14dd2d9ab6e305bd16cbb77f5076c0 +size 2212611 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 49f3d9e..ec70c6e 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb7a5b86453eb0d15bf34feafe69773038b30d7467e6034f6455921ca19b9862 -size 1938812 +oid sha256:9e0d634aeb2adb125981cefabd3be2f54de7e64d6ab2de0baaa00d73e5539b01 +size 2147701 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index d7fa9d6..3229eca 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3c25931da0737b93cc89558556e87537a3ac1518e2d8290258024fd68e6f338 -size 1721081 +oid sha256:62940b77df50ddab2d2e9dd813c2f09c8fe83ec8f4cc755d4cfc47a3145800db +size 1851501 diff --git a/Tools/README.md b/Tools/README.md index 414542f..2be84e2 100644 --- a/Tools/README.md +++ b/Tools/README.md @@ -57,7 +57,7 @@ Geographic tools live in [`Geo/tools/`](../Geo/README.md) and the Blender-side b | Command | Purpose | | --- | --- | | `UnrealEditor /Game/Hollywood/DemoMap -game -qaselftest` | Headless behaviour check: drives forward input for 2 s, then resets and pauses. Logs `GigLine QA: ... PASS/FAIL` lines and a final `RESULT`. Runs only with `-qaselftest`, so normal play is unaffected. | -| `-qaselftest` phases | Walk, reset, pause/unpause, a 16-row seam transect (0 holes) and a ground-referenced wall probe (0/35), plus a frame-time capture writing `Saved/Profiling/perf-walk-frametimes.csv` and logging `GigLine PERF:`. | +| `-qaselftest` phases | Walk, reset, pause/unpause, a 16-row seam transect (0 holes), a ground-referenced wall probe (0/35) and a **facade occlusion probe** that fires sideways from the road centre and requires a blocking wall wherever a building is staged (0/9), plus a frame-time capture writing `Saved/Profiling/perf-walk-frametimes.csv` and logging `GigLine PERF:`. | | `gigline.SetupLogs` cvar | Spawn/input setup logging, **off by default** (`DefaultEngine.ini [ConsoleVariables]`); enable at runtime with `gigline.SetupLogs 1`. | ## Reference and concept generation diff --git a/Tools/hero_facade_build.py b/Tools/hero_facade_build.py index 204d0fa..7a5887a 100644 --- a/Tools/hero_facade_build.py +++ b/Tools/hero_facade_build.py @@ -74,7 +74,7 @@ def cube(name, x, y, z, dx, dy, dz, material=None): return obj -def cylinder(name, x, y, z0, z1, radius, material, vertices=24): +def cylinder(name, x, y, z0, z1, radius, material, vertices=24, smooth=True): bpy.ops.mesh.primitive_cylinder_add( vertices=vertices, radius=radius, @@ -85,6 +85,11 @@ def cylinder(name, x, y, z0, z1, radius, material, vertices=24): obj.name = name if material: obj.data.materials.append(material) + if smooth: + # Round parts must shade smoothly *around* the axis while keeping the + # caps creased. Without this the columns read as faceted prisms, and the + # FBX carries no smoothing groups at all (Unreal warns about it). + bpy.ops.object.shade_smooth_by_angle(angle=math.radians(35.0)) return obj @@ -313,7 +318,9 @@ def export_fbx(path): axis_up="Z", use_space_transform=True, use_mesh_modifiers=True, - mesh_smooth_type="OFF", + # "FACE" exports smoothing groups; without it every import logs + # "No smoothing group information was found for this mesh". + mesh_smooth_type="FACE", path_mode="AUTO", bake_space_transform=False, ) diff --git a/Tools/ue_hero_facade_import.py b/Tools/ue_hero_facade_import.py index 455aab0..b36fd6c 100644 --- a/Tools/ue_hero_facade_import.py +++ b/Tools/ue_hero_facade_import.py @@ -61,6 +61,16 @@ def measure_and_place(): if asset is None: log(f"MISSING {DEST}/SM_HeroFacade") return + # Collision: complex-as-simple, not auto-generated convex hulls. + # The facade is 95 separate parts across 26 m; Unreal's auto hull generation + # wraps them in a few coarse hulls that bulged into the street (the QA wall + # probe went 0/35 -> 2/35 after trying it). Complex-as-simple makes the real + # triangles the simple collision, so line traces and capsule sweeps block on + # the actual wall — the same approach used for the terrain, for the same + # reason. The flag lives on the asset, so save it explicitly. + unreal.GigLineAssetTools.set_complex_collision_as_simple(asset, True) + saved = unreal.EditorAssetLibrary.save_loaded_asset(asset) + log(f"collision: {unreal.GigLineAssetTools.get_collision_complexity(asset)} (saved={saved})") box = asset.get_bounding_box() mn, mx = box.min, box.max log(f"SM_HeroFacade bounds cm: size=({mx.x - mn.x:.1f}, {mx.y - mn.y:.1f}, {mx.z - mn.z:.1f}) " -- 2.47.3 From 286d9f6479189e12bec80ed7ae0d7cea8eee5cf9 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 18:00:59 +0100 Subject: [PATCH 7/9] refactor(tools): one FBX export preset instead of six copies The bpy.ops.export_scene.fbx argument block was duplicated in six scripts (hero, block frontage, north buildings, site, scale test, MPFB character) and all six carried mesh_smooth_type="OFF", which drops smoothing groups and made every Unreal import warn and every round part faceted. Tools/fbx_export_preset.py now owns the presets: - preset_kwargs(preset, selection, **overrides) is bpy-free and unit-tested; - export_static()/export_character() are thin wrappers that import bpy lazily; - ue_metric_v1 and ue_character_v1 keep the recorded scale contract (FBX_SCALE_NONE, apply_unit_scale, -Y forward / Z up) and use FACE smoothing. Callers switched: hero_facade_build, export_block_frontage, export_north_buildings, scale_test_export, mpfb_character_export, Art/blender/site/export_site_fbx. Verified by re-exporting every asset through the preset and re-importing all of them: 0 smoothing warnings on site, frontage and north buildings; packaging and -qaselftest all PASS (walk, transect 0 holes, wall probe 0/35, facade probe 0/9). 49 tool tests pass (9 new for the preset contract). --- Art/blender/hero/hero-facade-2026-11-07.blend | 4 +- Art/blender/site/export_site_fbx.py | 18 +--- Game/GigLine/Content/Hollywood/DemoMap.umap | 4 +- .../Hollywood/Frontage/SM_Budget_6822.uasset | 4 +- .../Frontage/SM_ElCapitanTheatre.uasset | 4 +- .../Frontage/SM_Hollywood_6806.uasset | 4 +- .../Frontage/SM_Hollywood_6902.uasset | 4 +- .../Frontage/SM_Hollywood_6922.uasset | 4 +- .../Hollywood/Frontage/SM_LeeDrug_6800.uasset | 4 +- .../Hollywood/North/SM_Madame_Tussauds.uasset | 4 +- .../North/SM_TCL_Chinese_Theatre.uasset | 4 +- .../Hollywood/Site/Crossing_Markings.uasset | 4 +- .../Content/Hollywood/Site/Kerb_North.uasset | 4 +- .../Content/Hollywood/Site/Kerb_South.uasset | 4 +- .../Content/Hollywood/Site/M_Asphalt.uasset | 2 +- .../Content/Hollywood/Site/M_Concrete.uasset | 2 +- .../Hollywood/Site/M_FacadeStone.uasset | 2 +- .../Content/Hollywood/Site/M_Ground.uasset | 2 +- .../Hollywood/Site/M_KerbConcrete.uasset | 2 +- .../Content/Hollywood/Site/M_RoadPaint.uasset | 2 +- .../Content/Hollywood/Site/M_Stucco.uasset | 2 +- .../Hollywood/Site/Road_Hollywood.uasset | 4 +- .../Hollywood/Site/Sidewalk_North.uasset | 4 +- .../Hollywood/Site/Sidewalk_South.uasset | 4 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 4 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- MEMORY.md | 23 +++++ Screenshots/demo/review-demo-crossing.png | 4 +- .../demo/review-demo-north-buildings.png | 4 +- Screenshots/demo/review-demo-spawn-view.png | 4 +- Screenshots/demo/review-demo-street-level.png | 4 +- Screenshots/review-character.png | 4 +- Screenshots/review-ground-contact.png | 4 +- Screenshots/review-hero-facade-front.png | 4 +- Screenshots/review-hero-facade-oblique.png | 4 +- Screenshots/review-hero-portals.png | 4 +- Screenshots/review-npc-prefab.png | 4 +- Screenshots/review-overview.png | 4 +- Screenshots/review-player-placement.png | 4 +- Screenshots/review-scale-cubes.png | 4 +- Screenshots/review-shadow-compare.png | 4 +- Tools/README.md | 1 + Tools/export_block_frontage.py | 18 +--- Tools/export_north_buildings.py | 18 +--- Tools/fbx_export_preset.py | 94 +++++++++++++++++++ Tools/hero_facade_build.py | 21 +---- Tools/mpfb_character_export.py | 20 +--- Tools/scale_test_export.py | 18 +--- Tools/tests/test_fbx_export_preset.py | 70 ++++++++++++++ 49 files changed, 283 insertions(+), 158 deletions(-) create mode 100644 Tools/fbx_export_preset.py create mode 100644 Tools/tests/test_fbx_export_preset.py diff --git a/Art/blender/hero/hero-facade-2026-11-07.blend b/Art/blender/hero/hero-facade-2026-11-07.blend index b97c286..975dd5b 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.blend +++ b/Art/blender/hero/hero-facade-2026-11-07.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a1fb7ce48fa6a8b82a629caa61b6678e79d001491dfc5b5a00ce49acd13d9f0 -size 139669 +oid sha256:f93518ea18939682b8056fbad2741199f0e9dad6db427f0a749573a07ae4f232 +size 139688 diff --git a/Art/blender/site/export_site_fbx.py b/Art/blender/site/export_site_fbx.py index 7680e32..4f26b77 100644 --- a/Art/blender/site/export_site_fbx.py +++ b/Art/blender/site/export_site_fbx.py @@ -15,6 +15,9 @@ import os import sys import bpy +sys.path.insert(0, os.path.join(os.path.join(os.path.dirname(__file__), "..", "..", ".."), "Tools")) +import fbx_export_preset as fbx_preset # noqa: E402 + MESHES = ("Terrain_DEM", "Road_Hollywood", "Sidewalk_South", "Sidewalk_North", "Kerb_South", "Kerb_North", "Crossing_Markings") @@ -60,20 +63,7 @@ def main(): _ = bpy.context.view_layer bpy.context.view_layer.objects.active = obj path = os.path.join(args.out, name + ".fbx") - bpy.ops.export_scene.fbx( - filepath=path, - use_selection=True, - object_types={"MESH"}, - apply_unit_scale=True, - apply_scale_options="FBX_SCALE_NONE", - axis_forward="-Y", - axis_up="Z", - use_space_transform=True, - use_mesh_modifiers=True, - mesh_smooth_type="OFF", - path_mode="AUTO", - bake_space_transform=False, - ) + fbx_preset.export_static(path, selection=True) if mirrored: # The flip is an export correction, not a change to the source: undo it. obj.scale.y *= -1.0 diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index c11114b..6523f7b 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab6fbc24a8ebaa48287b8d81e4b180000d5692134349e9bd26f46a90f5d297aa -size 54508 +oid sha256:3239737465e1695fc16868978aabcca4767055e1ab45cb1c222591b7ff2bda22 +size 54516 diff --git a/Game/GigLine/Content/Hollywood/Frontage/SM_Budget_6822.uasset b/Game/GigLine/Content/Hollywood/Frontage/SM_Budget_6822.uasset index 29c9048..fd8d792 100644 --- a/Game/GigLine/Content/Hollywood/Frontage/SM_Budget_6822.uasset +++ b/Game/GigLine/Content/Hollywood/Frontage/SM_Budget_6822.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cc532260823c0b6dfd943744300fb5cbeff8ab87f63ceb092717641759b014a -size 78278 +oid sha256:04eea883885521fadfc2675c4ee93c7aba61cbbf84e464d34a634f1b778bc161 +size 78284 diff --git a/Game/GigLine/Content/Hollywood/Frontage/SM_ElCapitanTheatre.uasset b/Game/GigLine/Content/Hollywood/Frontage/SM_ElCapitanTheatre.uasset index c93c236..7182b89 100644 --- a/Game/GigLine/Content/Hollywood/Frontage/SM_ElCapitanTheatre.uasset +++ b/Game/GigLine/Content/Hollywood/Frontage/SM_ElCapitanTheatre.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97b279689536abc54f2dae5f78b9a82a1fe2bd138ee76557de279e9c7a48d7f3 -size 79377 +oid sha256:92b4a9e1ffebdec61f477c62228b02074d1afed6e76288b9cac7cfc21479bf94 +size 79348 diff --git a/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6806.uasset b/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6806.uasset index 7fcfeb4..f8f5611 100644 --- a/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6806.uasset +++ b/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6806.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4b522b03d10b7c5c98627f199c426143122f6c0e1d1d6d82938174152ca42d6 -size 79018 +oid sha256:21faaa28e97235717b973e3827604805edd88195fb0997c1ff374e8e04f4186a +size 78998 diff --git a/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6902.uasset b/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6902.uasset index 6799faf..49ee421 100644 --- a/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6902.uasset +++ b/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6902.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60f3a08ac1493fe918da2e38ad7b4355763a39cf90c7e9e6016911cd3505c46c -size 78339 +oid sha256:86082f721699b618c0989d250861bd6a079c45bc321f9472c191344ad3a9fef3 +size 78349 diff --git a/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6922.uasset b/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6922.uasset index 324bac4..8ffa7e4 100644 --- a/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6922.uasset +++ b/Game/GigLine/Content/Hollywood/Frontage/SM_Hollywood_6922.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1704908dd0d66a25672fdf6b1c8f3b8b731e361e38b33077b67dce3e6dd747e -size 78896 +oid sha256:2c06ffd414b54a3c8383344da54baf05938ba3aa2a6322f3d6801b2f7cc1ccfc +size 78881 diff --git a/Game/GigLine/Content/Hollywood/Frontage/SM_LeeDrug_6800.uasset b/Game/GigLine/Content/Hollywood/Frontage/SM_LeeDrug_6800.uasset index f683ef8..a0948ea 100644 --- a/Game/GigLine/Content/Hollywood/Frontage/SM_LeeDrug_6800.uasset +++ b/Game/GigLine/Content/Hollywood/Frontage/SM_LeeDrug_6800.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c3c8df33dd9aee5d6175c9f3ad50e4b453461750bdb3ea5543f61e4a63fa19c -size 78091 +oid sha256:ad59e28c16e965ddd814e69d9510233f93b44410bf42d5602e36609124879465 +size 78097 diff --git a/Game/GigLine/Content/Hollywood/North/SM_Madame_Tussauds.uasset b/Game/GigLine/Content/Hollywood/North/SM_Madame_Tussauds.uasset index dfc957a..08c9aa6 100644 --- a/Game/GigLine/Content/Hollywood/North/SM_Madame_Tussauds.uasset +++ b/Game/GigLine/Content/Hollywood/North/SM_Madame_Tussauds.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e62e32b685cecfc0d5a9071e4fc1a2fa634768f5f68be73eb8b52b3011960a0 -size 79860 +oid sha256:6916ce5e1856eaefccce5faa3d688f0bdb6398a2dcc56a872ceb00080db7993b +size 79982 diff --git a/Game/GigLine/Content/Hollywood/North/SM_TCL_Chinese_Theatre.uasset b/Game/GigLine/Content/Hollywood/North/SM_TCL_Chinese_Theatre.uasset index 823a712..d8f0531 100644 --- a/Game/GigLine/Content/Hollywood/North/SM_TCL_Chinese_Theatre.uasset +++ b/Game/GigLine/Content/Hollywood/North/SM_TCL_Chinese_Theatre.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2ee1d5bd60aa0368f9ec110efdd4618c8b0ac924bbd06af34e31ce5d302ef17 -size 80261 +oid sha256:6ba67436b139db9375a1e43d05ea5fdd9c4770f4f778f3ace12cc7a47426222f +size 80253 diff --git a/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset b/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset index 2f48750..e7c6d84 100644 --- a/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90e9c5586b43bd8a5073fdd98b48e477c0369dbfb935752a2e832b046c4ac9f1 -size 75501 +oid sha256:b87aee07bd35898e3acd37cc9f6c595cad62e68aaa68ff93db424687b983738b +size 75559 diff --git a/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset b/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset index e451175..57b7e5e 100644 --- a/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:096d4e05ce88191ce821b1987b973fdeed6f30ac67414ba50d40dc74e0341c41 -size 83558 +oid sha256:7fe2e4298ba7ac5d214cee36a604926ceadcdb929b643bdc0e571ac9de6354d4 +size 83660 diff --git a/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset b/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset index e1c291a..7a6b66b 100644 --- a/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c611c9f32b52c569b3e4c9a9cd337a2227f3d678b69e7033123a678bb9aa8d3f -size 83802 +oid sha256:cee2405bd726e30658551592811b4f7ade9d09eb53a3f5d7f7ac437b07f477c5 +size 84070 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index b5f45fe..55afb15 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:492410ca526af9484ed9d2f35139b05c00072fdf93156e470c4dea697913804b +oid sha256:1573ce34e0eedd36e9fea9c3b7870c3a7e40cd7763feeeafcf406f6821e1ddfa size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index 5f25f89..43ced3c 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01c5f65d30f0502c08ae6c3d0a6149bf22cd3cc6964386fab7823006433d09a7 +oid sha256:7ed5ce4a4a8d007723859d1bf72f8cda4dc44a0a1516861388cf453a8ed51bd8 size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index da554a9..e08b823 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab055873e8dd41063966798974289109b1a402fedc9856a0e8e8f22d5575c382 +oid sha256:d9e56b813e652f1db48f0d2c06fb971a3e626ac8a7db2355b844bed7e9cb0a9e size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 601239b..4dd5e9c 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ceb456eaaa65eb883ff9b5601d1da6801349396ffaff50d956eca62f8978c57 +oid sha256:f602277d7e29590cc74edc68947bfaf4005bb1b725b893048999bef871965e29 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index 78ed54a..ce1583d 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:95591e094b01819fe8fd4ccc36241c1c71aa9b364689e555468191f4a74992d5 +oid sha256:a33a56d8da461099abc07e4d2608c461fa6ecf64e86901a751ebd123a35c7b01 size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index ee34264..cab50f8 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:514e92d6639134304adb30c845cdcc4ce5d21debc4088e78de5446ae6949dafd +oid sha256:df8b9571db76547fcb0c14b17440434aa865cf06fede0870edddbe57c25a13c7 size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index 669842d..2835530 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12a5691b007ae60ced3f3bab90abd9a08825a460206dec097a589c94f58228ba +oid sha256:17de1d539b838415aa76f4637feabc200991ee52671dce1546da6564d6bc0761 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset b/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset index 2c299df..fdebf3d 100644 --- a/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a48b4b61a9a062c19d1f604634fb349eb5ea59def82803574b3b3376f7241f09 -size 309812 +oid sha256:496a3d53741a35ac7d45ba894c8c9661c39b4e922f968177795f818400dca192 +size 311045 diff --git a/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset b/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset index 5ae5e2d..f6ff33d 100644 --- a/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3534e2ba61975bb8c350cb0b3a78624b6ca90b8c92e0acb725c053883dcfaf29 -size 150179 +oid sha256:6e850dd628c7809e1607d748e97903b736780b215462efb2e9550abedec59b38 +size 150199 diff --git a/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset b/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset index fe14cd8..1587e25 100644 --- a/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b3113c472a0b83f6ba369efc8cdec91c0f7aa08c0b859c00661a624303253bb -size 164880 +oid sha256:1f979437847aa453436acbea6b0e5ae474f50d75da51a7d5cdca9782fcb9b790 +size 162907 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index 5f66af5..3f1cab2 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48ff0d06e31cb7824b60c2e13b9555c20c7b03d45cfd4efcab2f72ca61fb16b9 -size 335528 +oid sha256:ecff60acd3e6f7149564003fe68fb9fc8a89c21c9d0eebdafa6f8ae59c6ab270 +size 357901 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index 6bca92a..88400fa 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:631a70bc5f98ececab410ab698bc2047a7f65e3e2d010c679988bef28f70b430 +oid sha256:a39dff6294d91f55ab3ea581c8c1a7f663cbe2214e61d2836491d06965f383e8 size 28706 diff --git a/MEMORY.md b/MEMORY.md index 31ae523..63bd5ff 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -460,3 +460,26 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. - Probe expectations must mirror the staged buildings: the facade probe now carries explicit X spans per frontage (and the TCL/Tussaud's spans on the north side) so a gap between buildings is not reported as a defect. + +## 2026-11-09 — one FBX export preset instead of six copies + +- The `bpy.ops.export_scene.fbx(...)` argument block was duplicated in six scripts + (hero, block frontage, north buildings, site, scale test, MPFB character), and + all six carried `mesh_smooth_type="OFF"` — hence the "No smoothing group + information was found" warning on every import. +- Now `Tools/fbx_export_preset.py` holds `ue_metric_v1` and `ue_character_v1`: + `preset_kwargs()` (bpy-free, unit-tested) plus `export_static()` / + `export_character()` wrappers that import `bpy` lazily. Every caller imports it + and passes `selection=True/False`; the seven duplicated blocks are gone. +- Callers in `Tools/` resolve the module with + `sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))`; the Blender-side + `Art/blender/site/export_site_fbx.py` computes the repo root + (`..`, `..`, `..`) and joins `Tools`. Getting that wrong silently inserts + `Tools/Tools` — check the import path when adding a caller. +- Verified end to end: scale test, hero, frontage (6/6), site (7/7) and north + buildings all re-exported through the preset, re-imported with **0 smoothing + warnings**, DemoMap rebuilt and `-qaselftest` all PASS (walk, transect 0 holes, + wall probe 0/35, facade probe 0/9). +- `mpfb_character_export.py` was not re-run: it needs the MPFB add-on on + `BLENDER_USER_SCRIPTS` ("Add-on not loaded: bl_ext.blender_org.mpfb"), which is + pre-existing and unrelated; the character is not in `0.1.x` gameplay. diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index 53583a0..860efee 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c0144a5d8ad74cc56b512099e0bccf1b4913cc0969a40e2353a5d7b6c88dc4c -size 2670411 +oid sha256:4ced7093dbfd87341f26824b3d383afcadba6b84d02e9d22b46dcae504107dcf +size 2555823 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index 3f0fd57..9c49c20 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf0a8b0f98a3a8e37c6708a1ba6f37fce92d1954e5d02e8ef8051fdc669ad8f9 -size 2505075 +oid sha256:8922ee977c1d89df3d4d9e10caa2785f87deecd17bee4624cf5dbfbdeecadb73 +size 2238947 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 0fd459c..7a36e08 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25fb859414e73ccc043ab5cbba352bdab1ed45e668d82d3a1c4ccdd4f6e36441 -size 2627108 +oid sha256:cf464077cd4a79302b33d7f88be63aee6f586ab761c030cfb67661945eeee493 +size 2640409 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 5f559d9..de7adf8 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01c7e5f2385b9f4c7457b7d15745757568f5c26329b3db4ef08d44742ff5a25d -size 2448129 +oid sha256:6f6eb060018bd904b1e55eeaf1607fff013cec44334ecdc76a1b0f1dad17cb06 +size 2419233 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index 85e752d..4c51cc6 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6984bfec9d9d04e71ae10dd0e950f4bef7c82721e8c72abe70542ae7446e644f -size 2750769 +oid sha256:b5e133239d976a0c451845b126a4139afec85055592752639db430640c714f0d +size 2762684 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 9ed90e0..faa7954 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:797c379922881c6db39bb8afd710283e5c0d5928919b4214eb98ab0d2e89ebe5 -size 1817363 +oid sha256:d3ff3ccb37e39df6a85b46d55e42c830eedb472cca58784126dbc0c92f3cacd8 +size 1826522 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index 134198e..be22d0e 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e46779f2b62816fab2f651b3d61bd780f2d98926a2f1b3eecbf36d09fedda41 -size 1731572 +oid sha256:f08a527395660a98d8b39af4356ccdf1a38d7e3cab19ce7ad560cfd12a75c749 +size 1743785 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index b6db3e6..8dfd265 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c054e9e5edc10864f0a68f91248ec586121ba58cd57fac5509e0967859156594 -size 1399505 +oid sha256:29605038bf303924976deec33896c5534b65d43233ce3bc587c3e8a0320ebd65 +size 1402114 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index d3bcd07..6fed5e6 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43bc085789469e32f656e910996dd2a9b4744cae1a0fcb8670e69d8625c94876 -size 1367381 +oid sha256:9ae371b126e13e24610ca9358a10bc9524702ad3dda9ce672fcaac44bb03dc8e +size 1373251 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index 3140e12..26c6dd5 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:645767d4184dedc7569d9a443cf7c855f1205b8dfd85c7ccbcd16068bcb26c97 -size 1802903 +oid sha256:d26ee7178f4b7bd23c028d19e7cb8ded4109bbf6864f95c3e56e28c5eeed8c32 +size 1804784 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index c45ae01..e844489 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ca2ac170c369b2093c0b4bbb06bdf0cce318c897e75b74363a31bf56858bdab -size 2393713 +oid sha256:232ba45b93dc9871ec79363ba29033ef2ddf56bf2b90ed712718b136be3638f2 +size 2419553 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index ff8ca06..70a7a50 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16985e7229cd275af3567e9999e45c51db14dd2d9ab6e305bd16cbb77f5076c0 -size 2212611 +oid sha256:2b0d3c22b5e642a5ef4586f452e50753649923835ed41b7c9310a257fb124fca +size 2211043 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index ec70c6e..4b31d9b 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e0d634aeb2adb125981cefabd3be2f54de7e64d6ab2de0baaa00d73e5539b01 -size 2147701 +oid sha256:89c4381b77b18eebc27c1df85bd31ce1cba4b2f89fc73dbdb312cb60013f318f +size 2140459 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index 3229eca..a922f66 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62940b77df50ddab2d2e9dd813c2f09c8fe83ec8f4cc755d4cfc47a3145800db -size 1851501 +oid sha256:c3b6f8d9cc11087da4f7b47c3ed6e49af45098094ce29a2d729e137cabb4bb5b +size 1852570 diff --git a/Tools/README.md b/Tools/README.md index 2be84e2..efd3dca 100644 --- a/Tools/README.md +++ b/Tools/README.md @@ -16,6 +16,7 @@ Geographic tools live in [`Geo/tools/`](../Geo/README.md) and the Blender-side b | Tool | Purpose | | --- | --- | | `check-lfs.sh` | Fails if the `lfs` filter is missing or an LFS-tracked file was committed as a plain blob | +| `fbx_export_preset.py` | The **single** FBX export preset (`ue_metric_v1` / `ue_character_v1`): metres→centimetres via `FBX_SCALE_NONE`, axis mapping east +X / north −Y / up +Z, `mesh_smooth_type="FACE"` (smoothing groups survive the import). Every Blender exporter imports it instead of copying the argument block; `preset_kwargs()` is bpy-free and unit-tested. | | `sibling_asset_audit.py` | Reads the sibling project's prop library from GLB headers into `Art/props/reuse-manifest.json`; copies nothing | | `scale_test_export.py` / `ue_scale_test_import.py` | The 1 m = 100 uu scale test; the named presets `ue_metric_v1` live in these two files | diff --git a/Tools/export_block_frontage.py b/Tools/export_block_frontage.py index 50e7670..a03d9df 100644 --- a/Tools/export_block_frontage.py +++ b/Tools/export_block_frontage.py @@ -19,6 +19,9 @@ import os import sys import bpy +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import fbx_export_preset as fbx_preset # noqa: E402 + # blockout object name -> (asset name, note). Addresses from the verification doc. BUILDINGS = { @@ -69,20 +72,7 @@ def main(): bpy.context.view_layer.objects.active = new_obj path = os.path.join(args.out, asset_name + ".fbx") - bpy.ops.export_scene.fbx( - filepath=path, - use_selection=True, - object_types={"MESH"}, - apply_unit_scale=True, - apply_scale_options="FBX_SCALE_NONE", - axis_forward="-Y", - axis_up="Z", - use_space_transform=True, - use_mesh_modifiers=True, - mesh_smooth_type="OFF", - path_mode="AUTO", - bake_space_transform=False, - ) + fbx_preset.export_static(path, selection=True) world = new_obj.matrix_world zs = [(world @ v.co).z for v in new_mesh.vertices] ys = [(world @ v.co).y for v in new_mesh.vertices] diff --git a/Tools/export_north_buildings.py b/Tools/export_north_buildings.py index 6224772..06dfd50 100644 --- a/Tools/export_north_buildings.py +++ b/Tools/export_north_buildings.py @@ -13,6 +13,9 @@ import os import sys import bpy +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import fbx_export_preset as fbx_preset # noqa: E402 + BUILDINGS = ("TCL Chinese Theatre", "Madame Tussaud's") @@ -50,20 +53,7 @@ def main(): bpy.context.view_layer.objects.active = new_obj path = os.path.join(args.out, name.replace(" ", "_").replace("'", "") + ".fbx") - bpy.ops.export_scene.fbx( - filepath=path, - use_selection=True, - object_types={"MESH"}, - apply_unit_scale=True, - apply_scale_options="FBX_SCALE_NONE", - axis_forward="-Y", - axis_up="Z", - use_space_transform=True, - use_mesh_modifiers=True, - mesh_smooth_type="OFF", - path_mode="AUTO", - bake_space_transform=False, - ) + fbx_preset.export_static(path, selection=True) world = new_obj.matrix_world zs = [(world @ v.co).z for v in new_mesh.vertices] print(f"[north] {name:22} verts {len(new_mesh.vertices):5} z {min(zs):+.2f}..{max(zs):+.2f} m " diff --git a/Tools/fbx_export_preset.py b/Tools/fbx_export_preset.py new file mode 100644 index 0000000..d36ede5 --- /dev/null +++ b/Tools/fbx_export_preset.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""The one FBX export preset for this project ("ue_metric_v1"/"ue_character_v1"). + +Before this module the same `bpy.ops.export_scene.fbx(...)` argument block was +copied into six scripts (hero, frontage, north buildings, site, scale test, MPFB +character). They had already drifted only by accident, and every one of them +carried `mesh_smooth_type="OFF"` — which is why Unreal logged "No smoothing group +information was found for this mesh" on every import and round parts rendered +faceted. One preset, one place to fix that. + +Use from inside Blender: + + import sys, os + sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "Tools")) + import fbx_export_preset as preset + + preset.export_static(path) # whole scene, MESH only + preset.export_static(path, selection=True) # selected objects only + preset.export_character(path) # armature + mesh, character flags + +`preset_kwargs()` is pure (no `bpy`), so the argument set can be unit-tested +without Blender — see Tools/tests/test_fbx_export_preset.py. + +Why these values: +* `FBX_SCALE_NONE` + `apply_unit_scale` keeps Blender metres → Unreal centimetres + at exactly ×100, verified by the three-cube scale test (1 m → 100.00 uu). +* `axis_forward="-Y"`, `axis_up="Z"` is the project's recorded mapping: east → +X, + north → −Y, up → +Z. +* `mesh_smooth_type="FACE"` exports smoothing groups. `"OFF"` (the old value) + drops them, so Unreal rebuilds flat normals and every cylinder is faceted. +* `use_mesh_modifiers=True` bakes the bevel/modifier stack at export; the source + `.blend` stays non-destructive. +""" + +from __future__ import annotations + +# Shared by every mesh export. Values are the recorded ue_metric_v1 preset. +_METRIC = { + "object_types": {"MESH"}, + "apply_unit_scale": True, + "apply_scale_options": "FBX_SCALE_NONE", + "axis_forward": "-Y", + "axis_up": "Z", + "use_space_transform": True, + "use_mesh_modifiers": True, + "mesh_smooth_type": "FACE", + "path_mode": "AUTO", + "bake_space_transform": False, +} + +# Character exports differ only in the object set and the armature/path flags. +_CHARACTER = dict( + _METRIC, + object_types={"ARMATURE", "MESH"}, + add_leaf_bones=False, + path_mode="COPY", + embed_textures=False, +) + +PRESETS = {"ue_metric_v1": _METRIC, "ue_character_v1": _CHARACTER} + + +def preset_kwargs(preset: str = "ue_metric_v1", selection: bool = False, **overrides) -> dict: + """Return the `bpy.ops.export_scene.fbx` argument dict (no `bpy` needed). + + `preset` selects the base set, `selection` decides whether only selected + objects are exported, and `overrides` wins last for the rare special case. + """ + if preset not in PRESETS: + raise KeyError(f"unknown preset {preset!r}; known: {sorted(PRESETS)}") + kwargs = dict(PRESETS[preset]) + kwargs["use_selection"] = bool(selection) + kwargs.update(overrides) + if "filepath" in kwargs: + raise ValueError("pass the path to export_static/export_character, not as an override") + return kwargs + + +def _export(path: str, preset: str, selection: bool, overrides: dict) -> str: + import bpy # imported here so `preset_kwargs` stays usable without Blender + + kwargs = preset_kwargs(preset, selection=selection, **overrides) + bpy.ops.export_scene.fbx(filepath=path, **kwargs) + return path + + +def export_static(path: str, selection: bool = False, **overrides) -> str: + """Export meshes with the ue_metric_v1 preset. Returns the path.""" + return _export(path, "ue_metric_v1", selection, overrides) + + +def export_character(path: str, selection: bool = False, **overrides) -> str: + """Export armature + mesh with the ue_character_v1 preset. Returns the path.""" + return _export(path, "ue_character_v1", selection, overrides) diff --git a/Tools/hero_facade_build.py b/Tools/hero_facade_build.py index 7a5887a..2afca9a 100644 --- a/Tools/hero_facade_build.py +++ b/Tools/hero_facade_build.py @@ -33,6 +33,9 @@ import os import sys import bpy +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import fbx_export_preset as fbx_preset # noqa: E402 + # --- measured / derived ------------------------------------------------------ FRONTAGE_W = 25.75 @@ -306,24 +309,10 @@ def build(): def export_fbx(path): + # Preset lives in Tools/fbx_export_preset.py (ue_metric_v1). os.makedirs(os.path.dirname(path), exist_ok=True) # Named export preset "ue_metric_v1" - same settings as Tools/scale_test_export.py. - bpy.ops.export_scene.fbx( - filepath=path, - use_selection=False, - object_types={"MESH"}, - apply_unit_scale=True, - apply_scale_options="FBX_SCALE_NONE", - axis_forward="-Y", - axis_up="Z", - use_space_transform=True, - use_mesh_modifiers=True, - # "FACE" exports smoothing groups; without it every import logs - # "No smoothing group information was found for this mesh". - mesh_smooth_type="FACE", - path_mode="AUTO", - bake_space_transform=False, - ) + fbx_preset.export_static(path) print(f"[hero] exported FBX preset ue_metric_v1 -> {path}") diff --git a/Tools/mpfb_character_export.py b/Tools/mpfb_character_export.py index 37d15f5..a37dd4a 100644 --- a/Tools/mpfb_character_export.py +++ b/Tools/mpfb_character_export.py @@ -19,6 +19,9 @@ import sys import zlib import bpy +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import fbx_export_preset as fbx_preset # noqa: E402 + import numpy from mathutils import Euler @@ -149,22 +152,7 @@ def make_diffuse(human, size=1024): def export_fbx(human, path): os.makedirs(os.path.dirname(path), exist_ok=True) # Named export preset "ue_character_v1" — change only via a new preset name. - bpy.ops.export_scene.fbx( - filepath=path, - use_selection=False, - object_types={"ARMATURE", "MESH"}, - apply_unit_scale=True, - apply_scale_options="FBX_SCALE_NONE", - axis_forward="-Y", - axis_up="Z", - use_space_transform=True, - use_mesh_modifiers=True, - add_leaf_bones=False, - path_mode="COPY", - embed_textures=False, - mesh_smooth_type="OFF", - bake_space_transform=False, - ) + fbx_preset.export_character(path) log(f"export: FBX preset ue_character_v1 -> {path}") diff --git a/Tools/scale_test_export.py b/Tools/scale_test_export.py index bf46f0a..ffac49e 100644 --- a/Tools/scale_test_export.py +++ b/Tools/scale_test_export.py @@ -16,6 +16,9 @@ import os import sys import bpy +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import fbx_export_preset as fbx_preset # noqa: E402 + def build_scene(): @@ -44,20 +47,7 @@ def build_scene(): def export_fbx(path): os.makedirs(os.path.dirname(path), exist_ok=True) # Named export preset "ue_metric_v1" - change only via a new preset name. - bpy.ops.export_scene.fbx( - filepath=path, - use_selection=False, - object_types={"MESH"}, - apply_unit_scale=True, - apply_scale_options="FBX_SCALE_NONE", - axis_forward="-Y", - axis_up="Z", - use_space_transform=True, - use_mesh_modifiers=True, - mesh_smooth_type="OFF", - path_mode="AUTO", - bake_space_transform=False, - ) + fbx_preset.export_static(path) print(f"[scale_test] exported FBX preset ue_metric_v1 -> {path}") diff --git a/Tools/tests/test_fbx_export_preset.py b/Tools/tests/test_fbx_export_preset.py new file mode 100644 index 0000000..e86013e --- /dev/null +++ b/Tools/tests/test_fbx_export_preset.py @@ -0,0 +1,70 @@ +"""Tests for Tools/fbx_export_preset.py. + +The preset module keeps its argument set in plain dicts and builds it in +`preset_kwargs()`, so the export contract can be checked without starting +Blender. Only `export_static`/`export_character` import `bpy`. +""" + +import os +import sys +import unittest + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +sys.path.insert(0, os.path.join(ROOT, "Tools")) + +import fbx_export_preset as preset # noqa: E402 + + +class MetricPresetTest(unittest.TestCase): + def test_scale_and_axis_contract(self): + # These three are the project's recorded conversion contract: metres -> + # centimetres by a factor of exactly 100, east +X, north -Y, up +Z. + kwargs = preset.preset_kwargs() + self.assertTrue(kwargs["apply_unit_scale"]) + self.assertEqual(kwargs["apply_scale_options"], "FBX_SCALE_NONE") + self.assertEqual(kwargs["axis_forward"], "-Y") + self.assertEqual(kwargs["axis_up"], "Z") + + def test_smoothing_groups_are_exported(self): + # "OFF" (the pre-refactor value) drops smoothing groups and every Unreal + # import warns about it, with round parts faceted. + self.assertEqual(preset.preset_kwargs()["mesh_smooth_type"], "FACE") + + def test_selection_flag(self): + self.assertFalse(preset.preset_kwargs()["use_selection"]) + self.assertTrue(preset.preset_kwargs(selection=True)["use_selection"]) + + def test_object_types_are_meshes_only(self): + self.assertEqual(preset.preset_kwargs()["object_types"], {"MESH"}) + + +class CharacterPresetTest(unittest.TestCase): + def test_character_exports_armature_and_mesh(self): + kwargs = preset.preset_kwargs("ue_character_v1") + self.assertEqual(kwargs["object_types"], {"ARMATURE", "MESH"}) + self.assertFalse(kwargs["add_leaf_bones"]) + self.assertEqual(kwargs["path_mode"], "COPY") + self.assertFalse(kwargs["embed_textures"]) + + def test_character_keeps_the_scale_contract(self): + kwargs = preset.preset_kwargs("ue_character_v1") + self.assertEqual(kwargs["apply_scale_options"], "FBX_SCALE_NONE") + self.assertEqual(kwargs["mesh_smooth_type"], "FACE") + + +class OverrideTest(unittest.TestCase): + def test_overrides_win(self): + kwargs = preset.preset_kwargs(mesh_smooth_type="OFF") + self.assertEqual(kwargs["mesh_smooth_type"], "OFF") + + def test_unknown_preset_raises(self): + with self.assertRaises(KeyError): + preset.preset_kwargs("ue_imperial_v9") + + def test_filepath_must_not_be_an_override(self): + with self.assertRaises(ValueError): + preset.preset_kwargs(filepath="/tmp/x.fbx") + + +if __name__ == "__main__": + unittest.main() -- 2.47.3 From e86f183c53ce7aef0ab106b84b514d1c09e063d8 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 18:06:18 +0100 Subject: [PATCH 8/9] =?UTF-8?q?release:=20v0.1.2=20=E2=80=94=20cornice=20d?= =?UTF-8?q?entils,=20changelog=20entry,=20TODO=20pruning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Hero cornice finished: projecting corona over a 52-dentil course (0.18 x 0.30 x 0.22 m at 0.45 m centres) so the top of the order has a shadow line instead of one flat box. Hero 3044 tris / 148 parts, still 14.50 m; rebuilt, re-imported, DemoMap rebuilt, packaged -qaselftest all PASS, screenshots re-rendered. - CHANGELOG: full 0.1.2 entry (added: concept generator, FBX preset, facade probe, Ionic detail, tool tests; changed: 3.1 m storey height, 53.1% colonnade, smoothing groups; fixed: floating windows, flat medallions, missing facade collision, the three non-building heights). - TODO: 0.1.2 section removed (goal stays in ROADMAP, whose status line is updated). - MEMORY: release record incl. the recorded ornament assumptions. --- Art/blender/hero/hero-facade-2026-11-07.blend | 4 +- Art/blender/hero/hero-facade-2026-11-07.json | 9 + CHANGELOG.md | 162 ++++++++---------- Game/GigLine/Content/Hollywood/DemoMap.umap | 4 +- .../Hollywood/ElCapitan/SM_HeroFacade.uasset | 4 +- .../Content/Hollywood/Site/M_Asphalt.uasset | 2 +- .../Content/Hollywood/Site/M_Concrete.uasset | 2 +- .../Hollywood/Site/M_FacadeStone.uasset | 2 +- .../Content/Hollywood/Site/M_Ground.uasset | 2 +- .../Hollywood/Site/M_KerbConcrete.uasset | 2 +- .../Content/Hollywood/Site/M_RoadPaint.uasset | 2 +- .../Content/Hollywood/Site/M_Stucco.uasset | 2 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 2 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- MEMORY.md | 12 ++ Screenshots/README.md | 2 +- .../demo/review-demo-north-buildings.png | 4 +- Screenshots/demo/review-demo-spawn-view.png | 4 +- Screenshots/review-character.png | 4 +- Screenshots/review-ground-contact.png | 4 +- Screenshots/review-hero-facade-front.png | 4 +- Screenshots/review-hero-facade-oblique.png | 4 +- Screenshots/review-hero-portals.png | 4 +- Screenshots/review-npc-prefab.png | 4 +- Screenshots/review-overview.png | 4 +- Screenshots/review-player-placement.png | 4 +- Screenshots/review-scale-cubes.png | 4 +- Screenshots/review-shadow-compare.png | 4 +- TODO.md | 12 -- Tools/hero_facade_build.py | 20 ++- 30 files changed, 151 insertions(+), 144 deletions(-) diff --git a/Art/blender/hero/hero-facade-2026-11-07.blend b/Art/blender/hero/hero-facade-2026-11-07.blend index 975dd5b..8d91f5a 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.blend +++ b/Art/blender/hero/hero-facade-2026-11-07.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f93518ea18939682b8056fbad2741199f0e9dad6db427f0a749573a07ae4f232 -size 139688 +oid sha256:cadc2469e3e9fb41dc379a1c61489054533819478fa74befecaa37adcfdadd97 +size 158985 diff --git a/Art/blender/hero/hero-facade-2026-11-07.json b/Art/blender/hero/hero-facade-2026-11-07.json index a93b843..00d70b6 100644 --- a/Art/blender/hero/hero-facade-2026-11-07.json +++ b/Art/blender/hero/hero-facade-2026-11-07.json @@ -73,6 +73,15 @@ ], "evidence": "assumption: projecting cornice line" }, + { + "object": "Hero_Dentil_xN", + "dims_m": [ + 0.18, + 0.3, + 0.22 + ], + "evidence": "52 dentils at 0.45 m centres under the corona; assumption: photographed cornice reads as a dentilled course" + }, { "object": "Hero_Entablature", "dims_m": [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d1e3e4..5aa8adb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,127 +8,109 @@ Format: [Keep a Changelog](https://keepachangelog.com/) style, versions follow [ Nothing yet. -## [0.1.1] — 2026-11-08 +## [0.1.2] — 2026-11-09 -Collision-fidelity patch. No new scope: street geometry corrections and the QA -tooling that measures them. - -### Fixed - -- **Sidewalk outer edge ledge.** The sidewalk stood the full 0.15 m kerb height - above the DEM at both edges, leaving a 15.8 cm lip where the walk route crossed - from terrain onto the south sidewalk. The upstand now tapers from full at the - road-side edge to zero at the building-side edge; the north route's worst step - fell from 15.1 cm to 6.9 cm. -- **Crossing ramps too steep.** The kerb-flush run was a fixed 1.5 m, giving - ~8.7 % (measured 10–13 cm over 1.5 m). The run is now derived from a target - grade (`--max-ramp-grade`, default 8 % ⇒ 1.63 m); the crossing steps 3.4 cm at - 0.25 m sampling. +Scale and façade correction patch. Buildings and the hero elevation now match the reference photography and the cross-checked height data; no new gameplay scope. ### Added -- **Walk pre-check improvements** (`Art/blender/site/site_assembly.py`): sampling - coverage is independent of `--sample` (it previously shrank the route), and the - report now prints the grade and the arc-length/offset **location** of the worst - step, so a step can be located rather than guessed. +- **`Tools/facade_detail_concepts.py`** — generates frontal building plates (whole elevation, entrance in its façade, building with neighbours) from a local reference photograph through OpenRouter image models. Spec-driven, never overwrites, writes a provenance sidecar per image, output stays in the gitignored `Art/reference/` tree. Local working material only. +- **`Tools/fbx_export_preset.py`** — the single FBX export preset (`ue_metric_v1` / `ue_character_v1`). Replaces the argument block that had been copied into six exporters. +- **Façade occlusion probe** in `-qaselftest`: 40 m traces sideways from the road centre at walking height, required wherever a building is staged. +- **Ionic detail on the hero**: base moulding at every shaft foot, a square abacus over every capital, and a 52-dentil cornice course. +- **Tool tests**: `Tools/tests/` now covers the input driver, height classification, the Mapbox cross-check, the concept generator and the FBX preset (49 tests). ### Changed -- **Kerb height recorded as final** at 0.15 m modelled / 0.13 m as built — a - standard 6 in LA kerb; neither the 3DEP DEM nor the reference photography can - resolve it further (±2 cm), which is far below the character's 45 cm step - height. +- **Storey height 3.2 → 3.1 m**, calibrated against Mapbox building data, with explicit overrides for three rear outbuildings; the block cross-check now reports 66 matches and no disagreements. +- **Hero colonnade 47.6 % → 53.1 %** of the 14.50 m elevation, inside the photographed 50–60 % band (thinner entablature and parapet). +- Blockout regenerated at the new storey height; frontage re-exported and re-imported (6922 42.1 → 39.1 m, El Capitan Theatre 20.0 → 20.5 m). +- FBX exports now carry smoothing groups (`FACE` instead of `OFF`), so round geometry is no longer faceted and imports stop warning. + +### Fixed + +- **Windows floated 1.44 m in front of the wall**, ahead of the colonnade; they now sit on the wall plane behind the columns. +- **Parapet medallions were flat discs lying on the coping** instead of discs on the parapet face. +- **The hero façade had no usable collision** — the player could walk through it. It is now complex-as-simple; auto-generated convex hulls were tried and rejected because they bulged into the street. +- **The three "guessed" block heights were never buildings**: two `building=roof` canopies and a transit shelter. They are classified as non-building volumes and the block now reports zero guessed heights. ### Verified -- Site meshes rebuilt and re-imported (7/7, collision flags intact), DemoMap - rebuilt, packaged Development build `EXIT=0`. -- `-qaselftest` on the packaged build: walk 761 cm in 2 s at steady Z 456, reset - 0 cm, pause/unpause, transect 1456 samples across 16 rows / **0 holes**, wall - probe **0/35** blocking hits. +- Packaged build `-qaselftest`: walk, reset and pause pass; seam transect 1456 samples / 0 holes; wall probe 0/35; façade probe 0/9. +- Screenshots re-rendered for every change and approved by the owner. ### Known limitations -- One residual **13.4 cm surface step at s≈198 m** on the south sidewalk (8.0 cm - at s≈251 m north). It is not a gap and is below the 45 cm `MaxStepHeight`, so it - does not block traversal; the cause is a sidewalk-strip discontinuity near a - centreline vertex, recorded in `Art/blender/README.md` as a smoothness - refinement. -- Kerb radii at junctions, driveway aprons, drainage inlets and pavement joints - remain unmodelled (unchanged from `0.1.0`). +- Cornice dentil spacing, the base and abacus dimensions are recorded assumptions: the reference photography does not resolve them at our scale. +- Façade surfaces remain flat blockout materials; the textured pass is `0.1.4`. + +## [0.1.1] — 2026-11-08 + +Collision-fidelity patch. No new scope: street geometry corrections and the QA tooling that measures them. + +### Fixed + +- **Sidewalk outer edge ledge.** The sidewalk stood the full 0.15 m kerb height above the DEM at both edges, leaving a 15.8 cm lip where the walk route crossed from terrain onto the south sidewalk. The upstand now tapers from full at the road-side edge to zero at the building-side edge; the north route's worst step fell from 15.1 cm to 6.9 cm. +- **Crossing ramps too steep.** The kerb-flush run was a fixed 1.5 m, giving ~8.7 % (measured 10–13 cm over 1.5 m). The run is now derived from a target grade (`--max-ramp-grade`, default 8 % ⇒ 1.63 m); the crossing steps 3.4 cm at 0.25 m sampling. + +### Added + +- **Walk pre-check improvements** (`Art/blender/site/site_assembly.py`): sampling coverage is independent of `--sample` (it previously shrank the route), and the report now prints the grade and the arc-length/offset **location** of the worst step, so a step can be located rather than guessed. + +### Changed + +- **Kerb height recorded as final** at 0.15 m modelled / 0.13 m as built — a standard 6 in LA kerb; neither the 3DEP DEM nor the reference photography can resolve it further (±2 cm), which is far below the character's 45 cm step height. + +### Verified + +- Site meshes rebuilt and re-imported (7/7, collision flags intact), DemoMap rebuilt, packaged Development build `EXIT=0`. +- `-qaselftest` on the packaged build: walk 761 cm in 2 s at steady Z 456, reset 0 cm, pause/unpause, transect 1456 samples across 16 rows / **0 holes**, wall probe **0/35** blocking hits. + +### Known limitations + +- One residual **13.4 cm surface step at s≈198 m** on the south sidewalk (8.0 cm at s≈251 m north). It is not a gap and is below the 45 cm `MaxStepHeight`, so it does not block traversal; the cause is a sidewalk-strip discontinuity near a centreline vertex, recorded in `Art/blender/README.md` as a smoothness refinement. +- Kerb radii at junctions, driveway aprons, drainage inlets and pavement joints remain unmodelled (unchanged from `0.1.0`). Nothing yet. ## [0.1.0] — 2026-11-08 -The first playable release: a walkable exterior demo of the **6840 Hollywood Blvd** -(El Capitan Entertainment Centre) block in Unreal Engine, built on OpenStreetMap -layout data and USGS elevation, with the hero façade and the verified block -frontage staged on a walkable street. +The first playable release: a walkable exterior demo of the **6840 Hollywood Blvd** (El Capitan Entertainment Centre) block in Unreal Engine, built on OpenStreetMap layout data and USGS elevation, with the hero façade and the verified block frontage staged on a walkable street. ### Added -- **Unreal project** (`Game/GigLine`) — C++ game module, Enhanced Input, packaged - Linux build, and a `DemoMap` that a plain launch opens directly. -- **Walkable demo level** — terrain from the 3DEP DEM, Hollywood Blvd carriageway, - both sidewalks and kerbs with collision, the designated mid-block crossing, and - fixed daytime lighting (sun, sky light, sky atmosphere, height fog, pinned - exposure). -- **Hero façade** for 6840 Hollywood Blvd — six-column neoclassical elevation with - three genuine portal recesses, entablature, parapet and motto band - (`Tools/hero_facade_build.py`, `Tools/ue_hero_facade_import.py`). -- **Block frontage** — the five verified south-side neighbours (6922, 6902, 6838 - El Capitan Theatre, 6822 Budget, 6806–6822, 6800 Lee Drug) and the two north-side - buildings (TCL Chinese Theatre, Madame Tussaud's) placed at their OSM positions. -- **First-person player** — `AGigLineCharacter`: 1.75 m capsule, 1.60 m eye camera, - 4 m/s walk, mouse look, jump, reset (`R`) and pause (`Escape`); controls - documented in `Docs/controls.md` and shown in-game. -- **In-game ODbL attribution** — `AGigLineHUD` draws the OpenStreetMap credit and - licence line every frame. -- **QA harness** — `-qaselftest` (walk, reset, pause, seam transect, invisible-wall - probe, frame-time capture) and `Tools/input_test.py` / `Tools/input_emulation.py` - for OS-level virtual keyboard/mouse input. -- **Documentation** — setup, build, toolchain, licensing, ODbL review, release - checks, and arc42 architecture docs. +- **Unreal project** (`Game/GigLine`) — C++ game module, Enhanced Input, packaged Linux build, and a `DemoMap` that a plain launch opens directly. +- **Walkable demo level** — terrain from the 3DEP DEM, Hollywood Blvd carriageway, both sidewalks and kerbs with collision, the designated mid-block crossing, and fixed daytime lighting (sun, sky light, sky atmosphere, height fog, pinned exposure). +- **Hero façade** for 6840 Hollywood Blvd — six-column neoclassical elevation with three genuine portal recesses, entablature, parapet and motto band (`Tools/hero_facade_build.py`, `Tools/ue_hero_facade_import.py`). +- **Block frontage** — the five verified south-side neighbours (6922, 6902, 6838 El Capitan Theatre, 6822 Budget, 6806–6822, 6800 Lee Drug) and the two north-side buildings (TCL Chinese Theatre, Madame Tussaud's) placed at their OSM positions. +- **First-person player** — `AGigLineCharacter`: 1.75 m capsule, 1.60 m eye camera, 4 m/s walk, mouse look, jump, reset (`R`) and pause (`Escape`); controls documented in `Docs/controls.md` and shown in-game. +- **In-game ODbL attribution** — `AGigLineHUD` draws the OpenStreetMap credit and licence line every frame. +- **QA harness** — `-qaselftest` (walk, reset, pause, seam transect, invisible-wall probe, frame-time capture) and `Tools/input_test.py` / `Tools/input_emulation.py` for OS-level virtual keyboard/mouse input. +- **Documentation** — setup, build, toolchain, licensing, ODbL review, release checks, and arc42 architecture docs. ### Fixed -- **All controls were dead in packaged and PIE builds.** The mapping-context - generator wrote key bindings to the deprecated `mappings` array; UE 5.8 reads - `DefaultKeyMappings.Mappings`, so the cooked game had zero runtime mappings and - every key resolved to nothing. `Tools/ue_create_input_assets.py` now populates - the current field. -- **"Fall-through" was an 8 m invisible box.** `Terrain_DEM` shipped only a - bounding-box collision proxy; forcing complex-as-simple collision - (`UGigLineAssetTools`) put the player on the actual street. -- **Reset returned the player to mid-air** — the start position is now captured on - the first grounded frame. -- **Plain launch opened the engine template** — the default map now lives in - `DefaultEngine.ini` and points at `DemoMap`. -- **Game target would not compile** — removed editor-only API use - (`UStaticMesh::PostEditChange`, `AActor::GetActorLabel`). -- **`demo-north-buildings` screenshot** framed 85 % sky (camera 9.5 km west of the - buildings); re-pointed to the building mass. +- **All controls were dead in packaged and PIE builds.** The mapping-context generator wrote key bindings to the deprecated `mappings` array; UE 5.8 reads `DefaultKeyMappings.Mappings`, so the cooked game had zero runtime mappings and every key resolved to nothing. `Tools/ue_create_input_assets.py` now populates the current field. +- **"Fall-through" was an 8 m invisible box.** `Terrain_DEM` shipped only a bounding-box collision proxy; forcing complex-as-simple collision (`UGigLineAssetTools`) put the player on the actual street. +- **Reset returned the player to mid-air** — the start position is now captured on the first grounded frame. +- **Plain launch opened the engine template** — the default map now lives in `DefaultEngine.ini` and points at `DemoMap`. +- **Game target would not compile** — removed editor-only API use (`UStaticMesh::PostEditChange`, `AActor::GetActorLabel`). +- **`demo-north-buildings` screenshot** framed 85 % sky (camera 9.5 km west of the buildings); re-pointed to the building mass. ### Verified -- Both sides of the demo are traversable: 1456-sample seam transect, 0 holes, - no blocking collision or invisible walls (`-qaselftest` on the packaged build). -- Placement and street scale match the reference photography and Geo - measurements (road 24.3 m, sidewalk offsets 12.5/13.2 m, hero frontage 26.0 m). -- **414 fps average / p99 3.01 ms at 2560×1440** (Epic preset, TSR, VSync off, no - frame generation) — far above the 60 fps target. -- Fresh checkout builds and packages with the documented external engine - (UE 5.8.4). +- Both sides of the demo are traversable: 1456-sample seam transect, 0 holes, no blocking collision or invisible walls (`-qaselftest` on the packaged build). +- Placement and street scale match the reference photography and Geo measurements (road 24.3 m, sidewalk offsets 12.5/13.2 m, hero frontage 26.0 m). +- **414 fps average / p99 3.01 ms at 2560×1440** (Epic preset, TSR, VSync off, no frame generation) — far above the 60 fps target. +- Fresh checkout builds and packages with the documented external engine (UE 5.8.4). ### Known limitations -- Buildings other than the hero are flat blockout volumes; façade detail, - materials and Blosm style scripts are planned for `0.1.4`. -- Kerb height (0.13 m as built vs 0.15 m assumed), kerb radii, driveway aprons and - graded crossing ramps are deferred to `0.1.1`; crossing ramps are kerb flushes. +- Buildings other than the hero are flat blockout volumes; façade detail, materials and Blosm style scripts are planned for `0.1.4`. +- Kerb height (0.13 m as built vs 0.15 m assumed), kerb radii, driveway aprons and graded crossing ramps are deferred to `0.1.1`; crossing ramps are kerb flushes. - One block only; no vehicles, NPCs, audio, or settings UI yet. -[Unreleased]: https://git.allucanget.biz/zwitschi/gig-line/compare/v0.1.1...main +[Unreleased]: https://git.allucanget.biz/zwitschi/gig-line/compare/v0.1.2...main +[0.1.2]: https://git.allucanget.biz/zwitschi/gig-line/releases/tag/v0.1.2 [0.1.1]: https://git.allucanget.biz/zwitschi/gig-line/releases/tag/v0.1.1 [0.1.0]: https://git.allucanget.biz/zwitschi/gig-line/releases/tag/v0.1.0 diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 6523f7b..b9e63f2 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3239737465e1695fc16868978aabcca4767055e1ab45cb1c222591b7ff2bda22 -size 54516 +oid sha256:5805e28bd4c9368cd35f571bdceb0d6f048604226f69cf96fa385ee84380c211 +size 54509 diff --git a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset index 7141801..466c4da 100644 --- a/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset +++ b/Game/GigLine/Content/Hollywood/ElCapitan/SM_HeroFacade.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ddad5d7f8850af3547fe2f80c388e16e0559e266da058874f0fc36af2ac4f6b -size 129152 +oid sha256:76cdd4770b34206e7b53c27d1902fde238efde555580ce08cf87270882613b85 +size 142674 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index 55afb15..ee81ce5 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1573ce34e0eedd36e9fea9c3b7870c3a7e40cd7763feeeafcf406f6821e1ddfa +oid sha256:8b3b5a17f3a916bb27858051e5ba88b4266a420898128e3fb26577b4ca92ff15 size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index 43ced3c..30f1d14 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ed5ce4a4a8d007723859d1bf72f8cda4dc44a0a1516861388cf453a8ed51bd8 +oid sha256:35ef03e01d6cc6aee00d7bdea4063213b1b3f4ec717838f6694dcdfe85e593a8 size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index e08b823..99136e1 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9e56b813e652f1db48f0d2c06fb971a3e626ac8a7db2355b844bed7e9cb0a9e +oid sha256:092d4108e04ea0a90902249a2ff29480a61ce0001963fdbb7fffa7788facee46 size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 4dd5e9c..fea4b51 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f602277d7e29590cc74edc68947bfaf4005bb1b725b893048999bef871965e29 +oid sha256:6bb3fc7e0ba1c40897838d8ab01b053f467da130e54c19a91e46b61a15b09e2b size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index ce1583d..a3c6748 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a33a56d8da461099abc07e4d2608c461fa6ecf64e86901a751ebd123a35c7b01 +oid sha256:ef17b5d0ed660a13a60b294a9d36ab99787336b2655e4f350fcc2780e5fc5d04 size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index cab50f8..7e38022 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df8b9571db76547fcb0c14b17440434aa865cf06fede0870edddbe57c25a13c7 +oid sha256:60d614ddb19422a8fcca5474f731ef5640f7d7d60c6ef59780914c15f8367388 size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index 2835530..de5a3bb 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17de1d539b838415aa76f4637feabc200991ee52671dce1546da6564d6bc0761 +oid sha256:38bbe13637e5a27860b2b0cb2d75d9802446a8ee481825de46bd04bbf0b6f586 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index 3f1cab2..263ef74 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ecff60acd3e6f7149564003fe68fb9fc8a89c21c9d0eebdafa6f8ae59c6ab270 +oid sha256:22e56a42763de7a73b4d8974a3e8709d89ebdc666bde2ce5d21dea699cee3198 size 357901 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index 88400fa..060a2e4 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a39dff6294d91f55ab3ea581c8c1a7f663cbe2214e61d2836491d06965f383e8 +oid sha256:69e8eb5f0765ce2900ef8b56463b3c0c484120dfc4a6f8ac40436427a178040b size 28706 diff --git a/MEMORY.md b/MEMORY.md index 63bd5ff..090f0ee 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -483,3 +483,15 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. - `mpfb_character_export.py` was not re-run: it needs the MPFB add-on on `BLENDER_USER_SCRIPTS` ("Add-on not loaded: bl_ext.blender_org.mpfb"), which is pre-existing and unrelated; the character is not in `0.1.x` gameplay. + +## 2026-11-09 — v0.1.2 released + +- Cornice finished: projecting corona over a **52-dentil course** (0.18 × 0.30 × + 0.22 m at 0.45 m centres, z 12.12–12.34, 0.25 m clear of the corona). Hero is now + 3 044 tris across 148 parts, still 14.50 m. Verified: packaged `-qaselftest` all + PASS (transect 0 holes, wall probe 0/35, facade probe 0/9). +- `CHANGELOG.md` gets the `0.1.2` entry (added/changed/fixed/verified/limitations), + the `0.1.2` section is removed from `TODO.md`, `ROADMAP.md` status updated, tag + `v0.1.2` cut after the merge. +- Assumptions recorded rather than hidden: dentil spacing, base and abacus + dimensions are not resolvable in our reference photography. diff --git a/Screenshots/README.md b/Screenshots/README.md index 73e033f..04c3f64 100644 --- a/Screenshots/README.md +++ b/Screenshots/README.md @@ -59,5 +59,5 @@ Rebuilds `Game/GigLine/Content/Test/ReviewMap.umap` from current content, runs t - Floor speckle from the `Constant3Vector` wiring in `Tools/ue_build_review_map.py`. - Hero façade renders pale — Blender flat colours with no normal/roughness, so it reads as untextured stone (the `0.1.4` façade patch, not a lighting bug). - Banners sit on the column line rather than the wall (acceptable: they hang on the columns in the photographs). -- ~~Banners and window panels float detached from the colonnade wall~~ — **window panes fixed 2026-11-09**: they sat at Y −1.98, 1.44 m in *front* of the wall and ahead of the column line; they now sit on the wall plane at Y −0.56, behind the columns, and read as dark openings (see `review-hero-facade-front`). +- ~~Banners and window panels float detached from the colonnade wall~~ — **window panes fixed 2026-11-09**: they sat at Y −1.98, 1.44 m in _front_ of the wall and ahead of the column line; they now sit on the wall plane at Y −0.56, behind the columns, and read as dark openings (see `review-hero-facade-front`). - Between kerb and building line, the walkable surface is the terrain mesh, not a modelled pavement. diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index 9c49c20..7b9f729 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8922ee977c1d89df3d4d9e10caa2785f87deecd17bee4624cf5dbfbdeecadb73 -size 2238947 +oid sha256:4987b6fe125ea35123c1fc6b449316c5572611cde6fad23960a0133edd35c18a +size 2240373 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 7a36e08..7869397 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf464077cd4a79302b33d7f88be63aee6f586ab761c030cfb67661945eeee493 -size 2640409 +oid sha256:78bc63eb208566fe96bcbdd22f055aa6e9e2cde5cf5fd46970e35786235642fb +size 2640328 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index 4c51cc6..0497f75 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5e133239d976a0c451845b126a4139afec85055592752639db430640c714f0d -size 2762684 +oid sha256:59471b51a90ae76085929d748e602d79f61006d930a3bcde3414d91cc224f336 +size 2750928 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index faa7954..3bd0354 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3ff3ccb37e39df6a85b46d55e42c830eedb472cca58784126dbc0c92f3cacd8 -size 1826522 +oid sha256:188c438887a4cd08377c68168597494ae0bfb50a556c11c74dd5f0daf8324606 +size 1802093 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index be22d0e..2ee8935 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f08a527395660a98d8b39af4356ccdf1a38d7e3cab19ce7ad560cfd12a75c749 -size 1743785 +oid sha256:2aea3c9551c08984a4284c82950ed2f8b393dd89b3de0460025569716d84421a +size 1740280 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index 8dfd265..7bf77c5 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29605038bf303924976deec33896c5534b65d43233ce3bc587c3e8a0320ebd65 -size 1402114 +oid sha256:43a4d8e5c944ef0eb68123a8f76a56cf34b33d300854aee026e3ccf7632a2ace +size 1405528 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 6fed5e6..37e8782 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ae371b126e13e24610ca9358a10bc9524702ad3dda9ce672fcaac44bb03dc8e -size 1373251 +oid sha256:05dea90306fb44fd88d1ea9ec258dd65940ed7fb6a4a126657d645c49cd45de3 +size 1368740 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index 26c6dd5..0fed29f 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d26ee7178f4b7bd23c028d19e7cb8ded4109bbf6864f95c3e56e28c5eeed8c32 -size 1804784 +oid sha256:63b5ce004bfe7804f00d6e49c75a4c461f5414214817b4cffca5a3df0b136277 +size 1793145 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index e844489..8680147 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:232ba45b93dc9871ec79363ba29033ef2ddf56bf2b90ed712718b136be3638f2 -size 2419553 +oid sha256:e2b4e4008d19bbf05bd83b2700c5ad94e57a19d4dde3c57ccdddb31629e48216 +size 2417882 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index 70a7a50..49b4d25 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b0d3c22b5e642a5ef4586f452e50753649923835ed41b7c9310a257fb124fca -size 2211043 +oid sha256:a42ba17def6436697939e3fc1b16d70318bdfdc5098343457bdbca937884aa08 +size 2208471 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 4b31d9b..417db54 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89c4381b77b18eebc27c1df85bd31ce1cba4b2f89fc73dbdb312cb60013f318f -size 2140459 +oid sha256:da899284357ce4fcb95d4da36789a20b3adf52b77643630c7790112a3e582e28 +size 2135172 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index a922f66..895261c 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3b6f8d9cc11087da4f7b47c3ed6e49af45098094ce29a2d729e137cabb4bb5b -size 1852570 +oid sha256:b5c53303eeb5220eb026990204127e9d5c328614699f911ea6389969ab3a2f22 +size 1857026 diff --git a/TODO.md b/TODO.md index 333d831..432bcfa 100644 --- a/TODO.md +++ b/TODO.md @@ -9,18 +9,6 @@ Actionable task list for this project. This file is the single, central place fo - When all steps in a version section are done: write a `CHANGELOG.md` entry, then remove the version section from this file. - Release gate: a version is tagged only on the owner's explicit go-ahead once its release checks pass, not automatically when the checkboxes close. -## 0.1.2 — Scale and façade corrections (patch) - -Suggested blender skills: **references** (reference-image-match and visual-match-checklist templates — measure the guessed heights and colonnade proportions against the photographs), **archviz** (real-world scale and façade composition discipline), **camera-cinematography** (reproduce the reference camera angles when comparing renders to photos). - -### Patch tasks - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `scale-facade-0.1.2`) - -- [x] Correct building scale and street proportions flagged against references. **Mapbox adopted 2026-11-09.** `Geo/tools/mapbox_buildings.py` merges our OSM heights with Mapbox's building data for the same footprints; after adopting its two findings the cross-check reports **66 match, 6 non-building, 0 disagreements**. Adopted: **`LEVEL_HEIGHT` 3.2 → 3.1 m** (`block_height_report.py`, and the Blosm `--level-height` default), plus explicit `HEIGHT_OVERRIDES` (3.0 m) for the three rear `building=yes`/`apartments` structures Mapbox gives as single-storey. Blockout regenerated, frontage re-exported/re-imported, DemoMap rebuilt; packaged `-qaselftest` all PASS. Measured effect: 6922 42.1 → 39.1 m, El Capitan Theatre 20.0 → 20.5 m (both now ~1.9 m above their table height = roof mass). -- [ ] Refine hero façade details where reference photography shows discrepancies. **Started 2026-11-09:** built `Tools/facade_detail_concepts.py`, which generates architectural detail plates from the local reference photographs with an image model (`--list` free, `--all` generates, sidecars + `-vN` no-overwrite, output gitignored). Six **frontal building** studies generated locally under `Art/reference/facade-details/` (whole elevation, entrance in its facade, building with neighbours, pavement view, three-quarter, theatre frontage) — rephrased on owner instruction to show the building/entrance/neighbours rather than close-up detail crops. **First fix from the measurement pass:** window panes were 1.44 m in front of the wall (ahead of the columns) and now sit on the wall plane behind the colonnade. **Detail pass 2026-11-09 (all measured on the built mesh):** added an Ionic base moulding (1.36 m × 0.22 m) at each shaft foot and a square abacus (1.30 m × 0.14 m) over each capital, taking the abacus out of the capital zone so the colonnade still ends at 9.70 m; re-oriented the two parapet medallions, which were flat discs lying on the coping (1.1 × 1.1 × 0.02 in the wrong axes) instead of discs on the parapet face; window panes moved onto the wall plane. Hero is now 2 420 tris across 95 parts, still 14.50 m. Cornice/dentil profile refinement remains. -- [x] **Replace the placeholder heights.** **Resolved 2026-11-08 — they were never unknown buildings.** The three "guessed" ways are not building volumes at all: `1360755125` and `1360755126` are `building=roof` at `layer=1` (elevated canopies) and `1417995292` is `amenity=shelter` / `shelter_type=public_transport` (a transit shelter). The report defaulted them to "2 levels × 3.2 m" and produced the bogus 6.4 m. `Geo/tools/block_height_report.py` now classifies roof/shelter explicitly and reports **0 guessed heights**: all 15 block volumes have a real `height` tag, a `building:levels` derivation, or are correctly excluded as non-building volumes. No photograph measurement was needed, and no frontage building was affected. -- [x] Resolve the remaining unknown on the hero: the colonnade currently occupies about 45 % of the height against roughly 50–60 % in the photographs. Fix the vertical proportions. **Fixed 2026-11-09.** Measured baseline: colonnade (columns + capitals) 6.90 m of the 14.50 m envelope = **47.6 %**, because the entablature (3.40 m) and parapet (2.20 m) left only 7.90 m for the order. Thinned both to **3.00 m** and **1.80 m** (`Tools/hero_facade_build.py`), which lifts the colonnade to **7.70 m = 53.1 %** — inside the photographed 50–60 % band, with the 14.50 m envelope, the motto band and the medallions unchanged in position relative to the parapet. Hero rebuilt, re-imported (bounds 2604 × 1257 × 1450 cm) and re-rendered. -- [ ] Tag `v0.1.2` and write `CHANGELOG.md` entry; then remove this section. - ## 0.1.3 — Packaging and setup fixes (patch) Suggested blender skills: **export-pipeline** and **unreal-export** (scale/pivot/normals/materials/collision verification) if any packaging defect traces back to the Blender export presets. diff --git a/Tools/hero_facade_build.py b/Tools/hero_facade_build.py index 2afca9a..964a419 100644 --- a/Tools/hero_facade_build.py +++ b/Tools/hero_facade_build.py @@ -196,9 +196,25 @@ def build(): # elevation reads as layered stone rather than one flat plane. cube("Hero_Architrave", 0.0, -1.55, ent_z0 + 0.42, FRONTAGE_W, 1.65, 0.84, stone) note("Hero_Architrave", (FRONTAGE_W, 1.65, 0.84), "assumption: stacked entablature bands") - # Cornice under the parapet. - cube("Hero_Cornice", 0.0, -1.6, HEIGHT - PARAPET_H - 0.18, FRONTAGE_W, 1.75, 0.36, stone) + # Cornice under the parapet: a projecting corona carried on a dentil course, + # so the top of the order reads as layered stone with a shadow line rather + # than one flat box. Dentils hang under the corona and stand 0.25 m clear of + # it, which is what gives the elevation its cornice shadow at street level. + cornice_z = HEIGHT - PARAPET_H - 0.18 + cube("Hero_Cornice", 0.0, -1.6, cornice_z, FRONTAGE_W, 1.75, 0.36, stone) note("Hero_Cornice", (FRONTAGE_W, 1.75, 0.36), "assumption: projecting cornice line") + DENTIL_W, DENTIL_D, DENTIL_H, DENTIL_GAP = 0.18, 0.30, 0.22, 0.27 + dentil_y = -2.30 + dentil_z = cornice_z - 0.18 - DENTIL_H / 2.0 + dentil_span = FRONTAGE_W - 2.0 + dentil_count = int(dentil_span / (DENTIL_W + DENTIL_GAP)) + for i in range(dentil_count): + dx = -dentil_span / 2.0 + (DENTIL_W + DENTIL_GAP) * i + DENTIL_W / 2.0 + cube(f"Hero_Dentil_{i + 1}", dx, dentil_y, dentil_z, + DENTIL_W, DENTIL_D, DENTIL_H, stone) + note("Hero_Dentil_xN", (DENTIL_W, DENTIL_D, DENTIL_H), + f"{dentil_count} dentils at {DENTIL_W + DENTIL_GAP:.2f} m centres under the corona; " + "assumption: photographed cornice reads as a dentilled course") cube("Hero_Entablature", 0.0, -0.75, ent_z0 + ENTABLATURE_H / 2.0, FRONTAGE_W, 1.5, ENTABLATURE_H, stone) note("Hero_Entablature", (FRONTAGE_W, 1.5, ENTABLATURE_H), "assumption: entablature depth") -- 2.47.3 From 749147f3e95f3561d334d4c3378c475c48401f2a Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sun, 8 Nov 2026 18:48:02 +0100 Subject: [PATCH 9/9] fix(screenshots): level the elevation cameras for straight verticals archviz rule: an elevation must not lean. hero-facade-front looked up ~4 deg from 4.2 m at a 7.6 m target (columns converged); demo-spawn-view and demo-street-level were pitched too. All three now sit at the target's height, so pitch and roll are zero by construction and the verticals stay parallel. Screenshots re-rendered. A pixel-based verticality check is useless here (banners and windows break naive edge matching), so the guarantee is geometric and is recorded that way in the README and MEMORY. --- Game/GigLine/Content/Hollywood/DemoMap.umap | 2 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- MEMORY.md | 12 ++++++++++++ Screenshots/demo/review-demo-crossing.png | 4 ++-- Screenshots/demo/review-demo-north-buildings.png | 4 ++-- Screenshots/demo/review-demo-spawn-view.png | 4 ++-- Screenshots/demo/review-demo-street-level.png | 4 ++-- Screenshots/review-character.png | 4 ++-- Screenshots/review-ground-contact.png | 4 ++-- Screenshots/review-hero-facade-front.png | 4 ++-- Screenshots/review-hero-facade-oblique.png | 4 ++-- Screenshots/review-hero-portals.png | 4 ++-- Screenshots/review-npc-prefab.png | 4 ++-- Screenshots/review-overview.png | 4 ++-- Screenshots/review-player-placement.png | 4 ++-- Screenshots/review-scale-cubes.png | 4 ++-- Screenshots/review-shadow-compare.png | 4 ++-- Tools/ue_build_review_map.py | 12 +++++++++--- 18 files changed, 51 insertions(+), 33 deletions(-) diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index b9e63f2..0041601 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5805e28bd4c9368cd35f571bdceb0d6f048604226f69cf96fa385ee84380c211 +oid sha256:bcda8f7eacbbc8c20ff768177dc1c35863fd1bf403df142722880ca426e8a8f1 size 54509 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index 060a2e4..a36c204 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69e8eb5f0765ce2900ef8b56463b3c0c484120dfc4a6f8ac40436427a178040b +oid sha256:3c34637f8b929cab7a68725f550f65ebdfac790cb5af5e2349ef661dccd8faa0 size 28706 diff --git a/MEMORY.md b/MEMORY.md index 090f0ee..1b9bd8d 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -495,3 +495,15 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. `v0.1.2` cut after the merge. - Assumptions recorded rather than hidden: dentil spacing, base and abacus dimensions are not resolvable in our reference photography. + +## 2026-11-09 — elevation cameras levelled (straight verticals) + +- archviz MUST: an elevation must not lean. `hero-facade-front` looked up ~4° from + 4.2 m at a 7.6 m target; `demo-spawn-view` and `demo-street-level` were pitched + too. All three now put the camera at the target's height, so + `FindLookAtRotation` yields pitch 0 and roll 0 and verticals are parallel by + construction. +- Do not try to *measure* verticality from the rendered PNG with a naive edge + scan: banners, windows and the parapet produce different edge sets at different + heights and the pairwise match is meaningless (it reported a 418 px "drift"). + Verify it geometrically in the camera list instead. diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index 860efee..72ccf7a 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ced7093dbfd87341f26824b3d383afcadba6b84d02e9d22b46dcae504107dcf -size 2555823 +oid sha256:380647ec83dcdc1d1796a3f6a033dfcb86d634c8312faf0c4332c795a12dcc81 +size 2592475 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index 7b9f729..05d5445 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4987b6fe125ea35123c1fc6b449316c5572611cde6fad23960a0133edd35c18a -size 2240373 +oid sha256:f01bd1af993306a5de88397e6f0bcc79f64f0167b06353e54b8cc0719ff4881a +size 2261865 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 7869397..ad2ad70 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78bc63eb208566fe96bcbdd22f055aa6e9e2cde5cf5fd46970e35786235642fb -size 2640328 +oid sha256:63d49011bcf0ab52b96c4ec7b27eeba3d27de3bbbf951a8f8e0ac09117995f3e +size 2628687 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index de7adf8..f07d483 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f6eb060018bd904b1e55eeaf1607fff013cec44334ecdc76a1b0f1dad17cb06 -size 2419233 +oid sha256:d87896644e71e7a66b18fb9997d76d51a05cce5fa6fc97e3f698a45258d0b306 +size 2468639 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index 0497f75..82f9181 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59471b51a90ae76085929d748e602d79f61006d930a3bcde3414d91cc224f336 -size 2750928 +oid sha256:44df56de845bde433eb1d6de2294462c9933d8f6a800a4f3cdc01793c5b1497b +size 2528497 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 3bd0354..4dbada6 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:188c438887a4cd08377c68168597494ae0bfb50a556c11c74dd5f0daf8324606 -size 1802093 +oid sha256:9043e2e90ffead898262bae5c6f8ad0bbc700c5f52aa398ae6f486a858ac4af0 +size 1749002 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index 2ee8935..d523315 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2aea3c9551c08984a4284c82950ed2f8b393dd89b3de0460025569716d84421a -size 1740280 +oid sha256:c8c70fa7806c12a0cdbf2196b5f52f82f402e1b806f067e48a98970a94393e41 +size 1436443 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index 7bf77c5..6428303 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43a4d8e5c944ef0eb68123a8f76a56cf34b33d300854aee026e3ccf7632a2ace -size 1405528 +oid sha256:c53e905de74ffb3783f2895ed667e352179b7bc411246b3b5bcdae88a5b299f9 +size 1306447 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 37e8782..c54cf5b 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05dea90306fb44fd88d1ea9ec258dd65940ed7fb6a4a126657d645c49cd45de3 -size 1368740 +oid sha256:f7455b6cc2a5a81ed1848956c41555a7775b705c24a34a0cbd8e0d0717e8d499 +size 1321848 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index 0fed29f..74c6464 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63b5ce004bfe7804f00d6e49c75a4c461f5414214817b4cffca5a3df0b136277 -size 1793145 +oid sha256:99501ac2edfa22a64a7156fbc298930db64997008d7534189f0ee9a208b9506a +size 1735511 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index 8680147..0da3826 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2b4e4008d19bbf05bd83b2700c5ad94e57a19d4dde3c57ccdddb31629e48216 -size 2417882 +oid sha256:f40eda489a19e01f3e0e6428940e4da7ee6865c7397e4e9bbe64f6e7a84b4af0 +size 2488592 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index 49b4d25..102d17f 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a42ba17def6436697939e3fc1b16d70318bdfdc5098343457bdbca937884aa08 -size 2208471 +oid sha256:f66e9a9e157c4663b971d15dcdfc8d3b67d64584c9f92a0d5ff207aac7637d37 +size 2019699 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 417db54..3d27366 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da899284357ce4fcb95d4da36789a20b3adf52b77643630c7790112a3e582e28 -size 2135172 +oid sha256:be833e2571fa2311499bbd806d32984c4a0b7bcaa33af2ff362fc6c94f553bff +size 1937905 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index 895261c..3888105 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5c53303eeb5220eb026990204127e9d5c328614699f911ea6389969ab3a2f22 -size 1857026 +oid sha256:75c80b08b7905b9e6c9df673151c2b0d11362c3a433b402e22240b66c647181b +size 1726246 diff --git a/Tools/ue_build_review_map.py b/Tools/ue_build_review_map.py index 8c4aacb..583c037 100644 --- a/Tools/ue_build_review_map.py +++ b/Tools/ue_build_review_map.py @@ -236,7 +236,11 @@ try: # the plinth, which is what "portal detail" means here. ("hero-portals", unreal.Vector(hero_x + 100, -2250, 170), unreal.Vector(hero_x + 100, hero_y, 230)), # straight on from the north sidewalk; the building body spans Y -1443..+250 - ("hero-facade-front", unreal.Vector(hero_x + 200, -3200, 420), unreal.Vector(hero_x, hero_y + 400, 760)), + # Level horizon: camera height == target height, so the elevation's + # verticals stay parallel. The old shot looked up ~4 deg from 4.2 m at a + # 7.6 m target, which converged the columns — the one thing an + # architectural elevation must not do (archviz: "straight verticals"). + ("hero-facade-front", unreal.Vector(hero_x + 200, -3200, 760), unreal.Vector(hero_x, hero_y + 400, 760)), # oblique from the north-west, reading the colonnade in depth ("hero-facade-oblique", unreal.Vector(hero_x - 2200, -3400, 620), unreal.Vector(hero_x + 300, hero_y, 700)), ] @@ -276,12 +280,14 @@ try: demo_shots = [ # 14 m back so the 14.5 m elevation fits: at 2 m the camera sees only # the colonnade's underside. - ("demo-spawn-view", unreal.Vector(-13336, -3100, 420), unreal.Vector(-13336, 1300, 620)), + # Level horizon for the same reason: a block elevation is read by its + # verticals, and a pitched camera makes them lean. + ("demo-spawn-view", unreal.Vector(-13336, -3100, 620), unreal.Vector(-13336, 1300, 620)), # Street level, from the north sidewalk: the old camera sat at Y -400, # inside the facade body (which spans Y -1457..-200), so it looked at # the unlit back face. Y -2600 is on the sidewalk in front of the lit # elevation. - ("demo-street-level", unreal.Vector(-13420, -1650, 170), unreal.Vector(-13336, 1300, 400)), + ("demo-street-level", unreal.Vector(-13420, -1650, 170), unreal.Vector(-13336, 1300, 170)), # The designated mid-block crossing. Street arc length runs from the # west end (s=0 at X -27966 cm), so s=130.1 m is UE X -14956, not the # -24291 the old camera used (that is the s=36.6 crossing). Camera sits -- 2.47.3