@cesium/engine 22.0.0 → 22.2.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 (152) hide show
  1. package/Build/ThirdParty/Workers/zip-web-worker.js +10 -7
  2. package/Build/Workers/{chunk-AARZSH4V.js → chunk-2JNPWPLE.js} +8 -6
  3. package/Build/Workers/{chunk-M7HRE4QR.js → chunk-2YVTOY5Z.js} +15 -11
  4. package/Build/Workers/{chunk-QSMIHPUM.js → chunk-35J4D6PX.js} +3 -3
  5. package/Build/Workers/{chunk-XQ347YWU.js → chunk-3HUEBDFC.js} +16 -14
  6. package/Build/Workers/chunk-3JB2X2PR.js +2058 -0
  7. package/Build/Workers/{chunk-N52ZRKUE.js → chunk-4I7BCCNU.js} +6 -6
  8. package/Build/Workers/{chunk-NE5JTQJP.js → chunk-4MCPC4TE.js} +10 -8
  9. package/Build/Workers/{chunk-SZN34LQ5.js → chunk-4ZQN7M7E.js} +10 -10
  10. package/Build/Workers/{chunk-AOM3FHBN.js → chunk-64PJ4MTB.js} +69 -7
  11. package/Build/Workers/{chunk-LEFQBK6H.js → chunk-72LZ3FN6.js} +14 -12
  12. package/Build/Workers/{chunk-3GL53OCU.js → chunk-7CDQUIP5.js} +276 -2277
  13. package/Build/Workers/{chunk-ECHAJNQJ.js → chunk-7MGTX4WP.js} +12 -12
  14. package/Build/Workers/{chunk-5B7VZQZY.js → chunk-7OPRTZBT.js} +9 -7
  15. package/Build/Workers/{chunk-A4DPJIWS.js → chunk-A3NUMZBG.js} +8 -6
  16. package/Build/Workers/{chunk-FA3SCJDX.js → chunk-AMWXJ5A7.js} +2 -2
  17. package/Build/Workers/{chunk-NGKF5NTR.js → chunk-BKYJBTHW.js} +13 -5
  18. package/Build/Workers/{chunk-QCMRUVVF.js → chunk-C35SJ4QP.js} +15 -13
  19. package/Build/Workers/{chunk-LWJXCI3F.js → chunk-C6FTHSJA.js} +8 -6
  20. package/Build/Workers/{chunk-2D3GLFZD.js → chunk-CQCEPC6N.js} +15 -13
  21. package/Build/Workers/{chunk-KGLDJRSO.js → chunk-DCR62BCO.js} +19 -13
  22. package/Build/Workers/{chunk-KUB64XW6.js → chunk-DIJ7IG5D.js} +12 -10
  23. package/Build/Workers/{chunk-NHZNMTIR.js → chunk-ED4UXMYY.js} +5 -5
  24. package/Build/Workers/{chunk-JZFU2LEM.js → chunk-FM5XPC2E.js} +4 -4
  25. package/Build/Workers/chunk-FPRM6PCE.js +1460 -0
  26. package/Build/Workers/{chunk-34YXP222.js → chunk-G6WQA27G.js} +5 -5
  27. package/Build/Workers/{chunk-5ZF53EY6.js → chunk-GMHDOQPH.js} +4 -4
  28. package/Build/Workers/{chunk-MXHRZHDF.js → chunk-I45CATZK.js} +16 -36
  29. package/Build/Workers/{chunk-OUBBMEWX.js → chunk-I4D5IP46.js} +9 -7
  30. package/Build/Workers/{chunk-A6JAFSZT.js → chunk-IVN5HSOI.js} +8 -6
  31. package/Build/Workers/{chunk-RCCYW6E7.js → chunk-IWOSJVFQ.js} +19 -15
  32. package/Build/Workers/{chunk-JDJAPBZP.js → chunk-JERDRSEI.js} +1 -1
  33. package/Build/Workers/{chunk-H7B7FU2U.js → chunk-JFN2DQHY.js} +5 -5
  34. package/Build/Workers/chunk-JONWM4IO.js +55 -0
  35. package/Build/Workers/{chunk-EJO3NKMS.js → chunk-JUOSYFXT.js} +1 -1
  36. package/Build/Workers/{chunk-726NINF5.js → chunk-K64RQCRK.js} +20 -18
  37. package/Build/Workers/{chunk-L7U26FFD.js → chunk-K6BXEBAF.js} +20 -18
  38. package/Build/Workers/{chunk-YLXWC7OW.js → chunk-L2FSBEW2.js} +7 -5
  39. package/Build/Workers/{chunk-OE22564R.js → chunk-LDSQMLRC.js} +3 -3
  40. package/Build/Workers/{chunk-U7CX3HHE.js → chunk-MSTAVM2N.js} +15 -11
  41. package/Build/Workers/{chunk-IGX772ZQ.js → chunk-MWGB6DLR.js} +1 -1
  42. package/Build/Workers/{chunk-5T5SY63I.js → chunk-N5MNKWED.js} +2 -2
  43. package/Build/Workers/{chunk-XPVZWY4A.js → chunk-NY3CWLIZ.js} +12 -8
  44. package/Build/Workers/{chunk-XZO6F23E.js → chunk-O3GWUTWM.js} +1 -1
  45. package/Build/Workers/{chunk-VCVA7BMD.js → chunk-P7ISUYLW.js} +4 -4
  46. package/Build/Workers/{chunk-U4XMLGSR.js → chunk-PMDPP22G.js} +7 -7
  47. package/Build/Workers/{chunk-P2H75UV5.js → chunk-PSHZAHFE.js} +16 -11
  48. package/Build/Workers/{chunk-YLILBDWK.js → chunk-QO6Z5UJE.js} +2 -2
  49. package/Build/Workers/{chunk-EZ7NJXQN.js → chunk-SDUH3N6G.js} +4 -4
  50. package/Build/Workers/{chunk-GYRDA3XK.js → chunk-UBJYWGMV.js} +20 -16
  51. package/Build/Workers/{chunk-7XEJGXX2.js → chunk-V26Y7ZQL.js} +886 -50
  52. package/Build/Workers/{chunk-6HBKE43B.js → chunk-VGH2CSC7.js} +13 -9
  53. package/Build/Workers/{chunk-75HAJIDT.js → chunk-VSZ5DB2W.js} +1 -1
  54. package/Build/Workers/{chunk-W4PIP5PG.js → chunk-WH4HDRGN.js} +2 -2
  55. package/Build/Workers/{chunk-VVZ667H6.js → chunk-XPNY2VY3.js} +2 -2
  56. package/Build/Workers/{chunk-7KAXDKRU.js → chunk-YFEZPDAY.js} +13 -11
  57. package/Build/Workers/{chunk-RQRODXVN.js → chunk-ZGWX2R5I.js} +5 -1424
  58. package/Build/Workers/{chunk-BJSNGGBM.js → chunk-ZUWF63QU.js} +4 -4
  59. package/Build/Workers/combineGeometry.js +24 -21
  60. package/Build/Workers/createBoxGeometry.js +18 -15
  61. package/Build/Workers/createBoxOutlineGeometry.js +16 -13
  62. package/Build/Workers/createCircleGeometry.js +28 -24
  63. package/Build/Workers/createCircleOutlineGeometry.js +21 -17
  64. package/Build/Workers/createCoplanarPolygonGeometry.js +35 -31
  65. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +33 -29
  66. package/Build/Workers/createCorridorGeometry.js +32 -28
  67. package/Build/Workers/createCorridorOutlineGeometry.js +30 -26
  68. package/Build/Workers/createCylinderGeometry.js +20 -17
  69. package/Build/Workers/createCylinderOutlineGeometry.js +20 -16
  70. package/Build/Workers/createEllipseGeometry.js +28 -24
  71. package/Build/Workers/createEllipseOutlineGeometry.js +21 -17
  72. package/Build/Workers/createEllipsoidGeometry.js +19 -16
  73. package/Build/Workers/createEllipsoidOutlineGeometry.js +18 -15
  74. package/Build/Workers/createFrustumGeometry.js +18 -15
  75. package/Build/Workers/createFrustumOutlineGeometry.js +18 -15
  76. package/Build/Workers/createGeometry.js +25 -21
  77. package/Build/Workers/createGroundPolylineGeometry.js +25 -21
  78. package/Build/Workers/createPlaneGeometry.js +16 -13
  79. package/Build/Workers/createPlaneOutlineGeometry.js +15 -12
  80. package/Build/Workers/createPolygonGeometry.js +35 -31
  81. package/Build/Workers/createPolygonOutlineGeometry.js +32 -28
  82. package/Build/Workers/createPolylineGeometry.js +27 -23
  83. package/Build/Workers/createPolylineVolumeGeometry.js +33 -29
  84. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +29 -25
  85. package/Build/Workers/createRectangleGeometry.js +30 -26
  86. package/Build/Workers/createRectangleOutlineGeometry.js +23 -19
  87. package/Build/Workers/createSimplePolylineGeometry.js +25 -21
  88. package/Build/Workers/createSphereGeometry.js +19 -16
  89. package/Build/Workers/createSphereOutlineGeometry.js +18 -15
  90. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  91. package/Build/Workers/createVectorTileClampedPolylines.js +16 -13
  92. package/Build/Workers/createVectorTileGeometries.js +24 -21
  93. package/Build/Workers/createVectorTilePoints.js +15 -12
  94. package/Build/Workers/createVectorTilePolygons.js +24 -20
  95. package/Build/Workers/createVectorTilePolylines.js +16 -13
  96. package/Build/Workers/createVerticesFromCesium3DTilesTerrain.js +25 -22
  97. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +26 -21
  98. package/Build/Workers/createVerticesFromHeightmap.js +26 -21
  99. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +24 -19
  100. package/Build/Workers/createWallGeometry.js +26 -22
  101. package/Build/Workers/createWallOutlineGeometry.js +25 -21
  102. package/Build/Workers/decodeDraco.js +10 -10
  103. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  104. package/Build/Workers/decodeI3S.js +13 -11
  105. package/Build/Workers/gaussianSplatSorter.js +4 -4
  106. package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
  107. package/Build/Workers/incrementallyBuildTerrainPicker.js +121 -0
  108. package/Build/Workers/transcodeKTX2.js +6 -6
  109. package/Build/Workers/transferTypedArrayTest.js +1 -1
  110. package/Build/Workers/upsampleQuantizedTerrainMesh.js +24 -20
  111. package/Build/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +25 -22
  112. package/Source/Core/AxisAlignedBoundingBox.js +36 -0
  113. package/Source/Core/Cesium3DTilesTerrainData.js +2 -0
  114. package/Source/Core/Cesium3DTilesTerrainGeometryProcessor.js +2 -0
  115. package/Source/Core/GoogleEarthEnterpriseTerrainData.js +1 -0
  116. package/Source/Core/HeightmapTerrainData.js +2 -0
  117. package/Source/Core/IntersectionTests.js +80 -0
  118. package/Source/Core/Ion.js +1 -1
  119. package/Source/Core/QuantizedMeshTerrainData.js +1 -0
  120. package/Source/Core/TerrainMesh.js +207 -0
  121. package/Source/Core/TerrainPicker.js +607 -0
  122. package/Source/Core/TexturePacker.js +27 -12
  123. package/Source/Core/Transforms.js +28 -19
  124. package/Source/DataSources/BillboardGraphics.js +1 -1
  125. package/Source/DataSources/BillboardVisualizer.js +7 -4
  126. package/Source/Renderer/Buffer.js +32 -0
  127. package/Source/Renderer/BufferUsage.js +3 -1
  128. package/Source/Renderer/Context.js +85 -7
  129. package/Source/Renderer/Sync.js +104 -0
  130. package/Source/Renderer/TextureAtlas.js +75 -44
  131. package/Source/Scene/ArcGisMapService.js +1 -1
  132. package/Source/Scene/Azure2DImageryProvider.js +103 -20
  133. package/Source/Scene/Billboard.js +75 -28
  134. package/Source/Scene/BillboardCollection.js +21 -2
  135. package/Source/Scene/BillboardTexture.js +56 -7
  136. package/Source/Scene/Globe.js +3 -1
  137. package/Source/Scene/GlobeSurfaceTile.js +18 -66
  138. package/Source/Scene/GlobeSurfaceTileProvider.js +11 -0
  139. package/Source/Scene/Google2DImageryProvider.js +10 -15
  140. package/Source/Scene/LabelCollection.js +1 -0
  141. package/Source/Scene/PickFramebuffer.js +124 -36
  142. package/Source/Scene/Picking.js +99 -17
  143. package/Source/Scene/Scene.js +36 -4
  144. package/Source/Scene/TerrainFillMesh.js +1 -0
  145. package/Source/Shaders/BillboardCollectionFS.glsl +22 -9
  146. package/Source/Shaders/BillboardCollectionFS.js +22 -9
  147. package/Source/ThirdParty/Workers/zip-web-worker.js +1 -1
  148. package/Source/ThirdParty/zip-module.wasm +0 -0
  149. package/Source/Workers/incrementallyBuildTerrainPicker.js +108 -0
  150. package/index.d.ts +204 -4
  151. package/index.js +65 -63
  152. package/package.json +4 -4
