diff --git a/Docs/Architecture/architecture.md b/Docs/Architecture/architecture.md new file mode 100644 index 0000000..0c642c0 --- /dev/null +++ b/Docs/Architecture/architecture.md @@ -0,0 +1,449 @@ +# Gig Line Architecture Documentation + +> Linux-first walking/driving demo around 6840 Hollywood Blvd + +Version 0.1.0 — 2026-11-08 — initial architecture documentation + +# Introduction and Goals + +Gig Line is a Linux-first Unreal Engine 5 game that reconstructs a walkable (and eventually drivable) stretch of Hollywood Boulevard around 6840 Hollywood Blvd / El Capitan Entertainment Centre. The initial release (`0.1.0`) delivers a first-person walking demo of the south-side block between Highland Avenue and Orange Drive, plus north-side buildings within 50 m of the frontage. + +## Requirements Overview + +| ID | Description | +| --- | --- | +| F-1 | Walk both sides of Hollywood Blvd in the demo area without falling through geometry | +| F-2 | First-person movement (WASD + mouse look), jump, reset (R), pause (Escape) | +| F-3 | Fixed daytime lighting and atmosphere (sun, sky, fog, exposure) | +| F-4 | Geographic attribution display (ODbL: "© OpenStreetMap contributors" + licence link) | +| F-5 | Designated street crossing with zebra markings at signalised crossings | +| F-6 | Building façades recognisable against reference photography | +| F-7 | Terrain, road, and sidewalk follow real-world DEM elevation | +| F-8 | 60 FPS at 1440p on the documented workstation and quality preset | + +Full requirements and progress are in [TODO.md](../../TODO.md); version direction is in [ROADMAP.md](../../ROADMAP.md). + +## Quality Goals + +| Priority | Quality Goal | Scenario | +| --- | --- | --- | +| 1 | **Performance efficiency** | 60 FPS at 2560×1440 on RTX 5070 Ti, documented preset, no frame generation | +| 2 | **Terrain walkability** | Zero raycast holes across both sidewalks and the carriageway (84-sample transect passes) | +| 3 | **Geographic fidelity** | Building placement, street scale, and façade identity match reference photography | +| 4 | **Build reproducibility** | Fresh checkout + documented engine path produces a runnable Linux build | +| 5 | **Licensing compliance** | Every redistributable asset has verified provenance; ODbL attribution is visible at runtime | + +## Stakeholders + +| Role | Contact | Expectations | +| --- | --- | --- | +| Owner / Director | zwitschi | Sets scope, approves screenshots, cuts release tags | +| AI coding agents | multiple sessions | Read `AGENTS.md`, `TODO.md`, `ROADMAP.md`, and this document for architecture constraints; never commit directly to `main` | +| Players | end users | Walk the demo at 60 FPS without falling through the world; see a recognisable Hollywood block | +| OSM contributors | OpenStreetMap | ODbL attribution is displayed and derivative-database obligations are met | + +# Architecture Constraints + +## Technical Constraints + +| Constraint | Explanation | +| --- | --- | +| Engine: Unreal 5.8.4 | Pinned; no bundled Linux clang — uses system clang 23.1.4. Game targets use `BuildSettingsVersion.V7`. | +| Platform: Linux first | Developed and tested on Bazzite Linux (Fedora 45 base). Windows builds ship but are secondary. | +| GPU: RTX 5070 Ti 16 GB | Dev workstation target. Vulkan RHI; open kernel module driver 615.78.08. | +| No static lighting | `r.AllowStaticLighting=False`. The demo is a fixed daytime scene lit entirely dynamically to avoid "LIGHTING NEEDS TO BE REBUILT" warnings. | +| Blender→UE via FBX | Flat diffuse colours do not survive FBX→Unreal import. All materials are authored in UE. | +| Terrain collision | UE 5.8 exposes `CollisionTraceFlag` (not `bUseComplexAsSimpleCollision`); Python cannot set it. Must use C++ helper `UGigLineAssetTools::SetComplexCollisionAsSimple`. | +| Coordinate convention | South = +Y, north = −Y (ground truth = street mesh orientation). 1 m in Blender = 100 cm in Unreal. | + +## Organisational Constraints + +| Constraint | Explanation | +| --- | --- | +| Squash-merge to `main` | Every PR is squash-merged for a linear history. No direct commits to `main` except integration merges. | +| Visual review required | Any change affecting appearance must produce screenshots for human approval before being marked done. | +| Asset provenance | Every committed asset must have verified licence and redistribution permission recorded in `THIRD_PARTY_NOTICES.md`. | +| Reference photography | Local only, gitignored, never committed. Used for façade work under fair-use / internal-development rationale. | +| LFS for binaries | `.uasset`, `.umap`, `.blend` tracked with Git LFS; `Binaries/`, `Intermediate/`, `Saved/` are gitignored. | + +## Conventions + +| Convention | Explanation | +| --- | --- | +| Semantic versioning | `MAJOR.MINOR.PATCH`. `0.x` documents breaking changes. `1.0.0` = agreed game scope. | +| Task tracking in `TODO.md` | Single central task list. `- [ ]` open, `- [-]` or `- [~]` in progress, `- [x]` done, `- [A]` active, `- [D]` deferred. | +| Headless Blender | All Blender work driven by `bpy` scripts in `Tools/`, not MCP. Blender skills are method guides only. | +| Named export presets | `ue_metric_v1` for static meshes, `ue_character_v1` for skeletal. Every exporter calls the metre→centimetre conversion. | + +# Context and Scope + +## Business Context + +The system is a self-contained single-player game. It has no server backend, no multiplayer, and no live service dependencies. Its communication partners are: + +| Partner | Inbound | Outbound | +| --- | --- | --- | +| Player (keyboard/mouse) | WASD, mouse, R (reset), Escape (pause), Space (jump) | Rendered 3D scene + HUD | +| OSM data | Extracted building footprints, street geometry, elevation | Attribution string at runtime | +| Filesystem | Engine content (`.uasset`, `.umap`), Blender sources (`.blend`), DEM GeoTIFF | Saved maps, screenshots, packaged build | + +## Technical Context + +| Channel | Protocol / Format | Purpose | +| --- | --- | --- | +| Keyboard + mouse | Enhanced Input (IA_*, IMC_Default) | First-person movement, look, jump, reset, pause | +| Vulkan RHI | GPU rendering | Scene display at 60 FPS / 1440p | +| FBX | Autodesk FBX (binary) | Blender→Unreal mesh and skeleton transfer | +| GeoTIFF | 3DEP 1 m DEM | Terrain heightfield source | +| OSM XML | Overpass API extract | Building footprint and street layout source | +| Git / LFS | HTTPS to Gitea remote | Source control, binary asset storage | + +# Solution Strategy + +## Technology decisions + +** ****Unreal Engine 5.8.4*** for rendering, World Partition, physics (Chaos), and the Enhanced Input system. Chosen for its Linux support, open C++ source, and real-time rendering quality. +** ****Blender 5.2 LTS*** for all 3D modelling, UV work, and collision mesh authoring. Driven headlessly via `bpy` Python scripts, not MCP. +** ****QGIS 4.2.3*** for geographic data cleanup, coordinate conversion (EPSG:26911), and DEM preparation. +** ****Blosm 2.7.28*** for OSM building and street blockouts inside Blender (layout data only — not authoritative façade, height, or pavement detail). +** ****MPFB 2.0.18*** for human base meshes and baked materials (NPCs in `0.2.0+`). + +## Top-level decomposition + +The system is a single Unreal game module (`GigLine`) with no plugins beyond `EnhancedInput`. Content is organised by domain under `/Game/Hollywood/`: + +* `Site/` — terrain, road, sidewalks, kerbs, crossing markings, site materials +* `ElCapitan/` — hero façade mesh and materials +* `Frontage/` — south-side block building meshes +* `North/` — north-side building meshes +* `Input/` — Enhanced Input actions and mapping context + +All modelling and geographic processing live outside the game project in `Art/`, `Geo/`, and `Tools/`. The `Game/` directory contains only engine-ready content and C++ source. + +## Quality achievement + +** **Performance*: dynamic-only lighting (no build step, no static shadow maps), world-space-noise materials (cheap procedural variation), minimal overdraw (simple street-level geometry). +** **Walkability*: complex-as-simple collision on terrain (C++ helper forces the flag on the asset), block-all collision on every site mesh, swept transect QA verifies zero raycast holes. +** **Fidelity*: geographic data verified before modelling (footprints, bounds, DEM); building placement checked against street mesh, never in isolation; reference photography drives façade work. +** **Reproducibility*: pinned toolchain in `Docs/toolchain.md`, named export presets, `Tools/check-lfs.sh` gate, fresh-checkout build procedure in `Docs/build.md`. + +# Building Block View + +## Whitebox Overall System + +The system decomposes into five top-level building blocks: + +| **Name** | **Responsibility** | +| --- | --- | +| Gameplay | Player pawn, movement, camera, input bindings, HUD, game mode | +| Site | Terrain, road, sidewalks, kerbs, crossing markings, site-level collision | +| Façades | Hero façade (El Capitan), south block frontage, north-side buildings | +| Art Pipeline | Blender models, geographic data, export scripts, import scripts | +| QA & Review | Screenshot pipeline, self-test harness, visual review workflow | + +### Gameplay + +C++ classes in `Game/GigLine/Source/GigLine/`: + +| Class | Responsibility | Key detail | +| --- | --- | --- | +| `AGigLineCharacter` | First-person player pawn | 1.75 m capsule, 4.5 m/s walk, Enhanced Input bindings, reset, pause, `-qaselftest` harness | +| `AGigLineGameModeBase` | Sets game mode and HUD class | `HUDClass = AGigLineHUD` | +| `AGigLineHUD` | ODbL attribution overlay | `DrawText` every frame, bottom-left | +| `AGigLineNPCPerson` | NPC prefab (future) | Capsule + visible MPFB body, feet on Z 0 | +| `AGigLineShotActor` | Screenshot camera walker | Drives cameras in `-game` mode, `FScreenshotRequest`, quits | +| `UGigLineAssetTools` | C++ collision helpers | `SetComplexCollisionAsSimple` on `StaticMesh` assets | + +Input assets in `/Game/Input/`: `IA*Move`, `IA*MoveBack`, `IA*Strafe`, `IA*StrafeLeft`, `IA*Look`, `IA*Jump`, `IA*Reset`, `IA*Pause`, bound in `IMC_Default`. + +### Site + +Static meshes and materials in `/Game/Hollywood/Site/`: + +| Asset | Role | +| --- | --- | +| `Terrain_DEM` | Ground heightfield (complex-as-simple collision) | +| `Road_Hollywood` | Carriageway surface (block-all collision) | +| `Sidewalk_North`, `Sidewalk_South` | Pedestrian surfaces (block-all collision) | +| `Kerb_North`, `Kerb_South` | Kerb edges | +| `Crossing_Markings` | Zebra markings at signalised crossing | +| `M_Asphalt`, `M_Concrete`, `M_KerbConcrete`, `M_Ground`, `M_RoadPaint`, `M_Stucco`, `M_FacadeStone` | Procedural materials (world-space-noise blend + roughness) | + +### Façades + +| Asset | Role | +| --- | --- | +| `SM_HeroFacade` | El Capitan Entertainment Centre detailed façade | +| `SM_ElCapitanTheatre`, `SM_Budget_6822`, `SM_Hollywood_6806`, `SM_Hollywood_6902`, `SM_Hollywood_6922`, `SM_LeeDrug_6800` | South block frontage (6 buildings) | +| `SM_Madame_Tussauds`, `SM_TCL_Chinese_Theatre` | North-side buildings (within 50 m) | + +### Art Pipeline + +Python scripts in `Tools/` drive the content pipeline: + +| Script group | Purpose | +| --- | --- | +| `export_*`, `hero_facade_build` | Blender headless export (FBX) | +| `ue_import_*`, `ue_hero_facade_import` | Unreal headless import + placement | +| `ue_build_demo_map`, `ue_build_review_map` | Map assembly (lighting, meshes, player start) | +| `ue_create_input_assets` | Enhanced Input actions + mapping context | +| `render_screenshots.sh` | Screenshot capture pipeline | +| `judge_screenshot.py` | Vision-model pre-check (optional) | + +Source data: `Art/blender/` (`.blend` files), `Geo/` (OSM extracts, DEM, verification docs). + +### QA & Review + +* `AGigLineShotActor` walks fixed cameras in `-game` mode, captures PNGs, and quits. +* `-qaselftest` switch on `AGigLineCharacter` runs a core-ticker harness: walk 2 s, reset, pause/unpause, ground transect — all PASS/FAIL logged. +* `Screenshots/` holds committed PNGs and `README.md` approval table. + +## Level 2 + +### White Box Gameplay — Input Flow + +* `AGigLineCharacter::SetupPlayerInputComponent` binds `IA_*` actions to `MoveForward`, `MoveBack`, `MoveStrafe`, `MoveLeft`, `Look`, `StartJump`/`StopJump`, `ResetToStart`, `TogglePause`. +* Movement delegates to `ApplyMove(Forward, Strafe)` → `AddMovementInput`. +* Look applies yaw/pitch scaled by `LookSensitivity` (Y invertable via `bInvertLookY`). +* `ResetToStart` teleports to `StartLocation` (captured on first grounded frame), clears velocity, resets control rotation. +* `TogglePause` toggles `APlayerController::SetPause`, swaps input mode between `FInputModeGameOnly` and `FInputModeUIOnly`, shows/hides mouse cursor. + +### White Box Site — Collision Model + +* Every site mesh (road, sidewalks, kerbs, crossing) is `STATIC` with `BlockAll` collision. +* `Terrain*DEM` uses `CTF*UseComplexAsSimple` (forced by `UGigLineAssetTools` at build time, saved on the asset). +* The terrain corridor is carved to half-width 10.7 m around the road centreline so the player can walk the carriageway and both sidewalks. +* Ground Z: north sidewalk 395, road 366, south sidewalk 317 (3.94 m fall along the block, matching the DEM). + +# Runtime View + +## Walk the block + +* Player launches game → `AGigLineGameModeBase` spawns `AGigLineCharacter` at `PlayerStart` `(-13336, -1150, 600)`. +* Character falls 144 cm to road surface (Z 456) and begins walking. `StartLocation` captured on first grounded frame. +* Player holds W → `IA_Move` fires → `ApplyMove(1, 0)` → `AddMovementInput(ForwardVector, 1)` → capsule moves at 450 cm/s. +* Mouse move → `IA_Look` fires → yaw/pitch applied to controller rotation → camera follows (attached to capsule at 160 cm eye height). +* Player presses R → `ResetToStart` → teleport to `StartLocation`/`StartRotation`, `StopMovementImmediately`, reset control rotation. +* Player presses Escape → `TogglePause` → `SetPause(true)`, switch to `FInputModeUIOnly`, show cursor. World timers stop; core tickers continue. +* Player presses Escape again → `TogglePause` → `SetPause(false)`, switch to `FInputModeGameOnly`, hide cursor. + +## Screenshot capture + +* `Tools/render*screenshots.sh` compiles editor, builds `ReviewMap` from `Tools/ue*build*review*map.py`, launches game in `-game` mode. +* `AGigLineShotActor` iterates the camera list, sets view, calls `HighResShot 1280x720`, waits for capture. +* On last camera, requests engine quit. PNGs are copied to `Screenshots/` and committed. + +## QA self-test (`-qaselftest`) + +* Core ticker starts at `BeginPlay` (not a world timer — world timers freeze on pause). +* 1.0 s: begin driving forward input. +* 3.0 s: stop, measure displacement (> 200 cm = PASS). +* 3.5 s: call `ResetToStart`. +* 4.0 s: measure distance from spawn (< 100 cm = PASS). +* 4.5 s: call `TogglePause`, check `IsGamePaused()` (= true = PASS). +* 5.5 s: call `TogglePause`, check `IsGamePaused()` (= false = PASS). +* 6.0 s: swept ground transect across three lanes (Y −1400, −167, +1000), X −14900 to −9420 at 200 cm spacing. 84 samples, 0 holes = PASS. +* 7.0 s: final verdict logged. + +## Build and import pipeline + +* Blender headless (`Tools/export**.py`) reads `.blend` files, applies metre→centimetre conversion, exports FBX with `ue*metric_v1` preset. +* Unreal headless (`Tools/ue*import**.py`) imports FBX via Interchange, places meshes at geographic coordinates, sets collision profiles. +* `Tools/ue*build*demo_map.py` assembles `DemoMap`: creates/repositions actors, sets lighting, saves map and assets. + +# Deployment View + +## Infrastructure Level 1 — Development Workstation + +| Node | Specification | +| --- | --- | +| Dev workstation | Bazzite Linux 45 (Fedora 45 base, immutable ostree), Ryzen 7 7700X, 64 GB RAM, RTX 5070 Ti 16 GB, Vulkan RHI | +| Engine install | `/run/media/system/DATA/Engines/UE_5.8.4` (73 GiB, external to repo) | +| Project repo | `/run/media/system/DATA/Documents/06-games/gig-line` (Git + LFS, remote at `git.allucanget.biz`) | +| Build output | `/run/media/system/DATA/Builds/GigLine` (packaged Linux build, ~1.1 GiB) | + +**Motivation:** + +Single-machine development. No build farm, no CI pipeline yet. The engine, toolchain, and GPU are all on the same host. + +**Quality and Performance Features:** + +* Vulkan RHI on RTX 5070 Ti, open kernel module driver 615.78.08. +* System clang 23.1.4 (no bundled engine clang) compiles game code. +* Build time: ~90 s incremental, ~5 min clean for the editor target. + +**Mapping of Building Blocks to Infrastructure:** + +| Building Block | Infrastructure Element | +| --- | --- | +| Gameplay (C++) | Dev workstation — compiled to `libUnrealEditor-GigLine.so`, loaded by engine | +| Site + Façades (UE content) | Dev workstation — `.uasset`/`.umap` in `Game/GigLine/Content/` | +| Art Pipeline (Python/Blender) | Dev workstation — headless Blender 5.2 Flatpak, Python 3.14.8 | +| QA & Review | Dev workstation — game run in `-game` mode, PNGs to `Screenshots/` | +| Git remote | `git.allucanget.biz` — Gitea instance, LFS-enabled | + +## Infrastructure Level 2 — Packaged Build + +| Element | Detail | +| --- | --- | +| Linux packaged build | Development config, ~1.1 GiB. Contains engine binaries, game module, cooked content, no editor. | +| Run command | `./GigLine.sh -windowed -ResX=2560 -ResY=1440` | + +No server infrastructure. The game is a standalone executable. + +# Cross-cutting Concepts + +## Coordinate system and scale + +** ****Source CRS***: EPSG:26911 (UTM zone 11N). Local origin recorded in `Geo/`. +** ****Blender***: metres. East → +X, north → +Y (Blender convention). +** ****Unreal****: centimetres. East → +X, north → ****−Y*** (confirmed from street mesh: `Sidewalk*North` Y −1912..−1053, `Sidewalk*South` Y +718..+1447). +** ****Conversion***: every exporter calls the metre→centimetre function. Import presets (`ue*metric*v1`, `ue*character*v1`) are named and repeatable. + +Rule: place a building only against a neighbour or street mesh, never in isolation. + +## Collision model + +* Site meshes (road, sidewalks, kerbs, crossing): `STATIC` mobility, `BlockAll` collision profile. +* Terrain: `STATIC`, `CTF_UseComplexAsSimple` (forced by `UGigLineAssetTools` at build time, saved on the asset — the flag lives on the `UStaticMesh`/`UBodySetup`, not the map). +* Buildings: `STATIC`, simple collision (convex hull from mesh). +* Rule: the collision flag must be saved on the asset. Saving only the `.umap` silently reverts it. + +## Lighting + +* Dynamic-only: `r.AllowStaticLighting=False`. All lights are `MOVABLE`. +* Fixed daytime rig: directional light (sun, −62° pitch), sky light, exponential height fog, post-process volume with fixed exposure. +* Rationale: avoids "LIGHTING NEEDS TO BE REBUILT" warnings; no bake step; the scene never changes time of day. + +## Materials + +* All materials authored in Unreal, not carried from Blender (FBX import loses diffuse colours). +* World-space-noise blend nodes for cheap procedural variation (asphalt grain, concrete speckle, stucco roughness). +* Instance parameters where tunable (e.g. wetness, ageing). + +## Geographic data provenance + +* OSM extract is layout data only — not authoritative for façade, height, or pavement detail. +* DEM from 3DEP 1 m; elevation verified against cross-sections in `Geo/verification/`. +* Reference photography (local, gitignored) drives manual façade work. +* In-game ODbL attribution drawn by `AGigLineHUD` every frame, bottom-left. + +## QA harness + +* `-qaselftest`: core ticker (not world timer) so pause cannot freeze the test that proves pause works. +* `GigLine SIM` / `GigLine GROUND`: TEMP diagnostic logging, to be removed before release tag. +* Screenshot approval: human must tick `Screenshots/README.md` before visual work is marked done. + +# Architecture Decisions + +## ADR-1: Dynamic-only lighting for the demo + +** ****Context***: The demo is a fixed daytime scene. Stationary lights demand a lighting build and produce "LIGHTING NEEDS TO BE REBUILT" warnings. +** ****Decision***: `r.AllowStaticLighting=False`, all lights `MOVABLE`. +** ****Consequences***: No bake step, no warning, simpler iteration. Slightly higher GPU cost per frame (no baked shadows) — acceptable for the demo scope. + +## ADR-2: Materials authored in Unreal, not imported from Blender + +** ****Context***: FBX→Unreal import maps all Blender diffuse colours to white. Flat colour materials do not survive the pipeline. +** ****Decision***: Build all materials (asphalt, concrete, stucco, façade stone, road paint) directly in Unreal with procedural nodes. +** ****Consequences***: Materials cannot be previewed in Blender look-dev. Must round-trip to Unreal for visual check. But: full PBR control, world-space noise, no import surprise. + +## ADR-3: Complex-as-simple collision on terrain via C++ helper + +** ****Context***: UE 5.8 removed `bUseComplexAsSimpleCollision`. Python cannot set `CollisionTraceFlag` on `StaticMesh`/`BodySetup` at all. The Interchange default is bbox-only simple collision, which placed an invisible lid 8 m above the street. +** ****Decision***: `UGigLineAssetTools::SetComplexCollisionAsSimple` (C++) forces `CTF_UseComplexAsSimple` and saves the asset. +** ****Consequences***: One C++ helper class. The flag must be saved on the asset (not just the map). No Python workaround exists. + +## ADR-4: Reset captures StartLocation on first grounded frame + +** ****Context***: `BeginPlay` captures `StartLocation` at the PlayerStart, which is above grade (Z 600) so the capsule does not spawn embedded. Every reset dropped the player 1.4 m back into the air. +** ****Decision***: Repeating 0.25 s timer captures `StartLocation` once the character reports `IsMovingOnGround()`, then clears itself. +** ****Consequences***: Reset is correct. A one-shot timer at 2 s is wrong (fires after walking begins, records mid-stride position). + +## ADR-5: Core ticker for QA self-test, not world timer + +** ****Context***: Pausing the game stops world timers. A timer-driven test freezes exactly when it proves pause works. +** ****Decision***: `FTSTicker::GetCoreTicker()` drives the `-qaselftest` harness. +** ****Consequences***: Test runs even while paused. Must be enabled explicitly (`-qaselftest`), never in normal play. + +## ADR-6: South = +Y, north = −Y in Unreal + +** ****Context***: The street mesh established this convention: `Sidewalk*North` has Y range −1912..−1053, `Sidewalk*South` has +718..+1447. +** ****Decision***: Adopt it project-wide. Never place a building by assumption; always verify against a street mesh or neighbour. +** ****Consequences***: Matches Blender's north→+Y after the Y-flip in the `ue*metric*v1` export preset. + +## ADR-7: Headless Blender via bpy scripts, not MCP + +** ****Context***: Blender skill packs assume an MCP server; the project does not run one. +** ****Decision***: All Blender work driven by Python scripts in `Tools/`. Skill packs used as method guides (checklists, naming, proportions) only. +** ****Consequences***: Scripts are version-controlled and repeatable. No live Blender session needed for CI. + +# Quality Requirements + +## Quality Requirements Overview + +| Category | Requirement | Priority | +| --- | --- | --- | +| Performance efficiency | 60 FPS at 2560×1440, documented preset, no frame generation | 1 | +| Reliability / Terrain | Zero raycast holes across sidewalks and carriageway (84-sample transect) | 1 | +| Accuracy / Fidelity | Building placement matches reference photography within ~1 m | 2 | +| Accuracy / Fidelity | Street scale (lane width, sidewalk width) within ~10 cm of measured profile | 2 | +| Usability | WASD + mouse look, jump, reset (R), pause (Escape) — no tutorial needed | 2 | +| Compliance | ODbL attribution visible at runtime | 2 | +| Maintainability | Fresh checkout builds with documented engine installation | 2 | +| Portability | Linux build packages and runs; Windows build ships | 3 | + +## Quality Scenarios + +| ID | Source/Stimulus | Response | Metric | +| --- | --- | --- | --- | +| QS-1 | Player walks both sides of the demo | No fall-through, character stays at ground Z | 0 raycast holes in 84-sample transect | +| QS-2 | Player holds W for 2 s on flat road | Character moves forward | ≥ 200 cm displacement, Z constant within ±5 cm | +| QS-3 | Player presses R | Character teleports to spawn | < 100 cm from `StartLocation` | +| QS-4 | Player presses Escape | Game pauses, cursor appears | `IsGamePaused()` = true | +| QS-5 | Player presses Escape while paused | Game unpauses, cursor hides | `IsGamePaused()` = false | +| QS-6 | Game runs on dev workstation at 1440p | Frame rate stable | ≥ 60 FPS, 99th percentile ≥ 55 FPS | +| QS-7 | Fresh checkout + engine install | Build succeeds | Exit code 0, runnable binary produced | + +# Risks and Technical Debts + +| ID | Risk / Debt | Priority | Mitigation | +| --- | --- | --- | --- | +| R-1 | Terrain bbox proxy misdiagnosed as fall-through — already fixed, but the root-cause path (Interchange defaults to simple collision) could recur on reimport | High | `UGigLineAssetTools` runs in the build script; always reassert complex-as-simple after any reimport. Documented in `MEMORY.md` and ADR-3. | +| R-2 | Blosm 3Dsimple on Blender 5.2 — worked around, not resolved; `3Drealistic` mode untested | Medium | Pin Blosm 2.7.28 and Blender 5.2 LTS; test realistic mode before depending on it. | +| R-3 | Kerb height is an assumption (DEM does not resolve it) | Medium | Record the assumption in `Geo/verification/`; measure from reference photography if possible; mark as unresolved until verified. | +| R-4 | ODbL derivative-database posture for shipped builds is open | Medium | In-game attribution is done; legal review of shipped-DB obligations needed before public release. | +| R-5 | `GigLine SIM` / `GigLine GROUND` TEMP diagnostic logging still in `GigLineCharacter.cpp` | Medium | Strip behind a cvar or remove entirely before the `v0.1.0` release tag. | +| TD-1 | Materials are Unreal-only — no Blender preview round-trip | Low | Accepted (ADR-2). Look-dev happens in UE; screenshot review catches issues. | +| TD-2 | No CI pipeline — all builds and QA are manual on the dev workstation | Low | Acceptable for `0.x`. CI is a `0.3.0+` concern. | + +# Glossary + +| Term | Definition | +| --- | --- | +| Blosm | Blender add-on (2.7.28) that imports OSM data as 3D building and street blockouts. Used for layout only — not authoritative for façade or height. | +| Complex-as-simple collision | `CTF_UseComplexAsSimple`: Unreal collision mode where the render mesh triangles are used as the collision surface, instead of a simplified proxy. Required for terrain so the player walks on the actual ground shape. | +| DEM | Digital Elevation Model. 3DEP 1 m resolution GeoTIFF covering the demo bounds. Source of terrain heightfield. | +| El Capitan | El Capitan Entertainment Centre, 6838 Hollywood Blvd. The hero building of the demo. | +| Enhanced Input | Unreal's modern input system (UE 5+). Uses Input Actions (`IA_*`) and Input Mapping Contexts (`IMC_*`) instead of legacy axis/action bindings. | +| EPSG:26911 | UTM zone 11N, the projected CRS used for the demo area. Local origin recorded in `Geo/`. | +| Hero façade | The detailed, reference-calibrated model of the El Capitan building frontage. | +| MPFB | MakeHuman Plugin for Blender (2.0.18). Generates parametric human base meshes with rigs and baked materials. | +| ODbL | Open Database Licence 1.0. The licence covering OSM-derived data. Requires attribution and may impose share-alike on derivative databases. | +| PlayerStart | Unreal actor that defines where the player pawn spawns. Positioned above grade so the capsule does not embed in the floor on spawn. | +| QA self-test | The `-qaselftest` command-line switch that runs an automated behaviour check (walk, reset, pause, ground transect) via a core ticker. | +| Site | The terrain, road, sidewalks, kerbs, and crossing markings — the ground-level infrastructure of the demo area. | +| Squash merge | Git merge strategy that compresses all branch commits into one commit on `main`, keeping a linear history. | +| Swept transect | A QA technique that raycasts vertically at regular intervals along a path (e.g. every 200 cm along both sidewalks and the carriageway) and counts holes (misses). Zero holes = the block is fully walkable. | +| World Partition | Unreal's world composition system for large open-world levels. Not yet used in `0.1.0` but planned for `0.3.0+` driving routes. | +| Y convention | In Unreal, south = +Y, north = −Y (confirmed from street mesh orientation). In Blender, north = +Y; the `ue_metric_v1` export preset flips Y. | + +--- + +**About arc42** + +arc42, the template for documentation of software and system architecture. + +Template Version 0.1.0. Adapted for the Gig Line project. +Created, maintained and © by Dr. Peter Hruschka, Dr. Gernot Starke and contributors. +See .