@cesium/engine 21.0.1 → 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/Build/Workers/{chunk-LPKJSIMD.js → chunk-2D3GLFZD.js} +12 -12
  2. package/Build/Workers/chunk-34YXP222.js +352 -0
  3. package/Build/Workers/{chunk-UKA7OISV.js → chunk-3GL53OCU.js} +17 -18
  4. package/Build/Workers/{chunk-WQZL6CA2.js → chunk-5B7VZQZY.js} +6 -6
  5. package/Build/Workers/{chunk-FE565QHX.js → chunk-5T5SY63I.js} +2 -2
  6. package/Build/Workers/{chunk-RR3NCT4R.js → chunk-5ZF53EY6.js} +4 -4
  7. package/Build/Workers/{chunk-PZUZCAX3.js → chunk-6HBKE43B.js} +7 -7
  8. package/Build/Workers/{chunk-5YXA47QD.js → chunk-726NINF5.js} +16 -16
  9. package/Build/Workers/{chunk-3RKX3UFI.js → chunk-75HAJIDT.js} +1 -1
  10. package/Build/Workers/{chunk-CBPNIEGH.js → chunk-7KAXDKRU.js} +10 -10
  11. package/Build/Workers/chunk-7XEJGXX2.js +2759 -0
  12. package/Build/Workers/{chunk-U2GR5FDL.js → chunk-A4DPJIWS.js} +18 -10
  13. package/Build/Workers/{chunk-G3CKZ34K.js → chunk-A6JAFSZT.js} +5 -5
  14. package/Build/Workers/{chunk-2SI7DEW5.js → chunk-AARZSH4V.js} +5 -5
  15. package/Build/Workers/{chunk-W6KMV4F5.js → chunk-AOM3FHBN.js} +6 -6
  16. package/Build/Workers/{chunk-VVALNLSH.js → chunk-BJSNGGBM.js} +4 -4
  17. package/Build/Workers/{chunk-3YNW5K6O.js → chunk-ECHAJNQJ.js} +12 -12
  18. package/Build/Workers/{chunk-KZ7GDSAJ.js → chunk-EJO3NKMS.js} +1 -1
  19. package/Build/Workers/{chunk-UFSYRVC5.js → chunk-EZ7NJXQN.js} +4 -4
  20. package/Build/Workers/{chunk-P2UKEFCK.js → chunk-FA3SCJDX.js} +2 -2
  21. package/Build/Workers/{chunk-MXOGBWMP.js → chunk-GYRDA3XK.js} +14 -14
  22. package/Build/Workers/{chunk-KVB73ECP.js → chunk-H7B7FU2U.js} +7 -7
  23. package/Build/Workers/{chunk-XJVRYJVZ.js → chunk-IGX772ZQ.js} +1 -1
  24. package/Build/Workers/{chunk-MQPDOWGH.js → chunk-JDJAPBZP.js} +1 -1
  25. package/Build/Workers/{chunk-DDXI6UYW.js → chunk-JZFU2LEM.js} +4 -4
  26. package/Build/Workers/{chunk-DAJKOQW6.js → chunk-KGLDJRSO.js} +9 -9
  27. package/Build/Workers/{chunk-CSDYSXBI.js → chunk-KUB64XW6.js} +11 -11
  28. package/Build/Workers/{chunk-X3ZV3XNO.js → chunk-L7U26FFD.js} +16 -16
  29. package/Build/Workers/{chunk-YZ3RCE45.js → chunk-LEFQBK6H.js} +11 -11
  30. package/Build/Workers/{chunk-KEPPNSBL.js → chunk-LWJXCI3F.js} +5 -5
  31. package/Build/Workers/{chunk-YNOVMSUX.js → chunk-M7HRE4QR.js} +8 -8
  32. package/Build/Workers/{chunk-ASVODZNK.js → chunk-MXHRZHDF.js} +6 -6
  33. package/Build/Workers/{chunk-PJAA7QSC.js → chunk-N52ZRKUE.js} +6 -6
  34. package/Build/Workers/{chunk-W6I3LNPF.js → chunk-NE5JTQJP.js} +7 -7
  35. package/Build/Workers/{chunk-XG54SG4O.js → chunk-NGKF5NTR.js} +5 -5
  36. package/Build/Workers/{chunk-42EJCSIV.js → chunk-NHZNMTIR.js} +5 -5
  37. package/Build/Workers/{chunk-LU7DLY2L.js → chunk-OE22564R.js} +3 -3
  38. package/Build/Workers/{chunk-A2SP2EJZ.js → chunk-OUBBMEWX.js} +6 -6
  39. package/Build/Workers/{chunk-J2XQVKVH.js → chunk-P2H75UV5.js} +67 -33
  40. package/Build/Workers/{chunk-J3KPR6DJ.js → chunk-QCMRUVVF.js} +12 -12
  41. package/Build/Workers/{chunk-RVRN4KDB.js → chunk-QSMIHPUM.js} +2 -2
  42. package/Build/Workers/{chunk-EBDZDBJN.js → chunk-RCCYW6E7.js} +12 -12
  43. package/Build/Workers/{chunk-LV3G32QE.js → chunk-RQRODXVN.js} +4 -4
  44. package/Build/Workers/{chunk-OBS5EMZ6.js → chunk-SZN34LQ5.js} +10 -10
  45. package/Build/Workers/{chunk-IKUOV6DO.js → chunk-U4XMLGSR.js} +7 -7
  46. package/Build/Workers/{chunk-NYYQZ3LH.js → chunk-U7CX3HHE.js} +8 -8
  47. package/Build/Workers/{chunk-QNOIRRJK.js → chunk-VCVA7BMD.js} +4 -4
  48. package/Build/Workers/{chunk-TGJQMEL4.js → chunk-VVZ667H6.js} +2 -2
  49. package/Build/Workers/{chunk-DBHL2UVG.js → chunk-W4PIP5PG.js} +2 -2
  50. package/Build/Workers/{chunk-2QPH5QDK.js → chunk-XPVZWY4A.js} +8 -8
  51. package/Build/Workers/{chunk-4CORGH7N.js → chunk-XQ347YWU.js} +13 -13
  52. package/Build/Workers/{chunk-T7HU6E7G.js → chunk-XZO6F23E.js} +1 -1
  53. package/Build/Workers/{chunk-DTKSVIH5.js → chunk-YLILBDWK.js} +2 -2
  54. package/Build/Workers/{chunk-JG3C3LPY.js → chunk-YLXWC7OW.js} +4 -4
  55. package/Build/Workers/combineGeometry.js +21 -21
  56. package/Build/Workers/createBoxGeometry.js +15 -15
  57. package/Build/Workers/createBoxOutlineGeometry.js +13 -13
  58. package/Build/Workers/createCircleGeometry.js +23 -23
  59. package/Build/Workers/createCircleOutlineGeometry.js +16 -16
  60. package/Build/Workers/createCoplanarPolygonGeometry.js +30 -30
  61. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +28 -28
  62. package/Build/Workers/createCorridorGeometry.js +26 -26
  63. package/Build/Workers/createCorridorOutlineGeometry.js +25 -25
  64. package/Build/Workers/createCylinderGeometry.js +17 -17
  65. package/Build/Workers/createCylinderOutlineGeometry.js +15 -15
  66. package/Build/Workers/createEllipseGeometry.js +23 -23
  67. package/Build/Workers/createEllipseOutlineGeometry.js +16 -16
  68. package/Build/Workers/createEllipsoidGeometry.js +16 -16
  69. package/Build/Workers/createEllipsoidOutlineGeometry.js +15 -15
  70. package/Build/Workers/createFrustumGeometry.js +15 -15
  71. package/Build/Workers/createFrustumOutlineGeometry.js +15 -15
  72. package/Build/Workers/createGeometry.js +24 -22
  73. package/Build/Workers/createGroundPolylineGeometry.js +19 -19
  74. package/Build/Workers/createPlaneGeometry.js +13 -13
  75. package/Build/Workers/createPlaneOutlineGeometry.js +12 -12
  76. package/Build/Workers/createPolygonGeometry.js +29 -29
  77. package/Build/Workers/createPolygonOutlineGeometry.js +27 -27
  78. package/Build/Workers/createPolylineGeometry.js +22 -22
  79. package/Build/Workers/createPolylineVolumeGeometry.js +28 -28
  80. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +24 -24
  81. package/Build/Workers/createRectangleGeometry.js +24 -24
  82. package/Build/Workers/createRectangleOutlineGeometry.js +17 -17
  83. package/Build/Workers/createSimplePolylineGeometry.js +20 -20
  84. package/Build/Workers/createSphereGeometry.js +16 -16
  85. package/Build/Workers/createSphereOutlineGeometry.js +15 -15
  86. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  87. package/Build/Workers/createVectorTileClampedPolylines.js +12 -12
  88. package/Build/Workers/createVectorTileGeometries.js +21 -21
  89. package/Build/Workers/createVectorTilePoints.js +11 -11
  90. package/Build/Workers/createVectorTilePolygons.js +19 -19
  91. package/Build/Workers/createVectorTilePolylines.js +12 -12
  92. package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +88 -0
  93. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +21 -21
  94. package/Build/Workers/createVerticesFromHeightmap.js +21 -21
  95. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +19 -277
  96. package/Build/Workers/createWallGeometry.js +21 -21
  97. package/Build/Workers/createWallOutlineGeometry.js +20 -20
  98. package/Build/Workers/decodeDraco.js +10 -10
  99. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  100. package/Build/Workers/decodeI3S.js +9 -9
  101. package/Build/Workers/gaussianSplatSorter.js +4 -4
  102. package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
  103. package/Build/Workers/transcodeKTX2.js +6 -6
  104. package/Build/Workers/transferTypedArrayTest.js +1 -1
  105. package/Build/Workers/upsampleQuantizedTerrainMesh.js +19 -19
  106. package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +92 -0
  107. package/Source/Core/ArcGISTiledElevationTerrainProvider.js +2 -2
  108. package/Source/Core/Cesium3DTilesTerrainData.js +930 -0
  109. package/Source/Core/Cesium3DTilesTerrainGeometryProcessor.js +1866 -0
  110. package/Source/Core/Cesium3DTilesTerrainProvider.js +1052 -0
  111. package/Source/Core/CesiumTerrainProvider.js +2 -2
  112. package/Source/Core/Color.js +23 -6
  113. package/Source/Core/EllipsoidalOccluder.js +2 -2
  114. package/Source/Core/FeatureDetection.js +0 -2
  115. package/Source/Core/GoogleEarthEnterpriseMetadata.js +1 -1
  116. package/Source/Core/GoogleEarthEnterpriseTerrainData.js +1 -1
  117. package/Source/Core/GoogleEarthEnterpriseTerrainProvider.js +1 -1
  118. package/Source/Core/HeightmapTerrainData.js +10 -22
  119. package/Source/Core/HilbertOrder.js +0 -6
  120. package/Source/Core/ITwinPlatform.js +6 -6
  121. package/Source/Core/Ion.js +1 -1
  122. package/Source/Core/IonResource.js +35 -27
  123. package/Source/Core/PixelFormat.js +2 -2
  124. package/Source/Core/QuantizedMeshTerrainData.js +23 -57
  125. package/Source/Core/Resource.js +15 -11
  126. package/Source/Core/S2Cell.js +6 -18
  127. package/Source/Core/TaskProcessor.js +1 -1
  128. package/Source/Core/TerrainData.js +2 -1
  129. package/Source/Core/TerrainEncoding.js +215 -38
  130. package/Source/Core/TerrainMesh.js +8 -8
  131. package/Source/Core/TerrainProvider.js +151 -0
  132. package/Source/Core/VRTheWorldTerrainProvider.js +2 -2
  133. package/Source/Core/binarySearch.js +1 -1
  134. package/Source/Core/createWorldBathymetryAsync.js +2 -2
  135. package/Source/Core/createWorldTerrainAsync.js +3 -3
  136. package/Source/Core/loadImageFromTypedArray.js +9 -3
  137. package/Source/Core/mergeSort.js +1 -1
  138. package/Source/DataSources/PropertyArray.js +2 -2
  139. package/Source/Renderer/AutomaticUniforms.js +61 -0
  140. package/Source/Renderer/Context.js +13 -7
  141. package/Source/Renderer/Pass.js +10 -9
  142. package/Source/Renderer/UniformState.js +12 -0
  143. package/Source/Renderer/VertexArray.js +1 -1
  144. package/Source/Scene/ArcGisMapServerImageryProvider.js +1 -1
  145. package/Source/Scene/ArcGisMapService.js +1 -1
  146. package/Source/Scene/Azure2DImageryProvider.js +7 -5
  147. package/Source/Scene/BatchTable.js +2 -2
  148. package/Source/Scene/BillboardCollection.js +25 -21
  149. package/Source/Scene/BingMapsImageryProvider.js +1 -1
  150. package/Source/Scene/BoundingVolumeSemantics.js +54 -62
  151. package/Source/Scene/Cesium3DTile.js +3 -3
  152. package/Source/Scene/Cesium3DTilesVoxelProvider.js +1 -1
  153. package/Source/Scene/Cesium3DTileset.js +1 -1
  154. package/Source/Scene/EdgeFramebuffer.js +245 -0
  155. package/Source/Scene/FrameState.js +12 -0
  156. package/Source/Scene/GaussianSplat3DTileContent.js +12 -16
  157. package/Source/Scene/GaussianSplatPrimitive.js +12 -8
  158. package/Source/Scene/GaussianSplatSorter.js +2 -2
  159. package/Source/Scene/Globe.js +1 -1
  160. package/Source/Scene/GlobeSurfaceTile.js +10 -4
  161. package/Source/Scene/GltfBufferViewLoader.js +18 -0
  162. package/Source/Scene/GltfLoader.js +46 -8
  163. package/Source/Scene/Google2DImageryProvider.js +39 -27
  164. package/Source/Scene/GoogleEarthEnterpriseMapsProvider.js +1 -1
  165. package/Source/Scene/I3SDataProvider.js +1 -1
  166. package/Source/Scene/I3SDecoder.js +3 -3
  167. package/Source/Scene/ITwinData.js +4 -4
  168. package/Source/Scene/ImageryLayer.js +1 -1
  169. package/Source/Scene/Implicit3DTileContent.js +18 -7
  170. package/Source/Scene/ImplicitSubtree.js +3 -3
  171. package/Source/Scene/ImplicitTileset.js +2 -2
  172. package/Source/Scene/IonImageryProvider.js +15 -84
  173. package/Source/Scene/IonImageryProviderFactory.js +194 -0
  174. package/Source/Scene/LabelCollection.js +54 -36
  175. package/Source/Scene/MetadataComponentType.js +5 -5
  176. package/Source/Scene/MetadataTableProperty.js +3 -9
  177. package/Source/Scene/Model/EdgeDetectionPipelineStage.js +42 -0
  178. package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +800 -0
  179. package/Source/Scene/Model/MetadataPipelineStage.js +7 -7
  180. package/Source/Scene/Model/ModelDrawCommand.js +69 -0
  181. package/Source/Scene/Model/ModelImagery.js +4 -0
  182. package/Source/Scene/Model/ModelRuntimeNode.js +2 -2
  183. package/Source/Scene/Model/ModelRuntimePrimitive.js +13 -2
  184. package/Source/Scene/Model/ModelSceneGraph.js +15 -3
  185. package/Source/Scene/Model/ModelUtility.js +0 -1
  186. package/Source/Scene/Model/NodeRenderResources.js +1 -1
  187. package/Source/Scene/Model/PrimitiveRenderResources.js +1 -1
  188. package/Source/Scene/OIT.js +11 -1
  189. package/Source/Scene/PickFramebuffer.js +13 -17
  190. package/Source/Scene/Picking.js +104 -80
  191. package/Source/Scene/QuadtreePrimitive.js +34 -26
  192. package/Source/Scene/QuadtreeTile.js +66 -46
  193. package/Source/Scene/ResourceLoaderState.js +1 -1
  194. package/Source/Scene/Scene.js +124 -12
  195. package/Source/Scene/ScreenSpaceCameraController.js +1 -1
  196. package/Source/Scene/SensorVolumePortionToDisplay.js +6 -6
  197. package/Source/Scene/SingleTileImageryProvider.js +3 -3
  198. package/Source/Scene/Terrain.js +5 -5
  199. package/Source/Scene/TileMapServiceImageryProvider.js +2 -2
  200. package/Source/Scene/UrlTemplateImageryProvider.js +1 -1
  201. package/Source/Scene/View.js +3 -0
  202. package/Source/Scene/VoxelPrimitive.js +196 -189
  203. package/Source/Scene/VoxelShape.js +2 -0
  204. package/Source/Scene/createWorldImageryAsync.js +1 -1
  205. package/Source/Shaders/BillboardCollectionFS.glsl +102 -62
  206. package/Source/Shaders/BillboardCollectionFS.js +102 -63
  207. package/Source/Shaders/BillboardCollectionVS.glsl +44 -37
  208. package/Source/Shaders/BillboardCollectionVS.js +45 -38
  209. package/Source/Shaders/Builtin/Constants/passCesium3DTile.glsl +1 -1
  210. package/Source/Shaders/Builtin/Constants/passCesium3DTile.js +1 -1
  211. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassification.glsl +1 -1
  212. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassification.js +1 -1
  213. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassificationIgnoreShow.glsl +1 -1
  214. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassificationIgnoreShow.js +1 -1
  215. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdges.glsl +10 -0
  216. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdges.js +12 -0
  217. package/Source/Shaders/Builtin/Constants/passGaussianSplats.glsl +1 -1
  218. package/Source/Shaders/Builtin/Constants/passGaussianSplats.js +1 -1
  219. package/Source/Shaders/Builtin/Constants/passOpaque.glsl +1 -1
  220. package/Source/Shaders/Builtin/Constants/passOpaque.js +1 -1
  221. package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
  222. package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
  223. package/Source/Shaders/Builtin/Constants/passTranslucent.glsl +1 -1
  224. package/Source/Shaders/Builtin/Constants/passTranslucent.js +1 -1
  225. package/Source/Shaders/Builtin/Constants/passVoxels.glsl +1 -1
  226. package/Source/Shaders/Builtin/Constants/passVoxels.js +1 -1
  227. package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
  228. package/Source/Shaders/GlobeVS.glsl +1 -1
  229. package/Source/Shaders/GlobeVS.js +1 -1
  230. package/Source/Shaders/Model/EdgeDetectionStageFS.glsl +58 -0
  231. package/Source/Shaders/Model/EdgeDetectionStageFS.js +60 -0
  232. package/Source/Shaders/Model/EdgeVisibilityStageFS.glsl +83 -0
  233. package/Source/Shaders/Model/EdgeVisibilityStageFS.js +85 -0
  234. package/Source/Shaders/Model/ModelFS.glsl +5 -0
  235. package/Source/Shaders/Model/ModelFS.js +5 -0
  236. package/Source/Shaders/Model/PrimitiveOutlineStageFS.glsl +0 -1
  237. package/Source/Shaders/Model/PrimitiveOutlineStageFS.js +0 -1
  238. package/Source/Shaders/ShadowVolumeAppearanceFS.glsl +7 -15
  239. package/Source/Shaders/ShadowVolumeAppearanceFS.js +7 -15
  240. package/Source/Workers/createVerticesFromCesium3DTilesTerrain.js +46 -0
  241. package/Source/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +55 -0
  242. package/index.d.ts +281 -27
  243. package/index.js +200 -190
  244. package/package.json +2 -1
