@speridlabs/visus 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.es.js CHANGED
@@ -1,7 +1,10 @@
1
- import te, { useRef as ne, useMemo as oe, useEffect as ae } from "react";
2
- import { extend as se, useLoader as ue } from "@react-three/fiber";
3
- import { b as L, P as le } from "./ply-CQ9dyX1o.mjs";
4
- var _ = { exports: {} }, R = {};
1
+ var me = Object.defineProperty;
2
+ var xe = (z, e, s) => e in z ? me(z, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : z[e] = s;
3
+ var v = (z, e, s) => xe(z, typeof e != "symbol" ? e + "" : e, s);
4
+ import ye, { useRef as ge, useMemo as ve, useEffect as we } from "react";
5
+ import { extend as be, useLoader as Me } from "@react-three/fiber";
6
+ import * as i from "three";
7
+ var se = { exports: {} }, te = {};
5
8
  /**
6
9
  * @license React
7
10
  * react-jsx-runtime.production.js
@@ -11,29 +14,29 @@ var _ = { exports: {} }, R = {};
11
14
  * This source code is licensed under the MIT license found in the
12
15
  * LICENSE file in the root directory of this source tree.
13
16
  */
14
- var F;
15
- function ce() {
16
- if (F) return R;
17
- F = 1;
18
- var c = Symbol.for("react.transitional.element"), d = Symbol.for("react.fragment");
19
- function m(i, a, s) {
20
- var u = null;
21
- if (s !== void 0 && (u = "" + s), a.key !== void 0 && (u = "" + a.key), "key" in a) {
22
- s = {};
23
- for (var p in a)
24
- p !== "key" && (s[p] = a[p]);
25
- } else s = a;
26
- return a = s.ref, {
27
- $$typeof: c,
28
- type: i,
29
- key: u,
30
- ref: a !== void 0 ? a : null,
31
- props: s
17
+ var ue;
18
+ function Se() {
19
+ if (ue) return te;
20
+ ue = 1;
21
+ var z = Symbol.for("react.transitional.element"), e = Symbol.for("react.fragment");
22
+ function s(o, n, t) {
23
+ var a = null;
24
+ if (t !== void 0 && (a = "" + t), n.key !== void 0 && (a = "" + n.key), "key" in n) {
25
+ t = {};
26
+ for (var c in n)
27
+ c !== "key" && (t[c] = n[c]);
28
+ } else t = n;
29
+ return n = t.ref, {
30
+ $$typeof: z,
31
+ type: o,
32
+ key: a,
33
+ ref: n !== void 0 ? n : null,
34
+ props: t
32
35
  };
33
36
  }
34
- return R.Fragment = d, R.jsx = m, R.jsxs = m, R;
37
+ return te.Fragment = e, te.jsx = s, te.jsxs = s, te;
35
38
  }
36
- var b = {};
39
+ var re = {};
37
40
  /**
38
41
  * @license React
39
42
  * react-jsx-runtime.development.js
@@ -43,266 +46,1551 @@ var b = {};
43
46
  * This source code is licensed under the MIT license found in the
44
47
  * LICENSE file in the root directory of this source tree.
45
48
  */
46
- var I;
47
- function ie() {
48
- return I || (I = 1, process.env.NODE_ENV !== "production" && function() {
49
- function c(e) {
50
- if (e == null) return null;
51
- if (typeof e == "function")
52
- return e.$$typeof === K ? null : e.displayName || e.name || null;
53
- if (typeof e == "string") return e;
54
- switch (e) {
55
- case T:
49
+ var he;
50
+ function Te() {
51
+ return he || (he = 1, process.env.NODE_ENV !== "production" && function() {
52
+ function z(r) {
53
+ if (r == null) return null;
54
+ if (typeof r == "function")
55
+ return r.$$typeof === w ? null : r.displayName || r.name || null;
56
+ if (typeof r == "string") return r;
57
+ switch (r) {
58
+ case S:
56
59
  return "Fragment";
57
- case V:
60
+ case j:
58
61
  return "Profiler";
59
- case J:
62
+ case O:
60
63
  return "StrictMode";
61
- case B:
64
+ case $:
62
65
  return "Suspense";
63
- case H:
66
+ case D:
64
67
  return "SuspenseList";
65
- case Q:
68
+ case C:
66
69
  return "Activity";
67
70
  }
68
- if (typeof e == "object")
69
- switch (typeof e.tag == "number" && console.error(
71
+ if (typeof r == "object")
72
+ switch (typeof r.tag == "number" && console.error(
70
73
  "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
71
- ), e.$$typeof) {
72
- case q:
74
+ ), r.$$typeof) {
75
+ case d:
73
76
  return "Portal";
74
- case G:
75
- return (e.displayName || "Context") + ".Provider";
76
- case z:
77
- return (e._context.displayName || "Context") + ".Consumer";
78
- case X:
79
- var r = e.render;
80
- return e = e.displayName, e || (e = r.displayName || r.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
81
- case Z:
82
- return r = e.displayName || null, r !== null ? r : c(e.type) || "Memo";
83
- case y:
84
- r = e._payload, e = e._init;
77
+ case q:
78
+ return (r.displayName || "Context") + ".Provider";
79
+ case W:
80
+ return (r._context.displayName || "Context") + ".Consumer";
81
+ case H:
82
+ var f = r.render;
83
+ return r = r.displayName, r || (r = f.displayName || f.name || "", r = r !== "" ? "ForwardRef(" + r + ")" : "ForwardRef"), r;
84
+ case k:
85
+ return f = r.displayName || null, f !== null ? f : z(r.type) || "Memo";
86
+ case F:
87
+ f = r._payload, r = r._init;
85
88
  try {
86
- return c(e(r));
89
+ return z(r(f));
87
90
  } catch {
88
91
  }
89
92
  }
90
93
  return null;
91
94
  }
92
- function d(e) {
93
- return "" + e;
95
+ function e(r) {
96
+ return "" + r;
94
97
  }
95
- function m(e) {
98
+ function s(r) {
96
99
  try {
97
- d(e);
98
- var r = !1;
100
+ e(r);
101
+ var f = !1;
99
102
  } catch {
100
- r = !0;
103
+ f = !0;
101
104
  }
102
- if (r) {
103
- r = console;
104
- var t = r.error, n = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
105
- return t.call(
106
- r,
105
+ if (f) {
106
+ f = console;
107
+ var T = f.error, R = typeof Symbol == "function" && Symbol.toStringTag && r[Symbol.toStringTag] || r.constructor.name || "Object";
108
+ return T.call(
109
+ f,
107
110
  "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
108
- n
109
- ), d(e);
111
+ R
112
+ ), e(r);
110
113
  }
111
114
  }
112
- function i(e) {
113
- if (e === T) return "<>";
114
- if (typeof e == "object" && e !== null && e.$$typeof === y)
115
+ function o(r) {
116
+ if (r === S) return "<>";
117
+ if (typeof r == "object" && r !== null && r.$$typeof === F)
115
118
  return "<...>";
116
119
  try {
117
- var r = c(e);
118
- return r ? "<" + r + ">" : "<...>";
120
+ var f = z(r);
121
+ return f ? "<" + f + ">" : "<...>";
119
122
  } catch {
120
123
  return "<...>";
121
124
  }
122
125
  }
123
- function a() {
124
- var e = k.A;
125
- return e === null ? null : e.getOwner();
126
+ function n() {
127
+ var r = P.A;
128
+ return r === null ? null : r.getOwner();
126
129
  }
127
- function s() {
130
+ function t() {
128
131
  return Error("react-stack-top-frame");
129
132
  }
130
- function u(e) {
131
- if (j.call(e, "key")) {
132
- var r = Object.getOwnPropertyDescriptor(e, "key").get;
133
- if (r && r.isReactWarning) return !1;
133
+ function a(r) {
134
+ if (V.call(r, "key")) {
135
+ var f = Object.getOwnPropertyDescriptor(r, "key").get;
136
+ if (f && f.isReactWarning) return !1;
134
137
  }
135
- return e.key !== void 0;
138
+ return r.key !== void 0;
136
139
  }
137
- function p(e, r) {
138
- function t() {
139
- g || (g = !0, console.error(
140
+ function c(r, f) {
141
+ function T() {
142
+ y || (y = !0, console.error(
140
143
  "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
141
- r
144
+ f
142
145
  ));
143
146
  }
144
- t.isReactWarning = !0, Object.defineProperty(e, "key", {
145
- get: t,
147
+ T.isReactWarning = !0, Object.defineProperty(r, "key", {
148
+ get: T,
146
149
  configurable: !0
147
150
  });
148
151
  }
149
- function W() {
150
- var e = c(this.type);
151
- return N[e] || (N[e] = !0, console.error(
152
+ function l() {
153
+ var r = z(this.type);
154
+ return A[r] || (A[r] = !0, console.error(
152
155
  "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
153
- )), e = this.props.ref, e !== void 0 ? e : null;
154
- }
155
- function U(e, r, t, n, f, l, S, P) {
156
- return t = l.ref, e = {
157
- $$typeof: A,
158
- type: e,
159
- key: r,
160
- props: l,
161
- _owner: f
162
- }, (t !== void 0 ? t : null) !== null ? Object.defineProperty(e, "ref", {
156
+ )), r = this.props.ref, r !== void 0 ? r : null;
157
+ }
158
+ function m(r, f, T, R, N, h, I, B) {
159
+ return T = h.ref, r = {
160
+ $$typeof: x,
161
+ type: r,
162
+ key: f,
163
+ props: h,
164
+ _owner: N
165
+ }, (T !== void 0 ? T : null) !== null ? Object.defineProperty(r, "ref", {
163
166
  enumerable: !1,
164
- get: W
165
- }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
167
+ get: l
168
+ }) : Object.defineProperty(r, "ref", { enumerable: !1, value: null }), r._store = {}, Object.defineProperty(r._store, "validated", {
166
169
  configurable: !1,
167
170
  enumerable: !1,
168
171
  writable: !0,
169
172
  value: 0
170
- }), Object.defineProperty(e, "_debugInfo", {
173
+ }), Object.defineProperty(r, "_debugInfo", {
171
174
  configurable: !1,
172
175
  enumerable: !1,
173
176
  writable: !0,
174
177
  value: null
175
- }), Object.defineProperty(e, "_debugStack", {
178
+ }), Object.defineProperty(r, "_debugStack", {
176
179
  configurable: !1,
177
180
  enumerable: !1,
178
181
  writable: !0,
179
- value: S
180
- }), Object.defineProperty(e, "_debugTask", {
182
+ value: I
183
+ }), Object.defineProperty(r, "_debugTask", {
181
184
  configurable: !1,
182
185
  enumerable: !1,
183
186
  writable: !0,
184
- value: P
185
- }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
186
- }
187
- function O(e, r, t, n, f, l, S, P) {
188
- var o = r.children;
189
- if (o !== void 0)
190
- if (n)
191
- if (ee(o)) {
192
- for (n = 0; n < o.length; n++)
193
- x(o[n]);
194
- Object.freeze && Object.freeze(o);
187
+ value: B
188
+ }), Object.freeze && (Object.freeze(r.props), Object.freeze(r)), r;
189
+ }
190
+ function M(r, f, T, R, N, h, I, B) {
191
+ var u = f.children;
192
+ if (u !== void 0)
193
+ if (R)
194
+ if (U(u)) {
195
+ for (R = 0; R < u.length; R++)
196
+ b(u[R]);
197
+ Object.freeze && Object.freeze(u);
195
198
  } else
196
199
  console.error(
197
200
  "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
198
201
  );
199
- else x(o);
200
- if (j.call(r, "key")) {
201
- o = c(e);
202
- var E = Object.keys(r).filter(function(re) {
203
- return re !== "key";
202
+ else b(u);
203
+ if (V.call(f, "key")) {
204
+ u = z(r);
205
+ var _ = Object.keys(f).filter(function(G) {
206
+ return G !== "key";
204
207
  });
205
- n = 0 < E.length ? "{key: someKey, " + E.join(": ..., ") + ": ...}" : "{key: someKey}", M[o + n] || (E = 0 < E.length ? "{" + E.join(": ..., ") + ": ...}" : "{}", console.error(
208
+ R = 0 < _.length ? "{key: someKey, " + _.join(": ..., ") + ": ...}" : "{key: someKey}", J[u + R] || (_ = 0 < _.length ? "{" + _.join(": ..., ") + ": ...}" : "{}", console.error(
206
209
  `A props object containing a "key" prop is being spread into JSX:
207
210
  let props = %s;
208
211
  <%s {...props} />
209
212
  React keys must be passed directly to JSX without using spread:
210
213
  let props = %s;
211
214
  <%s key={someKey} {...props} />`,
212
- n,
213
- o,
214
- E,
215
- o
216
- ), M[o + n] = !0);
215
+ R,
216
+ u,
217
+ _,
218
+ u
219
+ ), J[u + R] = !0);
217
220
  }
218
- if (o = null, t !== void 0 && (m(t), o = "" + t), u(r) && (m(r.key), o = "" + r.key), "key" in r) {
219
- t = {};
220
- for (var w in r)
221
- w !== "key" && (t[w] = r[w]);
222
- } else t = r;
223
- return o && p(
224
- t,
225
- typeof e == "function" ? e.displayName || e.name || "Unknown" : e
226
- ), U(
227
- e,
228
- o,
229
- l,
230
- f,
231
- a(),
232
- t,
233
- S,
234
- P
221
+ if (u = null, T !== void 0 && (s(T), u = "" + T), a(f) && (s(f.key), u = "" + f.key), "key" in f) {
222
+ T = {};
223
+ for (var Y in f)
224
+ Y !== "key" && (T[Y] = f[Y]);
225
+ } else T = f;
226
+ return u && c(
227
+ T,
228
+ typeof r == "function" ? r.displayName || r.name || "Unknown" : r
229
+ ), m(
230
+ r,
231
+ u,
232
+ h,
233
+ N,
234
+ n(),
235
+ T,
236
+ I,
237
+ B
235
238
  );
236
239
  }
237
- function x(e) {
238
- typeof e == "object" && e !== null && e.$$typeof === A && e._store && (e._store.validated = 1);
240
+ function b(r) {
241
+ typeof r == "object" && r !== null && r.$$typeof === x && r._store && (r._store.validated = 1);
239
242
  }
240
- var v = te, A = Symbol.for("react.transitional.element"), q = Symbol.for("react.portal"), T = Symbol.for("react.fragment"), J = Symbol.for("react.strict_mode"), V = Symbol.for("react.profiler"), z = Symbol.for("react.consumer"), G = Symbol.for("react.context"), X = Symbol.for("react.forward_ref"), B = Symbol.for("react.suspense"), H = Symbol.for("react.suspense_list"), Z = Symbol.for("react.memo"), y = Symbol.for("react.lazy"), Q = Symbol.for("react.activity"), K = Symbol.for("react.client.reference"), k = v.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, j = Object.prototype.hasOwnProperty, ee = Array.isArray, h = console.createTask ? console.createTask : function() {
243
+ var p = ye, x = Symbol.for("react.transitional.element"), d = Symbol.for("react.portal"), S = Symbol.for("react.fragment"), O = Symbol.for("react.strict_mode"), j = Symbol.for("react.profiler"), W = Symbol.for("react.consumer"), q = Symbol.for("react.context"), H = Symbol.for("react.forward_ref"), $ = Symbol.for("react.suspense"), D = Symbol.for("react.suspense_list"), k = Symbol.for("react.memo"), F = Symbol.for("react.lazy"), C = Symbol.for("react.activity"), w = Symbol.for("react.client.reference"), P = p.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, V = Object.prototype.hasOwnProperty, U = Array.isArray, g = console.createTask ? console.createTask : function() {
241
244
  return null;
242
245
  };
243
- v = {
244
- "react-stack-bottom-frame": function(e) {
245
- return e();
246
+ p = {
247
+ "react-stack-bottom-frame": function(r) {
248
+ return r();
246
249
  }
247
250
  };
248
- var g, N = {}, C = v["react-stack-bottom-frame"].bind(
249
- v,
250
- s
251
- )(), Y = h(i(s)), M = {};
252
- b.Fragment = T, b.jsx = function(e, r, t, n, f) {
253
- var l = 1e4 > k.recentlyCreatedOwnerStacks++;
254
- return O(
255
- e,
251
+ var y, A = {}, E = p["react-stack-bottom-frame"].bind(
252
+ p,
253
+ t
254
+ )(), L = g(o(t)), J = {};
255
+ re.Fragment = S, re.jsx = function(r, f, T, R, N) {
256
+ var h = 1e4 > P.recentlyCreatedOwnerStacks++;
257
+ return M(
256
258
  r,
257
- t,
258
- !1,
259
- n,
260
259
  f,
261
- l ? Error("react-stack-top-frame") : C,
262
- l ? h(i(e)) : Y
260
+ T,
261
+ !1,
262
+ R,
263
+ N,
264
+ h ? Error("react-stack-top-frame") : E,
265
+ h ? g(o(r)) : L
263
266
  );
264
- }, b.jsxs = function(e, r, t, n, f) {
265
- var l = 1e4 > k.recentlyCreatedOwnerStacks++;
266
- return O(
267
- e,
267
+ }, re.jsxs = function(r, f, T, R, N) {
268
+ var h = 1e4 > P.recentlyCreatedOwnerStacks++;
269
+ return M(
268
270
  r,
269
- t,
270
- !0,
271
- n,
272
271
  f,
273
- l ? Error("react-stack-top-frame") : C,
274
- l ? h(i(e)) : Y
272
+ T,
273
+ !0,
274
+ R,
275
+ N,
276
+ h ? Error("react-stack-top-frame") : E,
277
+ h ? g(o(r)) : L
278
+ );
279
+ };
280
+ }()), re;
281
+ }
282
+ var de;
283
+ function Ce() {
284
+ return de || (de = 1, process.env.NODE_ENV === "production" ? se.exports = Se() : se.exports = Te()), se.exports;
285
+ }
286
+ var Ae = Ce();
287
+ class le {
288
+ constructor() {
289
+ v(this, "min", new i.Vector3(1 / 0, 1 / 0, 1 / 0));
290
+ v(this, "max", new i.Vector3(-1 / 0, -1 / 0, -1 / 0));
291
+ v(this, "center", new i.Vector3());
292
+ /** Half extents (size/2) */
293
+ v(this, "halfExtents", new i.Vector3());
294
+ }
295
+ /**
296
+ * Reset the bounding box to its initial state
297
+ */
298
+ reset() {
299
+ this.min.set(1 / 0, 1 / 0, 1 / 0), this.max.set(-1 / 0, -1 / 0, -1 / 0), this.center.set(0, 0, 0), this.halfExtents.set(0, 0, 0);
300
+ }
301
+ /**
302
+ * Expand the bounding box to include the given point
303
+ * @param point Point to include in the bounding box
304
+ */
305
+ expandByPoint(e) {
306
+ 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();
307
+ }
308
+ /**
309
+ * Expand this bounding box to include another bounding box
310
+ * @param box Bounding box to include
311
+ */
312
+ expandByBox(e) {
313
+ 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();
314
+ }
315
+ /**
316
+ * Update the center and half extents based on min/max
317
+ */
318
+ updateDerived() {
319
+ this.center.addVectors(this.min, this.max).multiplyScalar(0.5), this.halfExtents.subVectors(this.max, this.min).multiplyScalar(0.5);
320
+ }
321
+ /**
322
+ * Check if this box contains a point
323
+ * @param point Point to check
324
+ * @returns True if the point is inside the box
325
+ */
326
+ containsPoint(e) {
327
+ 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;
328
+ }
329
+ /**
330
+ * Create a Three.js Box3 from this bounding box
331
+ * @returns THREE.Box3 representation
332
+ */
333
+ toBox3() {
334
+ return new i.Box3().set(this.min, this.max);
335
+ }
336
+ /**
337
+ * Create a clone of this bounding box
338
+ * @returns New bounding box with the same values
339
+ */
340
+ clone() {
341
+ const e = new le();
342
+ return e.min.copy(this.min), e.max.copy(this.max), e.center.copy(this.center), e.halfExtents.copy(this.halfExtents), e;
343
+ }
344
+ }
345
+ class ze {
346
+ // TODO: there is no sh spherical harmonics
347
+ constructor(e = 0) {
348
+ v(this, "numSplats", 0);
349
+ v(this, "positions");
350
+ v(this, "rotations");
351
+ v(this, "scales");
352
+ v(this, "colors");
353
+ v(this, "opacities");
354
+ v(this, "centers");
355
+ v(this, "boundingBox", new le());
356
+ this.numSplats = e, this.allocateBuffers(e);
357
+ }
358
+ allocateBuffers(e) {
359
+ 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);
360
+ }
361
+ /**
362
+ * Set data for a specific splat
363
+ * @param index Splat index
364
+ * @param position Position vector
365
+ * @param rotation Quaternion
366
+ * @param scale Scale vector (expects LOG SCALE)
367
+ * @param color Color
368
+ * @param opacity Opacity value
369
+ */
370
+ setSplat(e, s, o, n, t, a) {
371
+ if (e >= this.numSplats)
372
+ throw new Error(
373
+ `Splat index out of bounds: ${e} >= ${this.numSplats}`
374
+ );
375
+ const c = e * 3, l = e * 4, m = e * 3, M = e * 3;
376
+ this.positions[c] = s.x, this.positions[c + 1] = s.y, this.positions[c + 2] = s.z, this.rotations[l] = o.x, this.rotations[l + 1] = o.y, this.rotations[l + 2] = o.z, this.rotations[l + 3] = o.w, this.scales[m] = n.x, this.scales[m + 1] = n.y, this.scales[m + 2] = n.z, this.colors[M] = t.r, this.colors[M + 1] = t.g, this.colors[M + 2] = t.b, this.opacities[e] = a, this.centers[c] = s.x, this.centers[c + 1] = s.y, this.centers[c + 2] = s.z;
377
+ }
378
+ /**
379
+ * Get a splat's data
380
+ * @param index Splat index
381
+ * @returns Object containing splat data (linear scale)
382
+ */
383
+ getSplat(e) {
384
+ if (e >= this.numSplats)
385
+ throw new Error(
386
+ `Splat index out of bounds: ${e} >= ${this.numSplats}`
387
+ );
388
+ const s = e * 3, o = e * 4, n = e * 3, t = e * 3;
389
+ return {
390
+ position: new i.Vector3(
391
+ this.positions[s],
392
+ this.positions[s + 1],
393
+ this.positions[s + 2]
394
+ ),
395
+ rotation: new i.Quaternion(
396
+ this.rotations[o],
397
+ this.rotations[o + 1],
398
+ this.rotations[o + 2],
399
+ this.rotations[o + 3]
400
+ ),
401
+ // Convert log scale back to linear scale for external use
402
+ scale: new i.Vector3(
403
+ Math.exp(this.scales[n]),
404
+ Math.exp(this.scales[n + 1]),
405
+ Math.exp(this.scales[n + 2])
406
+ ),
407
+ color: new i.Color(
408
+ this.colors[t],
409
+ this.colors[t + 1],
410
+ this.colors[t + 2]
411
+ ),
412
+ opacity: this.opacities[e]
413
+ };
414
+ }
415
+ /**
416
+ * Calculate the bounding box for all splats
417
+ * NOTE: Currently it only uses positions, not the actual splat bounds
418
+ */
419
+ calculateBoundingBox() {
420
+ this.boundingBox.reset();
421
+ const e = new i.Vector3();
422
+ for (let s = 0; s < this.numSplats; s++) {
423
+ const o = s * 3;
424
+ e.set(
425
+ this.positions[o],
426
+ this.positions[o + 1],
427
+ this.positions[o + 2]
428
+ ), this.boundingBox.expandByPoint(e);
429
+ }
430
+ return this.boundingBox;
431
+ }
432
+ /**
433
+ * Create a Three.js BufferGeometry from this splat data
434
+ * This is for visualization/debugging purposes only, not for rendering
435
+ */
436
+ createDebugGeometry() {
437
+ const e = new i.BufferGeometry();
438
+ e.setAttribute(
439
+ "position",
440
+ new i.BufferAttribute(this.positions, 3)
441
+ );
442
+ const s = new Float32Array(this.numSplats * 3), o = new i.Quaternion(), n = new i.Euler();
443
+ for (let t = 0; t < this.numSplats; t++) {
444
+ const a = t * 4, c = t * 3;
445
+ o.set(
446
+ this.rotations[a],
447
+ this.rotations[a + 1],
448
+ this.rotations[a + 2],
449
+ this.rotations[a + 3]
450
+ ), n.setFromQuaternion(o), s[c] = n.x, s[c + 1] = n.y, s[c + 2] = n.z;
451
+ }
452
+ return e.setAttribute(
453
+ "rotation",
454
+ new i.BufferAttribute(s, 3)
455
+ ), e.setAttribute(
456
+ "scale",
457
+ new i.BufferAttribute(this.scales, 3)
458
+ ), e.setAttribute(
459
+ "color",
460
+ new i.BufferAttribute(this.colors, 3)
461
+ ), e.setAttribute(
462
+ "opacity",
463
+ new i.BufferAttribute(this.opacities, 1)
464
+ ), e;
465
+ }
466
+ }
467
+ class ke extends i.Loader {
468
+ /**
469
+ * Load a PLY file with Gaussian Splat data
470
+ * @param url URL of the PLY file
471
+ * @param onLoad Optional callback when loading is complete
472
+ * @param onProgress Optional progress callback
473
+ * @param onError Optional error callback
474
+ */
475
+ load(e, s, o, n) {
476
+ const t = new i.FileLoader(this.manager);
477
+ t.setResponseType("arraybuffer"), t.setRequestHeader(this.requestHeader), t.setPath(this.path), t.setWithCredentials(this.withCredentials), t.load(
478
+ e,
479
+ (a) => {
480
+ try {
481
+ if (s) {
482
+ const c = this.parse(a);
483
+ s(c);
484
+ }
485
+ } catch (c) {
486
+ n ? n(c) : console.error(c), this.manager.itemError(e);
487
+ }
488
+ },
489
+ o,
490
+ n
491
+ );
492
+ }
493
+ /**
494
+ * Load a PLY file asynchronously and return a Promise
495
+ * @param url URL of the PLY file
496
+ * @param onProgress Optional progress callback
497
+ * @returns A Promise that resolves with the parsed SplatData
498
+ */
499
+ loadAsync(e, s) {
500
+ return new Promise((o, n) => {
501
+ const t = new i.FileLoader(this.manager);
502
+ t.setResponseType("arraybuffer"), t.setRequestHeader(this.requestHeader), t.setPath(this.path), t.setWithCredentials(this.withCredentials), t.load(
503
+ e,
504
+ (a) => {
505
+ try {
506
+ const c = this.parse(a);
507
+ o(c);
508
+ } catch (c) {
509
+ n(c), this.manager.itemError(e);
510
+ }
511
+ },
512
+ s,
513
+ (a) => {
514
+ n(a), this.manager.itemError(e);
515
+ }
516
+ );
517
+ });
518
+ }
519
+ /**
520
+ * Parse PLY buffer data into SplatData
521
+ * @param buffer ArrayBuffer containing PLY data
522
+ * @returns Parsed SplatData
523
+ */
524
+ parse(e) {
525
+ const s = new TextDecoder(), o = new Uint8Array(e), n = [112, 108, 121, 10], t = `
526
+ end_header
527
+ `;
528
+ for (let g = 0; g < n.length; g++)
529
+ if (o[g] !== n[g])
530
+ throw new Error("Invalid PLY file: Missing magic bytes");
531
+ let a = 0;
532
+ for (let g = 0; g < o.length - t.length; g++) {
533
+ let y = !0;
534
+ for (let A = 0; A < t.length; A++)
535
+ if (o[g + A] !== t.charCodeAt(A)) {
536
+ y = !1;
537
+ break;
538
+ }
539
+ if (y) {
540
+ a = g + t.length;
541
+ break;
542
+ }
543
+ }
544
+ if (a === 0)
545
+ throw new Error("Invalid PLY file: Could not find end of header");
546
+ const l = s.decode(
547
+ o.slice(0, a)
548
+ ).split(`
549
+ `), m = [];
550
+ let M = null;
551
+ for (let g = 1; g < l.length; g++) {
552
+ const y = l[g].trim();
553
+ if (y === "" || y === "end_header") continue;
554
+ const A = y.split(" ");
555
+ switch (A[0]) {
556
+ case "format":
557
+ M = A[1];
558
+ break;
559
+ case "element":
560
+ m.push({
561
+ name: A[1],
562
+ count: parseInt(A[2], 10),
563
+ properties: []
564
+ });
565
+ break;
566
+ case "property":
567
+ if (m.length === 0)
568
+ throw new Error(
569
+ "Invalid PLY file: Property without element"
570
+ );
571
+ m[m.length - 1].properties.push({
572
+ type: A[1],
573
+ name: A[2],
574
+ storage: null
575
+ });
576
+ break;
577
+ }
578
+ }
579
+ if (M !== "binary_little_endian")
580
+ throw new Error(`Unsupported PLY format: ${M}`);
581
+ const b = m.find((g) => g.name === "vertex");
582
+ if (!b)
583
+ throw new Error("Invalid PLY file: No vertex element found");
584
+ const p = new ze(b.count), x = new DataView(e);
585
+ let d = a;
586
+ const S = (g) => b.properties.findIndex((y) => y.name === g), O = S("x"), j = S("y"), W = S("z"), q = [
587
+ S("rot_0"),
588
+ S("rot_1"),
589
+ S("rot_2"),
590
+ S("rot_3")
591
+ ], H = [
592
+ S("scale_0"),
593
+ S("scale_1"),
594
+ S("scale_2")
595
+ ], $ = [
596
+ S("f_dc_0"),
597
+ S("f_dc_1"),
598
+ S("f_dc_2")
599
+ ], D = S("opacity");
600
+ if ([
601
+ O,
602
+ j,
603
+ W,
604
+ ...q,
605
+ ...H,
606
+ ...$,
607
+ D
608
+ ].some((g) => g === -1))
609
+ throw new Error("Invalid PLY file: Missing required properties");
610
+ const F = 0.28209479177387814, C = (g) => {
611
+ if (g > 0) return 1 / (1 + Math.exp(-g));
612
+ const y = Math.exp(g);
613
+ return y / (1 + y);
614
+ }, w = new i.Vector3(), P = new i.Quaternion(), V = new i.Vector3(), U = new i.Color();
615
+ for (let g = 0; g < b.count; g++) {
616
+ const y = [];
617
+ for (let E = 0; E < b.properties.length; E++) {
618
+ const J = b.properties[E].type;
619
+ let r;
620
+ switch (J) {
621
+ case "char":
622
+ r = x.getInt8(d), d += 1;
623
+ break;
624
+ case "uchar":
625
+ r = x.getUint8(d), d += 1;
626
+ break;
627
+ case "short":
628
+ r = x.getInt16(d, !0), d += 2;
629
+ break;
630
+ case "ushort":
631
+ r = x.getUint16(d, !0), d += 2;
632
+ break;
633
+ case "int":
634
+ r = x.getInt32(d, !0), d += 4;
635
+ break;
636
+ case "uint":
637
+ r = x.getUint32(d, !0), d += 4;
638
+ break;
639
+ case "float":
640
+ r = x.getFloat32(d, !0), d += 4;
641
+ break;
642
+ case "double":
643
+ r = x.getFloat64(d, !0), d += 8;
644
+ break;
645
+ default:
646
+ throw new Error(`Unsupported property type: ${J}`);
647
+ }
648
+ y.push(r);
649
+ }
650
+ w.set(
651
+ y[O],
652
+ y[j],
653
+ y[W]
654
+ ), P.set(
655
+ // TODO: dangerous see if true
656
+ y[q[1]],
657
+ // PLY stores rot 1,2,3,0 (x,y,z,w)
658
+ y[q[2]],
659
+ y[q[3]],
660
+ y[q[0]]
661
+ ).normalize(), V.set(
662
+ y[H[0]],
663
+ // Read directly assuming it's log scale
664
+ y[H[1]],
665
+ y[H[2]]
666
+ ), U.set(
667
+ 0.5 + y[$[0]] * F,
668
+ 0.5 + y[$[1]] * F,
669
+ 0.5 + y[$[2]] * F
670
+ ), U.r = Math.max(0, Math.min(1, U.r)), U.g = Math.max(0, Math.min(1, U.g)), U.b = Math.max(0, Math.min(1, U.b));
671
+ const A = C(y[D]);
672
+ p.setSplat(
673
+ g,
674
+ w,
675
+ P,
676
+ V,
677
+ // Pass log scale directly
678
+ U,
679
+ A
680
+ );
681
+ }
682
+ return p.calculateBoundingBox(), p;
683
+ }
684
+ }
685
+ class _e extends i.EventDispatcher {
686
+ constructor() {
687
+ super();
688
+ v(this, "worker");
689
+ v(this, "centers", null);
690
+ v(this, "orderTexture", null);
691
+ /** Bounding box data for optimization */
692
+ v(this, "chunks", null);
693
+ v(this, "lastCameraPosition", new i.Vector3());
694
+ v(this, "lastCameraDirection", new i.Vector3());
695
+ const s = this.createWorkerCode(), o = new Blob([s], { type: "application/javascript" });
696
+ this.worker = new Worker(URL.createObjectURL(o)), this.worker.onmessage = this.onWorkerMessage.bind(this);
697
+ }
698
+ /**
699
+ * Handles messages received from the sorting worker.
700
+ * @param event The message event from the worker.
701
+ */
702
+ onWorkerMessage(s) {
703
+ if (!this.orderTexture || !this.orderTexture.image)
704
+ return console.error("SplatSorter: Order texture not initialized!");
705
+ const { order: o, count: n } = s.data, t = this.orderTexture.image.data;
706
+ if (!(t instanceof Uint32Array))
707
+ return console.error(
708
+ "SplatSorter: Order texture data is not a Uint32Array!"
709
+ );
710
+ t.set(new Uint32Array(o)), this.orderTexture.needsUpdate = !0;
711
+ const a = t.buffer.slice(0), c = { order: a };
712
+ this.worker.postMessage(c, [a]), this.dispatchEvent({ type: "updated", count: n });
713
+ }
714
+ /**
715
+ * Initializes the sorter with necessary data and textures.
716
+ * @param orderTexture The THREE.DataTexture (R32UI) to store the sorted splat indices.
717
+ * @param centers A Float32Array containing the center position (x, y, z) for each splat.
718
+ * @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
719
+ */
720
+ init(s, o, n) {
721
+ if (!s || !(s.image.data instanceof Uint32Array))
722
+ throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
723
+ if (!o || o.length % 3 !== 0)
724
+ throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");
725
+ if (s.image.data.length < o.length / 3)
726
+ throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
727
+ const t = o.length / 3;
728
+ this.orderTexture = s, this.centers = o.slice();
729
+ const a = this.orderTexture.image.data;
730
+ for (let b = 0; b < t; b++) a[b] = b;
731
+ this.orderTexture.needsUpdate = !0;
732
+ const c = a.buffer.slice(0), l = this.centers.buffer.slice(0), m = {
733
+ order: c,
734
+ centers: l
735
+ }, M = [
736
+ c,
737
+ l
738
+ ];
739
+ if (n) {
740
+ this.chunks = n.slice();
741
+ const b = this.chunks.buffer.slice(0);
742
+ m.chunks = b, M.push(b);
743
+ }
744
+ this.worker.postMessage(m, M);
745
+ }
746
+ /**
747
+ * Applies an optional mapping to filter or reorder splats before sorting.
748
+ * The sorter will only consider splats whose original indices are present in the mapping.
749
+ * @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
750
+ */
751
+ setMapping(s) {
752
+ if (!this.centers)
753
+ return console.warn(
754
+ "SplatSorter: Cannot set mapping before initialization."
275
755
  );
756
+ let o;
757
+ const n = [];
758
+ if (!s) {
759
+ const l = this.centers.buffer.slice(0);
760
+ return o = {
761
+ centers: l,
762
+ mapping: null
763
+ }, n.push(l), this.worker.postMessage(o, n);
764
+ }
765
+ const t = new Float32Array(s.length * 3);
766
+ for (let l = 0; l < s.length; l++) {
767
+ const m = s[l];
768
+ if (m * 3 + 2 >= this.centers.length) {
769
+ console.warn(
770
+ `SplatSorter: Mapping index ${m} out of bounds.`
771
+ );
772
+ continue;
773
+ }
774
+ const M = m * 3, b = l * 3;
775
+ t[b + 0] = this.centers[M + 0], t[b + 1] = this.centers[M + 1], t[b + 2] = this.centers[M + 2];
776
+ }
777
+ const a = t.buffer.slice(0), c = s.buffer.slice(0);
778
+ o = {
779
+ centers: a,
780
+ mapping: c
781
+ }, n.push(a, c), this.worker.postMessage(o, n);
782
+ }
783
+ /**
784
+ * Updates the camera parameters used for sorting.
785
+ * @param position The camera's position in the sorter's local coordinate space.
786
+ * @param direction The camera's forward direction in the sorter's local coordinate space.
787
+ */
788
+ setCamera(s, o) {
789
+ const n = this.lastCameraPosition.distanceToSquared(s) > 1e-7, t = this.lastCameraDirection.dot(o) < 0.9999;
790
+ if (!n && !t)
791
+ return;
792
+ this.lastCameraPosition.copy(s), this.lastCameraDirection.copy(o);
793
+ const a = {
794
+ cameraPosition: { x: s.x, y: s.y, z: s.z },
795
+ cameraDirection: { x: o.x, y: o.y, z: o.z }
276
796
  };
277
- }()), b;
797
+ this.worker.postMessage(a);
798
+ }
799
+ /**
800
+ * Terminates the Web Worker and cleans up resources.
801
+ */
802
+ dispose() {
803
+ this.worker && this.worker.terminate(), this.orderTexture = null, this.centers = null, this.chunks = null;
804
+ }
805
+ /**
806
+ * Creates the self-contained code for the sorting Web Worker.
807
+ * @returns A string containing the JavaScript code for the worker.
808
+ */
809
+ createWorkerCode() {
810
+ return `(${(function() {
811
+ let o = null, n = null, t = null, a = null, c = null, l = null, m = !1;
812
+ const M = { x: 0, y: 0, z: 0 }, b = { x: 0, y: 0, z: 0 }, p = { x: 0, y: 0, z: 0 }, x = { x: 0, y: 0, z: 0 };
813
+ let d = null, S = null;
814
+ const O = 32, j = new Array(O).fill(0), W = new Array(O).fill(0), q = new Array(O).fill(0), H = (D, k, F) => {
815
+ for (; D <= k; ) {
816
+ const C = k + D >> 1, w = F(C);
817
+ if (w > 0) D = C + 1;
818
+ else if (w < 0) k = C - 1;
819
+ else return C;
820
+ }
821
+ return ~D;
822
+ }, $ = () => {
823
+ if (!o || !n || !c || !l)
824
+ return;
825
+ if (n.length === 0) {
826
+ const h = {
827
+ order: o.buffer,
828
+ count: 0
829
+ };
830
+ self.postMessage(h, [o.buffer]), o = null;
831
+ return;
832
+ }
833
+ const D = c.x, k = c.y, F = c.z, C = l.x, w = l.y, P = l.z, V = 1e-4, U = Math.abs(D - M.x) > V || Math.abs(k - M.y) > V || Math.abs(F - M.z) > V, g = Math.abs(C - b.x) > V || Math.abs(w - b.y) > V || Math.abs(P - b.z) > V;
834
+ if (!m && !U && !g)
835
+ return;
836
+ m = !1, M.x = D, M.y = k, M.z = F, b.x = C, b.y = w, b.z = P;
837
+ let y = 1 / 0, A = -1 / 0;
838
+ for (let h = 0; h < 8; ++h) {
839
+ const I = h & 1 ? p.x : x.x, B = h & 2 ? p.y : x.y, u = h & 4 ? p.z : x.z, _ = I * C + B * w + u * P;
840
+ y = Math.min(y, _), A = Math.max(A, _);
841
+ }
842
+ const E = n.length / 3, L = A - y, r = (1 << Math.max(
843
+ 10,
844
+ Math.min(20, Math.ceil(Math.log2(E / 4)))
845
+ )) + 1;
846
+ if ((!d || d.length !== E) && (d = new Uint32Array(E)), !S || S.length !== r ? S = new Uint32Array(r) : S.fill(0), L < 1e-7) {
847
+ for (let h = 0; h < E; ++h) d[h] = 0;
848
+ S[0] = E;
849
+ } else if (t && t.length > 0) {
850
+ const h = t.length / 6;
851
+ j.fill(0);
852
+ for (let u = 0; u < h; ++u) {
853
+ const _ = u * 6, Y = t[_ + 0], G = t[_ + 1], ne = t[_ + 2], Z = t[_ + 3], X = Y * C + G * w + ne * P - y, oe = X - Z, ee = X + Z, ie = Math.max(
854
+ 0,
855
+ Math.floor(oe * O / L)
856
+ ), ce = Math.min(
857
+ O,
858
+ Math.ceil(ee * O / L)
859
+ );
860
+ for (let Q = ie; Q < ce; ++Q)
861
+ j[Q]++;
862
+ }
863
+ let I = 0;
864
+ for (let u = 0; u < O; ++u) I += j[u];
865
+ q[0] = 0, W[0] = 0;
866
+ for (let u = 1; u < O; ++u)
867
+ q[u - 1] = j[u - 1] / I * r >>> 0, W[u] = W[u - 1] + q[u - 1];
868
+ q[O - 1] = j[O - 1] / I * r >>> 0;
869
+ const B = L / O;
870
+ for (let u = 0; u < E; ++u) {
871
+ const _ = u * 3, Y = n[_ + 0], G = n[_ + 1], ne = n[_ + 2], Z = Y * C + G * w + ne * P, oe = (A - Z) / B, ee = Math.max(
872
+ 0,
873
+ Math.min(
874
+ O - 1,
875
+ Math.floor(oe)
876
+ )
877
+ ), ie = oe - ee, ce = W[ee] + q[ee] * ie >>> 0, Q = Math.min(ce, r - 1);
878
+ d[u] = Q, S[Q]++;
879
+ }
880
+ } else {
881
+ const h = (r - 1) / L;
882
+ for (let I = 0; I < E; ++I) {
883
+ const B = I * 3, u = n[B + 0], _ = n[B + 1], Y = n[B + 2], G = u * C + _ * w + Y * P, Z = (A - G) * h >>> 0, X = Math.min(Z, r - 1);
884
+ d[I] = X, S[X]++;
885
+ }
886
+ }
887
+ for (let h = 1; h < r; h++)
888
+ S[h] += S[h - 1];
889
+ for (let h = E - 1; h >= 0; h--) {
890
+ const I = d[h], B = --S[I];
891
+ o[B] = a ? a[h] : h;
892
+ }
893
+ const f = D * C + k * w + F * P, T = (h) => {
894
+ if (!o) return -1 / 0;
895
+ const I = o[h], B = I;
896
+ if (!n || B * 3 + 2 >= n.length)
897
+ return -1 / 0;
898
+ const u = B * 3;
899
+ return n[u] * C + n[u + 1] * w + n[u + 2] * P - f;
900
+ };
901
+ let R = E;
902
+ if (E > 0 && T(E - 1) < 0) {
903
+ const h = H(
904
+ 0,
905
+ E - 1,
906
+ T
907
+ );
908
+ R = h < 0 ? ~h : h;
909
+ }
910
+ const N = {
911
+ order: o.buffer,
912
+ count: R
913
+ };
914
+ self.postMessage(N, [o.buffer]), o = null;
915
+ };
916
+ self.onmessage = (D) => {
917
+ const k = D.data;
918
+ k.order && (o = new Uint32Array(k.order));
919
+ let F = !1;
920
+ if (k.centers && (n = new Float32Array(k.centers), F = !0, m = !0), Object.prototype.hasOwnProperty.call(k, "mapping") && (a = k.mapping ? new Uint32Array(k.mapping) : null, m = !0), k.chunks) {
921
+ if (t = new Float32Array(k.chunks), t.length > 0 && t[3] > 0)
922
+ for (let C = 0; C < t.length / 6; ++C) {
923
+ const w = C * 6, P = t[w + 0], V = t[w + 1], U = t[w + 2], g = t[w + 3], y = t[w + 4], A = t[w + 5];
924
+ t[w + 0] = (P + g) * 0.5, t[w + 1] = (V + y) * 0.5, t[w + 2] = (U + A) * 0.5, t[w + 3] = Math.sqrt(
925
+ (g - P) ** 2 + (y - V) ** 2 + (A - U) ** 2
926
+ ) * 0.5;
927
+ }
928
+ m = !0;
929
+ }
930
+ if (F && n && n.length > 0) {
931
+ p.x = x.x = n[0], p.y = x.y = n[1], p.z = x.z = n[2];
932
+ for (let C = 1; C < n.length / 3; C++) {
933
+ const w = C * 3;
934
+ p.x = Math.min(p.x, n[w + 0]), x.x = Math.max(x.x, n[w + 0]), p.y = Math.min(p.y, n[w + 1]), x.y = Math.max(x.y, n[w + 1]), p.z = Math.min(p.z, n[w + 2]), x.z = Math.max(x.z, n[w + 2]);
935
+ }
936
+ } else F && n && n.length === 0 && (p.x = x.x = p.y = x.y = p.z = x.z = 0);
937
+ k.cameraPosition && (c = k.cameraPosition), k.cameraDirection && (l = k.cameraDirection), $();
938
+ };
939
+ }).toString()})();`;
940
+ }
941
+ }
942
+ const Ee = (z, e) => {
943
+ const s = Math.max(
944
+ 0,
945
+ Math.min(65535, Math.round((z + 1) / 2 * 65535))
946
+ ), o = Math.max(
947
+ 0,
948
+ Math.min(65535, Math.round((e + 1) / 2 * 65535))
949
+ );
950
+ return s << 16 | o;
951
+ }, Re = new ArrayBuffer(4), fe = new DataView(Re), Ie = (z) => (fe.setUint32(0, z, !0), fe.getFloat32(0, !0));
952
+ class Pe {
953
+ /**
954
+ * Create a new TextureManager for a set of splats
955
+ * @param splatData The splat data to manage textures for
956
+ */
957
+ constructor(e) {
958
+ v(this, "transformA");
959
+ // position xyz and rotation quaternion y,z components
960
+ v(this, "transformB");
961
+ // rotation quaternion x and scale xyz
962
+ v(this, "colorTexture");
963
+ // color an opacity
964
+ v(this, "orderTexture");
965
+ v(this, "textureWidth");
966
+ v(this, "textureHeight");
967
+ const s = e.numSplats;
968
+ this.textureWidth = Math.ceil(Math.sqrt(s)), this.textureHeight = Math.ceil(s / this.textureWidth), this.transformA = this.createTransformATexture(e), this.transformB = this.createTransformBTexture(e), this.colorTexture = this.createColorTexture(e), this.orderTexture = this.createOrderTexture(s);
969
+ }
970
+ /**
971
+ * Create the transform A texture (positions and quaternion w component)
972
+ * @param splatData The splat data
973
+ * @returns DataTexture containing position data
974
+ */
975
+ createTransformATexture(e) {
976
+ const s = e.numSplats, o = new Float32Array(
977
+ this.textureWidth * this.textureHeight * 4
978
+ );
979
+ for (let t = 0; t < s; t++) {
980
+ const a = t * 4, c = t * 3, l = t * 4;
981
+ o[a] = e.positions[c], o[a + 1] = e.positions[c + 1], o[a + 2] = e.positions[c + 2];
982
+ const m = e.rotations[l + 1], M = e.rotations[l + 2], b = Ee(m, M);
983
+ o[a + 3] = Ie(b);
984
+ }
985
+ const n = new i.DataTexture(
986
+ o,
987
+ this.textureWidth,
988
+ this.textureHeight,
989
+ i.RGBAFormat,
990
+ i.FloatType
991
+ // Store as Float32, shader will reinterpret bits
992
+ );
993
+ return n.needsUpdate = !0, n.magFilter = i.NearestFilter, n.minFilter = i.NearestFilter, n;
994
+ }
995
+ /**
996
+ * Create the transform B texture (scale and rotation xyz)
997
+ * @param splatData The splat data
998
+ * @returns DataTexture containing scale and rotation data
999
+ */
1000
+ createTransformBTexture(e) {
1001
+ const s = e.numSplats, o = new Float32Array(
1002
+ this.textureWidth * this.textureHeight * 4
1003
+ );
1004
+ for (let t = 0; t < s; t++) {
1005
+ const a = t * 4, c = t * 3, l = t * 4;
1006
+ o[a] = e.scales[c], o[a + 1] = e.scales[c + 1], o[a + 2] = e.scales[c + 2], o[a + 3] = e.rotations[l];
1007
+ }
1008
+ const n = new i.DataTexture(
1009
+ o,
1010
+ this.textureWidth,
1011
+ this.textureHeight,
1012
+ i.RGBAFormat,
1013
+ i.FloatType
1014
+ );
1015
+ return n.needsUpdate = !0, n.magFilter = i.NearestFilter, n.minFilter = i.NearestFilter, n;
1016
+ }
1017
+ /**
1018
+ * Create the color texture (RGB and opacity)
1019
+ * @param splatData The splat data
1020
+ * @returns DataTexture containing color data
1021
+ */
1022
+ createColorTexture(e) {
1023
+ const s = e.numSplats, o = new Float32Array(
1024
+ this.textureWidth * this.textureHeight * 4
1025
+ );
1026
+ for (let t = 0; t < s; t++) {
1027
+ const a = t * 4, c = t * 3;
1028
+ o[a] = e.colors[c], o[a + 1] = e.colors[c + 1], o[a + 2] = e.colors[c + 2], o[a + 3] = e.opacities[t];
1029
+ }
1030
+ const n = new i.DataTexture(
1031
+ o,
1032
+ this.textureWidth,
1033
+ this.textureHeight,
1034
+ i.RGBAFormat,
1035
+ i.FloatType
1036
+ );
1037
+ return n.needsUpdate = !0, n;
1038
+ }
1039
+ /**
1040
+ * Create the order texture for sorting
1041
+ * @param numSplats Number of splats
1042
+ * @returns DataTexture for storing order indices
1043
+ */
1044
+ createOrderTexture(e) {
1045
+ const s = new Uint32Array(this.textureWidth * this.textureHeight);
1046
+ for (let n = 0; n < e; n++)
1047
+ s[n] = n;
1048
+ const o = new i.DataTexture(
1049
+ s,
1050
+ this.textureWidth,
1051
+ this.textureHeight,
1052
+ i.RedIntegerFormat,
1053
+ i.UnsignedIntType
1054
+ );
1055
+ return o.needsUpdate = !0, o;
1056
+ }
1057
+ dispose() {
1058
+ this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
1059
+ }
1060
+ }
1061
+ const Oe = (
1062
+ /* glsl */
1063
+ `
1064
+ precision highp float;
1065
+ precision highp int;
1066
+ precision highp usampler2D;
1067
+ precision highp sampler2D;
1068
+
1069
+ // --- Uniforms (Provided by Three.js) ---
1070
+ // uniform mat4 modelViewMatrix; // Don't redeclare
1071
+ // uniform mat4 projectionMatrix; // Don't redeclare
1072
+ uniform vec2 viewport; // Viewport dimensions (width, height)
1073
+ uniform uint numSplats; // Total number of splats potentially renderable by sorter
1074
+
1075
+ // Textures
1076
+ uniform highp sampler2D transformA; // vec4: pos.xyz, packed_rot.yz
1077
+ uniform highp sampler2D transformB; // vec4: log_scale.xyz, rot.x
1078
+ uniform highp sampler2D splatColor; // vec4: color.rgb, opacity
1079
+ uniform highp usampler2D splatOrder; // uint: original splat index
1080
+
1081
+ // --- Attributes ---
1082
+ // Instancing attribute: base index for this block of splats
1083
+ attribute uint splatInstanceIndex;
1084
+
1085
+ // Per-vertex attribute of the quad (Built-in, don't redeclare 'position')
1086
+ // attribute vec3 position; // Use the built-in 'position'
1087
+ // position.xy: corner coords (-1..1)
1088
+ // position.z: index within the instance block (0..INSTANCE_BUFFER_SIZE-1)
1089
+
1090
+ // --- Varyings ---
1091
+ varying vec4 vColor;
1092
+ varying vec2 vUv; // For gaussian calculation in fragment shader
1093
+
1094
+ // --- Constants ---
1095
+ #define INSTANCE_BUFFER_SIZE 128.0 // Must match the size in SplatMesh
1096
+
1097
+ // --- Helper Functions ---
1098
+
1099
+ // Unpack two 16-bit floats (halfs) from a single 32-bit float (packed as uint bits)
1100
+ vec2 unpackHalf2x16FromFloat(float packedFloat) {
1101
+ uint packedUInt = floatBitsToUint(packedFloat);
1102
+ uint y_bits = packedUInt >> 16;
1103
+ uint z_bits = packedUInt & uint(0xFFFF);
1104
+
1105
+ // NOTE: This assumes packing used "packNormalizedFloatToUint16Pair"
1106
+ // which maps [-1, 1] to [0, 65535]. Adjust if packing method changes.
1107
+ float y = (float(y_bits) / 65535.0) * 2.0 - 1.0;
1108
+ float z = (float(z_bits) / 65535.0) * 2.0 - 1.0;
1109
+ return vec2(y, z);
1110
+ }
1111
+
1112
+ // Reconstruct quaternion from packed components (x, yz_packed)
1113
+ vec4 unpackRotation(float yz_packed, float x) {
1114
+ vec2 yz = unpackHalf2x16FromFloat(yz_packed);
1115
+ float y = yz.x;
1116
+ float z = yz.y;
1117
+ float w_squared = 1.0 - x*x - y*y - z*z;
1118
+ float w = (w_squared < 0.0) ? 0.0 : sqrt(w_squared); // Calculate w
1119
+ return vec4(x, y, z, w);
278
1120
  }
279
- var $;
280
- function fe() {
281
- return $ || ($ = 1, process.env.NODE_ENV === "production" ? _.exports = ce() : _.exports = ie()), _.exports;
1121
+
1122
+ // Convert quaternion to 3x3 rotation matrix
1123
+ mat3 quatToMat3(vec4 q) {
1124
+ float x = q.x, y = q.y, z = q.z, w = q.w;
1125
+ float x2 = x + x, y2 = y + y, z2 = z + z;
1126
+ float xx = x * x2, xy = x * y2, xz = x * z2;
1127
+ float yy = y * y2, yz = y * z2, zz = z * z2;
1128
+ float wx = w * x2, wy = w * y2, wz = w * z2;
1129
+
1130
+ return mat3(
1131
+ 1.0 - (yy + zz), xy + wz, xz - wy,
1132
+ xy - wz, 1.0 - (xx + zz), yz + wx,
1133
+ xz + wy, yz - wx, 1.0 - (xx + yy)
1134
+ );
282
1135
  }
283
- var de = fe();
284
- let D = !1;
285
- typeof window < "u" && !D && (se({ splatPrimitive: L }), D = !0);
286
- const Re = ({
287
- plyUrl: c,
288
- splatOptions: d = {},
289
- ...m
1136
+
1137
+ // Calculate model-space covariance components R * S^2 * transpose(R)
1138
+ void getModelCovariance(vec3 scale, vec4 rotation, out vec3 covA, out vec3 covB) {
1139
+ mat3 R = quatToMat3(rotation);
1140
+
1141
+ // Define M = R * S (where S is the diagonal scale matrix)
1142
+ // Note R is column-major, so R[0] is the first column, etc.
1143
+ // We want M's rows to be R's rows scaled by the corresponding scale factor.
1144
+ mat3 M = mat3(
1145
+ R[0][0] * scale.x, R[0][1] * scale.y, R[0][2] * scale.z, // Row 0 = (R_row0 * S)
1146
+ R[1][0] * scale.x, R[1][1] * scale.y, R[1][2] * scale.z, // Row 1 = (R_row1 * S)
1147
+ R[2][0] * scale.x, R[2][1] * scale.y, R[2][2] * scale.z // Row 2 = (R_row2 * S)
1148
+ );
1149
+
1150
+ // Now compute Vrk = M * transpose(M)
1151
+ // Vrk[i][j] = dot(M[i], M[j]) where M[i] is the i-th row vector of M.
1152
+ covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2])); // Vrk[0][0], Vrk[0][1], Vrk[0][2]
1153
+ covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2])); // Vrk[1][1], Vrk[1][2], Vrk[2][2]
1154
+ }
1155
+
1156
+ // --- Main Function ---
1157
+ void main(void) {
1158
+ // Calculate the final splat index for this vertex
1159
+ uint instanceOffset = uint(position.z); // Read index within instance from Z
1160
+ uint orderedSplatIndex = splatInstanceIndex + instanceOffset;
1161
+
1162
+ // Discard if this splat index is beyond the sorted count
1163
+ if (orderedSplatIndex >= numSplats) {
1164
+ gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Off-screen
1165
+ return;
1166
+ }
1167
+
1168
+ // --- Source Data Lookup ---
1169
+ uint texWidth = uint(textureSize(splatOrder, 0).x);
1170
+ ivec2 orderUV = ivec2(orderedSplatIndex % texWidth, orderedSplatIndex / texWidth);
1171
+ uint originalSplatIndex = texelFetch(splatOrder, orderUV, 0).r;
1172
+
1173
+ ivec2 dataUV = ivec2(originalSplatIndex % texWidth, originalSplatIndex / texWidth);
1174
+
1175
+ // Fetch data from textures
1176
+ vec4 texTransformA = texelFetch(transformA, dataUV, 0);
1177
+ vec4 texTransformB = texelFetch(transformB, dataUV, 0);
1178
+ vec4 texColor = texelFetch(splatColor, dataUV, 0);
1179
+
1180
+ vec3 splatPosition = texTransformA.xyz;
1181
+ vec3 splatLogScale = texTransformB.xyz; // Assume stored as log scale
1182
+ vec4 splatRotation = unpackRotation(texTransformA.w, texTransformB.w); // Unpack rot yz, x
1183
+ vec3 splatColor = texColor.rgb;
1184
+ float splatOpacity = texColor.a;
1185
+
1186
+ vec3 splatScale = exp(splatLogScale); // Convert log scale to actual scale
1187
+
1188
+ // --- Center Projection ---
1189
+
1190
+ // Compute normalized view-space center
1191
+ vec4 centerClipRaw = modelViewMatrix * vec4(splatPosition, 1.0);
1192
+ vec3 centerView = centerClipRaw.xyz / centerClipRaw.w;
1193
+
1194
+ // Early out if splat is behind the camera
1195
+ if (centerView.z > -0.2) { // Use small epsilon
1196
+ gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
1197
+ return;
1198
+ }
1199
+
1200
+ // Project to clip space
1201
+ vec4 centerClip = projectionMatrix * centerClipRaw;
1202
+
1203
+ // --- Covariance Calculation & Projection ---
1204
+
1205
+ // Calculating model space covariance (Vrk)
1206
+ vec3 covA, covB;
1207
+ getModelCovariance(splatScale, splatRotation, covA, covB);
1208
+ mat3 Vrk = mat3(
1209
+ covA.x, covA.y, covA.z,
1210
+ covA.y, covB.x, covB.y, // covB.x is Vrk[1][1]
1211
+ covA.z, covB.y, covB.z // covB.y is Vrk[1][2], covB.z is Vrk[2][2]
1212
+ );
1213
+
1214
+ // Calculate Jacobian J (screen space change wrt view space change)
1215
+ // Requres focal lenghts and view-space center depth (tz)
1216
+ float focalX = viewport.x * projectionMatrix[0][0];
1217
+ float focalY = viewport.y * projectionMatrix[1][1];
1218
+ float tz = centerView.z;
1219
+ float tz2 = tz * tz;
1220
+
1221
+ // Jacobian J = [fx/tz, 0, -fx*tx/tz^2]
1222
+ // [0, fy/tz, -fy*ty/tz^2]
1223
+ mat3 J = mat3(
1224
+ focalX / tz, 0.0, -focalX * centerView.x / tz2,
1225
+ 0.0, focalY / tz, -focalY * centerView.y / tz2,
1226
+ 0.0, 0.0, 0.0
1227
+ );
1228
+
1229
+ // Calculate W
1230
+ mat3 W = transpose(mat3(modelViewMatrix));
1231
+ // Calculate T = W * J
1232
+ mat3 T = W * J;
1233
+ // Calculate Projected 2D Covariance: SigmaProj = transpose(T) * Vrk * T
1234
+ mat3 SigmaProj = transpose(T) * Vrk * T;
1235
+
1236
+ // Extract 2D components and add bias
1237
+ float cov2D_11 = SigmaProj[0][0] + 0.3;
1238
+ float cov2D_12 = SigmaProj[0][1];
1239
+ float cov2D_22 = SigmaProj[1][1] + 0.3;
1240
+
1241
+ // --- Calculate 2D Screen Space Rotation & Scale ---
1242
+
1243
+ float det = cov2D_11 * cov2D_22 - cov2D_12 * cov2D_12;
1244
+ // Ensure determinant is non-negative before sqrt
1245
+ if (det <= 0.0) {
1246
+ gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Discard degenerated
1247
+ return;
1248
+ }
1249
+
1250
+ float trace = cov2D_11 + cov2D_22;
1251
+ float traceOver2 = 0.5 * trace;
1252
+ float discriminantSqrt = sqrt(max(traceOver2 * traceOver2 - det, 0.0)); // Avoid sqrt(negative)
1253
+
1254
+ float lambda1 = traceOver2 + discriminantSqrt; // Larger eigenvalue
1255
+ float lambda2 = max(0.1, traceOver2 - discriminantSqrt); // Smaller eigenvalue, clamped
1256
+
1257
+ // Compute eigenvectors
1258
+
1259
+ vec2 v1_eigen, v2_eigen;
1260
+
1261
+ // Handle diagonal case
1262
+ if(abs(cov2D_12) < 1e-16) {
1263
+ v1_eigen = vec2(1.0, 0.0);
1264
+ } else {
1265
+ v1_eigen = normalize(vec2(cov2D_12, lambda1 - cov2D_11)); // diagonal choice
1266
+ }
1267
+
1268
+ v2_eigen = vec2(-v1_eigen.y, v1_eigen.x); // Perpendicular eigenvector
1269
+
1270
+ // Calculate SCALED vectors (l1, l2, incorparate factor)
1271
+ float scaleFactor = 2.0 * sqrt(2.0); // ~2.8284
1272
+ float l1 = sqrt(lambda1) * scaleFactor; // scaleX
1273
+ float l2 = sqrt(lambda2) * scaleFactor; // scaleY
1274
+
1275
+ // Early out tiny splats
1276
+ if (l1 < 2.0 && l2 < 2.0) { // Check if smaller than ~2 pixel
1277
+ gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
1278
+ return;
1279
+ }
1280
+
1281
+ // Scaled eigenvectors for offset calculation
1282
+ vec2 v1_scaled = l1 * v1_eigen;
1283
+ vec2 v2_scaled = l2 * v2_eigen;
1284
+
1285
+ // --- FRUSTUM CHECK ---
1286
+
1287
+ vec2 clipRadius = vec2(max(l1, l2)) * (centerClip.w / viewport);
1288
+
1289
+ // Check if the bounding circle's edge is outside the [-w, w] range in clip space for x or y
1290
+ if (any(greaterThan(abs(centerClip.xy) + clipRadius, vec2(abs(centerClip.w))))) {
1291
+ gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Off-screen
1292
+ return;
1293
+ }
1294
+
1295
+ // --- END FRUSTUM CHECK ---
1296
+
1297
+ // --- Final Vertex Position ---
1298
+
1299
+ vec2 cornerOffset = position.xy; // (-1,-1) to (1,1)
1300
+
1301
+ // Clip the quad so only high-alpha core is visible
1302
+ float alpha = max(splatOpacity, 1e-6); // avoid log(0)
1303
+ float clip = min(1.0, sqrt(-log(1.0 / 255.0 / alpha)) / 2.0);
1304
+
1305
+ // Apply clip to the corner offset *before* calculating screen space offset
1306
+ vec2 clippedCornerOffset = cornerOffset * clip;
1307
+ vec2 screenOffsetPixels = clippedCornerOffset.x * v1_scaled + clippedCornerOffset.y * v2_scaled;
1308
+ //vec2 screenOffsetPixels = vec2(clippedCornerOffset.x, clippedCornerOffset.y);
1309
+
1310
+ // Convert pixel offset to clip space offset
1311
+ vec2 clipOffset = screenOffsetPixels * (centerClip.w / viewport);
1312
+
1313
+
1314
+ // Apply offset to center clip position
1315
+ gl_Position = centerClip + vec4(clipOffset, 0.0, 0.0);
1316
+
1317
+ // --- Pass data to Fragment Shader ---
1318
+
1319
+ vColor = vec4(splatColor, splatOpacity);
1320
+ vUv = clippedCornerOffset;
1321
+ }
1322
+ `
1323
+ ), Fe = (
1324
+ /* glsl */
1325
+ `
1326
+ precision highp float;
1327
+
1328
+ varying vec4 vColor; // Color and opacity passed from vertex shader
1329
+ varying vec2 vUv; // Quad UV coordinates (-1 to 1) passed from vertex shader
1330
+
1331
+ void main(void) {
1332
+
1333
+ float distSq = dot(vUv, vUv); // Calculate squared distance from center (in the quad's coordinate system)
1334
+ if (distSq > 1.0) discard; // Discard fragments outside the circle inscribed in the quad
1335
+
1336
+ // Calculate Gaussian function: alpha = opacity * exp(-distSq * factor)
1337
+ // The factor 4.0 corresponds to the original implementation's scaling.
1338
+ // factor = 1 / (2 * sigma^2), where sigma controls the spread.
1339
+ // Using 4.0 implies sigma^2 = 1/8.
1340
+ float alpha = exp(-distSq * 4.0) * vColor.a;
1341
+
1342
+ if (alpha < 1.0 / 255.0) discard; // Discard fragments with very low alpha
1343
+
1344
+ // Premultiply color by alpha (required for correct blending)
1345
+ gl_FragColor = vec4(vColor.rgb * alpha, alpha);
1346
+ }
1347
+ `
1348
+ );
1349
+ class Be extends i.ShaderMaterial {
1350
+ constructor(e = {}) {
1351
+ const s = {
1352
+ // Textures (values set via methods)
1353
+ transformA: { value: null },
1354
+ transformB: { value: null },
1355
+ splatColor: { value: null },
1356
+ splatOrder: { value: null },
1357
+ // Other uniforms
1358
+ viewport: { value: new i.Vector2(1, 1) },
1359
+ // Will be updated
1360
+ numSplats: { value: 0 }
1361
+ // Max splats to render (updated by sorter)
1362
+ };
1363
+ super({
1364
+ vertexShader: Oe,
1365
+ fragmentShader: Fe,
1366
+ uniforms: s,
1367
+ transparent: !0,
1368
+ blending: i.CustomBlending,
1369
+ // Premultiplied alpha blending:
1370
+ // color = src_color * src_alpha + dst_color * (1 - src_alpha)
1371
+ // alpha = src_alpha * 1 + dst_alpha * (1 - src_alpha)
1372
+ blendSrc: i.OneFactor,
1373
+ // Using ONE because shader outputs premultiplied color (color * alpha)
1374
+ blendDst: i.OneMinusSrcAlphaFactor,
1375
+ blendSrcAlpha: i.OneFactor,
1376
+ // source alpha comes from shader
1377
+ blendDstAlpha: i.OneMinusSrcAlphaFactor,
1378
+ blendEquation: i.AddEquation,
1379
+ blendEquationAlpha: i.AddEquation,
1380
+ depthTest: !0,
1381
+ depthWrite: !1,
1382
+ // Disable depth write for transparency
1383
+ side: i.DoubleSide,
1384
+ // Render both sides (or CULLFACE_NONE equivalent)
1385
+ // Optional settings from constructor
1386
+ alphaTest: e.alphaTest !== void 0 ? e.alphaTest : 0,
1387
+ // Typically 0 for blending
1388
+ toneMapped: e.toneMapped !== void 0 ? e.toneMapped : !1
1389
+ // prettier-ignore
1390
+ }), e.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = i.NoBlending);
1391
+ }
1392
+ /**
1393
+ * Update the viewport size
1394
+ * @param width Viewport width
1395
+ * @param height Viewport height
1396
+ */
1397
+ updateViewport(e, s) {
1398
+ this.uniforms.viewport.value.set(e, s);
1399
+ }
1400
+ /**
1401
+ * Set transform texture A (positions)
1402
+ * @param texture Texture containing positions
1403
+ */
1404
+ setTransformA(e) {
1405
+ this.uniforms.transformA.value = e;
1406
+ }
1407
+ /**
1408
+ * Set transform texture B (rotation, scale)
1409
+ * @param texture Texture containing rotation and scale data
1410
+ */
1411
+ setTransformB(e) {
1412
+ this.uniforms.transformB.value = e;
1413
+ }
1414
+ /**
1415
+ * Set color texture
1416
+ * @param texture Texture containing colors
1417
+ */
1418
+ setColorTexture(e) {
1419
+ this.uniforms.splatColor.value = e;
1420
+ }
1421
+ /**
1422
+ * Set order texture
1423
+ * @param texture Texture containing sort order
1424
+ */
1425
+ setOrderTexture(e) {
1426
+ this.uniforms.splatOrder.value = e;
1427
+ }
1428
+ /**
1429
+ * Set number of splats to render
1430
+ * @param count Number of splats
1431
+ */
1432
+ setNumSplats(e) {
1433
+ this.uniforms.numSplats.value = e;
1434
+ }
1435
+ }
1436
+ const K = class K extends i.Mesh {
1437
+ // Match shader constant
1438
+ /**
1439
+ * Create a new SplatMesh for rendering Gaussian splats
1440
+ * @param splatData The splat data to render
1441
+ * @param options Rendering options
1442
+ */
1443
+ constructor(s, o = {}) {
1444
+ const n = new Be(o), t = K.createInstancedGeometry(s.numSplats, K.INSTANCE_SIZE);
1445
+ super(t, n);
1446
+ v(this, "sorter");
1447
+ v(this, "splatData");
1448
+ v(this, "options");
1449
+ v(this, "textureManager");
1450
+ v(this, "material");
1451
+ v(this, "geometry");
1452
+ v(this, "lastCameraPositionLocal", new i.Vector3());
1453
+ v(this, "lastCameraDirectionLocal", new i.Vector3());
1454
+ v(this, "invModelMatrix", new i.Matrix4());
1455
+ this.geometry = t, this.material = n, this.splatData = s, this.frustumCulled = !1, this.options = { autoSort: !0, ...o }, this.textureManager = new Pe(s), this.sorter = new _e();
1456
+ let a = this.createChunks() || void 0;
1457
+ a === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), a = void 0, this.sorter.init(
1458
+ this.textureManager.orderTexture,
1459
+ this.splatData.centers,
1460
+ a ?? void 0
1461
+ ), this.sorter.addEventListener(
1462
+ "updated",
1463
+ (c) => {
1464
+ const l = c.count;
1465
+ this.geometry.instanceCount = Math.ceil(l / K.INSTANCE_SIZE), this.material.setNumSplats(l);
1466
+ }
1467
+ ), 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 i.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
1468
+ }
1469
+ /**
1470
+ * Creates the instanced geometry for rendering splats.
1471
+ * @param totalSplats Total number of splats in the data.
1472
+ * @param instanceSize Number of splats per instance.
1473
+ * @returns InstancedBufferGeometry
1474
+ */
1475
+ static createInstancedGeometry(s, o) {
1476
+ const n = Math.ceil(s / o), t = new i.BufferGeometry(), a = new Float32Array([
1477
+ // x, y, splat_index_in_instance
1478
+ -1,
1479
+ -1,
1480
+ 0,
1481
+ 1,
1482
+ -1,
1483
+ 0,
1484
+ 1,
1485
+ 1,
1486
+ 0,
1487
+ -1,
1488
+ 1,
1489
+ 0
1490
+ ]), c = new Uint16Array([0, 1, 2, 0, 2, 3]), l = new Float32Array(4 * 3 * o);
1491
+ for (let p = 0; p < o; p++) {
1492
+ const x = p * 4 * 3;
1493
+ for (let d = 0; d < 4; d++)
1494
+ l[x + d * 3 + 0] = a[d * 3 + 0], l[x + d * 3 + 1] = a[d * 3 + 1], l[x + d * 3 + 2] = p;
1495
+ }
1496
+ const m = new Uint32Array(6 * o);
1497
+ for (let p = 0; p < o; p++) {
1498
+ const x = p * 6, d = p * 4;
1499
+ m[x + 0] = c[0] + d, m[x + 1] = c[1] + d, m[x + 2] = c[2] + d, m[x + 3] = c[3] + d, m[x + 4] = c[4] + d, m[x + 5] = c[5] + d;
1500
+ }
1501
+ t.setAttribute("position", new i.BufferAttribute(l, 3)), t.setIndex(new i.BufferAttribute(m, 1));
1502
+ const M = new i.InstancedBufferGeometry();
1503
+ M.index = t.index, M.setAttribute("position", t.getAttribute("position"));
1504
+ const b = new Uint32Array(n);
1505
+ for (let p = 0; p < n; p++)
1506
+ b[p] = p * o;
1507
+ return M.setAttribute("splatInstanceIndex", new i.InstancedBufferAttribute(b, 1, !1)), M.instanceCount = 0, M;
1508
+ }
1509
+ /**
1510
+ * Create chunks data (bounding box min/max) for the sorter.
1511
+ * @returns Float32Array containing chunk data [minX, minY, minZ, maxX, maxY, maxZ] or null.
1512
+ */
1513
+ createChunks() {
1514
+ const s = this.splatData.boundingBox;
1515
+ return s.min.x === 1 / 0 || s.max.x === -1 / 0 ? null : new Float32Array([
1516
+ s.min.x,
1517
+ s.min.y,
1518
+ s.min.z,
1519
+ s.max.x,
1520
+ s.max.y,
1521
+ s.max.z
1522
+ ]);
1523
+ }
1524
+ /**
1525
+ * Update the viewport size
1526
+ * @param width Viewport width
1527
+ * @param height Viewport height
1528
+ */
1529
+ updateViewport(s, o) {
1530
+ this.material.updateViewport(s, o);
1531
+ }
1532
+ /**
1533
+ * Sorts splats based on camera position and direction.
1534
+ * @param camera The camera to sort against.
1535
+ */
1536
+ sort(s) {
1537
+ const o = new i.Vector3(), n = new i.Vector3();
1538
+ s.getWorldPosition(o), s.getWorldDirection(n), this.invModelMatrix.copy(this.matrixWorld).invert();
1539
+ const t = o.applyMatrix4(this.invModelMatrix), a = n.transformDirection(this.invModelMatrix), c = this.lastCameraPositionLocal.distanceToSquared(t) > 1e-6, l = this.lastCameraDirectionLocal.dot(a) < 0.999;
1540
+ this.options.autoSort && (c || l) && (this.lastCameraPositionLocal.copy(t), this.lastCameraDirectionLocal.copy(a), this.sorter.setCamera(t, a));
1541
+ }
1542
+ /**
1543
+ * THREE.js hook called before rendering the object.
1544
+ * Used here to trigger sorting and update viewport.
1545
+ * @param renderer The renderer
1546
+ * @param scene The scene
1547
+ * @param camera The camera
1548
+ */
1549
+ // prettier-ignore
1550
+ // @ts-expect-error scene is not used
1551
+ onBeforeRender(s, o, n) {
1552
+ this.sort(n);
1553
+ const t = s.getSize(new i.Vector2());
1554
+ let { width: a, height: c } = t;
1555
+ const l = s.xr;
1556
+ if (l.enabled && l.isPresenting) {
1557
+ const m = l.getCamera().cameras[0].view;
1558
+ m && (a = m.width, c = m.height);
1559
+ }
1560
+ this.updateViewport(a, c);
1561
+ }
1562
+ /**
1563
+ * Dispose of resources
1564
+ */
1565
+ dispose() {
1566
+ this.sorter.dispose(), this.geometry.dispose(), this.material.dispose(), this.textureManager.dispose();
1567
+ }
1568
+ };
1569
+ // Cached inverse matrix
1570
+ /** Number of splats combined into a single instanced draw call. */
1571
+ v(K, "INSTANCE_SIZE", 128);
1572
+ let ae = K, pe = !1;
1573
+ typeof window < "u" && !pe && (be({ splatPrimitive: ae }), pe = !0);
1574
+ const qe = ({
1575
+ plyUrl: z,
1576
+ splatOptions: e = {},
1577
+ ...s
290
1578
  }) => {
291
- const i = ne(null), a = ue(le, c), s = oe(
292
- () => [a, d || {}],
293
- [a, d]
1579
+ const o = ge(null), n = Me(ke, z), t = ve(
1580
+ () => [n, e || {}],
1581
+ [n, e]
294
1582
  );
295
- return ae(() => {
296
- const u = i.current;
297
- return u && !(u instanceof L) && console.warn(
1583
+ return we(() => {
1584
+ const a = o.current;
1585
+ return a && !(a instanceof ae) && console.warn(
298
1586
  "Visus: The 'Splat' component's internal mesh ref is not an instance of the core SplatMesh. This usually means `extend` was not called correctly. Please ensure you have called `extend({ splatPrimitive: SplatMesh })` in your R3F setup, where 'SplatMesh' is the class imported from 'visus' (or 'visus/react')."
299
1587
  ), () => {
300
- u && typeof u.dispose == "function" && u.dispose();
1588
+ a && typeof a.dispose == "function" && a.dispose();
301
1589
  };
302
- }, []), /* @__PURE__ */ de.jsx("splatPrimitive", { ref: i, args: s, ...m });
1590
+ }, []), /* @__PURE__ */ Ae.jsx("splatPrimitive", { ref: o, args: t, ...s });
303
1591
  };
304
1592
  export {
305
- le as PlyLoader,
306
- Re as Splat,
307
- L as SplatMesh
1593
+ ke as PlyLoader,
1594
+ qe as Splat,
1595
+ ae as SplatMesh
308
1596
  };