@loaders.gl/tiles 4.0.0-alpha.1 → 4.0.0-alpha.11
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/bundle.d.ts +2 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +2 -2
- package/dist/constants.d.ts +38 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +37 -30
- package/dist/dist.min.js +9163 -0
- package/dist/es5/bundle.js +6 -0
- package/dist/es5/bundle.js.map +1 -0
- package/dist/es5/constants.js +48 -0
- package/dist/es5/constants.js.map +1 -0
- package/dist/es5/index.js +93 -0
- package/dist/es5/index.js.map +1 -0
- package/dist/es5/tileset/format-3d-tiles/tileset-3d-traverser.js +70 -0
- package/dist/es5/tileset/format-3d-tiles/tileset-3d-traverser.js.map +1 -0
- package/dist/es5/tileset/format-i3s/i3s-pending-tiles-register.js +45 -0
- package/dist/es5/tileset/format-i3s/i3s-pending-tiles-register.js.map +1 -0
- package/dist/es5/tileset/format-i3s/i3s-tile-manager.js +84 -0
- package/dist/es5/tileset/format-i3s/i3s-tile-manager.js.map +1 -0
- package/dist/es5/tileset/format-i3s/i3s-tileset-traverser.js +143 -0
- package/dist/es5/tileset/format-i3s/i3s-tileset-traverser.js.map +1 -0
- package/dist/es5/tileset/helpers/3d-tiles-options.js +12 -0
- package/dist/es5/tileset/helpers/3d-tiles-options.js.map +1 -0
- package/dist/es5/tileset/helpers/bounding-volume.js +176 -0
- package/dist/es5/tileset/helpers/bounding-volume.js.map +1 -0
- package/dist/es5/tileset/helpers/frame-state.js +129 -0
- package/dist/es5/tileset/helpers/frame-state.js.map +1 -0
- package/dist/es5/tileset/helpers/i3s-lod.js +60 -0
- package/dist/es5/tileset/helpers/i3s-lod.js.map +1 -0
- package/dist/es5/tileset/helpers/tiles-3d-lod.js +103 -0
- package/dist/es5/tileset/helpers/tiles-3d-lod.js.map +1 -0
- package/dist/es5/tileset/helpers/transform-utils.js +50 -0
- package/dist/es5/tileset/helpers/transform-utils.js.map +1 -0
- package/dist/es5/tileset/helpers/zoom.js +63 -0
- package/dist/es5/tileset/helpers/zoom.js.map +1 -0
- package/dist/es5/tileset/tile-3d.js +536 -0
- package/dist/es5/tileset/tile-3d.js.map +1 -0
- package/dist/es5/tileset/tileset-3d.js +855 -0
- package/dist/es5/tileset/tileset-3d.js.map +1 -0
- package/dist/es5/tileset/tileset-cache.js +82 -0
- package/dist/es5/tileset/tileset-cache.js.map +1 -0
- package/dist/es5/tileset/tileset-traverser.js +321 -0
- package/dist/es5/tileset/tileset-traverser.js.map +1 -0
- package/dist/es5/types.js +2 -0
- package/dist/es5/types.js.map +1 -0
- package/dist/es5/utils/doubly-linked-list-node.js +21 -0
- package/dist/es5/utils/doubly-linked-list-node.js.map +1 -0
- package/dist/es5/utils/doubly-linked-list.js +88 -0
- package/dist/es5/utils/doubly-linked-list.js.map +1 -0
- package/dist/es5/utils/managed-array.js +126 -0
- package/dist/es5/utils/managed-array.js.map +1 -0
- package/dist/esm/bundle.js +4 -0
- package/dist/esm/bundle.js.map +1 -0
- package/dist/esm/constants.js +36 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/{tileset/traversers → esm/tileset/format-3d-tiles}/tileset-3d-traverser.js +2 -13
- package/dist/esm/tileset/format-3d-tiles/tileset-3d-traverser.js.map +1 -0
- package/dist/esm/tileset/format-i3s/i3s-pending-tiles-register.js +26 -0
- package/dist/esm/tileset/format-i3s/i3s-pending-tiles-register.js.map +1 -0
- package/dist/esm/tileset/format-i3s/i3s-tile-manager.js +79 -0
- package/dist/esm/tileset/format-i3s/i3s-tile-manager.js.map +1 -0
- package/dist/{tileset/traversers → esm/tileset/format-i3s}/i3s-tileset-traverser.js +16 -28
- package/dist/esm/tileset/format-i3s/i3s-tileset-traverser.js.map +1 -0
- package/dist/esm/tileset/helpers/3d-tiles-options.js +6 -0
- package/dist/esm/tileset/helpers/3d-tiles-options.js.map +1 -0
- package/dist/esm/tileset/helpers/bounding-volume.js +155 -0
- package/dist/esm/tileset/helpers/bounding-volume.js.map +1 -0
- package/dist/esm/tileset/helpers/frame-state.js +109 -0
- package/dist/esm/tileset/helpers/frame-state.js.map +1 -0
- package/dist/esm/tileset/helpers/i3s-lod.js +53 -0
- package/dist/esm/tileset/helpers/i3s-lod.js.map +1 -0
- package/dist/esm/tileset/helpers/tiles-3d-lod.js +100 -0
- package/dist/{tileset → esm/tileset}/helpers/tiles-3d-lod.js.map +1 -1
- package/dist/esm/tileset/helpers/transform-utils.js +50 -0
- package/dist/esm/tileset/helpers/transform-utils.js.map +1 -0
- package/dist/esm/tileset/helpers/zoom.js +55 -0
- package/dist/esm/tileset/helpers/zoom.js.map +1 -0
- package/dist/esm/tileset/tile-3d.js +414 -0
- package/dist/esm/tileset/tile-3d.js.map +1 -0
- package/dist/esm/tileset/tileset-3d.js +606 -0
- package/dist/esm/tileset/tileset-3d.js.map +1 -0
- package/dist/esm/tileset/tileset-cache.js +57 -0
- package/dist/esm/tileset/tileset-cache.js.map +1 -0
- package/dist/{tileset/traversers → esm/tileset}/tileset-traverser.js +29 -88
- package/dist/esm/tileset/tileset-traverser.js.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils/doubly-linked-list-node.js +12 -0
- package/dist/esm/utils/doubly-linked-list-node.js.map +1 -0
- package/dist/esm/utils/doubly-linked-list.js +65 -0
- package/dist/esm/utils/doubly-linked-list.js.map +1 -0
- package/dist/esm/utils/managed-array.js +87 -0
- package/dist/esm/utils/managed-array.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -9
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.d.ts +7 -0
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -0
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.js +54 -0
- package/dist/tileset/format-i3s/i3s-pending-tiles-register.d.ts +27 -0
- package/dist/tileset/format-i3s/i3s-pending-tiles-register.d.ts.map +1 -0
- package/dist/tileset/format-i3s/i3s-pending-tiles-register.js +47 -0
- package/dist/tileset/format-i3s/i3s-tile-manager.d.ts +34 -0
- package/dist/tileset/format-i3s/i3s-tile-manager.d.ts.map +1 -0
- package/dist/tileset/format-i3s/i3s-tile-manager.js +80 -0
- package/dist/tileset/format-i3s/i3s-tileset-traverser.d.ts +25 -0
- package/dist/tileset/format-i3s/i3s-tileset-traverser.d.ts.map +1 -0
- package/dist/tileset/format-i3s/i3s-tileset-traverser.js +92 -0
- package/dist/tileset/helpers/3d-tiles-options.d.ts +5 -0
- package/dist/tileset/helpers/3d-tiles-options.d.ts.map +1 -0
- package/dist/tileset/helpers/3d-tiles-options.js +8 -5
- package/dist/tileset/helpers/bounding-volume.d.ts +19 -0
- package/dist/tileset/helpers/bounding-volume.d.ts.map +1 -0
- package/dist/tileset/helpers/bounding-volume.js +274 -69
- package/dist/tileset/helpers/frame-state.d.ts +28 -0
- package/dist/tileset/helpers/frame-state.d.ts.map +1 -0
- package/dist/tileset/helpers/frame-state.js +131 -49
- package/dist/tileset/helpers/i3s-lod.d.ts +20 -0
- package/dist/tileset/helpers/i3s-lod.d.ts.map +1 -0
- package/dist/tileset/helpers/i3s-lod.js +82 -105
- package/dist/tileset/helpers/tiles-3d-lod.d.ts +8 -0
- package/dist/tileset/helpers/tiles-3d-lod.d.ts.map +1 -0
- package/dist/tileset/helpers/tiles-3d-lod.js +112 -100
- package/dist/tileset/helpers/transform-utils.d.ts +2 -0
- package/dist/tileset/helpers/transform-utils.d.ts.map +1 -0
- package/dist/tileset/helpers/transform-utils.js +51 -56
- package/dist/tileset/helpers/zoom.d.ts +46 -0
- package/dist/tileset/helpers/zoom.d.ts.map +1 -0
- package/dist/tileset/helpers/zoom.js +83 -30
- package/dist/tileset/tile-3d.d.ts +222 -0
- package/dist/tileset/tile-3d.d.ts.map +1 -0
- package/dist/tileset/tile-3d.js +607 -531
- package/dist/tileset/tileset-3d.d.ts +264 -0
- package/dist/tileset/tileset-3d.d.ts.map +1 -0
- package/dist/tileset/tileset-3d.js +693 -652
- package/dist/tileset/tileset-cache.d.ts +19 -0
- package/dist/tileset/tileset-cache.d.ts.map +1 -0
- package/dist/tileset/tileset-cache.js +66 -73
- package/dist/tileset/tileset-traverser.d.ts +57 -0
- package/dist/tileset/tileset-traverser.d.ts.map +1 -0
- package/dist/tileset/tileset-traverser.js +300 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/utils/doubly-linked-list-node.d.ts +11 -0
- package/dist/utils/doubly-linked-list-node.d.ts.map +1 -0
- package/dist/utils/doubly-linked-list-node.js +17 -8
- package/dist/utils/doubly-linked-list.d.ts +30 -0
- package/dist/utils/doubly-linked-list.d.ts.map +1 -0
- package/dist/utils/doubly-linked-list.js +91 -72
- package/dist/utils/managed-array.d.ts +85 -0
- package/dist/utils/managed-array.d.ts.map +1 -0
- package/dist/utils/managed-array.js +144 -103
- package/package.json +13 -10
- package/src/constants.ts +38 -18
- package/src/index.ts +7 -4
- package/src/tileset/{traversers → format-3d-tiles}/tileset-3d-traverser.ts +4 -2
- package/src/tileset/format-i3s/i3s-pending-tiles-register.ts +44 -0
- package/src/tileset/format-i3s/i3s-tile-manager.ts +101 -0
- package/src/tileset/{traversers → format-i3s}/i3s-tileset-traverser.ts +27 -15
- package/src/tileset/helpers/3d-tiles-options.ts +3 -1
- package/src/tileset/helpers/bounding-volume.ts +136 -0
- package/src/tileset/helpers/frame-state.ts +102 -18
- package/src/tileset/helpers/i3s-lod.ts +75 -96
- package/src/tileset/helpers/tiles-3d-lod.ts +2 -0
- package/src/tileset/helpers/transform-utils.ts +2 -0
- package/src/tileset/helpers/zoom.ts +84 -9
- package/src/tileset/tile-3d.ts +139 -123
- package/src/tileset/tileset-3d.ts +379 -252
- package/src/tileset/tileset-cache.ts +26 -17
- package/src/tileset/{traversers/tileset-traverser.ts → tileset-traverser.ts} +71 -72
- package/src/types.ts +36 -0
- package/src/utils/{doubly-linked-list-node.js → doubly-linked-list-node.ts} +7 -2
- package/src/utils/{doubly-linked-list.js → doubly-linked-list.ts} +5 -8
- package/src/utils/{managed-array.js → managed-array.ts} +5 -2
- package/dist/bundle.js.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/tileset/helpers/3d-tiles-options.js.map +0 -1
- package/dist/tileset/helpers/bounding-volume.js.map +0 -1
- package/dist/tileset/helpers/frame-state.js.map +0 -1
- package/dist/tileset/helpers/i3s-lod.js.map +0 -1
- package/dist/tileset/helpers/transform-utils.js.map +0 -1
- package/dist/tileset/helpers/zoom.js.map +0 -1
- package/dist/tileset/tile-3d.js.map +0 -1
- package/dist/tileset/tileset-3d.js.map +0 -1
- package/dist/tileset/tileset-cache.js.map +0 -1
- package/dist/tileset/traversers/i3s-tile-manager.js +0 -45
- package/dist/tileset/traversers/i3s-tile-manager.js.map +0 -1
- package/dist/tileset/traversers/i3s-tileset-traverser.js.map +0 -1
- package/dist/tileset/traversers/tileset-3d-traverser.js.map +0 -1
- package/dist/tileset/traversers/tileset-traverser.js.map +0 -1
- package/dist/utils/doubly-linked-list-node.js.map +0 -1
- package/dist/utils/doubly-linked-list.js.map +0 -1
- package/dist/utils/managed-array.js.map +0 -1
- package/src/tileset/traversers/i3s-tile-manager.ts +0 -39
|
@@ -1,61 +1,48 @@
|
|
|
1
|
+
// loaders.gl, MIT license
|
|
2
|
+
|
|
1
3
|
// This file is derived from the Cesium code base under Apache 2 license
|
|
2
4
|
// See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md
|
|
3
5
|
|
|
4
|
-
/*
|
|
5
|
-
|
|
6
|
-
The Tileset loading and rendering flow is as below,
|
|
7
|
-
A rendered (i.e. deck.gl `Tile3DLayer`) triggers `tileset.update()` after a `tileset` is loaded
|
|
8
|
-
`tileset` starts traversing the tile tree and update `requestTiles` (tiles of which content need
|
|
9
|
-
to be fetched) and `selectedTiles` (tiles ready for rendering under the current viewport).
|
|
10
|
-
`Tile3DLayer` will update rendering based on `selectedTiles`.
|
|
11
|
-
`Tile3DLayer` also listens to `onTileLoad` callback and trigger another round of `update and then traversal`
|
|
12
|
-
when new tiles are loaded.
|
|
13
|
-
|
|
14
|
-
As I3S tileset have stored `tileHeader` file (metadata) and tile content files (geometry, texture, ...) separately.
|
|
15
|
-
During each traversal, it issues `tilHeader` requests if that `tileHeader` is not yet fetched,
|
|
16
|
-
after the tile header is fulfilled, it will resume the traversal starting from the tile just fetched (not root).
|
|
17
|
-
|
|
18
|
-
Tile3DLayer
|
|
19
|
-
|
|
|
20
|
-
await load(tileset)
|
|
21
|
-
|
|
|
22
|
-
tileset.update()
|
|
23
|
-
| async load tileHeader
|
|
24
|
-
tileset.traverse() -------------------------- Queued
|
|
25
|
-
| resume traversal after fetched |
|
|
26
|
-
|----------------------------------------|
|
|
27
|
-
|
|
|
28
|
-
| async load tile content
|
|
29
|
-
tilset.requestedTiles ----------------------------- RequestScheduler
|
|
30
|
-
|
|
|
31
|
-
tilset.selectedTiles (ready for rendering) |
|
|
32
|
-
| Listen to |
|
|
33
|
-
Tile3DLayer ----------- onTileLoad ----------------------|
|
|
34
|
-
| | notify new tile is available
|
|
35
|
-
updateLayers |
|
|
36
|
-
tileset.update // trigger another round of update
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
6
|
import {Matrix4, Vector3} from '@math.gl/core';
|
|
40
7
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
41
8
|
import {Stats} from '@probe.gl/stats';
|
|
42
|
-
import {
|
|
43
|
-
|
|
44
|
-
assert,
|
|
45
|
-
path,
|
|
46
|
-
LoaderWithParser,
|
|
47
|
-
LoaderOptions
|
|
48
|
-
} from '@loaders.gl/loader-utils';
|
|
49
|
-
import TilesetCache from './tileset-cache';
|
|
9
|
+
import {RequestScheduler, path, LoaderWithParser, LoaderOptions} from '@loaders.gl/loader-utils';
|
|
10
|
+
import {TilesetCache} from './tileset-cache';
|
|
50
11
|
import {calculateTransformProps} from './helpers/transform-utils';
|
|
51
|
-
import {FrameState, getFrameState} from './helpers/frame-state';
|
|
52
|
-
import {getZoomFromBoundingVolume} from './helpers/zoom';
|
|
53
|
-
|
|
54
|
-
import
|
|
55
|
-
import
|
|
56
|
-
import I3SetTraverser from './traversers/i3s-tileset-traverser';
|
|
12
|
+
import {FrameState, getFrameState, limitSelectedTiles} from './helpers/frame-state';
|
|
13
|
+
import {getZoomFromBoundingVolume, getZoomFromExtent, getZoomFromFullExtent} from './helpers/zoom';
|
|
14
|
+
|
|
15
|
+
import type {GeospatialViewport, Viewport} from '../types';
|
|
16
|
+
import {Tile3D} from './tile-3d';
|
|
57
17
|
import {TILESET_TYPE} from '../constants';
|
|
58
18
|
|
|
19
|
+
import {TilesetTraverser} from './tileset-traverser';
|
|
20
|
+
|
|
21
|
+
// TODO - these should be moved into their respective modules
|
|
22
|
+
import {Tileset3DTraverser} from './format-3d-tiles/tileset-3d-traverser';
|
|
23
|
+
import {I3STilesetTraverser} from './format-i3s/i3s-tileset-traverser';
|
|
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
|
+
|
|
59
46
|
export type Tileset3DProps = {
|
|
60
47
|
// loading
|
|
61
48
|
throttleRequests?: boolean;
|
|
@@ -64,6 +51,8 @@ export type Tileset3DProps = {
|
|
|
64
51
|
loadTiles?: boolean;
|
|
65
52
|
basePath?: string;
|
|
66
53
|
maximumMemoryUsage?: number;
|
|
54
|
+
maximumTilesSelected?: number;
|
|
55
|
+
debounceTime?: number;
|
|
67
56
|
|
|
68
57
|
// Metadata
|
|
69
58
|
description?: string;
|
|
@@ -90,78 +79,63 @@ export type Tileset3DProps = {
|
|
|
90
79
|
type Props = {
|
|
91
80
|
description: string;
|
|
92
81
|
ellipsoid: object;
|
|
82
|
+
/** A 4x4 transformation matrix this transforms the entire tileset. */
|
|
93
83
|
modelMatrix: Matrix4;
|
|
84
|
+
/** Set to false to disable network request throttling */
|
|
94
85
|
throttleRequests: boolean;
|
|
86
|
+
/** Number of simultaneous requsts, if throttleRequests is true */
|
|
87
|
+
maxRequests: number;
|
|
95
88
|
maximumMemoryUsage: number;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
89
|
+
/** Maximum number limit of tiles selected for show. 0 means no limit */
|
|
90
|
+
maximumTilesSelected: number;
|
|
91
|
+
/** Delay time before the tileset traversal. It prevents traversal requests spam.*/
|
|
92
|
+
debounceTime: number;
|
|
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. */
|
|
99
100
|
onTraversalComplete: (selectedTiles: Tile3D[]) => Tile3D[];
|
|
101
|
+
/** The maximum screen space error used to drive level of detail refinement. */
|
|
100
102
|
maximumScreenSpaceError: number;
|
|
101
|
-
viewportTraversersMap: any;
|
|
103
|
+
viewportTraversersMap: Record<string, any> | null;
|
|
102
104
|
attributions: string[];
|
|
103
|
-
maxRequests: number;
|
|
104
105
|
loadTiles: boolean;
|
|
105
106
|
loadOptions: LoaderOptions;
|
|
106
107
|
updateTransforms: boolean;
|
|
108
|
+
/** View distance scale modifier */
|
|
107
109
|
viewDistanceScale: number;
|
|
108
110
|
basePath: string;
|
|
111
|
+
/** Optional async tile content loader */
|
|
109
112
|
contentLoader?: (tile: Tile3D) => Promise<void>;
|
|
110
|
-
|
|
113
|
+
/** @todo I3S specific knowledge should be moved to I3S module */
|
|
114
|
+
i3s: Record<string, any>;
|
|
111
115
|
};
|
|
112
116
|
|
|
113
117
|
const DEFAULT_PROPS: Props = {
|
|
114
118
|
description: '',
|
|
115
|
-
|
|
116
119
|
ellipsoid: Ellipsoid.WGS84,
|
|
117
|
-
// A 4x4 transformation matrix this transforms the entire tileset.
|
|
118
120
|
modelMatrix: new Matrix4(),
|
|
119
|
-
|
|
120
|
-
// Set to false to disable network request throttling
|
|
121
121
|
throttleRequests: true,
|
|
122
|
-
|
|
123
|
-
// Number of simultaneous requsts, if throttleRequests is true
|
|
124
122
|
maxRequests: 64,
|
|
125
|
-
|
|
126
123
|
maximumMemoryUsage: 32,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* Callback. Indicates this a tile's content was loaded
|
|
130
|
-
* @param tile {TileHeader}
|
|
131
|
-
*/
|
|
124
|
+
maximumTilesSelected: 0,
|
|
125
|
+
debounceTime: 0,
|
|
132
126
|
onTileLoad: () => {},
|
|
133
|
-
/**
|
|
134
|
-
* Callback. Indicates this a tile's content was unloaded
|
|
135
|
-
* @param tile {TileHeader}
|
|
136
|
-
*/
|
|
137
127
|
onTileUnload: () => {},
|
|
138
128
|
onTileError: () => {},
|
|
139
|
-
/**
|
|
140
|
-
* Callback. Allows post-process selectedTiles right after traversal.
|
|
141
|
-
* @param selectedTiles {TileHeader[]}
|
|
142
|
-
* @returns TileHeader[] - output array of tiles to return to deck.gl
|
|
143
|
-
*/
|
|
144
129
|
onTraversalComplete: (selectedTiles: Tile3D[]) => selectedTiles,
|
|
145
|
-
|
|
146
|
-
// Optional async tile content loader
|
|
147
130
|
contentLoader: undefined,
|
|
148
|
-
|
|
149
|
-
// View distance scale modifier
|
|
150
131
|
viewDistanceScale: 1.0,
|
|
151
|
-
|
|
152
|
-
// TODO CESIUM
|
|
153
|
-
// The maximum screen space error used to drive level of detail refinement.
|
|
154
132
|
maximumScreenSpaceError: 8,
|
|
155
|
-
|
|
156
133
|
loadTiles: true,
|
|
157
134
|
updateTransforms: true,
|
|
158
135
|
viewportTraversersMap: null,
|
|
159
|
-
|
|
160
136
|
loadOptions: {fetch: {}},
|
|
161
|
-
|
|
162
137
|
attributions: [],
|
|
163
138
|
basePath: '',
|
|
164
|
-
|
|
165
139
|
i3s: {}
|
|
166
140
|
};
|
|
167
141
|
|
|
@@ -174,16 +148,49 @@ const TILES_LOADED = 'Tiles Loaded';
|
|
|
174
148
|
const TILES_LOADING = 'Tiles Loading';
|
|
175
149
|
const TILES_UNLOADED = 'Tiles Unloaded';
|
|
176
150
|
const TILES_LOAD_FAILED = 'Failed Tile Loads';
|
|
177
|
-
const POINTS_COUNT = 'Points';
|
|
151
|
+
const POINTS_COUNT = 'Points/Vertices';
|
|
178
152
|
const TILES_GPU_MEMORY = 'Tile Memory Use';
|
|
179
153
|
|
|
180
|
-
|
|
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
|
+
*/
|
|
187
|
+
export class Tileset3D {
|
|
181
188
|
// props: Tileset3DProps;
|
|
182
189
|
options: Props;
|
|
183
|
-
loadOptions:
|
|
190
|
+
loadOptions: LoaderOptions;
|
|
184
191
|
|
|
185
192
|
type: string;
|
|
186
|
-
tileset:
|
|
193
|
+
tileset: TilesetJSON;
|
|
187
194
|
loader: LoaderWithParser;
|
|
188
195
|
url: string;
|
|
189
196
|
basePath: string;
|
|
@@ -192,55 +199,71 @@ export default class Tileset3D {
|
|
|
192
199
|
lodMetricType: string;
|
|
193
200
|
lodMetricValue: number;
|
|
194
201
|
refine: string;
|
|
195
|
-
root: Tile3D | null;
|
|
196
|
-
roots:
|
|
197
|
-
|
|
202
|
+
root: Tile3D | null = null;
|
|
203
|
+
roots: Record<string, Tile3D> = {};
|
|
204
|
+
/** @todo any->unknown */
|
|
205
|
+
asset: Record<string, any> = {};
|
|
198
206
|
|
|
199
|
-
|
|
207
|
+
// Metadata for the entire tileset
|
|
208
|
+
description: string = '';
|
|
200
209
|
properties: any;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
210
|
+
|
|
211
|
+
extras: any = null;
|
|
212
|
+
attributions: any = {};
|
|
213
|
+
credits: any = {};
|
|
204
214
|
|
|
205
215
|
stats: Stats;
|
|
206
216
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
selectedTiles: Tile3D[];
|
|
217
|
+
/** flags that contain information about data types in nested tiles */
|
|
218
|
+
contentFormats = {draco: false, meshopt: false, dds: false, ktx2: false};
|
|
210
219
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
220
|
+
// view props
|
|
221
|
+
cartographicCenter: Vector3 | null = null;
|
|
222
|
+
cartesianCenter: Vector3 | null = null;
|
|
223
|
+
zoom: number = 1;
|
|
224
|
+
boundingVolume: any = null;
|
|
225
|
+
|
|
226
|
+
/** Updated based on the camera position and direction */
|
|
227
|
+
dynamicScreenSpaceErrorComputedDensity: number = 0.0;
|
|
215
228
|
|
|
216
229
|
// METRICS
|
|
217
|
-
// The maximum amount of GPU memory (in MB) that may be used to cache tiles.
|
|
218
|
-
// Tiles not in view are unloaded to enforce private
|
|
219
|
-
// The total amount of GPU memory in bytes used by the tileset.
|
|
220
|
-
gpuMemoryUsageInBytes: any;
|
|
221
|
-
dynamicScreenSpaceErrorComputedDensity: any;
|
|
222
230
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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;
|
|
227
236
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
private _queryParams: any;
|
|
231
|
-
private _extensionsUsed: any;
|
|
232
|
-
private _tiles: {[id: string]: Tile3D};
|
|
237
|
+
/** The total amount of GPU memory in bytes used by the tileset. */
|
|
238
|
+
gpuMemoryUsageInBytes: number = 0;
|
|
233
239
|
|
|
234
|
-
|
|
235
|
-
|
|
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> = {};
|
|
236
245
|
|
|
237
|
-
|
|
238
|
-
private
|
|
239
|
-
private _requestedTiles: any;
|
|
240
|
-
private _emptyTiles: any;
|
|
241
|
-
private frameStateData: any;
|
|
246
|
+
/** counter for tracking tiles requests */
|
|
247
|
+
private _pendingCount: number = 0;
|
|
242
248
|
|
|
243
|
-
|
|
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>;
|
|
244
267
|
|
|
245
268
|
/**
|
|
246
269
|
* Create a new Tileset3D
|
|
@@ -248,83 +271,40 @@ export default class Tileset3D {
|
|
|
248
271
|
* @param props
|
|
249
272
|
*/
|
|
250
273
|
// eslint-disable-next-line max-statements
|
|
251
|
-
constructor(
|
|
252
|
-
assert(json);
|
|
253
|
-
|
|
274
|
+
constructor(tileset: TilesetJSON, options?: Tileset3DProps) {
|
|
254
275
|
// PUBLIC MEMBERS
|
|
255
276
|
this.options = {...DEFAULT_PROPS, ...options};
|
|
256
277
|
// raw data
|
|
257
|
-
this.tileset =
|
|
258
|
-
this.loader =
|
|
278
|
+
this.tileset = tileset;
|
|
279
|
+
this.loader = tileset.loader;
|
|
259
280
|
// could be 3d tiles, i3s
|
|
260
|
-
this.type =
|
|
281
|
+
this.type = tileset.type;
|
|
261
282
|
// The url to a tileset JSON file.
|
|
262
|
-
this.url =
|
|
263
|
-
this.basePath =
|
|
283
|
+
this.url = tileset.url;
|
|
284
|
+
this.basePath = tileset.basePath || path.dirname(this.url);
|
|
264
285
|
this.modelMatrix = this.options.modelMatrix;
|
|
265
286
|
this.ellipsoid = this.options.ellipsoid;
|
|
266
287
|
|
|
267
288
|
// Geometric error when the tree is not rendered at all
|
|
268
|
-
this.lodMetricType =
|
|
269
|
-
this.lodMetricValue =
|
|
270
|
-
this.refine =
|
|
289
|
+
this.lodMetricType = tileset.lodMetricType;
|
|
290
|
+
this.lodMetricValue = tileset.lodMetricValue;
|
|
291
|
+
this.refine = tileset.root.refine;
|
|
271
292
|
|
|
272
293
|
this.loadOptions = this.options.loadOptions || {};
|
|
273
294
|
|
|
274
|
-
this.root = null;
|
|
275
|
-
this.roots = {};
|
|
276
|
-
// view props
|
|
277
|
-
this.cartographicCenter = null;
|
|
278
|
-
this.cartesianCenter = null;
|
|
279
|
-
this.zoom = 1;
|
|
280
|
-
this.boundingVolume = null;
|
|
281
|
-
|
|
282
295
|
// TRAVERSAL
|
|
283
|
-
this.traverseCounter = 0;
|
|
284
|
-
this.geometricError = 0;
|
|
285
296
|
this._traverser = this._initializeTraverser();
|
|
286
|
-
this._cache = new TilesetCache();
|
|
287
297
|
this._requestScheduler = new RequestScheduler({
|
|
288
298
|
throttleRequests: this.options.throttleRequests,
|
|
289
299
|
maxRequests: this.options.maxRequests
|
|
290
300
|
});
|
|
291
|
-
// update tracker
|
|
292
|
-
// increase in each update cycle
|
|
293
|
-
this._frameNumber = 0;
|
|
294
|
-
|
|
295
|
-
// counter for tracking tiles requests
|
|
296
|
-
this._pendingCount = 0;
|
|
297
|
-
|
|
298
|
-
// HOLD TRAVERSAL RESULTS
|
|
299
|
-
this._tiles = {};
|
|
300
|
-
this.selectedTiles = [];
|
|
301
|
-
this._emptyTiles = [];
|
|
302
|
-
this._requestedTiles = [];
|
|
303
|
-
this.frameStateData = {};
|
|
304
|
-
this.lastUpdatedVieports = null;
|
|
305
|
-
|
|
306
|
-
this._queryParams = {};
|
|
307
|
-
this._queryParamsString = '';
|
|
308
301
|
|
|
309
302
|
// METRICS
|
|
310
|
-
// The maximum amount of GPU memory (in MB) that may be used to cache tiles.
|
|
311
|
-
// Tiles not in view are unloaded to enforce this.
|
|
312
|
-
this.maximumMemoryUsage = this.options.maximumMemoryUsage || 32;
|
|
313
303
|
// The total amount of GPU memory in bytes used by the tileset.
|
|
314
|
-
this.gpuMemoryUsageInBytes = 0;
|
|
315
304
|
this.stats = new Stats({id: this.url});
|
|
316
305
|
this._initializeStats();
|
|
317
306
|
|
|
318
|
-
|
|
319
|
-
this._extensionsUsed = undefined;
|
|
320
|
-
this.dynamicScreenSpaceErrorComputedDensity = 0.0; // Updated based on the camera position and direction
|
|
321
|
-
// Metadata for the entire tileset
|
|
322
|
-
this.extras = null;
|
|
323
|
-
this.asset = {};
|
|
324
|
-
this.credits = {};
|
|
325
|
-
this.description = this.options.description || '';
|
|
326
|
-
|
|
327
|
-
this._initializeTileSet(json);
|
|
307
|
+
this.tilesetInitializationPromise = this._initializeTileSet(tileset);
|
|
328
308
|
}
|
|
329
309
|
|
|
330
310
|
/** Release resources */
|
|
@@ -335,7 +315,7 @@ export default class Tileset3D {
|
|
|
335
315
|
/** Is the tileset loaded (update needs to have been called at least once) */
|
|
336
316
|
isLoaded(): boolean {
|
|
337
317
|
// Check that `_frameNumber !== 0` which means that update was called at least once
|
|
338
|
-
return this._pendingCount === 0 && this._frameNumber !== 0;
|
|
318
|
+
return this._pendingCount === 0 && this._frameNumber !== 0 && this._requestedTiles.length === 0;
|
|
339
319
|
}
|
|
340
320
|
|
|
341
321
|
get tiles(): object[] {
|
|
@@ -347,10 +327,7 @@ export default class Tileset3D {
|
|
|
347
327
|
}
|
|
348
328
|
|
|
349
329
|
get queryParams(): string {
|
|
350
|
-
|
|
351
|
-
this._queryParamsString = getQueryParamString(this._queryParams);
|
|
352
|
-
}
|
|
353
|
-
return this._queryParamsString;
|
|
330
|
+
return new URLSearchParams(this._queryParams).toString();
|
|
354
331
|
}
|
|
355
332
|
|
|
356
333
|
setProps(props: Tileset3DProps): void {
|
|
@@ -371,42 +348,79 @@ export default class Tileset3D {
|
|
|
371
348
|
if (isDataUrl) {
|
|
372
349
|
return tilePath;
|
|
373
350
|
}
|
|
374
|
-
return `${tilePath}${this.queryParams}`;
|
|
351
|
+
return `${tilePath}${tilePath.includes('?') ? '&' : '?'}${this.queryParams}`;
|
|
375
352
|
}
|
|
376
353
|
|
|
377
354
|
// TODO CESIUM specific
|
|
378
355
|
hasExtension(extensionName: string): boolean {
|
|
379
|
-
return Boolean(this._extensionsUsed
|
|
356
|
+
return Boolean(this._extensionsUsed.indexOf(extensionName) > -1);
|
|
380
357
|
}
|
|
381
358
|
|
|
382
359
|
/**
|
|
383
360
|
* Update visible tiles relying on a list of viewports
|
|
384
361
|
* @param viewports - list of viewports
|
|
362
|
+
* @deprecated
|
|
363
|
+
*/
|
|
364
|
+
update(viewports: Viewport[] | Viewport | null = null) {
|
|
365
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
366
|
+
this.tilesetInitializationPromise.then(() => {
|
|
367
|
+
if (!viewports && this.lastUpdatedVieports) {
|
|
368
|
+
viewports = this.lastUpdatedVieports;
|
|
369
|
+
} else {
|
|
370
|
+
this.lastUpdatedVieports = viewports;
|
|
371
|
+
}
|
|
372
|
+
if (viewports) {
|
|
373
|
+
this.doUpdate(viewports);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Update visible tiles relying on a list of viewports.
|
|
380
|
+
* Do it with debounce delay to prevent update spam
|
|
381
|
+
* @param viewports viewports
|
|
382
|
+
* @returns Promise of new frameNumber
|
|
383
|
+
*/
|
|
384
|
+
async selectTiles(viewports: Viewport[] | Viewport | null = null): Promise<number> {
|
|
385
|
+
await this.tilesetInitializationPromise;
|
|
386
|
+
if (viewports) {
|
|
387
|
+
this.lastUpdatedVieports = viewports;
|
|
388
|
+
}
|
|
389
|
+
if (!this.updatePromise) {
|
|
390
|
+
this.updatePromise = new Promise<number>((resolve) => {
|
|
391
|
+
setTimeout(() => {
|
|
392
|
+
if (this.lastUpdatedVieports) {
|
|
393
|
+
this.doUpdate(this.lastUpdatedVieports);
|
|
394
|
+
}
|
|
395
|
+
resolve(this._frameNumber);
|
|
396
|
+
this.updatePromise = null;
|
|
397
|
+
}, this.options.debounceTime);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
return this.updatePromise;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Update visible tiles relying on a list of viewports
|
|
405
|
+
* @param viewports viewports
|
|
385
406
|
*/
|
|
386
407
|
// eslint-disable-next-line max-statements, complexity
|
|
387
|
-
|
|
408
|
+
private doUpdate(viewports: Viewport[] | Viewport): void {
|
|
388
409
|
if ('loadTiles' in this.options && !this.options.loadTiles) {
|
|
389
410
|
return;
|
|
390
411
|
}
|
|
391
412
|
if (this.traverseCounter > 0) {
|
|
392
413
|
return;
|
|
393
414
|
}
|
|
394
|
-
|
|
395
|
-
viewports = this.lastUpdatedVieports;
|
|
396
|
-
} else {
|
|
397
|
-
this.lastUpdatedVieports = viewports;
|
|
398
|
-
}
|
|
399
|
-
if (!(viewports instanceof Array)) {
|
|
400
|
-
viewports = [viewports];
|
|
401
|
-
}
|
|
415
|
+
const preparedViewports = viewports instanceof Array ? viewports : [viewports];
|
|
402
416
|
|
|
403
417
|
this._cache.reset();
|
|
404
418
|
this._frameNumber++;
|
|
405
|
-
this.traverseCounter =
|
|
419
|
+
this.traverseCounter = preparedViewports.length;
|
|
406
420
|
const viewportsToTraverse: string[] = [];
|
|
407
421
|
// First loop to decrement traverseCounter
|
|
408
|
-
for (const viewport of
|
|
409
|
-
const id = viewport.id
|
|
422
|
+
for (const viewport of preparedViewports) {
|
|
423
|
+
const id = viewport.id;
|
|
410
424
|
if (this._needTraverse(id)) {
|
|
411
425
|
viewportsToTraverse.push(id);
|
|
412
426
|
} else {
|
|
@@ -415,8 +429,8 @@ export default class Tileset3D {
|
|
|
415
429
|
}
|
|
416
430
|
|
|
417
431
|
// Second loop to traverse
|
|
418
|
-
for (const viewport of
|
|
419
|
-
const id = viewport.id
|
|
432
|
+
for (const viewport of preparedViewports) {
|
|
433
|
+
const id = viewport.id;
|
|
420
434
|
if (!this.roots[id]) {
|
|
421
435
|
this.roots[id] = this._initializeTileHeaders(this.tileset, null);
|
|
422
436
|
}
|
|
@@ -424,7 +438,7 @@ export default class Tileset3D {
|
|
|
424
438
|
if (!viewportsToTraverse.includes(id)) {
|
|
425
439
|
continue; // eslint-disable-line no-continue
|
|
426
440
|
}
|
|
427
|
-
const frameState = getFrameState(viewport, this._frameNumber);
|
|
441
|
+
const frameState = getFrameState(viewport as GeospatialViewport, this._frameNumber);
|
|
428
442
|
this._traverser.traverse(this.roots[id], frameState, this.options);
|
|
429
443
|
}
|
|
430
444
|
}
|
|
@@ -457,7 +471,16 @@ export default class Tileset3D {
|
|
|
457
471
|
}
|
|
458
472
|
const currentFrameStateData = this.frameStateData[id];
|
|
459
473
|
const selectedTiles = Object.values(this._traverser.selectedTiles);
|
|
460
|
-
|
|
474
|
+
const [filteredSelectedTiles, unselectedTiles] = limitSelectedTiles(
|
|
475
|
+
selectedTiles,
|
|
476
|
+
frameState,
|
|
477
|
+
this.options.maximumTilesSelected
|
|
478
|
+
);
|
|
479
|
+
currentFrameStateData.selectedTiles = filteredSelectedTiles;
|
|
480
|
+
for (const tile of unselectedTiles) {
|
|
481
|
+
tile.unselect();
|
|
482
|
+
}
|
|
483
|
+
|
|
461
484
|
currentFrameStateData._requestedTiles = Object.values(this._traverser.requestedTiles);
|
|
462
485
|
currentFrameStateData._emptyTiles = Object.values(this._traverser.emptyTiles);
|
|
463
486
|
|
|
@@ -495,7 +518,7 @@ export default class Tileset3D {
|
|
|
495
518
|
this._updateStats();
|
|
496
519
|
}
|
|
497
520
|
|
|
498
|
-
_tilesChanged(oldSelectedTiles, selectedTiles) {
|
|
521
|
+
_tilesChanged(oldSelectedTiles: Tile3D[], selectedTiles: Tile3D[]): boolean {
|
|
499
522
|
if (oldSelectedTiles.length !== selectedTiles.length) {
|
|
500
523
|
return true;
|
|
501
524
|
}
|
|
@@ -506,7 +529,7 @@ export default class Tileset3D {
|
|
|
506
529
|
return changed;
|
|
507
530
|
}
|
|
508
531
|
|
|
509
|
-
_loadTiles() {
|
|
532
|
+
_loadTiles(): void {
|
|
510
533
|
// Sort requests by priority before making any requests.
|
|
511
534
|
// This makes it less likely this requests will be cancelled after being issued.
|
|
512
535
|
// requestedTiles.sort((a, b) => a._priority - b._priority);
|
|
@@ -518,12 +541,12 @@ export default class Tileset3D {
|
|
|
518
541
|
}
|
|
519
542
|
}
|
|
520
543
|
|
|
521
|
-
_unloadTiles() {
|
|
544
|
+
_unloadTiles(): void {
|
|
522
545
|
// unload tiles from cache when hit maximumMemoryUsage
|
|
523
546
|
this._cache.unloadTiles(this, (tileset, tile) => tileset._unloadTile(tile));
|
|
524
547
|
}
|
|
525
548
|
|
|
526
|
-
_updateStats() {
|
|
549
|
+
_updateStats(): void {
|
|
527
550
|
let tilesRenderable = 0;
|
|
528
551
|
let pointsRenderable = 0;
|
|
529
552
|
for (const tile of this.selectedTiles) {
|
|
@@ -531,6 +554,9 @@ export default class Tileset3D {
|
|
|
531
554
|
tilesRenderable++;
|
|
532
555
|
if (tile.content.pointCount) {
|
|
533
556
|
pointsRenderable += tile.content.pointCount;
|
|
557
|
+
} else {
|
|
558
|
+
// Calculate vertices for non point cloud tiles.
|
|
559
|
+
pointsRenderable += tile.content.vertexCount;
|
|
534
560
|
}
|
|
535
561
|
}
|
|
536
562
|
}
|
|
@@ -540,37 +566,91 @@ export default class Tileset3D {
|
|
|
540
566
|
this.stats.get(POINTS_COUNT).count = pointsRenderable;
|
|
541
567
|
}
|
|
542
568
|
|
|
543
|
-
_initializeTileSet(tilesetJson) {
|
|
569
|
+
async _initializeTileSet(tilesetJson: TilesetJSON): Promise<void> {
|
|
570
|
+
if (this.type === TILESET_TYPE.I3S) {
|
|
571
|
+
this.calculateViewPropsI3S();
|
|
572
|
+
tilesetJson.root = await tilesetJson.root;
|
|
573
|
+
}
|
|
544
574
|
this.root = this._initializeTileHeaders(tilesetJson, null);
|
|
545
575
|
|
|
546
|
-
// TODO CESIUM Specific
|
|
547
576
|
if (this.type === TILESET_TYPE.TILES3D) {
|
|
548
|
-
this.
|
|
577
|
+
this._initializeTiles3DTileset(tilesetJson);
|
|
578
|
+
this.calculateViewPropsTiles3D();
|
|
549
579
|
}
|
|
550
580
|
|
|
551
581
|
if (this.type === TILESET_TYPE.I3S) {
|
|
552
582
|
this._initializeI3STileset();
|
|
553
583
|
}
|
|
554
|
-
// Calculate cartographicCenter & zoom props to help apps center view on tileset
|
|
555
|
-
this._calculateViewProps();
|
|
556
584
|
}
|
|
557
585
|
|
|
558
|
-
|
|
559
|
-
|
|
586
|
+
/**
|
|
587
|
+
* Called during initialize Tileset to initialize the tileset's cartographic center (longitude, latitude) and zoom.
|
|
588
|
+
* These metrics help apps center view on tileset
|
|
589
|
+
* For I3S there is extent (<1.8 version) or fullExtent (>=1.8 version) to calculate view props
|
|
590
|
+
* @returns
|
|
591
|
+
*/
|
|
592
|
+
private calculateViewPropsI3S(): void {
|
|
593
|
+
// for I3S 1.8 try to calculate with fullExtent
|
|
594
|
+
const fullExtent = this.tileset.fullExtent;
|
|
595
|
+
if (fullExtent) {
|
|
596
|
+
const {xmin, xmax, ymin, ymax, zmin, zmax} = fullExtent;
|
|
597
|
+
this.cartographicCenter = new Vector3(
|
|
598
|
+
xmin + (xmax - xmin) / 2,
|
|
599
|
+
ymin + (ymax - ymin) / 2,
|
|
600
|
+
zmin + (zmax - zmin) / 2
|
|
601
|
+
);
|
|
602
|
+
this.cartesianCenter = Ellipsoid.WGS84.cartographicToCartesian(
|
|
603
|
+
this.cartographicCenter,
|
|
604
|
+
new Vector3()
|
|
605
|
+
);
|
|
606
|
+
this.zoom = getZoomFromFullExtent(fullExtent, this.cartographicCenter, this.cartesianCenter);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
// for I3S 1.6-1.7 try to calculate with extent
|
|
610
|
+
const extent = this.tileset.store?.extent;
|
|
611
|
+
if (extent) {
|
|
612
|
+
const [xmin, ymin, xmax, ymax] = extent;
|
|
613
|
+
this.cartographicCenter = new Vector3(xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2, 0);
|
|
614
|
+
this.cartesianCenter = Ellipsoid.WGS84.cartographicToCartesian(
|
|
615
|
+
this.cartographicCenter,
|
|
616
|
+
new Vector3()
|
|
617
|
+
);
|
|
618
|
+
this.zoom = getZoomFromExtent(extent, this.cartographicCenter, this.cartesianCenter);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
// eslint-disable-next-line no-console
|
|
622
|
+
console.warn('Extent is not defined in the tileset header');
|
|
623
|
+
this.cartographicCenter = new Vector3();
|
|
624
|
+
this.zoom = 1;
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Called during initialize Tileset to initialize the tileset's cartographic center (longitude, latitude) and zoom.
|
|
630
|
+
* These metrics help apps center view on tileset.
|
|
631
|
+
* For 3DTiles the root tile data is used to calculate view props.
|
|
632
|
+
* @returns
|
|
633
|
+
*/
|
|
634
|
+
private calculateViewPropsTiles3D() {
|
|
560
635
|
const root = this.root as Tile3D;
|
|
561
|
-
assert(root);
|
|
562
636
|
const {center} = root.boundingVolume;
|
|
563
637
|
// TODO - handle all cases
|
|
564
638
|
if (!center) {
|
|
565
|
-
// eslint-disable-next-line
|
|
639
|
+
// eslint-disable-next-line no-console
|
|
566
640
|
console.warn('center was not pre-calculated for the root tile');
|
|
567
641
|
this.cartographicCenter = new Vector3();
|
|
568
642
|
this.zoom = 1;
|
|
569
643
|
return;
|
|
570
644
|
}
|
|
571
|
-
|
|
645
|
+
|
|
646
|
+
// cartographic coordinates are undefined at the center of the ellipsoid
|
|
647
|
+
if (center[0] !== 0 || center[1] !== 0 || center[2] !== 0) {
|
|
648
|
+
this.cartographicCenter = Ellipsoid.WGS84.cartesianToCartographic(center, new Vector3());
|
|
649
|
+
} else {
|
|
650
|
+
this.cartographicCenter = new Vector3(0, 0, -Ellipsoid.WGS84.radii[0]);
|
|
651
|
+
}
|
|
572
652
|
this.cartesianCenter = center;
|
|
573
|
-
this.zoom = getZoomFromBoundingVolume(root.boundingVolume);
|
|
653
|
+
this.zoom = getZoomFromBoundingVolume(root.boundingVolume, this.cartographicCenter);
|
|
574
654
|
}
|
|
575
655
|
|
|
576
656
|
_initializeStats() {
|
|
@@ -582,13 +662,13 @@ export default class Tileset3D {
|
|
|
582
662
|
this.stats.get(TILES_LOADED);
|
|
583
663
|
this.stats.get(TILES_UNLOADED);
|
|
584
664
|
this.stats.get(TILES_LOAD_FAILED);
|
|
585
|
-
this.stats.get(POINTS_COUNT
|
|
665
|
+
this.stats.get(POINTS_COUNT);
|
|
586
666
|
this.stats.get(TILES_GPU_MEMORY, 'memory');
|
|
587
667
|
}
|
|
588
668
|
|
|
589
669
|
// Installs the main tileset JSON file or a tileset JSON file referenced from a tile.
|
|
590
670
|
// eslint-disable-next-line max-statements
|
|
591
|
-
_initializeTileHeaders(tilesetJson, parentTileHeader) {
|
|
671
|
+
_initializeTileHeaders(tilesetJson: TilesetJSON, parentTileHeader?: any) {
|
|
592
672
|
// A tileset JSON file referenced from a tile may exist in a different directory than the root tileset.
|
|
593
673
|
// Get the basePath relative to the external tileset.
|
|
594
674
|
const rootTile = new Tile3D(this, tilesetJson.root, parentTileHeader); // resource
|
|
@@ -600,7 +680,7 @@ export default class Tileset3D {
|
|
|
600
680
|
rootTile.depth = parentTileHeader.depth + 1;
|
|
601
681
|
}
|
|
602
682
|
|
|
603
|
-
//
|
|
683
|
+
// 3DTiles knows the hierarchy beforehand
|
|
604
684
|
if (this.type === TILESET_TYPE.TILES3D) {
|
|
605
685
|
const stack: Tile3D[] = [];
|
|
606
686
|
stack.push(rootTile);
|
|
@@ -611,6 +691,17 @@ export default class Tileset3D {
|
|
|
611
691
|
const children = tile.header.children || [];
|
|
612
692
|
for (const childHeader of children) {
|
|
613
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
|
+
|
|
614
705
|
tile.children.push(childTile);
|
|
615
706
|
childTile.depth = tile.depth + 1;
|
|
616
707
|
stack.push(childTile);
|
|
@@ -621,7 +712,7 @@ export default class Tileset3D {
|
|
|
621
712
|
return rootTile;
|
|
622
713
|
}
|
|
623
714
|
|
|
624
|
-
_initializeTraverser() {
|
|
715
|
+
_initializeTraverser(): TilesetTraverser {
|
|
625
716
|
let TraverserClass;
|
|
626
717
|
const type = this.type;
|
|
627
718
|
switch (type) {
|
|
@@ -629,7 +720,7 @@ export default class Tileset3D {
|
|
|
629
720
|
TraverserClass = Tileset3DTraverser;
|
|
630
721
|
break;
|
|
631
722
|
case TILESET_TYPE.I3S:
|
|
632
|
-
TraverserClass =
|
|
723
|
+
TraverserClass = I3STilesetTraverser;
|
|
633
724
|
break;
|
|
634
725
|
default:
|
|
635
726
|
TraverserClass = TilesetTraverser;
|
|
@@ -641,24 +732,24 @@ export default class Tileset3D {
|
|
|
641
732
|
});
|
|
642
733
|
}
|
|
643
734
|
|
|
644
|
-
_destroyTileHeaders(parentTile) {
|
|
735
|
+
_destroyTileHeaders(parentTile: Tile3D): void {
|
|
645
736
|
this._destroySubtree(parentTile);
|
|
646
737
|
}
|
|
647
738
|
|
|
648
|
-
async _loadTile(tile) {
|
|
739
|
+
async _loadTile(tile: Tile3D): Promise<void> {
|
|
649
740
|
let loaded;
|
|
650
741
|
try {
|
|
651
742
|
this._onStartTileLoading();
|
|
652
743
|
loaded = await tile.loadContent();
|
|
653
|
-
} catch (error) {
|
|
654
|
-
this._onTileLoadError(tile, error);
|
|
744
|
+
} catch (error: unknown) {
|
|
745
|
+
this._onTileLoadError(tile, error instanceof Error ? error : new Error('load failed'));
|
|
655
746
|
} finally {
|
|
656
747
|
this._onEndTileLoading();
|
|
657
748
|
this._onTileLoad(tile, loaded);
|
|
658
749
|
}
|
|
659
750
|
}
|
|
660
751
|
|
|
661
|
-
_onTileLoadError(tile, error) {
|
|
752
|
+
_onTileLoadError(tile: Tile3D, error: Error): void {
|
|
662
753
|
this.stats.get(TILES_LOAD_FAILED).incrementCount();
|
|
663
754
|
|
|
664
755
|
const message = error.message || error.toString();
|
|
@@ -668,20 +759,60 @@ export default class Tileset3D {
|
|
|
668
759
|
this.options.onTileError(tile, message, url);
|
|
669
760
|
}
|
|
670
761
|
|
|
671
|
-
_onTileLoad(tile, loaded) {
|
|
762
|
+
_onTileLoad(tile: Tile3D, loaded: boolean): void {
|
|
672
763
|
if (!loaded) {
|
|
673
764
|
return;
|
|
674
765
|
}
|
|
675
766
|
|
|
767
|
+
if (this.type === TILESET_TYPE.I3S) {
|
|
768
|
+
// We can't calculate tiles total in I3S in advance so we calculate it dynamically.
|
|
769
|
+
const nodesInNodePages = this.tileset?.nodePagesTile?.nodesInNodePages || 0;
|
|
770
|
+
this.stats.get(TILES_TOTAL).reset();
|
|
771
|
+
this.stats.get(TILES_TOTAL).addCount(nodesInNodePages);
|
|
772
|
+
}
|
|
773
|
+
|
|
676
774
|
// add coordinateOrigin and modelMatrix to tile
|
|
677
775
|
if (tile && tile.content) {
|
|
678
776
|
calculateTransformProps(tile, tile.content);
|
|
679
777
|
}
|
|
680
778
|
|
|
779
|
+
this.updateContentTypes(tile);
|
|
681
780
|
this._addTileToCache(tile);
|
|
682
781
|
this.options.onTileLoad(tile);
|
|
683
782
|
}
|
|
684
783
|
|
|
784
|
+
/**
|
|
785
|
+
* Update information about data types in nested tiles
|
|
786
|
+
* @param tile instance of a nested Tile3D
|
|
787
|
+
*/
|
|
788
|
+
private updateContentTypes(tile: Tile3D) {
|
|
789
|
+
if (this.type === TILESET_TYPE.I3S) {
|
|
790
|
+
if (tile.header.isDracoGeometry) {
|
|
791
|
+
this.contentFormats.draco = true;
|
|
792
|
+
}
|
|
793
|
+
switch (tile.header.textureFormat) {
|
|
794
|
+
case 'dds':
|
|
795
|
+
this.contentFormats.dds = true;
|
|
796
|
+
break;
|
|
797
|
+
case 'ktx2':
|
|
798
|
+
this.contentFormats.ktx2 = true;
|
|
799
|
+
break;
|
|
800
|
+
default:
|
|
801
|
+
}
|
|
802
|
+
} else if (this.type === TILESET_TYPE.TILES3D) {
|
|
803
|
+
const {extensionsRemoved = []} = tile.content?.gltf || {};
|
|
804
|
+
if (extensionsRemoved.includes('KHR_draco_mesh_compression')) {
|
|
805
|
+
this.contentFormats.draco = true;
|
|
806
|
+
}
|
|
807
|
+
if (extensionsRemoved.includes('EXT_meshopt_compression')) {
|
|
808
|
+
this.contentFormats.meshopt = true;
|
|
809
|
+
}
|
|
810
|
+
if (extensionsRemoved.includes('KHR_texture_basisu')) {
|
|
811
|
+
this.contentFormats.ktx2 = true;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
685
816
|
_onStartTileLoading() {
|
|
686
817
|
this._pendingCount++;
|
|
687
818
|
this.stats.get(TILES_LOADING).incrementCount();
|
|
@@ -692,7 +823,7 @@ export default class Tileset3D {
|
|
|
692
823
|
this.stats.get(TILES_LOADING).decrementCount();
|
|
693
824
|
}
|
|
694
825
|
|
|
695
|
-
_addTileToCache(tile) {
|
|
826
|
+
_addTileToCache(tile: Tile3D) {
|
|
696
827
|
this._cache.add(this, tile, (tileset) => tileset._updateCacheStats(tile));
|
|
697
828
|
}
|
|
698
829
|
|
|
@@ -701,12 +832,12 @@ export default class Tileset3D {
|
|
|
701
832
|
this.stats.get(TILES_IN_MEMORY).incrementCount();
|
|
702
833
|
|
|
703
834
|
// Good enough? Just use the raw binary ArrayBuffer's byte length.
|
|
704
|
-
this.gpuMemoryUsageInBytes += tile.
|
|
835
|
+
this.gpuMemoryUsageInBytes += tile.gpuMemoryUsageInBytes || 0;
|
|
705
836
|
this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
|
|
706
837
|
}
|
|
707
838
|
|
|
708
839
|
_unloadTile(tile) {
|
|
709
|
-
this.gpuMemoryUsageInBytes -=
|
|
840
|
+
this.gpuMemoryUsageInBytes -= tile.gpuMemoryUsageInBytes || 0;
|
|
710
841
|
|
|
711
842
|
this.stats.get(TILES_IN_MEMORY).decrementCount();
|
|
712
843
|
this.stats.get(TILES_UNLOADED).incrementCount();
|
|
@@ -759,13 +890,23 @@ export default class Tileset3D {
|
|
|
759
890
|
tile.destroy();
|
|
760
891
|
}
|
|
761
892
|
|
|
762
|
-
|
|
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
|
+
|
|
763
900
|
this.asset = tilesetJson.asset;
|
|
764
901
|
if (!this.asset) {
|
|
765
902
|
throw new Error('Tileset must have an asset property.');
|
|
766
903
|
}
|
|
767
|
-
if (
|
|
768
|
-
|
|
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.');
|
|
769
910
|
}
|
|
770
911
|
|
|
771
912
|
// Note: `asset.tilesetVersion` is version of the tileset itself (not the version of the 3D TILES standard)
|
|
@@ -783,29 +924,15 @@ export default class Tileset3D {
|
|
|
783
924
|
// Gets the tileset's properties dictionary object, which contains metadata about per-feature properties.
|
|
784
925
|
this.properties = tilesetJson.properties;
|
|
785
926
|
this.geometricError = tilesetJson.geometricError;
|
|
786
|
-
this._extensionsUsed = tilesetJson.extensionsUsed;
|
|
927
|
+
this._extensionsUsed = tilesetJson.extensionsUsed || [];
|
|
787
928
|
// Returns the extras property at the top of the tileset JSON (application specific metadata).
|
|
788
929
|
this.extras = tilesetJson.extras;
|
|
789
930
|
}
|
|
790
931
|
|
|
791
932
|
_initializeI3STileset() {
|
|
933
|
+
// @ts-expect-error
|
|
792
934
|
if (this.loadOptions.i3s && 'token' in this.loadOptions.i3s) {
|
|
793
|
-
this._queryParams.token = this.loadOptions.i3s.token;
|
|
935
|
+
this._queryParams.token = this.loadOptions.i3s.token as string;
|
|
794
936
|
}
|
|
795
937
|
}
|
|
796
938
|
}
|
|
797
|
-
|
|
798
|
-
function getQueryParamString(queryParams): string {
|
|
799
|
-
const queryParamStrings: string[] = [];
|
|
800
|
-
for (const key of Object.keys(queryParams)) {
|
|
801
|
-
queryParamStrings.push(`${key}=${queryParams[key]}`);
|
|
802
|
-
}
|
|
803
|
-
switch (queryParamStrings.length) {
|
|
804
|
-
case 0:
|
|
805
|
-
return '';
|
|
806
|
-
case 1:
|
|
807
|
-
return `?${queryParamStrings[0]}`;
|
|
808
|
-
default:
|
|
809
|
-
return `?${queryParamStrings.join('&')}`;
|
|
810
|
-
}
|
|
811
|
-
}
|