@cesium/engine 13.1.0 → 15.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 (183) hide show
  1. package/Build/Workers/{chunk-APCS5YJI.js → chunk-25TOENEE.js} +7 -7
  2. package/Build/Workers/{chunk-FNCXBBCF.js → chunk-2AVIUB5H.js} +2 -2
  3. package/Build/Workers/{chunk-OZTFRHA2.js → chunk-3JZGPJMZ.js} +6 -6
  4. package/Build/Workers/{chunk-5JY4LYO3.js → chunk-3LHBH4TC.js} +7 -7
  5. package/Build/Workers/{chunk-MGABCOOH.js → chunk-3LZF23RY.js} +6 -6
  6. package/Build/Workers/{chunk-AXYZUG4N.js → chunk-5S2B46UQ.js} +1 -1
  7. package/Build/Workers/{chunk-2SRHVCFD.js → chunk-67ONR44K.js} +6 -6
  8. package/Build/Workers/{chunk-PBJQFLKS.js → chunk-6EDBC234.js} +11 -11
  9. package/Build/Workers/{chunk-GSLKQJM2.js → chunk-6EV4VOET.js} +10 -10
  10. package/Build/Workers/{chunk-OGRXNUR2.js → chunk-7ITUZTFH.js} +1 -1
  11. package/Build/Workers/{chunk-IP7F2MVW.js → chunk-ARVZCY6X.js} +7 -7
  12. package/Build/Workers/{chunk-EYZFEJX3.js → chunk-B2UQN3DH.js} +6 -6
  13. package/Build/Workers/{chunk-WE4KF4AM.js → chunk-B2Y4ZS6X.js} +9 -9
  14. package/Build/Workers/{chunk-DWIKWWEE.js → chunk-BD2TPFGC.js} +5 -5
  15. package/Build/Workers/{chunk-5ICYLS6B.js → chunk-CHX2K5AC.js} +10 -10
  16. package/Build/Workers/{chunk-NQDKNE7V.js → chunk-CJGVEABL.js} +13 -13
  17. package/Build/Workers/{chunk-B34JXFHF.js → chunk-DYJHEP3B.js} +5 -5
  18. package/Build/Workers/{chunk-J7BMSSY7.js → chunk-E3H7AVMK.js} +13 -13
  19. package/Build/Workers/{chunk-TOHDFUJM.js → chunk-EZNAJPP5.js} +4 -4
  20. package/Build/Workers/{chunk-K62EHZFT.js → chunk-F7ZI463G.js} +15 -15
  21. package/Build/Workers/{chunk-EJ5DT5BP.js → chunk-FMZ5CX6V.js} +1 -1
  22. package/Build/Workers/{chunk-OARMSJUU.js → chunk-FRAWHNSR.js} +2 -2
  23. package/Build/Workers/{chunk-S3UM4OKP.js → chunk-GGV2XJHE.js} +7 -7
  24. package/Build/Workers/{chunk-SAKQO5NX.js → chunk-GK4QU6QI.js} +2 -2
  25. package/Build/Workers/{chunk-LFUFGHL3.js → chunk-HYPB7FAV.js} +10 -10
  26. package/Build/Workers/{chunk-3SCCWLZS.js → chunk-I4HO2ED2.js} +9 -9
  27. package/Build/Workers/{chunk-K6SQV4IS.js → chunk-IGINOLDX.js} +6 -6
  28. package/Build/Workers/{chunk-IXNXKVOB.js → chunk-ISQSYLZY.js} +4 -4
  29. package/Build/Workers/{chunk-PM76TX2X.js → chunk-JZAMRL5I.js} +6 -6
  30. package/Build/Workers/{chunk-CBE4HRBH.js → chunk-K5G2WELR.js} +7 -7
  31. package/Build/Workers/{chunk-EHGQQA7C.js → chunk-L5SO4Y5V.js} +1 -1
  32. package/Build/Workers/{chunk-M2AA2ARJ.js → chunk-LCMJQVIF.js} +11 -11
  33. package/Build/Workers/{chunk-HI73PIPQ.js → chunk-MWJW37I7.js} +2 -2
  34. package/Build/Workers/{chunk-WAJNX74N.js → chunk-NAGMYRDW.js} +27 -20
  35. package/Build/Workers/{chunk-WUIDEXAN.js → chunk-OYO6TKMU.js} +7 -7
  36. package/Build/Workers/{chunk-YVGU235V.js → chunk-PUTA3AE2.js} +4 -4
  37. package/Build/Workers/{chunk-ZWSWJYJP.js → chunk-Q5BHMNKU.js} +13 -13
  38. package/Build/Workers/{chunk-LQT2ZK7D.js → chunk-QTEX3Y4V.js} +17 -17
  39. package/Build/Workers/{chunk-UBAHTE4Q.js → chunk-QZKN2RXM.js} +1 -1
  40. package/Build/Workers/{chunk-T34EOLFR.js → chunk-RO2Z3LCR.js} +14 -14
  41. package/Build/Workers/{chunk-PTFIVVLX.js → chunk-RRN6LRDX.js} +12 -12
  42. package/Build/Workers/{chunk-B6IJY6AN.js → chunk-SLIA3GQP.js} +7 -7
  43. package/Build/Workers/{chunk-GIOZHX7U.js → chunk-TFCOEX3W.js} +2 -2
  44. package/Build/Workers/{chunk-KRVALCCI.js → chunk-TU6ZXHVU.js} +5 -5
  45. package/Build/Workers/{chunk-54I6VSRP.js → chunk-VJ2PDF64.js} +6 -6
  46. package/Build/Workers/{chunk-BMFWWTD7.js → chunk-VMVPONIV.js} +5 -5
  47. package/Build/Workers/{chunk-CNPP6TQ2.js → chunk-WPXU45PH.js} +4 -4
  48. package/Build/Workers/{chunk-2ONAV62A.js → chunk-XDHM4G3P.js} +7 -7
  49. package/Build/Workers/{chunk-KO232FLP.js → chunk-XED3RXKO.js} +2 -2
  50. package/Build/Workers/{chunk-5I3LPAS7.js → chunk-YNYCGTQH.js} +5 -5
  51. package/Build/Workers/{chunk-THDHWSEJ.js → chunk-Z4SI54EB.js} +4 -4
  52. package/Build/Workers/{chunk-R2KGFZBA.js → chunk-ZVDLC3T4.js} +13 -13
  53. package/Build/Workers/combineGeometry.js +22 -22
  54. package/Build/Workers/createBoxGeometry.js +16 -16
  55. package/Build/Workers/createBoxOutlineGeometry.js +14 -14
  56. package/Build/Workers/createCircleGeometry.js +24 -24
  57. package/Build/Workers/createCircleOutlineGeometry.js +17 -17
  58. package/Build/Workers/createCoplanarPolygonGeometry.js +31 -31
  59. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +29 -29
  60. package/Build/Workers/createCorridorGeometry.js +27 -27
  61. package/Build/Workers/createCorridorOutlineGeometry.js +26 -26
  62. package/Build/Workers/createCylinderGeometry.js +18 -18
  63. package/Build/Workers/createCylinderOutlineGeometry.js +16 -16
  64. package/Build/Workers/createEllipseGeometry.js +24 -24
  65. package/Build/Workers/createEllipseOutlineGeometry.js +17 -17
  66. package/Build/Workers/createEllipsoidGeometry.js +17 -17
  67. package/Build/Workers/createEllipsoidOutlineGeometry.js +16 -16
  68. package/Build/Workers/createFrustumGeometry.js +16 -16
  69. package/Build/Workers/createFrustumOutlineGeometry.js +16 -16
  70. package/Build/Workers/createGeometry.js +22 -22
  71. package/Build/Workers/createGroundPolylineGeometry.js +20 -20
  72. package/Build/Workers/createPlaneGeometry.js +14 -14
  73. package/Build/Workers/createPlaneOutlineGeometry.js +13 -13
  74. package/Build/Workers/createPolygonGeometry.js +30 -30
  75. package/Build/Workers/createPolygonOutlineGeometry.js +28 -28
  76. package/Build/Workers/createPolylineGeometry.js +23 -23
  77. package/Build/Workers/createPolylineVolumeGeometry.js +29 -29
  78. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +25 -25
  79. package/Build/Workers/createRectangleGeometry.js +25 -25
  80. package/Build/Workers/createRectangleOutlineGeometry.js +18 -18
  81. package/Build/Workers/createSimplePolylineGeometry.js +21 -21
  82. package/Build/Workers/createSphereGeometry.js +17 -17
  83. package/Build/Workers/createSphereOutlineGeometry.js +16 -16
  84. package/Build/Workers/createTaskProcessorWorker.js +3 -3
  85. package/Build/Workers/createVectorTileClampedPolylines.js +13 -13
  86. package/Build/Workers/createVectorTileGeometries.js +22 -22
  87. package/Build/Workers/createVectorTilePoints.js +12 -12
  88. package/Build/Workers/createVectorTilePolygons.js +20 -20
  89. package/Build/Workers/createVectorTilePolylines.js +13 -13
  90. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +20 -20
  91. package/Build/Workers/createVerticesFromHeightmap.js +20 -20
  92. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +17 -17
  93. package/Build/Workers/createWallGeometry.js +22 -22
  94. package/Build/Workers/createWallOutlineGeometry.js +21 -21
  95. package/Build/Workers/decodeDraco.js +15 -14
  96. package/Build/Workers/decodeGoogleEarthEnterprisePacket.js +5 -5
  97. package/Build/Workers/decodeI3S.js +10 -10
  98. package/Build/Workers/transcodeKTX2.js +50 -43
  99. package/Build/Workers/transferTypedArrayTest.js +1 -1
  100. package/Build/Workers/upsampleQuantizedTerrainMesh.js +20 -20
  101. package/Source/Core/Color.js +3 -3
  102. package/Source/Core/Credit.js +3 -3
  103. package/Source/Core/DistanceDisplayCondition.js +3 -3
  104. package/Source/Core/EllipsoidRhumbLine.js +1 -1
  105. package/Source/Core/Ion.js +1 -1
  106. package/Source/Core/OrientedBoundingBox.js +2 -2
  107. package/Source/Core/PolygonGeometryLibrary.js +26 -4
  108. package/Source/Core/Spherical.js +3 -3
  109. package/Source/Core/TexturePacker.js +166 -0
  110. package/Source/Core/writeTextToCanvas.js +0 -1
  111. package/Source/DataSources/BillboardVisualizer.js +3 -3
  112. package/Source/DataSources/BoundingSphereState.js +3 -3
  113. package/Source/DataSources/DataSourceClock.js +1 -1
  114. package/Source/DataSources/DataSourceDisplay.js +5 -2
  115. package/Source/DataSources/EntityCluster.js +44 -19
  116. package/Source/Renderer/AutomaticUniforms.js +2 -2
  117. package/Source/Renderer/Context.js +0 -4
  118. package/Source/Renderer/Texture.js +6 -5
  119. package/Source/Renderer/TextureAtlas.js +802 -0
  120. package/Source/Scene/ArcGisMapService.js +1 -1
  121. package/Source/Scene/Billboard.js +87 -142
  122. package/Source/Scene/BillboardCollection.js +132 -202
  123. package/Source/Scene/BillboardLoadState.js +44 -0
  124. package/Source/Scene/BillboardTexture.js +348 -0
  125. package/Source/Scene/Camera.js +2 -2
  126. package/Source/Scene/Cesium3DTile.js +56 -28
  127. package/Source/Scene/Cesium3DTilesVoxelProvider.js +403 -132
  128. package/Source/Scene/Cesium3DTilesetStatistics.js +0 -1
  129. package/Source/Scene/ClippingPolygon.js +2 -2
  130. package/Source/Scene/Expression.js +1 -0
  131. package/Source/Scene/GltfDracoLoader.js +45 -0
  132. package/Source/Scene/GltfIndexBufferLoader.js +5 -0
  133. package/Source/Scene/GltfLoader.js +22 -9
  134. package/Source/Scene/GltfVertexBufferLoader.js +13 -0
  135. package/Source/Scene/ITwinData.js +47 -1
  136. package/Source/Scene/ImageryLayer.js +1 -1
  137. package/Source/Scene/ImplicitSubtree.js +2 -0
  138. package/Source/Scene/KeyframeNode.js +16 -2
  139. package/Source/Scene/Label.js +1 -1
  140. package/Source/Scene/LabelCollection.js +212 -193
  141. package/Source/Scene/Megatexture.js +145 -81
  142. package/Source/Scene/Model/CustomShader.js +0 -2
  143. package/Source/Scene/Model/Model.js +1 -1
  144. package/Source/Scene/Model/ModelUtility.js +5 -1
  145. package/Source/Scene/Multiple3DTileContent.js +21 -8
  146. package/Source/Scene/PointPrimitive.js +1 -1
  147. package/Source/Scene/ResourceCache.js +17 -1
  148. package/Source/Scene/Scene.js +39 -15
  149. package/Source/Scene/ScreenSpaceCameraController.js +0 -8
  150. package/Source/Scene/SpatialNode.js +4 -11
  151. package/Source/Scene/Vector3DTilePoints.js +2 -5
  152. package/Source/Scene/VoxelBoxShape.js +12 -5
  153. package/Source/Scene/VoxelCell.js +6 -5
  154. package/Source/Scene/VoxelContent.js +171 -107
  155. package/Source/Scene/VoxelCylinderShape.js +65 -58
  156. package/Source/Scene/VoxelEllipsoidShape.js +15 -5
  157. package/Source/Scene/VoxelMetadataOrder.js +12 -0
  158. package/Source/Scene/VoxelPrimitive.js +245 -53
  159. package/Source/Scene/VoxelProvider.js +44 -29
  160. package/Source/Scene/VoxelRenderResources.js +30 -7
  161. package/Source/Scene/VoxelShape.js +10 -3
  162. package/Source/Scene/VoxelTraversal.js +326 -166
  163. package/Source/Scene/WebMapTileServiceImageryProvider.js +2 -2
  164. package/Source/Scene/createGooglePhotorealistic3DTileset.js +5 -8
  165. package/Source/Scene/processVoxelProperties.js +3 -0
  166. package/Source/Shaders/GlobeFS.glsl +10 -1
  167. package/Source/Shaders/GlobeFS.js +10 -1
  168. package/Source/Shaders/PolylineCommon.glsl +1 -1
  169. package/Source/Shaders/PolylineCommon.js +1 -1
  170. package/Source/Shaders/Voxels/Megatexture.glsl +4 -16
  171. package/Source/Shaders/Voxels/Megatexture.js +4 -16
  172. package/Source/Shaders/Voxels/Octree.glsl +44 -7
  173. package/Source/Shaders/Voxels/Octree.js +44 -7
  174. package/Source/Shaders/Voxels/VoxelFS.glsl +9 -15
  175. package/Source/Shaders/Voxels/VoxelFS.js +9 -15
  176. package/Source/Shaders/Voxels/convertUvToCylinder.glsl +15 -15
  177. package/Source/Shaders/Voxels/convertUvToCylinder.js +15 -15
  178. package/Source/Widget/CesiumWidget.js +16 -10
  179. package/Source/Workers/decodeDraco.js +4 -4
  180. package/index.d.ts +321 -110
  181. package/index.js +209 -205
  182. package/package.json +2 -2
  183. package/Source/Scene/TextureAtlas.js +0 -558
