@cesium/engine 22.0.0 → 22.1.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 (151) hide show
  1. package/Build/ThirdParty/Workers/zip-web-worker.js +10 -7
  2. package/Build/Workers/chunk-23T2IPHV.js +55 -0
  3. package/Build/Workers/{chunk-VVZ667H6.js → chunk-2AM4E2WD.js} +2 -2
  4. package/Build/Workers/{chunk-XQ347YWU.js → chunk-2MWF4IES.js} +16 -14
  5. package/Build/Workers/{chunk-75HAJIDT.js → chunk-2RCIRXNI.js} +1 -1
  6. package/Build/Workers/{chunk-RQRODXVN.js → chunk-3YTMGEXW.js} +5 -1424
  7. package/Build/Workers/{chunk-N52ZRKUE.js → chunk-4BHWJWS3.js} +6 -6
  8. package/Build/Workers/{chunk-5T5SY63I.js → chunk-5JKH4AMT.js} +2 -2
  9. package/Build/Workers/{chunk-EJO3NKMS.js → chunk-6HKAPCSO.js} +1 -1
  10. package/Build/Workers/{chunk-BJSNGGBM.js → chunk-A53R2F2L.js} +4 -4
  11. package/Build/Workers/{chunk-H7B7FU2U.js → chunk-A6YFUGJO.js} +5 -5
  12. package/Build/Workers/{chunk-VCVA7BMD.js → chunk-AJYWXC6I.js} +4 -4
  13. package/Build/Workers/{chunk-3GL53OCU.js → chunk-AOIO5VUS.js} +276 -2277
  14. package/Build/Workers/{chunk-SZN34LQ5.js → chunk-B7JRBTT6.js} +10 -10
  15. package/Build/Workers/{chunk-726NINF5.js → chunk-CHNDJRYA.js} +20 -18
  16. package/Build/Workers/{chunk-L7U26FFD.js → chunk-CJOV55CW.js} +20 -18
  17. package/Build/Workers/{chunk-NE5JTQJP.js → chunk-COGPE5Z2.js} +10 -8
  18. package/Build/Workers/{chunk-XPVZWY4A.js → chunk-CW7W27IZ.js} +12 -8
  19. package/Build/Workers/{chunk-GYRDA3XK.js → chunk-DICY26ID.js} +20 -16
  20. package/Build/Workers/{chunk-AOM3FHBN.js → chunk-DMEFNTUV.js} +69 -7
  21. package/Build/Workers/{chunk-XZO6F23E.js → chunk-DQSJEOZY.js} +1 -1
  22. package/Build/Workers/{chunk-MXHRZHDF.js → chunk-GDU4RZSZ.js} +16 -36
  23. package/Build/Workers/{chunk-JDJAPBZP.js → chunk-GKWOUMYA.js} +1 -1
  24. package/Build/Workers/{chunk-OUBBMEWX.js → chunk-GTY4K4IA.js} +9 -7
  25. package/Build/Workers/{chunk-LWJXCI3F.js → chunk-H6Q7E4BQ.js} +8 -6
  26. package/Build/Workers/{chunk-YLXWC7OW.js → chunk-HHGOFZVQ.js} +7 -5
  27. package/Build/Workers/{chunk-34YXP222.js → chunk-HXKUEOOD.js} +5 -5
  28. package/Build/Workers/{chunk-EZ7NJXQN.js → chunk-I4REFVXB.js} +4 -4
  29. package/Build/Workers/{chunk-OE22564R.js → chunk-IL5F6WEE.js} +3 -3
  30. package/Build/Workers/{chunk-QSMIHPUM.js → chunk-JKXPC5HD.js} +2 -2
  31. package/Build/Workers/{chunk-7KAXDKRU.js → chunk-KKGD7HAW.js} +13 -11
  32. package/Build/Workers/{chunk-YLILBDWK.js → chunk-KROSQJUA.js} +2 -2
  33. package/Build/Workers/{chunk-NHZNMTIR.js → chunk-L4JLDVCM.js} +5 -5
  34. package/Build/Workers/{chunk-2D3GLFZD.js → chunk-LIYMRHGR.js} +15 -13
  35. package/Build/Workers/{chunk-P2H75UV5.js → chunk-MKMZHRB3.js} +16 -11
  36. package/Build/Workers/{chunk-KUB64XW6.js → chunk-MO25ZQ2I.js} +12 -10
  37. package/Build/Workers/{chunk-ECHAJNQJ.js → chunk-O6RZEKHZ.js} +12 -12
  38. package/Build/Workers/{chunk-5ZF53EY6.js → chunk-OOCGX2OD.js} +4 -4
  39. package/Build/Workers/{chunk-NGKF5NTR.js → chunk-OXFU5HNU.js} +13 -5
  40. package/Build/Workers/{chunk-FA3SCJDX.js → chunk-P5CGIJUY.js} +2 -2
  41. package/Build/Workers/{chunk-W4PIP5PG.js → chunk-QEANVUGT.js} +2 -2
  42. package/Build/Workers/{chunk-AARZSH4V.js → chunk-QFBCIX7J.js} +8 -6
  43. package/Build/Workers/{chunk-JZFU2LEM.js → chunk-QUAH3XOT.js} +4 -4
  44. package/Build/Workers/{chunk-6HBKE43B.js → chunk-RXZDTDIY.js} +13 -9
  45. package/Build/Workers/{chunk-LEFQBK6H.js → chunk-SPA2KPH3.js} +14 -12
  46. package/Build/Workers/chunk-TDSVSW5A.js +1460 -0
  47. package/Build/Workers/{chunk-A6JAFSZT.js → chunk-UG2DPFOL.js} +8 -6
  48. package/Build/Workers/{chunk-U4XMLGSR.js → chunk-URGEDZBS.js} +7 -7
  49. package/Build/Workers/{chunk-A4DPJIWS.js → chunk-V35NQOJC.js} +8 -6
  50. package/Build/Workers/chunk-W4XUEDU5.js +2058 -0
  51. package/Build/Workers/{chunk-7XEJGXX2.js → chunk-WB4TSSBQ.js} +779 -24
  52. package/Build/Workers/{chunk-RCCYW6E7.js → chunk-WTLYD4FE.js} +19 -15
  53. package/Build/Workers/{chunk-5B7VZQZY.js → chunk-Y4ALZ4SS.js} +9 -7
  54. package/Build/Workers/{chunk-KGLDJRSO.js → chunk-YF2NVO5B.js} +19 -13
  55. package/Build/Workers/{chunk-IGX772ZQ.js → chunk-YSYSXSHF.js} +1 -1
  56. package/Build/Workers/{chunk-M7HRE4QR.js → chunk-YX562XOB.js} +15 -11
  57. package/Build/Workers/{chunk-QCMRUVVF.js → chunk-YZWA5B4R.js} +15 -13
  58. package/Build/Workers/{chunk-U7CX3HHE.js → chunk-Z6DFT4D3.js} +15 -11
  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 +67 -27
  131. package/Source/Scene/ArcGisMapService.js +1 -1
  132. package/Source/Scene/Azure2DImageryProvider.js +96 -12
  133. package/Source/Scene/Billboard.js +75 -28
  134. package/Source/Scene/BillboardCollection.js +7 -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/PickFramebuffer.js +124 -36
  141. package/Source/Scene/Picking.js +99 -17
  142. package/Source/Scene/Scene.js +36 -4
  143. package/Source/Scene/TerrainFillMesh.js +1 -0
  144. package/Source/Shaders/BillboardCollectionFS.glsl +22 -9
  145. package/Source/Shaders/BillboardCollectionFS.js +22 -9
  146. package/Source/ThirdParty/Workers/zip-web-worker.js +1 -1
  147. package/Source/ThirdParty/zip-module.wasm +0 -0
  148. package/Source/Workers/incrementallyBuildTerrainPicker.js +108 -0
  149. package/index.d.ts +207 -4
  150. package/index.js +28 -26
  151. package/package.json +2 -2
