@cesium/engine 20.0.2-ion.0 → 21.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 (182) hide show
  1. package/Build/ThirdParty/Workers/zip-web-worker.js +637 -0
  2. package/Build/Workers/{chunk-WZKTQZUW.js → chunk-2T4WAVWX.js} +6 -6
  3. package/Build/Workers/{chunk-6LULWCX3.js → chunk-3G5XEUPY.js} +1 -1
  4. package/Build/Workers/{chunk-OIMV4OE5.js → chunk-3MSNTCHW.js} +9 -9
  5. package/Build/Workers/{chunk-VZNF2GT7.js → chunk-3OPG2FGI.js} +4 -4
  6. package/Build/Workers/{chunk-MTBXKKSQ.js → chunk-3PUG3T2H.js} +12 -12
  7. package/Build/Workers/{chunk-XWRUYDF6.js → chunk-4PH27XAL.js} +2 -2
  8. package/Build/Workers/{chunk-P2V7PVDH.js → chunk-4VJYMLR6.js} +8 -8
  9. package/Build/Workers/{chunk-MFXTB5I4.js → chunk-5B3PGBQW.js} +11 -11
  10. package/Build/Workers/{chunk-USK6ZAY2.js → chunk-5GHCWGC4.js} +1 -1
  11. package/Build/Workers/{chunk-AHFTST3Q.js → chunk-5PEQUMCB.js} +12 -12
  12. package/Build/Workers/{chunk-23B3EYUM.js → chunk-64WSG7AT.js} +4 -4
  13. package/Build/Workers/{chunk-CEA3L7M7.js → chunk-6J6WGCWP.js} +4 -4
  14. package/Build/Workers/{chunk-VSMKMGX4.js → chunk-75B34CC6.js} +5 -5
  15. package/Build/Workers/{chunk-IS5FETN7.js → chunk-7PLX65MV.js} +5 -5
  16. package/Build/Workers/{chunk-FNUSHLOY.js → chunk-AR2FUSG6.js} +1 -1
  17. package/Build/Workers/{chunk-VLGVUVJY.js → chunk-ARYRHDEB.js} +6 -6
  18. package/Build/Workers/{chunk-FHLPYFIW.js → chunk-B7INTBBB.js} +13 -13
  19. package/Build/Workers/{chunk-BHAATGZA.js → chunk-BDPSQXLX.js} +5 -5
  20. package/Build/Workers/{chunk-QZGZIAK2.js → chunk-BU4CGMHO.js} +6 -6
  21. package/Build/Workers/{chunk-YNPZU55A.js → chunk-BUBVUXDO.js} +6 -6
  22. package/Build/Workers/{chunk-LS63ERFB.js → chunk-CF72FAKC.js} +4 -4
  23. package/Build/Workers/{chunk-D4XRQNUO.js → chunk-DJ4ROETJ.js} +5 -5
  24. package/Build/Workers/{chunk-ABTG74AR.js → chunk-E5XCZVIY.js} +1 -1
  25. package/Build/Workers/{chunk-AFKNTEMH.js → chunk-EAYW4CFP.js} +16 -16
  26. package/Build/Workers/{chunk-YXTWHLJA.js → chunk-EHFMZFVC.js} +4 -4
  27. package/Build/Workers/{chunk-H7HFDM3G.js → chunk-FFCKCQPK.js} +5 -5
  28. package/Build/Workers/{chunk-V6ZGOX4I.js → chunk-GKCZ2G36.js} +7 -7
  29. package/Build/Workers/{chunk-VODCZKV2.js → chunk-HJ7IZBEI.js} +4 -4
  30. package/Build/Workers/{chunk-66MGJQFZ.js → chunk-JJZWDROM.js} +2 -2
  31. package/Build/Workers/{chunk-F4PS6RFF.js → chunk-JUOEBO4F.js} +10 -10
  32. package/Build/Workers/{chunk-WORBFT5H.js → chunk-K4IDXMIZ.js} +9 -9
  33. package/Build/Workers/{chunk-Q3OWKSC5.js → chunk-LL6HN3W4.js} +10 -10
  34. package/Build/Workers/{chunk-YUHWFX5H.js → chunk-LNTUIO55.js} +2 -2
  35. package/Build/Workers/{chunk-VA7LWA5Q.js → chunk-LWOCFJEH.js} +9 -9
  36. package/Build/Workers/{chunk-5DF5RVIO.js → chunk-MMUISYW4.js} +16 -16
  37. package/Build/Workers/{chunk-K6THSIDU.js → chunk-MXYW4BQ3.js} +2 -2
  38. package/Build/Workers/{chunk-X55ZOYMS.js → chunk-N6DVKXZD.js} +12 -12
  39. package/Build/Workers/{chunk-NKKNQMEH.js → chunk-NP46ZIBY.js} +3 -3
  40. package/Build/Workers/{chunk-QID3DXQA.js → chunk-OW6F6CPZ.js} +7 -7
  41. package/Build/Workers/{chunk-CYC7JX3P.js → chunk-P6OAOFBU.js} +8 -8
  42. package/Build/Workers/{chunk-FYYP46TF.js → chunk-PXDMWXO5.js} +2 -2
  43. package/Build/Workers/{chunk-TZDR2BAP.js → chunk-QS7623NH.js} +6 -6
  44. package/Build/Workers/{chunk-D5X2LOJ2.js → chunk-ROH45IXJ.js} +7 -7
  45. package/Build/Workers/{chunk-UR36KLNW.js → chunk-S2P6LCIB.js} +4 -4
  46. package/Build/Workers/{chunk-Z2W7ZIGV.js → chunk-S4NZVXU6.js} +2 -2
  47. package/Build/Workers/{chunk-YSDOO7AG.js → chunk-SGGO5WVA.js} +5 -5
  48. package/Build/Workers/{chunk-H5IQLAJP.js → chunk-TG7N7TPY.js} +47 -50
  49. package/Build/Workers/{chunk-XIDMFHR4.js → chunk-TUZQG4RW.js} +14 -14
  50. package/Build/Workers/{chunk-JVG6T2WE.js → chunk-UHVE7V65.js} +12 -12
  51. package/Build/Workers/{chunk-FAQ2XNFV.js → chunk-UY2HVPDL.js} +5 -5
  52. package/Build/Workers/{chunk-CUU3WGXJ.js → chunk-YNLPRFUQ.js} +6 -6
  53. package/Build/Workers/{chunk-X6GXYB3M.js → chunk-ZYOHBCCE.js} +1 -1
  54. package/Build/Workers/combineGeometry.js +21 -21
  55. package/Build/Workers/createBoxGeometry.js +15 -15
  56. package/Build/Workers/createBoxOutlineGeometry.js +13 -13
  57. package/Build/Workers/createCircleGeometry.js +23 -23
  58. package/Build/Workers/createCircleOutlineGeometry.js +16 -16
  59. package/Build/Workers/createCoplanarPolygonGeometry.js +30 -30
  60. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +28 -28
  61. package/Build/Workers/createCorridorGeometry.js +26 -26
  62. package/Build/Workers/createCorridorOutlineGeometry.js +25 -25
  63. package/Build/Workers/createCylinderGeometry.js +17 -17
  64. package/Build/Workers/createCylinderOutlineGeometry.js +15 -15
  65. package/Build/Workers/createEllipseGeometry.js +23 -23
  66. package/Build/Workers/createEllipseOutlineGeometry.js +16 -16
  67. package/Build/Workers/createEllipsoidGeometry.js +16 -16
  68. package/Build/Workers/createEllipsoidOutlineGeometry.js +15 -15
  69. package/Build/Workers/createFrustumGeometry.js +15 -15
  70. package/Build/Workers/createFrustumOutlineGeometry.js +15 -15
  71. package/Build/Workers/createGeometry.js +21 -21
  72. package/Build/Workers/createGroundPolylineGeometry.js +19 -19
  73. package/Build/Workers/createPlaneGeometry.js +13 -13
  74. package/Build/Workers/createPlaneOutlineGeometry.js +12 -12
  75. package/Build/Workers/createPolygonGeometry.js +29 -29
  76. package/Build/Workers/createPolygonOutlineGeometry.js +27 -27
  77. package/Build/Workers/createPolylineGeometry.js +22 -22
  78. package/Build/Workers/createPolylineVolumeGeometry.js +28 -28
  79. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +24 -24
  80. package/Build/Workers/createRectangleGeometry.js +24 -24
  81. package/Build/Workers/createRectangleOutlineGeometry.js +17 -17
  82. package/Build/Workers/createSimplePolylineGeometry.js +20 -20
  83. package/Build/Workers/createSphereGeometry.js +16 -16
  84. package/Build/Workers/createSphereOutlineGeometry.js +15 -15
  85. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  86. package/Build/Workers/createVectorTileClampedPolylines.js +12 -12
  87. package/Build/Workers/createVectorTileGeometries.js +21 -21
  88. package/Build/Workers/createVectorTilePoints.js +11 -11
  89. package/Build/Workers/createVectorTilePolygons.js +19 -19
  90. package/Build/Workers/createVectorTilePolylines.js +12 -12
  91. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +19 -19
  92. package/Build/Workers/createVerticesFromHeightmap.js +19 -19
  93. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +16 -16
  94. package/Build/Workers/createWallGeometry.js +21 -21
  95. package/Build/Workers/createWallOutlineGeometry.js +20 -20
  96. package/Build/Workers/decodeDraco.js +10 -10
  97. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  98. package/Build/Workers/decodeI3S.js +9 -9
  99. package/Build/Workers/gaussianSplatSorter.js +4 -4
  100. package/Build/Workers/gaussianSplatTextureGenerator.js +4 -4
  101. package/Build/Workers/transcodeKTX2.js +6 -6
  102. package/Build/Workers/transferTypedArrayTest.js +1 -1
  103. package/Build/Workers/upsampleQuantizedTerrainMesh.js +19 -19
  104. package/Source/Core/Event.js +41 -49
  105. package/Source/Core/GoogleMaps.js +2 -2
  106. package/Source/Core/Ion.js +1 -1
  107. package/Source/Core/IonResource.js +30 -4
  108. package/Source/Core/Resource.js +5 -1
  109. package/Source/DataSources/KmlDataSource.js +62 -63
  110. package/Source/DataSources/exportKml.js +27 -30
  111. package/Source/Scene/ArcGisMapService.js +1 -1
  112. package/Source/Scene/Azure2DImageryProvider.js +308 -0
  113. package/Source/Scene/Billboard.js +4 -0
  114. package/Source/Scene/BillboardCollection.js +9 -2
  115. package/Source/Scene/ClippingPlaneCollection.js +3 -3
  116. package/Source/Scene/ClippingPolygon.js +91 -2
  117. package/Source/Scene/CreditDisplay.js +1 -1
  118. package/Source/Scene/GaussianSplat3DTileContent.js +54 -9
  119. package/Source/Scene/GaussianSplatPrimitive.js +49 -50
  120. package/Source/Scene/Google2DImageryProvider.js +614 -0
  121. package/Source/Scene/IonImageryProvider.js +22 -1
  122. package/Source/Scene/LabelCollection.js +1 -0
  123. package/Source/Scene/Material.js +248 -80
  124. package/Source/Scene/Primitive.js +6 -0
  125. package/Source/Scene/PrimitiveState.js +123 -0
  126. package/Source/Scene/Scene.js +2 -2
  127. package/Source/Scene/VoxelBoundsCollection.js +494 -0
  128. package/Source/Scene/VoxelBoxShape.js +236 -101
  129. package/Source/Scene/VoxelCylinderShape.js +315 -204
  130. package/Source/Scene/VoxelEllipsoidShape.js +402 -119
  131. package/Source/Scene/VoxelPrimitive.js +119 -84
  132. package/Source/Scene/VoxelRenderResources.js +17 -10
  133. package/Source/Scene/VoxelShape.js +21 -6
  134. package/Source/Scene/buildVoxelDrawCommands.js +61 -20
  135. package/Source/Scene/createGooglePhotorealistic3DTileset.js +1 -1
  136. package/Source/Scene/getClippingFunction.js +79 -88
  137. package/Source/Shaders/BillboardCollectionVS.glsl +2 -0
  138. package/Source/Shaders/BillboardCollectionVS.js +2 -0
  139. package/Source/Shaders/Voxels/IntersectBox.glsl +20 -33
  140. package/Source/Shaders/Voxels/IntersectBox.js +20 -33
  141. package/Source/Shaders/Voxels/IntersectCylinder.glsl +28 -32
  142. package/Source/Shaders/Voxels/IntersectCylinder.js +28 -32
  143. package/Source/Shaders/Voxels/IntersectDepth.glsl +1 -4
  144. package/Source/Shaders/Voxels/IntersectDepth.js +1 -4
  145. package/Source/Shaders/Voxels/IntersectEllipsoid.glsl +12 -20
  146. package/Source/Shaders/Voxels/IntersectEllipsoid.js +12 -20
  147. package/Source/Shaders/Voxels/IntersectLongitude.glsl +21 -9
  148. package/Source/Shaders/Voxels/IntersectLongitude.js +21 -9
  149. package/Source/Shaders/Voxels/{IntersectClippingPlanes.glsl → IntersectPlane.glsl} +5 -3
  150. package/Source/Shaders/Voxels/{IntersectClippingPlanes.js → IntersectPlane.js} +5 -3
  151. package/Source/Shaders/Voxels/Intersection.glsl +3 -3
  152. package/Source/Shaders/Voxels/Intersection.js +3 -3
  153. package/Source/Shaders/Voxels/Octree.glsl +46 -51
  154. package/Source/Shaders/Voxels/Octree.js +46 -51
  155. package/Source/Shaders/Voxels/VoxelFS.glsl +50 -48
  156. package/Source/Shaders/Voxels/VoxelFS.js +50 -48
  157. package/Source/Shaders/Voxels/VoxelUtils.glsl +0 -19
  158. package/Source/Shaders/Voxels/VoxelUtils.js +0 -19
  159. package/Source/Shaders/Voxels/convertLocalToBoxUv.glsl +30 -0
  160. package/Source/Shaders/Voxels/convertLocalToBoxUv.js +32 -0
  161. package/Source/Shaders/Voxels/convertLocalToCylinderUv.glsl +97 -0
  162. package/Source/Shaders/Voxels/convertLocalToCylinderUv.js +99 -0
  163. package/Source/Shaders/Voxels/convertLocalToEllipsoidUv.glsl +193 -0
  164. package/Source/Shaders/Voxels/convertLocalToEllipsoidUv.js +195 -0
  165. package/Source/ThirdParty/Workers/zip-web-worker.js +1 -0
  166. package/Source/ThirdParty/zip-module.wasm +0 -0
  167. package/index.d.ts +317 -14
  168. package/index.js +141 -139
  169. package/package.json +2 -2
  170. package/Build/ThirdParty/Workers/pako_deflate.min.js +0 -503
  171. package/Build/ThirdParty/Workers/pako_inflate.min.js +0 -698
  172. package/Build/ThirdParty/Workers/z-worker-pako.js +0 -601
  173. package/Source/Core/defaultValue.js +0 -48
  174. package/Source/Shaders/Voxels/convertUvToBox.glsl +0 -45
  175. package/Source/Shaders/Voxels/convertUvToBox.js +0 -46
  176. package/Source/Shaders/Voxels/convertUvToCylinder.glsl +0 -99
  177. package/Source/Shaders/Voxels/convertUvToCylinder.js +0 -101
  178. package/Source/Shaders/Voxels/convertUvToEllipsoid.glsl +0 -139
  179. package/Source/Shaders/Voxels/convertUvToEllipsoid.js +0 -141
  180. package/Source/ThirdParty/Workers/pako_deflate.min.js +0 -2
  181. package/Source/ThirdParty/Workers/pako_inflate.min.js +0 -2
  182. package/Source/ThirdParty/Workers/z-worker-pako.js +0 -1
