@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,12 @@
1
+ /**
2
+ * `@voluma/vlam/static-lod` - worker-built merged hierarchy for a fully
3
+ * decoded capture.
4
+ *
5
+ * {@link StaticLodSplatMesh.load} fetches through `@voluma/vlam/loaders` and
6
+ * then builds the hierarchy off the main thread. Import this entry rather
7
+ * than calling a streaming alias: there is none.
8
+ *
9
+ * @module static-lod
10
+ */
11
+ export { StaticLodSplatMesh, type StaticLodSplatMeshOptions, type StaticLodSplatMeshLoadOptions, type StaticLodLoadProgress, } from './static-lod-splat-mesh';
12
+ export type { StaticLodBuildProgress } from './static-lod';
@@ -1,7 +1,7 @@
1
1
  /** @role Bridge - Camera-aware rendering for worker-built static splat hierarchies. */
2
2
  import * as THREE from 'three/webgpu';
3
- import { type SplatLoadOptions } from './load-scene';
4
- import { SplatMesh, type SplatMeshOptions, type SplatUpdateOptions } from './splat-mesh';
3
+ import { type SplatDataLoadOptions } from '../loaders/load-splat-data';
4
+ import { SplatMesh, type SplatMeshOptions, type SplatUpdateOptions } from '../core/splat-mesh';
5
5
  import type { StaticLodBuildProgress } from './static-lod';
