@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
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
// loaders.gl
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
|
-
import { path } from '@loaders.gl/loader-utils';
|
|
4
|
+
import { path, RequestCache, sliceArrayBuffer } from '@loaders.gl/loader-utils';
|
|
5
5
|
import { Ellipsoid } from '@math.gl/geospatial';
|
|
6
|
-
import { Vector3 } from '@math.gl/core';
|
|
6
|
+
import { Matrix4, Vector3 } from '@math.gl/core';
|
|
7
7
|
import { Tileset3DTraverser } from "./tileset-3d-traverser.js";
|
|
8
8
|
import { Tile3D as Tile3DNode } from "../common/tile-3d.js";
|
|
9
9
|
import { getZoomFromBoundingVolume } from "../helpers/zoom.js";
|
|
10
10
|
import { TILESET_TYPE } from "../../constants.js";
|
|
11
|
+
import { get3DTilesSpatialReference } from "../../spatial/format-spatial-reference.js";
|
|
12
|
+
import { Tiles3DSpatialTransformer } from "../../spatial/tiles-3d-spatial-transformer.js";
|
|
13
|
+
import { applyTilesetSpatialOptions, markTilesetSpatialReferenceTransformed } from "../../spatial/spatial-types.js";
|
|
14
|
+
import { materializeImplicitSubtree } from "./implicit-tiling.js";
|
|
11
15
|
const EMPTY_CONTENT_FORMATS = {
|
|
12
16
|
draco: false,
|
|
13
17
|
meshopt: false,
|
|
14
18
|
dds: false,
|
|
15
19
|
ktx2: false
|
|
16
20
|
};
|
|
21
|
+
const DEFAULT_MAXIMUM_CACHED_SUBTREES = 32;
|
|
17
22
|
/**
|
|
18
23
|
* {@link Tileset3DSource} implementation for 3D Tiles datasets.
|
|
19
24
|
*/
|
|
@@ -45,9 +50,34 @@ export class Tiles3DSource {
|
|
|
45
50
|
/** Normalized source metadata after initialization. */
|
|
46
51
|
metadata;
|
|
47
52
|
queryParams = {};
|
|
53
|
+
/** Final request URLs cached by unmodified tile content URL. */
|
|
54
|
+
tileUrlCache = new Map();
|
|
55
|
+
/** Original content descriptors retained across {@link Tile3D.unloadContent} calls. */
|
|
56
|
+
tileContentHeaders = new WeakMap();
|
|
57
|
+
/** Installed nested roots by parent placement and ordered nested-content slot, across reloads. */
|
|
58
|
+
nestedTilesetRoots = new WeakMap();
|
|
59
|
+
/** Source-local namespaces assigned to distinct embedded glTF package file collections. */
|
|
60
|
+
packageNamespaces = new WeakMap();
|
|
61
|
+
/** Next source-local package namespace. */
|
|
62
|
+
nextPackageNamespace = 0;
|
|
63
|
+
/** Parsed subtree requests keyed by final source URL for deduplication and LRU reuse. */
|
|
64
|
+
implicitSubtreeCache;
|
|
65
|
+
/** Mutable counters exposed as a defensive snapshot through {@link getImplicitTilingStats}. */
|
|
66
|
+
implicitTilingStats = {
|
|
67
|
+
requestedSubtrees: 0,
|
|
68
|
+
loadedSubtrees: 0,
|
|
69
|
+
cacheHits: 0,
|
|
70
|
+
materializedTiles: 0
|
|
71
|
+
};
|
|
72
|
+
/** Whether the owning tileset has released this source. */
|
|
73
|
+
destroyed = false;
|
|
48
74
|
extensionsUsed = [];
|
|
49
75
|
resolver;
|
|
50
76
|
rootTileset;
|
|
77
|
+
/** CRS transformer shared by this source's headers and decoded glTF content. */
|
|
78
|
+
spatialTransformer;
|
|
79
|
+
/** Root header after composing source-frame transforms and rebuilding target bounds. */
|
|
80
|
+
preparedRootHeader;
|
|
51
81
|
/**
|
|
52
82
|
* Creates a 3D Tiles source.
|
|
53
83
|
* @param input Root metadata request, or preloaded root metadata for tests and internal callers.
|
|
@@ -63,6 +93,22 @@ export class Tiles3DSource {
|
|
|
63
93
|
this.resolver = request.resolver;
|
|
64
94
|
this.coreApi = request.coreApi;
|
|
65
95
|
this.loadOptions = loadOptions;
|
|
96
|
+
const maximumCachedSubtrees = Number(loadOptions['3d-tiles']?.maximumCachedSubtrees);
|
|
97
|
+
const maximumCacheEntries = Number.isFinite(maximumCachedSubtrees)
|
|
98
|
+
? Math.max(0, Math.floor(maximumCachedSubtrees))
|
|
99
|
+
: DEFAULT_MAXIMUM_CACHED_SUBTREES;
|
|
100
|
+
this.implicitSubtreeCache = new RequestCache({ maxEntries: maximumCacheEntries });
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Releases URL and parsed-subtree caches and blocks late subtree installation.
|
|
104
|
+
*
|
|
105
|
+
* The injected resolver or core API remains responsible for transport-level abort signals. A
|
|
106
|
+
* request that cannot be aborted may finish parsing, but it will not mutate destroyed tiles.
|
|
107
|
+
*/
|
|
108
|
+
destroy() {
|
|
109
|
+
this.destroyed = true;
|
|
110
|
+
this.tileUrlCache.clear();
|
|
111
|
+
this.implicitSubtreeCache.clear();
|
|
66
112
|
}
|
|
67
113
|
/**
|
|
68
114
|
* Fetches and validates top-level metadata, then normalizes common fields used by {@link Tileset3D}.
|
|
@@ -81,19 +127,22 @@ export class Tiles3DSource {
|
|
|
81
127
|
this.tileset = this.rootTileset;
|
|
82
128
|
if (this.rootTileset.queryString) {
|
|
83
129
|
const searchParams = new URLSearchParams(this.rootTileset.queryString);
|
|
84
|
-
|
|
130
|
+
for (const [parameterName, parameterValue] of searchParams.entries()) {
|
|
131
|
+
this.setQueryParameter(parameterName, parameterValue);
|
|
132
|
+
}
|
|
85
133
|
}
|
|
86
134
|
this.asset = this.rootTileset.asset;
|
|
87
135
|
if (!this.asset) {
|
|
88
136
|
throw new Error('Tileset must have an asset property.');
|
|
89
137
|
}
|
|
90
|
-
if (this.
|
|
138
|
+
if (this.rootTileset.formatVersion !== '2.0-draft' &&
|
|
139
|
+
this.asset.version !== '0.0' &&
|
|
91
140
|
this.asset.version !== '1.0' &&
|
|
92
141
|
this.asset.version !== '1.1') {
|
|
93
|
-
throw new Error('The tileset must be 3D Tiles version
|
|
142
|
+
throw new Error('The tileset must be 3D Tiles version 0.0, 1.0, 1.1, or 2.0-draft.');
|
|
94
143
|
}
|
|
95
144
|
if ('tilesetVersion' in this.asset) {
|
|
96
|
-
this.
|
|
145
|
+
this.setQueryParameter('v', this.asset.tilesetVersion);
|
|
97
146
|
}
|
|
98
147
|
this.properties = this.rootTileset.properties;
|
|
99
148
|
this.extras = this.rootTileset.extras;
|
|
@@ -107,7 +156,8 @@ export class Tiles3DSource {
|
|
|
107
156
|
tileset: this.rootTileset,
|
|
108
157
|
lodMetricType: this.rootTileset.lodMetricType,
|
|
109
158
|
lodMetricValue: this.rootTileset.lodMetricValue,
|
|
110
|
-
refine: this.rootTileset.root?.refine
|
|
159
|
+
refine: this.rootTileset.root?.refine,
|
|
160
|
+
spatialReference: get3DTilesSpatialReference(this.rootTileset)
|
|
111
161
|
};
|
|
112
162
|
}
|
|
113
163
|
/**
|
|
@@ -125,11 +175,26 @@ export class Tiles3DSource {
|
|
|
125
175
|
async getRootTileset() {
|
|
126
176
|
return this.getMetadata().tileset;
|
|
127
177
|
}
|
|
178
|
+
/** Prepare nonlinear CRS state before runtime headers are materialized. */
|
|
179
|
+
async prepareTileset(tileset) {
|
|
180
|
+
const spatialReference = tileset.spatialReference;
|
|
181
|
+
if (spatialReference.status === 'unresolved') {
|
|
182
|
+
throw new Error(spatialReference.warnings[0] ||
|
|
183
|
+
'3D Tiles spatial operations cannot be resolved from the supplied metadata and options');
|
|
184
|
+
}
|
|
185
|
+
if (spatialReference.status !== 'transformable' && spatialReference.status !== 'transformed') {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.spatialTransformer ||= new Tiles3DSpatialTransformer(spatialReference, tileset.options.spatial);
|
|
189
|
+
tileset.spatialReference = markTilesetSpatialReferenceTransformed(spatialReference);
|
|
190
|
+
this.preparedRootHeader = this.transformTileHeader(this.getMetadata().tileset.root, new Matrix4());
|
|
191
|
+
}
|
|
128
192
|
/**
|
|
129
|
-
* Builds
|
|
193
|
+
* Builds explicit runtime headers while leaving implicit subtree references lazy.
|
|
130
194
|
*/
|
|
131
195
|
initializeTileHeaders(tileset, tilesetJson, parentTile) {
|
|
132
|
-
const
|
|
196
|
+
const rootHeader = parentTile ? tilesetJson.root : this.preparedRootHeader || tilesetJson.root;
|
|
197
|
+
const rootTile = new Tile3DNode(tileset, rootHeader, parentTile || undefined);
|
|
133
198
|
if (parentTile) {
|
|
134
199
|
parentTile.children.push(rootTile);
|
|
135
200
|
rootTile.depth = parentTile.depth + 1;
|
|
@@ -145,7 +210,7 @@ export class Tiles3DSource {
|
|
|
145
210
|
const url = new URL(childTile.contentUrl);
|
|
146
211
|
const session = url.searchParams.get('session');
|
|
147
212
|
if (session) {
|
|
148
|
-
this.
|
|
213
|
+
this.setQueryParameter('session', session);
|
|
149
214
|
}
|
|
150
215
|
}
|
|
151
216
|
tile.children.push(childTile);
|
|
@@ -165,31 +230,179 @@ export class Tiles3DSource {
|
|
|
165
230
|
* Loads binary content or nested tileset JSON for a runtime tile.
|
|
166
231
|
*/
|
|
167
232
|
async loadTileContent(tile) {
|
|
168
|
-
const
|
|
233
|
+
const contentUrls = (tile.contentUrls || [tile.contentUrl]).filter(Boolean);
|
|
234
|
+
const cachedContentHeaders = this.tileContentHeaders.get(tile);
|
|
235
|
+
const contentHeaders = cachedContentHeaders ||
|
|
236
|
+
(Array.isArray(tile.header?.content)
|
|
237
|
+
? tile.header.content
|
|
238
|
+
: tile.header?.content
|
|
239
|
+
? [tile.header.content]
|
|
240
|
+
: []);
|
|
241
|
+
if (!cachedContentHeaders) {
|
|
242
|
+
this.tileContentHeaders.set(tile, contentHeaders);
|
|
243
|
+
}
|
|
169
244
|
const tilesetLoaderOptions = this.loadOptions[this.loader.id] || {};
|
|
170
245
|
const options = {
|
|
171
246
|
...this.loadOptions,
|
|
172
247
|
[this.loader.id]: {
|
|
173
248
|
...tilesetLoaderOptions,
|
|
174
|
-
|
|
175
|
-
|
|
249
|
+
// Content bytes, rather than URL suffixes, distinguish external tilesets from renderable
|
|
250
|
+
// payloads. This is required for signed and extensionless resources.
|
|
251
|
+
isTileset: 'auto',
|
|
252
|
+
assetGltfUpAxis: (this.asset && this.asset.gltfUpAxis) || 'Y',
|
|
253
|
+
_tilesetOptions: {
|
|
254
|
+
spatialReference: tile.header?._spatialReference || tile.tileset?.spatialReference,
|
|
255
|
+
spatialOptions: tile.tileset?.options.spatial,
|
|
256
|
+
spatialTransform: tile.header?._spatialTransform
|
|
257
|
+
}
|
|
176
258
|
}
|
|
177
259
|
};
|
|
178
|
-
const
|
|
179
|
-
|
|
260
|
+
const contents = await Promise.all(contentUrls.map((contentUrl, contentIndex) => {
|
|
261
|
+
const contentHeader = contentHeaders[contentIndex] || {};
|
|
262
|
+
const vectorExtension = contentHeader.extensions?.['3DTILES_content_gltf_vector'];
|
|
263
|
+
const vectorContent = contentHeader._vectorContent ||
|
|
264
|
+
(vectorExtension?.vector === true ? { clip: vectorExtension.clip === true } : undefined);
|
|
265
|
+
const contentOptions = vectorContent
|
|
266
|
+
? {
|
|
267
|
+
...options,
|
|
268
|
+
[this.loader.id]: {
|
|
269
|
+
...options[this.loader.id],
|
|
270
|
+
vectorContent
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
: options;
|
|
274
|
+
return this.loadContentResource(this.getTileUrl(contentUrl), contentHeader._resource, contentOptions);
|
|
275
|
+
}));
|
|
276
|
+
tile.contents = contents;
|
|
277
|
+
tile.content = contents[0] || null;
|
|
278
|
+
const nestedTilesets = contents.filter(content => content?.shape === 'tileset3d');
|
|
180
279
|
return {
|
|
181
280
|
loaded: true,
|
|
182
|
-
|
|
281
|
+
contents,
|
|
282
|
+
nestedTileset: nestedTilesets[0],
|
|
283
|
+
nestedTilesets
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/** Transform a tile header and its eagerly declared descendants. */
|
|
287
|
+
transformTileHeader(header, parentTransform = new Matrix4()) {
|
|
288
|
+
if (!this.spatialTransformer) {
|
|
289
|
+
return header;
|
|
290
|
+
}
|
|
291
|
+
return this.transformTileHeaderWithTransformer(header, this.spatialTransformer, parentTransform);
|
|
292
|
+
}
|
|
293
|
+
/** Rebuilds one header subtree using an explicitly selected CRS transformer. */
|
|
294
|
+
transformTileHeaderWithTransformer(header, transformer, parentTransform, spatialReference) {
|
|
295
|
+
const localTransform = header.transform ? new Matrix4(header.transform) : new Matrix4();
|
|
296
|
+
const composedTransform = new Matrix4(parentTransform).multiplyRight(localTransform);
|
|
297
|
+
const content = Array.isArray(header.content)
|
|
298
|
+
? header.content.map((entry) => this.transformContentHeader(entry, composedTransform, transformer))
|
|
299
|
+
: header.content
|
|
300
|
+
? this.transformContentHeader(header.content, composedTransform, transformer)
|
|
301
|
+
: header.content;
|
|
302
|
+
return {
|
|
303
|
+
...header,
|
|
304
|
+
transform: undefined,
|
|
305
|
+
boundingVolume: header.boundingVolume
|
|
306
|
+
? transformer.transformBoundingVolume(header.boundingVolume, composedTransform)
|
|
307
|
+
: header.boundingVolume,
|
|
308
|
+
_spatialReference: spatialReference,
|
|
309
|
+
_spatialTransform: composedTransform.toArray(),
|
|
310
|
+
content,
|
|
311
|
+
children: Array.isArray(header.children)
|
|
312
|
+
? header.children.map((child) => this.transformTileHeaderWithTransformer(child, transformer, composedTransform, spatialReference))
|
|
313
|
+
: header.children
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
transformContentHeader(content, composedTransform, transformer) {
|
|
317
|
+
return {
|
|
318
|
+
...content,
|
|
319
|
+
boundingVolume: content.boundingVolume
|
|
320
|
+
? transformer.transformBoundingVolume(content.boundingVolume, composedTransform)
|
|
321
|
+
: content.boundingVolume
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Loads, materializes, and installs exactly one implicit subtree.
|
|
326
|
+
*
|
|
327
|
+
* Final URLs pass through the same query inheritance and archive/custom resolver path as render
|
|
328
|
+
* content. Parsed resources are deduplicated by final URL, while the pure materializer creates
|
|
329
|
+
* lazy placeholders for every available child subtree instead of recursively fetching them.
|
|
330
|
+
*
|
|
331
|
+
* @param tile - Existing contentless subtree-root placeholder.
|
|
332
|
+
* @param frameState - View state that made this request eligible; priority is consumed earlier.
|
|
333
|
+
* @returns Counts describing the installed subtree.
|
|
334
|
+
*/
|
|
335
|
+
async loadTileChildren(tile, frameState) {
|
|
336
|
+
void frameState;
|
|
337
|
+
const reference = tile.header.implicitSubtree;
|
|
338
|
+
if (!reference) {
|
|
339
|
+
return { loaded: false, tileCount: 0, childSubtreeCount: 0 };
|
|
340
|
+
}
|
|
341
|
+
const subtreeUrl = this.getTileUrl(reference.subtreeUrl);
|
|
342
|
+
const subtree = await this.loadImplicitSubtreeResource(subtreeUrl, reference.resource);
|
|
343
|
+
if (this.destroyed || tile.isDestroyed()) {
|
|
344
|
+
return { loaded: false, tileCount: 0, childSubtreeCount: 0 };
|
|
345
|
+
}
|
|
346
|
+
const materializedSubtree = materializeImplicitSubtree(subtree, {
|
|
347
|
+
...reference,
|
|
348
|
+
subtreeUrl
|
|
349
|
+
});
|
|
350
|
+
const nestedSpatialReference = tile.header._spatialReference;
|
|
351
|
+
const subtreeTransformer = nestedSpatialReference
|
|
352
|
+
? new Tiles3DSpatialTransformer(nestedSpatialReference, tile.tileset.options.spatial)
|
|
353
|
+
: this.spatialTransformer;
|
|
354
|
+
const materializedRoot = subtreeTransformer
|
|
355
|
+
? this.transformTileHeaderWithTransformer(materializedSubtree.root, subtreeTransformer, new Matrix4(), nestedSpatialReference)
|
|
356
|
+
: materializedSubtree.root;
|
|
357
|
+
tile.applyImplicitSubtreeHeader(materializedRoot);
|
|
358
|
+
const materializedTileCount = this.initializeMaterializedChildren(tile.tileset, tile, materializedRoot.children);
|
|
359
|
+
this.implicitTilingStats.loadedSubtrees++;
|
|
360
|
+
this.implicitTilingStats.materializedTiles += materializedTileCount;
|
|
361
|
+
return {
|
|
362
|
+
loaded: true,
|
|
363
|
+
tileCount: materializedSubtree.tileCount,
|
|
364
|
+
childSubtreeCount: materializedSubtree.childSubtreeCount
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
/** Loads an implicit subtree for dataset traversal without camera state. */
|
|
368
|
+
async loadTileChildrenForTraversal(tile, signal) {
|
|
369
|
+
throwIfTraversalAborted(signal);
|
|
370
|
+
const result = await this.loadTileChildren(tile, {});
|
|
371
|
+
throwIfTraversalAborted(signal);
|
|
372
|
+
return result;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Returns a snapshot of implicit-subtree request, cache, and materialization counters.
|
|
376
|
+
*
|
|
377
|
+
* @returns Immutable-by-convention diagnostic values for runtime inspection.
|
|
378
|
+
*/
|
|
379
|
+
getImplicitTilingStats() {
|
|
380
|
+
return {
|
|
381
|
+
...this.implicitTilingStats,
|
|
382
|
+
cachedSubtrees: this.implicitSubtreeCache.size - this.implicitSubtreeCache.pendingSize,
|
|
383
|
+
pendingSubtrees: this.implicitSubtreeCache.pendingSize
|
|
183
384
|
};
|
|
184
385
|
}
|
|
185
386
|
/**
|
|
186
387
|
* Resolves a tile content URL with source-managed query parameters.
|
|
388
|
+
*
|
|
389
|
+
* Existing per-resource parameters take precedence over inherited root, version, and session
|
|
390
|
+
* values. Completed URLs are cached by the original tile path; {@link setQueryParameter}
|
|
391
|
+
* invalidates the cache before changed source state can be observed.
|
|
392
|
+
*
|
|
393
|
+
* @param tilePath - Unmodified absolute content URL or data URL from the tile header.
|
|
394
|
+
* @returns Content URL with any missing source parameters appended.
|
|
187
395
|
*/
|
|
188
396
|
getTileUrl(tilePath) {
|
|
189
397
|
if (tilePath.startsWith('data:')) {
|
|
190
398
|
return tilePath;
|
|
191
399
|
}
|
|
400
|
+
const cachedTileUrl = this.tileUrlCache.get(tilePath);
|
|
401
|
+
if (cachedTileUrl) {
|
|
402
|
+
return cachedTileUrl;
|
|
403
|
+
}
|
|
192
404
|
if (!Object.keys(this.queryParams).length) {
|
|
405
|
+
this.tileUrlCache.set(tilePath, tilePath);
|
|
193
406
|
return tilePath;
|
|
194
407
|
}
|
|
195
408
|
const [pathWithoutQuery, existingQuery = ''] = tilePath.split('?');
|
|
@@ -200,7 +413,26 @@ export class Tiles3DSource {
|
|
|
200
413
|
}
|
|
201
414
|
}
|
|
202
415
|
const queryParams = mergedQueryParams.toString();
|
|
203
|
-
|
|
416
|
+
const tileUrl = queryParams ? `${pathWithoutQuery}?${queryParams}` : pathWithoutQuery;
|
|
417
|
+
this.tileUrlCache.set(tilePath, tileUrl);
|
|
418
|
+
return tileUrl;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Updates an inherited source query parameter and invalidates derived request URLs.
|
|
422
|
+
*
|
|
423
|
+
* Root tokens and tileset versions normally settle during initialization. Some providers expose
|
|
424
|
+
* a session parameter on a child URL, so invalidation is required to prevent URLs cached earlier
|
|
425
|
+
* in header construction from retaining stale authentication state.
|
|
426
|
+
*
|
|
427
|
+
* @param parameterName - Query parameter name.
|
|
428
|
+
* @param parameterValue - Query parameter value.
|
|
429
|
+
*/
|
|
430
|
+
setQueryParameter(parameterName, parameterValue) {
|
|
431
|
+
if (this.queryParams[parameterName] === parameterValue) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
this.queryParams[parameterName] = parameterValue;
|
|
435
|
+
this.tileUrlCache.clear();
|
|
204
436
|
}
|
|
205
437
|
/**
|
|
206
438
|
* Derives the default view state from the root bounding volume.
|
|
@@ -241,10 +473,13 @@ export class Tiles3DSource {
|
|
|
241
473
|
return this.extensionsUsed.includes(extensionName);
|
|
242
474
|
}
|
|
243
475
|
/**
|
|
244
|
-
* Updates content-format flags and installs nested tileset subtrees.
|
|
476
|
+
* Updates content-format flags and installs nested tileset subtrees once per content slot.
|
|
477
|
+
* Reloading payloads retains attached roots and their descendants, including duplicate URLs
|
|
478
|
+
* declared in separate slots or parent placements. Detached roots are reinstalled in declaration order.
|
|
245
479
|
*/
|
|
246
480
|
onTileLoaded(tileset, tile, loadResult) {
|
|
247
|
-
const
|
|
481
|
+
const contents = tile.contents.length ? tile.contents : [tile.content];
|
|
482
|
+
const extensionsRemoved = contents.flatMap(content => content?.gltf?.extensionsRemoved || []);
|
|
248
483
|
if (extensionsRemoved.includes('KHR_draco_mesh_compression')) {
|
|
249
484
|
this.contentFormats.draco = true;
|
|
250
485
|
}
|
|
@@ -254,18 +489,91 @@ export class Tiles3DSource {
|
|
|
254
489
|
if (extensionsRemoved.includes('KHR_texture_basisu')) {
|
|
255
490
|
this.contentFormats.ktx2 = true;
|
|
256
491
|
}
|
|
257
|
-
|
|
258
|
-
|
|
492
|
+
const nestedTilesets = loadResult.nestedTilesets || (loadResult.nestedTileset ? [loadResult.nestedTileset] : []);
|
|
493
|
+
const installedRoots = this.nestedTilesetRoots.get(tile) || [];
|
|
494
|
+
for (const [nestedIndex, nestedTileset] of nestedTilesets.entries()) {
|
|
495
|
+
const installedRoot = installedRoots[nestedIndex];
|
|
496
|
+
if (installedRoot && tile.children.includes(installedRoot)) {
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
const nextRoot = installedRoots
|
|
500
|
+
.slice(nestedIndex + 1)
|
|
501
|
+
.find(root => tile.children.includes(root));
|
|
502
|
+
const nestedRoot = tileset._initializeTileHeaders(this.prepareNestedTileset(tileset, nestedTileset), tile);
|
|
503
|
+
// Header installation appends roots; restore declaration order before any later retained slot.
|
|
504
|
+
if (nextRoot) {
|
|
505
|
+
tile.children.splice(tile.children.indexOf(nestedRoot), 1);
|
|
506
|
+
tile.children.splice(tile.children.indexOf(nextRoot), 0, nestedRoot);
|
|
507
|
+
}
|
|
508
|
+
installedRoots[nestedIndex] = nestedRoot;
|
|
509
|
+
this.nestedTilesetRoots.set(tile, installedRoots);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Resolves a nested tileset's CRS independently and adapts it to the owning tileset output frame.
|
|
514
|
+
*
|
|
515
|
+
* Nested resources may use a different source CRS from their parent. Their headers and glTF
|
|
516
|
+
* payloads must therefore use a transformer built from the nested descriptor, while the parent
|
|
517
|
+
* runtime continues to expose one requested output frame to traversal and rendering.
|
|
518
|
+
*/
|
|
519
|
+
prepareNestedTileset(tileset, nestedTileset) {
|
|
520
|
+
const nestedSpatialReference = nestedTileset.spatialMetadata;
|
|
521
|
+
const parentSpatialReference = tileset.spatialReference;
|
|
522
|
+
if (nestedSpatialReference?.status === 'unresolved' ||
|
|
523
|
+
nestedSpatialReference?.crs.state === 'unknown') {
|
|
524
|
+
throw new Error(nestedSpatialReference.warnings[0] ||
|
|
525
|
+
'Nested 3D Tiles CRS is explicitly unresolved and cannot be placed in the parent frame');
|
|
526
|
+
}
|
|
527
|
+
if (!nestedSpatialReference || !nestedSpatialReference.sourceCrs) {
|
|
528
|
+
if (this.spatialTransformer &&
|
|
529
|
+
(parentSpatialReference.status === 'transformable' ||
|
|
530
|
+
parentSpatialReference.status === 'transformed')) {
|
|
531
|
+
return {
|
|
532
|
+
...nestedTileset,
|
|
533
|
+
spatialMetadata: parentSpatialReference,
|
|
534
|
+
root: this.transformTileHeaderWithTransformer(nestedTileset.root, this.spatialTransformer, new Matrix4(), parentSpatialReference)
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
return addNestedSpatialReference(nestedTileset, parentSpatialReference);
|
|
538
|
+
}
|
|
539
|
+
const parentCoordinateEpoch = parentSpatialReference.coordinateEpoch;
|
|
540
|
+
const nestedCoordinateEpoch = nestedSpatialReference.coordinateEpoch;
|
|
541
|
+
if (parentCoordinateEpoch !== undefined &&
|
|
542
|
+
nestedCoordinateEpoch !== undefined &&
|
|
543
|
+
parentCoordinateEpoch !== nestedCoordinateEpoch) {
|
|
544
|
+
throw new Error(`Nested 3D Tiles coordinate epoch ${nestedCoordinateEpoch} differs from parent epoch ${parentCoordinateEpoch}; epoch-aware transformation is unavailable`);
|
|
545
|
+
}
|
|
546
|
+
const outputCrs = parentSpatialReference.targetCrs || parentSpatialReference.sourceCrs;
|
|
547
|
+
if (!outputCrs) {
|
|
548
|
+
return addNestedSpatialReference(nestedTileset, nestedSpatialReference);
|
|
549
|
+
}
|
|
550
|
+
const nestedOutputReference = applyTilesetSpatialOptions(nestedSpatialReference, {
|
|
551
|
+
...tileset.options.spatial,
|
|
552
|
+
outputCoordinates: 'target-crs',
|
|
553
|
+
targetCrs: outputCrs
|
|
554
|
+
});
|
|
555
|
+
if (nestedOutputReference.status === 'unresolved') {
|
|
556
|
+
throw new Error(nestedOutputReference.warnings[0] ||
|
|
557
|
+
'Nested 3D Tiles CRS cannot be resolved in the parent output frame');
|
|
558
|
+
}
|
|
559
|
+
if (nestedOutputReference.status === 'native') {
|
|
560
|
+
return addNestedSpatialReference(nestedTileset, nestedOutputReference);
|
|
259
561
|
}
|
|
562
|
+
const nestedTransformer = new Tiles3DSpatialTransformer(nestedOutputReference, tileset.options.spatial);
|
|
563
|
+
return {
|
|
564
|
+
...nestedTileset,
|
|
565
|
+
spatialMetadata: nestedOutputReference,
|
|
566
|
+
root: this.transformTileHeaderWithTransformer(nestedTileset.root, nestedTransformer, new Matrix4(), nestedOutputReference)
|
|
567
|
+
};
|
|
260
568
|
}
|
|
261
569
|
/**
|
|
262
570
|
* Loads data through injected core APIs so this module stays independent from `@loaders.gl/core`.
|
|
263
571
|
*/
|
|
264
|
-
async loadWithCoreApi(url, options) {
|
|
572
|
+
async loadWithCoreApi(url, options, loader = this.loader) {
|
|
265
573
|
if (!this.coreApi) {
|
|
266
574
|
throw new Error('Tiles3DSource requires an injected coreApi to load tileset data');
|
|
267
575
|
}
|
|
268
|
-
return await this.coreApi.load(url,
|
|
576
|
+
return await this.coreApi.load(url, loader, options);
|
|
269
577
|
}
|
|
270
578
|
/**
|
|
271
579
|
* Loads data through an injected resolver when present, otherwise through the injected core API.
|
|
@@ -277,13 +585,150 @@ export class Tiles3DSource {
|
|
|
277
585
|
return await this.loadWithCoreApi(url, options);
|
|
278
586
|
}
|
|
279
587
|
/**
|
|
280
|
-
* Loads
|
|
588
|
+
* Loads an arbitrary source resource through an injected resolver or core API.
|
|
281
589
|
*/
|
|
282
|
-
async loadResourceData(url, options) {
|
|
590
|
+
async loadResourceData(url, options, loader = this.loader) {
|
|
283
591
|
if (this.resolver) {
|
|
284
|
-
return await this.resolver.loadResource(url,
|
|
592
|
+
return await this.resolver.loadResource(url, loader, options);
|
|
285
593
|
}
|
|
286
|
-
return await this.loadWithCoreApi(url, options);
|
|
594
|
+
return await this.loadWithCoreApi(url, options, loader);
|
|
595
|
+
}
|
|
596
|
+
/** Loads a URL content reference or parses a buffer-view file retained from a glTF package. */
|
|
597
|
+
async loadContentResource(url, packageResource, options) {
|
|
598
|
+
if (!packageResource) {
|
|
599
|
+
return await this.loadResourceData(url, options);
|
|
600
|
+
}
|
|
601
|
+
const file = packageResource.files[packageResource.fileIndex];
|
|
602
|
+
if (!file) {
|
|
603
|
+
throw new Error(`3D Tiles package references missing file ${packageResource.fileIndex}`);
|
|
604
|
+
}
|
|
605
|
+
if (file.uri) {
|
|
606
|
+
return await this.loadResourceData(this.getTileUrl(file.uri), options);
|
|
607
|
+
}
|
|
608
|
+
if (!this.coreApi) {
|
|
609
|
+
throw new Error('Tiles3DSource requires an injected coreApi to parse embedded package data');
|
|
610
|
+
}
|
|
611
|
+
const data = await this.getPackageFileData(file);
|
|
612
|
+
const packageNamespace = this.getPackageNamespace(packageResource.files);
|
|
613
|
+
const packageRootUrl = `gltf-package://${packageNamespace}/${packageResource.fileIndex}`;
|
|
614
|
+
const fileName = file.name || 'content';
|
|
615
|
+
const directorySeparatorIndex = fileName.lastIndexOf('/');
|
|
616
|
+
const packageBaseUrl = directorySeparatorIndex >= 0
|
|
617
|
+
? `${packageRootUrl}/${fileName.slice(0, directorySeparatorIndex)}`
|
|
618
|
+
: packageRootUrl;
|
|
619
|
+
return await this.coreApi.parse(data, this.loader, options, {
|
|
620
|
+
url: `${packageRootUrl}/${fileName}`,
|
|
621
|
+
filename: fileName,
|
|
622
|
+
baseUrl: packageBaseUrl,
|
|
623
|
+
loaders: [this.loader],
|
|
624
|
+
coreApi: this.coreApi,
|
|
625
|
+
_parse: this.coreApi.parse,
|
|
626
|
+
_tiles3dPackageFiles: packageResource.files,
|
|
627
|
+
fetch: async (resource, init) => {
|
|
628
|
+
const reference = resource.startsWith(`${packageRootUrl}/`)
|
|
629
|
+
? resource.slice(packageRootUrl.length + 1)
|
|
630
|
+
: resource;
|
|
631
|
+
const referencedFile = packageResource.files.find(packageFile => packageFile.name === reference || packageFile.originalUri === reference);
|
|
632
|
+
if (!referencedFile) {
|
|
633
|
+
throw new Error(`3D Tiles glTF package does not contain file ${reference}`);
|
|
634
|
+
}
|
|
635
|
+
if (referencedFile.uri) {
|
|
636
|
+
return await this.coreApi.fetchFile(this.getTileUrl(referencedFile.uri), init);
|
|
637
|
+
}
|
|
638
|
+
const referencedData = await this.getPackageFileData(referencedFile);
|
|
639
|
+
return new Response(referencedData, {
|
|
640
|
+
headers: { 'content-type': referencedFile.mimeType }
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
/** Returns a stable source-local namespace for one embedded glTF package file collection. */
|
|
646
|
+
getPackageNamespace(files) {
|
|
647
|
+
const existingNamespace = this.packageNamespaces.get(files);
|
|
648
|
+
if (existingNamespace !== undefined) {
|
|
649
|
+
return existingNamespace;
|
|
650
|
+
}
|
|
651
|
+
const packageNamespace = this.nextPackageNamespace++;
|
|
652
|
+
this.packageNamespaces.set(files, packageNamespace);
|
|
653
|
+
return packageNamespace;
|
|
654
|
+
}
|
|
655
|
+
/** Resolves a retained package-file byte range without eagerly copying other package files. */
|
|
656
|
+
async getPackageFileData(file) {
|
|
657
|
+
if (file.data) {
|
|
658
|
+
return sliceArrayBuffer(file.data, file.byteOffset, file.byteLength);
|
|
659
|
+
}
|
|
660
|
+
if (file.bufferUri && this.coreApi) {
|
|
661
|
+
const response = await this.coreApi.fetchFile(this.getTileUrl(file.bufferUri));
|
|
662
|
+
if (!response.ok) {
|
|
663
|
+
throw new Error(`Failed to fetch 3D Tiles package buffer: HTTP ${response.status}`);
|
|
664
|
+
}
|
|
665
|
+
const buffer = await response.arrayBuffer();
|
|
666
|
+
return sliceArrayBuffer(buffer, file.byteOffset, file.byteLength);
|
|
667
|
+
}
|
|
668
|
+
throw new Error('3D Tiles package file has no available byte source');
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Returns a parsed subtree from the LRU cache or starts one source-managed request.
|
|
672
|
+
*
|
|
673
|
+
* @param subtreeUrl - Final subtree URL after query inheritance.
|
|
674
|
+
* @param packageResource - Optional glTF package file satisfying the subtree reference.
|
|
675
|
+
* @returns Parsed subtree availability data.
|
|
676
|
+
*/
|
|
677
|
+
async loadImplicitSubtreeResource(subtreeUrl, packageResource) {
|
|
678
|
+
const cachedSubtree = this.implicitSubtreeCache.get(subtreeUrl);
|
|
679
|
+
if (cachedSubtree) {
|
|
680
|
+
this.implicitTilingStats.cacheHits++;
|
|
681
|
+
return await cachedSubtree;
|
|
682
|
+
}
|
|
683
|
+
this.implicitTilingStats.requestedSubtrees++;
|
|
684
|
+
const loaderOptions = this.loadOptions[this.loader.id] || {};
|
|
685
|
+
return await this.implicitSubtreeCache.getOrLoad(subtreeUrl, async () => {
|
|
686
|
+
const options = {
|
|
687
|
+
...this.loadOptions,
|
|
688
|
+
[this.loader.id]: {
|
|
689
|
+
...loaderOptions,
|
|
690
|
+
isTileset: false,
|
|
691
|
+
isSubtree: true
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
return (await (packageResource
|
|
695
|
+
? this.loadContentResource(subtreeUrl, packageResource, options)
|
|
696
|
+
: this.loadResourceData(subtreeUrl, options)));
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Instantiates every header represented by one materialized subtree.
|
|
701
|
+
*
|
|
702
|
+
* @param tileset - Owning runtime tileset.
|
|
703
|
+
* @param parentTile - Existing materialized parent.
|
|
704
|
+
* @param childHeaders - Headers to install below the parent.
|
|
705
|
+
* @returns Number of newly allocated runtime tile nodes.
|
|
706
|
+
*/
|
|
707
|
+
initializeMaterializedChildren(tileset, parentTile, childHeaders) {
|
|
708
|
+
let materializedTileCount = 0;
|
|
709
|
+
const stack = [
|
|
710
|
+
{ parentTile, childHeaders }
|
|
711
|
+
];
|
|
712
|
+
while (stack.length > 0) {
|
|
713
|
+
const entry = stack.pop();
|
|
714
|
+
for (const childHeader of entry.childHeaders) {
|
|
715
|
+
const childTile = new Tile3DNode(tileset, childHeader, entry.parentTile);
|
|
716
|
+
entry.parentTile.children.push(childTile);
|
|
717
|
+
childTile.depth = entry.parentTile.depth + 1;
|
|
718
|
+
tileset.stats.get('Tiles In Tileset(s)').incrementCount();
|
|
719
|
+
materializedTileCount++;
|
|
720
|
+
if (childHeader.children?.length) {
|
|
721
|
+
stack.push({ parentTile: childTile, childHeaders: childHeader.children });
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return materializedTileCount;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
/** Throws a cancellation reason before or after source-managed traversal work. */
|
|
729
|
+
function throwIfTraversalAborted(signal) {
|
|
730
|
+
if (signal?.aborted) {
|
|
731
|
+
throw signal.reason ?? new DOMException('The operation was aborted', 'AbortError');
|
|
287
732
|
}
|
|
288
733
|
}
|
|
289
734
|
function isTilesetRequest(input) {
|
|
@@ -309,4 +754,17 @@ function normalizeTiles3DRequest(input) {
|
|
|
309
754
|
coreApi: input.coreApi
|
|
310
755
|
};
|
|
311
756
|
}
|
|
757
|
+
/** Adds a nested CRS descriptor to each header without changing its native placement. */
|
|
758
|
+
function addNestedSpatialReference(nestedTileset, spatialReference) {
|
|
759
|
+
const addToHeader = (header) => ({
|
|
760
|
+
...header,
|
|
761
|
+
_spatialReference: spatialReference,
|
|
762
|
+
children: Array.isArray(header.children) ? header.children.map(addToHeader) : header.children
|
|
763
|
+
});
|
|
764
|
+
return {
|
|
765
|
+
...nestedTileset,
|
|
766
|
+
spatialMetadata: spatialReference,
|
|
767
|
+
root: addToHeader(nestedTileset.root)
|
|
768
|
+
};
|
|
769
|
+
}
|
|
312
770
|
//# sourceMappingURL=tiles-3d-source.js.map
|