Skip to content

Cleveland showcase: EndRace full-lap fix, arcade pace, V16 night polish - #1

Open
LumenHelixLab wants to merge 16 commits into
masterfrom
feature/cleveland-showcase-demo
Open

Cleveland showcase: EndRace full-lap fix, arcade pace, V16 night polish#1
LumenHelixLab wants to merge 16 commits into
masterfrom
feature/cleveland-showcase-demo

Conversation

@LumenHelixLab

Copy link
Copy Markdown
Owner

Summary

End-to-end verified Cleveland showcase pass: the M2 EndRace blocker is fixed and proven on track, cars now drive at real arcade pace, and the night scene no longer blows out.

Race loop (verified: full lap, 12/12 checkpoints, state=Finished, place 1)

  • CanonicalizeSplineS only flattens high-S while waiting for CP1 — previously any checkpoint past 85% of the lap (CP10 sits at 96.6%) was mathematically unreachable, so EndRace could never fire
  • AI recovery: never-rolled crawlers recover after a 4x stuck window instead of never
  • Countdown hold disables bReverseAsBrake (was fighting SetTargetGear(1) every physics substep, causing the gear=-1 flash at green), restored on release
  • Torque curve injected in the pawn constructor so Chaos first CreateVehicle sees a non-empty curve

Physics / pace (lap time 1676s → 790s, peak speed 23 → 65 km/h)

  • Arcade drive push switched from ETorqueCombineMethod::Override (capped wheels at MaxTorque/4, masking the engine) to Additive
  • Traction-control lerp was inverted (more slip = less cut); now monotonic
  • Wheel slip ratio unit fix (cm/s both sides) so TC gets real input
  • CheckpointGate null-deref guard

Visuals V16 (verified via in-game capture)

  • Car night lights: 28000lm/42m headlights ×3 cars painted the ground solid white → 4500lm/24m, taillights 1800lm/9m
  • Runway asphalt MID: roughness 0.22→0.50, specular 0.78→0.50, metallic→0 (mirror blowout → wet night sheen with tight light streaks)

Tooling

  • build_cleveland_circuit.py: hardcoded /workspace path → repo-relative (12 Cleveland tests unblocked)
  • build_cleveland_environment.py: committed IndentationError fixed
  • osm_to_xodr.py: reads one_way key (one-way lanes were silently dropped)

Known issues (not in this PR)

  • Charger doors render open — morph/AnimBP flag approach does not reach the CARLA door bones; needs asset-side or bone-pose fix
  • AI steering discipline (crash/recovery loops) — per handoff, next step is an arcade control layer or vendor spike (KinetiForge / R-Tune), not more raw Chaos tweaking

Verification

  • pytest: 274 passed, 5 skipped
  • UE 5.7 editor build: clean
  • Auto-lap playtest (-ClevelandAutoLap): finished full Burke Lakefront lap, evidence in Temp/cleveland_playtest_lap.txt

Research basis

Epic Chaos arcade-control documentation, KinetiForge (MIT) tuning guide, Space Dust Racing UE arcade physics tour (archived), Livio De La Cruz racing-game implementation survey.

racegps-sprint-agent added 16 commits August 15, 2026 00:10
…napping

- T1: circuit routes close exactly (finish_gap=0.0m, within 15km cap);
  route metadata gains loop_closure block
- T2: water_extractor rewrite (multipolygon relations, river polygons,
  lakes with holes, coastlines); standard-tier Overpass query now fetches
  water; Cleveland: 452 rivers, 811 lakes incl. Lake Erie
- T3: _snap_road_endpoints() spatial-grid union-find snapping (1.5m tol,
  never cross-layer); Cleveland: 468 pairs snapped, +361 intersections
- 28 new tests
… import

- T4: BP_CheckpointGate (self-sufficient visuals); Cleveland map has 105
  real BP gates, zero placeholders
- T5: Dodge Charger 2024 from carla-content 0.10.0 (CC-BY 4.0, attribution
  included); BP_DodgeCharger2024 child of AChaosVehiclePawn; 4th vehicle
  preset in CruiseSprintGameMode
- T10: headless full-city import; Cleveland map now bakes terrain,
  119,601 building instances, 7,256 water instances, 200 POIs, 105 gates,
  4 routes/spawns (340 actors); resumable import + prep tooling
