@speridlabs/visus 1.0.2 → 1.0.3

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