@@ -10,6 +10,7 @@ import SceneMode from "../Scene/SceneMode.js";
1010import Interval from "./Interval.js" ;
1111import Check from "./Check.js" ;
1212import DeveloperError from "./DeveloperError.js" ;
13+ import CesiumMath from "./Math.js" ;
1314
1415// Terrain picker can be 4 levels deep (0-3)
1516const MAXIMUM_TERRAIN_PICKER_LEVEL = 3 ;
@@ -20,7 +21,7 @@ const MAXIMUM_TERRAIN_PICKER_LEVEL = 3;
2021 * @alias TerrainPicker
2122 * @constructor
2223 *
23- * @param {Float32Array } vertices The terrain mesh's vertex buffer.
24+ * @param {Float64Array } vertices The terrain mesh's vertex buffer.
2425 * @param {Uint8Array|Uint16Array|Uint32Array } indices The terrain mesh's index buffer.
2526 * @param {TerrainEncoding } encoding The terrain mesh's vertex encoding.
2627 *
@@ -35,7 +36,7 @@ function TerrainPicker(vertices, indices, encoding) {
3536
3637 /**
3738 * The terrain mesh's vertex buffer.
38- * @type {Float32Array }
39+ * @type {Float64Array }
3940 */
4041 this . _vertices = vertices ;
4142 /**
@@ -268,7 +269,7 @@ function createAABBForNode(x, y, level) {
268269/**
269270 * Packs triangle vertex positions and index into provided buffers, for the worker to process.
270271 * (The worker does tests to organize triangles into child nodes of the quadtree.)
271- * @param {Float32Array } trianglePositionsBuffer The buffer to pack triangle vertex positions into.
272+ * @param {Float64Array } trianglePositionsBuffer The buffer to pack triangle vertex positions into.
272273 * @param {Uint32Array } triangleIndicesBuffer The buffer to pack triangle indices into.
273274 * @param {Cartesian3[] } trianglePositions The triangle's vertex positions.
274275 * @param {number } triangleIndex The triangle's index in the overall tile's index buffer.
@@ -424,7 +425,7 @@ function getClosestTriangleInNode(
424425 let triangleIndices ;
425426 if ( shouldBuildChildren ) {
426427 // If the tree can be built deeper, prepare buffers to store triangle data for child nodes
427- trianglePositions = new Float32Array ( triangleCount * 9 ) ; // 3 vertices per triangle * 3 floats per vertex
428+ trianglePositions = new Float64Array ( triangleCount * 9 ) ; // 3 vertices per triangle * 3 floats per vertex
428429 triangleIndices = new Uint32Array ( triangleCount ) ;
429430 }
430431
@@ -434,6 +435,7 @@ function getClosestTriangleInNode(
434435 encoding ,
435436 mode ,
436437 projection ,
438+ ray ,
437439 vertices ,
438440 indices [ 3 * triIndex ] ,
439441 scratchTrianglePoints [ 0 ] ,
@@ -442,6 +444,7 @@ function getClosestTriangleInNode(
442444 encoding ,
443445 mode ,
444446 projection ,
447+ ray ,
445448 vertices ,
446449 indices [ 3 * triIndex + 1 ] ,
447450 scratchTrianglePoints [ 1 ] ,
@@ -450,6 +453,7 @@ function getClosestTriangleInNode(
450453 encoding ,
451454 mode ,
452455 projection ,
456+ ray ,
453457 vertices ,
454458 indices [ 3 * triIndex + 2 ] ,
455459 scratchTrianglePoints [ 2 ] ,
@@ -502,7 +506,8 @@ const scratchCartographic = new Cartographic();
502506 * @param {TerrainEncoding } encoding The terrain encoding.
503507 * @param {SceneMode } mode The scene mode (2D/3D/Columbus View).
504508 * @param {MapProjection } projection The map projection.
505- * @param {Float32Array } vertices The vertex buffer of the terrain mesh.
509+ * @param {Ray } ray The pick ray being tested (used here as a reference to resolve antimeridian wrapping in 2D/Columbus View).
510+ * @param {Float64Array } vertices The terrain mesh's vertex buffer.
506511 * @param {Number } index The index of the vertex to get.
507512 * @param {Cartesian3 } result The decoded, exaggerated, and possibly projected vertex position.
508513 * @returns {Cartesian3 } The result vertex position.
@@ -512,6 +517,7 @@ function getVertexPosition(
512517 encoding ,
513518 mode ,
514519 projection ,
520+ ray ,
515521 vertices ,
516522 index ,
517523 result ,
@@ -535,6 +541,14 @@ function getVertexPosition(
535541 result ,
536542 ) ;
537543
544+ // Due to wrapping in 2D/CV modes, near the antimeridian, the vertex
545+ // position may correspond to the other side of the world from the ray origin.
546+ // Compare the vertex position to the ray origin and adjust it accordingly.
547+ // A spherical approximation is sufficient for cylindrical projections,
548+ // like mercator and geographic.
549+ const worldWidth = CesiumMath . TWO_PI * projection . ellipsoid . maximumRadius ;
550+ const k = Math . round ( ( ray . origin . y - position . y ) / worldWidth ) ;
551+ position . y += k * worldWidth ;
538552 return position ;
539553}
540554
@@ -544,7 +558,7 @@ function getVertexPosition(
544558 * @param {Matrix4 } inverseTransform
545559 * @param {TerrainNode } node
546560 * @param {Uint32Array } triangleIndices
547- * @param {Float32Array } trianglePositions
561+ * @param {Float64Array } trianglePositions
548562 * @returns {Promise<void> } A promise that resolves when the triangles have been added to the child nodes.
549563 * @private
550564 */
@@ -596,7 +610,10 @@ async function addTrianglesToChildrenNodes(
596610 // Assign these to the child nodes
597611 const result = await incrementallyBuildTerrainPickerPromise ;
598612 result . intersectingTrianglesArrays . forEach ( ( buffer , index ) => {
599- node . children [ index ] . intersectingTriangles = new Uint32Array ( buffer ) ;
613+ // Guard against case where tree is reset while waiting for worker
614+ if ( defined ( node . children [ index ] ) ) {
615+ node . children [ index ] . intersectingTriangles = new Uint32Array ( buffer ) ;
616+ }
600617 } ) ;
601618
602619 // The node's triangles have been distributed to its children
0 commit comments