- Axis remap choke point: ue5-import-level-spec maps data (x,y,z) ->
  UE (x,-z,y); everything standard Z-up
…port

- Cleveland: closed-loop circuit (0.0m gap), real water (452 rivers /
  811 lakes incl. Lake Erie), 468 endpoint snaps baked into baked map
- Akron: first full import (new Akron5_0KmWorld.umap matching runtime
  level-name contract); 30,777 buildings, 9,539 water instances, 4 routes,
  110 gates; legacy AkronWorld.umap preserved
- city_compiler: water sidecar shim (reads <city>_water_raw.osm when present)
- headless import: per-city BP_CityBuildings (cross-city HISM bucket fix),
  resume guard, bare map names in verify script
- verify-city-runtime-readiness PASSED both cities; 230 tests green
- T7: new citypack-qa CI job (validator smoke gate on committed
  tests/fixtures/citypack-mini + real tracked Akron pack);
  validator gains --ignore-disconnected-components (downgrades ONLY the
  accepted disjoint-OSM-components error; 4 new tests prove it can't
  mask real failures); sprint_status --print smoke step (informational)
- Hero spawn: DefaultPawnClass -> BP_DodgeCharger2024 via DefaultGame.ini
  (config wins over cpp constructor); GI default LastSelectedVehicle
  'Sedan' -> 'CARLA Charger' so tuning matches the mesh; spawn path is
  stock RestartPlayer -> DefaultPawnClass, presets only retune
- 234 passed, editor rebuild succeeded
…city maps

Baked city maps carry no GameMode override in World Settings, so direct
map boot fell back to engine default GameMode — no race logic, no spawn,
dead world. Verified: Cleveland5_0KmWorld now reaches Racing state.
…ck again

- DirectionalLight (75k lux, movable, drives atmosphere), SkyAtmosphere,
  SkyLight (real-time capture, no lightmass needed), ExponentialHeightFog
- World Settings GameMode override set per-map (belt-and-braces on top of
  GlobalDefaultGameMode ini)
- lighting stage integrated into headless city import pipeline (idempotent)
- runtime-readiness script now hard-fails on missing lighting rig
- 0 ensures, 234 tests green, readiness PASSED both cities
…nfig

- GeoToWorld/XodrToWorld now return standard Z-up (X east, Y north, Z up),
  matching the T10 baked-map axis remap; call-site lat/lon hacks removed
- StartPlay detects baked city maps: binds baked gates (16/16, max 0.4uu),
  ghost follows baked spline, no runtime duplicate gates/splines/teleport
- SpawnDefaultPawnAtTransform override: AdjustIfPossibleButAlwaysSpawn
  (real-scale Charger was silently failing spawn on collision -> black screen)
- GameInstanceClass moved to live GameMapsSettings section in DefaultEngine.ini
  (DefaultGame.ini section was dead; tuning/vehicle selection was silently null)
- Headless verified: pawn at valid city location, 0 runtime gates spawned,
  CARLA Charger + Arcade tuning applied, 0 ensures; 234 tests green
- Single MetersToUU constant in C++ (GeoToWorld/XodrToWorld/road widths)
- Bake choke point _spec_to_ue now (100x, -100z, 100y); terrain uses
  absolute elevations; spec actors/splines lifted onto terrain surface
- Both cities rebaked: Key Tower reads 289.0m (actual 288.6m)
- Pawn spawns exactly on baked PlayerStarts at real terrain height;
  16/16 gates bound, 0 runtime duplicates, 0 ensures, 234 tests green
- Legacy meter-scale AkronWorld.umap formally deprecated
…lt-in diagnostics

Root cause of recurring black screen: baked PlayerStarts sit decimeters-to-
meters BELOW the terrain heightfield; camera rendered the unlit terrain
underside. SpawnDefaultPawnAtTransform now column-traces and lifts any
embedded spawn to ground+100uu at runtime (no rebake needed).

Permanent self-diagnostics (owner request):
- CVar racegps.Diagnostics (default ON in Development)
- [raceGPS-PREFLIGHT] PASS/FAIL at StartPlay: lighting, terrain collision,
  pawn spawn, game instance, tuning, gates bound
- [raceGPS-DIAG] 15x1s samples (pawn pos/vel, up/down traces, HISM overlap,
  camera, FPS) + VERDICT line (ON_GROUND/FALLING/ENCLOSED/NO_PAWN)
