The /chatt diorama renders, but buildings float on a flat Y=0 slab below the draped terrain, which sits at its raw elevation (194–249m). The two layers are decoupled.
Root cause
src/world/Buildings.tsx hardcodes geo.translate(center[0], 0, center[1]) — every building base at Y=0.
src/world/Terrain.tsx displaces the plane by raw bilinear() elevation (194–249m), no normalization.
- No shared ENU-(x,z)→elevation sampler exists; the
Building type carries no ground elevation.
Fix
- Add
elevationAt(grid, manifest, x, z) + minElevation(grid) to src/world/terrainSample.ts. Correct axis sign (verified): u = x/groundWm + 0.5, v = 0.5 − z/groundHm (NOT z/h+0.5, which mirrors N↔S).
- Normalize terrain down by
minElevation so the lowest ground is Y=0.
- Seat each building base on
elevationAt(...) − minElevation; wire grid/manifest into <Buildings> from ChattWorld. Same for Heroes (fixed Y=8) and Streets.
Future idea (noted, not this issue): the flat Y=0 layer under the terrain is reserved for a possible 'underground Chattanooga' map pack.
The
/chattdiorama renders, but buildings float on a flat Y=0 slab below the draped terrain, which sits at its raw elevation (194–249m). The two layers are decoupled.Root cause
src/world/Buildings.tsxhardcodesgeo.translate(center[0], 0, center[1])— every building base at Y=0.src/world/Terrain.tsxdisplaces the plane by rawbilinear()elevation (194–249m), no normalization.Buildingtype carries no ground elevation.Fix
elevationAt(grid, manifest, x, z)+minElevation(grid)tosrc/world/terrainSample.ts. Correct axis sign (verified):u = x/groundWm + 0.5,v = 0.5 − z/groundHm(NOTz/h+0.5, which mirrors N↔S).minElevationso the lowest ground is Y=0.elevationAt(...) − minElevation; wiregrid/manifestinto<Buildings>fromChattWorld. Same forHeroes(fixed Y=8) andStreets.Future idea (noted, not this issue): the flat Y=0 layer under the terrain is reserved for a possible 'underground Chattanooga' map pack.