feat(hero): facade rework — inscription, medallions, motto band, banner lettering #39

Merged
zwitschi merged 93 commits from hero-facade-0.3.0 into main 2026-11-10 15:37:40 +01:00
Showing only changes of commit 16eaf5a07d - Show all commits
+5 -14
View File
@@ -26,20 +26,11 @@ Actionable task list for this project. This file is the single, central place fo
- [x] Fix the character and car floating. **The measurement was taken at the wrong moment.** The foot probe ran in `BeginPlay`, while the pawn is still at its spawn height and falling, so every trace reported a surface far below it (`ground 366` against an actor at 561) and read as a float that was not there. The probe now runs **three seconds after spawn**, from the capsule's feet, on three channels, and names the actor it hits. Character: the player start at Z 600 left the soles 39 cm in the air (the capsule settles at 561 on this pavement); the start is now the measured 561. Car: the template's lowest geometry is exhaust, so grounding on the whole model put the tyres 4 cm above the origin - it is now grounded on its wheels, staged at Z 342 after the traced road height (366) disagreed with the visible road by ~25 cm.
- [x] Fix the vehicle's material colour. The template's `car paint` is a legacy mix-shader graph that the FBX exporter cannot map, so `SM_Vehicle_Body` imported holding `WorldGridMaterial` and rendered black while Blender showed red. Legacy graphs are now converted to Principled before export (saturated colour wins over the grey diffuse next to it), and the staged body panel is assigned `M_Vehicle_HatchPaint`. Judge: `verdict=yes confidence=0.9`.
- [x] Fix the missing vehicle glazing. The `windows` material was metallic 1.0 with roughness 0.0 - a black void that read as an empty cabin. Now tinted translucent (opacity 0.85, roughness 0.08); opacity 0.45 was tried first and made the glass invisible. The vision judge still returns `verdict=no` for the frame, disagreeing with what is visibly tinted glass; it is advisory, and the human verdict decides.
- [A] Put the player on the sidewalk at its real height. The judge now flags the character and car as floating in the spawn view, and its criterion is in the expectation ("a shadow more than a hand's width below an object means the object is floating"). Two readings are possible and both fit the pixels: the object really floats, or it stands on the raised pavement and the sun throws its shadow past the kerb onto the road. `Tools/shadow_gap.py` now does the measurement: object vs shadow in pixels, as a fraction of the object's height. It works on synthetic frames (tests pass) but returns `unknown` on the real spawn view, because the crop contains two surfaces - the pale wall behind and the dark road below - and a single global background cannot classify both. Next: per-region backgrounds, or crop tightly around the feet and their shadow only.
**Root cause found: the player stands on the road.** Three spawn heights (455, 395, 469) produced **identical** captures, and the in-game probe names the surface every time:
```
GigLine top surface under player: hit Z=366 actor=StaticMeshActor_2 mesh=Road_Hollywood
```
The capsule lands on `Road_Hollywood` at Z 366, while the north sidewalk exists with collision and its top is at **Z 380** (`Demo_Sidewalk_North`, QueryAndPhysics). The character therefore stands ~14 cm **below** the sidewalk surface and reads as floating against the kerb - the shadow is thrown onto the road, which is genuinely lower.
Spawn height is irrelevant: the capsule falls through to the road regardless. The open question is the player start's **XY footprint**, not its Z - either it is not over the sidewalk mesh, or the sidewalk has a gap at that point.
**The measurement that says otherwise:** tracing down from 30 m above the player, the topmost surface is Z 366 and the capsule's feet sit at 369 - three centimetres, which is the capsule skin. If the character still looks like it floats, the gap is between the **rendered** pavement and its **collision** surface, not the spawn Z. That is the thing to measure next: the sidewalk mesh's rendered top versus the collider returned by the trace.
- [A] Reconcile the road and sidewalk surfaces. **They disagree by about 2 m, and that is the float.**
- The site export now slices sidewalks and kerbs into ~20 m pieces with explicit `UCX_` boxes, and the slice cuts are fixed (the far cut kept the wrong half, so every slice spanned the whole street). Slice tops descend honestly along the street: 380, 340, 309, 284, 254, 231, 205, **169 at the player's X**, 138, 104 cm.
- In the map at the same X: `Sidewalk_North_07` tops at **169 cm**, `Road_Hollywood` at **366 cm**. The road is ~2 m above its sidewalk, so the player lands on the road and no collision setting on the sidewalk can change that.
- Neither slicing, `UCX_` hulls, `set_complex_collision_as_simple`, nor winding (all 2790 sidewalk faces point up) changed the outcome - each of those was the wrong layer.
- **Next:** sample both source meshes at the player's XY in `Art/blender/street/street-2026-11-06.blend`. The road is built as `dem_z + 0.02` and the sidewalk as `dem_z + kerb * t` from the _same_ DEM sampler, so a 2 m gap cannot come from that code - the suspect is the DEM lookup or the mesh's coordinate frame, not the assembly logic.
- [ ] Implement enter/exit interaction.
- [ ] Build a closed driving route with boundaries.
- [ ] Tune basic handling to a drivable state.