@@ -262,9 +262,9 @@ function computePickingDrawingBufferRectangle(
262
262
  }
263
263
 
264
264
  /**
265
- * Returns an object with a <code>primitive</code> property that contains the first (top) primitive in the scene
266
- * at a particular window coordinate or undefined if nothing is at the location. Other properties may
267
- * potentially be set depending on the type of primitive and may be used to further identify the picked object.
265
+ * Returns a list of objects with a <code>primitive</code> property that contains the first (top) primitives
266
+ * in the scene at a particular window coordinate. Other properties may potentially be set depending on the
267
+ * type of primitive and may be used to further identify the picked object.
268
268
  * <p>
269
269
  * When a feature of a 3D Tiles tileset is picked, <code>pick</code> returns a {@link Cesium3DTileFeature} object.
270
270
  * </p>
@@ -272,9 +272,16 @@ function computePickingDrawingBufferRectangle(
272
272
  * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
273
273
  * @param {number} [width=3] Width of the pick rectangle.
274
274
  * @param {number} [height=3] Height of the pick rectangle.
275
- * @returns {object | undefined} Object containing the picked primitive.
275
+ * @param {number} [limit=1] If supplied, stop iterating after collecting this many objects.
276
+ * @returns {object[]} List of objects containing the picked primitives.
276
277
  */
