@loaders.gl/tiles 3.4.0-alpha.4 → 3.4.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 (45) hide show
  1. package/dist/constants.d.ts +6 -0
  2. package/dist/constants.d.ts.map +1 -1
  3. package/dist/constants.js +0 -1
  4. package/dist/dist.min.js +171 -151
  5. package/dist/es5/constants.js.map +1 -1
  6. package/dist/es5/tileset/helpers/3d-tiles-options.js.map +1 -1
  7. package/dist/es5/tileset/tile-3d.js +41 -71
  8. package/dist/es5/tileset/tile-3d.js.map +1 -1
  9. package/dist/es5/tileset/tileset-3d.js +68 -102
  10. package/dist/es5/tileset/tileset-3d.js.map +1 -1
  11. package/dist/es5/tileset/tileset-cache.js +4 -7
  12. package/dist/es5/tileset/tileset-cache.js.map +1 -1
  13. package/dist/es5/tileset/tileset-traverser.js +12 -22
  14. package/dist/es5/tileset/tileset-traverser.js.map +1 -1
  15. package/dist/esm/constants.js.map +1 -1
  16. package/dist/esm/tileset/helpers/3d-tiles-options.js.map +1 -1
  17. package/dist/esm/tileset/tile-3d.js +39 -71
  18. package/dist/esm/tileset/tile-3d.js.map +1 -1
  19. package/dist/esm/tileset/tileset-3d.js +64 -94
  20. package/dist/esm/tileset/tileset-3d.js.map +1 -1
  21. package/dist/esm/tileset/tileset-cache.js +4 -7
  22. package/dist/esm/tileset/tileset-cache.js.map +1 -1
  23. package/dist/esm/tileset/tileset-traverser.js +9 -19
  24. package/dist/esm/tileset/tileset-traverser.js.map +1 -1
  25. package/dist/tileset/helpers/3d-tiles-options.d.ts +3 -2
  26. package/dist/tileset/helpers/3d-tiles-options.d.ts.map +1 -1
  27. package/dist/tileset/tile-3d.d.ts +36 -21
  28. package/dist/tileset/tile-3d.d.ts.map +1 -1
  29. package/dist/tileset/tile-3d.js +58 -43
  30. package/dist/tileset/tileset-3d.d.ts +90 -43
  31. package/dist/tileset/tileset-3d.d.ts.map +1 -1
  32. package/dist/tileset/tileset-3d.js +108 -127
  33. package/dist/tileset/tileset-cache.d.ts +5 -4
  34. package/dist/tileset/tileset-cache.d.ts.map +1 -1
  35. package/dist/tileset/tileset-cache.js +4 -10
  36. package/dist/tileset/tileset-traverser.d.ts +32 -21
  37. package/dist/tileset/tileset-traverser.d.ts.map +1 -1
  38. package/dist/tileset/tileset-traverser.js +23 -35
  39. package/package.json +4 -4
  40. package/src/constants.ts +18 -0
  41. package/src/tileset/helpers/3d-tiles-options.ts +3 -1
  42. package/src/tileset/tile-3d.ts +70 -109
  43. package/src/tileset/tileset-3d.ts +178 -216
  44. package/src/tileset/tileset-cache.ts +20 -15
  45. package/src/tileset/tileset-traverser.ts +52 -68
@@ -3,58 +3,18 @@
3
3
  // This file is derived from the Cesium code base under Apache 2 license
4
4
  // See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md
5
5
 
