@loaders.gl/tiles 4.0.0-alpha.6 → 4.0.0-alpha.8

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 (47) hide show
  1. package/dist/constants.d.ts +24 -18
  2. package/dist/constants.d.ts.map +1 -1
  3. package/dist/constants.js +22 -19
  4. package/dist/dist.min.js +448 -206
  5. package/dist/es5/constants.js +22 -18
  6. package/dist/es5/constants.js.map +1 -1
  7. package/dist/es5/tileset/helpers/3d-tiles-options.js.map +1 -1
  8. package/dist/es5/tileset/tile-3d.js +42 -71
  9. package/dist/es5/tileset/tile-3d.js.map +1 -1
  10. package/dist/es5/tileset/tileset-3d.js +69 -104
  11. package/dist/es5/tileset/tileset-3d.js.map +1 -1
  12. package/dist/es5/tileset/tileset-cache.js +4 -7
  13. package/dist/es5/tileset/tileset-cache.js.map +1 -1
  14. package/dist/es5/tileset/tileset-traverser.js +12 -19
  15. package/dist/es5/tileset/tileset-traverser.js.map +1 -1
  16. package/dist/esm/constants.js +22 -18
  17. package/dist/esm/constants.js.map +1 -1
  18. package/dist/esm/tileset/helpers/3d-tiles-options.js.map +1 -1
  19. package/dist/esm/tileset/tile-3d.js +40 -71
  20. package/dist/esm/tileset/tile-3d.js.map +1 -1
  21. package/dist/esm/tileset/tileset-3d.js +65 -96
  22. package/dist/esm/tileset/tileset-3d.js.map +1 -1
  23. package/dist/esm/tileset/tileset-cache.js +4 -7
  24. package/dist/esm/tileset/tileset-cache.js.map +1 -1
  25. package/dist/esm/tileset/tileset-traverser.js +9 -16
  26. package/dist/esm/tileset/tileset-traverser.js.map +1 -1
  27. package/dist/tileset/helpers/3d-tiles-options.d.ts +3 -2
  28. package/dist/tileset/helpers/3d-tiles-options.d.ts.map +1 -1
  29. package/dist/tileset/tile-3d.d.ts +37 -21
  30. package/dist/tileset/tile-3d.d.ts.map +1 -1
  31. package/dist/tileset/tile-3d.js +57 -43
  32. package/dist/tileset/tileset-3d.d.ts +90 -43
  33. package/dist/tileset/tileset-3d.d.ts.map +1 -1
  34. package/dist/tileset/tileset-3d.js +111 -129
  35. package/dist/tileset/tileset-cache.d.ts +5 -4
  36. package/dist/tileset/tileset-cache.d.ts.map +1 -1
  37. package/dist/tileset/tileset-cache.js +4 -10
  38. package/dist/tileset/tileset-traverser.d.ts +32 -21
  39. package/dist/tileset/tileset-traverser.d.ts.map +1 -1
  40. package/dist/tileset/tileset-traverser.js +23 -32
  41. package/package.json +8 -5
  42. package/src/constants.ts +36 -18
  43. package/src/tileset/helpers/3d-tiles-options.ts +3 -1
  44. package/src/tileset/tile-3d.ts +68 -109
  45. package/src/tileset/tileset-3d.ts +183 -218
  46. package/src/tileset/tileset-cache.ts +20 -15
  47. package/src/tileset/tileset-traverser.ts +52 -65
@@ -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,7 @@ 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
+ return new URLSearchParams(this._queryParams).toString();
372
331
  }
373
332
 
