@voluma/vlam 0.2.4 → 0.3.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.
Files changed (138) hide show
  1. package/README.md +3 -4
  2. package/dist/chunk-loader-DlNwggfG.js +1859 -0
  3. package/dist/chunk-loader-DlNwggfG.js.map +1 -0
  4. package/dist/{compute-sorter.d.ts → core/compute-sorter.d.ts} +1 -1
  5. package/dist/core/index.d.ts +45 -0
  6. package/dist/{splat-scene.d.ts → core/merged-splat-mesh.d.ts} +14 -15
  7. package/dist/{orientation.d.ts → core/orientation.d.ts} +7 -7
  8. package/dist/{relighting.d.ts → core/relighting.d.ts} +1 -1
  9. package/dist/{source-transform.d.ts → core/source-transform.d.ts} +4 -4
  10. package/dist/{splat-budget.d.ts → core/splat-budget.d.ts} +2 -2
  11. package/dist/{splat-data.d.ts → core/splat-data.d.ts} +4 -4
  12. package/dist/{splat-mesh-material.d.ts → core/splat-mesh-material.d.ts} +2 -2
  13. package/dist/{splat-mesh-types.d.ts → core/splat-mesh-types.d.ts} +19 -10
  14. package/dist/{splat-mesh.d.ts → core/splat-mesh.d.ts} +4 -4
  15. package/dist/{splat-modifier.d.ts → core/splat-modifier.d.ts} +5 -5
  16. package/dist/{webgpu-limits.d.ts → core/webgpu-limits.d.ts} +0 -59
  17. package/dist/{effects.d.ts → effects/index.d.ts} +14 -13
  18. package/dist/effects.js.map +1 -1
  19. package/dist/formats/ksplat/index.d.ts +1 -1
  20. package/dist/formats/ksplat/parse-ksplat.d.ts +1 -1
  21. package/dist/formats/ksplat.js.map +1 -1
  22. package/dist/formats/lcc/collision-mesh.d.ts +3 -3
  23. package/dist/formats/lcc/collision-partition.d.ts +1 -1
  24. package/dist/formats/lcc/lcc.d.ts +3 -3
  25. package/dist/formats/lcc/lcc2.d.ts +2 -2
  26. package/dist/formats/lcc/parse-lcc.d.ts +1 -1
  27. package/dist/formats/lcc.js +17 -16
  28. package/dist/formats/lcc.js.map +1 -1
  29. package/dist/formats/ply/index.d.ts +1 -1
  30. package/dist/formats/ply/parse-compressed-ply.d.ts +2 -2
  31. package/dist/formats/ply/parse-splat-ply.d.ts +4 -4
  32. package/dist/formats/ply.js +1 -1
  33. package/dist/formats/ply.js.map +1 -1
  34. package/dist/formats/rad/frontier-worker-protocol.d.ts +8 -1
  35. package/dist/formats/rad/index.d.ts +2 -2
  36. package/dist/formats/rad/parse-rad.d.ts +2 -2
  37. package/dist/formats/rad/rad-foveated-source.d.ts +3 -3
  38. package/dist/formats/rad/rad.d.ts +7 -7
  39. package/dist/formats/rad.js +3 -3
  40. package/dist/formats/rad.js.map +1 -1
  41. package/dist/formats/sog/index.d.ts +1 -1
  42. package/dist/formats/sog/parse-sog.d.ts +6 -6
  43. package/dist/formats/sog.js.map +1 -1
  44. package/dist/formats/splat/index.d.ts +1 -1
  45. package/dist/formats/splat/parse-splat.d.ts +1 -1
  46. package/dist/formats/splat.js.map +1 -1
  47. package/dist/formats/spz/index.d.ts +1 -1
  48. package/dist/formats/spz/parse-spz.d.ts +1 -1
  49. package/dist/formats/spz.js.map +1 -1
  50. package/dist/half-float-Cs4FDq8Q.js.map +1 -1
  51. package/dist/index.js +253 -9047
  52. package/dist/index.js.map +1 -1
  53. package/dist/{chunk-loader.d.ts → loaders/chunk-loader.d.ts} +4 -4
  54. package/dist/loaders/index.d.ts +15 -0
  55. package/dist/{load-scene.d.ts → loaders/load-splat-data.d.ts} +16 -14
  56. package/dist/{load-worker-protocol.d.ts → loaders/load-worker-protocol.d.ts} +2 -2
  57. package/dist/{loading.d.ts → loaders/loading.d.ts} +8 -8
  58. package/dist/loaders.js +26 -0
  59. package/dist/loaders.js.map +1 -0
  60. package/dist/loading-wLo8vRbA.js.map +1 -1
  61. package/dist/{splat-mesh-types-CTN_duw2.js → lod-scheduler-B0a_uBlv.js} +133 -140
  62. package/dist/lod-scheduler-B0a_uBlv.js.map +1 -0
  63. package/dist/logging-BfPdd7NJ.js.map +1 -1
  64. package/dist/{ply-header-BwgExCn-.js → ply-header-B9WllbPg.js} +3 -3
  65. package/dist/ply-header-B9WllbPg.js.map +1 -0
  66. package/dist/radix-sorter-BrbUg_CV.js +178 -0
  67. package/dist/radix-sorter-BrbUg_CV.js.map +1 -0
  68. package/dist/relighting-Tiwep8yd.js +977 -0
  69. package/dist/relighting-Tiwep8yd.js.map +1 -0
  70. package/dist/selection/index.d.ts +13 -0
  71. package/dist/{selection-volume.d.ts → selection/selection-volume.d.ts} +1 -1
  72. package/dist/{splat-partition.d.ts → selection/splat-partition.d.ts} +2 -2
  73. package/dist/selection.js +137 -0
  74. package/dist/selection.js.map +1 -0
  75. package/dist/sh-pack-D5wAe5gg.js.map +1 -1
  76. package/dist/{splat-budget-DXew_86c.js → splat-budget-DuVZspPQ.js} +7 -7
  77. package/dist/splat-budget-DuVZspPQ.js.map +1 -0
  78. package/dist/splat-data-BZM5dhhx.js.map +1 -1
  79. package/dist/splat-mesh-CsLOQb08.js +1942 -0
  80. package/dist/splat-mesh-CsLOQb08.js.map +1 -0
  81. package/dist/splat-mesh-types-BZIko-_9.js +18 -0
  82. package/dist/splat-mesh-types-BZIko-_9.js.map +1 -0
  83. package/dist/static-lod/index.d.ts +12 -0
  84. package/dist/{static-lod-splat-mesh.d.ts → static-lod/static-lod-splat-mesh.d.ts} +3 -3
  85. package/dist/{static-lod-worker-protocol.d.ts → static-lod/static-lod-worker-protocol.d.ts} +1 -1
  86. package/dist/{static-lod.d.ts → static-lod/static-lod.d.ts} +1 -1
  87. package/dist/{static-lod-worker-D2fyqQZO.js → static-lod-worker-DktKnJkR.js} +46 -46
  88. package/dist/{static-lod-worker-D2fyqQZO.js.map → static-lod-worker-DktKnJkR.js.map} +1 -1
  89. package/dist/static-lod.js +148 -0
  90. package/dist/static-lod.js.map +1 -0
  91. package/dist/{budget-governor.d.ts → streaming/budget-governor.d.ts} +4 -4
  92. package/dist/{camera-budget-governor.d.ts → streaming/camera-budget-governor.d.ts} +11 -11
  93. package/dist/{chunk-cache-budget.d.ts → streaming/chunk-cache-budget.d.ts} +5 -5
  94. package/dist/{chunk-fetch-scheduler.d.ts → streaming/chunk-fetch-scheduler.d.ts} +4 -4
  95. package/dist/{dataset-source.d.ts → streaming/dataset-source.d.ts} +1 -1
  96. package/dist/streaming/index.d.ts +23 -0
  97. package/dist/{lod-scheduler.d.ts → streaming/lod-scheduler.d.ts} +1 -1
  98. package/dist/{lod-source.d.ts → streaming/lod-source.d.ts} +9 -9
  99. package/dist/{streamed-splat-mesh-utils.d.ts → streaming/streamed-splat-mesh-utils.d.ts} +2 -2
  100. package/dist/{streamed-splat-mesh.d.ts → streaming/streamed-splat-mesh.d.ts} +66 -32
  101. package/dist/streaming.js +2911 -0
  102. package/dist/streaming.js.map +1 -0
  103. package/dist/unified/index.d.ts +11 -0
  104. package/dist/{unified-splat-renderer.d.ts → unified/unified-splat-mesh.d.ts} +23 -16
  105. package/dist/unified/unified-work-buffer.d.ts +66 -0
  106. package/dist/{work-buffer-gather.d.ts → unified/work-buffer-gather.d.ts} +6 -6
  107. package/dist/{work-buffer-material.d.ts → unified/work-buffer-material.d.ts} +1 -1
  108. package/dist/unified.js +746 -0
  109. package/dist/unified.js.map +1 -0
  110. package/dist/webgpu-limits-Y3CI_6_6.js +43 -0
  111. package/dist/webgpu-limits-Y3CI_6_6.js.map +1 -0
  112. package/package.json +27 -7
  113. package/dist/index.d.ts +0 -54
  114. package/dist/ply-header-BwgExCn-.js.map +0 -1
  115. package/dist/splat-budget-DXew_86c.js.map +0 -1
  116. package/dist/splat-mesh-types-CTN_duw2.js.map +0 -1
  117. /package/dist/{create-splat-renderer.d.ts → core/create-splat-renderer.d.ts} +0 -0
  118. /package/dist/{depth-of-field.d.ts → core/depth-of-field.d.ts} +0 -0
  119. /package/dist/{half-float.d.ts → core/half-float.d.ts} +0 -0
  120. /package/dist/{logging.d.ts → core/logging.d.ts} +0 -0
  121. /package/dist/{radix-sort.d.ts → core/radix-sort.d.ts} +0 -0
  122. /package/dist/{radix-sorter.d.ts → core/radix-sorter.d.ts} +0 -0
  123. /package/dist/{relighting-pass.d.ts → core/relighting-pass.d.ts} +0 -0
  124. /package/dist/{sh-pack.d.ts → core/sh-pack.d.ts} +0 -0
  125. /package/dist/{sort-scheduler.d.ts → core/sort-scheduler.d.ts} +0 -0
  126. /package/dist/{sort-worker-protocol.d.ts → core/sort-worker-protocol.d.ts} +0 -0
  127. /package/dist/{sorter.d.ts → core/sorter.d.ts} +0 -0
  128. /package/dist/{splat-depth-pack.d.ts → core/splat-depth-pack.d.ts} +0 -0
  129. /package/dist/{splat-mesh-picking.d.ts → core/splat-mesh-picking.d.ts} +0 -0
  130. /package/dist/{splat-mesh-pool.d.ts → core/splat-mesh-pool.d.ts} +0 -0
  131. /package/dist/{splat-modifier-stack.d.ts → core/splat-modifier-stack.d.ts} +0 -0
  132. /package/dist/{splat-query.d.ts → core/splat-query.d.ts} +0 -0
  133. /package/dist/{splat-sort-bounds.d.ts → core/splat-sort-bounds.d.ts} +0 -0
  134. /package/dist/{storage-attribute-mirror.d.ts → core/storage-attribute-mirror.d.ts} +0 -0
  135. /package/dist/{worker-sorter.d.ts → core/worker-sorter.d.ts} +0 -0
  136. /package/dist/{xr-view.d.ts → core/xr-view.d.ts} +0 -0
  137. /package/dist/{ply-header.d.ts → loaders/ply-header.d.ts} +0 -0
  138. /package/dist/{lod-manifest.d.ts → streaming/lod-manifest.d.ts} +0 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `@voluma/vlam/streaming` - budgeted LOD streaming for scenes larger than
