@loaders.gl/tiles 4.4.5 → 5.0.0-alpha.2
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 +110 -1
- package/dist/dist.dev.js +6588 -2057
- package/dist/dist.min.js +1 -1
- package/dist/image-set.d.ts +94 -0
- package/dist/image-set.d.ts.map +1 -0
- package/dist/image-set.js +243 -0
- package/dist/image-set.js.map +1 -0
- package/dist/index.cjs +6872 -2160
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +33 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -8
- package/dist/index.js.map +1 -1
- package/dist/point-cloud/point-cloud-tile.d.ts +47 -0
- package/dist/point-cloud/point-cloud-tile.d.ts.map +1 -0
- package/dist/point-cloud/point-cloud-tile.js +70 -0
- package/dist/point-cloud/point-cloud-tile.js.map +1 -0
- package/dist/point-cloud/point-cloud-tileset.d.ts +131 -0
- package/dist/point-cloud/point-cloud-tileset.d.ts.map +1 -0
- package/dist/point-cloud/point-cloud-tileset.js +510 -0
- package/dist/point-cloud/point-cloud-tileset.js.map +1 -0
- package/dist/point-cloud/types.d.ts +64 -0
- package/dist/point-cloud/types.d.ts.map +1 -0
- package/dist/point-cloud/types.js +5 -0
- package/dist/point-cloud/types.js.map +1 -0
- package/dist/raster-set.d.ts +113 -0
- package/dist/raster-set.d.ts.map +1 -0
- package/dist/raster-set.js +274 -0
- package/dist/raster-set.js.map +1 -0
- package/dist/tileset-2d/adapter.d.ts +38 -0
- package/dist/tileset-2d/adapter.d.ts.map +1 -0
- package/dist/tileset-2d/adapter.js +5 -0
- package/dist/tileset-2d/adapter.js.map +1 -0
- package/dist/tileset-2d/index.d.ts +7 -0
- package/dist/tileset-2d/index.d.ts.map +1 -0
- package/dist/tileset-2d/index.js +6 -0
- package/dist/tileset-2d/index.js.map +1 -0
- package/dist/tileset-2d/tile-2d-header.d.ts +68 -0
- package/dist/tileset-2d/tile-2d-header.d.ts.map +1 -0
- package/dist/tileset-2d/tile-2d-header.js +181 -0
- package/dist/tileset-2d/tile-2d-header.js.map +1 -0
- package/dist/tileset-2d/tileset-2d.d.ts +201 -0
- package/dist/tileset-2d/tileset-2d.d.ts.map +1 -0
- package/dist/tileset-2d/tileset-2d.js +532 -0
- package/dist/tileset-2d/tileset-2d.js.map +1 -0
- package/dist/tileset-2d/types.d.ts +44 -0
- package/dist/tileset-2d/types.d.ts.map +1 -0
- package/dist/tileset-2d/types.js +5 -0
- package/dist/tileset-2d/types.js.map +1 -0
- package/dist/tileset-2d.d.ts +2 -0
- package/dist/tileset-2d.d.ts.map +1 -0
- package/dist/tileset-2d.js +5 -0
- package/dist/tileset-2d.js.map +1 -0
- package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts +60 -0
- package/dist/tileset-3d/common/indexed-archive-tileset-source.d.ts.map +1 -0
- package/dist/tileset-3d/common/indexed-archive-tileset-source.js +125 -0
- package/dist/tileset-3d/common/indexed-archive-tileset-source.js.map +1 -0
- package/dist/{tileset → tileset-3d/common}/tile-3d.d.ts +133 -29
- package/dist/tileset-3d/common/tile-3d.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d/common}/tile-3d.js +282 -77
- package/dist/tileset-3d/common/tile-3d.js.map +1 -0
- package/dist/tileset-3d/common/tileset-3d.d.ts +317 -0
- package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -0
- package/dist/tileset-3d/common/tileset-3d.js +807 -0
- package/dist/tileset-3d/common/tileset-3d.js.map +1 -0
- package/dist/tileset-3d/common/tileset-cache.d.ts +29 -0
- package/dist/tileset-3d/common/tileset-cache.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d/common}/tileset-cache.js +12 -4
- package/dist/tileset-3d/common/tileset-cache.js.map +1 -0
- package/dist/tileset-3d/common/tileset-source.d.ts +204 -0
- package/dist/tileset-3d/common/tileset-source.d.ts.map +1 -0
- package/dist/tileset-3d/common/tileset-source.js +17 -0
- package/dist/tileset-3d/common/tileset-source.js.map +1 -0
- package/dist/{tileset → tileset-3d/common}/tileset-traverser.d.ts +15 -2
- package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d/common}/tileset-traverser.js +30 -3
- package/dist/tileset-3d/common/tileset-traverser.js.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts +111 -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 +340 -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 +189 -0
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.d.ts.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js +510 -0
- package/dist/tileset-3d/format-3d-tiles/tiles-3d-source.js.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts +43 -0
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -0
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js +119 -0
- package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -0
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d}/format-i3s/i3s-pending-tiles-register.js +3 -0
- package/dist/tileset-3d/format-i3s/i3s-pending-tiles-register.js.map +1 -0
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts +99 -0
- package/dist/tileset-3d/format-i3s/i3s-source.d.ts.map +1 -0
- package/dist/tileset-3d/format-i3s/i3s-source.js +299 -0
- package/dist/tileset-3d/format-i3s/i3s-source.js.map +1 -0
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d}/format-i3s/i3s-tile-manager.js +5 -2
- package/dist/tileset-3d/format-i3s/i3s-tile-manager.js.map +1 -0
- package/dist/{tileset → tileset-3d}/format-i3s/i3s-tileset-traverser.d.ts +2 -2
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d}/format-i3s/i3s-tileset-traverser.js +17 -23
- package/dist/tileset-3d/format-i3s/i3s-tileset-traverser.js.map +1 -0
- package/dist/{tileset → tileset-3d}/helpers/3d-tiles-options.d.ts +1 -1
- package/dist/tileset-3d/helpers/3d-tiles-options.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d}/helpers/3d-tiles-options.js +3 -0
- package/dist/tileset-3d/helpers/3d-tiles-options.js.map +1 -0
- package/dist/tileset-3d/helpers/bounding-volume.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d}/helpers/bounding-volume.js +1 -0
- package/dist/tileset-3d/helpers/bounding-volume.js.map +1 -0
- package/dist/tileset-3d/helpers/frame-state.d.ts +86 -0
- package/dist/tileset-3d/helpers/frame-state.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d}/helpers/frame-state.js +84 -9
- package/dist/tileset-3d/helpers/frame-state.js.map +1 -0
- package/dist/{tileset → tileset-3d}/helpers/i3s-lod.d.ts +1 -1
- package/dist/tileset-3d/helpers/i3s-lod.d.ts.map +1 -0
- package/dist/{tileset → tileset-3d}/helpers/i3s-lod.js +1 -1
- package/dist/tileset-3d/helpers/i3s-lod.js.map +1 -0
- package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts +72 -0
- package/dist/tileset-3d/helpers/tiles-3d-lod.d.ts.map +1 -0
- package/dist/tileset-3d/helpers/tiles-3d-lod.js +257 -0
- package/dist/tileset-3d/helpers/tiles-3d-lod.js.map +1 -0
- 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/{tileset → tileset-3d}/helpers/transform-utils.d.ts +1 -1
- package/dist/tileset-3d/helpers/transform-utils.d.ts.map +1 -0
- package/dist/tileset-3d/helpers/transform-utils.js.map +1 -0
- package/dist/tileset-3d/helpers/zoom.d.ts.map +1 -0
- package/dist/tileset-3d/helpers/zoom.js.map +1 -0
- package/dist/types.d.ts +9 -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 +7 -6
- package/src/image-set.ts +328 -0
- package/src/index.ts +99 -9
- package/src/point-cloud/point-cloud-tile.ts +80 -0
- package/src/point-cloud/point-cloud-tileset.ts +713 -0
- package/src/point-cloud/types.ts +82 -0
- package/src/raster-set.ts +412 -0
- package/src/tileset-2d/adapter.ts +47 -0
- package/src/tileset-2d/index.ts +33 -0
- package/src/tileset-2d/tile-2d-header.ts +224 -0
- package/src/tileset-2d/tileset-2d.ts +716 -0
- package/src/tileset-2d/types.ts +39 -0
- package/src/tileset-2d.ts +5 -0
- package/src/tileset-3d/common/indexed-archive-tileset-source.ts +205 -0
- package/src/{tileset → tileset-3d/common}/tile-3d.ts +348 -93
- package/src/tileset-3d/common/tileset-3d.ts +1087 -0
- package/src/{tileset → tileset-3d/common}/tileset-cache.ts +16 -8
- package/src/tileset-3d/common/tileset-source.ts +255 -0
- package/src/{tileset → tileset-3d/common}/tileset-traverser.ts +32 -4
- package/src/tileset-3d/format-3d-tiles/implicit-tiling.ts +534 -0
- package/src/tileset-3d/format-3d-tiles/tiles-3d-source.ts +632 -0
- package/src/tileset-3d/format-3d-tiles/tileset-3d-traverser.ts +140 -0
- package/src/{tileset → tileset-3d}/format-i3s/i3s-pending-tiles-register.ts +4 -0
- package/src/tileset-3d/format-i3s/i3s-source.ts +366 -0
- package/src/{tileset → tileset-3d}/format-i3s/i3s-tile-manager.ts +6 -2
- package/src/{tileset → tileset-3d}/format-i3s/i3s-tileset-traverser.ts +19 -24
- package/src/{tileset → tileset-3d}/helpers/3d-tiles-options.ts +5 -1
- package/src/{tileset → tileset-3d}/helpers/bounding-volume.ts +2 -0
- package/src/tileset-3d/helpers/frame-state.ts +311 -0
- package/src/{tileset → tileset-3d}/helpers/i3s-lod.ts +2 -2
- package/src/tileset-3d/helpers/tiles-3d-lod.ts +370 -0
- package/src/tileset-3d/helpers/tiles-3d-request-priority.ts +301 -0
- package/src/{tileset → tileset-3d}/helpers/transform-utils.ts +1 -1
- package/src/types.ts +13 -0
- package/src/utils/doubly-linked-list.ts +2 -0
- package/src/utils/managed-array.ts +2 -0
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.d.ts +0 -7
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.d.ts.map +0 -1
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.js +0 -53
- package/dist/tileset/format-3d-tiles/tileset-3d-traverser.js.map +0 -1
- package/dist/tileset/format-i3s/i3s-pending-tiles-register.d.ts.map +0 -1
- package/dist/tileset/format-i3s/i3s-pending-tiles-register.js.map +0 -1
- package/dist/tileset/format-i3s/i3s-tile-manager.d.ts.map +0 -1
- package/dist/tileset/format-i3s/i3s-tile-manager.js.map +0 -1
- package/dist/tileset/format-i3s/i3s-tileset-traverser.d.ts.map +0 -1
- package/dist/tileset/format-i3s/i3s-tileset-traverser.js.map +0 -1
- package/dist/tileset/helpers/3d-tiles-options.d.ts.map +0 -1
- package/dist/tileset/helpers/3d-tiles-options.js.map +0 -1
- package/dist/tileset/helpers/bounding-volume.d.ts.map +0 -1
- package/dist/tileset/helpers/bounding-volume.js.map +0 -1
- package/dist/tileset/helpers/frame-state.d.ts +0 -28
- package/dist/tileset/helpers/frame-state.d.ts.map +0 -1
- package/dist/tileset/helpers/frame-state.js.map +0 -1
- package/dist/tileset/helpers/i3s-lod.d.ts.map +0 -1
- package/dist/tileset/helpers/i3s-lod.js.map +0 -1
- package/dist/tileset/helpers/tiles-3d-lod.d.ts +0 -8
- package/dist/tileset/helpers/tiles-3d-lod.d.ts.map +0 -1
- package/dist/tileset/helpers/tiles-3d-lod.js +0 -113
- package/dist/tileset/helpers/tiles-3d-lod.js.map +0 -1
- package/dist/tileset/helpers/transform-utils.d.ts.map +0 -1
- package/dist/tileset/helpers/transform-utils.js.map +0 -1
- package/dist/tileset/helpers/zoom.d.ts.map +0 -1
- package/dist/tileset/helpers/zoom.js.map +0 -1
- package/dist/tileset/tile-3d.d.ts.map +0 -1
- package/dist/tileset/tile-3d.js.map +0 -1
- package/dist/tileset/tileset-3d.d.ts +0 -284
- package/dist/tileset/tileset-3d.d.ts.map +0 -1
- package/dist/tileset/tileset-3d.js +0 -814
- package/dist/tileset/tileset-3d.js.map +0 -1
- package/dist/tileset/tileset-cache.d.ts +0 -19
- package/dist/tileset/tileset-cache.d.ts.map +0 -1
- package/dist/tileset/tileset-cache.js.map +0 -1
- package/dist/tileset/tileset-traverser.d.ts.map +0 -1
- package/dist/tileset/tileset-traverser.js.map +0 -1
- package/src/tileset/format-3d-tiles/tileset-3d-traverser.ts +0 -63
- package/src/tileset/helpers/frame-state.ts +0 -183
- package/src/tileset/helpers/tiles-3d-lod.ts +0 -149
- package/src/tileset/tileset-3d.ts +0 -1037
- /package/dist/{tileset → tileset-3d}/format-i3s/i3s-pending-tiles-register.d.ts +0 -0
- /package/dist/{tileset → tileset-3d}/format-i3s/i3s-tile-manager.d.ts +0 -0
- /package/dist/{tileset → tileset-3d}/helpers/bounding-volume.d.ts +0 -0
- /package/dist/{tileset → tileset-3d}/helpers/transform-utils.js +0 -0
- /package/dist/{tileset → tileset-3d}/helpers/zoom.d.ts +0 -0
- /package/dist/{tileset → tileset-3d}/helpers/zoom.js +0 -0
- /package/src/{tileset → tileset-3d}/helpers/zoom.ts +0 -0
|
@@ -0,0 +1,807 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) vis.gl contributors
|
|
3
|
+
// This file is derived from the Cesium code base under Apache 2 license
|
|
4
|
+
// See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md
|
|
5
|
+
import { Matrix4, Vector3 } from '@math.gl/core';
|
|
6
|
+
import { Ellipsoid } from '@math.gl/geospatial';
|
|
7
|
+
import { Stats } from '@probe.gl/stats';
|
|
8
|
+
import { RequestScheduler } from '@loaders.gl/loader-utils';
|
|
9
|
+
import { TilesetCache } from "./tileset-cache.js";
|
|
10
|
+
import { calculateTransformProps } from "../helpers/transform-utils.js";
|
|
11
|
+
import { getFrameState, limitSelectedTiles, updateCameraMotionState } from "../helpers/frame-state.js";
|
|
12
|
+
import { calculateDynamicScreenSpaceErrorDensity, updateRootTransformForDynamicScreenSpaceError } from "../helpers/tiles-3d-lod.js";
|
|
13
|
+
import { interpolateLinearly } from "../helpers/tiles-3d-request-priority.js";
|
|
14
|
+
import { TILESET_TYPE } from "../../constants.js";
|
|
15
|
+
import { isTileset3DSource } from "./tileset-source.js";
|
|
16
|
+
const BYTES_PER_MEBIBYTE = 1024 * 1024;
|
|
17
|
+
const DEFAULT_CACHE_BYTES = 512 * BYTES_PER_MEBIBYTE;
|
|
18
|
+
const DEFAULT_MAXIMUM_CACHE_OVERFLOW_BYTES = 512 * BYTES_PER_MEBIBYTE;
|
|
19
|
+
const DEFAULT_I3S_CACHE_BYTES = 32 * BYTES_PER_MEBIBYTE;
|
|
20
|
+
const DEFAULT_I3S_MAXIMUM_CACHE_OVERFLOW_BYTES = BYTES_PER_MEBIBYTE;
|
|
21
|
+
/**
|
|
22
|
+
* Validates a byte-based tile-cache budget.
|
|
23
|
+
*
|
|
24
|
+
* Fractions are accepted because JavaScript memory estimates are numbers, but negative, infinite,
|
|
25
|
+
* and `NaN` values cannot define a stable cache threshold.
|
|
26
|
+
*
|
|
27
|
+
* @param value - Proposed cache budget in bytes.
|
|
28
|
+
* @param optionName - Public option name used in an actionable error message.
|
|
29
|
+
* @returns The validated byte budget.
|
|
30
|
+
*/
|
|
31
|
+
function validateCacheByteLength(value, optionName) {
|
|
32
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
33
|
+
throw new Error(`${optionName} must be a finite number greater than or equal to 0`);
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the base cache target from byte-native or deprecated mebibyte options.
|
|
39
|
+
*
|
|
40
|
+
* The byte-native option takes precedence so mixed migration configurations are deterministic.
|
|
41
|
+
* The fallback is already expressed in bytes and is used for both construction and runtime updates.
|
|
42
|
+
*
|
|
43
|
+
* @param options - Options that may contain byte-native or deprecated cache values.
|
|
44
|
+
* @param fallbackCacheBytes - Existing or default cache target in bytes.
|
|
45
|
+
* @returns The resolved and validated cache target in bytes.
|
|
46
|
+
*/
|
|
47
|
+
function resolveCacheBytes(options, fallbackCacheBytes) {
|
|
48
|
+
const cacheBytes = options.cacheBytes ??
|
|
49
|
+
(options.maximumMemoryUsage !== undefined
|
|
50
|
+
? options.maximumMemoryUsage * BYTES_PER_MEBIBYTE
|
|
51
|
+
: fallbackCacheBytes);
|
|
52
|
+
return validateCacheByteLength(cacheBytes, 'cacheBytes');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolves cache overflow headroom from byte-native or deprecated mebibyte options.
|
|
56
|
+
*
|
|
57
|
+
* The byte-native option takes precedence so callers can migrate the two cache controls
|
|
58
|
+
* independently without unit ambiguity.
|
|
59
|
+
*
|
|
60
|
+
* @param options - Options that may contain byte-native or deprecated overflow values.
|
|
61
|
+
* @param fallbackOverflowBytes - Existing or default overflow headroom in bytes.
|
|
62
|
+
* @returns The resolved and validated overflow headroom in bytes.
|
|
63
|
+
*/
|
|
64
|
+
function resolveMaximumCacheOverflowBytes(options, fallbackOverflowBytes) {
|
|
65
|
+
const maximumCacheOverflowBytes = options.maximumCacheOverflowBytes ??
|
|
66
|
+
(options.memoryCacheOverflow !== undefined
|
|
67
|
+
? options.memoryCacheOverflow * BYTES_PER_MEBIBYTE
|
|
68
|
+
: fallbackOverflowBytes);
|
|
69
|
+
return validateCacheByteLength(maximumCacheOverflowBytes, 'maximumCacheOverflowBytes');
|
|
70
|
+
}
|
|
71
|
+
const DEFAULT_PROPS = {
|
|
72
|
+
description: '',
|
|
73
|
+
ellipsoid: Ellipsoid.WGS84,
|
|
74
|
+
modelMatrix: new Matrix4(),
|
|
75
|
+
throttleRequests: true,
|
|
76
|
+
maxRequests: 64,
|
|
77
|
+
cacheBytes: DEFAULT_CACHE_BYTES,
|
|
78
|
+
maximumCacheOverflowBytes: DEFAULT_MAXIMUM_CACHE_OVERFLOW_BYTES,
|
|
79
|
+
maximumMemoryUsage: DEFAULT_CACHE_BYTES / BYTES_PER_MEBIBYTE,
|
|
80
|
+
memoryCacheOverflow: DEFAULT_MAXIMUM_CACHE_OVERFLOW_BYTES / BYTES_PER_MEBIBYTE,
|
|
81
|
+
maximumTilesSelected: 0,
|
|
82
|
+
debounceTime: 0,
|
|
83
|
+
onTileLoad: () => { },
|
|
84
|
+
onTileUnload: () => { },
|
|
85
|
+
onTileError: () => { },
|
|
86
|
+
onSourceError: () => { },
|
|
87
|
+
onTilesetError: () => { },
|
|
88
|
+
onTraversalComplete: (selectedTiles) => selectedTiles,
|
|
89
|
+
onUpdate: () => { },
|
|
90
|
+
contentLoader: undefined,
|
|
91
|
+
viewDistanceScale: 1.0,
|
|
92
|
+
progressiveResolutionHeightFraction: 0.3,
|
|
93
|
+
foveatedScreenSpaceError: true,
|
|
94
|
+
foveatedConeSize: 0.1,
|
|
95
|
+
foveatedMinimumScreenSpaceErrorRelaxation: 0,
|
|
96
|
+
foveatedInterpolationCallback: interpolateLinearly,
|
|
97
|
+
foveatedTimeDelay: 0.2,
|
|
98
|
+
maximumScreenSpaceError: 8,
|
|
99
|
+
dynamicScreenSpaceError: true,
|
|
100
|
+
dynamicScreenSpaceErrorDensity: 2.0e-4,
|
|
101
|
+
dynamicScreenSpaceErrorFactor: 24,
|
|
102
|
+
dynamicScreenSpaceErrorHeightFalloff: 0.25,
|
|
103
|
+
memoryAdjustedScreenSpaceError: true,
|
|
104
|
+
loadTiles: true,
|
|
105
|
+
updateTransforms: true,
|
|
106
|
+
viewportTraversersMap: null,
|
|
107
|
+
loadOptions: { fetch: {} },
|
|
108
|
+
attributions: [],
|
|
109
|
+
basePath: '',
|
|
110
|
+
i3s: {}
|
|
111
|
+
};
|
|
112
|
+
const TILES_TOTAL = 'Tiles In Tileset(s)';
|
|
113
|
+
const TILES_IN_MEMORY = 'Tiles In Memory';
|
|
114
|
+
const TILES_IN_VIEW = 'Tiles In View';
|
|
115
|
+
const TILES_RENDERABLE = 'Tiles To Render';
|
|
116
|
+
const TILES_LOADED = 'Tiles Loaded';
|
|
117
|
+
const TILES_LOADING = 'Tiles Loading';
|
|
118
|
+
const TILES_UNLOADED = 'Tiles Unloaded';
|
|
119
|
+
const TILES_LOAD_FAILED = 'Failed Tile Loads';
|
|
120
|
+
const POINTS_COUNT = 'Points/Vertices';
|
|
121
|
+
const TILES_GPU_MEMORY = 'Tile Memory Use';
|
|
122
|
+
const MAXIMUM_SSE = 'Maximum Screen Space Error';
|
|
123
|
+
/**
|
|
124
|
+
* Shared runtime for tile traversal, selection, cache management, and request scheduling.
|
|
125
|
+
*
|
|
126
|
+
* Format-specific loading behavior is delegated to a {@link Tileset3DSource} implementation.
|
|
127
|
+
*/
|
|
128
|
+
export class Tileset3D {
|
|
129
|
+
options;
|
|
130
|
+
loadOptions;
|
|
131
|
+
/** Source implementation responsible for format-specific initialization and loading. */
|
|
132
|
+
source;
|
|
133
|
+
type;
|
|
134
|
+
tileset;
|
|
135
|
+
loader;
|
|
136
|
+
url;
|
|
137
|
+
basePath;
|
|
138
|
+
modelMatrix;
|
|
139
|
+
ellipsoid;
|
|
140
|
+
lodMetricType;
|
|
141
|
+
lodMetricValue;
|
|
142
|
+
refine;
|
|
143
|
+
root = null;
|
|
144
|
+
roots = {};
|
|
145
|
+
asset = {};
|
|
146
|
+
description = '';
|
|
147
|
+
properties;
|
|
148
|
+
extras = null;
|
|
149
|
+
attributions = {};
|
|
150
|
+
credits = {};
|
|
151
|
+
stats;
|
|
152
|
+
contentFormats;
|
|
153
|
+
cartographicCenter = null;
|
|
154
|
+
cartesianCenter = null;
|
|
155
|
+
zoom = 1;
|
|
156
|
+
boundingVolume = null;
|
|
157
|
+
/** Effective dynamic SSE density calculated for the most recently traversed viewport. */
|
|
158
|
+
dynamicScreenSpaceErrorComputedDensity = 0;
|
|
159
|
+
/** Estimated bytes currently retained by loaded tile content. */
|
|
160
|
+
gpuMemoryUsageInBytes = 0;
|
|
161
|
+
/** Active SSE threshold after optional cache-pressure adjustment, in logical/CSS pixels. */
|
|
162
|
+
memoryAdjustedScreenSpaceError = 0.0;
|
|
163
|
+
_cacheBytes = DEFAULT_CACHE_BYTES;
|
|
164
|
+
_maximumCacheOverflowBytes = DEFAULT_MAXIMUM_CACHE_OVERFLOW_BYTES;
|
|
165
|
+
_frameNumber = 0;
|
|
166
|
+
_tiles = {};
|
|
167
|
+
_pendingCount = 0;
|
|
168
|
+
selectedTiles = [];
|
|
169
|
+
traverseCounter = 0;
|
|
170
|
+
geometricError = 0;
|
|
171
|
+
lastUpdatedVieports = null;
|
|
172
|
+
_requestedTiles = [];
|
|
173
|
+
_emptyTiles = [];
|
|
174
|
+
frameStateData = {};
|
|
175
|
+
/** Last camera pose retained independently for each viewport. */
|
|
176
|
+
_cameraMotionStates = {};
|
|
177
|
+
/** Pending traversal that releases requests after camera motion settles. */
|
|
178
|
+
_deferredTraversalTimeout = null;
|
|
179
|
+
_traverser;
|
|
180
|
+
_cache = new TilesetCache();
|
|
181
|
+
_requestScheduler;
|
|
182
|
+
_heldTiles = new Set();
|
|
183
|
+
updatePromise = null;
|
|
184
|
+
tilesetInitializationPromise;
|
|
185
|
+
/**
|
|
186
|
+
* Creates a tileset runtime from an explicit source implementation.
|
|
187
|
+
* @param source Source-backed tileset implementation.
|
|
188
|
+
* @param options Traversal and runtime options.
|
|
189
|
+
*/
|
|
190
|
+
constructor(source, options) {
|
|
191
|
+
if (!isTileset3DSource(source)) {
|
|
192
|
+
throw new Error('Tileset3D requires a Tileset3DSource instance');
|
|
193
|
+
}
|
|
194
|
+
const suppliedOptions = options || {};
|
|
195
|
+
const usesTiles3DCacheDefaults = source.type === TILESET_TYPE.TILES3D;
|
|
196
|
+
const defaultCacheBytes = usesTiles3DCacheDefaults
|
|
197
|
+
? DEFAULT_PROPS.cacheBytes
|
|
198
|
+
: DEFAULT_I3S_CACHE_BYTES;
|
|
199
|
+
const defaultMaximumCacheOverflowBytes = usesTiles3DCacheDefaults
|
|
200
|
+
? DEFAULT_PROPS.maximumCacheOverflowBytes
|
|
201
|
+
: DEFAULT_I3S_MAXIMUM_CACHE_OVERFLOW_BYTES;
|
|
202
|
+
const cacheBytes = resolveCacheBytes(suppliedOptions, defaultCacheBytes);
|
|
203
|
+
const maximumCacheOverflowBytes = resolveMaximumCacheOverflowBytes(suppliedOptions, defaultMaximumCacheOverflowBytes);
|
|
204
|
+
this.options = {
|
|
205
|
+
...DEFAULT_PROPS,
|
|
206
|
+
...suppliedOptions,
|
|
207
|
+
cacheBytes,
|
|
208
|
+
maximumCacheOverflowBytes,
|
|
209
|
+
maximumMemoryUsage: cacheBytes / BYTES_PER_MEBIBYTE,
|
|
210
|
+
memoryCacheOverflow: maximumCacheOverflowBytes / BYTES_PER_MEBIBYTE,
|
|
211
|
+
memoryAdjustedScreenSpaceError: suppliedOptions.memoryAdjustedScreenSpaceError ?? usesTiles3DCacheDefaults
|
|
212
|
+
};
|
|
213
|
+
this.loadOptions = this.options.loadOptions || {};
|
|
214
|
+
this.source = source;
|
|
215
|
+
this.tileset = null;
|
|
216
|
+
this.loader = this.source.loader;
|
|
217
|
+
this.type = this.source.type;
|
|
218
|
+
this.url = this.source.url;
|
|
219
|
+
this.basePath = this.source.basePath;
|
|
220
|
+
this.modelMatrix = this.options.modelMatrix;
|
|
221
|
+
this.ellipsoid = this.options.ellipsoid;
|
|
222
|
+
this.lodMetricType = '';
|
|
223
|
+
this.lodMetricValue = 0;
|
|
224
|
+
this.refine = '';
|
|
225
|
+
this.contentFormats = this.source.contentFormats;
|
|
226
|
+
this._traverser = this._initializeTraverser();
|
|
227
|
+
this._requestScheduler = new RequestScheduler({
|
|
228
|
+
throttleRequests: this.options.throttleRequests,
|
|
229
|
+
maxRequests: this.options.maxRequests
|
|
230
|
+
});
|
|
231
|
+
this.memoryAdjustedScreenSpaceError = this.options.maximumScreenSpaceError;
|
|
232
|
+
this._cacheBytes = cacheBytes;
|
|
233
|
+
this._maximumCacheOverflowBytes = maximumCacheOverflowBytes;
|
|
234
|
+
this.stats = new Stats({ id: this.url });
|
|
235
|
+
this._initializeStats();
|
|
236
|
+
this.tilesetInitializationPromise = this._initializeTileSet();
|
|
237
|
+
}
|
|
238
|
+
destroy() {
|
|
239
|
+
this._clearDeferredTraversal();
|
|
240
|
+
this.source.destroy?.();
|
|
241
|
+
this._destroy();
|
|
242
|
+
}
|
|
243
|
+
isLoaded() {
|
|
244
|
+
return this._pendingCount === 0 && this._frameNumber !== 0 && this._requestedTiles.length === 0;
|
|
245
|
+
}
|
|
246
|
+
get tiles() {
|
|
247
|
+
return Object.values(this._tiles);
|
|
248
|
+
}
|
|
249
|
+
get frameNumber() {
|
|
250
|
+
return this._frameNumber;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Gets or sets the soft target, in bytes, for cached tile content not needed this frame.
|
|
254
|
+
*
|
|
255
|
+
* Current-frame tiles remain protected even when their estimated memory exceeds this target.
|
|
256
|
+
* Reducing the value makes unused least-recently-used tiles eligible for eviction on the next
|
|
257
|
+
* traversal.
|
|
258
|
+
* @default 536870912 for 3D Tiles; 33554432 for I3S
|
|
259
|
+
*/
|
|
260
|
+
get cacheBytes() {
|
|
261
|
+
return this._cacheBytes;
|
|
262
|
+
}
|
|
263
|
+
set cacheBytes(value) {
|
|
264
|
+
this._cacheBytes = validateCacheByteLength(value, 'cacheBytes');
|
|
265
|
+
this.options.cacheBytes = this._cacheBytes;
|
|
266
|
+
this.options.maximumMemoryUsage = this._cacheBytes / BYTES_PER_MEBIBYTE;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Gets or sets the additional current-frame headroom, in bytes, before memory-adjusted SSE rises.
|
|
270
|
+
*
|
|
271
|
+
* The pressure ceiling is `cacheBytes + maximumCacheOverflowBytes`. This value does not change
|
|
272
|
+
* the base target used to evict tiles that were not touched in the current frame.
|
|
273
|
+
* @default 536870912 for 3D Tiles; 1048576 for I3S
|
|
274
|
+
*/
|
|
275
|
+
get maximumCacheOverflowBytes() {
|
|
276
|
+
return this._maximumCacheOverflowBytes;
|
|
277
|
+
}
|
|
278
|
+
set maximumCacheOverflowBytes(value) {
|
|
279
|
+
this._maximumCacheOverflowBytes = validateCacheByteLength(value, 'maximumCacheOverflowBytes');
|
|
280
|
+
this.options.maximumCacheOverflowBytes = this._maximumCacheOverflowBytes;
|
|
281
|
+
this.options.memoryCacheOverflow = this._maximumCacheOverflowBytes / BYTES_PER_MEBIBYTE;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Gets or sets the soft cache target in mebibytes.
|
|
285
|
+
* @deprecated Use {@link Tileset3D.cacheBytes}. Assignments remain synchronized for compatibility.
|
|
286
|
+
*/
|
|
287
|
+
get maximumMemoryUsage() {
|
|
288
|
+
return this.cacheBytes / BYTES_PER_MEBIBYTE;
|
|
289
|
+
}
|
|
290
|
+
set maximumMemoryUsage(value) {
|
|
291
|
+
this.cacheBytes = validateCacheByteLength(value * BYTES_PER_MEBIBYTE, 'maximumMemoryUsage');
|
|
292
|
+
}
|
|
293
|
+
get queryParams() {
|
|
294
|
+
const rootUrl = this.source.getTileUrl(this.url);
|
|
295
|
+
const queryIndex = rootUrl.indexOf('?');
|
|
296
|
+
return queryIndex >= 0 ? rootUrl.slice(queryIndex + 1) : '';
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Updates traversal and runtime options, synchronizing byte-native and deprecated cache values.
|
|
300
|
+
*
|
|
301
|
+
* For each budget, the byte-native option takes precedence when both unit forms are supplied.
|
|
302
|
+
* Unspecified budgets retain their current byte values, avoiding repeated MiB conversion.
|
|
303
|
+
*
|
|
304
|
+
* @param props - Partial runtime options to apply.
|
|
305
|
+
*/
|
|
306
|
+
setProps(props) {
|
|
307
|
+
const cacheBytes = resolveCacheBytes(props, this.cacheBytes);
|
|
308
|
+
const maximumCacheOverflowBytes = resolveMaximumCacheOverflowBytes(props, this.maximumCacheOverflowBytes);
|
|
309
|
+
this.options = {
|
|
310
|
+
...this.options,
|
|
311
|
+
...props,
|
|
312
|
+
cacheBytes,
|
|
313
|
+
maximumCacheOverflowBytes,
|
|
314
|
+
maximumMemoryUsage: cacheBytes / BYTES_PER_MEBIBYTE,
|
|
315
|
+
memoryCacheOverflow: maximumCacheOverflowBytes / BYTES_PER_MEBIBYTE
|
|
316
|
+
};
|
|
317
|
+
this._cacheBytes = cacheBytes;
|
|
318
|
+
this._maximumCacheOverflowBytes = maximumCacheOverflowBytes;
|
|
319
|
+
}
|
|
320
|
+
getTileUrl(tilePath) {
|
|
321
|
+
return this.source.getTileUrl(tilePath);
|
|
322
|
+
}
|
|
323
|
+
hasExtension(extensionName) {
|
|
324
|
+
return Boolean(this.source.hasExtension?.(extensionName));
|
|
325
|
+
}
|
|
326
|
+
update(viewports = null) {
|
|
327
|
+
this.tilesetInitializationPromise.then(() => {
|
|
328
|
+
if (!viewports && this.lastUpdatedVieports) {
|
|
329
|
+
viewports = this.lastUpdatedVieports;
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
this.lastUpdatedVieports = viewports;
|
|
333
|
+
}
|
|
334
|
+
if (viewports) {
|
|
335
|
+
this.doUpdate(viewports);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
async selectTiles(viewports = null) {
|
|
340
|
+
await this.tilesetInitializationPromise;
|
|
341
|
+
if (viewports) {
|
|
342
|
+
this.lastUpdatedVieports = viewports;
|
|
343
|
+
}
|
|
344
|
+
if (!this.updatePromise) {
|
|
345
|
+
this.updatePromise = new Promise(resolve => {
|
|
346
|
+
setTimeout(() => {
|
|
347
|
+
if (this.lastUpdatedVieports) {
|
|
348
|
+
this.doUpdate(this.lastUpdatedVieports);
|
|
349
|
+
}
|
|
350
|
+
resolve(this._frameNumber);
|
|
351
|
+
this.updatePromise = null;
|
|
352
|
+
}, this.options.debounceTime);
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return this.updatePromise;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Moves the active LOD threshold toward the configured SSE or away from cache pressure.
|
|
359
|
+
*
|
|
360
|
+
* Usage below {@link Tileset3D.cacheBytes} restores quality in two-percent steps. Usage above
|
|
361
|
+
* `cacheBytes + maximumCacheOverflowBytes` reduces refinement in two-percent steps. Values in
|
|
362
|
+
* the overflow window leave the threshold unchanged, preventing rapid load/evict oscillation.
|
|
363
|
+
*/
|
|
364
|
+
adjustScreenSpaceError() {
|
|
365
|
+
if (this.gpuMemoryUsageInBytes < this.cacheBytes) {
|
|
366
|
+
this.memoryAdjustedScreenSpaceError = Math.max(this.memoryAdjustedScreenSpaceError / 1.02, this.options.maximumScreenSpaceError);
|
|
367
|
+
}
|
|
368
|
+
else if (this.gpuMemoryUsageInBytes > this.cacheBytes + this.maximumCacheOverflowBytes) {
|
|
369
|
+
this.memoryAdjustedScreenSpaceError *= 1.02;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
doUpdate(viewports) {
|
|
373
|
+
if ('loadTiles' in this.options && !this.options.loadTiles) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (this.traverseCounter > 0) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
const preparedViewports = viewports instanceof Array ? viewports : [viewports];
|
|
380
|
+
this._cache.reset();
|
|
381
|
+
this._frameNumber++;
|
|
382
|
+
this.traverseCounter = preparedViewports.length;
|
|
383
|
+
const currentTime = Date.now();
|
|
384
|
+
let minimumDeferredTraversalDelay = Number.POSITIVE_INFINITY;
|
|
385
|
+
const viewportsToTraverse = [];
|
|
386
|
+
for (const viewport of preparedViewports) {
|
|
387
|
+
const id = viewport.id;
|
|
388
|
+
if (this._needTraverse(id)) {
|
|
389
|
+
viewportsToTraverse.push(id);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
this.traverseCounter--;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
for (const viewport of preparedViewports) {
|
|
396
|
+
const id = viewport.id;
|
|
397
|
+
if (!this.roots[id]) {
|
|
398
|
+
this.roots[id] = this._initializeTileHeaders(this.tileset, null);
|
|
399
|
+
}
|
|
400
|
+
if (!viewportsToTraverse.includes(id)) {
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
const frameState = getFrameState(viewport, this._frameNumber);
|
|
404
|
+
const root = this.roots[id];
|
|
405
|
+
const cameraMotionUpdate = updateCameraMotionState(this._cameraMotionStates[id], frameState.camera.position, frameState.camera.direction, currentTime);
|
|
406
|
+
this._cameraMotionStates[id] = cameraMotionUpdate.state;
|
|
407
|
+
frameState.camera.timeSinceMovement = cameraMotionUpdate.timeSinceMovement;
|
|
408
|
+
// Dynamic SSE reads the root's inverse computed transform before traversal updates tile
|
|
409
|
+
// visibility. Refresh it from the current tileset model matrix here so animated local
|
|
410
|
+
// box/sphere tilesets never calculate their height falloff one transform behind the frame.
|
|
411
|
+
updateRootTransformForDynamicScreenSpaceError(root, this.modelMatrix);
|
|
412
|
+
frameState.dynamicScreenSpaceErrorDensity =
|
|
413
|
+
this.type === TILESET_TYPE.TILES3D &&
|
|
414
|
+
this.options.dynamicScreenSpaceError &&
|
|
415
|
+
!frameState.viewport.orthographic
|
|
416
|
+
? calculateDynamicScreenSpaceErrorDensity(root, frameState, this.options)
|
|
417
|
+
: 0;
|
|
418
|
+
// Keep the legacy diagnostic field, but traversal reads the per-viewport frame value above.
|
|
419
|
+
this.dynamicScreenSpaceErrorComputedDensity = frameState.dynamicScreenSpaceErrorDensity;
|
|
420
|
+
this._traverser.traverse(root, frameState, this.options);
|
|
421
|
+
if (Object.keys(this._traverser.deferredTiles).length > 0) {
|
|
422
|
+
minimumDeferredTraversalDelay = Math.min(minimumDeferredTraversalDelay, Math.max(this.options.foveatedTimeDelay - cameraMotionUpdate.timeSinceMovement, 0));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (Number.isFinite(minimumDeferredTraversalDelay)) {
|
|
426
|
+
this._scheduleDeferredTraversal(minimumDeferredTraversalDelay);
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
this._clearDeferredTraversal();
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Schedules one follow-up traversal when the moving-camera deferral window expires.
|
|
434
|
+
*
|
|
435
|
+
* Replacing an existing timer ensures continuing camera movement pushes the retry window forward
|
|
436
|
+
* instead of creating a queue of redundant traversals.
|
|
437
|
+
*
|
|
438
|
+
* @param delayInSeconds - Remaining stationary delay before deferred requests become eligible.
|
|
439
|
+
*/
|
|
440
|
+
_scheduleDeferredTraversal(delayInSeconds) {
|
|
441
|
+
this._clearDeferredTraversal();
|
|
442
|
+
this._deferredTraversalTimeout = setTimeout(() => {
|
|
443
|
+
this._deferredTraversalTimeout = null;
|
|
444
|
+
this.selectTiles().catch((error) => {
|
|
445
|
+
const traversalError = error instanceof Error ? error : new Error(String(error));
|
|
446
|
+
this._onTilesetError(traversalError);
|
|
447
|
+
});
|
|
448
|
+
}, Math.max(delayInSeconds * 1000, 0));
|
|
449
|
+
}
|
|
450
|
+
/** Clears a pending moving-camera follow-up traversal. */
|
|
451
|
+
_clearDeferredTraversal() {
|
|
452
|
+
if (this._deferredTraversalTimeout !== null) {
|
|
453
|
+
clearTimeout(this._deferredTraversalTimeout);
|
|
454
|
+
this._deferredTraversalTimeout = null;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
_needTraverse(viewportId) {
|
|
458
|
+
let traverserId = viewportId;
|
|
459
|
+
if (this.options.viewportTraversersMap) {
|
|
460
|
+
traverserId = this.options.viewportTraversersMap[viewportId];
|
|
461
|
+
}
|
|
462
|
+
return traverserId === viewportId;
|
|
463
|
+
}
|
|
464
|
+
_onTraversalEnd(frameState) {
|
|
465
|
+
const id = frameState.viewport.id;
|
|
466
|
+
if (!this.frameStateData[id]) {
|
|
467
|
+
this.frameStateData[id] = { selectedTiles: [], _requestedTiles: [], _emptyTiles: [] };
|
|
468
|
+
}
|
|
469
|
+
const currentFrameStateData = this.frameStateData[id];
|
|
470
|
+
const selectedTiles = Object.values(this._traverser.selectedTiles);
|
|
471
|
+
const [filteredSelectedTiles, unselectedTiles] = limitSelectedTiles(selectedTiles, frameState, this.options.maximumTilesSelected);
|
|
472
|
+
currentFrameStateData.selectedTiles = filteredSelectedTiles;
|
|
473
|
+
for (const tile of unselectedTiles) {
|
|
474
|
+
tile.unselect();
|
|
475
|
+
}
|
|
476
|
+
currentFrameStateData._requestedTiles = Object.values(this._traverser.requestedTiles);
|
|
477
|
+
currentFrameStateData._emptyTiles = Object.values(this._traverser.emptyTiles);
|
|
478
|
+
this.traverseCounter--;
|
|
479
|
+
if (this.traverseCounter > 0) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
this._updateTiles();
|
|
483
|
+
}
|
|
484
|
+
_updateTiles() {
|
|
485
|
+
const previousSelectedTiles = this.selectedTiles;
|
|
486
|
+
this.selectedTiles = [];
|
|
487
|
+
this._requestedTiles = [];
|
|
488
|
+
this._emptyTiles = [];
|
|
489
|
+
for (const frameStateKey in this.frameStateData) {
|
|
490
|
+
const frameStateDataValue = this.frameStateData[frameStateKey];
|
|
491
|
+
this.selectedTiles = this.selectedTiles.concat(frameStateDataValue.selectedTiles);
|
|
492
|
+
this._requestedTiles = this._requestedTiles.concat(frameStateDataValue._requestedTiles);
|
|
493
|
+
this._emptyTiles = this._emptyTiles.concat(frameStateDataValue._emptyTiles);
|
|
494
|
+
}
|
|
495
|
+
this.selectedTiles = this.options.onTraversalComplete(this.selectedTiles);
|
|
496
|
+
const selectedIds = new Set(this.selectedTiles.map(tile => tile.id));
|
|
497
|
+
const hasUndrawnTiles = this.selectedTiles.some(tile => !tile.tileDrawn);
|
|
498
|
+
let heldBackCount = 0;
|
|
499
|
+
if (hasUndrawnTiles) {
|
|
500
|
+
for (const tileId of selectedIds) {
|
|
501
|
+
this._heldTiles.add(tileId);
|
|
502
|
+
}
|
|
503
|
+
for (const tileId of this._heldTiles) {
|
|
504
|
+
if (selectedIds.has(tileId))
|
|
505
|
+
continue;
|
|
506
|
+
const tile = this._tiles[tileId];
|
|
507
|
+
if (tile && tile.contentAvailable) {
|
|
508
|
+
tile._selectedFrame = this._frameNumber;
|
|
509
|
+
this.selectedTiles.push(tile);
|
|
510
|
+
heldBackCount++;
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
this._heldTiles.delete(tileId);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
this._heldTiles = selectedIds;
|
|
519
|
+
}
|
|
520
|
+
if (heldBackCount > 0) {
|
|
521
|
+
setTimeout(() => {
|
|
522
|
+
this.selectTiles();
|
|
523
|
+
}, 0);
|
|
524
|
+
}
|
|
525
|
+
for (const tile of this.selectedTiles) {
|
|
526
|
+
this._tiles[tile.id] = tile;
|
|
527
|
+
}
|
|
528
|
+
this._loadTiles();
|
|
529
|
+
this._unloadTiles();
|
|
530
|
+
this._updateStats();
|
|
531
|
+
if (this._tilesChanged(previousSelectedTiles, this.selectedTiles)) {
|
|
532
|
+
this.options.onUpdate();
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
_tilesChanged(oldSelectedTiles, selectedTiles) {
|
|
536
|
+
if (oldSelectedTiles.length !== selectedTiles.length) {
|
|
537
|
+
return true;
|
|
538
|
+
}
|
|
539
|
+
const oldSet = new Set(oldSelectedTiles.map(tile => tile.id));
|
|
540
|
+
const newSet = new Set(selectedTiles.map(tile => tile.id));
|
|
541
|
+
let changed = oldSelectedTiles.some(tile => !newSet.has(tile.id));
|
|
542
|
+
changed = changed || selectedTiles.some(tile => !oldSet.has(tile.id));
|
|
543
|
+
return changed;
|
|
544
|
+
}
|
|
545
|
+
_loadTiles() {
|
|
546
|
+
this._requestedTiles.sort((tileA, tileB) => tileA._priority - tileB._priority);
|
|
547
|
+
for (const tile of this._requestedTiles) {
|
|
548
|
+
if (tile.contentUnloaded) {
|
|
549
|
+
this._loadTile(tile);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
_unloadTiles() {
|
|
554
|
+
this._cache.unloadTiles(this, (tileset, tile) => tileset._unloadTile(tile));
|
|
555
|
+
if (this.options.memoryAdjustedScreenSpaceError) {
|
|
556
|
+
this.adjustScreenSpaceError();
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
_updateStats() {
|
|
560
|
+
let tilesRenderable = 0;
|
|
561
|
+
let pointsRenderable = 0;
|
|
562
|
+
for (const tile of this.selectedTiles) {
|
|
563
|
+
if (tile.contentAvailable && tile.content) {
|
|
564
|
+
tilesRenderable++;
|
|
565
|
+
if (tile.content.pointCount) {
|
|
566
|
+
pointsRenderable += tile.content.pointCount;
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
pointsRenderable += tile.content.vertexCount;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
this.stats.get(TILES_IN_VIEW).count = this.selectedTiles.length;
|
|
574
|
+
this.stats.get(TILES_RENDERABLE).count = tilesRenderable;
|
|
575
|
+
this.stats.get(POINTS_COUNT).count = pointsRenderable;
|
|
576
|
+
this.stats.get(MAXIMUM_SSE).count = this.memoryAdjustedScreenSpaceError;
|
|
577
|
+
}
|
|
578
|
+
async _initializeTileSet() {
|
|
579
|
+
try {
|
|
580
|
+
const initializePromise = this.source.initialize();
|
|
581
|
+
const initialMetadata = this._getSourceMetadata();
|
|
582
|
+
if (initialMetadata) {
|
|
583
|
+
this._syncSourceState(initialMetadata);
|
|
584
|
+
}
|
|
585
|
+
if (initialMetadata?.tileset?.root &&
|
|
586
|
+
typeof initialMetadata.tileset.root.then !== 'function') {
|
|
587
|
+
this.root = this._initializeTileHeaders(initialMetadata.tileset, null);
|
|
588
|
+
this._applyViewState();
|
|
589
|
+
}
|
|
590
|
+
await initializePromise;
|
|
591
|
+
const metadata = this.source.getMetadata();
|
|
592
|
+
this._syncSourceState(metadata);
|
|
593
|
+
if (!this.root) {
|
|
594
|
+
this.root = this._initializeTileHeaders(metadata.tileset, null);
|
|
595
|
+
}
|
|
596
|
+
this._applyViewState();
|
|
597
|
+
}
|
|
598
|
+
catch (error) {
|
|
599
|
+
const sourceError = error instanceof Error ? error : new Error(String(error));
|
|
600
|
+
this._onSourceError(sourceError, this.root);
|
|
601
|
+
this._onTilesetError(sourceError);
|
|
602
|
+
throw sourceError;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
_initializeStats() {
|
|
606
|
+
this.stats.get(TILES_TOTAL);
|
|
607
|
+
this.stats.get(TILES_LOADING);
|
|
608
|
+
this.stats.get(TILES_IN_MEMORY);
|
|
609
|
+
this.stats.get(TILES_IN_VIEW);
|
|
610
|
+
this.stats.get(TILES_RENDERABLE);
|
|
611
|
+
this.stats.get(TILES_LOADED);
|
|
612
|
+
this.stats.get(TILES_UNLOADED);
|
|
613
|
+
this.stats.get(TILES_LOAD_FAILED);
|
|
614
|
+
this.stats.get(POINTS_COUNT);
|
|
615
|
+
this.stats.get(TILES_GPU_MEMORY, 'memory');
|
|
616
|
+
this.stats.get(MAXIMUM_SSE);
|
|
617
|
+
}
|
|
618
|
+
_initializeTileHeaders(tilesetJson, parentTileHeader) {
|
|
619
|
+
return this.source.initializeTileHeaders(this, tilesetJson, parentTileHeader);
|
|
620
|
+
}
|
|
621
|
+
_initializeTraverser() {
|
|
622
|
+
return this.source.createTraverser({
|
|
623
|
+
basePath: this.basePath,
|
|
624
|
+
onTraversalEnd: this._onTraversalEnd.bind(this)
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
_destroyTileHeaders(parentTile) {
|
|
628
|
+
this._destroySubtree(parentTile);
|
|
629
|
+
}
|
|
630
|
+
async _loadTile(tile) {
|
|
631
|
+
let loadResult = null;
|
|
632
|
+
try {
|
|
633
|
+
this._onStartTileLoading();
|
|
634
|
+
loadResult = await tile.loadContent();
|
|
635
|
+
}
|
|
636
|
+
catch (error) {
|
|
637
|
+
const tileError = error instanceof Error ? error : new Error('load failed');
|
|
638
|
+
this._onSourceError(tileError, tile);
|
|
639
|
+
this._onTileLoadError(tile, tileError);
|
|
640
|
+
}
|
|
641
|
+
finally {
|
|
642
|
+
this._onEndTileLoading();
|
|
643
|
+
this._onTileLoad(tile, loadResult);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Loads a source-managed lazy child-header group and reports failures through tile callbacks.
|
|
648
|
+
*
|
|
649
|
+
* Subtree metadata shares the normal loading counters but is not reported as render content and
|
|
650
|
+
* is not added to the GPU cache. Traversal is notified separately after the promise settles.
|
|
651
|
+
*
|
|
652
|
+
* @param tile - Runtime tile that owns the lazy subtree reference.
|
|
653
|
+
* @param frameState - View state that made the subtree eligible for refinement.
|
|
654
|
+
*/
|
|
655
|
+
async _loadTileChildren(tile, frameState) {
|
|
656
|
+
try {
|
|
657
|
+
this._onStartTileLoading();
|
|
658
|
+
await tile.loadChildren(frameState);
|
|
659
|
+
}
|
|
660
|
+
catch (error) {
|
|
661
|
+
const tileError = error instanceof Error ? error : new Error('subtree load failed');
|
|
662
|
+
this._onSourceError(tileError, tile);
|
|
663
|
+
this._onTileLoadError(tile, tileError);
|
|
664
|
+
}
|
|
665
|
+
finally {
|
|
666
|
+
this._onEndTileLoading();
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
_onTileLoadError(tile, error) {
|
|
670
|
+
this.stats.get(TILES_LOAD_FAILED).incrementCount();
|
|
671
|
+
const message = error.message || error.toString();
|
|
672
|
+
const url = tile.url;
|
|
673
|
+
console.error(`A 3D tile failed to load: ${tile.url} ${message}`);
|
|
674
|
+
this.options.onTileError(tile, message, url);
|
|
675
|
+
}
|
|
676
|
+
_onSourceError(error, tile = null) {
|
|
677
|
+
this.options.onSourceError(error, this.source, tile);
|
|
678
|
+
}
|
|
679
|
+
_onTilesetError(error) {
|
|
680
|
+
this.options.onTilesetError(error, this);
|
|
681
|
+
}
|
|
682
|
+
_onTileLoad(tile, loadResult) {
|
|
683
|
+
if (!loadResult?.loaded) {
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
if (tile.content) {
|
|
687
|
+
calculateTransformProps(tile, tile.content);
|
|
688
|
+
}
|
|
689
|
+
this.source.onTileLoaded?.(this, tile, loadResult);
|
|
690
|
+
this._syncSourceState(this.source.getMetadata());
|
|
691
|
+
const totalTiles = this.source.getTilesTotalCount?.();
|
|
692
|
+
if (totalTiles) {
|
|
693
|
+
this.stats.get(TILES_TOTAL).reset();
|
|
694
|
+
this.stats.get(TILES_TOTAL).addCount(totalTiles);
|
|
695
|
+
}
|
|
696
|
+
this._addTileToCache(tile);
|
|
697
|
+
this.options.onTileLoad(tile);
|
|
698
|
+
}
|
|
699
|
+
_onStartTileLoading() {
|
|
700
|
+
this._pendingCount++;
|
|
701
|
+
this.stats.get(TILES_LOADING).incrementCount();
|
|
702
|
+
}
|
|
703
|
+
_onEndTileLoading() {
|
|
704
|
+
this._pendingCount--;
|
|
705
|
+
this.stats.get(TILES_LOADING).decrementCount();
|
|
706
|
+
}
|
|
707
|
+
_addTileToCache(tile) {
|
|
708
|
+
this._cache.add(this, tile, tileset => tileset._updateCacheStats(tile));
|
|
709
|
+
}
|
|
710
|
+
_updateCacheStats(tile) {
|
|
711
|
+
this.stats.get(TILES_LOADED).incrementCount();
|
|
712
|
+
this.stats.get(TILES_IN_MEMORY).incrementCount();
|
|
713
|
+
this.gpuMemoryUsageInBytes += tile.gpuMemoryUsageInBytes || 0;
|
|
714
|
+
this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
|
|
715
|
+
if (this.options.memoryAdjustedScreenSpaceError) {
|
|
716
|
+
this.adjustScreenSpaceError();
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
_unloadTile(tile) {
|
|
720
|
+
this.gpuMemoryUsageInBytes -= tile.gpuMemoryUsageInBytes || 0;
|
|
721
|
+
this.stats.get(TILES_IN_MEMORY).decrementCount();
|
|
722
|
+
this.stats.get(TILES_UNLOADED).incrementCount();
|
|
723
|
+
this.stats.get(TILES_GPU_MEMORY).count = this.gpuMemoryUsageInBytes;
|
|
724
|
+
this.options.onTileUnload(tile);
|
|
725
|
+
tile.unloadContent();
|
|
726
|
+
}
|
|
727
|
+
_destroy() {
|
|
728
|
+
const stack = [];
|
|
729
|
+
if (this.root) {
|
|
730
|
+
stack.push(this.root);
|
|
731
|
+
}
|
|
732
|
+
while (stack.length > 0) {
|
|
733
|
+
const tile = stack.pop();
|
|
734
|
+
for (const child of tile.children) {
|
|
735
|
+
stack.push(child);
|
|
736
|
+
}
|
|
737
|
+
this._destroyTile(tile);
|
|
738
|
+
}
|
|
739
|
+
this.root = null;
|
|
740
|
+
}
|
|
741
|
+
_destroySubtree(tile) {
|
|
742
|
+
const rootTile = tile;
|
|
743
|
+
const stack = [rootTile];
|
|
744
|
+
while (stack.length > 0) {
|
|
745
|
+
tile = stack.pop();
|
|
746
|
+
for (const child of tile.children) {
|
|
747
|
+
stack.push(child);
|
|
748
|
+
}
|
|
749
|
+
if (tile !== rootTile) {
|
|
750
|
+
this._destroyTile(tile);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
rootTile.children = [];
|
|
754
|
+
}
|
|
755
|
+
_destroyTile(tile) {
|
|
756
|
+
this._cache.unloadTile(this, tile);
|
|
757
|
+
this._unloadTile(tile);
|
|
758
|
+
tile.destroy();
|
|
759
|
+
}
|
|
760
|
+
_syncSourceState(metadata) {
|
|
761
|
+
this.tileset = metadata.tileset;
|
|
762
|
+
this.loader = metadata.loader;
|
|
763
|
+
this.type = metadata.type;
|
|
764
|
+
this.url = metadata.url;
|
|
765
|
+
this.basePath = metadata.basePath;
|
|
766
|
+
this.lodMetricType = metadata.lodMetricType;
|
|
767
|
+
this.lodMetricValue = metadata.lodMetricValue;
|
|
768
|
+
this.refine = metadata.refine;
|
|
769
|
+
this.contentFormats = this.source.contentFormats;
|
|
770
|
+
this.asset = this.source.asset || this.asset;
|
|
771
|
+
this.properties = this.source.properties ?? this.properties;
|
|
772
|
+
this.extras = this.source.extras ?? this.extras;
|
|
773
|
+
if (this.options.attributions?.length) {
|
|
774
|
+
this.credits = { attributions: this.options.attributions };
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
this.credits = this.source.credits || this.credits;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
_applyViewState() {
|
|
781
|
+
const viewState = this.source.getViewState(this.root);
|
|
782
|
+
this.asset = viewState.asset || this.source.asset || {};
|
|
783
|
+
this.properties = viewState.properties ?? this.source.properties;
|
|
784
|
+
this.extras = viewState.extras ?? this.source.extras ?? null;
|
|
785
|
+
this.credits = viewState.credits ||
|
|
786
|
+
this.source.credits ||
|
|
787
|
+
this.credits || { attributions: this.options.attributions || [] };
|
|
788
|
+
this.description = viewState.description || this.options.description || '';
|
|
789
|
+
this.boundingVolume = viewState.boundingVolume || this.root?.boundingVolume || null;
|
|
790
|
+
this.cartographicCenter = viewState.cartographicCenter || new Vector3();
|
|
791
|
+
this.cartesianCenter = viewState.cartesianCenter || null;
|
|
792
|
+
this.zoom = viewState.zoom || 1;
|
|
793
|
+
this.geometricError = this.tileset?.geometricError || 0;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Returns normalized source metadata when initialization has already populated it.
|
|
797
|
+
*/
|
|
798
|
+
_getSourceMetadata() {
|
|
799
|
+
try {
|
|
800
|
+
return this.source.getMetadata();
|
|
801
|
+
}
|
|
802
|
+
catch {
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
//# sourceMappingURL=tileset-3d.js.map
|