@loaders.gl/tiles 5.0.0-alpha.10 → 5.0.0-alpha.12

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.
Files changed (80) hide show
  1. package/dist/dist.dev.js +37183 -19131
  2. package/dist/dist.min.js +22 -3
  3. package/dist/index.cjs +620 -2027
  4. package/dist/index.cjs.map +4 -3
  5. package/dist/index.d.ts +3 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/point-cloud-tile-source-loader-types.d.ts +31 -0
  10. package/dist/point-cloud-tile-source-loader-types.d.ts.map +1 -0
  11. package/dist/point-cloud-tile-source-loader-types.js +34 -0
  12. package/dist/point-cloud-tile-source-loader-types.js.map +1 -0
  13. package/dist/point-cloud-tile-source-loader.cjs +81 -0
  14. package/dist/point-cloud-tile-source-loader.cjs.map +7 -0
  15. package/dist/point-cloud-tile-source-loader.d.ts +27 -0
  16. package/dist/point-cloud-tile-source-loader.d.ts.map +1 -0
  17. package/dist/point-cloud-tile-source-loader.js +17 -0
  18. package/dist/point-cloud-tile-source-loader.js.map +1 -0
  19. package/dist/point-cloud-tile-source-types.d.ts +15 -0
  20. package/dist/point-cloud-tile-source-types.d.ts.map +1 -0
  21. package/dist/point-cloud-tile-source-types.js +5 -0
  22. package/dist/point-cloud-tile-source-types.js.map +1 -0
  23. package/dist/point-cloud-tile-source.cjs +105 -0
  24. package/dist/point-cloud-tile-source.cjs.map +7 -0
  25. package/dist/point-cloud-tile-source.d.ts +36 -0
  26. package/dist/point-cloud-tile-source.d.ts.map +1 -0
  27. package/dist/point-cloud-tile-source.js +84 -0
  28. package/dist/point-cloud-tile-source.js.map +1 -0
  29. package/dist/spatial/i3s-spatial-transformer.d.ts +16 -0
  30. package/dist/spatial/i3s-spatial-transformer.d.ts.map +1 -1
  31. package/dist/spatial/i3s-spatial-transformer.js +45 -0
  32. package/dist/spatial/i3s-spatial-transformer.js.map +1 -1
  33. package/dist/spatial/spatial-coordinate-transformer.d.ts +3 -1
  34. package/dist/spatial/spatial-coordinate-transformer.d.ts.map +1 -1
  35. package/dist/spatial/spatial-coordinate-transformer.js +25 -9
  36. package/dist/spatial/spatial-coordinate-transformer.js.map +1 -1
  37. package/dist/spatial/spatial-resource-registry.d.ts +3 -0
  38. package/dist/spatial/spatial-resource-registry.d.ts.map +1 -1
  39. package/dist/spatial/spatial-resource-registry.js +12 -3
  40. package/dist/spatial/spatial-resource-registry.js.map +1 -1
  41. package/dist/spatial/tiles-3d-spatial-transformer.d.ts.map +1 -1
  42. package/dist/spatial/tiles-3d-spatial-transformer.js +0 -12
  43. package/dist/spatial/tiles-3d-spatial-transformer.js.map +1 -1
  44. package/dist/tileset-2d.d.ts +2 -1
  45. package/dist/tileset-2d.d.ts.map +1 -1
  46. package/dist/tileset-2d.js +1 -1
  47. package/dist/tileset-2d.js.map +1 -1
  48. package/dist/tileset-3d/common/tileset-3d.d.ts +10 -1
  49. package/dist/tileset-3d/common/tileset-3d.d.ts.map +1 -1
  50. package/dist/tileset-3d/common/tileset-3d.js +42 -9
  51. package/dist/tileset-3d/common/tileset-3d.js.map +1 -1
  52. package/dist/tileset-3d/common/tileset-traverser.d.ts.map +1 -1
  53. package/dist/tileset-3d/common/tileset-traverser.js +2 -3
  54. package/dist/tileset-3d/common/tileset-traverser.js.map +1 -1
  55. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.d.ts.map +1 -1
  56. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js +0 -3
  57. package/dist/tileset-3d/format-3d-tiles/implicit-tiling.js.map +1 -1
  58. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts +1 -0
  59. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.d.ts.map +1 -1
  60. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js +12 -4
  61. package/dist/tileset-3d/format-3d-tiles/tileset-3d-traverser.js.map +1 -1
  62. package/dist/tileset-3d/helpers/s2-bounding-volume.d.ts.map +1 -1
  63. package/dist/tileset-3d/helpers/s2-bounding-volume.js +0 -3
  64. package/dist/tileset-3d/helpers/s2-bounding-volume.js.map +1 -1
  65. package/package.json +25 -13
  66. package/src/index.ts +8 -1
  67. package/src/point-cloud-tile-source-loader-types.ts +53 -0
  68. package/src/point-cloud-tile-source-loader.ts +32 -0
  69. package/src/point-cloud-tile-source-types.ts +20 -0
  70. package/src/point-cloud-tile-source.ts +112 -0
  71. package/src/spatial/i3s-spatial-transformer.ts +64 -0
  72. package/src/spatial/spatial-coordinate-transformer.ts +30 -9
  73. package/src/spatial/spatial-resource-registry.ts +14 -3
  74. package/src/spatial/tiles-3d-spatial-transformer.ts +0 -12
  75. package/src/tileset-2d.ts +25 -1
  76. package/src/tileset-3d/common/tileset-3d.ts +56 -12
  77. package/src/tileset-3d/common/tileset-traverser.ts +2 -4
  78. package/src/tileset-3d/format-3d-tiles/implicit-tiling.ts +0 -3
  79. package/src/tileset-3d/format-3d-tiles/tileset-3d-traverser.ts +16 -4
  80. package/src/tileset-3d/helpers/s2-bounding-volume.ts +0 -3