@@ -101,6 +101,8 @@ function Google2DImageryProvider(options) {
101
101
  key: encodeURIComponent(options.key),
102
102
  });
103
103
 
104
+ this._resource = resource.clone();
105
+
104
106
  let credit;
105
107
  if (defined(options.credit)) {
106
108
  credit = options.credit;
@@ -312,7 +314,7 @@ Object.defineProperties(Google2DImageryProvider.prototype, {
312
314
  * });
313
315
  * @example
314
316
  * // Google 2D roadmap overlay with custom styles
315
- * const googleTileProvider = Cesium.Google2DImageryProvider.fromIonAssetId({
317
+ * const googleTilesProvider = Cesium.Google2DImageryProvider.fromIonAssetId({
316
318
  * assetId: 3830184,
317
319
  * overlayLayerType: "layerRoadmap",
318
320
  * styles: [
@@ -403,7 +405,7 @@ Google2DImageryProvider.fromIonAssetId = async function (options) {
403
405
  * // Google 2D roadmap overlay with custom styles
404
406
  * Cesium.GoogleMaps.defaultApiKey = "your-api-key";
405
407
  *
406
- * const googleTileProvider = Cesium.Google2DImageryProvider.fromUrl({
408
+ * const googleTilesProvider = Cesium.Google2DImageryProvider.fromUrl({
407
409
  * overlayLayerType: "layerRoadmap",
408
410
  * styles: [
409
411
  * {
@@ -492,7 +494,7 @@ Google2DImageryProvider.prototype.requestImage = function (
492
494
  }
493
495
 
494
496
  // Asynchronously request and populate _attributionsByLevel if it hasn't been already. We do this here so that the promise can be properly awaited.
495
- if (promise && !defined(this._attributionsByLevel)) {
497
+ if (!defined(this._attributionsByLevel)) {
496
498
  return Promise.all([promise, this.getViewportCredits()]).then(
497
499
  (results) => results[0],
498
500
  );
@@ -533,12 +535,7 @@ Google2DImageryProvider.prototype.getViewportCredits = async function () {
533
535
  const promises = [];
534
536
  for (let level = 0; level < maximumLevel + 1; level++) {
535
537
  promises.push(
536
- fetchViewportAttribution(
537
- this._viewportUrl,
538
- this._key,
539
- this._session,
540
- level,
541
- ),
538
+ fetchViewportAttribution(this._resource, this._viewportUrl, level),
542
539
  );
543
540
  }
544
541
  const results = await Promise.all(promises);
@@ -559,12 +556,10 @@ Google2DImageryProvider.prototype.getViewportCredits = async function () {
559
556
  return attributionsByLevel;
560
557
  };
561
558
 
562
- async function fetchViewportAttribution(url, key, session, level) {
563
- const viewport = await Resource.fetch({
564
- url: url,
559
+ async function fetchViewportAttribution(resource, url, level) {
560
+ const viewportResource = resource.getDerivedResource({
561
+ url,
565
562
  queryParameters: {
566
- key,
567
- session,
568
563
  zoom: level,
569
564
  north: 90,
570
565
  south: -90,
@@ -573,7 +568,7 @@ async function fetchViewportAttribution(url, key, session, level) {
573
568
  },
574
569
  data: JSON.stringify(Frozen.EMPTY_OBJECT),
575
570
  });
576
- const viewportJson = JSON.parse(viewport);
571
+ const viewportJson = await viewportResource.fetchJson();
577
572
  return viewportJson.copyright;
578
573
  }
579
574
 
@@ -118,6 +118,7 @@ function unbindGlyphBillboard(labelCollection, glyph) {
118
118
  const billboard = glyph.billboard;
119
119
  if (defined(billboard)) {
120
120
  billboard.show = false;
121
+ billboard._clampedPosition = undefined;
121
122
  if (defined(billboard._removeCallbackFunc)) {
122
123
  billboard._removeCallbackFunc();
123
124
  billboard._removeCallbackFunc = undefined;
@@ -4,6 +4,10 @@ import defined from "../Core/defined.js";
4
4
  import destroyObject from "../Core/destroyObject.js";
5
5
  import FramebufferManager from "../Renderer/FramebufferManager.js";
6
6
  import PassState from "../Renderer/PassState.js";
7
+ import PixelDatatype from "../Renderer/PixelDatatype.js";
8
+ import PixelFormat from "../Core/PixelFormat.js";
9
+ import Sync from "../Renderer/Sync.js";
10
+ import RuntimeError from "../Core/RuntimeError.js";
7
11
 
8
12
  /**
9
13
  * @private
@@ -27,47 +31,18 @@ function PickFramebuffer(context) {
27
31
  this._height = 0;
28
32
  }
29
33
 
30
- PickFramebuffer.prototype.begin = function (screenSpaceRectangle, viewport) {
31
- const context = this._context;
32
- const { width, height } = viewport;
33
-
34
- BoundingRectangle.clone(
35
- screenSpaceRectangle,
36
- this._passState.scissorTest.rectangle,
37
- );
38
-
39
- // Create or recreate renderbuffers and framebuffer used for picking
40
- this._width = width;
41
- this._height = height;
42
- this._fb.update(context, width, height);
43
- this._passState.framebuffer = this._fb.framebuffer;
44
-
45
- this._passState.viewport.width = width;
46
- this._passState.viewport.height = height;
47
-
48
- return this._passState;
49
- };
50
-
51
34
  /**
52
- * Return the picked objects rendered within a given rectangle.
35
+ * Return the picked object(s) rendered within a given rectangle.
53
36
  *
54
- * @param {BoundingRectangle} screenSpaceRectangle
37
+ * @private
38
+ * @param {object} context The active context.
39
+ * @param {Uint8Array|Uint16Array|Float32Array|Uint32Array} pixels The pixels in the specified rectangle.
40
+ * @param {number} width The rectangle width.
41
+ * @param {number} height The rectangle height.
55
42
  * @param {number} [limit=1] If supplied, stop iterating after collecting this many objects.
56
43
  * @returns {object[]} A list of rendered objects, ordered by distance to the middle of the rectangle.
57
44
  */
58
- PickFramebuffer.prototype.end = function (screenSpaceRectangle, limit = 1) {
59
- const width = screenSpaceRectangle.width ?? 1.0;
60
- const height = screenSpaceRectangle.height ?? 1.0;
61
-
62
- const context = this._context;
63
- const pixels = context.readPixels({
64
- x: screenSpaceRectangle.x,
65
- y: screenSpaceRectangle.y,
66
- width: width,
67
- height: height,
68
- framebuffer: this._fb.framebuffer,
69
- });
70
-
45
+ function pickObjectsFromPixels(context, pixels, width, height, limit = 1) {
71
46
  const max = Math.max(width, height);
72
47
  const length = max * max;
73
48
  const halfWidth = Math.floor(width * 0.5);
@@ -121,6 +96,119 @@ PickFramebuffer.prototype.end = function (screenSpaceRectangle, limit = 1) {
121
96
  y += dy;
122
97
  }
123
98
  return [...objects];
99
+ }
100
+
101
+ PickFramebuffer.prototype.begin = function (screenSpaceRectangle, viewport) {
102
+ const context = this._context;
103
+ const { width, height } = viewport;
104
+
105
+ BoundingRectangle.clone(
106
+ screenSpaceRectangle,
107
+ this._passState.scissorTest.rectangle,
108
+ );
109
+
110
+ // Create or recreate renderbuffers and framebuffer used for picking
111
+ this._width = width;
112
+ this._height = height;
113
+ this._fb.update(context, width, height);
114
+ this._passState.framebuffer = this._fb.framebuffer;
115
+
116
+ this._passState.viewport.width = width;
117
+ this._passState.viewport.height = height;
118
+
119
+ return this._passState;
120
+ };
121
+
122
+ /**
123
+ * Return the picked objects rendered within a given rectangle using asynchronously without stalling the GPU.
124
+ * Requires WebGL2.
125
+ *
126
+ * @param {BoundingRectangle} screenSpaceRectangle
127
+ * @param {FrameState} frameState
128
+ * @param {number} [limit=1] If supplied, stop iterating after collecting this many objects.
129
+ * @returns {Promise<object[]>} A list of rendered objects, ordered by distance to the middle of the rectangle.
130
+ *
131
+ * @exception {RuntimeError} Async Picking Request Timeout.
132
+ * @exception {DeveloperError} A WebGL 2 context is required.
133
+ */
134
+ PickFramebuffer.prototype.endAsync = async function (
135
+ screenSpaceRectangle,
136
+ frameState,
137
+ limit = 1,
138
+ ) {
139
+ const width = screenSpaceRectangle.width ?? 1.0;
140
+ const height = screenSpaceRectangle.height ?? 1.0;
141
+
142
+ const context = this._context;
143
+ const framebuffer = this._fb.framebuffer;
144
+
145
+ let pixelDatatype = PixelDatatype.UNSIGNED_BYTE;
146
+ let pixelFormat = PixelFormat.RGBA;
147
+
148
+ if (defined(framebuffer) && framebuffer.numberOfColorAttachments > 0) {
149
+ pixelDatatype = framebuffer.getColorTexture(0).pixelDatatype;
150
+ pixelFormat = framebuffer.getColorTexture(0).pixelFormat;
151
+ }
152
+
153
+ const pbo = context.readPixelsToPBO({
154
+ x: screenSpaceRectangle.x,
155
+ y: screenSpaceRectangle.y,
156
+ width: width,
157
+ height: height,
158
+ framebuffer: framebuffer,
159
+ });
160
+
161
+ const sync = Sync.create({
162
+ context: context,
163
+ });
164
+
165
+ // Wait for the GPU to signal that it is ready to readback the PBO data
166
+ try {
167
+ await sync.waitForSignal((next) => frameState.afterRender.push(next));
168
+ const pixels = PixelFormat.createTypedArray(
169
+ pixelFormat,
170
+ pixelDatatype,
171
+ width,
172
+ height,
173
+ );
174
+ pbo.getBufferData(pixels);
175
+ const pickedObjects = pickObjectsFromPixels(
176
+ context,
177
+ pixels,
178
+ width,
179
+ height,
180
+ limit,
181
+ );
182
+ return pickedObjects;
183
+ } catch (e) {
184
+ throw new RuntimeError("Async Picking Request Timeout");
185
+ } finally {
186
+ sync.destroy();
187
+ pbo.destroy();
188
+ }
189
+ };
190
+
191
+ /**
192
+ * Return the picked objects rendered within a given rectangle.
193
+ *
194
+ * @param {BoundingRectangle} screenSpaceRectangle
195
+ * @param {number} [limit=1] If supplied, stop iterating after collecting this many objects.
196
+ * @returns {object[]} A list of rendered objects, ordered by distance to the middle of the rectangle.
197
+ */
198
+ PickFramebuffer.prototype.end = function (screenSpaceRectangle, limit = 1) {
199
+ const width = screenSpaceRectangle.width ?? 1.0;
200
+ const height = screenSpaceRectangle.height ?? 1.0;
201
+
202
+ const context = this._context;
203
+ const pixels = context.readPixels({
204
+ x: screenSpaceRectangle.x,
205
+ y: screenSpaceRectangle.y,
206
+ width: width,
207
+ height: height,
208
+ framebuffer: this._fb.framebuffer,
209
+ });
210
+
211
+ return pickObjectsFromPixels(context, pixels, width, height, limit);
124
212
  };
125
213
 
126
214
  /**
@@ -8,6 +8,7 @@ import Color from "../Core/Color.js";
8
8
  import defined from "../Core/defined.js";
9
9
  import DeveloperError from "../Core/DeveloperError.js";
10
10
  import Matrix4 from "../Core/Matrix4.js";
11
+ import oneTimeWarning from "../Core/oneTimeWarning.js";
11
12
  import OrthographicFrustum from "../Core/OrthographicFrustum.js";
12
13
  import OrthographicOffCenterFrustum from "../Core/OrthographicOffCenterFrustum.js";
13
14
  import PerspectiveFrustum from "../Core/PerspectiveFrustum.js";
@@ -262,30 +263,21 @@ function computePickingDrawingBufferRectangle(
262
263
  }
263
264
 
264
265
  /**
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
- * <p>
269
- * When a feature of a 3D Tiles tileset is picked, <code>pick</code> returns a {@link Cesium3DTileFeature} object.
270
- * </p>
266
+ * Setup needed before picking.
267
+ *
271
268
  * @param {Scene} scene
272
269
  * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
270
+ * @param {BoundingRectangle} drawingBufferRectangle The output drawing buffer recangle.
273
271
  * @param {number} [width=3] Width of the pick rectangle.
274
272
  * @param {number} [height=3] Height of the pick rectangle.
275
- * @param {number} [limit=1] If supplied, stop iterating after collecting this many objects.
276
- * @returns {object[]} List of objects containing the picked primitives.
277
273
  */
278
- Picking.prototype.pick = function (
274
+ function pickBegin(
279
275
  scene,
280
276
  windowPosition,
277
+ drawingBufferRectangle,
281
278
  width,
282
279
  height,
283
- limit = 1,
284
280
  ) {
285
- //>>includeStart('debug', pragmas.debug);
286
- Check.defined("windowPosition", windowPosition);
287
- //>>includeEnd('debug');
288
-
289
281
  const { context, frameState, defaultView } = scene;
290
282
  const { viewport, pickFramebuffer } = defaultView;
291
283
 
@@ -304,12 +296,12 @@ Picking.prototype.pick = function (
304
296
  windowPosition,
305
297
  scratchPosition,
306
298
  );
307
- const drawingBufferRectangle = computePickingDrawingBufferRectangle(
299
+ computePickingDrawingBufferRectangle(
308
300
  context.drawingBufferHeight,
309
301
  drawingBufferPosition,
310
302
  width,
311
303
  height,
312
- scratchRectangle,
304
+ drawingBufferRectangle,
313
305
  );
314
306
 
315
307
  scene.jobScheduler.disableThisFrame();
@@ -334,9 +326,99 @@ Picking.prototype.pick = function (
334
326
 
335
327
  scene.updateAndExecuteCommands(passState, scratchColorZero);
336
328
  scene.resolveFramebuffers(passState);
329
+ }
337
330
 
338
- const pickedObjects = pickFramebuffer.end(drawingBufferRectangle, limit);
331
+ /**
332
+ * Teardown needed after picking.
333
+ *
334
+ * @param {Scene} scene
335
+ */
336
+ function pickEnd(scene) {
337
+ const { context } = scene;
339
338
  context.endFrame();
339
+ }
340
+
341
+ /**
342
+ * Same operation as {@link Picking#pick}, but returns a Promise that resolves asynchronously without blocking the main render thread.
343
+ * Requires WebGL2 else using synchronous fallback.
344
+ *
345
+ * @see Picking#pick
346
+ *
347
+ * @param {Scene} scene
348
+ * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
349
+ * @param {number} [width=3] Width of the pick rectangle.
350
+ * @param {number} [height=3] Height of the pick rectangle.
351
+ * @param {number} [limit=1] If supplied, stop iterating after collecting this many objects.
352
+ * @returns {Promise<object[]>} List of objects containing the picked primitives.
353
+ *
354
+ * @exception {RuntimeError} Async Picking Request Timeout.
355
+ */
356
+ Picking.prototype.pickAsync = async function (
357
+ scene,
358
+ windowPosition,
359
+ width,
360
+ height,
361
+ limit = 1,
362
+ ) {
363
+ //>>includeStart('debug', pragmas.debug);
364
+ Check.defined("windowPosition", windowPosition);
365
+ //>>includeEnd('debug');
366
+
367
+ const { context, frameState, defaultView } = scene;
368
+ const { pickFramebuffer } = defaultView;
369
+ const drawingBufferRectangle = scratchRectangle;
370
+ pickBegin(scene, windowPosition, drawingBufferRectangle, width, height);
371
+ let pickedObjects;
372
+ if (context.webgl2) {
373
+ pickedObjects = pickFramebuffer.endAsync(
374
+ drawingBufferRectangle,
375
+ frameState,
376
+ limit,
377
+ ); // Promise<Object[]>
378
+ } else {
379
+ pickedObjects = pickFramebuffer.end(drawingBufferRectangle, limit); // Object[]
380
+ pickedObjects = Promise.resolve(pickedObjects); // Promise<Object[]> Wrap as Promise
381
+ oneTimeWarning(
382
+ "picking-async-fallback",
383
+ "Fallback to synchronous picking because async operation requires WebGL2 context.",
384
+ );
385
+ }
386
+ pickEnd(scene);
387
+ return pickedObjects;
388
+ };
389
+
390
+ /**
391
+ * Returns a list of objects with a <code>primitive</code> property that contains the first (top) primitives
392
+ * in the scene at a particular window coordinate. Other properties may potentially be set depending on the
393
+ * type of primitive and may be used to further identify the picked object.
394
+ * <p>
395
+ * When a feature of a 3D Tiles tileset is picked, <code>pick</code> returns a {@link Cesium3DTileFeature} object.
396
+ * </p>
397
+ * @param {Scene} scene
398
+ * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
399
+ * @param {number} [width=3] Width of the pick rectangle.
400
+ * @param {number} [height=3] Height of the pick rectangle.
401
+ * @param {number} [limit=1] If supplied, stop iterating after collecting this many objects.
402
+ * @returns {object[]} List of objects containing the picked primitives.
403
+ *
404
+ */
405
+ Picking.prototype.pick = function (
406
+ scene,
407
+ windowPosition,
408
+ width,
409
+ height,
410
+ limit = 1,
411
+ ) {
412
+ //>>includeStart('debug', pragmas.debug);
413
+ Check.defined("windowPosition", windowPosition);
414
+ //>>includeEnd('debug');
415
+
416
+ const { defaultView } = scene;
417
+ const { pickFramebuffer } = defaultView;
418
+ const drawingBufferRectangle = scratchRectangle;
419
+ pickBegin(scene, windowPosition, drawingBufferRectangle, width, height);
420
+ const pickedObjects = pickFramebuffer.end(drawingBufferRectangle, limit); // Object[]
421
+ pickEnd(scene);
340
422
  return pickedObjects;
341
423
  };
342
424
 
@@ -3932,14 +3932,15 @@ function callAfterRenderFunctions(scene) {
3932
3932
  // Functions are queued up during primitive update and executed here in case
3933
3933
  // the function modifies scene state that should remain constant over the frame.
3934
3934
  const functions = scene._frameState.afterRender;
3935
- for (let i = 0; i < functions.length; ++i) {
3936
- const shouldRequestRender = functions[i]();
3935
+ const functionsCpy = functions.slice(); // Snapshot before iterate allows callbacks to add functions for next frame
3936
+ functions.length = 0;
3937
+
3938
+ for (let i = 0; i < functionsCpy.length; ++i) {
3939
+ const shouldRequestRender = functionsCpy[i]();
3937
3940
  if (shouldRequestRender) {
3938
3941
  scene.requestRender();
3939
3942
  }
3940
3943
  }
3941
-
3942
- functions.length = 0;
3943
3944
  }
3944
3945
 
3945
3946
  function getGlobeHeight(scene) {
@@ -4517,6 +4518,37 @@ Scene.prototype.pick = function (windowPosition, width, height) {
4517
4518
  return this._picking.pick(this, windowPosition, width, height, 1)[0];
4518
4519
  };
4519
4520
 
4521
+ /**
4522
+ * Performs the same operation as Scene.pick but asynchonosly without blocking the main render thread.
4523
+ * Requires WebGL2 else using fallback.
4524
+ *
4525
+ * @example
4526
+ * // On mouse over, color the feature yellow.
4527
+ * handler.setInputAction(function(movement) {
4528
+ * const feature = scene.pickAsync(movement.endPosition).then(function(feature) {
4529
+ * if (feature instanceof Cesium.Cesium3DTileFeature) {
4530
+ * feature.color = Cesium.Color.YELLOW;
4531
+ * }
4532
+ * });
4533
+ * }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
4534
+ *
4535
+ * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
4536
+ * @param {number} [width=3] Width of the pick rectangle.
4537
+ * @param {number} [height=3] Height of the pick rectangle.
4538
+ * @returns {Promise<Object | undefined>} Object containing the picked primitive or <code>undefined</code> if nothing is at the location.
4539
+ *
4540
+ * @see Scene#pick
4541
+ */
4542
+ Scene.prototype.pickAsync = async function (windowPosition, width, height) {
4543
+ const result = await this._picking.pickAsync(
4544
+ this,
4545
+ windowPosition,
4546
+ width,
4547
+ height,
4548
+ 1,
4549
+ );
4550
+ return result[0];
4551
+ };
4520
4552
  /**
4521
4553
  * Returns a {@link VoxelCell} for the voxel sample rendered at a particular window coordinate,
4522
4554
  * or <code>undefined</code> if no voxel is rendered at that position.
@@ -1274,6 +1274,7 @@ function createFillMesh(tileProvider, frameState, tile, vertexArraysToDestroy) {
1274
1274
  vertexCount,
1275
1275
  minimumHeight,
1276
1276
  maximumHeight,
1277
+ rectangle,
1277
1278
  BoundingSphere.fromOrientedBoundingBox(obb),
1278
1279
  computeOccludeePoint(
1279
1280
  tileProvider,
@@ -131,7 +131,9 @@ void doThreePointDepthTest(float eyeDepth, bool applyTranslate) {
131
131
  }
132
132
  #endif
133
133
 
134
- void doDepthTest() {
134
+ // Extra manual depth testing is done to allow more control over how a billboard is occluded
135
+ // by the globe when near and far from the camera.
136
+ void doDepthTest(float globeDepth) {
135
137
  float temp = v_compressed.y;
136
138
  temp = temp * SHIFT_RIGHT1;
137
139
  float temp2 = (temp - floor(temp)) * SHIFT_LEFT1;
@@ -156,14 +158,10 @@ void doDepthTest() {
156
158
  }
157
159
  #endif
158
160
 
159
- // Automatic depth testing of billboards is disabled (@see BillboardCollection#update).
160
- // Instead, we do one of two types of manual depth tests (potentially in addition to the test above), depending on the camera's distance to the billboard fragment.
161
161
  // If we're far away, we just compare against a flat, camera-facing depth-plane at the ellipsoid's center.
162
162
  // If we're close, we compare against the globe depth texture (which includes depth from the 3D tile pass).
163
- vec2 fragSt = gl_FragCoord.xy / czm_viewport.zw;
164
- float globeDepth = getGlobeDepthAtCoords(fragSt);
165
- if (globeDepth == 0.0) return; // Not on globe
166
-
163
+
164
+ if (globeDepth == 0.0) return; // Not on globe
167
165
  float distanceToEllipsoidCenter = -length(czm_viewerPositionWC); // depth is negative by convention
168
166
  float testDistance = (eyeDepth > -u_coarseDepthTestDistance) ? globeDepth : distanceToEllipsoidCenter;
169
167
  if (eyeDepth < testDistance) {
@@ -175,7 +173,10 @@ void main()
175
173
  {
176
174
  if (v_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;
177
175
  if (v_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;
178
- doDepthTest();
176
+
177
+ vec2 fragSt = gl_FragCoord.xy / czm_viewport.zw;
178
+ float globeDepth = getGlobeDepthAtCoords(fragSt);
179
+ doDepthTest(globeDepth);
179
180
 
180
181
  vec4 color = texture(u_atlas, v_textureCoordinates);
181
182
 
@@ -243,6 +244,18 @@ void main()
243
244
  out_FragColor = color;
244
245
 
245
246
  #ifdef LOG_DEPTH
246
- czm_writeLogDepth();
247
+ // If we've made it here, we passed our manual depth test, above. But the automatic depth test will
248
+ // still run, and some fragments of the billboard may clip against the globe. To prevent that,
249
+ // ensure the depth value we write out is in front of the globe depth.
250
+ float depthArg = v_depthFromNearPlusOne;
251
+
252
+ if (globeDepth != 0.0) { // On the globe
253
+ float globeDepthFromNearPlusOne = (-globeDepth - czm_currentFrustum.x) + 1.0;
254
+ float nudge = max(globeDepthFromNearPlusOne * 5e-6, czm_epsilon7);
255
+ float globeOnTop = max(1.0, globeDepthFromNearPlusOne - nudge);
256
+ depthArg = min(depthArg, globeOnTop);
257
+ }
258
+
259
+ czm_writeLogDepth(depthArg);
247
260
  #endif
248
261
  }
@@ -132,7 +132,9 @@ void doThreePointDepthTest(float eyeDepth, bool applyTranslate) {\n\
132
132
  }\n\
133
133
  #endif\n\
134
134
  \n\
135
- void doDepthTest() {\n\
135
+ // Extra manual depth testing is done to allow more control over how a billboard is occluded \n\
136
+ // by the globe when near and far from the camera.\n\
137
+ void doDepthTest(float globeDepth) {\n\
136
138
  float temp = v_compressed.y;\n\
137
139
  temp = temp * SHIFT_RIGHT1;\n\
138
140
  float temp2 = (temp - floor(temp)) * SHIFT_LEFT1;\n\
@@ -157,14 +159,10 @@ void doDepthTest() {\n\
157
159
  }\n\
158
160
  #endif\n\
159
161
  \n\
160
- // Automatic depth testing of billboards is disabled (@see BillboardCollection#update).\n\
161
- // Instead, we do one of two types of manual depth tests (potentially in addition to the test above), depending on the camera's distance to the billboard fragment.\n\
162
162
  // If we're far away, we just compare against a flat, camera-facing depth-plane at the ellipsoid's center.\n\
163
163
  // If we're close, we compare against the globe depth texture (which includes depth from the 3D tile pass).\n\
164
- vec2 fragSt = gl_FragCoord.xy / czm_viewport.zw;\n\
165
- float globeDepth = getGlobeDepthAtCoords(fragSt);\n\
166
- if (globeDepth == 0.0) return; // Not on globe\n\
167
- \n\
164
+ \n\
165
+ if (globeDepth == 0.0) return; // Not on globe \n\
168
166
  float distanceToEllipsoidCenter = -length(czm_viewerPositionWC); // depth is negative by convention\n\
169
167
  float testDistance = (eyeDepth > -u_coarseDepthTestDistance) ? globeDepth : distanceToEllipsoidCenter;\n\
170
168
  if (eyeDepth < testDistance) {\n\
@@ -176,7 +174,10 @@ void main()\n\
176
174
  {\n\
177
175
  if (v_splitDirection < 0.0 && gl_FragCoord.x > czm_splitPosition) discard;\n\
178
176
  if (v_splitDirection > 0.0 && gl_FragCoord.x < czm_splitPosition) discard;\n\
179
- doDepthTest();\n\
177
+ \n\
178
+ vec2 fragSt = gl_FragCoord.xy / czm_viewport.zw;\n\
179
+ float globeDepth = getGlobeDepthAtCoords(fragSt);\n\
180
+ doDepthTest(globeDepth);\n\
180
181
  \n\
181
182
  vec4 color = texture(u_atlas, v_textureCoordinates);\n\
182
183
  \n\
@@ -244,6 +245,18 @@ void main()\n\
244
245
  out_FragColor = color;\n\
245
246
  \n\
246
247
  #ifdef LOG_DEPTH\n\
247
- czm_writeLogDepth();\n\
248
+ // If we've made it here, we passed our manual depth test, above. But the automatic depth test will\n\
249
+ // still run, and some fragments of the billboard may clip against the globe. To prevent that,\n\
250
+ // ensure the depth value we write out is in front of the globe depth.\n\
251
+ float depthArg = v_depthFromNearPlusOne;\n\
252
+ \n\
253
+ if (globeDepth != 0.0) { // On the globe\n\
254
+ float globeDepthFromNearPlusOne = (-globeDepth - czm_currentFrustum.x) + 1.0;\n\
255
+ float nudge = max(globeDepthFromNearPlusOne * 5e-6, czm_epsilon7);\n\
256
+ float globeOnTop = max(1.0, globeDepthFromNearPlusOne - nudge);\n\
257
+ depthArg = min(depthArg, globeOnTop);\n\
258
+ }\n\
259
+ \n\
260
+ czm_writeLogDepth(depthArg);\n\
248
261
  #endif\n\
249
262
  }";