The blockout cleaning pass found the map was rendering with 604 of 620 mesh actors
unmaterialed - every kit piece and all theatre trim.
Cause: ensure_material() deleted and recreated each /Game/Hollywood/Site/M_* asset on
every run, so actors staged by other tools kept references to deleted assets and fell
back to the default material. Nothing errored; the map looked merely slightly flat.
- Materials are now updated IN PLACE (load, delete_all_material_expressions, rebuild
the graph, recompile, save). Material.expressions is protected from Python, so the
editing library's deleter is used.
- 53 duplicated kit actor labels fixed (both shop piers of a bay shared one name).
- New Tools/ue_audit_scene.py gates the scene: every mesh actor has a material, every
verified frontage span is within +/-1 m (via ue_placement), no duplicate labels.
- render_screenshots.sh now runs the chain in the required order (demo map -> kit ->
theatre -> audit -> cameras -> capture) and exits non-zero on an audit failure,
because the demo builder rebuilds materials and later staging must follow it.
Scene audit: 0 failures. Packaged QA PASS. Spawn-view reference score 0.72.
Closes the 0.1.5 performance task. Same route and preset as 0.1.0 (packaged
Development, Epic scalability, TSR, VSync off, no frame generation, 2560x1440):
0.1.0 2.42 ms (414 fps) p99 3.01
0.1.5 (kit) 2.76 ms (363 fps) p99 3.64
The 625 kit actors and 8 generated textures cost about 12% of frame time and still
leave roughly six times the 60 fps floor. Frame-time series committed at
Docs/perf/0.1.5-kit-walk-frametimes.csv; comparison table added to
Docs/release-checks.md.
Records the measurement trap once more: runs showing ~105 fps were two overlapping
game instances, not the build - 363 fps reproduced twice on a clean single instance.
Hero detail:
- Fluting: 20 grooves per column as thin shadow-tone cylinders set into the shaft
(120 pieces) rather than boolean cuts - readable in silhouette and grazing light
at a fraction of the cost.
- Motto band: real recess with a moulded surround 6 cm proud and the panel 12 cm
behind, replacing the 8 cm dark stripe.
Hero 148 parts/3044 tris -> 271/5492, still 14.50 m.
Placement bug this exposed (a real one, invisible in a render):
- ue_hero_facade_import.py carried its own hero position (-12024.5, -1450) from
before the 0.1.0 frontage fix, so running the importer alone moved the hero 13 m
east and onto the north side of the boulevard. Only symptom: the reference score
fell 0.69 -> 0.56 and the 3x3 composition correlation flipped +0.54 -> -0.08.
- New Tools/ue_placement.py is the single source of truth (hero position, verified
frontage spans, span validators). Both the importer and the demo builder use it;
the import asserts the staged span and logs PLACEMENT ERROR otherwise.
- 11 new tests, including one that fails if the stale literal returns. 78 total.
Spawn-view score recovered to 0.72 (best yet); screenshots verified 4/4, packaged QA
all PASS.
Kit layout, found while starting the retail pass:
- Bays were round(width / 4.96), so 6922 (65.8 m wide) got 13 bays - a window every
4.96 m across a 37 m block. Capped at MAX_BAYS = 9, widening the module instead.
- Storeys were assumed exactly 310 cm apart, leaving ~1.6 m of bare wall under the
cornice on a tall building. The spread is now derived from the available height
(usable / storeys), so the top band lands inside the volume.
Result: 6922 9x11 (was 13x11), theatre 8x6, 6806 7x3, 6800 4x3, TCL 9x5.
Retail references: fetched Art/reference/retail-neighbours/01-lee-drug-and-neighbor.jpg
(Gb321, CC BY-SA 4.0) - 6800 and its neighbour at street level, confirmed to show
shopfronts and parapets. Commons has nothing for 6822 or 6806-6820, so those two
remain blocked on reference photography; recorded in TODO.
Re-applied the kit, repackaged, screenshots re-rendered and verified 4/4, packaged
QA all PASS.
- Remove stale -active suffix from Asset production heading
- Shorten the sidewalks/collision item (details in MEMORY.md)
- Mark collision authoring pass in 0.1.1 as partially done
(terrain+site done via UGigLineAssetTools; buildings pending)
- Add TEMP QA diagnostic removal to release checks
- Add architecture documentation and doc toolchain as done
- Restore ODbL derivative-database posture as active [A]
Drop the OpenStreetMap/ODbL attribution requirement, the Google imagery rule,
and the related F-4 requirement, risk R-4, release check, and TODO items across
AGENTS, PLAN, ROADMAP, README, setup, architecture sections, and manifests.
OSM data is now documented as local private use only. Also normalize
numbered-list indentation in the architecture docs.
The reported fall-through was a misdiagnosis: the player never fell. The
imported Terrain_DEM had only a bounding-box simple collision proxy, so a
downward trace anywhere in the block hit the terrain at Z 819 (the mesh
bbox max) and the street sat under an invisible 8 m lid. Standing on that
box looked plausible, which is why it read as working.
- add UGigLineAssetTools (C++): force CTF_UseComplexAsSimple on a static
mesh. UE 5.8 dropped bUseComplexAsSimpleCollision and Python cannot set
the flag; the builder also saves the asset, since the flag lives there
and a map-only save silently reverts it.
- spawn (-13336, -1150, 600): inside the carved corridor (the cut is a
10.7 m half-width around the road centreline), lands on the road at 456.
- fix ResetToStart returning to the mid-air PlayerStart captured in
BeginPlay: StartLocation is now captured on the first grounded frame.
- HighResShot 1280x720 instead of "1280 720", which is a multiplier.
- add -qaselftest: scripted walk/reset/pause on a core ticker plus a
swept ground transect. Results: walk 746 cm/2 s with Z steady, reset
0 cm from spawn, pause/unpause 1/0, transect 84 samples 0 holes.
- rebase onto main, keeping the frontage materials and placement fixes.
Adds the five remaining verified south-side buildings to the demo block
(6922, 6902, 6838 El Capitan Theatre, 6822 Budget, 6806-6820, 6800 Lee Drug),
exported in place from the OSM blockout by Tools/export_block_frontage.py,
imported to /Game/Hollywood/Frontage/ and staged by the demo builder with the
look material set (stone for the theatres, stucco for the retail run).
Adding neighbours exposed a pre-existing placement bug that was invisible while
the hero facade stood alone in an empty field:
- UE south is +Y here (south sidewalk Y +718..+1447), but the hero sat at
Y -1450 on the NORTH side of the street.
- It was also at X -12024..-9420, 26 m east of the 6840 footprint; the frontage
gap between 6902 and 6838 is X -14591..-12082.
- The two north-side buildings were on the SOUTH side, because their exporter
mirrored Y.
Fixes: hero moved to X -13336 / Y +1307, inside its frontage gap; the frontage
and north-building exporters no longer apply a Y mirror (the FBX preset already
lands Blender -Y south on UE +Y south); player start and demo cameras moved to
the north sidewalk looking south; sun raised to pitch -62 so both frontages read
instead of the north side silhouetting.
Result: the demo is a street - continuous south frontage with the hero in it,
both sidewalks, the road with the designated crossing, and the north-side
buildings across the road.
Screenshots re-rendered and approved by the owner.
Squash of branch frontage-block-0.1.0 (PR #6).
Completes "Materials and look development for all exported assets". Every
exported surface previously carried a flat Constant3Vector fill, which read as
plastic. ensure_material() in Tools/ue_build_demo_map.py now builds a
procedural material per surface:
- base colour blended between two shades by world-space noise
(WorldPosition -> Multiply -> Noise -> Lerp -> BaseColor) for large-scale
variation,
- an explicit roughness and specular so the surface type is readable.
M_Asphalt 0.92, M_Concrete 0.88, M_KerbConcrete 0.85, M_Ground 0.98,
M_RoadPaint 0.62, M_FacadeStone 0.72, M_Stucco 0.86
Site meshes take their material by mesh name; the hero facade and the two
north-side buildings take theirs by actor label, so they are covered even
though other scripts stage them. Materials are deleted and rebuilt on every
run, so a look change cannot be masked by a stale asset.
Result: the facade reads as warm stone with surface variation, asphalt as dark
asphalt with grain, concrete and kerbs lighter and matte, and the north
buildings in stucco instead of flat grey.
Screenshots re-rendered and approved by the owner. The richer texture-based
pass (baked/procedural brick_facade, seamless_concrete, glass, material
instances) stays in the 0.1.4 facade patch.
Squash of branch materials-lookdev-0.1.0 (PR #5).
Removes the stale - active - session suffix from the Character development
heading; the idle pose, warm skin, NPC prefab, and stable-naming items are all
done. The review-scene section above it also has no open items.
Completes "Geographic attribution display" for 0.1.0. The demo is built from
OpenStreetMap data (ODbL 1.0) and needs attribution wherever the derived work
is shown, so the credit now lives in the running game, not just the documents.
- AGigLineHUD (C++): plain AHUD::DrawText in the bottom-left draws
"(c) OpenStreetMap contributors" and "Data (c) OpenStreetMap contributors,
ODbL 1.0 - openstreetmap.org/copyright", with a shadow pass so it stays
legible over bright pavement and sky. No UMG widget asset is involved, so a
cook cannot drop the attribution through a missing widget reference.
- AGigLineGameModeBase: HUDClass = AGigLineHUD, so the credit is on by default
in both the DemoMap and the ReviewMap.
- AGigLineShotActor: screenshots are requested with the UI shown, so the credit
appears in every capture under Screenshots/ - the obligation is provable from
the images rather than only described.
Docs:
- THIRD_PARTY_NOTICES records that the attribution is displayed in-game and
where the code lives.
- Screenshots/README documents the overlay.
- TODO marks the item done and narrows the remaining ODbL question to the
shipped-derivative-database posture.
Squash of branch gameplay-attribution-0.1.0 (PR #4).
Completes "Fixed daytime lighting and basic ambience" for 0.1.0. All 14
screenshots approved by the owner.
Lighting rig (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)
- Unbound post-process volume with fixed exposure (min == max brightness) so a
shot cannot wash out or crush to black depending on how much sky it frames
- Dynamic-only: r.AllowStaticLighting=False plus MOVABLE lights and mesh
components, so the editor's "LIGHTING NEEDS TO BE REBUILT" warning no longer
fires and nothing needs baking
Bugs found and fixed on the way:
- Blender diffuse colours do not survive the FBX -> Unreal import: every site
material arrived white and the terrain arrived with WorldGridMaterial, which
is what actually made the scene look blown out. The demo builder now creates
and assigns M_Asphalt, M_Concrete, M_Ground and M_RoadPaint.
- Only one of the three crossings reached the game: each zebra band was its own
object, so Blender renamed the duplicates .001/.002 and exact-name site
assembly skipped them. All bands are now one Crossing_Markings mesh.
- Demo cameras: street-level sat inside the facade body (rendering its unlit
back face) and the crossing camera aimed at the s=36.6 crossing instead of
the designated s=130.1 (UE X -14956).
- The terrain had no material and imported as a bright default grid.
- Cleared a committed Android File Server SecurityToken (plugin disabled and
shipping-excluded; the value must stay empty).
Docs:
- Screenshots/README.md: one consolidated table for all 14 shots with map,
camera view and description; all approved.
- MEMORY.md: records the material-import, exposure, light_color struct,
band-naming, camera-bounds and lighting-build traps.
- TODO.md: lighting item marked done.
Squash of branch gameplay-lighting-0.1.0 (PR #3).
Root cause of the empty review frames: EditorLevelLibrary.load_level/new_level
are deprecated no-ops in -nullrhi commandlets, so staged actors landed in the
current world and got saved over the wrong map. Switched both map builders to
the LevelEditorSubsystem and reordered the review builder to save ReviewMap
before the DemoMap section (the switch-back to a map that only exists in
memory silently failed, writing demo content over ReviewMap).
Rebuilt both maps, re-rendered every screenshot; user visual check passed.
Screenshots/README.md cube naming corrected (A grounded, B floating), approval
states updated; TODO.md visual-review notes closed. MEMORY.md records the
deprecated-call and save-order traps.
- New C++ AGigLineNPCPerson: reusable NPC/pedestrian prefab built on the MPFB
human. ACharacter capsule half-height 83 cm (total 1.66 m, head top ~1.66 m
so a 1.60 m camera doesn't clip), the character skeletal mesh on the built-in
mesh as the visible body (feet on Z 0), AutoPossessAI for 0.5.0 pedestrians.
Staged at Z 0 in the review scene; captured as review-npc-prefab.png.
- AGigLineShotActor now names screenshots by stable camera name (no list-index
prefix): inserting or reordering cameras no longer renumbers files or orphans
the old ones. Re-rendered all review/demo shots with stable names.
- ue_build_review_map.py: chmod the target .umap before save_map (git marks maps
444 on checkout, silently making save_map return False and dropping stages).
- Screenshots/README.md, ROADMAP, TODO updated for the prefab + stable names.
- DemoMap.umap rebuilt by the render pipeline (north buildings + demo cameras).
Split the former ROADMAP.md checklists into TODO.md, which now holds
all actionable work and progress marks. ROADMAP.md keeps milestone
goals, scope, and release gates as prose with no checkboxes.
Update AGENTS.md, Docs/, Geo/README.md, MEMORY.md, and README.md to
point to the new file roles.