@loaders.gl/tiles 5.0.0-alpha.1 → 5.0.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/LICENSE +14 -3
- package/README.md +26 -0
- package/dist/dist.dev.js +20271 -5055
- package/dist/dist.min.js +3 -1
- package/dist/index.cjs +7849 -2081
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +25 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/point-cloud/point-cloud-tile.d.ts.map +1 -1
- package/dist/point-cloud/point-cloud-tile.js +3 -0
- package/dist/point-cloud/point-cloud-tile.js.map +1 -1
- package/dist/point-cloud/point-cloud-tileset.d.ts +4 -0
- package/dist/point-cloud/point-cloud-tileset.d.ts.map +1 -1
- package/dist/point-cloud/point-cloud-tileset.js +54 -12
- package/dist/point-cloud/point-cloud-tileset.js.map +1 -1
- package/dist/point-cloud/types.d.ts +17 -0
- package/dist/point-cloud/types.d.ts.map +1 -1
- package/dist/point-cloud/types.js +3 -0
- package/dist/point-cloud/types.js.map +1 -1
- package/dist/raster-set.d.ts +48 -31
- package/dist/raster-set.d.ts.map +1 -1
- package/dist/raster-set.js +104 -24
- package/dist/raster-set.js.map +1 -1
- package/dist/spatial/format-spatial-reference.d.ts +68 -0
- package/dist/spatial/format-spatial-reference.d.ts.map +1 -0
- package/dist/spatial/format-spatial-reference.js +291 -0
- package/dist/spatial/format-spatial-reference.js.map +1 -0
- package/dist/spatial/get-spatial-coordinate-frame.d.ts +20 -0
- package/dist/spatial/get-spatial-coordinate-frame.d.ts.map +1 -0
- package/dist/spatial/get-spatial-coordinate-frame.js +139 -0
- package/dist/spatial/get-spatial-coordinate-frame.js.map +1 -0
- package/dist/spatial/i3s-elevation.d.ts +20 -0
- package/dist/spatial/i3s-elevation.d.ts.map +1 -0
- package/dist/spatial/i3s-elevation.js +90 -0
- package/dist/spatial/i3s-elevation.js.map +1 -0
- package/dist/spatial/i3s-spatial-transformer.d.ts +189 -0
- package/dist/spatial/i3s-spatial-transformer.d.ts.map +1 -0
- package/dist/spatial/i3s-spatial-transformer.js +686 -0
- package/dist/spatial/i3s-spatial-transformer.js.map +1 -0
- package/dist/spatial/normalize-crs-identifier.d.ts +15 -0
- package/dist/spatial/normalize-crs-identifier.d.ts.map +1 -0
- package/dist/spatial/normalize-crs-identifier.js +22 -0
- package/dist/spatial/normalize-crs-identifier.js.map +1 -0
- package/dist/spatial/spatial-coordinate-transformer.d.ts +52 -0
- package/dist/spatial/spatial-coordinate-transformer.d.ts.map +1 -0
- package/dist/spatial/spatial-coordinate-transformer.js +295 -0
- package/dist/spatial/spatial-coordinate-transformer.js.map +1 -0
- package/dist/spatial/spatial-resource-registry.d.ts +44 -0
- package/dist/spatial/spatial-resource-registry.d.ts.map +1 -0
- package/dist/spatial/spatial-resource-registry.js +67 -0
- package/dist/spatial/spatial-resource-registry.js.map +1 -0
- package/dist/spatial/spatial-types.d.ts +190 -0
- package/dist/spatial/spatial-types.d.ts.map +1 -0
- package/dist/spatial/spatial-types.js +192 -0
- package/dist/spatial/spatial-types.js.map +1 -0
- package/dist/spatial/tiles-3d-spatial-transformer.d.ts +32 -0
- package/dist/spatial/tiles-3d-spatial-transformer.d.ts.map +1 -0
- package/dist/spatial/tiles-3d-spatial-transformer.js +175 -0
- package/dist/spatial/tiles-3d-spatial-transformer.js.map +1 -0
- package/dist/tileset-2d/adapter.d.ts +2 -3
- package/dist/tileset-2d/adapter.d.ts.map +1 -1
- package/dist/tileset-2d/tileset-2d.d.ts +2 -3
- package/dist/tileset-2d/tileset-2d.d.ts.map +1 -1
- package/dist/tileset-2d/tileset-2d.js.map +1 -1
- package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts +3 -3
- package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts.map +1 -1
- package/dist/tileset-3d/common/indexed-archive-tileset-source.js +9 -4
- package/dist/tileset-3d/common/indexed-archive-tileset-source.js.map +1 -1
- package/dist/tileset-3d/common/tile-3d-contracts.d.ts +63 -0
- package/dist/tileset-3d/common/tile-3d-contracts.d.ts.map +1 -0
- package/dist/tileset-3d/common/tile-3d-contracts.js +51 -0
- package/dist/tileset-3d/common/tile-3d-contracts.js.map +1 -0
- package/dist/tileset-3d/common/tile-3d.d.ts +176 -5
- package/dist/tileset-3d/common/tile-3d.d.ts.map +1 -1
- package/dist/tileset-3d/common/tile-3d.js +523 -89
- package/dist/tileset-3d/common/tile-3d.js.map +1 -1
- package/dist/tileset-3d/common/tileset-3d.d.ts +192 -9
- package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-3d.js +303 -23
- package/dist/tileset-3d/common/tileset-3d.js.map +1 -1
- package/dist/tileset-3d/common/tileset-cache.d.ts +11 -1
- package/dist/tileset-3d/common/tileset-cache.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-cache.js +11 -3
- package/dist/tileset-3d/common/tileset-cache.js.map +1 -1
- package/dist/tileset-3d/common/tileset-content-traversal.d.ts +37 -0
- package/dist/tileset-3d/common/tileset-content-traversal.d.ts.map +1 -0
- package/dist/tileset-3d/common/tileset-content-traversal.js +80 -0
- package/dist/tileset-3d/common/tileset-content-traversal.js.map +1 -0
- package/dist/tileset-3d/common/tileset-observability.d.ts +60 -0
- package/dist/tileset-3d/common/tileset-observability.d.ts.map +1 -0
- package/dist/tileset-3d/common/tileset-observability.js +39 -0
- package/dist/tileset-3d/common/tileset-observability.js.map +1 -0
- package/dist/tileset-3d/common/tileset-source.d.ts +51 -9
- package/dist/tileset-3d/common/tileset-source.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-source.js.map +1 -1
- package/dist/tileset-3d/common/tileset-traverser.d.ts +33 -1
- package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -1
- package/dist/tileset-3d/common/tileset-traverser.js +59 -11
- package/dist/tileset-3d/common/tileset-traverser.js.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts +182 -0
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js +681 -0
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts +127 -6
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js +485 -27
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts +103 -0
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -1
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js +278 -0
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js +3 -0
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts +23 -6
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-source.js +176 -25
- package/dist/tileset-3d/format-i3s/i3s-source.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.js +3 -0
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.js.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.d.ts.map +1 -1
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js +4 -1
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js.map +1 -1
- package/dist/tileset-3d/helpers/3d-tiles-options.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/3d-tiles-options.js +3 -0
- package/dist/tileset-3d/helpers/3d-tiles-options.js.map +1 -1
- package/dist/tileset-3d/helpers/bounding-volume.d.ts +7 -3
- package/dist/tileset-3d/helpers/bounding-volume.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/bounding-volume.js +20 -91
- package/dist/tileset-3d/helpers/bounding-volume.js.map +1 -1
- package/dist/tileset-3d/helpers/frame-state.d.ts +67 -2
- package/dist/tileset-3d/helpers/frame-state.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/frame-state.js +92 -10
- package/dist/tileset-3d/helpers/frame-state.js.map +1 -1
- package/dist/tileset-3d/helpers/i3s-lod.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/i3s-lod.js +20 -8
- package/dist/tileset-3d/helpers/i3s-lod.js.map +1 -1
- package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts +17 -0
- package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts.map +1 -0
- package/dist/tileset-3d/helpers/s2-bounding-volume.js +20 -0
- package/dist/tileset-3d/helpers/s2-bounding-volume.js.map +1 -0
- package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts +61 -9
- package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts.map +1 -1
- package/dist/tileset-3d/helpers/tiles-3d-lod.js +198 -93
- package/dist/tileset-3d/helpers/tiles-3d-lod.js.map +1 -1
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.d.ts +134 -0
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.d.ts.map +1 -0
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.js +179 -0
- package/dist/tileset-3d/helpers/tiles-3d-request-priority.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/doubly-linked-list.d.ts.map +1 -1
- package/dist/utils/doubly-linked-list.js +1 -0
- package/dist/utils/doubly-linked-list.js.map +1 -1
- package/dist/utils/managed-array.d.ts.map +1 -1
- package/dist/utils/managed-array.js +1 -0
- package/dist/utils/managed-array.js.map +1 -1
- package/package.json +12 -10
- package/src/index.ts +78 -1
- package/src/point-cloud/point-cloud-tile.ts +4 -0
- package/src/point-cloud/point-cloud-tileset.ts +70 -12
- package/src/point-cloud/types.ts +21 -0
- package/src/raster-set.ts +197 -67
- package/src/spatial/format-spatial-reference.ts +385 -0
- package/src/spatial/get-spatial-coordinate-frame.ts +169 -0
- package/src/spatial/i3s-elevation.ts +96 -0
- package/src/spatial/i3s-spatial-transformer.ts +957 -0
- package/src/spatial/normalize-crs-identifier.ts +26 -0
- package/src/spatial/spatial-coordinate-transformer.ts +376 -0
- package/src/spatial/spatial-resource-registry.ts +79 -0
- package/src/spatial/spatial-types.ts +422 -0
- package/src/spatial/tiles-3d-spatial-transformer.ts +206 -0
- package/src/tileset-2d/adapter.ts +2 -3
- package/src/tileset-2d/tileset-2d.ts +2 -3
- package/src/tileset-3d/common/indexed-archive-tileset-source.ts +13 -13
- package/src/tileset-3d/common/tile-3d-contracts.ts +115 -0
- package/src/tileset-3d/common/tile-3d.ts +629 -98
- package/src/tileset-3d/common/tileset-3d.ts +459 -29
- package/src/tileset-3d/common/tileset-cache.ts +15 -7
- package/src/tileset-3d/common/tileset-content-traversal.ts +114 -0
- package/src/tileset-3d/common/tileset-observability.ts +100 -0
- package/src/tileset-3d/common/tileset-source.ts +63 -13
- package/src/tileset-3d/common/tileset-traverser.ts +71 -11
- package/src/tileset-3d/format-3d-tiles/implicit-tiling.ts +1059 -0
- package/src/tileset-3d/format-3d-tiles/tiles-3d-source.ts +674 -28
- package/src/tileset-3d/format-3d-tiles/tileset-3d-traverser.ts +316 -0
- package/src/tileset-3d/format-i3s/i3s-pending-tiles-register.ts +4 -0
- package/src/tileset-3d/format-i3s/i3s-source.ts +220 -29
- package/src/tileset-3d/format-i3s/i3s-tile-manager.ts +4 -0
- package/src/tileset-3d/format-i3s/i3s-tileset-traverser.ts +6 -1
- package/src/tileset-3d/helpers/3d-tiles-options.ts +4 -0
- package/src/tileset-3d/helpers/bounding-volume.ts +31 -114
- package/src/tileset-3d/helpers/frame-state.ts +152 -13
- package/src/tileset-3d/helpers/i3s-lod.ts +22 -8
- package/src/tileset-3d/helpers/s2-bounding-volume.ts +35 -0
- package/src/tileset-3d/helpers/tiles-3d-lod.ts +291 -112
- package/src/tileset-3d/helpers/tiles-3d-request-priority.ts +301 -0
- package/src/types.ts +11 -0
- package/src/utils/doubly-linked-list.ts +2 -0
- package/src/utils/managed-array.ts +2 -0
|
@@ -7,14 +7,26 @@
|
|
|
7
7
|
import {Matrix4, Vector3} from '@math.gl/core';
|
|
8
8
|
import {Ellipsoid} from '@math.gl/geospatial';
|
|
9
9
|
import {Stats} from '@probe.gl/stats';
|
|
10
|
-
import {RequestScheduler,
|
|
10
|
+
import {RequestScheduler, Loader, LoaderOptions} from '@loaders.gl/loader-utils';
|
|
11
11
|
import {TilesetCache} from './tileset-cache';
|
|
12
12
|
import {calculateTransformProps} from '../helpers/transform-utils';
|
|
13
|
-
import {
|
|
13
|
+
import {getFrameState, limitSelectedTiles, updateCameraMotionState} from '../helpers/frame-state';
|
|
14
|
+
import type {CameraMotionState, FrameState} from '../helpers/frame-state';
|
|
15
|
+
import {
|
|
16
|
+
calculateDynamicScreenSpaceErrorDensity,
|
|
17
|
+
updateRootTransformForDynamicScreenSpaceError
|
|
18
|
+
} from '../helpers/tiles-3d-lod';
|
|
19
|
+
import {interpolateLinearly} from '../helpers/tiles-3d-request-priority';
|
|
20
|
+
import type {FoveatedInterpolationCallback} from '../helpers/tiles-3d-request-priority';
|
|
14
21
|
|
|
15
22
|
import type {GeospatialViewport, Viewport} from '../../types';
|
|
16
23
|
import {Tile3D} from './tile-3d';
|
|
17
24
|
import {TILESET_TYPE} from '../../constants';
|
|
25
|
+
import type {TilesetSpatialOptions, TilesetSpatialReference} from '../../spatial/spatial-types';
|
|
26
|
+
import {
|
|
27
|
+
applyTilesetSpatialOptions,
|
|
28
|
+
createTilesetSpatialReference
|
|
29
|
+
} from '../../spatial/spatial-types';
|
|
18
30
|
|
|
19
31
|
import {TilesetTraverser} from './tileset-traverser';
|
|
20
32
|
import {
|
|
@@ -34,8 +46,18 @@ export type Tileset3DProps = {
|
|
|
34
46
|
loadOptions?: LoaderOptions;
|
|
35
47
|
loadTiles?: boolean;
|
|
36
48
|
basePath?: string;
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Soft target, in bytes, for cached tile content that is not required by the current frame.
|
|
51
|
+
* The listed default applies to 3D Tiles; I3S retains its existing 32 MiB default.
|
|
52
|
+
* @default 536870912
|
|
53
|
+
*/
|
|
54
|
+
cacheBytes?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Additional bytes that the current-frame working set may use before memory-adjusted SSE rises.
|
|
57
|
+
* The listed default applies to 3D Tiles; I3S retains its existing 1 MiB default.
|
|
58
|
+
* @default 536870912
|
|
59
|
+
*/
|
|
60
|
+
maximumCacheOverflowBytes?: number;
|
|
39
61
|
maximumTilesSelected?: number;
|
|
40
62
|
debounceTime?: number;
|
|
41
63
|
|
|
@@ -44,12 +66,64 @@ export type Tileset3DProps = {
|
|
|
44
66
|
|
|
45
67
|
ellipsoid?: object;
|
|
46
68
|
modelMatrix?: Matrix4;
|
|
69
|
+
/** Automatic CRS output options and expert source-metadata recovery overrides. */
|
|
70
|
+
spatial?: TilesetSpatialOptions;
|
|
47
71
|
|
|
48
72
|
maximumScreenSpaceError?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Enables replacement traversal that may skip hierarchy levels while retaining ready ancestors
|
|
75
|
+
* as coverage. This trades temporary overdraw for faster refinement on deep trees.
|
|
76
|
+
* @default false
|
|
77
|
+
*/
|
|
78
|
+
skipLevelOfDetail?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* SSE above which tiles remain part of the non-skipping base traversal.
|
|
81
|
+
* @default 1024
|
|
82
|
+
*/
|
|
83
|
+
baseScreenSpaceError?: number;
|
|
84
|
+
/**
|
|
85
|
+
* Required SSE reduction from the nearest requested or loaded ancestor before loading a tile.
|
|
86
|
+
* @default 16
|
|
87
|
+
*/
|
|
88
|
+
skipScreenSpaceErrorFactor?: number;
|
|
89
|
+
/**
|
|
90
|
+
* Minimum hierarchy levels between requested tiles during skip-LOD traversal.
|
|
91
|
+
* @default 1
|
|
92
|
+
*/
|
|
93
|
+
skipLevels?: number;
|
|
94
|
+
/**
|
|
95
|
+
* Requests only final tiles that meet the active SSE target when skip-LOD is enabled.
|
|
96
|
+
* @default false
|
|
97
|
+
*/
|
|
98
|
+
immediatelyLoadDesiredLevelOfDetail?: boolean;
|
|
99
|
+
/** Enables perspective dynamic SSE to reduce distant, horizon-facing refinement. */
|
|
100
|
+
dynamicScreenSpaceError?: boolean;
|
|
101
|
+
/** Base dynamic SSE fog density in inverse meters. */
|
|
102
|
+
dynamicScreenSpaceErrorDensity?: number;
|
|
103
|
+
/** Maximum dynamic SSE reduction in logical/CSS pixels. */
|
|
104
|
+
dynamicScreenSpaceErrorFactor?: number;
|
|
105
|
+
/** Fraction of tileset height at which dynamic SSE begins to fade, clamped to `[0, 1]`. */
|
|
106
|
+
dynamicScreenSpaceErrorHeightFalloff?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Enables adaptive LOD reduction when estimated tile memory exceeds the overflow ceiling.
|
|
109
|
+
* Defaults to `true` for 3D Tiles and retains the existing `false` default for I3S.
|
|
110
|
+
*/
|
|
49
111
|
memoryAdjustedScreenSpaceError?: boolean;
|
|
50
112
|
viewportTraversersMap?: any;
|
|
51
113
|
updateTransforms?: boolean;
|
|
52
114
|
viewDistanceScale?: number;
|
|
115
|
+
/** Reduced viewport-height fraction used to prioritize coarse initial coverage; `0` disables it. */
|
|
116
|
+
progressiveResolutionHeightFraction?: number;
|
|
117
|
+
/** Whether requests nearer the center of a perspective viewport receive higher priority. */
|
|
118
|
+
foveatedScreenSpaceError?: boolean;
|
|
119
|
+
/** Fraction of the perspective field of view that receives no foveated SSE relaxation. */
|
|
120
|
+
foveatedConeSize?: number;
|
|
121
|
+
/** Minimum logical-pixel SSE relaxation immediately outside the foveated cone. */
|
|
122
|
+
foveatedMinimumScreenSpaceErrorRelaxation?: number;
|
|
123
|
+
/** Function that increases SSE relaxation from the foveated cone toward the viewport edge. */
|
|
124
|
+
foveatedInterpolationCallback?: FoveatedInterpolationCallback;
|
|
125
|
+
/** Seconds peripheral requests may wait after the camera moves. */
|
|
126
|
+
foveatedTimeDelay?: number;
|
|
53
127
|
|
|
54
128
|
onTileLoad?: (tile: Tile3D) => any;
|
|
55
129
|
onTileUnload?: (tile: Tile3D) => any;
|
|
@@ -69,8 +143,10 @@ type Props = {
|
|
|
69
143
|
modelMatrix: Matrix4;
|
|
70
144
|
throttleRequests: boolean;
|
|
71
145
|
maxRequests: number;
|
|
72
|
-
|
|
73
|
-
|
|
146
|
+
/** Soft target, in bytes, for evictable cached tile content. */
|
|
147
|
+
cacheBytes: number;
|
|
148
|
+
/** Current-frame headroom, in bytes, before memory-adjusted SSE rises. */
|
|
149
|
+
maximumCacheOverflowBytes: number;
|
|
74
150
|
maximumTilesSelected: number;
|
|
75
151
|
debounceTime: number;
|
|
76
152
|
onTileLoad: (tile: Tile3D) => void;
|
|
@@ -81,6 +157,25 @@ type Props = {
|
|
|
81
157
|
onTraversalComplete: (selectedTiles: Tile3D[]) => Tile3D[];
|
|
82
158
|
onUpdate: () => void;
|
|
83
159
|
maximumScreenSpaceError: number;
|
|
160
|
+
/** Whether replacement traversal may skip levels while retaining ancestor coverage. */
|
|
161
|
+
skipLevelOfDetail: boolean;
|
|
162
|
+
/** SSE above which tiles remain part of the non-skipping base traversal. */
|
|
163
|
+
baseScreenSpaceError: number;
|
|
164
|
+
/** Required SSE reduction between requested skip-LOD tiles. */
|
|
165
|
+
skipScreenSpaceErrorFactor: number;
|
|
166
|
+
/** Minimum hierarchy levels between requested skip-LOD tiles. */
|
|
167
|
+
skipLevels: number;
|
|
168
|
+
/** Whether skip-LOD requests only the final desired tiles. */
|
|
169
|
+
immediatelyLoadDesiredLevelOfDetail: boolean;
|
|
170
|
+
/** Whether perspective dynamic SSE is enabled. */
|
|
171
|
+
dynamicScreenSpaceError: boolean;
|
|
172
|
+
/** Base dynamic SSE fog density in inverse meters. */
|
|
173
|
+
dynamicScreenSpaceErrorDensity: number;
|
|
174
|
+
/** Maximum dynamic SSE reduction in logical/CSS pixels. */
|
|
175
|
+
dynamicScreenSpaceErrorFactor: number;
|
|
176
|
+
/** Fraction of tileset height at which dynamic SSE begins to fade. */
|
|
177
|
+
dynamicScreenSpaceErrorHeightFalloff: number;
|
|
178
|
+
/** Whether cache pressure may adapt the active SSE threshold. */
|
|
84
179
|
memoryAdjustedScreenSpaceError: boolean;
|
|
85
180
|
viewportTraversersMap: Record<string, any> | null;
|
|
86
181
|
attributions: string[];
|
|
@@ -88,19 +183,83 @@ type Props = {
|
|
|
88
183
|
loadOptions: LoaderOptions;
|
|
89
184
|
updateTransforms: boolean;
|
|
90
185
|
viewDistanceScale: number;
|
|
186
|
+
/** Reduced viewport-height fraction used to prioritize coarse initial coverage. */
|
|
187
|
+
progressiveResolutionHeightFraction: number;
|
|
188
|
+
/** Whether perspective requests are prioritized around the viewport center. */
|
|
189
|
+
foveatedScreenSpaceError: boolean;
|
|
190
|
+
/** Fraction of the perspective field of view with no foveated SSE relaxation. */
|
|
191
|
+
foveatedConeSize: number;
|
|
192
|
+
/** Minimum logical-pixel SSE relaxation outside the foveated cone. */
|
|
193
|
+
foveatedMinimumScreenSpaceErrorRelaxation: number;
|
|
194
|
+
/** Function used to interpolate foveated SSE relaxation. */
|
|
195
|
+
foveatedInterpolationCallback: FoveatedInterpolationCallback;
|
|
196
|
+
/** Seconds eligible peripheral requests wait after camera movement. */
|
|
197
|
+
foveatedTimeDelay: number;
|
|
91
198
|
basePath: string;
|
|
92
199
|
contentLoader?: (tile: Tile3D) => Promise<void>;
|
|
93
200
|
i3s: Record<string, any>;
|
|
201
|
+
/** Automatic CRS output options and expert source-metadata recovery overrides. */
|
|
202
|
+
spatial: TilesetSpatialOptions;
|
|
94
203
|
};
|
|
95
204
|
|
|
205
|
+
const BYTES_PER_MEBIBYTE = 1024 * 1024;
|
|
206
|
+
const DEFAULT_CACHE_BYTES = 512 * BYTES_PER_MEBIBYTE;
|
|
207
|
+
const DEFAULT_MAXIMUM_CACHE_OVERFLOW_BYTES = 512 * BYTES_PER_MEBIBYTE;
|
|
208
|
+
const DEFAULT_I3S_CACHE_BYTES = 32 * BYTES_PER_MEBIBYTE;
|
|
209
|
+
const DEFAULT_I3S_MAXIMUM_CACHE_OVERFLOW_BYTES = BYTES_PER_MEBIBYTE;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Validates a byte-based tile-cache budget.
|
|
213
|
+
*
|
|
214
|
+
* Fractions are accepted because JavaScript memory estimates are numbers, but negative, infinite,
|
|
215
|
+
* and `NaN` values cannot define a stable cache threshold.
|
|
216
|
+
*
|
|
217
|
+
* @param value - Proposed cache budget in bytes.
|
|
218
|
+
* @param optionName - Public option name used in an actionable error message.
|
|
219
|
+
* @returns The validated byte budget.
|
|
220
|
+
*/
|
|
221
|
+
function validateCacheByteLength(value: number, optionName: string): number {
|
|
222
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
223
|
+
throw new Error(`${optionName} must be a finite number greater than or equal to 0`);
|
|
224
|
+
}
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Resolves the base cache target from the byte-native option or its fallback.
|
|
230
|
+
*
|
|
231
|
+
* @param options - Options that may contain a byte-native cache value.
|
|
232
|
+
* @param fallbackCacheBytes - Existing or default cache target in bytes.
|
|
233
|
+
* @returns The resolved and validated cache target in bytes.
|
|
234
|
+
*/
|
|
235
|
+
function resolveCacheBytes(options: Tileset3DProps, fallbackCacheBytes: number): number {
|
|
236
|
+
const cacheBytes = options.cacheBytes ?? fallbackCacheBytes;
|
|
237
|
+
return validateCacheByteLength(cacheBytes, 'cacheBytes');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Resolves cache overflow headroom from the byte-native option or its fallback.
|
|
242
|
+
*
|
|
243
|
+
* @param options - Options that may contain a byte-native overflow value.
|
|
244
|
+
* @param fallbackOverflowBytes - Existing or default overflow headroom in bytes.
|
|
245
|
+
* @returns The resolved and validated overflow headroom in bytes.
|
|
246
|
+
*/
|
|
247
|
+
function resolveMaximumCacheOverflowBytes(
|
|
248
|
+
options: Tileset3DProps,
|
|
249
|
+
fallbackOverflowBytes: number
|
|
250
|
+
): number {
|
|
251
|
+
const maximumCacheOverflowBytes = options.maximumCacheOverflowBytes ?? fallbackOverflowBytes;
|
|
252
|
+
return validateCacheByteLength(maximumCacheOverflowBytes, 'maximumCacheOverflowBytes');
|
|
253
|
+
}
|
|
254
|
+
|
|
96
255
|
const DEFAULT_PROPS: Props = {
|
|
97
256
|
description: '',
|
|
98
257
|
ellipsoid: Ellipsoid.WGS84,
|
|
99
258
|
modelMatrix: new Matrix4(),
|
|
100
259
|
throttleRequests: true,
|
|
101
260
|
maxRequests: 64,
|
|
102
|
-
|
|
103
|
-
|
|
261
|
+
cacheBytes: DEFAULT_CACHE_BYTES,
|
|
262
|
+
maximumCacheOverflowBytes: DEFAULT_MAXIMUM_CACHE_OVERFLOW_BYTES,
|
|
104
263
|
maximumTilesSelected: 0,
|
|
105
264
|
debounceTime: 0,
|
|
106
265
|
onTileLoad: () => {},
|
|
@@ -112,15 +271,31 @@ const DEFAULT_PROPS: Props = {
|
|
|
112
271
|
onUpdate: () => {},
|
|
113
272
|
contentLoader: undefined,
|
|
114
273
|
viewDistanceScale: 1.0,
|
|
274
|
+
progressiveResolutionHeightFraction: 0.3,
|
|
275
|
+
foveatedScreenSpaceError: true,
|
|
276
|
+
foveatedConeSize: 0.1,
|
|
277
|
+
foveatedMinimumScreenSpaceErrorRelaxation: 0,
|
|
278
|
+
foveatedInterpolationCallback: interpolateLinearly,
|
|
279
|
+
foveatedTimeDelay: 0.2,
|
|
115
280
|
maximumScreenSpaceError: 8,
|
|
116
|
-
|
|
281
|
+
skipLevelOfDetail: false,
|
|
282
|
+
baseScreenSpaceError: 1024,
|
|
283
|
+
skipScreenSpaceErrorFactor: 16,
|
|
284
|
+
skipLevels: 1,
|
|
285
|
+
immediatelyLoadDesiredLevelOfDetail: false,
|
|
286
|
+
dynamicScreenSpaceError: true,
|
|
287
|
+
dynamicScreenSpaceErrorDensity: 2.0e-4,
|
|
288
|
+
dynamicScreenSpaceErrorFactor: 24,
|
|
289
|
+
dynamicScreenSpaceErrorHeightFalloff: 0.25,
|
|
290
|
+
memoryAdjustedScreenSpaceError: true,
|
|
117
291
|
loadTiles: true,
|
|
118
292
|
updateTransforms: true,
|
|
119
293
|
viewportTraversersMap: null,
|
|
120
294
|
loadOptions: {fetch: {}},
|
|
121
295
|
attributions: [],
|
|
122
296
|
basePath: '',
|
|
123
|
-
i3s: {}
|
|
297
|
+
i3s: {},
|
|
298
|
+
spatial: {}
|
|
124
299
|
};
|
|
125
300
|
|
|
126
301
|
const TILES_TOTAL = 'Tiles In Tileset(s)';
|
|
@@ -148,7 +323,7 @@ export class Tileset3D {
|
|
|
148
323
|
|
|
149
324
|
type: TILESET_TYPE;
|
|
150
325
|
tileset: TilesetJSON | null;
|
|
151
|
-
loader:
|
|
326
|
+
loader: Loader;
|
|
152
327
|
url: string;
|
|
153
328
|
basePath: string;
|
|
154
329
|
modelMatrix: Matrix4;
|
|
@@ -159,6 +334,18 @@ export class Tileset3D {
|
|
|
159
334
|
root: Tile3D | null = null;
|
|
160
335
|
roots: Record<string, Tile3D> = {};
|
|
161
336
|
asset: Record<string, any> = {};
|
|
337
|
+
/** Inline metadata schema declared by the source tileset, when present. */
|
|
338
|
+
schema: Record<string, any> | null = null;
|
|
339
|
+
/** External metadata schema URI declared by the source tileset, when present. */
|
|
340
|
+
schemaUri: string | null = null;
|
|
341
|
+
/** Metadata groups declared by the source tileset, in source order. */
|
|
342
|
+
groups: Array<Record<string, any>> = [];
|
|
343
|
+
/** Tileset-wide metadata entity, preserved without property-table decoding. */
|
|
344
|
+
metadata: Record<string, any> | null = null;
|
|
345
|
+
/** Tileset statistics metadata, preserved for application-level inspection. */
|
|
346
|
+
statistics: unknown = null;
|
|
347
|
+
/** Normalized source and target coordinate reference system metadata. */
|
|
348
|
+
spatialReference: TilesetSpatialReference = createTilesetSpatialReference({});
|
|
162
349
|
|
|
163
350
|
description = '';
|
|
164
351
|
properties: any;
|
|
@@ -174,14 +361,16 @@ export class Tileset3D {
|
|
|
174
361
|
zoom = 1;
|
|
175
362
|
boundingVolume: any = null;
|
|
176
363
|
|
|
177
|
-
|
|
364
|
+
/** Effective dynamic SSE density calculated for the most recently traversed viewport. */
|
|
365
|
+
dynamicScreenSpaceErrorComputedDensity = 0;
|
|
178
366
|
|
|
179
|
-
|
|
367
|
+
/** Estimated bytes currently retained by loaded tile content. */
|
|
180
368
|
gpuMemoryUsageInBytes = 0;
|
|
369
|
+
/** Active SSE threshold after optional cache-pressure adjustment, in logical/CSS pixels. */
|
|
181
370
|
memoryAdjustedScreenSpaceError = 0.0;
|
|
182
371
|
|
|
183
|
-
private _cacheBytes =
|
|
184
|
-
private
|
|
372
|
+
private _cacheBytes = DEFAULT_CACHE_BYTES;
|
|
373
|
+
private _maximumCacheOverflowBytes = DEFAULT_MAXIMUM_CACHE_OVERFLOW_BYTES;
|
|
185
374
|
|
|
186
375
|
_frameNumber = 0;
|
|
187
376
|
private _tiles: Record<string, Tile3D> = {};
|
|
@@ -195,6 +384,10 @@ export class Tileset3D {
|
|
|
195
384
|
private _requestedTiles: Tile3D[] = [];
|
|
196
385
|
private _emptyTiles: Tile3D[] = [];
|
|
197
386
|
private frameStateData: any = {};
|
|
387
|
+
/** Last camera pose retained independently for each viewport. */
|
|
388
|
+
private _cameraMotionStates: Record<string, CameraMotionState> = {};
|
|
389
|
+
/** Pending traversal that releases requests after camera motion settles. */
|
|
390
|
+
private _deferredTraversalTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
198
391
|
|
|
199
392
|
_traverser: TilesetTraverser;
|
|
200
393
|
_cache = new TilesetCache();
|
|
@@ -210,12 +403,32 @@ export class Tileset3D {
|
|
|
210
403
|
* @param options Traversal and runtime options.
|
|
211
404
|
*/
|
|
212
405
|
constructor(source: Tileset3DSource, options?: Tileset3DProps) {
|
|
213
|
-
this.options = {...DEFAULT_PROPS, ...options};
|
|
214
|
-
this.loadOptions = this.options.loadOptions || {};
|
|
215
|
-
|
|
216
406
|
if (!isTileset3DSource(source)) {
|
|
217
407
|
throw new Error('Tileset3D requires a Tileset3DSource instance');
|
|
218
408
|
}
|
|
409
|
+
|
|
410
|
+
const suppliedOptions = options || {};
|
|
411
|
+
const usesTiles3DCacheDefaults = source.type === TILESET_TYPE.TILES3D;
|
|
412
|
+
const defaultCacheBytes = usesTiles3DCacheDefaults
|
|
413
|
+
? DEFAULT_PROPS.cacheBytes
|
|
414
|
+
: DEFAULT_I3S_CACHE_BYTES;
|
|
415
|
+
const defaultMaximumCacheOverflowBytes = usesTiles3DCacheDefaults
|
|
416
|
+
? DEFAULT_PROPS.maximumCacheOverflowBytes
|
|
417
|
+
: DEFAULT_I3S_MAXIMUM_CACHE_OVERFLOW_BYTES;
|
|
418
|
+
const cacheBytes = resolveCacheBytes(suppliedOptions, defaultCacheBytes);
|
|
419
|
+
const maximumCacheOverflowBytes = resolveMaximumCacheOverflowBytes(
|
|
420
|
+
suppliedOptions,
|
|
421
|
+
defaultMaximumCacheOverflowBytes
|
|
422
|
+
);
|
|
423
|
+
this.options = {
|
|
424
|
+
...DEFAULT_PROPS,
|
|
425
|
+
...suppliedOptions,
|
|
426
|
+
cacheBytes,
|
|
427
|
+
maximumCacheOverflowBytes,
|
|
428
|
+
memoryAdjustedScreenSpaceError:
|
|
429
|
+
suppliedOptions.memoryAdjustedScreenSpaceError ?? usesTiles3DCacheDefaults
|
|
430
|
+
};
|
|
431
|
+
this.loadOptions = this.options.loadOptions || {};
|
|
219
432
|
this.source = source;
|
|
220
433
|
|
|
221
434
|
this.tileset = null;
|
|
@@ -237,8 +450,15 @@ export class Tileset3D {
|
|
|
237
450
|
});
|
|
238
451
|
|
|
239
452
|
this.memoryAdjustedScreenSpaceError = this.options.maximumScreenSpaceError;
|
|
240
|
-
this._cacheBytes =
|
|
241
|
-
this.
|
|
453
|
+
this._cacheBytes = cacheBytes;
|
|
454
|
+
this._maximumCacheOverflowBytes = maximumCacheOverflowBytes;
|
|
455
|
+
const metadata = this._getSourceMetadata();
|
|
456
|
+
if (metadata) {
|
|
457
|
+
this.spatialReference = applyTilesetSpatialOptions(
|
|
458
|
+
metadata.spatialReference,
|
|
459
|
+
this.options.spatial
|
|
460
|
+
);
|
|
461
|
+
}
|
|
242
462
|
|
|
243
463
|
this.stats = new Stats({id: this.url});
|
|
244
464
|
this._initializeStats();
|
|
@@ -247,6 +467,8 @@ export class Tileset3D {
|
|
|
247
467
|
}
|
|
248
468
|
|
|
249
469
|
destroy(): void {
|
|
470
|
+
this._clearDeferredTraversal();
|
|
471
|
+
this.source.destroy?.();
|
|
250
472
|
this._destroy();
|
|
251
473
|
}
|
|
252
474
|
|
|
@@ -262,14 +484,84 @@ export class Tileset3D {
|
|
|
262
484
|
return this._frameNumber;
|
|
263
485
|
}
|
|
264
486
|
|
|
487
|
+
/**
|
|
488
|
+
* Returns the tiles requested during the most recent completed traversal.
|
|
489
|
+
*
|
|
490
|
+
* A defensive copy makes request ordering deterministic for diagnostics and prevents callers
|
|
491
|
+
* from mutating the scheduler's working set.
|
|
492
|
+
*/
|
|
493
|
+
get requestedTiles(): readonly Tile3D[] {
|
|
494
|
+
return this._requestedTiles.slice();
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Returns empty tiles considered during the most recent completed traversal.
|
|
499
|
+
*
|
|
500
|
+
* Empty tiles can still be useful hierarchy placeholders, but their IDs are included in
|
|
501
|
+
* observability snapshots so applications can distinguish traversal work from render content.
|
|
502
|
+
*/
|
|
503
|
+
get emptyTiles(): readonly Tile3D[] {
|
|
504
|
+
return this._emptyTiles.slice();
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Gets or sets the soft target, in bytes, for cached tile content not needed this frame.
|
|
509
|
+
*
|
|
510
|
+
* Current-frame tiles remain protected even when their estimated memory exceeds this target.
|
|
511
|
+
* Reducing the value makes unused least-recently-used tiles eligible for eviction on the next
|
|
512
|
+
* traversal.
|
|
513
|
+
* @default 536870912 for 3D Tiles; 33554432 for I3S
|
|
514
|
+
*/
|
|
515
|
+
get cacheBytes(): number {
|
|
516
|
+
return this._cacheBytes;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
set cacheBytes(value: number) {
|
|
520
|
+
this._cacheBytes = validateCacheByteLength(value, 'cacheBytes');
|
|
521
|
+
this.options.cacheBytes = this._cacheBytes;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Gets or sets the additional current-frame headroom, in bytes, before memory-adjusted SSE rises.
|
|
526
|
+
*
|
|
527
|
+
* The pressure ceiling is `cacheBytes + maximumCacheOverflowBytes`. This value does not change
|
|
528
|
+
* the base target used to evict tiles that were not touched in the current frame.
|
|
529
|
+
* @default 536870912 for 3D Tiles; 1048576 for I3S
|
|
530
|
+
*/
|
|
531
|
+
get maximumCacheOverflowBytes(): number {
|
|
532
|
+
return this._maximumCacheOverflowBytes;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
set maximumCacheOverflowBytes(value: number) {
|
|
536
|
+
this._maximumCacheOverflowBytes = validateCacheByteLength(value, 'maximumCacheOverflowBytes');
|
|
537
|
+
this.options.maximumCacheOverflowBytes = this._maximumCacheOverflowBytes;
|
|
538
|
+
}
|
|
539
|
+
|
|
265
540
|
get queryParams(): string {
|
|
266
541
|
const rootUrl = this.source.getTileUrl(this.url);
|
|
267
542
|
const queryIndex = rootUrl.indexOf('?');
|
|
268
543
|
return queryIndex >= 0 ? rootUrl.slice(queryIndex + 1) : '';
|
|
269
544
|
}
|
|
270
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Updates traversal and runtime options while retaining unspecified byte budgets.
|
|
548
|
+
*
|
|
549
|
+
* @param props - Partial runtime options to apply.
|
|
550
|
+
*/
|
|
271
551
|
setProps(props: Tileset3DProps): void {
|
|
272
|
-
|
|
552
|
+
const cacheBytes = resolveCacheBytes(props, this.cacheBytes);
|
|
553
|
+
const maximumCacheOverflowBytes = resolveMaximumCacheOverflowBytes(
|
|
554
|
+
props,
|
|
555
|
+
this.maximumCacheOverflowBytes
|
|
556
|
+
);
|
|
557
|
+
this.options = {
|
|
558
|
+
...this.options,
|
|
559
|
+
...props,
|
|
560
|
+
cacheBytes,
|
|
561
|
+
maximumCacheOverflowBytes
|
|
562
|
+
};
|
|
563
|
+
this._cacheBytes = cacheBytes;
|
|
564
|
+
this._maximumCacheOverflowBytes = maximumCacheOverflowBytes;
|
|
273
565
|
}
|
|
274
566
|
|
|
275
567
|
getTileUrl(tilePath: string): string {
|
|
@@ -312,13 +604,20 @@ export class Tileset3D {
|
|
|
312
604
|
return this.updatePromise;
|
|
313
605
|
}
|
|
314
606
|
|
|
607
|
+
/**
|
|
608
|
+
* Moves the active LOD threshold toward the configured SSE or away from cache pressure.
|
|
609
|
+
*
|
|
610
|
+
* Usage below {@link Tileset3D.cacheBytes} restores quality in two-percent steps. Usage above
|
|
611
|
+
* `cacheBytes + maximumCacheOverflowBytes` reduces refinement in two-percent steps. Values in
|
|
612
|
+
* the overflow window leave the threshold unchanged, preventing rapid load/evict oscillation.
|
|
613
|
+
*/
|
|
315
614
|
adjustScreenSpaceError(): void {
|
|
316
|
-
if (this.gpuMemoryUsageInBytes < this.
|
|
615
|
+
if (this.gpuMemoryUsageInBytes < this.cacheBytes) {
|
|
317
616
|
this.memoryAdjustedScreenSpaceError = Math.max(
|
|
318
617
|
this.memoryAdjustedScreenSpaceError / 1.02,
|
|
319
618
|
this.options.maximumScreenSpaceError
|
|
320
619
|
);
|
|
321
|
-
} else if (this.gpuMemoryUsageInBytes > this.
|
|
620
|
+
} else if (this.gpuMemoryUsageInBytes > this.cacheBytes + this.maximumCacheOverflowBytes) {
|
|
322
621
|
this.memoryAdjustedScreenSpaceError *= 1.02;
|
|
323
622
|
}
|
|
324
623
|
}
|
|
@@ -331,10 +630,20 @@ export class Tileset3D {
|
|
|
331
630
|
return;
|
|
332
631
|
}
|
|
333
632
|
const preparedViewports = viewports instanceof Array ? viewports : [viewports];
|
|
633
|
+
const activeViewportIds = new Set(preparedViewports.map(viewport => viewport.id));
|
|
634
|
+
// A viewport may be removed between frames. Discard its completed state before aggregating
|
|
635
|
+
// requested and selected tiles so observability reflects only the current traversal inputs.
|
|
636
|
+
for (const frameStateId of Object.keys(this.frameStateData)) {
|
|
637
|
+
if (!activeViewportIds.has(frameStateId)) {
|
|
638
|
+
delete this.frameStateData[frameStateId];
|
|
639
|
+
}
|
|
640
|
+
}
|
|
334
641
|
|
|
335
642
|
this._cache.reset();
|
|
336
643
|
this._frameNumber++;
|
|
337
644
|
this.traverseCounter = preparedViewports.length;
|
|
645
|
+
const currentTime = Date.now();
|
|
646
|
+
let minimumDeferredTraversalDelay = Number.POSITIVE_INFINITY;
|
|
338
647
|
const viewportsToTraverse: string[] = [];
|
|
339
648
|
for (const viewport of preparedViewports) {
|
|
340
649
|
const id = viewport.id;
|
|
@@ -355,7 +664,70 @@ export class Tileset3D {
|
|
|
355
664
|
continue;
|
|
356
665
|
}
|
|
357
666
|
const frameState = getFrameState(viewport as GeospatialViewport, this._frameNumber);
|
|
358
|
-
this.
|
|
667
|
+
const root = this.roots[id];
|
|
668
|
+
const cameraMotionUpdate = updateCameraMotionState(
|
|
669
|
+
this._cameraMotionStates[id],
|
|
670
|
+
frameState.camera.position,
|
|
671
|
+
frameState.camera.direction,
|
|
672
|
+
currentTime
|
|
673
|
+
);
|
|
674
|
+
this._cameraMotionStates[id] = cameraMotionUpdate.state;
|
|
675
|
+
frameState.camera.timeSinceMovement = cameraMotionUpdate.timeSinceMovement;
|
|
676
|
+
// Dynamic SSE reads the root's inverse computed transform before traversal updates tile
|
|
677
|
+
// visibility. Refresh it from the current tileset model matrix here so animated local
|
|
678
|
+
// box/sphere tilesets never calculate their height falloff one transform behind the frame.
|
|
679
|
+
updateRootTransformForDynamicScreenSpaceError(root, this.modelMatrix);
|
|
680
|
+
frameState.dynamicScreenSpaceErrorDensity =
|
|
681
|
+
this.type === TILESET_TYPE.TILES3D &&
|
|
682
|
+
this.options.dynamicScreenSpaceError &&
|
|
683
|
+
!frameState.viewport.orthographic
|
|
684
|
+
? calculateDynamicScreenSpaceErrorDensity(root, frameState, this.options)
|
|
685
|
+
: 0;
|
|
686
|
+
// Keep the legacy diagnostic field, but traversal reads the per-viewport frame value above.
|
|
687
|
+
this.dynamicScreenSpaceErrorComputedDensity = frameState.dynamicScreenSpaceErrorDensity;
|
|
688
|
+
this._traverser.traverse(root, frameState, this.options);
|
|
689
|
+
if (Object.keys(this._traverser.deferredTiles).length > 0) {
|
|
690
|
+
minimumDeferredTraversalDelay = Math.min(
|
|
691
|
+
minimumDeferredTraversalDelay,
|
|
692
|
+
Math.max(this.options.foveatedTimeDelay - cameraMotionUpdate.timeSinceMovement, 0)
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
if (Number.isFinite(minimumDeferredTraversalDelay)) {
|
|
698
|
+
this._scheduleDeferredTraversal(minimumDeferredTraversalDelay);
|
|
699
|
+
} else {
|
|
700
|
+
this._clearDeferredTraversal();
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Schedules one follow-up traversal when the moving-camera deferral window expires.
|
|
706
|
+
*
|
|
707
|
+
* Replacing an existing timer ensures continuing camera movement pushes the retry window forward
|
|
708
|
+
* instead of creating a queue of redundant traversals.
|
|
709
|
+
*
|
|
710
|
+
* @param delayInSeconds - Remaining stationary delay before deferred requests become eligible.
|
|
711
|
+
*/
|
|
712
|
+
private _scheduleDeferredTraversal(delayInSeconds: number): void {
|
|
713
|
+
this._clearDeferredTraversal();
|
|
714
|
+
this._deferredTraversalTimeout = setTimeout(
|
|
715
|
+
() => {
|
|
716
|
+
this._deferredTraversalTimeout = null;
|
|
717
|
+
this.selectTiles().catch((error: unknown) => {
|
|
718
|
+
const traversalError = error instanceof Error ? error : new Error(String(error));
|
|
719
|
+
this._onTilesetError(traversalError);
|
|
720
|
+
});
|
|
721
|
+
},
|
|
722
|
+
Math.max(delayInSeconds * 1000, 0)
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/** Clears a pending moving-camera follow-up traversal. */
|
|
727
|
+
private _clearDeferredTraversal(): void {
|
|
728
|
+
if (this._deferredTraversalTimeout !== null) {
|
|
729
|
+
clearTimeout(this._deferredTraversalTimeout);
|
|
730
|
+
this._deferredTraversalTimeout = null;
|
|
359
731
|
}
|
|
360
732
|
}
|
|
361
733
|
|
|
@@ -475,6 +847,9 @@ export class Tileset3D {
|
|
|
475
847
|
|
|
476
848
|
_unloadTiles(): void {
|
|
477
849
|
this._cache.unloadTiles(this, (tileset, tile) => tileset._unloadTile(tile));
|
|
850
|
+
if (this.options.memoryAdjustedScreenSpaceError) {
|
|
851
|
+
this.adjustScreenSpaceError();
|
|
852
|
+
}
|
|
478
853
|
}
|
|
479
854
|
|
|
480
855
|
_updateStats(): void {
|
|
@@ -483,10 +858,13 @@ export class Tileset3D {
|
|
|
483
858
|
for (const tile of this.selectedTiles) {
|
|
484
859
|
if (tile.contentAvailable && tile.content) {
|
|
485
860
|
tilesRenderable++;
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
861
|
+
const contents = tile.contents.length ? tile.contents : [tile.content];
|
|
862
|
+
for (const content of contents) {
|
|
863
|
+
if (content.pointCount) {
|
|
864
|
+
pointsRenderable += content.pointCount;
|
|
865
|
+
} else {
|
|
866
|
+
pointsRenderable += content.vertexCount || 0;
|
|
867
|
+
}
|
|
490
868
|
}
|
|
491
869
|
}
|
|
492
870
|
}
|
|
@@ -506,7 +884,8 @@ export class Tileset3D {
|
|
|
506
884
|
}
|
|
507
885
|
if (
|
|
508
886
|
initialMetadata?.tileset?.root &&
|
|
509
|
-
typeof initialMetadata.tileset.root.then !== 'function'
|
|
887
|
+
typeof initialMetadata.tileset.root.then !== 'function' &&
|
|
888
|
+
(!this.source.prepareTileset || this.spatialReference?.status === 'native')
|
|
510
889
|
) {
|
|
511
890
|
this.root = this._initializeTileHeaders(initialMetadata.tileset, null);
|
|
512
891
|
this._applyViewState();
|
|
@@ -515,6 +894,7 @@ export class Tileset3D {
|
|
|
515
894
|
await initializePromise;
|
|
516
895
|
const metadata = this.source.getMetadata();
|
|
517
896
|
this._syncSourceState(metadata);
|
|
897
|
+
await this.source.prepareTileset?.(this);
|
|
518
898
|
if (!this.root) {
|
|
519
899
|
this.root = this._initializeTileHeaders(metadata.tileset, null);
|
|
520
900
|
}
|
|
@@ -571,6 +951,28 @@ export class Tileset3D {
|
|
|
571
951
|
}
|
|
572
952
|
}
|
|
573
953
|
|
|
954
|
+
/**
|
|
955
|
+
* Loads a source-managed lazy child-header group and reports failures through tile callbacks.
|
|
956
|
+
*
|
|
957
|
+
* Subtree metadata shares the normal loading counters but is not reported as render content and
|
|
958
|
+
* is not added to the GPU cache. Traversal is notified separately after the promise settles.
|
|
959
|
+
*
|
|
960
|
+
* @param tile - Runtime tile that owns the lazy subtree reference.
|
|
961
|
+
* @param frameState - View state that made the subtree eligible for refinement.
|
|
962
|
+
*/
|
|
963
|
+
async _loadTileChildren(tile: Tile3D, frameState: FrameState): Promise<void> {
|
|
964
|
+
try {
|
|
965
|
+
this._onStartTileLoading();
|
|
966
|
+
await tile.loadChildren(frameState);
|
|
967
|
+
} catch (error: unknown) {
|
|
968
|
+
const tileError = error instanceof Error ? error : new Error('subtree load failed');
|
|
969
|
+
this._onSourceError(tileError, tile);
|
|
970
|
+
this._onTileLoadError(tile, tileError);
|
|
971
|
+
} finally {
|
|
972
|
+
this._onEndTileLoading();
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
574
976
|
_onTileLoadError(tile: Tile3D, error: Error): void {
|
|
575
977
|
this.stats.get(TILES_LOAD_FAILED).incrementCount();
|
|
576
978
|
|
|
@@ -698,6 +1100,20 @@ export class Tileset3D {
|
|
|
698
1100
|
this.refine = metadata.refine;
|
|
699
1101
|
this.contentFormats = this.source.contentFormats;
|
|
700
1102
|
this.asset = this.source.asset || this.asset;
|
|
1103
|
+
const tileset = metadata.tileset as Record<string, any>;
|
|
1104
|
+
this.schema = tileset.schema || null;
|
|
1105
|
+
this.schemaUri = tileset.schemaUri || null;
|
|
1106
|
+
this.groups = tileset.groups || [];
|
|
1107
|
+
this.metadata = tileset.metadata || null;
|
|
1108
|
+
this.statistics = tileset.statistics ?? null;
|
|
1109
|
+
const spatialReference = applyTilesetSpatialOptions(
|
|
1110
|
+
metadata.spatialReference,
|
|
1111
|
+
this.options.spatial
|
|
1112
|
+
);
|
|
1113
|
+
this.spatialReference = preserveTransformedSpatialReference(
|
|
1114
|
+
this.spatialReference,
|
|
1115
|
+
spatialReference
|
|
1116
|
+
);
|
|
701
1117
|
this.properties = this.source.properties ?? this.properties;
|
|
702
1118
|
this.extras = this.source.extras ?? this.extras;
|
|
703
1119
|
if (this.options.attributions?.length) {
|
|
@@ -734,3 +1150,17 @@ export class Tileset3D {
|
|
|
734
1150
|
}
|
|
735
1151
|
}
|
|
736
1152
|
}
|
|
1153
|
+
|
|
1154
|
+
/** Preserve a completed runtime operation when asynchronous source metadata describes the same request. */
|
|
1155
|
+
function preserveTransformedSpatialReference(
|
|
1156
|
+
current: TilesetSpatialReference,
|
|
1157
|
+
next: TilesetSpatialReference
|
|
1158
|
+
): TilesetSpatialReference {
|
|
1159
|
+
return current?.status === 'transformed' &&
|
|
1160
|
+
current.sourceCrs === next.sourceCrs &&
|
|
1161
|
+
current.targetCrs === next.targetCrs &&
|
|
1162
|
+
current.targetHeightReference === next.targetHeightReference &&
|
|
1163
|
+
current.outputCoordinates === next.outputCoordinates
|
|
1164
|
+
? current
|
|
1165
|
+
: next;
|
|
1166
|
+
}
|