easy-three-utils 0.0.1

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 (166) hide show
  1. package/package.json +12 -0
  2. package/src/common/index.ts +24 -0
  3. package/src/common/useLine2.ts +87 -0
  4. package/src/common/useLoader.ts +184 -0
  5. package/src/common/useLocationCalculator.ts +145 -0
  6. package/src/common/useMark.ts +42 -0
  7. package/src/common/useTween.ts +86 -0
  8. package/src/core/basic/camera.ts +28 -0
  9. package/src/core/basic/clock.ts +11 -0
  10. package/src/core/basic/control.ts +32 -0
  11. package/src/core/basic/index.ts +35 -0
  12. package/src/core/basic/labelRenderer.ts +26 -0
  13. package/src/core/basic/light.ts +63 -0
  14. package/src/core/basic/renderer.ts +37 -0
  15. package/src/core/basic/scene.ts +11 -0
  16. package/src/core/basic/stats.ts +16 -0
  17. package/src/core/event.ts +74 -0
  18. package/src/core/index.ts +11 -0
  19. package/src/core/main.ts +389 -0
  20. package/src/draco/README.md +32 -0
  21. package/src/draco/draco_decoder.js +34 -0
  22. package/src/draco/draco_decoder.wasm +0 -0
  23. package/src/draco/draco_encoder.js +33 -0
  24. package/src/draco/draco_wasm_wrapper.js +117 -0
  25. package/src/draco/gltf/draco_decoder.js +33 -0
  26. package/src/draco/gltf/draco_decoder.wasm +0 -0
  27. package/src/draco/gltf/draco_encoder.js +33 -0
  28. package/src/draco/gltf/draco_wasm_wrapper.js +116 -0
  29. package/src/tileRenderer/base/Tile.d.ts +50 -0
  30. package/src/tileRenderer/base/TileBase.d.ts +76 -0
  31. package/src/tileRenderer/base/TileInternal.d.ts +36 -0
  32. package/src/tileRenderer/base/TilesRendererBase.d.ts +35 -0
  33. package/src/tileRenderer/base/TilesRendererBase.js +847 -0
  34. package/src/tileRenderer/base/Tileset.d.ts +66 -0
  35. package/src/tileRenderer/base/constants.d.ts +6 -0
  36. package/src/tileRenderer/base/constants.js +16 -0
  37. package/src/tileRenderer/base/loaders/B3DMLoaderBase.d.ts +18 -0
  38. package/src/tileRenderer/base/loaders/B3DMLoaderBase.js +85 -0
  39. package/src/tileRenderer/base/loaders/CMPTLoaderBase.d.ts +22 -0
  40. package/src/tileRenderer/base/loaders/CMPTLoaderBase.js +61 -0
  41. package/src/tileRenderer/base/loaders/I3DMLoaderBase.d.ts +21 -0
  42. package/src/tileRenderer/base/loaders/I3DMLoaderBase.js +130 -0
  43. package/src/tileRenderer/base/loaders/LoaderBase.d.ts +10 -0
  44. package/src/tileRenderer/base/loaders/LoaderBase.js +73 -0
  45. package/src/tileRenderer/base/loaders/PNTSLoaderBase.d.ts +17 -0
  46. package/src/tileRenderer/base/loaders/PNTSLoaderBase.js +82 -0
  47. package/src/tileRenderer/base/plugins/ImplicitTilingPlugin.js +12 -0
  48. package/src/tileRenderer/base/traverseFunctions.js +468 -0
  49. package/src/tileRenderer/gltf.js +144 -0
  50. package/src/tileRenderer/index.d.ts +41 -0
  51. package/src/tileRenderer/index.js +44 -0
  52. package/src/tileRenderer/plugins/README.md +578 -0
  53. package/src/tileRenderer/plugins/base/ImplicitTilingPlugin.d.ts +2 -0
  54. package/src/tileRenderer/plugins/base/ImplicitTilingPlugin.js +84 -0
  55. package/src/tileRenderer/plugins/base/SUBTREELoader.js +876 -0
  56. package/src/tileRenderer/plugins/index.d.ts +17 -0
  57. package/src/tileRenderer/plugins/index.js +17 -0
  58. package/src/tileRenderer/plugins/three/CesiumIonAuthPlugin.d.ts +9 -0
  59. package/src/tileRenderer/plugins/three/CesiumIonAuthPlugin.js +175 -0
  60. package/src/tileRenderer/plugins/three/DebugTilesPlugin.d.ts +29 -0
  61. package/src/tileRenderer/plugins/three/DebugTilesPlugin.js +677 -0
  62. package/src/tileRenderer/plugins/three/GLTFExtensionsPlugin.d.ts +18 -0
  63. package/src/tileRenderer/plugins/three/GLTFExtensionsPlugin.js +86 -0
  64. package/src/tileRenderer/plugins/three/GoogleAttributionsManager.js +62 -0
  65. package/src/tileRenderer/plugins/three/GoogleCloudAuthPlugin.d.ts +5 -0
  66. package/src/tileRenderer/plugins/three/GoogleCloudAuthPlugin.js +200 -0
  67. package/src/tileRenderer/plugins/three/ReorientationPlugin.d.ts +12 -0
  68. package/src/tileRenderer/plugins/three/ReorientationPlugin.js +136 -0
  69. package/src/tileRenderer/plugins/three/TileCompressionPlugin.d.ts +18 -0
  70. package/src/tileRenderer/plugins/three/TileCompressionPlugin.js +223 -0
  71. package/src/tileRenderer/plugins/three/UpdateOnChangePlugin.d.ts +5 -0
  72. package/src/tileRenderer/plugins/three/UpdateOnChangePlugin.js +87 -0
  73. package/src/tileRenderer/plugins/three/fade/FadeManager.js +370 -0
  74. package/src/tileRenderer/plugins/three/fade/TilesFadePlugin.d.ts +9 -0
  75. package/src/tileRenderer/plugins/three/fade/TilesFadePlugin.js +318 -0
  76. package/src/tileRenderer/plugins/three/gltf/GLTFCesiumRTCExtension.d.ts +5 -0
  77. package/src/tileRenderer/plugins/three/gltf/GLTFCesiumRTCExtension.js +27 -0
  78. package/src/tileRenderer/plugins/three/gltf/GLTFMeshFeaturesExtension.d.ts +30 -0
  79. package/src/tileRenderer/plugins/three/gltf/GLTFMeshFeaturesExtension.js +76 -0
  80. package/src/tileRenderer/plugins/three/gltf/GLTFStructuralMetadataExtension.d.ts +49 -0
  81. package/src/tileRenderer/plugins/three/gltf/GLTFStructuralMetadataExtension.js +147 -0
  82. package/src/tileRenderer/plugins/three/gltf/metadata/classes/ClassProperty.js +149 -0
  83. package/src/tileRenderer/plugins/three/gltf/metadata/classes/MeshFeatures.js +215 -0
  84. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyAttributeAccessor.js +107 -0
  85. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertySetAccessor.js +45 -0
  86. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyTableAccessor.js +209 -0
  87. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyTextureAccessor.js +244 -0
  88. package/src/tileRenderer/plugins/three/gltf/metadata/classes/StructuralMetadata.js +202 -0
  89. package/src/tileRenderer/plugins/three/gltf/metadata/math/Matrix2.js +55 -0
  90. package/src/tileRenderer/plugins/three/gltf/metadata/utilities/ClassPropertyHelpers.js +495 -0
  91. package/src/tileRenderer/plugins/three/gltf/metadata/utilities/TexCoordUtilities.js +72 -0
  92. package/src/tileRenderer/plugins/three/gltf/metadata/utilities/TextureReadUtility.js +154 -0
  93. package/src/tileRenderer/plugins/three/objects/EllipsoidRegionHelper.js +186 -0
  94. package/src/tileRenderer/plugins/three/objects/SphereHelper.js +55 -0
  95. package/src/tileRenderer/r3f/README.md +238 -0
  96. package/src/tileRenderer/r3f/components/CameraControls.jsx +132 -0
  97. package/src/tileRenderer/r3f/components/CameraTransition.jsx +177 -0
  98. package/src/tileRenderer/r3f/components/CanvasDOMOverlay.jsx +54 -0
  99. package/src/tileRenderer/r3f/components/CompassGizmo.jsx +260 -0
  100. package/src/tileRenderer/r3f/components/TilesAttributionOverlay.jsx +110 -0
  101. package/src/tileRenderer/r3f/components/TilesRenderer.jsx +239 -0
  102. package/src/tileRenderer/r3f/index.jsx +6 -0
  103. package/src/tileRenderer/r3f/utilities/useForceUpdate.jsx +8 -0
  104. package/src/tileRenderer/r3f/utilities/useObjectDep.jsx +59 -0
  105. package/src/tileRenderer/r3f/utilities/useOptions.jsx +143 -0
  106. package/src/tileRenderer/three/DebugTilesRenderer.d.ts +28 -0
  107. package/src/tileRenderer/three/DebugTilesRenderer.js +58 -0
  108. package/src/tileRenderer/three/TilesGroup.d.ts +9 -0
  109. package/src/tileRenderer/three/TilesGroup.js +91 -0
  110. package/src/tileRenderer/three/TilesRenderer.d.ts +37 -0
  111. package/src/tileRenderer/three/TilesRenderer.js +1049 -0
  112. package/src/tileRenderer/three/controls/CameraTransitionManager.js +305 -0
  113. package/src/tileRenderer/three/controls/EnvironmentControls.js +1295 -0
  114. package/src/tileRenderer/three/controls/GlobeControls.js +684 -0
  115. package/src/tileRenderer/three/controls/PivotPointMesh.js +104 -0
  116. package/src/tileRenderer/three/controls/PointerTracker.js +257 -0
  117. package/src/tileRenderer/three/controls/utils.js +113 -0
  118. package/src/tileRenderer/three/loaders/B3DMLoader.d.ts +26 -0
  119. package/src/tileRenderer/three/loaders/B3DMLoader.js +85 -0
  120. package/src/tileRenderer/three/loaders/CMPTLoader.d.ts +19 -0
  121. package/src/tileRenderer/three/loaders/CMPTLoader.js +97 -0
  122. package/src/tileRenderer/three/loaders/GLTFExtensionLoader.d.ts +11 -0
  123. package/src/tileRenderer/three/loaders/GLTFExtensionLoader.js +68 -0
  124. package/src/tileRenderer/three/loaders/I3DMLoader.d.ts +26 -0
  125. package/src/tileRenderer/three/loaders/I3DMLoader.js +256 -0
  126. package/src/tileRenderer/three/loaders/PNTSLoader.d.ts +25 -0
  127. package/src/tileRenderer/three/loaders/PNTSLoader.js +202 -0
  128. package/src/tileRenderer/three/loaders/gltf/GLTFCesiumRTCExtension.js +12 -0
  129. package/src/tileRenderer/three/loaders/gltf/GLTFMeshFeaturesExtension.js +12 -0
  130. package/src/tileRenderer/three/loaders/gltf/GLTFStructuralMetadataExtension.js +12 -0
  131. package/src/tileRenderer/three/math/Ellipsoid.d.ts +31 -0
  132. package/src/tileRenderer/three/math/Ellipsoid.js +337 -0
  133. package/src/tileRenderer/three/math/EllipsoidRegion.d.ts +23 -0
  134. package/src/tileRenderer/three/math/EllipsoidRegion.js +178 -0
  135. package/src/tileRenderer/three/math/ExtendedFrustum.js +65 -0
  136. package/src/tileRenderer/three/math/GeoConstants.d.ts +4 -0
  137. package/src/tileRenderer/three/math/GeoConstants.js +5 -0
  138. package/src/tileRenderer/three/math/GeoUtils.d.ts +9 -0
  139. package/src/tileRenderer/three/math/GeoUtils.js +106 -0
  140. package/src/tileRenderer/three/math/OBB.js +179 -0
  141. package/src/tileRenderer/three/math/TileBoundingVolume.js +272 -0
  142. package/src/tileRenderer/three/plugins/CesiumIonAuthPlugin.js +12 -0
  143. package/src/tileRenderer/three/plugins/DebugTilesPlugin.js +26 -0
  144. package/src/tileRenderer/three/plugins/GoogleCloudAuthPlugin.js +12 -0
  145. package/src/tileRenderer/three/raycastTraverse.js +178 -0
  146. package/src/tileRenderer/three/renderers/CesiumIonTilesRenderer.d.ts +14 -0
  147. package/src/tileRenderer/three/renderers/CesiumIonTilesRenderer.js +21 -0
  148. package/src/tileRenderer/three/renderers/GoogleTilesRenderer.d.ts +43 -0
  149. package/src/tileRenderer/three/renderers/GoogleTilesRenderer.js +48 -0
  150. package/src/tileRenderer/three/utilities.js +54 -0
  151. package/src/tileRenderer/utilities/BatchTable.d.ts +24 -0
  152. package/src/tileRenderer/utilities/BatchTable.js +82 -0
  153. package/src/tileRenderer/utilities/BatchTableHierarchyExtension.js +127 -0
  154. package/src/tileRenderer/utilities/FeatureTable.d.ts +30 -0
  155. package/src/tileRenderer/utilities/FeatureTable.js +159 -0
  156. package/src/tileRenderer/utilities/LRUCache.d.ts +8 -0
  157. package/src/tileRenderer/utilities/LRUCache.js +385 -0
  158. package/src/tileRenderer/utilities/PriorityQueue.d.ts +16 -0
  159. package/src/tileRenderer/utilities/PriorityQueue.js +137 -0
  160. package/src/tileRenderer/utilities/arrayToString.js +7 -0
  161. package/src/tileRenderer/utilities/readMagicBytes.js +29 -0
  162. package/src/tileRenderer/utilities/rgb565torgb.js +22 -0
  163. package/src/tileRenderer/utilities/urlExtension.js +34 -0
  164. package/tsconfig.json +42 -0
  165. package/tsconfig.node.json +11 -0
  166. package/typings/three.d.ts +27 -0