- Auto HighResShot at T+10s when rendering
Post-fix: VERDICT ON_GROUND, camera 196uu above terrain, 6/6 preflight PASS,
0 ensures, 234 tests green
… bisect

- HighResShot via GameViewportClient->Exec (GEngine->Exec silently swallowed
  viewport commands; no PNG was ever written before)
- File-poll confirmation logging: screenshot written/FAILED lines
- Birdseye bisect: temp ACameraActor 300m above pawn captures second frame
- Evidence: BOTH frames pure black (0.00/255) -> global render break,
  not spawn occlusion
- tools/diag_capture_game_window.py: OS-level window capture fallback
…,pitch,yaw)

ROOT CAUSE of the black screen: unreal.Rotator() python binding takes
fields ALPHABETICALLY (roll, pitch, yaw); the lighting rig passed
(pitch=-50, yaw=135, roll=0) positionally -> sun pitch=135 = zenith.
75000 lux fired into the sky; ground got zero direct light; SkyLight
real-time capture sampled an unlit scene so indirect was zero too.
Lit frames were mathematically black while unlit rendered fine.

Fix: keyword args in ue5-headless-lighting-rig.py, ue5-import-level-spec.py,
ue5-headless-city-import.py; both city maps re-rigged (rotation only).
Diag capture extended: ShowFlag bisect series, sun state dump.
PROOF: baseline luminance 0.00 -> 157.98; birdseye 161.38; direct-only and
indirect-only shots both sensible. 234 tests green, readiness PASSED.
…agentic handoff

Ship uncommitted Burke Lakefront showcase: grid/AI/checkpoints GameMode,
Chaos wheel CDO torque fix + playtest harness, night mats / roof-cloud hide,
Karla/citypack docs, garage plan, and AGENTIC_HANDOFF for next team.
EndRace still open (CP stall). GlobalDefaultGameMode unchanged (CruiseSprint).
Race loop:
- CanonicalizeSplineS: only flatten high-S to 0 while waiting for CP1; CP10 at
  0.97*L (and any CP past 85% of lap) was unreachable -> EndRace could never fire
- AI recovery: never-rolled crawlers now recover after 4x stuck window instead
  of never
- Countdown hold: disable bReverseAsBrake (fought SetTargetGear every substep ->
  gear=-1 flash at green), restore on release
- Torque curve injected in ctor so first Chaos CreateVehicle sees non-empty curve
- CheckpointGate: null-guard GetFirstPlayerController
- Wheel slip ratio: cm/s vs m/s unit mismatch (traction control got garbage)

Tooling:
- build_cleveland_circuit.py: hardcoded /workspace path -> repo-relative
- build_cleveland_environment.py: fix committed IndentationError
- osm_to_xodr.py: read one_way key (one-way lanes were silently dropped)

Verified: editor build clean; pytest 274 passed/5 skipped; auto-lap playtest
finished full lap (12/12 CPs, place 1, state=Finished)
Physics (verified on track: lap 1676s -> 790s, peak 23 -> 65 km/h):
- Arcade drive push: ETorqueCombineMethod::Override capped wheels at
  MaxTorque/4 per wheel (masked the real engine); now Additive - engine
  torque flows, push remains as floor if TorqueRatio latches again
- Traction control lerp was inverted (more slip = less cut); now cuts
  throttle monotonically with slip
- Slip ratio unit fix from prev commit makes TC input real (cm/s both sides)

Visuals (V16, verified via capture):
- Car night lights were 28000lm/42m headlights x3 cars - painted the ground
  solid white; now 4500lm/24m headlights, 1800lm/9m taillights
- ApplyNightGroundMaterials asphalt: roughness 0.22->0.50, specular
  0.78->0.50, metallic 0.06->0 (was mirror-glossy blowout under lights+bloom)
- MakeLookMID Road_Asphalt default overrides match (defense in depth)

Known issue (not fixed here): Charger doors render open - morph/AnimBP flag
approach in CloseVehicleDoors doesn't reach the CARLA door bones; needs an
asset-side or bone-pose solution.

Research basis: Epic Chaos arcade-control docs, KinetiForge (MIT) tuning
guide, Space Dust Racing UE arcade physics tour, Livio De La Cruz's
racing-game implementation survey.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant