@loaders.gl/tiles 4.0.4 → 4.1.0-alpha.10
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 +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/dist.dev.js +29 -10
- package/dist/index.cjs +39 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -1
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.js.map +1 -1
- package/dist/tileset/helpers/i3s-lod.d.ts.map +1 -1
- package/dist/tileset/helpers/i3s-lod.js.map +1 -1
- package/dist/tileset/helpers/tiles-3d-lod.d.ts.map +1 -1
- package/dist/tileset/helpers/tiles-3d-lod.js.map +1 -1
- package/dist/tileset/helpers/transform-utils.d.ts.map +1 -1
- package/dist/tileset/helpers/transform-utils.js.map +1 -1
- package/dist/tileset/helpers/zoom.d.ts.map +1 -1
- package/dist/tileset/helpers/zoom.js.map +1 -1
- package/dist/tileset/tile-3d.d.ts.map +1 -1
- package/dist/tileset/tile-3d.js.map +1 -1
- package/dist/tileset/tileset-3d.d.ts +15 -0
- package/dist/tileset/tileset-3d.d.ts.map +1 -1
- package/dist/tileset/tileset-3d.js +21 -0
- package/dist/tileset/tileset-3d.js.map +1 -1
- package/dist/tileset/tileset-cache.d.ts.map +1 -1
- package/dist/tileset/tileset-cache.js.map +1 -1
- package/dist/tileset/tileset-traverser.d.ts +0 -1
- package/dist/tileset/tileset-traverser.d.ts.map +1 -1
- package/dist/tileset/tileset-traverser.js +8 -10
- package/dist/tileset/tileset-traverser.js.map +1 -1
- package/dist/utils/doubly-linked-list-node.d.ts.map +1 -1
- package/dist/utils/doubly-linked-list-node.js.map +1 -1
- package/package.json +6 -6
- package/src/constants.ts +2 -1
- package/src/index.ts +2 -1
- package/src/tileset/format-3d-tiles/tileset-3d-traverser.ts +2 -1
- package/src/tileset/helpers/i3s-lod.ts +2 -1
- package/src/tileset/helpers/tiles-3d-lod.ts +2 -1
- package/src/tileset/helpers/transform-utils.ts +2 -1
- package/src/tileset/helpers/zoom.ts +2 -1
- package/src/tileset/tile-3d.ts +2 -1
- package/src/tileset/tileset-3d.ts +46 -2
- package/src/tileset/tileset-cache.ts +2 -1
- package/src/tileset/tileset-traverser.ts +15 -19
- package/src/utils/doubly-linked-list-node.ts +2 -1
package/src/tileset/tile-3d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
2
|
// Copyright (c) vis.gl contributors
|
|
3
3
|
|
|
4
4
|
// This file is derived from the Cesium code base under Apache 2 license
|
|
@@ -52,6 +52,7 @@ export type Tileset3DProps = {
|
|
|
52
52
|
loadTiles?: boolean;
|
|
53
53
|
basePath?: string;
|
|
54
54
|
maximumMemoryUsage?: number;
|
|
55
|
+
memoryCacheOverflow?: number;
|
|
55
56
|
maximumTilesSelected?: number;
|
|
56
57
|
debounceTime?: number;
|
|
57
58
|
|
|
@@ -65,6 +66,7 @@ export type Tileset3DProps = {
|
|
|
65
66
|
|
|
66
67
|
// Traversal
|
|
67
68
|
maximumScreenSpaceError?: number;
|
|
69
|
+
memoryAdjustedScreenSpaceError?: boolean;
|
|
68
70
|
viewportTraversersMap?: any;
|
|
69
71
|
updateTransforms?: boolean;
|
|
70
72
|
viewDistanceScale?: number;
|
|
@@ -86,7 +88,10 @@ type Props = {
|
|
|
86
88
|
throttleRequests: boolean;
|
|
87
89
|
/** Number of simultaneous requsts, if throttleRequests is true */
|
|
88
90
|
maxRequests: number;
|
|
91
|
+
/* Maximum amount of GPU memory (in MB) that may be used to cache tiles. */
|
|
89
92
|
maximumMemoryUsage: number;
|
|
93
|
+
/* The maximum additional memory (in MB) to allow for cache headroom before adjusting the screen spacer error */
|
|
94
|
+
memoryCacheOverflow: number;
|
|
90
95
|
/** Maximum number limit of tiles selected for show. 0 means no limit */
|
|
91
96
|
maximumTilesSelected: number;
|
|
92
97
|
/** Delay time before the tileset traversal. It prevents traversal requests spam.*/
|
|
@@ -101,6 +106,8 @@ type Props = {
|
|
|
101
106
|
onTraversalComplete: (selectedTiles: Tile3D[]) => Tile3D[];
|
|
102
107
|
/** The maximum screen space error used to drive level of detail refinement. */
|
|
103
108
|
maximumScreenSpaceError: number;
|
|
109
|
+
/** Whether to adjust the maximum screen space error to comply with the maximum memory limitation */
|
|
110
|
+
memoryAdjustedScreenSpaceError: boolean;
|
|
104
111
|
viewportTraversersMap: Record<string, any> | null;
|
|
105
112
|
attributions: string[];
|
|
106
113
|
loadTiles: boolean;
|
|
@@ -121,7 +128,9 @@ const DEFAULT_PROPS: Props = {
|
|
|
121
128
|
modelMatrix: new Matrix4(),
|
|
122
129
|
throttleRequests: true,
|
|
123
130
|
maxRequests: 64,
|
|
131
|
+
/** Default memory values optimized for viewing mesh-based 3D Tiles on both mobile and desktop devices */
|
|
124
132
|
maximumMemoryUsage: 32,
|
|
133
|
+
memoryCacheOverflow: 1,
|
|
125
134
|
maximumTilesSelected: 0,
|
|
126
135
|
debounceTime: 0,
|
|
127
136
|
onTileLoad: () => {},
|
|
@@ -131,6 +140,7 @@ const DEFAULT_PROPS: Props = {
|
|
|
131
140
|
contentLoader: undefined,
|
|
132
141
|
viewDistanceScale: 1.0,
|
|
133
142
|
maximumScreenSpaceError: 8,
|
|
143
|
+
memoryAdjustedScreenSpaceError: false,
|
|
134
144
|
loadTiles: true,
|
|
135
145
|
updateTransforms: true,
|
|
136
146
|
viewportTraversersMap: null,
|
|
@@ -151,6 +161,7 @@ const TILES_UNLOADED = 'Tiles Unloaded';
|
|
|
151
161
|
const TILES_LOAD_FAILED = 'Failed Tile Loads';
|
|
152
162
|
const POINTS_COUNT = 'Points/Vertices';
|
|
153
163
|
const TILES_GPU_MEMORY = 'Tile Memory Use';
|
|
164
|
+
const MAXIMUM_SSE = 'Maximum Screen Space Error';
|
|
154
165
|
|
|
155
166
|
/**
|
|
156
167
|
* The Tileset loading and rendering flow is as below,
|
|
@@ -238,6 +249,17 @@ export class Tileset3D {
|
|
|
238
249
|
/** The total amount of GPU memory in bytes used by the tileset. */
|
|
239
250
|
gpuMemoryUsageInBytes: number = 0;
|
|
240
251
|
|
|
252
|
+
/**
|
|
253
|
+
* If loading the level of detail required by maximumScreenSpaceError
|
|
254
|
+
* results in the memory usage exceeding maximumMemoryUsage (GPU), level of detail refinement
|
|
255
|
+
* will instead use this (larger) adjusted screen space error to achieve the
|
|
256
|
+
* best possible visual quality within the available memory.
|
|
257
|
+
*/
|
|
258
|
+
memoryAdjustedScreenSpaceError: number = 0.0;
|
|
259
|
+
|
|
260
|
+
private _cacheBytes: number = 0;
|
|
261
|
+
private _cacheOverflowBytes: number = 0;
|
|
262
|
+
|
|
241
263
|
/** Update tracker. increase in each update cycle. */
|
|
242
264
|
_frameNumber: number = 0;
|
|
243
265
|
private _queryParams: Record<string, string> = {};
|
|
@@ -300,6 +322,10 @@ export class Tileset3D {
|
|
|
300
322
|
maxRequests: this.options.maxRequests
|
|
301
323
|
});
|
|
302
324
|
|
|
325
|
+
this.memoryAdjustedScreenSpaceError = this.options.maximumScreenSpaceError;
|
|
326
|
+
this._cacheBytes = this.options.maximumMemoryUsage * 1024 * 1024;
|
|
327
|
+
this._cacheOverflowBytes = this.options.memoryCacheOverflow * 1024 * 1024;
|
|
328
|
+
|
|
303
329
|
// METRICS
|
|
304
330
|
// The total amount of GPU memory in bytes used by the tileset.
|
|
305
331
|
this.stats = new Stats({id: this.url});
|
|
@@ -406,6 +432,16 @@ export class Tileset3D {
|
|
|
406
432
|
return this.updatePromise;
|
|
407
433
|
}
|
|
408
434
|
|
|
435
|
+
adjustScreenSpaceError(): void {
|
|
436
|
+
if (this.gpuMemoryUsageInBytes < this._cacheBytes) {
|
|
437
|
+
this.memoryAdjustedScreenSpaceError = Math.max(
|
|
438
|
+
this.memoryAdjustedScreenSpaceError / 1.02,
|
|
439
|
+
this.options.maximumScreenSpaceError
|
|
440
|
+
);
|
|
441
|
+
} else if (this.gpuMemoryUsageInBytes > this._cacheBytes + this._cacheOverflowBytes) {
|
|
442
|
+
this.memoryAdjustedScreenSpaceError *= 1.02;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
409
445
|
/**
|
|
410
446
|
* Update visible tiles relying on a list of viewports
|
|
411
447
|
* @param viewports viewports
|
|
@@ -570,6 +606,7 @@ export class Tileset3D {
|
|
|
570
606
|
this.stats.get(TILES_IN_VIEW).count = this.selectedTiles.length;
|
|
571
607
|
this.stats.get(TILES_RENDERABLE).count = tilesRenderable;
|
|
572
608
|
this.stats.get(POINTS_COUNT).count = pointsRenderable;
|
|
609
|
+
this.stats.get(MAXIMUM_SSE).count = this.memoryAdjustedScreenSpaceError;
|
|
573
610
|
}
|
|
574
611
|
|
|
575
612
|
async _initializeTileSet(tilesetJson: TilesetJSON): Promise<void> {
|
|
@@ -667,6 +704,7 @@ export class Tileset3D {
|
|
|
667
704
|
this.stats.get(TILES_LOAD_FAILED);
|
|
668
705
|
this.stats.get(POINTS_COUNT);
|
|
669
706
|
this.stats.get(TILES_GPU_MEMORY, 'memory');
|
|
707
|
+
this.stats.get(MAXIMUM_SSE);
|
|
670
708
|
}
|
|
671
709
|
|
|
672
710
|
// Installs the main tileset JSON file or a tileset JSON file referenced from a tile.
|
|
@@ -835,9 +873,15 @@ export class Tileset3D {
|
|
|
835
873
|
this.stats.get(TILES_LOADED).incrementCount();
|
|
836
874
|
this.stats.get(TILES_IN_MEMORY).incrementCount();
|
|
837
875
|
|
|
838
|
-
//
|
|
876
|
+
// TODO: Calculate GPU memory usage statistics for a tile.
|
|
839
877
|
this.gpuMemoryUsageInBytes += tile.gpuMemoryUsageInBytes || 0;
|
|
878
|
+
|
|
840
879
|
this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
|
|
880
|
+
|
|
881
|
+
// Adjust SSE based on cache limits
|
|
882
|
+
if (this.options.memoryAdjustedScreenSpaceError) {
|
|
883
|
+
this.adjustScreenSpaceError();
|
|
884
|
+
}
|
|
841
885
|
}
|
|
842
886
|
|
|
843
887
|
_unloadTile(tile) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// loaders.gl
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
2
3
|
// Copyright (c) vis.gl contributors
|
|
3
4
|
|
|
4
5
|
import type {Tile3D} from './tile-3d';
|
|
@@ -10,7 +11,6 @@ export type TilesetTraverserProps = {
|
|
|
10
11
|
loadSiblings?: boolean;
|
|
11
12
|
skipLevelOfDetail?: boolean;
|
|
12
13
|
updateTransforms?: boolean;
|
|
13
|
-
maximumScreenSpaceError?: number;
|
|
14
14
|
onTraversalEnd?: (frameState) => any;
|
|
15
15
|
viewportTraversersMap?: Record<string, any>;
|
|
16
16
|
basePath?: string;
|
|
@@ -19,7 +19,6 @@ export type TilesetTraverserProps = {
|
|
|
19
19
|
export const DEFAULT_PROPS: Required<TilesetTraverserProps> = {
|
|
20
20
|
loadSiblings: false,
|
|
21
21
|
skipLevelOfDetail: false,
|
|
22
|
-
maximumScreenSpaceError: 2,
|
|
23
22
|
updateTransforms: true,
|
|
24
23
|
onTraversalEnd: () => {},
|
|
25
24
|
viewportTraversersMap: {},
|
|
@@ -294,7 +293,7 @@ export class TilesetTraverser {
|
|
|
294
293
|
screenSpaceError = tile.getScreenSpaceError(frameState, true);
|
|
295
294
|
}
|
|
296
295
|
|
|
297
|
-
return screenSpaceError >
|
|
296
|
+
return screenSpaceError > tile.tileset.memoryAdjustedScreenSpaceError;
|
|
298
297
|
}
|
|
299
298
|
|
|
300
299
|
updateTileVisibility(tile: Tile3D, frameState: FrameState): void {
|
|
@@ -334,38 +333,35 @@ export class TilesetTraverser {
|
|
|
334
333
|
executeEmptyTraversal(root: Tile3D, frameState: FrameState): boolean {
|
|
335
334
|
let allDescendantsLoaded = true;
|
|
336
335
|
const stack = this._emptyTraversalStack;
|
|
337
|
-
|
|
338
336
|
stack.push(root);
|
|
339
337
|
|
|
340
|
-
while (stack.length > 0
|
|
338
|
+
while (stack.length > 0) {
|
|
341
339
|
const tile = stack.pop();
|
|
342
340
|
|
|
341
|
+
const traverse = !tile.hasRenderContent && this.canTraverse(tile, frameState, false, false);
|
|
342
|
+
const emptyLeaf = !tile.hasRenderContent && tile.children.length === 0;
|
|
343
|
+
|
|
344
|
+
// Traversal stops but the tile does not have content yet
|
|
345
|
+
// There will be holes if the parent tries to refine to its children, so don't refine
|
|
346
|
+
// One exception: a parent may refine even if one of its descendants is an empty leaf
|
|
347
|
+
if (!traverse && !tile.contentAvailable && !emptyLeaf) {
|
|
348
|
+
allDescendantsLoaded = false;
|
|
349
|
+
}
|
|
350
|
+
|
|
343
351
|
this.updateTile(tile, frameState);
|
|
344
352
|
|
|
345
353
|
if (!tile.isVisibleAndInRequestVolume) {
|
|
346
|
-
// Load tiles that aren't visible since they are still needed for the parent to refine
|
|
347
354
|
this.loadTile(tile, frameState);
|
|
355
|
+
this.touchTile(tile, frameState);
|
|
348
356
|
}
|
|
349
357
|
|
|
350
|
-
this.touchTile(tile, frameState);
|
|
351
|
-
|
|
352
|
-
// Only traverse if the tile is empty - traversal stop at descendants with content
|
|
353
|
-
const traverse = !tile.hasRenderContent && this.canTraverse(tile, frameState, false, true);
|
|
354
|
-
|
|
355
358
|
if (traverse) {
|
|
356
359
|
const children = tile.children;
|
|
357
360
|
for (const child of children) {
|
|
358
|
-
// eslint-disable-next-line max-depth
|
|
359
|
-
if (stack.find(child)) {
|
|
360
|
-
stack.delete(child);
|
|
361
|
-
}
|
|
362
361
|
stack.push(child);
|
|
363
362
|
}
|
|
364
|
-
} else if (!tile.contentAvailable && !tile.hasEmptyContent) {
|
|
365
|
-
allDescendantsLoaded = false;
|
|
366
363
|
}
|
|
367
364
|
}
|
|
368
|
-
|
|
369
365
|
return allDescendantsLoaded;
|
|
370
366
|
}
|
|
371
367
|
}
|