feat(globe): engine members and the viewer bridge for the shell

Contract: camera.position(result?) and camera.height() for per-frame
readers, render.request(reason?), maps.releasePhotorealTiles, sources
with a caller-owned ready provider, isGlobeEngine. engine.maps now hides
every tileset it has shown, lets the last imagery/photoreal call win, and
setPhotorealTiles(null) restores the last base imagery and its credit
instead of leaving the photoreal credit on a bare globe.

Cesium engine: reads the Viewer camera/canvas aliases, detaches bridged
events through the remover Cesium returns, raises frame timestamps
without allocating, re-aims the horizon occluder only when the camera
moved, and renders the scene directly when the governor governs another
viewer (or none yet). engineFromViewer returns the registered scene
engine of a viewer, else builds and caches one. The render governor stays
the Cesium render backend under engine.render and gains
isRenderGovernorInstalled.
This commit is contained in:
German Khokhlov committed 2026-10-15 18:18:19 +04:00
1 parent a5c98c6b07
commit 58a196374f
26 files changed
+657 -45

No files matched your search

+18 -4
View File
@@ -4,9 +4,23 @@
import * as Cesium from 'cesium';
import { bridgeEvent } from './events.js';
const toMilliseconds = (scene, time) => [
Cesium.JulianDate.toDate(time).getTime(),
];
const scratchGregorian = new Cesium.GregorianDate();
// JulianDate.toDate(time).getTime() without the Date: frame events must not
// allocate. A raise without a time (not Cesium's own) reads the clock.
function unixMilliseconds(scene, time) {
if (!time) return Date.now();
const date = Cesium.JulianDate.toGregorianDate(time, scratchGregorian);
return Date.UTC(
date.year,
date.month - 1,
date.day,
date.hour,
date.minute,
date.isLeapSecond ? date.second - 1 : date.second,
date.millisecond,
);
}
/**
* @param {Cesium.Viewer} viewer
@@ -16,7 +30,7 @@ export function createCesiumFrames(viewer) {
const { scene } = viewer;
const bridges = ['preUpdate', 'preRender', 'postRender'].map((name) => [
name,
bridgeEvent(scene[name], toMilliseconds),
bridgeEvent(scene[name], null, { unary: unixMilliseconds }),
]);
return {
frames: Object.fromEntries(