374
333
  setProps(props: Tileset3DProps): void {
@@ -389,12 +348,12 @@ export class Tileset3D {
389
348
  if (isDataUrl) {
390
349
  return tilePath;
391
350
  }
392
- return `${tilePath}${this.queryParams}`;
351
+ return `${tilePath}${tilePath.includes('?') ? '&' : '?'}${this.queryParams}`;
393
352
  }
394
353
 
395
354
  // TODO CESIUM specific
396
355
  hasExtension(extensionName: string): boolean {
397
- return Boolean(this._extensionsUsed && this._extensionsUsed.indexOf(extensionName) > -1);
356
+ return Boolean(this._extensionsUsed.indexOf(extensionName) > -1);
398
357
  }
399
358
 
400
359
  /**
@@ -559,7 +518,7 @@ export class Tileset3D {
559
518
  this._updateStats();
560
519
  }
561
520
 
562
- _tilesChanged(oldSelectedTiles, selectedTiles) {
521
+ _tilesChanged(oldSelectedTiles: Tile3D[], selectedTiles: Tile3D[]): boolean {
563
522
  if (oldSelectedTiles.length !== selectedTiles.length) {
564
523
  return true;
565
524
  }
@@ -570,7 +529,7 @@ export class Tileset3D {
570
529
  return changed;
571
530
  }
572
531
 
573
- _loadTiles() {
532
+ _loadTiles(): void {
574
533
  // Sort requests by priority before making any requests.
575
534
  // This makes it less likely this requests will be cancelled after being issued.
576
535
  // requestedTiles.sort((a, b) => a._priority - b._priority);
@@ -582,12 +541,12 @@ export class Tileset3D {
582
541
  }
583
542
  }
584
543
 
585
- _unloadTiles() {
544
+ _unloadTiles(): void {
586
545
  // unload tiles from cache when hit maximumMemoryUsage
587
546
  this._cache.unloadTiles(this, (tileset, tile) => tileset._unloadTile(tile));
588
547
  }
589
548
 
590
- _updateStats() {
549
+ _updateStats(): void {
591
550
  let tilesRenderable = 0;
592
551
  let pointsRenderable = 0;
593
552
  for (const tile of this.selectedTiles) {
@@ -607,7 +566,7 @@ export class Tileset3D {
607
566
  this.stats.get(POINTS_COUNT).count = pointsRenderable;
608
567
  }
609
568
 
610
- async _initializeTileSet(tilesetJson) {
569
+ async _initializeTileSet(tilesetJson: TilesetJSON): Promise<void> {
611
570
  if (this.type === TILESET_TYPE.I3S) {
612
571
  this.calculateViewPropsI3S();
613
572
  tilesetJson.root = await tilesetJson.root;
@@ -630,7 +589,7 @@ export class Tileset3D {
630
589
  * For I3S there is extent (<1.8 version) or fullExtent (>=1.8 version) to calculate view props
631
590
  * @returns
632
591
  */
633
- private calculateViewPropsI3S() {
592
+ private calculateViewPropsI3S(): void {
634
593
  // for I3S 1.8 try to calculate with fullExtent
635
594
  const fullExtent = this.tileset.fullExtent;
636
595
  if (fullExtent) {
@@ -674,7 +633,6 @@ export class Tileset3D {
674
633
  */
675
634
  private calculateViewPropsTiles3D() {
676
635
  const root = this.root as Tile3D;
677
- assert(root);
678
636
  const {center} = root.boundingVolume;
679
637
  // TODO - handle all cases
680
638
  if (!center) {
@@ -710,7 +668,7 @@ export class Tileset3D {
710
668
 
711
669
  // Installs the main tileset JSON file or a tileset JSON file referenced from a tile.
712
670
  // eslint-disable-next-line max-statements
713
- _initializeTileHeaders(tilesetJson, parentTileHeader) {
671
+ _initializeTileHeaders(tilesetJson: TilesetJSON, parentTileHeader?: any) {
714
672
  // A tileset JSON file referenced from a tile may exist in a different directory than the root tileset.
715
673
  // Get the basePath relative to the external tileset.
716
674
  const rootTile = new Tile3D(this, tilesetJson.root, parentTileHeader); // resource
@@ -733,6 +691,17 @@ export class Tileset3D {
733
691
  const children = tile.header.children || [];
734
692
  for (const childHeader of children) {
735
693
  const childTile = new Tile3D(this, childHeader, tile);
694
+
695
+ // Special handling for Google
696
+ // A session key must be used for all tile requests
697
+ if (childTile.contentUrl?.includes('?session=')) {
698
+ const url = new URL(childTile.contentUrl);
699
+ const session = url.searchParams.get('session');
700
+ if (session) {
701
+ this._queryParams.session = session;
702
+ }
703
+ }
704
+
736
705
  tile.children.push(childTile);
737
706
  childTile.depth = tile.depth + 1;
738
707
  stack.push(childTile);
@@ -743,7 +712,7 @@ export class Tileset3D {
743
712
  return rootTile;
744
713
  }
745
714
 
746
- _initializeTraverser() {
715
+ _initializeTraverser(): TilesetTraverser {
747
716
  let TraverserClass;
748
717
  const type = this.type;
749
718
  switch (type) {
@@ -763,24 +732,24 @@ export class Tileset3D {
763
732
  });
764
733
  }
765
734
 
766
- _destroyTileHeaders(parentTile) {
735
+ _destroyTileHeaders(parentTile: Tile3D): void {
767
736
  this._destroySubtree(parentTile);
768
737
  }
769
738
 
770
- async _loadTile(tile) {
739
+ async _loadTile(tile: Tile3D): Promise<void> {
771
740
  let loaded;
772
741
  try {
773
742
  this._onStartTileLoading();
774
743
  loaded = await tile.loadContent();
775
- } catch (error) {
776
- this._onTileLoadError(tile, error);
744
+ } catch (error: unknown) {
745
+ this._onTileLoadError(tile, error instanceof Error ? error : new Error('load failed'));
777
746
  } finally {
778
747
  this._onEndTileLoading();
779
748
  this._onTileLoad(tile, loaded);
780
749
  }
781
750
  }
782
751
 
783
- _onTileLoadError(tile, error) {
752
+ _onTileLoadError(tile: Tile3D, error: Error): void {
784
753
  this.stats.get(TILES_LOAD_FAILED).incrementCount();
785
754
 
786
755
  const message = error.message || error.toString();
@@ -790,7 +759,7 @@ export class Tileset3D {
790
759
  this.options.onTileError(tile, message, url);
791
760
  }
792
761
 
793
- _onTileLoad(tile, loaded) {
762
+ _onTileLoad(tile: Tile3D, loaded: boolean): void {
794
763
  if (!loaded) {
795
764
  return;
796
765
  }
@@ -854,7 +823,7 @@ export class Tileset3D {
854
823
  this.stats.get(TILES_LOADING).decrementCount();
855
824
  }
856
825
 
857
- _addTileToCache(tile) {
826
+ _addTileToCache(tile: Tile3D) {
858
827
  this._cache.add(this, tile, (tileset) => tileset._updateCacheStats(tile));
859
828
  }
860
829
 
@@ -863,12 +832,12 @@ export class Tileset3D {
863
832
  this.stats.get(TILES_IN_MEMORY).incrementCount();
864
833
 
865
834
  // Good enough? Just use the raw binary ArrayBuffer's byte length.
866
- this.gpuMemoryUsageInBytes += tile.content.byteLength || 0;
835
+ this.gpuMemoryUsageInBytes += tile.gpuMemoryUsageInBytes || 0;
867
836
  this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
868
837
  }
869
838
 
870
839
  _unloadTile(tile) {
871
- this.gpuMemoryUsageInBytes -= (tile.content && tile.content.byteLength) || 0;
840
+ this.gpuMemoryUsageInBytes -= tile.gpuMemoryUsageInBytes || 0;
872
841
 
873
842
  this.stats.get(TILES_IN_MEMORY).decrementCount();
874
843
  this.stats.get(TILES_UNLOADED).incrementCount();
@@ -922,12 +891,22 @@ export class Tileset3D {
922
891
  }
923
892
 
924
893
  _initializeTiles3DTileset(tilesetJson) {
894
+ if (tilesetJson.queryString) {
895
+ const searchParams = new URLSearchParams(tilesetJson.queryString);
896
+ const queryParams = Object.fromEntries(searchParams.entries());
897
+ this._queryParams = {...this._queryParams, ...queryParams};
898
+ }
899
+
925
900
  this.asset = tilesetJson.asset;
926
901
  if (!this.asset) {
927
902
  throw new Error('Tileset must have an asset property.');
928
903
  }
929
- if (this.asset.version !== '0.0' && this.asset.version !== '1.0') {
930
- throw new Error('The tileset must be 3D Tiles version 0.0 or 1.0.');
904
+ if (
905
+ this.asset.version !== '0.0' &&
906
+ this.asset.version !== '1.0' &&
907
+ this.asset.version !== '1.1'
908
+ ) {
909
+ throw new Error('The tileset must be 3D Tiles version either 0.0 or 1.0 or 1.1.');
931
910
  }
932
911
 
933
912
  // Note: `asset.tilesetVersion` is version of the tileset itself (not the version of the 3D TILES standard)
@@ -945,29 +924,15 @@ export class Tileset3D {
945
924
  // Gets the tileset's properties dictionary object, which contains metadata about per-feature properties.
946
925
  this.properties = tilesetJson.properties;
947
926
  this.geometricError = tilesetJson.geometricError;
948
- this._extensionsUsed = tilesetJson.extensionsUsed;
927
+ this._extensionsUsed = tilesetJson.extensionsUsed || [];
949
928
  // Returns the extras property at the top of the tileset JSON (application specific metadata).
950
929
  this.extras = tilesetJson.extras;
951
930
  }
952
931
 
953
932
  _initializeI3STileset() {
933
+ // @ts-expect-error
954
934
  if (this.loadOptions.i3s && 'token' in this.loadOptions.i3s) {
955
- this._queryParams.token = this.loadOptions.i3s.token;
935
+ this._queryParams.token = this.loadOptions.i3s.token as string;
956
936
  }
957
937
  }
958
938
  }
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
- }