@speridlabs/visus 0.2.0 → 1.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 ct = Object.defineProperty;
2
- var lt = (k, t, r) => t in k ? ct(k, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : k[t] = r;
3
- var f = (k, t, r) => lt(k, typeof t != "symbol" ? t + "" : t, r);
4
- import * as n from "three";
1
+ var lt = Object.defineProperty;
2
+ var ht = (A, t, n) => t in A ? lt(A, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : A[t] = n;
3
+ var f = (A, t, n) => ht(A, typeof t != "symbol" ? t + "" : t, n);
4
+ import * as i from "three";
5
5
  class et {
6
6
  constructor() {
7
- f(this, "min", new n.Vector3(1 / 0, 1 / 0, 1 / 0));
8
- f(this, "max", new n.Vector3(-1 / 0, -1 / 0, -1 / 0));
9
- f(this, "center", new n.Vector3());
7
+ f(this, "min", new i.Vector3(1 / 0, 1 / 0, 1 / 0));
8
+ f(this, "max", new i.Vector3(-1 / 0, -1 / 0, -1 / 0));
9
+ f(this, "center", new i.Vector3());
10
10
  /** Half extents (size/2) */
11
- f(this, "halfExtents", new n.Vector3());
11
+ f(this, "halfExtents", new i.Vector3());
12
12
  }
13
13
  /**
14
14
  * Reset the bounding box to its initial state
@@ -49,7 +49,7 @@ 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 i.Box3().set(this.min, this.max);
53
53
  }
54
54
  /**
55
55
  * Create a clone of this bounding box
@@ -60,7 +60,7 @@ class et {
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 ht {
63
+ class ut {
64
64
  // TODO: there is no sh spherical harmonics
65
65
  constructor(t = 0) {
66
66
  f(this, "numSplats", 0);
@@ -85,13 +85,13 @@ class ht {
85
85
  * @param color Color
86
86
  * @param opacity Opacity value
87
87
  */
88
- setSplat(t, r, e, o, s, i) {
88
+ setSplat(t, n, e, r, s, o) {
89
89
  if (t >= this.numSplats)
90
90
  throw new Error(
91
91
  `Splat index out of bounds: ${t} >= ${this.numSplats}`
92
92
  );
93
93
  const a = t * 3, c = t * 4, h = t * 3, v = t * 3;
94
- this.positions[a] = r.x, this.positions[a + 1] = r.y, this.positions[a + 2] = r.z, this.rotations[c] = e.x, this.rotations[c + 1] = e.y, this.rotations[c + 2] = e.z, this.rotations[c + 3] = e.w, this.scales[h] = o.x, this.scales[h + 1] = o.y, this.scales[h + 2] = o.z, this.colors[v] = s.r, this.colors[v + 1] = s.g, this.colors[v + 2] = s.b, this.opacities[t] = i, this.centers[a] = r.x, this.centers[a + 1] = r.y, this.centers[a + 2] = r.z;
94
+ this.positions[a] = n.x, this.positions[a + 1] = n.y, this.positions[a + 2] = n.z, this.rotations[c] = e.x, this.rotations[c + 1] = e.y, this.rotations[c + 2] = e.z, this.rotations[c + 3] = e.w, this.scales[h] = r.x, this.scales[h + 1] = r.y, this.scales[h + 2] = r.z, this.colors[v] = s.r, this.colors[v + 1] = s.g, this.colors[v + 2] = s.b, this.opacities[t] = o, this.centers[a] = n.x, this.centers[a + 1] = n.y, this.centers[a + 2] = n.z;
95
95
  }
96
96
  /**
97
97
  * Get a splat's data
@@ -103,26 +103,26 @@ class ht {
103
103
  throw new Error(
104
104
  `Splat index out of bounds: ${t} >= ${this.numSplats}`
105
105
  );
106
- const r = t * 3, e = t * 4, o = t * 3, s = t * 3;
106
+ const n = t * 3, e = t * 4, r = t * 3, s = t * 3;
107
107
  return {
108
- position: new n.Vector3(
109
- this.positions[r],
110
- this.positions[r + 1],
111
- this.positions[r + 2]
108
+ position: new i.Vector3(
109
+ this.positions[n],
110
+ this.positions[n + 1],
111
+ this.positions[n + 2]
112
112
  ),
113
- rotation: new n.Quaternion(
113
+ rotation: new i.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[o]),
122
- Math.exp(this.scales[o + 1]),
123
- Math.exp(this.scales[o + 2])
120
+ scale: new i.Vector3(
121
+ Math.exp(this.scales[r]),
122
+ Math.exp(this.scales[r + 1]),
123
+ Math.exp(this.scales[r + 2])
124
124
  ),
125
- color: new n.Color(
125
+ color: new i.Color(
126
126
  this.colors[s],
127
127
  this.colors[s + 1],
128
128
  this.colors[s + 2]
@@ -136,9 +136,9 @@ class ht {
136
136
  */
137
137
  calculateBoundingBox() {
138
138
  this.boundingBox.reset();
139
- const t = new n.Vector3();
140
- for (let r = 0; r < this.numSplats; r++) {
141
- const e = r * 3;
139
+ const t = new i.Vector3();
140
+ for (let n = 0; n < this.numSplats; n++) {
141
+ const e = n * 3;
142
142
  t.set(
143
143
  this.positions[e],
144
144
  this.positions[e + 1],
@@ -152,37 +152,37 @@ class ht {
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 i.BufferGeometry();
156
156
  t.setAttribute(
157
157
  "position",
158
- new n.BufferAttribute(this.positions, 3)
158
+ new i.BufferAttribute(this.positions, 3)
159
159
  );
160
- const r = new Float32Array(this.numSplats * 3), e = new n.Quaternion(), o = new n.Euler();
160
+ const n = new Float32Array(this.numSplats * 3), e = new i.Quaternion(), r = new i.Euler();
161
161
  for (let s = 0; s < this.numSplats; s++) {
162
- const i = s * 4, a = s * 3;
162
+ const o = s * 4, a = s * 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
- ), o.setFromQuaternion(e), r[a] = o.x, r[a + 1] = o.y, r[a + 2] = o.z;
164
+ this.rotations[o],
165
+ this.rotations[o + 1],
166
+ this.rotations[o + 2],
167
+ this.rotations[o + 3]
168
+ ), r.setFromQuaternion(e), n[a] = r.x, n[a + 1] = r.y, n[a + 2] = r.z;
169
169
  }
170
170
  return t.setAttribute(
171
171
  "rotation",
172
- new n.BufferAttribute(r, 3)
172
+ new i.BufferAttribute(n, 3)
173
173
  ), t.setAttribute(
174
174
  "scale",
175
- new n.BufferAttribute(this.scales, 3)
175
+ new i.BufferAttribute(this.scales, 3)
176
176
  ), t.setAttribute(
177
177
  "color",
178
- new n.BufferAttribute(this.colors, 3)
178
+ new i.BufferAttribute(this.colors, 3)
179
179
  ), t.setAttribute(
180
180
  "opacity",
181
- new n.BufferAttribute(this.opacities, 1)
181
+ new i.BufferAttribute(this.opacities, 1)
182
182
  ), t;
183
183
  }
184
184
  }
185
- class ut extends n.EventDispatcher {
185
+ class dt extends i.EventDispatcher {
186
186
  constructor() {
187
187
  super();
188
188
  f(this, "worker");
@@ -190,26 +190,26 @@ class ut extends n.EventDispatcher {
190
190
  f(this, "orderTexture", null);
191
191
  /** Bounding box data for optimization */
192
192
  f(this, "chunks", null);
193
- f(this, "lastCameraPosition", new n.Vector3());
194
- f(this, "lastCameraDirection", new n.Vector3());
195
- const r = this.createWorkerCode(), e = new Blob([r], { type: "application/javascript" });
193
+ f(this, "lastCameraPosition", new i.Vector3());
194
+ f(this, "lastCameraDirection", new i.Vector3());
195
+ const n = this.createWorkerCode(), e = new Blob([n], { type: "application/javascript" });
196
196
  this.worker = new Worker(URL.createObjectURL(e)), this.worker.onmessage = this.onWorkerMessage.bind(this);
197
197
  }
198
198
  /**
199
199
  * Handles messages received from the sorting worker.
200
200
  * @param event The message event from the worker.
201
201
  */
202
- onWorkerMessage(r) {
202
+ onWorkerMessage(n) {
203
203
  if (!this.orderTexture || !this.orderTexture.image)
204
204
  return console.error("SplatSorter: Order texture not initialized!");
205
- const { order: e, count: o } = r.data, s = this.orderTexture.image.data;
205
+ const { order: e, count: r } = n.data, s = this.orderTexture.image.data;
206
206
  if (!(s instanceof Uint32Array))
207
207
  return console.error(
208
208
  "SplatSorter: Order texture data is not a Uint32Array!"
209
209
  );
210
210
  s.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
211
- const i = s.buffer.slice(0), a = { order: i };
212
- this.worker.postMessage(a, [i]), this.dispatchEvent({ type: "updated", count: o });
211
+ const o = s.buffer.slice(0), a = { order: o };
212
+ this.worker.postMessage(a, [o]), this.dispatchEvent({ type: "updated", count: r });
213
213
  }
214
214
  /**
215
215
  * Initializes the sorter with necessary data and textures.
@@ -217,29 +217,29 @@ class ut 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(r, e, o) {
221
- if (!r || !(r.image.data instanceof Uint32Array))
220
+ init(n, e, r) {
221
+ if (!n || !(n.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 (r.image.data.length < e.length / 3)
225
+ if (n.image.data.length < e.length / 3)
226
226
  throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
227
227
  const s = e.length / 3;
228
- this.orderTexture = r, this.centers = e.slice();
229
- const i = this.orderTexture.image.data;
230
- for (let g = 0; g < s; g++) i[g] = g;
228
+ this.orderTexture = n, this.centers = e.slice();
229
+ const o = this.orderTexture.image.data;
230
+ for (let y = 0; y < s; y++) o[y] = y;
231
231
  this.orderTexture.needsUpdate = !0;
232
- const a = i.buffer.slice(0), c = this.centers.buffer.slice(0), h = {
232
+ const a = o.buffer.slice(0), c = this.centers.buffer.slice(0), h = {
233
233
  order: a,
234
234
  centers: c
235
235
  }, v = [
236
236
  a,
237
237
  c
238
238
  ];
239
- if (o) {
240
- this.chunks = o.slice();
241
- const g = this.chunks.buffer.slice(0);
242
- h.chunks = g, v.push(g);
239
+ if (r) {
240
+ this.chunks = r.slice();
241
+ const y = this.chunks.buffer.slice(0);
242
+ h.chunks = y, v.push(y);
243
243
  }
244
244
  this.worker.postMessage(h, v);
245
245
  }
@@ -248,53 +248,53 @@ class ut extends n.EventDispatcher {
248
248
  * The sorter will only consider splats whose original indices are present in the mapping.
249
249
  * @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
250
250
  */
251
- setMapping(r) {
251
+ setMapping(n) {
252
252
  if (!this.centers)
253
253
  return console.warn(
254
254
  "SplatSorter: Cannot set mapping before initialization."
255
255
  );
256
256
  let e;
257
- const o = [];
258
- if (!r) {
257
+ const r = [];
258
+ if (!n) {
259
259
  const c = this.centers.buffer.slice(0);
260
260
  return e = {
261
261
  centers: c,
262
262
  mapping: null
263
- }, o.push(c), this.worker.postMessage(e, o);
263
+ }, r.push(c), this.worker.postMessage(e, r);
264
264
  }
265
- const s = new Float32Array(r.length * 3);
266
- for (let c = 0; c < r.length; c++) {
267
- const h = r[c];
265
+ const s = new Float32Array(n.length * 3);
266
+ for (let c = 0; c < n.length; c++) {
267
+ const h = n[c];
268
268
  if (h * 3 + 2 >= this.centers.length) {
269
269
  console.warn(
270
270
  `SplatSorter: Mapping index ${h} out of bounds.`
271
271
  );
272
272
  continue;
273
273
  }
274
- const v = h * 3, g = c * 3;
275
- s[g + 0] = this.centers[v + 0], s[g + 1] = this.centers[v + 1], s[g + 2] = this.centers[v + 2];
274
+ const v = h * 3, y = c * 3;
275
+ s[y + 0] = this.centers[v + 0], s[y + 1] = this.centers[v + 1], s[y + 2] = this.centers[v + 2];
276
276
  }
277
- const i = s.buffer.slice(0), a = r.buffer.slice(0);
277
+ const o = s.buffer.slice(0), a = n.buffer.slice(0);
278
278
  e = {
279
- centers: i,
279
+ centers: o,
280
280
  mapping: a
281
- }, o.push(i, a), this.worker.postMessage(e, o);
281
+ }, r.push(o, a), this.worker.postMessage(e, r);
282
282
  }
283
283
  /**
284
284
  * Updates the camera parameters used for sorting.
285
285
  * @param position The camera's position in the sorter's local coordinate space.
286
286
  * @param direction The camera's forward direction in the sorter's local coordinate space.
287
287
  */
288
- setCamera(r, e) {
289
- const o = this.lastCameraPosition.distanceToSquared(r) > 1e-7, s = this.lastCameraDirection.dot(e) < 0.9999;
290
- if (!o && !s)
288
+ setCamera(n, e) {
289
+ const r = this.lastCameraPosition.distanceToSquared(n) > 1e-7, s = this.lastCameraDirection.dot(e) < 0.9999;
290
+ if (!r && !s)
291
291
  return;
292
- this.lastCameraPosition.copy(r), this.lastCameraDirection.copy(e);
293
- const i = {
294
- cameraPosition: { x: r.x, y: r.y, z: r.z },
292
+ this.lastCameraPosition.copy(n), this.lastCameraDirection.copy(e);
293
+ const o = {
294
+ cameraPosition: { x: n.x, y: n.y, z: n.z },
295
295
  cameraDirection: { x: e.x, y: e.y, z: e.z }
296
296
  };
297
- this.worker.postMessage(i);
297
+ this.worker.postMessage(o);
298
298
  }
299
299
  /**
300
300
  * Terminates the Web Worker and cleans up resources.
@@ -308,148 +308,149 @@ class ut extends n.EventDispatcher {
308
308
  */
309
309
  createWorkerCode() {
310
310
  return `(${(function() {
311
- let e = null, o = null, s = null, i = null, a = null, c = null, h = !1;
312
- const v = { x: 0, y: 0, z: 0 }, g = { x: 0, y: 0, z: 0 }, p = { x: 0, y: 0, z: 0 }, u = { x: 0, y: 0, z: 0 };
311
+ let e = null, r = null, s = null, o = null, a = null, c = null, h = !1;
312
+ const v = { x: 0, y: 0, z: 0 }, y = { x: 0, y: 0, z: 0 }, p = { x: 0, y: 0, z: 0 }, u = { x: 0, y: 0, z: 0 };
313
313
  let l = null, b = null;
314
- const A = 32, O = new Array(A).fill(0), q = new Array(A).fill(0), R = new Array(A).fill(0), E = (F, z, _) => {
315
- for (; F <= z; ) {
316
- const M = z + F >> 1, m = _(M);
314
+ const B = 32, O = new Array(B).fill(0), q = new Array(B).fill(0), E = new Array(B).fill(0), R = (F, S, D) => {
315
+ for (; F <= S; ) {
316
+ const M = S + F >> 1, m = D(M);
317
317
  if (m > 0) F = M + 1;
318
- else if (m < 0) z = M - 1;
318
+ else if (m < 0) S = M - 1;
319
319
  else return M;
320
320
  }
321
321
  return ~F;
322
322
  }, W = () => {
323
- if (!e || !o || !a || !c)
323
+ if (!e || !r || !a || !c)
324
324
  return;
325
- if (o.length === 0) {
326
- const y = {
325
+ if (r.length === 0) {
326
+ const g = {
327
327
  order: e.buffer,
328
328
  count: 0
329
329
  };
330
- self.postMessage(y, [e.buffer]), e = null;
330
+ self.postMessage(g, [e.buffer]), e = null;
331
331
  return;
332
332
  }
333
- const F = a.x, z = a.y, _ = a.z, M = c.x, m = c.y, B = c.z, P = 1e-4, V = Math.abs(F - v.x) > P || Math.abs(z - v.y) > P || Math.abs(_ - v.z) > P, x = Math.abs(M - g.x) > P || Math.abs(m - g.y) > P || Math.abs(B - g.z) > P;
333
+ const F = a.x, S = a.y, D = a.z, M = c.x, m = c.y, C = c.z, _ = 1e-4, V = Math.abs(F - v.x) > _ || Math.abs(S - v.y) > _ || Math.abs(D - v.z) > _, x = Math.abs(M - y.x) > _ || Math.abs(m - y.y) > _ || Math.abs(C - y.z) > _;
334
334
  if (!h && !V && !x)
335
335
  return;
336
- h = !1, v.x = F, v.y = z, v.z = _, g.x = M, g.y = m, g.z = B;
337
- let d = 1 / 0, C = -1 / 0;
338
- for (let y = 0; y < 8; ++y) {
339
- const T = y & 1 ? p.x : u.x, U = y & 2 ? p.y : u.y, w = y & 4 ? p.z : u.z, D = T * M + U * m + w * B;
340
- d = Math.min(d, D), C = Math.max(C, D);
336
+ h = !1, v.x = F, v.y = S, v.z = D, y.x = M, y.y = m, y.z = C;
337
+ let d = 1 / 0, z = -1 / 0;
338
+ for (let g = 0; g < 8; ++g) {
339
+ const k = g & 1 ? p.x : u.x, U = g & 2 ? p.y : u.y, w = g & 4 ? p.z : u.z, P = k * M + U * m + w * C;
340
+ d = Math.min(d, P), z = Math.max(z, P);
341
341
  }
342
- const I = o.length / 3, L = C - d, S = (1 << Math.max(
342
+ const T = r.length / 3, L = z - d, I = (1 << Math.max(
343
343
  10,
344
- Math.min(20, Math.ceil(Math.log2(I / 4)))
344
+ Math.min(20, Math.ceil(Math.log2(T / 4)))
345
345
  )) + 1;
346
- if ((!l || l.length !== I) && (l = new Uint32Array(I)), !b || b.length !== S ? b = new Uint32Array(S) : b.fill(0), L < 1e-7) {
347
- for (let y = 0; y < I; ++y) l[y] = 0;
348
- b[0] = I;
346
+ if ((!l || l.length !== T) && (l = new Uint32Array(T)), !b || b.length !== I ? b = new Uint32Array(I) : b.fill(0), L < 1e-7) {
347
+ for (let g = 0; g < T; ++g) l[g] = 0;
348
+ b[0] = T;
349
349
  } else if (s && s.length > 0) {
350
- const y = s.length / 6;
350
+ const g = s.length / 6;
351
351
  O.fill(0);
352
- for (let w = 0; w < y; ++w) {
353
- const D = w * 6, G = s[D + 0], Z = s[D + 1], J = s[D + 2], N = s[D + 3], H = G * M + Z * m + J * B - d, K = H - N, $ = H + N, X = Math.max(
352
+ for (let w = 0; w < g; ++w) {
353
+ const P = w * 6, Z = s[P + 0], G = s[P + 1], $ = s[P + 2], H = s[P + 3], Y = Z * M + G * m + $ * C - d, J = Y - H, X = Y + H, Q = Math.max(
354
354
  0,
355
- Math.floor(K * A / L)
355
+ Math.floor(J * B / L)
356
356
  ), tt = Math.min(
357
- A,
358
- Math.ceil($ * A / L)
357
+ B,
358
+ Math.ceil(X * B / L)
359
359
  );
360
- for (let j = X; j < tt; ++j)
361
- O[j]++;
360
+ for (let N = Q; N < tt; ++N)
361
+ O[N]++;
362
362
  }
363
- let T = 0;
364
- for (let w = 0; w < A; ++w) T += O[w];
365
- R[0] = 0, q[0] = 0;
366
- for (let w = 1; w < A; ++w)
367
- R[w - 1] = O[w - 1] / T * S >>> 0, q[w] = q[w - 1] + R[w - 1];
368
- R[A - 1] = O[A - 1] / T * S >>> 0;
369
- const U = L / A;
370
- for (let w = 0; w < I; ++w) {
371
- const D = w * 3, G = o[D + 0], Z = o[D + 1], J = o[D + 2], N = G * M + Z * m + J * B, K = (C - N) / U, $ = Math.max(
363
+ let k = 0;
364
+ for (let w = 0; w < B; ++w) k += O[w];
365
+ E[0] = 0, q[0] = 0;
366
+ for (let w = 1; w < B; ++w)
367
+ E[w - 1] = O[w - 1] / k * I >>> 0, q[w] = q[w - 1] + E[w - 1];
368
+ E[B - 1] = O[B - 1] / k * I >>> 0;
369
+ const U = L / B;
370
+ for (let w = 0; w < T; ++w) {
371
+ const P = w * 3, Z = r[P + 0], G = r[P + 1], $ = r[P + 2], H = Z * M + G * m + $ * C, J = (z - H) / U, X = Math.max(
372
372
  0,
373
373
  Math.min(
374
- A - 1,
375
- Math.floor(K)
374
+ B - 1,
375
+ Math.floor(J)
376
376
  )
377
- ), X = K - $, tt = q[$] + R[$] * X >>> 0, j = Math.min(tt, S - 1);
378
- l[w] = j, b[j]++;
377
+ ), Q = J - X, tt = q[X] + E[X] * Q >>> 0, N = Math.min(tt, I - 1);
378
+ l[w] = N, b[N]++;
379
379
  }
380
380
  } else {
381
- const y = (S - 1) / L;
382
- for (let T = 0; T < I; ++T) {
383
- const U = T * 3, w = o[U + 0], D = o[U + 1], G = o[U + 2], Z = w * M + D * m + G * B, N = (C - Z) * y >>> 0, H = Math.min(N, S - 1);
384
- l[T] = H, b[H]++;
381
+ const g = (I - 1) / L;
382
+ for (let k = 0; k < T; ++k) {
383
+ const U = k * 3, w = r[U + 0], P = r[U + 1], Z = r[U + 2], G = w * M + P * m + Z * C, H = (z - G) * g >>> 0, Y = Math.min(H, I - 1);
384
+ l[k] = Y, b[Y]++;
385
385
  }
386
386
  }
387
- for (let y = 1; y < S; y++)
388
- b[y] += b[y - 1];
389
- for (let y = I - 1; y >= 0; y--) {
390
- const T = l[y], U = --b[T];
391
- e[U] = i ? i[y] : y;
387
+ for (let g = 1; g < I; g++)
388
+ b[g] += b[g - 1];
389
+ for (let g = T - 1; g >= 0; g--) {
390
+ const k = l[g], U = --b[k];
391
+ e[U] = o ? o[g] : g;
392
392
  }
393
- const it = F * M + z * m + _ * B, rt = (y) => {
393
+ const at = F * M + S * m + D * C, rt = (g) => {
394
394
  if (!e) return -1 / 0;
395
- const T = e[y], U = T;
396
- if (!o || U * 3 + 2 >= o.length)
395
+ const k = e[g], U = k;
396
+ if (!r || U * 3 + 2 >= r.length)
397
397
  return -1 / 0;
398
398
  const w = U * 3;
399
- return o[w] * M + o[w + 1] * m + o[w + 2] * B - it;
399
+ return r[w] * M + r[w + 1] * m + r[w + 2] * C - at;
400
400
  };
401
- let st = I;
402
- if (I > 0 && rt(I - 1) < 0) {
403
- const y = E(
401
+ let st = T;
402
+ if (T > 0 && rt(T - 1) < 0) {
403
+ const g = R(
404
404
  0,
405
- I - 1,
405
+ T - 1,
406
406
  rt
407
407
  );
408
- st = y < 0 ? ~y : y;
408
+ st = g < 0 ? ~g : g;
409
409
  }
410
- const at = {
410
+ const ct = {
411
411
  order: e.buffer,
412
412
  count: st
413
413
  };
414
- self.postMessage(at, [e.buffer]), e = null;
414
+ self.postMessage(ct, [e.buffer]), e = null;
415
415
  };
416
416
  self.onmessage = (F) => {
417
- const z = F.data;
418
- z.order && (e = new Uint32Array(z.order));
419
- let _ = !1;
420
- if (z.centers && (o = new Float32Array(z.centers), _ = !0, h = !0), Object.prototype.hasOwnProperty.call(z, "mapping") && (i = z.mapping ? new Uint32Array(z.mapping) : null, h = !0), z.chunks) {
421
- if (s = new Float32Array(z.chunks), s.length > 0 && s[3] > 0)
417
+ const S = F.data;
418
+ S.order && (e = new Uint32Array(S.order));
419
+ let D = !1;
420
+ if (S.centers && (r = new Float32Array(S.centers), D = !0, h = !0), Object.prototype.hasOwnProperty.call(S, "mapping") && (o = S.mapping ? new Uint32Array(S.mapping) : null, h = !0), S.chunks) {
421
+ if (s = new Float32Array(S.chunks), s.length > 0 && s[3] > 0)
422
422
  for (let M = 0; M < s.length / 6; ++M) {
423
- const m = M * 6, B = s[m + 0], P = s[m + 1], V = s[m + 2], x = s[m + 3], d = s[m + 4], C = s[m + 5];
424
- s[m + 0] = (B + x) * 0.5, s[m + 1] = (P + d) * 0.5, s[m + 2] = (V + C) * 0.5, s[m + 3] = Math.sqrt(
425
- (x - B) ** 2 + (d - P) ** 2 + (C - V) ** 2
423
+ const m = M * 6, C = s[m + 0], _ = s[m + 1], V = s[m + 2], x = s[m + 3], d = s[m + 4], z = s[m + 5];
424
+ s[m + 0] = (C + x) * 0.5, s[m + 1] = (_ + d) * 0.5, s[m + 2] = (V + z) * 0.5, s[m + 3] = Math.sqrt(
425
+ (x - C) ** 2 + (d - _) ** 2 + (z - V) ** 2
426
426
  ) * 0.5;
427
427
  }
428
428
  h = !0;
429
429
  }
430
- if (_ && o && o.length > 0) {
431
- p.x = u.x = o[0], p.y = u.y = o[1], p.z = u.z = o[2];
432
- for (let M = 1; M < o.length / 3; M++) {
430
+ if (D && r && r.length > 0) {
431
+ p.x = u.x = r[0], p.y = u.y = r[1], p.z = u.z = r[2];
432
+ for (let M = 1; M < r.length / 3; M++) {
433
433
  const m = M * 3;
434
- p.x = Math.min(p.x, o[m + 0]), u.x = Math.max(u.x, o[m + 0]), p.y = Math.min(p.y, o[m + 1]), u.y = Math.max(u.y, o[m + 1]), p.z = Math.min(p.z, o[m + 2]), u.z = Math.max(u.z, o[m + 2]);
434
+ p.x = Math.min(p.x, r[m + 0]), u.x = Math.max(u.x, r[m + 0]), p.y = Math.min(p.y, r[m + 1]), u.y = Math.max(u.y, r[m + 1]), p.z = Math.min(p.z, r[m + 2]), u.z = Math.max(u.z, r[m + 2]);
435
435
  }
436
- } else _ && o && o.length === 0 && (p.x = u.x = p.y = u.y = p.z = u.z = 0);
437
- z.cameraPosition && (a = z.cameraPosition), z.cameraDirection && (c = z.cameraDirection), W();
436
+ } else D && r && r.length === 0 && (p.x = u.x = p.y = u.y = p.z = u.z = 0);
437
+ S.cameraPosition && (a = S.cameraPosition), S.cameraDirection && (c = S.cameraDirection), W();
438
438
  };
439
439
  }).toString()})();`;
440
440
  }
441
441
  }
442
- const dt = (k, t) => {
443
- const r = Math.max(
444
- 0,
445
- Math.min(65535, Math.round((k + 1) / 2 * 65535))
446
- ), e = Math.max(
447
- 0,
448
- Math.min(65535, Math.round((t + 1) / 2 * 65535))
449
- );
450
- return r << 16 | e;
451
- }, ft = new ArrayBuffer(4), ot = new DataView(ft), pt = (k) => (ot.setUint32(0, k, !0), ot.getFloat32(0, !0));
452
- class mt {
442
+ const ft = (A, t) => {
443
+ const n = nt(A), e = nt(t);
444
+ return n | e << 16;
445
+ };
446
+ function nt(A) {
447
+ const t = new Float32Array([A]), e = new Int32Array(t.buffer)[0];
448
+ let r = e >> 16 & 32768, s = e >> 12 & 2047;
449
+ const o = e >> 23 & 255;
450
+ return o < 103 ? r : o > 142 ? (r |= 31744, r |= (o === 255 ? 0 : 1) && e & 8388607, r) : o < 113 ? (s |= 2048, r |= (s >> 114 - o) + (s >> 113 - o & 1), r) : (r |= o - 112 << 10 | s >> 1, r += s & 1, r);
451
+ }
452
+ const pt = new ArrayBuffer(4), ot = new DataView(pt), mt = (A) => (ot.setUint32(0, A, !0), ot.getFloat32(0, !0));
453
+ class xt {
453
454
  /**
454
455
  * Create a new TextureManager for a set of splats
455
456
  * @param splatData The splat data to manage textures for
@@ -464,8 +465,8 @@ class mt {
464
465
  f(this, "orderTexture");
465
466
  f(this, "textureWidth");
466
467
  f(this, "textureHeight");
467
- const r = t.numSplats;
468
- this.textureWidth = Math.ceil(Math.sqrt(r)), this.textureHeight = Math.ceil(r / this.textureWidth), this.transformA = this.createTransformATexture(t), this.transformB = this.createTransformBTexture(t), this.colorTexture = this.createColorTexture(t), this.orderTexture = this.createOrderTexture(r);
468
+ const n = t.numSplats;
469
+ this.textureWidth = Math.ceil(Math.sqrt(n)), this.textureHeight = Math.ceil(n / this.textureWidth), this.transformA = this.createTransformATexture(t), this.transformB = this.createTransformBTexture(t), this.colorTexture = this.createColorTexture(t), this.orderTexture = this.createOrderTexture(n);
469
470
  }
470
471
  /**
471
472
  * Create the transform A texture (positions and quaternion w component)
@@ -473,24 +474,24 @@ class mt {
473
474
  * @returns DataTexture containing position data
474
475
  */
475
476
  createTransformATexture(t) {
476
- const r = t.numSplats, e = new Float32Array(
477
+ const n = t.numSplats, e = new Float32Array(
477
478
  this.textureWidth * this.textureHeight * 4
478
479
  );
479
- for (let s = 0; s < r; s++) {
480
- const i = s * 4, a = s * 3, c = s * 4;
481
- e[i] = t.positions[a], e[i + 1] = t.positions[a + 1], e[i + 2] = t.positions[a + 2];
482
- const h = t.rotations[c + 1], v = t.rotations[c + 2], g = dt(h, v);
483
- e[i + 3] = pt(g);
480
+ for (let s = 0; s < n; s++) {
481
+ const o = s * 4, a = s * 3, c = s * 4;
482
+ e[o] = t.positions[a], e[o + 1] = t.positions[a + 1], e[o + 2] = t.positions[a + 2];
483
+ const h = t.rotations[c + 0], v = t.rotations[c + 1], y = ft(h, v);
484
+ e[o + 3] = mt(y);
484
485
  }
485
- const o = new n.DataTexture(
486
+ const r = new i.DataTexture(
486
487
  e,
487
488
  this.textureWidth,
488
489
  this.textureHeight,
489
- n.RGBAFormat,
490
- n.FloatType
490
+ i.RGBAFormat,
491
+ i.FloatType
491
492
  // Store as Float32, shader will reinterpret bits
492
493
  );
493
- return o.needsUpdate = !0, o.magFilter = n.NearestFilter, o.minFilter = n.NearestFilter, o;
494
+ return r.needsUpdate = !0, r.magFilter = i.NearestFilter, r.minFilter = i.NearestFilter, r;
494
495
  }
495
496
  /**
496
497
  * Create the transform B texture (scale and rotation xyz)
@@ -498,21 +499,21 @@ class mt {
498
499
  * @returns DataTexture containing scale and rotation data
499
500
  */
500
501
  createTransformBTexture(t) {
501
- const r = t.numSplats, e = new Float32Array(
502
+ const n = t.numSplats, e = new Float32Array(
502
503
  this.textureWidth * this.textureHeight * 4
503
504
  );
504
- for (let s = 0; s < r; s++) {
505
- const i = s * 4, a = s * 3, c = s * 4;
506
- e[i] = t.scales[a], e[i + 1] = t.scales[a + 1], e[i + 2] = t.scales[a + 2], e[i + 3] = t.rotations[c];
505
+ for (let s = 0; s < n; s++) {
506
+ const o = s * 4, a = s * 3, c = s * 4;
507
+ e[o] = t.scales[a], e[o + 1] = t.scales[a + 1], e[o + 2] = t.scales[a + 2], e[o + 3] = t.rotations[c + 2];
507
508
  }
508
- const o = new n.DataTexture(
509
+ const r = new i.DataTexture(
509
510
  e,
510
511
  this.textureWidth,
511
512
  this.textureHeight,
512
- n.RGBAFormat,
513
- n.FloatType
513
+ i.RGBAFormat,
514
+ i.FloatType
514
515
  );
515
- return o.needsUpdate = !0, o.magFilter = n.NearestFilter, o.minFilter = n.NearestFilter, o;
516
+ return r.needsUpdate = !0, r.magFilter = i.NearestFilter, r.minFilter = i.NearestFilter, r;
516
517
  }
517
518
  /**
518
519
  * Create the color texture (RGB and opacity)
@@ -520,21 +521,21 @@ class mt {
520
521
  * @returns DataTexture containing color data
521
522
  */
522
523
  createColorTexture(t) {
523
- const r = t.numSplats, e = new Float32Array(
524
+ const n = t.numSplats, e = new Float32Array(
524
525
  this.textureWidth * this.textureHeight * 4
525
526
  );
526
- for (let s = 0; s < r; s++) {
527
- const i = s * 4, a = s * 3;
528
- e[i] = t.colors[a], e[i + 1] = t.colors[a + 1], e[i + 2] = t.colors[a + 2], e[i + 3] = t.opacities[s];
527
+ for (let s = 0; s < n; s++) {
528
+ const o = s * 4, a = s * 3;
529
+ e[o] = t.colors[a], e[o + 1] = t.colors[a + 1], e[o + 2] = t.colors[a + 2], e[o + 3] = t.opacities[s];
529
530
  }
530
- const o = new n.DataTexture(
531
+ const r = new i.DataTexture(
531
532
  e,
532
533
  this.textureWidth,
533
534
  this.textureHeight,
534
- n.RGBAFormat,
535
- n.FloatType
535
+ i.RGBAFormat,
536
+ i.FloatType
536
537
  );
537
- return o.needsUpdate = !0, o;
538
+ return r.needsUpdate = !0, r;
538
539
  }
539
540
  /**
540
541
  * Create the order texture for sorting
@@ -542,15 +543,15 @@ class mt {
542
543
  * @returns DataTexture for storing order indices
543
544
  */
544
545
  createOrderTexture(t) {
545
- const r = new Uint32Array(this.textureWidth * this.textureHeight);
546
- for (let o = 0; o < t; o++)
547
- r[o] = o;
548
- const e = new n.DataTexture(
549
- r,
546
+ const n = new Uint32Array(this.textureWidth * this.textureHeight);
547
+ for (let r = 0; r < t; r++)
548
+ n[r] = r;
549
+ const e = new i.DataTexture(
550
+ n,
550
551
  this.textureWidth,
551
552
  this.textureHeight,
552
- n.RedIntegerFormat,
553
- n.UnsignedIntType
553
+ i.RedIntegerFormat,
554
+ i.UnsignedIntType
554
555
  );
555
556
  return e.needsUpdate = !0, e;
556
557
  }
@@ -558,7 +559,7 @@ class mt {
558
559
  this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
559
560
  }
560
561
  }
561
- const xt = (
562
+ const gt = (
562
563
  /* glsl */
563
564
  `
564
565
  precision highp float;
@@ -596,61 +597,53 @@ varying vec2 vUv; // For gaussian calculation in fragment shader
596
597
 
597
598
  // --- Helper Functions ---
598
599
 
599
- // Unpack two 16-bit floats (halfs) from a single 32-bit float (packed as uint bits)
600
- vec2 unpackHalf2x16FromFloat(float packedFloat) {
601
- uint packedUInt = floatBitsToUint(packedFloat);
602
- uint y_bits = packedUInt >> 16;
603
- uint z_bits = packedUInt & uint(0xFFFF);
604
-
605
- // NOTE: This assumes packing used "packNormalizedFloatToUint16Pair"
606
- // which maps [-1, 1] to [0, 65535]. Adjust if packing method changes.
607
- float y = (float(y_bits) / 65535.0) * 2.0 - 1.0;
608
- float z = (float(z_bits) / 65535.0) * 2.0 - 1.0;
609
- return vec2(y, z);
610
- }
600
+ // Use GLSL built-in unpackHalf2x16 for proper half-float unpacking
611
601
 
612
- // Reconstruct quaternion from packed components (x, yz_packed)
613
- vec4 unpackRotation(float yz_packed, float x) {
614
- vec2 yz = unpackHalf2x16FromFloat(yz_packed);
615
- float y = yz.x;
616
- float z = yz.y;
602
+ // Reconstruct quaternion from packed components (xy_packed, z)
603
+ // Returns (w,x,y,z) format for quatToMat3 compatibility
604
+ vec4 unpackRotation(float xy_packed, float z) {
605
+ vec2 xy = unpackHalf2x16(floatBitsToUint(xy_packed));
606
+ float x = xy.x;
607
+ float y = xy.y;
617
608
  float w_squared = 1.0 - x*x - y*y - z*z;
618
- float w = (w_squared < 0.0) ? 0.0 : sqrt(w_squared); // Calculate w
619
- return vec4(x, y, z, w);
609
+ float w = (w_squared < 0.0) ? 0.0 : sqrt(w_squared);
610
+ return vec4(w, x, y, z); // Return (w,x,y,z)
620
611
  }
621
612
 
622
613
  // Convert quaternion to 3x3 rotation matrix
623
- mat3 quatToMat3(vec4 q) {
624
- float x = q.x, y = q.y, z = q.z, w = q.w;
625
- float x2 = x + x, y2 = y + y, z2 = z + z;
626
- float xx = x * x2, xy = x * y2, xz = x * z2;
627
- float yy = y * y2, yz = y * z2, zz = z * z2;
628
- float wx = w * x2, wy = w * y2, wz = w * z2;
614
+ mat3 quatToMat3(vec4 R) {
615
+ vec4 R2 = R + R;
616
+ float X = R2.x * R.w;
617
+ vec4 Y = R2.y * R;
618
+ vec4 Z = R2.z * R;
619
+ float W = R2.w * R.w;
629
620
 
630
621
  return mat3(
631
- 1.0 - (yy + zz), xy + wz, xz - wy,
632
- xy - wz, 1.0 - (xx + zz), yz + wx,
633
- xz + wy, yz - wx, 1.0 - (xx + yy)
622
+ 1.0 - Z.z - W,
623
+ Y.z + X,
624
+ Y.w - Z.x,
625
+ Y.z - X,
626
+ 1.0 - Y.y - W,
627
+ Z.w + Y.x,
628
+ Y.w + Z.x,
629
+ Z.w - Y.x,
630
+ 1.0 - Y.y - Z.z
634
631
  );
635
632
  }
636
633
 
637
- // Calculate model-space covariance components R * S^2 * transpose(R)
634
+ // Calculate model-space covariance components
638
635
  void getModelCovariance(vec3 scale, vec4 rotation, out vec3 covA, out vec3 covB) {
639
- mat3 R = quatToMat3(rotation);
640
-
641
- // Define M = R * S (where S is the diagonal scale matrix)
642
- // Note R is column-major, so R[0] is the first column, etc.
643
- // We want M's rows to be R's rows scaled by the corresponding scale factor.
644
- mat3 M = mat3(
645
- R[0][0] * scale.x, R[0][1] * scale.y, R[0][2] * scale.z, // Row 0 = (R_row0 * S)
646
- R[1][0] * scale.x, R[1][1] * scale.y, R[1][2] * scale.z, // Row 1 = (R_row1 * S)
647
- R[2][0] * scale.x, R[2][1] * scale.y, R[2][2] * scale.z // Row 2 = (R_row2 * S)
648
- );
636
+ mat3 rot = quatToMat3(rotation);
637
+
638
+ // M = S * R (scale COLUMNS, then transpose)
639
+ mat3 M = transpose(mat3(
640
+ scale.x * rot[0], // scale.x * column 0
641
+ scale.y * rot[1], // scale.y * column 1
642
+ scale.z * rot[2] // scale.z * column 2
643
+ ));
649
644
 
650
- // Now compute Vrk = M * transpose(M)
651
- // Vrk[i][j] = dot(M[i], M[j]) where M[i] is the i-th row vector of M.
652
- covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2])); // Vrk[0][0], Vrk[0][1], Vrk[0][2]
653
- covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2])); // Vrk[1][1], Vrk[1][2], Vrk[2][2]
645
+ covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));
646
+ covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));
654
647
  }
655
648
 
656
649
  // --- Main Function ---
@@ -679,7 +672,7 @@ void main(void) {
679
672
 
680
673
  vec3 splatPosition = texTransformA.xyz;
681
674
  vec3 splatLogScale = texTransformB.xyz; // Assume stored as log scale
682
- vec4 splatRotation = unpackRotation(texTransformA.w, texTransformB.w); // Unpack rot yz, x
675
+ vec4 splatRotation = unpackRotation(texTransformA.w, texTransformB.w); // Unpack rot xy, z
683
676
  vec3 splatColor = texColor.rgb;
684
677
  float splatOpacity = texColor.a;
685
678
 
@@ -805,7 +798,6 @@ void main(void) {
805
798
  // Apply clip to the corner offset *before* calculating screen space offset
806
799
  vec2 clippedCornerOffset = cornerOffset * clip;
807
800
  vec2 screenOffsetPixels = clippedCornerOffset.x * v1_scaled + clippedCornerOffset.y * v2_scaled;
808
- //vec2 screenOffsetPixels = vec2(clippedCornerOffset.x, clippedCornerOffset.y);
809
801
 
810
802
  // Convert pixel offset to clip space offset
811
803
  vec2 clipOffset = screenOffsetPixels * (centerClip.w / viewport);
@@ -846,56 +838,56 @@ void main(void) {
846
838
  }
847
839
  `
848
840
  );
849
- class gt extends n.ShaderMaterial {
841
+ class vt extends i.ShaderMaterial {
850
842
  constructor(t = {}) {
851
- const r = {
843
+ const n = {
852
844
  // Textures (values set via methods)
853
845
  transformA: { value: null },
854
846
  transformB: { value: null },
855
847
  splatColor: { value: null },
856
848
  splatOrder: { value: null },
857
849
  // Other uniforms
858
- viewport: { value: new n.Vector2(1, 1) },
850
+ viewport: { value: new i.Vector2(1, 1) },
859
851
  // Will be updated
860
852
  numSplats: { value: 0 }
861
853
  // Max splats to render (updated by sorter)
862
854
  };
863
855
  super({
864
- vertexShader: xt,
856
+ vertexShader: gt,
865
857
  fragmentShader: yt,
866
- uniforms: r,
858
+ uniforms: n,
867
859
  transparent: !0,
868
- blending: n.CustomBlending,
860
+ blending: i.CustomBlending,
869
861
  // Premultiplied alpha blending:
870
862
  // color = src_color * src_alpha + dst_color * (1 - src_alpha)
871
863
  // alpha = src_alpha * 1 + dst_alpha * (1 - src_alpha)
872
- blendSrc: n.OneFactor,
864
+ blendSrc: i.OneFactor,
873
865
  // Using ONE because shader outputs premultiplied color (color * alpha)
874
- blendDst: n.OneMinusSrcAlphaFactor,
875
- blendSrcAlpha: n.OneFactor,
866
+ blendDst: i.OneMinusSrcAlphaFactor,
867
+ blendSrcAlpha: i.OneFactor,
876
868
  // source alpha comes from shader
877
- blendDstAlpha: n.OneMinusSrcAlphaFactor,
878
- blendEquation: n.AddEquation,
879
- blendEquationAlpha: n.AddEquation,
869
+ blendDstAlpha: i.OneMinusSrcAlphaFactor,
870
+ blendEquation: i.AddEquation,
871
+ blendEquationAlpha: i.AddEquation,
880
872
  depthTest: !0,
881
873
  depthWrite: !1,
882
874
  // Disable depth write for transparency
883
- side: n.DoubleSide,
875
+ side: i.DoubleSide,
884
876
  // Render both sides (or CULLFACE_NONE equivalent)
885
877
  // Optional settings from constructor
886
878
  alphaTest: t.alphaTest !== void 0 ? t.alphaTest : 0,
887
879
  // Typically 0 for blending
888
880
  toneMapped: t.toneMapped !== void 0 ? t.toneMapped : !1
889
881
  // prettier-ignore
890
- }), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = n.NoBlending);
882
+ }), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = i.NoBlending);
891
883
  }
892
884
  /**
893
885
  * Update the viewport size
894
886
  * @param width Viewport width
895
887
  * @param height Viewport height
896
888
  */
897
- updateViewport(t, r) {
898
- this.uniforms.viewport.value.set(t, r);
889
+ updateViewport(t, n) {
890
+ this.uniforms.viewport.value.set(t, n);
899
891
  }
900
892
  /**
901
893
  * Set transform texture A (positions)
@@ -933,38 +925,38 @@ class gt extends n.ShaderMaterial {
933
925
  this.uniforms.numSplats.value = t;
934
926
  }
935
927
  }
936
- const Y = class Y extends n.Mesh {
928
+ const j = class j extends i.Mesh {
937
929
  // Match shader constant
938
930
  /**
939
931
  * Create a new SplatMesh for rendering Gaussian splats
940
932
  * @param splatData The splat data to render
941
933
  * @param options Rendering options
942
934
  */
943
- constructor(r, e = {}) {
944
- const o = new gt(e), s = Y.createInstancedGeometry(r.numSplats, Y.INSTANCE_SIZE);
945
- super(s, o);
935
+ constructor(n, e = {}) {
936
+ const r = new vt(e), s = j.createInstancedGeometry(n.numSplats, j.INSTANCE_SIZE);
937
+ super(s, r);
946
938
  f(this, "sorter");
947
939
  f(this, "splatData");
948
940
  f(this, "options");
949
941
  f(this, "textureManager");
950
942
  f(this, "material");
951
943
  f(this, "geometry");
952
- f(this, "lastCameraPositionLocal", new n.Vector3());
953
- f(this, "lastCameraDirectionLocal", new n.Vector3());
954
- f(this, "invModelMatrix", new n.Matrix4());
955
- this.geometry = s, this.material = o, this.splatData = r, this.frustumCulled = !1, this.options = { autoSort: !0, ...e }, this.textureManager = new mt(r), this.sorter = new ut();
956
- let i = this.createChunks() || void 0;
957
- i === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), i = void 0, this.sorter.init(
944
+ f(this, "lastCameraPositionLocal", new i.Vector3());
945
+ f(this, "lastCameraDirectionLocal", new i.Vector3());
946
+ f(this, "invModelMatrix", new i.Matrix4());
947
+ this.geometry = s, this.material = r, this.splatData = n, this.frustumCulled = !1, this.options = { autoSort: !0, ...e }, this.textureManager = new xt(n), this.sorter = new dt();
948
+ let o = this.createChunks() || void 0;
949
+ o === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), o = void 0, this.sorter.init(
958
950
  this.textureManager.orderTexture,
959
951
  this.splatData.centers,
960
- i ?? void 0
952
+ o ?? void 0
961
953
  ), this.sorter.addEventListener(
962
954
  "updated",
963
955
  (a) => {
964
956
  const c = a.count;
965
- this.geometry.instanceCount = Math.ceil(c / Y.INSTANCE_SIZE), this.material.setNumSplats(c);
957
+ this.geometry.instanceCount = Math.ceil(c / j.INSTANCE_SIZE), this.material.setNumSplats(c);
966
958
  }
967
- ), 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 = r.boundingBox.toBox3(), this.geometry.boundingSphere = new n.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
959
+ ), 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 = n.boundingBox.toBox3(), this.geometry.boundingSphere = new i.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
968
960
  }
969
961
  /**
970
962
  * Creates the instanced geometry for rendering splats.
@@ -972,8 +964,8 @@ const Y = class Y extends n.Mesh {
972
964
  * @param instanceSize Number of splats per instance.
973
965
  * @returns InstancedBufferGeometry
974
966
  */
975
- static createInstancedGeometry(r, e) {
976
- const o = Math.ceil(r / e), s = new n.BufferGeometry(), i = new Float32Array([
967
+ static createInstancedGeometry(n, e) {
968
+ const r = Math.ceil(n / e), s = new i.BufferGeometry(), o = new Float32Array([
977
969
  // x, y, splat_index_in_instance
978
970
  -1,
979
971
  -1,
@@ -991,34 +983,34 @@ const Y = class Y extends n.Mesh {
991
983
  for (let p = 0; p < e; p++) {
992
984
  const u = p * 4 * 3;
993
985
  for (let l = 0; l < 4; l++)
994
- c[u + l * 3 + 0] = i[l * 3 + 0], c[u + l * 3 + 1] = i[l * 3 + 1], c[u + l * 3 + 2] = p;
986
+ c[u + l * 3 + 0] = o[l * 3 + 0], c[u + l * 3 + 1] = o[l * 3 + 1], c[u + l * 3 + 2] = p;
995
987
  }
996
988
  const h = new Uint32Array(6 * e);
997
989
  for (let p = 0; p < e; p++) {
998
990
  const u = p * 6, l = p * 4;
999
991
  h[u + 0] = a[0] + l, h[u + 1] = a[1] + l, h[u + 2] = a[2] + l, h[u + 3] = a[3] + l, h[u + 4] = a[4] + l, h[u + 5] = a[5] + l;
1000
992
  }
1001
- s.setAttribute("position", new n.BufferAttribute(c, 3)), s.setIndex(new n.BufferAttribute(h, 1));
1002
- const v = new n.InstancedBufferGeometry();
993
+ s.setAttribute("position", new i.BufferAttribute(c, 3)), s.setIndex(new i.BufferAttribute(h, 1));
994
+ const v = new i.InstancedBufferGeometry();
1003
995
  v.index = s.index, v.setAttribute("position", s.getAttribute("position"));
1004
- const g = new Uint32Array(o);
1005
- for (let p = 0; p < o; p++)
1006
- g[p] = p * e;
1007
- return v.setAttribute("splatInstanceIndex", new n.InstancedBufferAttribute(g, 1, !1)), v.instanceCount = 0, v;
996
+ const y = new Uint32Array(r);
997
+ for (let p = 0; p < r; p++)
998
+ y[p] = p * e;
999
+ return v.setAttribute("splatInstanceIndex", new i.InstancedBufferAttribute(y, 1, !1)), v.instanceCount = 0, v;
1008
1000
  }
1009
1001
  /**
1010
1002
  * Create chunks data (bounding box min/max) for the sorter.
1011
1003
  * @returns Float32Array containing chunk data [minX, minY, minZ, maxX, maxY, maxZ] or null.
1012
1004
  */
1013
1005
  createChunks() {
1014
- const r = this.splatData.boundingBox;
1015
- return r.min.x === 1 / 0 || r.max.x === -1 / 0 ? null : new Float32Array([
1016
- r.min.x,
1017
- r.min.y,
1018
- r.min.z,
1019
- r.max.x,
1020
- r.max.y,
1021
- r.max.z
1006
+ const n = this.splatData.boundingBox;
1007
+ return n.min.x === 1 / 0 || n.max.x === -1 / 0 ? null : new Float32Array([
1008
+ n.min.x,
1009
+ n.min.y,
1010
+ n.min.z,
1011
+ n.max.x,
1012
+ n.max.y,
1013
+ n.max.z
1022
1014
  ]);
1023
1015
  }
1024
1016
  /**
@@ -1026,18 +1018,18 @@ const Y = class Y extends n.Mesh {
1026
1018
  * @param width Viewport width
1027
1019
  * @param height Viewport height
1028
1020
  */
1029
- updateViewport(r, e) {
1030
- this.material.updateViewport(r, e);
1021
+ updateViewport(n, e) {
1022
+ this.material.updateViewport(n, e);
1031
1023
  }
1032
1024
  /**
1033
1025
  * Sorts splats based on camera position and direction.
1034
1026
  * @param camera The camera to sort against.
1035
1027
  */
1036
- sort(r) {
1037
- const e = new n.Vector3(), o = new n.Vector3();
1038
- r.getWorldPosition(e), r.getWorldDirection(o), this.invModelMatrix.copy(this.matrixWorld).invert();
1039
- const s = e.applyMatrix4(this.invModelMatrix), i = o.transformDirection(this.invModelMatrix), a = this.lastCameraPositionLocal.distanceToSquared(s) > 1e-6, c = this.lastCameraDirectionLocal.dot(i) < 0.999;
1040
- this.options.autoSort && (a || c) && (this.lastCameraPositionLocal.copy(s), this.lastCameraDirectionLocal.copy(i), this.sorter.setCamera(s, i));
1028
+ sort(n) {
1029
+ const e = new i.Vector3(), r = new i.Vector3();
1030
+ n.getWorldPosition(e), n.getWorldDirection(r), this.invModelMatrix.copy(this.matrixWorld).invert();
1031
+ const s = e.applyMatrix4(this.invModelMatrix), o = r.transformDirection(this.invModelMatrix), a = this.lastCameraPositionLocal.distanceToSquared(s) > 1e-6, c = this.lastCameraDirectionLocal.dot(o) < 0.999;
1032
+ this.options.autoSort && (a || c) && (this.lastCameraPositionLocal.copy(s), this.lastCameraDirectionLocal.copy(o), this.sorter.setCamera(s, o));
1041
1033
  }
1042
1034
  /**
1043
1035
  * THREE.js hook called before rendering the object.
@@ -1048,16 +1040,16 @@ const Y = class Y extends n.Mesh {
1048
1040
  */
1049
1041
  // prettier-ignore
1050
1042
  // @ts-expect-error scene is not used
1051
- onBeforeRender(r, e, o) {
1052
- this.sort(o);
1053
- const s = r.getSize(new n.Vector2());
1054
- let { width: i, height: a } = s;
1055
- const c = r.xr;
1043
+ onBeforeRender(n, e, r) {
1044
+ this.sort(r);
1045
+ const s = n.getSize(new i.Vector2());
1046
+ let { width: o, height: a } = s;
1047
+ const c = n.xr;
1056
1048
  if (c.enabled && c.isPresenting) {
1057
1049
  const h = c.getCamera().cameras[0].view;
1058
- h && (i = h.width, a = h.height);
1050
+ h && (o = h.width, a = h.height);
1059
1051
  }
1060
- this.updateViewport(i, a);
1052
+ this.updateViewport(o, a);
1061
1053
  }
1062
1054
  /**
1063
1055
  * Dispose of resources
@@ -1068,9 +1060,9 @@ const Y = class Y extends n.Mesh {
1068
1060
  };
1069
1061
  // Cached inverse matrix
1070
1062
  /** Number of splats combined into a single instanced draw call. */
1071
- f(Y, "INSTANCE_SIZE", 128);
1072
- let nt = Y;
1073
- class wt extends n.Loader {
1063
+ f(j, "INSTANCE_SIZE", 128);
1064
+ let it = j;
1065
+ class bt extends i.Loader {
1074
1066
  /**
1075
1067
  * Load a PLY file with Gaussian Splat data
1076
1068
  * @param url URL of the PLY file
@@ -1078,22 +1070,22 @@ class wt extends n.Loader {
1078
1070
  * @param onProgress Optional progress callback
1079
1071
  * @param onError Optional error callback
1080
1072
  */
1081
- load(t, r, e, o) {
1082
- const s = new n.FileLoader(this.manager);
1073
+ load(t, n, e, r) {
1074
+ const s = new i.FileLoader(this.manager);
1083
1075
  s.setResponseType("arraybuffer"), s.setRequestHeader(this.requestHeader), s.setPath(this.path), s.setWithCredentials(this.withCredentials), s.load(
1084
1076
  t,
1085
- (i) => {
1077
+ (o) => {
1086
1078
  try {
1087
- if (r) {
1088
- const a = this.parse(i);
1089
- r(a);
1079
+ if (n) {
1080
+ const a = this.parse(o);
1081
+ n(a);
1090
1082
  }
1091
1083
  } catch (a) {
1092
- o ? o(a) : console.error(a), this.manager.itemError(t);
1084
+ r ? r(a) : console.error(a), this.manager.itemError(t);
1093
1085
  }
1094
1086
  },
1095
1087
  e,
1096
- o
1088
+ r
1097
1089
  );
1098
1090
  }
1099
1091
  /**
@@ -1102,22 +1094,22 @@ class wt extends n.Loader {
1102
1094
  * @param onProgress Optional progress callback
1103
1095
  * @returns A Promise that resolves with the parsed SplatData
1104
1096
  */
1105
- loadAsync(t, r) {
1106
- return new Promise((e, o) => {
1107
- const s = new n.FileLoader(this.manager);
1097
+ loadAsync(t, n) {
1098
+ return new Promise((e, r) => {
1099
+ const s = new i.FileLoader(this.manager);
1108
1100
  s.setResponseType("arraybuffer"), s.setRequestHeader(this.requestHeader), s.setPath(this.path), s.setWithCredentials(this.withCredentials), s.load(
1109
1101
  t,
1110
- (i) => {
1102
+ (o) => {
1111
1103
  try {
1112
- const a = this.parse(i);
1104
+ const a = this.parse(o);
1113
1105
  e(a);
1114
1106
  } catch (a) {
1115
- o(a), this.manager.itemError(t);
1107
+ r(a), this.manager.itemError(t);
1116
1108
  }
1117
1109
  },
1118
- r,
1119
- (i) => {
1120
- o(i), this.manager.itemError(t);
1110
+ n,
1111
+ (o) => {
1112
+ r(o), this.manager.itemError(t);
1121
1113
  }
1122
1114
  );
1123
1115
  });
@@ -1128,44 +1120,44 @@ class wt extends n.Loader {
1128
1120
  * @returns Parsed SplatData
1129
1121
  */
1130
1122
  parse(t) {
1131
- const r = new TextDecoder(), e = new Uint8Array(t), o = [112, 108, 121, 10], s = `
1123
+ const n = new TextDecoder(), e = new Uint8Array(t), r = [112, 108, 121, 10], s = `
1132
1124
  end_header
1133
1125
  `;
1134
- for (let x = 0; x < o.length; x++)
1135
- if (e[x] !== o[x])
1126
+ for (let x = 0; x < r.length; x++)
1127
+ if (e[x] !== r[x])
1136
1128
  throw new Error("Invalid PLY file: Missing magic bytes");
1137
- let i = 0;
1129
+ let o = 0;
1138
1130
  for (let x = 0; x < e.length - s.length; x++) {
1139
1131
  let d = !0;
1140
- for (let C = 0; C < s.length; C++)
1141
- if (e[x + C] !== s.charCodeAt(C)) {
1132
+ for (let z = 0; z < s.length; z++)
1133
+ if (e[x + z] !== s.charCodeAt(z)) {
1142
1134
  d = !1;
1143
1135
  break;
1144
1136
  }
1145
1137
  if (d) {
1146
- i = x + s.length;
1138
+ o = x + s.length;
1147
1139
  break;
1148
1140
  }
1149
1141
  }
1150
- if (i === 0)
1142
+ if (o === 0)
1151
1143
  throw new Error("Invalid PLY file: Could not find end of header");
1152
- const c = r.decode(
1153
- e.slice(0, i)
1144
+ const c = n.decode(
1145
+ e.slice(0, o)
1154
1146
  ).split(`
1155
1147
  `), h = [];
1156
1148
  let v = null;
1157
1149
  for (let x = 1; x < c.length; x++) {
1158
1150
  const d = c[x].trim();
1159
1151
  if (d === "" || d === "end_header") continue;
1160
- const C = d.split(" ");
1161
- switch (C[0]) {
1152
+ const z = d.split(" ");
1153
+ switch (z[0]) {
1162
1154
  case "format":
1163
- v = C[1];
1155
+ v = z[1];
1164
1156
  break;
1165
1157
  case "element":
1166
1158
  h.push({
1167
- name: C[1],
1168
- count: parseInt(C[2], 10),
1159
+ name: z[1],
1160
+ count: parseInt(z[2], 10),
1169
1161
  properties: []
1170
1162
  });
1171
1163
  break;
@@ -1175,8 +1167,8 @@ end_header
1175
1167
  "Invalid PLY file: Property without element"
1176
1168
  );
1177
1169
  h[h.length - 1].properties.push({
1178
- type: C[1],
1179
- name: C[2],
1170
+ type: z[1],
1171
+ name: z[2],
1180
1172
  storage: null
1181
1173
  });
1182
1174
  break;
@@ -1184,17 +1176,17 @@ end_header
1184
1176
  }
1185
1177
  if (v !== "binary_little_endian")
1186
1178
  throw new Error(`Unsupported PLY format: ${v}`);
1187
- const g = h.find((x) => x.name === "vertex");
1188
- if (!g)
1179
+ const y = h.find((x) => x.name === "vertex");
1180
+ if (!y)
1189
1181
  throw new Error("Invalid PLY file: No vertex element found");
1190
- const p = new ht(g.count), u = new DataView(t);
1191
- let l = i;
1192
- const b = (x) => g.properties.findIndex((d) => d.name === x), A = b("x"), O = b("y"), q = b("z"), R = [
1182
+ const p = new ut(y.count), u = new DataView(t);
1183
+ let l = o;
1184
+ const b = (x) => y.properties.findIndex((d) => d.name === x), B = b("x"), O = b("y"), q = b("z"), E = [
1193
1185
  b("rot_0"),
1194
1186
  b("rot_1"),
1195
1187
  b("rot_2"),
1196
1188
  b("rot_3")
1197
- ], E = [
1189
+ ], R = [
1198
1190
  b("scale_0"),
1199
1191
  b("scale_1"),
1200
1192
  b("scale_2")
@@ -1204,98 +1196,97 @@ end_header
1204
1196
  b("f_dc_2")
1205
1197
  ], F = b("opacity");
1206
1198
  if ([
1207
- A,
1199
+ B,
1208
1200
  O,
1209
1201
  q,
1210
- ...R,
1211
1202
  ...E,
1203
+ ...R,
1212
1204
  ...W,
1213
1205
  F
1214
1206
  ].some((x) => x === -1))
1215
1207
  throw new Error("Invalid PLY file: Missing required properties");
1216
- const _ = 0.28209479177387814, M = (x) => {
1208
+ const D = 0.28209479177387814, M = (x) => {
1217
1209
  if (x > 0) return 1 / (1 + Math.exp(-x));
1218
1210
  const d = Math.exp(x);
1219
1211
  return d / (1 + d);
1220
- }, m = new n.Vector3(), B = new n.Quaternion(), P = new n.Vector3(), V = new n.Color();
1221
- for (let x = 0; x < g.count; x++) {
1212
+ }, m = new i.Vector3(), C = new i.Quaternion(), _ = new i.Vector3(), V = new i.Color();
1213
+ for (let x = 0; x < y.count; x++) {
1222
1214
  const d = [];
1223
- for (let I = 0; I < g.properties.length; I++) {
1224
- const Q = g.properties[I].type;
1225
- let S;
1226
- switch (Q) {
1215
+ for (let T = 0; T < y.properties.length; T++) {
1216
+ const K = y.properties[T].type;
1217
+ let I;
1218
+ switch (K) {
1227
1219
  case "char":
1228
- S = u.getInt8(l), l += 1;
1220
+ I = u.getInt8(l), l += 1;
1229
1221
  break;
1230
1222
  case "uchar":
1231
- S = u.getUint8(l), l += 1;
1223
+ I = u.getUint8(l), l += 1;
1232
1224
  break;
1233
1225
  case "short":
1234
- S = u.getInt16(l, !0), l += 2;
1226
+ I = u.getInt16(l, !0), l += 2;
1235
1227
  break;
1236
1228
  case "ushort":
1237
- S = u.getUint16(l, !0), l += 2;
1229
+ I = u.getUint16(l, !0), l += 2;
1238
1230
  break;
1239
1231
  case "int":
1240
- S = u.getInt32(l, !0), l += 4;
1232
+ I = u.getInt32(l, !0), l += 4;
1241
1233
  break;
1242
1234
  case "uint":
1243
- S = u.getUint32(l, !0), l += 4;
1235
+ I = u.getUint32(l, !0), l += 4;
1244
1236
  break;
1245
1237
  case "float":
1246
- S = u.getFloat32(l, !0), l += 4;
1238
+ I = u.getFloat32(l, !0), l += 4;
1247
1239
  break;
1248
1240
  case "double":
1249
- S = u.getFloat64(l, !0), l += 8;
1241
+ I = u.getFloat64(l, !0), l += 8;
1250
1242
  break;
1251
1243
  default:
1252
- throw new Error(`Unsupported property type: ${Q}`);
1244
+ throw new Error(`Unsupported property type: ${K}`);
1253
1245
  }
1254
- d.push(S);
1246
+ d.push(I);
1255
1247
  }
1256
1248
  m.set(
1257
- d[A],
1249
+ d[B],
1258
1250
  d[O],
1259
1251
  d[q]
1260
- ), B.set(
1261
- // TODO: dangerous see if true
1262
- d[R[1]],
1263
- // PLY stores rot 1,2,3,0 (x,y,z,w)
1264
- d[R[2]],
1265
- d[R[3]],
1266
- d[R[0]]
1267
- ).normalize(), P.set(
1268
- d[E[0]],
1269
- // Read directly assuming it's log scale
1252
+ ), C.set(
1270
1253
  d[E[1]],
1271
- d[E[2]]
1254
+ // PLY stores rot 1,2,3,0 (x,y,z,w)
1255
+ d[E[2]],
1256
+ d[E[3]],
1257
+ d[E[0]]
1258
+ ).normalize(), C.w < 0 && (C.x = -C.x, C.y = -C.y, C.z = -C.z, C.w = -C.w), _.set(
1259
+ d[R[0]],
1260
+ // Read directly assuming it's log scale
1261
+ d[R[1]],
1262
+ d[R[2]]
1272
1263
  ), V.set(
1273
- 0.5 + d[W[0]] * _,
1274
- 0.5 + d[W[1]] * _,
1275
- 0.5 + d[W[2]] * _
1264
+ 0.5 + d[W[0]] * D,
1265
+ 0.5 + d[W[1]] * D,
1266
+ 0.5 + d[W[2]] * D
1276
1267
  ), V.r = Math.max(0, Math.min(1, V.r)), V.g = Math.max(0, Math.min(1, V.g)), V.b = Math.max(0, Math.min(1, V.b));
1277
- const C = M(d[F]);
1268
+ const z = M(d[F]);
1278
1269
  p.setSplat(
1279
1270
  x,
1280
1271
  m,
1281
- B,
1282
- P,
1272
+ C,
1273
+ _,
1283
1274
  // Pass log scale directly
1284
1275
  V,
1285
- C
1276
+ z
1286
1277
  );
1287
1278
  }
1288
1279
  return p.calculateBoundingBox(), p;
1289
1280
  }
1290
1281
  }
1291
- const bt = "0.2.0";
1282
+ const Mt = "0.3.0";
1292
1283
  export {
1293
1284
  et as BoundingBox,
1294
- wt as PlyLoader,
1295
- ht as SplatData,
1296
- gt as SplatMaterial,
1297
- nt as SplatMesh,
1298
- ut as SplatSorter,
1299
- mt as TextureManager,
1300
- bt as VERSION
1285
+ bt as PlyLoader,
1286
+ ut as SplatData,
1287
+ vt as SplatMaterial,
1288
+ it as SplatMesh,
1289
+ dt as SplatSorter,
1290
+ xt as TextureManager,
1291
+ Mt as VERSION
1301
1292
  };