3
+ * GPU memory.
4
+ *
5
+ * {@link StreamedSplatMesh.load} opens Streamed SOG, LCC / `.lcc2`, and Spark
6
+ * `.rad`. Shared loading errors and request types are re-exported so a host
7
+ * that only imports this entry can still name them.
8
+ *
9
+ * Static auto-LOD lives on `@voluma/vlam/static-lod`.
10
+ *
11
+ * @module streaming
12
+ */
13
+ export { StreamedSplatMesh, type StreamedSplatMeshOptions, type InitialRevealState, type PersistentChannelOptions, type StreamedSplatPerformanceEvent, } from './streamed-splat-mesh';
14
+ export { BudgetGovernor, type BudgetGovernorOptions, type BudgetGovernedMember, } from './budget-governor';
15
+ export { CameraBudgetGovernor, type CameraBudgetGovernorOptions, type CameraBudgetMember, type CameraBudgetMemberOptions, } from './camera-budget-governor';
16
+ export { ChunkFetchScheduler, type ChunkFetchSchedulerOptions, type ChunkFetchClient, type ChunkFetchHandle, type ChunkFetchKind, } from './chunk-fetch-scheduler';
17
+ export { ChunkCacheBudget, type ChunkCacheBudgetOptions, type ChunkCacheClient, type ChunkCacheHandle, } from './chunk-cache-budget';
18
+ export { httpDatasetSource, createLocalDataset } from './dataset-source';
19
+ export type { SplatDatasetSource, LocalDataset } from './dataset-source';
20
+ export type { CollisionMeshTile } from '../formats/lcc/collision-mesh';
21
+ export type { SplatCollisionData, CollisionMeshDescriptor, EnvironmentTile } from './lod-source';
22
+ export { resolveCpuCacheBytes } from '../core/splat-budget';
23
+ export { SplatLoadError, isAbortError, type SplatProgressCallback, type StreamedSplatFormat, type SplatRequestOptions, type SplatLoadPhase, type SplatInputOptions, } from '../loaders/loading';
@@ -205,7 +205,7 @@ export declare class LodScheduler implements LodSource {
205
205
  * Uses leftover budget to restore detail after {@link enforceBudget}
206
206
  * demoted leaves, nearest first, while the total stays under the fill
207
207
  * target. By default this may also refine *past* the distance-chosen level
208
- * when headroom remains (octree / pagetable streams). With
208
+ * when headroom remains (octree / page-table streams). With
209
209
  * {@link fillPastDistance} false (classic LCC), fill never goes finer than
210
210
  * each leaf's distance-selected level - so a cell at the L1 band does not
211
211
  * fetch L0 only to demote moments later with the camera still.
@@ -1,9 +1,9 @@
1
1
  import * as THREE from 'three/webgpu';
2
2
  import { type LodRun } from './lod-scheduler';
3
- import type { ChunkFileFormat } from './loading';
4
- import type { RadChunkRangeRequest } from './load-worker-protocol';
5
- import type { LccChunkParams } from './formats/lcc/parse-lcc';
6
- import type { SplatData } from './splat-data';
3
+ import type { ChunkFileFormat } from '../loaders/loading';
4
+ import type { RadChunkRangeRequest } from '../loaders/load-worker-protocol';
5
+ import type { LccChunkParams } from '../formats/lcc/parse-lcc';
6
+ import type { SplatData } from '../core/splat-data';
7
7
  import type { SplatDatasetSource } from './dataset-source';
8
8
  /**
9
9
  * Per-frame LOD decision maker: given the camera, returns the set of runs
@@ -106,7 +106,7 @@ export interface CollisionMeshDescriptor {
106
106
  * Coordinates are source-local, the same frame as {@link StreamedScene.bounds}:
107
107
  * {@link StreamedScene.formatTransform} maps them to world.
108
108
  */
109
- export interface SceneCollision {
109
+ export interface SplatCollisionData {
110
110
  readonly meshes: readonly CollisionMeshDescriptor[];
111
111
  }
112
112
  /**
@@ -155,7 +155,7 @@ export interface StreamedScene {
155
155
  */
156
156
  readonly formatTransform?: THREE.Matrix4;
157
157
  /** Optional collision geometry the format ships; undefined when it has none. */
158
- readonly collision?: SceneCollision;
158
+ readonly collision?: SplatCollisionData;
159
159
  /**
160
160
  * Optional always-resident environment tile the format ships outside its LOD
161
161
  * structure (the `.lcc2` sky) - present only when the dataset carries one.
@@ -175,13 +175,13 @@ export interface StreamedScene {
175
175
  /**
176
176
  * Splats per chunk file, so a `(file, localIndex)` pair maps to a stable global
177
177
  * splat index (`file * chunkSize + local`). Set by `.rad`; the page-table
178
- * renderer (`foveationMode: 'pagetable'`) keys frontier splats by that global.
178
+ * renderer (`foveationMode: 'page-table'`) keys frontier splats by that global.
179
179
  */
180
180
  readonly chunkSize?: number;
181
181
  /**
182
182
  * A chunk the scene builder already fetched and decoded (`.rad` decodes chunk
183
183
  * 0 for the scene bounds and the SH codebook). Handing it straight to the
184
- * renderer saves a second round trip - and in `pagetable` mode it is what
184
+ * renderer saves a second round trip - and in `page-table` mode it is what
185
185
  * seeds the worker's tree roots, without which the first traversals return an
186
186
  * empty frontier and the view stays blank until chunk 0 arrives a second time.
187
187
  */
@@ -191,7 +191,7 @@ export interface StreamedScene {
191
191
  };
192
192
  /**
193
193
  * Source-local xyz subsample of the coarsest overview (`.rad` chunk 0).
194
- * Survives after pagetable mode transfers chunk-0 buffers to the worker, so
194
+ * Survives after page-table mode transfers chunk-0 buffers to the worker, so
195
195
  * a host can estimate terrain height before any later chunk decodes.
196
196
  */
197
197
  readonly overviewPositions?: Float32Array;
@@ -1,6 +1,6 @@
1
1
  /** Scheduling and data helpers shared by the streamed mesh implementation. */
2
- import type { SplatRange } from './splat-mesh';
3
- import type { SplatData } from './splat-data';
2
+ import type { SplatRange } from '../core/splat-mesh';
3
+ import type { SplatData } from '../core/splat-data';
4
4
  import type { LodRun } from './lod-scheduler';
5
5
  /** One resident entry: the run description plus its pool handle. */
6
6
  type ResidentEntry = [string, {
@@ -1,12 +1,11 @@
1
1
  export * from './streamed-splat-mesh-utils';
2
2
  import * as THREE from 'three/webgpu';
3
- import { SplatMesh, type SplatChannelOptions, type SplatMeshOptions, type SplatUpdateOptions } from './splat-mesh';
4
- import type { StaticLodSplatMesh, StaticLodSplatMeshLoadOptions } from './static-lod-splat-mesh';
3
+ import { SplatMesh, type SplatChannelOptions, type SplatMeshOptions, type SplatUpdateOptions } from '../core/splat-mesh';
5
4
  import { type StreamedScene } from './lod-source';
6
- import type { CollisionMeshTile } from './formats/lcc/collision-mesh';
7
- import { type SplatRequestOptions, type StreamedSplatFormat } from './loading';
8
- import { type SplatDeviceProfile } from './splat-budget';
9
- import { type FrontierFoveation } from './formats/rad/frontier-worker-protocol';
5
+ import type { CollisionMeshTile } from '../formats/lcc/collision-mesh';
6
+ import { type SplatRequestOptions, type StreamedSplatFormat } from '../loaders/loading';
7
+ import { type SplatDeviceProfile } from '../core/splat-budget';
8
+ import { type FrontierFoveation } from '../formats/rad/frontier-worker-protocol';
10
9
  import type { ChunkFetchScheduler } from './chunk-fetch-scheduler';
11
10
  import type { ChunkCacheBudget } from './chunk-cache-budget';
12
11
  /**
@@ -87,13 +86,13 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
87
86
  * should be able to *grow* this mesh's share: the pool is allocated once at
88
87
  * construction and never grows, so without headroom reserved here a governed
89
88
  * mesh can only ever be shrunk below the budget it was built with. That is
90
- * the whole reason a hand-split `pool / N` marker stays coarse near the
91
- * camera - every marker's ceiling was fixed at a quarter of the pool.
89
+ * the whole reason a hand-split `pool / N` mesh stays coarse near the
90
+ * camera - every mesh's ceiling was fixed at a quarter of the pool.
92
91
  *
93
92
  * It is not free: the pool costs its *ceiling* in memory whether or not the
94
93
  * budget ever reaches it (~64 B of GPU pool plus ~56 B of CPU backing per
95
94
  * splat, 1.5× for capacity slack). Price it with `estimateSplatPoolBytes`
96
- * before choosing - for several markers the
95
+ * before choosing - for several additional meshes the
97
96
  * sum of the ceilings is what has to fit, not the shared budget. A ceiling
98
97
  * around 1.5–2× a member's fair share is usually the right trade.
99
98
  *
@@ -101,12 +100,23 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
101
100
  * number.
102
101
  */
103
102
  maxBudget?: number;
103
+ /**
104
+ * Lets a host that pins {@link budget} and/or {@link maxBudget} still take the
105
+ * finest-level lift for `.rad` strategy selection and pool sizing. Without it,
106
+ * pinning either option disables the lift and a capture whose leaf count sits
107
+ * between the host ceiling and {@link FOVEATION_LEAF_THRESHOLD} incorrectly
108
+ * lands on the foveated page-table path instead of the prefix reader.
109
+ *
110
+ * {@link budgetCap} still vetoes the lift when set. Mobile and fill-constrained
111
+ * desktops remain exempt inside {@link liftBudgetToFinestLevel}.
112
+ */
113
+ allowFinestLevelLift?: boolean;
104
114
  /**
105
115
  * Multiplier on this mesh's LOD detail, matching Spark's per-mesh `lodScale`:
106
116
  * `> 1` refines further (finer cut, more splats drawn), `< 1` coarsens.
107
117
  * Default `1`.
108
118
  *
109
- * **`.rad` `foveationMode: 'pagetable'` only** - it scales the frontier cut
119
+ * **`.rad` `foveationMode: 'page-table'` only** - it scales the frontier cut
110
120
  * the page-table traversal is given (`pixel_scale × lodScale ≤ limit`, exactly
111
121
  * Spark's formula). It does nothing on a mesh with no per-splat cut to scale:
112
122
  * a moderate `.rad` read as a chunk prefix, or a Streamed SOG / LCC scene. For
@@ -128,7 +138,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
128
138
  * later streaming is stopped by {@link SplatMesh.dispose}.
129
139
  */
130
140
  signal?: AbortSignal;
131
- /** Base URL a relative manifest URL resolves against (like {@link loadScene}). */
141
+ /** Base URL a relative manifest URL resolves against (like {@link loadSplatData}). */
132
142
  baseUrl?: string | URL;
133
143
  /** World-unit distance inside which the finest LOD is used. Default 10. */
134
144
  lodBaseDistance?: number;
@@ -186,7 +196,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
186
196
  * to `'progressive'`.
187
197
  */
188
198
  initialReveal?: 'progressive' | 'hold-near-l0' | 'hold-coverage';
189
- /** Receives lightweight LOD swap markers for performance attribution. */
199
+ /** Receives lightweight LOD mutation events for performance attribution. */
190
200
  onPerformanceEvent?: (event: StreamedSplatPerformanceEvent) => void;
191
201
  /**
192
202
  * View-dependent color (higher-order SH). This is the streaming counterpart
@@ -234,7 +244,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
234
244
  * or suspended, and has one effect on its own: the background sweep that
235
245
  * pre-warms the whole capture into the page-table cache stops. That sweep is
236
246
  * pure speculation about a camera move that has not happened, and on a
237
- * multi-marker scene it is most of the traffic competing with the marker the
247
+ * multi-mesh scene it is most of the traffic competing with the mesh the
238
248
  * viewer is actually looking at.
239
249
  *
240
250
  * Unset (the default) leaves fetching exactly as it was: every mesh sweeps.
@@ -244,8 +254,8 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
244
254
  /**
245
255
  * Scene-wide fetch arbitration, shared by every streamed mesh the way a
246
256
  * {@link SplatMeshOptions.pool} is - see {@link ChunkFetchScheduler}. Without
247
- * one, each mesh fetches toward its own in-flight cap and a near marker's
248
- * detail queues behind a dozen far markers' background traffic.
257
+ * one, each mesh fetches toward its own in-flight cap and a near mesh's
258
+ * detail queues behind a dozen far meshes' background traffic.
249
259
  *
250
260
  * The scheduler is *not* owned by the mesh: dispose unregisters this mesh and
251
261
  * leaves the scheduler running for its siblings. Weights come from
@@ -261,7 +271,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
261
271
  * Without one, each `.rad` page-table mesh caps its own cache at
262
272
  * `max(cpuCacheBytes, min(2 GiB, this capture's decoded size))`: the right
263
273
  * number for a lone streamed scene, and no bound at all across a scene of
264
- * markers, because every mesh gets its own and each is sized to its own
274
+ * additional meshes, because every mesh gets its own and each is sized to its own
265
275
  * capture. With one, that figure becomes this mesh's *ceiling* and the budget
266
276
  * splits a scene total across every registered mesh by camera weight.
267
277
  *
@@ -328,11 +338,6 @@ export interface PersistentChannelOptions extends SplatChannelOptions {
328
338
  * `docs/formats/streamed-shn-notes.md`).
329
339
  */
330
340
  export declare class StreamedSplatMesh extends SplatMesh {
331
- /**
332
- * Loads a non-streamed splat file into a worker-built merged hierarchy.
333
- * The returned static mesh shares this class's runtime budget contract.
334
- */
335
- static loadAutoLod(input: string | URL, options: StaticLodSplatMeshLoadOptions): Promise<StaticLodSplatMesh>;
336
341
  private readonly scene;
337
342
  private readonly loader;
338
343
  /**
@@ -399,7 +404,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
399
404
  private lodLevelScratch;
400
405
  /** Desired-but-not-resident files this tick; protected from cache eviction. */
401
406
  private readonly neededFiles;
402
- /** Non-null in `foveationMode: 'pagetable'`: the worker that owns the chunk
407
+ /** Non-null in `foveationMode: 'page-table'`: the worker that owns the chunk
403
408
  * cache + traversal + pager off the main thread, and the always-active slab it
404
409
  * pages the returned frontier into. */
405
410
  private readonly frontierWorker;
@@ -454,8 +459,17 @@ export declare class StreamedSplatMesh extends SplatMesh {
454
459
  * governed budget outgrows it, rather than the library's own default. */
455
460
  private pageTableDrawTargetExplicit;
456
461
  /** Last frontier's drawn (non-degenerate) splat count - the true on-screen size
457
- * in `pagetable` mode, where the slab is fully "active" but mostly degenerate. */
462
+ * in `page-table` mode, where the slab is fully "active" but mostly degenerate. */
458
463
  private pageTableDrawn;
464
+ private frontierConverged;
465
+ private pendingFrontierSplats;
466
+ private staleResidentSplats;
467
+ private lastPlanAppends;
468
+ private lastPlanMoves;
469
+ private lastPlanGeneration;
470
+ private lastPlanBudget;
471
+ private lastPlanCamera;
472
+ private firstFrontierCamera;
459
473
  /** Monotonic reschedule id; a stale plan (superseded by a newer request) is
460
474
  * dropped. `pageTableInFlight` coalesces to one outstanding traversal. */
461
475
  private pageTableSeq;
@@ -563,8 +577,8 @@ export declare class StreamedSplatMesh extends SplatMesh {
563
577
  * tells the worker's pager the new slot count.
564
578
  *
565
579
  * This is the mechanism that makes a shared pool worth having: storage follows
566
- * the governed budget, so approaching a marker grows its pages while the ones
567
- * behind you hand theirs back, instead of every marker holding its ceiling for
580
+ * the governed budget, so approaching a mesh grows its pages while the ones
581
+ * behind you hand theirs back, instead of every mesh holding its ceiling for
568
582
  * the whole session. Growth stops at the construction ceiling and at whatever
569
583
  * the pool can actually spare - a mesh that cannot grow simply stays coarse
570
584
  * rather than throwing.
@@ -680,17 +694,37 @@ export declare class StreamedSplatMesh extends SplatMesh {
680
694
  * `undefined` when the format does not declare a content size.
681
695
  */
682
696
  get contentSplatCount(): number | undefined;
697
+ /**
698
+ * Which `.rad` streaming strategy this mesh selected at load, or `null` when
699
+ * the scene is not a Spark `.rad` capture.
700
+ */
701
+ get radStrategy(): 'prefix' | 'page-table' | null;
683
702
  /**
684
703
  * The drawn-splat target currently driving the `.rad` page-table frontier -
685
704
  * the governed budget, capped by
686
705
  * {@link SplatMeshOptions.foveationDrawBudget}. `0` on a mesh that is not in
687
- * `foveationMode: 'pagetable'`, which has no frontier to target.
706
+ * `foveationMode: 'page-table'`, which has no frontier to target.
688
707
  *
689
708
  * This is the number that decides how deep the traversal descends, so it is
690
709
  * what to watch when checking that a near mesh really did receive more
691
710
  * detail: {@link budget} is the pool's allowance, this is what is spent.
692
711
  */
693
712
  get drawBudget(): number;
713
+ /**
714
+ * Page-table frontier coherence for hosts that gate preload/transitions.
715
+ * `undefined` fields stay 0 when this mesh is not in page-table mode.
716
+ */
717
+ get frontierState(): Readonly<{
718
+ frontierConverged: boolean;
719
+ pendingFrontierSplats: number;
720
+ staleResidentSplats: number;
721
+ lastPlanAppends: number;
722
+ lastPlanMoves: number;
723
+ planGeneration: number;
724
+ planBudget: number;
725
+ lastPlanCamera: readonly [number, number, number] | null;
726
+ firstFrontierCamera: readonly [number, number, number] | null;
727
+ }>;
694
728
  /**
695
729
  * Spark's per-mesh `lodScale` (see {@link StreamedSplatMeshOptions.lodScale}).
696
730
  * Mutable: raise it to sharpen a focused mesh, lower it to coarsen a
@@ -700,7 +734,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
700
734
  */
701
735
  get lodScale(): number;
702
736
  set lodScale(value: number);
703
- /** In `pagetable` mode the slab is fully active but mostly degenerate, so the
737
+ /** In `page-table` mode the slab is fully active but mostly degenerate, so the
704
738
  * base `activeSplatCount` (slab size) is not the on-screen count - report the
705
739
  * frontier's drawn size instead. */
706
740
  get activeSplatCount(): number;
@@ -736,7 +770,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
736
770
  /** Chunk fetches currently in flight. */
737
771
  get pendingChunkCount(): number;
738
772
  /**
739
- * Main-thread cost of applying paging plans in `foveationMode: 'pagetable'`.
773
+ * Main-thread cost of applying paging plans in `foveationMode: 'page-table'`.
740
774
  *
741
775
  * A plan is applied whole, off the render loop's own timing, so its cost does
742
776
  * not appear in {@link getUpdateTimings} - but it lands on the same thread and
@@ -906,7 +940,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
906
940
  * and it starts enabled. Failed / unfit / disabled tiles do not block reveal.
907
941
  */
908
942
  private environmentPendingForReveal;
909
- /** Creates a marker for a changed streamed-LOD tick, if any. */
943
+ /** Creates a performance event for a changed streamed-LOD tick, if any. */
910
944
  private createPerformanceEvent;
911
945
  /** Returns whether all new rows can coexist with the currently visible region. */
912
946
  private canStageGroup;
@@ -963,7 +997,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
963
997
  /** Ranks the env tile ahead of every LOD want in {@link flushClassicFetches}. */
964
998
  private enqueueEnvironmentFetch;
965
999
  /**
966
- * Page-table reschedule (`foveationMode: 'pagetable'`): posts the camera to the
1000
+ * Page-table reschedule (`foveationMode: 'page-table'`): posts the camera to the
967
1001
  * worker, which owns the cache + traversal + pager and replies asynchronously
968
1002
  * with a paging plan. Coalesced to one outstanding request so the main thread
969
1003
  * never blocks. Also drives chunk fetching, in priority order.
@@ -979,8 +1013,8 @@ export declare class StreamedSplatMesh extends SplatMesh {
979
1013
  * worker's cache/traversal/gather can use it. */
980
1014
  private forwardChunkToWorker;
981
1015
  /** Parallel chunk fetches. HTTP/2 multiplexes them; on HTTP/1.1 the browser's
982
- * per-host cap simply queues. Same cap for classic and pagetable so near
983
- * detail is not structurally starved on the non-pagetable path. */
1016
+ * per-host cap simply queues. Same cap for classic and page-table so near
1017
+ * detail is not structurally starved on the non-page-table path. */
984
1018
  private get maxInflight();
985
1019
  /**
986
1020
  * Whether this mesh may run its speculative background sweep. A mesh with no