277
- Picking.prototype.pick = function (scene, windowPosition, width, height) {
278
+ Picking.prototype.pick = function (
279
+ scene,
280
+ windowPosition,
281
+ width,
282
+ height,
283
+ limit = 1,
284
+ ) {
278
285
  //>>includeStart('debug', pragmas.debug);
279
286
  Check.defined("windowPosition", windowPosition);
280
287
  //>>includeEnd('debug');
@@ -328,9 +335,9 @@ Picking.prototype.pick = function (scene, windowPosition, width, height) {
328
335
  scene.updateAndExecuteCommands(passState, scratchColorZero);
329
336
  scene.resolveFramebuffers(passState);
330
337
 
331
- const object = pickFramebuffer.end(drawingBufferRectangle);
338
+ const pickedObjects = pickFramebuffer.end(drawingBufferRectangle, limit);
332
339
  context.endFrame();
333
- return object;
340
+ return pickedObjects;
334
341
  };
335
342
 
336
343
  /**
@@ -711,39 +718,41 @@ Picking.prototype.pickPosition = function (scene, windowPosition, result) {
711
718
  return result;
712
719
  };
713
720
 
714
- function drillPick(limit, pickCallback) {
715
- // PERFORMANCE_IDEA: This function calls each primitive's update for each pass. Instead
716
- // we could update the primitive once, and then just execute their commands for each pass,
717
- // and cull commands for picked primitives. e.g., base on the command's owner.
718
- let i;
719
- let attributes;
720
- const result = [];
721
- const pickedPrimitives = [];
722
- const pickedAttributes = [];
723
- const pickedFeatures = [];
724
- if (!defined(limit)) {
725
- limit = Number.MAX_VALUE;
726
- }
727
-
728
- let pickedResult = pickCallback();
729
- while (defined(pickedResult)) {
721
+ /**
722
+ * @param {object[]} pickedResults the results from the pickCallback
723
+ * @param {number} limit If supplied, stop drilling after collecting this many picks.
724
+ * @param {object[]} results
725
+ * @param {object[]} pickedPrimitives
726
+ * @param {object[]} pickedAttributes
727
+ * @param {object[]} pickedFeatures
728
+ * @returns {boolean} whether picking should end
729
+ */
730
+ function addDrillPickedResults(
731
+ pickedResults,
732
+ limit,
733
+ results,
734
+ pickedPrimitives,
735
+ pickedAttributes,
736
+ pickedFeatures,
737
+ ) {
738
+ for (const pickedResult of pickedResults) {
730
739
  const object = pickedResult.object;
731
740
  const position = pickedResult.position;
732
741
  const exclude = pickedResult.exclude;
733
742
 
734
743
  if (defined(position) && !defined(object)) {
735
- result.push(pickedResult);
736
- break;
744
+ results.push(pickedResult);
745
+ return true;
737
746
  }
738
747
 
739
748
  if (!defined(object) || !defined(object.primitive)) {
740
- break;
749
+ return true;
741
750
  }
742
751
 
743
752
  if (!exclude) {
744
- result.push(pickedResult);
745
- if (0 >= --limit) {
746
- break;
753
+ results.push(pickedResult);
754
+ if (results.length >= limit) {
755
+ return true;
747
756
  }
748
757
  }
749
758
 
@@ -753,7 +762,7 @@ function drillPick(limit, pickCallback) {
753
762
  // If the picked object has a show attribute, use it.
754
763
  if (typeof primitive.getGeometryInstanceAttributes === "function") {
755
764
  if (defined(object.id)) {
756
- attributes = primitive.getGeometryInstanceAttributes(object.id);
765
+ const attributes = primitive.getGeometryInstanceAttributes(object.id);
757
766
  if (defined(attributes) && defined(attributes.show)) {
758
767
  hasShowAttribute = true;
759
768
  attributes.show = ShowGeometryInstanceAttribute.toValue(
@@ -776,28 +785,61 @@ function drillPick(limit, pickCallback) {
776
785
  primitive.show = false;
777
786
  pickedPrimitives.push(primitive);
778
787
  }
788
+ }
789
+ }
779
790
 
780
- pickedResult = pickCallback();
791
+ /**
792
+ * Drill pick by repeatedly calling a given `pickCallback`, each time stripping away the previously picked objects.
793
+ * @param {function(number): object[]} pickCallback Pick callback to execute each iteration
794
+ * @param {number} [limit=Number.MAX_VALUE] If supplied, stop drilling after collecting this many picks
795
+ * @returns {object[]} List of picked results
796
+ */
797
+ function drillPick(pickCallback, limit) {
798
+ // PERFORMANCE_IDEA: This function calls each primitive's update for each pass. Instead
799
+ // we could update the primitive once, and then just execute their commands for each pass,
800
+ // and cull commands for picked primitives. e.g., base on the command's owner.
801
+ const results = [];
802
+ const pickedPrimitives = [];
803
+ const pickedAttributes = [];
804
+ const pickedFeatures = [];
805
+ if (!defined(limit)) {
806
+ limit = Number.MAX_VALUE;
807
+ }
808
+
809
+ let pickedResults = pickCallback(limit);
810
+ while (defined(pickedResults) && pickedResults.length > 0) {
811
+ const complete = addDrillPickedResults(
812
+ pickedResults,
813
+ limit,
814
+ results,
815
+ pickedPrimitives,
816
+ pickedAttributes,
817
+ pickedFeatures,
818
+ );
819
+ if (complete) {
820
+ break;
821
+ }
822
+ pickedResults = pickCallback(limit - results.length);
781
823
  }
782
824
 
783
825
  // Unhide everything we hid while drill picking
784
- for (i = 0; i < pickedPrimitives.length; ++i) {
826
+ for (let i = 0; i < pickedPrimitives.length; ++i) {
785
827
  pickedPrimitives[i].show = true;
786
828
  }
787
829
 
788
- for (i = 0; i < pickedAttributes.length; ++i) {
789
- attributes = pickedAttributes[i];
830
+ for (let i = 0; i < pickedAttributes.length; ++i) {
831
+ const attributes = pickedAttributes[i];
790
832
  attributes.show = ShowGeometryInstanceAttribute.toValue(
791
833
  true,
792
834
  attributes.show,
793
835
  );
794
836
  }
795
837
 
796
- for (i = 0; i < pickedFeatures.length; ++i) {
838
+ for (let i = 0; i < pickedFeatures.length; ++i) {
797
839
  pickedFeatures[i].show = true;
798
840
  }
799
841
 
800
- return result;
842
+ return results;
801
843
  }
802
844
 
803
845
  Picking.prototype.drillPick = function (
@@ -807,21 +849,22 @@ Picking.prototype.drillPick = function (
807
849
  width,
808
850
  height,
809
851
  ) {
810
- const that = this;
811
- const pickCallback = function () {
812
- const object = that.pick(scene, windowPosition, width, height);
813
- if (defined(object)) {
814
- return {
815
- object: object,
816
- position: undefined,
817
- exclude: false,
818
- };
819
- }
852
+ const pickCallback = (limit) => {
853
+ const pickedObjects = this.pick(
854
+ scene,
855
+ windowPosition,
856
+ width,
857
+ height,
858
+ limit,
859
+ );
860
+ return pickedObjects.map((object) => ({
861
+ object: object,
862
+ position: undefined,
863
+ exclude: false,
864
+ }));
820
865
  };
821
- const objects = drillPick(limit, pickCallback);
822
- return objects.map(function (element) {
823
- return element.object;
824
- });
866
+ const objects = drillPick(pickCallback, limit);
867
+ return objects.map((element) => element.object);
825
868
  };
826
869
 
827
870
  const scratchRight = new Cartesian3();
@@ -928,7 +971,7 @@ function getTilesets(primitives, objectsToExclude, tilesets) {
928
971
  * @param {Picking} picking
929
972
  * @param {Scene} scene
930
973
  * @param {Ray} ray
931
- * @param {Object[] | undefined} objectsToExclude
974
+ * @param {object[] | undefined} objectsToExclude
932
975
  * @param {number | undefined} width
933
976
  * @param {Function} callback
934
977
  * @returns {Promise<Cartesian3 | undefined>}
@@ -1016,7 +1059,8 @@ function getRayIntersection(
1016
1059
  scene.resolveFramebuffers(passState);
1017
1060
 
1018
1061
  let position;
1019
- const object = view.pickFramebuffer.end(drawingBufferRectangle);
1062
+ // Picking one object, result is either [object] or []
1063
+ const object = view.pickFramebuffer.end(drawingBufferRectangle, 1)[0];
1020
1064
 
1021
1065
  if (scene.context.depthTexture) {
1022
1066
  const { frustumCommandsList } = view;
@@ -1054,7 +1098,7 @@ function getRayIntersection(
1054
1098
  }
1055
1099
  }
1056
1100
 
1057
- function getRayIntersections(
1101
+ function drillPickFromRay(
1058
1102
  picking,
1059
1103
  scene,
1060
1104
  ray,
@@ -1065,7 +1109,7 @@ function getRayIntersections(
1065
1109
  mostDetailed,
1066
1110
  ) {
1067
1111
  const pickCallback = function () {
1068
- return getRayIntersection(
1112
+ const pickResult = getRayIntersection(
1069
1113
  picking,
1070
1114
  scene,
1071
1115
  ray,
@@ -1074,8 +1118,9 @@ function getRayIntersections(
1074
1118
  requirePosition,
1075
1119
  mostDetailed,
1076
1120
  );
1121
+ return pickResult ? [pickResult] : undefined;
1077
1122
  };
1078
- return drillPick(limit, pickCallback);
1123
+ return drillPick(pickCallback, limit);
1079
1124
  }
1080
1125
 
1081
1126
  function pickFromRay(
@@ -1087,7 +1132,8 @@ function pickFromRay(
1087
1132
  requirePosition,
1088
1133
  mostDetailed,
1089
1134
  ) {
1090
- const results = getRayIntersections(
1135
+ // Use drillPickFromRay rather than getRayIntersection directly to select the first non-excluded object
1136
+ const results = drillPickFromRay(
1091
1137
  picking,
1092
1138
  scene,
1093
1139
  ray,
@@ -1102,28 +1148,6 @@ function pickFromRay(
1102
1148
  }
1103
1149
  }
1104
1150
 
1105
- function drillPickFromRay(
1106
- picking,
1107
- scene,
1108
- ray,
1109
- limit,
1110
- objectsToExclude,
1111
- width,
1112
- requirePosition,
1113
- mostDetailed,
1114
- ) {
1115
- return getRayIntersections(
1116
- picking,
1117
- scene,
1118
- ray,
1119
- limit,
1120
- objectsToExclude,
1121
- width,
1122
- requirePosition,
1123
- mostDetailed,
1124
- );
1125
- }
1126
-
1127
1151
  function deferPromiseUntilPostRender(scene, promise) {
1128
1152
  // Resolve promise after scene's postRender in case entities are created when the promise resolves.
1129
1153
  // Entities can't be created between viewer._onTick and viewer._postRender.
@@ -1365,7 +1389,7 @@ function sampleHeightMostDetailed(
1365
1389
  * @param {Picking} picking
1366
1390
  * @param {Scene} scene
1367
1391
  * @param {Cartesian3} cartesian
1368
- * @param {Object[]} [objectsToExclude]
1392
+ * @param {object[]} [objectsToExclude]
1369
1393
  * @param {number} [width]
1370
1394
  * @param {Cartesian3} [result]
1371
1395
  * @returns {Promise<Cartesian3 | undefined>}
@@ -1519,7 +1543,7 @@ Picking.prototype.sampleHeightMostDetailed = function (
1519
1543
  * @private
1520
1544
  * @param {Scene} scene
1521
1545
  * @param {Cartesian3[]} cartesians
1522
- * @param {Object[]} [objectsToExclude]
1546
+ * @param {object[]} [objectsToExclude]
1523
1547
  * @param {number} [width]
1524
1548
  * @returns {Promise<Array<Cartesian3 | undefined>>}
1525
1549
  */
@@ -90,7 +90,6 @@ function QuadtreePrimitive(options) {
90
90
  this._removeHeightCallbacks = [];
91
91
 
92
92
  this._tileToUpdateHeights = [];
93
- this._lastTileIndex = 0;
94
93
  this._updateHeightsTimeSlice = 2.0;
95
94
 
96
95
  // If a culled tile contains _cameraPositionCartographic or _cameraReferenceFrameOriginCartographic, it will be marked
@@ -217,10 +216,8 @@ function invalidateAllTiles(primitive) {
217
216
  for (let i = 0; i < levelZeroTiles.length; ++i) {
218
217
  const tile = levelZeroTiles[i];
219
218
  const customData = tile.customData;
220
- const customDataLength = customData.length;
221
219
 
222
- for (let j = 0; j < customDataLength; ++j) {
223
- const data = customData[j];
220
+ for (const data of customData) {
224
221
  data.level = 0;
225
222
  primitive._addHeightCallbacks.push(data);
226
223
  }
@@ -513,7 +510,6 @@ function selectTilesForRendering(primitive, frameState) {
513
510
  tilesToRender.length = 0;
514
511
 
515
512
  // We can't render anything before the level zero tiles exist.
516
- let i;
517
513
  const tileProvider = primitive._tileProvider;
518
514
  if (!defined(primitive._levelZeroTiles)) {
519
515
  const tilingScheme = tileProvider.tilingScheme;
@@ -524,7 +520,7 @@ function selectTilesForRendering(primitive, frameState) {
524
520
  const numberOfRootTiles = primitive._levelZeroTiles.length;
525
521
  if (rootTraversalDetails.length < numberOfRootTiles) {
526
522
  rootTraversalDetails = new Array(numberOfRootTiles);
527
- for (i = 0; i < numberOfRootTiles; ++i) {
523
+ for (let i = 0; i < numberOfRootTiles; ++i) {
528
524
  if (rootTraversalDetails[i] === undefined) {
529
525
  rootTraversalDetails[i] = new TraversalDetails();
530
526
  }
@@ -537,7 +533,6 @@ function selectTilesForRendering(primitive, frameState) {
537
533
 
538
534
  primitive._occluders.ellipsoid.cameraPosition = frameState.camera.positionWC;
539
535
 
540
- let tile;
541
536
  const levelZeroTiles = primitive._levelZeroTiles;
542
537
  const occluders =
543
538
  levelZeroTiles.length > 1 ? primitive._occluders : undefined;
@@ -550,18 +545,28 @@ function selectTilesForRendering(primitive, frameState) {
550
545
 
551
546
  const customDataAdded = primitive._addHeightCallbacks;
552
547
  const customDataRemoved = primitive._removeHeightCallbacks;
553
- const frameNumber = frameState.frameNumber;
554
548
 
555
- let len;
556
- if (customDataAdded.length > 0 || customDataRemoved.length > 0) {
557
- for (i = 0, len = levelZeroTiles.length; i < len; ++i) {
558
- tile = levelZeroTiles[i];
559
- tile._updateCustomData(frameNumber, customDataAdded, customDataRemoved);
549
+ customDataAdded.forEach((data) => {
550
+ const tile = levelZeroTiles.find((tile) =>
551
+ Rectangle.contains(tile.rectangle, data.positionCartographic),
552
+ );
553
+ if (tile) {
554
+ tile._addedCustomData.push(data);
560
555
  }
556
+ });
561
557
 
562
- customDataAdded.length = 0;
563
- customDataRemoved.length = 0;
564
- }
558
+ customDataRemoved.forEach((data) => {
559
+ const tile = levelZeroTiles.find((tile) =>
560
+ Rectangle.contains(tile.rectangle, data.positionCartographic),
561
+ );
562
+ if (tile) {
563
+ tile._removedCustomData.push(data);
564
+ }
565
+ });
566
+
567
+ levelZeroTiles.forEach((tile) => tile.updateCustomData());
568
+ customDataAdded.length = 0;
569
+ customDataRemoved.length = 0;
565
570
 
566
571
  const camera = frameState.camera;
567
572
 
@@ -577,8 +582,8 @@ function selectTilesForRendering(primitive, frameState) {
577
582
  );
578
583
 
579
584
  // Traverse in depth-first, near-to-far order.
580
- for (i = 0, len = levelZeroTiles.length; i < len; ++i) {
581
- tile = levelZeroTiles[i];
585
+ for (let i = 0; i < levelZeroTiles.length; ++i) {
586
+ const tile = levelZeroTiles[i];
582
587
  primitive._tileReplacementQueue.markTileRendered(tile);
583
588
  if (!tile.renderable) {
584
589
  queueTileLoad(primitive, primitive._tileLoadQueueHigh, tile, frameState);
@@ -596,7 +601,7 @@ function selectTilesForRendering(primitive, frameState) {
596
601
  }
597
602
  }
598
603
 
599
- primitive._lastSelectionFrameNumber = frameNumber;
604
+ primitive._lastSelectionFrameNumber = frameState.frameNumber;
600
605
  }
601
606
 
602
607
  function queueTileLoad(primitive, queue, tile, frameState) {
@@ -716,7 +721,7 @@ function visitTile(
716
721
  ++debug.tilesVisited;
717
722
 
718
723
  primitive._tileReplacementQueue.markTileRendered(tile);
719
- tile._updateCustomData(frameState.frameNumber);
724
+ tile.updateCustomData();
720
725
 
721
726
  if (tile.level > debug.maxDepthVisited) {
722
727
  debug.maxDepthVisited = tile.level;
@@ -1417,15 +1422,18 @@ function updateHeights(primitive, frameState) {
1417
1422
  // Ensure stale position cache is cleared
1418
1423
  tile.clearPositionCache();
1419
1424
  tilesToUpdateHeights.shift();
1420
- primitive._lastTileIndex = 0;
1421
1425
  continue;
1422
1426
  }
1423
1427
  const customData = tile.customData;
1424
- const customDataLength = customData.length;
1428
+ if (!defined(tile._customDataIterator)) {
1429
+ tile._customDataIterator = customData.values();
1430
+ }
1431
+ const customDataIterator = tile._customDataIterator;
1425
1432
 
1426
1433
  let timeSliceMax = false;
1427
- for (i = primitive._lastTileIndex; i < customDataLength; ++i) {
1428
- const data = customData[i];
1434
+ let nextData;
1435
+ while (!(nextData = customDataIterator.next()).done) {
1436
+ const data = nextData.value;
1429
1437
 
1430
1438
  // No need to run this code when the tile is upsampled, because the height will be the same as its parent.
1431
1439
  const terrainData = tile.data.terrainData;
@@ -1543,10 +1551,10 @@ function updateHeights(primitive, frameState) {
1543
1551
  }
1544
1552
 
1545
1553
  if (timeSliceMax) {
1546
- primitive._lastTileIndex = i;
1554
+ tile._customDataIterator = customDataIterator;
1547
1555
  break;
1548
1556
  } else {
1549
- primitive._lastTileIndex = 0;
1557
+ tile._customDataIterator = undefined;
1550
1558
  tilesToUpdateHeights.shift();
1551
1559
  }
1552
1560
  }
@@ -1,6 +1,7 @@
1
1
  import defined from "../Core/defined.js";
2
2
  import DeveloperError from "../Core/DeveloperError.js";
3
3
  import Rectangle from "../Core/Rectangle.js";
4
+ import Cartographic from "../Core/Cartographic.js";
4
5
  import QuadtreeTileLoadState from "./QuadtreeTileLoadState.js";
5
6
  import TileSelectionResult from "./TileSelectionResult.js";
6
7
 
@@ -107,8 +108,10 @@ function QuadtreeTile(options) {
107
108
  this._distance = 0.0;
108
109
  this._loadPriority = 0.0;
109
110
 
110
- this._customData = [];
111
- this._frameUpdated = undefined;
111
+ this._customData = new Set();
112
+ this._customDataIterator = undefined;
113
+ this._addedCustomData = [];
114
+ this._removedCustomData = [];
112
115
  this._lastSelectionResult = TileSelectionResult.NONE;
113
116
  this._lastSelectionResultFrame = undefined;
114
117
  this._loadedCallbacks = {};
@@ -265,7 +268,7 @@ QuadtreeTile.prototype._getCacheKey = function (
265
268
  * @param {number} maximumScreenSpaceError The maximum screen-space error, in pixels, that is allowed.
266
269
  * A higher maximum error will render fewer tiles and improve performance, while a lower
267
270
  * value will improve visual quality.
268
- * @returns {Object|undefined} The cached position data or undefined if not found.
271
+ * @returns {object|undefined} The cached position data or undefined if not found.
269
272
  */
270
273
  QuadtreeTile.prototype.getPositionCacheEntry = function (
271
274
  cartographic,
@@ -285,7 +288,7 @@ QuadtreeTile.prototype.getPositionCacheEntry = function (
285
288
  * @param {number} maximumScreenSpaceError The maximum screen-space error, in pixels, that is allowed.
286
289
  * A higher maximum error will render fewer tiles and improve performance, while a lower
287
290
  * value will improve visual quality.
288
- * @param {Object} value - The object to be cached.
291
+ * @param {object} value - The object to be cached.
289
292
  */
290
293
  QuadtreeTile.prototype.setPositionCacheEntry = function (
291
294
  cartographic,
@@ -311,52 +314,69 @@ QuadtreeTile.prototype.clearPositionCache = function () {
311
314
  }
312
315
  };
313
316
 
314
- QuadtreeTile.prototype._updateCustomData = function (
315
- frameNumber,
316
- added,
317
- removed,
318
- ) {
319
- let customData = this.customData;
320
-
321
- let i;
322
- let data;
323
- let rectangle;
324
-
325
- if (defined(added) && defined(removed)) {
326
- customData = customData.filter(function (value) {
327
- return removed.indexOf(value) === -1;
328
- });
329
- this._customData = customData;
330
-
331
- rectangle = this._rectangle;
332
- for (i = 0; i < added.length; ++i) {
333
- data = added[i];
334
- if (Rectangle.contains(rectangle, data.positionCartographic)) {
335
- customData.push(data);
336
- }
337
- }
317
+ QuadtreeTile.prototype.updateCustomData = function () {
318
+ const added = this._addedCustomData;
319
+ const removed = this._removedCustomData;
320
+ if (added.length === 0 && removed.length === 0) {
321
+ return;
322
+ }
338
323
 
339
- this._frameUpdated = frameNumber;
340
- } else {
341
- // interior or leaf tile, update from parent
342
- const parent = this._parent;
343
- if (defined(parent) && this._frameUpdated !== parent._frameUpdated) {
344
- customData.length = 0;
345
-
346
- rectangle = this._rectangle;
347
- const parentCustomData = parent.customData;
348
- for (i = 0; i < parentCustomData.length; ++i) {
349
- data = parentCustomData[i];
350
- if (Rectangle.contains(rectangle, data.positionCartographic)) {
351
- customData.push(data);
352
- }
353
- }
324
+ const customData = this.customData;
325
+ for (let i = 0; i < added.length; ++i) {
326
+ const data = added[i];
327
+ customData.add(data);
328
+
329
+ const child = childTileAtPosition(this, data.positionCartographic);
330
+ child._addedCustomData.push(data);
331
+ }
332
+ this._addedCustomData.length = 0;
354
333
 
355
- this._frameUpdated = parent._frameUpdated;
334
+ for (let i = 0; i < removed.length; ++i) {
335
+ const data = removed[i];
336
+ if (customData.has(data)) {
337
+ customData.delete(data);
356
338
  }
339
+
340
+ const child = childTileAtPosition(this, data.positionCartographic);
341
+ child._removedCustomData.push(data);
357
342
  }
343
+ this._removedCustomData.length = 0;
358
344
  };
359
345
 
346
+ const splitPointScratch = new Cartographic();
347
+
348
+ /**
349
+ * Determines which child tile that contains the specified position. Assumes the position is within
350
+ * the bounds of the parent tile.
351
+ * @private
352
+ * @param {QuadtreeTile} tile - The parent tile.
353
+ * @param {Cartographic} positionCartographic - The cartographic position.
354
+ * @returns {QuadtreeTile} The child tile that contains the position.
355
+ */
356
+ function childTileAtPosition(tile, positionCartographic) {
357
+ // Can't assume that a given tiling scheme divides a parent into four tiles at its rectangle's center.
358
+ // But we can safely take any child tile's rectangle and take its center-facing corner as the parent's split point.
359
+ const nwChildRectangle = tile.northwestChild.rectangle;
360
+ const tileSplitPoint = Rectangle.southeast(
361
+ nwChildRectangle,
362
+ splitPointScratch,
363
+ );
364
+
365
+ const x = positionCartographic.longitude >= tileSplitPoint.longitude ? 1 : 0;
366
+ const y = positionCartographic.latitude < tileSplitPoint.latitude ? 1 : 0;
367
+
368
+ switch (y * 2 + x) {
369
+ case 0:
370
+ return tile.northwestChild;
371
+ case 1:
372
+ return tile.northeastChild;
373
+ case 2:
374
+ return tile.southwestChild;
375
+ default:
376
+ return tile.southeastChild;
377
+ }
378
+ }
379
+
360
380
  Object.defineProperties(QuadtreeTile.prototype, {
361
381
  /**
362
382
  * Gets the tiling scheme used to tile the surface.
@@ -522,9 +542,9 @@ Object.defineProperties(QuadtreeTile.prototype, {
522
542
  },
523
543
 
524
544
  /**
525
- * An array of objects associated with this tile.
545
+ * A set of objects associated with this tile.
526
546
  * @memberof QuadtreeTile.prototype
527
- * @type {Array}
547
+ * @type {Set}
528
548
  */
529
549
  customData: {
530
550
  get: function () {
@@ -31,7 +31,7 @@ const ResourceLoaderState = {
31
31
  /**
32
32
  * The resource is processing. GPU resources are allocated in this state as needed.
33
33
  *
34
- * @type {Number}
34
+ * @type {number}
35
35
  * @constant
36
36
  * @private
37
37
  */