@@ -0,0 +1,847 @@
1
+ import { getUrlExtension } from '../utilities/urlExtension.js';
2
+ import { LRUCache } from '../utilities/LRUCache.js';
3
+ import { PriorityQueue } from '../utilities/PriorityQueue.js';
4
+ import { markUsedTiles, toggleTiles, markVisibleTiles, markUsedSetLeaves, traverseSet } from './traverseFunctions.js';
5
+ import { UNLOADED, LOADING, PARSING, LOADED, FAILED } from './constants.js';
6
+
7
+ const PLUGIN_REGISTERED = Symbol('PLUGIN_REGISTERED');
8
+
9
+ // priority queue sort function that takes two tiles to compare. Returning 1 means
10
+ // "tile a" is loaded first.
11
+ const priorityCallback = (a, b) => {
12
+
13
+ if (a.__depthFromRenderedParent !== b.__depthFromRenderedParent) {
14
+
15
+ // load shallower tiles first using "depth from rendered parent" to help
16
+ // even out depth disparities caused by non-content parent tiles
17
+ return a.__depthFromRenderedParent > b.__depthFromRenderedParent ? - 1 : 1;
18
+
19
+ } else if (a.__inFrustum !== b.__inFrustum) {
20
+
21
+ // load tiles that are in the frustum at the current depth
22
+ return a.__inFrustum ? 1 : - 1;
23
+
24
+ } else if (a.__used !== b.__used) {
25
+
26
+ // load tiles that have been used
27
+ return a.__used ? 1 : - 1;
28
+
29
+ } else if (a.__error !== b.__error) {
30
+
31
+ // load the tile with the higher error
32
+ return a.__error > b.__error ? 1 : - 1;
33
+
34
+ } else if (a.__distanceFromCamera !== b.__distanceFromCamera) {
35
+
36
+ // and finally visible tiles which have equal error (ex: if geometricError === 0)
37
+ // should prioritize based on distance.
38
+ return a.__distanceFromCamera > b.__distanceFromCamera ? - 1 : 1;
39
+
40
+ }
41
+
42
+ return 0;
43
+
44
+ };
45
+
46
+ // lru cache unload callback that takes two tiles to compare. Returning 1 means "tile a"
47
+ // is unloaded first.
48
+ const lruPriorityCallback = (a, b) => {
49
+
50
+ if (a.__depthFromRenderedParent !== b.__depthFromRenderedParent) {
51
+
52
+ // dispose of deeper tiles first
53
+ return a.__depthFromRenderedParent > b.__depthFromRenderedParent ? 1 : - 1;
54
+
55
+ } else if (a.__loadingState !== b.__loadingState) {
56
+
57
+ // dispose of tiles that are earlier along in the loading process first
58
+ return a.__loadingState > b.__loadingState ? - 1 : 1;
59
+
60
+ } else if (a.__lastFrameVisited !== b.__lastFrameVisited) {
61
+
62
+ // dispose of least recent tiles first
63
+ return a.__lastFrameVisited > b.__lastFrameVisited ? - 1 : 1;
64
+
65
+ } else if (a.__hasUnrenderableContent !== b.__hasUnrenderableContent) {
66
+
67
+ // dispose of external tile sets last
68
+ return a.__hasUnrenderableContent ? - 1 : 1;
69
+
70
+ } else if (a.__error !== b.__error) {
71
+
72
+ // unload the tile with lower error
73
+ return a.__error > b.__error ? - 1 : 1;
74
+
75
+ }
76
+
77
+ return 0;
78
+
79
+ };
80
+
81
+ export class TilesRendererBase {
82
+
83
+ get root() {
84
+
85
+ const tileSet = this.rootTileSet;
86
+ return tileSet ? tileSet.root : null;
87
+
88
+ }
89
+
90
+ set loadSiblings(v) {
91
+
92
+ console.warn('TilesRenderer: "loadSiblings" option has been removed.');
93
+
94
+ }
95
+
96
+ set stopAtEmptyTiles(v) {
97
+
98
+ console.warn('TilesRenderer: "stopAtEmptyTiles" option has been removed.');
99
+
100
+ }
101
+
102
+ set preprocessURL(v) {
103
+
104
+ console.warn('TilesRendererBase: The "preprocessURL" callback has been deprecated. Use a plugin, instead.');
105
+ this._preprocessURL = v;
106
+
107
+ }
108
+
109
+ get preprocessURL() {
110
+
111
+ return this._preprocessURL;
112
+
113
+ }
114
+
115
+ constructor(url = null) {
116
+ // state
117
+ this.rootLoadingState = UNLOADED;
118
+ this.rootTileSet = null;
119
+ this.rootURL = url;
120
+ this.fetchOptions = {};
121
+ this.plugins = [];
122
+ this.queuedTiles = [];
123
+
124
+ this._preprocessURL = null;
125
+
126
+ const lruCache = new LRUCache();
127
+ lruCache.unloadPriorityCallback = lruPriorityCallback;
128
+
129
+ const downloadQueue = new PriorityQueue();
130
+ downloadQueue.maxJobs = 10;
131
+ downloadQueue.priorityCallback = priorityCallback;
132
+
133
+ const parseQueue = new PriorityQueue();
134
+ parseQueue.maxJobs = 1;
135
+ parseQueue.priorityCallback = priorityCallback;
136
+
137
+ this.lruCache = lruCache;
138
+ this.downloadQueue = downloadQueue;
139
+ this.parseQueue = parseQueue;
140
+ this.stats = {
141
+ parsing: 0,
142
+ downloading: 0,
143
+ failed: 0,
144
+ inFrustum: 0,
145
+ used: 0,
146
+ active: 0,
147
+ visible: 0,
148
+ };
149
+ this.frameCount = 0;
150
+
151
+ // options
152
+ this.errorTarget = 6.0;
153
+ this.errorThreshold = Infinity;
154
+ this.displayActiveTiles = false;
155
+ this.maxDepth = Infinity;
156
+
157
+ }
158
+
159
+ // Plugins
160
+ registerPlugin(plugin) {
161
+
162
+ if (plugin[PLUGIN_REGISTERED] === true) {
163
+
164
+ throw new Error('TilesRendererBase: A plugin can only be registered to a single tile set');
165
+
166
+ }
167
+
168
+ this.plugins.push(plugin);
169
+ plugin[PLUGIN_REGISTERED] = true;
170
+ if (plugin.init) {
171
+
172
+ plugin.init(this);
173
+
174
+ }
175
+
176
+ }
177
+
178
+ unregisterPlugin(plugin) {
179
+
180
+ const plugins = this.plugins;
181
+ if (typeof plugin === 'string') {
182
+
183
+ plugin = this.getPluginByName(name);
184
+
185
+ }
186
+
187
+ if (plugins.includes(plugin)) {
188
+
189
+ const index = plugins.indexOf(plugin);
190
+ plugins.splice(index, 1);
191
+ if (plugin.dispose) {
192
+
193
+ plugin.dispose();
194
+
195
+ }
196
+
197
+ return true;
198
+
199
+ }
200
+
201
+ return false;
202
+
203
+ }
204
+
205
+ getPluginByName(name) {
206
+
207
+ return this.plugins.find(p => p.name === name) || null;
208
+
209
+ }
210
+
211
+ traverse(beforecb, aftercb) {
212
+
213
+ if (!this.root) return;
214
+
215
+ traverseSet(this.root, (tile, ...args) => {
216
+
217
+ this.ensureChildrenArePreprocessed(tile);
218
+ return beforecb ? beforecb(tile, ...args) : false;
219
+
220
+ }, aftercb);
221
+
222
+ }
223
+
224
+ queueTileForDownload(tile) {
225
+
226
+ this.queuedTiles.push(tile);
227
+
228
+ }
229
+
230
+ // Public API
231
+ update() {
232
+
233
+ const stats = this.stats;
234
+ const lruCache = this.lruCache;
235
+ if (this.rootLoadingState === UNLOADED) {
236
+
237
+ this.rootLoadingState = LOADING;
238
+ this.invokeOnePlugin(plugin => plugin.loadRootTileSet && plugin.loadRootTileSet())
239
+ .then(() => this.rootLoadingState = LOADED)
240
+ .catch(() => this.rootLoadingState = FAILED);
241
+
242
+ }
243
+
244
+ if (!this.root) {
245
+
246
+ return;
247
+
248
+ }
249
+
250
+ const root = this.root;
251
+
252
+ stats.inFrustum = 0;
253
+ stats.used = 0;
254
+ stats.active = 0;
255
+ stats.visible = 0;
256
+ this.frameCount++;
257
+
258
+ markUsedTiles(root, this);
259
+ markUsedSetLeaves(root, this);
260
+ markVisibleTiles(root, this);
261
+ toggleTiles(root, this);
262
+
263
+ // TODO: This will only sort for one tile set. We may want to store this queue on the
264
+ // LRUCache so multiple tile sets can use it at once
265
+ // start the downloads of the tiles as needed
266
+ const queuedTiles = this.queuedTiles;
267
+ queuedTiles.sort(lruCache.unloadPriorityCallback);
268
+
269
+ for (let i = 0, l = queuedTiles.length; i < l && !lruCache.isFull(); i++) {
270
+
271
+ this.requestTileContents(queuedTiles[i]);
272
+
273
+ }
274
+
275
+ queuedTiles.length = 0;
276
+
277
+ // start the downloads
278
+ lruCache.scheduleUnload();
279
+
280
+ }
281
+
282
+ resetFailedTiles() {
283
+
284
+ // reset the root tile if it's finished but never loaded
285
+ if (this.rootLoadingState === FAILED) {
286
+
287
+ this.rootLoadingState = UNLOADED;
288
+
289
+ }
290
+
291
+ const stats = this.stats;
292
+ if (stats.failed === 0) {
293
+
294
+ return;
295
+
296
+ }
297
+
298
+ this.traverse(tile => {
299
+
300
+ if (tile.__loadingState === FAILED) {
301
+
302
+ tile.__loadingState = UNLOADED;
303
+
304
+ }
305
+
306
+ });
307
+
308
+ stats.failed = 0;
309
+
310
+ }
311
+
312
+ dispose() {
313
+
314
+ // dispose of all the plugins
315
+ this.invokeAllPlugins(plugin => {
316
+
317
+ plugin !== this && plugin.dispose && plugin.dispose();
318
+
319
+ });
320
+
321
+ const lruCache = this.lruCache;
322
+
323
+ // Make sure we've collected all children before disposing of the internal tilesets to avoid
324
+ // dangling children that we inadvertantly skip when deleting the nested tileset.
325
+ const toRemove = [];
326
+ this.traverse(t => {
327
+
328
+ toRemove.push(t);
329
+ return false;
330
+
331
+ });
332
+ for (let i = 0, l = toRemove.length; i < l; i++) {
333
+
334
+ lruCache.remove(toRemove[i]);
335
+
336
+ }
337
+
338
+ this.stats = {
339
+ parsing: 0,
340
+ downloading: 0,
341
+ failed: 0,
342
+ inFrustum: 0,
343
+ used: 0,
344
+ active: 0,
345
+ visible: 0,
346
+ };
347
+ this.frameCount = 0;
348
+
349
+ }
350
+
351
+ // Overrideable
352
+ fetchData(url, options) {
353
+
354
+ return fetch(url, options);
355
+
356
+ }
357
+
358
+ parseTile(buffer, tile, extension) {
359
+
360
+ return null;
361
+
362
+ }
363
+
364
+ disposeTile(tile) {
365
+
366
+ if (tile.__visible) {
367
+
368
+ this.setTileVisible(tile, false);
369
+ tile.__visible = false;
370
+
371
+ }
372
+
373
+ if (tile.__active) {
374
+
375
+ this.setTileActive(tile, false);
376
+ tile.__active = false;
377
+
378
+ }
379
+
380
+ }
381
+
382
+ preprocessNode(tile, tileSetDir, parentTile = null) {
383
+
384
+ if (tile.content) {
385
+ // Fix old file formats
386
+ if (!('uri' in tile.content) && 'url' in tile.content) {
387
+ tile.content.uri = tile.content.url;
388
+ delete tile.content.url;
389
+
390
+ }
391
+
392
+ // NOTE: fix for some cases where tilesets provide the bounding volume
393
+ // but volumes are not present.
394
+ if (
395
+ tile.content.boundingVolume &&
396
+ !(
397
+ 'box' in tile.content.boundingVolume ||
398
+ 'sphere' in tile.content.boundingVolume ||
399
+ 'region' in tile.content.boundingVolume
400
+ )
401
+ ) {
402
+ delete tile.content.boundingVolume;
403
+
404
+ }
405
+
406
+ }
407
+
408
+ tile.parent = parentTile;
409
+ tile.children = tile.children || [];
410
+
411
+ if (tile.content?.uri) {
412
+
413
+ // "content" should only indicate loadable meshes, not external tile sets
414
+ const extension = getUrlExtension(tile.content.uri);
415
+
416
+ tile.__hasContent = true;
417
+ tile.__hasUnrenderableContent = Boolean(extension && /json$/.test(extension));
418
+ tile.__hasRenderableContent = !tile.__hasUnrenderableContent;
419
+
420
+ } else {
421
+
422
+ tile.__hasContent = false;
423
+ tile.__hasUnrenderableContent = false;
424
+ tile.__hasRenderableContent = false;
425
+
426
+ }
427
+
428
+ // Expected to be set during calculateError()
429
+ tile.__distanceFromCamera = Infinity;
430
+ tile.__error = Infinity;
431
+
432
+ tile.__inFrustum = false;
433
+ tile.__isLeaf = false;
434
+
435
+ tile.__usedLastFrame = false;
436
+ tile.__used = false;
437
+
438
+ tile.__wasSetVisible = false;
439
+ tile.__visible = false;
440
+ tile.__childrenWereVisible = false;
441
+ tile.__allChildrenLoaded = false;
442
+
443
+ tile.__wasSetActive = false;
444
+ tile.__active = false;
445
+
446
+ tile.__loadingState = UNLOADED;
447
+ tile.__loadIndex = 0;
448
+
449
+ tile.__loadAbort = null;
450
+
451
+ if (parentTile === null) {
452
+
453
+ tile.__depth = 0;
454
+ tile.__depthFromRenderedParent = 0;
455
+ tile.refine = tile.refine || 'REPLACE';
456
+
457
+ } else {
458
+
459
+ // increment the "depth from parent" when we encounter a new tile with content
460
+ tile.__depth = parentTile.__depth + 1;
461
+ tile.__depthFromRenderedParent = parentTile.__depthFromRenderedParent + (tile.__hasRenderableContent ? 1 : 0);
462
+
463
+ tile.refine = tile.refine || parentTile.refine;
464
+
465
+ }
466
+
467
+ tile.__basePath = tileSetDir;
468
+
469
+ tile.__lastFrameVisited = - 1;
470
+
471
+ this.invokeAllPlugins(plugin => {
472
+
473
+ plugin !== this && plugin.preprocessNode && plugin.preprocessNode(tile, tileSetDir, parentTile);
474
+
475
+ });
476
+
477
+ }
478
+
479
+ setTileActive(tile, state) {
480
+
481
+ }
482
+
483
+ setTileVisible(tile, state) {
484
+
485
+ }
486
+
487
+ calculateError(tile) {
488
+
489
+ return 0;
490
+
491
+ }
492
+
493
+ tileInView(tile) {
494
+
495
+ return true;
496
+
497
+ }
498
+
499
+ ensureChildrenArePreprocessed(tile) {
500
+
501
+ const children = tile.children;
502
+ for (let i = 0, l = children.length; i < l; i++) {
503
+
504
+ const child = children[i];
505
+ if ('__depth' in child) {
506
+
507
+ break;
508
+
509
+ }
510
+
511
+ this.preprocessNode(child, tile.__basePath, tile);
512
+
513
+ }
514
+
515
+ }
516
+
517
+ // Private Functions
518
+ preprocessTileSet(json, url, parent = null) {
519
+
520
+ const version = json.asset.version;
521
+ const [major, minor] = version.split('.').map(v => parseInt(v));
522
+ console.assert(
523
+ major <= 1,
524
+ 'TilesRenderer: asset.version is expected to be a 1.x or a compatible version.',
525
+ );
526
+
527
+ if (major === 1 && minor > 0) {
528
+
529
+ console.warn('TilesRenderer: tiles versions at 1.1 or higher have limited support. Some new extensions and features may not be supported.');
530
+
531
+ }
532
+
533
+ // remove trailing slash and last path-segment from the URL
534
+ let basePath = url.replace(/\/[^/]*\/?$/, '');
535
+ basePath = new URL(basePath, window.location.href).toString();
536
+ this.preprocessNode(json.root, basePath, parent);
537
+
538
+ }
539
+
540
+ loadRootTileSet() {
541
+
542
+ // transform the url
543
+ let processedUrl = this.rootURL;
544
+ this.invokeAllPlugins(plugin => processedUrl = plugin.preprocessURL ? plugin.preprocessURL(processedUrl, null) : processedUrl);
545
+
546
+ // load the tile set root
547
+ const pr = this
548
+ .invokeOnePlugin(plugin => plugin.fetchData && plugin.fetchData(processedUrl, this.fetchOptions))
549
+ .then(res => {
550
+
551
+ if (res.ok) {
552
+
553
+ return res.json();
554
+
555
+ } else {
556
+
557
+ throw new Error(`TilesRenderer: Failed to load tileset "${processedUrl}" with status ${res.status} : ${res.statusText}`);
558
+
559
+ }
560
+
561
+ })
562
+ .then(json => {
563
+
564
+ this.preprocessTileSet(json, processedUrl);
565
+ this.rootTileSet = json;
566
+
567
+ });
568
+
569
+ pr.catch(err => {
570
+
571
+ console.error(err);
572
+ this.rootTileSet = null;
573
+
574
+ });
575
+
576
+ return pr;
577
+
578
+ }
579
+
580
+ requestTileContents(tile) {
581
+ // If the tile is already being loaded then don't
582
+ // start it again.
583
+ if (tile.__loadingState !== UNLOADED) {
584
+
585
+ return;
586
+
587
+ }
588
+
589
+ let isExternalTileSet = false;
590
+ let uri = new URL(tile.content.uri, tile.__basePath + '/').toString();
591
+ this.invokeAllPlugins(plugin => uri = plugin.preprocessURL ? plugin.preprocessURL(uri, tile) : uri);
592
+
593
+ const stats = this.stats;
594
+ const lruCache = this.lruCache;
595
+ const downloadQueue = this.downloadQueue;
596
+ const parseQueue = this.parseQueue;
597
+ const extension = getUrlExtension(uri);
598
+ const addedSuccessfully = lruCache.add(tile, t => {
599
+
600
+ // Stop the load if it's started
601
+ if (t.__loadingState === LOADING) {
602
+
603
+ t.__loadAbort.abort();
604
+ t.__loadAbort = null;
605
+
606
+ } else if (isExternalTileSet) {
607
+
608
+ t.children.length = 0;
609
+
610
+ } else {
611
+
612
+ this.invokeAllPlugins(plugin => {
613
+
614
+ plugin.disposeTile && plugin.disposeTile(t);
615
+
616
+ });
617
+
618
+ }
619
+
620
+ // Decrement stats
621
+ if (t.__loadingState === LOADING) {
622
+
623
+ stats.downloading--;
624
+
625
+ } else if (t.__loadingState === PARSING) {
626
+
627
+ stats.parsing--;
628
+
629
+ }
630
+
631
+ t.__loadingState = UNLOADED;
632
+ t.__loadIndex++;
633
+
634
+ parseQueue.remove(t);
635
+ downloadQueue.remove(t);
636
+
637
+ });
638
+
639
+ // if we couldn't add the tile to the lru cache because it's full then skip
640
+ if (!addedSuccessfully) {
641
+
642
+ return;
643
+
644
+ }
645
+
646
+ // Track a new load index so we avoid the condition where this load is stopped and
647
+ // another begins soon after so we don't parse twice.
648
+ tile.__loadIndex++;
649
+ const loadIndex = tile.__loadIndex;
650
+ const controller = new AbortController();
651
+ const signal = controller.signal;
652
+
653
+ stats.downloading++;
654
+ tile.__loadAbort = controller;
655
+ tile.__loadingState = LOADING;
656
+
657
+ const errorCallback = e => {
658
+
659
+ // if it has been unloaded then the tile has been disposed
660
+ if (tile.__loadIndex !== loadIndex) {
661
+
662
+ return;
663
+
664
+ }
665
+
666
+ if (e.name !== 'AbortError') {
667
+
668
+ parseQueue.remove(tile);
669
+ downloadQueue.remove(tile);
670
+
671
+ if (tile.__loadingState === PARSING) {
672
+
673
+ stats.parsing--;
674
+
675
+ } else if (tile.__loadingState === LOADING) {
676
+
677
+ stats.downloading--;
678
+
679
+ }
680
+
681
+ stats.failed++;
682
+
683
+ console.error(`TilesRenderer : Failed to load tile at url "${tile.content.uri}".`);
684
+ console.error(e);
685
+ tile.__loadingState = FAILED;
686
+ lruCache.setLoaded(tile, true);
687
+
688
+ } else {
689
+
690
+ lruCache.remove(tile);
691
+
692
+ }
693
+
694
+ };
695
+
696
+ // queue the download and parse
697
+ return downloadQueue.add(tile, downloadTile => {
698
+
699
+ if (downloadTile.__loadIndex !== loadIndex) {
700
+
701
+ return Promise.resolve();
702
+
703
+ }
704
+
705
+ return this.invokeOnePlugin(plugin => plugin.fetchData && plugin.fetchData(uri, { ...this.fetchOptions, signal }));
706
+
707
+ })
708
+ .then(res => {
709
+
710
+ if (tile.__loadIndex !== loadIndex) {
711
+
712
+ return;
713
+
714
+ }
715
+
716
+ if (res.ok) {
717
+
718
+ return extension === 'json' ? res.json() : res.arrayBuffer();
719
+
720
+ } else {
721
+
722
+ throw new Error(`Failed to load model with error code ${res.status}`);
723
+
724
+ }
725
+
726
+ })
727
+ .then(content => {
728
+
729
+ // if it has been unloaded then the tile has been disposed
730
+ if (tile.__loadIndex !== loadIndex) {
731
+
732
+ return;
733
+
734
+ }
735
+
736
+ stats.downloading--;
737
+ stats.parsing++;
738
+ tile.__loadAbort = null;
739
+ tile.__loadingState = PARSING;
740
+
741
+ return parseQueue.add(tile, parseTile => {
742
+
743
+ // if it has been unloaded then the tile has been disposed
744
+ if (parseTile.__loadIndex !== loadIndex) {
745
+
746
+ return Promise.resolve();
747
+
748
+ }
749
+
750
+ if (extension === 'json' && content.root) {
751
+
752
+ this.preprocessTileSet(content, uri, tile);
753
+ tile.children.push(content.root);
754
+ isExternalTileSet = true;
755
+ return Promise.resolve();
756
+
757
+ } else {
758
+
759
+ return this.invokeOnePlugin(plugin => plugin.parseTile && plugin.parseTile(content, parseTile, extension, uri));
760
+
761
+ }
762
+
763
+ });
764
+
765
+ })
766
+ .then(() => {
767
+
768
+ // if it has been unloaded then the tile has been disposed
769
+ if (tile.__loadIndex !== loadIndex) {
770
+
771
+ return;
772
+
773
+ }
774
+
775
+ stats.parsing--;
776
+ tile.__loadingState = LOADED;
777
+ lruCache.setLoaded(tile, true);
778
+
779
+ // If the memory of the item hasn't been registered yet then that means the memory usage hasn't
780
+ // been accounted for by the cache yet so we need to check if it fits or if we should remove it.
781
+ if (lruCache.getMemoryUsage(tile) === null) {
782
+
783
+ if (lruCache.isFull() && lruCache.computeMemoryUsageCallback(tile) > 0) {
784
+
785
+ // And if the cache is full due to newly loaded memory then lets discard this tile - it will
786
+ // be loaded again later from the disk cache if needed.
787
+ lruCache.remove(tile);
788
+
789
+ } else {
790
+
791
+ // Otherwise update the item to the latest known value
792
+ lruCache.updateMemoryUsage(tile);
793
+
794
+ }
795
+
796
+ }
797
+
798
+ })
799
+ .catch(errorCallback);
800
+
801
+ }
802
+
803
+ getAttributions(target = []) {
804
+
805
+ this.invokeAllPlugins(plugin => plugin !== this && plugin.getAttributions && plugin.getAttributions(target));
806
+ return target;
807
+
808
+ }
809
+
810
+ invokeOnePlugin(func) {
811
+
812
+ const plugins = [...this.plugins, this];
813
+ for (let i = 0; i < plugins.length; i++) {
814
+
815
+ const result = func(plugins[i]);
816
+ if (result) {
817
+
818
+ return result;
819
+
820
+ }
821
+
822
+ }
823
+
824
+ return null;
825
+
826
+ }
827
+
828
+ invokeAllPlugins(func) {
829
+
830
+ const plugins = [...this.plugins, this];
831
+ const pending = [];
832
+ for (let i = 0; i < plugins.length; i++) {
833
+
834
+ const result = func(plugins[i]);
835
+ if (result) {
836
+
837
+ pending.push(result);
838
+
839
+ }
840
+
841
+ }
842
+
843
+ return pending.length === 0 ? null : Promise.all(pending);
844
+
845
+ }
846
+
847
+ }