@speridlabs/visus 1.0.4 → 2.0.1

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 = (I, t, s) => t in I ? lt(I, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : I[t] = s;
3
- var c = (I, t, s) => ht(I, typeof t != "symbol" ? t + "" : t, s);
4
- import * as n from "three";
5
- class et {
1
+ var pt = Object.defineProperty;
2
+ var ft = (k, t, o) => t in k ? pt(k, t, { enumerable: !0, configurable: !0, writable: !0, value: o }) : k[t] = o;
3
+ var h = (k, t, o) => ft(k, typeof t != "symbol" ? t + "" : t, o);
4
+ import * as a from "three";
5
+ class ct {
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,32 +49,31 @@ 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 ct();
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 mt {
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, "boundingBox", new ct());
74
73
  this.numSplats = t, this.allocateBuffers(t);
75
74
  }
76
75
  allocateBuffers(t) {
77
- this.positions = new Float32Array(t * 3), this.rotations = new Float32Array(t * 4), this.scales = new Float32Array(t * 3), this.colors = new Float32Array(t * 3), this.opacities = new Float32Array(t), this.centers = new Float32Array(t * 3);
76
+ this.positions = new Float32Array(t * 3), this.rotations = new Float32Array(t * 4), this.scales = new Float32Array(t * 3), this.colors = new Float32Array(t * 3), this.opacities = new Float32Array(t);
78
77
  }
79
78
  /**
80
79
  * Set data for a specific splat
@@ -85,13 +84,13 @@ class ut {
85
84
  * @param color Color
86
85
  * @param opacity Opacity value
87
86
  */
88
- setSplat(t, s, e, r, o, i) {
87
+ setSplat(t, o, e, s, r, n) {
89
88
  if (t >= this.numSplats)
90
89
  throw new Error(
91
90
  `Splat index out of bounds: ${t} >= ${this.numSplats}`
92
91
  );
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;
92
+ const i = t * 3, l = t * 4, x = t * 3, b = t * 3;
93
+ this.positions[i] = o.x, this.positions[i + 1] = o.y, this.positions[i + 2] = o.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] = s.x, this.scales[x + 1] = s.y, this.scales[x + 2] = s.z, this.colors[b] = r.r, this.colors[b + 1] = r.g, this.colors[b + 2] = r.b, this.opacities[t] = n;
95
94
  }
96
95
  /**
97
96
  * Get a splat's data
@@ -103,29 +102,29 @@ class ut {
103
102
  throw new Error(
104
103
  `Splat index out of bounds: ${t} >= ${this.numSplats}`
105
104
  );
106
- const s = t * 3, e = t * 4, r = t * 3, o = t * 3;
105
+ const o = t * 3, e = t * 4, s = t * 3, r = t * 3;
107
106
  return {
108
- position: new n.Vector3(
109
- this.positions[s],
110
- this.positions[s + 1],
111
- this.positions[s + 2]
107
+ position: new a.Vector3(
108
+ this.positions[o],
109
+ this.positions[o + 1],
110
+ this.positions[o + 2]
112
111
  ),
113
- rotation: new n.Quaternion(
112
+ rotation: new a.Quaternion(
114
113
  this.rotations[e],
115
114
  this.rotations[e + 1],
116
115
  this.rotations[e + 2],
117
116
  this.rotations[e + 3]
118
117
  ),
119
118
  // 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])
119
+ scale: new a.Vector3(
120
+ Math.exp(this.scales[s]),
121
+ Math.exp(this.scales[s + 1]),
122
+ Math.exp(this.scales[s + 2])
124
123
  ),
125
- color: new n.Color(
126
- this.colors[o],
127
- this.colors[o + 1],
128
- this.colors[o + 2]
124
+ color: new a.Color(
125
+ this.colors[r],
126
+ this.colors[r + 1],
127
+ this.colors[r + 2]
129
128
  ),
130
129
  opacity: this.opacities[t]
131
130
  };
@@ -136,9 +135,9 @@ class ut {
136
135
  */
137
136
  calculateBoundingBox() {
138
137
  this.boundingBox.reset();
139
- const t = new n.Vector3();
140
- for (let s = 0; s < this.numSplats; s++) {
141
- const e = s * 3;
138
+ const t = new a.Vector3();
139
+ for (let o = 0; o < this.numSplats; o++) {
140
+ const e = o * 3;
142
141
  t.set(
143
142
  this.positions[e],
144
143
  this.positions[e + 1],
@@ -152,99 +151,100 @@ class ut {
152
151
  * This is for visualization/debugging purposes only, not for rendering
153
152
  */
154
153
  createDebugGeometry() {
155
- const t = new n.BufferGeometry();
154
+ const t = new a.BufferGeometry();
156
155
  t.setAttribute(
157
156
  "position",
158
- new n.BufferAttribute(this.positions, 3)
157
+ new a.BufferAttribute(this.positions, 3)
159
158
  );
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;
159
+ const o = new Float32Array(this.numSplats * 3), e = new a.Quaternion(), s = new a.Euler();
160
+ for (let r = 0; r < this.numSplats; r++) {
161
+ const n = r * 4, i = r * 3;
163
162
  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;
163
+ this.rotations[n],
164
+ this.rotations[n + 1],
165
+ this.rotations[n + 2],
166
+ this.rotations[n + 3]
167
+ ), s.setFromQuaternion(e), o[i] = s.x, o[i + 1] = s.y, o[i + 2] = s.z;
169
168
  }
170
169
  return t.setAttribute(
171
170
  "rotation",
172
- new n.BufferAttribute(s, 3)
171
+ new a.BufferAttribute(o, 3)
173
172
  ), t.setAttribute(
174
173
  "scale",
175
- new n.BufferAttribute(this.scales, 3)
174
+ new a.BufferAttribute(this.scales, 3)
176
175
  ), t.setAttribute(
177
176
  "color",
178
- new n.BufferAttribute(this.colors, 3)
177
+ new a.BufferAttribute(this.colors, 3)
179
178
  ), t.setAttribute(
180
179
  "opacity",
181
- new n.BufferAttribute(this.opacities, 1)
180
+ new a.BufferAttribute(this.opacities, 1)
182
181
  ), t;
183
182
  }
184
183
  }
185
- class dt extends n.EventDispatcher {
184
+ class xt extends a.EventDispatcher {
186
185
  constructor() {
187
186
  super();
188
- c(this, "worker");
189
- c(this, "centers", null);
190
- c(this, "orderTexture", null);
187
+ h(this, "worker");
188
+ h(this, "centers", null);
189
+ h(this, "orderTexture", null);
191
190
  /** Bounding box data for optimization */
192
- c(this, "chunks", null);
193
- c(this, "lastCameraPosition", new n.Vector3());
194
- c(this, "lastCameraDirection", new n.Vector3());
195
- const s = this.createWorkerCode(), e = new Blob([s], { type: "application/javascript" });
191
+ h(this, "chunks", null);
192
+ h(this, "lastCameraPosition", new a.Vector3());
193
+ h(this, "lastCameraDirection", new a.Vector3());
194
+ const o = this.createWorkerCode(), e = new Blob([o], { type: "application/javascript" });
196
195
  this.worker = new Worker(URL.createObjectURL(e)), this.worker.onmessage = this.onWorkerMessage.bind(this);
197
196
  }
198
197
  /**
199
198
  * Handles messages received from the sorting worker.
200
199
  * @param event The message event from the worker.
201
200
  */
202
- onWorkerMessage(s) {
201
+ onWorkerMessage(o) {
203
202
  if (!this.orderTexture || !this.orderTexture.image)
204
203
  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))
204
+ const { order: e, count: s } = o.data, r = this.orderTexture.image.data;
205
+ if (!(r instanceof Uint32Array))
207
206
  return console.error(
208
207
  "SplatSorter: Order texture data is not a Uint32Array!"
209
208
  );
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 });
209
+ r.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
210
+ const n = r.buffer.slice(0), i = { order: n };
211
+ this.worker.postMessage(i, [n]), this.dispatchEvent({ type: "updated", count: s });
213
212
  }
214
213
  /**
215
214
  * Initializes the sorter with necessary data and textures.
216
215
  * @param orderTexture The THREE.DataTexture (R32UI) to store the sorted splat indices.
217
216
  * @param centers A Float32Array containing the center position (x, y, z) for each splat.
218
217
  * @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
218
+ * @param transferOwnership Optional: If true, transfers ownership of centers buffer to worker (saves memory, main thread loses access). Default: false.
219
219
  */
220
- init(s, e, r) {
221
- if (!s || !(s.image.data instanceof Uint32Array))
220
+ init(o, e, s, r = !1) {
221
+ if (!o || !(o.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
- if (s.image.data.length < e.length / 3)
225
+ if (o.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;
228
- this.orderTexture = s, this.centers = e.slice();
227
+ const n = e.length / 3;
228
+ this.orderTexture = o, r ? this.centers = null : this.centers = e.slice();
229
229
  const i = this.orderTexture.image.data;
230
- for (let g = 0; g < o; g++) i[g] = g;
230
+ for (let u = 0; u < n; u++) i[u] = u;
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 l = i.buffer.slice(0), x = r ? e.buffer : e.buffer.slice(0), b = {
233
+ order: l,
234
+ centers: x
235
+ }, C = [
236
+ l,
237
+ x
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 (s) {
240
+ this.chunks = s.slice();
241
+ const u = this.chunks.buffer.slice(0);
242
+ b.chunks = u, C.push(u);
243
243
  }
244
- this.worker.postMessage(f, v), queueMicrotask(() => {
244
+ this.worker.postMessage(b, C), queueMicrotask(() => {
245
245
  this.dispatchEvent({
246
246
  type: "updated",
247
- count: o
247
+ count: n
248
248
  });
249
249
  });
250
250
  }
@@ -253,53 +253,53 @@ class dt extends n.EventDispatcher {
253
253
  * The sorter will only consider splats whose original indices are present in the mapping.
254
254
  * @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
255
255
  */
256
- setMapping(s) {
256
+ setMapping(o) {
257
257
  if (!this.centers)
258
258
  return console.warn(
259
259
  "SplatSorter: Cannot set mapping before initialization."
260
260
  );
261
261
  let e;
262
- const r = [];
263
- if (!s) {
264
- const d = this.centers.buffer.slice(0);
262
+ const s = [];
263
+ if (!o) {
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
+ }, s.push(l), this.worker.postMessage(e, s);
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(o.length * 3);
271
+ for (let l = 0; l < o.length; l++) {
272
+ const x = o[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 b = x * 3, C = l * 3;
280
+ r[C + 0] = this.centers[b + 0], r[C + 1] = this.centers[b + 1], r[C + 2] = this.centers[b + 2];
281
281
  }
282
- const i = o.buffer.slice(0), a = s.buffer.slice(0);
282
+ const n = r.buffer.slice(0), i = o.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
+ }, s.push(n, i), this.worker.postMessage(e, s);
287
287
  }
288
288
  /**
289
289
  * Updates the camera parameters used for sorting.
290
290
  * @param position The camera's position in the sorter's local coordinate space.
291
291
  * @param direction The camera's forward direction in the sorter's local coordinate space.
292
292
  */
293
- setCamera(s, e) {
294
- const r = this.lastCameraPosition.distanceToSquared(s) > 1e-7, o = this.lastCameraDirection.dot(e) < 0.9999;
295
- if (!r && !o)
293
+ setCamera(o, e) {
294
+ const s = this.lastCameraPosition.distanceToSquared(o) > 1e-7, r = this.lastCameraDirection.dot(e) < 0.9999;
295
+ if (!s && !r)
296
296
  return;
297
- this.lastCameraPosition.copy(s), this.lastCameraDirection.copy(e);
298
- const i = {
299
- cameraPosition: { x: s.x, y: s.y, z: s.z },
297
+ this.lastCameraPosition.copy(o), this.lastCameraDirection.copy(e);
298
+ const n = {
299
+ cameraPosition: { x: o.x, y: o.y, z: o.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,165 +313,165 @@ 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 _ = 32, O = new Array(_).fill(0), q = new Array(_).fill(0), E = new Array(_).fill(0), R = (k, S, F) => {
320
- for (; k <= S; ) {
321
- const M = S + k >> 1, m = F(M);
322
- if (m > 0) k = M + 1;
323
- else if (m < 0) S = M - 1;
316
+ let e = null, s = null, r = null, n = null, i = null, l = null, x = !1;
317
+ const b = { x: 0, y: 0, z: 0 }, C = { x: 0, y: 0, z: 0 }, u = { x: 0, y: 0, z: 0 }, g = { x: 0, y: 0, z: 0 };
318
+ let v = null, S = null;
319
+ const I = 32, R = new Array(I).fill(0), Y = new Array(I).fill(0), W = new Array(I).fill(0), ot = (w, d, P) => {
320
+ for (; w <= d; ) {
321
+ const M = d + w >> 1, f = P(M);
322
+ if (f > 0) w = M + 1;
323
+ else if (f < 0) d = M - 1;
324
324
  else return M;
325
325
  }
326
- return ~k;
327
- }, W = () => {
328
- if (!e || !r || !a || !d)
326
+ return ~w;
327
+ }, L = () => {
328
+ if (!e || !s || !i || !l)
329
329
  return;
330
- if (r.length === 0) {
331
- const y = {
330
+ if (s.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, S = a.y, F = a.z, M = d.x, m = d.y, C = d.z, V = 1e-4, P = Math.abs(k - v.x) > V || Math.abs(S - v.y) > V || Math.abs(F - v.z) > V, x = Math.abs(M - g.x) > V || Math.abs(m - g.y) > V || Math.abs(C - g.z) > V;
339
- if (!f && !P && !x)
338
+ const w = i.x, d = i.y, P = i.z, M = l.x, f = l.y, A = l.z, T = 1e-4, j = Math.abs(w - b.x) > T || Math.abs(d - b.y) > T || Math.abs(P - b.z) > T, J = Math.abs(M - C.x) > T || Math.abs(f - C.y) > T || Math.abs(A - C.z) > T;
339
+ if (!x && !j && !J)
340
340
  return;
341
- f = !1, v.x = k, v.y = S, v.z = F, g.x = M, g.y = m, g.z = C;
342
- let u = 1 / 0, z = -1 / 0;
343
- for (let y = 0; y < 8; ++y) {
344
- const B = y & 1 ? p.x : h.x, U = y & 2 ? p.y : h.y, w = y & 4 ? p.z : h.z, D = B * M + U * m + w * C;
345
- u = Math.min(u, D), z = Math.max(z, D);
341
+ x = !1, b.x = w, b.y = d, b.z = P, C.x = M, C.y = f, C.z = A;
342
+ let $ = 1 / 0, D = -1 / 0;
343
+ for (let c = 0; c < 8; ++c) {
344
+ const y = c & 1 ? u.x : g.x, B = c & 2 ? u.y : g.y, m = c & 4 ? u.z : g.z, z = y * M + B * f + m * A;
345
+ $ = Math.min($, z), D = Math.max(D, z);
346
346
  }
347
- const T = r.length / 3, L = z - u, A = (1 << Math.max(
347
+ const _ = s.length / 3, N = D - $, E = (1 << Math.max(
348
348
  10,
349
- Math.min(20, Math.ceil(Math.log2(T / 4)))
349
+ Math.min(20, Math.ceil(Math.log2(_ / 4)))
350
350
  )) + 1;
351
- if ((!l || l.length !== T) && (l = new Uint32Array(T)), !b || b.length !== A ? b = new Uint32Array(A) : b.fill(0), L < 1e-7) {
352
- for (let y = 0; y < T; ++y) l[y] = 0;
353
- b[0] = T;
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 + $ * C - u, J = Y - H, G = Y + H, Q = Math.max(
351
+ if ((!v || v.length !== _) && (v = new Uint32Array(_)), !S || S.length !== E ? S = new Uint32Array(E) : S.fill(0), N < 1e-7) {
352
+ for (let c = 0; c < _; ++c) v[c] = 0;
353
+ S[0] = _;
354
+ } else if (r && r.length > 0) {
355
+ const c = r.length / 6;
356
+ R.fill(0);
357
+ for (let m = 0; m < c; ++m) {
358
+ const z = m * 6, U = r[z + 0], V = r[z + 1], O = r[z + 2], F = r[z + 3], q = U * M + V * f + O * A - $, X = q - F, Z = q + F, K = Math.max(
359
359
  0,
360
- Math.floor(J * _ / L)
361
- ), tt = Math.min(
362
- _,
363
- Math.ceil(G * _ / L)
360
+ Math.floor(X * I / N)
361
+ ), Q = Math.min(
362
+ I,
363
+ Math.ceil(Z * I / N)
364
364
  );
365
- for (let N = Q; N < tt; ++N)
366
- O[N]++;
365
+ for (let H = K; H < Q; ++H)
366
+ R[H]++;
367
367
  }
368
- let B = 0;
369
- for (let w = 0; w < _; ++w) B += O[w];
370
- E[0] = 0, q[0] = 0;
371
- for (let w = 1; w < _; ++w)
372
- E[w - 1] = O[w - 1] / B * A >>> 0, q[w] = q[w - 1] + E[w - 1];
373
- E[_ - 1] = O[_ - 1] / B * A >>> 0;
374
- const U = L / _;
375
- for (let w = 0; w < T; ++w) {
376
- const D = w * 3, X = r[D + 0], Z = r[D + 1], $ = r[D + 2], H = X * M + Z * m + $ * C, J = (z - H) / U, G = Math.max(
368
+ let y = 0;
369
+ for (let m = 0; m < I; ++m) y += R[m];
370
+ W[0] = 0, Y[0] = 0;
371
+ for (let m = 1; m < I; ++m)
372
+ W[m - 1] = R[m - 1] / y * E >>> 0, Y[m] = Y[m - 1] + W[m - 1];
373
+ W[I - 1] = R[I - 1] / y * E >>> 0;
374
+ const B = N / I;
375
+ for (let m = 0; m < _; ++m) {
376
+ const z = m * 3, U = s[z + 0], V = s[z + 1], O = s[z + 2], F = U * M + V * f + O * A, X = (D - F) / B, Z = Math.max(
377
377
  0,
378
378
  Math.min(
379
- _ - 1,
380
- Math.floor(J)
379
+ I - 1,
380
+ Math.floor(X)
381
381
  )
382
- ), Q = J - G, tt = q[G] + E[G] * Q >>> 0, N = Math.min(tt, A - 1);
383
- l[w] = N, b[N]++;
382
+ ), K = X - Z, Q = Y[Z] + W[Z] * K >>> 0, H = Math.min(Q, E - 1);
383
+ v[m] = H, S[H]++;
384
384
  }
385
385
  } else {
386
- const y = (A - 1) / L;
387
- for (let B = 0; B < T; ++B) {
388
- const U = B * 3, w = r[U + 0], D = r[U + 1], X = r[U + 2], Z = w * M + D * m + X * C, H = (z - Z) * y >>> 0, Y = Math.min(H, A - 1);
389
- l[B] = Y, b[Y]++;
386
+ const c = (E - 1) / N;
387
+ for (let y = 0; y < _; ++y) {
388
+ const B = y * 3, m = s[B + 0], z = s[B + 1], U = s[B + 2], V = m * M + z * f + U * A, F = (D - V) * c >>> 0, q = Math.min(F, E - 1);
389
+ v[y] = q, S[q]++;
390
390
  }
391
391
  }
392
- for (let y = 1; y < A; y++)
393
- b[y] += b[y - 1];
394
- for (let y = T - 1; y >= 0; y--) {
395
- const B = l[y], U = --b[B];
396
- e[U] = i ? i[y] : y;
392
+ for (let c = 1; c < E; c++)
393
+ S[c] += S[c - 1];
394
+ for (let c = _ - 1; c >= 0; c--) {
395
+ const y = v[c], B = --S[y];
396
+ e[B] = n ? n[c] : c;
397
397
  }
398
- const at = k * M + S * m + F * C, rt = (y) => {
398
+ const st = w * M + d * f + P * A, tt = (c) => {
399
399
  if (!e) return -1 / 0;
400
- const B = e[y], U = B;
401
- if (!r || U * 3 + 2 >= r.length)
400
+ const y = e[c], B = y;
401
+ if (!s || B * 3 + 2 >= s.length)
402
402
  return -1 / 0;
403
- const w = U * 3;
404
- return r[w] * M + r[w + 1] * m + r[w + 2] * C - at;
403
+ const m = B * 3;
404
+ return s[m] * M + s[m + 1] * f + s[m + 2] * A - st;
405
405
  };
406
- let st = T;
407
- if (T > 0 && rt(T - 1) < 0) {
408
- const y = R(
406
+ let et = _;
407
+ if (_ > 0 && tt(_ - 1) < 0) {
408
+ const c = ot(
409
409
  0,
410
- T - 1,
411
- rt
410
+ _ - 1,
411
+ tt
412
412
  );
413
- st = y < 0 ? ~y : y;
413
+ et = c < 0 ? ~c : c;
414
414
  }
415
- const ct = {
415
+ const p = {
416
416
  order: e.buffer,
417
- count: st
417
+ count: et
418
418
  };
419
- self.postMessage(ct, [e.buffer]), e = null;
419
+ self.postMessage(p, [e.buffer]), e = null;
420
420
  };
421
- self.onmessage = (k) => {
422
- const S = k.data;
423
- S.order && (e = new Uint32Array(S.order));
424
- let F = !1;
425
- if (S.centers && (r = new Float32Array(S.centers), F = !0, f = !0), Object.prototype.hasOwnProperty.call(S, "mapping") && (i = S.mapping ? new Uint32Array(S.mapping) : null, f = !0), S.chunks) {
426
- if (o = new Float32Array(S.chunks), o.length > 0 && o[3] > 0)
427
- for (let M = 0; M < o.length / 6; ++M) {
428
- const m = M * 6, C = o[m + 0], V = o[m + 1], P = o[m + 2], x = o[m + 3], u = o[m + 4], z = o[m + 5];
429
- o[m + 0] = (C + x) * 0.5, o[m + 1] = (V + u) * 0.5, o[m + 2] = (P + z) * 0.5, o[m + 3] = Math.sqrt(
430
- (x - C) ** 2 + (u - V) ** 2 + (z - P) ** 2
421
+ self.onmessage = (w) => {
422
+ const d = w.data;
423
+ d.order && (e = new Uint32Array(d.order));
424
+ let P = !1;
425
+ if (d.centers && (s = new Float32Array(d.centers), P = !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 M = 0; M < r.length / 6; ++M) {
428
+ const f = M * 6, A = r[f + 0], T = r[f + 1], j = r[f + 2], J = r[f + 3], $ = r[f + 4], D = r[f + 5];
429
+ r[f + 0] = (A + J) * 0.5, r[f + 1] = (T + $) * 0.5, r[f + 2] = (j + D) * 0.5, r[f + 3] = Math.sqrt(
430
+ (J - A) ** 2 + ($ - T) ** 2 + (D - 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 (P && s && s.length > 0) {
436
+ u.x = g.x = s[0], u.y = g.y = s[1], u.z = g.z = s[2];
437
+ for (let M = 1; M < s.length / 3; M++) {
438
+ const f = M * 3;
439
+ u.x = Math.min(u.x, s[f + 0]), g.x = Math.max(g.x, s[f + 0]), u.y = Math.min(u.y, s[f + 1]), g.y = Math.max(g.y, s[f + 1]), u.z = Math.min(u.z, s[f + 2]), g.z = Math.max(g.z, s[f + 2]);
440
440
  }
441
- } else F && r && r.length === 0 && (p.x = h.x = p.y = h.y = p.z = h.z = 0);
442
- S.cameraPosition && (a = S.cameraPosition), S.cameraDirection && (d = S.cameraDirection), W();
441
+ } else P && s && s.length === 0 && (u.x = g.x = u.y = g.y = u.z = g.z = 0);
442
+ d.cameraPosition && (i = d.cameraPosition), d.cameraDirection && (l = d.cameraDirection), L();
443
443
  };
444
444
  }).toString()})();`;
445
445
  }
446
446
  }
447
- const pt = (I, t) => {
448
- const s = ot(I), e = ot(t);
449
- return s | e << 16;
447
+ const yt = (k, t) => {
448
+ const o = ht(k), e = ht(t);
449
+ return o | e << 16;
450
450
  };
451
- function ot(I) {
452
- const t = new Float32Array([I]), 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 ht(k) {
452
+ const t = new Float32Array([k]), e = new Int32Array(t.buffer)[0];
453
+ let s = e >> 16 & 32768, r = e >> 12 & 2047;
454
+ const n = e >> 23 & 255;
455
+ return n < 103 ? s : n > 142 ? (s |= 31744, s |= (n === 255 ? 0 : 1) && e & 8388607, s) : n < 113 ? (r |= 2048, s |= (r >> 114 - n) + (r >> 113 - n & 1), s) : (s |= n - 112 << 10 | r >> 1, s += r & 1, s);
456
456
  }
457
- const ft = new ArrayBuffer(4), nt = new DataView(ft), mt = (I) => (nt.setUint32(0, I, !0), nt.getFloat32(0, !0));
458
- class xt {
457
+ const gt = new ArrayBuffer(4), ut = new DataView(gt), vt = (k) => (ut.setUint32(0, k, !0), ut.getFloat32(0, !0));
458
+ class wt {
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");
473
- const s = t.numSplats;
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);
470
+ h(this, "orderTexture");
471
+ h(this, "textureWidth");
472
+ h(this, "textureHeight");
473
+ const o = t.numSplats;
474
+ this.textureWidth = Math.ceil(Math.sqrt(o)), this.textureHeight = Math.ceil(o / this.textureWidth), this.transformA = this.createTransformATexture(t), this.transformB = this.createTransformBTexture(t), this.colorTexture = this.createColorTexture(t), this.orderTexture = this.createOrderTexture(o);
475
475
  }
476
476
  /**
477
477
  * Create the transform A texture (positions and quaternion w component)
@@ -479,24 +479,24 @@ class xt {
479
479
  * @returns DataTexture containing position data
480
480
  */
481
481
  createTransformATexture(t) {
482
- const s = t.numSplats, e = new Float32Array(
482
+ const o = 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 < o; 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], b = t.rotations[l + 1], C = yt(x, b);
489
+ e[n + 3] = vt(C);
490
490
  }
491
- const r = new n.DataTexture(
491
+ const s = 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 s.needsUpdate = !0, s.magFilter = a.NearestFilter, s.minFilter = a.NearestFilter, s;
500
500
  }
501
501
  /**
502
502
  * Create the transform B texture (scale and rotation xyz)
@@ -504,21 +504,21 @@ class xt {
504
504
  * @returns DataTexture containing scale and rotation data
505
505
  */
506
506
  createTransformBTexture(t) {
507
- const s = t.numSplats, e = new Float32Array(
507
+ const o = 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 < o; 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 s = 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 s.needsUpdate = !0, s.magFilter = a.NearestFilter, s.minFilter = a.NearestFilter, s;
522
522
  }
523
523
  /**
524
524
  * Create the color texture (RGB and opacity)
@@ -526,21 +526,21 @@ class xt {
526
526
  * @returns DataTexture containing color data
527
527
  */
528
528
  createColorTexture(t) {
529
- const s = t.numSplats, e = new Float32Array(
529
+ const o = 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 < o; 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 s = 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 s.needsUpdate = !0, s;
544
544
  }
545
545
  /**
546
546
  * Create the order texture for sorting
@@ -548,15 +548,15 @@ class xt {
548
548
  * @returns DataTexture for storing order indices
549
549
  */
550
550
  createOrderTexture(t) {
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(
555
- s,
551
+ const o = new Uint32Array(this.textureWidth * this.textureHeight);
552
+ for (let s = 0; s < t; s++)
553
+ o[s] = s;
554
+ const e = new a.DataTexture(
555
+ o,
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 bt = (
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
+ ), Mt = (
826
826
  /* glsl */
827
827
  `
828
828
  precision highp float;
@@ -856,56 +856,56 @@ void main(void) {
856
856
  }
857
857
  `
858
858
  );
859
- class vt extends n.ShaderMaterial {
859
+ class Ct extends a.ShaderMaterial {
860
860
  constructor(t = {}) {
861
- const s = {
861
+ const o = {
862
862
  // Textures (values set via methods)
863
863
  transformA: { value: null },
864
864
  transformB: { value: null },
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,
876
- uniforms: s,
874
+ vertexShader: bt,
875
+ fragmentShader: Mt,
876
+ uniforms: o,
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
904
904
  * @param width Viewport width
905
905
  * @param height Viewport height
906
906
  */
907
- updateViewport(t, s) {
908
- this.uniforms.viewport.value.set(t, s);
907
+ updateViewport(t, o) {
908
+ this.uniforms.viewport.value.set(t, o);
909
909
  }
910
910
  /**
911
911
  * Set transform texture A (positions)
@@ -943,47 +943,48 @@ 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 rt = class rt extends a.Mesh {
947
947
  // Match shader constant
948
948
  /**
949
949
  * Create a new SplatMesh for rendering Gaussian splats
950
950
  * @param splatData The splat data to render
951
951
  * @param options Rendering options
952
952
  */
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());
953
+ constructor(o, e = {}) {
954
+ const s = new Ct(e), r = rt.createInstancedGeometry(o.numSplats, rt.INSTANCE_SIZE);
955
+ super(r, s);
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) => {
974
- const e = s.count;
975
- this.geometry.instanceCount = Math.ceil(e / j.INSTANCE_SIZE), this.material.setNumSplats(e);
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", (o) => {
974
+ const e = o.count;
975
+ this.geometry.instanceCount = Math.ceil(e / rt.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 = s, this.splatData = o, 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 wt(o), this.sorter = new xt();
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
- 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);
984
+ this.splatData.positions,
985
+ n ?? void 0,
986
+ !this.options.keepSplatData
987
+ ), 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 = o.boundingBox.toBox3(), this.geometry.boundingSphere = new a.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere), this.options.keepSplatData || (this.splatData = null);
987
988
  }
988
989
  /**
989
990
  * Creates the instanced geometry for rendering splats.
@@ -991,8 +992,8 @@ const j = class j extends n.Mesh {
991
992
  * @param instanceSize Number of splats per instance.
992
993
  * @returns InstancedBufferGeometry
993
994
  */
994
- static createInstancedGeometry(s, e) {
995
- const r = Math.ceil(s / e), o = new n.BufferGeometry(), i = new Float32Array([
995
+ static createInstancedGeometry(o, e) {
996
+ const s = Math.ceil(o / e), r = new a.BufferGeometry(), n = new Float32Array([
996
997
  // x, y, splat_index_in_instance
997
998
  -1,
998
999
  -1,
@@ -1006,38 +1007,40 @@ const j = class j extends n.Mesh {
1006
1007
  -1,
1007
1008
  1,
1008
1009
  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;
1010
+ ]), i = new Uint16Array([0, 1, 2, 0, 2, 3]), l = new Float32Array(4 * 3 * e);
1011
+ for (let u = 0; u < e; u++) {
1012
+ const g = u * 4 * 3;
1013
+ for (let v = 0; v < 4; v++)
1014
+ l[g + v * 3 + 0] = n[v * 3 + 0], l[g + v * 3 + 1] = n[v * 3 + 1], l[g + v * 3 + 2] = u;
1014
1015
  }
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;
1016
+ const x = new Uint32Array(6 * e);
1017
+ for (let u = 0; u < e; u++) {
1018
+ const g = u * 6, v = u * 4;
1019
+ x[g + 0] = i[0] + v, x[g + 1] = i[1] + v, x[g + 2] = i[2] + v, x[g + 3] = i[3] + v, x[g + 4] = i[4] + v, x[g + 5] = i[5] + v;
1019
1020
  }
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;
1021
+ r.setAttribute("position", new a.BufferAttribute(l, 3)), r.setIndex(new a.BufferAttribute(x, 1));
1022
+ const b = new a.InstancedBufferGeometry();
1023
+ b.index = r.index, b.setAttribute("position", r.getAttribute("position"));
1024
+ const C = new Uint32Array(s);
1025
+ for (let u = 0; u < s; u++)
1026
+ C[u] = u * e;
1027
+ return b.setAttribute("splatInstanceIndex", new a.InstancedBufferAttribute(C, 1, !1)), b.instanceCount = 0, b;
1027
1028
  }
1028
1029
  /**
1029
1030
  * Create chunks data (bounding box min/max) for the sorter.
1030
1031
  * @returns Float32Array containing chunk data [minX, minY, minZ, maxX, maxY, maxZ] or null.
1031
1032
  */
1032
1033
  createChunks() {
1033
- const s = this.splatData.boundingBox;
1034
- return s.min.x === 1 / 0 || s.max.x === -1 / 0 ? null : new Float32Array([
1035
- s.min.x,
1036
- s.min.y,
1037
- s.min.z,
1038
- s.max.x,
1039
- s.max.y,
1040
- s.max.z
1034
+ if (!this.splatData)
1035
+ return null;
1036
+ const o = this.splatData.boundingBox;
1037
+ return o.min.x === 1 / 0 || o.max.x === -1 / 0 ? null : new Float32Array([
1038
+ o.min.x,
1039
+ o.min.y,
1040
+ o.min.z,
1041
+ o.max.x,
1042
+ o.max.y,
1043
+ o.max.z
1041
1044
  ]);
1042
1045
  }
1043
1046
  /**
@@ -1045,17 +1048,17 @@ const j = class j extends n.Mesh {
1045
1048
  * @param width Viewport width
1046
1049
  * @param height Viewport height
1047
1050
  */
1048
- updateViewport(s, e) {
1049
- s === this._vpW && e === this._vpH || (this._vpW = s, this._vpH = e, this.material.updateViewport(s, e));
1051
+ updateViewport(o, e) {
1052
+ o === this._vpW && e === this._vpH || (this._vpW = o, this._vpH = e, this.material.updateViewport(o, e));
1050
1053
  }
1051
1054
  /**
1052
1055
  * Sorts splats based on camera position and direction.
1053
1056
  * @param camera The camera to sort against.
1054
1057
  */
1055
- sort(s) {
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));
1058
+ sort(o) {
1059
+ o.getWorldPosition(this._camPosW), o.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);
1060
+ const e = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6, s = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
1061
+ this.options.autoSort && (e || s) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
1059
1062
  }
1060
1063
  /**
1061
1064
  * THREE.js hook called before rendering the object.
@@ -1066,8 +1069,8 @@ const j = class j extends n.Mesh {
1066
1069
  */
1067
1070
  // prettier-ignore
1068
1071
  // @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);
1072
+ onBeforeRender(o, e, s) {
1073
+ this.sort(s), o.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
1071
1074
  }
1072
1075
  /**
1073
1076
  * Dispose of resources
@@ -1077,9 +1080,41 @@ const j = class j extends n.Mesh {
1077
1080
  }
1078
1081
  };
1079
1082
  /** 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 {
1083
+ h(rt, "INSTANCE_SIZE", 128);
1084
+ let dt = rt;
1085
+ class At extends a.Loader {
1086
+ constructor(o) {
1087
+ super(o);
1088
+ h(this, "requestId", 0);
1089
+ h(this, "worker");
1090
+ h(this, "pendingCallbacks", /* @__PURE__ */ new Map());
1091
+ const e = this.createWorkerCode(), s = new Blob([e], { type: "application/javascript" });
1092
+ this.worker = new Worker(URL.createObjectURL(s)), this.worker.onmessage = this.onWorkerMessage.bind(this);
1093
+ }
1094
+ /**
1095
+ * Handles messages received from the parsing worker
1096
+ * @param event The message event from the worker
1097
+ */
1098
+ onWorkerMessage(o) {
1099
+ const { requestId: e, error: s, result: r } = o.data, n = this.pendingCallbacks.get(e);
1100
+ if (!n) return console.warn(`PlyLoader: Received response for unknown request ${e}`);
1101
+ if (this.pendingCallbacks.delete(e), s) return n.reject(new Error(s));
1102
+ if (!r) return n.reject(new Error("Worker returned no result"));
1103
+ try {
1104
+ const i = new mt(0);
1105
+ 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.boundingBox.min.set(
1106
+ r.boundingBox.minX,
1107
+ r.boundingBox.minY,
1108
+ r.boundingBox.minZ
1109
+ ), i.boundingBox.max.set(
1110
+ r.boundingBox.maxX,
1111
+ r.boundingBox.maxY,
1112
+ r.boundingBox.maxZ
1113
+ ), n.resolve(i);
1114
+ } catch (i) {
1115
+ n.reject(i);
1116
+ }
1117
+ }
1083
1118
  /**
1084
1119
  * Load a PLY file with Gaussian Splat data
1085
1120
  * @param url URL of the PLY file
@@ -1087,21 +1122,18 @@ class bt extends n.Loader {
1087
1122
  * @param onProgress Optional progress callback
1088
1123
  * @param onError Optional error callback
1089
1124
  */
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,
1125
+ load(o, e, s, r) {
1126
+ const n = new a.FileLoader(this.manager);
1127
+ n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
1128
+ o,
1094
1129
  (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
- }
1130
+ this.parseAsync(i).then((l) => {
1131
+ e && e(l);
1132
+ }).catch((l) => {
1133
+ r ? r(l) : console.error(l), this.manager.itemError(o);
1134
+ });
1103
1135
  },
1104
- e,
1136
+ s,
1105
1137
  r
1106
1138
  );
1107
1139
  }
@@ -1111,197 +1143,255 @@ class bt extends n.Loader {
1111
1143
  * @param onProgress Optional progress callback
1112
1144
  * @returns A Promise that resolves with the parsed SplatData
1113
1145
  */
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,
1146
+ loadAsync(o, e) {
1147
+ return new Promise((s, r) => {
1148
+ const n = new a.FileLoader(this.manager);
1149
+ n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
1150
+ o,
1119
1151
  (i) => {
1120
- try {
1121
- const a = this.parse(i);
1122
- e(a);
1123
- } catch (a) {
1124
- r(a), this.manager.itemError(t);
1125
- }
1152
+ this.parseAsync(i).then(s).catch((l) => {
1153
+ r(l), this.manager.itemError(o);
1154
+ });
1126
1155
  },
1127
- s,
1156
+ e,
1128
1157
  (i) => {
1129
- r(i), this.manager.itemError(t);
1158
+ r(i), this.manager.itemError(o);
1130
1159
  }
1131
1160
  );
1132
1161
  });
1133
1162
  }
1134
1163
  /**
1135
- * Parse PLY buffer data into SplatData
1164
+ * Parse PLY buffer data asynchronously using Web Worker
1136
1165
  * @param buffer ArrayBuffer containing PLY data
1137
- * @returns Parsed SplatData
1166
+ * @returns Promise that resolves with parsed SplatData
1138
1167
  */
1139
- parse(t) {
1140
- const s = new TextDecoder(), e = new Uint8Array(t), r = [112, 108, 121, 10], o = `
1168
+ parseAsync(o) {
1169
+ return new Promise((e, s) => {
1170
+ const r = this.requestId++;
1171
+ this.pendingCallbacks.set(r, { resolve: e, reject: s });
1172
+ const n = {
1173
+ requestId: r,
1174
+ buffer: o
1175
+ };
1176
+ this.worker.postMessage(n, [o]);
1177
+ });
1178
+ }
1179
+ /**
1180
+ * Terminate the Web Worker and clean up resources
1181
+ */
1182
+ dispose() {
1183
+ this.worker && this.worker.terminate(), this.pendingCallbacks.clear();
1184
+ }
1185
+ /**
1186
+ * Creates the self-contained code for the parsing Web Worker
1187
+ * @returns A string containing the JavaScript code for the worker
1188
+ */
1189
+ createWorkerCode() {
1190
+ return `(${(function() {
1191
+ self.onmessage = (s) => {
1192
+ const { requestId: r, buffer: n } = s.data;
1193
+ try {
1194
+ const i = e(n), l = {
1195
+ requestId: r,
1196
+ result: i
1197
+ };
1198
+ self.postMessage(l, [
1199
+ i.positions,
1200
+ i.rotations,
1201
+ i.scales,
1202
+ i.colors,
1203
+ i.opacities
1204
+ ]);
1205
+ } catch (i) {
1206
+ const l = {
1207
+ requestId: r,
1208
+ error: i instanceof Error ? i.message : String(i)
1209
+ };
1210
+ self.postMessage(l);
1211
+ }
1212
+ };
1213
+ function e(s) {
1214
+ const r = new TextDecoder(), n = new Uint8Array(s), i = [112, 108, 121, 10], l = `
1141
1215
  end_header
1142
1216
  `;
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 z = 0; z < o.length; z++)
1150
- if (e[x + z] !== o.charCodeAt(z)) {
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 z = u.split(" ");
1168
- switch (z[0]) {
1169
- case "format":
1170
- v = z[1];
1171
- break;
1172
- case "element":
1173
- f.push({
1174
- name: z[1],
1175
- count: parseInt(z[2], 10),
1176
- properties: []
1177
- });
1178
- break;
1179
- case "property":
1180
- if (f.length === 0)
1217
+ for (let p = 0; p < i.length; p++)
1218
+ if (n[p] !== i[p])
1181
1219
  throw new Error(
1182
- "Invalid PLY file: Property without element"
1220
+ "Invalid PLY file: Missing magic bytes"
1183
1221
  );
1184
- f[f.length - 1].properties.push({
1185
- type: z[1],
1186
- name: z[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), _ = 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
- _,
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(), C = 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 T = 0; T < g.properties.length; T++) {
1231
- const K = g.properties[T].type;
1232
- let A;
1233
- switch (K) {
1234
- case "char":
1235
- A = h.getInt8(l), l += 1;
1236
- break;
1237
- case "uchar":
1238
- A = h.getUint8(l), l += 1;
1239
- break;
1240
- case "short":
1241
- A = h.getInt16(l, !0), l += 2;
1242
- break;
1243
- case "ushort":
1244
- A = h.getUint16(l, !0), l += 2;
1245
- break;
1246
- case "int":
1247
- A = h.getInt32(l, !0), l += 4;
1248
- break;
1249
- case "uint":
1250
- A = h.getUint32(l, !0), l += 4;
1251
- break;
1252
- case "float":
1253
- A = h.getFloat32(l, !0), l += 4;
1254
- break;
1255
- case "double":
1256
- A = h.getFloat64(l, !0), l += 8;
1222
+ let x = 0;
1223
+ for (let p = 0; p < n.length - l.length; p++) {
1224
+ let c = !0;
1225
+ for (let y = 0; y < l.length; y++)
1226
+ if (n[p + y] !== l.charCodeAt(y)) {
1227
+ c = !1;
1228
+ break;
1229
+ }
1230
+ if (c) {
1231
+ x = p + l.length;
1257
1232
  break;
1258
- default:
1259
- throw new Error(`Unsupported property type: ${K}`);
1233
+ }
1260
1234
  }
1261
- u.push(A);
1235
+ if (x === 0)
1236
+ throw new Error(
1237
+ "Invalid PLY file: Could not find end of header"
1238
+ );
1239
+ const C = r.decode(
1240
+ n.subarray(0, x)
1241
+ ).split(`
1242
+ `), u = [];
1243
+ let g = null;
1244
+ for (let p = 1; p < C.length; p++) {
1245
+ const c = C[p].trim();
1246
+ if (c === "" || c === "end_header") continue;
1247
+ const y = c.split(" ");
1248
+ switch (y[0]) {
1249
+ case "format":
1250
+ g = y[1];
1251
+ break;
1252
+ case "element":
1253
+ u.push({
1254
+ name: y[1],
1255
+ count: parseInt(y[2], 10),
1256
+ properties: []
1257
+ });
1258
+ break;
1259
+ case "property":
1260
+ if (u.length === 0)
1261
+ throw new Error(
1262
+ "Invalid PLY file: Property without element"
1263
+ );
1264
+ u[u.length - 1].properties.push({
1265
+ type: y[1],
1266
+ name: y[2]
1267
+ });
1268
+ break;
1269
+ }
1270
+ }
1271
+ if (g !== "binary_little_endian")
1272
+ throw new Error(`Unsupported PLY format: ${g}`);
1273
+ const v = u.find((p) => p.name === "vertex");
1274
+ if (!v)
1275
+ throw new Error(
1276
+ "Invalid PLY file: No vertex element found"
1277
+ );
1278
+ const S = v.count, I = new Float32Array(S * 3), R = new Float32Array(S * 4), Y = new Float32Array(S * 3), W = new Float32Array(S * 3), ot = new Float32Array(S), L = new DataView(s);
1279
+ let w = x;
1280
+ const d = (p) => v.properties.findIndex(
1281
+ (c) => c.name === p
1282
+ ), P = d("x"), M = d("y"), f = d("z"), A = [
1283
+ d("rot_0"),
1284
+ d("rot_1"),
1285
+ d("rot_2"),
1286
+ d("rot_3")
1287
+ ], T = [
1288
+ d("scale_0"),
1289
+ d("scale_1"),
1290
+ d("scale_2")
1291
+ ], j = [
1292
+ d("f_dc_0"),
1293
+ d("f_dc_1"),
1294
+ d("f_dc_2")
1295
+ ], J = d("opacity");
1296
+ if ([
1297
+ P,
1298
+ M,
1299
+ f,
1300
+ ...A,
1301
+ ...T,
1302
+ ...j,
1303
+ J
1304
+ ].some((p) => p === -1))
1305
+ throw new Error(
1306
+ "Invalid PLY file: Missing required properties"
1307
+ );
1308
+ const D = 0.28209479177387814, _ = (p) => {
1309
+ if (p > 0) return 1 / (1 + Math.exp(-p));
1310
+ const c = Math.exp(p);
1311
+ return c / (1 + c);
1312
+ };
1313
+ let N = 1 / 0, nt = 1 / 0, E = 1 / 0, st = -1 / 0, tt = -1 / 0, et = -1 / 0;
1314
+ for (let p = 0; p < S; p++) {
1315
+ const c = [];
1316
+ for (let at = 0; at < v.properties.length; at++) {
1317
+ const lt = v.properties[at].type;
1318
+ let G;
1319
+ switch (lt) {
1320
+ case "char":
1321
+ G = L.getInt8(w), w += 1;
1322
+ break;
1323
+ case "uchar":
1324
+ G = L.getUint8(w), w += 1;
1325
+ break;
1326
+ case "short":
1327
+ G = L.getInt16(w, !0), w += 2;
1328
+ break;
1329
+ case "ushort":
1330
+ G = L.getUint16(w, !0), w += 2;
1331
+ break;
1332
+ case "int":
1333
+ G = L.getInt32(w, !0), w += 4;
1334
+ break;
1335
+ case "uint":
1336
+ G = L.getUint32(w, !0), w += 4;
1337
+ break;
1338
+ case "float":
1339
+ G = L.getFloat32(w, !0), w += 4;
1340
+ break;
1341
+ case "double":
1342
+ G = L.getFloat64(w, !0), w += 8;
1343
+ break;
1344
+ default:
1345
+ throw new Error(
1346
+ `Unsupported property type: ${lt}`
1347
+ );
1348
+ }
1349
+ c.push(G);
1350
+ }
1351
+ const y = c[P], B = c[M], m = c[f], z = p * 3;
1352
+ I[z] = y, I[z + 1] = B, I[z + 2] = m, N = Math.min(N, y), nt = Math.min(nt, B), E = Math.min(E, m), st = Math.max(st, y), tt = Math.max(tt, B), et = Math.max(et, m);
1353
+ let U = c[A[1]], V = c[A[2]], O = c[A[3]], F = c[A[0]];
1354
+ const q = Math.sqrt(
1355
+ U * U + V * V + O * O + F * F
1356
+ );
1357
+ q > 0 && (U /= q, V /= q, O /= q, F /= q), F < 0 && (U = -U, V = -V, O = -O, F = -F);
1358
+ const X = p * 4;
1359
+ R[X] = U, R[X + 1] = V, R[X + 2] = O, R[X + 3] = F;
1360
+ const Z = p * 3;
1361
+ Y[Z] = c[T[0]], Y[Z + 1] = c[T[1]], Y[Z + 2] = c[T[2]];
1362
+ let K = 0.5 + c[j[0]] * D, Q = 0.5 + c[j[1]] * D, H = 0.5 + c[j[2]] * D;
1363
+ K = Math.max(0, Math.min(1, K)), Q = Math.max(0, Math.min(1, Q)), H = Math.max(0, Math.min(1, H));
1364
+ const it = p * 3;
1365
+ W[it] = K, W[it + 1] = Q, W[it + 2] = H, ot[p] = _(c[J]);
1366
+ }
1367
+ return {
1368
+ numSplats: S,
1369
+ positions: I.buffer,
1370
+ rotations: R.buffer,
1371
+ scales: Y.buffer,
1372
+ colors: W.buffer,
1373
+ opacities: ot.buffer,
1374
+ boundingBox: {
1375
+ minX: N,
1376
+ minY: nt,
1377
+ minZ: E,
1378
+ maxX: st,
1379
+ maxY: tt,
1380
+ maxZ: et
1381
+ }
1382
+ };
1262
1383
  }
1263
- m.set(
1264
- u[_],
1265
- u[O],
1266
- u[q]
1267
- ), C.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(), C.w < 0 && (C.x = -C.x, C.y = -C.y, C.z = -C.z, C.w = -C.w), 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 z = M(u[k]);
1284
- p.setSplat(
1285
- x,
1286
- m,
1287
- C,
1288
- V,
1289
- // Pass log scale directly
1290
- P,
1291
- z
1292
- );
1293
- }
1294
- return p.calculateBoundingBox(), p;
1384
+ }).toString()})();`;
1295
1385
  }
1296
1386
  }
1297
- const Mt = "0.3.0";
1387
+ const zt = "0.3.0";
1298
1388
  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
1389
+ ct as BoundingBox,
1390
+ At as PlyLoader,
1391
+ mt as SplatData,
1392
+ Ct as SplatMaterial,
1393
+ dt as SplatMesh,
1394
+ xt as SplatSorter,
1395
+ wt as TextureManager,
1396
+ zt as VERSION
1307
1397
  };