From 121c0398b0da7c579fc4d705240e7e0966f4d223 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sat, 7 Nov 2026 16:59:04 +0100 Subject: [PATCH 1/4] todo: demo level closed; claim Fixed daytime lighting on gameplay-lighting-0.1.0 --- TODO.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index 9b78b7c..e5d3374 100644 --- a/TODO.md +++ b/TODO.md @@ -89,13 +89,13 @@ The MPFB character asset is planned as the NPC template (see `ROADMAP.md`). Keep - [-] Build sidewalks, roads, and collision meshes. Terrain, road, sidewalks and kerbs exist (`Art/blender/terrain/`, `street/`) and are assembled in `site/site-2026-11-06.blend`; collision and details (crossing markings, kerb radii, aprons) are not built. Ground must follow the DEM: 3.94 m fall along the block, ~2 % crown between the gutters at ±10–11 m from the centreline, north sidewalk higher than south. Kerb height is an unresolved assumption — the DEM does not resolve it (`Geo/verification/2026-11-06-cross-sections.md`). - [ ] Materials and look development for all exported assets. -### Gameplay - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `gameplay-crossing-0.1.0`) +### Gameplay - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `gameplay-lighting-0.1.0`) - [x] First-person movement, mouse look, and Enhanced Input bindings. Implemented 2026-11-07: `AGigLineCharacter` (C++, 1.75 m capsule, 1.60 m eye camera, 4 m/s walk, mouse look in deg/s, jump) as the default pawn, with five actions and an 11-entry context in `/Game/Input` built by `Tools/ue_create_input_assets.py`. **Not yet confirmed interactively** — launch PIE on `Test/ReviewMap` and walk. Screenshot review pending (`Screenshots/README.md`). - [~] Collision, reset, and pause functionality. Reset (**R**) and pause (**Escape**, a real game pause that releases the cursor) are implemented in `AGigLineCharacter` with `/Game/Input/IA_Reset` and `IA_Pause`. Collision now exists — terrain, road and sidewalks import as complex-as-simple, so a simple hull cannot ramp over the kerbs. **Not verified by hand**: walk, reset and pause need a human at the keyboard. No pause menu widget yet, only the pause itself. -- [-] Build the walkable demo level: terrain, street, and hero facade assembled into one map with a start point on the north sidewalk, so the demo is something a player can walk rather than a review staging. **Built 2026-11-07** by `Tools/ue_build_demo_map.py` → `/Game/Hollywood/DemoMap`: sun/sky, `Hero_Facade`, six site meshes imported with collision (`Terrain_DEM`, `Road_Hollywood`, both sidewalks and both kerbs), and a `Demo_PlayerStart` on the north sidewalk 20 m back from the frontage. Demo views in `Screenshots/demo/` re-rendered and ☑ approved 2026-11-07. +- [x] Build the walkable demo level: terrain, street, and hero facade assembled into one map with a start point on the north sidewalk, so the demo is something a player can walk rather than a review staging. **Built 2026-11-07** by `Tools/ue_build_demo_map.py` → `/Game/Hollywood/DemoMap`: sun/sky, `Hero_Facade`, six site meshes imported with collision (`Terrain_DEM`, `Road_Hollywood`, both sidewalks and both kerbs), and a `Demo_PlayerStart` on the north sidewalk 20 m back from the frontage. Demo views in `Screenshots/demo/` re-rendered and ☑ approved 2026-11-07. - [x] Walkable sidewalks and a designated street crossing. Crossing chosen: mid-block signalised crossing, OSM way 385648319, at 130 m along the block (`Geo/verification/2026-11-06-street-profile.md`). Done 2026-11-07: continental zebra markings (0.5 m bars / 0.5 m gaps, 3 m band) at all three signalised crossings, no collision on the paint; kerbs were already flushed at the crossings. Enablers found on the way: the street surfaces were 100 % down-facing (invisible in engine) — winding flipped; the terrain buried the street — 10.7 m corridor cut around the centreline (sidewalks cover the transition, walk-check 0 holes); LFS-lockable `.blend`/`.umap` check out read-only — builders now chmod before saving and fail loudly. Screenshot ☑ approved 2026-11-07 (`Screenshots/demo/review-demo-crossing`); the corridor renders near-black in shadow — that is the still-open **Fixed daytime lighting** item, not the crossing. -- [ ] Fixed daytime lighting and basic ambience. +- [-] Fixed daytime lighting and basic ambience. Current state: `Demo_Sun` at pitch −35, yaw 200 puts the street corridor in shadow — the crossing shot renders near-black. Plan: rotate sun yaw so light comes down the street axis (e/w), raise sun intensity, boost skylight fill, set fixed daytime (no time-of-day motion). - [ ] Geographic attribution display ("© OpenStreetMap contributors" + license link). ### Repository publication -- 2.47.3 From 830ce596fa7a8710286185388a951d984152113c Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sat, 7 Nov 2026 17:56:21 +0100 Subject: [PATCH 2/4] lighting: fixed daytime rig, real surface materials, crossing fix Fixed daytime lighting and basic ambience for the DemoMap: - Sun pitch -50 / yaw 120 (intensity 4, warm), sky light 2.6 with real-time capture, sky atmosphere, height fog, and an unbound post-process volume with fixed exposure (min = max brightness) so no shot washes out or crushes to black depending on how much sky it frames. - Root cause of the washed-out look was NOT the sun: Blender's flat diffuse colours do not survive the FBX->Unreal import. Every site material arrived white and the terrain arrived with WorldGridMaterial. The demo builder now creates and assigns M_Asphalt / M_Concrete / M_Ground / M_RoadPaint. - Crossing fix: each zebra band was its own object, so Blender renamed the duplicates .001/.002 and site assembly (exact-name append) kept only one. All bands are now a single Crossing_Markings mesh (36 verts, 3 bands). - Terrain gets a Ground_Earth material in the builder so it stops importing as a white grid. - Demo cameras: street-level no longer sits inside the facade body (was rendering its back face), and the crossing camera aims at the designated s=130.1 crossing (UE X -14956) looking along the crosswalk. Screenshots re-rendered; the four demo views are marked needs-review for the owner's approval. MEMORY.md records the material-import, exposure, light_color, band-naming and camera-bounds traps. --- Art/blender/site/site-2026-11-06.blend | 4 +- Art/blender/street/street-2026-11-06.blend | 4 +- Art/blender/street/street_mesh.py | 42 +++--- Art/blender/terrain/terrain-2026-11-06.blend | 4 +- Art/blender/terrain/terrain_from_dem.py | 6 + Game/GigLine/Content/Hollywood/DemoMap.umap | 4 +- .../Hollywood/Site/Crossing_Markings.uasset | 4 +- .../Content/Hollywood/Site/Kerb_North.uasset | 2 +- .../Content/Hollywood/Site/Kerb_South.uasset | 2 +- .../Content/Hollywood/Site/M_Asphalt.uasset | 3 + .../Content/Hollywood/Site/M_Concrete.uasset | 3 + .../Content/Hollywood/Site/M_Ground.uasset | 3 + .../Content/Hollywood/Site/M_RoadPaint.uasset | 3 + .../Hollywood/Site/Road_Hollywood.uasset | 2 +- .../Hollywood/Site/Sidewalk_North.uasset | 2 +- .../Hollywood/Site/Sidewalk_South.uasset | 2 +- .../Content/Hollywood/Site/Terrain_DEM.uasset | 4 +- Game/GigLine/Content/Test/ReviewMap.umap | 2 +- MEMORY.md | 9 ++ Screenshots/README.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/ue_build_demo_map.py | 129 ++++++++++++++++-- Tools/ue_build_review_map.py | 13 +- 37 files changed, 241 insertions(+), 82 deletions(-) create mode 100644 Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset create mode 100644 Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset create mode 100644 Game/GigLine/Content/Hollywood/Site/M_Ground.uasset create mode 100644 Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset diff --git a/Art/blender/site/site-2026-11-06.blend b/Art/blender/site/site-2026-11-06.blend index 83aa233..cb34036 100644 --- a/Art/blender/site/site-2026-11-06.blend +++ b/Art/blender/site/site-2026-11-06.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d6d303913de1a2c24b3e04ceb6c43a84a46355470b14ebab6acf146f7dbb636 -size 991800 +oid sha256:2a54ae747e4990399c8f269b8ebe5a3f1bf0d6cca4ac2dd9ca2562f66f5eedfb +size 994709 diff --git a/Art/blender/street/street-2026-11-06.blend b/Art/blender/street/street-2026-11-06.blend index 71028dc..ae518a9 100644 --- a/Art/blender/street/street-2026-11-06.blend +++ b/Art/blender/street/street-2026-11-06.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6f546fcf86cd08a5e37571a7f42b2e6615925f71f7ca5ed850e801313591f70 -size 514043 +oid sha256:5744a2138e894a485f026d92b9311f7ecde12c280dd096bbbde5776694b32ae2 +size 514185 diff --git a/Art/blender/street/street_mesh.py b/Art/blender/street/street_mesh.py index 201b616..368a18c 100644 --- a/Art/blender/street/street_mesh.py +++ b/Art/blender/street/street_mesh.py @@ -261,20 +261,24 @@ def main(): paint = bpy.data.materials.new("Road_Paint_White") paint.diffuse_color = (0.85, 0.85, 0.85, 1.0) - def crossing_band(s_c): + # All three bands live in ONE object. Creating one object per crossing used + # to produce Crossing_Markings, .001 and .002; site assembly appends by the + # exact name, so only the first crossing ever reached the game. + band_verts, band_faces = [], [] + + def add_crossing_band(s_c): # Stripes are emitted as two triangles each: the road crown makes the # quad non-planar and the FBX SDK refuses to triangulate it on import # ("unable to triangulate mesh" — the mesh is omitted entirely). zone = 3.0 # band length along the road, m w, g = 0.5, 0.5 # stripe width / gap, m span = (SOUTH_GUTTER + 0.2, NORTH_GUTTER - 0.2) - verts, faces = [], [] n = int(zone // (w + g)) covered = n * w + (n - 1) * g # actual stripe coverage, centred on s_c for k in range(n): s0 = s_c - covered / 2 + k * (w + g) - corners = [] - base_idx = len(verts) # verts grows only after the stripe is sampled + base_idx = len(band_verts) # sampled positions, then vertices + pts = [] for s_edge in (s0, s0 + w): base, normal, _ = at(s_edge) for off in span: @@ -284,23 +288,23 @@ def main(): # interpolates the DEM along 1 m rows while the markings sample # only their own corners, so a 1 cm lift left parts of the # stripes sunk under the road and invisible in game. - corners.append((base_idx + len(corners), (x, y, (dem_z(x, y) or 0.0) + 0.06))) - # corners order: (s0,off_s), (s0,off_n), (s1,off_s), (s1,off_n) - idx = [c[0] for c in corners] - verts.extend(c[1] for c in corners) - faces.append((idx[0], idx[3], idx[1])) - faces.append((idx[0], idx[2], idx[3])) - mesh = bpy.data.meshes.new("Crossing_Markings") - mesh.from_pydata(verts, [], faces) - mesh.update() - mesh.materials.append(paint) - obj = bpy.data.objects.new("Crossing_Markings", mesh) - bpy.context.scene.collection.objects.link(obj) - return obj + pts.append((x, y, (dem_z(x, y) or 0.0) + 0.06)) + # pts order: (s0,off_s), (s0,off_n), (s1,off_s), (s1,off_n) + band_verts.extend(pts) + band_faces.append((base_idx + 0, base_idx + 3, base_idx + 1)) + band_faces.append((base_idx + 0, base_idx + 2, base_idx + 3)) for s_c in CROSSINGS: - band = crossing_band(s_c) - print(f"crossing band at s={s_c:.1f}: {len(band.data.polygons)} stripes") + add_crossing_band(s_c) + + mesh = bpy.data.meshes.new("Crossing_Markings") + mesh.from_pydata(band_verts, [], band_faces) + mesh.update() + mesh.materials.append(paint) + markings = bpy.data.objects.new("Crossing_Markings", mesh) + bpy.context.scene.collection.objects.link(markings) + print(f"crossing markings: {len(CROSSINGS)} bands, " + f"{len(markings.data.vertices)} verts, {len(markings.data.polygons)} faces") for obj in (road, sw_s, sw_n): print(f"{obj.name:16} verts {len(obj.data.vertices):5} faces {len(obj.data.polygons):5}") diff --git a/Art/blender/terrain/terrain-2026-11-06.blend b/Art/blender/terrain/terrain-2026-11-06.blend index c294b9b..fd74a93 100644 --- a/Art/blender/terrain/terrain-2026-11-06.blend +++ b/Art/blender/terrain/terrain-2026-11-06.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9707f1256667ce156f8104cf84c461a1ee074a2a62c932fd377c9bb39e8f41d8 -size 431130 +oid sha256:bf33bfa11b78194c3dce1f061aaf904af4d82d7294f291772073e8d7d31ac016 +size 433475 diff --git a/Art/blender/terrain/terrain_from_dem.py b/Art/blender/terrain/terrain_from_dem.py index aa007cf..1ecfde7 100644 --- a/Art/blender/terrain/terrain_from_dem.py +++ b/Art/blender/terrain/terrain_from_dem.py @@ -224,6 +224,12 @@ def main(): mesh = bpy.data.meshes.new("Terrain_DEM") mesh.from_pydata(verts, [], faces) mesh.update() + # Without a material the mesh imports into Unreal with the default white + # material and blows out under the demo sun. A muted earth tone keeps the + # ground reading as ground. + ground = bpy.data.materials.new("Ground_Earth") + ground.diffuse_color = (0.30, 0.28, 0.25, 1.0) + mesh.materials.append(ground) obj = bpy.data.objects.new("Terrain_DEM", mesh) bpy.context.scene.collection.objects.link(obj) diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 97dc8de..adfeb64 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:2a2b7a61aa8b3c86c3944849107aa00d3ab6fa0d35056d50b02a65acbd4854a1 -size 33816 +oid sha256:3f3925238751bd1cfd9b145a7bc3a12945392434b7ea3f345bc822116f4f5a51 +size 44553 diff --git a/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset b/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset index b85f6c7..4c3e2c1 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:27a75622ca7ea90976cd88677961ca6d195b61e965a0ff17d6c8909b012918af -size 74929 +oid sha256:70c729bb152a8bbd7cfe2f457e0d3fa1b1bac455d696bb27d23644aecff7cecd +size 75501 diff --git a/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset b/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset index 10a7d05..88cb645 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:ddadef2aaa688c7525f87d4498949ea64bf9f0e463bc0118bd86a3989a2f5acd +oid sha256:7893216176a7977d4784234bf10e6b49a219ab31dd61497f8db7958c5a04b7ce size 83550 diff --git a/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset b/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset index 3a001b0..7f5ec1b 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:8e13d22b4ae7ed978c6755adfd5b8c02d98157177976f792794c083b95797270 +oid sha256:fd5493759b160992ebec5073e59d67a6ea8ceeb1fbb35b0624223668934cebc3 size 83797 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset new file mode 100644 index 0000000..bb6d30d --- /dev/null +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc0d523f0fb587306a9e946e27b10113eb89df1218e6fdb8553b29f083384e49 +size 4605 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset new file mode 100644 index 0000000..fa49e20 --- /dev/null +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c765035f6c076c4016831884b167fa93e162bab7d0038f55cd09d240105dfa4c +size 4610 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset new file mode 100644 index 0000000..5948d47 --- /dev/null +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21454ed393d70dc103e0ad7ca00b06aed6fded381062ddcde87a424c05ff580d +size 4600 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset new file mode 100644 index 0000000..7aa4d2f --- /dev/null +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:891ee60d2feac3e741509e9e03756e9941b4561994e1a77732f565b7aae5bb52 +size 4615 diff --git a/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset b/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset index 3809334..908fab3 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:20165ed97f13fb5fba8391ca8735d9cf965eb97d676282d549afafb1a274b0ca +oid sha256:5b2c133f3dc163f937cc7f73de9ee35a31659451e43171abdaa1b1fc5b357e1a size 309810 diff --git a/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset b/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset index 0ad1590..1416015 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:e32a1f9590b943a40f05efbd531ec4e1a6c6933c579a5dec4a3dca8753e408c0 +oid sha256:a3fa880ce24eff71415cf8039b9e2347181087c2fa42ac217b022a55e1cc68a8 size 150676 diff --git a/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset b/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset index 5b0956e..9b7eae9 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:d66130107a5d5d996d8367cc1cbb55c7ef506a91df419f0c9ad5ee74d652b915 +oid sha256:bf71bb2cd8feebb44a102f9a4f44179a5d26d7fb125cf5fbec31d5084acbd9c4 size 164347 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index bd1a338..7d7ac7d 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:6d5d3a6fb6646ebeef426b7c07a58b872060779e6ffe0c8b073939ee93299ab8 -size 333138 +oid sha256:aa5407698175d4ca2a8e0ee7e3bdde23654337445260c9b314a62667d8edcdc1 +size 335528 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index 8db2af7..1f0d7e8 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:4d399b3e1b28616e58f445fca8a7de82e9bf1df7c4308500473fc0c63d6d597d +oid sha256:18fafef3a73b195fdbc21ff1c6e9a8d55f691ae3626e2f588d64871554297b31 size 28613 diff --git a/MEMORY.md b/MEMORY.md index 0e5e9b1..e19febc 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -174,3 +174,12 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. - **`EditorLevelLibrary.load_level`/`new_level` are deprecated no-ops in `-nullrhi` commandlets** (they return without switching worlds, so staged actors land in whatever world is current and get saved over the wrong map). Use the `LevelEditorSubsystem`: `unreal.get_editor_subsystem(unreal.LevelEditorSubsystem).load_level(path)` actually switches. Symptom was ReviewMap containing Demo actors + `ShotSequencer`. - **Map-save ordering bug in `Tools/ue_build_review_map.py`**: the script saved ReviewMap *after* the DemoMap section, but the switch back to ReviewMap fails silently because the map only exists in memory at that point — so the final `save_map` wrote the demo world over ReviewMap. Fix: save ReviewMap first, then stage the demo cameras, and never switch back. Both maps verified by probe (ReviewMap lists Review actors; DemoMap lists Demo actors). - Rebuilt ReviewMap after the fixes: character, both cubes (A grounded, B floating at 2 m), pawn, NPC prefab, hero facade all present; user re-approved the shots. README cube naming corrected (README had A/B swapped vs the script). + +## 2026-11-07 — Materials and lighting in the demo map + +- **Blender flat diffuse colours do not survive FBX -> Unreal.** Every site mesh (road, sidewalks, kerbs, crossing paint) imported with a material asset that had a default *white* base colour, and the terrain imported with `WorldGridMaterial` (UE's bright grey grid). That — not the sun — is what made the demo look blown out and washed white. Fix: create the colours in UE (`M_Asphalt`, `M_Concrete`, `M_Ground`, `M_RoadPaint` via `Constant3Vector`) and assign them per actor in `Tools/ue_build_demo_map.py`. +- **Auto-exposure makes review shots non-comparable**: the same road rendered washed-out in one framing and near-black in another because each camera saw a different amount of sky. Fix: an unbound `PostProcessVolume` with `AEM_HISTOGRAM` and `auto_exposure_min_brightness == auto_exposure_max_brightness` (fixed exposure). Do not use `AEM_MANUAL` + `auto_exposure_bias` — a bias of 11 blew the whole frame out. +- **`DirectionalLightComponent.light_color` takes a `Color` struct, not `LinearColor`** (`unreal.Color(r=255,g=245,b=230,a=255)`); passing `LinearColor` raises a nativize error. +- **One band per object loses geometry downstream.** `crossing_band()` created `Crossing_Markings` each call, so Blender renamed the second and third to `.001`/`.002`; `site_assembly.py` appends by exact name, so only one crossing ever reached the game. Build all bands into a single mesh instead of one object per band. +- **Street arc length -> UE X:** s=0 is the west end of the block (UE X −27966 cm) and s increases eastward, so the designated mid-block crossing at s=130.1 m is UE X ≈ −14956, not the −24291 used by an earlier camera (that is the s=36.6 crossing). +- **Camera placement in the demo map needs the mesh bounds, not intuition.** The hero façade body spans UE Y −1457..−200, so a "street level" camera at Y −400 is *inside* the building and renders its unlit back face. Read `get_bounding_box()` on the staged meshes before choosing a camera. diff --git a/Screenshots/README.md b/Screenshots/README.md index a022080..c2e6285 100644 --- a/Screenshots/README.md +++ b/Screenshots/README.md @@ -22,8 +22,14 @@ and exits — about a minute. The camera list lives in - **Floor**: 160 m square, top face at Z 0. The character measures Z 0..83 cm. - **Cubes**: `Cube_ScaleTest_A` rests on the floor, `Cube_ScaleTest_B` floats at Z 2 m; both are exactly 1 m — the scale reference. -- **Lighting**: one warm key light plus sky fill (review rig, not the `0.1.0` - daytime look). Beyond the floor is open: the horizon is a black band. +- **Lighting (review map)**: one warm key light plus sky fill, neutral exposure. +- **Lighting (demo map)**: fixed daytime — sun at pitch -50 / yaw 120 (intensity + 4, warm), sky light 2.6, sky atmosphere, height fog, and a manual-exposure + post-process volume (min = max brightness 1.0) so a shot cannot wash out or + crush to black depending on how much sky it frames. Surface colours are + assigned explicitly in `Tools/ue_build_demo_map.py` (`M_Asphalt`, `M_Concrete`, + `M_Ground`, `M_RoadPaint`) because Blender's flat diffuse colours do not + survive the FBX → Unreal import. ## Review-map shots @@ -53,10 +59,10 @@ Rendered from `/Game/Hollywood/DemoMap`, the walkable level. Click an image for | File | Preview | Approval | What it shows | | --- | --- | --- | --- | -| `demo/review-demo-spawn-view.png` | [spawn view](demo/review-demo-spawn-view.png) | ☑ | Spawn view: north sidewalk, the hero façade across the road | -| `demo/review-demo-street-level.png` | [street level](demo/review-demo-street-level.png) | ☑ | Street level: portals, flights, banners, colonnade | -| `demo/review-demo-crossing.png` | [crossing](demo/review-demo-crossing.png) | ☑ | The designated mid-block crossing (s=130 m): zebra markings on the road, kerbs flushed to ramps. Camera on the north sidewalk looking south-west. Note: the road renders near-black in shadow — the fixed-daytime-lighting item, not the markings | -| `demo/review-demo-north-buildings.png` | [north buildings](demo/review-demo-north-buildings.png) | ☑ | North-side background buildings (TCL, Tussaud's) across the Blvd | +| `demo/review-demo-spawn-view.png` | [spawn view](demo/review-demo-spawn-view.png) | needs review | Spawn view from the north sidewalk: the hero façade across the road under fixed daytime light | +| `demo/review-demo-street-level.png` | [street level](demo/review-demo-street-level.png) | needs review | Street level from the north sidewalk: the façade colonnade and columns at eye height, now sunlit with cast shadows (was backlit and near-black) | +| `demo/review-demo-crossing.png` | [crossing](demo/review-demo-crossing.png) | needs review | The designated mid-block crossing at s=130 m (UE X -14956): three continental zebra bars on the dark asphalt, kerbs flushed to ramps, camera on the north sidewalk looking along the crosswalk | +| `demo/review-demo-north-buildings.png` | [north buildings](demo/review-demo-north-buildings.png) | needs review | North-side background buildings (TCL, Tussaud's) across the Blvd, lit against the sky | ## What to look for diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index 041f7ed..f9523d8 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:b6bd66678c132a8fa09004f2f2e3d160b1c99122e1d1365932d7e31ed0933199 -size 1628670 +oid sha256:90b3f9e5aa44b2bd5f446c0532e1ecc7947e005188e909748f1d6520abf1648d +size 1568849 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index 137a99a..4ffe045 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:5eaa60227e5f6e307e1bf878b33d3f52634e0121dcaa6af73afd7fff5728499b -size 2304425 +oid sha256:1b3eb0d7831dcd3fe83cf2e0b65dc6b8f20b21ebf3d03ae538ad60565f5a5037 +size 1390196 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 9132d32..9635de1 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:a312b5ee86cd5c9fef8b686d2aae429199f88caae7276d6fb714d1d73fed996a -size 2571043 +oid sha256:a9106c7c915119e4df4bedc22404028ed060a71e309ff1662931890b55469644 +size 1573928 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 86a9834..22d99fc 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:2675eb353573003961c8d81ba24c2bbbe1f1052c11c4ee38cd786cab7115b686 -size 1975605 +oid sha256:fd5e854bfce63b51d573817bd86ca897b06cbf231b02c0302f7e99b1bb7c6870 +size 1783060 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index b550695..7aed33b 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:ea60ed98f688bab482160386d851b39a10868c64bf1371b3628427cc25a3de97 -size 2498425 +oid sha256:f314dcc5211758e70c0fde67ece08eaeef863cc27596eefb15fd706ed20d6ce8 +size 2476490 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 2c74a02..04fba20 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:03b47847338f6d840e1e2dd370fce585c599cd72db0cf1393b82cc91964619c0 -size 1778455 +oid sha256:ef80c5c6eb63b79e97ba41d8a79793b2215b71c854966c093904016aa3eb47da +size 1793304 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index 564b65c..24fbb72 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:fabcc154b139f35e0c6910f87a042c6cc51b9e263993cbfb49a15fa3817736d3 -size 2052242 +oid sha256:6a6b384911d4f07d1e165545ee6c78338869df8a8d30231d1194e7b89a6349df +size 2051886 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index 07d778c..1da0b73 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:20a85e17ab952b5f8de52556bbe9bf7b4dfb03c7e430a371eafa625b0874b4d7 -size 1917582 +oid sha256:9d47147cd5b8c4959ce61da5b7ea72c6bf4dab21bebfd9a2426809f873e72938 +size 1932092 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 69194a1..87dcc4a 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:8fa065612a714476d37f5cc4bb28182b30dc9b10cfcfd37cc04257d177b41f33 -size 1774919 +oid sha256:ce2496abd2848ae5d73c17e4eb7c2ccb9bd39437f0f47ee1f2e81b75a64974c6 +size 1778660 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index b10ff0f..3003951 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:c1522a746881f69e8fb2e327610ad9fd7d98e673c200ea8d781daab1f23317cc -size 1721860 +oid sha256:8de11af89103a6ab42531adbcab2985e29f239e0a2122972d1308d1ca98edba3 +size 1721002 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index d518bc4..76dcd69 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:78b318299a7633fb267c961ecfd61f5fe7a0a3278d28103b634d21f47bc01c49 -size 2580045 +oid sha256:50c31d72e9149efbd61e4dd454f2671342162a1a3aa58140c1427d523e2091a5 +size 2608909 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index f39f1df..d86b002 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:605fc1ee8ef167a57d119ef83e741ab1e6d8fbba923bfe5aa162f0dda1069830 -size 1969709 +oid sha256:4c21d2f5f92612cca6963b3217ae9f2ebf45c94837a09b6f0e8398622a9bc040 +size 1964636 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 8fc47eb..9ca844c 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:26c64adad9f64789c85882a224d402ae4e8ca20eb73736731925972275fc560d -size 1906660 +oid sha256:daad42906dd5ee802051d09ca813a293a4b73927dd68adc876fc6612ce8ef951 +size 1902016 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index 2d975fa..f5555bc 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:bab0f21cc8a6c90889e0003510b7df68f6f23d16e69e9ba08faec40deef77c8b -size 1735259 +oid sha256:79123a8f37fd95b617decda35469f7c629f89bbe5f64c063f8b087b27f2615ce +size 1731317 diff --git a/TODO.md b/TODO.md index e5d3374..7061a9d 100644 --- a/TODO.md +++ b/TODO.md @@ -95,7 +95,7 @@ The MPFB character asset is planned as the NPC template (see `ROADMAP.md`). Keep - [~] Collision, reset, and pause functionality. Reset (**R**) and pause (**Escape**, a real game pause that releases the cursor) are implemented in `AGigLineCharacter` with `/Game/Input/IA_Reset` and `IA_Pause`. Collision now exists — terrain, road and sidewalks import as complex-as-simple, so a simple hull cannot ramp over the kerbs. **Not verified by hand**: walk, reset and pause need a human at the keyboard. No pause menu widget yet, only the pause itself. - [x] Build the walkable demo level: terrain, street, and hero facade assembled into one map with a start point on the north sidewalk, so the demo is something a player can walk rather than a review staging. **Built 2026-11-07** by `Tools/ue_build_demo_map.py` → `/Game/Hollywood/DemoMap`: sun/sky, `Hero_Facade`, six site meshes imported with collision (`Terrain_DEM`, `Road_Hollywood`, both sidewalks and both kerbs), and a `Demo_PlayerStart` on the north sidewalk 20 m back from the frontage. Demo views in `Screenshots/demo/` re-rendered and ☑ approved 2026-11-07. - [x] Walkable sidewalks and a designated street crossing. Crossing chosen: mid-block signalised crossing, OSM way 385648319, at 130 m along the block (`Geo/verification/2026-11-06-street-profile.md`). Done 2026-11-07: continental zebra markings (0.5 m bars / 0.5 m gaps, 3 m band) at all three signalised crossings, no collision on the paint; kerbs were already flushed at the crossings. Enablers found on the way: the street surfaces were 100 % down-facing (invisible in engine) — winding flipped; the terrain buried the street — 10.7 m corridor cut around the centreline (sidewalks cover the transition, walk-check 0 holes); LFS-lockable `.blend`/`.umap` check out read-only — builders now chmod before saving and fail loudly. Screenshot ☑ approved 2026-11-07 (`Screenshots/demo/review-demo-crossing`); the corridor renders near-black in shadow — that is the still-open **Fixed daytime lighting** item, not the crossing. -- [-] Fixed daytime lighting and basic ambience. Current state: `Demo_Sun` at pitch −35, yaw 200 puts the street corridor in shadow — the crossing shot renders near-black. Plan: rotate sun yaw so light comes down the street axis (e/w), raise sun intensity, boost skylight fill, set fixed daytime (no time-of-day motion). +- [-] Fixed daytime lighting and basic ambience. **Implemented 2026-11-07**, pending screenshot approval. Demo map now has a fixed daytime rig in `Tools/ue_build_demo_map.py`: sun pitch −50 / yaw 120 (intensity 4, warm 255/245/230, atmosphere sun light), sky light 2.6 with real-time capture, sky atmosphere, height fog (density 0.008), and a manual-exposure post-process volume (min = max brightness 1.0) so a shot cannot wash out or crush to black. Two root causes found while doing it: (a) **Blender flat diffuse colours do not survive the FBX→UE import** — every site mesh arrived white and the terrain arrived with `WorldGridMaterial`, which is what actually made the scene look blown out; explicit `M_Asphalt` / `M_Concrete` / `M_Ground` / `M_RoadPaint` materials are now created and assigned in the demo builder. (b) only **one of the three crossings** was reaching the game: each band was its own object and Blender renamed the duplicates `.001`/`.002`, which site assembly skips; all bands are now one `Crossing_Markings` object. Demo cameras also fixed: street-level sat inside the façade body, and the crossing camera aimed at the wrong crossing (s=36.6 instead of the designated s=130.1 at UE X −14956). - [ ] Geographic attribution display ("© OpenStreetMap contributors" + license link). ### Repository publication diff --git a/Tools/ue_build_demo_map.py b/Tools/ue_build_demo_map.py index a79107d..cbbde45 100644 --- a/Tools/ue_build_demo_map.py +++ b/Tools/ue_build_demo_map.py @@ -50,6 +50,29 @@ def spawn(cls, loc, label, rot=None): return actor +def ensure_material(asset_name, rgb): + """Create/reuse a flat-colour material under /Game/Hollywood/Site. + + Used where the FBX material round-trip does not survive import: the terrain + arrives with WorldGridMaterial (UE's bright default grid), which reads as a + blown-out white field under the demo sun. + """ + path = f"/Game/Hollywood/Site/{asset_name}" + if unreal.EditorAssetLibrary.does_asset_exist(path): + return unreal.EditorAssetLibrary.load_asset(path) + mat = unreal.AssetToolsHelpers.get_asset_tools().create_asset( + asset_name, "/Game/Hollywood/Site", unreal.Material, unreal.MaterialFactoryNew()) + node = unreal.MaterialEditingLibrary.create_material_expression( + mat, unreal.MaterialExpressionConstant3Vector) + node.set_editor_property("constant", unreal.LinearColor(rgb[0], rgb[1], rgb[2], 1.0)) + unreal.MaterialEditingLibrary.connect_material_property( + node, "", unreal.MaterialProperty.MP_BASE_COLOR) + unreal.MaterialEditingLibrary.recompile_material(mat) + unreal.EditorAssetLibrary.save_loaded_asset(mat) + log(f"created material {asset_name} rgb={rgb}") + return mat + + def clear(prefixes=()): removed = 0 for actor in unreal.EditorLevelLibrary.get_all_level_actors(): @@ -74,12 +97,87 @@ def build(): removed = clear(("Demo_", "PlayerStart", "Hero_Facade")) log(f"cleared {removed} previous demo actors") - # --- lighting --------------------------------------------------------- - spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 2000), "Demo_Sun", - unreal.Rotator(pitch=-35.0, yaw=200.0, roll=0.0)) - spawn(unreal.SkyLight, unreal.Vector(0, 0, 2000), "Demo_SkyLight") + # --- lighting: fixed daytime ------------------------------------------ + # The demo is a fixed daytime scene, not a time-of-day simulation. Three + # things matter and each was wrong before: + # + # 1. Sun angle. The hero facade front faces -Y and the road faces +Z. A sun + # at yaw 120 / pitch -50 shines toward (-X, +Y, down), so it lights both + # the facade front and the carriageway instead of raking across them. + # 2. Exposure. Auto-exposure made the same road washed-out in one shot and + # near-black in the next, because each camera framed a different amount + # of sky. A manual-exposure post-process volume pins it. + # 3. Ambience. A height fog gives the street depth and hides the terrain + # edge that otherwise reads as a black band at the horizon. + sun = spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 2000), "Demo_Sun", + unreal.Rotator(pitch=-50.0, yaw=120.0, roll=0.0)) + if sun: + comp = sun.get_component_by_class(unreal.DirectionalLightComponent) + if comp: + for prop, value in ( + ("intensity", 4.0), + ("light_color", unreal.Color(r=255, g=245, b=230, a=255)), + ("atmosphere_sun_light", True), + ): + try: + comp.set_editor_property(prop, value) + except Exception as exc: # noqa: BLE001 + log(f"sun.{prop} not set: {exc!r}") + log("staged: Demo_Sun (pitch -50, yaw 120, intensity 4, warm)") + + sky = spawn(unreal.SkyLight, unreal.Vector(0, 0, 2000), "Demo_SkyLight") + if sky: + comp = sky.get_component_by_class(unreal.SkyLightComponent) + if comp: + for prop, value in (("intensity", 2.6), ("real_time_capture", True)): + try: + comp.set_editor_property(prop, value) + except Exception as exc: # noqa: BLE001 + log(f"sky.{prop} not set: {exc!r}") + log("staged: Demo_SkyLight (intensity 2.6, real-time capture)") + spawn(unreal.SkyAtmosphere, unreal.Vector(0, 0, 0), "Demo_Sky") - log("staged: sun, sky light, sky atmosphere") + log("staged: Demo_Sky (sky atmosphere)") + + fog = spawn(unreal.ExponentialHeightFog, unreal.Vector(0, 0, 0), "Demo_Fog") + if fog: + comp = fog.get_component_by_class(unreal.ExponentialHeightFogComponent) + if comp: + for prop, value in ( + ("fog_density", 0.008), + ("fog_height_falloff", 0.15), + ("start_distance", 3000.0), + ): + try: + comp.set_editor_property(prop, value) + except Exception as exc: # noqa: BLE001 + log(f"fog.{prop} not set: {exc!r}") + log("staged: Demo_Fog (height fog, density 0.008)") + + # Fixed exposure: without this the same road renders washed out or black + # depending on how much sky the camera frames. Pinning min == max brightness + # freezes the exposure at one value (the classic fixed-exposure trick); + # AEM_MANUAL with a bias was tried first and blew the frame out. + ppv = spawn(unreal.PostProcessVolume, unreal.Vector(0, 0, 0), "Demo_PostProcess") + if ppv: + ppv.set_editor_property("unbound", True) + settings = ppv.get_editor_property("settings") + for prop, value in ( + ("override_auto_exposure_method", True), + ("auto_exposure_method", unreal.AutoExposureMethod.AEM_HISTOGRAM), + ("override_auto_exposure_min_brightness", True), + ("auto_exposure_min_brightness", 1.0), + ("override_auto_exposure_max_brightness", True), + ("auto_exposure_max_brightness", 1.0), + ("override_auto_exposure_bias", True), + ("auto_exposure_bias", 0.0), + ): + try: + settings.set_editor_property(prop, value) + except Exception as exc: # noqa: BLE001 + log(f"pp.{prop} not set: {exc!r}") + ppv.set_editor_property("settings", settings) + log("staged: Demo_PostProcess (fixed exposure, min=max brightness 1.0)") # --- hero facade on the measured building line ------------------------ hero = unreal.EditorAssetLibrary.load_asset("/Game/Hollywood/ElCapitan/SM_HeroFacade") @@ -93,9 +191,21 @@ def build(): log("MISSING: SM_HeroFacade — run Tools/ue_hero_facade_import.py") # --- site meshes, if they have been imported -------------------------- + # Blender's flat diffuse colours do not survive FBX -> Unreal: Interchange + # builds a material with a default white base colour, and the terrain even + # lands with WorldGridMaterial. Every site surface therefore rendered white, + # which is what washed out the demo. Assign explicit colours per mesh here. + SURFACE_MATERIALS = { + "Terrain_DEM": ("M_Ground", (0.30, 0.28, 0.25)), + "Road_Hollywood": ("M_Asphalt", (0.055, 0.055, 0.06)), + "Sidewalk_South": ("M_Concrete", (0.52, 0.50, 0.47)), + "Sidewalk_North": ("M_Concrete", (0.52, 0.50, 0.47)), + "Kerb_South": ("M_Concrete", (0.52, 0.50, 0.47)), + "Kerb_North": ("M_Concrete", (0.52, 0.50, 0.47)), + "Crossing_Markings": ("M_RoadPaint", (0.80, 0.80, 0.78)), + } imported = 0 - for name in ("Terrain_DEM", "Road_Hollywood", "Sidewalk_South", "Sidewalk_North", - "Kerb_South", "Kerb_North", "Crossing_Markings"): + for name, (mat_name, rgb) in SURFACE_MATERIALS.items(): mesh = unreal.EditorAssetLibrary.load_asset(f"/Game/Hollywood/Site/{name}") if mesh is None: continue @@ -103,8 +213,11 @@ def build(): if actor: actor.static_mesh_component.set_static_mesh(mesh) actor.static_mesh_component.set_mobility(unreal.ComponentMobility.STATIC) + mat = ensure_material(mat_name, rgb) + if mat: + actor.static_mesh_component.set_material(0, mat) imported += 1 - log(f"staged {imported} site meshes from /Game/Hollywood/Site") + log(f"staged {imported} site meshes with explicit surface materials") # --- player start: north sidewalk, facing the hero frontage ------------- # Signs were measured from the imported meshes rather than assumed: the FBX diff --git a/Tools/ue_build_review_map.py b/Tools/ue_build_review_map.py index bd48a94..edd3ce9 100644 --- a/Tools/ue_build_review_map.py +++ b/Tools/ue_build_review_map.py @@ -258,8 +258,17 @@ try: # 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(-10722.5, -3500, 165), unreal.Vector(-10722.5, -1450, 700)), - ("demo-street-level", unreal.Vector(-11000, -400, 165), unreal.Vector(-10722.5, -1450, 500)), - ("demo-crossing", unreal.Vector(-23750, -1800, 480), unreal.Vector(-24291, -1400, 300)), + # 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(-10850, -2600, 170), unreal.Vector(-10722.5, -1450, 400)), + # 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 + # on the north sidewalk looking along the crosswalk itself, which is + # the pedestrian's view and shows the zebra bars as bars. + ("demo-crossing", unreal.Vector(-15250, -2500, 400), unreal.Vector(-14956, 400, 150)), # the two north-side background buildings (TCL, Tussaud's) seen from # the south sidewalk, across Hollywood Blvd: their frontage and mass. ("demo-north-buildings", unreal.Vector(-22800, -1000, 400), unreal.Vector(-22800, 3000, 300)), -- 2.47.3 From 240bad9af1774264f1ea619618a52b24cbb8a60c Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sat, 7 Nov 2026 18:08:49 +0100 Subject: [PATCH 3/4] lighting: dynamic-only lights so no lighting build is required The editor warned 'LIGHTING NEEDS TO BE REBUILT' (Build Lighting Only / BuildLighting) because the sun and sky were Stationary with no baked lightmap. The demo is a fixed daytime scene lit entirely dynamically, so: - Config/DefaultEngine.ini: r.AllowStaticLighting=False - nothing to build. - DemoMap + ReviewMap builders: sun, sky light, height fog and the staged mesh components are set to ComponentMobility.MOVABLE. Also clears the Android File Server SecurityToken in DefaultEngine.ini: the plugin is disabled and excluded from shipping, and the value is a credential that must not be committed. All 14 screenshots re-rendered; no lighting warnings in the build or run logs. --- Game/GigLine/Config/DefaultEngine.ini | 11 ++++++-- Game/GigLine/Content/Hollywood/DemoMap.umap | 4 +-- Game/GigLine/Content/Test/ReviewMap.umap | 4 +-- MEMORY.md | 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 +-- Tools/ue_build_demo_map.py | 18 +++++++++++-- Tools/ue_build_review_map.py | 27 +++++++++++++++---- 20 files changed, 81 insertions(+), 41 deletions(-) diff --git a/Game/GigLine/Config/DefaultEngine.ini b/Game/GigLine/Config/DefaultEngine.ini index 22075f3..80015db 100644 --- a/Game/GigLine/Config/DefaultEngine.ini +++ b/Game/GigLine/Config/DefaultEngine.ini @@ -2,7 +2,12 @@ GlobalDefaultGameMode="/Script/GigLine.GigLineGameModeBase" [/Script/Engine.RendererSettings] -; Leave defaults for 0.1.0; quality preset is documented at release time. +; Dynamic-only lighting. With static lighting allowed, the stationary sun and +; sky light demanded a baked lighting build and the editor warned +; "LIGHTING NEEDS TO BE REBUILT" (Build Lighting Only / BuildLighting) on every +; map. The demo is a fixed daytime scene lit entirely dynamically, so disable +; static lighting outright — nothing to build, no warning. +r.AllowStaticLighting=False [URL] GameName=GigLine @@ -10,7 +15,9 @@ GameName=GigLine [/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] bEnablePlugin=False bAllowNetworkConnection=False -SecurityToken=01A1B5CDAFDE7AAEB5DFBB48880D25DE +; SecurityToken intentionally empty: it is a credential, and the plugin is +; disabled and excluded from shipping. Never commit a real token here. +SecurityToken= bIncludeInShipping=False bAllowExternalStartInShipping=False bCompileAFSProject=False diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index adfeb64..b3426fd 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:3f3925238751bd1cfd9b145a7bc3a12945392434b7ea3f345bc822116f4f5a51 -size 44553 +oid sha256:db7e2632a0e5c75d7722f0aab9f727a931fed942c0ee870892da02c2e4c79710 +size 44952 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index 1f0d7e8..5fee868 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:18fafef3a73b195fdbc21ff1c6e9a8d55f691ae3626e2f588d64871554297b31 -size 28613 +oid sha256:ed3baf3965562bea42fd99f8a47438491d86b383a77a0620c592a5964197c198 +size 28715 diff --git a/MEMORY.md b/MEMORY.md index e19febc..ba707ff 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -183,3 +183,5 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. - **One band per object loses geometry downstream.** `crossing_band()` created `Crossing_Markings` each call, so Blender renamed the second and third to `.001`/`.002`; `site_assembly.py` appends by exact name, so only one crossing ever reached the game. Build all bands into a single mesh instead of one object per band. - **Street arc length -> UE X:** s=0 is the west end of the block (UE X −27966 cm) and s increases eastward, so the designated mid-block crossing at s=130.1 m is UE X ≈ −14956, not the −24291 used by an earlier camera (that is the s=36.6 crossing). - **Camera placement in the demo map needs the mesh bounds, not intuition.** The hero façade body spans UE Y −1457..−200, so a "street level" camera at Y −400 is *inside* the building and renders its unlit back face. Read `get_bounding_box()` on the staged meshes before choosing a camera. +- **"LIGHTING NEEDS TO BE REBUILT" (Build Lighting Only / `BuildLighting`) appears whenever a map has Stationary/Static lights and no baked lightmap.** For a fully dynamic scene the clean fix is `r.AllowStaticLighting=False` in `Config/DefaultEngine.ini` plus `set_mobility(ComponentMobility.MOVABLE)` on the directional light, sky light and height fog (and MOVABLE on the staged mesh components). Nothing to build, warning gone. Note the cvar is read at startup, so each new commandlet/game run picks it up. +- The Android File Server `SecurityToken` kept reappearing in `Config/DefaultEngine.ini`; the plugin is disabled and excluded from shipping, so the value is cleared and must stay empty — it is a credential and must not be committed. diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index f9523d8..ae841f7 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:90b3f9e5aa44b2bd5f446c0532e1ecc7947e005188e909748f1d6520abf1648d -size 1568849 +oid sha256:7f70435845fa5e34a04ba2e3ca193b54db655791076e8cb80d88546ada3af143 +size 1570518 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index 4ffe045..515855f 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:1b3eb0d7831dcd3fe83cf2e0b65dc6b8f20b21ebf3d03ae538ad60565f5a5037 -size 1390196 +oid sha256:807dc31930ffcbcf3c2449f34eb731a7694c8142afe0252666425cb7d385caa8 +size 1536544 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 9635de1..81376d8 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:a9106c7c915119e4df4bedc22404028ed060a71e309ff1662931890b55469644 -size 1573928 +oid sha256:5970fb86c28990883a15745305f1a1ca4419b8c5a450dbe3fb39e6f24b19f59d +size 1587231 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 22d99fc..6c21f6a 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:fd5e854bfce63b51d573817bd86ca897b06cbf231b02c0302f7e99b1bb7c6870 -size 1783060 +oid sha256:0214e624ebacd17c430cada10a4446c1977a17a380d54e720a48bbb8babc5ac0 +size 1763767 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index 7aed33b..7fb4c72 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:f314dcc5211758e70c0fde67ece08eaeef863cc27596eefb15fd706ed20d6ce8 -size 2476490 +oid sha256:806dba0d9bf0ee00d4174d0834babcd2bfa83b4c2132955565ff2759b555b337 +size 2519676 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 04fba20..23b215c 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:ef80c5c6eb63b79e97ba41d8a79793b2215b71c854966c093904016aa3eb47da -size 1793304 +oid sha256:c7b403af87a3f50a394bcfd7d997b714553c1580912cffa5bc868b4503104d01 +size 1729770 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index 24fbb72..f73dbf5 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:6a6b384911d4f07d1e165545ee6c78338869df8a8d30231d1194e7b89a6349df -size 2051886 +oid sha256:da3ac44e5fd1bf0f9c0675e7582014b871f5ec2ea74543fed201d686c1d307dd +size 2075675 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index 1da0b73..1f39b90 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:9d47147cd5b8c4959ce61da5b7ea72c6bf4dab21bebfd9a2426809f873e72938 -size 1932092 +oid sha256:81cab701b528d7ad97225384d966c8282c6e2b3c22ad90e37a3fac4b72473ca5 +size 1939088 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 87dcc4a..6863b08 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:ce2496abd2848ae5d73c17e4eb7c2ccb9bd39437f0f47ee1f2e81b75a64974c6 -size 1778660 +oid sha256:29a42347337c797a696b795f594d7eebc58c51a3258cd1726bce0475d3b3ebcc +size 1757866 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index 3003951..d874e8d 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:8de11af89103a6ab42531adbcab2985e29f239e0a2122972d1308d1ca98edba3 -size 1721002 +oid sha256:1cbd2acd364eb35a5802393d5d3f94036948a054020c2c9e967f5c2153ee3792 +size 1722019 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index 76dcd69..7839f02 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:50c31d72e9149efbd61e4dd454f2671342162a1a3aa58140c1427d523e2091a5 -size 2608909 +oid sha256:91b3c428b7118df3ff9d11d0b114130b7380c6fa49834f8bac6eb9747a9e5f15 +size 3164110 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index d86b002..3ff2e11 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:4c21d2f5f92612cca6963b3217ae9f2ebf45c94837a09b6f0e8398622a9bc040 -size 1964636 +oid sha256:836ddf77b91575b61eb54d11981a0d6b8fad6e0ff82e54143d863e48b906921d +size 2009205 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 9ca844c..ce4f357 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:daad42906dd5ee802051d09ca813a293a4b73927dd68adc876fc6612ce8ef951 -size 1902016 +oid sha256:07f91984000f49c7960e87829fac422351942ddda08b56f47a2addeb428f08f3 +size 2027852 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index f5555bc..9aeac8d 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:79123a8f37fd95b617decda35469f7c629f89bbe5f64c063f8b087b27f2615ce -size 1731317 +oid sha256:aa8b21c253851de43194647be76a5c8bd69fdda315a1f163f7f16566c45e1a62 +size 1684025 diff --git a/Tools/ue_build_demo_map.py b/Tools/ue_build_demo_map.py index cbbde45..2883931 100644 --- a/Tools/ue_build_demo_map.py +++ b/Tools/ue_build_demo_map.py @@ -123,6 +123,12 @@ def build(): comp.set_editor_property(prop, value) except Exception as exc: # noqa: BLE001 log(f"sun.{prop} not set: {exc!r}") + # Movable: static lighting is disabled (r.AllowStaticLighting=False), + # so nothing needs a lighting build. + try: + comp.set_mobility(unreal.ComponentMobility.MOVABLE) + except Exception as exc: # noqa: BLE001 + log(f"sun mobility not set: {exc!r}") log("staged: Demo_Sun (pitch -50, yaw 120, intensity 4, warm)") sky = spawn(unreal.SkyLight, unreal.Vector(0, 0, 2000), "Demo_SkyLight") @@ -134,6 +140,10 @@ def build(): comp.set_editor_property(prop, value) except Exception as exc: # noqa: BLE001 log(f"sky.{prop} not set: {exc!r}") + try: + comp.set_mobility(unreal.ComponentMobility.MOVABLE) + except Exception as exc: # noqa: BLE001 + log(f"sky mobility not set: {exc!r}") log("staged: Demo_SkyLight (intensity 2.6, real-time capture)") spawn(unreal.SkyAtmosphere, unreal.Vector(0, 0, 0), "Demo_Sky") @@ -152,6 +162,10 @@ def build(): comp.set_editor_property(prop, value) except Exception as exc: # noqa: BLE001 log(f"fog.{prop} not set: {exc!r}") + try: + comp.set_mobility(unreal.ComponentMobility.MOVABLE) + except Exception as exc: # noqa: BLE001 + log(f"fog mobility not set: {exc!r}") log("staged: Demo_Fog (height fog, density 0.008)") # Fixed exposure: without this the same road renders washed out or black @@ -185,7 +199,7 @@ def build(): actor = spawn(unreal.StaticMeshActor, unreal.Vector(-10722.5, -1443.0, 0.0), "Hero_Facade") if actor: actor.static_mesh_component.set_static_mesh(hero) - actor.static_mesh_component.set_mobility(unreal.ComponentMobility.STATIC) + actor.static_mesh_component.set_mobility(unreal.ComponentMobility.MOVABLE) log("staged: Hero_Facade at the building line") else: log("MISSING: SM_HeroFacade — run Tools/ue_hero_facade_import.py") @@ -212,7 +226,7 @@ def build(): actor = spawn(unreal.StaticMeshActor, unreal.Vector(0, 0, 0), f"Demo_{name}") if actor: actor.static_mesh_component.set_static_mesh(mesh) - actor.static_mesh_component.set_mobility(unreal.ComponentMobility.STATIC) + actor.static_mesh_component.set_mobility(unreal.ComponentMobility.MOVABLE) mat = ensure_material(mat_name, rgb) if mat: actor.static_mesh_component.set_material(0, mat) diff --git a/Tools/ue_build_review_map.py b/Tools/ue_build_review_map.py index edd3ce9..55a9baf 100644 --- a/Tools/ue_build_review_map.py +++ b/Tools/ue_build_review_map.py @@ -96,11 +96,28 @@ try: else: log("floor spawn failed") - if spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 900), "RenderKeyLight", - rot=unreal.Rotator(pitch=-38.0, yaw=35.0, roll=0.0)): - log("staged: DirectionalLight") - if spawn(unreal.SkyLight, unreal.Vector(0, 0, 1200), "RenderFillSky"): - log("staged: SkyLight") + # Lights are Movable and the project disables static lighting + # (r.AllowStaticLighting=False), so no baked lighting build is needed and + # the editor stops asking to rebuild lighting. + sun = spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 900), "RenderKeyLight", + rot=unreal.Rotator(pitch=-38.0, yaw=35.0, roll=0.0)) + if sun: + comp = sun.get_component_by_class(unreal.DirectionalLightComponent) + if comp: + try: + comp.set_mobility(unreal.ComponentMobility.MOVABLE) + except Exception as exc: # noqa: BLE001 + log(f"key light mobility not set: {exc!r}") + log("staged: DirectionalLight (movable)") + sky = spawn(unreal.SkyLight, unreal.Vector(0, 0, 1200), "RenderFillSky") + if sky: + comp = sky.get_component_by_class(unreal.SkyLightComponent) + if comp: + try: + comp.set_mobility(unreal.ComponentMobility.MOVABLE) + except Exception as exc: # noqa: BLE001 + log(f"fill sky mobility not set: {exc!r}") + log("staged: SkyLight (movable)") if spawn(unreal.SkyAtmosphere, unreal.Vector(0, 0, 0), "RenderSky"): log("staged: SkyAtmosphere") -- 2.47.3 From 04081ed178b9b5b662316a4c0c4df54e8dd426cf Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sat, 7 Nov 2026 18:16:12 +0100 Subject: [PATCH 4/4] docs: consolidate screenshot table, mark all shots approved - Screenshots/README.md: one table for all 14 shots (review + demo) with an index, the map each came from, camera view and description; all approved 2026-11-07 by the owner. Scene conventions now document both maps and the dynamic-only lighting setup. - TODO.md: Fixed daytime lighting marked done; the stale 'corridor renders near-black' note on the crossing item updated. --- Screenshots/README.md | 79 ++++++++++++++++++++----------------------- TODO.md | 4 +-- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/Screenshots/README.md b/Screenshots/README.md index c2e6285..29723f5 100644 --- a/Screenshots/README.md +++ b/Screenshots/README.md @@ -17,52 +17,45 @@ camera list via `AGigLineShotActor`, captures each shot, copies the PNGs here and exits — about a minute. The camera list lives in `Tools/ue_build_review_map.py`; add new shots there, remove retired ones here. +> Naming: shots use their stable camera name (no index prefix), so adding or +> reordering cameras never renumbers files or orphans the old ones. Click an +> image for the full-size PNG. + +## Shot list + +All ☑ approved 2026-11-07. + +| # | File | Preview | Map | View | What it shows | +| --- | --- | --- | --- | --- | --- | +| 1 | `review-overview.png` | [overview](review-overview.png) | Review | 7 m up, NE | Whole review layout: character + both cubes on the floor | +| 2 | `review-character.png` | [character](review-character.png) | Review | eye height, south | MPFB mannequin, idle pose + warm skin; feet meet the plane | +| 3 | `review-scale-cubes.png` | [scale cubes](review-scale-cubes.png) | Review | south | Floating vs grounded cube: cast vs contact shadow | +| 4 | `review-player-placement.png` | [player placement](review-player-placement.png) | Review | spawn | The `AGigLineCharacter` pawn, capsule height and landing | +| 5 | `review-npc-prefab.png` | [npc prefab](review-npc-prefab.png) | Review | mid, west | The `AGigLineNPCPerson` prefab: collision capsule + visible MPFB body, feet on Z 0 | +| 6 | `review-ground-contact.png` | [ground contact](review-ground-contact.png) | Review | knee height, feet | Floating/sinking character is obvious here | +| 7 | `review-shadow-compare.png` | [shadow compare](review-shadow-compare.png) | Review | low angle | Detached (floating) vs touching (grounded) shadows | +| 8 | `review-hero-portals.png` | [hero portals](review-hero-portals.png) | Review | 8 m, eye height | Three genuine 1.2 m portal recesses with flights and plinth | +| 9 | `review-hero-facade-front.png` | [hero facade front](review-hero-facade-front.png) | Review | road side, straight-on | Hero façade elevation and column rhythm | +| 10 | `review-hero-facade-oblique.png` | [hero facade oblique](review-hero-facade-oblique.png) | Review | north-west | Body depth and column line standing proud of the mass | +| 11 | `demo/review-demo-spawn-view.png` | [spawn view](demo/review-demo-spawn-view.png) | Demo | spawn point | Spawn view from the north sidewalk: the hero façade across the road under fixed daytime light | +| 12 | `demo/review-demo-street-level.png` | [street level](demo/review-demo-street-level.png) | Demo | eye height, north side | The façade colonnade and columns, sunlit with cast shadows | +| 13 | `demo/review-demo-crossing.png` | [crossing](demo/review-demo-crossing.png) | Demo | along the crosswalk | The designated mid-block crossing at s=130 m (UE X -14956): three continental zebra bars on the asphalt, kerbs flushed to ramps | +| 14 | `demo/review-demo-north-buildings.png` | [north buildings](demo/review-demo-north-buildings.png) | Demo | across the Blvd | North-side background buildings (TCL, Tussaud's), lit against the sky | + ## Scene conventions -- **Floor**: 160 m square, top face at Z 0. The character measures Z 0..83 cm. +- **Review map** (`/Game/Test/ReviewMap`): 160 m floor, top face at Z 0; the + character measures Z 0..83 cm. One warm key light plus sky fill. - **Cubes**: `Cube_ScaleTest_A` rests on the floor, `Cube_ScaleTest_B` floats at Z 2 m; both are exactly 1 m — the scale reference. -- **Lighting (review map)**: one warm key light plus sky fill, neutral exposure. -- **Lighting (demo map)**: fixed daytime — sun at pitch -50 / yaw 120 (intensity - 4, warm), sky light 2.6, sky atmosphere, height fog, and a manual-exposure - post-process volume (min = max brightness 1.0) so a shot cannot wash out or - crush to black depending on how much sky it frames. Surface colours are - assigned explicitly in `Tools/ue_build_demo_map.py` (`M_Asphalt`, `M_Concrete`, - `M_Ground`, `M_RoadPaint`) because Blender's flat diffuse colours do not - survive the FBX → Unreal import. - -## Review-map shots - -All ☑ approved 2026-11-07 (re-rendered with the character and cubes restored; -user visual check passed). - -> Naming: shots use their stable `Tools/ue_build_review_map.py` camera name (no -> index prefix), so adding or reordering cameras never renumbers files or -> orphans the old ones. Click an image for the full-size PNG. - -| File | Preview | View | What it shows | -| --- | --- | --- | --- | -| `review-overview.png` | [overview](review-overview.png) | 7 m up, NE | Whole review layout: character + both cubes on the floor | -| `review-character.png` | [character](review-character.png) | eye height, south | MPFB mannequin, idle pose + warm skin; feet meet the plane | -| `review-scale-cubes.png` | [scale cubes](review-scale-cubes.png) | south | Floating vs grounded cube: cast vs contact shadow | -| `review-player-placement.png` | [player placement](review-player-placement.png) | spawn | The `AGigLineCharacter` pawn, capsule height and landing | -| `review-npc-prefab.png` | [npc prefab](review-npc-prefab.png) | mid, west | The `AGigLineNPCPerson` prefab: collision capsule + visible MPFB body, feet on Z 0 (**new 2026-11-07**) | -| `review-ground-contact.png` | [ground contact](review-ground-contact.png) | knee height, feet | Floating/sinking character is obvious here | -| `review-shadow-compare.png` | [shadow compare](review-shadow-compare.png) | low angle | Detached (floating) vs touching (grounded) shadows | -| `review-hero-portals.png` | [hero portals](review-hero-portals.png) | 8 m, eye height | Three genuine 1.2 m portal recesses with flights and plinth | -| `review-hero-facade-front.png` | [hero facade front](review-hero-facade-front.png) | road side, straight-on | Hero façade elevation and column rhythm | -| `review-hero-facade-oblique.png` | [hero facade oblique](review-hero-facade-oblique.png) | north-west | Body depth and column line standing proud of the mass | - -## Demo-map views - -Rendered from `/Game/Hollywood/DemoMap`, the walkable level. Click an image for the full-size PNG. - -| File | Preview | Approval | What it shows | -| --- | --- | --- | --- | -| `demo/review-demo-spawn-view.png` | [spawn view](demo/review-demo-spawn-view.png) | needs review | Spawn view from the north sidewalk: the hero façade across the road under fixed daytime light | -| `demo/review-demo-street-level.png` | [street level](demo/review-demo-street-level.png) | needs review | Street level from the north sidewalk: the façade colonnade and columns at eye height, now sunlit with cast shadows (was backlit and near-black) | -| `demo/review-demo-crossing.png` | [crossing](demo/review-demo-crossing.png) | needs review | The designated mid-block crossing at s=130 m (UE X -14956): three continental zebra bars on the dark asphalt, kerbs flushed to ramps, camera on the north sidewalk looking along the crosswalk | -| `demo/review-demo-north-buildings.png` | [north buildings](demo/review-demo-north-buildings.png) | needs review | North-side background buildings (TCL, Tussaud's) across the Blvd, lit against the sky | +- **Demo map** (`/Game/Hollywood/DemoMap`): fixed daytime — sun at pitch −50 / + yaw 120 (intensity 4, warm), sky light 2.6, sky atmosphere, height fog, fixed + exposure. Surface colours are assigned explicitly in + `Tools/ue_build_demo_map.py` (`M_Asphalt`, `M_Concrete`, `M_Ground`, + `M_RoadPaint`) because Blender's flat diffuse colours do not survive the + FBX → Unreal import. +- **Lighting is dynamic-only** (`r.AllowStaticLighting=False`, all lights + Movable), so no lighting build is ever required. ## What to look for @@ -79,4 +72,4 @@ Rendered from `/Game/Hollywood/DemoMap`, the walkable level. Click an image for - Banners and window panels float detached from the colonnade wall (next modelling pass). - Between kerb and building line, the walkable surface is the terrain mesh, not - a modelled pavement. \ No newline at end of file + a modelled pavement. diff --git a/TODO.md b/TODO.md index 7061a9d..47817bc 100644 --- a/TODO.md +++ b/TODO.md @@ -94,8 +94,8 @@ The MPFB character asset is planned as the NPC template (see `ROADMAP.md`). Keep - [x] First-person movement, mouse look, and Enhanced Input bindings. Implemented 2026-11-07: `AGigLineCharacter` (C++, 1.75 m capsule, 1.60 m eye camera, 4 m/s walk, mouse look in deg/s, jump) as the default pawn, with five actions and an 11-entry context in `/Game/Input` built by `Tools/ue_create_input_assets.py`. **Not yet confirmed interactively** — launch PIE on `Test/ReviewMap` and walk. Screenshot review pending (`Screenshots/README.md`). - [~] Collision, reset, and pause functionality. Reset (**R**) and pause (**Escape**, a real game pause that releases the cursor) are implemented in `AGigLineCharacter` with `/Game/Input/IA_Reset` and `IA_Pause`. Collision now exists — terrain, road and sidewalks import as complex-as-simple, so a simple hull cannot ramp over the kerbs. **Not verified by hand**: walk, reset and pause need a human at the keyboard. No pause menu widget yet, only the pause itself. - [x] Build the walkable demo level: terrain, street, and hero facade assembled into one map with a start point on the north sidewalk, so the demo is something a player can walk rather than a review staging. **Built 2026-11-07** by `Tools/ue_build_demo_map.py` → `/Game/Hollywood/DemoMap`: sun/sky, `Hero_Facade`, six site meshes imported with collision (`Terrain_DEM`, `Road_Hollywood`, both sidewalks and both kerbs), and a `Demo_PlayerStart` on the north sidewalk 20 m back from the frontage. Demo views in `Screenshots/demo/` re-rendered and ☑ approved 2026-11-07. -- [x] Walkable sidewalks and a designated street crossing. Crossing chosen: mid-block signalised crossing, OSM way 385648319, at 130 m along the block (`Geo/verification/2026-11-06-street-profile.md`). Done 2026-11-07: continental zebra markings (0.5 m bars / 0.5 m gaps, 3 m band) at all three signalised crossings, no collision on the paint; kerbs were already flushed at the crossings. Enablers found on the way: the street surfaces were 100 % down-facing (invisible in engine) — winding flipped; the terrain buried the street — 10.7 m corridor cut around the centreline (sidewalks cover the transition, walk-check 0 holes); LFS-lockable `.blend`/`.umap` check out read-only — builders now chmod before saving and fail loudly. Screenshot ☑ approved 2026-11-07 (`Screenshots/demo/review-demo-crossing`); the corridor renders near-black in shadow — that is the still-open **Fixed daytime lighting** item, not the crossing. -- [-] Fixed daytime lighting and basic ambience. **Implemented 2026-11-07**, pending screenshot approval. Demo map now has a fixed daytime rig in `Tools/ue_build_demo_map.py`: sun pitch −50 / yaw 120 (intensity 4, warm 255/245/230, atmosphere sun light), sky light 2.6 with real-time capture, sky atmosphere, height fog (density 0.008), and a manual-exposure post-process volume (min = max brightness 1.0) so a shot cannot wash out or crush to black. Two root causes found while doing it: (a) **Blender flat diffuse colours do not survive the FBX→UE import** — every site mesh arrived white and the terrain arrived with `WorldGridMaterial`, which is what actually made the scene look blown out; explicit `M_Asphalt` / `M_Concrete` / `M_Ground` / `M_RoadPaint` materials are now created and assigned in the demo builder. (b) only **one of the three crossings** was reaching the game: each band was its own object and Blender renamed the duplicates `.001`/`.002`, which site assembly skips; all bands are now one `Crossing_Markings` object. Demo cameras also fixed: street-level sat inside the façade body, and the crossing camera aimed at the wrong crossing (s=36.6 instead of the designated s=130.1 at UE X −14956). +- [x] Walkable sidewalks and a designated street crossing. Crossing chosen: mid-block signalised crossing, OSM way 385648319, at 130 m along the block (`Geo/verification/2026-11-06-street-profile.md`). Done 2026-11-07: continental zebra markings (0.5 m bars / 0.5 m gaps, 3 m band) at all three signalised crossings, no collision on the paint; kerbs were already flushed at the crossings. Enablers found on the way: the street surfaces were 100 % down-facing (invisible in engine) — winding flipped; the terrain buried the street — 10.7 m corridor cut around the centreline (sidewalks cover the transition, walk-check 0 holes); LFS-lockable `.blend`/`.umap` check out read-only — builders now chmod before saving and fail loudly. Screenshot ☑ approved 2026-11-07 (`Screenshots/demo/review-demo-crossing`); the corridor renders near-black in shadow — that was the **Fixed daytime lighting** item, now also done. +- [x] Fixed daytime lighting and basic ambience. **Done 2026-11-07, screenshots approved.** Demo map now has a fixed daytime rig in `Tools/ue_build_demo_map.py`: sun pitch −50 / yaw 120 (intensity 4, warm 255/245/230, atmosphere sun light), sky light 2.6 with real-time capture, sky atmosphere, height fog (density 0.008), and a manual-exposure post-process volume (min = max brightness 1.0) so a shot cannot wash out or crush to black. Two root causes found while doing it: (a) **Blender flat diffuse colours do not survive the FBX→UE import** — every site mesh arrived white and the terrain arrived with `WorldGridMaterial`, which is what actually made the scene look blown out; explicit `M_Asphalt` / `M_Concrete` / `M_Ground` / `M_RoadPaint` materials are now created and assigned in the demo builder. (b) only **one of the three crossings** was reaching the game: each band was its own object and Blender renamed the duplicates `.001`/`.002`, which site assembly skips; all bands are now one `Crossing_Markings` object. Demo cameras also fixed: street-level sat inside the façade body, and the crossing camera aimed at the wrong crossing (s=36.6 instead of the designated s=130.1 at UE X −14956). Lighting is dynamic-only (`r.AllowStaticLighting=False`, all lights Movable) so the editor's "LIGHTING NEEDS TO BE REBUILT" warning no longer fires. All four demo views approved by the owner. - [ ] Geographic attribution display ("© OpenStreetMap contributors" + license link). ### Repository publication -- 2.47.3