mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-12 06:12:18 +00:00
fix(camera): judge a voice tilt's frame limit by the way its pitch moves
The pre-check picked the in-place look from args.direction alone, while the tilt itself turns down for any direction but up. A tilt sent as left or right at the frame limit was checked as a turn left or right, refused as losing the globe, though it turns down toward the planet. A rotate sent as up or down was checked as a look up or down, though it turns right. A tilt's look now comes from its goal pitch against the current pitch (tiltLook), and the tick tilts in place through tiltInPlaceWithinFrame(cam, m, goalPitch). Neither depends on the direction word, so a tilt to an absolute angle, or a tilt with no direction, can use them as they are.
This commit is contained in:
1 parent
f53342932d
commit
a20076fc5e
2 files changed
+51
-9
No files matched your search
@@ -1426,6 +1426,26 @@ test('voice tilt from orbit stops with the planet still on screen and then says
|
|||||||
assert.ok(camera.pitch > radians(-68.5) && camera.pitch < radians(-66));
|
assert.ok(camera.pitch > radians(-68.5) && camera.pitch < radians(-66));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The frame limit judges a tilt by the way its pitch moves, not by the
|
||||||
|
// direction word: a tilt sent as left or right turns down.
|
||||||
|
for (const direction of ['left', 'right']) {
|
||||||
|
test(`a tilt ${direction} from the frame limit is judged as the look down it is`, (t) => {
|
||||||
|
withScope(t, false);
|
||||||
|
const { camera, finishOnce } = harness(t, {
|
||||||
|
pitch: -80,
|
||||||
|
viewportWidth: 1600,
|
||||||
|
viewportHeight: 900,
|
||||||
|
});
|
||||||
|
assert.equal(moveCamera({ motion: 'tilt', direction: 'up' }).ok, true);
|
||||||
|
finishOnce();
|
||||||
|
const atLimit = camera.pitch;
|
||||||
|
const result = moveCamera({ motion: 'tilt', direction });
|
||||||
|
assert.equal(result.ok, true, result.error);
|
||||||
|
finishOnce();
|
||||||
|
assert.ok(camera.pitch < atLimit - radians(5), 'the tilt turned down');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
test('voice turn in place from orbit stops with the planet still on screen', (t) => {
|
test('voice turn in place from orbit stops with the planet still on screen', (t) => {
|
||||||
withScope(t, false); // the whole frame is visible
|
withScope(t, false); // the whole frame is visible
|
||||||
const { camera, tick } = harness(t, { pitch: -75 });
|
const { camera, tick } = harness(t, { pitch: -75 });
|
||||||
|
|||||||
+31
-9
@@ -1090,6 +1090,23 @@ function lookWithinFrame(cam, m, look, angle) {
|
|||||||
if (allowed < angle) interruptCameraMotion('globe-out-of-frame');
|
if (allowed < angle) interruptCameraMotion('globe-out-of-frame');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The in-place look a pitch change from `fromPitch` to `goalPitch` makes:
|
||||||
|
* 'lookUp', 'lookDown', or null when it does not move. A tilt is judged by
|
||||||
|
* the way its pitch moves, whatever form or direction word it came in.
|
||||||
|
*/
|
||||||
|
function tiltLook(fromPitch, goalPitch) {
|
||||||
|
if (!Number.isFinite(fromPitch) || !Number.isFinite(goalPitch)) return null;
|
||||||
|
if (goalPitch > fromPitch) return 'lookUp';
|
||||||
|
return goalPitch < fromPitch ? 'lookDown' : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tilt `m` in place to `goalPitch`, as far as the frame limit allows. */
|
||||||
|
function tiltInPlaceWithinFrame(cam, m, goalPitch) {
|
||||||
|
const look = tiltLook(cam.pitch, goalPitch);
|
||||||
|
if (look) lookWithinFrame(cam, m, look, Math.abs(goalPitch - cam.pitch));
|
||||||
|
}
|
||||||
|
|
||||||
/** True when the pre-check proved a half-degree `look` from `cam`'s pose. */
|
/** True when the pre-check proved a half-degree `look` from `cam`'s pose. */
|
||||||
function lookProven(cam, look) {
|
function lookProven(cam, look) {
|
||||||
return (
|
return (
|
||||||
@@ -1358,7 +1375,7 @@ function onTick() {
|
|||||||
interruptCameraMotion('tilt-clamp');
|
interruptCameraMotion('tilt-clamp');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lookWithinFrame(cam, m, up ? 'lookUp' : 'lookDown', stepRad);
|
tiltInPlaceWithinFrame(cam, m, next);
|
||||||
} else {
|
} else {
|
||||||
lookWithinFrame(
|
lookWithinFrame(
|
||||||
cam,
|
cam,
|
||||||
@@ -1662,15 +1679,20 @@ export function moveCamera(args = {}, runNavigation = null) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// A tilt is judged by the way its pitch will move (any direction other
|
||||||
|
// than up tilts down); a rotate turns left only when told to, as it runs.
|
||||||
const look =
|
const look =
|
||||||
motion === 'tilt' || motion === 'rotate'
|
motion === 'tilt'
|
||||||
? {
|
? tiltLook(
|
||||||
up: 'lookUp',
|
_viewer.camera.pitch,
|
||||||
down: 'lookDown',
|
_viewer.camera.pitch +
|
||||||
left: 'lookLeft',
|
Cesium.Math.toRadians(ONCE.tiltDeg) * (direction === 'up' ? 1 : -1),
|
||||||
right: 'lookRight',
|
)
|
||||||
}[direction]
|
: motion === 'rotate'
|
||||||
: null;
|
? direction === 'left'
|
||||||
|
? 'lookLeft'
|
||||||
|
: 'lookRight'
|
||||||
|
: null;
|
||||||
// Honest limits from orbit too: a stopped turn rests within 0.05° of its
|
// Honest limits from orbit too: a stopped turn rests within 0.05° of its
|
||||||
// limit, so one that cannot go half a degree further is refused rather than
|
// limit, so one that cannot go half a degree further is refused rather than
|
||||||
// run and reported as done, and one that can is then turned at least that
|
// run and reported as done, and one that can is then turned at least that
|
||||||
|
|||||||
Reference in new issue
Block a user