@@ -327,12 +327,58 @@ function Material(options) {
327
327
 
328
328
  this._defaultTexture = undefined;
329
329
 
330
+ /**
331
+ * Any and all promises that are created when initializing the material.
332
+ * Examples: loading images and cubemaps.
333
+ *
334
+ * @type {Promise[]}
335
+ * @private
336
+ */
337
+ this._initializationPromises = [];
338
+
339
+ /**
340
+ * An error that occurred in async operations during material initialization.
341
+ * Only one error is stored.
342
+ *
343
+ * @type {Error|undefined}
344
+ * @private
345
+ */
346
+ this._initializationError = undefined;
347
+
330
348
  initializeMaterial(options, this);
331
349
  Object.defineProperties(this, {
332
350
  type: {
333
351
  value: this.type,
334
352
  writable: false,
335
353
  },
354
+
355
+ /**
356
+ * The {@link TextureMinificationFilter} to apply to this material's textures.
357
+ * @type {TextureMinificationFilter}
358
+ * @default TextureMinificationFilter.LINEAR
359
+ */
360
+ minificationFilter: {
361
+ get: function () {
362
+ return this._minificationFilter;
363
+ },
364
+ set: function (value) {
365
+ this._minificationFilter = value;
366
+ },
367
+ },
368
+
369
+ /**
370
+ * The {@link TextureMagnificationFilter} to apply to this material's textures.
371
+ * @type {TextureMagnificationFilter}
372
+ * @default TextureMagnificationFilter.LINEAR
373
+ */
374
+ magnificationFilter: {
375
+ get: function () {
376
+ return this._magnificationFilter;
377
+ },
378
+ set: function (value) {
379
+ this._magnificationFilter = value;
380
+ },
381
+ },
336
382
  });
337
383
 
338
384
  if (!defined(Material._uniformList[this.type])) {
@@ -384,6 +430,68 @@ Material.fromType = function (type, uniforms) {
384
430
  return material;
385
431
  };
386
432
 
433
+ /**
434
+ * Creates a new material using an existing material type and returns a promise that resolves when
435
+ * all of the material's resources have been loaded.
436
+ *
437
+ * @param {string} type The base material type.
438
+ * @param {object} [uniforms] Overrides for the default uniforms.
439
+ * @returns {Promise<Material>} A promise that resolves to a new material object when all resources are loaded.
440
+ *
441
+ * @exception {DeveloperError} material with that type does not exist.
442
+ *
443
+ * @example
444
+ * const material = await Cesium.Material.fromTypeAsync('Image', {
445
+ * image: '../Images/Cesium_Logo_overlay.png'
446
+ * });
447
+ */
448
+ Material.fromTypeAsync = async function (type, uniforms) {
449
+ //>>includeStart('debug', pragmas.debug);
450
+ if (!defined(Material._materialCache.getMaterial(type))) {
451
+ throw new DeveloperError(`material with type '${type}' does not exist.`);
452
+ }
453
+ //>>includeEnd('debug');
454
+
455
+ const initializationPromises = [];
456
+ // Unlike Material.fromType, we need to specify the uniforms in the Material constructor up front,
457
+ // or else anything that needs to be async loaded won't be kicked off until the next Update call.
458
+ const material = new Material({
459
+ fabric: {
460
+ type: type,
461
+ uniforms: uniforms,
462
+ },
463
+ });
464
+
465
+ // Recursively collect initialization promises for this material and its submaterials.
466
+ getInitializationPromises(material, initializationPromises);
467
+ await Promise.all(initializationPromises);
468
+ initializationPromises.length = 0;
469
+
470
+ if (defined(material._initializationError)) {
471
+ throw material._initializationError;
472
+ }
473
+
474
+ return material;
475
+ };
476
+
477
+ /**
478
+ * Recursively traverses the material and its submaterials to collect all initialization promises.
479
+ * @param {Material} material The material to traverse.
480
+ * @param {Promise[]} initializationPromises The array to collect promises into.
481
+ *
482
+ * @private
483
+ */
484
+ function getInitializationPromises(material, initializationPromises) {
485
+ initializationPromises.push(...material._initializationPromises);
486
+ const submaterials = material.materials;
487
+ for (const name in submaterials) {
488
+ if (submaterials.hasOwnProperty(name)) {
489
+ const submaterial = submaterials[name];
490
+ getInitializationPromises(submaterial, initializationPromises);
491
+ }
492
+ }
493
+ }
494
+
387
495
  /**
388
496
  * Gets whether or not this material is translucent.
389
497
  * @returns {boolean} <code>true</code> if this material is translucent, <code>false</code> otherwise.
@@ -586,6 +694,7 @@ function initializeMaterial(options, result) {
586
694
  result._strict = options.strict ?? false;
587
695
  result._count = options.count ?? 0;
588
696
  result._template = clone(options.fabric ?? Frozen.EMPTY_OBJECT);
697
+ result.fabric = clone(options.fabric ?? Frozen.EMPTY_OBJECT);
589
698
  result._template.uniforms = clone(
590
699
  result._template.uniforms ?? Frozen.EMPTY_OBJECT,
591
700
  );
@@ -616,15 +725,15 @@ function initializeMaterial(options, result) {
616
725
  // Make sure the template has no obvious errors. More error checking happens later.
617
726
  checkForTemplateErrors(result);
618
727
 
728
+ createMethodDefinition(result);
729
+ createUniforms(result);
730
+ createSubMaterials(result);
731
+
619
732
  // If the material has a new type, add it to the cache.
620
733
  if (!defined(cachedMaterial)) {
621
734
  Material._materialCache.addMaterial(result.type, result);
622
735
  }
623
736
 
624
- createMethodDefinition(result);
625
- createUniforms(result);
626
- createSubMaterials(result);
627
-
628
737
  const defaultTranslucent =
629
738
  result._translucentFunctions.length === 0 ? true : undefined;
630
739
  translucent = translucent ?? defaultTranslucent;
@@ -858,10 +967,10 @@ function createTexture2DUpdateFunction(uniformId) {
858
967
  texture.destroy();
859
968
  }
860
969
  texture = undefined;
970
+ material._texturePaths[uniformId] = undefined;
861
971
  }
862
972
 
863
973
  if (!defined(texture)) {
864
- material._texturePaths[uniformId] = undefined;
865
974
  texture = material._textures[uniformId] = material._defaultTexture;
866
975
 
867
976
  uniformDimensionsName = `${uniformId}Dimensions`;
@@ -876,59 +985,90 @@ function createTexture2DUpdateFunction(uniformId) {
876
985
  return;
877
986
  }
878
987
 
879
- // When using the entity layer, the Resource objects get recreated on getValue because
880
- // they are clonable. That's why we check the url property for Resources
881
- // because the instances aren't the same and we keep trying to load the same
882
- // image if it fails to load.
883
- const isResource = uniformValue instanceof Resource;
884
988
  if (
885
- !defined(material._texturePaths[uniformId]) ||
886
- (isResource &&
887
- uniformValue.url !== material._texturePaths[uniformId].url) ||
888
- (!isResource && uniformValue !== material._texturePaths[uniformId])
889
- ) {
890
- if (typeof uniformValue === "string" || isResource) {
891
- const resource = isResource
892
- ? uniformValue
893
- : Resource.createIfNeeded(uniformValue);
894
-
895
- let promise;
896
- if (ktx2Regex.test(resource.url)) {
897
- promise = loadKTX2(resource.url);
898
- } else {
899
- promise = resource.fetchImage();
900
- }
901
-
902
- Promise.resolve(promise)
903
- .then(function (image) {
904
- material._loadedImages.push({
905
- id: uniformId,
906
- image: image,
907
- });
908
- })
909
- .catch(function () {
910
- if (defined(texture) && texture !== material._defaultTexture) {
911
- texture.destroy();
912
- }
913
- material._textures[uniformId] = material._defaultTexture;
914
- });
915
- } else if (
916
- uniformValue instanceof HTMLCanvasElement ||
989
+ (uniformValue instanceof HTMLCanvasElement ||
917
990
  uniformValue instanceof HTMLImageElement ||
918
991
  uniformValue instanceof ImageBitmap ||
919
- uniformValue instanceof OffscreenCanvas
920
- ) {
921
- material._loadedImages.push({
922
- id: uniformId,
923
- image: uniformValue,
924
- });
925
- }
926
-
992
+ uniformValue instanceof OffscreenCanvas) &&
993
+ uniformValue !== material._texturePaths[uniformId]
994
+ ) {
995
+ material._loadedImages.push({
996
+ id: uniformId,
997
+ image: uniformValue,
998
+ });
927
999
  material._texturePaths[uniformId] = uniformValue;
1000
+ return;
928
1001
  }
1002
+
1003
+ // If we get to this point, the image should be a string URL or Resource.
1004
+ // Don't wait on the promise to resolve, just start loading the image and poll status from the update loop.
1005
+ loadTexture2DImageForUniform(material, uniformId);
929
1006
  };
930
1007
  }
931
1008
 
1009
+ /**
1010
+ * For a given uniform ID, potentially loads a texture image for the material, if the uniform value is a Resource or string URL,
1011
+ * and has changed since the last time this was called (either on construction or update).
1012
+ *
1013
+ * @param {Material} material The material to load the texture for.
1014
+ * @param {string} uniformId The ID of the uniform of the image.
1015
+ * @returns A promise that resolves when the image is loaded, or a resolved promise if image loading is not necessary.
1016
+ *
1017
+ * @private
1018
+ */
1019
+ function loadTexture2DImageForUniform(material, uniformId) {
1020
+ const uniforms = material.uniforms;
1021
+ const uniformValue = uniforms[uniformId];
1022
+ if (uniformValue === Material.DefaultImageId) {
1023
+ return Promise.resolve();
1024
+ }
1025
+
1026
+ // Attempt to make a resource from the uniform value. If it's not already a resource or string, this returns the original object.
1027
+ const resource = Resource.createIfNeeded(uniformValue);
1028
+ if (!(resource instanceof Resource)) {
1029
+ return Promise.resolve();
1030
+ }
1031
+
1032
+ // When using the entity layer, the Resource objects get recreated on getValue because
1033
+ // they are clonable. That's why we check the url property for Resources
1034
+ // because the instances aren't the same and we keep trying to load the same
1035
+ // image if it fails to load.
1036
+ const oldResource = Resource.createIfNeeded(
1037
+ material._texturePaths[uniformId],
1038
+ );
1039
+ const uniformHasChanged =
1040
+ !defined(oldResource) || oldResource.url !== resource.url;
1041
+ if (!uniformHasChanged) {
1042
+ return Promise.resolve();
1043
+ }
1044
+
1045
+ let promise;
1046
+ if (ktx2Regex.test(resource.url)) {
1047
+ promise = loadKTX2(resource.url);
1048
+ } else {
1049
+ promise = resource.fetchImage();
1050
+ }
1051
+
1052
+ Promise.resolve(promise)
1053
+ .then(function (image) {
1054
+ material._loadedImages.push({
1055
+ id: uniformId,
1056
+ image: image,
1057
+ });
1058
+ })
1059
+ .catch(function (error) {
1060
+ material._initializationError = error;
1061
+ const texture = material._textures[uniformId];
1062
+ if (defined(texture) && texture !== material._defaultTexture) {
1063
+ texture.destroy();
1064
+ }
1065
+ material._textures[uniformId] = material._defaultTexture;
1066
+ });
1067
+
1068
+ material._texturePaths[uniformId] = uniformValue;
1069
+ return promise;
1070
+ }
1071
+
932
1072
  function createCubeMapUpdateFunction(uniformId) {
933
1073
  return function (material, context) {
934
1074
  const uniformValue = material.uniforms[uniformId];
@@ -944,42 +1084,64 @@ function createCubeMapUpdateFunction(uniformId) {
944
1084
  }
945
1085
 
946
1086
  if (!defined(material._textures[uniformId])) {
947
- material._texturePaths[uniformId] = undefined;
948
1087
  material._textures[uniformId] = context.defaultCubeMap;
949
1088
  }
950
1089
 
951
- if (uniformValue === Material.DefaultCubeMapId) {
952
- return;
953
- }
1090
+ loadCubeMapImagesForUniform(material, uniformId);
1091
+ };
1092
+ }
954
1093
 
955
- const path =
956
- uniformValue.positiveX +
957
- uniformValue.negativeX +
958
- uniformValue.positiveY +
959
- uniformValue.negativeY +
960
- uniformValue.positiveZ +
961
- uniformValue.negativeZ;
962
-
963
- if (path !== material._texturePaths[uniformId]) {
964
- const promises = [
965
- Resource.createIfNeeded(uniformValue.positiveX).fetchImage(),
966
- Resource.createIfNeeded(uniformValue.negativeX).fetchImage(),
967
- Resource.createIfNeeded(uniformValue.positiveY).fetchImage(),
968
- Resource.createIfNeeded(uniformValue.negativeY).fetchImage(),
969
- Resource.createIfNeeded(uniformValue.positiveZ).fetchImage(),
970
- Resource.createIfNeeded(uniformValue.negativeZ).fetchImage(),
971
- ];
972
-
973
- Promise.all(promises).then(function (images) {
974
- material._loadedCubeMaps.push({
975
- id: uniformId,
976
- images: images,
977
- });
1094
+ /**
1095
+ * Loads the images for a cubemap uniform, if it has changed since the last time this was called.
1096
+ *
1097
+ * @param {Material} material The material to load the cubemap images for.
1098
+ * @param {string} uniformId The ID of the uniform that corresponds to the cubemap images.
1099
+ * @returns A promise that resolves when the images are loaded, or a resolved promise if image loading is not necessary.
1100
+ */
1101
+ function loadCubeMapImagesForUniform(material, uniformId) {
1102
+ const uniforms = material.uniforms;
1103
+ const uniformValue = uniforms[uniformId];
1104
+ if (uniformValue === Material.DefaultCubeMapId) {
1105
+ return Promise.resolve();
1106
+ }
1107
+
1108
+ const path =
1109
+ uniformValue.positiveX +
1110
+ uniformValue.negativeX +
1111
+ uniformValue.positiveY +
1112
+ uniformValue.negativeY +
1113
+ uniformValue.positiveZ +
1114
+ uniformValue.negativeZ;
1115
+
1116
+ // The uniform value is unchanged, no update / image load necessary.
1117
+ if (path === material._texturePaths[uniformId]) {
1118
+ return Promise.resolve();
1119
+ }
1120
+
1121
+ const promises = [
1122
+ Resource.createIfNeeded(uniformValue.positiveX).fetchImage(),
1123
+ Resource.createIfNeeded(uniformValue.negativeX).fetchImage(),
1124
+ Resource.createIfNeeded(uniformValue.positiveY).fetchImage(),
1125
+ Resource.createIfNeeded(uniformValue.negativeY).fetchImage(),
1126
+ Resource.createIfNeeded(uniformValue.positiveZ).fetchImage(),
1127
+ Resource.createIfNeeded(uniformValue.negativeZ).fetchImage(),
1128
+ ];
1129
+
1130
+ const allPromise = Promise.all(promises);
1131
+ allPromise
1132
+ .then(function (images) {
1133
+ material._loadedCubeMaps.push({
1134
+ id: uniformId,
1135
+ images: images,
978
1136
  });
1137
+ })
1138
+ .catch(function (error) {
1139
+ material._initializationError = error;
1140
+ });
979
1141
 
980
- material._texturePaths[uniformId] = path;
981
- }
982
- };
1142
+ material._texturePaths[uniformId] = path;
1143
+
1144
+ return allPromise;
983
1145
  }
984
1146
 
985
1147
  function createUniforms(material) {
@@ -1059,11 +1221,17 @@ function createUniform(material, uniformId) {
1059
1221
  return material._textures[uniformId];
1060
1222
  };
1061
1223
  material._updateFunctions.push(createTexture2DUpdateFunction(uniformId));
1224
+ material._initializationPromises.push(
1225
+ loadTexture2DImageForUniform(material, uniformId),
1226
+ );
1062
1227
  } else if (uniformType === "samplerCube") {
1063
1228
  material._uniforms[newUniformId] = function () {
1064
1229
  return material._textures[uniformId];
1065
1230
  };
1066
1231
  material._updateFunctions.push(createCubeMapUpdateFunction(uniformId));
1232
+ material._initializationPromises.push(
1233
+ loadCubeMapImagesForUniform(material, uniformId),
1234
+ );
1067
1235
  } else if (uniformType.indexOf("mat") !== -1) {
1068
1236
  const scratchMatrix = new matrixMap[uniformType]();
1069
1237
  material._uniforms[newUniformId] = function () {
@@ -2489,10 +2489,16 @@ Primitive.prototype.destroy = function () {
2489
2489
  function setReady(primitive, frameState, state, error) {
2490
2490
  primitive._error = error;
2491
2491
  primitive._state = state;
2492
+
2492
2493
  frameState.afterRender.push(function () {
2493
2494
  primitive._ready =
2494
2495
  primitive._state === PrimitiveState.COMPLETE ||
2495
2496
  primitive._state === PrimitiveState.FAILED;
2497
+
2498
+ // Returning 'true' here will ensure that another rendering pass is
2499
+ // triggered after the primitive actually became ready, to make sure
2500
+ // that it is in fact rendered even in "request render mode"
2501
+ return true;
2496
2502
  });
2497
2503
  }
2498
2504
  export default Primitive;
@@ -1,13 +1,136 @@
1
1
  /**
2
+ * The states that describe the lifecycle of a <code>Primitive</code>, as
3
+ * represented by the <code>primitive._state</code>.
4
+ *
5
+ * The state transitions are triggered by calls to the <code>update</code>
6
+ * function, but the actual state changes may happen asynchronously if the
7
+ * <code>asynchronous</code> flag of the primitive was set to
8
+ * <code>true</code>.
9
+ *
2
10
  * @private
3
11
  */
4
12
  const PrimitiveState = {
13
+ /**
14
+ * The initial state of a primitive.
15
+ *
16
+ * Note that this does NOT mean that the primitive is "ready", as indicated
17
+ * by the <code>_ready</code> property. It means the opposite: Nothing was
18
+ * done with the primitive at all.
19
+ *
20
+ * For primitives that are created with the <code>asynchronous:true</code>
21
+ * setting and that are in this state, the <code>update</code> call starts
22
+ * the creation of the geometry using web workers, and the primitive goes
23
+ * into the <code>CREATING</code> state.
24
+ *
25
+ * For synchronously created primitives, this state never matters. They will
26
+ * go into the COMBINED (or FAILED) state directly due to a call to the
27
+ * <code>update</code> function, if they are not yet FAILED, COMBINED,
28
+ * or COMPLETE.
29
+ */
5
30
  READY: 0,
31
+
32
+ /**
33
+ * The process of creating the primitive geometry is ongoing.
34
+ *
35
+ * A primitive can only ever be in this state when it was created
36
+ * with the <code>asynchronous:true</code> setting.
37
+ *
38
+ * It means that web workers are currently creating the geometry
39
+ * of the primitive.
40
+ *
41
+ * When the geometry creation succeeds, then the primitive will go
42
+ * into the CREATED state. Otherwise, it will go into the FAILED
43
+ * state. Both will happen asynchronously.
44
+ *
45
+ * The <code>update</code> function has to be called regularly
46
+ * until either of these states is reached.
47
+ */
6
48
  CREATING: 1,
49
+
50
+ /**
51
+ * The geometry for the primitive has been created.
52
+ *
53
+ * A primitive can only ever be in this state when it was created
54
+ * with the <code>asynchronous:true</code> setting.
55
+ *
56
+ * It means that web workers have (asynchronously) finished the
57
+ * creation of the geometry, but further (asynchronous) processing
58
+ * is necessary: If a primitive is determined to be in this state
59
+ * during a call to <code>update</code>, an asynchronous process
60
+ * is triggered to "combine" the geometry, meaning that the primitive
61
+ * will go into the COMBINING state.
62
+ */
7
63
  CREATED: 2,
64
+
65
+ /**
66
+ * The asynchronous creation of the geometry has been finished, but the
67
+ * asynchronous process of combining the geometry has not finished yet.
68
+ *
69
+ * A primitive can only ever be in this state when it was created
70
+ * with the <code>asynchronous:true</code> setting.
71
+ *
72
+ * It means that whatever is done with
73
+ * <code>PrimitivePipeline.packCombineGeometryParameters</code> has
74
+ * not finished yet. When combining the geometry succeeds, the
75
+ * primitive will go into the COMBINED state. Otherwise, it will
76
+ * go into the FAILED state.
77
+ */
8
78
  COMBINING: 3,
79
+
80
+ /**
81
+ * The geometry data is in a form that can be uploaded to the GPU.
82
+ *
83
+ * For <i>synchronous</i> primitives, this means that the geometry
84
+ * has been created (synchronously) due to the first call to the
85
+ * <code>update</code> function.
86
+ *
87
+ * For <i>asynchronous</i> primitives, this means that the asynchronous
88
+ * creation of the geometry and the asynchronous combination of the
89
+ * geometry have both finished.
90
+ *
91
+ * The <code>update</code> function has to be called regularly until
92
+ * this state is reached. When it is reached, the <code>update</code>
93
+ * call will cause the transition into the COMPLETE state.
94
+ */
9
95
  COMBINED: 4,
96
+
97
+ /**
98
+ * The geometry has been created and uploaded to the GPU.
99
+ *
100
+ * When this state is reached, it eventually causes the <code>_ready</code>
101
+ * flag of the primitive to become <code>true</code>.
102
+ *
103
+ * Note: Setting the <code>ready</code> flag does NOT happen in the
104
+ * <code>update</code> call: It only happens after rendering the next
105
+ * frame!
106
+ *
107
+ * Note: This state does not mean that nothing has to be done
108
+ * anymore (so the work is not "complete"). When the primitive is in
109
+ * this state, the <code>update</code> function still has to be
110
+ * called regularly.
111
+ */
10
112
  COMPLETE: 5,
113
+
114
+ /**
115
+ * The creation of the primitive failed.
116
+ *
117
+ * When this state is reached, it eventually causes the <code>_ready</code>
118
+ * flag of the primitive to become <code>true</code>.
119
+ *
120
+ * Note: Setting the <code>ready</code> flag does NOT happen in the
121
+ * <code>update</code> call: It only happens after rendering the next
122
+ * frame!
123
+ *
124
+ * This state can be reached when the (synchronous or asynchronous)
125
+ * creation of the geometry, or the (asynchronous) combination of
126
+ * the geometry caused any form of error.
127
+ *
128
+ * It may or may not imply the presence of the <code>_error</code> property.
129
+ * When the <code>_error</code> property is present on a FAILED primitive,
130
+ * this error will be thrown during the <code>update</code> call. When it
131
+ * is not present for a FAILED primitive, then the <code>update</code> call
132
+ * will do nothing.
133
+ */
11
134
  FAILED: 6,
12
135
  };
13
136
  export default Object.freeze(PrimitiveState);
@@ -100,8 +100,8 @@ const requestRenderAfterFrame = function (scene) {
100
100
  * @param {object} options Object with the following properties:
101
101
  * @param {HTMLCanvasElement} options.canvas The HTML canvas element to create the scene for.
102
102
  * @param {ContextOptions} [options.contextOptions] Context and WebGL creation properties.
103
- * @param {Element} [options.creditContainer] The HTML element in which the credits will be displayed.
104
- * @param {Element} [options.creditViewport] The HTML element in which to display the credit popup. If not specified, the viewport will be a added as a sibling of the canvas.
103
+ * @param {Element} [options.creditContainer] The HTML element in which the credits will be displayed. If not specified, a credit container will be created and added as a sibling of the canvas.
104
+ * @param {Element} [options.creditViewport] The HTML element in which to display the credit popup. If not specified, the viewport will be added as a sibling of the canvas.
105
105
  * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.default] The default ellipsoid. If not specified, the default ellipsoid is used.
106
106
  * @param {MapProjection} [options.mapProjection=new GeographicProjection(options.ellipsoid)] The map projection to use in 2D and Columbus View modes.
107
107
  * @param {boolean} [options.orderIndependentTranslucency=true] If true and the configuration supports it, use order independent translucency.