mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
refactor(pick): use the globe engine
pickGroundPosition takes the globe engine (picker.pickPosition, then camera.pickEllipsoid) and still accepts a Cesium viewer from callers that hold one (layers until phase 1c), with one shared ground-or-ellipsoid rule. isSurfacePick classifies engine pick results exactly as the Cesium picks they wrap.
This commit is contained in:
1 parent
aaa6074663
commit
c2a0d20f3d
2 files changed
+77
-15
No files matched your search
+31
-15
@@ -1,3 +1,5 @@
|
|||||||
|
import { isGlobeEngine } from '../globe/contract.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validation for positions that came back from a Cesium screen pick.
|
* Validation for positions that came back from a Cesium screen pick.
|
||||||
*
|
*
|
||||||
@@ -52,29 +54,43 @@ export function isPickedWorldPosition(position) {
|
|||||||
* The world position under a screen point: the rendered surface where the
|
* The world position under a screen point: the rendered surface where the
|
||||||
* depth buffer has it, else the ellipsoid; null over the sky.
|
* depth buffer has it, else the ellipsoid; null over the sky.
|
||||||
*
|
*
|
||||||
* @param {object} viewer A Cesium viewer.
|
* @param {object} target The globe engine (`engine.picker.pickPosition`, then
|
||||||
|
* `engine.camera.pickEllipsoid`), or a Cesium viewer from callers that
|
||||||
|
* still hold one (`scene.pickPosition`, then `camera.pickEllipsoid`).
|
||||||
* @param {{x: number, y: number}} screenPosition
|
* @param {{x: number, y: number}} screenPosition
|
||||||
* @returns {{x: number, y: number, z: number}|null} A Cartesian3.
|
* @returns {{x: number, y: number, z: number}|null} A Cartesian3.
|
||||||
*/
|
*/
|
||||||
export function pickGroundPosition(viewer, screenPosition) {
|
export function pickGroundPosition(target, screenPosition) {
|
||||||
const scene = viewer?.scene;
|
if (isGlobeEngine(target)) {
|
||||||
|
const { picker, camera } = target;
|
||||||
|
return groundUnder(
|
||||||
|
screenPosition,
|
||||||
|
picker.pickPositionSupported ? picker : null,
|
||||||
|
camera,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const scene = target?.scene;
|
||||||
|
return groundUnder(
|
||||||
|
screenPosition,
|
||||||
|
scene?.pickPositionSupported && typeof scene.pickPosition === 'function'
|
||||||
|
? scene
|
||||||
|
: null,
|
||||||
|
typeof target?.camera?.pickEllipsoid === 'function' ? target.camera : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function groundUnder(screenPosition, depth, ellipsoid) {
|
||||||
let position = null;
|
let position = null;
|
||||||
if (
|
if (depth) {
|
||||||
scene?.pickPositionSupported &&
|
|
||||||
typeof scene.pickPosition === 'function'
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
position = scene.pickPosition(screenPosition);
|
position = depth.pickPosition(screenPosition);
|
||||||
} catch {
|
} catch {
|
||||||
position = null;
|
position = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (!isPickedWorldPosition(position) && ellipsoid) {
|
||||||
!isPickedWorldPosition(position) &&
|
|
||||||
typeof viewer?.camera?.pickEllipsoid === 'function'
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
position = viewer.camera.pickEllipsoid(screenPosition);
|
position = ellipsoid.pickEllipsoid(screenPosition);
|
||||||
} catch {
|
} catch {
|
||||||
position = null;
|
position = null;
|
||||||
}
|
}
|
||||||
@@ -83,8 +99,8 @@ export function pickGroundPosition(viewer, screenPosition) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether a `scene.pick()` result is the map itself: nothing, or 3D tile
|
* Whether a pick result (`engine.picker.pick()` or `scene.pick()`) is the
|
||||||
* content (which has no id).
|
* map itself: nothing, or 3D tile content (which has no id).
|
||||||
*
|
*
|
||||||
* @param {object|null|undefined} picked
|
* @param {object|null|undefined} picked
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
|
|||||||
@@ -184,3 +184,49 @@ test('a surface pick is nothing, or Google 3D tile content without an id', async
|
|||||||
assert.equal(isSurfacePick({ id: 'flight:1', content: {} }), false);
|
assert.equal(isSurfacePick({ id: 'flight:1', content: {} }), false);
|
||||||
assert.equal(isSurfacePick({ primitive: {} }), false, 'an unnamed primitive');
|
assert.equal(isSurfacePick({ primitive: {} }), false, 'an unnamed primitive');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('on a globe engine the ground is the picked surface, else the ellipsoid, never the sky', async () => {
|
||||||
|
const { pickGroundPosition } = await import('./scenePick.js');
|
||||||
|
const { createFakeEngine } = await import('../globe/testing/fakeEngine.js');
|
||||||
|
const ground = { x: 6378137, y: 0, z: 0 };
|
||||||
|
const sky = { x: 500, y: 0, z: 0 };
|
||||||
|
const screen = { x: 10, y: 20 };
|
||||||
|
const engine = createFakeEngine();
|
||||||
|
engine.fake.script('pickPosition', ground);
|
||||||
|
engine.fake.script('pickEllipsoid', undefined);
|
||||||
|
assert.equal(pickGroundPosition(engine, screen), ground);
|
||||||
|
assert.deepEqual(engine.fake.callsOf('picker.pickPosition')[0].args, [screen]);
|
||||||
|
engine.fake.script('pickPosition', sky);
|
||||||
|
engine.fake.script('pickEllipsoid', ground);
|
||||||
|
assert.equal(pickGroundPosition(engine, screen), ground);
|
||||||
|
engine.fake.script('pickPosition', () => {
|
||||||
|
throw new Error('depth read failed');
|
||||||
|
});
|
||||||
|
assert.equal(pickGroundPosition(engine, screen), ground);
|
||||||
|
engine.fake.script('pickEllipsoid', undefined);
|
||||||
|
assert.equal(pickGroundPosition(engine, screen), null);
|
||||||
|
const unsupported = createFakeEngine();
|
||||||
|
unsupported.picker.pickPositionSupported = false;
|
||||||
|
unsupported.fake.script('pickEllipsoid', ground);
|
||||||
|
assert.equal(pickGroundPosition(unsupported, screen), ground);
|
||||||
|
assert.equal(unsupported.fake.callsOf('picker.pickPosition').length, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('engine pick results classify like the Cesium picks they wrap', async () => {
|
||||||
|
const { isSurfacePick } = await import('./scenePick.js');
|
||||||
|
const { createCesiumPicker } = await import('../globe/cesium/picker.js');
|
||||||
|
const { createFakeViewer } = await import('../globe/cesium/testing/fakeViewer.mjs');
|
||||||
|
const raws = [
|
||||||
|
undefined,
|
||||||
|
{ content: {}, primitive: {} },
|
||||||
|
{ primitive: { isCesium3DTileset: true } },
|
||||||
|
{ id: 'flight:1', content: {} },
|
||||||
|
{ primitive: {} },
|
||||||
|
];
|
||||||
|
for (const raw of raws) {
|
||||||
|
const viewer = createFakeViewer();
|
||||||
|
viewer.scene.pick = () => raw;
|
||||||
|
const { picker } = createCesiumPicker(viewer);
|
||||||
|
assert.equal(isSurfacePick(picker.pick({ x: 1, y: 2 })), isSurfacePick(raw), JSON.stringify(raw));
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in new issue
Block a user