@speridlabs/visus 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.es.js CHANGED
@@ -1,14 +1,14 @@
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);
1
+ var le = Object.defineProperty;
2
+ var ue = (z, e, t) => e in z ? le(z, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : z[e] = t;
3
+ var p = (z, e, t) => ue(z, typeof e != "symbol" ? e + "" : e, t);
4
4
  import * as i from "three";
5
- class et {
5
+ class te {
6
6
  constructor() {
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());
7
+ p(this, "min", new i.Vector3(1 / 0, 1 / 0, 1 / 0));
8
+ p(this, "max", new i.Vector3(-1 / 0, -1 / 0, -1 / 0));
9
+ p(this, "center", new i.Vector3());
10
10
  /** Half extents (size/2) */
11
- f(this, "halfExtents", new i.Vector3());
11
+ p(this, "halfExtents", new i.Vector3());
12
12
  }
13
13
  /**
14
14
  * Reset the bounding box to its initial state
@@ -20,15 +20,15 @@ class et {
20
20
  * Expand the bounding box to include the given point
21
21
  * @param point Point to include in the bounding box
22
22
  */
23
- expandByPoint(t) {
24
- this.min.x = Math.min(this.min.x, t.x), this.min.y = Math.min(this.min.y, t.y), this.min.z = Math.min(this.min.z, t.z), this.max.x = Math.max(this.max.x, t.x), this.max.y = Math.max(this.max.y, t.y), this.max.z = Math.max(this.max.z, t.z), this.updateDerived();
23
+ expandByPoint(e) {
24
+ this.min.x = Math.min(this.min.x, e.x), this.min.y = Math.min(this.min.y, e.y), this.min.z = Math.min(this.min.z, e.z), this.max.x = Math.max(this.max.x, e.x), this.max.y = Math.max(this.max.y, e.y), this.max.z = Math.max(this.max.z, e.z), this.updateDerived();
25
25
  }
26
26
  /**
27
27
  * Expand this bounding box to include another bounding box
28
28
  * @param box Bounding box to include
29
29
  */
30
- expandByBox(t) {
31
- this.min.x = Math.min(this.min.x, t.min.x), this.min.y = Math.min(this.min.y, t.min.y), this.min.z = Math.min(this.min.z, t.min.z), this.max.x = Math.max(this.max.x, t.max.x), this.max.y = Math.max(this.max.y, t.max.y), this.max.z = Math.max(this.max.z, t.max.z), this.updateDerived();
30
+ expandByBox(e) {
31
+ this.min.x = Math.min(this.min.x, e.min.x), this.min.y = Math.min(this.min.y, e.min.y), this.min.z = Math.min(this.min.z, e.min.z), this.max.x = Math.max(this.max.x, e.max.x), this.max.y = Math.max(this.max.y, e.max.y), this.max.z = Math.max(this.max.z, e.max.z), this.updateDerived();
32
32
  }
33
33
  /**
34
34
  * Update the center and half extents based on min/max
@@ -41,8 +41,8 @@ class et {
41
41
  * @param point Point to check
42
42
  * @returns True if the point is inside the box
43
43
  */
44
- containsPoint(t) {
45
- return t.x >= this.min.x && t.x <= this.max.x && t.y >= this.min.y && t.y <= this.max.y && t.z >= this.min.z && t.z <= this.max.z;
44
+ containsPoint(e) {
45
+ return e.x >= this.min.x && e.x <= this.max.x && e.y >= this.min.y && e.y <= this.max.y && e.z >= this.min.z && e.z <= this.max.z;
46
46
  }
47
47
  /**
48
48
  * Create a Three.js Box3 from this bounding box
@@ -56,25 +56,25 @@ class et {
56
56
  * @returns New bounding box with the same values
57
57
  */
58
58
  clone() {
59
- const t = new et();
60
- return t.min.copy(this.min), t.max.copy(this.max), t.center.copy(this.center), t.halfExtents.copy(this.halfExtents), t;
59
+ const e = new te();
60
+ return e.min.copy(this.min), e.max.copy(this.max), e.center.copy(this.center), e.halfExtents.copy(this.halfExtents), e;
61
61
  }
62
62
  }
63
- class ut {
63
+ class de {
64
64
  // TODO: there is no sh spherical harmonics
65
- constructor(t = 0) {
66
- f(this, "numSplats", 0);
67
- f(this, "positions");
68
- f(this, "rotations");
69
- f(this, "scales");
70
- f(this, "colors");
71
- f(this, "opacities");
72
- f(this, "centers");
73
- f(this, "boundingBox", new et());
74
- this.numSplats = t, this.allocateBuffers(t);
65
+ constructor(e = 0) {
66
+ p(this, "numSplats", 0);
67
+ p(this, "positions");
68
+ p(this, "rotations");
69
+ p(this, "scales");
70
+ p(this, "colors");
71
+ p(this, "opacities");
72
+ p(this, "centers");
73
+ p(this, "boundingBox", new te());
74
+ this.numSplats = e, this.allocateBuffers(e);
75
75
  }
76
- 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
+ allocateBuffers(e) {
77
+ this.positions = new Float32Array(e * 3), this.rotations = new Float32Array(e * 4), this.scales = new Float32Array(e * 3), this.colors = new Float32Array(e * 3), this.opacities = new Float32Array(e), this.centers = new Float32Array(e * 3);
78
78
  }
79
79
  /**
80
80
  * Set data for a specific splat
@@ -85,36 +85,36 @@ class ut {
85
85
  * @param color Color
86
86
  * @param opacity Opacity value
87
87
  */
88
- setSplat(t, n, e, r, s, o) {
89
- if (t >= this.numSplats)
88
+ setSplat(e, t, o, r, n, s) {
89
+ if (e >= this.numSplats)
90
90
  throw new Error(
91
- `Splat index out of bounds: ${t} >= ${this.numSplats}`
91
+ `Splat index out of bounds: ${e} >= ${this.numSplats}`
92
92
  );
93
- const a = t * 3, c = t * 4, h = t * 3, v = t * 3;
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;
93
+ const a = e * 3, c = e * 4, f = e * 3, m = e * 3;
94
+ this.positions[a] = t.x, this.positions[a + 1] = t.y, this.positions[a + 2] = t.z, this.rotations[c] = o.x, this.rotations[c + 1] = o.y, this.rotations[c + 2] = o.z, this.rotations[c + 3] = o.w, this.scales[f] = r.x, this.scales[f + 1] = r.y, this.scales[f + 2] = r.z, this.colors[m] = n.r, this.colors[m + 1] = n.g, this.colors[m + 2] = n.b, this.opacities[e] = s, this.centers[a] = t.x, this.centers[a + 1] = t.y, this.centers[a + 2] = t.z;
95
95
  }
96
96
  /**
97
97
  * Get a splat's data
98
98
  * @param index Splat index
99
99
  * @returns Object containing splat data (linear scale)
100
100
  */
101
- getSplat(t) {
102
- if (t >= this.numSplats)
101
+ getSplat(e) {
102
+ if (e >= this.numSplats)
103
103
  throw new Error(
104
- `Splat index out of bounds: ${t} >= ${this.numSplats}`
104
+ `Splat index out of bounds: ${e} >= ${this.numSplats}`
105
105
  );
106
- const n = t * 3, e = t * 4, r = t * 3, s = t * 3;
106
+ const t = e * 3, o = e * 4, r = e * 3, n = e * 3;
107
107
  return {
108
108
  position: new i.Vector3(
109
- this.positions[n],
110
- this.positions[n + 1],
111
- this.positions[n + 2]
109
+ this.positions[t],
110
+ this.positions[t + 1],
111
+ this.positions[t + 2]
112
112
  ),
113
113
  rotation: new i.Quaternion(
114
- this.rotations[e],
115
- this.rotations[e + 1],
116
- this.rotations[e + 2],
117
- this.rotations[e + 3]
114
+ this.rotations[o],
115
+ this.rotations[o + 1],
116
+ this.rotations[o + 2],
117
+ this.rotations[o + 3]
118
118
  ),
119
119
  // Convert log scale back to linear scale for external use
120
120
  scale: new i.Vector3(
@@ -123,11 +123,11 @@ class ut {
123
123
  Math.exp(this.scales[r + 2])
124
124
  ),
125
125
  color: new i.Color(
126
- this.colors[s],
127
- this.colors[s + 1],
128
- this.colors[s + 2]
126
+ this.colors[n],
127
+ this.colors[n + 1],
128
+ this.colors[n + 2]
129
129
  ),
130
- opacity: this.opacities[t]
130
+ opacity: this.opacities[e]
131
131
  };
132
132
  }
133
133
  /**
@@ -136,14 +136,14 @@ class ut {
136
136
  */
137
137
  calculateBoundingBox() {
138
138
  this.boundingBox.reset();
139
- const t = new i.Vector3();
140
- for (let n = 0; n < this.numSplats; n++) {
141
- const e = n * 3;
142
- t.set(
143
- this.positions[e],
144
- this.positions[e + 1],
145
- this.positions[e + 2]
146
- ), this.boundingBox.expandByPoint(t);
139
+ const e = new i.Vector3();
140
+ for (let t = 0; t < this.numSplats; t++) {
141
+ const o = t * 3;
142
+ e.set(
143
+ this.positions[o],
144
+ this.positions[o + 1],
145
+ this.positions[o + 2]
146
+ ), this.boundingBox.expandByPoint(e);
147
147
  }
148
148
  return this.boundingBox;
149
149
  }
@@ -152,64 +152,64 @@ class ut {
152
152
  * This is for visualization/debugging purposes only, not for rendering
153
153
  */
154
154
  createDebugGeometry() {
155
- const t = new i.BufferGeometry();
156
- t.setAttribute(
155
+ const e = new i.BufferGeometry();
156
+ e.setAttribute(
157
157
  "position",
158
158
  new i.BufferAttribute(this.positions, 3)
159
159
  );
160
- const n = new Float32Array(this.numSplats * 3), e = new i.Quaternion(), r = new i.Euler();
161
- for (let s = 0; s < this.numSplats; s++) {
162
- const o = s * 4, a = s * 3;
163
- e.set(
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;
160
+ const t = new Float32Array(this.numSplats * 3), o = new i.Quaternion(), r = new i.Euler();
161
+ for (let n = 0; n < this.numSplats; n++) {
162
+ const s = n * 4, a = n * 3;
163
+ o.set(
164
+ this.rotations[s],
165
+ this.rotations[s + 1],
166
+ this.rotations[s + 2],
167
+ this.rotations[s + 3]
168
+ ), r.setFromQuaternion(o), t[a] = r.x, t[a + 1] = r.y, t[a + 2] = r.z;
169
169
  }
170
- return t.setAttribute(
170
+ return e.setAttribute(
171
171
  "rotation",
172
- new i.BufferAttribute(n, 3)
173
- ), t.setAttribute(
172
+ new i.BufferAttribute(t, 3)
173
+ ), e.setAttribute(
174
174
  "scale",
175
175
  new i.BufferAttribute(this.scales, 3)
176
- ), t.setAttribute(
176
+ ), e.setAttribute(
177
177
  "color",
178
178
  new i.BufferAttribute(this.colors, 3)
179
- ), t.setAttribute(
179
+ ), e.setAttribute(
180
180
  "opacity",
181
181
  new i.BufferAttribute(this.opacities, 1)
182
- ), t;
182
+ ), e;
183
183
  }
184
184
  }
185
- class dt extends i.EventDispatcher {
185
+ class he extends i.EventDispatcher {
186
186
  constructor() {
187
187
  super();
188
- f(this, "worker");
189
- f(this, "centers", null);
190
- f(this, "orderTexture", null);
188
+ p(this, "worker");
189
+ p(this, "centers", null);
190
+ p(this, "orderTexture", null);
191
191
  /** Bounding box data for optimization */
192
- f(this, "chunks", null);
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
- this.worker = new Worker(URL.createObjectURL(e)), this.worker.onmessage = this.onWorkerMessage.bind(this);
192
+ p(this, "chunks", null);
193
+ p(this, "lastCameraPosition", new i.Vector3());
194
+ p(this, "lastCameraDirection", new i.Vector3());
195
+ const t = this.createWorkerCode(), o = new Blob([t], { type: "application/javascript" });
196
+ this.worker = new Worker(URL.createObjectURL(o)), 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(n) {
202
+ onWorkerMessage(t) {
203
203
  if (!this.orderTexture || !this.orderTexture.image)
204
204
  return console.error("SplatSorter: Order texture not initialized!");
205
- const { order: e, count: r } = n.data, s = this.orderTexture.image.data;
206
- if (!(s instanceof Uint32Array))
205
+ const { order: o, count: r } = t.data, n = this.orderTexture.image.data;
206
+ if (!(n instanceof Uint32Array))
207
207
  return console.error(
208
208
  "SplatSorter: Order texture data is not a Uint32Array!"
209
209
  );
210
- s.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
211
- const o = s.buffer.slice(0), a = { order: o };
212
- this.worker.postMessage(a, [o]), this.dispatchEvent({ type: "updated", count: r });
210
+ n.set(new Uint32Array(o)), this.orderTexture.needsUpdate = !0;
211
+ const s = n.buffer.slice(0), a = { order: s };
212
+ this.worker.postMessage(a, [s]), this.dispatchEvent({ type: "updated", count: r });
213
213
  }
214
214
  /**
215
215
  * Initializes the sorter with necessary data and textures.
@@ -217,84 +217,84 @@ class dt extends i.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(n, e, r) {
221
- if (!n || !(n.image.data instanceof Uint32Array))
220
+ init(t, o, r) {
221
+ if (!t || !(t.image.data instanceof Uint32Array))
222
222
  throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
223
- if (!e || e.length % 3 !== 0)
223
+ if (!o || o.length % 3 !== 0)
224
224
  throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");
225
- if (n.image.data.length < e.length / 3)
225
+ if (t.image.data.length < o.length / 3)
226
226
  throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
227
- const s = e.length / 3;
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;
227
+ const n = o.length / 3;
228
+ this.orderTexture = t, this.centers = o.slice();
229
+ const s = this.orderTexture.image.data;
230
+ for (let x = 0; x < n; x++) s[x] = x;
231
231
  this.orderTexture.needsUpdate = !0;
232
- const a = o.buffer.slice(0), c = this.centers.buffer.slice(0), h = {
232
+ const a = s.buffer.slice(0), c = this.centers.buffer.slice(0), f = {
233
233
  order: a,
234
234
  centers: c
235
- }, v = [
235
+ }, m = [
236
236
  a,
237
237
  c
238
238
  ];
239
239
  if (r) {
240
240
  this.chunks = r.slice();
241
- const y = this.chunks.buffer.slice(0);
242
- h.chunks = y, v.push(y);
241
+ const x = this.chunks.buffer.slice(0);
242
+ f.chunks = x, m.push(x);
243
243
  }
244
- this.worker.postMessage(h, v);
244
+ this.worker.postMessage(f, m);
245
245
  }
246
246
  /**
247
247
  * Applies an optional mapping to filter or reorder splats before sorting.
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(n) {
251
+ setMapping(t) {
252
252
  if (!this.centers)
253
253
  return console.warn(
254
254
  "SplatSorter: Cannot set mapping before initialization."
255
255
  );
256
- let e;
256
+ let o;
257
257
  const r = [];
258
- if (!n) {
258
+ if (!t) {
259
259
  const c = this.centers.buffer.slice(0);
260
- return e = {
260
+ return o = {
261
261
  centers: c,
262
262
  mapping: null
263
- }, r.push(c), this.worker.postMessage(e, r);
263
+ }, r.push(c), this.worker.postMessage(o, r);
264
264
  }
265
- const s = new Float32Array(n.length * 3);
266
- for (let c = 0; c < n.length; c++) {
267
- const h = n[c];
268
- if (h * 3 + 2 >= this.centers.length) {
265
+ const n = new Float32Array(t.length * 3);
266
+ for (let c = 0; c < t.length; c++) {
267
+ const f = t[c];
268
+ if (f * 3 + 2 >= this.centers.length) {
269
269
  console.warn(
270
- `SplatSorter: Mapping index ${h} out of bounds.`
270
+ `SplatSorter: Mapping index ${f} out of bounds.`
271
271
  );
272
272
  continue;
273
273
  }
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];
274
+ const m = f * 3, x = c * 3;
275
+ n[x + 0] = this.centers[m + 0], n[x + 1] = this.centers[m + 1], n[x + 2] = this.centers[m + 2];
276
276
  }
277
- const o = s.buffer.slice(0), a = n.buffer.slice(0);
278
- e = {
279
- centers: o,
277
+ const s = n.buffer.slice(0), a = t.buffer.slice(0);
278
+ o = {
279
+ centers: s,
280
280
  mapping: a
281
- }, r.push(o, a), this.worker.postMessage(e, r);
281
+ }, r.push(s, a), this.worker.postMessage(o, 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(n, e) {
289
- const r = this.lastCameraPosition.distanceToSquared(n) > 1e-7, s = this.lastCameraDirection.dot(e) < 0.9999;
290
- if (!r && !s)
288
+ setCamera(t, o) {
289
+ const r = this.lastCameraPosition.distanceToSquared(t) > 1e-7, n = this.lastCameraDirection.dot(o) < 0.9999;
290
+ if (!r && !n)
291
291
  return;
292
- this.lastCameraPosition.copy(n), this.lastCameraDirection.copy(e);
293
- const o = {
294
- cameraPosition: { x: n.x, y: n.y, z: n.z },
295
- cameraDirection: { x: e.x, y: e.y, z: e.z }
292
+ this.lastCameraPosition.copy(t), this.lastCameraDirection.copy(o);
293
+ const s = {
294
+ cameraPosition: { x: t.x, y: t.y, z: t.z },
295
+ cameraDirection: { x: o.x, y: o.y, z: o.z }
296
296
  };
297
- this.worker.postMessage(o);
297
+ this.worker.postMessage(s);
298
298
  }
299
299
  /**
300
300
  * Terminates the Web Worker and cleans up resources.
@@ -308,183 +308,183 @@ class dt extends i.EventDispatcher {
308
308
  */
309
309
  createWorkerCode() {
310
310
  return `(${(function() {
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
- let l = null, b = null;
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
- if (m > 0) F = M + 1;
318
- else if (m < 0) S = M - 1;
319
- else return M;
311
+ let o = null, r = null, n = null, s = null, a = null, c = null, f = !1;
312
+ const m = { x: 0, y: 0, z: 0 }, x = { x: 0, y: 0, z: 0 }, v = { x: 0, y: 0, z: 0 }, d = { x: 0, y: 0, z: 0 };
313
+ let S = null, u = null;
314
+ const M = 32, O = new Array(M).fill(0), H = new Array(M).fill(0), R = new Array(M).fill(0), P = (B, A, F) => {
315
+ for (; B <= A; ) {
316
+ const C = A + B >> 1, y = F(C);
317
+ if (y > 0) B = C + 1;
318
+ else if (y < 0) A = C - 1;
319
+ else return C;
320
320
  }
321
- return ~F;
321
+ return ~B;
322
322
  }, W = () => {
323
- if (!e || !r || !a || !c)
323
+ if (!o || !r || !a || !c)
324
324
  return;
325
325
  if (r.length === 0) {
326
326
  const g = {
327
- order: e.buffer,
327
+ order: o.buffer,
328
328
  count: 0
329
329
  };
330
- self.postMessage(g, [e.buffer]), e = null;
330
+ self.postMessage(g, [o.buffer]), o = null;
331
331
  return;
332
332
  }
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
- if (!h && !V && !x)
333
+ const B = a.x, A = a.y, F = a.z, C = c.x, y = c.y, _ = c.z, I = 1e-4, V = Math.abs(B - m.x) > I || Math.abs(A - m.y) > I || Math.abs(F - m.z) > I, E = Math.abs(C - x.x) > I || Math.abs(y - x.y) > I || Math.abs(_ - x.z) > I;
334
+ if (!f && !V && !E)
335
335
  return;
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;
336
+ f = !1, m.x = B, m.y = A, m.z = F, x.x = C, x.y = y, x.z = _;
337
+ let l = 1 / 0, h = -1 / 0;
338
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);
339
+ const T = g & 1 ? v.x : d.x, k = g & 2 ? v.y : d.y, b = g & 4 ? v.z : d.z, D = T * C + k * y + b * _;
340
+ l = Math.min(l, D), h = Math.max(h, D);
341
341
  }
342
- const T = r.length / 3, L = z - d, I = (1 << Math.max(
342
+ const w = r.length / 3, q = h - l, L = (1 << Math.max(
343
343
  10,
344
- Math.min(20, Math.ceil(Math.log2(T / 4)))
344
+ Math.min(20, Math.ceil(Math.log2(w / 4)))
345
345
  )) + 1;
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
- } else if (s && s.length > 0) {
350
- const g = s.length / 6;
346
+ if ((!S || S.length !== w) && (S = new Uint32Array(w)), !u || u.length !== L ? u = new Uint32Array(L) : u.fill(0), q < 1e-7) {
347
+ for (let g = 0; g < w; ++g) S[g] = 0;
348
+ u[0] = w;
349
+ } else if (n && n.length > 0) {
350
+ const g = n.length / 6;
351
351
  O.fill(0);
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(
352
+ for (let b = 0; b < g; ++b) {
353
+ const D = b * 6, Z = n[D + 0], X = n[D + 1], J = n[D + 2], Y = n[D + 3], G = Z * C + X * y + J * _ - l, K = G - Y, $ = G + Y, Q = Math.max(
354
354
  0,
355
- Math.floor(J * B / L)
356
- ), tt = Math.min(
357
- B,
358
- Math.ceil(X * B / L)
355
+ Math.floor(K * M / q)
356
+ ), ee = Math.min(
357
+ M,
358
+ Math.ceil($ * M / q)
359
359
  );
360
- for (let N = Q; N < tt; ++N)
361
- O[N]++;
360
+ for (let j = Q; j < ee; ++j)
361
+ O[j]++;
362
362
  }
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(
363
+ let T = 0;
364
+ for (let b = 0; b < M; ++b) T += O[b];
365
+ R[0] = 0, H[0] = 0;
366
+ for (let b = 1; b < M; ++b)
367
+ R[b - 1] = O[b - 1] / T * L >>> 0, H[b] = H[b - 1] + R[b - 1];
368
+ R[M - 1] = O[M - 1] / T * L >>> 0;
369
+ const k = q / M;
370
+ for (let b = 0; b < w; ++b) {
371
+ const D = b * 3, Z = r[D + 0], X = r[D + 1], J = r[D + 2], Y = Z * C + X * y + J * _, K = (h - Y) / k, $ = Math.max(
372
372
  0,
373
373
  Math.min(
374
- B - 1,
375
- Math.floor(J)
374
+ M - 1,
375
+ Math.floor(K)
376
376
  )
377
- ), Q = J - X, tt = q[X] + E[X] * Q >>> 0, N = Math.min(tt, I - 1);
378
- l[w] = N, b[N]++;
377
+ ), Q = K - $, ee = H[$] + R[$] * Q >>> 0, j = Math.min(ee, L - 1);
378
+ S[b] = j, u[j]++;
379
379
  }
380
380
  } else {
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]++;
381
+ const g = (L - 1) / q;
382
+ for (let T = 0; T < w; ++T) {
383
+ const k = T * 3, b = r[k + 0], D = r[k + 1], Z = r[k + 2], X = b * C + D * y + Z * _, Y = (h - X) * g >>> 0, G = Math.min(Y, L - 1);
384
+ S[T] = G, u[G]++;
385
385
  }
386
386
  }
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;
387
+ for (let g = 1; g < L; g++)
388
+ u[g] += u[g - 1];
389
+ for (let g = w - 1; g >= 0; g--) {
390
+ const T = S[g], k = --u[T];
391
+ o[k] = s ? s[g] : g;
392
392
  }
393
- const at = F * M + S * m + D * C, rt = (g) => {
394
- if (!e) return -1 / 0;
395
- const k = e[g], U = k;
396
- if (!r || U * 3 + 2 >= r.length)
393
+ const U = B * C + A * y + F * _, re = (g) => {
394
+ if (!o) return -1 / 0;
395
+ const T = o[g], k = T;
396
+ if (!r || k * 3 + 2 >= r.length)
397
397
  return -1 / 0;
398
- const w = U * 3;
399
- return r[w] * M + r[w + 1] * m + r[w + 2] * C - at;
398
+ const b = k * 3;
399
+ return r[b] * C + r[b + 1] * y + r[b + 2] * _ - U;
400
400
  };
401
- let st = T;
402
- if (T > 0 && rt(T - 1) < 0) {
403
- const g = R(
401
+ let oe = w;
402
+ if (w > 0 && re(w - 1) < 0) {
403
+ const g = P(
404
404
  0,
405
- T - 1,
406
- rt
405
+ w - 1,
406
+ re
407
407
  );
408
- st = g < 0 ? ~g : g;
408
+ oe = g < 0 ? ~g : g;
409
409
  }
410
- const ct = {
411
- order: e.buffer,
412
- count: st
410
+ const ce = {
411
+ order: o.buffer,
412
+ count: oe
413
413
  };
414
- self.postMessage(ct, [e.buffer]), e = null;
414
+ self.postMessage(ce, [o.buffer]), o = null;
415
415
  };
416
- self.onmessage = (F) => {
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
- for (let M = 0; M < s.length / 6; ++M) {
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
416
+ self.onmessage = (B) => {
417
+ const A = B.data;
418
+ A.order && (o = new Uint32Array(A.order));
419
+ let F = !1;
420
+ if (A.centers && (r = new Float32Array(A.centers), F = !0, f = !0), Object.prototype.hasOwnProperty.call(A, "mapping") && (s = A.mapping ? new Uint32Array(A.mapping) : null, f = !0), A.chunks) {
421
+ if (n = new Float32Array(A.chunks), n.length > 0 && n[3] > 0)
422
+ for (let C = 0; C < n.length / 6; ++C) {
423
+ const y = C * 6, _ = n[y + 0], I = n[y + 1], V = n[y + 2], E = n[y + 3], l = n[y + 4], h = n[y + 5];
424
+ n[y + 0] = (_ + E) * 0.5, n[y + 1] = (I + l) * 0.5, n[y + 2] = (V + h) * 0.5, n[y + 3] = Math.sqrt(
425
+ (E - _) ** 2 + (l - I) ** 2 + (h - V) ** 2
426
426
  ) * 0.5;
427
427
  }
428
- h = !0;
428
+ f = !0;
429
429
  }
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
- const m = M * 3;
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]);
430
+ if (F && r && r.length > 0) {
431
+ v.x = d.x = r[0], v.y = d.y = r[1], v.z = d.z = r[2];
432
+ for (let C = 1; C < r.length / 3; C++) {
433
+ const y = C * 3;
434
+ v.x = Math.min(v.x, r[y + 0]), d.x = Math.max(d.x, r[y + 0]), v.y = Math.min(v.y, r[y + 1]), d.y = Math.max(d.y, r[y + 1]), v.z = Math.min(v.z, r[y + 2]), d.z = Math.max(d.z, r[y + 2]);
435
435
  }
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();
436
+ } else F && r && r.length === 0 && (v.x = d.x = v.y = d.y = v.z = d.z = 0);
437
+ A.cameraPosition && (a = A.cameraPosition), A.cameraDirection && (c = A.cameraDirection), W();
438
438
  };
439
439
  }).toString()})();`;
440
440
  }
441
441
  }
442
- const ft = (A, t) => {
443
- const n = nt(A), e = nt(t);
444
- return n | e << 16;
442
+ const fe = (z, e) => {
443
+ const t = ne(z), o = ne(e);
444
+ return t | o << 16;
445
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);
446
+ function ne(z) {
447
+ const e = new Float32Array([z]), o = new Int32Array(e.buffer)[0];
448
+ let r = o >> 16 & 32768, n = o >> 12 & 2047;
449
+ const s = o >> 23 & 255;
450
+ return s < 103 ? r : s > 142 ? (r |= 31744, r |= (s === 255 ? 0 : 1) && o & 8388607, r) : s < 113 ? (n |= 2048, r |= (n >> 114 - s) + (n >> 113 - s & 1), r) : (r |= s - 112 << 10 | n >> 1, r += n & 1, r);
451
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 {
452
+ const pe = new ArrayBuffer(4), se = new DataView(pe), me = (z) => (se.setUint32(0, z, !0), se.getFloat32(0, !0));
453
+ class xe {
454
454
  /**
455
455
  * Create a new TextureManager for a set of splats
456
456
  * @param splatData The splat data to manage textures for
457
457
  */
458
- constructor(t) {
459
- f(this, "transformA");
458
+ constructor(e) {
459
+ p(this, "transformA");
460
460
  // position xyz and rotation quaternion y,z components
461
- f(this, "transformB");
461
+ p(this, "transformB");
462
462
  // rotation quaternion x and scale xyz
463
- f(this, "colorTexture");
463
+ p(this, "colorTexture");
464
464
  // color an opacity
465
- f(this, "orderTexture");
466
- f(this, "textureWidth");
467
- f(this, "textureHeight");
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);
465
+ p(this, "orderTexture");
466
+ p(this, "textureWidth");
467
+ p(this, "textureHeight");
468
+ const t = e.numSplats;
469
+ this.textureWidth = Math.ceil(Math.sqrt(t)), this.textureHeight = Math.ceil(t / this.textureWidth), this.transformA = this.createTransformATexture(e), this.transformB = this.createTransformBTexture(e), this.colorTexture = this.createColorTexture(e), this.orderTexture = this.createOrderTexture(t);
470
470
  }
471
471
  /**
472
472
  * Create the transform A texture (positions and quaternion w component)
473
473
  * @param splatData The splat data
474
474
  * @returns DataTexture containing position data
475
475
  */
476
- createTransformATexture(t) {
477
- const n = t.numSplats, e = new Float32Array(
476
+ createTransformATexture(e) {
477
+ const t = e.numSplats, o = new Float32Array(
478
478
  this.textureWidth * this.textureHeight * 4
479
479
  );
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);
480
+ for (let n = 0; n < t; n++) {
481
+ const s = n * 4, a = n * 3, c = n * 4;
482
+ o[s] = e.positions[a], o[s + 1] = e.positions[a + 1], o[s + 2] = e.positions[a + 2];
483
+ const f = e.rotations[c + 0], m = e.rotations[c + 1], x = fe(f, m);
484
+ o[s + 3] = me(x);
485
485
  }
486
486
  const r = new i.DataTexture(
487
- e,
487
+ o,
488
488
  this.textureWidth,
489
489
  this.textureHeight,
490
490
  i.RGBAFormat,
@@ -498,16 +498,16 @@ class xt {
498
498
  * @param splatData The splat data
499
499
  * @returns DataTexture containing scale and rotation data
500
500
  */
501
- createTransformBTexture(t) {
502
- const n = t.numSplats, e = new Float32Array(
501
+ createTransformBTexture(e) {
502
+ const t = e.numSplats, o = new Float32Array(
503
503
  this.textureWidth * this.textureHeight * 4
504
504
  );
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];
505
+ for (let n = 0; n < t; n++) {
506
+ const s = n * 4, a = n * 3, c = n * 4;
507
+ o[s] = e.scales[a], o[s + 1] = e.scales[a + 1], o[s + 2] = e.scales[a + 2], o[s + 3] = e.rotations[c + 2];
508
508
  }
509
509
  const r = new i.DataTexture(
510
- e,
510
+ o,
511
511
  this.textureWidth,
512
512
  this.textureHeight,
513
513
  i.RGBAFormat,
@@ -520,16 +520,16 @@ class xt {
520
520
  * @param splatData The splat data
521
521
  * @returns DataTexture containing color data
522
522
  */
523
- createColorTexture(t) {
524
- const n = t.numSplats, e = new Float32Array(
523
+ createColorTexture(e) {
524
+ const t = e.numSplats, o = new Float32Array(
525
525
  this.textureWidth * this.textureHeight * 4
526
526
  );
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];
527
+ for (let n = 0; n < t; n++) {
528
+ const s = n * 4, a = n * 3;
529
+ o[s] = e.colors[a], o[s + 1] = e.colors[a + 1], o[s + 2] = e.colors[a + 2], o[s + 3] = e.opacities[n];
530
530
  }
531
531
  const r = new i.DataTexture(
532
- e,
532
+ o,
533
533
  this.textureWidth,
534
534
  this.textureHeight,
535
535
  i.RGBAFormat,
@@ -542,24 +542,24 @@ class xt {
542
542
  * @param numSplats Number of splats
543
543
  * @returns DataTexture for storing order indices
544
544
  */
545
- createOrderTexture(t) {
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,
545
+ createOrderTexture(e) {
546
+ const t = new Uint32Array(this.textureWidth * this.textureHeight);
547
+ for (let r = 0; r < e; r++)
548
+ t[r] = r;
549
+ const o = new i.DataTexture(
550
+ t,
551
551
  this.textureWidth,
552
552
  this.textureHeight,
553
553
  i.RedIntegerFormat,
554
554
  i.UnsignedIntType
555
555
  );
556
- return e.needsUpdate = !0, e;
556
+ return o.needsUpdate = !0, o;
557
557
  }
558
558
  dispose() {
559
559
  this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
560
560
  }
561
561
  }
562
- const gt = (
562
+ const ge = (
563
563
  /* glsl */
564
564
  `
565
565
  precision highp float;
@@ -765,6 +765,10 @@ void main(void) {
765
765
  float l1 = sqrt(lambda1) * scaleFactor; // scaleX
766
766
  float l2 = sqrt(lambda2) * scaleFactor; // scaleY
767
767
 
768
+ float vmin = min(512.0, min(viewport.x, viewport.y));
769
+ l1 = min(l1, 2.0 * vmin);
770
+ l2 = min(l2, 2.0 * vmin);
771
+
768
772
  // Early out tiny splats
769
773
  if (l1 < 2.0 && l2 < 2.0) { // Check if smaller than ~2 pixel
770
774
  gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
@@ -775,14 +779,15 @@ void main(void) {
775
779
  vec2 v1_scaled = l1 * v1_eigen;
776
780
  vec2 v2_scaled = l2 * v2_eigen;
777
781
 
778
- // --- FRUSTUM CHECK ---
782
+ // --- FRUSTUM CHECK (laxo, estilo PlayCanvas) ---
779
783
 
780
- vec2 clipRadius = vec2(max(l1, l2)) * (centerClip.w / viewport);
784
+ vec2 c = centerClip.ww / viewport; // pixel to clip
785
+ float r = max(l1, l2); // radius in pixels
781
786
 
782
- // Check if the bounding circle's edge is outside the [-w, w] range in clip space for x or y
783
- if (any(greaterThan(abs(centerClip.xy) + clipRadius, vec2(abs(centerClip.w))))) {
784
- gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Off-screen
785
- return;
787
+ // Remove if the center - radius is already out of -w..w
788
+ if (any(greaterThan(abs(centerClip.xy) - vec2(r) * c, centerClip.ww))) {
789
+ gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
790
+ return;
786
791
  }
787
792
 
788
793
  // --- END FRUSTUM CHECK ---
@@ -812,7 +817,7 @@ void main(void) {
812
817
  vUv = clippedCornerOffset;
813
818
  }
814
819
  `
815
- ), yt = (
820
+ ), ye = (
816
821
  /* glsl */
817
822
  `
818
823
  precision highp float;
@@ -820,6 +825,14 @@ precision highp float;
820
825
  varying vec4 vColor; // Color and opacity passed from vertex shader
821
826
  varying vec2 vUv; // Quad UV coordinates (-1 to 1) passed from vertex shader
822
827
 
828
+ // Fast approximate e^x based on https://nic.schraudolph.org/pubs/Schraudolph99.pdf
829
+ const float EXP_A = 12102203.0; // ≈ 2^23 / ln(2)
830
+ const int EXP_BC_RMS = 1064866808; // (127 << 23) - 60801 * 8
831
+ float fastExp(float x) {
832
+ int i = int(EXP_A * x) + EXP_BC_RMS;
833
+ return intBitsToFloat(i);
834
+ }
835
+
823
836
  void main(void) {
824
837
 
825
838
  float distSq = dot(vUv, vUv); // Calculate squared distance from center (in the quad's coordinate system)
@@ -829,7 +842,7 @@ void main(void) {
829
842
  // The factor 4.0 corresponds to the original implementation's scaling.
830
843
  // factor = 1 / (2 * sigma^2), where sigma controls the spread.
831
844
  // Using 4.0 implies sigma^2 = 1/8.
832
- float alpha = exp(-distSq * 4.0) * vColor.a;
845
+ float alpha = fastExp(-distSq * 4.0) * vColor.a;
833
846
 
834
847
  if (alpha < 1.0 / 255.0) discard; // Discard fragments with very low alpha
835
848
 
@@ -838,9 +851,9 @@ void main(void) {
838
851
  }
839
852
  `
840
853
  );
841
- class vt extends i.ShaderMaterial {
842
- constructor(t = {}) {
843
- const n = {
854
+ class we extends i.ShaderMaterial {
855
+ constructor(e = {}) {
856
+ const t = {
844
857
  // Textures (values set via methods)
845
858
  transformA: { value: null },
846
859
  transformB: { value: null },
@@ -853,9 +866,9 @@ class vt extends i.ShaderMaterial {
853
866
  // Max splats to render (updated by sorter)
854
867
  };
855
868
  super({
856
- vertexShader: gt,
857
- fragmentShader: yt,
858
- uniforms: n,
869
+ vertexShader: ge,
870
+ fragmentShader: ye,
871
+ uniforms: t,
859
872
  transparent: !0,
860
873
  blending: i.CustomBlending,
861
874
  // Premultiplied alpha blending:
@@ -875,88 +888,109 @@ class vt extends i.ShaderMaterial {
875
888
  side: i.DoubleSide,
876
889
  // Render both sides (or CULLFACE_NONE equivalent)
877
890
  // Optional settings from constructor
878
- alphaTest: t.alphaTest !== void 0 ? t.alphaTest : 0,
891
+ alphaTest: e.alphaTest !== void 0 ? e.alphaTest : 0,
879
892
  // Typically 0 for blending
880
- toneMapped: t.toneMapped !== void 0 ? t.toneMapped : !1
893
+ toneMapped: e.toneMapped !== void 0 ? e.toneMapped : !1
881
894
  // prettier-ignore
882
- }), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = i.NoBlending);
895
+ }), e.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = i.NoBlending);
883
896
  }
884
897
  /**
885
898
  * Update the viewport size
886
899
  * @param width Viewport width
887
900
  * @param height Viewport height
888
901
  */
889
- updateViewport(t, n) {
890
- this.uniforms.viewport.value.set(t, n);
902
+ updateViewport(e, t) {
903
+ this.uniforms.viewport.value.set(e, t);
891
904
  }
892
905
  /**
893
906
  * Set transform texture A (positions)
894
907
  * @param texture Texture containing positions
895
908
  */
896
- setTransformA(t) {
897
- this.uniforms.transformA.value = t;
909
+ setTransformA(e) {
910
+ this.uniforms.transformA.value = e;
898
911
  }
899
912
  /**
900
913
  * Set transform texture B (rotation, scale)
901
914
  * @param texture Texture containing rotation and scale data
902
915
  */
903
- setTransformB(t) {
904
- this.uniforms.transformB.value = t;
916
+ setTransformB(e) {
917
+ this.uniforms.transformB.value = e;
905
918
  }
906
919
  /**
907
920
  * Set color texture
908
921
  * @param texture Texture containing colors
909
922
  */
910
- setColorTexture(t) {
911
- this.uniforms.splatColor.value = t;
923
+ setColorTexture(e) {
924
+ this.uniforms.splatColor.value = e;
912
925
  }
913
926
  /**
914
927
  * Set order texture
915
928
  * @param texture Texture containing sort order
916
929
  */
917
- setOrderTexture(t) {
918
- this.uniforms.splatOrder.value = t;
930
+ setOrderTexture(e) {
931
+ this.uniforms.splatOrder.value = e;
919
932
  }
920
933
  /**
921
934
  * Set number of splats to render
922
935
  * @param count Number of splats
923
936
  */
924
- setNumSplats(t) {
925
- this.uniforms.numSplats.value = t;
937
+ setNumSplats(e) {
938
+ this.uniforms.numSplats.value = e;
926
939
  }
927
940
  }
928
- const j = class j extends i.Mesh {
941
+ const N = class N extends i.Mesh {
929
942
  // Match shader constant
930
943
  /**
931
944
  * Create a new SplatMesh for rendering Gaussian splats
932
945
  * @param splatData The splat data to render
933
946
  * @param options Rendering options
934
947
  */
935
- constructor(n, e = {}) {
936
- const r = new vt(e), s = j.createInstancedGeometry(n.numSplats, j.INSTANCE_SIZE);
937
- super(s, r);
938
- f(this, "sorter");
939
- f(this, "splatData");
940
- f(this, "options");
941
- f(this, "textureManager");
942
- f(this, "material");
943
- f(this, "geometry");
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(
948
+ constructor(t, o = {}) {
949
+ const r = (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0;
950
+ r && console.debug(
951
+ "[1/8] MESH SplatMesh: creating mesh with",
952
+ t.numSplats,
953
+ "splats"
954
+ );
955
+ const n = new we(o), s = N.createInstancedGeometry(t.numSplats, N.INSTANCE_SIZE);
956
+ r && console.debug(
957
+ "[2/8] MESH SplatMesh: created instanced geometry with",
958
+ Math.ceil(t.numSplats / N.INSTANCE_SIZE),
959
+ "instances"
960
+ );
961
+ super(s, n);
962
+ p(this, "sorter");
963
+ p(this, "splatData");
964
+ p(this, "options");
965
+ p(this, "textureManager");
966
+ p(this, "material");
967
+ p(this, "geometry");
968
+ p(this, "lastCameraPositionLocal", new i.Vector3());
969
+ p(this, "lastCameraDirectionLocal", new i.Vector3());
970
+ p(this, "invModelMatrix", new i.Matrix4());
971
+ this.geometry = s, this.material = n, this.splatData = t, this.frustumCulled = !1, this.options = { autoSort: !0, ...o }, r && console.debug("[3/8] MESH SplatMesh: initializing texture manager"), this.textureManager = new xe(t), this.sorter = new he(), r && console.debug("[4/8] MESH SplatMesh: creating chunks for sorter");
972
+ let a = this.createChunks() || void 0;
973
+ a === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), a = void 0, r && console.debug(
974
+ "[5/8] MESH SplatMesh: initializing sorter with",
975
+ a ? "chunks" : "no chunks"
976
+ ), this.sorter.init(
950
977
  this.textureManager.orderTexture,
951
978
  this.splatData.centers,
952
- o ?? void 0
979
+ a ?? void 0
953
980
  ), this.sorter.addEventListener(
954
981
  "updated",
955
- (a) => {
956
- const c = a.count;
957
- this.geometry.instanceCount = Math.ceil(c / j.INSTANCE_SIZE), this.material.setNumSplats(c);
982
+ (c) => {
983
+ const f = c.count;
984
+ r && console.debug(
985
+ "[6/8] MESH SplatMesh: sorter updated, rendering",
986
+ f,
987
+ "splats"
988
+ ), this.geometry.instanceCount = Math.ceil(f / N.INSTANCE_SIZE), this.material.setNumSplats(f);
958
989
  }
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);
990
+ ), r && console.debug("[7/8] MESH SplatMesh: setting up material textures"), 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 = t.boundingBox.toBox3(), this.geometry.boundingSphere = new i.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere), r && console.debug(
991
+ "[8/8] MESH SplatMesh: mesh initialization complete, bounding box:",
992
+ t.boundingBox
993
+ );
960
994
  }
961
995
  /**
962
996
  * Creates the instanced geometry for rendering splats.
@@ -964,8 +998,16 @@ const j = class j extends i.Mesh {
964
998
  * @param instanceSize Number of splats per instance.
965
999
  * @returns InstancedBufferGeometry
966
1000
  */
967
- static createInstancedGeometry(n, e) {
968
- const r = Math.ceil(n / e), s = new i.BufferGeometry(), o = new Float32Array([
1001
+ static createInstancedGeometry(t, o) {
1002
+ const r = (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0, n = Math.ceil(t / o);
1003
+ r && console.debug(
1004
+ "MESH createInstancedGeometry: creating geometry for",
1005
+ t,
1006
+ "splats,",
1007
+ n,
1008
+ "instances"
1009
+ );
1010
+ const s = new i.BufferGeometry(), a = new Float32Array([
969
1011
  // x, y, splat_index_in_instance
970
1012
  -1,
971
1013
  -1,
@@ -979,57 +1021,79 @@ const j = class j extends i.Mesh {
979
1021
  -1,
980
1022
  1,
981
1023
  0
982
- ]), a = new Uint16Array([0, 1, 2, 0, 2, 3]), c = new Float32Array(4 * 3 * e);
983
- for (let p = 0; p < e; p++) {
984
- const u = p * 4 * 3;
985
- for (let l = 0; l < 4; l++)
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;
1024
+ ]), c = new Uint16Array([0, 1, 2, 0, 2, 3]), f = new Float32Array(4 * 3 * o);
1025
+ for (let d = 0; d < o; d++) {
1026
+ const S = d * 4 * 3;
1027
+ for (let u = 0; u < 4; u++)
1028
+ f[S + u * 3 + 0] = a[u * 3 + 0], f[S + u * 3 + 1] = a[u * 3 + 1], f[S + u * 3 + 2] = d;
987
1029
  }
988
- const h = new Uint32Array(6 * e);
989
- for (let p = 0; p < e; p++) {
990
- const u = p * 6, l = p * 4;
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;
1030
+ const m = new Uint32Array(6 * o);
1031
+ for (let d = 0; d < o; d++) {
1032
+ const S = d * 6, u = d * 4;
1033
+ m[S + 0] = c[0] + u, m[S + 1] = c[1] + u, m[S + 2] = c[2] + u, m[S + 3] = c[3] + u, m[S + 4] = c[4] + u, m[S + 5] = c[5] + u;
992
1034
  }
993
- s.setAttribute("position", new i.BufferAttribute(c, 3)), s.setIndex(new i.BufferAttribute(h, 1));
994
- const v = new i.InstancedBufferGeometry();
995
- v.index = s.index, v.setAttribute("position", s.getAttribute("position"));
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;
1035
+ s.setAttribute("position", new i.BufferAttribute(f, 3)), s.setIndex(new i.BufferAttribute(m, 1));
1036
+ const x = new i.InstancedBufferGeometry();
1037
+ x.index = s.index, x.setAttribute("position", s.getAttribute("position"));
1038
+ const v = new Uint32Array(n);
1039
+ for (let d = 0; d < n; d++)
1040
+ v[d] = d * o;
1041
+ return x.setAttribute("splatInstanceIndex", new i.InstancedBufferAttribute(v, 1, !1)), x.instanceCount = 0, r && console.debug(
1042
+ "MESH createInstancedGeometry: geometry created with",
1043
+ x.attributes.position.count,
1044
+ "vertices"
1045
+ ), x;
1000
1046
  }
1001
1047
  /**
1002
1048
  * Create chunks data (bounding box min/max) for the sorter.
1003
1049
  * @returns Float32Array containing chunk data [minX, minY, minZ, maxX, maxY, maxZ] or null.
1004
1050
  */
1005
1051
  createChunks() {
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
1052
+ const t = (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0, o = this.splatData.boundingBox;
1053
+ if (o.min.x === 1 / 0 || o.max.x === -1 / 0)
1054
+ return t && console.debug(
1055
+ "MESH createChunks: invalid bounding box, cannot create chunks"
1056
+ ), null;
1057
+ const r = new Float32Array([
1058
+ o.min.x,
1059
+ o.min.y,
1060
+ o.min.z,
1061
+ o.max.x,
1062
+ o.max.y,
1063
+ o.max.z
1014
1064
  ]);
1065
+ return t && console.debug(
1066
+ "MESH createChunks: created chunks with bounding box",
1067
+ o
1068
+ ), r;
1015
1069
  }
1016
1070
  /**
1017
1071
  * Update the viewport size
1018
1072
  * @param width Viewport width
1019
1073
  * @param height Viewport height
1020
1074
  */
1021
- updateViewport(n, e) {
1022
- this.material.updateViewport(n, e);
1075
+ updateViewport(t, o) {
1076
+ (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0 && console.debug(
1077
+ "MESH updateViewport: updating viewport to",
1078
+ t,
1079
+ "x",
1080
+ o
1081
+ ), this.material.updateViewport(t, o);
1023
1082
  }
1024
1083
  /**
1025
1084
  * Sorts splats based on camera position and direction.
1026
1085
  * @param camera The camera to sort against.
1027
1086
  */
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));
1087
+ sort(t) {
1088
+ const o = (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0, r = new i.Vector3(), n = new i.Vector3();
1089
+ t.getWorldPosition(r), t.getWorldDirection(n), this.invModelMatrix.copy(this.matrixWorld).invert();
1090
+ const s = r.applyMatrix4(this.invModelMatrix), a = n.transformDirection(this.invModelMatrix), c = this.lastCameraPositionLocal.distanceToSquared(s) > 1e-6, f = this.lastCameraDirectionLocal.dot(a) < 0.999;
1091
+ this.options.autoSort && (c || f) && (o && console.debug(
1092
+ "MESH sort: camera changed, triggering sort. Position changed:",
1093
+ c,
1094
+ "Direction changed:",
1095
+ f
1096
+ ), this.lastCameraPositionLocal.copy(s), this.lastCameraDirectionLocal.copy(a), this.sorter.setCamera(s, a));
1033
1097
  }
1034
1098
  /**
1035
1099
  * THREE.js hook called before rendering the object.
@@ -1040,29 +1104,30 @@ const j = class j extends i.Mesh {
1040
1104
  */
1041
1105
  // prettier-ignore
1042
1106
  // @ts-expect-error scene is not used
1043
- onBeforeRender(n, e, r) {
1107
+ onBeforeRender(t, o, r) {
1044
1108
  this.sort(r);
1045
- const s = n.getSize(new i.Vector2());
1046
- let { width: o, height: a } = s;
1047
- const c = n.xr;
1109
+ const n = t.getSize(new i.Vector2());
1110
+ let { width: s, height: a } = n;
1111
+ const c = t.xr;
1048
1112
  if (c.enabled && c.isPresenting) {
1049
- const h = c.getCamera().cameras[0].view;
1050
- h && (o = h.width, a = h.height);
1113
+ const f = c.getCamera().cameras[0].view;
1114
+ f && (s = f.width, a = f.height);
1051
1115
  }
1052
- this.updateViewport(o, a);
1116
+ this.updateViewport(s, a);
1053
1117
  }
1054
1118
  /**
1055
1119
  * Dispose of resources
1056
1120
  */
1057
1121
  dispose() {
1058
- this.sorter.dispose(), this.geometry.dispose(), this.material.dispose(), this.textureManager.dispose();
1122
+ const t = (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0;
1123
+ t && console.debug("MESH dispose: cleaning up mesh resources"), this.sorter.dispose(), this.geometry.dispose(), this.material.dispose(), this.textureManager.dispose(), t && console.debug("MESH dispose: mesh resources cleaned up");
1059
1124
  }
1060
1125
  };
1061
1126
  // Cached inverse matrix
1062
1127
  /** Number of splats combined into a single instanced draw call. */
1063
- f(j, "INSTANCE_SIZE", 128);
1064
- let it = j;
1065
- class bt extends i.Loader {
1128
+ p(N, "INSTANCE_SIZE", 128);
1129
+ let ie = N;
1130
+ class be extends i.Loader {
1066
1131
  /**
1067
1132
  * Load a PLY file with Gaussian Splat data
1068
1133
  * @param url URL of the PLY file
@@ -1070,21 +1135,22 @@ class bt extends i.Loader {
1070
1135
  * @param onProgress Optional progress callback
1071
1136
  * @param onError Optional error callback
1072
1137
  */
1073
- load(t, n, e, r) {
1138
+ load(e, t, o, r) {
1139
+ (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0 && console.debug("[1/12] LOADER PlyLoader: loading", e);
1074
1140
  const s = new i.FileLoader(this.manager);
1075
1141
  s.setResponseType("arraybuffer"), s.setRequestHeader(this.requestHeader), s.setPath(this.path), s.setWithCredentials(this.withCredentials), s.load(
1076
- t,
1077
- (o) => {
1142
+ e,
1143
+ (a) => {
1078
1144
  try {
1079
- if (n) {
1080
- const a = this.parse(o);
1081
- n(a);
1145
+ if (t) {
1146
+ const c = this.parse(a);
1147
+ t(c);
1082
1148
  }
1083
- } catch (a) {
1084
- r ? r(a) : console.error(a), this.manager.itemError(t);
1149
+ } catch (c) {
1150
+ r ? r(c) : console.error(c), this.manager.itemError(e);
1085
1151
  }
1086
1152
  },
1087
- e,
1153
+ o,
1088
1154
  r
1089
1155
  );
1090
1156
  }
@@ -1094,22 +1160,22 @@ class bt extends i.Loader {
1094
1160
  * @param onProgress Optional progress callback
1095
1161
  * @returns A Promise that resolves with the parsed SplatData
1096
1162
  */
1097
- loadAsync(t, n) {
1098
- return new Promise((e, r) => {
1099
- const s = new i.FileLoader(this.manager);
1100
- s.setResponseType("arraybuffer"), s.setRequestHeader(this.requestHeader), s.setPath(this.path), s.setWithCredentials(this.withCredentials), s.load(
1101
- t,
1102
- (o) => {
1163
+ loadAsync(e, t) {
1164
+ return new Promise((o, r) => {
1165
+ const n = new i.FileLoader(this.manager);
1166
+ n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
1167
+ e,
1168
+ (s) => {
1103
1169
  try {
1104
- const a = this.parse(o);
1105
- e(a);
1170
+ const a = this.parse(s);
1171
+ o(a);
1106
1172
  } catch (a) {
1107
- r(a), this.manager.itemError(t);
1173
+ r(a), this.manager.itemError(e);
1108
1174
  }
1109
1175
  },
1110
- n,
1111
- (o) => {
1112
- r(o), this.manager.itemError(t);
1176
+ t,
1177
+ (s) => {
1178
+ r(s), this.manager.itemError(e);
1113
1179
  }
1114
1180
  );
1115
1181
  });
@@ -1119,174 +1185,264 @@ class bt extends i.Loader {
1119
1185
  * @param buffer ArrayBuffer containing PLY data
1120
1186
  * @returns Parsed SplatData
1121
1187
  */
1122
- parse(t) {
1123
- const n = new TextDecoder(), e = new Uint8Array(t), r = [112, 108, 121, 10], s = `
1188
+ parse(e) {
1189
+ const t = (typeof window < "u" && window.__VISUS_SPLAT_DEBUG__) === !0;
1190
+ t && console.debug(
1191
+ "[2/12] LOADER PlyLoader: starting parse, buffer size:",
1192
+ e.byteLength
1193
+ );
1194
+ const o = new TextDecoder(), r = new Uint8Array(e), n = [112, 108, 121, 10], s = `
1124
1195
  end_header
1125
1196
  `;
1126
- for (let x = 0; x < r.length; x++)
1127
- if (e[x] !== r[x])
1197
+ for (let l = 0; l < n.length; l++)
1198
+ if (r[l] !== n[l])
1128
1199
  throw new Error("Invalid PLY file: Missing magic bytes");
1129
- let o = 0;
1130
- for (let x = 0; x < e.length - s.length; x++) {
1131
- let d = !0;
1132
- for (let z = 0; z < s.length; z++)
1133
- if (e[x + z] !== s.charCodeAt(z)) {
1134
- d = !1;
1200
+ t && console.debug("[3/12] LOADER PlyLoader: PLY magic bytes verified");
1201
+ let a = 0;
1202
+ for (let l = 0; l < r.length - s.length; l++) {
1203
+ let h = !0;
1204
+ for (let w = 0; w < s.length; w++)
1205
+ if (r[l + w] !== s.charCodeAt(w)) {
1206
+ h = !1;
1135
1207
  break;
1136
1208
  }
1137
- if (d) {
1138
- o = x + s.length;
1209
+ if (h) {
1210
+ a = l + s.length;
1139
1211
  break;
1140
1212
  }
1141
1213
  }
1142
- if (o === 0)
1214
+ if (a === 0)
1143
1215
  throw new Error("Invalid PLY file: Could not find end of header");
1144
- const c = n.decode(
1145
- e.slice(0, o)
1146
- ).split(`
1147
- `), h = [];
1148
- let v = null;
1149
- for (let x = 1; x < c.length; x++) {
1150
- const d = c[x].trim();
1151
- if (d === "" || d === "end_header") continue;
1152
- const z = d.split(" ");
1153
- switch (z[0]) {
1216
+ t && console.debug(
1217
+ "[4/12] LOADER PlyLoader: header length:",
1218
+ a
1219
+ );
1220
+ const c = o.decode(r.subarray(0, a));
1221
+ t && console.debug("[5/12] LOADER PlyLoader: header text:", c);
1222
+ const f = c.split(`
1223
+ `), m = [];
1224
+ let x = null;
1225
+ for (let l = 1; l < f.length; l++) {
1226
+ const h = f[l].trim();
1227
+ if (h === "" || h === "end_header") continue;
1228
+ const w = h.split(" ");
1229
+ switch (w[0]) {
1154
1230
  case "format":
1155
- v = z[1];
1231
+ x = w[1], t && console.debug(
1232
+ "[6/12] LOADER PlyLoader: format detected:",
1233
+ x
1234
+ );
1156
1235
  break;
1157
1236
  case "element":
1158
- h.push({
1159
- name: z[1],
1160
- count: parseInt(z[2], 10),
1237
+ m.push({
1238
+ name: w[1],
1239
+ count: parseInt(w[2], 10),
1161
1240
  properties: []
1162
- });
1241
+ }), t && console.debug(
1242
+ "[6/12] LOADER PlyLoader: element found:",
1243
+ w[1],
1244
+ "count:",
1245
+ w[2]
1246
+ );
1163
1247
  break;
1164
1248
  case "property":
1165
- if (h.length === 0)
1249
+ if (m.length === 0)
1166
1250
  throw new Error(
1167
1251
  "Invalid PLY file: Property without element"
1168
1252
  );
1169
- h[h.length - 1].properties.push({
1170
- type: z[1],
1171
- name: z[2],
1253
+ m[m.length - 1].properties.push({
1254
+ type: w[1],
1255
+ name: w[2],
1172
1256
  storage: null
1173
- });
1257
+ }), t && console.debug(
1258
+ "[6/12] LOADER PlyLoader: property found:",
1259
+ w[2],
1260
+ "type:",
1261
+ w[1]
1262
+ );
1174
1263
  break;
1175
1264
  }
1176
1265
  }
1177
- if (v !== "binary_little_endian")
1178
- throw new Error(`Unsupported PLY format: ${v}`);
1179
- const y = h.find((x) => x.name === "vertex");
1180
- if (!y)
1266
+ if (x !== "binary_little_endian")
1267
+ throw new Error(`Unsupported PLY format: ${x}`);
1268
+ const v = m.find((l) => l.name === "vertex");
1269
+ if (!v)
1181
1270
  throw new Error("Invalid PLY file: No vertex element found");
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 = [
1185
- b("rot_0"),
1186
- b("rot_1"),
1187
- b("rot_2"),
1188
- b("rot_3")
1189
- ], R = [
1190
- b("scale_0"),
1191
- b("scale_1"),
1192
- b("scale_2")
1271
+ t && console.debug(
1272
+ "[7/12] LOADER PlyLoader: vertex element properties:",
1273
+ v.properties.map((l) => l.name)
1274
+ );
1275
+ const d = new de(v.count);
1276
+ t && console.debug(
1277
+ "[8/12] LOADER PlyLoader: created SplatData for",
1278
+ v.count,
1279
+ "splats"
1280
+ );
1281
+ const S = new DataView(e);
1282
+ let u = a;
1283
+ const M = (l) => v.properties.findIndex((h) => h.name === l), O = M("x"), H = M("y"), R = M("z"), P = [
1284
+ M("rot_0"),
1285
+ M("rot_1"),
1286
+ M("rot_2"),
1287
+ M("rot_3")
1193
1288
  ], W = [
1194
- b("f_dc_0"),
1195
- b("f_dc_1"),
1196
- b("f_dc_2")
1197
- ], F = b("opacity");
1198
- if ([
1199
- B,
1289
+ M("scale_0"),
1290
+ M("scale_1"),
1291
+ M("scale_2")
1292
+ ], B = [
1293
+ M("f_dc_0"),
1294
+ M("f_dc_1"),
1295
+ M("f_dc_2")
1296
+ ], A = M("opacity");
1297
+ if (t && console.debug("[9/12] LOADER PlyLoader: property indices:", {
1298
+ position: [O, H, R],
1299
+ rotation: P,
1300
+ scale: W,
1301
+ color: B,
1302
+ opacity: A
1303
+ }), [
1200
1304
  O,
1201
- q,
1202
- ...E,
1203
- ...R,
1305
+ H,
1306
+ R,
1307
+ ...P,
1204
1308
  ...W,
1205
- F
1206
- ].some((x) => x === -1))
1309
+ ...B,
1310
+ A
1311
+ ].some((l) => l === -1))
1207
1312
  throw new Error("Invalid PLY file: Missing required properties");
1208
- const D = 0.28209479177387814, M = (x) => {
1209
- if (x > 0) return 1 / (1 + Math.exp(-x));
1210
- const d = Math.exp(x);
1211
- return d / (1 + d);
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++) {
1214
- const d = [];
1215
- for (let T = 0; T < y.properties.length; T++) {
1216
- const K = y.properties[T].type;
1217
- let I;
1218
- switch (K) {
1313
+ const C = 0.28209479177387814, y = (l) => {
1314
+ if (l > 0) return 1 / (1 + Math.exp(-l));
1315
+ const h = Math.exp(l);
1316
+ return h / (1 + h);
1317
+ };
1318
+ t && console.debug(
1319
+ "[10/12] LOADER PlyLoader: starting binary data parsing, offset:",
1320
+ u
1321
+ );
1322
+ const _ = new i.Vector3(), I = new i.Quaternion(), V = new i.Vector3(), E = new i.Color();
1323
+ for (let l = 0; l < v.count; l++) {
1324
+ t && l % 1e4 === 0 && console.debug(
1325
+ `[10/12] LOADER PlyLoader: processing splat ${l}/${v.count} (${(l / v.count * 100).toFixed(1)}%)`
1326
+ );
1327
+ const h = [];
1328
+ for (let q = 0; q < v.properties.length; q++) {
1329
+ const L = v.properties[q].type;
1330
+ let U;
1331
+ switch (L) {
1219
1332
  case "char":
1220
- I = u.getInt8(l), l += 1;
1333
+ U = S.getInt8(u), u += 1;
1221
1334
  break;
1222
1335
  case "uchar":
1223
- I = u.getUint8(l), l += 1;
1336
+ U = S.getUint8(u), u += 1;
1224
1337
  break;
1225
1338
  case "short":
1226
- I = u.getInt16(l, !0), l += 2;
1339
+ U = S.getInt16(u, !0), u += 2;
1227
1340
  break;
1228
1341
  case "ushort":
1229
- I = u.getUint16(l, !0), l += 2;
1342
+ U = S.getUint16(u, !0), u += 2;
1230
1343
  break;
1231
1344
  case "int":
1232
- I = u.getInt32(l, !0), l += 4;
1345
+ U = S.getInt32(u, !0), u += 4;
1233
1346
  break;
1234
1347
  case "uint":
1235
- I = u.getUint32(l, !0), l += 4;
1348
+ U = S.getUint32(u, !0), u += 4;
1236
1349
  break;
1237
1350
  case "float":
1238
- I = u.getFloat32(l, !0), l += 4;
1351
+ U = S.getFloat32(u, !0), u += 4;
1239
1352
  break;
1240
1353
  case "double":
1241
- I = u.getFloat64(l, !0), l += 8;
1354
+ U = S.getFloat64(u, !0), u += 8;
1242
1355
  break;
1243
1356
  default:
1244
- throw new Error(`Unsupported property type: ${K}`);
1357
+ throw new Error(`Unsupported property type: ${L}`);
1245
1358
  }
1246
- d.push(I);
1359
+ h.push(U);
1247
1360
  }
1248
- m.set(
1249
- d[B],
1250
- d[O],
1251
- d[q]
1252
- ), C.set(
1253
- d[E[1]],
1361
+ _.set(
1362
+ h[O],
1363
+ h[H],
1364
+ h[R]
1365
+ ), I.set(
1366
+ h[P[1]],
1254
1367
  // 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]]
1368
+ h[P[2]],
1369
+ h[P[3]],
1370
+ h[P[0]]
1371
+ ).normalize(), t && l < 5 && console.debug(
1372
+ `[10/12] LOADER PlyLoader: splat ${l} rotation:`,
1373
+ {
1374
+ original: [
1375
+ h[P[0]],
1376
+ h[P[1]],
1377
+ h[P[2]],
1378
+ h[P[3]]
1379
+ ],
1380
+ processed: [
1381
+ I.x,
1382
+ I.y,
1383
+ I.z,
1384
+ I.w
1385
+ ]
1386
+ }
1263
1387
  ), V.set(
1264
- 0.5 + d[W[0]] * D,
1265
- 0.5 + d[W[1]] * D,
1266
- 0.5 + d[W[2]] * D
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));
1268
- const z = M(d[F]);
1269
- p.setSplat(
1270
- x,
1271
- m,
1272
- C,
1388
+ h[W[0]],
1389
+ // Read directly assuming it's log scale
1390
+ h[W[1]],
1391
+ h[W[2]]
1392
+ ), E.set(
1393
+ 0.5 + h[B[0]] * C,
1394
+ 0.5 + h[B[1]] * C,
1395
+ 0.5 + h[B[2]] * C
1396
+ ), E.r = Math.max(0, Math.min(1, E.r)), E.g = Math.max(0, Math.min(1, E.g)), E.b = Math.max(0, Math.min(1, E.b));
1397
+ const w = y(h[A]);
1398
+ t && l < 3 && console.debug(`[10/12] LOADER PlyLoader: splat ${l} data:`, {
1399
+ position: [_.x, _.y, _.z],
1400
+ rotation: [
1401
+ I.x,
1402
+ I.y,
1403
+ I.z,
1404
+ I.w
1405
+ ],
1406
+ scale: [V.x, V.y, V.z],
1407
+ color: [E.r, E.g, E.b],
1408
+ opacity: w
1409
+ }), d.setSplat(
1410
+ l,
1273
1411
  _,
1274
- // Pass log scale directly
1412
+ I,
1275
1413
  V,
1276
- z
1414
+ // Pass log scale directly
1415
+ E,
1416
+ w
1277
1417
  );
1278
1418
  }
1279
- return p.calculateBoundingBox(), p;
1419
+ return t && console.debug(
1420
+ "[11/12] LOADER PlyLoader: finished parsing all splats, calculating bounding box"
1421
+ ), d.calculateBoundingBox(), t && console.debug(
1422
+ "[12/12] LOADER PlyLoader: parsing complete, bounding box:",
1423
+ {
1424
+ min: [
1425
+ d.boundingBox.min.x,
1426
+ d.boundingBox.min.y,
1427
+ d.boundingBox.min.z
1428
+ ],
1429
+ max: [
1430
+ d.boundingBox.max.x,
1431
+ d.boundingBox.max.y,
1432
+ d.boundingBox.max.z
1433
+ ]
1434
+ }
1435
+ ), d;
1280
1436
  }
1281
1437
  }
1282
- const Mt = "0.3.0";
1438
+ const Se = "0.3.0";
1283
1439
  export {
1284
- et as BoundingBox,
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
1440
+ te as BoundingBox,
1441
+ be as PlyLoader,
1442
+ de as SplatData,
1443
+ we as SplatMaterial,
1444
+ ie as SplatMesh,
1445
+ he as SplatSorter,
1446
+ xe as TextureManager,
1447
+ Se as VERSION
1292
1448
  };