@speridlabs/visus 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.d.ts +335 -347
- package/dist/main.es.js +1454 -838
- package/dist/main.umd.js +164 -195
- package/dist/react.d.ts +6 -2
- package/dist/react.es.js +1616 -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
|
+
}
|
|
464
501
|
}
|
|
465
|
-
class
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
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
|
+
}
|
|
658
|
+
}
|
|
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,747 @@ 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
|
+
/**
|
|
1341
|
+
* Detect if a buffer is a ZIP file by checking magic bytes
|
|
1342
|
+
* ZIP files start with signature: PK\x03\x04 (0x50 0x4B 0x03 0x04)
|
|
1343
|
+
*/
|
|
1344
|
+
isZipBuffer(e) {
|
|
1345
|
+
if (e.byteLength < 4) return !1;
|
|
1346
|
+
const t = new Uint8Array(e, 0, 4);
|
|
1347
|
+
return t[0] === 80 && t[1] === 75 && t[2] === 3 && t[3] === 4;
|
|
1348
|
+
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Load a SOGS file (meta.json + textures)
|
|
1351
|
+
* @param url URL of the meta.json file
|
|
1352
|
+
* @param onLoad Optional callback when loading is complete
|
|
1353
|
+
* @param onProgress Optional progress callback
|
|
1354
|
+
* @param onError Optional error callback
|
|
1355
|
+
*/
|
|
1356
|
+
load(e, t, r, s) {
|
|
1357
|
+
const a = new h.FileLoader(this.manager);
|
|
1358
|
+
a.setResponseType("arraybuffer"), a.setRequestHeader(this.requestHeader), a.setPath(this.path), a.setWithCredentials(this.withCredentials), a.load(
|
|
1359
|
+
e,
|
|
1360
|
+
(o) => {
|
|
1361
|
+
this.parseAsync(e, o).then((i) => {
|
|
1362
|
+
t && t(i);
|
|
1363
|
+
}).catch((i) => {
|
|
1364
|
+
this.manager.itemError(e), s && s(i), console.error("Error loading SOGS meta:", i);
|
|
1365
|
+
});
|
|
1366
|
+
},
|
|
1367
|
+
r,
|
|
1368
|
+
s
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* Load a SOGS file asynchronously and return a Promise
|
|
1373
|
+
* @param url URL of the meta.json file
|
|
1374
|
+
* @param onProgress Optional progress callback
|
|
1375
|
+
* @returns A Promise that resolves with the parsed SplatData
|
|
1376
|
+
*/
|
|
1377
|
+
loadAsync(e, t) {
|
|
1378
|
+
return new Promise((r, s) => {
|
|
1379
|
+
const a = new h.FileLoader(this.manager);
|
|
1380
|
+
a.setResponseType("arraybuffer"), a.setRequestHeader(this.requestHeader), a.setPath(this.path), a.setWithCredentials(this.withCredentials), a.load(
|
|
1381
|
+
e,
|
|
1382
|
+
(o) => {
|
|
1383
|
+
this.parseAsync(e, o).then(r).catch((i) => {
|
|
1384
|
+
s(i), this.manager.itemError(e);
|
|
1385
|
+
});
|
|
1386
|
+
},
|
|
1387
|
+
t,
|
|
1388
|
+
(o) => {
|
|
1389
|
+
s(o), this.manager.itemError(e);
|
|
1390
|
+
}
|
|
1391
|
+
);
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
async parseAsync(e, t) {
|
|
1395
|
+
if (!(t instanceof ArrayBuffer)) throw new Error("SOGS loader: expected ArrayBuffer payload");
|
|
1396
|
+
if (this.isZipBuffer(t)) return this.parseZipAsync(t);
|
|
1397
|
+
const s = new TextDecoder("utf-8").decode(t), a = JSON.parse(s);
|
|
1398
|
+
return this.parseMetaAsync(e, a);
|
|
1399
|
+
}
|
|
1400
|
+
async parseMetaAsync(e, t) {
|
|
1401
|
+
const { numSplats: r, files: s, ranges: a } = Oe(t), o = new h.TextureLoader(this.manager);
|
|
1402
|
+
o.setPath(this.path), o.setRequestHeader(this.requestHeader), o.setWithCredentials(this.withCredentials);
|
|
1403
|
+
const i = (E, T) => {
|
|
1404
|
+
try {
|
|
1405
|
+
return new URL(T, E).toString();
|
|
1406
|
+
} catch {
|
|
1407
|
+
return E.substring(0, E.lastIndexOf("/") + 1) + T;
|
|
1408
|
+
}
|
|
1409
|
+
}, m = (E, T) => {
|
|
1410
|
+
const P = i(e, E);
|
|
1411
|
+
return new Promise((H, L) => {
|
|
1412
|
+
o.load(
|
|
1413
|
+
P,
|
|
1414
|
+
(A) => {
|
|
1415
|
+
A.generateMipmaps = !1, A.magFilter = h.NearestFilter, A.minFilter = h.NearestFilter, A.flipY = !1, H(A);
|
|
1416
|
+
},
|
|
1417
|
+
void 0,
|
|
1418
|
+
(A) => {
|
|
1419
|
+
const C = A instanceof Error ? A.message : String(A);
|
|
1420
|
+
L(
|
|
1421
|
+
new Error(
|
|
1422
|
+
`SOGS loader: failed to load ${T} (${E}): ${C}`
|
|
1423
|
+
)
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
);
|
|
1427
|
+
});
|
|
1428
|
+
};
|
|
1429
|
+
if (!Array.isArray(s.sh0) || s.sh0.length < 1) throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");
|
|
1430
|
+
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)");
|
|
1431
|
+
if (!Array.isArray(s.quats) || s.quats.length < 1) throw new Error("SOGS loader: files.quats must have at least 1 entry");
|
|
1432
|
+
if (!Array.isArray(s.scales) || s.scales.length < 1) throw new Error("SOGS loader: files.scales must have at least 1 entry");
|
|
1433
|
+
const [f, y, l, u, x] = await Promise.all([
|
|
1434
|
+
m(s.means[0], "means_l"),
|
|
1435
|
+
m(s.means[1], "means_u"),
|
|
1436
|
+
m(s.quats[0], "quats"),
|
|
1437
|
+
m(s.scales[0], "scales"),
|
|
1438
|
+
m(s.sh0[0], "sh0")
|
|
1439
|
+
]), g = { means_l: f, means_u: y, quats: l, scales: u, sh0: x }, v = new Fe(r, a, g), b = Ce.packSogs(v);
|
|
1440
|
+
return v.dispose(), b;
|
|
1441
|
+
}
|
|
1442
|
+
async parseZipAsync(e) {
|
|
1443
|
+
const t = Mt(new Uint8Array(e)), r = Object.keys(t), s = r.find((_) => _.toLowerCase().endsWith("meta.json")) ?? null;
|
|
1444
|
+
if (!s) throw new Error("SOGS loader: zip missing meta.json");
|
|
1445
|
+
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 = (_) => {
|
|
1446
|
+
const w = l(_), p = [l(a + w), w];
|
|
1447
|
+
for (const j of p) {
|
|
1448
|
+
const Y = t[j];
|
|
1449
|
+
if (Y) return Y;
|
|
1450
|
+
}
|
|
1451
|
+
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;
|
|
1452
|
+
if (q) return t[q];
|
|
1453
|
+
throw new Error(`SOGS loader: zip missing file "${_}"`);
|
|
1454
|
+
}, x = (_) => {
|
|
1455
|
+
const w = _.toLowerCase();
|
|
1456
|
+
return w.endsWith(".png") ? "image/png" : w.endsWith(".jpg") || w.endsWith(".jpeg") ? "image/jpeg" : w.endsWith(".webp") ? "image/webp" : "application/octet-stream";
|
|
1457
|
+
}, g = new h.TextureLoader(this.manager);
|
|
1458
|
+
g.setRequestHeader(this.requestHeader), g.setWithCredentials(this.withCredentials);
|
|
1459
|
+
const v = (_, w) => {
|
|
1460
|
+
const p = u(_), R = new Blob([p], {
|
|
1461
|
+
type: x(_)
|
|
1462
|
+
}), q = URL.createObjectURL(R);
|
|
1463
|
+
return new Promise((j, Y) => {
|
|
1464
|
+
g.load(
|
|
1465
|
+
q,
|
|
1466
|
+
(V) => {
|
|
1467
|
+
URL.revokeObjectURL(q), V.generateMipmaps = !1, V.magFilter = h.NearestFilter, V.minFilter = h.NearestFilter, V.flipY = !1, j(V);
|
|
1468
|
+
},
|
|
1469
|
+
void 0,
|
|
1470
|
+
(V) => {
|
|
1471
|
+
URL.revokeObjectURL(q);
|
|
1472
|
+
const D = V instanceof Error ? V.message : String(V);
|
|
1473
|
+
Y(
|
|
1474
|
+
new Error(
|
|
1475
|
+
`SOGS loader: failed to load ${w} from zip (${_}): ${D}`
|
|
1476
|
+
)
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
);
|
|
1480
|
+
});
|
|
1481
|
+
};
|
|
1482
|
+
if (!Array.isArray(f.sh0) || f.sh0.length < 1) throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");
|
|
1483
|
+
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)");
|
|
1484
|
+
if (!Array.isArray(f.quats) || f.quats.length < 1) throw new Error("SOGS loader: files.quats must have at least 1 entry");
|
|
1485
|
+
if (!Array.isArray(f.scales) || f.scales.length < 1) throw new Error("SOGS loader: files.scales must have at least 1 entry");
|
|
1486
|
+
const [b, E, T, P, H] = await Promise.all([
|
|
1487
|
+
v(f.means[0], "means_l"),
|
|
1488
|
+
v(f.means[1], "means_u"),
|
|
1489
|
+
v(f.quats[0], "quats"),
|
|
1490
|
+
v(f.scales[0], "scales"),
|
|
1491
|
+
v(f.sh0[0], "sh0")
|
|
1492
|
+
]), L = { means_l: b, means_u: E, quats: T, scales: P, sh0: H }, A = new Fe(m, y, L), C = Ce.packSogs(A);
|
|
1493
|
+
return A.dispose(), C;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
class At extends h.EventDispatcher {
|
|
769
1497
|
constructor() {
|
|
770
1498
|
super();
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
1499
|
+
M(this, "worker");
|
|
1500
|
+
M(this, "centers", null);
|
|
1501
|
+
M(this, "orderTexture", null);
|
|
774
1502
|
/** Bounding box data for optimization */
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
const
|
|
779
|
-
this.worker = new Worker(URL.createObjectURL(
|
|
1503
|
+
M(this, "chunks", null);
|
|
1504
|
+
M(this, "lastCameraPosition", new h.Vector3());
|
|
1505
|
+
M(this, "lastCameraDirection", new h.Vector3());
|
|
1506
|
+
const t = this.createWorkerCode(), r = new Blob([t], { type: "application/javascript" });
|
|
1507
|
+
this.worker = new Worker(URL.createObjectURL(r)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
780
1508
|
}
|
|
781
1509
|
/**
|
|
782
1510
|
* Handles messages received from the sorting worker.
|
|
783
1511
|
* @param event The message event from the worker.
|
|
784
1512
|
*/
|
|
785
|
-
onWorkerMessage(
|
|
1513
|
+
onWorkerMessage(t) {
|
|
786
1514
|
if (!this.orderTexture || !this.orderTexture.image)
|
|
787
1515
|
return console.error("SplatSorter: Order texture not initialized!");
|
|
788
|
-
const { order:
|
|
789
|
-
if (!(
|
|
1516
|
+
const { order: r, count: s } = t.data, a = this.orderTexture.image.data;
|
|
1517
|
+
if (!(a instanceof Uint32Array))
|
|
790
1518
|
return console.error(
|
|
791
1519
|
"SplatSorter: Order texture data is not a Uint32Array!"
|
|
792
1520
|
);
|
|
793
|
-
|
|
794
|
-
const
|
|
795
|
-
this.worker.postMessage(i, [
|
|
1521
|
+
a.set(new Uint32Array(r)), this.orderTexture.source.data.updateRanges || (this.orderTexture.source.data.updateRanges = []), this.orderTexture.needsUpdate = !0;
|
|
1522
|
+
const o = a.buffer.slice(0), i = { order: o };
|
|
1523
|
+
this.worker.postMessage(i, [o]), this.dispatchEvent({ type: "updated", count: s });
|
|
796
1524
|
}
|
|
797
1525
|
/**
|
|
798
1526
|
* Initializes the sorter with necessary data and textures.
|
|
@@ -801,38 +1529,38 @@ class Pe extends l.EventDispatcher {
|
|
|
801
1529
|
* @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
|
|
802
1530
|
* @param transferOwnership Optional: If true, transfers ownership of centers buffer to worker (saves memory, main thread loses access). Default: false.
|
|
803
1531
|
*/
|
|
804
|
-
init(
|
|
805
|
-
if (!
|
|
1532
|
+
init(t, r, s, a = !1) {
|
|
1533
|
+
if (!t || !(t.image.data instanceof Uint32Array))
|
|
806
1534
|
throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
|
|
807
|
-
if (!
|
|
1535
|
+
if (!r || r.length % 3 !== 0)
|
|
808
1536
|
throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");
|
|
809
|
-
if (
|
|
1537
|
+
if (t.image.data.length < r.length / 3)
|
|
810
1538
|
throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
|
|
811
|
-
if (
|
|
1539
|
+
if (r.buffer.byteLength === 0)
|
|
812
1540
|
throw new Error(
|
|
813
1541
|
"SplatSorter: positions buffer is detached (likely React StrictMode + cached asset). "
|
|
814
1542
|
);
|
|
815
|
-
const
|
|
816
|
-
this.orderTexture =
|
|
1543
|
+
const o = r.length / 3;
|
|
1544
|
+
this.orderTexture = t, a ? this.centers = null : this.centers = r.slice();
|
|
817
1545
|
const i = this.orderTexture.image.data;
|
|
818
|
-
for (let
|
|
1546
|
+
for (let u = 0; u < o; u++) i[u] = u;
|
|
819
1547
|
this.orderTexture.source.data.updateRanges || (this.orderTexture.source.data.updateRanges = []), this.orderTexture.needsUpdate = !0;
|
|
820
|
-
const
|
|
821
|
-
order:
|
|
822
|
-
centers:
|
|
823
|
-
},
|
|
824
|
-
|
|
825
|
-
|
|
1548
|
+
const m = i.buffer.slice(0), f = a ? r.buffer : r.buffer.slice(0), y = {
|
|
1549
|
+
order: m,
|
|
1550
|
+
centers: f
|
|
1551
|
+
}, l = [
|
|
1552
|
+
m,
|
|
1553
|
+
f
|
|
826
1554
|
];
|
|
827
|
-
if (
|
|
828
|
-
this.chunks =
|
|
829
|
-
const
|
|
830
|
-
|
|
1555
|
+
if (s) {
|
|
1556
|
+
this.chunks = s.slice();
|
|
1557
|
+
const u = this.chunks.buffer.slice(0);
|
|
1558
|
+
y.chunks = u, l.push(u);
|
|
831
1559
|
}
|
|
832
|
-
this.worker.postMessage(
|
|
1560
|
+
this.worker.postMessage(y, l), queueMicrotask(() => {
|
|
833
1561
|
this.dispatchEvent({
|
|
834
1562
|
type: "updated",
|
|
835
|
-
count:
|
|
1563
|
+
count: o
|
|
836
1564
|
});
|
|
837
1565
|
});
|
|
838
1566
|
}
|
|
@@ -841,53 +1569,53 @@ class Pe extends l.EventDispatcher {
|
|
|
841
1569
|
* The sorter will only consider splats whose original indices are present in the mapping.
|
|
842
1570
|
* @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
|
|
843
1571
|
*/
|
|
844
|
-
setMapping(
|
|
1572
|
+
setMapping(t) {
|
|
845
1573
|
if (!this.centers)
|
|
846
1574
|
return console.warn(
|
|
847
1575
|
"SplatSorter: Cannot set mapping before initialization."
|
|
848
1576
|
);
|
|
849
|
-
let
|
|
850
|
-
const
|
|
851
|
-
if (!
|
|
852
|
-
const
|
|
853
|
-
return
|
|
854
|
-
centers:
|
|
1577
|
+
let r;
|
|
1578
|
+
const s = [];
|
|
1579
|
+
if (!t) {
|
|
1580
|
+
const m = this.centers.buffer.slice(0);
|
|
1581
|
+
return r = {
|
|
1582
|
+
centers: m,
|
|
855
1583
|
mapping: null
|
|
856
|
-
},
|
|
1584
|
+
}, s.push(m), this.worker.postMessage(r, s);
|
|
857
1585
|
}
|
|
858
|
-
const
|
|
859
|
-
for (let
|
|
860
|
-
const
|
|
861
|
-
if (
|
|
1586
|
+
const a = new Float32Array(t.length * 3);
|
|
1587
|
+
for (let m = 0; m < t.length; m++) {
|
|
1588
|
+
const f = t[m];
|
|
1589
|
+
if (f * 3 + 2 >= this.centers.length) {
|
|
862
1590
|
console.warn(
|
|
863
|
-
`SplatSorter: Mapping index ${
|
|
1591
|
+
`SplatSorter: Mapping index ${f} out of bounds.`
|
|
864
1592
|
);
|
|
865
1593
|
continue;
|
|
866
1594
|
}
|
|
867
|
-
const
|
|
868
|
-
|
|
1595
|
+
const y = f * 3, l = m * 3;
|
|
1596
|
+
a[l + 0] = this.centers[y + 0], a[l + 1] = this.centers[y + 1], a[l + 2] = this.centers[y + 2];
|
|
869
1597
|
}
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
centers:
|
|
1598
|
+
const o = a.buffer.slice(0), i = t.buffer.slice(0);
|
|
1599
|
+
r = {
|
|
1600
|
+
centers: o,
|
|
873
1601
|
mapping: i
|
|
874
|
-
},
|
|
1602
|
+
}, s.push(o, i), this.worker.postMessage(r, s);
|
|
875
1603
|
}
|
|
876
1604
|
/**
|
|
877
1605
|
* Updates the camera parameters used for sorting.
|
|
878
1606
|
* @param position The camera's position in the sorter's local coordinate space.
|
|
879
1607
|
* @param direction The camera's forward direction in the sorter's local coordinate space.
|
|
880
1608
|
*/
|
|
881
|
-
setCamera(
|
|
882
|
-
const
|
|
883
|
-
if (!
|
|
1609
|
+
setCamera(t, r) {
|
|
1610
|
+
const s = this.lastCameraPosition.distanceToSquared(t) > 1e-7, a = this.lastCameraDirection.dot(r) < 0.9999;
|
|
1611
|
+
if (!s && !a)
|
|
884
1612
|
return;
|
|
885
|
-
this.lastCameraPosition.copy(
|
|
886
|
-
const
|
|
887
|
-
cameraPosition: { x:
|
|
888
|
-
cameraDirection: { x:
|
|
1613
|
+
this.lastCameraPosition.copy(t), this.lastCameraDirection.copy(r);
|
|
1614
|
+
const o = {
|
|
1615
|
+
cameraPosition: { x: t.x, y: t.y, z: t.z },
|
|
1616
|
+
cameraDirection: { x: r.x, y: r.y, z: r.z }
|
|
889
1617
|
};
|
|
890
|
-
this.worker.postMessage(
|
|
1618
|
+
this.worker.postMessage(o);
|
|
891
1619
|
}
|
|
892
1620
|
/**
|
|
893
1621
|
* Terminates the Web Worker and cleans up resources.
|
|
@@ -901,258 +1629,186 @@ class Pe extends l.EventDispatcher {
|
|
|
901
1629
|
*/
|
|
902
1630
|
createWorkerCode() {
|
|
903
1631
|
return `(${(function() {
|
|
904
|
-
let
|
|
905
|
-
const
|
|
906
|
-
let
|
|
907
|
-
const
|
|
908
|
-
for (; A <=
|
|
909
|
-
const
|
|
910
|
-
if (
|
|
911
|
-
else if (
|
|
912
|
-
else return
|
|
1632
|
+
let r = null, s = null, a = null, o = null, i = null, m = null, f = !1;
|
|
1633
|
+
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 };
|
|
1634
|
+
let g = null, v = null;
|
|
1635
|
+
const b = 32, E = new Array(b).fill(0), T = new Array(b).fill(0), P = new Array(b).fill(0), H = (A, C, _) => {
|
|
1636
|
+
for (; A <= C; ) {
|
|
1637
|
+
const w = C + A >> 1, p = _(w);
|
|
1638
|
+
if (p > 0) A = w + 1;
|
|
1639
|
+
else if (p < 0) C = w - 1;
|
|
1640
|
+
else return w;
|
|
913
1641
|
}
|
|
914
1642
|
return ~A;
|
|
915
1643
|
}, L = () => {
|
|
916
|
-
if (!
|
|
1644
|
+
if (!r || !s || !i || !m)
|
|
917
1645
|
return;
|
|
918
|
-
if (
|
|
919
|
-
const
|
|
920
|
-
order:
|
|
1646
|
+
if (s.length === 0) {
|
|
1647
|
+
const d = {
|
|
1648
|
+
order: r.buffer,
|
|
921
1649
|
count: 0
|
|
922
1650
|
};
|
|
923
|
-
self.postMessage(
|
|
1651
|
+
self.postMessage(d, [r.buffer]), r = null;
|
|
924
1652
|
return;
|
|
925
1653
|
}
|
|
926
|
-
const A = i.x,
|
|
927
|
-
if (!
|
|
1654
|
+
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;
|
|
1655
|
+
if (!f && !j && !Y)
|
|
928
1656
|
return;
|
|
929
|
-
|
|
930
|
-
let
|
|
931
|
-
for (let
|
|
932
|
-
const
|
|
933
|
-
|
|
1657
|
+
f = !1, y.x = A, y.y = C, y.z = _, l.x = w, l.y = p, l.z = R;
|
|
1658
|
+
let V = 1 / 0, D = -1 / 0;
|
|
1659
|
+
for (let d = 0; d < 8; ++d) {
|
|
1660
|
+
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;
|
|
1661
|
+
V = Math.min(V, U), D = Math.max(D, U);
|
|
934
1662
|
}
|
|
935
|
-
const
|
|
1663
|
+
const O = s.length / 3, J = D - V, c = (1 << Math.max(
|
|
936
1664
|
10,
|
|
937
|
-
Math.min(20, Math.ceil(Math.log2(
|
|
1665
|
+
Math.min(20, Math.ceil(Math.log2(O / 4)))
|
|
938
1666
|
)) + 1;
|
|
939
|
-
if ((!
|
|
940
|
-
for (let
|
|
941
|
-
|
|
942
|
-
} else if (
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
for (let
|
|
946
|
-
const
|
|
1667
|
+
if ((!g || g.length !== O) && (g = new Uint32Array(O)), !v || v.length !== c ? v = new Uint32Array(c) : v.fill(0), J < 1e-7) {
|
|
1668
|
+
for (let d = 0; d < O; ++d) g[d] = 0;
|
|
1669
|
+
v[0] = O;
|
|
1670
|
+
} else if (a && a.length > 0) {
|
|
1671
|
+
const d = a.length / 6;
|
|
1672
|
+
E.fill(0);
|
|
1673
|
+
for (let S = 0; S < d; ++S) {
|
|
1674
|
+
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
1675
|
0,
|
|
948
|
-
Math.floor(
|
|
949
|
-
),
|
|
950
|
-
|
|
951
|
-
Math.ceil(
|
|
1676
|
+
Math.floor(re * b / J)
|
|
1677
|
+
), he = Math.min(
|
|
1678
|
+
b,
|
|
1679
|
+
Math.ceil(se * b / J)
|
|
952
1680
|
);
|
|
953
|
-
for (let
|
|
954
|
-
|
|
1681
|
+
for (let oe = ue; oe < he; ++oe)
|
|
1682
|
+
E[oe]++;
|
|
955
1683
|
}
|
|
956
|
-
let
|
|
957
|
-
for (let
|
|
958
|
-
|
|
959
|
-
for (let
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
const
|
|
963
|
-
for (let
|
|
964
|
-
const
|
|
1684
|
+
let z = 0;
|
|
1685
|
+
for (let S = 0; S < b; ++S) z += E[S];
|
|
1686
|
+
P[0] = 0, T[0] = 0;
|
|
1687
|
+
for (let S = 1; S < b; ++S)
|
|
1688
|
+
P[S - 1] = E[S - 1] / z * c >>> 0, T[S] = T[S - 1] + P[S - 1];
|
|
1689
|
+
P[b - 1] = E[b - 1] / z * c >>> 0;
|
|
1690
|
+
const W = J / b;
|
|
1691
|
+
for (let S = 0; S < O; ++S) {
|
|
1692
|
+
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
1693
|
0,
|
|
966
1694
|
Math.min(
|
|
967
|
-
|
|
968
|
-
Math.floor(
|
|
1695
|
+
b - 1,
|
|
1696
|
+
Math.floor(re)
|
|
969
1697
|
)
|
|
970
|
-
),
|
|
971
|
-
S
|
|
1698
|
+
), ue = re - se, he = T[se] + P[se] * ue >>> 0, oe = Math.min(he, c - 1);
|
|
1699
|
+
g[S] = oe, v[oe]++;
|
|
972
1700
|
}
|
|
973
1701
|
} else {
|
|
974
|
-
const
|
|
975
|
-
for (let
|
|
976
|
-
const
|
|
977
|
-
|
|
1702
|
+
const d = (c - 1) / J;
|
|
1703
|
+
for (let z = 0; z < O; ++z) {
|
|
1704
|
+
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);
|
|
1705
|
+
g[z] = K, v[K]++;
|
|
978
1706
|
}
|
|
979
1707
|
}
|
|
980
|
-
for (let
|
|
981
|
-
|
|
982
|
-
for (let
|
|
983
|
-
const
|
|
984
|
-
|
|
1708
|
+
for (let d = 1; d < c; d++)
|
|
1709
|
+
v[d] += v[d - 1];
|
|
1710
|
+
for (let d = O - 1; d >= 0; d--) {
|
|
1711
|
+
const z = g[d], W = --v[z];
|
|
1712
|
+
r[W] = o ? o[d] : d;
|
|
985
1713
|
}
|
|
986
|
-
const
|
|
987
|
-
if (!
|
|
988
|
-
const
|
|
989
|
-
if (!
|
|
1714
|
+
const k = A * w + C * p + _ * R, B = (d) => {
|
|
1715
|
+
if (!r) return -1 / 0;
|
|
1716
|
+
const z = r[d], W = z;
|
|
1717
|
+
if (!s || W * 3 + 2 >= s.length)
|
|
990
1718
|
return -1 / 0;
|
|
991
|
-
const
|
|
992
|
-
return
|
|
1719
|
+
const S = W * 3;
|
|
1720
|
+
return s[S] * w + s[S + 1] * p + s[S + 2] * R - k;
|
|
993
1721
|
};
|
|
994
|
-
let
|
|
995
|
-
if (
|
|
996
|
-
const
|
|
1722
|
+
let F = O;
|
|
1723
|
+
if (O > 0 && B(O - 1) < 0) {
|
|
1724
|
+
const d = H(
|
|
997
1725
|
0,
|
|
998
|
-
|
|
999
|
-
|
|
1726
|
+
O - 1,
|
|
1727
|
+
B
|
|
1000
1728
|
);
|
|
1001
|
-
|
|
1729
|
+
F = d < 0 ? ~d : d;
|
|
1002
1730
|
}
|
|
1003
|
-
const
|
|
1004
|
-
order:
|
|
1005
|
-
count:
|
|
1731
|
+
const I = {
|
|
1732
|
+
order: r.buffer,
|
|
1733
|
+
count: F
|
|
1006
1734
|
};
|
|
1007
|
-
self.postMessage(
|
|
1735
|
+
self.postMessage(I, [r.buffer]), r = null;
|
|
1008
1736
|
};
|
|
1009
1737
|
self.onmessage = (A) => {
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
let
|
|
1013
|
-
if (
|
|
1014
|
-
if (
|
|
1015
|
-
for (let
|
|
1016
|
-
const
|
|
1017
|
-
|
|
1018
|
-
(
|
|
1738
|
+
const C = A.data;
|
|
1739
|
+
C.order && (r = new Uint32Array(C.order));
|
|
1740
|
+
let _ = !1;
|
|
1741
|
+
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) {
|
|
1742
|
+
if (a = new Float32Array(C.chunks), a.length > 0 && a[3] > 0)
|
|
1743
|
+
for (let w = 0; w < a.length / 6; ++w) {
|
|
1744
|
+
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];
|
|
1745
|
+
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(
|
|
1746
|
+
(Y - R) ** 2 + (V - q) ** 2 + (D - j) ** 2
|
|
1019
1747
|
) * 0.5;
|
|
1020
1748
|
}
|
|
1021
|
-
|
|
1749
|
+
f = !0;
|
|
1022
1750
|
}
|
|
1023
|
-
if (
|
|
1024
|
-
|
|
1025
|
-
for (let
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1751
|
+
if (_ && s && s.length > 0) {
|
|
1752
|
+
u.x = x.x = s[0], u.y = x.y = s[1], u.z = x.z = s[2];
|
|
1753
|
+
for (let w = 1; w < s.length / 3; w++) {
|
|
1754
|
+
const p = w * 3;
|
|
1755
|
+
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
1756
|
}
|
|
1029
|
-
} else
|
|
1030
|
-
|
|
1757
|
+
} else _ && s && s.length === 0 && (u.x = x.x = u.y = x.y = u.z = x.z = 0);
|
|
1758
|
+
C.cameraPosition && (i = C.cameraPosition), C.cameraDirection && (m = C.cameraDirection), L();
|
|
1031
1759
|
};
|
|
1032
1760
|
}).toString()})();`;
|
|
1033
1761
|
}
|
|
1034
1762
|
}
|
|
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
|
-
*/
|
|
1763
|
+
class kt {
|
|
1051
1764
|
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);
|
|
1063
|
-
}
|
|
1064
|
-
/**
|
|
1065
|
-
* Create the transform A texture (positions and quaternion w component)
|
|
1066
|
-
* @param splatData The splat data
|
|
1067
|
-
* @returns DataTexture containing position data
|
|
1068
|
-
*/
|
|
1069
|
-
createTransformATexture(e) {
|
|
1070
|
-
const o = e.numSplats, t = new Float32Array(
|
|
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;
|
|
1765
|
+
M(this, "packedGeometry");
|
|
1766
|
+
// RGBA32UI
|
|
1767
|
+
M(this, "packedColor");
|
|
1768
|
+
// RGBA8
|
|
1769
|
+
M(this, "orderTexture");
|
|
1770
|
+
// RB32UI
|
|
1771
|
+
M(this, "width");
|
|
1772
|
+
M(this, "height");
|
|
1773
|
+
this.width = e.textureWidth, this.height = e.textureHeight, this.packedColor = this.createColorTexture(e), this.packedGeometry = this.createGeometryTexture(e), this.orderTexture = this.createOrderTexture(e.numSplats);
|
|
1088
1774
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
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
|
|
1775
|
+
createGeometryTexture(e) {
|
|
1776
|
+
const t = new h.DataTexture(
|
|
1777
|
+
e.packedGeometry,
|
|
1778
|
+
this.width,
|
|
1779
|
+
this.height,
|
|
1780
|
+
h.RGBAIntegerFormat,
|
|
1781
|
+
h.UnsignedIntType
|
|
1108
1782
|
);
|
|
1109
|
-
return
|
|
1783
|
+
return t.internalFormat = "RGBA32UI", t.minFilter = h.NearestFilter, t.magFilter = h.NearestFilter, t.needsUpdate = !0, t;
|
|
1110
1784
|
}
|
|
1111
|
-
/**
|
|
1112
|
-
* Create the color texture (RGB and opacity)
|
|
1113
|
-
* @param splatData The splat data
|
|
1114
|
-
* @returns DataTexture containing color data
|
|
1115
|
-
*/
|
|
1116
1785
|
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
|
|
1786
|
+
const t = new h.DataTexture(
|
|
1787
|
+
e.packedColor,
|
|
1788
|
+
this.width,
|
|
1789
|
+
this.height,
|
|
1790
|
+
h.RGBAFormat,
|
|
1791
|
+
h.UnsignedByteType
|
|
1130
1792
|
);
|
|
1131
|
-
return
|
|
1793
|
+
return t.minFilter = h.NearestFilter, t.magFilter = h.NearestFilter, t.needsUpdate = !0, t;
|
|
1132
1794
|
}
|
|
1133
|
-
/**
|
|
1134
|
-
* Create the order texture for sorting
|
|
1135
|
-
* @param numSplats Number of splats
|
|
1136
|
-
* @returns DataTexture for storing order indices
|
|
1137
|
-
*/
|
|
1138
1795
|
createOrderTexture(e) {
|
|
1139
|
-
const
|
|
1140
|
-
for (let
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
this.
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
l.UnsignedIntType
|
|
1796
|
+
const t = new Uint32Array(this.width * this.height);
|
|
1797
|
+
for (let s = 0; s < e; s++) t[s] = s;
|
|
1798
|
+
const r = new h.DataTexture(
|
|
1799
|
+
t,
|
|
1800
|
+
this.width,
|
|
1801
|
+
this.height,
|
|
1802
|
+
h.RedIntegerFormat,
|
|
1803
|
+
h.UnsignedIntType
|
|
1148
1804
|
);
|
|
1149
|
-
return
|
|
1805
|
+
return r.minFilter = h.NearestFilter, r.magFilter = h.NearestFilter, r.needsUpdate = !0, r;
|
|
1150
1806
|
}
|
|
1151
1807
|
dispose() {
|
|
1152
|
-
this.
|
|
1808
|
+
this.packedGeometry.dispose(), this.packedColor.dispose(), this.orderTexture.dispose();
|
|
1153
1809
|
}
|
|
1154
1810
|
}
|
|
1155
|
-
const
|
|
1811
|
+
const Et = (
|
|
1156
1812
|
/* glsl */
|
|
1157
1813
|
`
|
|
1158
1814
|
precision highp float;
|
|
@@ -1160,55 +1816,47 @@ precision highp int;
|
|
|
1160
1816
|
precision highp usampler2D;
|
|
1161
1817
|
precision highp sampler2D;
|
|
1162
1818
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
uniform vec2 viewport; // Viewport dimensions (width, height)
|
|
1167
|
-
uniform uint numSplats; // Total number of splats potentially renderable by sorter
|
|
1819
|
+
uniform int texWidth;
|
|
1820
|
+
uniform vec2 viewport;
|
|
1821
|
+
uniform uint numSplats;
|
|
1168
1822
|
|
|
1169
|
-
// Textures
|
|
1170
|
-
uniform
|
|
1171
|
-
uniform
|
|
1172
|
-
uniform
|
|
1173
|
-
uniform highp usampler2D splatOrder; // uint: original splat index
|
|
1823
|
+
// --- Unified Packed Textures ---
|
|
1824
|
+
uniform usampler2D packedGeometry; // RGBA32UI: Geometry (Pos, Rot, Scale)
|
|
1825
|
+
uniform sampler2D packedColor; // RGBA8: Color (RGB) + Opacity (A)
|
|
1826
|
+
uniform usampler2D splatOrder; // R32UI: Sort Index
|
|
1174
1827
|
|
|
1175
|
-
// ---
|
|
1176
|
-
|
|
1177
|
-
|
|
1828
|
+
// --- Decompression Ranges ---
|
|
1829
|
+
uniform vec3 meansMin;
|
|
1830
|
+
uniform vec3 meansMax;
|
|
1831
|
+
uniform vec3 scalesMin;
|
|
1832
|
+
uniform vec3 scalesMax;
|
|
1833
|
+
uniform vec3 sh0Min;
|
|
1834
|
+
uniform vec3 sh0Max;
|
|
1178
1835
|
|
|
1179
|
-
//
|
|
1180
|
-
|
|
1181
|
-
// position.xy: corner coords (-1..1)
|
|
1182
|
-
// position.z: index within the instance block (0..INSTANCE_BUFFER_SIZE-1)
|
|
1836
|
+
// --- Attributes ---
|
|
1837
|
+
in uint splatInstanceIndex;
|
|
1183
1838
|
|
|
1184
|
-
// ---
|
|
1185
|
-
|
|
1186
|
-
|
|
1839
|
+
// --- Outputs ---
|
|
1840
|
+
out vec4 vColor;
|
|
1841
|
+
out vec2 vUv;
|
|
1187
1842
|
|
|
1188
1843
|
// --- Constants ---
|
|
1189
|
-
|
|
1844
|
+
const vec4 DISCARD_VERTEX = vec4(0.0, 0.0, 2.0, 1.0);
|
|
1845
|
+
const float SH_C0 = 0.28209479177387814; // 1/(2*sqrt(pi))
|
|
1846
|
+
const float QUAT_NORM = 1.41421356237; // sqrt(2)
|
|
1190
1847
|
|
|
1191
1848
|
// --- Helper Functions ---
|
|
1192
1849
|
|
|
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)
|
|
1850
|
+
// Extract raw bytes as integers (no /255 )
|
|
1851
|
+
uvec4 unpackBytes(uint v) {
|
|
1852
|
+
return (uvec4(v) >> uvec4(24u, 16u, 8u, 0u)) & 0xffu;
|
|
1204
1853
|
}
|
|
1205
1854
|
|
|
1206
|
-
// Convert quaternion to 3x3 rotation matrix
|
|
1207
1855
|
mat3 quatToMat3(vec4 R) {
|
|
1208
1856
|
vec4 R2 = R + R;
|
|
1209
1857
|
float X = R2.x * R.w;
|
|
1210
|
-
vec4 Y
|
|
1211
|
-
vec4 Z
|
|
1858
|
+
vec4 Y = R2.y * R;
|
|
1859
|
+
vec4 Z = R2.z * R;
|
|
1212
1860
|
float W = R2.w * R.w;
|
|
1213
1861
|
|
|
1214
1862
|
return mat3(
|
|
@@ -1224,199 +1872,176 @@ mat3 quatToMat3(vec4 R) {
|
|
|
1224
1872
|
);
|
|
1225
1873
|
}
|
|
1226
1874
|
|
|
1227
|
-
// Calculate model-space covariance components
|
|
1228
1875
|
void getModelCovariance(vec3 scale, vec4 rotation, out vec3 covA, out vec3 covB) {
|
|
1229
1876
|
mat3 rot = quatToMat3(rotation);
|
|
1230
|
-
|
|
1231
|
-
// M = S * R (scale COLUMNS, then transpose)
|
|
1232
1877
|
mat3 M = transpose(mat3(
|
|
1233
|
-
scale.x * rot[0],
|
|
1234
|
-
scale.y * rot[1],
|
|
1235
|
-
scale.z * rot[2]
|
|
1878
|
+
scale.x * rot[0],
|
|
1879
|
+
scale.y * rot[1],
|
|
1880
|
+
scale.z * rot[2]
|
|
1236
1881
|
));
|
|
1237
1882
|
|
|
1238
1883
|
covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));
|
|
1239
1884
|
covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));
|
|
1240
1885
|
}
|
|
1241
1886
|
|
|
1242
|
-
// --- Main
|
|
1243
|
-
void main(
|
|
1244
|
-
// Calculate
|
|
1245
|
-
uint instanceOffset = uint(position.z);
|
|
1246
|
-
uint
|
|
1887
|
+
// --- Main ---
|
|
1888
|
+
void main() {
|
|
1889
|
+
// Calculate Instance ID & Source Data UV
|
|
1890
|
+
uint instanceOffset = uint(position.z);
|
|
1891
|
+
uint orderIndex = splatInstanceIndex + instanceOffset;
|
|
1247
1892
|
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Off-screen
|
|
1893
|
+
if (orderIndex >= numSplats) {
|
|
1894
|
+
gl_Position = DISCARD_VERTEX;
|
|
1251
1895
|
return;
|
|
1252
1896
|
}
|
|
1253
1897
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
ivec2 orderUV = ivec2(orderedSplatIndex % texWidth, orderedSplatIndex / texWidth);
|
|
1257
|
-
uint originalSplatIndex = texelFetch(splatOrder, orderUV, 0).r;
|
|
1898
|
+
uint w = uint(texWidth);
|
|
1899
|
+
ivec2 orderUV = ivec2(int(orderIndex % w), int(orderIndex / w));
|
|
1258
1900
|
|
|
1259
|
-
|
|
1901
|
+
// Fetch original splat ID from the order texture
|
|
1902
|
+
uint splatID = texelFetch(splatOrder, orderUV, 0).r;
|
|
1903
|
+
ivec2 dataUV = ivec2(int(splatID % w), int(splatID / w));
|
|
1260
1904
|
|
|
1261
|
-
// Fetch
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
vec4
|
|
1905
|
+
// Fetch Packed Data
|
|
1906
|
+
// x: Means Low, y: Means High, z: Rotation, w: Scale
|
|
1907
|
+
uvec4 geom = texelFetch(packedGeometry, dataUV, 0);
|
|
1908
|
+
vec4 colorRaw = texelFetch(packedColor, dataUV, 0);
|
|
1265
1909
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
float splatOpacity = texColor.a;
|
|
1910
|
+
// Decompress Position (Means) (assume world-space)
|
|
1911
|
+
// Reconstruct 16-bit values from two 8-bit channels
|
|
1912
|
+
uvec3 lo = unpackBytes(geom.x).xyz;
|
|
1913
|
+
uvec3 hi = unpackBytes(geom.y).xyz;
|
|
1271
1914
|
|
|
1272
|
-
|
|
1915
|
+
// (hi << 8) | lo => 0..65535 then normalize
|
|
1916
|
+
vec3 meansNorm = vec3((hi << 8u) | lo) * (1.0 / 65535.0);
|
|
1917
|
+
vec3 modelCenter = mix(meansMin, meansMax, meansNorm);
|
|
1273
1918
|
|
|
1274
|
-
//
|
|
1919
|
+
// Decompress Rotation (Quaternions)
|
|
1920
|
+
uvec4 qB = unpackBytes(geom.z);
|
|
1921
|
+
vec3 abc = (vec3(qB.xyz) * (1.0 / 255.0) - 0.5) * QUAT_NORM;
|
|
1922
|
+
float d = sqrt(max(0.0, 1.0 - dot(abc, abc)));
|
|
1923
|
+
uint mode = qB.w; // already 0..3
|
|
1275
1924
|
|
|
1276
|
-
// Compute normalized view-space center
|
|
1277
|
-
vec4 centerClipRaw = modelViewMatrix * vec4(splatPosition, 1.0);
|
|
1278
|
-
vec3 centerView = centerClipRaw.xyz / centerClipRaw.w;
|
|
1279
1925
|
|
|
1280
|
-
//
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1926
|
+
// Reconstruct Quaternion (x, y, z, w)
|
|
1927
|
+
// quat in (w,x,y,z)
|
|
1928
|
+
vec4 quat;
|
|
1929
|
+
if (mode == 0u) quat = vec4(d, abc); // (w, x, y, z)
|
|
1930
|
+
else if (mode == 1u) quat = vec4(abc.x, d, abc.yz); // stored (w,y,z)
|
|
1931
|
+
else if (mode == 2u) quat = vec4(abc.xy, d, abc.z); // stored (w,x,z)
|
|
1932
|
+
else quat = vec4(abc, d); // stored (w,x,y)
|
|
1285
1933
|
|
|
1286
|
-
//
|
|
1287
|
-
|
|
1934
|
+
// Decompress Scale
|
|
1935
|
+
uvec3 sB = unpackBytes(geom.w).xyz;
|
|
1936
|
+
vec3 sNorm = vec3(sB) * (1.0 / 255.0);
|
|
1937
|
+
vec3 sLerp = mix(scalesMin, scalesMax, sNorm);
|
|
1938
|
+
vec3 scale = exp(sLerp); // log scale stored
|
|
1288
1939
|
|
|
1289
|
-
//
|
|
1940
|
+
// Decompress Color & Opacity
|
|
1941
|
+
vec4 clr;
|
|
1942
|
+
vec3 sh = mix(sh0Min, sh0Max, colorRaw.rgb);
|
|
1943
|
+
clr.rgb = vec3(0.5) + sh * SH_C0;
|
|
1944
|
+
clr.a = colorRaw.a; // Opacity passed directly (linear or sigmoid handled by loader)
|
|
1290
1945
|
|
|
1291
|
-
//
|
|
1946
|
+
// --- Standard Gaussian Splat Projection ---
|
|
1947
|
+
|
|
1948
|
+
// View Space Setup
|
|
1949
|
+
mat4 modelView = modelViewMatrix;
|
|
1950
|
+
vec4 centerView = modelView * vec4(modelCenter, 1.0);
|
|
1951
|
+
|
|
1952
|
+
// Cull behind camera
|
|
1953
|
+
if (centerView.z > -0.2) {
|
|
1954
|
+
gl_Position = DISCARD_VERTEX;
|
|
1955
|
+
return;
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
// Covariance in 3D
|
|
1292
1959
|
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
|
-
);
|
|
1960
|
+
getModelCovariance(scale, quat, covA, covB);
|
|
1299
1961
|
|
|
1300
|
-
//
|
|
1301
|
-
// Requres focal lenghts and view-space center depth (tz)
|
|
1962
|
+
// Project to 2D
|
|
1302
1963
|
float focalX = viewport.x * projectionMatrix[0][0];
|
|
1303
1964
|
float focalY = viewport.y * projectionMatrix[1][1];
|
|
1304
|
-
float
|
|
1305
|
-
|
|
1965
|
+
float J1 = focalX / centerView.z;
|
|
1966
|
+
vec2 J2 = -J1 / centerView.z * centerView.xy;
|
|
1306
1967
|
|
|
1307
|
-
// Jacobian J = [fx/tz, 0, -fx*tx/tz^2]
|
|
1308
|
-
// [0, fy/tz, -fy*ty/tz^2]
|
|
1309
1968
|
mat3 J = mat3(
|
|
1310
|
-
|
|
1311
|
-
0.0,
|
|
1312
|
-
0.0,
|
|
1969
|
+
J1, 0.0, J2.x,
|
|
1970
|
+
0.0, J1, J2.y,
|
|
1971
|
+
0.0, 0.0, 0.0
|
|
1313
1972
|
);
|
|
1314
1973
|
|
|
1315
|
-
|
|
1316
|
-
mat3 W = transpose(mat3(modelViewMatrix));
|
|
1317
|
-
// Calculate T = W * J
|
|
1974
|
+
mat3 W = transpose(mat3(modelView));
|
|
1318
1975
|
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
|
-
}
|
|
1976
|
+
mat3 Vrk = mat3(
|
|
1977
|
+
covA.x, covA.y, covA.z,
|
|
1978
|
+
covA.y, covB.x, covB.y,
|
|
1979
|
+
covA.z, covB.y, covB.z
|
|
1980
|
+
);
|
|
1981
|
+
mat3 cov = transpose(T) * Vrk * T;
|
|
1353
1982
|
|
|
1354
|
-
|
|
1983
|
+
// Eigendecomposition for Quad dimensions
|
|
1984
|
+
float diagonal1 = cov[0][0] + 0.3;
|
|
1985
|
+
float offDiagonal = cov[0][1];
|
|
1986
|
+
float diagonal2 = cov[1][1] + 0.3;
|
|
1355
1987
|
|
|
1356
|
-
|
|
1357
|
-
float
|
|
1358
|
-
float
|
|
1359
|
-
float
|
|
1988
|
+
float mid = 0.5 * (diagonal1 + diagonal2);
|
|
1989
|
+
float radius = length(vec2((diagonal1 - diagonal2) * 0.5, offDiagonal));
|
|
1990
|
+
float lambda1 = mid + radius;
|
|
1991
|
+
float lambda2 = max(mid - radius, 0.1);
|
|
1360
1992
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1993
|
+
// Screen space quad vectors
|
|
1994
|
+
float vmin = min(1024.0, min(viewport.x, viewport.y)); // Safety clamp
|
|
1995
|
+
float l1 = 2.0 * min(sqrt(2.0 * lambda1), vmin);
|
|
1996
|
+
float l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);
|
|
1364
1997
|
|
|
1365
|
-
//
|
|
1366
|
-
if (l1 < 2.0 && l2 < 2.0) {
|
|
1367
|
-
|
|
1368
|
-
|
|
1998
|
+
// Discard tiny splats
|
|
1999
|
+
if (l1 < 2.0 && l2 < 2.0) {
|
|
2000
|
+
gl_Position = DISCARD_VERTEX;
|
|
2001
|
+
return;
|
|
1369
2002
|
}
|
|
1370
2003
|
|
|
1371
|
-
|
|
1372
|
-
vec2
|
|
1373
|
-
vec2
|
|
2004
|
+
vec2 diagVec = normalize(vec2(offDiagonal, lambda1 - diagonal1));
|
|
2005
|
+
vec2 v1 = l1 * diagVec;
|
|
2006
|
+
vec2 v2 = l2 * vec2(diagVec.y, -diagVec.x);
|
|
1374
2007
|
|
|
1375
|
-
//
|
|
1376
|
-
|
|
1377
|
-
vec2 c =
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
2008
|
+
// Vertex Position (Quad Expansion)
|
|
2009
|
+
vec4 centerProj = projectionMatrix * centerView;
|
|
2010
|
+
vec2 c = centerProj.ww / viewport; // Correction for clip space
|
|
2011
|
+
|
|
2012
|
+
// Frustum cull
|
|
2013
|
+
if (any(greaterThan(abs(centerProj.xy) - vec2(max(l1, l2)) * c, centerProj.ww))) {
|
|
2014
|
+
gl_Position = DISCARD_VERTEX;
|
|
1383
2015
|
return;
|
|
1384
2016
|
}
|
|
1385
2017
|
|
|
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 ---
|
|
2018
|
+
// Quad offset based on 'position' attribute (-1 to 1)
|
|
2019
|
+
vec2 offset = (position.x * v1 + position.y * v2) * c;
|
|
2020
|
+
|
|
2021
|
+
// Corner Clipping (for gaussian shape)
|
|
2022
|
+
// Assuming simple linear opacity here, otherwise inverse sigmoid logic required
|
|
2023
|
+
float alpha = max(clr.a, 1.0/255.0);
|
|
2024
|
+
float clip = min(1.0, sqrt(-log(1.0 / 255.0 / alpha)) / 2.0);
|
|
2025
|
+
|
|
2026
|
+
offset *= clip;
|
|
2027
|
+
vec2 clippedUV = position.xy * clip;
|
|
1408
2028
|
|
|
1409
|
-
|
|
1410
|
-
|
|
2029
|
+
gl_Position = centerProj + vec4(offset, 0.0, 0.0);
|
|
2030
|
+
|
|
2031
|
+
// Outputs
|
|
2032
|
+
vUv = clippedUV;
|
|
2033
|
+
vColor = vec4(max(clr.rgb, vec3(0.0)), clr.a);
|
|
1411
2034
|
}
|
|
1412
2035
|
`
|
|
1413
|
-
),
|
|
2036
|
+
), Ct = (
|
|
1414
2037
|
/* glsl */
|
|
1415
2038
|
`
|
|
1416
2039
|
precision highp float;
|
|
1417
2040
|
|
|
1418
|
-
|
|
1419
|
-
|
|
2041
|
+
in vec4 vColor; // Color and opacity passed from vertex shader
|
|
2042
|
+
in vec2 vUv; // Quad UV coordinates (-1 to 1) passed from vertex shader
|
|
2043
|
+
|
|
2044
|
+
out vec4 fragColor; // Output variable
|
|
1420
2045
|
|
|
1421
2046
|
// Fast approximate e^x based on https://nic.schraudolph.org/pubs/Schraudolph99.pdf
|
|
1422
2047
|
const float EXP_A = 12102203.0; // ≈ 2^23 / ln(2)
|
|
@@ -1440,88 +2065,86 @@ void main(void) {
|
|
|
1440
2065
|
if (alpha < 1.0 / 255.0) discard; // Discard fragments with very low alpha
|
|
1441
2066
|
|
|
1442
2067
|
// Premultiply color by alpha (required for correct blending)
|
|
1443
|
-
|
|
2068
|
+
fragColor = vec4(vColor.rgb * alpha, alpha);
|
|
1444
2069
|
}
|
|
1445
2070
|
`
|
|
1446
2071
|
);
|
|
1447
|
-
class
|
|
2072
|
+
class It extends h.ShaderMaterial {
|
|
1448
2073
|
constructor(e = {}) {
|
|
1449
|
-
const
|
|
1450
|
-
// Textures
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
2074
|
+
const t = {
|
|
2075
|
+
// Packed Textures
|
|
2076
|
+
packedGeometry: { value: null },
|
|
2077
|
+
// RGBA32UI: .r=MeansLow, .g=MeansHigh, .b=Quats, .a=Scales
|
|
2078
|
+
packedColor: { value: null },
|
|
2079
|
+
// RGBA8: .rgb=Color, .a=Opacity
|
|
1454
2080
|
splatOrder: { value: null },
|
|
1455
|
-
//
|
|
1456
|
-
|
|
1457
|
-
|
|
2081
|
+
// Index map
|
|
2082
|
+
// Decompression Ranges
|
|
2083
|
+
meansMin: { value: new h.Vector3() },
|
|
2084
|
+
meansMax: { value: new h.Vector3() },
|
|
2085
|
+
scalesMin: { value: new h.Vector3() },
|
|
2086
|
+
scalesMax: { value: new h.Vector3() },
|
|
2087
|
+
sh0Min: { value: new h.Vector3() },
|
|
2088
|
+
sh0Max: { value: new h.Vector3() },
|
|
2089
|
+
// Render State
|
|
2090
|
+
texWidth: { value: 0 },
|
|
2091
|
+
viewport: { value: new h.Vector2(1, 1) },
|
|
1458
2092
|
numSplats: { value: 0 }
|
|
1459
|
-
// Max splats to render (updated by sorter)
|
|
1460
2093
|
};
|
|
1461
2094
|
super({
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
2095
|
+
uniforms: t,
|
|
2096
|
+
vertexShader: Et,
|
|
2097
|
+
fragmentShader: Ct,
|
|
1465
2098
|
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,
|
|
2099
|
+
glslVersion: h.GLSL3,
|
|
2100
|
+
blendSrc: h.OneFactor,
|
|
2101
|
+
blendSrcAlpha: h.OneFactor,
|
|
2102
|
+
blending: h.CustomBlending,
|
|
2103
|
+
blendEquation: h.AddEquation,
|
|
2104
|
+
blendEquationAlpha: h.AddEquation,
|
|
2105
|
+
blendDst: h.OneMinusSrcAlphaFactor,
|
|
2106
|
+
blendDstAlpha: h.OneMinusSrcAlphaFactor,
|
|
1478
2107
|
depthTest: !0,
|
|
1479
2108
|
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);
|
|
2109
|
+
side: h.DoubleSide,
|
|
2110
|
+
alphaTest: e.alphaTest ?? 0,
|
|
2111
|
+
toneMapped: e.toneMapped ?? !1
|
|
2112
|
+
}), e.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = h.NoBlending);
|
|
2113
|
+
}
|
|
2114
|
+
setTexWidth(e) {
|
|
2115
|
+
this.uniforms.texWidth.value = e | 0;
|
|
1489
2116
|
}
|
|
1490
2117
|
/**
|
|
1491
2118
|
* Update the viewport size
|
|
1492
2119
|
* @param width Viewport width
|
|
1493
2120
|
* @param height Viewport height
|
|
1494
2121
|
*/
|
|
1495
|
-
updateViewport(e,
|
|
1496
|
-
this.uniforms.viewport.value.set(e,
|
|
2122
|
+
updateViewport(e, t) {
|
|
2123
|
+
this.uniforms.viewport.value.set(e, t);
|
|
1497
2124
|
}
|
|
1498
2125
|
/**
|
|
1499
|
-
* Set
|
|
1500
|
-
* @param texture Texture containing positions
|
|
2126
|
+
* Set the main packed geometry texture (RGBA32UI)
|
|
1501
2127
|
*/
|
|
1502
|
-
|
|
1503
|
-
this.uniforms.
|
|
2128
|
+
setPackedGeometry(e) {
|
|
2129
|
+
this.uniforms.packedGeometry.value = e;
|
|
1504
2130
|
}
|
|
1505
2131
|
/**
|
|
1506
|
-
* Set
|
|
1507
|
-
* @param texture Texture containing rotation and scale data
|
|
2132
|
+
* Set the packed color texture (RGBA8)
|
|
1508
2133
|
*/
|
|
1509
|
-
|
|
1510
|
-
this.uniforms.
|
|
2134
|
+
setPackedColor(e) {
|
|
2135
|
+
this.uniforms.packedColor.value = e;
|
|
1511
2136
|
}
|
|
1512
2137
|
/**
|
|
1513
|
-
* Set
|
|
1514
|
-
* @param texture Texture containing colors
|
|
2138
|
+
* Set order texture for sorting
|
|
1515
2139
|
*/
|
|
1516
|
-
|
|
1517
|
-
this.uniforms.
|
|
2140
|
+
setOrderTexture(e) {
|
|
2141
|
+
this.uniforms.splatOrder.value = e;
|
|
1518
2142
|
}
|
|
1519
2143
|
/**
|
|
1520
|
-
* Set
|
|
1521
|
-
* @param texture Texture containing sort order
|
|
2144
|
+
* Set the ranges needed to decompress the packed floats
|
|
1522
2145
|
*/
|
|
1523
|
-
|
|
1524
|
-
this.uniforms.
|
|
2146
|
+
setRanges(e) {
|
|
2147
|
+
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
2148
|
}
|
|
1526
2149
|
/**
|
|
1527
2150
|
* Set number of splats to render
|
|
@@ -1531,48 +2154,40 @@ class Ve extends l.ShaderMaterial {
|
|
|
1531
2154
|
this.uniforms.numSplats.value = e;
|
|
1532
2155
|
}
|
|
1533
2156
|
}
|
|
1534
|
-
const
|
|
2157
|
+
const de = class de extends h.Mesh {
|
|
1535
2158
|
// Match shader constant
|
|
1536
2159
|
/**
|
|
1537
2160
|
* Create a new SplatMesh for rendering Gaussian splats
|
|
1538
2161
|
* @param splatData The splat data to render
|
|
1539
2162
|
* @param options Rendering options
|
|
1540
2163
|
*/
|
|
1541
|
-
constructor(
|
|
1542
|
-
const
|
|
1543
|
-
super(
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
2164
|
+
constructor(t, r = {}) {
|
|
2165
|
+
const s = new It(r), a = de.createInstancedGeometry(t.numSplats, de.INSTANCE_SIZE);
|
|
2166
|
+
super(a, s);
|
|
2167
|
+
M(this, "sorter");
|
|
2168
|
+
M(this, "options");
|
|
2169
|
+
M(this, "splatData");
|
|
2170
|
+
M(this, "textureManager");
|
|
2171
|
+
M(this, "material");
|
|
2172
|
+
M(this, "geometry");
|
|
2173
|
+
M(this, "lastCameraPositionLocal", new h.Vector3());
|
|
2174
|
+
M(this, "lastCameraDirectionLocal", new h.Vector3());
|
|
2175
|
+
M(this, "invModelMatrix", new h.Matrix4());
|
|
1553
2176
|
// Cached inverse matrix
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
const
|
|
1563
|
-
this.geometry.instanceCount = Math.ceil(
|
|
2177
|
+
M(this, "_vpW", -1);
|
|
2178
|
+
M(this, "_vpH", -1);
|
|
2179
|
+
M(this, "_size", new h.Vector2());
|
|
2180
|
+
M(this, "_camPosW", new h.Vector3());
|
|
2181
|
+
M(this, "_camDirW", new h.Vector3());
|
|
2182
|
+
M(this, "_camPosL", new h.Vector3());
|
|
2183
|
+
M(this, "_camDirL", new h.Vector3());
|
|
2184
|
+
M(this, "onSorterUpdated", (t) => {
|
|
2185
|
+
const r = t.count;
|
|
2186
|
+
this.geometry.instanceCount = Math.ceil(r / de.INSTANCE_SIZE), this.material.setNumSplats(r);
|
|
1564
2187
|
});
|
|
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);
|
|
2188
|
+
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);
|
|
2189
|
+
let o = this.createChunks() || void 0;
|
|
2190
|
+
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
2191
|
}
|
|
1577
2192
|
/**
|
|
1578
2193
|
* Creates the instanced geometry for rendering splats.
|
|
@@ -1580,8 +2195,8 @@ const se = class se extends l.Mesh {
|
|
|
1580
2195
|
* @param instanceSize Number of splats per instance.
|
|
1581
2196
|
* @returns InstancedBufferGeometry
|
|
1582
2197
|
*/
|
|
1583
|
-
static createInstancedGeometry(
|
|
1584
|
-
const
|
|
2198
|
+
static createInstancedGeometry(t, r) {
|
|
2199
|
+
const s = Math.ceil(t / r), a = new h.BufferGeometry(), o = new Float32Array([
|
|
1585
2200
|
// x, y, splat_index_in_instance
|
|
1586
2201
|
-1,
|
|
1587
2202
|
-1,
|
|
@@ -1595,24 +2210,24 @@ const se = class se extends l.Mesh {
|
|
|
1595
2210
|
-1,
|
|
1596
2211
|
1,
|
|
1597
2212
|
0
|
|
1598
|
-
]), i = new Uint16Array([0, 1, 2, 0, 2, 3]),
|
|
1599
|
-
for (let
|
|
1600
|
-
const
|
|
1601
|
-
for (let
|
|
1602
|
-
|
|
2213
|
+
]), i = new Uint16Array([0, 1, 2, 0, 2, 3]), m = new Float32Array(4 * 3 * r);
|
|
2214
|
+
for (let u = 0; u < r; u++) {
|
|
2215
|
+
const x = u * 4 * 3;
|
|
2216
|
+
for (let g = 0; g < 4; g++)
|
|
2217
|
+
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
2218
|
}
|
|
1604
|
-
const
|
|
1605
|
-
for (let
|
|
1606
|
-
const
|
|
1607
|
-
|
|
2219
|
+
const f = new Uint32Array(6 * r);
|
|
2220
|
+
for (let u = 0; u < r; u++) {
|
|
2221
|
+
const x = u * 6, g = u * 4;
|
|
2222
|
+
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
2223
|
}
|
|
1609
|
-
|
|
1610
|
-
const
|
|
1611
|
-
|
|
1612
|
-
const
|
|
1613
|
-
for (let
|
|
1614
|
-
|
|
1615
|
-
return
|
|
2224
|
+
a.setAttribute("position", new h.BufferAttribute(m, 3)), a.setIndex(new h.BufferAttribute(f, 1));
|
|
2225
|
+
const y = new h.InstancedBufferGeometry();
|
|
2226
|
+
y.index = a.index, y.setAttribute("position", a.getAttribute("position"));
|
|
2227
|
+
const l = new Uint32Array(s);
|
|
2228
|
+
for (let u = 0; u < s; u++)
|
|
2229
|
+
l[u] = u * r;
|
|
2230
|
+
return y.setAttribute("splatInstanceIndex", new h.InstancedBufferAttribute(l, 1, !1)), y.instanceCount = 0, y;
|
|
1616
2231
|
}
|
|
1617
2232
|
/**
|
|
1618
2233
|
* Create chunks data (bounding box min/max) for the sorter.
|
|
@@ -1621,14 +2236,14 @@ const se = class se extends l.Mesh {
|
|
|
1621
2236
|
createChunks() {
|
|
1622
2237
|
if (!this.splatData)
|
|
1623
2238
|
return null;
|
|
1624
|
-
const
|
|
1625
|
-
return
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
2239
|
+
const t = this.splatData.boundingBox;
|
|
2240
|
+
return t.min.x === 1 / 0 || t.max.x === -1 / 0 ? null : new Float32Array([
|
|
2241
|
+
t.min.x,
|
|
2242
|
+
t.min.y,
|
|
2243
|
+
t.min.z,
|
|
2244
|
+
t.max.x,
|
|
2245
|
+
t.max.y,
|
|
2246
|
+
t.max.z
|
|
1632
2247
|
]);
|
|
1633
2248
|
}
|
|
1634
2249
|
/**
|
|
@@ -1636,17 +2251,17 @@ const se = class se extends l.Mesh {
|
|
|
1636
2251
|
* @param width Viewport width
|
|
1637
2252
|
* @param height Viewport height
|
|
1638
2253
|
*/
|
|
1639
|
-
updateViewport(
|
|
1640
|
-
|
|
2254
|
+
updateViewport(t, r) {
|
|
2255
|
+
t === this._vpW && r === this._vpH || (this._vpW = t, this._vpH = r, this.material.updateViewport(t, r));
|
|
1641
2256
|
}
|
|
1642
2257
|
/**
|
|
1643
2258
|
* Sorts splats based on camera position and direction.
|
|
1644
2259
|
* @param camera The camera to sort against.
|
|
1645
2260
|
*/
|
|
1646
|
-
sort(
|
|
1647
|
-
|
|
1648
|
-
const
|
|
1649
|
-
this.options.autoSort && (
|
|
2261
|
+
sort(t) {
|
|
2262
|
+
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);
|
|
2263
|
+
const r = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6, s = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
|
|
2264
|
+
this.options.autoSort && (r || s) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
|
|
1650
2265
|
}
|
|
1651
2266
|
/**
|
|
1652
2267
|
* THREE.js hook called before rendering the object.
|
|
@@ -1657,8 +2272,8 @@ const se = class se extends l.Mesh {
|
|
|
1657
2272
|
*/
|
|
1658
2273
|
// prettier-ignore
|
|
1659
2274
|
// @ts-expect-error scene is not used
|
|
1660
|
-
onBeforeRender(
|
|
1661
|
-
this.sort(
|
|
2275
|
+
onBeforeRender(t, r, s) {
|
|
2276
|
+
this.sort(s), t.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
|
|
1662
2277
|
}
|
|
1663
2278
|
/**
|
|
1664
2279
|
* Dispose of resources
|
|
@@ -1668,39 +2283,51 @@ const se = class se extends l.Mesh {
|
|
|
1668
2283
|
}
|
|
1669
2284
|
};
|
|
1670
2285
|
/** Number of splats combined into a single instanced draw call. */
|
|
1671
|
-
|
|
1672
|
-
let
|
|
1673
|
-
const
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2286
|
+
M(de, "INSTANCE_SIZE", 128);
|
|
2287
|
+
let Te = de;
|
|
2288
|
+
const ve = /* @__PURE__ */ new Map(), Ft = ({
|
|
2289
|
+
url: n,
|
|
2290
|
+
type: e,
|
|
2291
|
+
debug: t = !1,
|
|
2292
|
+
splatOptions: r = {},
|
|
2293
|
+
...s
|
|
1678
2294
|
}) => {
|
|
1679
|
-
|
|
1680
|
-
const
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
2295
|
+
if (!n) throw new Error('Splat component requires either "url" or "plyUrl" prop');
|
|
2296
|
+
const a = Tt(n, e);
|
|
2297
|
+
t && console.debug("SPLAT: rendering", { url: n, type: a, splatOptions: r, meshProps: s });
|
|
2298
|
+
const [o, i] = Xe(null), m = Ze(null);
|
|
2299
|
+
return Je(() => {
|
|
2300
|
+
const f = Ne(n, a, r);
|
|
2301
|
+
return _t(n, a, r).then(
|
|
2302
|
+
(y) => {
|
|
2303
|
+
i(y);
|
|
1686
2304
|
}
|
|
1687
2305
|
), () => {
|
|
1688
|
-
|
|
2306
|
+
t && console.debug("SPLAT: releasing mesh for", n), zt(f);
|
|
1689
2307
|
};
|
|
1690
|
-
}, [
|
|
1691
|
-
},
|
|
1692
|
-
const
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
2308
|
+
}, [n, a, r, t]), o ? /* @__PURE__ */ tt.jsx("primitive", { ref: m, object: o, ...s }) : null;
|
|
2309
|
+
}, Rt = (n) => {
|
|
2310
|
+
const e = n.toLowerCase();
|
|
2311
|
+
return e.endsWith(".ply") ? "ply" : e.endsWith(".sogs") || e.endsWith(".zip") || e.endsWith(".json") ? "sogs" : null;
|
|
2312
|
+
}, Tt = (n, e) => {
|
|
2313
|
+
if (e) return e;
|
|
2314
|
+
const t = Rt(n);
|
|
2315
|
+
if (t) return t;
|
|
2316
|
+
throw new Error(`Cannot determine file type from URL: "${n}". `);
|
|
2317
|
+
}, Ne = (n, e, t) => `${n}:${e}:${JSON.stringify(t)}`, _t = async (n, e, t) => {
|
|
2318
|
+
const r = Ne(n, e, t), s = ve.get(r);
|
|
2319
|
+
if (s)
|
|
2320
|
+
return s.refCount++, s.mesh;
|
|
2321
|
+
const o = await (e === "ply" ? new st() : new St()).loadAsync(n), i = new Te(o, t);
|
|
2322
|
+
return ve.set(r, { mesh: i, refCount: 1 }), i;
|
|
1697
2323
|
};
|
|
1698
|
-
function
|
|
1699
|
-
const e =
|
|
1700
|
-
e && (e.refCount--, e.refCount <= 0 && (e.mesh.dispose(),
|
|
2324
|
+
function zt(n) {
|
|
2325
|
+
const e = ve.get(n);
|
|
2326
|
+
e && (e.refCount--, e.refCount <= 0 && (e.mesh.dispose(), ve.delete(n)));
|
|
1701
2327
|
}
|
|
1702
2328
|
export {
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
2329
|
+
st as PlyLoader,
|
|
2330
|
+
St as SogsLoader,
|
|
2331
|
+
Ft as Splat,
|
|
2332
|
+
Te as SplatMesh
|
|
1706
2333
|
};
|