terriajs
Version:
Geospatial data visualization platform.
114 lines • 5.11 kB
JavaScript
import BoundingSphere from "terriajs-cesium/Source/Core/BoundingSphere";
import Cartesian3 from "terriajs-cesium/Source/Core/Cartesian3";
import Cartographic from "terriajs-cesium/Source/Core/Cartographic";
import IntersectionTests from "terriajs-cesium/Source/Core/IntersectionTests";
import Ray from "terriajs-cesium/Source/Core/Ray";
import defined from "terriajs-cesium/Source/Core/defined";
import SceneMode from "terriajs-cesium/Source/Scene/SceneMode";
const scratchArray = [];
const scratchSphereIntersectionResult = {
start: 0.0,
stop: 0.0
};
// This is adapted from CesiumJS's `Globe.pick` function, but extended
// to return more information.
export default function pickTriangle(ray, scene, cullBackFaces, result) {
const mode = scene.mode;
const projection = scene.mapProjection;
const sphereIntersections = scratchArray;
sphereIntersections.length = 0;
const globeAny = scene.globe;
const surface = globeAny._surface;
const tilesToRender = surface._tilesToRender;
let length = tilesToRender.length;
let tile;
let i;
for (i = 0; i < length; ++i) {
tile = tilesToRender[i];
const surfaceTile = tile.data;
if (!defined(surfaceTile)) {
continue;
}
let boundingVolume = surfaceTile.pickBoundingSphere;
if (mode !== SceneMode.SCENE3D) {
surfaceTile.pickBoundingSphere = boundingVolume =
BoundingSphere.fromRectangleWithHeights2D(tile.rectangle, projection, surfaceTile.tileBoundingRegion.minimumHeight, surfaceTile.tileBoundingRegion.maximumHeight, boundingVolume);
Cartesian3.fromElements(boundingVolume.center.z, boundingVolume.center.x, boundingVolume.center.y, boundingVolume.center);
}
else if (defined(surfaceTile.renderedMesh)) {
BoundingSphere.clone(surfaceTile.tileBoundingRegion.boundingSphere, boundingVolume);
}
else {
// So wait how did we render this thing then? It shouldn't be possible to get here.
continue;
}
const boundingSphereIntersection = IntersectionTests.raySphere(ray, boundingVolume, scratchSphereIntersectionResult);
if (defined(boundingSphereIntersection)) {
sphereIntersections.push(tile);
}
}
sphereIntersections.sort(createComparePickTileFunction(ray.origin));
let intersection;
length = sphereIntersections.length;
for (i = 0; i < length; ++i) {
intersection = pickTriangleFromGlobeSurfaceTile(sphereIntersections[i].data, ray, scene.mode, scene.mapProjection, cullBackFaces, result);
if (intersection !== undefined) {
result.tile = sphereIntersections[i];
break;
}
}
return intersection === undefined ? undefined : result;
}
function createComparePickTileFunction(rayOrigin) {
return function (a, b) {
const aDist = BoundingSphere.distanceSquaredTo(a.data.pickBoundingSphere, rayOrigin);
const bDist = BoundingSphere.distanceSquaredTo(b.data.pickBoundingSphere, rayOrigin);
return aDist - bDist;
};
}
const scratchCartographic = new Cartographic();
function getPosition(encoding, mode, projection, vertices, index, result) {
let position = encoding.getExaggeratedPosition(vertices, index, result);
if (defined(mode) && mode !== SceneMode.SCENE3D) {
const ellipsoid = projection.ellipsoid;
const positionCartographic = ellipsoid.cartesianToCartographic(position, scratchCartographic);
position = projection.project(positionCartographic, result);
position = Cartesian3.fromElements(position.z, position.x, position.y, result);
}
return position;
}
const scratchV0 = new Cartesian3();
const scratchV1 = new Cartesian3();
const scratchV2 = new Cartesian3();
function pickTriangleFromGlobeSurfaceTile(globeSurfaceTile, ray, mode, projection, cullBackFaces, result) {
const mesh = globeSurfaceTile.renderedMesh;
if (!defined(mesh)) {
return undefined;
}
const vertices = mesh.vertices;
const indices = mesh.indices;
const encoding = mesh.encoding;
const indicesLength = indices.length;
let minT = Number.MAX_VALUE;
for (let i = 0; i < indicesLength; i += 3) {
const i0 = indices[i];
const i1 = indices[i + 1];
const i2 = indices[i + 2];
const v0 = getPosition(encoding, mode, projection, vertices, i0, scratchV0);
const v1 = getPosition(encoding, mode, projection, vertices, i1, scratchV1);
const v2 = getPosition(encoding, mode, projection, vertices, i2, scratchV2);
const t = IntersectionTests.rayTriangleParametric(ray, v0, v1, v2, cullBackFaces);
if (defined(t) && t < minT && t >= 0.0) {
minT = t;
Cartesian3.clone(v0, result.v0);
Cartesian3.clone(v1, result.v1);
Cartesian3.clone(v2, result.v2);
}
}
if (minT === Number.MAX_VALUE) {
return undefined;
}
Ray.getPoint(ray, minT, result.intersection);
return result;
}
//# sourceMappingURL=pickTriangle.js.map