@voluma/vlam 0.2.4 → 0.3.0
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/README.md +3 -2
- package/dist/budget-governor.d.ts +4 -4
- package/dist/camera-budget-governor.d.ts +11 -11
- package/dist/chunk-cache-budget.d.ts +5 -5
- package/dist/chunk-fetch-scheduler.d.ts +4 -4
- package/dist/chunk-loader-DlNwggfG.js +1859 -0
- package/dist/chunk-loader-DlNwggfG.js.map +1 -0
- package/dist/chunk-loader.d.ts +2 -2
- package/dist/compute-sorter.d.ts +1 -1
- package/dist/effects.d.ts +11 -10
- package/dist/effects.js.map +1 -1
- package/dist/formats/ksplat/index.d.ts +1 -1
- package/dist/formats/lcc/collision-mesh.d.ts +2 -2
- package/dist/formats/lcc.js +17 -16
- package/dist/formats/lcc.js.map +1 -1
- package/dist/formats/ply/index.d.ts +1 -1
- package/dist/formats/ply/parse-splat-ply.d.ts +2 -2
- package/dist/formats/ply.js +1 -1
- package/dist/formats/ply.js.map +1 -1
- package/dist/formats/rad/index.d.ts +1 -1
- package/dist/formats/rad/parse-rad.d.ts +1 -1
- package/dist/formats/rad/rad.d.ts +2 -2
- package/dist/formats/rad.js +3 -3
- package/dist/formats/rad.js.map +1 -1
- package/dist/formats/sog/index.d.ts +1 -1
- package/dist/formats/sog/parse-sog.d.ts +4 -4
- package/dist/formats/sog.js.map +1 -1
- package/dist/formats/splat/index.d.ts +1 -1
- package/dist/formats/spz/index.d.ts +1 -1
- package/dist/index.d.ts +16 -25
- package/dist/index.js +253 -9047
- package/dist/index.js.map +1 -1
- package/dist/{load-scene.d.ts → load-splat-data.d.ts} +15 -13
- package/dist/loaders.d.ts +15 -0
- package/dist/loaders.js +26 -0
- package/dist/loaders.js.map +1 -0
- package/dist/loading-wLo8vRbA.js.map +1 -1
- package/dist/loading.d.ts +8 -8
- package/dist/{splat-mesh-types-CTN_duw2.js → lod-scheduler-B0a_uBlv.js} +133 -140
- package/dist/lod-scheduler-B0a_uBlv.js.map +1 -0
- package/dist/lod-scheduler.d.ts +1 -1
- package/dist/lod-source.d.ts +5 -5
- package/dist/{splat-scene.d.ts → merged-splat-mesh.d.ts} +14 -15
- package/dist/orientation.d.ts +7 -7
- package/dist/{ply-header-BwgExCn-.js → ply-header-B9WllbPg.js} +3 -3
- package/dist/{ply-header-BwgExCn-.js.map → ply-header-B9WllbPg.js.map} +1 -1
- package/dist/radix-sorter-R0FCSqKu.js +178 -0
- package/dist/radix-sorter-R0FCSqKu.js.map +1 -0
- package/dist/relighting-CSQF3UcL.js +969 -0
- package/dist/relighting-CSQF3UcL.js.map +1 -0
- package/dist/relighting.d.ts +1 -1
- package/dist/selection.d.ts +13 -0
- package/dist/selection.js +137 -0
- package/dist/selection.js.map +1 -0
- package/dist/source-transform.d.ts +4 -4
- package/dist/{splat-budget-DXew_86c.js → splat-budget-DuVZspPQ.js} +7 -7
- package/dist/{splat-budget-DXew_86c.js.map → splat-budget-DuVZspPQ.js.map} +1 -1
- package/dist/splat-budget.d.ts +1 -1
- package/dist/splat-data-BZM5dhhx.js.map +1 -1
- package/dist/splat-data.d.ts +4 -4
- package/dist/splat-mesh-aQdcWA6v.js +1942 -0
- package/dist/splat-mesh-aQdcWA6v.js.map +1 -0
- package/dist/splat-mesh-material.d.ts +2 -2
- package/dist/splat-mesh-types-BZIko-_9.js +18 -0
- package/dist/splat-mesh-types-BZIko-_9.js.map +1 -0
- package/dist/splat-mesh-types.d.ts +14 -8
- package/dist/splat-mesh.d.ts +4 -4
- package/dist/splat-modifier.d.ts +5 -5
- package/dist/splat-partition.d.ts +1 -1
- package/dist/static-lod-entry.d.ts +12 -0
- package/dist/static-lod-splat-mesh.d.ts +2 -2
- package/dist/{static-lod-worker-D2fyqQZO.js → static-lod-worker-DktKnJkR.js} +46 -46
- package/dist/{static-lod-worker-D2fyqQZO.js.map → static-lod-worker-DktKnJkR.js.map} +1 -1
- package/dist/static-lod.js +148 -0
- package/dist/static-lod.js.map +1 -0
- package/dist/streamed-splat-mesh.d.ts +21 -27
- package/dist/streaming.d.ts +23 -0
- package/dist/streaming.js +2877 -0
- package/dist/streaming.js.map +1 -0
- package/dist/{unified-splat-renderer.d.ts → unified-splat-mesh.d.ts} +10 -10
- package/dist/unified-work-buffer.d.ts +66 -0
- package/dist/unified.d.ts +11 -0
- package/dist/unified.js +738 -0
- package/dist/unified.js.map +1 -0
- package/dist/webgpu-limits-Y3CI_6_6.js +43 -0
- package/dist/webgpu-limits-Y3CI_6_6.js.map +1 -0
- package/dist/webgpu-limits.d.ts +0 -59
- package/dist/work-buffer-gather.d.ts +1 -1
- package/package.json +24 -4
- package/dist/splat-mesh-types-CTN_duw2.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-lod.js","sources":["../src/lib/static-lod-splat-mesh.ts"],"sourcesContent":["/** @role Bridge - Camera-aware rendering for worker-built static splat hierarchies. */\nimport * as THREE from 'three/webgpu';\nimport { loadSplatData, type SplatDataLoadOptions } from './load-splat-data';\nimport type { SplatData } from './splat-data';\nimport { SplatMesh, type SplatMeshOptions, type SplatUpdateOptions } from './splat-mesh';\nimport type { StaticLodBuildProgress } from './static-lod';\nimport type { StaticLodWorkerRequest, StaticLodWorkerResponse } from './static-lod-worker-protocol';\n\nconst BUDGET_GRANULARITY = 4096;\nconst CAMERA_RESCHEDULE_INTERVAL_MS = 250;\n\nexport interface StaticLodSplatMeshOptions extends SplatMeshOptions {\n /** Initial selected-frontier budget. Defaults to the build ceiling. */\n budget?: number;\n /** Finest frontier retained by the hierarchy and immutable pool ceiling. */\n maxBudget: number;\n /** Reports the spatial ordering and hierarchy-build phase. */\n onLodProgress?: (progress: StaticLodBuildProgress) => void;\n /** Phase-aware progress spanning download, decode completion and LOD build. */\n onAutoLodProgress?: (progress: StaticLodLoadProgress) => void;\n}\n\nexport interface StaticLodLoadProgress {\n readonly phase: 'download' | 'decode' | 'lod-build';\n readonly completed: number;\n readonly total: number;\n}\n\nexport interface StaticLodSplatMeshLoadOptions\n extends StaticLodSplatMeshOptions, SplatDataLoadOptions {}\n\nconst transferablesFor = (data: SplatData): Transferable[] => {\n const transferables: Transferable[] = [\n data.positions.buffer as ArrayBuffer,\n data.colors.buffer as ArrayBuffer,\n data.covariances.buffer as ArrayBuffer,\n ];\n if (data.sh) transferables.push(data.sh.labels.buffer as ArrayBuffer);\n if (data.shPacked) transferables.push(data.shPacked.packed.buffer as ArrayBuffer);\n return transferables;\n};\n\nconst normalizeBudget = (value: number, ceiling: number): number => {\n if (!Number.isFinite(value) || value <= 0) {\n throw new RangeError('StaticLodSplatMesh budget must be a positive finite number.');\n }\n const clamped = Math.min(ceiling, Math.floor(value));\n if (clamped === ceiling || clamped < BUDGET_GRANULARITY) return Math.max(1, clamped);\n return Math.max(\n BUDGET_GRANULARITY,\n Math.floor(clamped / BUDGET_GRANULARITY) * BUDGET_GRANULARITY,\n );\n};\n\nconst buildInWorker = async (\n source: SplatData,\n options: StaticLodSplatMeshOptions,\n signal: AbortSignal | undefined,\n): Promise<{\n data: SplatData;\n contentSplatCount: number;\n finestSplatCount: number;\n worker: Worker;\n}> => {\n const module = await import('./static-lod-worker?worker&inline');\n const WorkerClass = module.default;\n const worker = new WorkerClass();\n return await new Promise((resolve, reject) => {\n const abort = (): void => {\n worker.terminate();\n reject(new DOMException('Static LOD build aborted.', 'AbortError'));\n };\n if (signal?.aborted) {\n abort();\n return;\n }\n signal?.addEventListener('abort', abort, { once: true });\n worker.onerror = (event): void => {\n signal?.removeEventListener('abort', abort);\n worker.terminate();\n reject(new Error(event.message));\n };\n worker.onmessage = (event: MessageEvent<StaticLodWorkerResponse>): void => {\n const response = event.data;\n if (response.type === 'progress') {\n options.onLodProgress?.(response.progress);\n options.onAutoLodProgress?.({ phase: 'lod-build', ...response.progress });\n return;\n }\n if (response.type === 'error') {\n signal?.removeEventListener('abort', abort);\n worker.terminate();\n reject(new Error(response.message));\n return;\n }\n if (response.type !== 'built') return;\n signal?.removeEventListener('abort', abort);\n resolve({\n data: response.data,\n contentSplatCount: response.contentSplatCount,\n finestSplatCount: response.finestSplatCount,\n worker,\n });\n };\n const request: StaticLodWorkerRequest = {\n type: 'build',\n source,\n maxBudget: options.maxBudget,\n };\n worker.postMessage(request, transferablesFor(source));\n });\n};\n\n/**\n * Static splat mesh backed by a merged hierarchy and camera-aware frontier.\n * The full hierarchy is uploaded once; camera/budget cuts only remap the\n * active pool indices and never rewrite resident splat attributes.\n */\nexport class StaticLodSplatMesh extends SplatMesh {\n private readonly worker: Worker;\n private readonly ceilingValue: number;\n private readonly contentCountValue: number;\n private budgetValue: number;\n private sequence = 0;\n private lastScheduleAt = -Infinity;\n private selectionPending = false;\n private readonly cameraLocal = new THREE.Vector3();\n private readonly cameraForward = new THREE.Vector3(0, 0, -1);\n private readonly inverseWorld = new THREE.Matrix4();\n\n private constructor(\n data: SplatData,\n contentSplatCount: number,\n finestSplatCount: number,\n worker: Worker,\n options: StaticLodSplatMeshOptions,\n ) {\n super(data, options);\n this.worker = worker;\n this.ceilingValue = finestSplatCount;\n this.contentCountValue = contentSplatCount;\n this.budgetValue = normalizeBudget(options.budget ?? this.ceilingValue, this.ceilingValue);\n // Hierarchy layout: finest level occupies pool indices `[0, finest)`.\n this.replaceActivePrefix(this.ceilingValue);\n this.worker.onmessage = (event: MessageEvent<StaticLodWorkerResponse>): void => {\n const response = event.data;\n if (response.type === 'error') {\n this.selectionPending = false;\n return;\n }\n if (response.type !== 'selection' || response.sequence !== this.sequence) return;\n this.selectionPending = false;\n this.replaceActiveIndices(response.indices);\n };\n if (this.budgetValue < this.ceilingValue) this.scheduleSelection(true);\n }\n\n /** Loads, decodes and builds a merged static hierarchy without blocking UI. */\n static async load(\n input: string | URL,\n options: StaticLodSplatMeshLoadOptions,\n ): Promise<StaticLodSplatMesh> {\n let decodeReported = false;\n const source = await loadSplatData(input, {\n ...options,\n onProgress: (completed, total) => {\n options.onProgress?.(completed, total);\n options.onAutoLodProgress?.({ phase: 'download', completed, total });\n if (!decodeReported && total > 0 && completed >= total) {\n decodeReported = true;\n options.onAutoLodProgress?.({ phase: 'decode', completed: 0, total: 1 });\n }\n },\n });\n if (!decodeReported) {\n options.onAutoLodProgress?.({ phase: 'decode', completed: 0, total: 1 });\n }\n options.onAutoLodProgress?.({ phase: 'decode', completed: 1, total: 1 });\n const result = await buildInWorker(source, options, options.signal);\n return new StaticLodSplatMesh(\n result.data,\n result.contentSplatCount,\n result.finestSplatCount,\n result.worker,\n options,\n );\n }\n\n get budget(): number {\n return this.budgetValue;\n }\n\n get budgetCeiling(): number {\n return this.ceilingValue;\n }\n\n get maxBudget(): number {\n return this.ceilingValue;\n }\n\n get contentSplatCount(): number {\n return this.contentCountValue;\n }\n\n /** Changes the selected frontier budget within the immutable build ceiling. */\n setBudget(value: number): number {\n const next = normalizeBudget(value, this.ceilingValue);\n if (next === this.budgetValue) return next;\n this.budgetValue = next;\n this.selectionPending = false;\n this.scheduleSelection(true);\n return next;\n }\n\n override update(\n camera: THREE.PerspectiveCamera,\n renderer: THREE.WebGPURenderer,\n options: SplatUpdateOptions = {},\n ): void {\n super.update(camera, renderer, options);\n this.updateLod(camera);\n }\n\n /** Schedules a camera-aware cut when a unified renderer owns drawing/sorting. */\n updateLod(camera: THREE.PerspectiveCamera): void {\n camera.updateMatrixWorld();\n this.updateWorldMatrix(true, false);\n this.inverseWorld.copy(this.matrixWorld).invert();\n this.cameraLocal.setFromMatrixPosition(camera.matrixWorld).applyMatrix4(this.inverseWorld);\n camera.getWorldDirection(this.cameraForward).transformDirection(this.inverseWorld);\n this.scheduleSelection(false);\n }\n\n override dispose(): void {\n if (this.disposed) return;\n this.worker.terminate();\n super.dispose();\n }\n\n private scheduleSelection(immediate: boolean): void {\n if (this.disposed || this.selectionPending) return;\n const now = performance.now();\n if (!immediate && now - this.lastScheduleAt < CAMERA_RESCHEDULE_INTERVAL_MS) return;\n this.lastScheduleAt = now;\n this.selectionPending = true;\n const request: StaticLodWorkerRequest = {\n type: 'select',\n sequence: ++this.sequence,\n budget: this.budgetValue,\n cameraLocal: this.cameraLocal.toArray(),\n cameraForward: this.cameraForward.toArray(),\n };\n this.worker.postMessage(request);\n }\n}\n"],"names":["BUDGET_GRANULARITY","CAMERA_RESCHEDULE_INTERVAL_MS","transferablesFor","data","transferables","normalizeBudget","value","ceiling","clamped","buildInWorker","source","options","signal","WorkerClass","worker","resolve","reject","abort","event","response","_a","_b","request","StaticLodSplatMesh","SplatMesh","contentSplatCount","finestSplatCount","__publicField","THREE","input","decodeReported","loadSplatData","completed","total","_c","result","next","camera","renderer","immediate","now"],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './streamed-splat-mesh-utils';
|
|
2
2
|
import * as THREE from 'three/webgpu';
|
|
3
3
|
import { SplatMesh, type SplatChannelOptions, type SplatMeshOptions, type SplatUpdateOptions } from './splat-mesh';
|
|
4
|
-
import type { StaticLodSplatMesh, StaticLodSplatMeshLoadOptions } from './static-lod-splat-mesh';
|
|
5
4
|
import { type StreamedScene } from './lod-source';
|
|
6
5
|
import type { CollisionMeshTile } from './formats/lcc/collision-mesh';
|
|
7
6
|
import { type SplatRequestOptions, type StreamedSplatFormat } from './loading';
|
|
@@ -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`
|
|
91
|
-
* camera - every
|
|
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
|
|
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
|
*
|
|
@@ -106,7 +105,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
|
|
|
106
105
|
* `> 1` refines further (finer cut, more splats drawn), `< 1` coarsens.
|
|
107
106
|
* Default `1`.
|
|
108
107
|
*
|
|
109
|
-
* **`.rad` `foveationMode: '
|
|
108
|
+
* **`.rad` `foveationMode: 'page-table'` only** - it scales the frontier cut
|
|
110
109
|
* the page-table traversal is given (`pixel_scale × lodScale ≤ limit`, exactly
|
|
111
110
|
* Spark's formula). It does nothing on a mesh with no per-splat cut to scale:
|
|
112
111
|
* a moderate `.rad` read as a chunk prefix, or a Streamed SOG / LCC scene. For
|
|
@@ -128,7 +127,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
|
|
|
128
127
|
* later streaming is stopped by {@link SplatMesh.dispose}.
|
|
129
128
|
*/
|
|
130
129
|
signal?: AbortSignal;
|
|
131
|
-
/** Base URL a relative manifest URL resolves against (like {@link
|
|
130
|
+
/** Base URL a relative manifest URL resolves against (like {@link loadSplatData}). */
|
|
132
131
|
baseUrl?: string | URL;
|
|
133
132
|
/** World-unit distance inside which the finest LOD is used. Default 10. */
|
|
134
133
|
lodBaseDistance?: number;
|
|
@@ -186,7 +185,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
|
|
|
186
185
|
* to `'progressive'`.
|
|
187
186
|
*/
|
|
188
187
|
initialReveal?: 'progressive' | 'hold-near-l0' | 'hold-coverage';
|
|
189
|
-
/** Receives lightweight LOD
|
|
188
|
+
/** Receives lightweight LOD mutation events for performance attribution. */
|
|
190
189
|
onPerformanceEvent?: (event: StreamedSplatPerformanceEvent) => void;
|
|
191
190
|
/**
|
|
192
191
|
* View-dependent color (higher-order SH). This is the streaming counterpart
|
|
@@ -234,7 +233,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
|
|
|
234
233
|
* or suspended, and has one effect on its own: the background sweep that
|
|
235
234
|
* pre-warms the whole capture into the page-table cache stops. That sweep is
|
|
236
235
|
* pure speculation about a camera move that has not happened, and on a
|
|
237
|
-
* multi-
|
|
236
|
+
* multi-mesh scene it is most of the traffic competing with the mesh the
|
|
238
237
|
* viewer is actually looking at.
|
|
239
238
|
*
|
|
240
239
|
* Unset (the default) leaves fetching exactly as it was: every mesh sweeps.
|
|
@@ -244,8 +243,8 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
|
|
|
244
243
|
/**
|
|
245
244
|
* Scene-wide fetch arbitration, shared by every streamed mesh the way a
|
|
246
245
|
* {@link SplatMeshOptions.pool} is - see {@link ChunkFetchScheduler}. Without
|
|
247
|
-
* one, each mesh fetches toward its own in-flight cap and a near
|
|
248
|
-
* detail queues behind a dozen far
|
|
246
|
+
* one, each mesh fetches toward its own in-flight cap and a near mesh's
|
|
247
|
+
* detail queues behind a dozen far meshes' background traffic.
|
|
249
248
|
*
|
|
250
249
|
* The scheduler is *not* owned by the mesh: dispose unregisters this mesh and
|
|
251
250
|
* leaves the scheduler running for its siblings. Weights come from
|
|
@@ -261,7 +260,7 @@ export interface StreamedSplatMeshOptions extends SplatMeshOptions {
|
|
|
261
260
|
* Without one, each `.rad` page-table mesh caps its own cache at
|
|
262
261
|
* `max(cpuCacheBytes, min(2 GiB, this capture's decoded size))`: the right
|
|
263
262
|
* number for a lone streamed scene, and no bound at all across a scene of
|
|
264
|
-
*
|
|
263
|
+
* additional meshes, because every mesh gets its own and each is sized to its own
|
|
265
264
|
* capture. With one, that figure becomes this mesh's *ceiling* and the budget
|
|
266
265
|
* splits a scene total across every registered mesh by camera weight.
|
|
267
266
|
*
|
|
@@ -328,11 +327,6 @@ export interface PersistentChannelOptions extends SplatChannelOptions {
|
|
|
328
327
|
* `docs/formats/streamed-shn-notes.md`).
|
|
329
328
|
*/
|
|
330
329
|
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
330
|
private readonly scene;
|
|
337
331
|
private readonly loader;
|
|
338
332
|
/**
|
|
@@ -399,7 +393,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
399
393
|
private lodLevelScratch;
|
|
400
394
|
/** Desired-but-not-resident files this tick; protected from cache eviction. */
|
|
401
395
|
private readonly neededFiles;
|
|
402
|
-
/** Non-null in `foveationMode: '
|
|
396
|
+
/** Non-null in `foveationMode: 'page-table'`: the worker that owns the chunk
|
|
403
397
|
* cache + traversal + pager off the main thread, and the always-active slab it
|
|
404
398
|
* pages the returned frontier into. */
|
|
405
399
|
private readonly frontierWorker;
|
|
@@ -454,7 +448,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
454
448
|
* governed budget outgrows it, rather than the library's own default. */
|
|
455
449
|
private pageTableDrawTargetExplicit;
|
|
456
450
|
/** Last frontier's drawn (non-degenerate) splat count - the true on-screen size
|
|
457
|
-
* in `
|
|
451
|
+
* in `page-table` mode, where the slab is fully "active" but mostly degenerate. */
|
|
458
452
|
private pageTableDrawn;
|
|
459
453
|
/** Monotonic reschedule id; a stale plan (superseded by a newer request) is
|
|
460
454
|
* dropped. `pageTableInFlight` coalesces to one outstanding traversal. */
|
|
@@ -563,8 +557,8 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
563
557
|
* tells the worker's pager the new slot count.
|
|
564
558
|
*
|
|
565
559
|
* This is the mechanism that makes a shared pool worth having: storage follows
|
|
566
|
-
* the governed budget, so approaching a
|
|
567
|
-
* behind you hand theirs back, instead of every
|
|
560
|
+
* the governed budget, so approaching a mesh grows its pages while the ones
|
|
561
|
+
* behind you hand theirs back, instead of every mesh holding its ceiling for
|
|
568
562
|
* the whole session. Growth stops at the construction ceiling and at whatever
|
|
569
563
|
* the pool can actually spare - a mesh that cannot grow simply stays coarse
|
|
570
564
|
* rather than throwing.
|
|
@@ -684,7 +678,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
684
678
|
* The drawn-splat target currently driving the `.rad` page-table frontier -
|
|
685
679
|
* the governed budget, capped by
|
|
686
680
|
* {@link SplatMeshOptions.foveationDrawBudget}. `0` on a mesh that is not in
|
|
687
|
-
* `foveationMode: '
|
|
681
|
+
* `foveationMode: 'page-table'`, which has no frontier to target.
|
|
688
682
|
*
|
|
689
683
|
* This is the number that decides how deep the traversal descends, so it is
|
|
690
684
|
* what to watch when checking that a near mesh really did receive more
|
|
@@ -700,7 +694,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
700
694
|
*/
|
|
701
695
|
get lodScale(): number;
|
|
702
696
|
set lodScale(value: number);
|
|
703
|
-
/** In `
|
|
697
|
+
/** In `page-table` mode the slab is fully active but mostly degenerate, so the
|
|
704
698
|
* base `activeSplatCount` (slab size) is not the on-screen count - report the
|
|
705
699
|
* frontier's drawn size instead. */
|
|
706
700
|
get activeSplatCount(): number;
|
|
@@ -736,7 +730,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
736
730
|
/** Chunk fetches currently in flight. */
|
|
737
731
|
get pendingChunkCount(): number;
|
|
738
732
|
/**
|
|
739
|
-
* Main-thread cost of applying paging plans in `foveationMode: '
|
|
733
|
+
* Main-thread cost of applying paging plans in `foveationMode: 'page-table'`.
|
|
740
734
|
*
|
|
741
735
|
* A plan is applied whole, off the render loop's own timing, so its cost does
|
|
742
736
|
* not appear in {@link getUpdateTimings} - but it lands on the same thread and
|
|
@@ -906,7 +900,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
906
900
|
* and it starts enabled. Failed / unfit / disabled tiles do not block reveal.
|
|
907
901
|
*/
|
|
908
902
|
private environmentPendingForReveal;
|
|
909
|
-
/** Creates a
|
|
903
|
+
/** Creates a performance event for a changed streamed-LOD tick, if any. */
|
|
910
904
|
private createPerformanceEvent;
|
|
911
905
|
/** Returns whether all new rows can coexist with the currently visible region. */
|
|
912
906
|
private canStageGroup;
|
|
@@ -963,7 +957,7 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
963
957
|
/** Ranks the env tile ahead of every LOD want in {@link flushClassicFetches}. */
|
|
964
958
|
private enqueueEnvironmentFetch;
|
|
965
959
|
/**
|
|
966
|
-
* Page-table reschedule (`foveationMode: '
|
|
960
|
+
* Page-table reschedule (`foveationMode: 'page-table'`): posts the camera to the
|
|
967
961
|
* worker, which owns the cache + traversal + pager and replies asynchronously
|
|
968
962
|
* with a paging plan. Coalesced to one outstanding request so the main thread
|
|
969
963
|
* never blocks. Also drives chunk fetching, in priority order.
|
|
@@ -979,8 +973,8 @@ export declare class StreamedSplatMesh extends SplatMesh {
|
|
|
979
973
|
* worker's cache/traversal/gather can use it. */
|
|
980
974
|
private forwardChunkToWorker;
|
|
981
975
|
/** 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
|
|
983
|
-
* detail is not structurally starved on the non-
|
|
976
|
+
* per-host cap simply queues. Same cap for classic and page-table so near
|
|
977
|
+
* detail is not structurally starved on the non-page-table path. */
|
|
984
978
|
private get maxInflight();
|
|
985
979
|
/**
|
|
986
980
|
* Whether this mesh may run its speculative background sweep. A mesh with no
|
|
@@ -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 './splat-budget';
|
|
23
|
+
export { SplatLoadError, isAbortError, type SplatProgressCallback, type StreamedSplatFormat, type SplatRequestOptions, type SplatLoadPhase, type SplatInputOptions, } from './loading';
|