@speridlabs/visus 1.0.3 → 2.0.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/dist/main.es.js CHANGED
@@ -1,14 +1,14 @@
1
- var lt = Object.defineProperty;
2
- var ht = (A, t, s) => t in A ? lt(A, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : A[t] = s;
3
- var c = (A, t, s) => ht(A, typeof t != "symbol" ? t + "" : t, s);
4
- import * as n from "three";
5
- class et {
1
+ var pt = Object.defineProperty;
2
+ var mt = (k, t, s) => t in k ? pt(k, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : k[t] = s;
3
+ var h = (k, t, s) => mt(k, typeof t != "symbol" ? t + "" : t, s);
4
+ import * as a from "three";
5
+ class lt {
6
6
  constructor() {
7
- c(this, "min", new n.Vector3(1 / 0, 1 / 0, 1 / 0));
8
- c(this, "max", new n.Vector3(-1 / 0, -1 / 0, -1 / 0));
9
- c(this, "center", new n.Vector3());
7
+ h(this, "min", new a.Vector3(1 / 0, 1 / 0, 1 / 0));
8
+ h(this, "max", new a.Vector3(-1 / 0, -1 / 0, -1 / 0));
9
+ h(this, "center", new a.Vector3());
10
10
  /** Half extents (size/2) */
11
- c(this, "halfExtents", new n.Vector3());
11
+ h(this, "halfExtents", new a.Vector3());
12
12
  }
13
13
  /**
14
14
  * Reset the bounding box to its initial state
@@ -49,28 +49,28 @@ class et {
49
49
  * @returns THREE.Box3 representation
50
50
  */
51
51
  toBox3() {
52
- return new n.Box3().set(this.min, this.max);
52
+ return new a.Box3().set(this.min, this.max);
53
53
  }
54
54
  /**
55
55
  * Create a clone of this bounding box
56
56
  * @returns New bounding box with the same values
57
57
  */
58
58
  clone() {
59
- const t = new et();
59
+ const t = new lt();
60
60
  return t.min.copy(this.min), t.max.copy(this.max), t.center.copy(this.center), t.halfExtents.copy(this.halfExtents), t;
61
61
  }
62
62
  }
63
- class ut {
63
+ class xt {
64
64
  // TODO: there is no sh spherical harmonics
65
65
  constructor(t = 0) {
66
- c(this, "numSplats", 0);
67
- c(this, "positions");
68
- c(this, "rotations");
69
- c(this, "scales");
70
- c(this, "colors");
71
- c(this, "opacities");
72
- c(this, "centers");
73
- c(this, "boundingBox", new et());
66
+ h(this, "numSplats", 0);
67
+ h(this, "positions");
68
+ h(this, "rotations");
69
+ h(this, "scales");
70
+ h(this, "colors");
71
+ h(this, "opacities");
72
+ h(this, "centers");
73
+ h(this, "boundingBox", new lt());
74
74
  this.numSplats = t, this.allocateBuffers(t);
75
75
  }
76
76
  allocateBuffers(t) {
@@ -85,13 +85,13 @@ class ut {
85
85
  * @param color Color
86
86
  * @param opacity Opacity value
87
87
  */
88
- setSplat(t, s, e, r, o, i) {
88
+ setSplat(t, s, e, o, r, n) {
89
89
  if (t >= this.numSplats)
90
90
  throw new Error(
91
91
  `Splat index out of bounds: ${t} >= ${this.numSplats}`
92
92
  );
93
- const a = t * 3, d = t * 4, f = t * 3, v = t * 3;
94
- this.positions[a] = s.x, this.positions[a + 1] = s.y, this.positions[a + 2] = s.z, this.rotations[d] = e.x, this.rotations[d + 1] = e.y, this.rotations[d + 2] = e.z, this.rotations[d + 3] = e.w, this.scales[f] = r.x, this.scales[f + 1] = r.y, this.scales[f + 2] = r.z, this.colors[v] = o.r, this.colors[v + 1] = o.g, this.colors[v + 2] = o.b, this.opacities[t] = i, this.centers[a] = s.x, this.centers[a + 1] = s.y, this.centers[a + 2] = s.z;
93
+ const i = t * 3, l = t * 4, x = t * 3, w = t * 3;
94
+ this.positions[i] = s.x, this.positions[i + 1] = s.y, this.positions[i + 2] = s.z, this.rotations[l] = e.x, this.rotations[l + 1] = e.y, this.rotations[l + 2] = e.z, this.rotations[l + 3] = e.w, this.scales[x] = o.x, this.scales[x + 1] = o.y, this.scales[x + 2] = o.z, this.colors[w] = r.r, this.colors[w + 1] = r.g, this.colors[w + 2] = r.b, this.opacities[t] = n, this.centers[i] = s.x, this.centers[i + 1] = s.y, this.centers[i + 2] = s.z;
95
95
  }
96
96
  /**
97
97
  * Get a splat's data
@@ -103,29 +103,29 @@ class ut {
103
103
  throw new Error(
104
104
  `Splat index out of bounds: ${t} >= ${this.numSplats}`
105
105
  );
106
- const s = t * 3, e = t * 4, r = t * 3, o = t * 3;
106
+ const s = t * 3, e = t * 4, o = t * 3, r = t * 3;
107
107
  return {
108
- position: new n.Vector3(
108
+ position: new a.Vector3(
109
109
  this.positions[s],
110
110
  this.positions[s + 1],
111
111
  this.positions[s + 2]
112
112
  ),
113
- rotation: new n.Quaternion(
113
+ rotation: new a.Quaternion(
114
114
  this.rotations[e],
115
115
  this.rotations[e + 1],
116
116
  this.rotations[e + 2],
117
117
  this.rotations[e + 3]
118
118
  ),
119
119
  // Convert log scale back to linear scale for external use
120
- scale: new n.Vector3(
121
- Math.exp(this.scales[r]),
122
- Math.exp(this.scales[r + 1]),
123
- Math.exp(this.scales[r + 2])
120
+ scale: new a.Vector3(
121
+ Math.exp(this.scales[o]),
122
+ Math.exp(this.scales[o + 1]),
123
+ Math.exp(this.scales[o + 2])
124
124
  ),
125
- color: new n.Color(
126
- this.colors[o],
127
- this.colors[o + 1],
128
- this.colors[o + 2]
125
+ color: new a.Color(
126
+ this.colors[r],
127
+ this.colors[r + 1],
128
+ this.colors[r + 2]
129
129
  ),
130
130
  opacity: this.opacities[t]
131
131
  };
@@ -136,7 +136,7 @@ class ut {
136
136
  */
137
137
  calculateBoundingBox() {
138
138
  this.boundingBox.reset();
139
- const t = new n.Vector3();
139
+ const t = new a.Vector3();
140
140
  for (let s = 0; s < this.numSplats; s++) {
141
141
  const e = s * 3;
142
142
  t.set(
@@ -152,46 +152,46 @@ class ut {
152
152
  * This is for visualization/debugging purposes only, not for rendering
153
153
  */
154
154
  createDebugGeometry() {
155
- const t = new n.BufferGeometry();
155
+ const t = new a.BufferGeometry();
156
156
  t.setAttribute(
157
157
  "position",
158
- new n.BufferAttribute(this.positions, 3)
158
+ new a.BufferAttribute(this.positions, 3)
159
159
  );
160
- const s = new Float32Array(this.numSplats * 3), e = new n.Quaternion(), r = new n.Euler();
161
- for (let o = 0; o < this.numSplats; o++) {
162
- const i = o * 4, a = o * 3;
160
+ const s = new Float32Array(this.numSplats * 3), e = new a.Quaternion(), o = new a.Euler();
161
+ for (let r = 0; r < this.numSplats; r++) {
162
+ const n = r * 4, i = r * 3;
163
163
  e.set(
164
- this.rotations[i],
165
- this.rotations[i + 1],
166
- this.rotations[i + 2],
167
- this.rotations[i + 3]
168
- ), r.setFromQuaternion(e), s[a] = r.x, s[a + 1] = r.y, s[a + 2] = r.z;
164
+ this.rotations[n],
165
+ this.rotations[n + 1],
166
+ this.rotations[n + 2],
167
+ this.rotations[n + 3]
168
+ ), o.setFromQuaternion(e), s[i] = o.x, s[i + 1] = o.y, s[i + 2] = o.z;
169
169
  }
170
170
  return t.setAttribute(
171
171
  "rotation",
172
- new n.BufferAttribute(s, 3)
172
+ new a.BufferAttribute(s, 3)
173
173
  ), t.setAttribute(
174
174
  "scale",
175
- new n.BufferAttribute(this.scales, 3)
175
+ new a.BufferAttribute(this.scales, 3)
176
176
  ), t.setAttribute(
177
177
  "color",
178
- new n.BufferAttribute(this.colors, 3)
178
+ new a.BufferAttribute(this.colors, 3)
179
179
  ), t.setAttribute(
180
180
  "opacity",
181
- new n.BufferAttribute(this.opacities, 1)
181
+ new a.BufferAttribute(this.opacities, 1)
182
182
  ), t;
183
183
  }
184
184
  }
185
- class dt extends n.EventDispatcher {
185
+ class yt extends a.EventDispatcher {
186
186
  constructor() {
187
187
  super();
188
- c(this, "worker");
189
- c(this, "centers", null);
190
- c(this, "orderTexture", null);
188
+ h(this, "worker");
189
+ h(this, "centers", null);
190
+ h(this, "orderTexture", null);
191
191
  /** Bounding box data for optimization */
192
- c(this, "chunks", null);
193
- c(this, "lastCameraPosition", new n.Vector3());
194
- c(this, "lastCameraDirection", new n.Vector3());
192
+ h(this, "chunks", null);
193
+ h(this, "lastCameraPosition", new a.Vector3());
194
+ h(this, "lastCameraDirection", new a.Vector3());
195
195
  const s = this.createWorkerCode(), e = new Blob([s], { type: "application/javascript" });
196
196
  this.worker = new Worker(URL.createObjectURL(e)), this.worker.onmessage = this.onWorkerMessage.bind(this);
197
197
  }
@@ -202,14 +202,14 @@ class dt extends n.EventDispatcher {
202
202
  onWorkerMessage(s) {
203
203
  if (!this.orderTexture || !this.orderTexture.image)
204
204
  return console.error("SplatSorter: Order texture not initialized!");
205
- const { order: e, count: r } = s.data, o = this.orderTexture.image.data;
206
- if (!(o instanceof Uint32Array))
205
+ const { order: e, count: o } = s.data, r = this.orderTexture.image.data;
206
+ if (!(r instanceof Uint32Array))
207
207
  return console.error(
208
208
  "SplatSorter: Order texture data is not a Uint32Array!"
209
209
  );
210
- o.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
211
- const i = o.buffer.slice(0), a = { order: i };
212
- this.worker.postMessage(a, [i]), this.dispatchEvent({ type: "updated", count: r });
210
+ r.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
211
+ const n = r.buffer.slice(0), i = { order: n };
212
+ this.worker.postMessage(i, [n]), this.dispatchEvent({ type: "updated", count: o });
213
213
  }
214
214
  /**
215
215
  * Initializes the sorter with necessary data and textures.
@@ -217,34 +217,34 @@ class dt extends n.EventDispatcher {
217
217
  * @param centers A Float32Array containing the center position (x, y, z) for each splat.
218
218
  * @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
219
219
  */
220
- init(s, e, r) {
220
+ init(s, e, o) {
221
221
  if (!s || !(s.image.data instanceof Uint32Array))
222
222
  throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
223
223
  if (!e || e.length % 3 !== 0)
224
224
  throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");
225
225
  if (s.image.data.length < e.length / 3)
226
226
  throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
227
- const o = e.length / 3;
227
+ const r = e.length / 3;
228
228
  this.orderTexture = s, this.centers = e.slice();
229
- const i = this.orderTexture.image.data;
230
- for (let g = 0; g < o; g++) i[g] = g;
229
+ const n = this.orderTexture.image.data;
230
+ for (let b = 0; b < r; b++) n[b] = b;
231
231
  this.orderTexture.needsUpdate = !0;
232
- const a = i.buffer.slice(0), d = this.centers.buffer.slice(0), f = {
233
- order: a,
234
- centers: d
235
- }, v = [
236
- a,
237
- d
232
+ const i = n.buffer.slice(0), l = this.centers.buffer.slice(0), x = {
233
+ order: i,
234
+ centers: l
235
+ }, w = [
236
+ i,
237
+ l
238
238
  ];
239
- if (r) {
240
- this.chunks = r.slice();
241
- const g = this.chunks.buffer.slice(0);
242
- f.chunks = g, v.push(g);
239
+ if (o) {
240
+ this.chunks = o.slice();
241
+ const b = this.chunks.buffer.slice(0);
242
+ x.chunks = b, w.push(b);
243
243
  }
244
- this.worker.postMessage(f, v), queueMicrotask(() => {
244
+ this.worker.postMessage(x, w), queueMicrotask(() => {
245
245
  this.dispatchEvent({
246
246
  type: "updated",
247
- count: o
247
+ count: r
248
248
  });
249
249
  });
250
250
  }
@@ -259,31 +259,31 @@ class dt extends n.EventDispatcher {
259
259
  "SplatSorter: Cannot set mapping before initialization."
260
260
  );
261
261
  let e;
262
- const r = [];
262
+ const o = [];
263
263
  if (!s) {
264
- const d = this.centers.buffer.slice(0);
264
+ const l = this.centers.buffer.slice(0);
265
265
  return e = {
266
- centers: d,
266
+ centers: l,
267
267
  mapping: null
268
- }, r.push(d), this.worker.postMessage(e, r);
268
+ }, o.push(l), this.worker.postMessage(e, o);
269
269
  }
270
- const o = new Float32Array(s.length * 3);
271
- for (let d = 0; d < s.length; d++) {
272
- const f = s[d];
273
- if (f * 3 + 2 >= this.centers.length) {
270
+ const r = new Float32Array(s.length * 3);
271
+ for (let l = 0; l < s.length; l++) {
272
+ const x = s[l];
273
+ if (x * 3 + 2 >= this.centers.length) {
274
274
  console.warn(
275
- `SplatSorter: Mapping index ${f} out of bounds.`
275
+ `SplatSorter: Mapping index ${x} out of bounds.`
276
276
  );
277
277
  continue;
278
278
  }
279
- const v = f * 3, g = d * 3;
280
- o[g + 0] = this.centers[v + 0], o[g + 1] = this.centers[v + 1], o[g + 2] = this.centers[v + 2];
279
+ const w = x * 3, b = l * 3;
280
+ r[b + 0] = this.centers[w + 0], r[b + 1] = this.centers[w + 1], r[b + 2] = this.centers[w + 2];
281
281
  }
282
- const i = o.buffer.slice(0), a = s.buffer.slice(0);
282
+ const n = r.buffer.slice(0), i = s.buffer.slice(0);
283
283
  e = {
284
- centers: i,
285
- mapping: a
286
- }, r.push(i, a), this.worker.postMessage(e, r);
284
+ centers: n,
285
+ mapping: i
286
+ }, o.push(n, i), this.worker.postMessage(e, o);
287
287
  }
288
288
  /**
289
289
  * Updates the camera parameters used for sorting.
@@ -291,15 +291,15 @@ class dt extends n.EventDispatcher {
291
291
  * @param direction The camera's forward direction in the sorter's local coordinate space.
292
292
  */
293
293
  setCamera(s, e) {
294
- const r = this.lastCameraPosition.distanceToSquared(s) > 1e-7, o = this.lastCameraDirection.dot(e) < 0.9999;
295
- if (!r && !o)
294
+ const o = this.lastCameraPosition.distanceToSquared(s) > 1e-7, r = this.lastCameraDirection.dot(e) < 0.9999;
295
+ if (!o && !r)
296
296
  return;
297
297
  this.lastCameraPosition.copy(s), this.lastCameraDirection.copy(e);
298
- const i = {
298
+ const n = {
299
299
  cameraPosition: { x: s.x, y: s.y, z: s.z },
300
300
  cameraDirection: { x: e.x, y: e.y, z: e.z }
301
301
  };
302
- this.worker.postMessage(i);
302
+ this.worker.postMessage(n);
303
303
  }
304
304
  /**
305
305
  * Terminates the Web Worker and cleans up resources.
@@ -313,163 +313,163 @@ class dt extends n.EventDispatcher {
313
313
  */
314
314
  createWorkerCode() {
315
315
  return `(${(function() {
316
- let e = null, r = null, o = null, i = null, a = null, d = null, f = !1;
317
- const v = { x: 0, y: 0, z: 0 }, g = { x: 0, y: 0, z: 0 }, p = { x: 0, y: 0, z: 0 }, h = { x: 0, y: 0, z: 0 };
318
- let l = null, b = null;
319
- const T = 32, O = new Array(T).fill(0), q = new Array(T).fill(0), E = new Array(T).fill(0), R = (k, C, F) => {
320
- for (; k <= C; ) {
321
- const M = C + k >> 1, m = F(M);
322
- if (m > 0) k = M + 1;
323
- else if (m < 0) C = M - 1;
324
- else return M;
316
+ let e = null, o = null, r = null, n = null, i = null, l = null, x = !1;
317
+ const w = { x: 0, y: 0, z: 0 }, b = { x: 0, y: 0, z: 0 }, f = { x: 0, y: 0, z: 0 }, y = { x: 0, y: 0, z: 0 };
318
+ let v = null, S = null;
319
+ const z = 32, V = new Array(z).fill(0), Y = new Array(z).fill(0), R = new Array(z).fill(0), ot = (A, d, M) => {
320
+ for (; A <= d; ) {
321
+ const C = d + A >> 1, m = M(C);
322
+ if (m > 0) A = C + 1;
323
+ else if (m < 0) d = C - 1;
324
+ else return C;
325
325
  }
326
- return ~k;
327
- }, W = () => {
328
- if (!e || !r || !a || !d)
326
+ return ~A;
327
+ }, K = () => {
328
+ if (!e || !o || !i || !l)
329
329
  return;
330
- if (r.length === 0) {
331
- const y = {
330
+ if (o.length === 0) {
331
+ const c = {
332
332
  order: e.buffer,
333
333
  count: 0
334
334
  };
335
- self.postMessage(y, [e.buffer]), e = null;
335
+ self.postMessage(c, [e.buffer]), e = null;
336
336
  return;
337
337
  }
338
- const k = a.x, C = a.y, F = a.z, M = d.x, m = d.y, B = d.z, V = 1e-4, P = Math.abs(k - v.x) > V || Math.abs(C - v.y) > V || Math.abs(F - v.z) > V, x = Math.abs(M - g.x) > V || Math.abs(m - g.y) > V || Math.abs(B - g.z) > V;
339
- if (!f && !P && !x)
338
+ const A = i.x, d = i.y, M = i.z, C = l.x, m = l.y, _ = l.z, T = 1e-4, j = Math.abs(A - w.x) > T || Math.abs(d - w.y) > T || Math.abs(M - w.z) > T, N = Math.abs(C - b.x) > T || Math.abs(m - b.y) > T || Math.abs(_ - b.z) > T;
339
+ if (!x && !j && !N)
340
340
  return;
341
- f = !1, v.x = k, v.y = C, v.z = F, g.x = M, g.y = m, g.z = B;
342
- let u = 1 / 0, S = -1 / 0;
343
- for (let y = 0; y < 8; ++y) {
344
- const _ = y & 1 ? p.x : h.x, U = y & 2 ? p.y : h.y, w = y & 4 ? p.z : h.z, D = _ * M + U * m + w * B;
345
- u = Math.min(u, D), S = Math.max(S, D);
341
+ x = !1, w.x = A, w.y = d, w.z = M, b.x = C, b.y = m, b.z = _;
342
+ let O = 1 / 0, X = -1 / 0;
343
+ for (let c = 0; c < 8; ++c) {
344
+ const u = c & 1 ? f.x : y.x, g = c & 2 ? f.y : y.y, p = c & 4 ? f.z : y.z, I = u * C + g * m + p * _;
345
+ O = Math.min(O, I), X = Math.max(X, I);
346
346
  }
347
- const I = r.length / 3, L = S - u, z = (1 << Math.max(
347
+ const B = o.length / 3, G = X - O, D = (1 << Math.max(
348
348
  10,
349
- Math.min(20, Math.ceil(Math.log2(I / 4)))
349
+ Math.min(20, Math.ceil(Math.log2(B / 4)))
350
350
  )) + 1;
351
- if ((!l || l.length !== I) && (l = new Uint32Array(I)), !b || b.length !== z ? b = new Uint32Array(z) : b.fill(0), L < 1e-7) {
352
- for (let y = 0; y < I; ++y) l[y] = 0;
353
- b[0] = I;
354
- } else if (o && o.length > 0) {
355
- const y = o.length / 6;
356
- O.fill(0);
357
- for (let w = 0; w < y; ++w) {
358
- const D = w * 6, X = o[D + 0], Z = o[D + 1], $ = o[D + 2], H = o[D + 3], Y = X * M + Z * m + $ * B - u, J = Y - H, G = Y + H, Q = Math.max(
351
+ if ((!v || v.length !== B) && (v = new Uint32Array(B)), !S || S.length !== D ? S = new Uint32Array(D) : S.fill(0), G < 1e-7) {
352
+ for (let c = 0; c < B; ++c) v[c] = 0;
353
+ S[0] = B;
354
+ } else if (r && r.length > 0) {
355
+ const c = r.length / 6;
356
+ V.fill(0);
357
+ for (let p = 0; p < c; ++p) {
358
+ const I = p * 6, E = r[I + 0], U = r[I + 1], q = r[I + 2], P = r[I + 3], F = E * C + U * m + q * _ - O, W = F - P, L = F + P, $ = Math.max(
359
359
  0,
360
- Math.floor(J * T / L)
361
- ), tt = Math.min(
362
- T,
363
- Math.ceil(G * T / L)
360
+ Math.floor(W * z / G)
361
+ ), J = Math.min(
362
+ z,
363
+ Math.ceil(L * z / G)
364
364
  );
365
- for (let N = Q; N < tt; ++N)
366
- O[N]++;
365
+ for (let H = $; H < J; ++H)
366
+ V[H]++;
367
367
  }
368
- let _ = 0;
369
- for (let w = 0; w < T; ++w) _ += O[w];
370
- E[0] = 0, q[0] = 0;
371
- for (let w = 1; w < T; ++w)
372
- E[w - 1] = O[w - 1] / _ * z >>> 0, q[w] = q[w - 1] + E[w - 1];
373
- E[T - 1] = O[T - 1] / _ * z >>> 0;
374
- const U = L / T;
375
- for (let w = 0; w < I; ++w) {
376
- const D = w * 3, X = r[D + 0], Z = r[D + 1], $ = r[D + 2], H = X * M + Z * m + $ * B, J = (S - H) / U, G = Math.max(
368
+ let u = 0;
369
+ for (let p = 0; p < z; ++p) u += V[p];
370
+ R[0] = 0, Y[0] = 0;
371
+ for (let p = 1; p < z; ++p)
372
+ R[p - 1] = V[p - 1] / u * D >>> 0, Y[p] = Y[p - 1] + R[p - 1];
373
+ R[z - 1] = V[z - 1] / u * D >>> 0;
374
+ const g = G / z;
375
+ for (let p = 0; p < B; ++p) {
376
+ const I = p * 3, E = o[I + 0], U = o[I + 1], q = o[I + 2], P = E * C + U * m + q * _, W = (X - P) / g, L = Math.max(
377
377
  0,
378
378
  Math.min(
379
- T - 1,
380
- Math.floor(J)
379
+ z - 1,
380
+ Math.floor(W)
381
381
  )
382
- ), Q = J - G, tt = q[G] + E[G] * Q >>> 0, N = Math.min(tt, z - 1);
383
- l[w] = N, b[N]++;
382
+ ), $ = W - L, J = Y[L] + R[L] * $ >>> 0, H = Math.min(J, D - 1);
383
+ v[p] = H, S[H]++;
384
384
  }
385
385
  } else {
386
- const y = (z - 1) / L;
387
- for (let _ = 0; _ < I; ++_) {
388
- const U = _ * 3, w = r[U + 0], D = r[U + 1], X = r[U + 2], Z = w * M + D * m + X * B, H = (S - Z) * y >>> 0, Y = Math.min(H, z - 1);
389
- l[_] = Y, b[Y]++;
386
+ const c = (D - 1) / G;
387
+ for (let u = 0; u < B; ++u) {
388
+ const g = u * 3, p = o[g + 0], I = o[g + 1], E = o[g + 2], U = p * C + I * m + E * _, P = (X - U) * c >>> 0, F = Math.min(P, D - 1);
389
+ v[u] = F, S[F]++;
390
390
  }
391
391
  }
392
- for (let y = 1; y < z; y++)
393
- b[y] += b[y - 1];
394
- for (let y = I - 1; y >= 0; y--) {
395
- const _ = l[y], U = --b[_];
396
- e[U] = i ? i[y] : y;
392
+ for (let c = 1; c < D; c++)
393
+ S[c] += S[c - 1];
394
+ for (let c = B - 1; c >= 0; c--) {
395
+ const u = v[c], g = --S[u];
396
+ e[g] = n ? n[c] : c;
397
397
  }
398
- const at = k * M + C * m + F * B, rt = (y) => {
398
+ const rt = A * C + d * m + M * _, Q = (c) => {
399
399
  if (!e) return -1 / 0;
400
- const _ = e[y], U = _;
401
- if (!r || U * 3 + 2 >= r.length)
400
+ const u = e[c], g = u;
401
+ if (!o || g * 3 + 2 >= o.length)
402
402
  return -1 / 0;
403
- const w = U * 3;
404
- return r[w] * M + r[w + 1] * m + r[w + 2] * B - at;
403
+ const p = g * 3;
404
+ return o[p] * C + o[p + 1] * m + o[p + 2] * _ - rt;
405
405
  };
406
- let st = I;
407
- if (I > 0 && rt(I - 1) < 0) {
408
- const y = R(
406
+ let tt = B;
407
+ if (B > 0 && Q(B - 1) < 0) {
408
+ const c = ot(
409
409
  0,
410
- I - 1,
411
- rt
410
+ B - 1,
411
+ Q
412
412
  );
413
- st = y < 0 ? ~y : y;
413
+ tt = c < 0 ? ~c : c;
414
414
  }
415
- const ct = {
415
+ const st = {
416
416
  order: e.buffer,
417
- count: st
417
+ count: tt
418
418
  };
419
- self.postMessage(ct, [e.buffer]), e = null;
419
+ self.postMessage(st, [e.buffer]), e = null;
420
420
  };
421
- self.onmessage = (k) => {
422
- const C = k.data;
423
- C.order && (e = new Uint32Array(C.order));
424
- let F = !1;
425
- if (C.centers && (r = new Float32Array(C.centers), F = !0, f = !0), Object.prototype.hasOwnProperty.call(C, "mapping") && (i = C.mapping ? new Uint32Array(C.mapping) : null, f = !0), C.chunks) {
426
- if (o = new Float32Array(C.chunks), o.length > 0 && o[3] > 0)
427
- for (let M = 0; M < o.length / 6; ++M) {
428
- const m = M * 6, B = o[m + 0], V = o[m + 1], P = o[m + 2], x = o[m + 3], u = o[m + 4], S = o[m + 5];
429
- o[m + 0] = (B + x) * 0.5, o[m + 1] = (V + u) * 0.5, o[m + 2] = (P + S) * 0.5, o[m + 3] = Math.sqrt(
430
- (x - B) ** 2 + (u - V) ** 2 + (S - P) ** 2
421
+ self.onmessage = (A) => {
422
+ const d = A.data;
423
+ d.order && (e = new Uint32Array(d.order));
424
+ let M = !1;
425
+ if (d.centers && (o = new Float32Array(d.centers), M = !0, x = !0), Object.prototype.hasOwnProperty.call(d, "mapping") && (n = d.mapping ? new Uint32Array(d.mapping) : null, x = !0), d.chunks) {
426
+ if (r = new Float32Array(d.chunks), r.length > 0 && r[3] > 0)
427
+ for (let C = 0; C < r.length / 6; ++C) {
428
+ const m = C * 6, _ = r[m + 0], T = r[m + 1], j = r[m + 2], N = r[m + 3], O = r[m + 4], X = r[m + 5];
429
+ r[m + 0] = (_ + N) * 0.5, r[m + 1] = (T + O) * 0.5, r[m + 2] = (j + X) * 0.5, r[m + 3] = Math.sqrt(
430
+ (N - _) ** 2 + (O - T) ** 2 + (X - j) ** 2
431
431
  ) * 0.5;
432
432
  }
433
- f = !0;
433
+ x = !0;
434
434
  }
435
- if (F && r && r.length > 0) {
436
- p.x = h.x = r[0], p.y = h.y = r[1], p.z = h.z = r[2];
437
- for (let M = 1; M < r.length / 3; M++) {
438
- const m = M * 3;
439
- p.x = Math.min(p.x, r[m + 0]), h.x = Math.max(h.x, r[m + 0]), p.y = Math.min(p.y, r[m + 1]), h.y = Math.max(h.y, r[m + 1]), p.z = Math.min(p.z, r[m + 2]), h.z = Math.max(h.z, r[m + 2]);
435
+ if (M && o && o.length > 0) {
436
+ f.x = y.x = o[0], f.y = y.y = o[1], f.z = y.z = o[2];
437
+ for (let C = 1; C < o.length / 3; C++) {
438
+ const m = C * 3;
439
+ f.x = Math.min(f.x, o[m + 0]), y.x = Math.max(y.x, o[m + 0]), f.y = Math.min(f.y, o[m + 1]), y.y = Math.max(y.y, o[m + 1]), f.z = Math.min(f.z, o[m + 2]), y.z = Math.max(y.z, o[m + 2]);
440
440
  }
441
- } else F && r && r.length === 0 && (p.x = h.x = p.y = h.y = p.z = h.z = 0);
442
- C.cameraPosition && (a = C.cameraPosition), C.cameraDirection && (d = C.cameraDirection), W();
441
+ } else M && o && o.length === 0 && (f.x = y.x = f.y = y.y = f.z = y.z = 0);
442
+ d.cameraPosition && (i = d.cameraPosition), d.cameraDirection && (l = d.cameraDirection), K();
443
443
  };
444
444
  }).toString()})();`;
445
445
  }
446
446
  }
447
- const pt = (A, t) => {
448
- const s = ot(A), e = ot(t);
447
+ const gt = (k, t) => {
448
+ const s = ut(k), e = ut(t);
449
449
  return s | e << 16;
450
450
  };
451
- function ot(A) {
452
- const t = new Float32Array([A]), e = new Int32Array(t.buffer)[0];
453
- let r = e >> 16 & 32768, o = e >> 12 & 2047;
454
- const i = e >> 23 & 255;
455
- return i < 103 ? r : i > 142 ? (r |= 31744, r |= (i === 255 ? 0 : 1) && e & 8388607, r) : i < 113 ? (o |= 2048, r |= (o >> 114 - i) + (o >> 113 - i & 1), r) : (r |= i - 112 << 10 | o >> 1, r += o & 1, r);
451
+ function ut(k) {
452
+ const t = new Float32Array([k]), e = new Int32Array(t.buffer)[0];
453
+ let o = e >> 16 & 32768, r = e >> 12 & 2047;
454
+ const n = e >> 23 & 255;
455
+ return n < 103 ? o : n > 142 ? (o |= 31744, o |= (n === 255 ? 0 : 1) && e & 8388607, o) : n < 113 ? (r |= 2048, o |= (r >> 114 - n) + (r >> 113 - n & 1), o) : (o |= n - 112 << 10 | r >> 1, o += r & 1, o);
456
456
  }
457
- const ft = new ArrayBuffer(4), nt = new DataView(ft), mt = (A) => (nt.setUint32(0, A, !0), nt.getFloat32(0, !0));
458
- class xt {
457
+ const vt = new ArrayBuffer(4), dt = new DataView(vt), wt = (k) => (dt.setUint32(0, k, !0), dt.getFloat32(0, !0));
458
+ class bt {
459
459
  /**
460
460
  * Create a new TextureManager for a set of splats
461
461
  * @param splatData The splat data to manage textures for
462
462
  */
463
463
  constructor(t) {
464
- c(this, "transformA");
464
+ h(this, "transformA");
465
465
  // position xyz and rotation quaternion y,z components
466
- c(this, "transformB");
466
+ h(this, "transformB");
467
467
  // rotation quaternion x and scale xyz
468
- c(this, "colorTexture");
468
+ h(this, "colorTexture");
469
469
  // color an opacity
470
- c(this, "orderTexture");
471
- c(this, "textureWidth");
472
- c(this, "textureHeight");
470
+ h(this, "orderTexture");
471
+ h(this, "textureWidth");
472
+ h(this, "textureHeight");
473
473
  const s = t.numSplats;
474
474
  this.textureWidth = Math.ceil(Math.sqrt(s)), this.textureHeight = Math.ceil(s / this.textureWidth), this.transformA = this.createTransformATexture(t), this.transformB = this.createTransformBTexture(t), this.colorTexture = this.createColorTexture(t), this.orderTexture = this.createOrderTexture(s);
475
475
  }
@@ -482,21 +482,21 @@ class xt {
482
482
  const s = t.numSplats, e = new Float32Array(
483
483
  this.textureWidth * this.textureHeight * 4
484
484
  );
485
- for (let o = 0; o < s; o++) {
486
- const i = o * 4, a = o * 3, d = o * 4;
487
- e[i] = t.positions[a], e[i + 1] = t.positions[a + 1], e[i + 2] = t.positions[a + 2];
488
- const f = t.rotations[d + 0], v = t.rotations[d + 1], g = pt(f, v);
489
- e[i + 3] = mt(g);
485
+ for (let r = 0; r < s; r++) {
486
+ const n = r * 4, i = r * 3, l = r * 4;
487
+ e[n] = t.positions[i], e[n + 1] = t.positions[i + 1], e[n + 2] = t.positions[i + 2];
488
+ const x = t.rotations[l + 0], w = t.rotations[l + 1], b = gt(x, w);
489
+ e[n + 3] = wt(b);
490
490
  }
491
- const r = new n.DataTexture(
491
+ const o = new a.DataTexture(
492
492
  e,
493
493
  this.textureWidth,
494
494
  this.textureHeight,
495
- n.RGBAFormat,
496
- n.FloatType
495
+ a.RGBAFormat,
496
+ a.FloatType
497
497
  // Store as Float32, shader will reinterpret bits
498
498
  );
499
- return r.needsUpdate = !0, r.magFilter = n.NearestFilter, r.minFilter = n.NearestFilter, r;
499
+ return o.needsUpdate = !0, o.magFilter = a.NearestFilter, o.minFilter = a.NearestFilter, o;
500
500
  }
501
501
  /**
502
502
  * Create the transform B texture (scale and rotation xyz)
@@ -507,18 +507,18 @@ class xt {
507
507
  const s = t.numSplats, e = new Float32Array(
508
508
  this.textureWidth * this.textureHeight * 4
509
509
  );
510
- for (let o = 0; o < s; o++) {
511
- const i = o * 4, a = o * 3, d = o * 4;
512
- e[i] = t.scales[a], e[i + 1] = t.scales[a + 1], e[i + 2] = t.scales[a + 2], e[i + 3] = t.rotations[d + 2];
510
+ for (let r = 0; r < s; r++) {
511
+ const n = r * 4, i = r * 3, l = r * 4;
512
+ e[n] = t.scales[i], e[n + 1] = t.scales[i + 1], e[n + 2] = t.scales[i + 2], e[n + 3] = t.rotations[l + 2];
513
513
  }
514
- const r = new n.DataTexture(
514
+ const o = new a.DataTexture(
515
515
  e,
516
516
  this.textureWidth,
517
517
  this.textureHeight,
518
- n.RGBAFormat,
519
- n.FloatType
518
+ a.RGBAFormat,
519
+ a.FloatType
520
520
  );
521
- return r.needsUpdate = !0, r.magFilter = n.NearestFilter, r.minFilter = n.NearestFilter, r;
521
+ return o.needsUpdate = !0, o.magFilter = a.NearestFilter, o.minFilter = a.NearestFilter, o;
522
522
  }
523
523
  /**
524
524
  * Create the color texture (RGB and opacity)
@@ -529,18 +529,18 @@ class xt {
529
529
  const s = t.numSplats, e = new Float32Array(
530
530
  this.textureWidth * this.textureHeight * 4
531
531
  );
532
- for (let o = 0; o < s; o++) {
533
- const i = o * 4, a = o * 3;
534
- e[i] = t.colors[a], e[i + 1] = t.colors[a + 1], e[i + 2] = t.colors[a + 2], e[i + 3] = t.opacities[o];
532
+ for (let r = 0; r < s; r++) {
533
+ const n = r * 4, i = r * 3;
534
+ e[n] = t.colors[i], e[n + 1] = t.colors[i + 1], e[n + 2] = t.colors[i + 2], e[n + 3] = t.opacities[r];
535
535
  }
536
- const r = new n.DataTexture(
536
+ const o = new a.DataTexture(
537
537
  e,
538
538
  this.textureWidth,
539
539
  this.textureHeight,
540
- n.RGBAFormat,
541
- n.FloatType
540
+ a.RGBAFormat,
541
+ a.FloatType
542
542
  );
543
- return r.needsUpdate = !0, r;
543
+ return o.needsUpdate = !0, o;
544
544
  }
545
545
  /**
546
546
  * Create the order texture for sorting
@@ -549,14 +549,14 @@ class xt {
549
549
  */
550
550
  createOrderTexture(t) {
551
551
  const s = new Uint32Array(this.textureWidth * this.textureHeight);
552
- for (let r = 0; r < t; r++)
553
- s[r] = r;
554
- const e = new n.DataTexture(
552
+ for (let o = 0; o < t; o++)
553
+ s[o] = o;
554
+ const e = new a.DataTexture(
555
555
  s,
556
556
  this.textureWidth,
557
557
  this.textureHeight,
558
- n.RedIntegerFormat,
559
- n.UnsignedIntType
558
+ a.RedIntegerFormat,
559
+ a.UnsignedIntType
560
560
  );
561
561
  return e.needsUpdate = !0, e;
562
562
  }
@@ -564,7 +564,7 @@ class xt {
564
564
  this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
565
565
  }
566
566
  }
567
- const yt = (
567
+ const Mt = (
568
568
  /* glsl */
569
569
  `
570
570
  precision highp float;
@@ -822,7 +822,7 @@ void main(void) {
822
822
  vUv = clippedCornerOffset;
823
823
  }
824
824
  `
825
- ), gt = (
825
+ ), Ct = (
826
826
  /* glsl */
827
827
  `
828
828
  precision highp float;
@@ -856,7 +856,7 @@ void main(void) {
856
856
  }
857
857
  `
858
858
  );
859
- class vt extends n.ShaderMaterial {
859
+ class St extends a.ShaderMaterial {
860
860
  constructor(t = {}) {
861
861
  const s = {
862
862
  // Textures (values set via methods)
@@ -865,39 +865,39 @@ class vt extends n.ShaderMaterial {
865
865
  splatColor: { value: null },
866
866
  splatOrder: { value: null },
867
867
  // Other uniforms
868
- viewport: { value: new n.Vector2(1, 1) },
868
+ viewport: { value: new a.Vector2(1, 1) },
869
869
  // Will be updated
870
870
  numSplats: { value: 0 }
871
871
  // Max splats to render (updated by sorter)
872
872
  };
873
873
  super({
874
- vertexShader: yt,
875
- fragmentShader: gt,
874
+ vertexShader: Mt,
875
+ fragmentShader: Ct,
876
876
  uniforms: s,
877
877
  transparent: !0,
878
- blending: n.CustomBlending,
878
+ blending: a.CustomBlending,
879
879
  // Premultiplied alpha blending:
880
880
  // color = src_color * src_alpha + dst_color * (1 - src_alpha)
881
881
  // alpha = src_alpha * 1 + dst_alpha * (1 - src_alpha)
882
- blendSrc: n.OneFactor,
882
+ blendSrc: a.OneFactor,
883
883
  // Using ONE because shader outputs premultiplied color (color * alpha)
884
- blendDst: n.OneMinusSrcAlphaFactor,
885
- blendSrcAlpha: n.OneFactor,
884
+ blendDst: a.OneMinusSrcAlphaFactor,
885
+ blendSrcAlpha: a.OneFactor,
886
886
  // source alpha comes from shader
887
- blendDstAlpha: n.OneMinusSrcAlphaFactor,
888
- blendEquation: n.AddEquation,
889
- blendEquationAlpha: n.AddEquation,
887
+ blendDstAlpha: a.OneMinusSrcAlphaFactor,
888
+ blendEquation: a.AddEquation,
889
+ blendEquationAlpha: a.AddEquation,
890
890
  depthTest: !0,
891
891
  depthWrite: !1,
892
892
  // Disable depth write for transparency
893
- side: n.DoubleSide,
893
+ side: a.DoubleSide,
894
894
  // Render both sides (or CULLFACE_NONE equivalent)
895
895
  // Optional settings from constructor
896
896
  alphaTest: t.alphaTest !== void 0 ? t.alphaTest : 0,
897
897
  // Typically 0 for blending
898
898
  toneMapped: t.toneMapped !== void 0 ? t.toneMapped : !1
899
899
  // prettier-ignore
900
- }), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = n.NoBlending);
900
+ }), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = a.NoBlending);
901
901
  }
902
902
  /**
903
903
  * Update the viewport size
@@ -943,7 +943,7 @@ class vt extends n.ShaderMaterial {
943
943
  this.uniforms.numSplats.value = t;
944
944
  }
945
945
  }
946
- const j = class j extends n.Mesh {
946
+ const et = class et extends a.Mesh {
947
947
  // Match shader constant
948
948
  /**
949
949
  * Create a new SplatMesh for rendering Gaussian splats
@@ -951,39 +951,39 @@ const j = class j extends n.Mesh {
951
951
  * @param options Rendering options
952
952
  */
953
953
  constructor(s, e = {}) {
954
- const r = new vt(e), o = j.createInstancedGeometry(s.numSplats, j.INSTANCE_SIZE);
955
- super(o, r);
956
- c(this, "sorter");
957
- c(this, "splatData");
958
- c(this, "options");
959
- c(this, "textureManager");
960
- c(this, "material");
961
- c(this, "geometry");
962
- c(this, "lastCameraPositionLocal", new n.Vector3());
963
- c(this, "lastCameraDirectionLocal", new n.Vector3());
964
- c(this, "invModelMatrix", new n.Matrix4());
954
+ const o = new St(e), r = et.createInstancedGeometry(s.numSplats, et.INSTANCE_SIZE);
955
+ super(r, o);
956
+ h(this, "sorter");
957
+ h(this, "splatData");
958
+ h(this, "options");
959
+ h(this, "textureManager");
960
+ h(this, "material");
961
+ h(this, "geometry");
962
+ h(this, "lastCameraPositionLocal", new a.Vector3());
963
+ h(this, "lastCameraDirectionLocal", new a.Vector3());
964
+ h(this, "invModelMatrix", new a.Matrix4());
965
965
  // Cached inverse matrix
966
- c(this, "_vpW", -1);
967
- c(this, "_vpH", -1);
968
- c(this, "_size", new n.Vector2());
969
- c(this, "_camPosW", new n.Vector3());
970
- c(this, "_camDirW", new n.Vector3());
971
- c(this, "_camPosL", new n.Vector3());
972
- c(this, "_camDirL", new n.Vector3());
973
- c(this, "onSorterUpdated", (s) => {
966
+ h(this, "_vpW", -1);
967
+ h(this, "_vpH", -1);
968
+ h(this, "_size", new a.Vector2());
969
+ h(this, "_camPosW", new a.Vector3());
970
+ h(this, "_camDirW", new a.Vector3());
971
+ h(this, "_camPosL", new a.Vector3());
972
+ h(this, "_camDirL", new a.Vector3());
973
+ h(this, "onSorterUpdated", (s) => {
974
974
  const e = s.count;
975
- this.geometry.instanceCount = Math.ceil(e / j.INSTANCE_SIZE), this.material.setNumSplats(e);
975
+ this.geometry.instanceCount = Math.ceil(e / et.INSTANCE_SIZE), this.material.setNumSplats(e);
976
976
  });
977
- this.geometry = o, this.material = r, this.splatData = s, this.frustumCulled = !1, this.options = {
977
+ this.geometry = r, this.material = o, this.splatData = s, this.frustumCulled = !1, this.options = {
978
978
  autoSort: !0,
979
979
  ...e
980
- }, this.textureManager = new xt(s), this.sorter = new dt();
981
- let i = this.createChunks() || void 0;
982
- i === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), i = void 0, this.sorter.addEventListener("updated", this.onSorterUpdated), this.sorter.init(
980
+ }, this.textureManager = new bt(s), this.sorter = new yt();
981
+ let n = this.createChunks() || void 0;
982
+ n === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), n = void 0, this.sorter.addEventListener("updated", this.onSorterUpdated), this.sorter.init(
983
983
  this.textureManager.orderTexture,
984
984
  this.splatData.centers,
985
- i ?? void 0
986
- ), this.material.setTransformA(this.textureManager.transformA), this.material.setTransformB(this.textureManager.transformB), this.material.setColorTexture(this.textureManager.colorTexture), this.material.setOrderTexture(this.textureManager.orderTexture), this.material.setNumSplats(0), this.geometry.boundingBox = s.boundingBox.toBox3(), this.geometry.boundingSphere = new n.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
985
+ n ?? void 0
986
+ ), this.material.setTransformA(this.textureManager.transformA), this.material.setTransformB(this.textureManager.transformB), this.material.setColorTexture(this.textureManager.colorTexture), this.material.setOrderTexture(this.textureManager.orderTexture), this.material.setNumSplats(0), this.geometry.boundingBox = s.boundingBox.toBox3(), this.geometry.boundingSphere = new a.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
987
987
  }
988
988
  /**
989
989
  * Creates the instanced geometry for rendering splats.
@@ -992,7 +992,7 @@ const j = class j extends n.Mesh {
992
992
  * @returns InstancedBufferGeometry
993
993
  */
994
994
  static createInstancedGeometry(s, e) {
995
- const r = Math.ceil(s / e), o = new n.BufferGeometry(), i = new Float32Array([
995
+ const o = Math.ceil(s / e), r = new a.BufferGeometry(), n = new Float32Array([
996
996
  // x, y, splat_index_in_instance
997
997
  -1,
998
998
  -1,
@@ -1006,24 +1006,24 @@ const j = class j extends n.Mesh {
1006
1006
  -1,
1007
1007
  1,
1008
1008
  0
1009
- ]), a = new Uint16Array([0, 1, 2, 0, 2, 3]), d = new Float32Array(4 * 3 * e);
1010
- for (let p = 0; p < e; p++) {
1011
- const h = p * 4 * 3;
1012
- for (let l = 0; l < 4; l++)
1013
- d[h + l * 3 + 0] = i[l * 3 + 0], d[h + l * 3 + 1] = i[l * 3 + 1], d[h + l * 3 + 2] = p;
1009
+ ]), i = new Uint16Array([0, 1, 2, 0, 2, 3]), l = new Float32Array(4 * 3 * e);
1010
+ for (let f = 0; f < e; f++) {
1011
+ const y = f * 4 * 3;
1012
+ for (let v = 0; v < 4; v++)
1013
+ l[y + v * 3 + 0] = n[v * 3 + 0], l[y + v * 3 + 1] = n[v * 3 + 1], l[y + v * 3 + 2] = f;
1014
1014
  }
1015
- const f = new Uint32Array(6 * e);
1016
- for (let p = 0; p < e; p++) {
1017
- const h = p * 6, l = p * 4;
1018
- f[h + 0] = a[0] + l, f[h + 1] = a[1] + l, f[h + 2] = a[2] + l, f[h + 3] = a[3] + l, f[h + 4] = a[4] + l, f[h + 5] = a[5] + l;
1015
+ const x = new Uint32Array(6 * e);
1016
+ for (let f = 0; f < e; f++) {
1017
+ const y = f * 6, v = f * 4;
1018
+ x[y + 0] = i[0] + v, x[y + 1] = i[1] + v, x[y + 2] = i[2] + v, x[y + 3] = i[3] + v, x[y + 4] = i[4] + v, x[y + 5] = i[5] + v;
1019
1019
  }
1020
- o.setAttribute("position", new n.BufferAttribute(d, 3)), o.setIndex(new n.BufferAttribute(f, 1));
1021
- const v = new n.InstancedBufferGeometry();
1022
- v.index = o.index, v.setAttribute("position", o.getAttribute("position"));
1023
- const g = new Uint32Array(r);
1024
- for (let p = 0; p < r; p++)
1025
- g[p] = p * e;
1026
- return v.setAttribute("splatInstanceIndex", new n.InstancedBufferAttribute(g, 1, !1)), v.instanceCount = 0, v;
1020
+ r.setAttribute("position", new a.BufferAttribute(l, 3)), r.setIndex(new a.BufferAttribute(x, 1));
1021
+ const w = new a.InstancedBufferGeometry();
1022
+ w.index = r.index, w.setAttribute("position", r.getAttribute("position"));
1023
+ const b = new Uint32Array(o);
1024
+ for (let f = 0; f < o; f++)
1025
+ b[f] = f * e;
1026
+ return w.setAttribute("splatInstanceIndex", new a.InstancedBufferAttribute(b, 1, !1)), w.instanceCount = 0, w;
1027
1027
  }
1028
1028
  /**
1029
1029
  * Create chunks data (bounding box min/max) for the sorter.
@@ -1054,8 +1054,8 @@ const j = class j extends n.Mesh {
1054
1054
  */
1055
1055
  sort(s) {
1056
1056
  s.getWorldPosition(this._camPosW), s.getWorldDirection(this._camDirW), this.invModelMatrix.copy(this.matrixWorld).invert(), this._camPosL.copy(this._camPosW).applyMatrix4(this.invModelMatrix), this._camDirL.copy(this._camDirW).transformDirection(this.invModelMatrix);
1057
- const e = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6, r = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
1058
- this.options.autoSort && (e || r) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
1057
+ const e = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6, o = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
1058
+ this.options.autoSort && (e || o) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
1059
1059
  }
1060
1060
  /**
1061
1061
  * THREE.js hook called before rendering the object.
@@ -1066,8 +1066,8 @@ const j = class j extends n.Mesh {
1066
1066
  */
1067
1067
  // prettier-ignore
1068
1068
  // @ts-expect-error scene is not used
1069
- onBeforeRender(s, e, r) {
1070
- this.sort(r), s.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
1069
+ onBeforeRender(s, e, o) {
1070
+ this.sort(o), s.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
1071
1071
  }
1072
1072
  /**
1073
1073
  * Dispose of resources
@@ -1077,9 +1077,41 @@ const j = class j extends n.Mesh {
1077
1077
  }
1078
1078
  };
1079
1079
  /** Number of splats combined into a single instanced draw call. */
1080
- c(j, "INSTANCE_SIZE", 128);
1081
- let it = j;
1082
- class bt extends n.Loader {
1080
+ h(et, "INSTANCE_SIZE", 128);
1081
+ let ft = et;
1082
+ class zt extends a.Loader {
1083
+ constructor(s) {
1084
+ super(s);
1085
+ h(this, "requestId", 0);
1086
+ h(this, "worker");
1087
+ h(this, "pendingCallbacks", /* @__PURE__ */ new Map());
1088
+ const e = this.createWorkerCode(), o = new Blob([e], { type: "application/javascript" });
1089
+ this.worker = new Worker(URL.createObjectURL(o)), this.worker.onmessage = this.onWorkerMessage.bind(this);
1090
+ }
1091
+ /**
1092
+ * Handles messages received from the parsing worker
1093
+ * @param event The message event from the worker
1094
+ */
1095
+ onWorkerMessage(s) {
1096
+ const { requestId: e, error: o, result: r } = s.data, n = this.pendingCallbacks.get(e);
1097
+ if (!n) return console.warn(`PlyLoader: Received response for unknown request ${e}`);
1098
+ if (this.pendingCallbacks.delete(e), o) return n.reject(new Error(o));
1099
+ if (!r) return n.reject(new Error("Worker returned no result"));
1100
+ try {
1101
+ const i = new xt(0);
1102
+ i.numSplats = r.numSplats, i.positions = new Float32Array(r.positions), i.rotations = new Float32Array(r.rotations), i.scales = new Float32Array(r.scales), i.colors = new Float32Array(r.colors), i.opacities = new Float32Array(r.opacities), i.centers = new Float32Array(r.centers), i.boundingBox.min.set(
1103
+ r.boundingBox.minX,
1104
+ r.boundingBox.minY,
1105
+ r.boundingBox.minZ
1106
+ ), i.boundingBox.max.set(
1107
+ r.boundingBox.maxX,
1108
+ r.boundingBox.maxY,
1109
+ r.boundingBox.maxZ
1110
+ ), n.resolve(i);
1111
+ } catch (i) {
1112
+ n.reject(i);
1113
+ }
1114
+ }
1083
1115
  /**
1084
1116
  * Load a PLY file with Gaussian Splat data
1085
1117
  * @param url URL of the PLY file
@@ -1087,21 +1119,18 @@ class bt extends n.Loader {
1087
1119
  * @param onProgress Optional progress callback
1088
1120
  * @param onError Optional error callback
1089
1121
  */
1090
- load(t, s, e, r) {
1091
- const o = new n.FileLoader(this.manager);
1092
- o.setResponseType("arraybuffer"), o.setRequestHeader(this.requestHeader), o.setPath(this.path), o.setWithCredentials(this.withCredentials), o.load(
1093
- t,
1122
+ load(s, e, o, r) {
1123
+ const n = new a.FileLoader(this.manager);
1124
+ n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
1125
+ s,
1094
1126
  (i) => {
1095
- try {
1096
- if (s) {
1097
- const a = this.parse(i);
1098
- s(a);
1099
- }
1100
- } catch (a) {
1101
- r ? r(a) : console.error(a), this.manager.itemError(t);
1102
- }
1127
+ this.parseAsync(i).then((l) => {
1128
+ e && e(l);
1129
+ }).catch((l) => {
1130
+ r ? r(l) : console.error(l), this.manager.itemError(s);
1131
+ });
1103
1132
  },
1104
- e,
1133
+ o,
1105
1134
  r
1106
1135
  );
1107
1136
  }
@@ -1111,197 +1140,257 @@ class bt extends n.Loader {
1111
1140
  * @param onProgress Optional progress callback
1112
1141
  * @returns A Promise that resolves with the parsed SplatData
1113
1142
  */
1114
- loadAsync(t, s) {
1115
- return new Promise((e, r) => {
1116
- const o = new n.FileLoader(this.manager);
1117
- o.setResponseType("arraybuffer"), o.setRequestHeader(this.requestHeader), o.setPath(this.path), o.setWithCredentials(this.withCredentials), o.load(
1118
- t,
1143
+ loadAsync(s, e) {
1144
+ return new Promise((o, r) => {
1145
+ const n = new a.FileLoader(this.manager);
1146
+ n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
1147
+ s,
1119
1148
  (i) => {
1120
- try {
1121
- const a = this.parse(i);
1122
- e(a);
1123
- } catch (a) {
1124
- r(a), this.manager.itemError(t);
1125
- }
1149
+ this.parseAsync(i).then(o).catch((l) => {
1150
+ r(l), this.manager.itemError(s);
1151
+ });
1126
1152
  },
1127
- s,
1153
+ e,
1128
1154
  (i) => {
1129
- r(i), this.manager.itemError(t);
1155
+ r(i), this.manager.itemError(s);
1130
1156
  }
1131
1157
  );
1132
1158
  });
1133
1159
  }
1134
1160
  /**
1135
- * Parse PLY buffer data into SplatData
1161
+ * Parse PLY buffer data asynchronously using Web Worker
1136
1162
  * @param buffer ArrayBuffer containing PLY data
1137
- * @returns Parsed SplatData
1163
+ * @returns Promise that resolves with parsed SplatData
1138
1164
  */
1139
- parse(t) {
1140
- const s = new TextDecoder(), e = new Uint8Array(t), r = [112, 108, 121, 10], o = `
1165
+ parseAsync(s) {
1166
+ return new Promise((e, o) => {
1167
+ const r = this.requestId++;
1168
+ this.pendingCallbacks.set(r, { resolve: e, reject: o });
1169
+ const n = {
1170
+ requestId: r,
1171
+ buffer: s
1172
+ };
1173
+ this.worker.postMessage(n, [s]);
1174
+ });
1175
+ }
1176
+ /**
1177
+ * Terminate the Web Worker and clean up resources
1178
+ */
1179
+ dispose() {
1180
+ this.worker && this.worker.terminate(), this.pendingCallbacks.clear();
1181
+ }
1182
+ /**
1183
+ * Creates the self-contained code for the parsing Web Worker
1184
+ * @returns A string containing the JavaScript code for the worker
1185
+ */
1186
+ createWorkerCode() {
1187
+ return `(${(function() {
1188
+ self.onmessage = (o) => {
1189
+ const { requestId: r, buffer: n } = o.data;
1190
+ try {
1191
+ const i = e(n), l = {
1192
+ requestId: r,
1193
+ result: i
1194
+ };
1195
+ self.postMessage(l, [
1196
+ i.positions,
1197
+ i.rotations,
1198
+ i.scales,
1199
+ i.colors,
1200
+ i.opacities,
1201
+ i.centers
1202
+ ]);
1203
+ } catch (i) {
1204
+ const l = {
1205
+ requestId: r,
1206
+ error: i instanceof Error ? i.message : String(i)
1207
+ };
1208
+ self.postMessage(l);
1209
+ }
1210
+ };
1211
+ function e(o) {
1212
+ const r = new TextDecoder(), n = new Uint8Array(o), i = [112, 108, 121, 10], l = `
1141
1213
  end_header
1142
1214
  `;
1143
- for (let x = 0; x < r.length; x++)
1144
- if (e[x] !== r[x])
1145
- throw new Error("Invalid PLY file: Missing magic bytes");
1146
- let i = 0;
1147
- for (let x = 0; x < e.length - o.length; x++) {
1148
- let u = !0;
1149
- for (let S = 0; S < o.length; S++)
1150
- if (e[x + S] !== o.charCodeAt(S)) {
1151
- u = !1;
1152
- break;
1153
- }
1154
- if (u) {
1155
- i = x + o.length;
1156
- break;
1157
- }
1158
- }
1159
- if (i === 0)
1160
- throw new Error("Invalid PLY file: Could not find end of header");
1161
- const d = s.decode(e.subarray(0, i)).split(`
1162
- `), f = [];
1163
- let v = null;
1164
- for (let x = 1; x < d.length; x++) {
1165
- const u = d[x].trim();
1166
- if (u === "" || u === "end_header") continue;
1167
- const S = u.split(" ");
1168
- switch (S[0]) {
1169
- case "format":
1170
- v = S[1];
1171
- break;
1172
- case "element":
1173
- f.push({
1174
- name: S[1],
1175
- count: parseInt(S[2], 10),
1176
- properties: []
1177
- });
1178
- break;
1179
- case "property":
1180
- if (f.length === 0)
1215
+ for (let c = 0; c < i.length; c++)
1216
+ if (n[c] !== i[c])
1181
1217
  throw new Error(
1182
- "Invalid PLY file: Property without element"
1218
+ "Invalid PLY file: Missing magic bytes"
1183
1219
  );
1184
- f[f.length - 1].properties.push({
1185
- type: S[1],
1186
- name: S[2],
1187
- storage: null
1188
- });
1189
- break;
1190
- }
1191
- }
1192
- if (v !== "binary_little_endian")
1193
- throw new Error(`Unsupported PLY format: ${v}`);
1194
- const g = f.find((x) => x.name === "vertex");
1195
- if (!g)
1196
- throw new Error("Invalid PLY file: No vertex element found");
1197
- const p = new ut(g.count), h = new DataView(t);
1198
- let l = i;
1199
- const b = (x) => g.properties.findIndex((u) => u.name === x), T = b("x"), O = b("y"), q = b("z"), E = [
1200
- b("rot_0"),
1201
- b("rot_1"),
1202
- b("rot_2"),
1203
- b("rot_3")
1204
- ], R = [
1205
- b("scale_0"),
1206
- b("scale_1"),
1207
- b("scale_2")
1208
- ], W = [
1209
- b("f_dc_0"),
1210
- b("f_dc_1"),
1211
- b("f_dc_2")
1212
- ], k = b("opacity");
1213
- if ([
1214
- T,
1215
- O,
1216
- q,
1217
- ...E,
1218
- ...R,
1219
- ...W,
1220
- k
1221
- ].some((x) => x === -1))
1222
- throw new Error("Invalid PLY file: Missing required properties");
1223
- const F = 0.28209479177387814, M = (x) => {
1224
- if (x > 0) return 1 / (1 + Math.exp(-x));
1225
- const u = Math.exp(x);
1226
- return u / (1 + u);
1227
- }, m = new n.Vector3(), B = new n.Quaternion(), V = new n.Vector3(), P = new n.Color();
1228
- for (let x = 0; x < g.count; x++) {
1229
- const u = [];
1230
- for (let I = 0; I < g.properties.length; I++) {
1231
- const K = g.properties[I].type;
1232
- let z;
1233
- switch (K) {
1234
- case "char":
1235
- z = h.getInt8(l), l += 1;
1236
- break;
1237
- case "uchar":
1238
- z = h.getUint8(l), l += 1;
1239
- break;
1240
- case "short":
1241
- z = h.getInt16(l, !0), l += 2;
1242
- break;
1243
- case "ushort":
1244
- z = h.getUint16(l, !0), l += 2;
1245
- break;
1246
- case "int":
1247
- z = h.getInt32(l, !0), l += 4;
1248
- break;
1249
- case "uint":
1250
- z = h.getUint32(l, !0), l += 4;
1251
- break;
1252
- case "float":
1253
- z = h.getFloat32(l, !0), l += 4;
1254
- break;
1255
- case "double":
1256
- z = h.getFloat64(l, !0), l += 8;
1220
+ let x = 0;
1221
+ for (let c = 0; c < n.length - l.length; c++) {
1222
+ let u = !0;
1223
+ for (let g = 0; g < l.length; g++)
1224
+ if (n[c + g] !== l.charCodeAt(g)) {
1225
+ u = !1;
1226
+ break;
1227
+ }
1228
+ if (u) {
1229
+ x = c + l.length;
1257
1230
  break;
1258
- default:
1259
- throw new Error(`Unsupported property type: ${K}`);
1231
+ }
1260
1232
  }
1261
- u.push(z);
1233
+ if (x === 0)
1234
+ throw new Error(
1235
+ "Invalid PLY file: Could not find end of header"
1236
+ );
1237
+ const b = r.decode(
1238
+ n.subarray(0, x)
1239
+ ).split(`
1240
+ `), f = [];
1241
+ let y = null;
1242
+ for (let c = 1; c < b.length; c++) {
1243
+ const u = b[c].trim();
1244
+ if (u === "" || u === "end_header") continue;
1245
+ const g = u.split(" ");
1246
+ switch (g[0]) {
1247
+ case "format":
1248
+ y = g[1];
1249
+ break;
1250
+ case "element":
1251
+ f.push({
1252
+ name: g[1],
1253
+ count: parseInt(g[2], 10),
1254
+ properties: []
1255
+ });
1256
+ break;
1257
+ case "property":
1258
+ if (f.length === 0)
1259
+ throw new Error(
1260
+ "Invalid PLY file: Property without element"
1261
+ );
1262
+ f[f.length - 1].properties.push({
1263
+ type: g[1],
1264
+ name: g[2]
1265
+ });
1266
+ break;
1267
+ }
1268
+ }
1269
+ if (y !== "binary_little_endian")
1270
+ throw new Error(`Unsupported PLY format: ${y}`);
1271
+ const v = f.find((c) => c.name === "vertex");
1272
+ if (!v)
1273
+ throw new Error(
1274
+ "Invalid PLY file: No vertex element found"
1275
+ );
1276
+ const S = v.count, z = new Float32Array(S * 3), V = new Float32Array(S * 4), Y = new Float32Array(S * 3), R = new Float32Array(S * 3), ot = new Float32Array(S), K = new Float32Array(S * 3), A = new DataView(o);
1277
+ let d = x;
1278
+ const M = (c) => v.properties.findIndex(
1279
+ (u) => u.name === c
1280
+ ), C = M("x"), m = M("y"), _ = M("z"), T = [
1281
+ M("rot_0"),
1282
+ M("rot_1"),
1283
+ M("rot_2"),
1284
+ M("rot_3")
1285
+ ], j = [
1286
+ M("scale_0"),
1287
+ M("scale_1"),
1288
+ M("scale_2")
1289
+ ], N = [
1290
+ M("f_dc_0"),
1291
+ M("f_dc_1"),
1292
+ M("f_dc_2")
1293
+ ], O = M("opacity");
1294
+ if ([
1295
+ C,
1296
+ m,
1297
+ _,
1298
+ ...T,
1299
+ ...j,
1300
+ ...N,
1301
+ O
1302
+ ].some((c) => c === -1))
1303
+ throw new Error(
1304
+ "Invalid PLY file: Missing required properties"
1305
+ );
1306
+ const B = 0.28209479177387814, G = (c) => {
1307
+ if (c > 0) return 1 / (1 + Math.exp(-c));
1308
+ const u = Math.exp(c);
1309
+ return u / (1 + u);
1310
+ };
1311
+ let nt = 1 / 0, D = 1 / 0, rt = 1 / 0, Q = -1 / 0, tt = -1 / 0, st = -1 / 0;
1312
+ for (let c = 0; c < S; c++) {
1313
+ const u = [];
1314
+ for (let ct = 0; ct < v.properties.length; ct++) {
1315
+ const ht = v.properties[ct].type;
1316
+ let Z;
1317
+ switch (ht) {
1318
+ case "char":
1319
+ Z = A.getInt8(d), d += 1;
1320
+ break;
1321
+ case "uchar":
1322
+ Z = A.getUint8(d), d += 1;
1323
+ break;
1324
+ case "short":
1325
+ Z = A.getInt16(d, !0), d += 2;
1326
+ break;
1327
+ case "ushort":
1328
+ Z = A.getUint16(d, !0), d += 2;
1329
+ break;
1330
+ case "int":
1331
+ Z = A.getInt32(d, !0), d += 4;
1332
+ break;
1333
+ case "uint":
1334
+ Z = A.getUint32(d, !0), d += 4;
1335
+ break;
1336
+ case "float":
1337
+ Z = A.getFloat32(d, !0), d += 4;
1338
+ break;
1339
+ case "double":
1340
+ Z = A.getFloat64(d, !0), d += 8;
1341
+ break;
1342
+ default:
1343
+ throw new Error(
1344
+ `Unsupported property type: ${ht}`
1345
+ );
1346
+ }
1347
+ u.push(Z);
1348
+ }
1349
+ const g = u[C], p = u[m], I = u[_], E = c * 3;
1350
+ z[E] = g, z[E + 1] = p, z[E + 2] = I, nt = Math.min(nt, g), D = Math.min(D, p), rt = Math.min(rt, I), Q = Math.max(Q, g), tt = Math.max(tt, p), st = Math.max(st, I);
1351
+ let U = u[T[1]], q = u[T[2]], P = u[T[3]], F = u[T[0]];
1352
+ const W = Math.sqrt(
1353
+ U * U + q * q + P * P + F * F
1354
+ );
1355
+ W > 0 && (U /= W, q /= W, P /= W, F /= W), F < 0 && (U = -U, q = -q, P = -P, F = -F);
1356
+ const L = c * 4;
1357
+ V[L] = U, V[L + 1] = q, V[L + 2] = P, V[L + 3] = F;
1358
+ const $ = c * 3;
1359
+ Y[$] = u[j[0]], Y[$ + 1] = u[j[1]], Y[$ + 2] = u[j[2]];
1360
+ let J = 0.5 + u[N[0]] * B, H = 0.5 + u[N[1]] * B, it = 0.5 + u[N[2]] * B;
1361
+ J = Math.max(0, Math.min(1, J)), H = Math.max(0, Math.min(1, H)), it = Math.max(0, Math.min(1, it));
1362
+ const at = c * 3;
1363
+ R[at] = J, R[at + 1] = H, R[at + 2] = it, ot[c] = G(u[O]), K[E] = g, K[E + 1] = p, K[E + 2] = I;
1364
+ }
1365
+ return {
1366
+ numSplats: S,
1367
+ positions: z.buffer,
1368
+ rotations: V.buffer,
1369
+ scales: Y.buffer,
1370
+ colors: R.buffer,
1371
+ opacities: ot.buffer,
1372
+ centers: K.buffer,
1373
+ boundingBox: {
1374
+ minX: nt,
1375
+ minY: D,
1376
+ minZ: rt,
1377
+ maxX: Q,
1378
+ maxY: tt,
1379
+ maxZ: st
1380
+ }
1381
+ };
1262
1382
  }
1263
- m.set(
1264
- u[T],
1265
- u[O],
1266
- u[q]
1267
- ), B.set(
1268
- u[E[1]],
1269
- // PLY stores rot 1,2,3,0 (x,y,z,w)
1270
- u[E[2]],
1271
- u[E[3]],
1272
- u[E[0]]
1273
- ).normalize(), V.set(
1274
- u[R[0]],
1275
- // Read directly assuming it's log scale
1276
- u[R[1]],
1277
- u[R[2]]
1278
- ), P.set(
1279
- 0.5 + u[W[0]] * F,
1280
- 0.5 + u[W[1]] * F,
1281
- 0.5 + u[W[2]] * F
1282
- ), P.r = Math.max(0, Math.min(1, P.r)), P.g = Math.max(0, Math.min(1, P.g)), P.b = Math.max(0, Math.min(1, P.b));
1283
- const S = M(u[k]);
1284
- p.setSplat(
1285
- x,
1286
- m,
1287
- B,
1288
- V,
1289
- // Pass log scale directly
1290
- P,
1291
- S
1292
- );
1293
- }
1294
- return p.calculateBoundingBox(), p;
1383
+ }).toString()})();`;
1295
1384
  }
1296
1385
  }
1297
- const Mt = "0.3.0";
1386
+ const kt = "0.3.0";
1298
1387
  export {
1299
- et as BoundingBox,
1300
- bt as PlyLoader,
1301
- ut as SplatData,
1302
- vt as SplatMaterial,
1303
- it as SplatMesh,
1304
- dt as SplatSorter,
1305
- xt as TextureManager,
1306
- Mt as VERSION
1388
+ lt as BoundingBox,
1389
+ zt as PlyLoader,
1390
+ xt as SplatData,
1391
+ St as SplatMaterial,
1392
+ ft as SplatMesh,
1393
+ yt as SplatSorter,
1394
+ bt as TextureManager,
1395
+ kt as VERSION
1307
1396
  };