package/src/tileset-2d.ts CHANGED
@@ -2,4 +2,28 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- export * from './tileset-2d/index';
5
+ export {
6
+ SharedTile2DHeader,
7
+ Tileset2D,
8
+ STRATEGY_DEFAULT,
9
+ STRATEGY_NEVER,
10
+ STRATEGY_REPLACE
11
+ } from './tileset-2d/index';
12
+ export type {
13
+ Bounds,
14
+ GeoBoundingBox,
15
+ NonGeoBoundingBox,
16
+ TileBoundingBox,
17
+ TileIndex,
18
+ TileLoadProps,
19
+ ZRange,
20
+ Tileset2DAdapter,
21
+ Tileset2DTileContext,
22
+ Tileset2DTraversalContext,
23
+ Tile2DLoadDataProps,
24
+ RefinementStrategy,
25
+ RefinementStrategyFunction,
26
+ Tileset2DBaseProps,
27
+ Tileset2DProps,
28
+ Tile2DListener
29
+ } from './tileset-2d/index';
@@ -41,6 +41,8 @@ import {
41
41
  export type {TilesetJSON} from './tileset-source';
42
42
 
43
43
  export type Tileset3DProps = {
44
+ /** Format options forwarded to I3S content requests, including source-coordinate decoding. */
45
+ i3s?: Record<string, unknown>;
44
46
  throttleRequests?: boolean;
45
47
  maxRequests?: number;
46
48
  loadOptions?: LoaderOptions;
@@ -73,7 +75,7 @@ export type Tileset3DProps = {
73
75
  /**
74
76
  * Enables replacement traversal that may skip hierarchy levels while retaining ready ancestors
75
77
  * as coverage. This trades temporary overdraw for faster refinement on deep trees.
76
- * @default false
78
+ * Defaults to `true` for 3D Tiles and `false` for I3S. Set to `false` to request every level.
77
79
  */
78
80
  skipLevelOfDetail?: boolean;
79
81
  /**
@@ -393,7 +395,8 @@ export class Tileset3D {
393
395
  _cache = new TilesetCache();
394
396
  _requestScheduler: RequestScheduler;
395
397
 
396
- private _heldTiles: Set<string> = new Set();
398
+ /** Drawn fallback instances retained independently for each viewport tree. */
399
+ private _heldTiles: Set<Tile3D> = new Set();
397
400
  private updatePromise: Promise<number> | null = null;
398
401
  tilesetInitializationPromise: Promise<void>;
399
402
 
@@ -425,6 +428,7 @@ export class Tileset3D {
425
428
  ...suppliedOptions,
426
429
  cacheBytes,
427
430
  maximumCacheOverflowBytes,
431
+ skipLevelOfDetail: suppliedOptions.skipLevelOfDetail ?? source.type === TILESET_TYPE.TILES3D,
428
432
  memoryAdjustedScreenSpaceError:
429
433
  suppliedOptions.memoryAdjustedScreenSpaceError ?? usesTiles3DCacheDefaults
430
434
  };
@@ -782,28 +786,50 @@ export class Tileset3D {
782
786
 
783
787
  this.selectedTiles = this.options.onTraversalComplete(this.selectedTiles);
784
788
 
785
- const selectedIds = new Set(this.selectedTiles.map(tile => tile.id));
789
+ const selectedTiles = new Set(this.selectedTiles);
786
790
  const hasUndrawnTiles = this.selectedTiles.some(tile => !tile.tileDrawn);
787
791
 
788
792
  let heldBackCount = 0;
789
793
  if (hasUndrawnTiles) {
790
- for (const tileId of selectedIds) {
791
- this._heldTiles.add(tileId);
794
+ const activeRoots = new Set(
795
+ Object.keys(this.frameStateData).map(viewportId => this.roots[viewportId])
796
+ );
797
+ const descendantReadiness = new Map<Tile3D, boolean>();
798
+ for (const tile of this.selectedTiles) {
799
+ for (let ancestor = tile.parent; ancestor; ancestor = ancestor.parent) {
800
+ descendantReadiness.set(
801
+ ancestor,
802
+ (descendantReadiness.get(ancestor) ?? true) && tile.tileDrawn
803
+ );
804
+ }
792
805
  }
793
- for (const tileId of this._heldTiles) {
794
- if (selectedIds.has(tileId)) continue;
795
-
796
- const tile = this._tiles[tileId];
797
- if (tile && tile.contentAvailable) {
806
+ // Drawing can finish between traversals. Promote only previously selected
807
+ // geometry that actually drew; pending tiles cannot provide visible fallback.
808
+ for (const tile of previousSelectedTiles) {
809
+ if (tile.tileDrawn) this._heldTiles.add(tile);
810
+ }
811
+ for (const tile of this._heldTiles) {
812
+ let root = tile;
813
+ while (root.parent) root = root.parent;
814
+ // Removed viewport trees cannot contribute fallback to the remaining views.
815
+ if (!activeRoots.has(root)) {
816
+ this._heldTiles.delete(tile);
817
+ continue;
818
+ }
819
+ if (selectedTiles.has(tile)) continue;
820
+ if (
821
+ tile.contentAvailable &&
822
+ !this._hasDrawnReplacement(tile, selectedTiles, descendantReadiness)
823
+ ) {
798
824
  tile._selectedFrame = this._frameNumber;
799
825
  this.selectedTiles.push(tile);
800
826
  heldBackCount++;
801
827
  } else {
802
- this._heldTiles.delete(tileId);
828
+ this._heldTiles.delete(tile);
803
829
  }
804
830
  }
805
831
  } else {
806
- this._heldTiles = selectedIds;
832
+ this._heldTiles = selectedTiles;
807
833
  }
808
834
 
809
835
  if (heldBackCount > 0) {
@@ -825,6 +851,24 @@ export class Tileset3D {
825
851
  }
826
852
  }
827
853
 
854
+ /**
855
+ * Releases fallback geometry once its own selected replacement has drawn.
856
+ * Unrelated pending branches must not delay this region's handoff. When no related
857
+ * replacement is selected, retain the fallback until the complete selection has drawn.
858
+ */
859
+ private _hasDrawnReplacement(
860
+ tile: Tile3D,
861
+ selectedTiles: Set<Tile3D>,
862
+ descendantReadiness: Map<Tile3D, boolean>
863
+ ): boolean {
864
+ for (let ancestor = tile.parent; ancestor; ancestor = ancestor.parent) {
865
+ if (selectedTiles.has(ancestor)) {
866
+ return ancestor.tileDrawn;
867
+ }
868
+ }
869
+ return descendantReadiness.get(tile) === true;
870
+ }
871
+
828
872
  _tilesChanged(oldSelectedTiles: Tile3D[], selectedTiles: Tile3D[]): boolean {
829
873
  if (oldSelectedTiles.length !== selectedTiles.length) {
830
874
  return true;
@@ -236,11 +236,9 @@ export class TilesetTraverser {
236
236
  } else {
237
237
  childRefines = child.contentAvailable;
238
238
  }
239
+ // Readiness controls replacement, not discovery. Visit every sibling so
240
+ // one unavailable child cannot serialize requests or hide ready siblings.
239
241
  refines = refines && childRefines;
240
-
241
- if (!refines) {
242
- return false;
243
- }
244
242
  }
245
243
  }
246
244
 
@@ -3,9 +3,6 @@
3
3
  // Copyright vis.gl contributors
4
4
 
5
5
  import {LOD_METRIC_TYPE, TILE_REFINEMENT, TILE_TYPE} from '../../constants';
6
- // TypeScript's legacy `node` resolution does not inspect package `exports`, but this public
7
- // subpath is resolved by the package at runtime and avoids loading unrelated DGGS decoders.
8
- // @ts-expect-error Conditional package subpath exports require a modern module resolver.
9
6
  import {getS2DescendantIndex, getS2IndexFromToken, getS2TokenFromIndex} from '@math.gl/dggs/s2';
10
7
  import {convertS2BoundingVolumeToOBB, type S2VolumeInfo} from '../helpers/s2-bounding-volume';
11
8
 
@@ -70,7 +70,9 @@ export class Tileset3DTraverser extends TilesetTraverser {
70
70
  if (!tile.hasRenderContent) {
71
71
  this.emptyTiles[tile.id] = tile;
72
72
  this.loadTile(tile, frameState);
73
- if (stoppedRefining) {
73
+ // A known empty terminal branch needs no fallback geometry. Lazy child groups still
74
+ // report hasChildren while unresolved, so they retain coverage until materialized.
75
+ if (stoppedRefining && (!tile.hasEmptyContent || tile.hasChildren)) {
74
76
  this.selectDesiredTile(tile, frameState);
75
77
  }
76
78
  } else if (tile.refine === TILE_REFINEMENT.ADD) {
@@ -121,7 +123,7 @@ export class Tileset3DTraverser extends TilesetTraverser {
121
123
  if (child.isVisibleAndInRequestVolume) {
122
124
  stack.push(child);
123
125
  hasVisibleChild = true;
124
- } else if (this.options.loadSiblings) {
126
+ } else if (this.options.loadSiblings && child._inRequestVolume) {
125
127
  this.loadTile(child, frameState);
126
128
  this.touchTile(child, frameState);
127
129
  }
@@ -234,6 +236,11 @@ export class Tileset3DTraverser extends TilesetTraverser {
234
236
  while (fallbackTile) {
235
237
  if (this.shouldSelectTile(fallbackTile, frameState)) {
236
238
  this.selectTile(fallbackTile, frameState);
239
+ if (fallbackTile !== tile) {
240
+ // On zoom-out the desired coarse level may still be unavailable. Preserve
241
+ // nearby detail that already drew while the ancestor fills uncovered pixels.
242
+ this.selectLoadedDescendants(tile, frameState, true);
243
+ }
237
244
  return;
238
245
  }
239
246
  fallbackTile = fallbackTile.parent;
@@ -246,8 +253,13 @@ export class Tileset3DTraverser extends TilesetTraverser {
246
253
  *
247
254
  * @param root - Unavailable tile whose descendants are searched.
248
255
  * @param frameState - Current culling state.
256
+ * @param drawnOnly - Reuse drawn detail without starting obsolete GPU work.
249
257
  */
250
- private selectLoadedDescendants(root: Tile3D, frameState: FrameState): void {
258
+ private selectLoadedDescendants(
259
+ root: Tile3D,
260
+ frameState: FrameState,
261
+ drawnOnly: boolean = false
262
+ ): void {
251
263
  const stack: Array<{tile: Tile3D; depth: number}> = [{tile: root, depth: 0}];
252
264
  while (stack.length > 0) {
253
265
  const {tile, depth} = stack.pop() as {tile: Tile3D; depth: number};
@@ -256,7 +268,7 @@ export class Tileset3DTraverser extends TilesetTraverser {
256
268
  if (!child.isVisibleAndInRequestVolume) {
257
269
  continue;
258
270
  }
259
- if (child.contentAvailable) {
271
+ if (this.shouldSelectTile(child, frameState) && (!drawnOnly || child.tileDrawn)) {
260
272
  this.selectTile(child, frameState);
261
273
  this.touchTile(child, frameState);
262
274
  } else if (depth < 1) {
@@ -2,9 +2,6 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright vis.gl contributors
4
4
 
5
- // TypeScript's legacy `node` resolution does not inspect package `exports`, but this public
6
- // subpath is resolved by the package at runtime and avoids loading unrelated DGGS decoders.
7
- // @ts-expect-error Conditional package subpath exports require a modern module resolver.
8
5
  import {getS2Bounds} from '@math.gl/dggs/s2';
9
6
  import {Ellipsoid, makeOBBFromRegion} from '@math.gl/geospatial';
10
7