fix(camera): keep a deferred recovery check through long holds

A Director hold longer than the settle check's five-minute bound used
to expire the deferred check, so a run that ended on a stars-only shot
after a long hold stayed there until the next move. While a flight or a
playing scene defers the check, its bound no longer counts down; the
flight or scene bounds the deferral itself.

Also correct the trackball note in CURRENT-STATE: Cesium's tilt tests
the screen centre, so any tilt (drag or touch) with the centre on the
stars between 1,000 and 7,500 km now tilts about the planet's edge or
does nothing, wherever it starts. Rotation drags that start on the
planet are unchanged.
This commit is contained in:
Manjunath committed 2026-11-05 14:45:29 +05:30
1 parent 29935cc094
commit 852e93d074
3 files changed
+48 -43

No files matched your search

+40 -40
View File
@@ -70,46 +70,46 @@ below 1,000 km. Above that height a few drags could turn the whole planet out of
frame and leave only stars, so Shift+drag does nothing there. Cesium also turns
the camera in place for a drag that starts on the stars below its trackball
height (7,500 km by default); that height is lowered to 1,000 km, so such a drag
orbits the globe above it, as it does higher up, and a tilt drag from the stars
there tilts about the planet's edge or does nothing. Otherwise orbit, tilt and
zoom are unchanged at every height. How much of the frame shows the planet's
surface is measured by casting a 32×18 grid of view rays at the ellipsoid; while
the scope mask is on (the default) only the rays inside its keyhole count, since
the mask hides or dims the rest. Voice tilt and in-place turns of a free 3D
camera above 1,000 km stop when about a tenth of the frame still shows the
surface (or about as much as it showed when it started), never less than about
1% of the visible frame, and a view that already shows less only keeps or gains
what it has. A turn that cannot go half a degree further without crossing that
limit is refused with a reason instead of reported as done, and a turn it
accepts turns at least that half degree. A turn that keeps or gains surface is
not refused, even after the window has been resized, except that near the limit,
where the planet's edge crosses the sample grid, sampling wobble can
occasionally refuse one (most often above about 15,000 km and on phone or
ultrawide frames); nothing then turns away from the planet. A turn that starts
where the last voice turn left the camera keeps that turn's limit, or a higher
one if the planet now fills more, so repeating the request does not take any
more; once anything else has moved or turned the camera, a turn is measured from
what is on screen. When a camera move ends above 1,000 km with no ray on the
surface, the camera turns straight down at the same position and heading. The
end of a move is taken from Cesium's move-end event and from a check of its own
that samples the pose every 250 ms after a move starts and acts once it has held
for half a second, because at some of these poses the camera drifts by a
rounding error every frame and Cesium never sees it stop. That check keeps
watching until move-end arrives, recovering once after each move that comes to
rest, and gives up five minutes after the camera last moved. Limb glow, and a
surface sliver up to about one grid cell thick (some 50 px on a 900 px tall
frame), can count as out of view. The zoom-out guard above keeps wheel and pinch
zoom-outs in view; this catches the other ways a move can end looking away, such
as a saved or shared view that did. Views with more surface than that, such as
the oblique orbital Director shots, are left as they are, and so are tracked or
locked cameras, a camera flight in progress, a Director scene while it plays
(holds included) and the 2D and Columbus modes; a check a flight or scene defers
runs once it ends. A Director shot loaded or replayed outside a run is not a
playing scene. A view that loses its surface without a camera move (a resize, or
turning the scope on) is left as it is until the next move. A voice turn
requested while the camera is tracked is judged by the pose voice's release of
the follow camera will leave, before that release, so a refused turn keeps the
tracking.
orbits the globe above it, as it does higher up, and a tilt (drag or touch)
while the screen centre is on the stars there tilts about the planet's edge or
does nothing, wherever it starts. Rotation drags that start on the planet, and
zoom, are unchanged. How much of the frame shows the planet's surface is
measured by casting a 32×18 grid of view rays at the ellipsoid; while the scope
mask is on (the default) only the rays inside its keyhole count, since the mask
hides or dims the rest. Voice tilt and in-place turns of a free 3D camera above
1,000 km stop when about a tenth of the frame still shows the surface (or about
as much as it showed when it started), never less than about 1% of the visible
frame, and a view that already shows less only keeps or gains what it has. A
turn that cannot go half a degree further without crossing that limit is refused
with a reason instead of reported as done, and a turn it accepts turns at least
that half degree. A turn that keeps or gains surface is not refused, even after
the window has been resized, except that near the limit, where the planet's edge
crosses the sample grid, sampling wobble can occasionally refuse one (most often
above about 15,000 km and on phone or ultrawide frames); nothing then turns away
from the planet. A turn that starts where the last voice turn left the camera
keeps that turn's limit, or a higher one if the planet now fills more, so
repeating the request does not take any more; once anything else has moved or
turned the camera, a turn is measured from what is on screen. When a camera move
ends above 1,000 km with no ray on the surface, the camera turns straight down
at the same position and heading. The end of a move is taken from Cesium's
move-end event and from a check of its own that samples the pose every 250 ms
after a move starts and acts once it has held for half a second, because at some
of these poses the camera drifts by a rounding error every frame and Cesium
never sees it stop. That check keeps watching until move-end arrives, recovering
once after each move that comes to rest, and gives up five minutes after the
camera last moved. Limb glow, and a surface sliver up to about one grid cell
thick (some 50 px on a 900 px tall frame), can count as out of view. The
zoom-out guard above keeps wheel and pinch zoom-outs in view; this catches the
other ways a move can end looking away, such as a saved or shared view that did.
Views with more surface than that, such as the oblique orbital Director shots,
are left as they are, and so are tracked or locked cameras, a camera flight in
progress, a Director scene while it plays (holds included) and the 2D and
Columbus modes; a check a flight or scene defers runs once it ends. A Director
shot loaded or replayed outside a run is not a playing scene. A view that loses
its surface without a camera move (a resize, or turning the scope on) is left as
it is until the next move. A voice turn requested while the camera is tracked is
judged by the pose voice's release of the follow camera will leave, before that
release, so a refused turn keeps the tracking.
Analyst region queries resolve unique Natural Earth names offline without
geocoding, so Gold Coast and Ivory Coast name the West African natural regions.
+2
View File
@@ -765,6 +765,8 @@ test('a check a scene or flight defers runs once it ends', () => {
// A hold on a stars-only shot: quiet, with or without Cesium's moveEnd.
for (let i = 0; i < 4; i += 1) timers.tick();
if (viaMoveEnd) camera.moveEnd.raiseEvent();
// Longer than the settle check's five-minute bound.
for (let i = 0; i < 1500; i += 1) timers.tick();
assert.equal(globeOutOfFrame(camera), true, 'left alone while it plays');
assert.equal(timers.pending(), 1, 'still watching');
playing = false;
+6 -3
View File
@@ -174,7 +174,7 @@ const SETTLE_GIVE_UP_MS = 5 * 60_000;
* Heading and position are kept. Tracked cameras, locked ones (non-identity
* transform), a camera flight in progress, the 2D and Columbus modes, and any
* time `paused` returns true (an authored scene playing) are left alone; a
* check they defer runs again once they end, within the settle check's bound.
* check they defer runs once they end, however long they last.
* `keyholeRadius`
* returns the radius of the visible circle when a scope mask hides the rest of
* the frame (see `globeFrameShare`), or 0; it is read at every check.
@@ -261,8 +261,11 @@ export function installGlobeInViewRecovery(
}
// Two quiet samples in a row after a move: at rest for half a second, as
// for moveEnd.
if (restingSamples >= 2 && movedSinceCheck && recover())
movedSinceCheck = false;
if (restingSamples >= 2 && movedSinceCheck) {
if (recover()) movedSinceCheck = false;
// A flight or a playing scene bounds its own deferral.
else settleElapsed = 0;
}
if (settleElapsed >= SETTLE_GIVE_UP_MS) return;
Cesium.Cartesian3.clone(camera.positionWC, lastPosition);
Cesium.Cartesian3.clone(camera.directionWC, lastDirection);