6
- /*
7
-
8
- The Tileset loading and rendering flow is as below,
9
- A rendered (i.e. deck.gl `Tile3DLayer`) triggers `tileset.update()` after a `tileset` is loaded
10
- `tileset` starts traversing the tile tree and update `requestTiles` (tiles of which content need
11
- to be fetched) and `selectedTiles` (tiles ready for rendering under the current viewport).
12
- `Tile3DLayer` will update rendering based on `selectedTiles`.
13
- `Tile3DLayer` also listens to `onTileLoad` callback and trigger another round of `update and then traversal`
14
- when new tiles are loaded.
15
-
16
- As I3S tileset have stored `tileHeader` file (metadata) and tile content files (geometry, texture, ...) separately.
17
- During each traversal, it issues `tilHeader` requests if that `tileHeader` is not yet fetched,
18
- after the tile header is fulfilled, it will resume the traversal starting from the tile just fetched (not root).
19
-
20
- Tile3DLayer
21
- |
22
- await load(tileset)
23
- |
24
- tileset.update()
25
- | async load tileHeader
26
- tileset.traverse() -------------------------- Queued
27
- | resume traversal after fetched |
28
- |----------------------------------------|
29
- |
30
- | async load tile content
31
- tilset.requestedTiles ----------------------------- RequestScheduler
32
- |
33
- tilset.selectedTiles (ready for rendering) |
34
- | Listen to |
35
- Tile3DLayer ----------- onTileLoad ----------------------|
36
- | | notify new tile is available
37
- updateLayers |
38
- tileset.update // trigger another round of update
39
- */
40
-
41
6
  import {Matrix4, Vector3} from '@math.gl/core';
42
7
  import {Ellipsoid} from '@math.gl/geospatial';
43
8
  import {Stats} from '@probe.gl/stats';
44
- import {
45
- RequestScheduler,
46
- assert,
47
- path,
48
- LoaderWithParser,
49
- LoaderOptions
50
- } from '@loaders.gl/loader-utils';
9
+ import {RequestScheduler, path, LoaderWithParser, LoaderOptions} from '@loaders.gl/loader-utils';
51
10
  import {TilesetCache} from './tileset-cache';
52
11
  import {calculateTransformProps} from './helpers/transform-utils';
53
12
  import {FrameState, getFrameState, limitSelectedTiles} from './helpers/frame-state';
54
13
  import {getZoomFromBoundingVolume, getZoomFromExtent, getZoomFromFullExtent} from './helpers/zoom';
14
+
15
+ import type {GeospatialViewport, Viewport} from '../types';
55
16
  import {Tile3D} from './tile-3d';
56
17
  import {TILESET_TYPE} from '../constants';
57
- import {GeospatialViewport, Viewport} from '../types';
58
18
 
59
19
  import {TilesetTraverser} from './tileset-traverser';
60
20
 
@@ -62,6 +22,27 @@ import {TilesetTraverser} from './tileset-traverser';
62
22
  import {Tileset3DTraverser} from './format-3d-tiles/tileset-3d-traverser';
63
23
  import {I3STilesetTraverser} from './format-i3s/i3s-tileset-traverser';
64
24
 