@@ -1,6 +1,8 @@
1
1
  import Cartesian2 from "../Core/Cartesian2.js";
2
+ import Cartesian3 from "../Core/Cartesian3.js";
2
3
  import CesiumMath from "../Core/Math.js";
3
4
  import CullingVolume from "../Core/CullingVolume.js";
5
+ import defaultValue from "../Core/defaultValue.js";
4
6
  import defined from "../Core/defined.js";
5
7
  import destroyObject from "../Core/destroyObject.js";
6
8
  import DoubleEndedPriorityQueue from "../Core/DoubleEndedPriorityQueue.js";
@@ -15,6 +17,7 @@ import SpatialNode from "./SpatialNode.js";
15
17
  import Texture from "../Renderer/Texture.js";
16
18
  import TextureMagnificationFilter from "../Renderer/TextureMagnificationFilter.js";
17
19
  import TextureMinificationFilter from "../Renderer/TextureMinificationFilter.js";
20
+ import VoxelMetadataOrder from "./VoxelMetadataOrder.js";
18
21
 
19
22
  /**
20
23
  * Handles tileset traversal, tile requests, and GPU resources. Intended to be
@@ -23,32 +26,59 @@ import TextureMinificationFilter from "../Renderer/TextureMinificationFilter.js"
23
26
  * @alias VoxelTraversal
24
27
  * @constructor
25
28
  *
26
- * @param {VoxelPrimitive} primitive
27
- * @param {Context} context
28
- * @param {Cartesian3} dimensions
29
- * @param {MetadataType[]} types
30
- * @param {MetadataComponentType[]} componentTypes
31
- * @param {number} keyframeCount
32
- * @param {number} [maximumTextureMemoryByteLength]
29
+ * @param {VoxelPrimitive} primitive The voxel primitive for which this traversal will be used.
30
+ * @param {Context} context The context in which to create GPU resources.
31
+ * @param {number} keyframeCount The number of keyframes in the tileset.
32
+ * @param {number} [maximumTextureMemoryByteLength] The maximum amount of memory to use for textures.
33
33
  *
34
34
  * @private
35
35
  */