6
6
  export interface StaticLodSplatMeshOptions extends SplatMeshOptions {
7
7
  /** Initial selected-frontier budget. Defaults to the build ceiling. */
@@ -18,7 +18,7 @@ export interface StaticLodLoadProgress {
18
18
  readonly completed: number;
19
19
  readonly total: number;
20
20
  }
21
- export interface StaticLodSplatMeshLoadOptions extends StaticLodSplatMeshOptions, SplatLoadOptions {
21
+ export interface StaticLodSplatMeshLoadOptions extends StaticLodSplatMeshOptions, SplatDataLoadOptions {
22
22
  }
23
23
  /**
24
24
  * Static splat mesh backed by a merged hierarchy and camera-aware frontier.
@@ -1,4 +1,4 @@
1
- import type { SplatData } from './splat-data';
1
+ import type { SplatData } from '../core/splat-data';
2
2
  import type { StaticLodBuildProgress } from './static-lod';
3
3
  export interface StaticLodBuildRequest {
4
4
  readonly type: 'build';
@@ -1,4 +1,4 @@
1
- import type { SplatData } from './splat-data';
1
+ import type { SplatData } from '../core/splat-data';
2
2
  /** Progress emitted while a static scene is spatially ordered and merged. */
3
3
  export interface StaticLodBuildProgress {
4
4
  readonly completed: number;
@@ -18,14 +18,14 @@ function rt(t, n, o = lt) {
18
18
  };
19
19
  }
20
20
  function ht(t, n, o, s, e, i = Number.POSITIVE_INFINITY) {
21
- const c = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), l = new ft(), p = s.origin.x, h = s.origin.y, f = s.origin.z, r = s.forward, a = (r == null ? void 0 : r.x) ?? 0, M = (r == null ? void 0 : r.y) ?? 0, b = (r == null ? void 0 : r.z) ?? 0, N = r !== void 0, { coneDot0: S, coneDot: v, coneFoveate: F, behindFoveate: A } = s, R = (y) => {
22
- const d = Math.floor(y / o), m = t.get(d);
23
- return !m || !m.radTree ? null : { data: m, local: y - d * o };
24
- }, D = (y, d) => {
21
+ const c = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), l = new ft(), p = s.origin.x, h = s.origin.y, f = s.origin.z, r = s.forward, a = (r == null ? void 0 : r.x) ?? 0, M = (r == null ? void 0 : r.y) ?? 0, b = (r == null ? void 0 : r.z) ?? 0, N = r !== void 0, { coneDot0: S, coneDot: v, coneFoveate: F, behindFoveate: A } = s, R = (y) => {
22
+ const u = Math.floor(y / o), m = t.get(u);
23
+ return !m || !m.radTree ? null : { data: m, local: y - u * o };
24
+ }, D = (y, u) => {
25
25
  let m = c.get(y);
26
- m || (m = [], c.set(y, m)), m.push(d);
27
- }, V = (y, d) => {
28
- const m = y.positions, P = d * 3, E = m[P] - p, C = m[P + 1] - h, O = m[P + 2] - f, x = Math.sqrt(E * E + C * C + O * O) || 1e-6, U = y.radTree.size[d] / x;
26
+ m || (m = [], c.set(y, m)), m.push(u);
27
+ }, V = (y, u) => {
28
+ const m = y.positions, P = u * 3, E = m[P] - p, C = m[P + 1] - h, O = m[P + 2] - f, x = Math.sqrt(E * E + C * C + O * O) || 1e-6, U = y.radTree.size[u] / x;
29
29
  if (!N) return U;
30
30
  const I = E * a + C * M + O * b;
31
31
  if (I <= 0) return U * A;
@@ -41,19 +41,19 @@ function ht(t, n, o, s, e, i = Number.POSITIVE_INFINITY) {
41
41
  const $ = /* @__PURE__ */ new Set();
42
42
  for (const y of n) {
43
43
  if ($.has(y)) continue;
44
- const d = R(y);
45
- d && ($.add(y), l.push(y, V(d.data, d.local)), _++);
44
+ const u = R(y);
45
+ u && ($.add(y), l.push(y, V(u.data, u.local)), _++);
46
46
  }
47
47
  let k = !1;
48
48
  for (; l.size > 0; ) {
49
49
  const y = l.peekPriority();
50
50
  if (y <= e) break;
51
- const d = l.peek(), m = R(d);
51
+ const u = l.peek(), m = R(u);
52
52
  if (!m) {
53
53
  l.pop(), _--;
54
54
  continue;
55
55
  }
56
- const P = Math.floor(d / o), E = m.data.radTree, C = E.childCount[m.local];
56
+ const P = Math.floor(u / o), E = m.data.radTree, C = E.childCount[m.local];
57
57
  if (C === 0) {
58
58
  l.pop(), D(P, m.local);
59
59
  continue;
@@ -67,7 +67,7 @@ function ht(t, n, o, s, e, i = Number.POSITIVE_INFINITY) {
67
67
  const x = E.childStart[m.local], U = Math.floor(x / o), I = Math.floor((x + C - 1) / o);
68
68
  let T = !0;
69
69
  for (let L = U; L <= I; L++)
70
- t.has(L) || (T = !1, y > (u.get(L) ?? 0) && u.set(L, y));
70
+ t.has(L) || (T = !1, y > (d.get(L) ?? 0) && d.set(L, y));
71
71
  if (!T) {
72
72
  D(P, m.local);
73
73
  continue;
@@ -80,9 +80,9 @@ function ht(t, n, o, s, e, i = Number.POSITIVE_INFINITY) {
80
80
  }
81
81
  let w = !1;
82
82
  for (; l.size > 0; ) {
83
- const y = l.pop(), d = Math.floor(y / o), m = y - d * o;
84
- if (D(d, m), !w) {
85
- const P = t.get(d), E = P == null ? void 0 : P.radTree, C = E ? E.childCount[m] : 0;
83
+ const y = l.pop(), u = Math.floor(y / o), m = y - u * o;
84
+ if (D(u, m), !w) {
85
+ const P = t.get(u), E = P == null ? void 0 : P.radTree, C = E ? E.childCount[m] : 0;
86
86
  if (C > 0) {
87
87
  const O = E.childStart[m], x = Math.floor(O / o), U = Math.floor((O + C - 1) / o);
88
88
  let I = !0;
@@ -94,9 +94,9 @@ function ht(t, n, o, s, e, i = Number.POSITIVE_INFINITY) {
94
94
  }
95
95
  const G = /* @__PURE__ */ new Map();
96
96
  let Y = 0;
97
- for (const [y, d] of c)
98
- G.set(y, Uint32Array.from(d)), Y += d.length;
99
- return { selection: G, count: Y, touched: u, budgetClamped: k, refinable: w };
97
+ for (const [y, u] of c)
98
+ G.set(y, Uint32Array.from(u)), Y += u.length;
99
+ return { selection: G, count: Y, touched: d, budgetClamped: k, refinable: w };
100
100
  }
101
101
  class ft {
102
102
  constructor() {
@@ -129,13 +129,13 @@ class ft {
129
129
  if (n.length > 0) {
130
130
  n[0] = e, o[0] = i;
131
131
  const c = n.length;
132
- let u = 0;
132
+ let d = 0;
133
133
  for (; ; ) {
134
- const l = 2 * u + 1, p = l + 1;
135
- let h = u;
136
- if (l < c && o[l] > o[h] && (h = l), p < c && o[p] > o[h] && (h = p), h === u) break;
137
- const f = n[u], r = o[u];
138
- n[u] = n[h], o[u] = o[h], n[h] = f, o[h] = r, u = h;
134
+ const l = 2 * d + 1, p = l + 1;
135
+ let h = d;
136
+ if (l < c && o[l] > o[h] && (h = l), p < c && o[p] > o[h] && (h = p), h === d) break;
137
+ const f = n[d], r = o[d];
138
+ n[d] = n[h], o[d] = o[h], n[h] = f, o[h] = r, d = h;
139
139
  }
140
140
  }
141
141
  return s;
@@ -145,8 +145,8 @@ function nt(t) {
145
145
  return [0, 3, 8, 15][t] ?? 0;
146
146
  }
147
147
  const ot = 10, z = 1 << ot, q = 1e-18, st = (t, n) => {
148
- const o = n * 6, s = t[o], e = t[o + 1], i = t[o + 2], c = t[o + 3], u = t[o + 4], l = t[o + 5];
149
- return s * (c * l - u * u) - e * (e * l - u * i) + i * (e * u - c * i);
148
+ const o = n * 6, s = t[o], e = t[o + 1], i = t[o + 2], c = t[o + 3], d = t[o + 4], l = t[o + 5];
149
+ return s * (c * l - d * d) - e * (e * l - d * i) + i * (e * d - c * i);
150
150
  }, pt = (t, n, o) => {
151
151
  const s = t[o * 4 + 3] / 255, e = Math.sqrt(Math.max(q, st(n, o)));
152
152
  return Math.max(q, s * e);
@@ -156,7 +156,7 @@ const ot = 10, z = 1 << ot, q = 1e-18, st = (t, n) => {
156
156
  }, W = (t) => {
157
157
  let n = t & 1023;
158
158
  return n = (n | n << 16) & 50331903, n = (n | n << 8) & 50393103, n = (n | n << 4) & 51130563, n = (n | n << 2) & 153391689, n >>> 0;
159
- }, ut = (t, n, o) => (W(t) | W(n) << 1 | W(o) << 2) >>> 0, dt = (t, n) => {
159
+ }, dt = (t, n, o) => (W(t) | W(n) << 1 | W(o) << 2) >>> 0, ut = (t, n) => {
160
160
  const o = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY], s = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];
161
161
  for (let p = 0; p < n; p++) {
162
162
  const h = p * 3;
@@ -165,7 +165,7 @@ const ot = 10, z = 1 << ot, q = 1e-18, st = (t, n) => {
165
165
  o[f] = Math.min(o[f], r), s[f] = Math.max(s[f], r);
166
166
  }
167
167
  }
168
- let e = new Uint32Array(n), i = new Uint32Array(n), c = new Uint32Array(n), u = new Uint32Array(n);
168
+ let e = new Uint32Array(n), i = new Uint32Array(n), c = new Uint32Array(n), d = new Uint32Array(n);
169
169
  const l = o.map(
170
170
  (p, h) => (z - 1) / Math.max(1e-12, s[h] - p)
171
171
  );
@@ -189,7 +189,7 @@ const ot = 10, z = 1 << ot, q = 1e-18, st = (t, n) => {
189
189
  Math.floor((t[h + 2] - o[2]) * l[2])
190
190
  )
191
191
  );
192
- e[p] = p, c[p] = ut(f, r, a);
192
+ e[p] = p, c[p] = dt(f, r, a);
193
193
  }
194
194
  for (let p = 0; p < 30; p += ot) {
195
195
  const h = new Uint32Array(z);
@@ -204,9 +204,9 @@ const ot = 10, z = 1 << ot, q = 1e-18, st = (t, n) => {
204
204
  }
205
205
  for (let r = 0; r < n; r++) {
206
206
  const a = c[r], M = a >>> p & z - 1, b = h[M];
207
- h[M] = b + 1, u[b] = a, i[b] = e[r];
207
+ h[M] = b + 1, d[b] = a, i[b] = e[r];
208
208
  }
209
- [c, u] = [u, c], [e, i] = [i, e];
209
+ [c, d] = [d, c], [e, i] = [i, e];
210
210
  }
211
211
  return e;
212
212
  };
@@ -261,11 +261,11 @@ const B = (t) => t.shPacked ? nt(t.shPacked.bands) : 0, mt = (t, n) => ({
261
261
  );
262
262
  }
263
263
  }, ct = (t, n, o, s, e) => {
264
- let i = 0, c = n, u = -1;
264
+ let i = 0, c = n, d = -1;
265
265
  const l = [0, 0, 0], p = [0, 0, 0];
266
266
  for (let a = n; a < o; a++) {
267
267
  const M = t.masses[a];
268
- i += M, M > u && (u = M, c = a);
268
+ i += M, M > d && (d = M, c = a);
269
269
  for (let b = 0; b < 3; b++)
270
270
  l[b] = l[b] + t.positions[a * 3 + b] * M, p[b] = p[b] + t.colors[a * 4 + b] * M;
271
271
  }
@@ -305,8 +305,8 @@ const B = (t) => t.shPacked ? nt(t.shPacked.bands) : 0, mt = (t, n) => ({
305
305
  }
306
306
  const s = Math.ceil(t.count / o.count), e = mt(s, t);
307
307
  for (let i = 0; i < o.count; i++) {
308
- const c = Math.floor(i * t.count / o.count), u = Math.max(c + 1, Math.floor((i + 1) * t.count / o.count));
309
- e.count = u - c;
308
+ const c = Math.floor(i * t.count / o.count), d = Math.max(c + 1, Math.floor((i + 1) * t.count / o.count));
309
+ e.count = d - c;
310
310
  for (let l = 0; l < e.count; l++)
311
311
  g(t, n[c + l], e, l);
312
312
  ct(e, 0, e.count, o, i);
@@ -323,17 +323,17 @@ function Mt(t, n, o) {
323
323
  return { data: t, contentSplatCount: 0, finestSplatCount: 0, roots: new Uint32Array() };
324
324
  const s = Math.max(1, Math.min(t.count, Math.floor(n)));
325
325
  o == null || o({ completed: 0, total: t.count });
326
- const e = dt(t.positions, t.count), i = [s];
326
+ const e = ut(t.positions, t.count), i = [s];
327
327
  for (; (i.at(-1) ?? 0) > 1; )
328
328
  i.push(Math.ceil(i.at(-1) / 2));
329
- const c = i.reduce((k, w) => k + w, 0), u = new Float32Array(c * 3), l = new Uint8Array(c * 4), p = new Float32Array(c * 6), h = new Float64Array(c), f = new Uint32Array(c), r = new Uint16Array(c), a = new Uint32Array(c), M = new Float32Array(c), b = t.sh ? new Uint32Array(c) : void 0, N = B(t), S = t.shPacked ? new Uint32Array(c * N) : void 0, v = [];
329
+ const c = i.reduce((k, w) => k + w, 0), d = new Float32Array(c * 3), l = new Uint8Array(c * 4), p = new Float32Array(c * 6), h = new Float64Array(c), f = new Uint32Array(c), r = new Uint16Array(c), a = new Uint32Array(c), M = new Float32Array(c), b = t.sh ? new Uint32Array(c) : void 0, N = B(t), S = t.shPacked ? new Uint32Array(c * N) : void 0, v = [];
330
330
  let F = 0;
331
331
  const A = i.map((k) => {
332
332
  v.push(F);
333
333
  const w = F;
334
334
  return F += k, {
335
335
  count: k,
336
- positions: u.subarray(w * 3, F * 3),
336
+ positions: d.subarray(w * 3, F * 3),
337
337
  colors: l.subarray(w * 4, F * 4),
338
338
  covariances: p.subarray(w * 6, F * 6),
339
339
  masses: h.subarray(w, F),
@@ -351,20 +351,20 @@ function Mt(t, n, o) {
351
351
  yt(A[k - 1], A[k]);
352
352
  for (let k = 1; k < A.length; k++) {
353
353
  const w = A[k], G = A[k - 1], Y = v[k], y = v[k - 1];
354
- for (let d = 0; d < w.count; d++) {
355
- const m = Math.min(2, G.count - d * 2);
356
- r[Y + d] = m, a[Y + d] = y + d * 2;
354
+ for (let u = 0; u < w.count; u++) {
355
+ const m = Math.min(2, G.count - u * 2);
356
+ r[Y + u] = m, a[Y + u] = y + u * 2;
357
357
  }
358
358
  }
359
359
  const R = { childCount: r, childStart: a, size: M }, D = t.sh && b ? { ...t.sh, labels: b } : void 0, V = t.shPacked && S ? { ...t.shPacked, packed: S } : void 0, _ = {
360
360
  count: c,
361
- positions: u,
361
+ positions: d,
362
362
  colors: l,
363
363
  covariances: p,
364
364
  ...D ? { sh: D } : {},
365
365
  ...V ? { shPacked: V } : {},
366
366
  ...t.antialias === void 0 ? {} : { antialias: t.antialias },
367
- ...t.sourceFormat === void 0 ? {} : { sourceFormat: t.sourceFormat },
367
+ ...t.format === void 0 ? {} : { format: t.format },
368
368
  radTree: R
369
369
  };
370
370
  return o == null || o({ completed: t.count, total: t.count }), {
@@ -383,7 +383,7 @@ const kt = (t) => (J(t), {
383
383
  ...t.sh ? { sh: { ...t.sh, labels: t.sh.labels.slice() } } : {},
384
384
  ...t.shPacked ? { shPacked: { ...t.shPacked, packed: t.shPacked.packed.slice() } } : {},
385
385
  ...t.antialias === void 0 ? {} : { antialias: t.antialias },
386
- ...t.sourceFormat === void 0 ? {} : { sourceFormat: t.sourceFormat }
386
+ ...t.format === void 0 ? {} : { format: t.format }
387
387
  });
388
388
  function wt(t, n) {
389
389
  try {
@@ -445,7 +445,7 @@ self.onmessage = (t) => {
445
445
  j(n);
446
446
  });
447
447
  };
448
- //# sourceMappingURL=static-lod-worker-BFIwsvQc.js.map
448
+ //# sourceMappingURL=static-lod-worker-CjrXUR8x.js.map
449
449
  `, o = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", a], { type: "text/javascript;charset=utf-8" });
450
450
  function r(n) {
451
451
  let t;
@@ -471,4 +471,4 @@ function r(n) {
471
471
  export {
472
472
  r as default
473
473
  };
474
- //# sourceMappingURL=static-lod-worker-D2fyqQZO.js.map
474
+ //# sourceMappingURL=static-lod-worker-DktKnJkR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"static-lod-worker-D2fyqQZO.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"static-lod-worker-DktKnJkR.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,148 @@
1
+ var S = Object.defineProperty;
2
+ var V = (s, r, e) => r in s ? S(s, r, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[r] = e;
3
+ var i = (s, r, e) => V(s, typeof r != "symbol" ? r + "" : r, e);
4
+ import * as g from "three/webgpu";
5
+ import { loadSplatData as L } from "./loaders.js";
6
+ import { S as P } from "./splat-mesh-CsLOQb08.js";
7
+ const b = 4096, A = 250, x = (s) => {
8
+ const r = [
9
+ s.positions.buffer,
10
+ s.colors.buffer,
11
+ s.covariances.buffer
12
+ ];
13
+ return s.sh && r.push(s.sh.labels.buffer), s.shPacked && r.push(s.shPacked.packed.buffer), r;
14
+ }, w = (s, r) => {
15
+ if (!Number.isFinite(s) || s <= 0)
16
+ throw new RangeError("StaticLodSplatMesh budget must be a positive finite number.");
17
+ const e = Math.min(r, Math.floor(s));
18
+ return e === r || e < b ? Math.max(1, e) : Math.max(
19
+ b,
20
+ Math.floor(e / b) * b
21
+ );
22
+ }, E = async (s, r, e) => {
23
+ const n = (await import("./static-lod-worker-DktKnJkR.js")).default, o = new n();
24
+ return await new Promise((c, d) => {
25
+ const a = () => {
26
+ o.terminate(), d(new DOMException("Static LOD build aborted.", "AbortError"));
27
+ };
28
+ if (e != null && e.aborted) {
29
+ a();
30
+ return;
31
+ }
32
+ e == null || e.addEventListener("abort", a, { once: !0 }), o.onerror = (l) => {
33
+ e == null || e.removeEventListener("abort", a), o.terminate(), d(new Error(l.message));
34
+ }, o.onmessage = (l) => {
35
+ var f, m;
36
+ const u = l.data;
37
+ if (u.type === "progress") {
38
+ (f = r.onLodProgress) == null || f.call(r, u.progress), (m = r.onAutoLodProgress) == null || m.call(r, { phase: "lod-build", ...u.progress });
39
+ return;
40
+ }
41
+ if (u.type === "error") {
42
+ e == null || e.removeEventListener("abort", a), o.terminate(), d(new Error(u.message));
43
+ return;
44
+ }
45
+ u.type === "built" && (e == null || e.removeEventListener("abort", a), c({
46
+ data: u.data,
47
+ contentSplatCount: u.contentSplatCount,
48
+ finestSplatCount: u.finestSplatCount,
49
+ worker: o
50
+ }));
51
+ };
52
+ const h = {
53
+ type: "build",
54
+ source: s,
55
+ maxBudget: r.maxBudget
56
+ };
57
+ o.postMessage(h, x(s));
58
+ });
59
+ };
60
+ class p extends P {
61
+ constructor(e, t, n, o, c) {
62
+ super(e, c);
63
+ i(this, "worker");
64
+ i(this, "ceilingValue");
65
+ i(this, "contentCountValue");
66
+ i(this, "budgetValue");
67
+ i(this, "sequence", 0);
68
+ i(this, "lastScheduleAt", -1 / 0);
69
+ i(this, "selectionPending", !1);
70
+ i(this, "cameraLocal", new g.Vector3());
71
+ i(this, "cameraForward", new g.Vector3(0, 0, -1));
72
+ i(this, "inverseWorld", new g.Matrix4());
73
+ this.worker = o, this.ceilingValue = n, this.contentCountValue = t, this.budgetValue = w(c.budget ?? this.ceilingValue, this.ceilingValue), this.replaceActivePrefix(this.ceilingValue), this.worker.onmessage = (d) => {
74
+ const a = d.data;
75
+ if (a.type === "error") {
76
+ this.selectionPending = !1;
77
+ return;
78
+ }
79
+ a.type !== "selection" || a.sequence !== this.sequence || (this.selectionPending = !1, this.replaceActiveIndices(a.indices));
80
+ }, this.budgetValue < this.ceilingValue && this.scheduleSelection(!0);
81
+ }
82
+ /** Loads, decodes and builds a merged static hierarchy without blocking UI. */
83
+ static async load(e, t) {
84
+ var d, a;
85
+ let n = !1;
86
+ const o = await L(e, {
87
+ ...t,
88
+ onProgress: (h, l) => {
89
+ var u, f, m;
90
+ (u = t.onProgress) == null || u.call(t, h, l), (f = t.onAutoLodProgress) == null || f.call(t, { phase: "download", completed: h, total: l }), !n && l > 0 && h >= l && (n = !0, (m = t.onAutoLodProgress) == null || m.call(t, { phase: "decode", completed: 0, total: 1 }));
91
+ }
92
+ });
93
+ n || (d = t.onAutoLodProgress) == null || d.call(t, { phase: "decode", completed: 0, total: 1 }), (a = t.onAutoLodProgress) == null || a.call(t, { phase: "decode", completed: 1, total: 1 });
94
+ const c = await E(o, t, t.signal);
95
+ return new p(
96
+ c.data,
97
+ c.contentSplatCount,
98
+ c.finestSplatCount,
99
+ c.worker,
100
+ t
101
+ );
102
+ }
103
+ get budget() {
104
+ return this.budgetValue;
105
+ }
106
+ get budgetCeiling() {
107
+ return this.ceilingValue;
108
+ }
109
+ get maxBudget() {
110
+ return this.ceilingValue;
111
+ }
112
+ get contentSplatCount() {
113
+ return this.contentCountValue;
114
+ }
115
+ /** Changes the selected frontier budget within the immutable build ceiling. */
116
+ setBudget(e) {
117
+ const t = w(e, this.ceilingValue);
118
+ return t === this.budgetValue || (this.budgetValue = t, this.selectionPending = !1, this.scheduleSelection(!0)), t;
119
+ }
120
+ update(e, t, n = {}) {
121
+ super.update(e, t, n), this.updateLod(e);
122
+ }
123
+ /** Schedules a camera-aware cut when a unified renderer owns drawing/sorting. */
124
+ updateLod(e) {
125
+ e.updateMatrixWorld(), this.updateWorldMatrix(!0, !1), this.inverseWorld.copy(this.matrixWorld).invert(), this.cameraLocal.setFromMatrixPosition(e.matrixWorld).applyMatrix4(this.inverseWorld), e.getWorldDirection(this.cameraForward).transformDirection(this.inverseWorld), this.scheduleSelection(!1);
126
+ }
127
+ dispose() {
128
+ this.disposed || (this.worker.terminate(), super.dispose());
129
+ }
130
+ scheduleSelection(e) {
131
+ if (this.disposed || this.selectionPending) return;
132
+ const t = performance.now();
133
+ if (!e && t - this.lastScheduleAt < A) return;
134
+ this.lastScheduleAt = t, this.selectionPending = !0;
135
+ const n = {
136
+ type: "select",
137
+ sequence: ++this.sequence,
138
+ budget: this.budgetValue,
139
+ cameraLocal: this.cameraLocal.toArray(),
140
+ cameraForward: this.cameraForward.toArray()
141
+ };
142
+ this.worker.postMessage(n);
143
+ }
144
+ }
145
+ export {
146
+ p as StaticLodSplatMesh
147
+ };
148
+ //# sourceMappingURL=static-lod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-lod.js","sources":["../src/lib/static-lod/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 '../loaders/load-splat-data';\nimport type { SplatData } from '../core/splat-data';\nimport { SplatMesh, type SplatMeshOptions, type SplatUpdateOptions } from '../core/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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"}
@@ -2,10 +2,10 @@
2
2
  * Shared splat-budget governance across multiple streamed meshes.
3
3
  *
4
4
  * A single `StreamedSplatMesh` keeps itself within a per-device budget, but a
5
- * host that shows several streamed scenes at once (a main capture plus marker
5
+ * host that shows several streamed scenes at once (a main capture plus additional
6
6
  * or inset meshes) must not let each mesh claim the whole device budget -
7
7
  * their pools are separate, so the costs add. Historically hosts hand-tuned
8
- * this ("shrink the main mesh to 0.7 when markers exist"); the
8
+ * this ("shrink the main mesh to 0.7 when additional meshes exist"); the
9
9
  * {@link BudgetGovernor} makes it a first-class policy: register each mesh
10
10
  * with a priority weight and the governor splits one total budget across the
11
11
  * members, reallocating when membership, weights, or the total change.
@@ -50,7 +50,7 @@ export interface BudgetGovernorOptions {
50
50
  /**
51
51
  * Grow dead-band as a fraction of a member's current budget (default
52
52
  * `0.1`). A reallocation that would *raise* a member's budget by no more
53
- * than this fraction is skipped, so brief membership churn (a marker mesh
53
+ * than this fraction is skipped, so brief membership churn (an additional mesh
54
54
  * appearing for a moment) does not thrash LOD schedules. Shrinks always
55
55
  * apply immediately - that is what keeps `sum(member budgets) ≤ total` an
56
56
  * invariant rather than a goal.
@@ -98,7 +98,7 @@ export declare class BudgetGovernor {
98
98
  *
99
99
  * @param member - The mesh (or compatible object) to govern.
100
100
  * @param options - `weight` (default `1`): the member's share is
101
- * proportional to its weight - e.g. main mesh `7`, marker `3` reproduces
101
+ * proportional to its weight - e.g. main mesh `7`, additional mesh `3` reproduces
102
102
  * the old 0.7 host split. `0` registers the member suspended.
103
103
  */
104
104
  register(member: BudgetGovernedMember, options?: {
@@ -2,16 +2,16 @@
2
2
  * Camera-driven splat-budget weighting across several streamed meshes.
3
3
  *
4
4
  * {@link BudgetGovernor} splits one total by *priority*, which a host must
5
- * choose and maintain. That is the wrong axis for a scene of markers: what
6
- * makes a marker worth splats is that the camera is near it, and that changes
7
- * every frame. Splitting a pool evenly instead (`pool / N`) gives the marker
8
- * you fly up to a quarter of the budget it needs while three markers nobody is
5
+ * choose and maintain. That is the wrong axis for a scene of additional meshes:
6
+ * what makes a mesh worth splats is that the camera is near it, and that changes
7
+ * every frame. Splitting a pool evenly instead (`pool / N`) gives the mesh
8
+ * you fly up to a quarter of the budget it needs while three meshes nobody is
9
9
  * looking at hold the rest.
10
10
  *
11
11
  * {@link CameraBudgetGovernor} closes that loop: each update it measures every
12
12
  * member's projected size from the camera, multiplies in the host's priority
13
13
  * tier, and writes the resulting weights to a `BudgetGovernor` in one batch.
14
- * Approaching one of four markers pulls budget off the far ones automatically.
14
+ * Approaching one of four additional meshes pulls budget off the far ones automatically.
15
15
  *
16
16
  * This is Spark's model, reached differently. Spark shares one `lodSplatCount`
17
17
  * and biases meshes with a per-mesh `lodScale` (focused 2, adjacent 0.25,
@@ -53,7 +53,7 @@ export interface CameraBudgetMember extends BudgetGovernedMember {
53
53
  /**
54
54
  * The visibility that actually decides whether the member's splats reach the
55
55
  * screen, when that differs from `visible`. `SplatMesh` provides it: a
56
- * `UnifiedSplatRenderer` forces `visible = false` on every source it owns
56
+ * `UnifiedSplatMesh` forces `visible = false` on every source it owns
57
57
  * (only to keep the regular scene draw from double-drawing them) while the
58
58
  * source may be fully on screen through the unified draw - without this, the
59
59
  * governor would suspend every unified source and freeze its streaming.
@@ -117,8 +117,8 @@ export interface CameraBudgetMemberOptions {
117
117
  /**
118
118
  * Pins this member's weight, opting it out of camera weighting while it still
119
119
  * competes for the same total. Use it for a main scene that should hold a
120
- * steady share while markers fight over the rest - e.g. `fixedWeight: 4`
121
- * against markers averaging `1`.
120
+ * steady share while additional meshes fight over the rest - e.g. `fixedWeight: 4`
121
+ * against extras averaging `1`.
122
122
  */
123
123
  fixedWeight?: number;
124
124
  }
@@ -129,8 +129,8 @@ export interface CameraBudgetMemberOptions {
129
129
  * ```js
130
130
  * const governor = new CameraBudgetGovernor({ totalBudget: 4_000_000 });
131
131
  * governor.register(main, { fixedWeight: 4 }); // steady share
132
- * governor.register(markerA); // camera-weighted, priority 1
133
- * governor.register(markerB);
132
+ * governor.register(extraA); // camera-weighted, priority 1
133
+ * governor.register(extraB);
134
134
  *
135
135
  * // once per frame, after the scene graph is up to date:
136
136
  * governor.update(camera);
@@ -142,7 +142,7 @@ export interface CameraBudgetMemberOptions {
142
142
  *
143
143
  * **A member can only grow into a budget its pool can hold.** A streamed mesh
144
144
  * allocates its pool once, from its construction budget, and clamps `setBudget`
145
- * to it - so a marker built at a quarter of the total can never be given more
145
+ * to it - so a mesh built at a quarter of the total can never be given more
146
146
  * than a quarter, however close the camera gets. Construct governed meshes with
147
147
  * `maxBudget` set to the largest share they should ever reach, and price those
148
148
  * ceilings with `estimateSplatPoolBytes` first: the pools cost their ceilings
@@ -2,9 +2,9 @@
2
2
  * Cross-mesh decoded-chunk cache arbitration.
3
3
  *
4
4
  * Every {@link StreamedSplatMesh} caps its own decoded-chunk cache, and in
5
- * `foveationMode: 'pagetable'` that cap is `min(2 GiB, this capture's decoded
6
- * size)` - a number sized for *one* streamed scene. A scene of streamed markers
7
- * therefore has no ceiling at all: thirteen markers plus a main are thirteen
5
+ * `foveationMode: 'page-table'` that cap is `min(2 GiB, this capture's decoded
6
+ * size)` - a number sized for *one* streamed scene. A scene of streamed additional meshes
7
+ * therefore has no ceiling at all: thirteen extras plus a main are thirteen
8
8
  * plus one independent caps, and because each is sized to its own capture, a
9
9
  * desktop that fits them never evicts. The background sweep then runs to
10
10
  * completion against every one of them, pulling every capture in the scene into
@@ -43,8 +43,8 @@ export interface ChunkCacheClient {
43
43
  *
44
44
  * Bytes above it are handed to siblings that can use them, the way
45
45
  * `BudgetGovernor` waterfills past a member's `maxBudget`. Without it a scene
46
- * of one large capture and a dozen small markers would reserve most of the
47
- * envelope for markers that cannot fill it.
46
+ * of one large capture and a dozen small additional meshes would reserve most of the
47
+ * envelope for extras that cannot fill it.
48
48
  */
49
49
  readonly ceilingBytes: number;
50
50
  /**
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Every {@link StreamedSplatMesh} owns its own `ChunkLoader` worker and issues
5
5
  * chunk requests toward its own in-flight cap, so a scene of streamed meshes
6
- * fetches with no shared ordering: a marker the camera is pointed at competes
6
+ * fetches with no shared ordering: a mesh the camera is pointed at competes
7
7
  * for bandwidth and connection slots against a dozen distant ones, each of
8
8
  * which is equally entitled to its own cap. Spark does not have this problem
9
9
  * structurally - one global traversal orders every fetch want
@@ -81,7 +81,7 @@ export interface ChunkFetchSchedulerOptions {
81
81
  * Slots every registered mesh may hold regardless of weight. Default 1.
82
82
  *
83
83
  * Without a floor a scene's far meshes stop fetching entirely while the
84
- * focused one streams, and a marker with no coarse coverage draws nothing -
84
+ * focused one streams, and a mesh with no coarse coverage draws nothing -
85
85
  * so the floor is what turns "far meshes wait" into "far meshes trickle".
86
86
  *
87
87
  * One slot is always granted regardless of this setting: a mesh entitled to
@@ -156,8 +156,8 @@ export declare class ChunkFetchScheduler {
156
156
  * asks - which is what keeps the first mesh to reschedule from taking the
157
157
  * pipe and holding it. Dividing the *remainder* after every participant's
158
158
  * floor instead would invert the whole point on a large scene: thirteen
159
- * markers and a main at floor 1 consume a 16-slot pipe entirely, leaving the
160
- * focused marker a smaller share than the far ones it is competing with.
159
+ * additional meshes and a main at floor 1 consume a 16-slot pipe entirely, leaving the
160
+ * focused mesh a smaller share than the far ones it is competing with.
161
161
  *
162
162
  * The denominator counts every mesh that plausibly wants the pipe - all
163
163
  * registered meshes except those both weightless and idle, plus the caller.
@@ -1,4 +1,4 @@
1
- import { type SplatRequestOptions, type StreamedSplatFormat } from './loading';
1
+ import { type SplatRequestOptions, type StreamedSplatFormat } from '../loaders/loading';
2
2
  /**
3
3
  * Where a streamed dataset's files come from.
4
4
  *