From b84d47ec18f2a44e11941f272389636902a6e28f Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Mon, 9 Nov 2026 18:22:52 +0100 Subject: [PATCH] test(profile): the road is a flat slab at 366 while the sidewalks slope Added a -profile probe: one downward trace every 20 m along the street at the player's Y, naming the surface each time. It settles the question the bounding boxes could not: x=-14336..-2336 z=366 Road_Hollywood (flat) x=-336 z=302 Road_Hollywood x=1664 z=5 Terrain_DEM The road is FLAT at 366 cm across the demo block, while the sidewalk slices follow the DEM and descend 380 -> 104 cm. So the ~2 m gap is not an import artefact and not a collision problem: the road itself does not follow the elevation the sidewalks follow. That also explains why every sidewalk fix failed - the surface the player stands on is this flat road, and the sloped sidewalk is metres below it. Next: how rows is built in Art/blender/street/street_mesh.py. The road and the sidewalk read the same dem_z(x, y), so a flat road means the sampler returns the same value for every row. --- .../Source/GigLine/GigLineCharacter.cpp | 30 +++++++++++++++++++ MEMORY.md | 14 +++++++++ 2 files changed, 44 insertions(+) diff --git a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp index bb5733d..e4f6591 100644 --- a/Game/GigLine/Source/GigLine/GigLineCharacter.cpp +++ b/Game/GigLine/Source/GigLine/GigLineCharacter.cpp @@ -1045,6 +1045,36 @@ void AGigLineCharacter::Tick(float DeltaSeconds) if (FootProbeDelay <= 0.f) { LogFootProbes(); + if (FParse::Param(FCommandLine::Get(), TEXT("profile")) && GetWorld()) + { + // Ground profile along the street: one downward trace every 20 m at the + // player's Y, naming the surface each time. Comparing the road's profile + // with the sidewalks' is what the per-mesh bounding boxes could not do. + const FVector Base = GetActorLocation(); + for (int32 Step = 0; Step < 14; ++Step) + { + const float X = Base.X + Step * 2000.0f - 1000.0f; + FHitResult Hit; + FCollisionQueryParams Q(TEXT("GigLineProfile"), false, this); + const bool bHit = GetWorld()->LineTraceSingleByChannel(Hit, + FVector(X, Base.Y, Base.Z + 2000.0f), + FVector(X, Base.Y, Base.Z - 4000.0f), ECC_WorldStatic, Q); + FString MeshName = TEXT("none"); + if (bHit) + { + if (const UStaticMeshComponent* HitMesh = + Cast(Hit.GetComponent())) + { + if (const UStaticMesh* Asset = HitMesh->GetStaticMesh()) + { + MeshName = Asset->GetName(); + } + } + } + UE_LOG(LogTemp, Warning, TEXT("GigLine profile x=%.0f z=%.0f mesh=%s"), + X, bHit ? Hit.ImpactPoint.Z : -9999.f, *MeshName); + } + } if (bProbeAndQuit && GetWorld()) { // One frame later, so the log lines are flushed before the process exits. diff --git a/MEMORY.md b/MEMORY.md index b116d05..a7240bb 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -546,3 +546,17 @@ Scope: facts and traps that cost time to establish. Planned work lives in [TODO. - Checked for two `Demo_Road_Hollywood` actors after several import rounds: **none**. One actor, at the origin, identity scale, mesh Z spanning -44..366 cm. - So the 366 cm the trace reports at the player's XY is the road mesh's own local height there, not a stale duplicate and not a far-side hit. The sidewalk slice at the same X tops at 169 cm. - In the source blend at the same street position both surfaces sit around 1.4-1.6 m and agree within a kerb height, so the ~2 m gap appears **after** the mesh leaves Blender - which points at the import path (unit handling, or the Y mirror noted in `export_site_fbx.py`) rather than the strip generation. + +## 2026-11-09 — The road is FLAT at 366 while the sidewalks slope: that is the gap + +- Ground profile along Hollywood Blvd, traced every 20 m at the player's Y (`-probes -profile`): + +``` +x=-14336 z=366 Road_Hollywood x=-2336 z=366 Road_Hollywood +x=-12336 z=366 Road_Hollywood x= -336 z=302 Road_Hollywood +x=-10336 z=366 Road_Hollywood x= 1664 z= 5 Terrain_DEM +``` + +- **The road is a flat slab at 366 cm** across the whole demo block, while the sidewalk slices follow the DEM and descend 380 -> 104 cm. The gap is therefore in the street generator: the road is not sampling the elevation per row the way the sidewalks do, or it was written with a single Z. +- That also explains why every sidewalk fix failed - the street the player actually stands on is the flat road, and the sloped sidewalk is metres below it. +- **Next:** inspect how `rows` is built in `Art/blender/street/street_mesh.py` - the road's `road_z` reads `dem_z(x, y)` from the same rows as the sidewalk, so a flat result means `dem_z` is returning the same value for every row (origin offset or a lookup that fails and falls back), and the fix is in that sampler.