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.
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
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
constrain photoreal geometry, and retry work remains bounded. Already sampled
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() {} };
let sampleHeightImpl = sampleHeight;
const sampleCalls = { count: 0 };
// The camera frustum, reduced to the one answer ground sampling asks of it.
let baseVisibility = Cesium.Intersect.INSIDE;
const overlayHost = {
setVisible: (...args) => hostCalls.push(['visible', ...args]),
setEntries: (...args) => hostCalls.push(['entries', ...args]),
@@ -107,7 +109,19 @@ async function createRealLocalLayerHarness({
},
camera: {
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,
flyTo() {},
},
@@ -151,6 +165,10 @@ async function createRealLocalLayerHarness({
sampleCalls,
/** Swap scene.sampleHeight mid-test (e.g. tiles finally arrive). */
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() {
if (originalWindow === undefined) delete globalThis.window;
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);
});
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) => {
const env = await createRealLocalLayerHarness({
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
// and the stem stays at ellipsoid height (buried/floating) until
// the user happens to move. Schedule the frame the retry needs.
// Gated on a sampleable scene and in-range records only, so a far
// camera (or a keyless scene) stays fully idle; the distance is
// only computed for still-unsampled stems.
// Gated on a sampleable scene and in-range, in-view records only,
// so a far camera (or a keyless scene) stays fully idle; the
// distance is only computed for still-unsampled stems.
if (
canSampleGround &&
!record.groundSampled &&
@@ -1010,7 +1010,8 @@ export function createLocalGeoJsonLayer(
Cesium.Cartesian3.distance(
viewer.camera.positionWC,
record.base,
) < GROUND_SAMPLE_MAX_DISTANCE_M
) < GROUND_SAMPLE_MAX_DISTANCE_M &&
groundSampleInView(viewer, record)
) {
groundRetryPending = true;
}
@@ -1130,9 +1131,87 @@ function refreshLocalTerrainFloor(viewer, record) {
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) {
if (record.groundSampled || !viewer.scene.sampleHeightSupported) return false;
if (now - record.lastGroundSampleMs < GROUND_SAMPLE_RETRY_MS) return false;
if (!groundSampleInView(viewer, record)) return false;
record.lastGroundSampleMs = now;
const globe = viewer.scene.globe;
if (globe?.show && globe.tilesLoaded === false) return false;