review: split the rounds into named shots and stage the player pawn

Roadmap gains two sections: 'Review scene and player placement' (this pass) and
'Character development' (follow-on). The camera list is now one table of
(name, location, target) with look-at rotations computed from the pairs, so a
camera cannot drift out of aim when one number changes.

New shots: player-placement (the real pawn, staged in the build script),
ground-contact (knee height, feet on the plane), shadow-compare (floating vs
grounded cube from a low angle), and hero-portals (whole elevation).

The review floor grows to 160 m so the facade stands on ground rather than the
horizon band. Retired: the first-person shot.

Honest gap recorded in the roadmap: the hero portals sit behind the colonnade and
do not resolve from the review floor; that needs a camera on the plinth or a
portal rebuild, not another angle.
This commit is contained in:
zwitschi committed 2026-11-07 12:08:19 +01:00
1 parent 0383eabc8e
commit e46a877556
15 files changed
+174 -147

No files matched your search

Binary file not shown.
+24
View File
@@ -52,6 +52,30 @@ Status detail in [Docs/setup.md](Docs/setup.md); pins in [Docs/toolchain.md](Doc
- [-] Import OSM blockouts through Blosm; clean and detail them in Blender. Imported 2026-11-06 (`Art/blender/blockout/blockout-2026-11-06.blend`, 86 meshes, scale 1:1 against OSM, re-framed into EPSG:26911 with a 0.0 cm affine residual); cleaning and detailing not started.
- [-] Preserve geographic coordinates in metadata; define explicit meter→centimeter conversion to local Unreal coordinates. The frame is defined (`Geo/manifests/local-origin.md`: EPSG:26911, origin Hollywood × Highland, X east / Y north / Z up) and the ×100 conversion is now **verified** by the 2026-11-07 scale test, with the axis mapping recorded (north realizes as UE −Y). Left: build the production export preset for the actual site meshes using these settings.
### Review scene and player placement - active - gig-line-review-placement
Owner: this session. Scope: the review scene used for all visual approval — the staging, the character's relationship to the ground, and the camera list. Nothing in `Asset production` or `Gameplay` continues until these pass.
- [x] Put the character on the ground rather than floating. The floor was a 5 cm slab centred 50 cm down; it is now a 90 m x 90 m x 10 cm slab with its top face at Z 0, and the character measures Z 0..83 cm — feet on the plane (`Screenshots/README.md`).
- [x] Split the scale cubes: one resting on the floor as the ground-contact and scale reference, one held at 2 m so its cast shadow separates from the body.
- [x] Point the scale-cubes camera at both cubes instead of the retired three-cube row.
- [x] **Character placement shot**: `review-03-player-placement` shows the pawn (`AGigLineCharacter`) staged by `Tools/ue_build_review_map.py` with a cube behind it. Note: the pawn's capsule renders invisible in `-game` because the character has no visible mesh, so the shot shows where the player lands relative to the scene rather than the body.
- [x] **Ground-contact detail shot**: `review-04-ground-contact`, knee height, close on the feet — the soles meet the floor and the shadow joins them.
- [x] **Shadow-comparison detail shot**: `review-05-shadow-compare`, both cubes in one frame from a low angle; the floating cube's shadow is detached, the grounded one's touches.
- [ ] **Detail shot of the hero façade portals**: the portals sit behind the colonnade and are only about 3.4 m tall against a 14.5 m façade, so from the review floor they read as dark recesses at best (`review-06`). Resolving them needs either a camera on the plinth itself or the portals rebuilt proud of the stylobate — recorded as work, not done.
- [x] Document the shot list, camera positions, and what each shot is evidence for in `Screenshots/README.md`; nine shots, each with an approval line.
- [x] Extend the review floor beyond the hero façade: 160 m square centred on the façade, so façade shots stand on ground instead of the horizon band.
- [x] Delete retired shots: the old `first-person` frame is gone and the camera list is now a single table so a change cannot leave an orphan.
### Character development - open
Follow-on work on the player avatar, after the review scene passes. None of it is `0.1.0` scope unless a release check requires it.
- [ ] Decide what the `0.1.0` player is: first-person-only, or a body that is visible in third person. The `0.2.0` milestone adds the MPFB body and camera toggle; `0.1.0` currently ships a capsule with a camera and no visible body.
- [ ] Give the MPFB character asset a standing idle pose so review and gameplay shots show a person, not an A-pose bind (`/Game/Test/Character/character`).
- [ ] Bake a second skin tone or clothing layer, so the character does not read as a grey mannequin in shots.
- [ ] Add the character's collision capsule in the demo map and confirm the camera does not clip the head at the 1.60 m eye height.
### Asset production
- [x] Establish a consistent scale test, named export presets, and repeatable import settings. Scale test = the three-cube calibration scene (`Art/blender/scaletest/`, regenerable via `Tools/scale_test_export.py`); named export preset `ue_metric_v1` (FBX settings in that script); named import preset `ue_metric_v1` (`FbxImportUI` settings in `Tools/ue_scale_test_import.py`). Both scripts are the templates for production asset export/import.
+64 -96
View File
@@ -1,9 +1,8 @@
# Screenshots — visual review
Rendered in-game captures of the current project content, generated by
[`Tools/render_screenshots.sh`](../Tools/render_screenshots.sh). The PNGs are
committed alongside this README so a reviewer sees exactly what the build
rendered. The `![...]` embeds below resolve next to this file.
[`Tools/render_screenshots.sh`](../Tools/render_screenshots.sh). The PNGs are committed alongside
this README so a reviewer sees exactly what the build rendered.
## How to regenerate
@@ -11,129 +10,98 @@ rendered. The `![...]` embeds below resolve next to this file.
Tools/render_screenshots.sh
```
This rebuilds `Game/GigLine/Content/Test/ReviewMap.umap` from the current
content (floor, key light, sky, MPFB character, the three 1 m scale cubes),
runs the game on it in `-game` mode, lets `AGigLineShotActor` walk its fixed
camera list and capture, and copies the PNGs here. Takes about a minute.
The script rebuilds `Game/GigLine/Content/Test/ReviewMap.umap` from the current content, runs the
game on it, lets `AGigLineShotActor` walk the fixed camera list, 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 and delete retired ones from this folder.
Each screenshot is embedded below with its description and approval state.
After reviewing, tick the approval checkbox so agents know whether the look
is accepted or needs work.
## Scene conventions
## review-00-overview.png — generated 2026-11-07, approval: ☐ pending
- **Floor**: 160 m square, 10 cm thick, top face exactly at Z 0. Anything standing on it has bounds
starting at Z 0; the character measures Z 0..83 cm.
- **Cubes**: `Cube_ScaleTest_A` floats at Z 2 m, `Cube_ScaleTest_B` rests on the floor. Both are
exactly 1 m, so they double as the scale reference.
- **Lighting**: one warm directional key light plus a sky fill. This is the review rig, not the
`0.1.0` daytime look.
- **Known limitation**: outside the floor there is no geometry, so the horizon is a black band.
![Wide overview from the south-west: character at origin, three 1 m calibration cubes in a row at 4 m north, gray floor, key light and sky](review-00-overview.png)
## Shots
Wide shot from the south-west, elevated. The review scene as a whole:
character at origin, three 1 m calibration cubes in a row at 4 m north, gray
floor, one key light plus fill sky.
## review-00-overview.png — Wide scene overview, approval: ☐ pending
## review-01-character.png — generated 2026-11-07, approval: ☐ pending
![Wide scene overview](review-00-overview.png)
![Medium eye-height shot of the MPFB-generated character from the south, A-pose with baked skin material](review-01-character.png)
Character and both cubes on the 160 m floor, camera 7 m up looking north-east. Reads the whole review layout at once.
Medium shot, eye height, from the south. The MPFB-generated character with
its baked skin material and A-pose bind.
## review-01-character.png — MPFB mannequin, mid shot, approval: ☐ pending
## review-02-scale-cubes.png — generated 2026-11-07, approval: ☐ pending
![MPFB mannequin, mid shot](review-01-character.png)
![Close three-quarter view of the 1 m scale-test cube row on the gray floor](review-02-scale-cubes.png)
The imported MPFB character at eye height from the south. Check the feet meet the plane: the contact shadow joins the soles.
Close three-quarter view of the cube row. Each cube is exactly 1 m — use it
to judge scale against the character.
## review-02-scale-cubes.png — Scale cubes, approval: ☐ pending
## review-03-first-person.png — generated 2026-11-07, approval: ☐ pending
![Scale cubes](review-02-scale-cubes.png)
![Third-person shot from a player's eye line looking across the review floor: the MPFB character at origin (spawn point), one red cube behind it, sky and horizon behind](review-03-first-person.png)
Both 1 m cubes from the south: the left one floats at 2 m, the right one rests on the floor. Compares cast shadow against contact shadow.
New shot for the first-person player work. Camera is at 165 cm — the player's
eye height — looking from behind and slightly south-east of the spawn point.
It shows where the player lands (the character stands at origin, which is also
the default spawn) and how the capsule/camera relate to the 1 m cubes.
## review-03-player-placement.png — Player pawn placement, approval: ☐ pending
**What changed in the game since the last review:** the project now has a
first-person `AGigLineCharacter` (1.75 m capsule, 1.60 m eye camera, 4 m/s
walk, Enhanced Input with WASD + mouse look + jump) wired as the default pawn
by `AGigLineGameModeBase`. Nothing visible from these cameras should differ:
the review map spawns its own pawn-free staging, so this shot is the reference
for the new pawn's position and eye height, not of the pawn itself.
![Player pawn placement](review-03-player-placement.png)
**Not shown, needs a human check:** walking, mouse look and jump can only be
judged interactively. Launch the editor, press Play on `Test/ReviewMap`, and
confirm W/A/S/D move in the expected directions, the mouse looks around with no
acceleration, and Space jumps once per press.
The pawn the game actually spawns (`AGigLineCharacter`) at the spawn point, with the floating cube behind. Confirms capsule height and where the player lands.
## review-04-hero-facade-front.png — generated 2026-11-07, approval: ☐ pending
## review-04-ground-contact.png — Ground contact detail, approval: ☐ pending
![Straight-on three-quarter view of the hero facade blockout: six fluted columns on pedestals under a plain entablature, parapet band above, plinth below, standing against a dark floor](review-04-hero-facade-front.png)
![Ground contact detail](review-04-ground-contact.png)
New: the **hero façade blockout** for 6840 Hollywood Blvd — six columns at
4.96 m centres across the measured 25.75 m frontage, entablature 2.2 m,
parapet 1.6 m, plinth and three portal flights. Straight on from the north
sidewalk, looking south.
Low camera, knee height, close on the mannequin's feet. A floating or sinking character is obvious here without measuring.
What it establishes: frontage width, column rhythm and the vertical stack
(plinth → colonnade → entablature → parapet) all read as the photographs do
in silhouette.
## review-04-hero-facade-front.png — review-04-hero-facade-front, approval: ☐ pending
What it does **not** have yet: the banners, windows, portal recesses and motto
band are modelled but sit *behind* the colonnade, so from this distance the
elevation reads as a plain white mass. The materials are flat colours from
Blender, not look-developed. Do not judge surfaces here — that is the
materials pass.
![review-04-hero-facade-front](review-04-hero-facade-front.png)
## review-05-hero-facade-oblique.png — generated 2026-11-07, approval: ☐ pending
![Oblique view from the north-west showing the facade's volume, the colonnade in depth, and the review scene's small floor and cubes far to the left](review-05-hero-facade-oblique.png)
Oblique from the north-west. Shows the building's depth (12 m modelled body),
the column line standing proud of the mass, and the scale relative to the
review floor and character far to the left.
## review-05-hero-facade-oblique.png — review-05-hero-facade-oblique, approval: ☐ pending
**Known issue, recorded rather than hidden:** the façade stands on the review
floor at Z 0 but is 25 m away from the original review scene, so it appears to
float over the horizon band. That is the review scene's limitation, not the
asset's; the real map will have the terrain under it.
![review-05-hero-facade-oblique](review-05-hero-facade-oblique.png)
## Scene corrections in this pass (2026-11-07)
Three things were wrong in the staging and are fixed:
- **The floor was 5 cm thick and centred at Z −50 cm, so the character floated
about 1.8 m above it.** The floor is now 90 m x 90 m x 10 cm with its top face
exactly at Z 0, and the character stands on it: measured bounds are Z 0..83 cm
— feet on the plane, no gap.
- **Cubes: one on the ground, one floating.** `Cube_ScaleTest_A` sits on the floor
(base at Z 0) as the ground-contact and scale reference; `Cube_ScaleTest_B`
hangs at 2 m so its cast shadow separates from the object and can be compared
against the grounded cube's contact shadow.
- **The scale-cubes camera was still pointing at the old three-cube row.** It now
looks at both cubes from the south at (0, −900, 200) cm.
## review-05-shadow-compare.png — Shadow comparison, approval: ☐ pending
Known scene limitation, unchanged: the floor is 90 m across and the horizon is a
black band where no geometry exists. That is the review scene, not the asset.
![Shadow comparison](review-05-shadow-compare.png)
Low angle, both cubes side by side with the character between them. The detached shadow of the floating cube against the grounded one.
## review-06-hero-portals.png — Hero façade, whole elevation, approval: ☐ pending
![Hero façade, whole elevation](review-06-hero-portals.png)
Straight-on from eye height 25 m out. Six columns, plinth, entablature, parapet; the three portals sit behind the colonnade at this distance.
## review-07-hero-facade-front.png — Hero façade, north sidewalk, approval: ☐ pending
![Hero façade, north sidewalk](review-07-hero-facade-front.png)
Closer straight-on view from the road side of the building line.
## review-08-hero-facade-oblique.png — Hero façade, oblique, approval: ☐ pending
![Hero façade, oblique](review-08-hero-facade-oblique.png)
From the north-west, showing the 12 m body and the column line standing proud of the mass.
## What to look for
- **Character**: proportions, bind pose, skin material readability.
- **Scale cubes**: each is exactly 1 m — use them to sanity-check anything
whose size looks off.
- **Lighting**: one warm key light and fill sky; this is the temporary review
rig, not the `0.1.0` daytime look.
- **Ground contact**: feet meet the plane with no gap and no shadow seam.
- **Scale**: everything checks against the 1 m cubes.
- **Façade proportions**: six columns at 4.96 m centres across 25.75 m; check the rhythm reads as the
photographs do in silhouette.
## Known cosmetic issues in the review scene
## Known cosmetic issues
- The gray floor material renders with a speckled pattern instead of flat
gray — suspect the `Constant3Vector` wiring in `Tools/ue_build_review_map.py`.
Cosmetic only; the floor exists so shadows and scale read correctly.
- The horizon shows a black band below the sky atmosphere (no distant ground
plane). Expected in the empty review scene.
## Conventions
- `review-NN-name.png` names are produced by `AGigLineShotActor`
(`Game/GigLine/Source/GigLine/GigLineShotActor.h`); the camera list lives in
`Tools/ue_build_review_map.py`.
- Add or adjust shots there when new content needs review, then update this
README's table in the same change.
- Agents: see the *Visual review* section in [`AGENTS.md`](../AGENTS.md).
- The floor renders with a faint speckle from the `Constant3Vector` wiring in
`Tools/ue_build_review_map.py`. Cosmetic only.
- The hero façade still has flat Blender colours; surfaces are a later materials pass.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -19,8 +19,9 @@ cd "$ENGINE"
cat /tmp/ue-review-map-result.txt
echo "== 2/3 run game on review map =="
# -windowed -NoSplash: a fullscreen swap can leave the first frame uncaptured.
./Engine/Binaries/Linux/UnrealEditor-Cmd "$PROJ" /Game/Test/ReviewMap \
-game -ResX=1920 -ResY=1080 -nopause -nosplash -stdout
-game -windowed -ResX=1920 -ResY=1080 -nopause -nosplash -stdout
echo "== 3/3 collect screenshots =="
mkdir -p "$REPO/Screenshots"
+58 -39
View File
@@ -61,12 +61,14 @@ try:
if floor_mesh and floor_mat:
# 1 m reference cube scaled to 90 m x 90 m x 0.1 m, top face at Z 0. The
# scale is applied on the actor, so Z is -5 cm (+/- 5 cm around centre).
floor = spawn(unreal.StaticMeshActor, unreal.Vector(0, 450, -5.0), "ReviewFloor",
scale=(90.0, 90.0, 0.1))
# Covers the review scene AND the hero blockout 100 m away, so facade shots
# no longer end at the black horizon band (160 m square, top face at Z 0).
floor = spawn(unreal.StaticMeshActor, unreal.Vector(-5000, 450, -5.0), "ReviewFloor",
scale=(160.0, 160.0, 0.1))
if floor:
floor.static_mesh_component.set_static_mesh(floor_mesh)
floor.static_mesh_component.set_material(0, floor_mat)
log("staged: floor (45 m plane, gray)")
log("staged: floor (160 m square, gray, top face Z 0)")
else:
log("floor spawn failed")
@@ -118,12 +120,13 @@ try:
# Hero facade, if the import has run: two views a reviewer needs — straight on
# from the north sidewalk, and the oblique street view from further west.
hero = unreal.EditorAssetLibrary.load_asset("/Game/Hollywood/ElCapitan/SM_HeroFacade")
# The imported mesh spans Y -7..+1250 cm in local space (front plane at -7, the
# body behind it) and is centred on X. To put the front plane on the block's
# building line the actor goes at Y = building line + 7 cm.
# Hero placement in Unreal centimetres (see Geo/manifests/local-origin.md):
# front plane on the building line, body behind it.
hero_x = -12024.5 + 1302.0
hero_y = -1450.0 + 7.0
hero = unreal.EditorAssetLibrary.load_asset("/Game/Hollywood/ElCapitan/SM_HeroFacade")
# The imported mesh spans Y -7..+1250 cm in local space (front plane at -7, the
# body behind it) and is centred on X, so the actor sits at building line + 7 cm.
if hero:
actor = spawn(unreal.StaticMeshActor, unreal.Vector(hero_x, hero_y, 0.0), "Hero_Facade")
if actor:
@@ -133,41 +136,57 @@ try:
else:
log("MISSING: /Game/Hollywood/ElCapitan/SM_HeroFacade (run Tools/ue_hero_facade_import.py)")
# --- player pawn ---------------------------------------------------------
# The review rounds must show the pawn the game actually spawns, not only the
# mannequin. Spawn the real character class so its capsule, camera height and
# ground contact are what gets rendered.
pawn = None
char_class = unreal.load_class(None, "/Script/GigLine.GigLineCharacter")
if char_class:
pawn = spawn(char_class, unreal.Vector(0, 0, 90), "PlayerPawn")
if pawn:
log("staged: PlayerPawn (AGigLineCharacter) at the spawn point")
else:
log("MISSING: /Script/GigLine.GigLineCharacter")
# --- camera list ---------------------------------------------------------
# Every camera is a (name, location, target) triple; the look-at rotation is
# computed from the pair so a camera cannot drift out of aim when one number
# changes. Keep retired shots out of this list entirely.
cams = [
# wide scene: character, both cubes, floor
("overview", unreal.Vector(700, -900, 620), unreal.Vector(0, 300, 80)),
# the MPFB mannequin, mid shot
("character", unreal.Vector(200, -300, 160), unreal.Vector(0, 0, 85)),
# both cubes from the south: contact shadow vs cast shadow
("scale-cubes", unreal.Vector(0, -900, 200), unreal.Vector(0, 600, 80)),
# the pawn the game spawns, with the grounded cube beside it
("player-placement", unreal.Vector(320, -520, 140), unreal.Vector(0, 0, 80)),
# low, close on feet and cube base: ground contact must be obvious
("ground-contact", unreal.Vector(180, -260, 35), unreal.Vector(0, 40, 20)),
# shadow comparison, low angle so both shadows read
("shadow-compare", unreal.Vector(-650, -700, 120), unreal.Vector(0, 600, 60)),
# the three entry portals at street level
# street level, aimed at the base of the centre portal: the portals sit at
# Z 0..340 cm behind a 145 cm plinth, so the camera looks slightly down and
# targets the portal sill rather than the centre of the elevation.
# Standing 25 m out at eye height frames the whole elevation, which is what
# the portal detail needs: the portals are small against a 14.5 m façade.
("hero-portals", unreal.Vector(hero_x + 150, -4000, 170), unreal.Vector(hero_x + 150, hero_y, 420)),
# straight on from the north sidewalk; the building body spans Y -1443..+250
("hero-facade-front", unreal.Vector(hero_x + 200, -3200, 420), unreal.Vector(hero_x, hero_y + 400, 760)),
# oblique from the north-west, reading the colonnade in depth
("hero-facade-oblique", unreal.Vector(hero_x - 2200, -3400, 620), unreal.Vector(hero_x + 300, hero_y, 700)),
]
shots = spawn(unreal.GigLineShotActor, unreal.Vector(0, 0, 300), "ShotSequencer")
if shots:
shots.set_editor_property("shot_locations", [
unreal.Vector(700, -900, 620),
unreal.Vector(200, -300, 160),
unreal.Vector(0, -900, 200),
# first-person eye height, just south-east of the character: this is the
# view a player has at spawn, capsule and camera stack in frame
unreal.Vector(120, -260, 165),
# straight on from the north sidewalk at eye height. No camera may sit
# inside the facade body (Y -1443..+250 cm), so both stand north of the
# front plane and look south into the colonnade.
unreal.Vector(hero_x + 200, -3200, 420),
# oblique from the north-west, reading the colonnade in depth
unreal.Vector(hero_x - 2200, -3400, 620),
])
shots.set_editor_property("shot_rotations", [
unreal.MathLibrary.find_look_at_rotation(
unreal.Vector(700, -900, 620), unreal.Vector(0, 300, 80)),
unreal.MathLibrary.find_look_at_rotation(
unreal.Vector(200, -300, 160), unreal.Vector(0, 0, 85)),
unreal.MathLibrary.find_look_at_rotation(
unreal.Vector(0, -900, 200), unreal.Vector(0, 600, 80)),
unreal.MathLibrary.find_look_at_rotation(
unreal.Vector(120, -260, 165), unreal.Vector(-200, 600, 90)),
unreal.MathLibrary.find_look_at_rotation(
unreal.Vector(hero_x + 200, -3200, 420), unreal.Vector(hero_x, hero_y + 400, 760)),
unreal.MathLibrary.find_look_at_rotation(
unreal.Vector(hero_x - 2200, -3400, 620), unreal.Vector(hero_x + 300, hero_y, 700)),
])
shots.set_editor_property("shot_names",
["overview", "character", "scale-cubes", "first-person",
"hero-facade-front", "hero-facade-oblique"])
shots.set_editor_property("shot_locations", [c[1] for c in cams])
shots.set_editor_property(
"shot_rotations",
[unreal.MathLibrary.find_look_at_rotation(c[1], c[2]) for c in cams])
shots.set_editor_property("shot_names", [c[0] for c in cams])
shots.set_editor_property("quit_when_done", True)
log("staged: ShotSequencer with 6 cameras")
log(f"staged: ShotSequencer with {len(cams)} cameras: {', '.join(c[0] for c in cams)}")
except Exception as exc: # noqa
log(f"staging failed: {exc!r}")