@loaders.gl/tiles 4.0.0-alpha.6 → 4.0.0-alpha.7
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.
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +0 -1
- package/dist/dist.min.js +429 -187
- package/dist/es5/constants.js.map +1 -1
- package/dist/es5/tileset/helpers/3d-tiles-options.js.map +1 -1
- package/dist/es5/tileset/tile-3d.js +42 -71
- package/dist/es5/tileset/tile-3d.js.map +1 -1
- package/dist/es5/tileset/tileset-3d.js +68 -103
- package/dist/es5/tileset/tileset-3d.js.map +1 -1
- package/dist/es5/tileset/tileset-cache.js +4 -7
- package/dist/es5/tileset/tileset-cache.js.map +1 -1
- package/dist/es5/tileset/tileset-traverser.js +12 -19
- package/dist/es5/tileset/tileset-traverser.js.map +1 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/tileset/helpers/3d-tiles-options.js.map +1 -1
- package/dist/esm/tileset/tile-3d.js +40 -71
- package/dist/esm/tileset/tile-3d.js.map +1 -1
- package/dist/esm/tileset/tileset-3d.js +64 -95
- package/dist/esm/tileset/tileset-3d.js.map +1 -1
- package/dist/esm/tileset/tileset-cache.js +4 -7
- package/dist/esm/tileset/tileset-cache.js.map +1 -1
- package/dist/esm/tileset/tileset-traverser.js +9 -16
- package/dist/esm/tileset/tileset-traverser.js.map +1 -1
- package/dist/tileset/helpers/3d-tiles-options.d.ts +3 -2
- package/dist/tileset/helpers/3d-tiles-options.d.ts.map +1 -1
- package/dist/tileset/tile-3d.d.ts +37 -21
- package/dist/tileset/tile-3d.d.ts.map +1 -1
- package/dist/tileset/tile-3d.js +57 -43
- package/dist/tileset/tileset-3d.d.ts +90 -43
- package/dist/tileset/tileset-3d.d.ts.map +1 -1
- package/dist/tileset/tileset-3d.js +110 -128
- package/dist/tileset/tileset-cache.d.ts +5 -4
- package/dist/tileset/tileset-cache.d.ts.map +1 -1
- package/dist/tileset/tileset-cache.js +4 -10
- package/dist/tileset/tileset-traverser.d.ts +32 -21
- package/dist/tileset/tileset-traverser.d.ts.map +1 -1
- package/dist/tileset/tileset-traverser.js +23 -32
- package/package.json +8 -5
- package/src/constants.ts +18 -0
- package/src/tileset/helpers/3d-tiles-options.ts +3 -1
- package/src/tileset/tile-3d.ts +68 -109
- package/src/tileset/tileset-3d.ts +182 -217
- package/src/tileset/tileset-cache.ts +20 -15
- 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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
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:
|
|
190
|
+
loadOptions: LoaderOptions;
|
|
197
191
|
|
|
198
192
|
type: string;
|
|
199
|
-
tileset:
|
|
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:
|
|
210
|
-
|
|
202
|
+
root: Tile3D | null = null;
|
|
203
|
+
roots: Record<string, Tile3D> = {};
|
|
204
|
+
/** @todo any->unknown */
|
|
205
|
+
asset: Record<string, any> = {};
|
|
211
206
|
|
|
212
|
-
|
|
207
|
+
// Metadata for the entire tileset
|
|
208
|
+
description: string = '';
|
|
213
209
|
properties: any;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
220
|
+
// view props
|
|
221
|
+
cartographicCenter: Vector3 | null = null;
|
|
222
|
+
cartesianCenter: Vector3 | null = null;
|
|
223
|
+
zoom: number = 1;
|
|
224
|
+
boundingVolume: any = null;
|
|
228
225
|
|
|
229
|
-
|
|
230
|
-
|
|
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
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
247
|
-
|
|
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
|
-
|
|
253
|
-
|
|
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
|
-
|
|
256
|
-
private
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
276
|
-
this.loader =
|
|
278
|
+
this.tileset = tileset;
|
|
279
|
+
this.loader = tileset.loader;
|
|
277
280
|
// could be 3d tiles, i3s
|
|
278
|
-
this.type =
|
|
281
|
+
this.type = tileset.type;
|
|
279
282
|
// The url to a tileset JSON file.
|
|
280
|
-
this.url =
|
|
281
|
-
this.basePath =
|
|
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 =
|
|
287
|
-
this.lodMetricValue =
|
|
288
|
-
this.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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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 -=
|
|
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,11 +891,21 @@ 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 (
|
|
904
|
+
if (
|
|
905
|
+
this.asset.version !== '0.0' &&
|
|
906
|
+
this.asset.version !== '1.0' &&
|
|
907
|
+
this.asset.version !== '1.1'
|
|
908
|
+
) {
|
|
930
909
|
throw new Error('The tileset must be 3D Tiles version 0.0 or 1.0.');
|
|
931
910
|
}
|
|
932
911
|
|
|
@@ -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
|
-
}
|