25
+ export type TilesetJSON = any;
26
+
27
+ /*
28
+ export type TilesetJSON = {
29
+ loader;
30
+ // could be 3d tiles, i3s
31
+ type: 'I3S' | '3DTILES';
32
+ /** The url to the top level tileset JSON file. *
33
+ url: string;
34
+ basePath?: string;
35
+ // Geometric error when the tree is not rendered at all
36
+ lodMetricType: string;
37
+ lodMetricValue: number;
38
+ root: {
39
+ refine: string;
40
+ [key: string]: unknown;
41
+ },
42
+ [key: string]: unknown;
43
+ };
44
+ */
45
+
65
46
  export type Tileset3DProps = {
66
47
  // loading
67
48
  throttleRequests?: boolean;
@@ -98,83 +79,63 @@ export type Tileset3DProps = {
98
79
  type Props = {
99
80
  description: string;
100
81
  ellipsoid: object;
82
+ /** A 4x4 transformation matrix this transforms the entire tileset. */
101
83
  modelMatrix: Matrix4;
84
+ /** Set to false to disable network request throttling */
102
85
  throttleRequests: boolean;
86
+ /** Number of simultaneous requsts, if throttleRequests is true */
87
+ maxRequests: number;
103
88
  maximumMemoryUsage: number;
89
+ /** Maximum number limit of tiles selected for show. 0 means no limit */
104
90
  maximumTilesSelected: number;
91
+ /** Delay time before the tileset traversal. It prevents traversal requests spam.*/
105
92
  debounceTime: number;
106
- onTileLoad: (tile: Tile3D) => any;
107
- onTileUnload: (tile: Tile3D) => any;
108
- onTileError: (tile: Tile3D, message: string, url: string) => any;
93
+ /** Callback. Indicates this a tile's content was loaded */
94
+ onTileLoad: (tile: Tile3D) => void;
95
+ /** Callback. Indicates this a tile's content was unloaded (cache full) */
96
+ onTileUnload: (tile: Tile3D) => void;
97
+ /** Callback. Indicates this a tile's content failed to load */
98
+ onTileError: (tile: Tile3D, message: string, url: string) => void;
99
+ /** Callback. Allows post-process selectedTiles right after traversal. */
109
100
  onTraversalComplete: (selectedTiles: Tile3D[]) => Tile3D[];
101
+ /** The maximum screen space error used to drive level of detail refinement. */
110
102
  maximumScreenSpaceError: number;
111
- viewportTraversersMap: any;
103
+ viewportTraversersMap: Record<string, any> | null;
112
104
  attributions: string[];
113
- maxRequests: number;
114
105
  loadTiles: boolean;
115
106
  loadOptions: LoaderOptions;
116
107
  updateTransforms: boolean;
108
+ /** View distance scale modifier */
117
109
  viewDistanceScale: number;
118
110
  basePath: string;
111
+ /** Optional async tile content loader */
119
112
  contentLoader?: (tile: Tile3D) => Promise<void>;
120
- i3s: {[key: string]: any};
113
+ /** @todo I3S specific knowledge should be moved to I3S module */
114
+ i3s: Record<string, any>;
121
115
  };
122
116
 
123
117
  const DEFAULT_PROPS: Props = {
124
118
  description: '',
125
-
126
119
  ellipsoid: Ellipsoid.WGS84,
127
- // A 4x4 transformation matrix this transforms the entire tileset.
128
120
  modelMatrix: new Matrix4(),
129
-
130
- // Set to false to disable network request throttling
131
121
  throttleRequests: true,
132
-
133
- // Number of simultaneous requsts, if throttleRequests is true
134
122
  maxRequests: 64,
135
-
136
123
  maximumMemoryUsage: 32,
137
- /** Maximum number limit of tiles selected for show. 0 means no limit */
138
124
  maximumTilesSelected: 0,
139
- /** Delay time before the tileset traversal. It prevents traversal requests spam.*/
140
125
  debounceTime: 0,
141
-
142
- /**
143
- * Callback. Indicates this a tile's content was loaded
144
- * @param tile {TileHeader}
145
- */
146
126
  onTileLoad: () => {},
147
- /**
148
- * Callback. Indicates this a tile's content was unloaded
149
- * @param tile {TileHeader}
150
- */
151
127
  onTileUnload: () => {},
152
128
  onTileError: () => {},
153
- /**
154
- * Callback. Allows post-process selectedTiles right after traversal.
155
- * @param selectedTiles {TileHeader[]}
156
- * @returns TileHeader[] - output array of tiles to return to deck.gl
157
- */
158
129
  onTraversalComplete: (selectedTiles: Tile3D[]) => selectedTiles,
159
-
160
- // Optional async tile content loader
161
130
  contentLoader: undefined,
162
-
163
- // View distance scale modifier
164
131
  viewDistanceScale: 1.0,
165
-
166
- // The maximum screen space error used to drive level of detail refinement.
167
132
  maximumScreenSpaceError: 8,
168
-
169
133
  loadTiles: true,
170
134
  updateTransforms: true,
171
135
  viewportTraversersMap: null,
172
-
173
136
  loadOptions: {fetch: {}},
174
-
175
137
  attributions: [],
176
138
  basePath: '',
177
-
178
139
  i3s: {}
179
140
  };
180
141
 
@@ -190,13 +151,46 @@ const TILES_LOAD_FAILED = 'Failed Tile Loads';
190
151
  const POINTS_COUNT = 'Points/Vertices';
191
152
  const TILES_GPU_MEMORY = 'Tile Memory Use';
192
153
 
154
+ /**
155
+ * The Tileset loading and rendering flow is as below,
156
+ * A rendered (i.e. deck.gl `Tile3DLayer`) triggers `tileset.update()` after a `tileset` is loaded
157
+ * `tileset` starts traversing the tile tree and update `requestTiles` (tiles of which content need
158
+ * to be fetched) and `selectedTiles` (tiles ready for rendering under the current viewport).
159
+ * `Tile3DLayer` will update rendering based on `selectedTiles`.
160
+ * `Tile3DLayer` also listens to `onTileLoad` callback and trigger another round of `update and then traversal`
161
+ * when new tiles are loaded.
162
+
163
+ * As I3S tileset have stored `tileHeader` file (metadata) and tile content files (geometry, texture, ...) separately.
164
+ * During each traversal, it issues `tilHeader` requests if that `tileHeader` is not yet fetched,
165
+ * after the tile header is fulfilled, it will resume the traversal starting from the tile just fetched (not root).
166
+
167
+ * Tile3DLayer
168
+ * |
169
+ * await load(tileset)
170
+ * |
171
+ * tileset.update()
172
+ * | async load tileHeader
173
+ * tileset.traverse() -------------------------- Queued
174
+ * | resume traversal after fetched |
175
+ * |----------------------------------------|
176
+ * |
177
+ * | async load tile content
178
+ * tilset.requestedTiles ----------------------------- RequestScheduler
179
+ * |
180
+ * tilset.selectedTiles (ready for rendering) |
181
+ * | Listen to |
182
+ * Tile3DLayer ----------- onTileLoad ----------------------|
183
+ * | | notify new tile is available
184
+ * updateLayers |
185
+ * tileset.update // trigger another round of update
186
+ */
193
187
  export class Tileset3D {
194
188
  // props: Tileset3DProps;
195
189
  options: Props;
196
- loadOptions: {[key: string]: any};
190
+ loadOptions: LoaderOptions;
197
191
 
198
192
  type: string;
199
- tileset: {[key: string]: any};
193
+ tileset: TilesetJSON;
200
194
  loader: LoaderWithParser;
201
195
  url: string;
202
196
  basePath: string;
@@ -205,60 +199,71 @@ export class Tileset3D {
205
199
  lodMetricType: string;
206
200
  lodMetricValue: number;
207
201
  refine: string;
208
- root: Tile3D | null;
209
- roots: {[key: string]: Tile3D};
210
- asset: {[key: string]: any};
202
+ root: Tile3D | null = null;
203
+ roots: Record<string, Tile3D> = {};
204
+ /** @todo any->unknown */
205
+ asset: Record<string, any> = {};
211
206
 
212
- description: string;
207
+ // Metadata for the entire tileset
208
+ description: string = '';
213
209
  properties: any;
214
- extras: any;
215
- attributions: any;
216
- credits: any;
210
+
211
+ extras: any = null;
212
+ attributions: any = {};
213
+ credits: any = {};
217
214
 
218
215
  stats: Stats;
219
216
 
220
217
  /** flags that contain information about data types in nested tiles */
221
218
  contentFormats = {draco: false, meshopt: false, dds: false, ktx2: false};
222
219
 
223
- traverseCounter: number;
224
- geometricError: number;
225
- selectedTiles: Tile3D[];
226
- private updatePromise: Promise<number> | null = null;
227
- tilesetInitializationPromise: Promise<void>;
220
+ // view props
221
+ cartographicCenter: Vector3 | null = null;
222
+ cartesianCenter: Vector3 | null = null;
223
+ zoom: number = 1;
224
+ boundingVolume: any = null;
228
225
 
229
- cartographicCenter: Vector3 | null;
230
- cartesianCenter: Vector3 | null;
231
- zoom: number;
232
- boundingVolume: any;
226
+ /** Updated based on the camera position and direction */
227
+ dynamicScreenSpaceErrorComputedDensity: number = 0.0;
233
228
 
234
229
  // METRICS
235
- // The maximum amount of GPU memory (in MB) that may be used to cache tiles.
236
- // Tiles not in view are unloaded to enforce private
237
- // The total amount of GPU memory in bytes used by the tileset.
238
- gpuMemoryUsageInBytes: any;
239
- dynamicScreenSpaceErrorComputedDensity: any;
240
230
 
241
- // TRAVERSAL
242
- _traverser: TilesetTraverser;
243
- private _cache: TilesetCache;
244
- _requestScheduler: RequestScheduler;
231
+ /**
232
+ * The maximum amount of GPU memory (in MB) that may be used to cache tiles
233
+ * Tiles not in view are unloaded to enforce private
234
+ */
235
+ maximumMemoryUsage: number = 32;
245
236
 
246
- _frameNumber: number;
247
- private _queryParamsString: string;
248
- private _queryParams: any;
249
- private _extensionsUsed: any;
250
- private _tiles: {[id: string]: Tile3D};
237
+ /** The total amount of GPU memory in bytes used by the tileset. */
238
+ gpuMemoryUsageInBytes: number = 0;
251
239
 
252
- // counter for tracking tiles requests
253
- private _pendingCount: any;
240
+ /** Update tracker. increase in each update cycle. */
241
+ _frameNumber: number = 0;
242
+ private _queryParams: Record<string, string> = {};
243
+ private _extensionsUsed: string[] = [];
244
+ private _tiles: Record<string, Tile3D> = {};
254
245
 
255
- // HOLD TRAVERSAL RESULTS
256
- private lastUpdatedVieports: Viewport[] | Viewport | null;
257
- private _requestedTiles: any;
258
- private _emptyTiles: any;
259
- private frameStateData: any;
246
+ /** counter for tracking tiles requests */
247
+ private _pendingCount: number = 0;
260
248
 
261
- maximumMemoryUsage: number;
249
+ /** Hold traversal results */
250
+ selectedTiles: Tile3D[] = [];
251
+
252
+ // TRAVERSAL
253
+ traverseCounter: number = 0;
254
+ geometricError: number = 0;
255
+ private lastUpdatedVieports: Viewport[] | Viewport | null = null;
256
+ private _requestedTiles: Tile3D[] = [];
257
+ private _emptyTiles: Tile3D[] = [];
258
+ private frameStateData: any = {};
259
+
260
+ _traverser: TilesetTraverser;
261
+ _cache = new TilesetCache();
262
+ _requestScheduler: RequestScheduler;
263
+
264
+ // Promise tracking
265
+ private updatePromise: Promise<number> | null = null;
266
+ tilesetInitializationPromise: Promise<void>;
262
267
 
263
268
  /**
264
269
  * Create a new Tileset3D
@@ -266,83 +271,40 @@ export class Tileset3D {
266
271
  * @param props
267
272
  */
268
273
  // eslint-disable-next-line max-statements
269
- constructor(json: any, options?: Tileset3DProps) {
270
- assert(json);
271
-
274
+ constructor(tileset: TilesetJSON, options?: Tileset3DProps) {
272
275
  // PUBLIC MEMBERS
273
276
  this.options = {...DEFAULT_PROPS, ...options};
274
277
  // raw data
275
- this.tileset = json;
276
- this.loader = json.loader;
278
+ this.tileset = tileset;
279
+ this.loader = tileset.loader;
277
280
  // could be 3d tiles, i3s
278
- this.type = json.type;
281
+ this.type = tileset.type;
279
282
  // The url to a tileset JSON file.
280
- this.url = json.url;
281
- this.basePath = json.basePath || path.dirname(this.url);
283
+ this.url = tileset.url;
284
+ this.basePath = tileset.basePath || path.dirname(this.url);
282
285
  this.modelMatrix = this.options.modelMatrix;
283
286
  this.ellipsoid = this.options.ellipsoid;
284
287
 
285
288
  // Geometric error when the tree is not rendered at all
286
- this.lodMetricType = json.lodMetricType;
287
- this.lodMetricValue = json.lodMetricValue;
288
- this.refine = json.root.refine;
289
+ this.lodMetricType = tileset.lodMetricType;
290
+ this.lodMetricValue = tileset.lodMetricValue;
291
+ this.refine = tileset.root.refine;
289
292
 
290
293
  this.loadOptions = this.options.loadOptions || {};
291
294
 
292
- this.root = null;
293
- this.roots = {};
294
- // view props
295
- this.cartographicCenter = null;
296
- this.cartesianCenter = null;
297
- this.zoom = 1;
298
- this.boundingVolume = null;
299
-
300
295
  // TRAVERSAL
301
- this.traverseCounter = 0;
302
- this.geometricError = 0;
303
296
  this._traverser = this._initializeTraverser();
304
- this._cache = new TilesetCache();
305
297
  this._requestScheduler = new RequestScheduler({
306
298
  throttleRequests: this.options.throttleRequests,
307
299
  maxRequests: this.options.maxRequests
308
300
  });
309
- // update tracker
310
- // increase in each update cycle
311
- this._frameNumber = 0;
312
-
313
- // counter for tracking tiles requests
314
- this._pendingCount = 0;
315
-
316
- // HOLD TRAVERSAL RESULTS
317
- this._tiles = {};
318
- this.selectedTiles = [];
319
- this._emptyTiles = [];
320
- this._requestedTiles = [];
321
- this.frameStateData = {};
322
- this.lastUpdatedVieports = null;
323
-
324
- this._queryParams = {};
325
- this._queryParamsString = '';
326
301
 
327
302
  // METRICS
328
- // The maximum amount of GPU memory (in MB) that may be used to cache tiles.
329
- // Tiles not in view are unloaded to enforce this.
330
- this.maximumMemoryUsage = this.options.maximumMemoryUsage || 32;
331
303
  // The total amount of GPU memory in bytes used by the tileset.
332
- this.gpuMemoryUsageInBytes = 0;
333
304
  this.stats = new Stats({id: this.url});
334
305
  this._initializeStats();
335
306
 
336
- // EXTRACTED FROM TILESET
337
- this._extensionsUsed = undefined;
338
- this.dynamicScreenSpaceErrorComputedDensity = 0.0; // Updated based on the camera position and direction
339
- // Metadata for the entire tileset
340
- this.extras = null;
341
- this.asset = {};
342
- this.credits = {};
343
- this.description = this.options.description || '';
344
-
345
- this.tilesetInitializationPromise = this._initializeTileSet(json);
307
+ this.tilesetInitializationPromise = this._initializeTileSet(tileset);
346
308
  }
347
309
 
348
310
  /** Release resources */
@@ -365,10 +327,8 @@ export class Tileset3D {
365
327
  }
366
328
 
367
329
  get queryParams(): string {
368
- if (!this._queryParamsString) {
369
- this._queryParamsString = getQueryParamString(this._queryParams);
370
- }
371
- return this._queryParamsString;
330
+ const search = new URLSearchParams(this._queryParams).toString();
331
+ return search ? `?${search}` : '';
372
332
  }
373
333
 
374
334
  setProps(props: Tileset3DProps): void {
@@ -389,12 +349,12 @@ export class Tileset3D {
389
349
  if (isDataUrl) {
390
350
  return tilePath;
391
351
  }
392
- return `${tilePath}${this.queryParams}`;
352
+ return `${tilePath}${tilePath.includes('?') ? '&' : '?'}${this.queryParams}`;
393
353
  }
394
354
 
395
355
  // TODO CESIUM specific
396
356
  hasExtension(extensionName: string): boolean {
397
- return Boolean(this._extensionsUsed && this._extensionsUsed.indexOf(extensionName) > -1);
357
+ return Boolean(this._extensionsUsed.indexOf(extensionName) > -1);
398
358
  }
399
359
 
400
360
  /**
@@ -559,7 +519,7 @@ export class Tileset3D {
559
519
  this._updateStats();
560
520
  }
561
521
 
562
- _tilesChanged(oldSelectedTiles, selectedTiles) {
522
+ _tilesChanged(oldSelectedTiles: Tile3D[], selectedTiles: Tile3D[]): boolean {
563
523
  if (oldSelectedTiles.length !== selectedTiles.length) {
564
524
  return true;
565
525
  }
@@ -570,7 +530,7 @@ export class Tileset3D {
570
530
  return changed;
571
531
  }
572
532
 
573
- _loadTiles() {
533
+ _loadTiles(): void {
574
534
  // Sort requests by priority before making any requests.
575
535
  // This makes it less likely this requests will be cancelled after being issued.
576
536
  // requestedTiles.sort((a, b) => a._priority - b._priority);
@@ -582,12 +542,12 @@ export class Tileset3D {
582
542
  }
583
543
  }
584
544
 
585
- _unloadTiles() {
545
+ _unloadTiles(): void {
586
546
  // unload tiles from cache when hit maximumMemoryUsage
587
547
  this._cache.unloadTiles(this, (tileset, tile) => tileset._unloadTile(tile));
588
548
  }
589
549
 
590
- _updateStats() {
550
+ _updateStats(): void {
591
551
  let tilesRenderable = 0;
592
552
  let pointsRenderable = 0;
593
553
  for (const tile of this.selectedTiles) {
@@ -607,7 +567,7 @@ export class Tileset3D {
607
567
  this.stats.get(POINTS_COUNT).count = pointsRenderable;
608
568
  }
609
569
 
610
- async _initializeTileSet(tilesetJson) {
570
+ async _initializeTileSet(tilesetJson: TilesetJSON): Promise<void> {
611
571
  if (this.type === TILESET_TYPE.I3S) {
612
572
  this.calculateViewPropsI3S();
613
573
  tilesetJson.root = await tilesetJson.root;
@@ -630,7 +590,7 @@ export class Tileset3D {
630
590
  * For I3S there is extent (<1.8 version) or fullExtent (>=1.8 version) to calculate view props
631
591
  * @returns
632
592
  */
633
- private calculateViewPropsI3S() {
593
+ private calculateViewPropsI3S(): void {
634
594
  // for I3S 1.8 try to calculate with fullExtent
635
595
  const fullExtent = this.tileset.fullExtent;
636
596
  if (fullExtent) {
@@ -674,7 +634,6 @@ export class Tileset3D {
674
634
  */
675
635
  private calculateViewPropsTiles3D() {
676
636
  const root = this.root as Tile3D;
677
- assert(root);
678
637
  const {center} = root.boundingVolume;
679
638
  // TODO - handle all cases
680
639
  if (!center) {
@@ -710,7 +669,7 @@ export class Tileset3D {
710
669
 
711
670
  // Installs the main tileset JSON file or a tileset JSON file referenced from a tile.
712
671
  // eslint-disable-next-line max-statements
713
- _initializeTileHeaders(tilesetJson, parentTileHeader) {
672
+ _initializeTileHeaders(tilesetJson: TilesetJSON, parentTileHeader?: any) {
714
673
  // A tileset JSON file referenced from a tile may exist in a different directory than the root tileset.
715
674
  // Get the basePath relative to the external tileset.
716
675
  const rootTile = new Tile3D(this, tilesetJson.root, parentTileHeader); // resource
@@ -733,6 +692,17 @@ export class Tileset3D {
733
692
  const children = tile.header.children || [];
734
693
  for (const childHeader of children) {
735
694
  const childTile = new Tile3D(this, childHeader, tile);
695
+
696
+ // Special handling for Google
697
+ // A session key must be used for all tile requests
698
+ if (childTile.contentUrl?.includes('?session=')) {
699
+ const url = new URL(childTile.contentUrl);
700
+ const session = url.searchParams.get('session');
701
+ if (session) {
702
+ this._queryParams.session = session;
703
+ }
704
+ }
705
+
736
706
  tile.children.push(childTile);
737
707
  childTile.depth = tile.depth + 1;
738
708
  stack.push(childTile);
@@ -743,7 +713,7 @@ export class Tileset3D {
743
713
  return rootTile;
744
714
  }
745
715
 
746
- _initializeTraverser() {
716
+ _initializeTraverser(): TilesetTraverser {
747
717
  let TraverserClass;
748
718
  const type = this.type;
749
719
  switch (type) {
@@ -763,24 +733,24 @@ export class Tileset3D {
763
733
  });
764
734
  }
765
735
 
766
- _destroyTileHeaders(parentTile) {
736
+ _destroyTileHeaders(parentTile: Tile3D): void {
767
737
  this._destroySubtree(parentTile);
768
738
  }
769
739
 
770
- async _loadTile(tile) {
740
+ async _loadTile(tile: Tile3D): Promise<void> {
771
741
  let loaded;
772
742
  try {
773
743
  this._onStartTileLoading();
774
744
  loaded = await tile.loadContent();
775
- } catch (error) {
776
- this._onTileLoadError(tile, error);
745
+ } catch (error: unknown) {
746
+ this._onTileLoadError(tile, error instanceof Error ? error : new Error('load failed'));
777
747
  } finally {
778
748
  this._onEndTileLoading();
779
749
  this._onTileLoad(tile, loaded);
780
750
  }
781
751
  }
782
752
 
783
- _onTileLoadError(tile, error) {
753
+ _onTileLoadError(tile: Tile3D, error: Error): void {
784
754
  this.stats.get(TILES_LOAD_FAILED).incrementCount();
785
755
 
786
756
  const message = error.message || error.toString();
@@ -790,7 +760,7 @@ export class Tileset3D {
790
760
  this.options.onTileError(tile, message, url);
791
761
  }
792
762
 
793
- _onTileLoad(tile, loaded) {
763
+ _onTileLoad(tile: Tile3D, loaded: boolean): void {
794
764
  if (!loaded) {
795
765
  return;
796
766
  }
@@ -854,7 +824,7 @@ export class Tileset3D {
854
824
  this.stats.get(TILES_LOADING).decrementCount();
855
825
  }
856
826
 
857
- _addTileToCache(tile) {
827
+ _addTileToCache(tile: Tile3D) {
858
828
  this._cache.add(this, tile, (tileset) => tileset._updateCacheStats(tile));
859
829
  }
860
830
 
@@ -863,12 +833,12 @@ export class Tileset3D {
863
833
  this.stats.get(TILES_IN_MEMORY).incrementCount();
864
834
 
865
835
  // Good enough? Just use the raw binary ArrayBuffer's byte length.
866
- this.gpuMemoryUsageInBytes += tile.content.byteLength || 0;
836
+ this.gpuMemoryUsageInBytes += tile.gpuMemoryUsageInBytes || 0;
867
837
  this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
868
838
  }
869
839
 
870
840
  _unloadTile(tile) {
871
- this.gpuMemoryUsageInBytes -= (tile.content && tile.content.byteLength) || 0;
841
+ this.gpuMemoryUsageInBytes -= tile.gpuMemoryUsageInBytes || 0;
872
842
 
873
843
  this.stats.get(TILES_IN_MEMORY).decrementCount();
874
844
  this.stats.get(TILES_UNLOADED).incrementCount();
@@ -922,6 +892,12 @@ export class Tileset3D {
922
892
  }
923
893
 
924
894
  _initializeTiles3DTileset(tilesetJson) {
895
+ if (tilesetJson.queryString) {
896
+ const searchParams = new URLSearchParams(tilesetJson.queryString);
897
+ const queryParams = Object.fromEntries(searchParams.entries());
898
+ this._queryParams = {...this._queryParams, ...queryParams};
899
+ }
900
+
925
901
  this.asset = tilesetJson.asset;
926
902
  if (!this.asset) {
927
903
  throw new Error('Tileset must have an asset property.');
@@ -945,29 +921,15 @@ export class Tileset3D {
945
921
  // Gets the tileset's properties dictionary object, which contains metadata about per-feature properties.
946
922
  this.properties = tilesetJson.properties;
947
923
  this.geometricError = tilesetJson.geometricError;
948
- this._extensionsUsed = tilesetJson.extensionsUsed;
924
+ this._extensionsUsed = tilesetJson.extensionsUsed || [];
949
925
  // Returns the extras property at the top of the tileset JSON (application specific metadata).
950
926
  this.extras = tilesetJson.extras;
951
927
  }
952
928
 
953
929
  _initializeI3STileset() {
930
+ // @ts-expect-error
954
931
  if (this.loadOptions.i3s && 'token' in this.loadOptions.i3s) {
955
- this._queryParams.token = this.loadOptions.i3s.token;
932
+ this._queryParams.token = this.loadOptions.i3s.token as string;
956
933
  }
957
934
  }
958
935
  }
959
-
960
- function getQueryParamString(queryParams): string {
961
- const queryParamStrings: string[] = [];
962
- for (const key of Object.keys(queryParams)) {
963
- queryParamStrings.push(`${key}=${queryParams[key]}`);
964
- }
965
- switch (queryParamStrings.length) {
966
- case 0:
967
- return '';
968
- case 1:
969
- return `?${queryParamStrings[0]}`;
970
- default:
971
- return `?${queryParamStrings.join('&')}`;
972
- }
973
- }