@cesium/engine 21.0.1 → 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 (267) 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-TGJQMEL4.js → chunk-2AM4E2WD.js} +2 -2
  4. package/Build/Workers/{chunk-4CORGH7N.js → chunk-2MWF4IES.js} +16 -14
  5. package/Build/Workers/{chunk-3RKX3UFI.js → chunk-2RCIRXNI.js} +1 -1
  6. package/Build/Workers/{chunk-LV3G32QE.js → chunk-3YTMGEXW.js} +5 -1424
  7. package/Build/Workers/{chunk-PJAA7QSC.js → chunk-4BHWJWS3.js} +6 -6
  8. package/Build/Workers/{chunk-FE565QHX.js → chunk-5JKH4AMT.js} +2 -2
  9. package/Build/Workers/{chunk-KZ7GDSAJ.js → chunk-6HKAPCSO.js} +1 -1
  10. package/Build/Workers/{chunk-VVALNLSH.js → chunk-A53R2F2L.js} +4 -4
  11. package/Build/Workers/{chunk-KVB73ECP.js → chunk-A6YFUGJO.js} +7 -7
  12. package/Build/Workers/{chunk-QNOIRRJK.js → chunk-AJYWXC6I.js} +4 -4
  13. package/Build/Workers/{chunk-UKA7OISV.js → chunk-AOIO5VUS.js} +282 -2284
  14. package/Build/Workers/{chunk-OBS5EMZ6.js → chunk-B7JRBTT6.js} +10 -10
  15. package/Build/Workers/{chunk-5YXA47QD.js → chunk-CHNDJRYA.js} +20 -18
  16. package/Build/Workers/{chunk-X3ZV3XNO.js → chunk-CJOV55CW.js} +20 -18
  17. package/Build/Workers/{chunk-W6I3LNPF.js → chunk-COGPE5Z2.js} +10 -8
  18. package/Build/Workers/{chunk-2QPH5QDK.js → chunk-CW7W27IZ.js} +14 -10
  19. package/Build/Workers/{chunk-MXOGBWMP.js → chunk-DICY26ID.js} +20 -16
  20. package/Build/Workers/{chunk-W6KMV4F5.js → chunk-DMEFNTUV.js} +69 -7
  21. package/Build/Workers/{chunk-T7HU6E7G.js → chunk-DQSJEOZY.js} +1 -1
  22. package/Build/Workers/{chunk-ASVODZNK.js → chunk-GDU4RZSZ.js} +16 -36
  23. package/Build/Workers/{chunk-MQPDOWGH.js → chunk-GKWOUMYA.js} +1 -1
  24. package/Build/Workers/{chunk-A2SP2EJZ.js → chunk-GTY4K4IA.js} +9 -7
  25. package/Build/Workers/{chunk-KEPPNSBL.js → chunk-H6Q7E4BQ.js} +8 -6
  26. package/Build/Workers/{chunk-JG3C3LPY.js → chunk-HHGOFZVQ.js} +7 -5
  27. package/Build/Workers/chunk-HXKUEOOD.js +352 -0
  28. package/Build/Workers/{chunk-UFSYRVC5.js → chunk-I4REFVXB.js} +4 -4
  29. package/Build/Workers/{chunk-LU7DLY2L.js → chunk-IL5F6WEE.js} +3 -3
  30. package/Build/Workers/{chunk-RVRN4KDB.js → chunk-JKXPC5HD.js} +2 -2
  31. package/Build/Workers/{chunk-CBPNIEGH.js → chunk-KKGD7HAW.js} +13 -11
  32. package/Build/Workers/{chunk-DTKSVIH5.js → chunk-KROSQJUA.js} +2 -2
  33. package/Build/Workers/{chunk-42EJCSIV.js → chunk-L4JLDVCM.js} +5 -5
  34. package/Build/Workers/{chunk-LPKJSIMD.js → chunk-LIYMRHGR.js} +15 -13
  35. package/Build/Workers/{chunk-J2XQVKVH.js → chunk-MKMZHRB3.js} +74 -35
  36. package/Build/Workers/{chunk-CSDYSXBI.js → chunk-MO25ZQ2I.js} +14 -12
  37. package/Build/Workers/{chunk-3YNW5K6O.js → chunk-O6RZEKHZ.js} +12 -12
  38. package/Build/Workers/{chunk-RR3NCT4R.js → chunk-OOCGX2OD.js} +4 -4
  39. package/Build/Workers/{chunk-XG54SG4O.js → chunk-OXFU5HNU.js} +13 -5
  40. package/Build/Workers/{chunk-P2UKEFCK.js → chunk-P5CGIJUY.js} +2 -2
  41. package/Build/Workers/{chunk-DBHL2UVG.js → chunk-QEANVUGT.js} +2 -2
  42. package/Build/Workers/{chunk-2SI7DEW5.js → chunk-QFBCIX7J.js} +8 -6
  43. package/Build/Workers/{chunk-DDXI6UYW.js → chunk-QUAH3XOT.js} +4 -4
  44. package/Build/Workers/{chunk-PZUZCAX3.js → chunk-RXZDTDIY.js} +13 -9
  45. package/Build/Workers/{chunk-YZ3RCE45.js → chunk-SPA2KPH3.js} +14 -12
  46. package/Build/Workers/chunk-TDSVSW5A.js +1460 -0
  47. package/Build/Workers/{chunk-G3CKZ34K.js → chunk-UG2DPFOL.js} +8 -6
  48. package/Build/Workers/{chunk-IKUOV6DO.js → chunk-URGEDZBS.js} +7 -7
  49. package/Build/Workers/{chunk-U2GR5FDL.js → chunk-V35NQOJC.js} +21 -11
  50. package/Build/Workers/chunk-W4XUEDU5.js +2058 -0
  51. package/Build/Workers/chunk-WB4TSSBQ.js +3514 -0
  52. package/Build/Workers/{chunk-EBDZDBJN.js → chunk-WTLYD4FE.js} +19 -15
  53. package/Build/Workers/{chunk-WQZL6CA2.js → chunk-Y4ALZ4SS.js} +9 -7
  54. package/Build/Workers/{chunk-DAJKOQW6.js → chunk-YF2NVO5B.js} +19 -13
  55. package/Build/Workers/{chunk-XJVRYJVZ.js → chunk-YSYSXSHF.js} +1 -1
  56. package/Build/Workers/{chunk-YNOVMSUX.js → chunk-YX562XOB.js} +15 -11
  57. package/Build/Workers/{chunk-J3KPR6DJ.js → chunk-YZWA5B4R.js} +15 -13
  58. package/Build/Workers/{chunk-NYYQZ3LH.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 +28 -22
  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 +91 -0
  97. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +28 -23
  98. package/Build/Workers/createVerticesFromHeightmap.js +28 -23
  99. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +26 -279
  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 +95 -0
  112. package/Source/Core/ArcGISTiledElevationTerrainProvider.js +2 -2
  113. package/Source/Core/AxisAlignedBoundingBox.js +36 -0
  114. package/Source/Core/Cesium3DTilesTerrainData.js +932 -0
  115. package/Source/Core/Cesium3DTilesTerrainGeometryProcessor.js +1868 -0
  116. package/Source/Core/Cesium3DTilesTerrainProvider.js +1052 -0
  117. package/Source/Core/CesiumTerrainProvider.js +2 -2
  118. package/Source/Core/Color.js +23 -6
  119. package/Source/Core/EllipsoidalOccluder.js +2 -2
  120. package/Source/Core/FeatureDetection.js +0 -2
  121. package/Source/Core/GoogleEarthEnterpriseMetadata.js +1 -1
  122. package/Source/Core/GoogleEarthEnterpriseTerrainData.js +2 -1
  123. package/Source/Core/GoogleEarthEnterpriseTerrainProvider.js +1 -1
  124. package/Source/Core/HeightmapTerrainData.js +12 -22
  125. package/Source/Core/HilbertOrder.js +0 -6
  126. package/Source/Core/ITwinPlatform.js +6 -6
  127. package/Source/Core/IntersectionTests.js +80 -0
  128. package/Source/Core/Ion.js +1 -1
  129. package/Source/Core/IonResource.js +35 -27
  130. package/Source/Core/PixelFormat.js +2 -2
  131. package/Source/Core/QuantizedMeshTerrainData.js +24 -57
  132. package/Source/Core/Resource.js +15 -11
  133. package/Source/Core/S2Cell.js +6 -18
  134. package/Source/Core/TaskProcessor.js +1 -1
  135. package/Source/Core/TerrainData.js +2 -1
  136. package/Source/Core/TerrainEncoding.js +215 -38
  137. package/Source/Core/TerrainMesh.js +215 -8
  138. package/Source/Core/TerrainPicker.js +607 -0
  139. package/Source/Core/TerrainProvider.js +151 -0
  140. package/Source/Core/TexturePacker.js +27 -12
  141. package/Source/Core/Transforms.js +28 -19
  142. package/Source/Core/VRTheWorldTerrainProvider.js +2 -2
  143. package/Source/Core/binarySearch.js +1 -1
  144. package/Source/Core/createWorldBathymetryAsync.js +2 -2
  145. package/Source/Core/createWorldTerrainAsync.js +3 -3
  146. package/Source/Core/loadImageFromTypedArray.js +9 -3
  147. package/Source/Core/mergeSort.js +1 -1
  148. package/Source/DataSources/BillboardGraphics.js +1 -1
  149. package/Source/DataSources/BillboardVisualizer.js +7 -4
  150. package/Source/DataSources/PropertyArray.js +2 -2
  151. package/Source/Renderer/AutomaticUniforms.js +61 -0
  152. package/Source/Renderer/Buffer.js +32 -0
  153. package/Source/Renderer/BufferUsage.js +3 -1
  154. package/Source/Renderer/Context.js +98 -14
  155. package/Source/Renderer/Pass.js +10 -9
  156. package/Source/Renderer/Sync.js +104 -0
  157. package/Source/Renderer/TextureAtlas.js +67 -27
  158. package/Source/Renderer/UniformState.js +12 -0
  159. package/Source/Renderer/VertexArray.js +1 -1
  160. package/Source/Scene/ArcGisMapServerImageryProvider.js +1 -1
  161. package/Source/Scene/ArcGisMapService.js +1 -1
  162. package/Source/Scene/Azure2DImageryProvider.js +99 -13
  163. package/Source/Scene/BatchTable.js +2 -2
  164. package/Source/Scene/Billboard.js +75 -28
  165. package/Source/Scene/BillboardCollection.js +24 -15
  166. package/Source/Scene/BillboardTexture.js +56 -7
  167. package/Source/Scene/BingMapsImageryProvider.js +1 -1
  168. package/Source/Scene/BoundingVolumeSemantics.js +54 -62
  169. package/Source/Scene/Cesium3DTile.js +3 -3
  170. package/Source/Scene/Cesium3DTilesVoxelProvider.js +1 -1
  171. package/Source/Scene/Cesium3DTileset.js +1 -1
  172. package/Source/Scene/EdgeFramebuffer.js +245 -0
  173. package/Source/Scene/FrameState.js +12 -0
  174. package/Source/Scene/GaussianSplat3DTileContent.js +12 -16
  175. package/Source/Scene/GaussianSplatPrimitive.js +12 -8
  176. package/Source/Scene/GaussianSplatSorter.js +2 -2
  177. package/Source/Scene/Globe.js +4 -2
  178. package/Source/Scene/GlobeSurfaceTile.js +28 -70
  179. package/Source/Scene/GlobeSurfaceTileProvider.js +11 -0
  180. package/Source/Scene/GltfBufferViewLoader.js +18 -0
  181. package/Source/Scene/GltfLoader.js +46 -8
  182. package/Source/Scene/Google2DImageryProvider.js +48 -41
  183. package/Source/Scene/GoogleEarthEnterpriseMapsProvider.js +1 -1
  184. package/Source/Scene/I3SDataProvider.js +1 -1
  185. package/Source/Scene/I3SDecoder.js +3 -3
  186. package/Source/Scene/ITwinData.js +4 -4
  187. package/Source/Scene/ImageryLayer.js +1 -1
  188. package/Source/Scene/Implicit3DTileContent.js +18 -7
  189. package/Source/Scene/ImplicitSubtree.js +3 -3
  190. package/Source/Scene/ImplicitTileset.js +2 -2
  191. package/Source/Scene/IonImageryProvider.js +15 -84
  192. package/Source/Scene/IonImageryProviderFactory.js +194 -0
  193. package/Source/Scene/LabelCollection.js +54 -36
  194. package/Source/Scene/MetadataComponentType.js +5 -5
  195. package/Source/Scene/MetadataTableProperty.js +3 -9
  196. package/Source/Scene/Model/EdgeDetectionPipelineStage.js +42 -0
  197. package/Source/Scene/Model/EdgeVisibilityPipelineStage.js +800 -0
  198. package/Source/Scene/Model/MetadataPipelineStage.js +7 -7
  199. package/Source/Scene/Model/ModelDrawCommand.js +69 -0
  200. package/Source/Scene/Model/ModelImagery.js +4 -0
  201. package/Source/Scene/Model/ModelRuntimeNode.js +2 -2
  202. package/Source/Scene/Model/ModelRuntimePrimitive.js +13 -2
  203. package/Source/Scene/Model/ModelSceneGraph.js +15 -3
  204. package/Source/Scene/Model/ModelUtility.js +0 -1
  205. package/Source/Scene/Model/NodeRenderResources.js +1 -1
  206. package/Source/Scene/Model/PrimitiveRenderResources.js +1 -1
  207. package/Source/Scene/OIT.js +11 -1
  208. package/Source/Scene/PickFramebuffer.js +134 -50
  209. package/Source/Scene/Picking.js +195 -89
  210. package/Source/Scene/QuadtreePrimitive.js +34 -26
  211. package/Source/Scene/QuadtreeTile.js +66 -46
  212. package/Source/Scene/ResourceLoaderState.js +1 -1
  213. package/Source/Scene/Scene.js +160 -16
  214. package/Source/Scene/ScreenSpaceCameraController.js +1 -1
  215. package/Source/Scene/SensorVolumePortionToDisplay.js +6 -6
  216. package/Source/Scene/SingleTileImageryProvider.js +3 -3
  217. package/Source/Scene/Terrain.js +5 -5
  218. package/Source/Scene/TerrainFillMesh.js +1 -0
  219. package/Source/Scene/TileMapServiceImageryProvider.js +2 -2
  220. package/Source/Scene/UrlTemplateImageryProvider.js +1 -1
  221. package/Source/Scene/View.js +3 -0
  222. package/Source/Scene/VoxelPrimitive.js +196 -189
  223. package/Source/Scene/VoxelShape.js +2 -0
  224. package/Source/Scene/createWorldImageryAsync.js +1 -1
  225. package/Source/Shaders/BillboardCollectionFS.glsl +115 -62
  226. package/Source/Shaders/BillboardCollectionFS.js +115 -63
  227. package/Source/Shaders/BillboardCollectionVS.glsl +44 -37
  228. package/Source/Shaders/BillboardCollectionVS.js +45 -38
  229. package/Source/Shaders/Builtin/Constants/passCesium3DTile.glsl +1 -1
  230. package/Source/Shaders/Builtin/Constants/passCesium3DTile.js +1 -1
  231. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassification.glsl +1 -1
  232. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassification.js +1 -1
  233. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassificationIgnoreShow.glsl +1 -1
  234. package/Source/Shaders/Builtin/Constants/passCesium3DTileClassificationIgnoreShow.js +1 -1
  235. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdges.glsl +10 -0
  236. package/Source/Shaders/Builtin/Constants/passCesium3DTileEdges.js +12 -0
  237. package/Source/Shaders/Builtin/Constants/passGaussianSplats.glsl +1 -1
  238. package/Source/Shaders/Builtin/Constants/passGaussianSplats.js +1 -1
  239. package/Source/Shaders/Builtin/Constants/passOpaque.glsl +1 -1
  240. package/Source/Shaders/Builtin/Constants/passOpaque.js +1 -1
  241. package/Source/Shaders/Builtin/Constants/passOverlay.glsl +1 -1
  242. package/Source/Shaders/Builtin/Constants/passOverlay.js +1 -1
  243. package/Source/Shaders/Builtin/Constants/passTranslucent.glsl +1 -1
  244. package/Source/Shaders/Builtin/Constants/passTranslucent.js +1 -1
  245. package/Source/Shaders/Builtin/Constants/passVoxels.glsl +1 -1
  246. package/Source/Shaders/Builtin/Constants/passVoxels.js +1 -1
  247. package/Source/Shaders/Builtin/CzmBuiltins.js +2 -0
  248. package/Source/Shaders/GlobeVS.glsl +1 -1
  249. package/Source/Shaders/GlobeVS.js +1 -1
  250. package/Source/Shaders/Model/EdgeDetectionStageFS.glsl +58 -0
  251. package/Source/Shaders/Model/EdgeDetectionStageFS.js +60 -0
  252. package/Source/Shaders/Model/EdgeVisibilityStageFS.glsl +83 -0
  253. package/Source/Shaders/Model/EdgeVisibilityStageFS.js +85 -0
  254. package/Source/Shaders/Model/ModelFS.glsl +5 -0
  255. package/Source/Shaders/Model/ModelFS.js +5 -0
  256. package/Source/Shaders/Model/PrimitiveOutlineStageFS.glsl +0 -1
  257. package/Source/Shaders/Model/PrimitiveOutlineStageFS.js +0 -1
  258. package/Source/Shaders/ShadowVolumeAppearanceFS.glsl +7 -15
  259. package/Source/Shaders/ShadowVolumeAppearanceFS.js +7 -15
  260. package/Source/ThirdParty/Workers/zip-web-worker.js +1 -1
  261. package/Source/ThirdParty/zip-module.wasm +0 -0
  262. package/Source/Workers/createVerticesFromCesium3DTilesTerrain.js +46 -0
  263. package/Source/Workers/incrementallyBuildTerrainPicker.js +108 -0
  264. package/Source/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +55 -0
  265. package/index.d.ts +488 -31
  266. package/index.js +202 -190
  267. package/package.json +3 -2
@@ -1,4 +1,5 @@
1
1
  import Check from "../Core/Check.js";
2
+ import Frozen from "../Core/Frozen.js";
2
3
  import Credit from "../Core/Credit.js";
3
4
  import defined from "../Core/defined.js";
4
5
  import Resource from "../Core/Resource.js";
@@ -14,7 +15,7 @@ const trailingSlashRegex = /\/$/;
14
15
  *
15
16
  * @property {object} options Object with the following properties:
16
17
  * @property {string} [options.url="https://atlas.microsoft.com/"] The Azure server url.
17
- * @property {string} [options.tilesetId="microsoft.imagery"] The Azure tileset ID. Valid options are {@link microsoft.imagery}, {@link microsoft.base.road}, and {@link microsoft.base.labels.road}
18
+ * @property {string} options.tilesetId="microsoft.imagery" The Azure tileset ID. Valid options are {@link microsoft.imagery}, {@link microsoft.base.road}, and {@link microsoft.base.labels.road}
18
19
  * @property {string} options.subscriptionKey The public subscription key for the imagery.
19
20
  * @property {Ellipsoid} [options.ellipsoid=Ellipsoid.default] The ellipsoid. If not specified, the default ellipsoid is used.
20
21
  * @property {number} [options.minimumLevel=0] The minimum level-of-detail supported by the imagery provider. Take care when specifying
@@ -29,7 +30,6 @@ const trailingSlashRegex = /\/$/;
29
30
  *
30
31
  * @alias Azure2DImageryProvider
31
32
  * @constructor
32
- * @private
33
33
  * @param {Azure2DImageryProvider.ConstructorOptions} options Object describing initialization options
34
34
  *
35
35
  * @example
@@ -41,16 +41,18 @@ const trailingSlashRegex = /\/$/;
41
41
  */
42
42
  function Azure2DImageryProvider(options) {
43
43
  options = options ?? {};
44
- options.maximumLevel = options.maximumLevel ?? 22;
45
- options.minimumLevel = options.minimumLevel ?? 0;
44
+ const tilesetId = options.tilesetId ?? "microsoft.imagery";
45
+ this._maximumLevel = options.maximumLevel ?? 22;
46
+ this._minimumLevel = options.minimumLevel ?? 0;
46
47
 
47
- const subscriptionKey =
48
+ this._subscriptionKey =
48
49
  options.subscriptionKey ?? options["subscription-key"];
49
50
  //>>includeStart('debug', pragmas.debug);
50
- Check.defined("options.tilesetId", options.tilesetId);
51
- Check.defined("options.subscriptionKey", subscriptionKey);
51
+ Check.defined("options.subscriptionKey", this._subscriptionKey);
52
52
  //>>includeEnd('debug');
53
53
 
54
+ this._tilesetId = options.tilesetId;
55
+
54
56
  const resource =
55
57
  options.url instanceof IonResource
56
58
  ? options.url
@@ -60,19 +62,23 @@ function Azure2DImageryProvider(options) {
60
62
  if (!trailingSlashRegex.test(templateUrl)) {
61
63
  templateUrl += "/";
62
64
  }
63
- templateUrl += `map/tile`;
64
65
 
65
- resource.url = templateUrl;
66
+ const tilesUrl = `${templateUrl}map/tile`;
67
+ this._viewportUrl = `${templateUrl}map/attribution`;
68
+
69
+ resource.url = tilesUrl;
66
70
 
67
71
  resource.setQueryParameters({
68
72
  "api-version": "2024-04-01",
69
- tilesetId: options.tilesetId,
73
+ tilesetId: tilesetId,
74
+ "subscription-key": this._subscriptionKey,
70
75
  zoom: `{z}`,
71
76
  x: `{x}`,
72
77
  y: `{y}`,
73
- "subscription-key": subscriptionKey,
74
78
  });
75
79
 
80
+ this._resource = resource;
81
+
76
82
  let credit;
77
83
  if (defined(options.credit)) {
78
84
  credit = options.credit;
@@ -83,6 +89,8 @@ function Azure2DImageryProvider(options) {
83
89
 
84
90
  const provider = new UrlTemplateImageryProvider({
85
91
  ...options,
92
+ maximumLevel: this._maximumLevel,
93
+ minimumLevel: this._minimumLevel,
86
94
  url: resource,
87
95
  credit: credit,
88
96
  });
@@ -91,6 +99,7 @@ function Azure2DImageryProvider(options) {
91
99
 
92
100
  // This will be defined for ion resources
93
101
  this._tileCredits = resource.credits;
102
+ this._attributionsByLevel = undefined;
94
103
  }
95
104
 
96
105
  Object.defineProperties(Azure2DImageryProvider.prototype, {
@@ -261,7 +270,18 @@ Object.defineProperties(Azure2DImageryProvider.prototype, {
261
270
  * @returns {Credit[]|undefined} The credits to be displayed when the tile is displayed.
262
271
  */
263
272
  Azure2DImageryProvider.prototype.getTileCredits = function (x, y, level) {
264
- return this._imageryProvider.getTileCredits(x, y, level);
273
+ const hasAttributions = defined(this._attributionsByLevel);
274
+
275
+ if (!hasAttributions || !defined(this._tileCredits)) {
276
+ return undefined;
277
+ }
278
+
279
+ const innerCredits = this._attributionsByLevel.get(level);
280
+ if (!defined(this._tileCredits)) {
281
+ return innerCredits;
282
+ }
283
+
284
+ return this._tileCredits.concat(innerCredits);
265
285
  };
266
286
 
267
287
  /**
@@ -280,7 +300,21 @@ Azure2DImageryProvider.prototype.requestImage = function (
280
300
  level,
281
301
  request,
282
302
  ) {
283
- return this._imageryProvider.requestImage(x, y, level, request);
303
+ const promise = this._imageryProvider.requestImage(x, y, level, request);
304
+
305
+ // If the requestImage call returns undefined, it couldn't be scheduled this frame. Make sure to return undefined so this can be handled upstream.
306
+ if (!defined(promise)) {
307
+ return undefined;
308
+ }
309
+
310
+ // Asynchronously request and populate _attributionsByLevel if it hasn't been already. We do this here so that the promise can be properly awaited.
311
+ if (!defined(this._attributionsByLevel)) {
312
+ return Promise.all([promise, this.getViewportCredits()]).then(
313
+ (results) => results[0],
314
+ );
315
+ }
316
+
317
+ return promise;
284
318
  };
285
319
 
286
320
  /**
@@ -304,5 +338,57 @@ Azure2DImageryProvider.prototype.pickFeatures = function (
304
338
  return undefined;
305
339
  };
306
340
 
341
+ /**
342
+ * Get attribution for imagery from Azure Maps to display in the credits
343
+ * @private
344
+ * @return {Promise<Map<Credit[]>>} The list of attribution sources to display in the credits.
345
+ */
346
+ Azure2DImageryProvider.prototype.getViewportCredits = async function () {
347
+ const maximumLevel = this._maximumLevel;
348
+
349
+ const promises = [];
350
+ for (let level = 0; level < maximumLevel + 1; level++) {
351
+ promises.push(
352
+ fetchViewportAttribution(
353
+ this._resource,
354
+ this._viewportUrl,
355
+ this._subscriptionKey,
356
+ this._tilesetId,
357
+ level,
358
+ ),
359
+ );
360
+ }
361
+ const results = await Promise.all(promises);
362
+
363
+ const attributionsByLevel = new Map();
364
+ for (let level = 0; level < maximumLevel + 1; level++) {
365
+ const credits = [];
366
+ const attributions = results[level].join(",");
367
+ if (attributions) {
368
+ const levelCredits = new Credit(attributions);
369
+ credits.push(levelCredits);
370
+ }
371
+ attributionsByLevel.set(level, credits);
372
+ }
373
+
374
+ this._attributionsByLevel = attributionsByLevel;
375
+
376
+ return attributionsByLevel;
377
+ };
378
+
379
+ async function fetchViewportAttribution(resource, url, key, tilesetId, level) {
380
+ const viewportResource = resource.getDerivedResource({
381
+ url,
382
+ queryParameters: {
383
+ zoom: level,
384
+ bounds: "-180,-90,180,90",
385
+ },
386
+ data: JSON.stringify(Frozen.EMPTY_OBJECT),
387
+ });
388
+
389
+ const viewportJson = await viewportResource.fetchJson();
390
+ return viewportJson.copyrights;
391
+ }
392
+
307
393
  // Exposed for tests
308
394
  export default Azure2DImageryProvider;
@@ -20,7 +20,7 @@ import Texture from "../Renderer/Texture.js";
20
20
  * @private
21
21
  *
22
22
  * @param {Context} context The context in which the batch table is created.
23
- * @param {Object[]} attributes An array of objects describing a per instance attribute. Each object contains a datatype, components per attributes, whether it is normalized and a function name
23
+ * @param {object[]} attributes An array of objects describing a per instance attribute. Each object contains a datatype, components per attributes, whether it is normalized and a function name
24
24
  * to retrieve the value in the vertex shader.
25
25
  * @param {number} numberOfInstances The number of instances in a batch table.
26
26
  *
@@ -131,7 +131,7 @@ Object.defineProperties(BatchTable.prototype, {
131
131
  /**
132
132
  * The attribute descriptions.
133
133
  * @memberOf BatchTable.prototype
134
- * @type {Object[]}
134
+ * @type {object[]}
135
135
  * @readonly
136
136
  */
137
137
  attributes: {
@@ -23,6 +23,8 @@ import SceneMode from "./SceneMode.js";
23
23
  import SceneTransforms from "./SceneTransforms.js";
24
24
  import VerticalOrigin from "./VerticalOrigin.js";
25
25
  import SplitDirection from "./SplitDirection.js";
26
+ import getExtensionFromUri from "../Core/getExtensionFromUri.js";
27
+ import isDataUri from "../Core/isDataUri.js";
26
28
 
27
29
  /**
28
30
  * @typedef {object} Billboard.ConstructorOptions
@@ -32,7 +34,7 @@ import SplitDirection from "./SplitDirection.js";
32
34
  * @property {Cartesian3} position The cartesian position of the billboard.
33
35
  * @property {*} [id] A user-defined object to return when the billboard is picked with {@link Scene#pick}.
34
36
  * @property {boolean} [show=true] Determines if this billboard will be shown.
35
- * @property {string | HTMLCanvasElement} [image] A loaded HTMLImageElement, ImageData, or a url to an image to use for the billboard.
37
+ * @property {string | HTMLImageElement | HTMLCanvasElement} [image] A loaded HTMLImageElement, ImageData, or a url to an image to use for the billboard.
36
38
  * @property {number} [scale=1.0] A number specifying the uniform scale that is multiplied with the billboard's image size in pixels.
37
39
  * @property {Cartesian2} [pixelOffset=Cartesian2.ZERO] A {@link Cartesian2} Specifying the pixel offset in screen space from the origin of this billboard.
38
40
  * @property {Cartesian3} [eyeOffset=Cartesian3.ZERO] A {@link Cartesian3} Specifying the 3D Cartesian offset applied to this billboard in eye coordinates.
@@ -189,31 +191,27 @@ function Billboard(options, billboardCollection) {
189
191
  this._batchIndex = undefined; // Used only by Vector3DTilePoints and BillboardCollection
190
192
 
191
193
  this._imageTexture = new BillboardTexture(billboardCollection);
194
+
195
+ this._imageId = options.imageId;
192
196
  this._imageWidth = undefined;
193
197
  this._imageHeight = undefined;
194
-
195
198
  this._labelDimensions = undefined;
196
199
  this._labelHorizontalOrigin = undefined;
197
200
  this._labelTranslate = undefined;
198
201
 
199
202
  const image = options.image;
200
- let imageId = options.imageId;
201
203
  if (defined(image)) {
202
- if (!defined(imageId)) {
203
- if (typeof image === "string") {
204
- imageId = image;
205
- } else if (defined(image.src)) {
206
- imageId = image.src;
207
- } else {
208
- imageId = createGuid();
209
- }
210
- }
211
-
212
- this._imageTexture.loadImage(imageId, image);
204
+ this._computeImageTextureProperties(options.imageId, image);
205
+ this._imageTexture.loadImage(
206
+ this._imageId,
207
+ image,
208
+ this._imageWidth,
209
+ this._imageHeight,
210
+ );
213
211
  }
214
212
 
215
213
  if (defined(options.imageSubRegion)) {
216
- this._imageTexture.addImageSubRegion(imageId, options.imageSubRegion);
214
+ this._imageTexture.addImageSubRegion(this._imageId, options.imageSubRegion);
217
215
  }
218
216
 
219
217
  this._actualClampedPosition = undefined;
@@ -947,18 +945,13 @@ Object.defineProperties(Billboard.prototype, {
947
945
  return;
948
946
  }
949
947
 
950
- let id;
951
- if (typeof value === "string") {
952
- id = value;
953
- } else if (value instanceof Resource) {
954
- id = value._url;
955
- } else if (defined(value.src)) {
956
- id = value.src;
957
- } else {
958
- id = createGuid();
959
- }
960
-
961
- this._imageTexture.loadImage(id, value);
948
+ this._computeImageTextureProperties(undefined, value);
949
+ this._imageTexture.loadImage(
950
+ this._imageId,
951
+ value,
952
+ this._imageWidth,
953
+ this._imageHeight,
954
+ );
962
955
  },
963
956
  },
964
957
 
@@ -1252,7 +1245,13 @@ Billboard.prototype.setImage = function (id, image) {
1252
1245
  Check.defined("image", image);
1253
1246
  //>>includeEnd('debug');
1254
1247
 
1255
- this._imageTexture.loadImage(id, image);
1248
+ this._computeImageTextureProperties(id, image);
1249
+ this._imageTexture.loadImage(
1250
+ this._imageId,
1251
+ image,
1252
+ this._imageWidth,
1253
+ this._imageHeight,
1254
+ );
1256
1255
  };
1257
1256
 
1258
1257
  /**
@@ -1268,6 +1267,54 @@ Billboard.prototype.setImageTexture = function (billboardTexture) {
1268
1267
  BillboardTexture.clone(billboardTexture, this._imageTexture);
1269
1268
  };
1270
1269
 
1270
+ /** Arbitrary limit on allocated SVG size, in pixels. Raster images use image resolution. */
1271
+ const SVG_MAX_SIZE_PX = 512;
1272
+
1273
+ /**
1274
+ * Computes billboard texture ID, width, and height. For raster images, width and height are left
1275
+ * undefined, defaulting to image resolution. For SVG, use billboard pixel width and height.
1276
+ * @param {string | undefined} id The id of the image.
1277
+ * @param {string | HTMLImageElement | HTMLCanvasElement | undefined} image A loaded HTMLImageElement, ImageData, or a url to an image to use for the billboard.
1278
+ * @private
1279
+ */
1280
+ Billboard.prototype._computeImageTextureProperties = function (id, image) {
1281
+ this._imageWidth = undefined;
1282
+ this._imageHeight = undefined;
1283
+
1284
+ if (!defined(image)) {
1285
+ this._imageId = createGuid();
1286
+ return;
1287
+ }
1288
+
1289
+ let imageUri;
1290
+ if (typeof image === "string") {
1291
+ imageUri = image;
1292
+ } else if (image instanceof Resource) {
1293
+ imageUri = image._url;
1294
+ } else if (defined(image.src)) {
1295
+ imageUri = image.src;
1296
+ }
1297
+
1298
+ this._imageId = id ?? imageUri ?? createGuid();
1299
+
1300
+ const hasSizeInPixels =
1301
+ defined(this._width) && defined(this._height) && !this._sizeInMeters;
1302
+
1303
+ if (hasSizeInPixels && isSvgUri(imageUri)) {
1304
+ this._imageWidth = Math.min(this._width, SVG_MAX_SIZE_PX);
1305
+ this._imageHeight = Math.min(this._height, SVG_MAX_SIZE_PX);
1306
+ }
1307
+ };
1308
+
1309
+ function isSvgUri(uri) {
1310
+ if (!defined(uri)) {
1311
+ return false;
1312
+ }
1313
+ return isDataUri(uri)
1314
+ ? uri.startsWith("data:image/svg+xml")
1315
+ : getExtensionFromUri(uri) === "svg";
1316
+ }
1317
+
1271
1318
  /**
1272
1319
  * Uses a sub-region of the image with the given id as the image for this billboard,
1273
1320
  * measured in pixels from the bottom-left.
@@ -13,7 +13,6 @@ import EncodedCartesian3 from "../Core/EncodedCartesian3.js";
13
13
  import IndexDatatype from "../Core/IndexDatatype.js";
14
14
  import CesiumMath from "../Core/Math.js";
15
15
  import Matrix4 from "../Core/Matrix4.js";
16
- import WebGLConstants from "../Core/WebGLConstants.js";
17
16
  import Buffer from "../Renderer/Buffer.js";
18
17
  import BufferUsage from "../Renderer/BufferUsage.js";
19
18
  import ContextLimits from "../Renderer/ContextLimits.js";
@@ -34,6 +33,8 @@ import SceneMode from "./SceneMode.js";
34
33
  import SDFSettings from "./SDFSettings.js";
35
34
  import TextureAtlas from "../Renderer/TextureAtlas.js";
36
35
  import VerticalOrigin from "./VerticalOrigin.js";
36
+ import Ellipsoid from "../Core/Ellipsoid.js";
37
+ import WebGLConstants from "../Core/WebGLConstants.js";
37
38
 
38
39
  const SHOW_INDEX = Billboard.SHOW_INDEX;
39
40
  const POSITION_INDEX = Billboard.POSITION_INDEX;
@@ -315,6 +316,8 @@ function BillboardCollection(options) {
315
316
  ];
316
317
 
317
318
  this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints
319
+ this._coarseDepthTestDistance = Ellipsoid.default.minimumRadius / 100;
320
+ this._threePointDepthTestDistance = Ellipsoid.default.minimumRadius / 1000;
318
321
 
319
322
  this._uniforms = {
320
323
  u_atlas: () => {
@@ -323,6 +326,16 @@ function BillboardCollection(options) {
323
326
  u_highlightColor: () => {
324
327
  return this._highlightColor;
325
328
  },
329
+ // An eye-space distance, beyond which, the billboard is simply tested against a camera-facing plane at the ellipsoid's center,
330
+ // rather than against a depth texture. Note: only if the disableDepthTestingDistance property permits.
331
+ u_coarseDepthTestDistance: () => {
332
+ return this._coarseDepthTestDistance;
333
+ },
334
+ // Within this distance, if the billboard is clamped to the ground, we'll depth-test 3 key points.
335
+ // If any key point is visible, the whole billboard will be visible.
336
+ u_threePointDepthTestDistance: () => {
337
+ return this._threePointDepthTestDistance;
338
+ },
326
339
  };
327
340
 
328
341
  const scene = this._scene;
@@ -1372,9 +1385,6 @@ function writeCompressedAttribute3(
1372
1385
  const clampToGround =
1373
1386
  isHeightReferenceClamp(billboard.heightReference) &&
1374
1387
  frameState.context.depthTexture;
1375
- if (!defined(disableDepthTestDistance)) {
1376
- disableDepthTestDistance = clampToGround ? 5000.0 : 0.0;
1377
- }
1378
1388
 
1379
1389
  disableDepthTestDistance *= disableDepthTestDistance;
1380
1390
  if (clampToGround || disableDepthTestDistance > 0.0) {
@@ -2042,7 +2052,6 @@ BillboardCollection.prototype.update = function (frameState) {
2042
2052
  // If OPAQUE_AND_TRANSLUCENT is in use, only the opaque pass gets the benefit of the depth buffer,
2043
2053
  // not the translucent pass. Otherwise, if the TRANSLUCENT pass is on its own, it turns on
2044
2054
  // a depthMask in lieu of full depth sorting (because it has opaque-ish fragments that look bad in OIT).
2045
- // When the TRANSLUCENT depth mask is in use, label backgrounds require the depth func to be LEQUAL.
2046
2055
  const useTranslucentDepthMask =
2047
2056
  this._blendOption === BlendOption.TRANSLUCENT;
2048
2057
 
@@ -2141,9 +2150,9 @@ BillboardCollection.prototype.update = function (frameState) {
2141
2150
  }
2142
2151
  if (this._shaderClampToGround) {
2143
2152
  if (supportVSTextureReads) {
2144
- vs.defines.push("VERTEX_DEPTH_CHECK");
2153
+ vs.defines.push("VS_THREE_POINT_DEPTH_CHECK");
2145
2154
  } else {
2146
- vs.defines.push("FRAGMENT_DEPTH_CHECK");
2155
+ vs.defines.push("FS_THREE_POINT_DEPTH_CHECK");
2147
2156
  }
2148
2157
  }
2149
2158
 
@@ -2162,9 +2171,9 @@ BillboardCollection.prototype.update = function (frameState) {
2162
2171
  });
2163
2172
  if (this._shaderClampToGround) {
2164
2173
  if (supportVSTextureReads) {
2165
- fs.defines.push("VERTEX_DEPTH_CHECK");
2174
+ fs.defines.push("VS_THREE_POINT_DEPTH_CHECK");
2166
2175
  } else {
2167
- fs.defines.push("FRAGMENT_DEPTH_CHECK");
2176
+ fs.defines.push("FS_THREE_POINT_DEPTH_CHECK");
2168
2177
  }
2169
2178
  }
2170
2179
 
@@ -2187,9 +2196,9 @@ BillboardCollection.prototype.update = function (frameState) {
2187
2196
  });
2188
2197
  if (this._shaderClampToGround) {
2189
2198
  if (supportVSTextureReads) {
2190
- fs.defines.push("VERTEX_DEPTH_CHECK");
2199
+ fs.defines.push("VS_THREE_POINT_DEPTH_CHECK");
2191
2200
  } else {
2192
- fs.defines.push("FRAGMENT_DEPTH_CHECK");
2201
+ fs.defines.push("FS_THREE_POINT_DEPTH_CHECK");
2193
2202
  }
2194
2203
  }
2195
2204
  if (this._sdf) {
@@ -2212,9 +2221,9 @@ BillboardCollection.prototype.update = function (frameState) {
2212
2221
  });
2213
2222
  if (this._shaderClampToGround) {
2214
2223
  if (supportVSTextureReads) {
2215
- fs.defines.push("VERTEX_DEPTH_CHECK");
2224
+ fs.defines.push("VS_THREE_POINT_DEPTH_CHECK");
2216
2225
  } else {
2217
- fs.defines.push("FRAGMENT_DEPTH_CHECK");
2226
+ fs.defines.push("FS_THREE_POINT_DEPTH_CHECK");
2218
2227
  }
2219
2228
  }
2220
2229
  if (this._sdf) {
@@ -2237,9 +2246,9 @@ BillboardCollection.prototype.update = function (frameState) {
2237
2246
  });
2238
2247
  if (this._shaderClampToGround) {
2239
2248
  if (supportVSTextureReads) {
2240
- fs.defines.push("VERTEX_DEPTH_CHECK");
2249
+ fs.defines.push("VS_THREE_POINT_DEPTH_CHECK");
2241
2250
  } else {
2242
- fs.defines.push("FRAGMENT_DEPTH_CHECK");
2251
+ fs.defines.push("FS_THREE_POINT_DEPTH_CHECK");
2243
2252
  }
2244
2253
  }
2245
2254
  if (this._sdf) {
@@ -160,8 +160,15 @@ BillboardTexture.prototype.unload = async function () {
160
160
  * @param {string} id An identifier to detect whether the image already exists in the atlas.
161
161
  * @param {HTMLImageElement|HTMLCanvasElement|string|Resource|Promise|TextureAtlas.CreateImageCallback} image An image or canvas to add to the texture atlas,
162
162
  * or a URL to an Image, or a Promise for an image, or a function that creates an image.
163
+ * @param {number} width A number specifying the width of the texture. If undefined, the image width will be used.
164
+ * @param {number} height A number specifying the height of the texture. If undefined, the image height will be used.
163
165
  */
164
- BillboardTexture.prototype.loadImage = async function (id, image) {
166
+ BillboardTexture.prototype.loadImage = async function (
167
+ id,
168
+ image,
169
+ width,
170
+ height,
171
+ ) {
165
172
  if (this._id === id) {
166
173
  // This image has already been loaded
167
174
  return;
@@ -192,7 +199,7 @@ BillboardTexture.prototype.loadImage = async function (id, image) {
192
199
  let index;
193
200
  const atlas = this._billboardCollection.textureAtlas;
194
201
  try {
195
- index = await atlas.addImage(id, image);
202
+ index = await atlas.addImage(id, image, width, height);
196
203
  } catch (error) {
197
204
  // There was an error loading the image
198
205
  billboardTexture._loadState = BillboardLoadState.ERROR;
@@ -251,16 +258,38 @@ BillboardTexture.prototype.loadImage = async function (id, image) {
251
258
  * @param {string} id An identifier to detect whether the image already exists in the atlas.
252
259
  * @param {BoundingRectangle} subRegion An {@link BoundingRectangle} defining a region of an existing image, measured in pixels from the bottom-left of the image.
253
260
  */
254
- BillboardTexture.prototype.addImageSubRegion = async function (id, subRegion) {
261
+ BillboardTexture.prototype.addImageSubRegion = function (id, subRegion) {
255
262
  this._id = id;
256
- this._loadState = BillboardLoadState.LOADING;
257
263
  this._loadError = undefined;
258
264
  this._hasSubregion = true;
259
265
 
260
- let index;
261
266
  const atlas = this._billboardCollection.textureAtlas;
267
+ const indexOrPromise = atlas.addImageSubRegion(id, subRegion);
268
+
269
+ if (typeof indexOrPromise === "number") {
270
+ this.setImageSubRegion(indexOrPromise, subRegion);
271
+ return;
272
+ }
273
+
274
+ this.loadImageSubRegion(id, subRegion, indexOrPromise);
275
+ };
276
+
277
+ /**
278
+ * @see {TextureAtlas#addImageSubRegion}
279
+ * @private
280
+ * @param {string} id An identifier to detect whether the image already exists in the atlas.
281
+ * @param {BoundingRectangle} subRegion An {@link BoundingRectangle} defining a region of an existing image, measured in pixels from the bottom-left of the image.
282
+ * @param {Promise<number>} indexPromise A promise that resolves to the image region index.
283
+ */
284
+ BillboardTexture.prototype.loadImageSubRegion = async function (
285
+ id,
286
+ subRegion,
287
+ indexPromise,
288
+ ) {
289
+ let index;
262
290
  try {
263
- index = await atlas.addImageSubRegion(id, subRegion);
291
+ this._loadState = BillboardLoadState.LOADING;
292
+ index = await indexPromise;
264
293
  } catch (error) {
265
294
  // There was an error loading the referenced image
266
295
  this._loadState = BillboardLoadState.ERROR;
@@ -268,6 +297,27 @@ BillboardTexture.prototype.addImageSubRegion = async function (id, subRegion) {
268
297
  return;
269
298
  }
270
299
 
300
+ if (this._id !== id) {
301
+ // Another load was initiated and resolved resolved before this one. This operation is cancelled.
302
+ return;
303
+ }
304
+
305
+ this._loadState = BillboardLoadState.LOADED;
306
+
307
+ this.setImageSubRegion(index, subRegion);
308
+ };
309
+
310
+ /**
311
+ * @see {TextureAtlas#addImageSubRegion}
312
+ * @private
313
+ * @param {number} index The resolved index in the {@link TextureAtlas}
314
+ * @param {BoundingRectangle} subRegion An {@link BoundingRectangle} defining a region of an existing image, measured in pixels from the bottom-left of the image.
315
+ */
316
+ BillboardTexture.prototype.setImageSubRegion = function (index, subRegion) {
317
+ if (this._index === index) {
318
+ return;
319
+ }
320
+
271
321
  if (!defined(index) || index === -1) {
272
322
  this._loadState = BillboardLoadState.FAILED;
273
323
  this._index = -1;
@@ -280,7 +330,6 @@ BillboardTexture.prototype.addImageSubRegion = async function (id, subRegion) {
280
330
  this._height = subRegion.height;
281
331
 
282
332
  this._index = index;
283
- this._loadState = BillboardLoadState.LOADED;
284
333
 
285
334
  this.dirty = true;
286
335
  };
@@ -457,7 +457,7 @@ Object.defineProperties(BingMapsImageryProvider.prototype, {
457
457
  /**
458
458
  * Creates an {@link ImageryProvider} which provides tiled imagery using the Bing Maps Imagery REST API.
459
459
  *
460
- * @param {Resource|String} url The url of the Bing Maps server hosting the imagery.
460
+ * @param {Resource|string} url The url of the Bing Maps server hosting the imagery.
461
461
  * @param {BingMapsImageryProvider.ConstructorOptions} options Object describing initialization options
462
462
  * @returns {Promise<BingMapsImageryProvider>} A promise that resolves to the created BingMapsImageryProvider
463
463
  *