Merge pull request #1464 from quanticsoul4772/upstream/datacenter-ground-sampling

fix(infrastructure): ground-sample only stem bases the camera sees
This commit is contained in:
German Khokhlov authored and GitHub committed 2026-11-04 17:39:36 +04:00
commit 4859ba4c94
4 files changed
+242 -6

No files matched your search

@@ -0,0 +1,4 @@
- Ground-sample Data Centers and Dams markers only when the camera sees the
ground under them. Unseen ground read through the Earth and retried every
2 s; over Ashburn, Virginia on the Esri map, slow frames reached 2 s
(quanticsoul4772, #1464).
+6 -1
View File
@@ -2191,7 +2191,12 @@ during continuous motion. Disable/re-enable resets selection cleanly.
Close-up stem sizing uses camera-to-feature distance without a 5 km minimum. Close-up stem sizing uses camera-to-feature distance without a 5 km minimum.
Unchanged overlay entries do not request another frame; moved positions, Unchanged overlay entries do not request another frame; moved positions,
changed membership and re-enabling still publish. Ground sampling waits for 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 visible globe tiles to settle, and skips markers whose ground the camera
cannot see (unseen ground reads through the Earth and would retry every 2 s).
Ground is tested at loaded globe terrain, or across -9,000 to 9,000 m when the
globe is hidden, so photoreal views skip only ground well out of view. Until it is
seen, a stem keeps its unsampled height, which can show for a stem whose base
is just off screen. Sampling uses valid loaded terrain as a floor while
retaining rooftop and below-sea-level elevations. A hidden globe does not retaining rooftop and below-sea-level elevations. A hidden globe does not
constrain photoreal geometry, and retry work remains bounded. Already sampled constrain photoreal geometry, and retry work remains bounded. Already sampled
nearby markers follow higher settled terrain on existing bounded walks, without nearby markers follow higher settled terrain on existing bounded walks, without
+149 -1
View File
@@ -90,6 +90,8 @@ async function createRealLocalLayerHarness({
globalThis.window = { dispatchEvent() {} }; globalThis.window = { dispatchEvent() {} };
let sampleHeightImpl = sampleHeight; let sampleHeightImpl = sampleHeight;
const sampleCalls = { count: 0 }; const sampleCalls = { count: 0 };
// The camera frustum, reduced to the one answer ground sampling asks of it.
let baseVisibility = Cesium.Intersect.INSIDE;
const overlayHost = { const overlayHost = {
setVisible: (...args) => hostCalls.push(['visible', ...args]), setVisible: (...args) => hostCalls.push(['visible', ...args]),
setEntries: (...args) => hostCalls.push(['entries', ...args]), setEntries: (...args) => hostCalls.push(['entries', ...args]),
@@ -107,7 +109,19 @@ async function createRealLocalLayerHarness({
}, },
camera: { camera: {
positionWC: Cesium.Cartesian3.fromDegrees(-97.695, 30.205, 100_000), positionWC: Cesium.Cartesian3.fromDegrees(-97.695, 30.205, 100_000),
frustum: { fov: Math.PI / 3 }, directionWC: new Cesium.Cartesian3(),
upWC: new Cesium.Cartesian3(),
frustum: {
fov: Math.PI / 3,
// No planes: everything is in view. One plane no point satisfies:
// nothing is.
computeCullingVolume: () => ({
planes:
baseVisibility === Cesium.Intersect.OUTSIDE
? [new Cesium.Cartesian4(0, 0, 0, -1)]
: [],
}),
},
moveEnd, moveEnd,
flyTo() {}, flyTo() {},
}, },
@@ -151,6 +165,10 @@ async function createRealLocalLayerHarness({
sampleCalls, sampleCalls,
/** Swap scene.sampleHeight mid-test (e.g. tiles finally arrive). */ /** Swap scene.sampleHeight mid-test (e.g. tiles finally arrive). */
setSampleHeight(next) { sampleHeightImpl = next; }, setSampleHeight(next) { sampleHeightImpl = next; },
/** Put the feature's base inside (true) or outside the camera frustum. */
setBaseInView(inView) {
baseVisibility = inView ? Cesium.Intersect.INSIDE : Cesium.Intersect.OUTSIDE;
},
cleanup() { cleanup() {
if (originalWindow === undefined) delete globalThis.window; if (originalWindow === undefined) delete globalThis.window;
else globalThis.window = originalWindow; else globalThis.window = originalWindow;
@@ -736,6 +754,136 @@ test('ground sampling waits for visible globe tiles before caching a height', as
assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01); assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01);
}); });
test('an unseen base is not sampled and arms no retry until it is in view', async (t) => {
// Out of view the scene has no surface under the base, so the depth sample
// would pass through the Earth (about -6,344 km) and fail on every retry.
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 117,
});
_resetRenderGovernorForTest();
const governorScene = { renders: 0, requestRender() { this.renders += 1; } };
installRenderGovernor({ scene: governorScene });
governorScene.renders = 0; // discard the governor's own install settling frame
t.mock.timers.enable({ apis: ['setTimeout'] });
const clock = installFakeClock(t);
t.after(() => {
env.layer.destroy(env.viewer);
env.cleanup();
_resetRenderGovernorForTest();
});
env.viewer.scene.globe = { show: true, tilesLoaded: true, getHeight: () => 117 };
setCameraAltitude(env, 20_000);
env.setBaseInView(false);
runArmedRetryChain(env, t, clock, 5);
assert.equal(env.sampleCalls.count, 0, 'an off-screen base must not be sampled');
assert.equal(governorScene.renders, 0, 'an off-screen base must not keep a parked camera rendering');
assert.ok(Math.abs(baseHeightM(env)) < 0.01);
// In the frustum but over the horizon: 50 m up, about 67 km away.
env.setBaseInView(true);
env.viewer.camera.positionWC = Cesium.Cartesian3.fromDegrees(-97.0, 30.205, 50);
runArmedRetryChain(env, t, clock, 5);
assert.equal(env.sampleCalls.count, 0, 'a base over the horizon must not be sampled');
assert.equal(governorScene.renders, 0);
setCameraAltitude(env, 20_000);
env.preRender.raise();
assert.equal(env.sampleCalls.count, 1, 'the base is sampled on the first walk that sees it');
assert.ok(Math.abs(baseHeightM(env) - 117) < 0.01);
});
/**
* Give the harness a real Cesium camera `southM` metres south of the base at
* `cameraM` metres above the ellipsoid, looking at the base's ground at
* `groundM` (or directly away from it).
*/
function aimRealCamera(env, { groundM, cameraM, southM, away = false, fov = Math.PI / 3 }) {
const entity = env.dataSources[0].entities.values[0];
const base = Cesium.Cartographic.fromCartesian(entity.__localBaseCartesian);
const ground = Cesium.Cartesian3.fromRadians(base.longitude, base.latitude, groundM);
const position = Cesium.Cartesian3.fromRadians(
base.longitude,
base.latitude - southM / 6_371_000,
cameraM,
);
const direction = Cesium.Cartesian3.normalize(
away
? Cesium.Cartesian3.subtract(position, ground, new Cesium.Cartesian3())
: Cesium.Cartesian3.subtract(ground, position, new Cesium.Cartesian3()),
new Cesium.Cartesian3(),
);
const right = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.cross(
direction,
Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(position),
new Cesium.Cartesian3(),
),
new Cesium.Cartesian3(),
);
const up = Cesium.Cartesian3.cross(right, direction, new Cesium.Cartesian3());
const frustum = new Cesium.PerspectiveFrustum({
fov,
aspectRatio: 800 / 600,
near: 1,
far: 1e8,
});
Object.assign(env.viewer.camera, {
positionWC: position,
directionWC: direction,
upWC: up,
frustum,
});
return frustum
.computeCullingVolume(position, direction, up)
.computeVisibility(new Cesium.BoundingSphere(entity.__localBaseCartesian, 1));
}
const loadedTerrain = (height) => ({ show: true, tilesLoaded: true, getHeight: () => height });
const hiddenGlobe = { show: false, tilesLoaded: true, getHeight: () => undefined };
for (const { label, globe, groundM, cameraM, southM, fov, baseOffScreen } of [
// The Dead Sea (about -430 m) under a hidden globe, seen steeply down
// through a narrow view: both 0 m and 9,000 m above it are off screen.
{ label: 'hidden-globe depression', globe: hiddenGlobe, groundM: -430, cameraM: 20, southM: 180, fov: Math.PI / 12, baseOffScreen: true },
// 2,500 m terrain from 3 km away at a shallow angle: the ellipsoid-height
// base is far below the bottom of the screen.
{ label: 'high ground with loaded terrain', globe: loadedTerrain(2_500), groundM: 2_500, cameraM: 3_500, southM: 3_000, baseOffScreen: true },
{ label: 'high ground under a hidden globe', globe: hiddenGlobe, groundM: 2_500, cameraM: 3_500, southM: 3_000, baseOffScreen: true },
// A low-geoid coast (about -63 m near Mumbai) from a camera 50 m above the
// ellipsoid: the ellipsoidal horizon would hide the ground itself.
{ label: 'ground below the ellipsoid', globe: loadedTerrain(-63), groundM: -63, cameraM: 50, southM: 2_000, baseOffScreen: false },
]) {
test(`${label} in view is sampled`, async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => groundM,
});
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
env.viewer.scene.globe = globe;
const baseVisibility = aimRealCamera(env, { groundM, cameraM, southM, fov });
if (baseOffScreen)
assert.equal(baseVisibility, Cesium.Intersect.OUTSIDE, 'precondition: the ellipsoid-height base is off screen');
clock.advance(2_100);
env.preRender.raise();
assert.equal(env.sampleCalls.count, 1, 'the ground in view is sampled');
assert.ok(Math.abs(baseHeightM(env) - groundM) < 0.01);
});
}
test('under a hidden globe, ground behind the camera is not sampled', async (t) => {
const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 2_500,
});
const clock = installFakeClock(t);
t.after(() => { env.layer.destroy(env.viewer); env.cleanup(); });
env.viewer.scene.globe = hiddenGlobe;
aimRealCamera(env, { groundM: 2_500, cameraM: 3_500, southM: 3_000, away: true });
clock.advance(2_100);
env.preRender.raise();
assert.equal(env.sampleCalls.count, 0);
});
test('settled terrain refinement lifts an already sampled stem without another GPU sample', async (t) => { test('settled terrain refinement lifts an already sampled stem without another GPU sample', async (t) => {
const env = await createRealLocalLayerHarness({ const env = await createRealLocalLayerHarness({
sampleHeightSupported: true, sampleHeight: () => 117, sampleHeightSupported: true, sampleHeight: () => 117,
+83 -4
View File
@@ -1000,9 +1000,9 @@ export function createLocalGeoJsonLayer(
// governor the retry's preRender never arrives on a parked camera // governor the retry's preRender never arrives on a parked camera
// and the stem stays at ellipsoid height (buried/floating) until // and the stem stays at ellipsoid height (buried/floating) until
// the user happens to move. Schedule the frame the retry needs. // the user happens to move. Schedule the frame the retry needs.
// Gated on a sampleable scene and in-range records only, so a far // Gated on a sampleable scene and in-range, in-view records only,
// camera (or a keyless scene) stays fully idle; the distance is // so a far camera (or a keyless scene) stays fully idle; the
// only computed for still-unsampled stems. // distance is only computed for still-unsampled stems.
if ( if (
canSampleGround && canSampleGround &&
!record.groundSampled && !record.groundSampled &&
@@ -1010,7 +1010,8 @@ export function createLocalGeoJsonLayer(
Cesium.Cartesian3.distance( Cesium.Cartesian3.distance(
viewer.camera.positionWC, viewer.camera.positionWC,
record.base, record.base,
) < GROUND_SAMPLE_MAX_DISTANCE_M ) < GROUND_SAMPLE_MAX_DISTANCE_M &&
groundSampleInView(viewer, record)
) { ) {
groundRetryPending = true; groundRetryPending = true;
} }
@@ -1130,9 +1131,87 @@ function refreshLocalTerrainFloor(viewer, record) {
return true; return true;
} }
const groundSampleOccluder = new Cesium.EllipsoidalOccluder(
Cesium.Ellipsoid.WGS84,
);
const groundSampleCarto = new Cesium.Cartographic();
const groundSampleLow = new Cesium.Cartesian3();
const groundSampleHigh = new Cesium.Cartesian3();
/** The record's vertical at `height` metres above the ellipsoid. */
function groundSamplePoint(record, height, result) {
groundSampleCarto.longitude = record.carto.longitude;
groundSampleCarto.latitude = record.carto.latitude;
groundSampleCarto.height = height;
return Cesium.Cartographic.toCartesian(
groundSampleCarto,
Cesium.Ellipsoid.WGS84,
result,
);
}
/**
* Whether the camera can see the ground under the record: inside the view
* frustum and above the horizon. scene.sampleHeight reads only surface
* rendered for the current view, so a sample of unseen ground passes through
* the Earth (about -6,344 km near Ashburn on Esri) and fails on every 2 s
* retry, each one a full offscreen render; 110 unseen data centres there held
* rest frames at 58-589 ms. Unsampled bases sit on the ellipsoid, so the test
* uses loaded globe terrain when there is some. Otherwise (a hidden globe) it
* tests the vertical across +/-GROUND_SAMPLE_MAX_ABS_HEIGHT_M, every height a
* sample can accept, so high or below-ellipsoid ground in view is never
* mistaken for an unseen base. Unseen ground is sampled on the first walk that
* sees it.
*/
function groundSampleInView(viewer, record) {
const camera = viewer.camera;
const globe = viewer.scene.globe;
const terrain = globe?.show ? globe.getHeight?.(record.carto) : undefined;
const known =
Number.isFinite(terrain) &&
Math.abs(terrain) <= GROUND_SAMPLE_MAX_ABS_HEIGHT_M;
const low = groundSamplePoint(
record,
known ? terrain : -GROUND_SAMPLE_MAX_ABS_HEIGHT_M,
groundSampleLow,
);
const high = known
? low
: groundSamplePoint(
record,
GROUND_SAMPLE_MAX_ABS_HEIGHT_M,
groundSampleHigh,
);
// The vertical is unseen only when both ends are outside the same plane.
const { planes } = camera.frustum.computeCullingVolume(
camera.positionWC,
camera.directionWC,
camera.upWC,
);
for (const plane of planes) {
if (
Cesium.Cartesian3.dot(plane, low) + plane.w < 0 &&
Cesium.Cartesian3.dot(plane, high) + plane.w < 0
)
return false;
}
// The ellipsoidal occluder hides every point below the ellipsoid from a
// camera near it, so ground below 0 m (low-geoid coasts, the Dead Sea) is
// tested at 0 m; unknown ground at the top of the vertical.
const horizonHeight = known
? Math.max(terrain, 0)
: GROUND_SAMPLE_MAX_ABS_HEIGHT_M;
groundSampleOccluder.cameraPosition = camera.positionWC;
return groundSampleOccluder.isPointVisible(
groundSamplePoint(record, horizonHeight, groundSampleHigh),
);
}
function sampleLocalGroundHeight(viewer, record, now) { function sampleLocalGroundHeight(viewer, record, now) {
if (record.groundSampled || !viewer.scene.sampleHeightSupported) return false; if (record.groundSampled || !viewer.scene.sampleHeightSupported) return false;
if (now - record.lastGroundSampleMs < GROUND_SAMPLE_RETRY_MS) return false; if (now - record.lastGroundSampleMs < GROUND_SAMPLE_RETRY_MS) return false;
if (!groundSampleInView(viewer, record)) return false;
record.lastGroundSampleMs = now; record.lastGroundSampleMs = now;
const globe = viewer.scene.globe; const globe = viewer.scene.globe;
if (globe?.show && globe.tilesLoaded === false) return false; if (globe?.show && globe.tilesLoaded === false) return false;