mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
fix(infrastructure): follow refined terrain after initial sampling
This commit is contained in:
1 parent
b5568de9fa
commit
412ee211b5
4 files changed
+63
-5
No files matched your search
@@ -16,6 +16,7 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
|
||||
- Unchanged local infrastructure overlays no longer sustain idle rendering.
|
||||
Ground samples wait for visible terrain to settle and cannot place a marker
|
||||
below its loaded surface; roofs and valid below-sea-level heights are retained.
|
||||
Already sampled markers also follow higher terrain as close-up tiles refine.
|
||||
|
||||
- Datacenter and dam marker stems use bounded, zoom-dependent active sets with
|
||||
stable selection during camera motion. Close-up stems scale to the actual
|
||||
|
||||
@@ -12,7 +12,9 @@ Unchanged overlay entries do not request another frame; moved positions,
|
||||
changed membership and re-enabling still publish. Ground sampling waits for
|
||||
visible globe tiles to settle and uses valid loaded terrain as a floor while
|
||||
retaining rooftop and below-sea-level elevations. A hidden globe does not
|
||||
constrain photoreal geometry, and retry work remains bounded.
|
||||
constrain photoreal geometry, and retry work remains bounded. Already sampled
|
||||
nearby markers follow higher settled terrain on existing bounded walks, without
|
||||
additional GPU samples or timers, when close-up tile detail refines the floor.
|
||||
The submarine-cable renderer is unchanged. These limits bound active stem work;
|
||||
they do not reduce the materialized entity count or establish an FPS gain.
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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],
|
||||
|
||||
Reference in new issue
Block a user