36
36
  function VoxelTraversal(
37
37
  primitive,
38
38
  context,
39
- dimensions,
40
- types,
41
- componentTypes,
42
39
  keyframeCount,
43
40
  maximumTextureMemoryByteLength,
44
41
  ) {
42
+ const { provider, dimensions, paddingBefore, paddingAfter } = primitive;
43
+ const { types, componentTypes, metadataOrder } = provider;
44
+
45
+ const inputDimensions = Cartesian3.add(
46
+ dimensions,
47
+ paddingBefore,
48
+ new Cartesian3(),
49
+ );
50
+ Cartesian3.add(inputDimensions, paddingAfter, inputDimensions);
51
+
52
+ if (metadataOrder === VoxelMetadataOrder.GLTF) {
53
+ const inputDimensionsY = inputDimensions.y;
54
+ inputDimensions.y = inputDimensions.z;
55
+ inputDimensions.z = inputDimensionsY;
56
+ }
57
+
58
+ if (
59
+ !defined(maximumTextureMemoryByteLength) &&
60
+ defined(provider.maximumTileCount)
61
+ ) {
62
+ maximumTextureMemoryByteLength = getApproximateTextureMemoryByteLength(
63
+ provider.maximumTileCount,
64
+ inputDimensions,
65
+ types,
66
+ componentTypes,
67
+ );
68
+ }
69
+
45
70
  /**
46
- * TODO: maybe this shouldn't be stored or passed into update function?
47
71
  * @type {VoxelPrimitive}
48
72
  * @private
49
73
  */
50
74
  this._primitive = primitive;
51
75
 
76
+ /**
77
+ * @type {number}
78
+ * @private
79
+ */
80
+ this.textureMemoryByteLength = 0;
81
+
52
82
  /**
53
83
  * @type {Megatexture[]}
54
84
  * @readonly
@@ -63,11 +93,14 @@ function VoxelTraversal(
63
93
 
64
94
  this.megatextures[i] = new Megatexture(
65
95
  context,
66
- dimensions,
96
+ inputDimensions,
67
97
  componentCount,
68
98
  componentType,
69
99
  maximumTextureMemoryByteLength,
70
100
  );
101
+
102
+ this.textureMemoryByteLength +=
103
+ this.megatextures[i].textureMemoryByteLength;
71
104
  }
72
105
 
73
106
  const maximumTileCount = this.megatextures[0].maximumTileCount;
@@ -84,6 +117,15 @@ function VoxelTraversal(
84
117
  */
85
118
  this._debugPrint = false;
86
119
 
120
+ /**
121
+ * @type {boolean}
122
+ * @private
123
+ */
124
+ this._calculateStatistics = defaultValue(
125
+ this._primitive._calculateStatistics,
126
+ false,
127
+ );
128
+
87
129
  /**
88
130
  * @type {number}
89
131
  * @private
@@ -113,6 +155,12 @@ function VoxelTraversal(
113
155
  */
114
156
  this._highPriorityKeyframeNodes = new Array(maximumTileCount);
115
157
 
158
+ /**
159
+ * @type {number}
160
+ * @private
161
+ */
162
+ this._highPriorityKeyframeNodeCount = 0;
163
+
116
164
  /**
117
165
  * @type {KeyframeNode[]}
118
166
  * @private
@@ -143,6 +191,12 @@ function VoxelTraversal(
143
191
  */
144
192
  this._binaryTreeKeyframeWeighting = new Array(keyframeCount);
145
193
 
194
+ /**
195
+ * @type {boolean}
196
+ * @private
197
+ */
198
+ this._initialTilesLoaded = false;
199
+
146
200
  const binaryTreeKeyframeWeighting = this._binaryTreeKeyframeWeighting;
147
201
  binaryTreeKeyframeWeighting[0] = 0;
148
202
  binaryTreeKeyframeWeighting[keyframeCount - 1] = 0;
@@ -312,17 +366,24 @@ VoxelTraversal.prototype.update = function (
312
366
 
313
367
  this._frameNumber = frameState.frameNumber;
314
368
  const timestamp0 = getTimestamp();
315
- loadAndUnload(this, frameState);
369
+ selectKeyframeNodes(this, frameState);
370
+ updateKeyframeNodes(this, frameState);
316
371
  const timestamp1 = getTimestamp();
317
372
  generateOctree(this, sampleCount, levelBlendFactor);
318
373
  const timestamp2 = getTimestamp();
319
374
 
320
- if (this._debugPrint) {
375
+ const checkEventListeners =
376
+ primitive.loadProgress.numberOfListeners > 0 ||
377
+ primitive.allTilesLoaded.numberOfListeners > 0 ||
378
+ primitive.initialTilesLoaded.numberOfListeners > 0;
379
+
380
+ if (this._debugPrint || this._calculateStatistics || checkEventListeners) {
321
381
  const loadAndUnloadTimeMs = timestamp1 - timestamp0;
322
382
  const generateOctreeTimeMs = timestamp2 - timestamp1;
323
383
  const totalTimeMs = timestamp2 - timestamp0;
324
- printDebugInformation(
384
+ postPassesUpdate(
325
385
  this,
386
+ frameState,
326
387
  loadAndUnloadTimeMs,
327
388
  generateOctreeTimeMs,
328
389
  totalTimeMs,
@@ -374,6 +435,7 @@ VoxelTraversal.prototype.destroy = function () {
374
435
  for (let i = 0; i < megatextureLength; i++) {
375
436
  megatextures[i] = megatextures[i] && megatextures[i].destroy();
376
437
  }
438
+ this.textureMemoryByteLength = 0;
377
439
 
378
440
  this.internalNodeTexture =
379
441
  this.internalNodeTexture && this.internalNodeTexture.destroy();
@@ -417,61 +479,44 @@ function requestData(that, keyframeNode) {
417
479
  return;
418
480
  }
419
481
 
420
- const provider = that._primitive._provider;
482
+ const primitive = that._primitive;
483
+ const provider = primitive.provider;
484
+ const { keyframe, spatialNode } = keyframeNode;
485
+ if (
486
+ defined(provider.availableLevels) &&
487
+ spatialNode.level >= provider.availableLevels
488
+ ) {
489
+ return;
490
+ }
421
491
 
422
492
  function postRequestSuccess(result) {
423
493
  that._simultaneousRequestCount--;
424
- const length = provider.types.length;
425
-
426
- if (!defined(result)) {
427
- keyframeNode.state = KeyframeNode.LoadState.UNAVAILABLE;
428
- } else if (result === KeyframeNode.LoadState.FAILED) {
429
- keyframeNode.state = KeyframeNode.LoadState.FAILED;
430
- } else if (!Array.isArray(result) || result.length !== length) {
431
- // TODO should this throw runtime error?
432
- keyframeNode.state = KeyframeNode.LoadState.FAILED;
433
- } else {
434
- const megatextures = that.megatextures;
435
- for (let i = 0; i < length; i++) {
436
- const { voxelCountPerTile, channelCount } = megatextures[i];
437
- const { x, y, z } = voxelCountPerTile;
438
- const tileVoxelCount = x * y * z;
439
-
440
- const data = result[i];
441
- const expectedLength = tileVoxelCount * channelCount;
442
- if (data.length === expectedLength) {
443
- keyframeNode.metadata[i] = data;
444
- // State is received only when all metadata requests have been received
445
- keyframeNode.state = KeyframeNode.LoadState.RECEIVED;
446
- } else {
447
- keyframeNode.state = KeyframeNode.LoadState.FAILED;
448
- break;
449
- }
450
- }
451
- }
494
+ keyframeNode.content = result;
495
+ keyframeNode.state = defined(result)
496
+ ? KeyframeNode.LoadState.PROCESSING
497
+ : KeyframeNode.LoadState.UNAVAILABLE;
452
498
  }
453
499
 
454
- function postRequestFailure() {
500
+ function postRequestFailure(error) {
455
501
  that._simultaneousRequestCount--;
456
502
  keyframeNode.state = KeyframeNode.LoadState.FAILED;
503
+ that._primitive.tileFailed.raiseEvent();
457
504
  }
458
505
 
459
- const { keyframe, spatialNode } = keyframeNode;
460
- const promise = provider.requestData({
506
+ const requestParameters = {
461
507
  tileLevel: spatialNode.level,
462
508
  tileX: spatialNode.x,
463
509
  tileY: spatialNode.y,
464
510
  tileZ: spatialNode.z,
465
511
  keyframe: keyframe,
466
- });
467
-
468
- if (defined(promise)) {
469
- that._simultaneousRequestCount++;
470
- keyframeNode.state = KeyframeNode.LoadState.RECEIVING;
471
- promise.then(postRequestSuccess).catch(postRequestFailure);
472
- } else {
473
- keyframeNode.state = KeyframeNode.LoadState.FAILED;
512
+ };
513
+ const promise = provider.requestData(requestParameters);
514
+ if (!defined(promise)) {
515
+ return;
474
516
  }
517
+ that._simultaneousRequestCount++;
518
+ keyframeNode.state = KeyframeNode.LoadState.RECEIVING;
519
+ promise.then(postRequestSuccess).catch(postRequestFailure);
475
520
  }
476
521
 
477
522
  /**
@@ -487,105 +532,23 @@ function mapInfiniteRangeToZeroOne(x) {
487
532
  }
488
533
 
489
534
  /**
490
- * @function
491
- *
492
535
  * @param {VoxelTraversal} that
493
536
  * @param {FrameState} frameState
494
537
  *
495
538
  * @private
496
539
  */
497
- function loadAndUnload(that, frameState) {
540
+ function selectKeyframeNodes(that, frameState) {
498
541
  const frameNumber = that._frameNumber;
499
- const primitive = that._primitive;
500
- const shape = primitive._shape;
501
- const targetScreenSpaceError = primitive.screenSpaceError;
502
542
  const priorityQueue = that._priorityQueue;
503
- const keyframeCount = that._keyframeCount;
504
-
505
- const previousKeyframe = CesiumMath.clamp(
506
- Math.floor(that._keyframeLocation),
507
- 0,
508
- keyframeCount - 2,
509
- );
510
- const nextKeyframe = previousKeyframe + 1;
511
-
512
- const { camera, context, pixelRatio } = frameState;
513
- const { positionWC, frustum } = camera;
514
- const screenHeight = context.drawingBufferHeight / pixelRatio;
515
- const screenSpaceErrorMultiplier = screenHeight / frustum.sseDenominator;
516
-
517
- /**
518
- * @ignore
519
- * @param {SpatialNode} spatialNode
520
- * @param {number} visibilityPlaneMask
521
- */
522
- function addToQueueRecursive(spatialNode, visibilityPlaneMask) {
523
- spatialNode.computeScreenSpaceError(positionWC, screenSpaceErrorMultiplier);
524
-
525
- visibilityPlaneMask = spatialNode.visibility(
526
- frameState,
527
- visibilityPlaneMask,
528
- );
529
- if (visibilityPlaneMask === CullingVolume.MASK_OUTSIDE) {
530
- return;
531
- }
532
- spatialNode.visitedFrameNumber = frameNumber;
533
-
534
- // Create keyframe nodes at the playhead.
535
- // If they already exist, nothing will be created.
536
- if (keyframeCount === 1) {
537
- spatialNode.createKeyframeNode(0);
538
- } else if (spatialNode.keyframeNodes.length !== keyframeCount) {
539
- for (let k = 0; k < keyframeCount; k++) {
540
- spatialNode.createKeyframeNode(k);
541
- }
542
- }
543
- const { screenSpaceError, keyframeNodes } = spatialNode;
544
- const ssePriority = mapInfiniteRangeToZeroOne(screenSpaceError);
545
-
546
- let hasLoadedKeyframe = false;
547
- for (let i = 0; i < keyframeNodes.length; i++) {
548
- const keyframeNode = keyframeNodes[i];
549
-
550
- keyframeNode.priority =
551
- 10.0 * ssePriority +
552
- keyframePriority(
553
- previousKeyframe,
554
- keyframeNode.keyframe,
555
- nextKeyframe,
556
- that,
557
- );
558
-
559
- if (
560
- keyframeNode.state !== KeyframeNode.LoadState.UNAVAILABLE &&
561
- keyframeNode.state !== KeyframeNode.LoadState.FAILED &&
562
- keyframeNode.priority !== -Number.MAX_VALUE
563
- ) {
564
- priorityQueue.insert(keyframeNode);
565
- }
566
- if (keyframeNode.state === KeyframeNode.LoadState.LOADED) {
567
- hasLoadedKeyframe = true;
568
- }
569
- }
570
-
571
- if (screenSpaceError < targetScreenSpaceError || !hasLoadedKeyframe) {
572
- // Free up memory
573
- spatialNode.children = undefined;
574
- return;
575
- }
576
-
577
- if (!defined(spatialNode.children)) {
578
- spatialNode.constructChildNodes(shape);
579
- }
580
- for (let childIndex = 0; childIndex < 8; childIndex++) {
581
- const child = spatialNode.children[childIndex];
582
- addToQueueRecursive(child, visibilityPlaneMask);
583
- }
584
- }
585
543
 
586
544
  // Add all the nodes to the queue, to sort them by priority.
587
545
  priorityQueue.reset();
588
- addToQueueRecursive(that.rootNode, CullingVolume.MASK_INDETERMINATE);
546
+ addToQueueRecursive(
547
+ that.rootNode,
548
+ CullingVolume.MASK_INDETERMINATE,
549
+ that,
550
+ frameState,
551
+ );
589
552
 
590
553
  // Move the nodes from the queue to array of high priority nodes.
591
554
  const highPriorityKeyframeNodes = that._highPriorityKeyframeNodes;
@@ -598,23 +561,29 @@ function loadAndUnload(that, frameState) {
598
561
  highPriorityKeyframeNode;
599
562
  highPriorityKeyframeNodeCount++;
600
563
  }
564
+ that._highPriorityKeyframeNodeCount = highPriorityKeyframeNodeCount;
565
+ }
566
+
567
+ /**
568
+ * @param {VoxelTraversal} that
569
+ * @param {FrameState} frameState
570
+ *
571
+ * @private
572
+ */
573
+ function updateKeyframeNodes(that, frameState) {
574
+ const megatexture = that.megatextures[0];
575
+ const keyframeNodesInMegatextureCount = megatexture.occupiedCount;
601
576
 
602
577
  // Sort the list of keyframe nodes in the megatexture by priority, so
603
578
  // we can remove the lowest priority nodes if we need space.
604
579
  const keyframeNodesInMegatexture = that._keyframeNodesInMegatexture;
605
- // TODO: some of the megatexture state should be stored once, not duplicate for each megatexture
606
- const megatexture = that.megatextures[0];
607
- const keyframeNodesInMegatextureCount = megatexture.occupiedCount;
608
580
  keyframeNodesInMegatexture.length = keyframeNodesInMegatextureCount;
609
- keyframeNodesInMegatexture.sort(function (a, b) {
610
- if (a.highPriorityFrameNumber === b.highPriorityFrameNumber) {
611
- return b.priority - a.priority;
612
- }
613
- return b.highPriorityFrameNumber - a.highPriorityFrameNumber;
614
- });
581
+ keyframeNodesInMegatexture.sort(keyframeNodeSort);
615
582
 
616
583
  // Add the high priority nodes to the megatexture,
617
584
  // removing existing lower-priority nodes if necessary.
585
+ const highPriorityKeyframeNodes = that._highPriorityKeyframeNodes;
586
+ const highPriorityKeyframeNodeCount = that._highPriorityKeyframeNodeCount;
618
587
  let destroyedCount = 0;
619
588
  let addedCount = 0;
620
589
 
@@ -623,7 +592,7 @@ function loadAndUnload(that, frameState) {
623
592
  highPriorityKeyframeNodeIndex < highPriorityKeyframeNodeCount;
624
593
  highPriorityKeyframeNodeIndex++
625
594
  ) {
626
- highPriorityKeyframeNode =
595
+ const highPriorityKeyframeNode =
627
596
  highPriorityKeyframeNodes[highPriorityKeyframeNodeIndex];
628
597
 
629
598
  if (
@@ -637,7 +606,18 @@ function loadAndUnload(that, frameState) {
637
606
  if (highPriorityKeyframeNode.state === KeyframeNode.LoadState.UNLOADED) {
638
607
  requestData(that, highPriorityKeyframeNode);
639
608
  }
640
- if (highPriorityKeyframeNode.state === KeyframeNode.LoadState.RECEIVED) {
609
+ if (highPriorityKeyframeNode.state === KeyframeNode.LoadState.PROCESSING) {
610
+ const { content } = highPriorityKeyframeNode;
611
+ content.update(that._primitive, frameState);
612
+ if (!content.ready) {
613
+ continue;
614
+ }
615
+ if (!validateMetadata(content.metadata, that)) {
616
+ highPriorityKeyframeNode.content = undefined;
617
+ highPriorityKeyframeNode.state = KeyframeNode.LoadState.FAILED;
618
+ that._primitive.tileFailed.raiseEvent();
619
+ continue;
620
+ }
641
621
  let addNodeIndex = 0;
642
622
  if (megatexture.isFull()) {
643
623
  // If the megatexture is full, try removing a discardable node with the lowest priority.
@@ -645,6 +625,7 @@ function loadAndUnload(that, frameState) {
645
625
  destroyedCount++;
646
626
 
647
627
  const discardNode = keyframeNodesInMegatexture[addNodeIndex];
628
+ that._primitive.tileUnload.raiseEvent();
648
629
  discardNode.spatialNode.destroyKeyframeNode(
649
630
  discardNode,
650
631
  that.megatextures,
@@ -657,9 +638,138 @@ function loadAndUnload(that, frameState) {
657
638
  highPriorityKeyframeNode,
658
639
  that.megatextures,
659
640
  );
641
+ highPriorityKeyframeNode.state = KeyframeNode.LoadState.LOADED;
660
642
  keyframeNodesInMegatexture[addNodeIndex] = highPriorityKeyframeNode;
643
+ that._primitive.tileLoad.raiseEvent();
644
+ }
645
+ }
646
+ }
647
+
648
+ function keyframeNodeSort(a, b) {
649
+ if (a.highPriorityFrameNumber === b.highPriorityFrameNumber) {
650
+ return b.priority - a.priority;
651
+ }
652
+ return b.highPriorityFrameNumber - a.highPriorityFrameNumber;
653
+ }
654
+
655
+ /**
656
+ * Check if an array of metadata is of the expected type and size
657
+ *
658
+ * @param {TypedArray[]} metadata The metadata to validate
659
+ * @param {VoxelTraversal} traversal The traversal to validate against
660
+ * @returns {boolean} <code>true</code> if the metadata is valid, <code>false</code> otherwise
661
+ *
662
+ * @private
663
+ */
664
+ function validateMetadata(metadata, traversal) {
665
+ const length = traversal._primitive.provider.types.length;
666
+ if (!Array.isArray(metadata) || metadata.length !== length) {
667
+ return false;
668
+ }
669
+ const { megatextures } = traversal;
670
+ for (let i = 0; i < length; i++) {
671
+ const { voxelCountPerTile, channelCount } = megatextures[i];
672
+ const { x, y, z } = voxelCountPerTile;
673
+ const tileVoxelCount = x * y * z;
674
+
675
+ const data = metadata[i];
676
+ const expectedLength = tileVoxelCount * channelCount;
677
+ if (data.length !== expectedLength) {
678
+ return false;
661
679
  }
662
680
  }
681
+ return true;
682
+ }
683
+
684
+ /**
685
+ * @param {SpatialNode} spatialNode
686
+ * @param {number} visibilityPlaneMask
687
+ * @param {VoxelTraversal} that
688
+ * @param {FrameState} frameState
689
+ *
690
+ * @private
691
+ */
692
+ function addToQueueRecursive(
693
+ spatialNode,
694
+ visibilityPlaneMask,
695
+ that,
696
+ frameState,
697
+ ) {
698
+ const { camera, context, pixelRatio, frameNumber } = frameState;
699
+ const { positionWC, frustum } = camera;
700
+ const screenHeight = context.drawingBufferHeight / pixelRatio;
701
+ const screenSpaceErrorMultiplier = screenHeight / frustum.sseDenominator;
702
+
703
+ spatialNode.computeScreenSpaceError(positionWC, screenSpaceErrorMultiplier);
704
+
705
+ visibilityPlaneMask = spatialNode.visibility(frameState, visibilityPlaneMask);
706
+ if (visibilityPlaneMask === CullingVolume.MASK_OUTSIDE) {
707
+ return;
708
+ }
709
+ spatialNode.visitedFrameNumber = frameNumber;
710
+
711
+ const primitive = that._primitive;
712
+ const shape = primitive._shape;
713
+ const targetScreenSpaceError = primitive.screenSpaceError;
714
+ const priorityQueue = that._priorityQueue;
715
+ const keyframeCount = that._keyframeCount;
716
+ const previousKeyframe = CesiumMath.clamp(
717
+ Math.floor(that._keyframeLocation),
718
+ 0,
719
+ keyframeCount - 2,
720
+ );
721
+ const nextKeyframe = previousKeyframe + 1;
722
+
723
+ // Create keyframe nodes at the playhead.
724
+ // If they already exist, nothing will be created.
725
+ if (keyframeCount === 1) {
726
+ spatialNode.createKeyframeNode(0);
727
+ } else if (spatialNode.keyframeNodes.length !== keyframeCount) {
728
+ for (let k = 0; k < keyframeCount; k++) {
729
+ spatialNode.createKeyframeNode(k);
730
+ }
731
+ }
732
+ const { screenSpaceError, keyframeNodes } = spatialNode;
733
+ const ssePriority = mapInfiniteRangeToZeroOne(screenSpaceError);
734
+
735
+ let hasLoadedKeyframe = false;
736
+ for (let i = 0; i < keyframeNodes.length; i++) {
737
+ const keyframeNode = keyframeNodes[i];
738
+
739
+ keyframeNode.priority =
740
+ 10.0 * ssePriority +
741
+ keyframePriority(
742
+ previousKeyframe,
743
+ keyframeNode.keyframe,
744
+ nextKeyframe,
745
+ that,
746
+ );
747
+
748
+ if (
749
+ keyframeNode.state !== KeyframeNode.LoadState.UNAVAILABLE &&
750
+ keyframeNode.state !== KeyframeNode.LoadState.FAILED &&
751
+ keyframeNode.priority !== -Number.MAX_VALUE
752
+ ) {
753
+ priorityQueue.insert(keyframeNode);
754
+ }
755
+ if (keyframeNode.state === KeyframeNode.LoadState.LOADED) {
756
+ hasLoadedKeyframe = true;
757
+ }
758
+ }
759
+
760
+ if (screenSpaceError < targetScreenSpaceError || !hasLoadedKeyframe) {
761
+ // Free up memory
762
+ spatialNode.children = undefined;
763
+ return;
764
+ }
765
+
766
+ if (!defined(spatialNode.children)) {
767
+ spatialNode.constructChildNodes(shape);
768
+ }
769
+ for (let childIndex = 0; childIndex < 8; childIndex++) {
770
+ const child = spatialNode.children[childIndex];
771
+ addToQueueRecursive(child, visibilityPlaneMask, that, frameState);
772
+ }
663
773
  }
664
774
 
665
775
  /**
@@ -703,8 +813,9 @@ function keyframePriority(previousKeyframe, keyframe, nextKeyframe, traversal) {
703
813
  *
704
814
  * @private
705
815
  */
706
- function printDebugInformation(
816
+ function postPassesUpdate(
707
817
  that,
818
+ frameState,
708
819
  loadAndUnloadTimeMs,
709
820
  generateOctreeTimeMs,
710
821
  totalTimeMs,
@@ -722,16 +833,12 @@ function printDebugInformation(
722
833
  loadStateIndex < loadStateCount;
723
834
  loadStateIndex++
724
835
  ) {
725
- const keyframeArray = new Array(keyframeCount);
836
+ const keyframeArray = new Array(keyframeCount).fill(0);
726
837
  loadStatesByKeyframe[loadStateIndex] = keyframeArray;
727
- for (let i = 0; i < keyframeCount; i++) {
728
- keyframeArray[i] = 0;
729
- }
730
838
  loadStateByCount[loadStateIndex] = 0;
731
839
  }
732
840
 
733
841
  /**
734
- * @ignore
735
842
  * @param {SpatialNode} node
736
843
  */
737
844
  function traverseRecursive(node) {
@@ -758,13 +865,66 @@ function printDebugInformation(
758
865
  }
759
866
  traverseRecursive(rootNode);
760
867
 
868
+ that._primitive.statistics.numberOfTilesWithContentReady =
869
+ loadStateByCount[KeyframeNode.LoadState.LOADED];
870
+ that._primitive.statistics.visited = nodeCountTotal;
871
+
872
+ const numberOfPendingRequests =
873
+ loadStateByCount[KeyframeNode.LoadState.RECEIVING];
874
+ const numberOfTilesProcessing =
875
+ loadStateByCount[KeyframeNode.LoadState.PROCESSING];
876
+
877
+ const progressChanged =
878
+ numberOfPendingRequests !==
879
+ that._primitive.statistics.numberOfPendingRequests ||
880
+ numberOfTilesProcessing !==
881
+ that._primitive.statistics.numberOfTilesProcessing;
882
+
883
+ if (progressChanged) {
884
+ frameState.afterRender.push(function () {
885
+ that._primitive.loadProgress.raiseEvent(
886
+ numberOfPendingRequests,
887
+ numberOfTilesProcessing,
888
+ );
889
+
890
+ return true;
891
+ });
892
+ }
893
+
894
+ that._primitive.statistics.numberOfPendingRequests = numberOfPendingRequests;
895
+ that._primitive.statistics.numberOfTilesProcessing = numberOfTilesProcessing;
896
+
897
+ const tilesLoaded =
898
+ numberOfPendingRequests === 0 && numberOfTilesProcessing === 0;
899
+
900
+ // Events are raised (added to the afterRender queue) here since promises
901
+ // may resolve outside of the update loop that then raise events, e.g.,
902
+ // model's readyEvent
903
+ if (progressChanged && tilesLoaded) {
904
+ frameState.afterRender.push(function () {
905
+ that._primitive.allTilesLoaded.raiseEvent();
906
+ return true;
907
+ });
908
+ if (!that._initialTilesLoaded) {
909
+ that._initialTilesLoaded = true;
910
+ frameState.afterRender.push(function () {
911
+ that._primitive.initialTilesLoaded.raiseEvent();
912
+ return true;
913
+ });
914
+ }
915
+ }
916
+
917
+ if (!that._debugPrint) {
918
+ return;
919
+ }
920
+
761
921
  const loadedKeyframeStatistics = `KEYFRAMES: ${
762
922
  loadStatesByKeyframe[KeyframeNode.LoadState.LOADED]
763
923
  }`;
764
924
  const loadStateStatistics =
765
925
  `UNLOADED: ${loadStateByCount[KeyframeNode.LoadState.UNLOADED]} | ` +
766
926
  `RECEIVING: ${loadStateByCount[KeyframeNode.LoadState.RECEIVING]} | ` +
767
- `RECEIVED: ${loadStateByCount[KeyframeNode.LoadState.RECEIVED]} | ` +
927
+ `PROCESSING: ${loadStateByCount[KeyframeNode.LoadState.PROCESSING]} | ` +
768
928
  `LOADED: ${loadStateByCount[KeyframeNode.LoadState.LOADED]} | ` +
769
929
  `FAILED: ${loadStateByCount[KeyframeNode.LoadState.FAILED]} | ` +
770
930
  `UNAVAILABLE: ${loadStateByCount[KeyframeNode.LoadState.UNAVAILABLE]} | ` +
@@ -825,7 +985,6 @@ const GpuOctreeFlag = {
825
985
  * @function
826
986
  *
827
987
  * @param {VoxelTraversal} that
828
- * @param {FrameState} frameState
829
988
  * @param {number} sampleCount
830
989
  * @param {number} levelBlendFactor
831
990
  * @private
@@ -842,7 +1001,6 @@ function generateOctree(that, sampleCount, levelBlendFactor) {
842
1001
  const leafNodeOctreeData = [];
843
1002
 
844
1003
  /**
845
- * @ignore
846
1004
  * @param {SpatialNode} node
847
1005
  * @param {number} childOctreeIndex
848
1006
  * @param {number} childEntryIndex
@@ -892,6 +1050,7 @@ function generateOctree(that, sampleCount, levelBlendFactor) {
892
1050
  } else {
893
1051
  // Store the leaf node information instead
894
1052
  // Recursion stops here because there are no renderable children
1053
+ that._primitive.tileVisible.raiseEvent();
895
1054
  if (useLeafNodes) {
896
1055
  const baseIdx = leafNodeCount * 5;
897
1056
  const keyframeNode = node.renderableKeyframeNodePrevious;
@@ -1078,8 +1237,9 @@ function copyToLeafNodeTexture(data, texelsPerTile, tilesPerRow, texture) {
1078
1237
  * @param {Cartesian3} dimensions
1079
1238
  * @param {MetadataType[]} types
1080
1239
  * @param {MetadataComponentType[]} componentTypes
1240
+ * @private
1081
1241
  */
1082
- VoxelTraversal.getApproximateTextureMemoryByteLength = function (
1242
+ function getApproximateTextureMemoryByteLength(
1083
1243
  tileCount,
1084
1244
  dimensions,
1085
1245
  types,
@@ -1103,6 +1263,6 @@ VoxelTraversal.getApproximateTextureMemoryByteLength = function (
1103
1263
  }
1104
1264
 
1105
1265
  return textureMemoryByteLength;
1106
- };
1266
+ }
1107
1267
 
1108
1268
  export default VoxelTraversal;