@@ -1131,23 +1131,32 @@ Transforms.rotationMatrixFromPositionVelocity = function (
1131
1131
  return result;
1132
1132
  };
1133
1133
 
1134
- const swizzleMatrix = new Matrix4(
1135
- 0.0,
1136
- 0.0,
1137
- 1.0,
1138
- 0.0,
1139
- 1.0,
1140
- 0.0,
1141
- 0.0,
1142
- 0.0,
1143
- 0.0,
1144
- 1.0,
1145
- 0.0,
1146
- 0.0,
1147
- 0.0,
1148
- 0.0,
1149
- 0.0,
1150
- 1.0,
1134
+ /**
1135
+ * An immutable matrix that swaps x, y, z for 2D.
1136
+ *
1137
+ * @type {Matrix4}
1138
+ * @constant
1139
+ * @private
1140
+ */
1141
+ Transforms.SWIZZLE_3D_TO_2D_MATRIX = Object.freeze(
1142
+ new Matrix4(
1143
+ 0.0,
1144
+ 0.0,
1145
+ 1.0,
1146
+ 0.0,
1147
+ 1.0,
1148
+ 0.0,
1149
+ 0.0,
1150
+ 0.0,
1151
+ 0.0,
1152
+ 1.0,
1153
+ 0.0,
1154
+ 0.0,
1155
+ 0.0,
1156
+ 0.0,
1157
+ 0.0,
1158
+ 1.0,
1159
+ ),
1151
1160
  );
1152
1161
 
1153
1162
  const scratchCartographic = new Cartographic();
@@ -1210,7 +1219,7 @@ Transforms.basisTo2D = function (projection, matrix, result) {
1210
1219
  const toENU = Matrix4.inverseTransformation(fromENU, scratchToENU);
1211
1220
  const rotation = Matrix4.getMatrix3(matrix, scratchRotation);
1212
1221
  const local = Matrix4.multiplyByMatrix3(toENU, rotation, result);
1213
- Matrix4.multiply(swizzleMatrix, local, result); // Swap x, y, z for 2D
1222
+ Matrix4.multiply(Transforms.SWIZZLE_3D_TO_2D_MATRIX, local, result); // Swap x, y, z for 2D
1214
1223
  Matrix4.setTranslation(result, projectedPosition, result); // Use the projected center
1215
1224
 
1216
1225
  return result;
@@ -1260,7 +1269,7 @@ Transforms.ellipsoidTo2DModelMatrix = function (projection, center, result) {
1260
1269
  projectedPosition,
1261
1270
  scratchFromENU,
1262
1271
  );
1263
- Matrix4.multiply(swizzleMatrix, toENU, result);
1272
+ Matrix4.multiply(Transforms.SWIZZLE_3D_TO_2D_MATRIX, toENU, result);
1264
1273
  Matrix4.multiply(translation, result, result);
1265
1274
 
1266
1275
  return result;
@@ -10,7 +10,7 @@ import createPropertyDescriptor from "./createPropertyDescriptor.js";
10
10
  * Initialization options for the BillboardGraphics constructor
11
11
  *
12
12
  * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the billboard.
13
- * @property {Property | string | HTMLCanvasElement} [image] A Property specifying the Image, URI, or Canvas to use for the billboard.
13
+ * @property {Property | string | HTMLImageElement | HTMLCanvasElement} [image] A Property specifying the Image, URI, or Canvas to use for the billboard.
14
14
  * @property {Property | number} [scale=1.0] A numeric Property specifying the scale to apply to the image size.
15
15
  * @property {Property | Cartesian2} [pixelOffset=Cartesian2.ZERO] A {@link Cartesian2} Property specifying the pixel offset.
16
16
  * @property {Property | Cartesian3} [eyeOffset=Cartesian3.ZERO] A {@link Cartesian3} Property specifying the eye offset.
@@ -131,10 +131,6 @@ BillboardVisualizer.prototype.update = function (time) {
131
131
  }
132
132
 
133
133
  billboard.show = show;
134
- if (item.textureValue !== textureValue) {
135
- billboard.image = textureValue;
136
- item.textureValue = textureValue;
137
- }
138
134
  billboard.position = position;
139
135
  billboard.color = Property.getValueOrDefault(
140
136
  billboardGraphics._color,
@@ -227,6 +223,13 @@ BillboardVisualizer.prototype.update = function (time) {
227
223
  defaultSplitDirection,
228
224
  );
229
225
 
226
+ // Apply .image last, so any necessary property values are available
227
+ // in Billboard#_computeImageTextureSize before adding to the atlas.
228
+ if (item.textureValue !== textureValue) {
229
+ billboard.image = textureValue;
230
+ item.textureValue = textureValue;
231
+ }
232
+
230
233
  const subRegion = Property.getValueOrUndefined(
231
234
  billboardGraphics._imageSubRegion,
232
235
  time,
@@ -72,6 +72,26 @@ function Buffer(options) {
72
72
  this.vertexArrayDestroyable = true;
73
73
  }
74
74
 
75
+ Buffer.createPixelBuffer = function (options) {
76
+ //>>includeStart('debug', pragmas.debug);
77
+ Check.defined("options.context", options.context);
78
+ //>>includeEnd('debug');
79
+
80
+ if (!options.context._webgl2) {
81
+ throw new DeveloperError(
82
+ "A WebGL 2 context is required to create PixelBuffers.",
83
+ );
84
+ }
85
+
86
+ return new Buffer({
87
+ context: options.context,
88
+ bufferTarget: WebGLConstants.PIXEL_PACK_BUFFER,
89
+ typedArray: options.typedArray,
90
+ sizeInBytes: options.sizeInBytes,
91
+ usage: options.usage,
92
+ });
93
+ };
94
+
75
95
  /**
76
96
  * Creates a vertex buffer, which contains untyped vertex data in GPU-controlled memory.
77
97
  * <br /><br />
@@ -242,6 +262,18 @@ Buffer.prototype._getBuffer = function () {
242
262
  return this._buffer;
243
263
  };
244
264
 
265
+ Buffer.prototype._bind = function () {
266
+ const gl = this._gl;
267
+ const target = this._bufferTarget;
268
+ gl.bindBuffer(target, this._buffer);
269
+ };
270
+
271
+ Buffer.prototype._unBind = function () {
272
+ const gl = this._gl;
273
+ const target = this._bufferTarget;
274
+ gl.bindBuffer(target, null);
275
+ };
276
+
245
277
  Buffer.prototype.copyFromArrayView = function (arrayView, offsetInBytes) {
246
278
  offsetInBytes = offsetInBytes ?? 0;
247
279
 
@@ -7,12 +7,14 @@ const BufferUsage = {
7
7
  STREAM_DRAW: WebGLConstants.STREAM_DRAW,
8
8
  STATIC_DRAW: WebGLConstants.STATIC_DRAW,
9
9
  DYNAMIC_DRAW: WebGLConstants.DYNAMIC_DRAW,
10
+ DYNAMIC_READ: WebGLConstants.DYNAMIC_READ,
10
11
 
11
12
  validate: function (bufferUsage) {
12
13
  return (
13
14
  bufferUsage === BufferUsage.STREAM_DRAW ||
14
15
  bufferUsage === BufferUsage.STATIC_DRAW ||
15
- bufferUsage === BufferUsage.DYNAMIC_DRAW
16
+ bufferUsage === BufferUsage.DYNAMIC_DRAW ||
17
+ bufferUsage === BufferUsage.DYNAMIC_READ
16
18
  );
17
19
  },
18
20
  };
@@ -1,3 +1,4 @@
1
+ import Buffer from "./Buffer.js";
1
2
  import Check from "../Core/Check.js";
2
3
  import Color from "../Core/Color.js";
3
4
  import ComponentDatatype from "../Core/ComponentDatatype.js";
@@ -1442,13 +1443,88 @@ Context.prototype.endFrame = function () {
1442
1443
  };
1443
1444
 
1444
1445
  /**
1446
+ * @typedef {object} ReadState
1447
+ *
1448
+ * Options defining a rectangle to read pixels from.
1449
+ *
1450
+ * @private
1451
+ * @property {number} [x=0] The x offset of the rectangle to read from.
1452
+ * @property {number} [y=0] The y offset of the rectangle to read from.
1453
+ * @property {number} [width=this.drawingBufferWidth] The width of the rectangle to read from.
1454
+ * @property {number} [height=this.drawingBufferHeight] The height of the rectangle to read from.
1455
+ * @property {FrameBuffer|undefined} [framebuffer] The framebuffer to read from. If undefined, the read will be from the default framebuffer.
1456
+ */
1457
+
1458
+ /**
1459
+ * Read pixels from a framebuffer into a Pixel Buffer Object (PBO).
1460
+ *
1461
+ * @private
1462
+ * @param {ReadState} readState Options defining a rectangle to read pixels from.
1463
+ * @returns {Buffer} A PixelBuffer containing the pixels read from the specified rectangle.
1464
+ *
1465
+ * @exception {DeveloperError} A WebGL 2 context is required to read pixels using a PBO.
1466
+ */
1467
+ Context.prototype.readPixelsToPBO = function (readState) {
1468
+ const gl = this._gl;
1469
+
1470
+ readState = readState ?? Frozen.EMPTY_OBJECT;
1471
+ const x = Math.max(readState.x ?? 0, 0);
1472
+ const y = Math.max(readState.y ?? 0, 0);
1473
+ const width = readState.width ?? this.drawingBufferWidth;
1474
+ const height = readState.height ?? this.drawingBufferHeight;
1475
+ const framebuffer = readState.framebuffer;
1476
+
1477
+ if (!this._webgl2) {
1478
+ throw new DeveloperError(
1479
+ "A WebGL 2 context is required to read pixels using a PBO.",
1480
+ );
1481
+ }
1482
+
1483
+ //>>includeStart('debug', pragmas.debug);
1484
+ Check.typeOf.number.greaterThan("readState.width", width, 0);
1485
+ Check.typeOf.number.greaterThan("readState.height", height, 0);
1486
+ //>>includeEnd('debug');
1487
+
1488
+ let pixelDatatype = PixelDatatype.UNSIGNED_BYTE;
1489
+ let pixelFormat = PixelFormat.RGBA;
1490
+ if (defined(framebuffer) && framebuffer.numberOfColorAttachments > 0) {
1491
+ pixelDatatype = framebuffer.getColorTexture(0).pixelDatatype;
1492
+ pixelFormat = framebuffer.getColorTexture(0).pixelFormat;
1493
+ }
1494
+
1495
+ const pixels = Buffer.createPixelBuffer({
1496
+ context: this,
1497
+ sizeInBytes: PixelFormat.textureSizeInBytes(
1498
+ pixelFormat,
1499
+ pixelDatatype,
1500
+ width,
1501
+ height,
1502
+ ),
1503
+ usage: BufferUsage.DYNAMIC_READ,
1504
+ });
1505
+
1506
+ bindFramebuffer(this, framebuffer);
1507
+
1508
+ pixels._bind();
1509
+ gl.readPixels(
1510
+ x,
1511
+ y,
1512
+ width,
1513
+ height,
1514
+ pixelFormat,
1515
+ PixelDatatype.toWebGLConstant(pixelDatatype, this),
1516
+ 0,
1517
+ );
1518
+ pixels._unBind();
1519
+
1520
+ return pixels;
1521
+ };
1522
+
1523
+ /**
1524
+ * Read pixels from a framebuffer into a typed array.
1525
+ *
1445
1526
  * @private
1446
- * @param {object} readState An object with the following properties:
1447
- * @param {number} [readState.x=0] The x offset of the rectangle to read from.
1448
- * @param {number} [readState.y=0] The y offset of the rectangle to read from.
1449
- * @param {number} [readState.width=this.drawingBufferWidth] The width of the rectangle to read from.
1450
- * @param {number} [readState.height=this.drawingBufferHeight] The height of the rectangle to read from.
1451
- * @param {Framebuffer} [readState.framebuffer] The framebuffer to read from. If undefined, the read will be from the default framebuffer.
1527
+ * @param {ReadState} readState Options defining a rectangle to read pixels from.
1452
1528
  * @returns {Uint8Array|Uint16Array|Float32Array|Uint32Array} The pixels in the specified rectangle.
1453
1529
  */
1454
1530
  Context.prototype.readPixels = function (readState) {
@@ -1467,12 +1543,14 @@ Context.prototype.readPixels = function (readState) {
1467
1543
  //>>includeEnd('debug');
1468
1544
 
1469
1545
  let pixelDatatype = PixelDatatype.UNSIGNED_BYTE;
1546
+ let pixelFormat = PixelFormat.RGBA;
1470
1547
  if (defined(framebuffer) && framebuffer.numberOfColorAttachments > 0) {
1471
1548
  pixelDatatype = framebuffer.getColorTexture(0).pixelDatatype;
1549
+ pixelFormat = framebuffer.getColorTexture(0).pixelFormat;
1472
1550
  }
1473
1551
 
1474
1552
  const pixels = PixelFormat.createTypedArray(
1475
- PixelFormat.RGBA,
1553
+ pixelFormat,
1476
1554
  pixelDatatype,
1477
1555
  width,
1478
1556
  height,
@@ -0,0 +1,104 @@
1
+ import Check from "../Core/Check.js";
2
+ import destroyObject from "../Core/destroyObject.js";
3
+ import DeveloperError from "../Core/DeveloperError.js";
4
+ import Frozen from "../Core/Frozen.js";
5
+ import RuntimeError from "../Core/RuntimeError.js";
6
+ import WebGLConstants from "../Core/WebGLConstants.js";
7
+
8
+ /**
9
+ * The WebGLSync interface is part of the WebGL 2 API and is used to synchronize activities between the GPU and the application.
10
+ *
11
+ * @param {object} options Object with the following properties:
12
+ * @param {Context} context
13
+ *
14
+ * @exception {DeveloperError} A WebGL 2 context is required to use Sync operations.
15
+ *
16
+ * @private
17
+ * @constructor
18
+ */
19
+ function Sync(options) {
20
+ options = options ?? Frozen.EMPTY_OBJECT;
21
+ const context = options.context;
22
+
23
+ //>>includeStart('debug', pragmas.debug);
24
+ Check.defined("options.context", context);
25
+ //>>includeEnd('debug');
26
+
27
+ if (!context._webgl2) {
28
+ throw new DeveloperError(
29
+ "A WebGL 2 context is required to use Sync operations.",
30
+ );
31
+ }
32
+
33
+ const gl = context._gl;
34
+ const sync = gl.fenceSync(WebGLConstants.SYNC_GPU_COMMANDS_COMPLETE, 0);
35
+
36
+ this._gl = gl;
37
+ this._sync = sync;
38
+ }
39
+ Sync.create = function (options) {
40
+ return new Sync(options);
41
+ };
42
+ /**
43
+ * Query the sync status of this Sync object.
44
+ *
45
+ * @returns {number} Returns a WebGLConstants indicating the status of the sync object (WebGLConstants.SIGNALED or WebGLConstants.UNSIGNALED).
46
+ *
47
+ * @private
48
+ */
49
+ Sync.prototype.getStatus = function () {
50
+ const status = this._gl.getSyncParameter(
51
+ this._sync,
52
+ WebGLConstants.SYNC_STATUS,
53
+ );
54
+ return status;
55
+ };
56
+ Sync.prototype.isDestroyed = function () {
57
+ return false;
58
+ };
59
+ Sync.prototype.destroy = function () {
60
+ this._gl.deleteSync(this._sync);
61
+ return destroyObject(this);
62
+ };
63
+
64
+ /**
65
+ * Incremantally polls the status of the Sync object until signaled then resolves.
66
+ * Usually polling should be done once per frame.
67
+ *
68
+ * @example
69
+ * try {
70
+ * await sync.waitForSignal(function (next) {
71
+ * setTimeout(next, 100);
72
+ * });
73
+ *} catch (e) {
74
+ * throw "Signal timeout";
75
+ *} finally {
76
+ * sync.destroy();
77
+ *}
78
+ *
79
+ * @param {function} scheduleFunction Function for scheduling the next poll. Receives a callback as its only parameter.
80
+ * @param {number} [ttl=10] Max number of iterations to poll until timeout.
81
+ *
82
+ * @exception {RuntimeError} Wait for signal timeout.
83
+ */
84
+ Sync.prototype.waitForSignal = async function (scheduleFunction, ttl) {
85
+ const self = this;
86
+ ttl = ttl ?? 10;
87
+ function waitForSignal0(resolve, reject, ttl) {
88
+ return () => {
89
+ const syncStatus = self.getStatus();
90
+ const signaled = syncStatus === WebGLConstants.SIGNALED;
91
+ if (signaled) {
92
+ resolve();
93
+ } else if (ttl <= 0) {
94
+ reject(new RuntimeError("Wait for signal timeout"));
95
+ } else {
96
+ scheduleFunction(waitForSignal0(resolve, reject, ttl - 1));
97
+ }
98
+ };
99
+ }
100
+ return new Promise((resolve, reject) => {
101
+ scheduleFunction(waitForSignal0(resolve, reject, ttl));
102
+ });
103
+ };
104
+ export default Sync;
@@ -59,12 +59,16 @@ function TextureAtlas(options) {
59
59
  this._initialSize = initialSize;
60
60
 
61
61
  this._texturePacker = undefined;
62
+ /** @type {BoundingRectangle[]} */
62
63
  this._rectangles = [];
64
+ /** @type {Map<number, number>} */
63
65
  this._subRegions = new Map();
64
66
  this._guid = createGuid();
65
67
 
66
68
  this._imagesToAddQueue = [];
69
+ /** @type {Map<string, number>} */
67
70
  this._indexById = new Map();
71
+ /** @type {Map<string, Promise<number>>} */
68
72
  this._indexPromiseById = new Map();
69
73
  this._nextIndex = 0;
70
74
  }
@@ -644,34 +648,51 @@ async function resolveImage(image, id) {
644
648
  * @param {string} id An identifier to detect whether the image already exists in the atlas.
645
649
  * @param {HTMLImageElement|HTMLCanvasElement|string|Resource|Promise|TextureAtlas.CreateImageCallback} image An image or canvas to add to the texture atlas,
646
650
  * or a URL to an Image, or a Promise for an image, or a function that creates an image.
647
- * @returns {Promise<number>} A Promise that resolves to the image region index. -1 is returned if resouces are in the process of being destroyed.
651
+ * @param {number} width A number specifying the width of the texture. If undefined, the image width will be used.
652
+ * @param {number} height A number specifying the height of the texture. If undefined, the image height will be used.
653
+ * @returns {Promise<number>} A Promise that resolves to the image region index, or -1 if resources are in the process of being destroyed.
648
654
  */
649
- TextureAtlas.prototype.addImage = function (id, image) {
655
+ TextureAtlas.prototype.addImage = function (id, image, width, height) {
650
656
  //>>includeStart('debug', pragmas.debug);
651
657
  Check.typeOf.string("id", id);
652
658
  Check.defined("image", image);
653
659
  //>>includeEnd('debug');
654
660
 
655
661
  let promise = this._indexPromiseById.get(id);
662
+ let index = this._indexById.get(id);
656
663
  if (defined(promise)) {
657
- // This image has already been added
664
+ // This image is already being added
658
665
  return promise;
659
666
  }
667
+ if (defined(index)) {
668
+ // This image has already been added and resolved
669
+ return Promise.resolve(index);
670
+ }
660
671
 
661
- const index = this._nextIndex++;
672
+ index = this._nextIndex++;
662
673
  this._indexById.set(id, index);
663
674
 
664
675
  const resolveAndAddImage = async () => {
665
- image = await resolveImage(image, id);
676
+ const resolvedImage = await resolveImage(image, id);
666
677
  //>>includeStart('debug', pragmas.debug);
667
- Check.defined("image", image);
678
+ Check.defined("image", resolvedImage);
668
679
  //>>includeEnd('debug');
669
680
 
670
- if (this.isDestroyed() || !defined(image)) {
681
+ if (this.isDestroyed() || !defined(resolvedImage)) {
682
+ this._indexPromiseById.delete(id);
671
683
  return -1;
672
684
  }
673
685
 
674
- return this._addImage(index, image);
686
+ if (defined(width)) {
687
+ resolvedImage.width = width;
688
+ }
689
+ if (defined(height)) {
690
+ resolvedImage.height = height;
691
+ }
692
+
693
+ const imageIndex = await this._addImage(index, resolvedImage);
694
+ this._indexPromiseById.delete(id);
695
+ return imageIndex;
675
696
  };
676
697
 
677
698
  promise = resolveAndAddImage();
@@ -679,46 +700,65 @@ TextureAtlas.prototype.addImage = function (id, image) {
679
700
  return promise;
680
701
  };
681
702
 
703
+ /**
704
+ * Get an existing sub-region of an existing atlas image as additional image indices.
705
+ * @private
706
+ * @param {string} id The identifier of the existing image.
707
+ * @param {BoundingRectangle} subRegion An {@link BoundingRectangle} defining a region of an existing image, measured in pixels from the bottom-left of the image.
708
+ * @param {number} imageIndex The index of the image.
709
+ * @returns {Promise<number> | number | undefined} The existing subRegion index, or undefined if not yet added.
710
+ */
711
+ TextureAtlas.prototype.getCachedImageSubRegion = function (
712
+ id,
713
+ subRegion,
714
+ imageIndex,
715
+ ) {
716
+ const imagePromise = this._indexPromiseById.get(id);
717
+ for (const [index, parentIndex] of this._subRegions.entries()) {
718
+ if (imageIndex === parentIndex) {
719
+ const boundingRegion = this._rectangles[index];
720
+ if (boundingRegion.equals(subRegion)) {
721
+ // The subregion is already being tracked
722
+ if (imagePromise) {
723
+ return imagePromise.then((resolvedImageIndex) =>
724
+ resolvedImageIndex === -1 ? -1 : index,
725
+ );
726
+ }
727
+ return index;
728
+ }
729
+ }
730
+ }
731
+ };
732
+
682
733
  /**
683
734
  * Add a sub-region of an existing atlas image as additional image indices.
684
735
  * @private
685
736
  * @param {string} id The identifier of the existing image.
686
737
  * @param {BoundingRectangle} subRegion An {@link BoundingRectangle} defining a region of an existing image, measured in pixels from the bottom-left of the image.
687
- * @returns {Promise<number>} A Promise that resolves to the image region index. -1 is returned if resouces are in the process of being destroyed.
738
+ * @returns {number | Promise<number>} The resolved image region index, or a Promise that resolves to it. -1 is returned if resources are in the process of being destroyed.
688
739
  */
689
740
  TextureAtlas.prototype.addImageSubRegion = function (id, subRegion) {
690
741
  //>>includeStart('debug', pragmas.debug);
691
742
  Check.typeOf.string("id", id);
692
743
  Check.defined("subRegion", subRegion);
693
744
  //>>includeEnd('debug');
694
-
695
745
  const imageIndex = this._indexById.get(id);
696
746
  if (!defined(imageIndex)) {
697
747
  throw new RuntimeError(`image with id "${id}" not found in the atlas.`);
698
748
  }
699
749
 
700
- const indexPromise = this._indexPromiseById.get(id);
701
- for (const [index, parentIndex] of this._subRegions.entries()) {
702
- if (imageIndex === parentIndex) {
703
- const boundingRegion = this._rectangles[index];
704
- if (boundingRegion.equals(subRegion)) {
705
- // The subregion is already being tracked
706
- return indexPromise.then((resolvedImageIndex) => {
707
- if (resolvedImageIndex === -1) {
708
- // The atlas has been destroyed
709
- return -1;
710
- }
711
-
712
- return index;
713
- });
714
- }
715
- }
750
+ let index = this.getCachedImageSubRegion(id, subRegion, imageIndex);
751
+ if (defined(index)) {
752
+ return index;
716
753
  }
717
754
 
718
- const index = this._nextIndex++;
755
+ index = this._nextIndex++;
719
756
  this._subRegions.set(index, imageIndex);
720
757
  this._rectangles[index] = subRegion.clone();
721
758
 
759
+ const indexPromise =
760
+ this._indexPromiseById.get(id) ?? Promise.resolve(imageIndex);
761
+
722
762
  return indexPromise.then((imageIndex) => {
723
763
  if (imageIndex === -1) {
724
764
  // The atlas has been destroyed
@@ -4,7 +4,7 @@ import Resource from "../Core/Resource.js";
4
4
 
5
5
  let defaultTokenCredit;
6
6
  const defaultAccessToken =
7
- "AAPTxy8BH1VEsoebNVZXo8HurEOF051kAEKlhkOhBEc9BmTlKbWoQXtdb-m2VclxMHo8eEPu_iyh95DPKVzeyNrKkb2zc_ICfJxY7tPEl4aVdWCyU_P18q9k6D26yO7pAVtbr3I-gxRJb412PB_FydyuNKYsVRiVLqJGaYOCYhJeY3Tv8USWG4TQVu6i2mMZ8CBE68HAd3DByIRkBcjQRnker5_UyWjO86QZxpbnykaqDtY.AT1_zMTIWhVd";
7
+ "AAPTxy8BH1VEsoebNVZXo8HurEOF051kAEKlhkOhBEc9BmRA_-es9rk59JndtXxJExAf4pmezE6N8auY2oiYF7U6dXh7yRaT1sNQtBY9wlqlw0devC6v78rHPdmwJcUuC_MbH3liCP4RLfDGesom_8vT8bbbaPe8MoNz66fpwDaRk4lfCE9paNVC2Mx1K0Dgg7eJJ4TF14HaUnSgkHUcR7gLbj_277ZHX9P-QkLR9Tqcf_Y.AT1_7xNXmYif";
8
8
  /**
9
9
  * Default options for accessing the ArcGIS image tile service.
10
10
  *