fix(infrastructure): follow refined terrain after initial sampling

This commit is contained in:
Sameh Khamis committed 2026-09-11 09:05:41 -07:00
1 parent b5568de9fa
commit 412ee211b5
4 files changed
+63 -5

No files matched your search

+23 -3
View File
@@ -807,7 +807,8 @@ export function createLocalGeoJsonLayer({
if (!isActive) continue;
const wasGroundSampled = record.groundSampled;
if (refreshStemGeometry) {
const terrainFloorChanged = refreshLocalTerrainFloor(viewer, record);
if (refreshStemGeometry || terrainFloorChanged) {
updateLocalStemGeometry(viewer, record, now);
} else if (canSampleGround && !record.groundSampled
&& now - record.lastGroundSampleMs >= GROUND_SAMPLE_RETRY_MS) {
@@ -911,6 +912,21 @@ function insertLocalCellContender(contenders, record) {
if (contenders.length > LOCAL_OVERLAY_CELL_SURPLUS) contenders.length = LOCAL_OVERLAY_CELL_SURPLUS;
}
function refreshLocalTerrainFloor(viewer, record) {
const globe = viewer.scene.globe;
if (!record.groundSampled || !globe?.show || globe.tilesLoaded === false) return false;
if (Cesium.Cartesian3.distance(viewer.camera.positionWC, record.base)
>= GROUND_SAMPLE_MAX_DISTANCE_M) return false;
// Camera motion can refine terrain after the first successful depth sample.
// Reuse the loaded mesh on existing bounded walks; never arm a timer or do
// another GPU readback just to maintain this floor. Keep roof elevations.
const height = globe.getHeight?.(record.carto);
if (!Number.isFinite(height) || Math.abs(height) > GROUND_SAMPLE_MAX_ABS_HEIGHT_M
|| height <= record.groundHeight) return false;
setLocalGroundHeight(record, height);
return true;
}
function sampleLocalGroundHeight(viewer, record, now) {
if (record.groundSampled || !viewer.scene.sampleHeightSupported) return false;
if (now - record.lastGroundSampleMs < GROUND_SAMPLE_RETRY_MS) return false;
@@ -933,7 +949,12 @@ function sampleLocalGroundHeight(viewer, record, now) {
sampled = Math.max(sampled, terrainHeight);
}
record.groundSampled = true;
record.groundHeight = sampled;
setLocalGroundHeight(record, sampled);
return true;
}
function setLocalGroundHeight(record, height) {
record.groundHeight = height;
Cesium.Cartesian3.fromRadians(
record.carto.longitude,
record.carto.latitude,
@@ -942,7 +963,6 @@ function sampleLocalGroundHeight(viewer, record, now) {
record.base,
);
record.entity.__localBaseCartesian = record.base;
return true;
}
function updateLocalStemGeometry(viewer, record, now, knownDistance = null) {
+36 -1
View File
@@ -497,7 +497,7 @@ test('local infrastructure creates no native labels or per-frame geometry callba
assert.match(source, /const stemPositionBuffers = \[\[base, tip\], \[base, tip\]\]/);
assert.match(source, /record\.entity\.polyline\.positions\.setValue\(stemPositions\)/);
assert.match(source, /viewer\.camera\.moveEnd\.addEventListener/);
assert.match(source, /if \(refreshStemGeometry\)/);
assert.match(source, /if \(refreshStemGeometry \|\| terrainFloorChanged\)/);
assert.match(source, /now - _lastVisibilityUpdate < VISIBILITY_UPDATE_MS/);
});
@@ -728,6 +728,41 @@ test('ground sampling waits for visible globe tiles before caching a height', as
assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01);
});
test('settled terrain refinement lifts an already sampled stem without another GPU sample', async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 117,
});
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
let terrain = 117;
const globe = { show: true, tilesLoaded: true, getHeight: () => terrain };
env.viewer.scene.globe = globe;
setCameraAltitude(env, 20_000);
env.preRender.raise();
assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01);
terrain = 120;
globe.tilesLoaded = false;
clock.advance(500);
env.preRender.raise();
assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01, 'wait for the refined mesh to settle');
globe.tilesLoaded = true;
clock.advance(500);
env.preRender.raise();
assert.ok(Math.abs(baseHeightM(env) - 120) < 0.01, 'a parked marker must follow the refined floor');
terrain = 110;
clock.advance(500);
env.preRender.raise();
assert.ok(Math.abs(baseHeightM(env) - 120) < 0.01, 'a lower floor must not flatten existing geometry');
terrain = 140;
globe.show = false;
clock.advance(500);
env.preRender.raise();
assert.ok(Math.abs(baseHeightM(env) - 120) < 0.01, 'hidden globe terrain must not constrain geometry');
assert.equal(env.sampleCalls.count, 1, 'terrain maintenance must not repeat the GPU readback');
});
for (const [terrainHeight, sampledHeight, expectedHeight, globeShown] of [
[117, -2238, 117, true],
[-400, -410, -400, true],