@speridlabs/visus 2.3.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.d.ts +336 -347
- package/dist/main.es.js +1457 -838
- package/dist/main.umd.js +164 -195
- package/dist/react.d.ts +6 -2
- package/dist/react.es.js +1619 -989
- package/package.json +4 -1
package/dist/react.es.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import
|
|
5
|
-
import * as
|
|
6
|
-
var
|
|
1
|
+
var Ye = Object.defineProperty;
|
|
2
|
+
var $e = (n, e, t) => e in n ? Ye(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
|
|
3
|
+
var M = (n, e, t) => $e(n, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import He, { useState as Xe, useRef as Ze, useEffect as Je } from "react";
|
|
5
|
+
import * as h from "three";
|
|
6
|
+
var we = { exports: {} }, pe = {};
|
|
7
7
|
/**
|
|
8
8
|
* @license React
|
|
9
9
|
* react-jsx-runtime.production.js
|
|
@@ -13,29 +13,29 @@ var ce = { exports: {} }, ae = {};
|
|
|
13
13
|
* This source code is licensed under the MIT license found in the
|
|
14
14
|
* LICENSE file in the root directory of this source tree.
|
|
15
15
|
*/
|
|
16
|
-
var
|
|
17
|
-
function
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
var
|
|
21
|
-
function
|
|
22
|
-
var
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
for (var i in
|
|
26
|
-
i !== "key" && (
|
|
27
|
-
} else
|
|
28
|
-
return
|
|
29
|
-
$$typeof:
|
|
30
|
-
type:
|
|
31
|
-
key:
|
|
32
|
-
ref:
|
|
33
|
-
props:
|
|
16
|
+
var Pe;
|
|
17
|
+
function Qe() {
|
|
18
|
+
if (Pe) return pe;
|
|
19
|
+
Pe = 1;
|
|
20
|
+
var n = Symbol.for("react.transitional.element"), e = Symbol.for("react.fragment");
|
|
21
|
+
function t(r, s, a) {
|
|
22
|
+
var o = null;
|
|
23
|
+
if (a !== void 0 && (o = "" + a), s.key !== void 0 && (o = "" + s.key), "key" in s) {
|
|
24
|
+
a = {};
|
|
25
|
+
for (var i in s)
|
|
26
|
+
i !== "key" && (a[i] = s[i]);
|
|
27
|
+
} else a = s;
|
|
28
|
+
return s = a.ref, {
|
|
29
|
+
$$typeof: n,
|
|
30
|
+
type: r,
|
|
31
|
+
key: o,
|
|
32
|
+
ref: s !== void 0 ? s : null,
|
|
33
|
+
props: a
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
-
return
|
|
36
|
+
return pe.Fragment = e, pe.jsx = t, pe.jsxs = t, pe;
|
|
37
37
|
}
|
|
38
|
-
var
|
|
38
|
+
var xe = {};
|
|
39
39
|
/**
|
|
40
40
|
* @license React
|
|
41
41
|
* react-jsx-runtime.development.js
|
|
@@ -45,251 +45,251 @@ var ie = {};
|
|
|
45
45
|
* This source code is licensed under the MIT license found in the
|
|
46
46
|
* LICENSE file in the root directory of this source tree.
|
|
47
47
|
*/
|
|
48
|
-
var
|
|
49
|
-
function
|
|
50
|
-
return
|
|
51
|
-
function
|
|
52
|
-
if (
|
|
53
|
-
if (typeof
|
|
54
|
-
return
|
|
55
|
-
if (typeof
|
|
56
|
-
switch (
|
|
57
|
-
case
|
|
48
|
+
var Be;
|
|
49
|
+
function Ke() {
|
|
50
|
+
return Be || (Be = 1, process.env.NODE_ENV !== "production" && function() {
|
|
51
|
+
function n(c) {
|
|
52
|
+
if (c == null) return null;
|
|
53
|
+
if (typeof c == "function")
|
|
54
|
+
return c.$$typeof === p ? null : c.displayName || c.name || null;
|
|
55
|
+
if (typeof c == "string") return c;
|
|
56
|
+
switch (c) {
|
|
57
|
+
case v:
|
|
58
58
|
return "Fragment";
|
|
59
|
-
case
|
|
59
|
+
case E:
|
|
60
60
|
return "Profiler";
|
|
61
|
-
case
|
|
61
|
+
case b:
|
|
62
62
|
return "StrictMode";
|
|
63
63
|
case L:
|
|
64
64
|
return "Suspense";
|
|
65
65
|
case A:
|
|
66
66
|
return "SuspenseList";
|
|
67
|
-
case
|
|
67
|
+
case w:
|
|
68
68
|
return "Activity";
|
|
69
69
|
}
|
|
70
|
-
if (typeof
|
|
71
|
-
switch (typeof
|
|
70
|
+
if (typeof c == "object")
|
|
71
|
+
switch (typeof c.tag == "number" && console.error(
|
|
72
72
|
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
|
|
73
|
-
),
|
|
74
|
-
case
|
|
73
|
+
), c.$$typeof) {
|
|
74
|
+
case g:
|
|
75
75
|
return "Portal";
|
|
76
|
-
case
|
|
77
|
-
return (
|
|
76
|
+
case P:
|
|
77
|
+
return (c.displayName || "Context") + ".Provider";
|
|
78
|
+
case T:
|
|
79
|
+
return (c._context.displayName || "Context") + ".Consumer";
|
|
78
80
|
case H:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return
|
|
83
|
-
case
|
|
84
|
-
|
|
85
|
-
case D:
|
|
86
|
-
p = s._payload, s = s._init;
|
|
81
|
+
var k = c.render;
|
|
82
|
+
return c = c.displayName, c || (c = k.displayName || k.name || "", c = c !== "" ? "ForwardRef(" + c + ")" : "ForwardRef"), c;
|
|
83
|
+
case C:
|
|
84
|
+
return k = c.displayName || null, k !== null ? k : n(c.type) || "Memo";
|
|
85
|
+
case _:
|
|
86
|
+
k = c._payload, c = c._init;
|
|
87
87
|
try {
|
|
88
|
-
return
|
|
88
|
+
return n(c(k));
|
|
89
89
|
} catch {
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
return null;
|
|
93
93
|
}
|
|
94
|
-
function e(
|
|
95
|
-
return "" +
|
|
94
|
+
function e(c) {
|
|
95
|
+
return "" + c;
|
|
96
96
|
}
|
|
97
|
-
function
|
|
97
|
+
function t(c) {
|
|
98
98
|
try {
|
|
99
|
-
e(
|
|
100
|
-
var
|
|
99
|
+
e(c);
|
|
100
|
+
var k = !1;
|
|
101
101
|
} catch {
|
|
102
|
-
|
|
102
|
+
k = !0;
|
|
103
103
|
}
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
var
|
|
107
|
-
return
|
|
108
|
-
|
|
104
|
+
if (k) {
|
|
105
|
+
k = console;
|
|
106
|
+
var B = k.error, F = typeof Symbol == "function" && Symbol.toStringTag && c[Symbol.toStringTag] || c.constructor.name || "Object";
|
|
107
|
+
return B.call(
|
|
108
|
+
k,
|
|
109
109
|
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
|
|
110
|
-
|
|
111
|
-
), e(
|
|
110
|
+
F
|
|
111
|
+
), e(c);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
function
|
|
115
|
-
if (
|
|
116
|
-
if (typeof
|
|
114
|
+
function r(c) {
|
|
115
|
+
if (c === v) return "<>";
|
|
116
|
+
if (typeof c == "object" && c !== null && c.$$typeof === _)
|
|
117
117
|
return "<...>";
|
|
118
118
|
try {
|
|
119
|
-
var
|
|
120
|
-
return
|
|
119
|
+
var k = n(c);
|
|
120
|
+
return k ? "<" + k + ">" : "<...>";
|
|
121
121
|
} catch {
|
|
122
122
|
return "<...>";
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
function
|
|
126
|
-
var
|
|
127
|
-
return
|
|
125
|
+
function s() {
|
|
126
|
+
var c = R.A;
|
|
127
|
+
return c === null ? null : c.getOwner();
|
|
128
128
|
}
|
|
129
|
-
function
|
|
129
|
+
function a() {
|
|
130
130
|
return Error("react-stack-top-frame");
|
|
131
131
|
}
|
|
132
|
-
function
|
|
133
|
-
if (
|
|
134
|
-
var
|
|
135
|
-
if (
|
|
132
|
+
function o(c) {
|
|
133
|
+
if (q.call(c, "key")) {
|
|
134
|
+
var k = Object.getOwnPropertyDescriptor(c, "key").get;
|
|
135
|
+
if (k && k.isReactWarning) return !1;
|
|
136
136
|
}
|
|
137
|
-
return
|
|
137
|
+
return c.key !== void 0;
|
|
138
138
|
}
|
|
139
|
-
function i(
|
|
140
|
-
function
|
|
141
|
-
|
|
139
|
+
function i(c, k) {
|
|
140
|
+
function B() {
|
|
141
|
+
V || (V = !0, console.error(
|
|
142
142
|
"%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)",
|
|
143
|
-
|
|
143
|
+
k
|
|
144
144
|
));
|
|
145
145
|
}
|
|
146
|
-
|
|
147
|
-
get:
|
|
146
|
+
B.isReactWarning = !0, Object.defineProperty(c, "key", {
|
|
147
|
+
get: B,
|
|
148
148
|
configurable: !0
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
|
-
function
|
|
152
|
-
var
|
|
153
|
-
return
|
|
151
|
+
function m() {
|
|
152
|
+
var c = n(this.type);
|
|
153
|
+
return D[c] || (D[c] = !0, console.error(
|
|
154
154
|
"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."
|
|
155
|
-
)),
|
|
155
|
+
)), c = this.props.ref, c !== void 0 ? c : null;
|
|
156
156
|
}
|
|
157
|
-
function
|
|
158
|
-
return
|
|
159
|
-
$$typeof:
|
|
160
|
-
type:
|
|
161
|
-
key:
|
|
162
|
-
props:
|
|
163
|
-
_owner:
|
|
164
|
-
}, (
|
|
157
|
+
function f(c, k, B, F, I, d, z, W) {
|
|
158
|
+
return B = d.ref, c = {
|
|
159
|
+
$$typeof: x,
|
|
160
|
+
type: c,
|
|
161
|
+
key: k,
|
|
162
|
+
props: d,
|
|
163
|
+
_owner: I
|
|
164
|
+
}, (B !== void 0 ? B : null) !== null ? Object.defineProperty(c, "ref", {
|
|
165
165
|
enumerable: !1,
|
|
166
|
-
get:
|
|
167
|
-
}) : Object.defineProperty(
|
|
166
|
+
get: m
|
|
167
|
+
}) : Object.defineProperty(c, "ref", { enumerable: !1, value: null }), c._store = {}, Object.defineProperty(c._store, "validated", {
|
|
168
168
|
configurable: !1,
|
|
169
169
|
enumerable: !1,
|
|
170
170
|
writable: !0,
|
|
171
171
|
value: 0
|
|
172
|
-
}), Object.defineProperty(
|
|
172
|
+
}), Object.defineProperty(c, "_debugInfo", {
|
|
173
173
|
configurable: !1,
|
|
174
174
|
enumerable: !1,
|
|
175
175
|
writable: !0,
|
|
176
176
|
value: null
|
|
177
|
-
}), Object.defineProperty(
|
|
177
|
+
}), Object.defineProperty(c, "_debugStack", {
|
|
178
178
|
configurable: !1,
|
|
179
179
|
enumerable: !1,
|
|
180
180
|
writable: !0,
|
|
181
|
-
value:
|
|
182
|
-
}), Object.defineProperty(
|
|
181
|
+
value: z
|
|
182
|
+
}), Object.defineProperty(c, "_debugTask", {
|
|
183
183
|
configurable: !1,
|
|
184
184
|
enumerable: !1,
|
|
185
185
|
writable: !0,
|
|
186
|
-
value:
|
|
187
|
-
}), Object.freeze && (Object.freeze(
|
|
186
|
+
value: W
|
|
187
|
+
}), Object.freeze && (Object.freeze(c.props), Object.freeze(c)), c;
|
|
188
188
|
}
|
|
189
|
-
function
|
|
190
|
-
var
|
|
191
|
-
if (
|
|
192
|
-
if (
|
|
193
|
-
if (
|
|
194
|
-
for (
|
|
195
|
-
|
|
196
|
-
Object.freeze && Object.freeze(
|
|
189
|
+
function y(c, k, B, F, I, d, z, W) {
|
|
190
|
+
var S = k.children;
|
|
191
|
+
if (S !== void 0)
|
|
192
|
+
if (F)
|
|
193
|
+
if (j(S)) {
|
|
194
|
+
for (F = 0; F < S.length; F++)
|
|
195
|
+
l(S[F]);
|
|
196
|
+
Object.freeze && Object.freeze(S);
|
|
197
197
|
} else
|
|
198
198
|
console.error(
|
|
199
199
|
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
|
|
200
200
|
);
|
|
201
|
-
else
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
var
|
|
205
|
-
return
|
|
201
|
+
else l(S);
|
|
202
|
+
if (q.call(k, "key")) {
|
|
203
|
+
S = n(c);
|
|
204
|
+
var U = Object.keys(k).filter(function(X) {
|
|
205
|
+
return X !== "key";
|
|
206
206
|
});
|
|
207
|
-
|
|
207
|
+
F = 0 < U.length ? "{key: someKey, " + U.join(": ..., ") + ": ...}" : "{key: someKey}", N[S + F] || (U = 0 < U.length ? "{" + U.join(": ..., ") + ": ...}" : "{}", console.error(
|
|
208
208
|
`A props object containing a "key" prop is being spread into JSX:
|
|
209
209
|
let props = %s;
|
|
210
210
|
<%s {...props} />
|
|
211
211
|
React keys must be passed directly to JSX without using spread:
|
|
212
212
|
let props = %s;
|
|
213
213
|
<%s key={someKey} {...props} />`,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
),
|
|
214
|
+
F,
|
|
215
|
+
S,
|
|
216
|
+
U,
|
|
217
|
+
S
|
|
218
|
+
), N[S + F] = !0);
|
|
219
219
|
}
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
for (var
|
|
223
|
-
|
|
224
|
-
} else
|
|
225
|
-
return
|
|
226
|
-
|
|
227
|
-
typeof
|
|
228
|
-
),
|
|
229
|
-
s,
|
|
230
|
-
d,
|
|
220
|
+
if (S = null, B !== void 0 && (t(B), S = "" + B), o(k) && (t(k.key), S = "" + k.key), "key" in k) {
|
|
221
|
+
B = {};
|
|
222
|
+
for (var $ in k)
|
|
223
|
+
$ !== "key" && (B[$] = k[$]);
|
|
224
|
+
} else B = k;
|
|
225
|
+
return S && i(
|
|
226
|
+
B,
|
|
227
|
+
typeof c == "function" ? c.displayName || c.name || "Unknown" : c
|
|
228
|
+
), f(
|
|
231
229
|
c,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
230
|
+
S,
|
|
231
|
+
d,
|
|
232
|
+
I,
|
|
233
|
+
s(),
|
|
234
|
+
B,
|
|
235
|
+
z,
|
|
236
|
+
W
|
|
237
237
|
);
|
|
238
238
|
}
|
|
239
|
-
function
|
|
240
|
-
typeof
|
|
239
|
+
function l(c) {
|
|
240
|
+
typeof c == "object" && c !== null && c.$$typeof === x && c._store && (c._store.validated = 1);
|
|
241
241
|
}
|
|
242
|
-
var
|
|
242
|
+
var u = He, x = Symbol.for("react.transitional.element"), g = Symbol.for("react.portal"), v = Symbol.for("react.fragment"), b = Symbol.for("react.strict_mode"), E = Symbol.for("react.profiler"), T = Symbol.for("react.consumer"), P = Symbol.for("react.context"), H = Symbol.for("react.forward_ref"), L = Symbol.for("react.suspense"), A = Symbol.for("react.suspense_list"), C = Symbol.for("react.memo"), _ = Symbol.for("react.lazy"), w = Symbol.for("react.activity"), p = Symbol.for("react.client.reference"), R = u.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, q = Object.prototype.hasOwnProperty, j = Array.isArray, Y = console.createTask ? console.createTask : function() {
|
|
243
243
|
return null;
|
|
244
244
|
};
|
|
245
|
-
|
|
246
|
-
"react-stack-bottom-frame": function(
|
|
247
|
-
return
|
|
245
|
+
u = {
|
|
246
|
+
"react-stack-bottom-frame": function(c) {
|
|
247
|
+
return c();
|
|
248
248
|
}
|
|
249
249
|
};
|
|
250
|
-
var
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
)(),
|
|
254
|
-
|
|
255
|
-
var
|
|
256
|
-
return
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
250
|
+
var V, D = {}, O = u["react-stack-bottom-frame"].bind(
|
|
251
|
+
u,
|
|
252
|
+
a
|
|
253
|
+
)(), J = Y(r(a)), N = {};
|
|
254
|
+
xe.Fragment = v, xe.jsx = function(c, k, B, F, I) {
|
|
255
|
+
var d = 1e4 > R.recentlyCreatedOwnerStacks++;
|
|
256
|
+
return y(
|
|
257
|
+
c,
|
|
258
|
+
k,
|
|
259
|
+
B,
|
|
260
260
|
!1,
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
F,
|
|
262
|
+
I,
|
|
263
|
+
d ? Error("react-stack-top-frame") : O,
|
|
264
|
+
d ? Y(r(c)) : J
|
|
265
265
|
);
|
|
266
|
-
},
|
|
267
|
-
var
|
|
268
|
-
return
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
}, xe.jsxs = function(c, k, B, F, I) {
|
|
267
|
+
var d = 1e4 > R.recentlyCreatedOwnerStacks++;
|
|
268
|
+
return y(
|
|
269
|
+
c,
|
|
270
|
+
k,
|
|
271
|
+
B,
|
|
272
272
|
!0,
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
273
|
+
F,
|
|
274
|
+
I,
|
|
275
|
+
d ? Error("react-stack-top-frame") : O,
|
|
276
|
+
d ? Y(r(c)) : J
|
|
277
277
|
);
|
|
278
278
|
};
|
|
279
|
-
}()),
|
|
279
|
+
}()), xe;
|
|
280
280
|
}
|
|
281
|
-
var
|
|
282
|
-
function
|
|
283
|
-
return
|
|
281
|
+
var De;
|
|
282
|
+
function et() {
|
|
283
|
+
return De || (De = 1, process.env.NODE_ENV === "production" ? we.exports = Qe() : we.exports = Ke()), we.exports;
|
|
284
284
|
}
|
|
285
|
-
var
|
|
286
|
-
class
|
|
285
|
+
var tt = et();
|
|
286
|
+
class be {
|
|
287
287
|
constructor() {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
288
|
+
M(this, "min", new h.Vector3(1 / 0, 1 / 0, 1 / 0));
|
|
289
|
+
M(this, "max", new h.Vector3(-1 / 0, -1 / 0, -1 / 0));
|
|
290
|
+
M(this, "center", new h.Vector3());
|
|
291
291
|
/** Half extents (size/2) */
|
|
292
|
-
|
|
292
|
+
M(this, "halfExtents", new h.Vector3());
|
|
293
293
|
}
|
|
294
294
|
/**
|
|
295
295
|
* Reset the bounding box to its initial state
|
|
@@ -330,27 +330,26 @@ class fe {
|
|
|
330
330
|
* @returns THREE.Box3 representation
|
|
331
331
|
*/
|
|
332
332
|
toBox3() {
|
|
333
|
-
return new
|
|
333
|
+
return new h.Box3().set(this.min, this.max);
|
|
334
334
|
}
|
|
335
335
|
/**
|
|
336
336
|
* Create a clone of this bounding box
|
|
337
337
|
* @returns New bounding box with the same values
|
|
338
338
|
*/
|
|
339
339
|
clone() {
|
|
340
|
-
const e = new
|
|
340
|
+
const e = new be();
|
|
341
341
|
return e.min.copy(this.min), e.max.copy(this.max), e.center.copy(this.center), e.halfExtents.copy(this.halfExtents), e;
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
|
-
class
|
|
345
|
-
// TODO: there is no sh spherical harmonics
|
|
344
|
+
class rt {
|
|
346
345
|
constructor(e = 0) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
346
|
+
M(this, "numSplats", 0);
|
|
347
|
+
M(this, "positions");
|
|
348
|
+
M(this, "rotations");
|
|
349
|
+
M(this, "scales");
|
|
350
|
+
M(this, "colors");
|
|
351
|
+
M(this, "opacities");
|
|
352
|
+
M(this, "boundingBox", new be());
|
|
354
353
|
this.numSplats = e, this.allocateBuffers(e);
|
|
355
354
|
}
|
|
356
355
|
allocateBuffers(e) {
|
|
@@ -365,13 +364,13 @@ class Re {
|
|
|
365
364
|
* @param color Color
|
|
366
365
|
* @param opacity Opacity value
|
|
367
366
|
*/
|
|
368
|
-
setSplat(e,
|
|
367
|
+
setSplat(e, t, r, s, a, o) {
|
|
369
368
|
if (e >= this.numSplats)
|
|
370
369
|
throw new Error(
|
|
371
370
|
`Splat index out of bounds: ${e} >= ${this.numSplats}`
|
|
372
371
|
);
|
|
373
|
-
const i = e * 3,
|
|
374
|
-
this.positions[i] =
|
|
372
|
+
const i = e * 3, m = e * 4, f = e * 3, y = e * 3;
|
|
373
|
+
this.positions[i] = t.x, this.positions[i + 1] = t.y, this.positions[i + 2] = t.z, this.rotations[m] = r.x, this.rotations[m + 1] = r.y, this.rotations[m + 2] = r.z, this.rotations[m + 3] = r.w, this.scales[f] = s.x, this.scales[f + 1] = s.y, this.scales[f + 2] = s.z, this.colors[y] = a.r, this.colors[y + 1] = a.g, this.colors[y + 2] = a.b, this.opacities[e] = o;
|
|
375
374
|
}
|
|
376
375
|
/**
|
|
377
376
|
* Get a splat's data
|
|
@@ -383,29 +382,29 @@ class Re {
|
|
|
383
382
|
throw new Error(
|
|
384
383
|
`Splat index out of bounds: ${e} >= ${this.numSplats}`
|
|
385
384
|
);
|
|
386
|
-
const
|
|
385
|
+
const t = e * 3, r = e * 4, s = e * 3, a = e * 3;
|
|
387
386
|
return {
|
|
388
|
-
position: new
|
|
389
|
-
this.positions[
|
|
390
|
-
this.positions[
|
|
391
|
-
this.positions[
|
|
387
|
+
position: new h.Vector3(
|
|
388
|
+
this.positions[t],
|
|
389
|
+
this.positions[t + 1],
|
|
390
|
+
this.positions[t + 2]
|
|
392
391
|
),
|
|
393
|
-
rotation: new
|
|
394
|
-
this.rotations[
|
|
395
|
-
this.rotations[
|
|
396
|
-
this.rotations[
|
|
397
|
-
this.rotations[
|
|
392
|
+
rotation: new h.Quaternion(
|
|
393
|
+
this.rotations[r],
|
|
394
|
+
this.rotations[r + 1],
|
|
395
|
+
this.rotations[r + 2],
|
|
396
|
+
this.rotations[r + 3]
|
|
398
397
|
),
|
|
399
398
|
// Convert log scale back to linear scale for external use
|
|
400
|
-
scale: new
|
|
401
|
-
Math.exp(this.scales[
|
|
402
|
-
Math.exp(this.scales[
|
|
403
|
-
Math.exp(this.scales[
|
|
399
|
+
scale: new h.Vector3(
|
|
400
|
+
Math.exp(this.scales[s]),
|
|
401
|
+
Math.exp(this.scales[s + 1]),
|
|
402
|
+
Math.exp(this.scales[s + 2])
|
|
404
403
|
),
|
|
405
|
-
color: new
|
|
406
|
-
this.colors[
|
|
407
|
-
this.colors[
|
|
408
|
-
this.colors[
|
|
404
|
+
color: new h.Color(
|
|
405
|
+
this.colors[a],
|
|
406
|
+
this.colors[a + 1],
|
|
407
|
+
this.colors[a + 2]
|
|
409
408
|
),
|
|
410
409
|
opacity: this.opacities[e]
|
|
411
410
|
};
|
|
@@ -416,13 +415,13 @@ class Re {
|
|
|
416
415
|
*/
|
|
417
416
|
calculateBoundingBox() {
|
|
418
417
|
this.boundingBox.reset();
|
|
419
|
-
const e = new
|
|
420
|
-
for (let
|
|
421
|
-
const
|
|
418
|
+
const e = new h.Vector3();
|
|
419
|
+
for (let t = 0; t < this.numSplats; t++) {
|
|
420
|
+
const r = t * 3;
|
|
422
421
|
e.set(
|
|
423
|
-
this.positions[
|
|
424
|
-
this.positions[
|
|
425
|
-
this.positions[
|
|
422
|
+
this.positions[r],
|
|
423
|
+
this.positions[r + 1],
|
|
424
|
+
this.positions[r + 2]
|
|
426
425
|
), this.boundingBox.expandByPoint(e);
|
|
427
426
|
}
|
|
428
427
|
return this.boundingBox;
|
|
@@ -432,68 +431,265 @@ class Re {
|
|
|
432
431
|
* This is for visualization/debugging purposes only, not for rendering
|
|
433
432
|
*/
|
|
434
433
|
createDebugGeometry() {
|
|
435
|
-
const e = new
|
|
434
|
+
const e = new h.BufferGeometry();
|
|
436
435
|
e.setAttribute(
|
|
437
436
|
"position",
|
|
438
|
-
new
|
|
437
|
+
new h.BufferAttribute(this.positions, 3)
|
|
439
438
|
);
|
|
440
|
-
const
|
|
441
|
-
for (let
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
this.rotations[
|
|
445
|
-
this.rotations[
|
|
446
|
-
this.rotations[
|
|
447
|
-
this.rotations[
|
|
448
|
-
),
|
|
439
|
+
const t = new Float32Array(this.numSplats * 3), r = new h.Quaternion(), s = new h.Euler();
|
|
440
|
+
for (let a = 0; a < this.numSplats; a++) {
|
|
441
|
+
const o = a * 4, i = a * 3;
|
|
442
|
+
r.set(
|
|
443
|
+
this.rotations[o],
|
|
444
|
+
this.rotations[o + 1],
|
|
445
|
+
this.rotations[o + 2],
|
|
446
|
+
this.rotations[o + 3]
|
|
447
|
+
), s.setFromQuaternion(r), t[i] = s.x, t[i + 1] = s.y, t[i + 2] = s.z;
|
|
449
448
|
}
|
|
450
449
|
return e.setAttribute(
|
|
451
450
|
"rotation",
|
|
452
|
-
new
|
|
451
|
+
new h.BufferAttribute(t, 3)
|
|
453
452
|
), e.setAttribute(
|
|
454
453
|
"scale",
|
|
455
|
-
new
|
|
454
|
+
new h.BufferAttribute(this.scales, 3)
|
|
456
455
|
), e.setAttribute(
|
|
457
456
|
"color",
|
|
458
|
-
new
|
|
457
|
+
new h.BufferAttribute(this.colors, 3)
|
|
459
458
|
), e.setAttribute(
|
|
460
459
|
"opacity",
|
|
461
|
-
new
|
|
460
|
+
new h.BufferAttribute(this.opacities, 1)
|
|
462
461
|
), e;
|
|
463
462
|
}
|
|
463
|
+
dispose() {
|
|
464
|
+
this.numSplats = 0, this.scales = new Float32Array(0), this.colors = new Float32Array(0), this.positions = new Float32Array(0), this.rotations = new Float32Array(0), this.opacities = new Float32Array(0);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
class Fe {
|
|
468
|
+
// Upper 8 bits of 16-bit means
|
|
469
|
+
constructor(e, t, r) {
|
|
470
|
+
M(this, "ranges");
|
|
471
|
+
M(this, "numSplats", 0);
|
|
472
|
+
M(this, "boundingBox", new be());
|
|
473
|
+
// Original SOGS textures
|
|
474
|
+
M(this, "sh0");
|
|
475
|
+
// SH DC coefficients + alpha
|
|
476
|
+
M(this, "quats");
|
|
477
|
+
// Quaternion components + mode
|
|
478
|
+
M(this, "scales");
|
|
479
|
+
// Scale values (8-bit)
|
|
480
|
+
M(this, "means_l");
|
|
481
|
+
// Lower 8 bits of 16-bit means
|
|
482
|
+
M(this, "means_u");
|
|
483
|
+
this.ranges = t, this.numSplats = e, this.sh0 = r.sh0, this.quats = r.quats, this.scales = r.scales, this.means_l = r.means_l, this.means_u = r.means_u, this.boundingBox = this.calculateBoundingBox();
|
|
484
|
+
}
|
|
485
|
+
calculateBoundingBox() {
|
|
486
|
+
this.boundingBox.reset();
|
|
487
|
+
const { mins: e, maxs: t } = this.ranges.means, r = (s) => Math.sign(s) * (Math.exp(Math.abs(s)) - 1);
|
|
488
|
+
return this.boundingBox.center.set(
|
|
489
|
+
(r(e[0]) + r(t[0])) * 0.5,
|
|
490
|
+
(r(e[1]) + r(t[1])) * 0.5,
|
|
491
|
+
(r(e[2]) + r(t[2])) * 0.5
|
|
492
|
+
), this.boundingBox.halfExtents.set(
|
|
493
|
+
(r(t[0]) - r(e[0])) * 0.5,
|
|
494
|
+
(r(t[1]) - r(e[1])) * 0.5,
|
|
495
|
+
(r(t[2]) - r(e[2])) * 0.5
|
|
496
|
+
), this.boundingBox;
|
|
497
|
+
}
|
|
498
|
+
dispose() {
|
|
499
|
+
this.sh0.dispose(), this.quats.dispose(), this.scales.dispose(), this.means_l.dispose(), this.means_u.dispose();
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
class qe {
|
|
503
|
+
// RGBA32UI - (Position + Rotation + Scale)
|
|
504
|
+
// RGBA32UI Texture Content:
|
|
505
|
+
// .r = Means Lower (RGB)
|
|
506
|
+
// .g = Means Upper (RGB)
|
|
507
|
+
// .b = Rotation (RGBA)
|
|
508
|
+
// .a = Scale (RGB)
|
|
509
|
+
constructor(e, t, r, s, a, o, i, m) {
|
|
510
|
+
// Info data - cpu
|
|
511
|
+
M(this, "numSplats");
|
|
512
|
+
M(this, "textureWidth");
|
|
513
|
+
M(this, "textureHeight");
|
|
514
|
+
M(this, "ranges");
|
|
515
|
+
M(this, "centers");
|
|
516
|
+
// TODO: see if necesary or can be compressed somehow
|
|
517
|
+
M(this, "boundingBox");
|
|
518
|
+
// GPU Textures
|
|
519
|
+
M(this, "packedColor");
|
|
520
|
+
// RGBA8 - (Color + Opacity)
|
|
521
|
+
// RGBA8 Texture Content:
|
|
522
|
+
// .rgb = Color, .a = Opacity
|
|
523
|
+
M(this, "packedGeometry");
|
|
524
|
+
this.numSplats = e, this.textureWidth = t, this.textureHeight = r, this.boundingBox = m, this.ranges = i, this.centers = s, this.packedColor = o, this.packedGeometry = a;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Optional: Reconstruct a full JS object for a specific splat.
|
|
528
|
+
* Useful for raycasting or debugging.
|
|
529
|
+
*/
|
|
530
|
+
// public getSplat(index: number) {
|
|
531
|
+
// throw new Error('Not implemented yet');
|
|
532
|
+
// }
|
|
533
|
+
dispose() {
|
|
534
|
+
this.centers = new Float32Array(0), this.packedColor = new Uint8Array(0), this.packedGeometry = new Uint32Array(0);
|
|
535
|
+
}
|
|
536
|
+
// public abstract deserialize(): ISplat;
|
|
537
|
+
// public abstract returnPacked(): ISplat;
|
|
538
|
+
}
|
|
539
|
+
const me = 0.28209479177387814;
|
|
540
|
+
class Ce {
|
|
541
|
+
/**
|
|
542
|
+
* Packs PLY data (Float32) into the Unified SOGS-like Format.
|
|
543
|
+
*/
|
|
544
|
+
// prettier-ignore
|
|
545
|
+
static packPly(e) {
|
|
546
|
+
const t = e.numSplats, r = Math.ceil(Math.sqrt(t)), s = Math.ceil(t / r), a = r * s, { ranges: o, colorScale: i } = this.calculatePlyRanges(e), m = new Uint32Array(a * 4), f = new Uint8Array(a * 4), y = new h.Quaternion();
|
|
547
|
+
for (let l = 0; l < t; l++) {
|
|
548
|
+
const u = l * 4, x = l * 3, g = l * 4, v = e.positions[x + 0], b = e.positions[x + 1], E = e.positions[x + 2], T = this.clamp01(this.norm(v, o.means.min.x, o.means.max.x)), P = this.clamp01(this.norm(b, o.means.min.y, o.means.max.y)), H = this.clamp01(this.norm(E, o.means.min.z, o.means.max.z)), L = T * 65535 | 0, A = P * 65535 | 0, C = H * 65535 | 0;
|
|
549
|
+
m[u + 0] = this.pack4Bytes(L & 255, A & 255, C & 255, 0), m[u + 1] = this.pack4Bytes(L >> 8, A >> 8, C >> 8, 0), y.set(e.rotations[g], e.rotations[g + 1], e.rotations[g + 2], e.rotations[g + 3]).normalize();
|
|
550
|
+
let _ = y.w, w = y.x, p = y.y, R = y.z;
|
|
551
|
+
const q = Math.abs(_), j = Math.abs(w), Y = Math.abs(p), V = Math.abs(R);
|
|
552
|
+
let D = 0, O = q;
|
|
553
|
+
j > O && (O = j, D = 1), Y > O && (O = Y, D = 2), V > O && (O = V, D = 3), (D === 0 ? _ : D === 1 ? w : D === 2 ? p : R) < 0 && (_ = -_, w = -w, p = -p, R = -R);
|
|
554
|
+
let N = 0, c = 0, k = 0;
|
|
555
|
+
D === 0 && (N = w, c = p, k = R), D === 1 && (N = _, c = p, k = R), D === 2 && (N = _, c = w, k = R), D === 3 && (N = _, c = w, k = p);
|
|
556
|
+
const B = (se) => Math.min(255, Math.max(0, Math.round((0.5 + se / Math.SQRT2) * 255)));
|
|
557
|
+
m[u + 2] = this.pack4Bytes(B(N), B(c), B(k), D);
|
|
558
|
+
const F = this.norm(e.scales[x + 0], o.scales.min.x, o.scales.max.x), I = this.norm(e.scales[x + 1], o.scales.min.y, o.scales.max.y), d = this.norm(e.scales[x + 2], o.scales.min.z, o.scales.max.z);
|
|
559
|
+
m[u + 3] = this.pack4Bytes(Math.floor(F * 255), Math.floor(I * 255), Math.floor(d * 255), 0);
|
|
560
|
+
const z = this.clamp01(e.colors[x + 0] * i), W = this.clamp01(e.colors[x + 1] * i), S = this.clamp01(e.colors[x + 2] * i), U = (z - 0.5) / me, $ = (W - 0.5) / me, X = (S - 0.5) / me, Q = this.clamp01(this.norm(U, o.sh0.min.x, o.sh0.max.x)), Z = this.clamp01(this.norm($, o.sh0.min.y, o.sh0.max.y)), K = this.clamp01(this.norm(X, o.sh0.min.z, o.sh0.max.z)), re = this.clamp01(e.opacities[l]);
|
|
561
|
+
f[u + 0] = Math.round(Q * 255), f[u + 1] = Math.round(Z * 255), f[u + 2] = Math.round(K * 255), f[u + 3] = Math.round(re * 255);
|
|
562
|
+
}
|
|
563
|
+
return new qe(t, r, s, e.positions, m, f, o, e.boundingBox);
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Packs SOGS data.
|
|
567
|
+
* Interleaves the separate textures into the Unified RGBA32UI buffer.
|
|
568
|
+
* Decodes centers for sorting.
|
|
569
|
+
*/
|
|
570
|
+
// prettier-ignore
|
|
571
|
+
static packSogs(e) {
|
|
572
|
+
const t = e.numSplats, r = Math.ceil(Math.sqrt(t)), s = Math.ceil(t / r), a = r * s, o = this.convertSogsRanges(e.ranges), i = e.ranges.means.mins[0], m = e.ranges.means.mins[1], f = e.ranges.means.mins[2], y = e.ranges.means.maxs[0], l = e.ranges.means.maxs[1], u = e.ranges.means.maxs[2], x = (w) => Math.sign(w) * (Math.exp(Math.abs(w)) - 1), g = new h.Vector3(
|
|
573
|
+
x(i),
|
|
574
|
+
x(m),
|
|
575
|
+
x(f)
|
|
576
|
+
), v = new h.Vector3(
|
|
577
|
+
x(y),
|
|
578
|
+
x(l),
|
|
579
|
+
x(u)
|
|
580
|
+
);
|
|
581
|
+
o.means.min.copy(g), o.means.max.copy(v);
|
|
582
|
+
const b = e, E = this.getPixels(b.means_l), T = this.getPixels(b.means_u), P = this.getPixels(b.quats), H = this.getPixels(b.scales), L = this.getPixels(b.sh0), A = new Uint32Array(a * 4), C = new Uint8Array(a * 4), _ = new Float32Array(t * 3);
|
|
583
|
+
for (let w = 0; w < t; w++) {
|
|
584
|
+
const p = w * 4, R = T[p + 0], q = E[p + 0], j = T[p + 1], Y = E[p + 1], V = T[p + 2], D = E[p + 2], O = (R << 8 | q) / 65535, J = (j << 8 | Y) / 65535, N = (V << 8 | D) / 65535, c = this.sogsDecode(O, i, y), k = this.sogsDecode(J, m, l), B = this.sogsDecode(N, f, u);
|
|
585
|
+
_[w * 3 + 0] = c, _[w * 3 + 1] = k, _[w * 3 + 2] = B;
|
|
586
|
+
const F = this.clamp01(this.norm(c, g.x, v.x)) * 65535 | 0, I = this.clamp01(this.norm(k, g.y, v.y)) * 65535 | 0, d = this.clamp01(this.norm(B, g.z, v.z)) * 65535 | 0;
|
|
587
|
+
A[p + 0] = this.pack4Bytes(F & 255, I & 255, d & 255, 0), A[p + 1] = this.pack4Bytes(F >> 8, I >> 8, d >> 8, 0), A[p + 3] = this.pack4Bytes(H[p], H[p + 1], H[p + 2], 0);
|
|
588
|
+
const W = P[p + 3] - 252;
|
|
589
|
+
A[p + 2] = this.pack4Bytes(P[p + 0], P[p + 1], P[p + 2], W), C[p + 0] = L[p], C[p + 1] = L[p + 1], C[p + 2] = L[p + 2];
|
|
590
|
+
const S = L[p + 3] / 255, U = e.ranges.sh0.mins[3] + (e.ranges.sh0.maxs[3] - e.ranges.sh0.mins[3]) * S, $ = 1 / (1 + Math.exp(-U));
|
|
591
|
+
C[p + 3] = Math.round(Math.max(0, Math.min(1, $)) * 255);
|
|
592
|
+
}
|
|
593
|
+
return new qe(t, r, s, _, A, C, o, e.boundingBox);
|
|
594
|
+
}
|
|
595
|
+
// --- Helpers ---
|
|
596
|
+
// prettier-ignore
|
|
597
|
+
static pack4Bytes(e, t, r, s) {
|
|
598
|
+
return (e & 255) << 24 | (t & 255) << 16 | (r & 255) << 8 | s & 255;
|
|
599
|
+
}
|
|
600
|
+
// prettier-ignore
|
|
601
|
+
static getPixels(e) {
|
|
602
|
+
const t = e.image, r = t.width, s = t.height;
|
|
603
|
+
if (t.data && (t.data instanceof Uint8Array || t.data instanceof Uint8ClampedArray)) return new Uint8Array(t.data);
|
|
604
|
+
const a = document.createElement("canvas");
|
|
605
|
+
a.width = r, a.height = s;
|
|
606
|
+
const o = a.getContext("2d", { willReadFrequently: !0 });
|
|
607
|
+
if (!o) throw new Error("Canvas init failed");
|
|
608
|
+
return o.drawImage(t, 0, 0), new Uint8Array(o.getImageData(0, 0, r, s).data);
|
|
609
|
+
}
|
|
610
|
+
static convertSogsRanges(e) {
|
|
611
|
+
const t = (r) => new h.Vector3(r[0], r[1], r[2]);
|
|
612
|
+
return {
|
|
613
|
+
sh0: { min: t(e.sh0.mins), max: t(e.sh0.maxs) },
|
|
614
|
+
means: { min: t(e.means.mins), max: t(e.means.maxs) },
|
|
615
|
+
scales: { min: t(e.scales.mins), max: t(e.scales.maxs) }
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
static calculatePlyRanges(e) {
|
|
619
|
+
const t = new h.Vector3(1 / 0, 1 / 0, 1 / 0), r = new h.Vector3(-1 / 0, -1 / 0, -1 / 0), s = new h.Vector3(1 / 0, 1 / 0, 1 / 0), a = new h.Vector3(-1 / 0, -1 / 0, -1 / 0), o = new h.Vector3(1 / 0, 1 / 0, 1 / 0), i = new h.Vector3(-1 / 0, -1 / 0, -1 / 0);
|
|
620
|
+
let m = 0;
|
|
621
|
+
for (let y = 0; y < e.numSplats; y++) {
|
|
622
|
+
const l = y * 3, u = e.positions[l + 0], x = e.positions[l + 1], g = e.positions[l + 2];
|
|
623
|
+
t.x = Math.min(t.x, u), r.x = Math.max(r.x, u), t.y = Math.min(t.y, x), r.y = Math.max(r.y, x), t.z = Math.min(t.z, g), r.z = Math.max(r.z, g), s.x = Math.min(s.x, e.scales[l]), a.x = Math.max(a.x, e.scales[l]), s.y = Math.min(s.y, e.scales[l + 1]), a.y = Math.max(a.y, e.scales[l + 1]), s.z = Math.min(s.z, e.scales[l + 2]), a.z = Math.max(a.z, e.scales[l + 2]), m = Math.max(
|
|
624
|
+
m,
|
|
625
|
+
e.colors[l],
|
|
626
|
+
e.colors[l + 1],
|
|
627
|
+
e.colors[l + 2]
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
const f = m > 1.5 ? 1 / 255 : 1;
|
|
631
|
+
for (let y = 0; y < e.numSplats; y++) {
|
|
632
|
+
const l = y * 3, u = this.clamp01(e.colors[l + 0] * f), x = this.clamp01(e.colors[l + 1] * f), g = this.clamp01(e.colors[l + 2] * f), v = (u - 0.5) / me, b = (x - 0.5) / me, E = (g - 0.5) / me;
|
|
633
|
+
o.x = Math.min(o.x, v), i.x = Math.max(i.x, v), o.y = Math.min(o.y, b), i.y = Math.max(i.y, b), o.z = Math.min(o.z, E), i.z = Math.max(i.z, E);
|
|
634
|
+
}
|
|
635
|
+
return {
|
|
636
|
+
colorScale: f,
|
|
637
|
+
ranges: {
|
|
638
|
+
sh0: { min: o, max: i },
|
|
639
|
+
means: { min: t, max: r },
|
|
640
|
+
scales: { min: s, max: a }
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
static clamp01(e) {
|
|
645
|
+
return Math.max(0, Math.min(1, e));
|
|
646
|
+
}
|
|
647
|
+
// prettier-ignore
|
|
648
|
+
// private static lerp(a: number, b: number, t: number) { return a + (b - a) * t; } // prettier-ignore
|
|
649
|
+
// private static invSogsMap(v: number) { return Math.sign(v) * Math.log(Math.abs(v) + 1) } // prettier-ignore
|
|
650
|
+
static norm(e, t, r) {
|
|
651
|
+
return (e - t) / (r - t || 1);
|
|
652
|
+
}
|
|
653
|
+
// prettier-ignore
|
|
654
|
+
static sogsDecode(e, t, r) {
|
|
655
|
+
const s = t + (r - t) * e;
|
|
656
|
+
return Math.sign(s) * (Math.exp(Math.abs(s)) - 1);
|
|
657
|
+
}
|
|
464
658
|
}
|
|
465
|
-
class
|
|
466
|
-
constructor(
|
|
467
|
-
super(
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
659
|
+
class st extends h.Loader {
|
|
660
|
+
constructor(t) {
|
|
661
|
+
super(t);
|
|
662
|
+
M(this, "requestId", 0);
|
|
663
|
+
M(this, "worker");
|
|
664
|
+
M(this, "pendingCallbacks", /* @__PURE__ */ new Map());
|
|
471
665
|
this.withCredentials = !0;
|
|
472
|
-
const
|
|
473
|
-
this.worker = new Worker(URL.createObjectURL(
|
|
666
|
+
const r = this.createWorkerCode(), s = new Blob([r], { type: "application/javascript" });
|
|
667
|
+
this.worker = new Worker(URL.createObjectURL(s)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
474
668
|
}
|
|
475
669
|
/**
|
|
476
670
|
* Handles messages received from the parsing worker
|
|
477
671
|
* @param event The message event from the worker
|
|
478
672
|
*/
|
|
479
|
-
onWorkerMessage(
|
|
480
|
-
const { requestId:
|
|
481
|
-
if (!
|
|
482
|
-
if (this.pendingCallbacks.delete(
|
|
483
|
-
if (!
|
|
673
|
+
onWorkerMessage(t) {
|
|
674
|
+
const { requestId: r, error: s, result: a } = t.data, o = this.pendingCallbacks.get(r);
|
|
675
|
+
if (!o) return console.warn(`PlyLoader: Received response for unknown request ${r}`);
|
|
676
|
+
if (this.pendingCallbacks.delete(r), s) return o.reject(new Error(s));
|
|
677
|
+
if (!a) return o.reject(new Error("Worker returned no result"));
|
|
484
678
|
try {
|
|
485
|
-
const i = new
|
|
486
|
-
i.numSplats =
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
679
|
+
const i = new rt(0);
|
|
680
|
+
i.numSplats = a.numSplats, i.positions = new Float32Array(a.positions), i.rotations = new Float32Array(a.rotations), i.scales = new Float32Array(a.scales), i.colors = new Float32Array(a.colors), i.opacities = new Float32Array(a.opacities), i.boundingBox.min.set(
|
|
681
|
+
a.boundingBox.minX,
|
|
682
|
+
a.boundingBox.minY,
|
|
683
|
+
a.boundingBox.minZ
|
|
490
684
|
), i.boundingBox.max.set(
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
), this.worker.terminate()
|
|
685
|
+
a.boundingBox.maxX,
|
|
686
|
+
a.boundingBox.maxY,
|
|
687
|
+
a.boundingBox.maxZ
|
|
688
|
+
), this.worker.terminate();
|
|
689
|
+
const m = Ce.packPly(i);
|
|
690
|
+
i.dispose(), o.resolve(m);
|
|
495
691
|
} catch (i) {
|
|
496
|
-
|
|
692
|
+
o.reject(i);
|
|
497
693
|
}
|
|
498
694
|
}
|
|
499
695
|
/**
|
|
@@ -503,19 +699,19 @@ class ze extends l.Loader {
|
|
|
503
699
|
* @param onProgress Optional progress callback
|
|
504
700
|
* @param onError Optional error callback
|
|
505
701
|
*/
|
|
506
|
-
load(
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
702
|
+
load(t, r, s, a) {
|
|
703
|
+
const o = new h.FileLoader(this.manager);
|
|
704
|
+
o.setResponseType("arraybuffer"), o.setRequestHeader(this.requestHeader), o.setPath(this.path), o.setWithCredentials(this.withCredentials), o.load(
|
|
705
|
+
t,
|
|
510
706
|
(i) => {
|
|
511
|
-
this.parseAsync(i).then((
|
|
512
|
-
|
|
513
|
-
}).catch((
|
|
514
|
-
|
|
707
|
+
this.parseAsync(i).then((m) => {
|
|
708
|
+
r && r(m);
|
|
709
|
+
}).catch((m) => {
|
|
710
|
+
a ? a(m) : console.error(m), this.manager.itemError(t);
|
|
515
711
|
});
|
|
516
712
|
},
|
|
517
|
-
|
|
518
|
-
|
|
713
|
+
s,
|
|
714
|
+
a
|
|
519
715
|
);
|
|
520
716
|
}
|
|
521
717
|
/**
|
|
@@ -524,19 +720,19 @@ class ze extends l.Loader {
|
|
|
524
720
|
* @param onProgress Optional progress callback
|
|
525
721
|
* @returns A Promise that resolves with the parsed SplatData
|
|
526
722
|
*/
|
|
527
|
-
loadAsync(
|
|
528
|
-
return new Promise((
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
|
|
723
|
+
loadAsync(t, r) {
|
|
724
|
+
return new Promise((s, a) => {
|
|
725
|
+
const o = new h.FileLoader(this.manager);
|
|
726
|
+
o.setResponseType("arraybuffer"), o.setRequestHeader(this.requestHeader), o.setPath(this.path), o.setWithCredentials(this.withCredentials), o.load(
|
|
727
|
+
t,
|
|
532
728
|
(i) => {
|
|
533
|
-
this.parseAsync(i).then(
|
|
534
|
-
|
|
729
|
+
this.parseAsync(i).then(s).catch((m) => {
|
|
730
|
+
a(m), this.manager.itemError(t);
|
|
535
731
|
});
|
|
536
732
|
},
|
|
537
|
-
|
|
733
|
+
r,
|
|
538
734
|
(i) => {
|
|
539
|
-
|
|
735
|
+
a(i), this.manager.itemError(t);
|
|
540
736
|
}
|
|
541
737
|
);
|
|
542
738
|
});
|
|
@@ -546,15 +742,15 @@ class ze extends l.Loader {
|
|
|
546
742
|
* @param buffer ArrayBuffer containing PLY data
|
|
547
743
|
* @returns Promise that resolves with parsed SplatData
|
|
548
744
|
*/
|
|
549
|
-
parseAsync(
|
|
550
|
-
return new Promise((
|
|
551
|
-
const
|
|
552
|
-
this.pendingCallbacks.set(
|
|
553
|
-
const
|
|
554
|
-
requestId:
|
|
555
|
-
buffer:
|
|
745
|
+
parseAsync(t) {
|
|
746
|
+
return new Promise((r, s) => {
|
|
747
|
+
const a = this.requestId++;
|
|
748
|
+
this.pendingCallbacks.set(a, { resolve: r, reject: s });
|
|
749
|
+
const o = {
|
|
750
|
+
requestId: a,
|
|
751
|
+
buffer: t
|
|
556
752
|
};
|
|
557
|
-
this.worker.postMessage(
|
|
753
|
+
this.worker.postMessage(o, [t]);
|
|
558
754
|
});
|
|
559
755
|
}
|
|
560
756
|
/**
|
|
@@ -569,14 +765,14 @@ class ze extends l.Loader {
|
|
|
569
765
|
*/
|
|
570
766
|
createWorkerCode() {
|
|
571
767
|
return `(${(function() {
|
|
572
|
-
self.onmessage = (
|
|
573
|
-
const { requestId:
|
|
768
|
+
self.onmessage = (s) => {
|
|
769
|
+
const { requestId: a, buffer: o } = s.data;
|
|
574
770
|
try {
|
|
575
|
-
const i =
|
|
576
|
-
requestId:
|
|
771
|
+
const i = r(o), m = {
|
|
772
|
+
requestId: a,
|
|
577
773
|
result: i
|
|
578
774
|
};
|
|
579
|
-
self.postMessage(
|
|
775
|
+
self.postMessage(m, [
|
|
580
776
|
i.positions,
|
|
581
777
|
i.rotations,
|
|
582
778
|
i.scales,
|
|
@@ -584,215 +780,750 @@ class ze extends l.Loader {
|
|
|
584
780
|
i.opacities
|
|
585
781
|
]);
|
|
586
782
|
} catch (i) {
|
|
587
|
-
const
|
|
588
|
-
requestId:
|
|
783
|
+
const m = {
|
|
784
|
+
requestId: a,
|
|
589
785
|
error: i instanceof Error ? i.message : String(i)
|
|
590
786
|
};
|
|
591
|
-
self.postMessage(
|
|
787
|
+
self.postMessage(m);
|
|
592
788
|
}
|
|
593
789
|
};
|
|
594
|
-
function
|
|
595
|
-
const
|
|
790
|
+
function r(s) {
|
|
791
|
+
const a = new TextDecoder(), o = new Uint8Array(s), i = [112, 108, 121, 10], m = `
|
|
596
792
|
end_header
|
|
597
793
|
`;
|
|
598
|
-
for (let
|
|
599
|
-
if (
|
|
794
|
+
for (let I = 0; I < i.length; I++)
|
|
795
|
+
if (o[I] !== i[I])
|
|
600
796
|
throw new Error(
|
|
601
797
|
"Invalid PLY file: Missing magic bytes"
|
|
602
798
|
);
|
|
603
|
-
let
|
|
604
|
-
for (let
|
|
605
|
-
let
|
|
606
|
-
for (let
|
|
607
|
-
if (
|
|
608
|
-
|
|
799
|
+
let f = 0;
|
|
800
|
+
for (let I = 0; I < o.length - m.length; I++) {
|
|
801
|
+
let d = !0;
|
|
802
|
+
for (let z = 0; z < m.length; z++)
|
|
803
|
+
if (o[I + z] !== m.charCodeAt(z)) {
|
|
804
|
+
d = !1;
|
|
609
805
|
break;
|
|
610
806
|
}
|
|
611
|
-
if (
|
|
612
|
-
|
|
807
|
+
if (d) {
|
|
808
|
+
f = I + m.length;
|
|
613
809
|
break;
|
|
614
810
|
}
|
|
615
811
|
}
|
|
616
|
-
if (
|
|
812
|
+
if (f === 0)
|
|
617
813
|
throw new Error(
|
|
618
814
|
"Invalid PLY file: Could not find end of header"
|
|
619
815
|
);
|
|
620
|
-
const
|
|
621
|
-
|
|
816
|
+
const l = a.decode(
|
|
817
|
+
o.subarray(0, f)
|
|
622
818
|
).split(`
|
|
623
|
-
`),
|
|
624
|
-
let
|
|
625
|
-
for (let
|
|
626
|
-
const
|
|
627
|
-
if (
|
|
628
|
-
const
|
|
629
|
-
switch (
|
|
819
|
+
`), u = [];
|
|
820
|
+
let x = null;
|
|
821
|
+
for (let I = 1; I < l.length; I++) {
|
|
822
|
+
const d = l[I].trim();
|
|
823
|
+
if (d === "" || d === "end_header") continue;
|
|
824
|
+
const z = d.split(" ");
|
|
825
|
+
switch (z[0]) {
|
|
630
826
|
case "format":
|
|
631
|
-
|
|
827
|
+
x = z[1];
|
|
632
828
|
break;
|
|
633
829
|
case "element":
|
|
634
|
-
|
|
635
|
-
name:
|
|
636
|
-
count: parseInt(
|
|
830
|
+
u.push({
|
|
831
|
+
name: z[1],
|
|
832
|
+
count: parseInt(z[2], 10),
|
|
637
833
|
properties: []
|
|
638
834
|
});
|
|
639
835
|
break;
|
|
640
836
|
case "property":
|
|
641
|
-
if (
|
|
837
|
+
if (u.length === 0)
|
|
642
838
|
throw new Error(
|
|
643
839
|
"Invalid PLY file: Property without element"
|
|
644
840
|
);
|
|
645
|
-
|
|
646
|
-
type:
|
|
647
|
-
name:
|
|
841
|
+
u[u.length - 1].properties.push({
|
|
842
|
+
type: z[1],
|
|
843
|
+
name: z[2]
|
|
648
844
|
});
|
|
649
845
|
break;
|
|
650
846
|
}
|
|
651
847
|
}
|
|
652
|
-
if (
|
|
653
|
-
throw new Error(`Unsupported PLY format: ${
|
|
654
|
-
const
|
|
655
|
-
if (!
|
|
848
|
+
if (x !== "binary_little_endian")
|
|
849
|
+
throw new Error(`Unsupported PLY format: ${x}`);
|
|
850
|
+
const g = u.find((I) => I.name === "vertex");
|
|
851
|
+
if (!g)
|
|
656
852
|
throw new Error(
|
|
657
853
|
"Invalid PLY file: No vertex element found"
|
|
658
854
|
);
|
|
659
|
-
const
|
|
660
|
-
let A =
|
|
661
|
-
const
|
|
662
|
-
(
|
|
663
|
-
),
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
],
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
],
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
],
|
|
855
|
+
const v = g.count, b = new Float32Array(v * 3), E = new Float32Array(v * 4), T = new Float32Array(v * 3), P = new Float32Array(v * 3), H = new Float32Array(v), L = new DataView(s);
|
|
856
|
+
let A = f;
|
|
857
|
+
const C = (I) => g.properties.findIndex(
|
|
858
|
+
(d) => d.name === I
|
|
859
|
+
), _ = C("x"), w = C("y"), p = C("z"), R = [
|
|
860
|
+
C("rot_0"),
|
|
861
|
+
C("rot_1"),
|
|
862
|
+
C("rot_2"),
|
|
863
|
+
C("rot_3")
|
|
864
|
+
], q = [
|
|
865
|
+
C("scale_0"),
|
|
866
|
+
C("scale_1"),
|
|
867
|
+
C("scale_2")
|
|
868
|
+
], j = [
|
|
869
|
+
C("f_dc_0"),
|
|
870
|
+
C("f_dc_1"),
|
|
871
|
+
C("f_dc_2")
|
|
872
|
+
], Y = C("opacity");
|
|
677
873
|
if ([
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
874
|
+
_,
|
|
875
|
+
w,
|
|
876
|
+
p,
|
|
681
877
|
...R,
|
|
682
|
-
...
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
].some((
|
|
878
|
+
...q,
|
|
879
|
+
...j,
|
|
880
|
+
Y
|
|
881
|
+
].some((I) => I === -1))
|
|
686
882
|
throw new Error(
|
|
687
883
|
"Invalid PLY file: Missing required properties"
|
|
688
884
|
);
|
|
689
|
-
const
|
|
690
|
-
if (
|
|
691
|
-
const
|
|
692
|
-
return
|
|
885
|
+
const D = 0.28209479177387814, O = (I) => {
|
|
886
|
+
if (I > 0) return 1 / (1 + Math.exp(-I));
|
|
887
|
+
const d = Math.exp(I);
|
|
888
|
+
return d / (1 + d);
|
|
693
889
|
};
|
|
694
|
-
let
|
|
695
|
-
for (let
|
|
696
|
-
const
|
|
697
|
-
for (let
|
|
698
|
-
const
|
|
699
|
-
let
|
|
700
|
-
switch (
|
|
890
|
+
let J = 1 / 0, N = 1 / 0, c = 1 / 0, k = -1 / 0, B = -1 / 0, F = -1 / 0;
|
|
891
|
+
for (let I = 0; I < v; I++) {
|
|
892
|
+
const d = [];
|
|
893
|
+
for (let Se = 0; Se < g.properties.length; Se++) {
|
|
894
|
+
const ze = g.properties[Se].type;
|
|
895
|
+
let ce;
|
|
896
|
+
switch (ze) {
|
|
701
897
|
case "char":
|
|
702
|
-
|
|
898
|
+
ce = L.getInt8(A), A += 1;
|
|
703
899
|
break;
|
|
704
900
|
case "uchar":
|
|
705
|
-
|
|
901
|
+
ce = L.getUint8(A), A += 1;
|
|
706
902
|
break;
|
|
707
903
|
case "short":
|
|
708
|
-
|
|
904
|
+
ce = L.getInt16(A, !0), A += 2;
|
|
709
905
|
break;
|
|
710
906
|
case "ushort":
|
|
711
|
-
|
|
907
|
+
ce = L.getUint16(A, !0), A += 2;
|
|
712
908
|
break;
|
|
713
909
|
case "int":
|
|
714
|
-
|
|
910
|
+
ce = L.getInt32(A, !0), A += 4;
|
|
715
911
|
break;
|
|
716
912
|
case "uint":
|
|
717
|
-
|
|
913
|
+
ce = L.getUint32(A, !0), A += 4;
|
|
718
914
|
break;
|
|
719
915
|
case "float":
|
|
720
|
-
|
|
916
|
+
ce = L.getFloat32(A, !0), A += 4;
|
|
721
917
|
break;
|
|
722
918
|
case "double":
|
|
723
|
-
|
|
919
|
+
ce = L.getFloat64(A, !0), A += 8;
|
|
724
920
|
break;
|
|
725
921
|
default:
|
|
726
922
|
throw new Error(
|
|
727
|
-
`Unsupported property type: ${
|
|
923
|
+
`Unsupported property type: ${ze}`
|
|
728
924
|
);
|
|
729
925
|
}
|
|
730
|
-
|
|
926
|
+
d.push(ce);
|
|
731
927
|
}
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
let
|
|
735
|
-
const
|
|
736
|
-
|
|
928
|
+
const z = d[_], W = d[w], S = d[p], U = I * 3;
|
|
929
|
+
b[U] = z, b[U + 1] = W, b[U + 2] = S, J = Math.min(J, z), N = Math.min(N, W), c = Math.min(c, S), k = Math.max(k, z), B = Math.max(B, W), F = Math.max(F, S);
|
|
930
|
+
let $ = d[R[1]], X = d[R[2]], Q = d[R[3]], Z = d[R[0]];
|
|
931
|
+
const K = Math.sqrt(
|
|
932
|
+
$ * $ + X * X + Q * Q + Z * Z
|
|
737
933
|
);
|
|
738
|
-
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
let
|
|
744
|
-
|
|
745
|
-
const
|
|
746
|
-
|
|
934
|
+
K > 0 && ($ /= K, X /= K, Q /= K, Z /= K), Z < 0 && ($ = -$, X = -X, Q = -Q, Z = -Z);
|
|
935
|
+
const re = I * 4;
|
|
936
|
+
E[re] = $, E[re + 1] = X, E[re + 2] = Q, E[re + 3] = Z;
|
|
937
|
+
const se = I * 3;
|
|
938
|
+
T[se] = d[q[0]], T[se + 1] = d[q[1]], T[se + 2] = d[q[2]];
|
|
939
|
+
let ue = 0.5 + d[j[0]] * D, he = 0.5 + d[j[1]] * D, oe = 0.5 + d[j[2]] * D;
|
|
940
|
+
ue = Math.max(0, Math.min(1, ue)), he = Math.max(0, Math.min(1, he)), oe = Math.max(0, Math.min(1, oe));
|
|
941
|
+
const Me = I * 3;
|
|
942
|
+
P[Me] = ue, P[Me + 1] = he, P[Me + 2] = oe, H[I] = O(d[Y]);
|
|
747
943
|
}
|
|
748
944
|
return {
|
|
749
|
-
numSplats:
|
|
750
|
-
positions:
|
|
751
|
-
rotations:
|
|
752
|
-
scales:
|
|
753
|
-
colors:
|
|
754
|
-
opacities:
|
|
945
|
+
numSplats: v,
|
|
946
|
+
positions: b.buffer,
|
|
947
|
+
rotations: E.buffer,
|
|
948
|
+
scales: T.buffer,
|
|
949
|
+
colors: P.buffer,
|
|
950
|
+
opacities: H.buffer,
|
|
755
951
|
boundingBox: {
|
|
756
|
-
minX:
|
|
757
|
-
minY:
|
|
758
|
-
minZ:
|
|
759
|
-
maxX:
|
|
760
|
-
maxY:
|
|
761
|
-
maxZ:
|
|
952
|
+
minX: J,
|
|
953
|
+
minY: N,
|
|
954
|
+
minZ: c,
|
|
955
|
+
maxX: k,
|
|
956
|
+
maxY: B,
|
|
957
|
+
maxZ: F
|
|
762
958
|
}
|
|
763
959
|
};
|
|
764
960
|
}
|
|
765
961
|
}).toString()})();`;
|
|
766
962
|
}
|
|
767
963
|
}
|
|
768
|
-
|
|
964
|
+
var ee = Uint8Array, fe = Uint16Array, nt = Int32Array, Ue = new ee([
|
|
965
|
+
0,
|
|
966
|
+
0,
|
|
967
|
+
0,
|
|
968
|
+
0,
|
|
969
|
+
0,
|
|
970
|
+
0,
|
|
971
|
+
0,
|
|
972
|
+
0,
|
|
973
|
+
1,
|
|
974
|
+
1,
|
|
975
|
+
1,
|
|
976
|
+
1,
|
|
977
|
+
2,
|
|
978
|
+
2,
|
|
979
|
+
2,
|
|
980
|
+
2,
|
|
981
|
+
3,
|
|
982
|
+
3,
|
|
983
|
+
3,
|
|
984
|
+
3,
|
|
985
|
+
4,
|
|
986
|
+
4,
|
|
987
|
+
4,
|
|
988
|
+
4,
|
|
989
|
+
5,
|
|
990
|
+
5,
|
|
991
|
+
5,
|
|
992
|
+
5,
|
|
993
|
+
0,
|
|
994
|
+
/* unused */
|
|
995
|
+
0,
|
|
996
|
+
0,
|
|
997
|
+
/* impossible */
|
|
998
|
+
0
|
|
999
|
+
]), Ve = new ee([
|
|
1000
|
+
0,
|
|
1001
|
+
0,
|
|
1002
|
+
0,
|
|
1003
|
+
0,
|
|
1004
|
+
1,
|
|
1005
|
+
1,
|
|
1006
|
+
2,
|
|
1007
|
+
2,
|
|
1008
|
+
3,
|
|
1009
|
+
3,
|
|
1010
|
+
4,
|
|
1011
|
+
4,
|
|
1012
|
+
5,
|
|
1013
|
+
5,
|
|
1014
|
+
6,
|
|
1015
|
+
6,
|
|
1016
|
+
7,
|
|
1017
|
+
7,
|
|
1018
|
+
8,
|
|
1019
|
+
8,
|
|
1020
|
+
9,
|
|
1021
|
+
9,
|
|
1022
|
+
10,
|
|
1023
|
+
10,
|
|
1024
|
+
11,
|
|
1025
|
+
11,
|
|
1026
|
+
12,
|
|
1027
|
+
12,
|
|
1028
|
+
13,
|
|
1029
|
+
13,
|
|
1030
|
+
/* unused */
|
|
1031
|
+
0,
|
|
1032
|
+
0
|
|
1033
|
+
]), at = new ee([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]), Le = function(n, e) {
|
|
1034
|
+
for (var t = new fe(31), r = 0; r < 31; ++r)
|
|
1035
|
+
t[r] = e += 1 << n[r - 1];
|
|
1036
|
+
for (var s = new nt(t[30]), r = 1; r < 30; ++r)
|
|
1037
|
+
for (var a = t[r]; a < t[r + 1]; ++a)
|
|
1038
|
+
s[a] = a - t[r] << 5 | r;
|
|
1039
|
+
return { b: t, r: s };
|
|
1040
|
+
}, je = Le(Ue, 2), We = je.b, ot = je.r;
|
|
1041
|
+
We[28] = 258, ot[258] = 28;
|
|
1042
|
+
var it = Le(Ve, 0), ct = it.b, Ie = new fe(32768);
|
|
1043
|
+
for (var G = 0; G < 32768; ++G) {
|
|
1044
|
+
var le = (G & 43690) >> 1 | (G & 21845) << 1;
|
|
1045
|
+
le = (le & 52428) >> 2 | (le & 13107) << 2, le = (le & 61680) >> 4 | (le & 3855) << 4, Ie[G] = ((le & 65280) >> 8 | (le & 255) << 8) >> 1;
|
|
1046
|
+
}
|
|
1047
|
+
var ye = function(n, e, t) {
|
|
1048
|
+
for (var r = n.length, s = 0, a = new fe(e); s < r; ++s)
|
|
1049
|
+
n[s] && ++a[n[s] - 1];
|
|
1050
|
+
var o = new fe(e);
|
|
1051
|
+
for (s = 1; s < e; ++s)
|
|
1052
|
+
o[s] = o[s - 1] + a[s - 1] << 1;
|
|
1053
|
+
var i;
|
|
1054
|
+
if (t) {
|
|
1055
|
+
i = new fe(1 << e);
|
|
1056
|
+
var m = 15 - e;
|
|
1057
|
+
for (s = 0; s < r; ++s)
|
|
1058
|
+
if (n[s])
|
|
1059
|
+
for (var f = s << 4 | n[s], y = e - n[s], l = o[n[s] - 1]++ << y, u = l | (1 << y) - 1; l <= u; ++l)
|
|
1060
|
+
i[Ie[l] >> m] = f;
|
|
1061
|
+
} else
|
|
1062
|
+
for (i = new fe(r), s = 0; s < r; ++s)
|
|
1063
|
+
n[s] && (i[s] = Ie[o[n[s] - 1]++] >> 15 - n[s]);
|
|
1064
|
+
return i;
|
|
1065
|
+
}, ge = new ee(288);
|
|
1066
|
+
for (var G = 0; G < 144; ++G)
|
|
1067
|
+
ge[G] = 8;
|
|
1068
|
+
for (var G = 144; G < 256; ++G)
|
|
1069
|
+
ge[G] = 9;
|
|
1070
|
+
for (var G = 256; G < 280; ++G)
|
|
1071
|
+
ge[G] = 7;
|
|
1072
|
+
for (var G = 280; G < 288; ++G)
|
|
1073
|
+
ge[G] = 8;
|
|
1074
|
+
var Ge = new ee(32);
|
|
1075
|
+
for (var G = 0; G < 32; ++G)
|
|
1076
|
+
Ge[G] = 5;
|
|
1077
|
+
var lt = /* @__PURE__ */ ye(ge, 9, 1), ut = /* @__PURE__ */ ye(Ge, 5, 1), Ae = function(n) {
|
|
1078
|
+
for (var e = n[0], t = 1; t < n.length; ++t)
|
|
1079
|
+
n[t] > e && (e = n[t]);
|
|
1080
|
+
return e;
|
|
1081
|
+
}, ne = function(n, e, t) {
|
|
1082
|
+
var r = e / 8 | 0;
|
|
1083
|
+
return (n[r] | n[r + 1] << 8) >> (e & 7) & t;
|
|
1084
|
+
}, ke = function(n, e) {
|
|
1085
|
+
var t = e / 8 | 0;
|
|
1086
|
+
return (n[t] | n[t + 1] << 8 | n[t + 2] << 16) >> (e & 7);
|
|
1087
|
+
}, ht = function(n) {
|
|
1088
|
+
return (n + 7) / 8 | 0;
|
|
1089
|
+
}, _e = function(n, e, t) {
|
|
1090
|
+
return (e == null || e < 0) && (e = 0), (t == null || t > n.length) && (t = n.length), new ee(n.subarray(e, t));
|
|
1091
|
+
}, mt = [
|
|
1092
|
+
"unexpected EOF",
|
|
1093
|
+
"invalid block type",
|
|
1094
|
+
"invalid length/literal",
|
|
1095
|
+
"invalid distance",
|
|
1096
|
+
"stream finished",
|
|
1097
|
+
"no stream handler",
|
|
1098
|
+
,
|
|
1099
|
+
"no callback",
|
|
1100
|
+
"invalid UTF-8 data",
|
|
1101
|
+
"extra field too long",
|
|
1102
|
+
"date not in range 1980-2099",
|
|
1103
|
+
"filename too long",
|
|
1104
|
+
"stream finishing",
|
|
1105
|
+
"invalid zip data"
|
|
1106
|
+
// determined by unknown compression method
|
|
1107
|
+
], te = function(n, e, t) {
|
|
1108
|
+
var r = new Error(e || mt[n]);
|
|
1109
|
+
if (r.code = n, Error.captureStackTrace && Error.captureStackTrace(r, te), !t)
|
|
1110
|
+
throw r;
|
|
1111
|
+
return r;
|
|
1112
|
+
}, ft = function(n, e, t, r) {
|
|
1113
|
+
var s = n.length, a = r ? r.length : 0;
|
|
1114
|
+
if (!s || e.f && !e.l)
|
|
1115
|
+
return t || new ee(0);
|
|
1116
|
+
var o = !t, i = o || e.i != 2, m = e.i;
|
|
1117
|
+
o && (t = new ee(s * 3));
|
|
1118
|
+
var f = function(X) {
|
|
1119
|
+
var Q = t.length;
|
|
1120
|
+
if (X > Q) {
|
|
1121
|
+
var Z = new ee(Math.max(Q * 2, X));
|
|
1122
|
+
Z.set(t), t = Z;
|
|
1123
|
+
}
|
|
1124
|
+
}, y = e.f || 0, l = e.p || 0, u = e.b || 0, x = e.l, g = e.d, v = e.m, b = e.n, E = s * 8;
|
|
1125
|
+
do {
|
|
1126
|
+
if (!x) {
|
|
1127
|
+
y = ne(n, l, 1);
|
|
1128
|
+
var T = ne(n, l + 1, 3);
|
|
1129
|
+
if (l += 3, T)
|
|
1130
|
+
if (T == 1)
|
|
1131
|
+
x = lt, g = ut, v = 9, b = 5;
|
|
1132
|
+
else if (T == 2) {
|
|
1133
|
+
var A = ne(n, l, 31) + 257, C = ne(n, l + 10, 15) + 4, _ = A + ne(n, l + 5, 31) + 1;
|
|
1134
|
+
l += 14;
|
|
1135
|
+
for (var w = new ee(_), p = new ee(19), R = 0; R < C; ++R)
|
|
1136
|
+
p[at[R]] = ne(n, l + R * 3, 7);
|
|
1137
|
+
l += C * 3;
|
|
1138
|
+
for (var q = Ae(p), j = (1 << q) - 1, Y = ye(p, q, 1), R = 0; R < _; ) {
|
|
1139
|
+
var V = Y[ne(n, l, j)];
|
|
1140
|
+
l += V & 15;
|
|
1141
|
+
var P = V >> 4;
|
|
1142
|
+
if (P < 16)
|
|
1143
|
+
w[R++] = P;
|
|
1144
|
+
else {
|
|
1145
|
+
var D = 0, O = 0;
|
|
1146
|
+
for (P == 16 ? (O = 3 + ne(n, l, 3), l += 2, D = w[R - 1]) : P == 17 ? (O = 3 + ne(n, l, 7), l += 3) : P == 18 && (O = 11 + ne(n, l, 127), l += 7); O--; )
|
|
1147
|
+
w[R++] = D;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
var J = w.subarray(0, A), N = w.subarray(A);
|
|
1151
|
+
v = Ae(J), b = Ae(N), x = ye(J, v, 1), g = ye(N, b, 1);
|
|
1152
|
+
} else
|
|
1153
|
+
te(1);
|
|
1154
|
+
else {
|
|
1155
|
+
var P = ht(l) + 4, H = n[P - 4] | n[P - 3] << 8, L = P + H;
|
|
1156
|
+
if (L > s) {
|
|
1157
|
+
m && te(0);
|
|
1158
|
+
break;
|
|
1159
|
+
}
|
|
1160
|
+
i && f(u + H), t.set(n.subarray(P, L), u), e.b = u += H, e.p = l = L * 8, e.f = y;
|
|
1161
|
+
continue;
|
|
1162
|
+
}
|
|
1163
|
+
if (l > E) {
|
|
1164
|
+
m && te(0);
|
|
1165
|
+
break;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
i && f(u + 131072);
|
|
1169
|
+
for (var c = (1 << v) - 1, k = (1 << b) - 1, B = l; ; B = l) {
|
|
1170
|
+
var D = x[ke(n, l) & c], F = D >> 4;
|
|
1171
|
+
if (l += D & 15, l > E) {
|
|
1172
|
+
m && te(0);
|
|
1173
|
+
break;
|
|
1174
|
+
}
|
|
1175
|
+
if (D || te(2), F < 256)
|
|
1176
|
+
t[u++] = F;
|
|
1177
|
+
else if (F == 256) {
|
|
1178
|
+
B = l, x = null;
|
|
1179
|
+
break;
|
|
1180
|
+
} else {
|
|
1181
|
+
var I = F - 254;
|
|
1182
|
+
if (F > 264) {
|
|
1183
|
+
var R = F - 257, d = Ue[R];
|
|
1184
|
+
I = ne(n, l, (1 << d) - 1) + We[R], l += d;
|
|
1185
|
+
}
|
|
1186
|
+
var z = g[ke(n, l) & k], W = z >> 4;
|
|
1187
|
+
z || te(3), l += z & 15;
|
|
1188
|
+
var N = ct[W];
|
|
1189
|
+
if (W > 3) {
|
|
1190
|
+
var d = Ve[W];
|
|
1191
|
+
N += ke(n, l) & (1 << d) - 1, l += d;
|
|
1192
|
+
}
|
|
1193
|
+
if (l > E) {
|
|
1194
|
+
m && te(0);
|
|
1195
|
+
break;
|
|
1196
|
+
}
|
|
1197
|
+
i && f(u + 131072);
|
|
1198
|
+
var S = u + I;
|
|
1199
|
+
if (u < N) {
|
|
1200
|
+
var U = a - N, $ = Math.min(N, S);
|
|
1201
|
+
for (U + u < 0 && te(3); u < $; ++u)
|
|
1202
|
+
t[u] = r[U + u];
|
|
1203
|
+
}
|
|
1204
|
+
for (; u < S; ++u)
|
|
1205
|
+
t[u] = t[u - N];
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
e.l = x, e.p = B, e.b = u, e.f = y, x && (y = 1, e.m = v, e.d = g, e.n = b);
|
|
1209
|
+
} while (!y);
|
|
1210
|
+
return u != t.length && o ? _e(t, 0, u) : t.subarray(0, u);
|
|
1211
|
+
}, dt = /* @__PURE__ */ new ee(0), ie = function(n, e) {
|
|
1212
|
+
return n[e] | n[e + 1] << 8;
|
|
1213
|
+
}, ae = function(n, e) {
|
|
1214
|
+
return (n[e] | n[e + 1] << 8 | n[e + 2] << 16 | n[e + 3] << 24) >>> 0;
|
|
1215
|
+
}, Ee = function(n, e) {
|
|
1216
|
+
return ae(n, e) + ae(n, e + 4) * 4294967296;
|
|
1217
|
+
};
|
|
1218
|
+
function pt(n, e) {
|
|
1219
|
+
return ft(n, { i: 2 }, e && e.out, e && e.dictionary);
|
|
1220
|
+
}
|
|
1221
|
+
var Re = typeof TextDecoder < "u" && /* @__PURE__ */ new TextDecoder(), xt = 0;
|
|
1222
|
+
try {
|
|
1223
|
+
Re.decode(dt, { stream: !0 }), xt = 1;
|
|
1224
|
+
} catch {
|
|
1225
|
+
}
|
|
1226
|
+
var yt = function(n) {
|
|
1227
|
+
for (var e = "", t = 0; ; ) {
|
|
1228
|
+
var r = n[t++], s = (r > 127) + (r > 223) + (r > 239);
|
|
1229
|
+
if (t + s > n.length)
|
|
1230
|
+
return { s: e, r: _e(n, t - 1) };
|
|
1231
|
+
s ? s == 3 ? (r = ((r & 15) << 18 | (n[t++] & 63) << 12 | (n[t++] & 63) << 6 | n[t++] & 63) - 65536, e += String.fromCharCode(55296 | r >> 10, 56320 | r & 1023)) : s & 1 ? e += String.fromCharCode((r & 31) << 6 | n[t++] & 63) : e += String.fromCharCode((r & 15) << 12 | (n[t++] & 63) << 6 | n[t++] & 63) : e += String.fromCharCode(r);
|
|
1232
|
+
}
|
|
1233
|
+
};
|
|
1234
|
+
function gt(n, e) {
|
|
1235
|
+
if (e) {
|
|
1236
|
+
for (var t = "", r = 0; r < n.length; r += 16384)
|
|
1237
|
+
t += String.fromCharCode.apply(null, n.subarray(r, r + 16384));
|
|
1238
|
+
return t;
|
|
1239
|
+
} else {
|
|
1240
|
+
if (Re)
|
|
1241
|
+
return Re.decode(n);
|
|
1242
|
+
var s = yt(n), a = s.s, t = s.r;
|
|
1243
|
+
return t.length && te(8), a;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
var wt = function(n, e) {
|
|
1247
|
+
return e + 30 + ie(n, e + 26) + ie(n, e + 28);
|
|
1248
|
+
}, vt = function(n, e, t) {
|
|
1249
|
+
var r = ie(n, e + 28), s = gt(n.subarray(e + 46, e + 46 + r), !(ie(n, e + 8) & 2048)), a = e + 46 + r, o = ae(n, e + 20), i = t && o == 4294967295 ? bt(n, a) : [o, ae(n, e + 24), ae(n, e + 42)], m = i[0], f = i[1], y = i[2];
|
|
1250
|
+
return [ie(n, e + 10), m, f, s, a + ie(n, e + 30) + ie(n, e + 32), y];
|
|
1251
|
+
}, bt = function(n, e) {
|
|
1252
|
+
for (; ie(n, e) != 1; e += 4 + ie(n, e + 2))
|
|
1253
|
+
;
|
|
1254
|
+
return [Ee(n, e + 12), Ee(n, e + 4), Ee(n, e + 20)];
|
|
1255
|
+
};
|
|
1256
|
+
function Mt(n, e) {
|
|
1257
|
+
for (var t = {}, r = n.length - 22; ae(n, r) != 101010256; --r)
|
|
1258
|
+
(!r || n.length - r > 65558) && te(13);
|
|
1259
|
+
var s = ie(n, r + 8);
|
|
1260
|
+
if (!s)
|
|
1261
|
+
return {};
|
|
1262
|
+
var a = ae(n, r + 16), o = a == 4294967295 || s == 65535;
|
|
1263
|
+
if (o) {
|
|
1264
|
+
var i = ae(n, r - 12);
|
|
1265
|
+
o = ae(n, i) == 101075792, o && (s = ae(n, i + 32), a = ae(n, i + 48));
|
|
1266
|
+
}
|
|
1267
|
+
for (var m = 0; m < s; ++m) {
|
|
1268
|
+
var f = vt(n, a, o), y = f[0], l = f[1], u = f[2], x = f[3], g = f[4], v = f[5], b = wt(n, v);
|
|
1269
|
+
a = g, y ? y == 8 ? t[x] = pt(n.subarray(b, b + l), { out: new ee(u) }) : te(14, "unknown compression type " + y) : t[x] = _e(n, b, b + l);
|
|
1270
|
+
}
|
|
1271
|
+
return t;
|
|
1272
|
+
}
|
|
1273
|
+
const Oe = (n) => {
|
|
1274
|
+
if (typeof n != "object" || n === null) throw new Error("Invalid SOGS metadata: not an object");
|
|
1275
|
+
const e = n, t = e.version ?? 1;
|
|
1276
|
+
if (t !== 1) throw new Error(`Unsupported SOGS version: ${String(t)}`);
|
|
1277
|
+
const r = (v) => {
|
|
1278
|
+
const b = e[v];
|
|
1279
|
+
if (typeof b != "object" || b === null) throw new Error(`Invalid SOGS metadata section: ${v}`);
|
|
1280
|
+
return b;
|
|
1281
|
+
}, s = r("means"), a = r("sh0"), o = r("quats"), i = r("scales"), m = typeof e.count == "number" && Number.isFinite(e.count) ? e.count : void 0, f = Array.isArray(s.shape) ? s.shape : void 0, y = f && typeof f[0] == "number" ? f[0] : void 0;
|
|
1282
|
+
if (m === void 0 && y === void 0)
|
|
1283
|
+
throw new Error(
|
|
1284
|
+
"Invalid SOGS metadata: unable to determine splat count"
|
|
1285
|
+
);
|
|
1286
|
+
if (m !== void 0 && y !== void 0 && m !== y)
|
|
1287
|
+
throw new Error(
|
|
1288
|
+
"Inconsistent SOGS metadata: count does not match means.shape[0]"
|
|
1289
|
+
);
|
|
1290
|
+
const l = m ?? y, u = (v, b) => {
|
|
1291
|
+
const E = v.mins, T = v.maxs;
|
|
1292
|
+
if (!Array.isArray(E) || E.length !== 3)
|
|
1293
|
+
throw new Error(`${b}.mins must be length-3`);
|
|
1294
|
+
if (!Array.isArray(T) || T.length !== 3)
|
|
1295
|
+
throw new Error(`${b}.maxs must be length-3`);
|
|
1296
|
+
if (![...E, ...T].every(
|
|
1297
|
+
(P) => typeof P == "number" && Number.isFinite(P)
|
|
1298
|
+
))
|
|
1299
|
+
throw new Error(`${b}.mins/maxs must be finite numbers`);
|
|
1300
|
+
return {
|
|
1301
|
+
mins: [E[0], E[1], E[2]],
|
|
1302
|
+
maxs: [T[0], T[1], T[2]]
|
|
1303
|
+
};
|
|
1304
|
+
}, x = (v, b) => {
|
|
1305
|
+
const E = v.mins, T = v.maxs;
|
|
1306
|
+
if (!Array.isArray(E) || E.length !== 4)
|
|
1307
|
+
throw new Error(`${b}.mins must be length-4`);
|
|
1308
|
+
if (!Array.isArray(T) || T.length !== 4)
|
|
1309
|
+
throw new Error(`${b}.maxs must be length-4`);
|
|
1310
|
+
if (![...E, ...T].every(
|
|
1311
|
+
(P) => typeof P == "number" && Number.isFinite(P)
|
|
1312
|
+
))
|
|
1313
|
+
throw new Error(`${b}.mins/maxs must be finite numbers`);
|
|
1314
|
+
return {
|
|
1315
|
+
mins: [E[0], E[1], E[2], E[3]],
|
|
1316
|
+
maxs: [T[0], T[1], T[2], T[3]]
|
|
1317
|
+
};
|
|
1318
|
+
}, g = (v, b) => {
|
|
1319
|
+
const E = v.files;
|
|
1320
|
+
if (!Array.isArray(E)) throw new Error(`${b}.files is not an array`);
|
|
1321
|
+
if (!E.every((T) => typeof T == "string")) throw new Error(`${b}.files contains non-strings`);
|
|
1322
|
+
return E;
|
|
1323
|
+
};
|
|
1324
|
+
return {
|
|
1325
|
+
numSplats: l,
|
|
1326
|
+
files: {
|
|
1327
|
+
sh0: g(a, "sh0"),
|
|
1328
|
+
means: g(s, "means"),
|
|
1329
|
+
quats: g(o, "quats"),
|
|
1330
|
+
scales: g(i, "scales")
|
|
1331
|
+
},
|
|
1332
|
+
ranges: {
|
|
1333
|
+
sh0: x(a, "sh0"),
|
|
1334
|
+
means: u(s, "means"),
|
|
1335
|
+
scales: u(i, "scales")
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
};
|
|
1339
|
+
class St extends h.Loader {
|
|
1340
|
+
constructor(e) {
|
|
1341
|
+
super(e), this.withCredentials = !0;
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
* Detect if a buffer is a ZIP file by checking magic bytes
|
|
1345
|
+
* ZIP files start with signature: PK\x03\x04 (0x50 0x4B 0x03 0x04)
|
|
1346
|
+
*/
|
|
1347
|
+
isZipBuffer(e) {
|
|
1348
|
+
if (e.byteLength < 4) return !1;
|
|
1349
|
+
const t = new Uint8Array(e, 0, 4);
|
|
1350
|
+
return t[0] === 80 && t[1] === 75 && t[2] === 3 && t[3] === 4;
|
|
1351
|
+
}
|
|
1352
|
+
/**
|
|
1353
|
+
* Load a SOGS file (meta.json + textures)
|
|
1354
|
+
* @param url URL of the meta.json file
|
|
1355
|
+
* @param onLoad Optional callback when loading is complete
|
|
1356
|
+
* @param onProgress Optional progress callback
|
|
1357
|
+
* @param onError Optional error callback
|
|
1358
|
+
*/
|
|
1359
|
+
load(e, t, r, s) {
|
|
1360
|
+
const a = new h.FileLoader(this.manager);
|
|
1361
|
+
a.setResponseType("arraybuffer"), a.setRequestHeader(this.requestHeader), a.setPath(this.path), a.setWithCredentials(this.withCredentials), a.load(
|
|
1362
|
+
e,
|
|
1363
|
+
(o) => {
|
|
1364
|
+
this.parseAsync(e, o).then((i) => {
|
|
1365
|
+
t && t(i);
|
|
1366
|
+
}).catch((i) => {
|
|
1367
|
+
this.manager.itemError(e), s && s(i), console.error("Error loading SOGS meta:", i);
|
|
1368
|
+
});
|
|
1369
|
+
},
|
|
1370
|
+
r,
|
|
1371
|
+
s
|
|
1372
|
+
);
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Load a SOGS file asynchronously and return a Promise
|
|
1376
|
+
* @param url URL of the meta.json file
|
|
1377
|
+
* @param onProgress Optional progress callback
|
|
1378
|
+
* @returns A Promise that resolves with the parsed SplatData
|
|
1379
|
+
*/
|
|
1380
|
+
loadAsync(e, t) {
|
|
1381
|
+
return new Promise((r, s) => {
|
|
1382
|
+
const a = new h.FileLoader(this.manager);
|
|
1383
|
+
a.setResponseType("arraybuffer"), a.setRequestHeader(this.requestHeader), a.setPath(this.path), a.setWithCredentials(this.withCredentials), a.load(
|
|
1384
|
+
e,
|
|
1385
|
+
(o) => {
|
|
1386
|
+
this.parseAsync(e, o).then(r).catch((i) => {
|
|
1387
|
+
s(i), this.manager.itemError(e);
|
|
1388
|
+
});
|
|
1389
|
+
},
|
|
1390
|
+
t,
|
|
1391
|
+
(o) => {
|
|
1392
|
+
s(o), this.manager.itemError(e);
|
|
1393
|
+
}
|
|
1394
|
+
);
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
async parseAsync(e, t) {
|
|
1398
|
+
if (!(t instanceof ArrayBuffer)) throw new Error("SOGS loader: expected ArrayBuffer payload");
|
|
1399
|
+
if (this.isZipBuffer(t)) return this.parseZipAsync(t);
|
|
1400
|
+
const s = new TextDecoder("utf-8").decode(t), a = JSON.parse(s);
|
|
1401
|
+
return this.parseMetaAsync(e, a);
|
|
1402
|
+
}
|
|
1403
|
+
async parseMetaAsync(e, t) {
|
|
1404
|
+
const { numSplats: r, files: s, ranges: a } = Oe(t), o = new h.TextureLoader(this.manager);
|
|
1405
|
+
o.setPath(this.path), o.setRequestHeader(this.requestHeader), o.setWithCredentials(this.withCredentials);
|
|
1406
|
+
const i = (E, T) => {
|
|
1407
|
+
try {
|
|
1408
|
+
return new URL(T, E).toString();
|
|
1409
|
+
} catch {
|
|
1410
|
+
return E.substring(0, E.lastIndexOf("/") + 1) + T;
|
|
1411
|
+
}
|
|
1412
|
+
}, m = (E, T) => {
|
|
1413
|
+
const P = i(e, E);
|
|
1414
|
+
return new Promise((H, L) => {
|
|
1415
|
+
o.load(
|
|
1416
|
+
P,
|
|
1417
|
+
(A) => {
|
|
1418
|
+
A.generateMipmaps = !1, A.magFilter = h.NearestFilter, A.minFilter = h.NearestFilter, A.flipY = !1, H(A);
|
|
1419
|
+
},
|
|
1420
|
+
void 0,
|
|
1421
|
+
(A) => {
|
|
1422
|
+
const C = A instanceof Error ? A.message : String(A);
|
|
1423
|
+
L(
|
|
1424
|
+
new Error(
|
|
1425
|
+
`SOGS loader: failed to load ${T} (${E}): ${C}`
|
|
1426
|
+
)
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
);
|
|
1430
|
+
});
|
|
1431
|
+
};
|
|
1432
|
+
if (!Array.isArray(s.sh0) || s.sh0.length < 1) throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");
|
|
1433
|
+
if (!Array.isArray(s.means) || s.means.length < 2) throw new Error("SOGS loader: files.means must have at least 2 entries (means_l, means_u)");
|
|
1434
|
+
if (!Array.isArray(s.quats) || s.quats.length < 1) throw new Error("SOGS loader: files.quats must have at least 1 entry");
|
|
1435
|
+
if (!Array.isArray(s.scales) || s.scales.length < 1) throw new Error("SOGS loader: files.scales must have at least 1 entry");
|
|
1436
|
+
const [f, y, l, u, x] = await Promise.all([
|
|
1437
|
+
m(s.means[0], "means_l"),
|
|
1438
|
+
m(s.means[1], "means_u"),
|
|
1439
|
+
m(s.quats[0], "quats"),
|
|
1440
|
+
m(s.scales[0], "scales"),
|
|
1441
|
+
m(s.sh0[0], "sh0")
|
|
1442
|
+
]), g = { means_l: f, means_u: y, quats: l, scales: u, sh0: x }, v = new Fe(r, a, g), b = Ce.packSogs(v);
|
|
1443
|
+
return v.dispose(), b;
|
|
1444
|
+
}
|
|
1445
|
+
async parseZipAsync(e) {
|
|
1446
|
+
const t = Mt(new Uint8Array(e)), r = Object.keys(t), s = r.find((_) => _.toLowerCase().endsWith("meta.json")) ?? null;
|
|
1447
|
+
if (!s) throw new Error("SOGS loader: zip missing meta.json");
|
|
1448
|
+
const a = s.includes("/") ? s.slice(0, s.lastIndexOf("/") + 1) : "", o = new TextDecoder(), i = JSON.parse(o.decode(t[s])), { numSplats: m, files: f, ranges: y } = Oe(i), l = (_) => _.replace(/\\/g, "/").replace(/^\.?\//, ""), u = (_) => {
|
|
1449
|
+
const w = l(_), p = [l(a + w), w];
|
|
1450
|
+
for (const j of p) {
|
|
1451
|
+
const Y = t[j];
|
|
1452
|
+
if (Y) return Y;
|
|
1453
|
+
}
|
|
1454
|
+
const R = w.split("/").pop(), q = r.find((j) => l(j).endsWith("/" + w)) ?? r.find((j) => l(j).endsWith("/" + R)) ?? r.find((j) => l(j) === R) ?? null;
|
|
1455
|
+
if (q) return t[q];
|
|
1456
|
+
throw new Error(`SOGS loader: zip missing file "${_}"`);
|
|
1457
|
+
}, x = (_) => {
|
|
1458
|
+
const w = _.toLowerCase();
|
|
1459
|
+
return w.endsWith(".png") ? "image/png" : w.endsWith(".jpg") || w.endsWith(".jpeg") ? "image/jpeg" : w.endsWith(".webp") ? "image/webp" : "application/octet-stream";
|
|
1460
|
+
}, g = new h.TextureLoader(this.manager);
|
|
1461
|
+
g.setRequestHeader(this.requestHeader), g.setWithCredentials(this.withCredentials);
|
|
1462
|
+
const v = (_, w) => {
|
|
1463
|
+
const p = u(_), R = new Blob([p], {
|
|
1464
|
+
type: x(_)
|
|
1465
|
+
}), q = URL.createObjectURL(R);
|
|
1466
|
+
return new Promise((j, Y) => {
|
|
1467
|
+
g.load(
|
|
1468
|
+
q,
|
|
1469
|
+
(V) => {
|
|
1470
|
+
URL.revokeObjectURL(q), V.generateMipmaps = !1, V.magFilter = h.NearestFilter, V.minFilter = h.NearestFilter, V.flipY = !1, j(V);
|
|
1471
|
+
},
|
|
1472
|
+
void 0,
|
|
1473
|
+
(V) => {
|
|
1474
|
+
URL.revokeObjectURL(q);
|
|
1475
|
+
const D = V instanceof Error ? V.message : String(V);
|
|
1476
|
+
Y(
|
|
1477
|
+
new Error(
|
|
1478
|
+
`SOGS loader: failed to load ${w} from zip (${_}): ${D}`
|
|
1479
|
+
)
|
|
1480
|
+
);
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
});
|
|
1484
|
+
};
|
|
1485
|
+
if (!Array.isArray(f.sh0) || f.sh0.length < 1) throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");
|
|
1486
|
+
if (!Array.isArray(f.means) || f.means.length < 2) throw new Error("SOGS loader: files.means must have at least 2 entries (means_l, means_u)");
|
|
1487
|
+
if (!Array.isArray(f.quats) || f.quats.length < 1) throw new Error("SOGS loader: files.quats must have at least 1 entry");
|
|
1488
|
+
if (!Array.isArray(f.scales) || f.scales.length < 1) throw new Error("SOGS loader: files.scales must have at least 1 entry");
|
|
1489
|
+
const [b, E, T, P, H] = await Promise.all([
|
|
1490
|
+
v(f.means[0], "means_l"),
|
|
1491
|
+
v(f.means[1], "means_u"),
|
|
1492
|
+
v(f.quats[0], "quats"),
|
|
1493
|
+
v(f.scales[0], "scales"),
|
|
1494
|
+
v(f.sh0[0], "sh0")
|
|
1495
|
+
]), L = { means_l: b, means_u: E, quats: T, scales: P, sh0: H }, A = new Fe(m, y, L), C = Ce.packSogs(A);
|
|
1496
|
+
return A.dispose(), C;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
class At extends h.EventDispatcher {
|
|
769
1500
|
constructor() {
|
|
770
1501
|
super();
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
1502
|
+
M(this, "worker");
|
|
1503
|
+
M(this, "centers", null);
|
|
1504
|
+
M(this, "orderTexture", null);
|
|
774
1505
|
/** Bounding box data for optimization */
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
const
|
|
779
|
-
this.worker = new Worker(URL.createObjectURL(
|
|
1506
|
+
M(this, "chunks", null);
|
|
1507
|
+
M(this, "lastCameraPosition", new h.Vector3());
|
|
1508
|
+
M(this, "lastCameraDirection", new h.Vector3());
|
|
1509
|
+
const t = this.createWorkerCode(), r = new Blob([t], { type: "application/javascript" });
|
|
1510
|
+
this.worker = new Worker(URL.createObjectURL(r)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
780
1511
|
}
|
|
781
1512
|
/**
|
|
782
1513
|
* Handles messages received from the sorting worker.
|
|
783
1514
|
* @param event The message event from the worker.
|
|
784
1515
|
*/
|
|
785
|
-
onWorkerMessage(
|
|
1516
|
+
onWorkerMessage(t) {
|
|
786
1517
|
if (!this.orderTexture || !this.orderTexture.image)
|
|
787
1518
|
return console.error("SplatSorter: Order texture not initialized!");
|
|
788
|
-
const { order:
|
|
789
|
-
if (!(
|
|
1519
|
+
const { order: r, count: s } = t.data, a = this.orderTexture.image.data;
|
|
1520
|
+
if (!(a instanceof Uint32Array))
|
|
790
1521
|
return console.error(
|
|
791
1522
|
"SplatSorter: Order texture data is not a Uint32Array!"
|
|
792
1523
|
);
|
|
793
|
-
|
|
794
|
-
const
|
|
795
|
-
this.worker.postMessage(i, [
|
|
1524
|
+
a.set(new Uint32Array(r)), this.orderTexture.source.data.updateRanges || (this.orderTexture.source.data.updateRanges = []), this.orderTexture.needsUpdate = !0;
|
|
1525
|
+
const o = a.buffer.slice(0), i = { order: o };
|
|
1526
|
+
this.worker.postMessage(i, [o]), this.dispatchEvent({ type: "updated", count: s });
|
|
796
1527
|
}
|
|
797
1528
|
/**
|
|
798
1529
|
* Initializes the sorter with necessary data and textures.
|
|
@@ -801,38 +1532,38 @@ class Pe extends l.EventDispatcher {
|
|
|
801
1532
|
* @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
|
|
802
1533
|
* @param transferOwnership Optional: If true, transfers ownership of centers buffer to worker (saves memory, main thread loses access). Default: false.
|
|
803
1534
|
*/
|
|
804
|
-
init(
|
|
805
|
-
if (!
|
|
1535
|
+
init(t, r, s, a = !1) {
|
|
1536
|
+
if (!t || !(t.image.data instanceof Uint32Array))
|
|
806
1537
|
throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
|
|
807
|
-
if (!
|
|
1538
|
+
if (!r || r.length % 3 !== 0)
|
|
808
1539
|
throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");
|
|
809
|
-
if (
|
|
1540
|
+
if (t.image.data.length < r.length / 3)
|
|
810
1541
|
throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
|
|
811
|
-
if (
|
|
1542
|
+
if (r.buffer.byteLength === 0)
|
|
812
1543
|
throw new Error(
|
|
813
1544
|
"SplatSorter: positions buffer is detached (likely React StrictMode + cached asset). "
|
|
814
1545
|
);
|
|
815
|
-
const
|
|
816
|
-
this.orderTexture =
|
|
1546
|
+
const o = r.length / 3;
|
|
1547
|
+
this.orderTexture = t, a ? this.centers = null : this.centers = r.slice();
|
|
817
1548
|
const i = this.orderTexture.image.data;
|
|
818
|
-
for (let
|
|
1549
|
+
for (let u = 0; u < o; u++) i[u] = u;
|
|
819
1550
|
this.orderTexture.source.data.updateRanges || (this.orderTexture.source.data.updateRanges = []), this.orderTexture.needsUpdate = !0;
|
|
820
|
-
const
|
|
821
|
-
order:
|
|
822
|
-
centers:
|
|
823
|
-
},
|
|
824
|
-
|
|
825
|
-
|
|
1551
|
+
const m = i.buffer.slice(0), f = a ? r.buffer : r.buffer.slice(0), y = {
|
|
1552
|
+
order: m,
|
|
1553
|
+
centers: f
|
|
1554
|
+
}, l = [
|
|
1555
|
+
m,
|
|
1556
|
+
f
|
|
826
1557
|
];
|
|
827
|
-
if (
|
|
828
|
-
this.chunks =
|
|
829
|
-
const
|
|
830
|
-
|
|
1558
|
+
if (s) {
|
|
1559
|
+
this.chunks = s.slice();
|
|
1560
|
+
const u = this.chunks.buffer.slice(0);
|
|
1561
|
+
y.chunks = u, l.push(u);
|
|
831
1562
|
}
|
|
832
|
-
this.worker.postMessage(
|
|
1563
|
+
this.worker.postMessage(y, l), queueMicrotask(() => {
|
|
833
1564
|
this.dispatchEvent({
|
|
834
1565
|
type: "updated",
|
|
835
|
-
count:
|
|
1566
|
+
count: o
|
|
836
1567
|
});
|
|
837
1568
|
});
|
|
838
1569
|
}
|
|
@@ -841,53 +1572,53 @@ class Pe extends l.EventDispatcher {
|
|
|
841
1572
|
* The sorter will only consider splats whose original indices are present in the mapping.
|
|
842
1573
|
* @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
|
|
843
1574
|
*/
|
|
844
|
-
setMapping(
|
|
1575
|
+
setMapping(t) {
|
|
845
1576
|
if (!this.centers)
|
|
846
1577
|
return console.warn(
|
|
847
1578
|
"SplatSorter: Cannot set mapping before initialization."
|
|
848
1579
|
);
|
|
849
|
-
let
|
|
850
|
-
const
|
|
851
|
-
if (!
|
|
852
|
-
const
|
|
853
|
-
return
|
|
854
|
-
centers:
|
|
1580
|
+
let r;
|
|
1581
|
+
const s = [];
|
|
1582
|
+
if (!t) {
|
|
1583
|
+
const m = this.centers.buffer.slice(0);
|
|
1584
|
+
return r = {
|
|
1585
|
+
centers: m,
|
|
855
1586
|
mapping: null
|
|
856
|
-
},
|
|
1587
|
+
}, s.push(m), this.worker.postMessage(r, s);
|
|
857
1588
|
}
|
|
858
|
-
const
|
|
859
|
-
for (let
|
|
860
|
-
const
|
|
861
|
-
if (
|
|
1589
|
+
const a = new Float32Array(t.length * 3);
|
|
1590
|
+
for (let m = 0; m < t.length; m++) {
|
|
1591
|
+
const f = t[m];
|
|
1592
|
+
if (f * 3 + 2 >= this.centers.length) {
|
|
862
1593
|
console.warn(
|
|
863
|
-
`SplatSorter: Mapping index ${
|
|
1594
|
+
`SplatSorter: Mapping index ${f} out of bounds.`
|
|
864
1595
|
);
|
|
865
1596
|
continue;
|
|
866
1597
|
}
|
|
867
|
-
const
|
|
868
|
-
|
|
1598
|
+
const y = f * 3, l = m * 3;
|
|
1599
|
+
a[l + 0] = this.centers[y + 0], a[l + 1] = this.centers[y + 1], a[l + 2] = this.centers[y + 2];
|
|
869
1600
|
}
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
centers:
|
|
1601
|
+
const o = a.buffer.slice(0), i = t.buffer.slice(0);
|
|
1602
|
+
r = {
|
|
1603
|
+
centers: o,
|
|
873
1604
|
mapping: i
|
|
874
|
-
},
|
|
1605
|
+
}, s.push(o, i), this.worker.postMessage(r, s);
|
|
875
1606
|
}
|
|
876
1607
|
/**
|
|
877
1608
|
* Updates the camera parameters used for sorting.
|
|
878
1609
|
* @param position The camera's position in the sorter's local coordinate space.
|
|
879
1610
|
* @param direction The camera's forward direction in the sorter's local coordinate space.
|
|
880
1611
|
*/
|
|
881
|
-
setCamera(
|
|
882
|
-
const
|
|
883
|
-
if (!
|
|
1612
|
+
setCamera(t, r) {
|
|
1613
|
+
const s = this.lastCameraPosition.distanceToSquared(t) > 1e-7, a = this.lastCameraDirection.dot(r) < 0.9999;
|
|
1614
|
+
if (!s && !a)
|
|
884
1615
|
return;
|
|
885
|
-
this.lastCameraPosition.copy(
|
|
886
|
-
const
|
|
887
|
-
cameraPosition: { x:
|
|
888
|
-
cameraDirection: { x:
|
|
1616
|
+
this.lastCameraPosition.copy(t), this.lastCameraDirection.copy(r);
|
|
1617
|
+
const o = {
|
|
1618
|
+
cameraPosition: { x: t.x, y: t.y, z: t.z },
|
|
1619
|
+
cameraDirection: { x: r.x, y: r.y, z: r.z }
|
|
889
1620
|
};
|
|
890
|
-
this.worker.postMessage(
|
|
1621
|
+
this.worker.postMessage(o);
|
|
891
1622
|
}
|
|
892
1623
|
/**
|
|
893
1624
|
* Terminates the Web Worker and cleans up resources.
|
|
@@ -901,258 +1632,186 @@ class Pe extends l.EventDispatcher {
|
|
|
901
1632
|
*/
|
|
902
1633
|
createWorkerCode() {
|
|
903
1634
|
return `(${(function() {
|
|
904
|
-
let
|
|
905
|
-
const
|
|
906
|
-
let
|
|
907
|
-
const
|
|
908
|
-
for (; A <=
|
|
909
|
-
const
|
|
910
|
-
if (
|
|
911
|
-
else if (
|
|
912
|
-
else return
|
|
1635
|
+
let r = null, s = null, a = null, o = null, i = null, m = null, f = !1;
|
|
1636
|
+
const y = { x: 0, y: 0, z: 0 }, l = { x: 0, y: 0, z: 0 }, u = { x: 0, y: 0, z: 0 }, x = { x: 0, y: 0, z: 0 };
|
|
1637
|
+
let g = null, v = null;
|
|
1638
|
+
const b = 32, E = new Array(b).fill(0), T = new Array(b).fill(0), P = new Array(b).fill(0), H = (A, C, _) => {
|
|
1639
|
+
for (; A <= C; ) {
|
|
1640
|
+
const w = C + A >> 1, p = _(w);
|
|
1641
|
+
if (p > 0) A = w + 1;
|
|
1642
|
+
else if (p < 0) C = w - 1;
|
|
1643
|
+
else return w;
|
|
913
1644
|
}
|
|
914
1645
|
return ~A;
|
|
915
1646
|
}, L = () => {
|
|
916
|
-
if (!
|
|
1647
|
+
if (!r || !s || !i || !m)
|
|
917
1648
|
return;
|
|
918
|
-
if (
|
|
919
|
-
const
|
|
920
|
-
order:
|
|
1649
|
+
if (s.length === 0) {
|
|
1650
|
+
const d = {
|
|
1651
|
+
order: r.buffer,
|
|
921
1652
|
count: 0
|
|
922
1653
|
};
|
|
923
|
-
self.postMessage(
|
|
1654
|
+
self.postMessage(d, [r.buffer]), r = null;
|
|
924
1655
|
return;
|
|
925
1656
|
}
|
|
926
|
-
const A = i.x,
|
|
927
|
-
if (!
|
|
1657
|
+
const A = i.x, C = i.y, _ = i.z, w = m.x, p = m.y, R = m.z, q = 1e-4, j = Math.abs(A - y.x) > q || Math.abs(C - y.y) > q || Math.abs(_ - y.z) > q, Y = Math.abs(w - l.x) > q || Math.abs(p - l.y) > q || Math.abs(R - l.z) > q;
|
|
1658
|
+
if (!f && !j && !Y)
|
|
928
1659
|
return;
|
|
929
|
-
|
|
930
|
-
let
|
|
931
|
-
for (let
|
|
932
|
-
const
|
|
933
|
-
|
|
1660
|
+
f = !1, y.x = A, y.y = C, y.z = _, l.x = w, l.y = p, l.z = R;
|
|
1661
|
+
let V = 1 / 0, D = -1 / 0;
|
|
1662
|
+
for (let d = 0; d < 8; ++d) {
|
|
1663
|
+
const z = d & 1 ? u.x : x.x, W = d & 2 ? u.y : x.y, S = d & 4 ? u.z : x.z, U = z * w + W * p + S * R;
|
|
1664
|
+
V = Math.min(V, U), D = Math.max(D, U);
|
|
934
1665
|
}
|
|
935
|
-
const
|
|
1666
|
+
const O = s.length / 3, J = D - V, c = (1 << Math.max(
|
|
936
1667
|
10,
|
|
937
|
-
Math.min(20, Math.ceil(Math.log2(
|
|
1668
|
+
Math.min(20, Math.ceil(Math.log2(O / 4)))
|
|
938
1669
|
)) + 1;
|
|
939
|
-
if ((!
|
|
940
|
-
for (let
|
|
941
|
-
|
|
942
|
-
} else if (
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
for (let
|
|
946
|
-
const
|
|
1670
|
+
if ((!g || g.length !== O) && (g = new Uint32Array(O)), !v || v.length !== c ? v = new Uint32Array(c) : v.fill(0), J < 1e-7) {
|
|
1671
|
+
for (let d = 0; d < O; ++d) g[d] = 0;
|
|
1672
|
+
v[0] = O;
|
|
1673
|
+
} else if (a && a.length > 0) {
|
|
1674
|
+
const d = a.length / 6;
|
|
1675
|
+
E.fill(0);
|
|
1676
|
+
for (let S = 0; S < d; ++S) {
|
|
1677
|
+
const U = S * 6, $ = a[U + 0], X = a[U + 1], Q = a[U + 2], Z = a[U + 3], K = $ * w + X * p + Q * R - V, re = K - Z, se = K + Z, ue = Math.max(
|
|
947
1678
|
0,
|
|
948
|
-
Math.floor(
|
|
949
|
-
),
|
|
950
|
-
|
|
951
|
-
Math.ceil(
|
|
1679
|
+
Math.floor(re * b / J)
|
|
1680
|
+
), he = Math.min(
|
|
1681
|
+
b,
|
|
1682
|
+
Math.ceil(se * b / J)
|
|
952
1683
|
);
|
|
953
|
-
for (let
|
|
954
|
-
|
|
1684
|
+
for (let oe = ue; oe < he; ++oe)
|
|
1685
|
+
E[oe]++;
|
|
955
1686
|
}
|
|
956
|
-
let
|
|
957
|
-
for (let
|
|
958
|
-
|
|
959
|
-
for (let
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
const
|
|
963
|
-
for (let
|
|
964
|
-
const
|
|
1687
|
+
let z = 0;
|
|
1688
|
+
for (let S = 0; S < b; ++S) z += E[S];
|
|
1689
|
+
P[0] = 0, T[0] = 0;
|
|
1690
|
+
for (let S = 1; S < b; ++S)
|
|
1691
|
+
P[S - 1] = E[S - 1] / z * c >>> 0, T[S] = T[S - 1] + P[S - 1];
|
|
1692
|
+
P[b - 1] = E[b - 1] / z * c >>> 0;
|
|
1693
|
+
const W = J / b;
|
|
1694
|
+
for (let S = 0; S < O; ++S) {
|
|
1695
|
+
const U = S * 3, $ = s[U + 0], X = s[U + 1], Q = s[U + 2], Z = $ * w + X * p + Q * R, re = (D - Z) / W, se = Math.max(
|
|
965
1696
|
0,
|
|
966
1697
|
Math.min(
|
|
967
|
-
|
|
968
|
-
Math.floor(
|
|
1698
|
+
b - 1,
|
|
1699
|
+
Math.floor(re)
|
|
969
1700
|
)
|
|
970
|
-
),
|
|
971
|
-
S
|
|
1701
|
+
), ue = re - se, he = T[se] + P[se] * ue >>> 0, oe = Math.min(he, c - 1);
|
|
1702
|
+
g[S] = oe, v[oe]++;
|
|
972
1703
|
}
|
|
973
1704
|
} else {
|
|
974
|
-
const
|
|
975
|
-
for (let
|
|
976
|
-
const
|
|
977
|
-
|
|
1705
|
+
const d = (c - 1) / J;
|
|
1706
|
+
for (let z = 0; z < O; ++z) {
|
|
1707
|
+
const W = z * 3, S = s[W + 0], U = s[W + 1], $ = s[W + 2], X = S * w + U * p + $ * R, Z = (D - X) * d >>> 0, K = Math.min(Z, c - 1);
|
|
1708
|
+
g[z] = K, v[K]++;
|
|
978
1709
|
}
|
|
979
1710
|
}
|
|
980
|
-
for (let
|
|
981
|
-
|
|
982
|
-
for (let
|
|
983
|
-
const
|
|
984
|
-
|
|
1711
|
+
for (let d = 1; d < c; d++)
|
|
1712
|
+
v[d] += v[d - 1];
|
|
1713
|
+
for (let d = O - 1; d >= 0; d--) {
|
|
1714
|
+
const z = g[d], W = --v[z];
|
|
1715
|
+
r[W] = o ? o[d] : d;
|
|
985
1716
|
}
|
|
986
|
-
const
|
|
987
|
-
if (!
|
|
988
|
-
const
|
|
989
|
-
if (!
|
|
1717
|
+
const k = A * w + C * p + _ * R, B = (d) => {
|
|
1718
|
+
if (!r) return -1 / 0;
|
|
1719
|
+
const z = r[d], W = z;
|
|
1720
|
+
if (!s || W * 3 + 2 >= s.length)
|
|
990
1721
|
return -1 / 0;
|
|
991
|
-
const
|
|
992
|
-
return
|
|
1722
|
+
const S = W * 3;
|
|
1723
|
+
return s[S] * w + s[S + 1] * p + s[S + 2] * R - k;
|
|
993
1724
|
};
|
|
994
|
-
let
|
|
995
|
-
if (
|
|
996
|
-
const
|
|
1725
|
+
let F = O;
|
|
1726
|
+
if (O > 0 && B(O - 1) < 0) {
|
|
1727
|
+
const d = H(
|
|
997
1728
|
0,
|
|
998
|
-
|
|
999
|
-
|
|
1729
|
+
O - 1,
|
|
1730
|
+
B
|
|
1000
1731
|
);
|
|
1001
|
-
|
|
1732
|
+
F = d < 0 ? ~d : d;
|
|
1002
1733
|
}
|
|
1003
|
-
const
|
|
1004
|
-
order:
|
|
1005
|
-
count:
|
|
1734
|
+
const I = {
|
|
1735
|
+
order: r.buffer,
|
|
1736
|
+
count: F
|
|
1006
1737
|
};
|
|
1007
|
-
self.postMessage(
|
|
1738
|
+
self.postMessage(I, [r.buffer]), r = null;
|
|
1008
1739
|
};
|
|
1009
1740
|
self.onmessage = (A) => {
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
let
|
|
1013
|
-
if (
|
|
1014
|
-
if (
|
|
1015
|
-
for (let
|
|
1016
|
-
const
|
|
1017
|
-
|
|
1018
|
-
(
|
|
1741
|
+
const C = A.data;
|
|
1742
|
+
C.order && (r = new Uint32Array(C.order));
|
|
1743
|
+
let _ = !1;
|
|
1744
|
+
if (C.centers && (s = new Float32Array(C.centers), _ = !0, f = !0), Object.prototype.hasOwnProperty.call(C, "mapping") && (o = C.mapping ? new Uint32Array(C.mapping) : null, f = !0), C.chunks) {
|
|
1745
|
+
if (a = new Float32Array(C.chunks), a.length > 0 && a[3] > 0)
|
|
1746
|
+
for (let w = 0; w < a.length / 6; ++w) {
|
|
1747
|
+
const p = w * 6, R = a[p + 0], q = a[p + 1], j = a[p + 2], Y = a[p + 3], V = a[p + 4], D = a[p + 5];
|
|
1748
|
+
a[p + 0] = (R + Y) * 0.5, a[p + 1] = (q + V) * 0.5, a[p + 2] = (j + D) * 0.5, a[p + 3] = Math.sqrt(
|
|
1749
|
+
(Y - R) ** 2 + (V - q) ** 2 + (D - j) ** 2
|
|
1019
1750
|
) * 0.5;
|
|
1020
1751
|
}
|
|
1021
|
-
|
|
1752
|
+
f = !0;
|
|
1022
1753
|
}
|
|
1023
|
-
if (
|
|
1024
|
-
|
|
1025
|
-
for (let
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1754
|
+
if (_ && s && s.length > 0) {
|
|
1755
|
+
u.x = x.x = s[0], u.y = x.y = s[1], u.z = x.z = s[2];
|
|
1756
|
+
for (let w = 1; w < s.length / 3; w++) {
|
|
1757
|
+
const p = w * 3;
|
|
1758
|
+
u.x = Math.min(u.x, s[p + 0]), x.x = Math.max(x.x, s[p + 0]), u.y = Math.min(u.y, s[p + 1]), x.y = Math.max(x.y, s[p + 1]), u.z = Math.min(u.z, s[p + 2]), x.z = Math.max(x.z, s[p + 2]);
|
|
1028
1759
|
}
|
|
1029
|
-
} else
|
|
1030
|
-
|
|
1760
|
+
} else _ && s && s.length === 0 && (u.x = x.x = u.y = x.y = u.z = x.z = 0);
|
|
1761
|
+
C.cameraPosition && (i = C.cameraPosition), C.cameraDirection && (m = C.cameraDirection), L();
|
|
1031
1762
|
};
|
|
1032
1763
|
}).toString()})();`;
|
|
1033
1764
|
}
|
|
1034
1765
|
}
|
|
1035
|
-
|
|
1036
|
-
const o = ye(x), t = ye(e);
|
|
1037
|
-
return o | t << 16;
|
|
1038
|
-
};
|
|
1039
|
-
function ye(x) {
|
|
1040
|
-
const e = new Float32Array([x]), t = new Int32Array(e.buffer)[0];
|
|
1041
|
-
let r = t >> 16 & 32768, n = t >> 12 & 2047;
|
|
1042
|
-
const a = t >> 23 & 255;
|
|
1043
|
-
return a < 103 ? r : a > 142 ? (r |= 31744, r |= (a === 255 ? 0 : 1) && t & 8388607, r) : a < 113 ? (n |= 2048, r |= (n >> 114 - a) + (n >> 113 - a & 1), r) : (r |= a - 112 << 10 | n >> 1, r += n & 1, r);
|
|
1044
|
-
}
|
|
1045
|
-
const Fe = new ArrayBuffer(4), ve = new DataView(Fe), Oe = (x) => (ve.setUint32(0, x, !0), ve.getFloat32(0, !0));
|
|
1046
|
-
class De {
|
|
1047
|
-
/**
|
|
1048
|
-
* Create a new TextureManager for a set of splats
|
|
1049
|
-
* @param splatData The splat data to manage textures for
|
|
1050
|
-
*/
|
|
1766
|
+
class kt {
|
|
1051
1767
|
constructor(e) {
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
//
|
|
1056
|
-
|
|
1057
|
-
//
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
const o = e.numSplats;
|
|
1062
|
-
this.textureWidth = Math.ceil(Math.sqrt(o)), this.textureHeight = Math.ceil(o / this.textureWidth), this.transformA = this.createTransformATexture(e), this.transformB = this.createTransformBTexture(e), this.colorTexture = this.createColorTexture(e), this.orderTexture = this.createOrderTexture(o);
|
|
1768
|
+
M(this, "packedGeometry");
|
|
1769
|
+
// RGBA32UI
|
|
1770
|
+
M(this, "packedColor");
|
|
1771
|
+
// RGBA8
|
|
1772
|
+
M(this, "orderTexture");
|
|
1773
|
+
// RB32UI
|
|
1774
|
+
M(this, "width");
|
|
1775
|
+
M(this, "height");
|
|
1776
|
+
this.width = e.textureWidth, this.height = e.textureHeight, this.packedColor = this.createColorTexture(e), this.packedGeometry = this.createGeometryTexture(e), this.orderTexture = this.createOrderTexture(e.numSplats);
|
|
1063
1777
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
this.textureWidth * this.textureHeight * 4
|
|
1072
|
-
);
|
|
1073
|
-
for (let n = 0; n < o; n++) {
|
|
1074
|
-
const a = n * 4, i = n * 3, u = n * 4;
|
|
1075
|
-
t[a] = e.positions[i], t[a + 1] = e.positions[i + 1], t[a + 2] = e.positions[i + 2];
|
|
1076
|
-
const w = e.rotations[u + 0], C = e.rotations[u + 1], _ = Be(w, C);
|
|
1077
|
-
t[a + 3] = Oe(_);
|
|
1078
|
-
}
|
|
1079
|
-
const r = new l.DataTexture(
|
|
1080
|
-
t,
|
|
1081
|
-
this.textureWidth,
|
|
1082
|
-
this.textureHeight,
|
|
1083
|
-
l.RGBAFormat,
|
|
1084
|
-
l.FloatType
|
|
1085
|
-
// Store as Float32, shader will reinterpret bits
|
|
1086
|
-
);
|
|
1087
|
-
return r.magFilter = l.NearestFilter, r.minFilter = l.NearestFilter, r.source.data.updateRanges || (r.source.data.updateRanges = []), r.needsUpdate = !0, r;
|
|
1088
|
-
}
|
|
1089
|
-
/**
|
|
1090
|
-
* Create the transform B texture (scale and rotation xyz)
|
|
1091
|
-
* @param splatData The splat data
|
|
1092
|
-
* @returns DataTexture containing scale and rotation data
|
|
1093
|
-
*/
|
|
1094
|
-
createTransformBTexture(e) {
|
|
1095
|
-
const o = e.numSplats, t = new Float32Array(
|
|
1096
|
-
this.textureWidth * this.textureHeight * 4
|
|
1097
|
-
);
|
|
1098
|
-
for (let n = 0; n < o; n++) {
|
|
1099
|
-
const a = n * 4, i = n * 3, u = n * 4;
|
|
1100
|
-
t[a] = e.scales[i], t[a + 1] = e.scales[i + 1], t[a + 2] = e.scales[i + 2], t[a + 3] = e.rotations[u + 2];
|
|
1101
|
-
}
|
|
1102
|
-
const r = new l.DataTexture(
|
|
1103
|
-
t,
|
|
1104
|
-
this.textureWidth,
|
|
1105
|
-
this.textureHeight,
|
|
1106
|
-
l.RGBAFormat,
|
|
1107
|
-
l.FloatType
|
|
1778
|
+
createGeometryTexture(e) {
|
|
1779
|
+
const t = new h.DataTexture(
|
|
1780
|
+
e.packedGeometry,
|
|
1781
|
+
this.width,
|
|
1782
|
+
this.height,
|
|
1783
|
+
h.RGBAIntegerFormat,
|
|
1784
|
+
h.UnsignedIntType
|
|
1108
1785
|
);
|
|
1109
|
-
return
|
|
1786
|
+
return t.internalFormat = "RGBA32UI", t.minFilter = h.NearestFilter, t.magFilter = h.NearestFilter, t.needsUpdate = !0, t;
|
|
1110
1787
|
}
|
|
1111
|
-
/**
|
|
1112
|
-
* Create the color texture (RGB and opacity)
|
|
1113
|
-
* @param splatData The splat data
|
|
1114
|
-
* @returns DataTexture containing color data
|
|
1115
|
-
*/
|
|
1116
1788
|
createColorTexture(e) {
|
|
1117
|
-
const
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
}
|
|
1124
|
-
const r = new l.DataTexture(
|
|
1125
|
-
t,
|
|
1126
|
-
this.textureWidth,
|
|
1127
|
-
this.textureHeight,
|
|
1128
|
-
l.RGBAFormat,
|
|
1129
|
-
l.FloatType
|
|
1789
|
+
const t = new h.DataTexture(
|
|
1790
|
+
e.packedColor,
|
|
1791
|
+
this.width,
|
|
1792
|
+
this.height,
|
|
1793
|
+
h.RGBAFormat,
|
|
1794
|
+
h.UnsignedByteType
|
|
1130
1795
|
);
|
|
1131
|
-
return
|
|
1796
|
+
return t.minFilter = h.NearestFilter, t.magFilter = h.NearestFilter, t.needsUpdate = !0, t;
|
|
1132
1797
|
}
|
|
1133
|
-
/**
|
|
1134
|
-
* Create the order texture for sorting
|
|
1135
|
-
* @param numSplats Number of splats
|
|
1136
|
-
* @returns DataTexture for storing order indices
|
|
1137
|
-
*/
|
|
1138
1798
|
createOrderTexture(e) {
|
|
1139
|
-
const
|
|
1140
|
-
for (let
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
this.
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
l.UnsignedIntType
|
|
1799
|
+
const t = new Uint32Array(this.width * this.height);
|
|
1800
|
+
for (let s = 0; s < e; s++) t[s] = s;
|
|
1801
|
+
const r = new h.DataTexture(
|
|
1802
|
+
t,
|
|
1803
|
+
this.width,
|
|
1804
|
+
this.height,
|
|
1805
|
+
h.RedIntegerFormat,
|
|
1806
|
+
h.UnsignedIntType
|
|
1148
1807
|
);
|
|
1149
|
-
return
|
|
1808
|
+
return r.minFilter = h.NearestFilter, r.magFilter = h.NearestFilter, r.needsUpdate = !0, r;
|
|
1150
1809
|
}
|
|
1151
1810
|
dispose() {
|
|
1152
|
-
this.
|
|
1811
|
+
this.packedGeometry.dispose(), this.packedColor.dispose(), this.orderTexture.dispose();
|
|
1153
1812
|
}
|
|
1154
1813
|
}
|
|
1155
|
-
const
|
|
1814
|
+
const Et = (
|
|
1156
1815
|
/* glsl */
|
|
1157
1816
|
`
|
|
1158
1817
|
precision highp float;
|
|
@@ -1160,55 +1819,47 @@ precision highp int;
|
|
|
1160
1819
|
precision highp usampler2D;
|
|
1161
1820
|
precision highp sampler2D;
|
|
1162
1821
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
uniform vec2 viewport; // Viewport dimensions (width, height)
|
|
1167
|
-
uniform uint numSplats; // Total number of splats potentially renderable by sorter
|
|
1822
|
+
uniform int texWidth;
|
|
1823
|
+
uniform vec2 viewport;
|
|
1824
|
+
uniform uint numSplats;
|
|
1168
1825
|
|
|
1169
|
-
// Textures
|
|
1170
|
-
uniform
|
|
1171
|
-
uniform
|
|
1172
|
-
uniform
|
|
1173
|
-
uniform highp usampler2D splatOrder; // uint: original splat index
|
|
1826
|
+
// --- Unified Packed Textures ---
|
|
1827
|
+
uniform usampler2D packedGeometry; // RGBA32UI: Geometry (Pos, Rot, Scale)
|
|
1828
|
+
uniform sampler2D packedColor; // RGBA8: Color (RGB) + Opacity (A)
|
|
1829
|
+
uniform usampler2D splatOrder; // R32UI: Sort Index
|
|
1174
1830
|
|
|
1175
|
-
// ---
|
|
1176
|
-
|
|
1177
|
-
|
|
1831
|
+
// --- Decompression Ranges ---
|
|
1832
|
+
uniform vec3 meansMin;
|
|
1833
|
+
uniform vec3 meansMax;
|
|
1834
|
+
uniform vec3 scalesMin;
|
|
1835
|
+
uniform vec3 scalesMax;
|
|
1836
|
+
uniform vec3 sh0Min;
|
|
1837
|
+
uniform vec3 sh0Max;
|
|
1178
1838
|
|
|
1179
|
-
//
|
|
1180
|
-
|
|
1181
|
-
// position.xy: corner coords (-1..1)
|
|
1182
|
-
// position.z: index within the instance block (0..INSTANCE_BUFFER_SIZE-1)
|
|
1839
|
+
// --- Attributes ---
|
|
1840
|
+
in uint splatInstanceIndex;
|
|
1183
1841
|
|
|
1184
|
-
// ---
|
|
1185
|
-
|
|
1186
|
-
|
|
1842
|
+
// --- Outputs ---
|
|
1843
|
+
out vec4 vColor;
|
|
1844
|
+
out vec2 vUv;
|
|
1187
1845
|
|
|
1188
1846
|
// --- Constants ---
|
|
1189
|
-
|
|
1847
|
+
const vec4 DISCARD_VERTEX = vec4(0.0, 0.0, 2.0, 1.0);
|
|
1848
|
+
const float SH_C0 = 0.28209479177387814; // 1/(2*sqrt(pi))
|
|
1849
|
+
const float QUAT_NORM = 1.41421356237; // sqrt(2)
|
|
1190
1850
|
|
|
1191
1851
|
// --- Helper Functions ---
|
|
1192
1852
|
|
|
1193
|
-
//
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
// Returns (w,x,y,z) format for quatToMat3 compatibility
|
|
1197
|
-
vec4 unpackRotation(float xy_packed, float z) {
|
|
1198
|
-
vec2 xy = unpackHalf2x16(floatBitsToUint(xy_packed));
|
|
1199
|
-
float x = xy.x;
|
|
1200
|
-
float y = xy.y;
|
|
1201
|
-
float w_squared = 1.0 - x*x - y*y - z*z;
|
|
1202
|
-
float w = (w_squared < 0.0) ? 0.0 : sqrt(w_squared);
|
|
1203
|
-
return vec4(w, x, y, z); // Return (w,x,y,z)
|
|
1853
|
+
// Extract raw bytes as integers (no /255 )
|
|
1854
|
+
uvec4 unpackBytes(uint v) {
|
|
1855
|
+
return (uvec4(v) >> uvec4(24u, 16u, 8u, 0u)) & 0xffu;
|
|
1204
1856
|
}
|
|
1205
1857
|
|
|
1206
|
-
// Convert quaternion to 3x3 rotation matrix
|
|
1207
1858
|
mat3 quatToMat3(vec4 R) {
|
|
1208
1859
|
vec4 R2 = R + R;
|
|
1209
1860
|
float X = R2.x * R.w;
|
|
1210
|
-
vec4 Y
|
|
1211
|
-
vec4 Z
|
|
1861
|
+
vec4 Y = R2.y * R;
|
|
1862
|
+
vec4 Z = R2.z * R;
|
|
1212
1863
|
float W = R2.w * R.w;
|
|
1213
1864
|
|
|
1214
1865
|
return mat3(
|
|
@@ -1224,199 +1875,176 @@ mat3 quatToMat3(vec4 R) {
|
|
|
1224
1875
|
);
|
|
1225
1876
|
}
|
|
1226
1877
|
|
|
1227
|
-
// Calculate model-space covariance components
|
|
1228
1878
|
void getModelCovariance(vec3 scale, vec4 rotation, out vec3 covA, out vec3 covB) {
|
|
1229
1879
|
mat3 rot = quatToMat3(rotation);
|
|
1230
|
-
|
|
1231
|
-
// M = S * R (scale COLUMNS, then transpose)
|
|
1232
1880
|
mat3 M = transpose(mat3(
|
|
1233
|
-
scale.x * rot[0],
|
|
1234
|
-
scale.y * rot[1],
|
|
1235
|
-
scale.z * rot[2]
|
|
1881
|
+
scale.x * rot[0],
|
|
1882
|
+
scale.y * rot[1],
|
|
1883
|
+
scale.z * rot[2]
|
|
1236
1884
|
));
|
|
1237
1885
|
|
|
1238
1886
|
covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));
|
|
1239
1887
|
covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));
|
|
1240
1888
|
}
|
|
1241
1889
|
|
|
1242
|
-
// --- Main
|
|
1243
|
-
void main(
|
|
1244
|
-
// Calculate
|
|
1245
|
-
uint instanceOffset = uint(position.z);
|
|
1246
|
-
uint
|
|
1890
|
+
// --- Main ---
|
|
1891
|
+
void main() {
|
|
1892
|
+
// Calculate Instance ID & Source Data UV
|
|
1893
|
+
uint instanceOffset = uint(position.z);
|
|
1894
|
+
uint orderIndex = splatInstanceIndex + instanceOffset;
|
|
1247
1895
|
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Off-screen
|
|
1896
|
+
if (orderIndex >= numSplats) {
|
|
1897
|
+
gl_Position = DISCARD_VERTEX;
|
|
1251
1898
|
return;
|
|
1252
1899
|
}
|
|
1253
1900
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
ivec2 orderUV = ivec2(orderedSplatIndex % texWidth, orderedSplatIndex / texWidth);
|
|
1257
|
-
uint originalSplatIndex = texelFetch(splatOrder, orderUV, 0).r;
|
|
1901
|
+
uint w = uint(texWidth);
|
|
1902
|
+
ivec2 orderUV = ivec2(int(orderIndex % w), int(orderIndex / w));
|
|
1258
1903
|
|
|
1259
|
-
|
|
1904
|
+
// Fetch original splat ID from the order texture
|
|
1905
|
+
uint splatID = texelFetch(splatOrder, orderUV, 0).r;
|
|
1906
|
+
ivec2 dataUV = ivec2(int(splatID % w), int(splatID / w));
|
|
1260
1907
|
|
|
1261
|
-
// Fetch
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
vec4
|
|
1908
|
+
// Fetch Packed Data
|
|
1909
|
+
// x: Means Low, y: Means High, z: Rotation, w: Scale
|
|
1910
|
+
uvec4 geom = texelFetch(packedGeometry, dataUV, 0);
|
|
1911
|
+
vec4 colorRaw = texelFetch(packedColor, dataUV, 0);
|
|
1265
1912
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
float splatOpacity = texColor.a;
|
|
1913
|
+
// Decompress Position (Means) (assume world-space)
|
|
1914
|
+
// Reconstruct 16-bit values from two 8-bit channels
|
|
1915
|
+
uvec3 lo = unpackBytes(geom.x).xyz;
|
|
1916
|
+
uvec3 hi = unpackBytes(geom.y).xyz;
|
|
1271
1917
|
|
|
1272
|
-
|
|
1918
|
+
// (hi << 8) | lo => 0..65535 then normalize
|
|
1919
|
+
vec3 meansNorm = vec3((hi << 8u) | lo) * (1.0 / 65535.0);
|
|
1920
|
+
vec3 modelCenter = mix(meansMin, meansMax, meansNorm);
|
|
1273
1921
|
|
|
1274
|
-
//
|
|
1922
|
+
// Decompress Rotation (Quaternions)
|
|
1923
|
+
uvec4 qB = unpackBytes(geom.z);
|
|
1924
|
+
vec3 abc = (vec3(qB.xyz) * (1.0 / 255.0) - 0.5) * QUAT_NORM;
|
|
1925
|
+
float d = sqrt(max(0.0, 1.0 - dot(abc, abc)));
|
|
1926
|
+
uint mode = qB.w; // already 0..3
|
|
1275
1927
|
|
|
1276
|
-
// Compute normalized view-space center
|
|
1277
|
-
vec4 centerClipRaw = modelViewMatrix * vec4(splatPosition, 1.0);
|
|
1278
|
-
vec3 centerView = centerClipRaw.xyz / centerClipRaw.w;
|
|
1279
1928
|
|
|
1280
|
-
//
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1929
|
+
// Reconstruct Quaternion (x, y, z, w)
|
|
1930
|
+
// quat in (w,x,y,z)
|
|
1931
|
+
vec4 quat;
|
|
1932
|
+
if (mode == 0u) quat = vec4(d, abc); // (w, x, y, z)
|
|
1933
|
+
else if (mode == 1u) quat = vec4(abc.x, d, abc.yz); // stored (w,y,z)
|
|
1934
|
+
else if (mode == 2u) quat = vec4(abc.xy, d, abc.z); // stored (w,x,z)
|
|
1935
|
+
else quat = vec4(abc, d); // stored (w,x,y)
|
|
1285
1936
|
|
|
1286
|
-
//
|
|
1287
|
-
|
|
1937
|
+
// Decompress Scale
|
|
1938
|
+
uvec3 sB = unpackBytes(geom.w).xyz;
|
|
1939
|
+
vec3 sNorm = vec3(sB) * (1.0 / 255.0);
|
|
1940
|
+
vec3 sLerp = mix(scalesMin, scalesMax, sNorm);
|
|
1941
|
+
vec3 scale = exp(sLerp); // log scale stored
|
|
1288
1942
|
|
|
1289
|
-
//
|
|
1943
|
+
// Decompress Color & Opacity
|
|
1944
|
+
vec4 clr;
|
|
1945
|
+
vec3 sh = mix(sh0Min, sh0Max, colorRaw.rgb);
|
|
1946
|
+
clr.rgb = vec3(0.5) + sh * SH_C0;
|
|
1947
|
+
clr.a = colorRaw.a; // Opacity passed directly (linear or sigmoid handled by loader)
|
|
1290
1948
|
|
|
1291
|
-
//
|
|
1949
|
+
// --- Standard Gaussian Splat Projection ---
|
|
1950
|
+
|
|
1951
|
+
// View Space Setup
|
|
1952
|
+
mat4 modelView = modelViewMatrix;
|
|
1953
|
+
vec4 centerView = modelView * vec4(modelCenter, 1.0);
|
|
1954
|
+
|
|
1955
|
+
// Cull behind camera
|
|
1956
|
+
if (centerView.z > -0.2) {
|
|
1957
|
+
gl_Position = DISCARD_VERTEX;
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
// Covariance in 3D
|
|
1292
1962
|
vec3 covA, covB;
|
|
1293
|
-
getModelCovariance(
|
|
1294
|
-
mat3 Vrk = mat3(
|
|
1295
|
-
covA.x, covA.y, covA.z,
|
|
1296
|
-
covA.y, covB.x, covB.y, // covB.x is Vrk[1][1]
|
|
1297
|
-
covA.z, covB.y, covB.z // covB.y is Vrk[1][2], covB.z is Vrk[2][2]
|
|
1298
|
-
);
|
|
1963
|
+
getModelCovariance(scale, quat, covA, covB);
|
|
1299
1964
|
|
|
1300
|
-
//
|
|
1301
|
-
// Requres focal lenghts and view-space center depth (tz)
|
|
1965
|
+
// Project to 2D
|
|
1302
1966
|
float focalX = viewport.x * projectionMatrix[0][0];
|
|
1303
1967
|
float focalY = viewport.y * projectionMatrix[1][1];
|
|
1304
|
-
float
|
|
1305
|
-
|
|
1968
|
+
float J1 = focalX / centerView.z;
|
|
1969
|
+
vec2 J2 = -J1 / centerView.z * centerView.xy;
|
|
1306
1970
|
|
|
1307
|
-
// Jacobian J = [fx/tz, 0, -fx*tx/tz^2]
|
|
1308
|
-
// [0, fy/tz, -fy*ty/tz^2]
|
|
1309
1971
|
mat3 J = mat3(
|
|
1310
|
-
|
|
1311
|
-
0.0,
|
|
1312
|
-
0.0,
|
|
1972
|
+
J1, 0.0, J2.x,
|
|
1973
|
+
0.0, J1, J2.y,
|
|
1974
|
+
0.0, 0.0, 0.0
|
|
1313
1975
|
);
|
|
1314
1976
|
|
|
1315
|
-
|
|
1316
|
-
mat3 W = transpose(mat3(modelViewMatrix));
|
|
1317
|
-
// Calculate T = W * J
|
|
1977
|
+
mat3 W = transpose(mat3(modelView));
|
|
1318
1978
|
mat3 T = W * J;
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
float cov2D_22 = SigmaProj[1][1] + 0.3;
|
|
1326
|
-
|
|
1327
|
-
// --- Calculate 2D Screen Space Rotation & Scale ---
|
|
1328
|
-
|
|
1329
|
-
float det = cov2D_11 * cov2D_22 - cov2D_12 * cov2D_12;
|
|
1330
|
-
// Ensure determinant is non-negative before sqrt
|
|
1331
|
-
if (det <= 0.0) {
|
|
1332
|
-
gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Discard degenerated
|
|
1333
|
-
return;
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
float trace = cov2D_11 + cov2D_22;
|
|
1337
|
-
float traceOver2 = 0.5 * trace;
|
|
1338
|
-
float discriminantSqrt = sqrt(max(traceOver2 * traceOver2 - det, 0.0)); // Avoid sqrt(negative)
|
|
1339
|
-
|
|
1340
|
-
float lambda1 = traceOver2 + discriminantSqrt; // Larger eigenvalue
|
|
1341
|
-
float lambda2 = max(0.1, traceOver2 - discriminantSqrt); // Smaller eigenvalue, clamped
|
|
1342
|
-
|
|
1343
|
-
// Compute eigenvectors
|
|
1344
|
-
|
|
1345
|
-
vec2 v1_eigen, v2_eigen;
|
|
1346
|
-
|
|
1347
|
-
// Handle diagonal case
|
|
1348
|
-
if(abs(cov2D_12) < 1e-16) {
|
|
1349
|
-
v1_eigen = vec2(1.0, 0.0);
|
|
1350
|
-
} else {
|
|
1351
|
-
v1_eigen = normalize(vec2(cov2D_12, lambda1 - cov2D_11)); // diagonal choice
|
|
1352
|
-
}
|
|
1979
|
+
mat3 Vrk = mat3(
|
|
1980
|
+
covA.x, covA.y, covA.z,
|
|
1981
|
+
covA.y, covB.x, covB.y,
|
|
1982
|
+
covA.z, covB.y, covB.z
|
|
1983
|
+
);
|
|
1984
|
+
mat3 cov = transpose(T) * Vrk * T;
|
|
1353
1985
|
|
|
1354
|
-
|
|
1986
|
+
// Eigendecomposition for Quad dimensions
|
|
1987
|
+
float diagonal1 = cov[0][0] + 0.3;
|
|
1988
|
+
float offDiagonal = cov[0][1];
|
|
1989
|
+
float diagonal2 = cov[1][1] + 0.3;
|
|
1355
1990
|
|
|
1356
|
-
|
|
1357
|
-
float
|
|
1358
|
-
float
|
|
1359
|
-
float
|
|
1991
|
+
float mid = 0.5 * (diagonal1 + diagonal2);
|
|
1992
|
+
float radius = length(vec2((diagonal1 - diagonal2) * 0.5, offDiagonal));
|
|
1993
|
+
float lambda1 = mid + radius;
|
|
1994
|
+
float lambda2 = max(mid - radius, 0.1);
|
|
1360
1995
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1996
|
+
// Screen space quad vectors
|
|
1997
|
+
float vmin = min(1024.0, min(viewport.x, viewport.y)); // Safety clamp
|
|
1998
|
+
float l1 = 2.0 * min(sqrt(2.0 * lambda1), vmin);
|
|
1999
|
+
float l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);
|
|
1364
2000
|
|
|
1365
|
-
//
|
|
1366
|
-
if (l1 < 2.0 && l2 < 2.0) {
|
|
1367
|
-
|
|
1368
|
-
|
|
2001
|
+
// Discard tiny splats
|
|
2002
|
+
if (l1 < 2.0 && l2 < 2.0) {
|
|
2003
|
+
gl_Position = DISCARD_VERTEX;
|
|
2004
|
+
return;
|
|
1369
2005
|
}
|
|
1370
2006
|
|
|
1371
|
-
|
|
1372
|
-
vec2
|
|
1373
|
-
vec2
|
|
2007
|
+
vec2 diagVec = normalize(vec2(offDiagonal, lambda1 - diagonal1));
|
|
2008
|
+
vec2 v1 = l1 * diagVec;
|
|
2009
|
+
vec2 v2 = l2 * vec2(diagVec.y, -diagVec.x);
|
|
1374
2010
|
|
|
1375
|
-
//
|
|
1376
|
-
|
|
1377
|
-
vec2 c =
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
2011
|
+
// Vertex Position (Quad Expansion)
|
|
2012
|
+
vec4 centerProj = projectionMatrix * centerView;
|
|
2013
|
+
vec2 c = centerProj.ww / viewport; // Correction for clip space
|
|
2014
|
+
|
|
2015
|
+
// Frustum cull
|
|
2016
|
+
if (any(greaterThan(abs(centerProj.xy) - vec2(max(l1, l2)) * c, centerProj.ww))) {
|
|
2017
|
+
gl_Position = DISCARD_VERTEX;
|
|
1383
2018
|
return;
|
|
1384
2019
|
}
|
|
1385
2020
|
|
|
1386
|
-
//
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
// Apply clip to the corner offset *before* calculating screen space offset
|
|
1397
|
-
vec2 clippedCornerOffset = cornerOffset * clip;
|
|
1398
|
-
vec2 screenOffsetPixels = clippedCornerOffset.x * v1_scaled + clippedCornerOffset.y * v2_scaled;
|
|
1399
|
-
|
|
1400
|
-
// Convert pixel offset to clip space offset
|
|
1401
|
-
vec2 clipOffset = screenOffsetPixels * (centerClip.w / viewport);
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
// Apply offset to center clip position
|
|
1405
|
-
gl_Position = centerClip + vec4(clipOffset, 0.0, 0.0);
|
|
1406
|
-
|
|
1407
|
-
// --- Pass data to Fragment Shader ---
|
|
2021
|
+
// Quad offset based on 'position' attribute (-1 to 1)
|
|
2022
|
+
vec2 offset = (position.x * v1 + position.y * v2) * c;
|
|
2023
|
+
|
|
2024
|
+
// Corner Clipping (for gaussian shape)
|
|
2025
|
+
// Assuming simple linear opacity here, otherwise inverse sigmoid logic required
|
|
2026
|
+
float alpha = max(clr.a, 1.0/255.0);
|
|
2027
|
+
float clip = min(1.0, sqrt(-log(1.0 / 255.0 / alpha)) / 2.0);
|
|
2028
|
+
|
|
2029
|
+
offset *= clip;
|
|
2030
|
+
vec2 clippedUV = position.xy * clip;
|
|
1408
2031
|
|
|
1409
|
-
|
|
1410
|
-
|
|
2032
|
+
gl_Position = centerProj + vec4(offset, 0.0, 0.0);
|
|
2033
|
+
|
|
2034
|
+
// Outputs
|
|
2035
|
+
vUv = clippedUV;
|
|
2036
|
+
vColor = vec4(max(clr.rgb, vec3(0.0)), clr.a);
|
|
1411
2037
|
}
|
|
1412
2038
|
`
|
|
1413
|
-
),
|
|
2039
|
+
), Ct = (
|
|
1414
2040
|
/* glsl */
|
|
1415
2041
|
`
|
|
1416
2042
|
precision highp float;
|
|
1417
2043
|
|
|
1418
|
-
|
|
1419
|
-
|
|
2044
|
+
in vec4 vColor; // Color and opacity passed from vertex shader
|
|
2045
|
+
in vec2 vUv; // Quad UV coordinates (-1 to 1) passed from vertex shader
|
|
2046
|
+
|
|
2047
|
+
out vec4 fragColor; // Output variable
|
|
1420
2048
|
|
|
1421
2049
|
// Fast approximate e^x based on https://nic.schraudolph.org/pubs/Schraudolph99.pdf
|
|
1422
2050
|
const float EXP_A = 12102203.0; // ≈ 2^23 / ln(2)
|
|
@@ -1440,88 +2068,86 @@ void main(void) {
|
|
|
1440
2068
|
if (alpha < 1.0 / 255.0) discard; // Discard fragments with very low alpha
|
|
1441
2069
|
|
|
1442
2070
|
// Premultiply color by alpha (required for correct blending)
|
|
1443
|
-
|
|
2071
|
+
fragColor = vec4(vColor.rgb * alpha, alpha);
|
|
1444
2072
|
}
|
|
1445
2073
|
`
|
|
1446
2074
|
);
|
|
1447
|
-
class
|
|
2075
|
+
class It extends h.ShaderMaterial {
|
|
1448
2076
|
constructor(e = {}) {
|
|
1449
|
-
const
|
|
1450
|
-
// Textures
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
2077
|
+
const t = {
|
|
2078
|
+
// Packed Textures
|
|
2079
|
+
packedGeometry: { value: null },
|
|
2080
|
+
// RGBA32UI: .r=MeansLow, .g=MeansHigh, .b=Quats, .a=Scales
|
|
2081
|
+
packedColor: { value: null },
|
|
2082
|
+
// RGBA8: .rgb=Color, .a=Opacity
|
|
1454
2083
|
splatOrder: { value: null },
|
|
1455
|
-
//
|
|
1456
|
-
|
|
1457
|
-
|
|
2084
|
+
// Index map
|
|
2085
|
+
// Decompression Ranges
|
|
2086
|
+
meansMin: { value: new h.Vector3() },
|
|
2087
|
+
meansMax: { value: new h.Vector3() },
|
|
2088
|
+
scalesMin: { value: new h.Vector3() },
|
|
2089
|
+
scalesMax: { value: new h.Vector3() },
|
|
2090
|
+
sh0Min: { value: new h.Vector3() },
|
|
2091
|
+
sh0Max: { value: new h.Vector3() },
|
|
2092
|
+
// Render State
|
|
2093
|
+
texWidth: { value: 0 },
|
|
2094
|
+
viewport: { value: new h.Vector2(1, 1) },
|
|
1458
2095
|
numSplats: { value: 0 }
|
|
1459
|
-
// Max splats to render (updated by sorter)
|
|
1460
2096
|
};
|
|
1461
2097
|
super({
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
2098
|
+
uniforms: t,
|
|
2099
|
+
vertexShader: Et,
|
|
2100
|
+
fragmentShader: Ct,
|
|
1465
2101
|
transparent: !0,
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
blendDst:
|
|
1473
|
-
|
|
1474
|
-
// source alpha comes from shader
|
|
1475
|
-
blendDstAlpha: l.OneMinusSrcAlphaFactor,
|
|
1476
|
-
blendEquation: l.AddEquation,
|
|
1477
|
-
blendEquationAlpha: l.AddEquation,
|
|
2102
|
+
glslVersion: h.GLSL3,
|
|
2103
|
+
blendSrc: h.OneFactor,
|
|
2104
|
+
blendSrcAlpha: h.OneFactor,
|
|
2105
|
+
blending: h.CustomBlending,
|
|
2106
|
+
blendEquation: h.AddEquation,
|
|
2107
|
+
blendEquationAlpha: h.AddEquation,
|
|
2108
|
+
blendDst: h.OneMinusSrcAlphaFactor,
|
|
2109
|
+
blendDstAlpha: h.OneMinusSrcAlphaFactor,
|
|
1478
2110
|
depthTest: !0,
|
|
1479
2111
|
depthWrite: !1,
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
// prettier-ignore
|
|
1488
|
-
}), e.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = l.NoBlending);
|
|
2112
|
+
side: h.DoubleSide,
|
|
2113
|
+
alphaTest: e.alphaTest ?? 0,
|
|
2114
|
+
toneMapped: e.toneMapped ?? !1
|
|
2115
|
+
}), e.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = h.NoBlending);
|
|
2116
|
+
}
|
|
2117
|
+
setTexWidth(e) {
|
|
2118
|
+
this.uniforms.texWidth.value = e | 0;
|
|
1489
2119
|
}
|
|
1490
2120
|
/**
|
|
1491
2121
|
* Update the viewport size
|
|
1492
2122
|
* @param width Viewport width
|
|
1493
2123
|
* @param height Viewport height
|
|
1494
2124
|
*/
|
|
1495
|
-
updateViewport(e,
|
|
1496
|
-
this.uniforms.viewport.value.set(e,
|
|
2125
|
+
updateViewport(e, t) {
|
|
2126
|
+
this.uniforms.viewport.value.set(e, t);
|
|
1497
2127
|
}
|
|
1498
2128
|
/**
|
|
1499
|
-
* Set
|
|
1500
|
-
* @param texture Texture containing positions
|
|
2129
|
+
* Set the main packed geometry texture (RGBA32UI)
|
|
1501
2130
|
*/
|
|
1502
|
-
|
|
1503
|
-
this.uniforms.
|
|
2131
|
+
setPackedGeometry(e) {
|
|
2132
|
+
this.uniforms.packedGeometry.value = e;
|
|
1504
2133
|
}
|
|
1505
2134
|
/**
|
|
1506
|
-
* Set
|
|
1507
|
-
* @param texture Texture containing rotation and scale data
|
|
2135
|
+
* Set the packed color texture (RGBA8)
|
|
1508
2136
|
*/
|
|
1509
|
-
|
|
1510
|
-
this.uniforms.
|
|
2137
|
+
setPackedColor(e) {
|
|
2138
|
+
this.uniforms.packedColor.value = e;
|
|
1511
2139
|
}
|
|
1512
2140
|
/**
|
|
1513
|
-
* Set
|
|
1514
|
-
* @param texture Texture containing colors
|
|
2141
|
+
* Set order texture for sorting
|
|
1515
2142
|
*/
|
|
1516
|
-
|
|
1517
|
-
this.uniforms.
|
|
2143
|
+
setOrderTexture(e) {
|
|
2144
|
+
this.uniforms.splatOrder.value = e;
|
|
1518
2145
|
}
|
|
1519
2146
|
/**
|
|
1520
|
-
* Set
|
|
1521
|
-
* @param texture Texture containing sort order
|
|
2147
|
+
* Set the ranges needed to decompress the packed floats
|
|
1522
2148
|
*/
|
|
1523
|
-
|
|
1524
|
-
this.uniforms.
|
|
2149
|
+
setRanges(e) {
|
|
2150
|
+
this.uniforms.meansMin.value.copy(e.means.min), this.uniforms.meansMax.value.copy(e.means.max), this.uniforms.scalesMin.value.copy(e.scales.min), this.uniforms.scalesMax.value.copy(e.scales.max), this.uniforms.sh0Min.value.copy(e.sh0.min), this.uniforms.sh0Max.value.copy(e.sh0.max);
|
|
1525
2151
|
}
|
|
1526
2152
|
/**
|
|
1527
2153
|
* Set number of splats to render
|
|
@@ -1531,48 +2157,40 @@ class Ve extends l.ShaderMaterial {
|
|
|
1531
2157
|
this.uniforms.numSplats.value = e;
|
|
1532
2158
|
}
|
|
1533
2159
|
}
|
|
1534
|
-
const
|
|
2160
|
+
const de = class de extends h.Mesh {
|
|
1535
2161
|
// Match shader constant
|
|
1536
2162
|
/**
|
|
1537
2163
|
* Create a new SplatMesh for rendering Gaussian splats
|
|
1538
2164
|
* @param splatData The splat data to render
|
|
1539
2165
|
* @param options Rendering options
|
|
1540
2166
|
*/
|
|
1541
|
-
constructor(
|
|
1542
|
-
const
|
|
1543
|
-
super(
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
2167
|
+
constructor(t, r = {}) {
|
|
2168
|
+
const s = new It(r), a = de.createInstancedGeometry(t.numSplats, de.INSTANCE_SIZE);
|
|
2169
|
+
super(a, s);
|
|
2170
|
+
M(this, "sorter");
|
|
2171
|
+
M(this, "options");
|
|
2172
|
+
M(this, "splatData");
|
|
2173
|
+
M(this, "textureManager");
|
|
2174
|
+
M(this, "material");
|
|
2175
|
+
M(this, "geometry");
|
|
2176
|
+
M(this, "lastCameraPositionLocal", new h.Vector3());
|
|
2177
|
+
M(this, "lastCameraDirectionLocal", new h.Vector3());
|
|
2178
|
+
M(this, "invModelMatrix", new h.Matrix4());
|
|
1553
2179
|
// Cached inverse matrix
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
const
|
|
1563
|
-
this.geometry.instanceCount = Math.ceil(
|
|
2180
|
+
M(this, "_vpW", -1);
|
|
2181
|
+
M(this, "_vpH", -1);
|
|
2182
|
+
M(this, "_size", new h.Vector2());
|
|
2183
|
+
M(this, "_camPosW", new h.Vector3());
|
|
2184
|
+
M(this, "_camDirW", new h.Vector3());
|
|
2185
|
+
M(this, "_camPosL", new h.Vector3());
|
|
2186
|
+
M(this, "_camDirL", new h.Vector3());
|
|
2187
|
+
M(this, "onSorterUpdated", (t) => {
|
|
2188
|
+
const r = t.count;
|
|
2189
|
+
this.geometry.instanceCount = Math.ceil(r / de.INSTANCE_SIZE), this.material.setNumSplats(r);
|
|
1564
2190
|
});
|
|
1565
|
-
this.geometry =
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
}, this.textureManager = new De(o), this.sorter = new Pe();
|
|
1569
|
-
let a = this.createChunks() || void 0;
|
|
1570
|
-
a === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), a = void 0, this.sorter.addEventListener("updated", this.onSorterUpdated), this.sorter.init(
|
|
1571
|
-
this.textureManager.orderTexture,
|
|
1572
|
-
this.splatData.positions,
|
|
1573
|
-
a ?? void 0,
|
|
1574
|
-
!this.options.keepSplatData
|
|
1575
|
-
), this.material.setTransformA(this.textureManager.transformA), this.material.setTransformB(this.textureManager.transformB), this.material.setColorTexture(this.textureManager.colorTexture), this.material.setOrderTexture(this.textureManager.orderTexture), this.material.setNumSplats(0), this.geometry.boundingBox = o.boundingBox.toBox3(), this.geometry.boundingSphere = new l.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere), this.options.keepSplatData || (this.splatData = null);
|
|
2191
|
+
this.geometry = a, this.material = s, this.options = { autoSort: !0, ...r }, this.splatData = t, this.frustumCulled = !1, this.sorter = new At(), this.textureManager = new kt(t);
|
|
2192
|
+
let o = this.createChunks() || void 0;
|
|
2193
|
+
o === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), o = void 0, this.sorter.addEventListener("updated", this.onSorterUpdated), this.sorter.init(this.textureManager.orderTexture, this.splatData.centers, o ?? void 0, !this.options.keepSplatData), this.material.setRanges(t.ranges), this.material.setTexWidth(t.textureWidth), this.material.setPackedColor(this.textureManager.packedColor), this.material.setOrderTexture(this.textureManager.orderTexture), this.material.setPackedGeometry(this.textureManager.packedGeometry), this.material.setNumSplats(0), this.geometry.boundingBox = t.boundingBox.toBox3(), this.geometry.boundingSphere = new h.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere), this.options.keepSplatData || (this.splatData = null);
|
|
1576
2194
|
}
|
|
1577
2195
|
/**
|
|
1578
2196
|
* Creates the instanced geometry for rendering splats.
|
|
@@ -1580,8 +2198,8 @@ const se = class se extends l.Mesh {
|
|
|
1580
2198
|
* @param instanceSize Number of splats per instance.
|
|
1581
2199
|
* @returns InstancedBufferGeometry
|
|
1582
2200
|
*/
|
|
1583
|
-
static createInstancedGeometry(
|
|
1584
|
-
const
|
|
2201
|
+
static createInstancedGeometry(t, r) {
|
|
2202
|
+
const s = Math.ceil(t / r), a = new h.BufferGeometry(), o = new Float32Array([
|
|
1585
2203
|
// x, y, splat_index_in_instance
|
|
1586
2204
|
-1,
|
|
1587
2205
|
-1,
|
|
@@ -1595,24 +2213,24 @@ const se = class se extends l.Mesh {
|
|
|
1595
2213
|
-1,
|
|
1596
2214
|
1,
|
|
1597
2215
|
0
|
|
1598
|
-
]), i = new Uint16Array([0, 1, 2, 0, 2, 3]),
|
|
1599
|
-
for (let
|
|
1600
|
-
const
|
|
1601
|
-
for (let
|
|
1602
|
-
|
|
2216
|
+
]), i = new Uint16Array([0, 1, 2, 0, 2, 3]), m = new Float32Array(4 * 3 * r);
|
|
2217
|
+
for (let u = 0; u < r; u++) {
|
|
2218
|
+
const x = u * 4 * 3;
|
|
2219
|
+
for (let g = 0; g < 4; g++)
|
|
2220
|
+
m[x + g * 3 + 0] = o[g * 3 + 0], m[x + g * 3 + 1] = o[g * 3 + 1], m[x + g * 3 + 2] = u;
|
|
1603
2221
|
}
|
|
1604
|
-
const
|
|
1605
|
-
for (let
|
|
1606
|
-
const
|
|
1607
|
-
|
|
2222
|
+
const f = new Uint32Array(6 * r);
|
|
2223
|
+
for (let u = 0; u < r; u++) {
|
|
2224
|
+
const x = u * 6, g = u * 4;
|
|
2225
|
+
f[x + 0] = i[0] + g, f[x + 1] = i[1] + g, f[x + 2] = i[2] + g, f[x + 3] = i[3] + g, f[x + 4] = i[4] + g, f[x + 5] = i[5] + g;
|
|
1608
2226
|
}
|
|
1609
|
-
|
|
1610
|
-
const
|
|
1611
|
-
|
|
1612
|
-
const
|
|
1613
|
-
for (let
|
|
1614
|
-
|
|
1615
|
-
return
|
|
2227
|
+
a.setAttribute("position", new h.BufferAttribute(m, 3)), a.setIndex(new h.BufferAttribute(f, 1));
|
|
2228
|
+
const y = new h.InstancedBufferGeometry();
|
|
2229
|
+
y.index = a.index, y.setAttribute("position", a.getAttribute("position"));
|
|
2230
|
+
const l = new Uint32Array(s);
|
|
2231
|
+
for (let u = 0; u < s; u++)
|
|
2232
|
+
l[u] = u * r;
|
|
2233
|
+
return y.setAttribute("splatInstanceIndex", new h.InstancedBufferAttribute(l, 1, !1)), y.instanceCount = 0, y;
|
|
1616
2234
|
}
|
|
1617
2235
|
/**
|
|
1618
2236
|
* Create chunks data (bounding box min/max) for the sorter.
|
|
@@ -1621,14 +2239,14 @@ const se = class se extends l.Mesh {
|
|
|
1621
2239
|
createChunks() {
|
|
1622
2240
|
if (!this.splatData)
|
|
1623
2241
|
return null;
|
|
1624
|
-
const
|
|
1625
|
-
return
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
2242
|
+
const t = this.splatData.boundingBox;
|
|
2243
|
+
return t.min.x === 1 / 0 || t.max.x === -1 / 0 ? null : new Float32Array([
|
|
2244
|
+
t.min.x,
|
|
2245
|
+
t.min.y,
|
|
2246
|
+
t.min.z,
|
|
2247
|
+
t.max.x,
|
|
2248
|
+
t.max.y,
|
|
2249
|
+
t.max.z
|
|
1632
2250
|
]);
|
|
1633
2251
|
}
|
|
1634
2252
|
/**
|
|
@@ -1636,17 +2254,17 @@ const se = class se extends l.Mesh {
|
|
|
1636
2254
|
* @param width Viewport width
|
|
1637
2255
|
* @param height Viewport height
|
|
1638
2256
|
*/
|
|
1639
|
-
updateViewport(
|
|
1640
|
-
|
|
2257
|
+
updateViewport(t, r) {
|
|
2258
|
+
t === this._vpW && r === this._vpH || (this._vpW = t, this._vpH = r, this.material.updateViewport(t, r));
|
|
1641
2259
|
}
|
|
1642
2260
|
/**
|
|
1643
2261
|
* Sorts splats based on camera position and direction.
|
|
1644
2262
|
* @param camera The camera to sort against.
|
|
1645
2263
|
*/
|
|
1646
|
-
sort(
|
|
1647
|
-
|
|
1648
|
-
const
|
|
1649
|
-
this.options.autoSort && (
|
|
2264
|
+
sort(t) {
|
|
2265
|
+
t.getWorldPosition(this._camPosW), t.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);
|
|
2266
|
+
const r = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6, s = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
|
|
2267
|
+
this.options.autoSort && (r || s) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
|
|
1650
2268
|
}
|
|
1651
2269
|
/**
|
|
1652
2270
|
* THREE.js hook called before rendering the object.
|
|
@@ -1657,8 +2275,8 @@ const se = class se extends l.Mesh {
|
|
|
1657
2275
|
*/
|
|
1658
2276
|
// prettier-ignore
|
|
1659
2277
|
// @ts-expect-error scene is not used
|
|
1660
|
-
onBeforeRender(
|
|
1661
|
-
this.sort(
|
|
2278
|
+
onBeforeRender(t, r, s) {
|
|
2279
|
+
this.sort(s), t.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
|
|
1662
2280
|
}
|
|
1663
2281
|
/**
|
|
1664
2282
|
* Dispose of resources
|
|
@@ -1668,39 +2286,51 @@ const se = class se extends l.Mesh {
|
|
|
1668
2286
|
}
|
|
1669
2287
|
};
|
|
1670
2288
|
/** Number of splats combined into a single instanced draw call. */
|
|
1671
|
-
|
|
1672
|
-
let
|
|
1673
|
-
const
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2289
|
+
M(de, "INSTANCE_SIZE", 128);
|
|
2290
|
+
let Te = de;
|
|
2291
|
+
const ve = /* @__PURE__ */ new Map(), Ft = ({
|
|
2292
|
+
url: n,
|
|
2293
|
+
type: e,
|
|
2294
|
+
debug: t = !1,
|
|
2295
|
+
splatOptions: r = {},
|
|
2296
|
+
...s
|
|
1678
2297
|
}) => {
|
|
1679
|
-
|
|
1680
|
-
const
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
2298
|
+
if (!n) throw new Error('Splat component requires either "url" or "plyUrl" prop');
|
|
2299
|
+
const a = Tt(n, e);
|
|
2300
|
+
t && console.debug("SPLAT: rendering", { url: n, type: a, splatOptions: r, meshProps: s });
|
|
2301
|
+
const [o, i] = Xe(null), m = Ze(null);
|
|
2302
|
+
return Je(() => {
|
|
2303
|
+
const f = Ne(n, a, r);
|
|
2304
|
+
return _t(n, a, r).then(
|
|
2305
|
+
(y) => {
|
|
2306
|
+
i(y);
|
|
1686
2307
|
}
|
|
1687
2308
|
), () => {
|
|
1688
|
-
|
|
2309
|
+
t && console.debug("SPLAT: releasing mesh for", n), zt(f);
|
|
1689
2310
|
};
|
|
1690
|
-
}, [
|
|
1691
|
-
},
|
|
1692
|
-
const
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
2311
|
+
}, [n, a, r, t]), o ? /* @__PURE__ */ tt.jsx("primitive", { ref: m, object: o, ...s }) : null;
|
|
2312
|
+
}, Rt = (n) => {
|
|
2313
|
+
const e = n.toLowerCase();
|
|
2314
|
+
return e.endsWith(".ply") ? "ply" : e.endsWith(".sogs") || e.endsWith(".zip") || e.endsWith(".json") ? "sogs" : null;
|
|
2315
|
+
}, Tt = (n, e) => {
|
|
2316
|
+
if (e) return e;
|
|
2317
|
+
const t = Rt(n);
|
|
2318
|
+
if (t) return t;
|
|
2319
|
+
throw new Error(`Cannot determine file type from URL: "${n}". `);
|
|
2320
|
+
}, Ne = (n, e, t) => `${n}:${e}:${JSON.stringify(t)}`, _t = async (n, e, t) => {
|
|
2321
|
+
const r = Ne(n, e, t), s = ve.get(r);
|
|
2322
|
+
if (s)
|
|
2323
|
+
return s.refCount++, s.mesh;
|
|
2324
|
+
const o = await (e === "ply" ? new st() : new St()).loadAsync(n), i = new Te(o, t);
|
|
2325
|
+
return ve.set(r, { mesh: i, refCount: 1 }), i;
|
|
1697
2326
|
};
|
|
1698
|
-
function
|
|
1699
|
-
const e =
|
|
1700
|
-
e && (e.refCount--, e.refCount <= 0 && (e.mesh.dispose(),
|
|
2327
|
+
function zt(n) {
|
|
2328
|
+
const e = ve.get(n);
|
|
2329
|
+
e && (e.refCount--, e.refCount <= 0 && (e.mesh.dispose(), ve.delete(n)));
|
|
1701
2330
|
}
|
|
1702
2331
|
export {
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
2332
|
+
st as PlyLoader,
|
|
2333
|
+
St as SogsLoader,
|
|
2334
|
+
Ft as Splat,
|
|
2335
|
+
Te as SplatMesh
|
|
1706
2336
|
};
|