@speridlabs/visus 2.2.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 +1455 -838
- package/dist/main.umd.js +164 -195
- package/dist/react.d.ts +6 -2
- package/dist/react.es.js +1617 -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,67 +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
|
+
}
|
|
464
466
|
}
|
|
465
|
-
class
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
this
|
|
467
|
+
class Fe {
|
|
468
|
+
// Upper 8 bits of 16-bit means
|
|
469
|
+
constructor(e, t, r) {
|
|
470
|
+
M(this, "ranges");
|
|
471
|
+
M(this, "numSplats", 0);
|
|
472
|
+
M(this, "boundingBox", new be());
|
|
473
|
+
// Original SOGS textures
|
|
474
|
+
M(this, "sh0");
|
|
475
|
+
// SH DC coefficients + alpha
|
|
476
|
+
M(this, "quats");
|
|
477
|
+
// Quaternion components + mode
|
|
478
|
+
M(this, "scales");
|
|
479
|
+
// Scale values (8-bit)
|
|
480
|
+
M(this, "means_l");
|
|
481
|
+
// Lower 8 bits of 16-bit means
|
|
482
|
+
M(this, "means_u");
|
|
483
|
+
this.ranges = t, this.numSplats = e, this.sh0 = r.sh0, this.quats = r.quats, this.scales = r.scales, this.means_l = r.means_l, this.means_u = r.means_u, this.boundingBox = this.calculateBoundingBox();
|
|
484
|
+
}
|
|
485
|
+
calculateBoundingBox() {
|
|
486
|
+
this.boundingBox.reset();
|
|
487
|
+
const { mins: e, maxs: t } = this.ranges.means, r = (s) => Math.sign(s) * (Math.exp(Math.abs(s)) - 1);
|
|
488
|
+
return this.boundingBox.center.set(
|
|
489
|
+
(r(e[0]) + r(t[0])) * 0.5,
|
|
490
|
+
(r(e[1]) + r(t[1])) * 0.5,
|
|
491
|
+
(r(e[2]) + r(t[2])) * 0.5
|
|
492
|
+
), this.boundingBox.halfExtents.set(
|
|
493
|
+
(r(t[0]) - r(e[0])) * 0.5,
|
|
494
|
+
(r(t[1]) - r(e[1])) * 0.5,
|
|
495
|
+
(r(t[2]) - r(e[2])) * 0.5
|
|
496
|
+
), this.boundingBox;
|
|
497
|
+
}
|
|
498
|
+
dispose() {
|
|
499
|
+
this.sh0.dispose(), this.quats.dispose(), this.scales.dispose(), this.means_l.dispose(), this.means_u.dispose();
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
class qe {
|
|
503
|
+
// RGBA32UI - (Position + Rotation + Scale)
|
|
504
|
+
// RGBA32UI Texture Content:
|
|
505
|
+
// .r = Means Lower (RGB)
|
|
506
|
+
// .g = Means Upper (RGB)
|
|
507
|
+
// .b = Rotation (RGBA)
|
|
508
|
+
// .a = Scale (RGB)
|
|
509
|
+
constructor(e, t, r, s, a, o, i, m) {
|
|
510
|
+
// Info data - cpu
|
|
511
|
+
M(this, "numSplats");
|
|
512
|
+
M(this, "textureWidth");
|
|
513
|
+
M(this, "textureHeight");
|
|
514
|
+
M(this, "ranges");
|
|
515
|
+
M(this, "centers");
|
|
516
|
+
// TODO: see if necesary or can be compressed somehow
|
|
517
|
+
M(this, "boundingBox");
|
|
518
|
+
// GPU Textures
|
|
519
|
+
M(this, "packedColor");
|
|
520
|
+
// RGBA8 - (Color + Opacity)
|
|
521
|
+
// RGBA8 Texture Content:
|
|
522
|
+
// .rgb = Color, .a = Opacity
|
|
523
|
+
M(this, "packedGeometry");
|
|
524
|
+
this.numSplats = e, this.textureWidth = t, this.textureHeight = r, this.boundingBox = m, this.ranges = i, this.centers = s, this.packedColor = o, this.packedGeometry = a;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Optional: Reconstruct a full JS object for a specific splat.
|
|
528
|
+
* Useful for raycasting or debugging.
|
|
529
|
+
*/
|
|
530
|
+
// public getSplat(index: number) {
|
|
531
|
+
// throw new Error('Not implemented yet');
|
|
532
|
+
// }
|
|
533
|
+
dispose() {
|
|
534
|
+
this.centers = new Float32Array(0), this.packedColor = new Uint8Array(0), this.packedGeometry = new Uint32Array(0);
|
|
535
|
+
}
|
|
536
|
+
// public abstract deserialize(): ISplat;
|
|
537
|
+
// public abstract returnPacked(): ISplat;
|
|
538
|
+
}
|
|
539
|
+
const me = 0.28209479177387814;
|
|
540
|
+
class Ce {
|
|
541
|
+
/**
|
|
542
|
+
* Packs PLY data (Float32) into the Unified SOGS-like Format.
|
|
543
|
+
*/
|
|
544
|
+
// prettier-ignore
|
|
545
|
+
static packPly(e) {
|
|
546
|
+
const t = e.numSplats, r = Math.ceil(Math.sqrt(t)), s = Math.ceil(t / r), a = r * s, { ranges: o, colorScale: i } = this.calculatePlyRanges(e), m = new Uint32Array(a * 4), f = new Uint8Array(a * 4), y = new h.Quaternion();
|
|
547
|
+
for (let l = 0; l < t; l++) {
|
|
548
|
+
const u = l * 4, x = l * 3, g = l * 4, v = e.positions[x + 0], b = e.positions[x + 1], E = e.positions[x + 2], T = this.clamp01(this.norm(v, o.means.min.x, o.means.max.x)), P = this.clamp01(this.norm(b, o.means.min.y, o.means.max.y)), H = this.clamp01(this.norm(E, o.means.min.z, o.means.max.z)), L = T * 65535 | 0, A = P * 65535 | 0, C = H * 65535 | 0;
|
|
549
|
+
m[u + 0] = this.pack4Bytes(L & 255, A & 255, C & 255, 0), m[u + 1] = this.pack4Bytes(L >> 8, A >> 8, C >> 8, 0), y.set(e.rotations[g], e.rotations[g + 1], e.rotations[g + 2], e.rotations[g + 3]).normalize();
|
|
550
|
+
let _ = y.w, w = y.x, p = y.y, R = y.z;
|
|
551
|
+
const q = Math.abs(_), j = Math.abs(w), Y = Math.abs(p), V = Math.abs(R);
|
|
552
|
+
let D = 0, O = q;
|
|
553
|
+
j > O && (O = j, D = 1), Y > O && (O = Y, D = 2), V > O && (O = V, D = 3), (D === 0 ? _ : D === 1 ? w : D === 2 ? p : R) < 0 && (_ = -_, w = -w, p = -p, R = -R);
|
|
554
|
+
let N = 0, c = 0, k = 0;
|
|
555
|
+
D === 0 && (N = w, c = p, k = R), D === 1 && (N = _, c = p, k = R), D === 2 && (N = _, c = w, k = R), D === 3 && (N = _, c = w, k = p);
|
|
556
|
+
const B = (se) => Math.min(255, Math.max(0, Math.round((0.5 + se / Math.SQRT2) * 255)));
|
|
557
|
+
m[u + 2] = this.pack4Bytes(B(N), B(c), B(k), D);
|
|
558
|
+
const F = this.norm(e.scales[x + 0], o.scales.min.x, o.scales.max.x), I = this.norm(e.scales[x + 1], o.scales.min.y, o.scales.max.y), d = this.norm(e.scales[x + 2], o.scales.min.z, o.scales.max.z);
|
|
559
|
+
m[u + 3] = this.pack4Bytes(Math.floor(F * 255), Math.floor(I * 255), Math.floor(d * 255), 0);
|
|
560
|
+
const z = this.clamp01(e.colors[x + 0] * i), W = this.clamp01(e.colors[x + 1] * i), S = this.clamp01(e.colors[x + 2] * i), U = (z - 0.5) / me, $ = (W - 0.5) / me, X = (S - 0.5) / me, Q = this.clamp01(this.norm(U, o.sh0.min.x, o.sh0.max.x)), Z = this.clamp01(this.norm($, o.sh0.min.y, o.sh0.max.y)), K = this.clamp01(this.norm(X, o.sh0.min.z, o.sh0.max.z)), re = this.clamp01(e.opacities[l]);
|
|
561
|
+
f[u + 0] = Math.round(Q * 255), f[u + 1] = Math.round(Z * 255), f[u + 2] = Math.round(K * 255), f[u + 3] = Math.round(re * 255);
|
|
562
|
+
}
|
|
563
|
+
return new qe(t, r, s, e.positions, m, f, o, e.boundingBox);
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Packs SOGS data.
|
|
567
|
+
* Interleaves the separate textures into the Unified RGBA32UI buffer.
|
|
568
|
+
* Decodes centers for sorting.
|
|
569
|
+
*/
|
|
570
|
+
// prettier-ignore
|
|
571
|
+
static packSogs(e) {
|
|
572
|
+
const t = e.numSplats, r = Math.ceil(Math.sqrt(t)), s = Math.ceil(t / r), a = r * s, o = this.convertSogsRanges(e.ranges), i = e.ranges.means.mins[0], m = e.ranges.means.mins[1], f = e.ranges.means.mins[2], y = e.ranges.means.maxs[0], l = e.ranges.means.maxs[1], u = e.ranges.means.maxs[2], x = (w) => Math.sign(w) * (Math.exp(Math.abs(w)) - 1), g = new h.Vector3(
|
|
573
|
+
x(i),
|
|
574
|
+
x(m),
|
|
575
|
+
x(f)
|
|
576
|
+
), v = new h.Vector3(
|
|
577
|
+
x(y),
|
|
578
|
+
x(l),
|
|
579
|
+
x(u)
|
|
580
|
+
);
|
|
581
|
+
o.means.min.copy(g), o.means.max.copy(v);
|
|
582
|
+
const b = e, E = this.getPixels(b.means_l), T = this.getPixels(b.means_u), P = this.getPixels(b.quats), H = this.getPixels(b.scales), L = this.getPixels(b.sh0), A = new Uint32Array(a * 4), C = new Uint8Array(a * 4), _ = new Float32Array(t * 3);
|
|
583
|
+
for (let w = 0; w < t; w++) {
|
|
584
|
+
const p = w * 4, R = T[p + 0], q = E[p + 0], j = T[p + 1], Y = E[p + 1], V = T[p + 2], D = E[p + 2], O = (R << 8 | q) / 65535, J = (j << 8 | Y) / 65535, N = (V << 8 | D) / 65535, c = this.sogsDecode(O, i, y), k = this.sogsDecode(J, m, l), B = this.sogsDecode(N, f, u);
|
|
585
|
+
_[w * 3 + 0] = c, _[w * 3 + 1] = k, _[w * 3 + 2] = B;
|
|
586
|
+
const F = this.clamp01(this.norm(c, g.x, v.x)) * 65535 | 0, I = this.clamp01(this.norm(k, g.y, v.y)) * 65535 | 0, d = this.clamp01(this.norm(B, g.z, v.z)) * 65535 | 0;
|
|
587
|
+
A[p + 0] = this.pack4Bytes(F & 255, I & 255, d & 255, 0), A[p + 1] = this.pack4Bytes(F >> 8, I >> 8, d >> 8, 0), A[p + 3] = this.pack4Bytes(H[p], H[p + 1], H[p + 2], 0);
|
|
588
|
+
const W = P[p + 3] - 252;
|
|
589
|
+
A[p + 2] = this.pack4Bytes(P[p + 0], P[p + 1], P[p + 2], W), C[p + 0] = L[p], C[p + 1] = L[p + 1], C[p + 2] = L[p + 2];
|
|
590
|
+
const S = L[p + 3] / 255, U = e.ranges.sh0.mins[3] + (e.ranges.sh0.maxs[3] - e.ranges.sh0.mins[3]) * S, $ = 1 / (1 + Math.exp(-U));
|
|
591
|
+
C[p + 3] = Math.round(Math.max(0, Math.min(1, $)) * 255);
|
|
592
|
+
}
|
|
593
|
+
return new qe(t, r, s, _, A, C, o, e.boundingBox);
|
|
594
|
+
}
|
|
595
|
+
// --- Helpers ---
|
|
596
|
+
// prettier-ignore
|
|
597
|
+
static pack4Bytes(e, t, r, s) {
|
|
598
|
+
return (e & 255) << 24 | (t & 255) << 16 | (r & 255) << 8 | s & 255;
|
|
599
|
+
}
|
|
600
|
+
// prettier-ignore
|
|
601
|
+
static getPixels(e) {
|
|
602
|
+
const t = e.image, r = t.width, s = t.height;
|
|
603
|
+
if (t.data && (t.data instanceof Uint8Array || t.data instanceof Uint8ClampedArray)) return new Uint8Array(t.data);
|
|
604
|
+
const a = document.createElement("canvas");
|
|
605
|
+
a.width = r, a.height = s;
|
|
606
|
+
const o = a.getContext("2d", { willReadFrequently: !0 });
|
|
607
|
+
if (!o) throw new Error("Canvas init failed");
|
|
608
|
+
return o.drawImage(t, 0, 0), new Uint8Array(o.getImageData(0, 0, r, s).data);
|
|
609
|
+
}
|
|
610
|
+
static convertSogsRanges(e) {
|
|
611
|
+
const t = (r) => new h.Vector3(r[0], r[1], r[2]);
|
|
612
|
+
return {
|
|
613
|
+
sh0: { min: t(e.sh0.mins), max: t(e.sh0.maxs) },
|
|
614
|
+
means: { min: t(e.means.mins), max: t(e.means.maxs) },
|
|
615
|
+
scales: { min: t(e.scales.mins), max: t(e.scales.maxs) }
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
static calculatePlyRanges(e) {
|
|
619
|
+
const t = new h.Vector3(1 / 0, 1 / 0, 1 / 0), r = new h.Vector3(-1 / 0, -1 / 0, -1 / 0), s = new h.Vector3(1 / 0, 1 / 0, 1 / 0), a = new h.Vector3(-1 / 0, -1 / 0, -1 / 0), o = new h.Vector3(1 / 0, 1 / 0, 1 / 0), i = new h.Vector3(-1 / 0, -1 / 0, -1 / 0);
|
|
620
|
+
let m = 0;
|
|
621
|
+
for (let y = 0; y < e.numSplats; y++) {
|
|
622
|
+
const l = y * 3, u = e.positions[l + 0], x = e.positions[l + 1], g = e.positions[l + 2];
|
|
623
|
+
t.x = Math.min(t.x, u), r.x = Math.max(r.x, u), t.y = Math.min(t.y, x), r.y = Math.max(r.y, x), t.z = Math.min(t.z, g), r.z = Math.max(r.z, g), s.x = Math.min(s.x, e.scales[l]), a.x = Math.max(a.x, e.scales[l]), s.y = Math.min(s.y, e.scales[l + 1]), a.y = Math.max(a.y, e.scales[l + 1]), s.z = Math.min(s.z, e.scales[l + 2]), a.z = Math.max(a.z, e.scales[l + 2]), m = Math.max(
|
|
624
|
+
m,
|
|
625
|
+
e.colors[l],
|
|
626
|
+
e.colors[l + 1],
|
|
627
|
+
e.colors[l + 2]
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
const f = m > 1.5 ? 1 / 255 : 1;
|
|
631
|
+
for (let y = 0; y < e.numSplats; y++) {
|
|
632
|
+
const l = y * 3, u = this.clamp01(e.colors[l + 0] * f), x = this.clamp01(e.colors[l + 1] * f), g = this.clamp01(e.colors[l + 2] * f), v = (u - 0.5) / me, b = (x - 0.5) / me, E = (g - 0.5) / me;
|
|
633
|
+
o.x = Math.min(o.x, v), i.x = Math.max(i.x, v), o.y = Math.min(o.y, b), i.y = Math.max(i.y, b), o.z = Math.min(o.z, E), i.z = Math.max(i.z, E);
|
|
634
|
+
}
|
|
635
|
+
return {
|
|
636
|
+
colorScale: f,
|
|
637
|
+
ranges: {
|
|
638
|
+
sh0: { min: o, max: i },
|
|
639
|
+
means: { min: t, max: r },
|
|
640
|
+
scales: { min: s, max: a }
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
static clamp01(e) {
|
|
645
|
+
return Math.max(0, Math.min(1, e));
|
|
646
|
+
}
|
|
647
|
+
// prettier-ignore
|
|
648
|
+
// private static lerp(a: number, b: number, t: number) { return a + (b - a) * t; } // prettier-ignore
|
|
649
|
+
// private static invSogsMap(v: number) { return Math.sign(v) * Math.log(Math.abs(v) + 1) } // prettier-ignore
|
|
650
|
+
static norm(e, t, r) {
|
|
651
|
+
return (e - t) / (r - t || 1);
|
|
652
|
+
}
|
|
653
|
+
// prettier-ignore
|
|
654
|
+
static sogsDecode(e, t, r) {
|
|
655
|
+
const s = t + (r - t) * e;
|
|
656
|
+
return Math.sign(s) * (Math.exp(Math.abs(s)) - 1);
|
|
657
|
+
}
|
|
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());
|
|
665
|
+
this.withCredentials = !0;
|
|
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);
|
|
473
668
|
}
|
|
474
669
|
/**
|
|
475
670
|
* Handles messages received from the parsing worker
|
|
476
671
|
* @param event The message event from the worker
|
|
477
672
|
*/
|
|
478
|
-
onWorkerMessage(
|
|
479
|
-
const { requestId:
|
|
480
|
-
if (!
|
|
481
|
-
if (this.pendingCallbacks.delete(
|
|
482
|
-
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"));
|
|
483
678
|
try {
|
|
484
|
-
const i = new
|
|
485
|
-
i.numSplats =
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
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
|
|
489
684
|
), i.boundingBox.max.set(
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
), 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);
|
|
494
691
|
} catch (i) {
|
|
495
|
-
|
|
692
|
+
o.reject(i);
|
|
496
693
|
}
|
|
497
694
|
}
|
|
498
695
|
/**
|
|
@@ -502,19 +699,19 @@ class ze extends l.Loader {
|
|
|
502
699
|
* @param onProgress Optional progress callback
|
|
503
700
|
* @param onError Optional error callback
|
|
504
701
|
*/
|
|
505
|
-
load(
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
|
|
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,
|
|
509
706
|
(i) => {
|
|
510
|
-
this.parseAsync(i).then((
|
|
511
|
-
|
|
512
|
-
}).catch((
|
|
513
|
-
|
|
707
|
+
this.parseAsync(i).then((m) => {
|
|
708
|
+
r && r(m);
|
|
709
|
+
}).catch((m) => {
|
|
710
|
+
a ? a(m) : console.error(m), this.manager.itemError(t);
|
|
514
711
|
});
|
|
515
712
|
},
|
|
516
|
-
|
|
517
|
-
|
|
713
|
+
s,
|
|
714
|
+
a
|
|
518
715
|
);
|
|
519
716
|
}
|
|
520
717
|
/**
|
|
@@ -523,19 +720,19 @@ class ze extends l.Loader {
|
|
|
523
720
|
* @param onProgress Optional progress callback
|
|
524
721
|
* @returns A Promise that resolves with the parsed SplatData
|
|
525
722
|
*/
|
|
526
|
-
loadAsync(
|
|
527
|
-
return new Promise((
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
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,
|
|
531
728
|
(i) => {
|
|
532
|
-
this.parseAsync(i).then(
|
|
533
|
-
|
|
729
|
+
this.parseAsync(i).then(s).catch((m) => {
|
|
730
|
+
a(m), this.manager.itemError(t);
|
|
534
731
|
});
|
|
535
732
|
},
|
|
536
|
-
|
|
733
|
+
r,
|
|
537
734
|
(i) => {
|
|
538
|
-
|
|
735
|
+
a(i), this.manager.itemError(t);
|
|
539
736
|
}
|
|
540
737
|
);
|
|
541
738
|
});
|
|
@@ -545,15 +742,15 @@ class ze extends l.Loader {
|
|
|
545
742
|
* @param buffer ArrayBuffer containing PLY data
|
|
546
743
|
* @returns Promise that resolves with parsed SplatData
|
|
547
744
|
*/
|
|
548
|
-
parseAsync(
|
|
549
|
-
return new Promise((
|
|
550
|
-
const
|
|
551
|
-
this.pendingCallbacks.set(
|
|
552
|
-
const
|
|
553
|
-
requestId:
|
|
554
|
-
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
|
|
555
752
|
};
|
|
556
|
-
this.worker.postMessage(
|
|
753
|
+
this.worker.postMessage(o, [t]);
|
|
557
754
|
});
|
|
558
755
|
}
|
|
559
756
|
/**
|
|
@@ -568,14 +765,14 @@ class ze extends l.Loader {
|
|
|
568
765
|
*/
|
|
569
766
|
createWorkerCode() {
|
|
570
767
|
return `(${(function() {
|
|
571
|
-
self.onmessage = (
|
|
572
|
-
const { requestId:
|
|
768
|
+
self.onmessage = (s) => {
|
|
769
|
+
const { requestId: a, buffer: o } = s.data;
|
|
573
770
|
try {
|
|
574
|
-
const i =
|
|
575
|
-
requestId:
|
|
771
|
+
const i = r(o), m = {
|
|
772
|
+
requestId: a,
|
|
576
773
|
result: i
|
|
577
774
|
};
|
|
578
|
-
self.postMessage(
|
|
775
|
+
self.postMessage(m, [
|
|
579
776
|
i.positions,
|
|
580
777
|
i.rotations,
|
|
581
778
|
i.scales,
|
|
@@ -583,215 +780,747 @@ class ze extends l.Loader {
|
|
|
583
780
|
i.opacities
|
|
584
781
|
]);
|
|
585
782
|
} catch (i) {
|
|
586
|
-
const
|
|
587
|
-
requestId:
|
|
783
|
+
const m = {
|
|
784
|
+
requestId: a,
|
|
588
785
|
error: i instanceof Error ? i.message : String(i)
|
|
589
786
|
};
|
|
590
|
-
self.postMessage(
|
|
787
|
+
self.postMessage(m);
|
|
591
788
|
}
|
|
592
789
|
};
|
|
593
|
-
function
|
|
594
|
-
const
|
|
790
|
+
function r(s) {
|
|
791
|
+
const a = new TextDecoder(), o = new Uint8Array(s), i = [112, 108, 121, 10], m = `
|
|
595
792
|
end_header
|
|
596
793
|
`;
|
|
597
|
-
for (let
|
|
598
|
-
if (
|
|
794
|
+
for (let I = 0; I < i.length; I++)
|
|
795
|
+
if (o[I] !== i[I])
|
|
599
796
|
throw new Error(
|
|
600
797
|
"Invalid PLY file: Missing magic bytes"
|
|
601
798
|
);
|
|
602
|
-
let
|
|
603
|
-
for (let
|
|
604
|
-
let
|
|
605
|
-
for (let
|
|
606
|
-
if (
|
|
607
|
-
|
|
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;
|
|
608
805
|
break;
|
|
609
806
|
}
|
|
610
|
-
if (
|
|
611
|
-
|
|
807
|
+
if (d) {
|
|
808
|
+
f = I + m.length;
|
|
612
809
|
break;
|
|
613
810
|
}
|
|
614
811
|
}
|
|
615
|
-
if (
|
|
812
|
+
if (f === 0)
|
|
616
813
|
throw new Error(
|
|
617
814
|
"Invalid PLY file: Could not find end of header"
|
|
618
815
|
);
|
|
619
|
-
const
|
|
620
|
-
|
|
816
|
+
const l = a.decode(
|
|
817
|
+
o.subarray(0, f)
|
|
621
818
|
).split(`
|
|
622
|
-
`),
|
|
623
|
-
let
|
|
624
|
-
for (let
|
|
625
|
-
const
|
|
626
|
-
if (
|
|
627
|
-
const
|
|
628
|
-
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]) {
|
|
629
826
|
case "format":
|
|
630
|
-
|
|
827
|
+
x = z[1];
|
|
631
828
|
break;
|
|
632
829
|
case "element":
|
|
633
|
-
|
|
634
|
-
name:
|
|
635
|
-
count: parseInt(
|
|
830
|
+
u.push({
|
|
831
|
+
name: z[1],
|
|
832
|
+
count: parseInt(z[2], 10),
|
|
636
833
|
properties: []
|
|
637
834
|
});
|
|
638
835
|
break;
|
|
639
836
|
case "property":
|
|
640
|
-
if (
|
|
837
|
+
if (u.length === 0)
|
|
641
838
|
throw new Error(
|
|
642
839
|
"Invalid PLY file: Property without element"
|
|
643
840
|
);
|
|
644
|
-
|
|
645
|
-
type:
|
|
646
|
-
name:
|
|
841
|
+
u[u.length - 1].properties.push({
|
|
842
|
+
type: z[1],
|
|
843
|
+
name: z[2]
|
|
647
844
|
});
|
|
648
845
|
break;
|
|
649
846
|
}
|
|
650
847
|
}
|
|
651
|
-
if (
|
|
652
|
-
throw new Error(`Unsupported PLY format: ${
|
|
653
|
-
const
|
|
654
|
-
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)
|
|
655
852
|
throw new Error(
|
|
656
853
|
"Invalid PLY file: No vertex element found"
|
|
657
854
|
);
|
|
658
|
-
const
|
|
659
|
-
let A =
|
|
660
|
-
const
|
|
661
|
-
(
|
|
662
|
-
),
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
],
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
],
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
],
|
|
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");
|
|
676
873
|
if ([
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
874
|
+
_,
|
|
875
|
+
w,
|
|
876
|
+
p,
|
|
680
877
|
...R,
|
|
681
|
-
...
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
].some((
|
|
878
|
+
...q,
|
|
879
|
+
...j,
|
|
880
|
+
Y
|
|
881
|
+
].some((I) => I === -1))
|
|
685
882
|
throw new Error(
|
|
686
883
|
"Invalid PLY file: Missing required properties"
|
|
687
884
|
);
|
|
688
|
-
const
|
|
689
|
-
if (
|
|
690
|
-
const
|
|
691
|
-
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);
|
|
692
889
|
};
|
|
693
|
-
let
|
|
694
|
-
for (let
|
|
695
|
-
const
|
|
696
|
-
for (let
|
|
697
|
-
const
|
|
698
|
-
let
|
|
699
|
-
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) {
|
|
700
897
|
case "char":
|
|
701
|
-
|
|
898
|
+
ce = L.getInt8(A), A += 1;
|
|
702
899
|
break;
|
|
703
900
|
case "uchar":
|
|
704
|
-
|
|
901
|
+
ce = L.getUint8(A), A += 1;
|
|
705
902
|
break;
|
|
706
903
|
case "short":
|
|
707
|
-
|
|
904
|
+
ce = L.getInt16(A, !0), A += 2;
|
|
708
905
|
break;
|
|
709
906
|
case "ushort":
|
|
710
|
-
|
|
907
|
+
ce = L.getUint16(A, !0), A += 2;
|
|
711
908
|
break;
|
|
712
909
|
case "int":
|
|
713
|
-
|
|
910
|
+
ce = L.getInt32(A, !0), A += 4;
|
|
714
911
|
break;
|
|
715
912
|
case "uint":
|
|
716
|
-
|
|
913
|
+
ce = L.getUint32(A, !0), A += 4;
|
|
717
914
|
break;
|
|
718
915
|
case "float":
|
|
719
|
-
|
|
916
|
+
ce = L.getFloat32(A, !0), A += 4;
|
|
720
917
|
break;
|
|
721
918
|
case "double":
|
|
722
|
-
|
|
919
|
+
ce = L.getFloat64(A, !0), A += 8;
|
|
723
920
|
break;
|
|
724
921
|
default:
|
|
725
922
|
throw new Error(
|
|
726
|
-
`Unsupported property type: ${
|
|
923
|
+
`Unsupported property type: ${ze}`
|
|
727
924
|
);
|
|
728
925
|
}
|
|
729
|
-
|
|
926
|
+
d.push(ce);
|
|
730
927
|
}
|
|
731
|
-
const
|
|
732
|
-
|
|
733
|
-
let
|
|
734
|
-
const
|
|
735
|
-
|
|
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
|
|
736
933
|
);
|
|
737
|
-
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
const
|
|
741
|
-
|
|
742
|
-
let
|
|
743
|
-
|
|
744
|
-
const
|
|
745
|
-
|
|
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]);
|
|
746
943
|
}
|
|
747
944
|
return {
|
|
748
|
-
numSplats:
|
|
749
|
-
positions:
|
|
750
|
-
rotations:
|
|
751
|
-
scales:
|
|
752
|
-
colors:
|
|
753
|
-
opacities:
|
|
945
|
+
numSplats: v,
|
|
946
|
+
positions: b.buffer,
|
|
947
|
+
rotations: E.buffer,
|
|
948
|
+
scales: T.buffer,
|
|
949
|
+
colors: P.buffer,
|
|
950
|
+
opacities: H.buffer,
|
|
754
951
|
boundingBox: {
|
|
755
|
-
minX:
|
|
756
|
-
minY:
|
|
757
|
-
minZ:
|
|
758
|
-
maxX:
|
|
759
|
-
maxY:
|
|
760
|
-
maxZ:
|
|
952
|
+
minX: J,
|
|
953
|
+
minY: N,
|
|
954
|
+
minZ: c,
|
|
955
|
+
maxX: k,
|
|
956
|
+
maxY: B,
|
|
957
|
+
maxZ: F
|
|
761
958
|
}
|
|
762
959
|
};
|
|
763
960
|
}
|
|
764
961
|
}).toString()})();`;
|
|
765
962
|
}
|
|
766
963
|
}
|
|
767
|
-
|
|
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 {
|
|
768
1497
|
constructor() {
|
|
769
1498
|
super();
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
1499
|
+
M(this, "worker");
|
|
1500
|
+
M(this, "centers", null);
|
|
1501
|
+
M(this, "orderTexture", null);
|
|
773
1502
|
/** Bounding box data for optimization */
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
const
|
|
778
|
-
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);
|
|
779
1508
|
}
|
|
780
1509
|
/**
|
|
781
1510
|
* Handles messages received from the sorting worker.
|
|
782
1511
|
* @param event The message event from the worker.
|
|
783
1512
|
*/
|
|
784
|
-
onWorkerMessage(
|
|
1513
|
+
onWorkerMessage(t) {
|
|
785
1514
|
if (!this.orderTexture || !this.orderTexture.image)
|
|
786
1515
|
return console.error("SplatSorter: Order texture not initialized!");
|
|
787
|
-
const { order:
|
|
788
|
-
if (!(
|
|
1516
|
+
const { order: r, count: s } = t.data, a = this.orderTexture.image.data;
|
|
1517
|
+
if (!(a instanceof Uint32Array))
|
|
789
1518
|
return console.error(
|
|
790
1519
|
"SplatSorter: Order texture data is not a Uint32Array!"
|
|
791
1520
|
);
|
|
792
|
-
|
|
793
|
-
const
|
|
794
|
-
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 });
|
|
795
1524
|
}
|
|
796
1525
|
/**
|
|
797
1526
|
* Initializes the sorter with necessary data and textures.
|
|
@@ -800,38 +1529,38 @@ class Pe extends l.EventDispatcher {
|
|
|
800
1529
|
* @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
|
|
801
1530
|
* @param transferOwnership Optional: If true, transfers ownership of centers buffer to worker (saves memory, main thread loses access). Default: false.
|
|
802
1531
|
*/
|
|
803
|
-
init(
|
|
804
|
-
if (!
|
|
1532
|
+
init(t, r, s, a = !1) {
|
|
1533
|
+
if (!t || !(t.image.data instanceof Uint32Array))
|
|
805
1534
|
throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
|
|
806
|
-
if (!
|
|
1535
|
+
if (!r || r.length % 3 !== 0)
|
|
807
1536
|
throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");
|
|
808
|
-
if (
|
|
1537
|
+
if (t.image.data.length < r.length / 3)
|
|
809
1538
|
throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
|
|
810
|
-
if (
|
|
1539
|
+
if (r.buffer.byteLength === 0)
|
|
811
1540
|
throw new Error(
|
|
812
1541
|
"SplatSorter: positions buffer is detached (likely React StrictMode + cached asset). "
|
|
813
1542
|
);
|
|
814
|
-
const
|
|
815
|
-
this.orderTexture =
|
|
1543
|
+
const o = r.length / 3;
|
|
1544
|
+
this.orderTexture = t, a ? this.centers = null : this.centers = r.slice();
|
|
816
1545
|
const i = this.orderTexture.image.data;
|
|
817
|
-
for (let
|
|
1546
|
+
for (let u = 0; u < o; u++) i[u] = u;
|
|
818
1547
|
this.orderTexture.source.data.updateRanges || (this.orderTexture.source.data.updateRanges = []), this.orderTexture.needsUpdate = !0;
|
|
819
|
-
const
|
|
820
|
-
order:
|
|
821
|
-
centers:
|
|
822
|
-
},
|
|
823
|
-
|
|
824
|
-
|
|
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
|
|
825
1554
|
];
|
|
826
|
-
if (
|
|
827
|
-
this.chunks =
|
|
828
|
-
const
|
|
829
|
-
|
|
1555
|
+
if (s) {
|
|
1556
|
+
this.chunks = s.slice();
|
|
1557
|
+
const u = this.chunks.buffer.slice(0);
|
|
1558
|
+
y.chunks = u, l.push(u);
|
|
830
1559
|
}
|
|
831
|
-
this.worker.postMessage(
|
|
1560
|
+
this.worker.postMessage(y, l), queueMicrotask(() => {
|
|
832
1561
|
this.dispatchEvent({
|
|
833
1562
|
type: "updated",
|
|
834
|
-
count:
|
|
1563
|
+
count: o
|
|
835
1564
|
});
|
|
836
1565
|
});
|
|
837
1566
|
}
|
|
@@ -840,53 +1569,53 @@ class Pe extends l.EventDispatcher {
|
|
|
840
1569
|
* The sorter will only consider splats whose original indices are present in the mapping.
|
|
841
1570
|
* @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
|
|
842
1571
|
*/
|
|
843
|
-
setMapping(
|
|
1572
|
+
setMapping(t) {
|
|
844
1573
|
if (!this.centers)
|
|
845
1574
|
return console.warn(
|
|
846
1575
|
"SplatSorter: Cannot set mapping before initialization."
|
|
847
1576
|
);
|
|
848
|
-
let
|
|
849
|
-
const
|
|
850
|
-
if (!
|
|
851
|
-
const
|
|
852
|
-
return
|
|
853
|
-
centers:
|
|
1577
|
+
let r;
|
|
1578
|
+
const s = [];
|
|
1579
|
+
if (!t) {
|
|
1580
|
+
const m = this.centers.buffer.slice(0);
|
|
1581
|
+
return r = {
|
|
1582
|
+
centers: m,
|
|
854
1583
|
mapping: null
|
|
855
|
-
},
|
|
1584
|
+
}, s.push(m), this.worker.postMessage(r, s);
|
|
856
1585
|
}
|
|
857
|
-
const
|
|
858
|
-
for (let
|
|
859
|
-
const
|
|
860
|
-
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) {
|
|
861
1590
|
console.warn(
|
|
862
|
-
`SplatSorter: Mapping index ${
|
|
1591
|
+
`SplatSorter: Mapping index ${f} out of bounds.`
|
|
863
1592
|
);
|
|
864
1593
|
continue;
|
|
865
1594
|
}
|
|
866
|
-
const
|
|
867
|
-
|
|
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];
|
|
868
1597
|
}
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
centers:
|
|
1598
|
+
const o = a.buffer.slice(0), i = t.buffer.slice(0);
|
|
1599
|
+
r = {
|
|
1600
|
+
centers: o,
|
|
872
1601
|
mapping: i
|
|
873
|
-
},
|
|
1602
|
+
}, s.push(o, i), this.worker.postMessage(r, s);
|
|
874
1603
|
}
|
|
875
1604
|
/**
|
|
876
1605
|
* Updates the camera parameters used for sorting.
|
|
877
1606
|
* @param position The camera's position in the sorter's local coordinate space.
|
|
878
1607
|
* @param direction The camera's forward direction in the sorter's local coordinate space.
|
|
879
1608
|
*/
|
|
880
|
-
setCamera(
|
|
881
|
-
const
|
|
882
|
-
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)
|
|
883
1612
|
return;
|
|
884
|
-
this.lastCameraPosition.copy(
|
|
885
|
-
const
|
|
886
|
-
cameraPosition: { x:
|
|
887
|
-
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 }
|
|
888
1617
|
};
|
|
889
|
-
this.worker.postMessage(
|
|
1618
|
+
this.worker.postMessage(o);
|
|
890
1619
|
}
|
|
891
1620
|
/**
|
|
892
1621
|
* Terminates the Web Worker and cleans up resources.
|
|
@@ -900,258 +1629,186 @@ class Pe extends l.EventDispatcher {
|
|
|
900
1629
|
*/
|
|
901
1630
|
createWorkerCode() {
|
|
902
1631
|
return `(${(function() {
|
|
903
|
-
let
|
|
904
|
-
const
|
|
905
|
-
let
|
|
906
|
-
const
|
|
907
|
-
for (; A <=
|
|
908
|
-
const
|
|
909
|
-
if (
|
|
910
|
-
else if (
|
|
911
|
-
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;
|
|
912
1641
|
}
|
|
913
1642
|
return ~A;
|
|
914
1643
|
}, L = () => {
|
|
915
|
-
if (!
|
|
1644
|
+
if (!r || !s || !i || !m)
|
|
916
1645
|
return;
|
|
917
|
-
if (
|
|
918
|
-
const
|
|
919
|
-
order:
|
|
1646
|
+
if (s.length === 0) {
|
|
1647
|
+
const d = {
|
|
1648
|
+
order: r.buffer,
|
|
920
1649
|
count: 0
|
|
921
1650
|
};
|
|
922
|
-
self.postMessage(
|
|
1651
|
+
self.postMessage(d, [r.buffer]), r = null;
|
|
923
1652
|
return;
|
|
924
1653
|
}
|
|
925
|
-
const A = i.x,
|
|
926
|
-
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)
|
|
927
1656
|
return;
|
|
928
|
-
|
|
929
|
-
let
|
|
930
|
-
for (let
|
|
931
|
-
const
|
|
932
|
-
|
|
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);
|
|
933
1662
|
}
|
|
934
|
-
const
|
|
1663
|
+
const O = s.length / 3, J = D - V, c = (1 << Math.max(
|
|
935
1664
|
10,
|
|
936
|
-
Math.min(20, Math.ceil(Math.log2(
|
|
1665
|
+
Math.min(20, Math.ceil(Math.log2(O / 4)))
|
|
937
1666
|
)) + 1;
|
|
938
|
-
if ((!
|
|
939
|
-
for (let
|
|
940
|
-
|
|
941
|
-
} else if (
|
|
942
|
-
const
|
|
943
|
-
|
|
944
|
-
for (let
|
|
945
|
-
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(
|
|
946
1675
|
0,
|
|
947
|
-
Math.floor(
|
|
948
|
-
),
|
|
949
|
-
|
|
950
|
-
Math.ceil(
|
|
1676
|
+
Math.floor(re * b / J)
|
|
1677
|
+
), he = Math.min(
|
|
1678
|
+
b,
|
|
1679
|
+
Math.ceil(se * b / J)
|
|
951
1680
|
);
|
|
952
|
-
for (let
|
|
953
|
-
|
|
1681
|
+
for (let oe = ue; oe < he; ++oe)
|
|
1682
|
+
E[oe]++;
|
|
954
1683
|
}
|
|
955
|
-
let
|
|
956
|
-
for (let
|
|
957
|
-
|
|
958
|
-
for (let
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
const
|
|
962
|
-
for (let
|
|
963
|
-
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(
|
|
964
1693
|
0,
|
|
965
1694
|
Math.min(
|
|
966
|
-
|
|
967
|
-
Math.floor(
|
|
1695
|
+
b - 1,
|
|
1696
|
+
Math.floor(re)
|
|
968
1697
|
)
|
|
969
|
-
),
|
|
970
|
-
S
|
|
1698
|
+
), ue = re - se, he = T[se] + P[se] * ue >>> 0, oe = Math.min(he, c - 1);
|
|
1699
|
+
g[S] = oe, v[oe]++;
|
|
971
1700
|
}
|
|
972
1701
|
} else {
|
|
973
|
-
const
|
|
974
|
-
for (let
|
|
975
|
-
const
|
|
976
|
-
|
|
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]++;
|
|
977
1706
|
}
|
|
978
1707
|
}
|
|
979
|
-
for (let
|
|
980
|
-
|
|
981
|
-
for (let
|
|
982
|
-
const
|
|
983
|
-
|
|
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;
|
|
984
1713
|
}
|
|
985
|
-
const
|
|
986
|
-
if (!
|
|
987
|
-
const
|
|
988
|
-
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)
|
|
989
1718
|
return -1 / 0;
|
|
990
|
-
const
|
|
991
|
-
return
|
|
1719
|
+
const S = W * 3;
|
|
1720
|
+
return s[S] * w + s[S + 1] * p + s[S + 2] * R - k;
|
|
992
1721
|
};
|
|
993
|
-
let
|
|
994
|
-
if (
|
|
995
|
-
const
|
|
1722
|
+
let F = O;
|
|
1723
|
+
if (O > 0 && B(O - 1) < 0) {
|
|
1724
|
+
const d = H(
|
|
996
1725
|
0,
|
|
997
|
-
|
|
998
|
-
|
|
1726
|
+
O - 1,
|
|
1727
|
+
B
|
|
999
1728
|
);
|
|
1000
|
-
|
|
1729
|
+
F = d < 0 ? ~d : d;
|
|
1001
1730
|
}
|
|
1002
|
-
const
|
|
1003
|
-
order:
|
|
1004
|
-
count:
|
|
1731
|
+
const I = {
|
|
1732
|
+
order: r.buffer,
|
|
1733
|
+
count: F
|
|
1005
1734
|
};
|
|
1006
|
-
self.postMessage(
|
|
1735
|
+
self.postMessage(I, [r.buffer]), r = null;
|
|
1007
1736
|
};
|
|
1008
1737
|
self.onmessage = (A) => {
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
let
|
|
1012
|
-
if (
|
|
1013
|
-
if (
|
|
1014
|
-
for (let
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1017
|
-
(
|
|
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
|
|
1018
1747
|
) * 0.5;
|
|
1019
1748
|
}
|
|
1020
|
-
|
|
1749
|
+
f = !0;
|
|
1021
1750
|
}
|
|
1022
|
-
if (
|
|
1023
|
-
|
|
1024
|
-
for (let
|
|
1025
|
-
const
|
|
1026
|
-
|
|
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]);
|
|
1027
1756
|
}
|
|
1028
|
-
} else
|
|
1029
|
-
|
|
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();
|
|
1030
1759
|
};
|
|
1031
1760
|
}).toString()})();`;
|
|
1032
1761
|
}
|
|
1033
1762
|
}
|
|
1034
|
-
|
|
1035
|
-
const o = ye(x), t = ye(e);
|
|
1036
|
-
return o | t << 16;
|
|
1037
|
-
};
|
|
1038
|
-
function ye(x) {
|
|
1039
|
-
const e = new Float32Array([x]), t = new Int32Array(e.buffer)[0];
|
|
1040
|
-
let r = t >> 16 & 32768, n = t >> 12 & 2047;
|
|
1041
|
-
const a = t >> 23 & 255;
|
|
1042
|
-
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);
|
|
1043
|
-
}
|
|
1044
|
-
const Fe = new ArrayBuffer(4), ve = new DataView(Fe), Oe = (x) => (ve.setUint32(0, x, !0), ve.getFloat32(0, !0));
|
|
1045
|
-
class De {
|
|
1046
|
-
/**
|
|
1047
|
-
* Create a new TextureManager for a set of splats
|
|
1048
|
-
* @param splatData The splat data to manage textures for
|
|
1049
|
-
*/
|
|
1763
|
+
class kt {
|
|
1050
1764
|
constructor(e) {
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
//
|
|
1055
|
-
|
|
1056
|
-
//
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
const o = e.numSplats;
|
|
1061
|
-
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);
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* Create the transform A texture (positions and quaternion w component)
|
|
1065
|
-
* @param splatData The splat data
|
|
1066
|
-
* @returns DataTexture containing position data
|
|
1067
|
-
*/
|
|
1068
|
-
createTransformATexture(e) {
|
|
1069
|
-
const o = e.numSplats, t = new Float32Array(
|
|
1070
|
-
this.textureWidth * this.textureHeight * 4
|
|
1071
|
-
);
|
|
1072
|
-
for (let n = 0; n < o; n++) {
|
|
1073
|
-
const a = n * 4, i = n * 3, u = n * 4;
|
|
1074
|
-
t[a] = e.positions[i], t[a + 1] = e.positions[i + 1], t[a + 2] = e.positions[i + 2];
|
|
1075
|
-
const w = e.rotations[u + 0], C = e.rotations[u + 1], _ = Be(w, C);
|
|
1076
|
-
t[a + 3] = Oe(_);
|
|
1077
|
-
}
|
|
1078
|
-
const r = new l.DataTexture(
|
|
1079
|
-
t,
|
|
1080
|
-
this.textureWidth,
|
|
1081
|
-
this.textureHeight,
|
|
1082
|
-
l.RGBAFormat,
|
|
1083
|
-
l.FloatType
|
|
1084
|
-
// Store as Float32, shader will reinterpret bits
|
|
1085
|
-
);
|
|
1086
|
-
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);
|
|
1087
1774
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
this.textureWidth * this.textureHeight * 4
|
|
1096
|
-
);
|
|
1097
|
-
for (let n = 0; n < o; n++) {
|
|
1098
|
-
const a = n * 4, i = n * 3, u = n * 4;
|
|
1099
|
-
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];
|
|
1100
|
-
}
|
|
1101
|
-
const r = new l.DataTexture(
|
|
1102
|
-
t,
|
|
1103
|
-
this.textureWidth,
|
|
1104
|
-
this.textureHeight,
|
|
1105
|
-
l.RGBAFormat,
|
|
1106
|
-
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
|
|
1107
1782
|
);
|
|
1108
|
-
return
|
|
1783
|
+
return t.internalFormat = "RGBA32UI", t.minFilter = h.NearestFilter, t.magFilter = h.NearestFilter, t.needsUpdate = !0, t;
|
|
1109
1784
|
}
|
|
1110
|
-
/**
|
|
1111
|
-
* Create the color texture (RGB and opacity)
|
|
1112
|
-
* @param splatData The splat data
|
|
1113
|
-
* @returns DataTexture containing color data
|
|
1114
|
-
*/
|
|
1115
1785
|
createColorTexture(e) {
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
}
|
|
1123
|
-
const r = new l.DataTexture(
|
|
1124
|
-
t,
|
|
1125
|
-
this.textureWidth,
|
|
1126
|
-
this.textureHeight,
|
|
1127
|
-
l.RGBAFormat,
|
|
1128
|
-
l.FloatType
|
|
1786
|
+
const t = new h.DataTexture(
|
|
1787
|
+
e.packedColor,
|
|
1788
|
+
this.width,
|
|
1789
|
+
this.height,
|
|
1790
|
+
h.RGBAFormat,
|
|
1791
|
+
h.UnsignedByteType
|
|
1129
1792
|
);
|
|
1130
|
-
return
|
|
1793
|
+
return t.minFilter = h.NearestFilter, t.magFilter = h.NearestFilter, t.needsUpdate = !0, t;
|
|
1131
1794
|
}
|
|
1132
|
-
/**
|
|
1133
|
-
* Create the order texture for sorting
|
|
1134
|
-
* @param numSplats Number of splats
|
|
1135
|
-
* @returns DataTexture for storing order indices
|
|
1136
|
-
*/
|
|
1137
1795
|
createOrderTexture(e) {
|
|
1138
|
-
const
|
|
1139
|
-
for (let
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
this.
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
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
|
|
1147
1804
|
);
|
|
1148
|
-
return
|
|
1805
|
+
return r.minFilter = h.NearestFilter, r.magFilter = h.NearestFilter, r.needsUpdate = !0, r;
|
|
1149
1806
|
}
|
|
1150
1807
|
dispose() {
|
|
1151
|
-
this.
|
|
1808
|
+
this.packedGeometry.dispose(), this.packedColor.dispose(), this.orderTexture.dispose();
|
|
1152
1809
|
}
|
|
1153
1810
|
}
|
|
1154
|
-
const
|
|
1811
|
+
const Et = (
|
|
1155
1812
|
/* glsl */
|
|
1156
1813
|
`
|
|
1157
1814
|
precision highp float;
|
|
@@ -1159,55 +1816,47 @@ precision highp int;
|
|
|
1159
1816
|
precision highp usampler2D;
|
|
1160
1817
|
precision highp sampler2D;
|
|
1161
1818
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
uniform vec2 viewport; // Viewport dimensions (width, height)
|
|
1166
|
-
uniform uint numSplats; // Total number of splats potentially renderable by sorter
|
|
1819
|
+
uniform int texWidth;
|
|
1820
|
+
uniform vec2 viewport;
|
|
1821
|
+
uniform uint numSplats;
|
|
1167
1822
|
|
|
1168
|
-
// Textures
|
|
1169
|
-
uniform
|
|
1170
|
-
uniform
|
|
1171
|
-
uniform
|
|
1172
|
-
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
|
|
1173
1827
|
|
|
1174
|
-
// ---
|
|
1175
|
-
|
|
1176
|
-
|
|
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;
|
|
1177
1835
|
|
|
1178
|
-
//
|
|
1179
|
-
|
|
1180
|
-
// position.xy: corner coords (-1..1)
|
|
1181
|
-
// position.z: index within the instance block (0..INSTANCE_BUFFER_SIZE-1)
|
|
1836
|
+
// --- Attributes ---
|
|
1837
|
+
in uint splatInstanceIndex;
|
|
1182
1838
|
|
|
1183
|
-
// ---
|
|
1184
|
-
|
|
1185
|
-
|
|
1839
|
+
// --- Outputs ---
|
|
1840
|
+
out vec4 vColor;
|
|
1841
|
+
out vec2 vUv;
|
|
1186
1842
|
|
|
1187
1843
|
// --- Constants ---
|
|
1188
|
-
|
|
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)
|
|
1189
1847
|
|
|
1190
1848
|
// --- Helper Functions ---
|
|
1191
1849
|
|
|
1192
|
-
//
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
// Returns (w,x,y,z) format for quatToMat3 compatibility
|
|
1196
|
-
vec4 unpackRotation(float xy_packed, float z) {
|
|
1197
|
-
vec2 xy = unpackHalf2x16(floatBitsToUint(xy_packed));
|
|
1198
|
-
float x = xy.x;
|
|
1199
|
-
float y = xy.y;
|
|
1200
|
-
float w_squared = 1.0 - x*x - y*y - z*z;
|
|
1201
|
-
float w = (w_squared < 0.0) ? 0.0 : sqrt(w_squared);
|
|
1202
|
-
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;
|
|
1203
1853
|
}
|
|
1204
1854
|
|
|
1205
|
-
// Convert quaternion to 3x3 rotation matrix
|
|
1206
1855
|
mat3 quatToMat3(vec4 R) {
|
|
1207
1856
|
vec4 R2 = R + R;
|
|
1208
1857
|
float X = R2.x * R.w;
|
|
1209
|
-
vec4 Y
|
|
1210
|
-
vec4 Z
|
|
1858
|
+
vec4 Y = R2.y * R;
|
|
1859
|
+
vec4 Z = R2.z * R;
|
|
1211
1860
|
float W = R2.w * R.w;
|
|
1212
1861
|
|
|
1213
1862
|
return mat3(
|
|
@@ -1223,199 +1872,176 @@ mat3 quatToMat3(vec4 R) {
|
|
|
1223
1872
|
);
|
|
1224
1873
|
}
|
|
1225
1874
|
|
|
1226
|
-
// Calculate model-space covariance components
|
|
1227
1875
|
void getModelCovariance(vec3 scale, vec4 rotation, out vec3 covA, out vec3 covB) {
|
|
1228
1876
|
mat3 rot = quatToMat3(rotation);
|
|
1229
|
-
|
|
1230
|
-
// M = S * R (scale COLUMNS, then transpose)
|
|
1231
1877
|
mat3 M = transpose(mat3(
|
|
1232
|
-
scale.x * rot[0],
|
|
1233
|
-
scale.y * rot[1],
|
|
1234
|
-
scale.z * rot[2]
|
|
1878
|
+
scale.x * rot[0],
|
|
1879
|
+
scale.y * rot[1],
|
|
1880
|
+
scale.z * rot[2]
|
|
1235
1881
|
));
|
|
1236
1882
|
|
|
1237
1883
|
covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));
|
|
1238
1884
|
covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));
|
|
1239
1885
|
}
|
|
1240
1886
|
|
|
1241
|
-
// --- Main
|
|
1242
|
-
void main(
|
|
1243
|
-
// Calculate
|
|
1244
|
-
uint instanceOffset = uint(position.z);
|
|
1245
|
-
uint
|
|
1887
|
+
// --- Main ---
|
|
1888
|
+
void main() {
|
|
1889
|
+
// Calculate Instance ID & Source Data UV
|
|
1890
|
+
uint instanceOffset = uint(position.z);
|
|
1891
|
+
uint orderIndex = splatInstanceIndex + instanceOffset;
|
|
1246
1892
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Off-screen
|
|
1893
|
+
if (orderIndex >= numSplats) {
|
|
1894
|
+
gl_Position = DISCARD_VERTEX;
|
|
1250
1895
|
return;
|
|
1251
1896
|
}
|
|
1252
1897
|
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
ivec2 orderUV = ivec2(orderedSplatIndex % texWidth, orderedSplatIndex / texWidth);
|
|
1256
|
-
uint originalSplatIndex = texelFetch(splatOrder, orderUV, 0).r;
|
|
1898
|
+
uint w = uint(texWidth);
|
|
1899
|
+
ivec2 orderUV = ivec2(int(orderIndex % w), int(orderIndex / w));
|
|
1257
1900
|
|
|
1258
|
-
|
|
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));
|
|
1259
1904
|
|
|
1260
|
-
// Fetch
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
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);
|
|
1264
1909
|
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
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;
|
|
1270
1914
|
|
|
1271
|
-
|
|
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);
|
|
1272
1918
|
|
|
1273
|
-
//
|
|
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
|
|
1274
1924
|
|
|
1275
|
-
// Compute normalized view-space center
|
|
1276
|
-
vec4 centerClipRaw = modelViewMatrix * vec4(splatPosition, 1.0);
|
|
1277
|
-
vec3 centerView = centerClipRaw.xyz / centerClipRaw.w;
|
|
1278
1925
|
|
|
1279
|
-
//
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
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)
|
|
1284
1933
|
|
|
1285
|
-
//
|
|
1286
|
-
|
|
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
|
|
1287
1939
|
|
|
1288
|
-
//
|
|
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)
|
|
1289
1945
|
|
|
1290
|
-
//
|
|
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
|
|
1291
1959
|
vec3 covA, covB;
|
|
1292
|
-
getModelCovariance(
|
|
1293
|
-
mat3 Vrk = mat3(
|
|
1294
|
-
covA.x, covA.y, covA.z,
|
|
1295
|
-
covA.y, covB.x, covB.y, // covB.x is Vrk[1][1]
|
|
1296
|
-
covA.z, covB.y, covB.z // covB.y is Vrk[1][2], covB.z is Vrk[2][2]
|
|
1297
|
-
);
|
|
1960
|
+
getModelCovariance(scale, quat, covA, covB);
|
|
1298
1961
|
|
|
1299
|
-
//
|
|
1300
|
-
// Requres focal lenghts and view-space center depth (tz)
|
|
1962
|
+
// Project to 2D
|
|
1301
1963
|
float focalX = viewport.x * projectionMatrix[0][0];
|
|
1302
1964
|
float focalY = viewport.y * projectionMatrix[1][1];
|
|
1303
|
-
float
|
|
1304
|
-
|
|
1965
|
+
float J1 = focalX / centerView.z;
|
|
1966
|
+
vec2 J2 = -J1 / centerView.z * centerView.xy;
|
|
1305
1967
|
|
|
1306
|
-
// Jacobian J = [fx/tz, 0, -fx*tx/tz^2]
|
|
1307
|
-
// [0, fy/tz, -fy*ty/tz^2]
|
|
1308
1968
|
mat3 J = mat3(
|
|
1309
|
-
|
|
1310
|
-
0.0,
|
|
1311
|
-
0.0,
|
|
1969
|
+
J1, 0.0, J2.x,
|
|
1970
|
+
0.0, J1, J2.y,
|
|
1971
|
+
0.0, 0.0, 0.0
|
|
1312
1972
|
);
|
|
1313
1973
|
|
|
1314
|
-
|
|
1315
|
-
mat3 W = transpose(mat3(modelViewMatrix));
|
|
1316
|
-
// Calculate T = W * J
|
|
1974
|
+
mat3 W = transpose(mat3(modelView));
|
|
1317
1975
|
mat3 T = W * J;
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
float cov2D_22 = SigmaProj[1][1] + 0.3;
|
|
1325
|
-
|
|
1326
|
-
// --- Calculate 2D Screen Space Rotation & Scale ---
|
|
1327
|
-
|
|
1328
|
-
float det = cov2D_11 * cov2D_22 - cov2D_12 * cov2D_12;
|
|
1329
|
-
// Ensure determinant is non-negative before sqrt
|
|
1330
|
-
if (det <= 0.0) {
|
|
1331
|
-
gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // Discard degenerated
|
|
1332
|
-
return;
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
|
-
float trace = cov2D_11 + cov2D_22;
|
|
1336
|
-
float traceOver2 = 0.5 * trace;
|
|
1337
|
-
float discriminantSqrt = sqrt(max(traceOver2 * traceOver2 - det, 0.0)); // Avoid sqrt(negative)
|
|
1338
|
-
|
|
1339
|
-
float lambda1 = traceOver2 + discriminantSqrt; // Larger eigenvalue
|
|
1340
|
-
float lambda2 = max(0.1, traceOver2 - discriminantSqrt); // Smaller eigenvalue, clamped
|
|
1341
|
-
|
|
1342
|
-
// Compute eigenvectors
|
|
1343
|
-
|
|
1344
|
-
vec2 v1_eigen, v2_eigen;
|
|
1345
|
-
|
|
1346
|
-
// Handle diagonal case
|
|
1347
|
-
if(abs(cov2D_12) < 1e-16) {
|
|
1348
|
-
v1_eigen = vec2(1.0, 0.0);
|
|
1349
|
-
} else {
|
|
1350
|
-
v1_eigen = normalize(vec2(cov2D_12, lambda1 - cov2D_11)); // diagonal choice
|
|
1351
|
-
}
|
|
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;
|
|
1352
1982
|
|
|
1353
|
-
|
|
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;
|
|
1354
1987
|
|
|
1355
|
-
|
|
1356
|
-
float
|
|
1357
|
-
float
|
|
1358
|
-
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);
|
|
1359
1992
|
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
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);
|
|
1363
1997
|
|
|
1364
|
-
//
|
|
1365
|
-
if (l1 < 2.0 && l2 < 2.0) {
|
|
1366
|
-
|
|
1367
|
-
|
|
1998
|
+
// Discard tiny splats
|
|
1999
|
+
if (l1 < 2.0 && l2 < 2.0) {
|
|
2000
|
+
gl_Position = DISCARD_VERTEX;
|
|
2001
|
+
return;
|
|
1368
2002
|
}
|
|
1369
2003
|
|
|
1370
|
-
|
|
1371
|
-
vec2
|
|
1372
|
-
vec2
|
|
2004
|
+
vec2 diagVec = normalize(vec2(offDiagonal, lambda1 - diagonal1));
|
|
2005
|
+
vec2 v1 = l1 * diagVec;
|
|
2006
|
+
vec2 v2 = l2 * vec2(diagVec.y, -diagVec.x);
|
|
1373
2007
|
|
|
1374
|
-
//
|
|
1375
|
-
|
|
1376
|
-
vec2 c =
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
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;
|
|
1382
2015
|
return;
|
|
1383
2016
|
}
|
|
1384
2017
|
|
|
1385
|
-
//
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
// Apply clip to the corner offset *before* calculating screen space offset
|
|
1396
|
-
vec2 clippedCornerOffset = cornerOffset * clip;
|
|
1397
|
-
vec2 screenOffsetPixels = clippedCornerOffset.x * v1_scaled + clippedCornerOffset.y * v2_scaled;
|
|
1398
|
-
|
|
1399
|
-
// Convert pixel offset to clip space offset
|
|
1400
|
-
vec2 clipOffset = screenOffsetPixels * (centerClip.w / viewport);
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
// Apply offset to center clip position
|
|
1404
|
-
gl_Position = centerClip + vec4(clipOffset, 0.0, 0.0);
|
|
1405
|
-
|
|
1406
|
-
// --- 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;
|
|
1407
2028
|
|
|
1408
|
-
|
|
1409
|
-
|
|
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);
|
|
1410
2034
|
}
|
|
1411
2035
|
`
|
|
1412
|
-
),
|
|
2036
|
+
), Ct = (
|
|
1413
2037
|
/* glsl */
|
|
1414
2038
|
`
|
|
1415
2039
|
precision highp float;
|
|
1416
2040
|
|
|
1417
|
-
|
|
1418
|
-
|
|
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
|
|
1419
2045
|
|
|
1420
2046
|
// Fast approximate e^x based on https://nic.schraudolph.org/pubs/Schraudolph99.pdf
|
|
1421
2047
|
const float EXP_A = 12102203.0; // ≈ 2^23 / ln(2)
|
|
@@ -1439,88 +2065,86 @@ void main(void) {
|
|
|
1439
2065
|
if (alpha < 1.0 / 255.0) discard; // Discard fragments with very low alpha
|
|
1440
2066
|
|
|
1441
2067
|
// Premultiply color by alpha (required for correct blending)
|
|
1442
|
-
|
|
2068
|
+
fragColor = vec4(vColor.rgb * alpha, alpha);
|
|
1443
2069
|
}
|
|
1444
2070
|
`
|
|
1445
2071
|
);
|
|
1446
|
-
class
|
|
2072
|
+
class It extends h.ShaderMaterial {
|
|
1447
2073
|
constructor(e = {}) {
|
|
1448
|
-
const
|
|
1449
|
-
// Textures
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
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
|
|
1453
2080
|
splatOrder: { value: null },
|
|
1454
|
-
//
|
|
1455
|
-
|
|
1456
|
-
|
|
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) },
|
|
1457
2092
|
numSplats: { value: 0 }
|
|
1458
|
-
// Max splats to render (updated by sorter)
|
|
1459
2093
|
};
|
|
1460
2094
|
super({
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
2095
|
+
uniforms: t,
|
|
2096
|
+
vertexShader: Et,
|
|
2097
|
+
fragmentShader: Ct,
|
|
1464
2098
|
transparent: !0,
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
blendDst:
|
|
1472
|
-
|
|
1473
|
-
// source alpha comes from shader
|
|
1474
|
-
blendDstAlpha: l.OneMinusSrcAlphaFactor,
|
|
1475
|
-
blendEquation: l.AddEquation,
|
|
1476
|
-
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,
|
|
1477
2107
|
depthTest: !0,
|
|
1478
2108
|
depthWrite: !1,
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
// prettier-ignore
|
|
1487
|
-
}), 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;
|
|
1488
2116
|
}
|
|
1489
2117
|
/**
|
|
1490
2118
|
* Update the viewport size
|
|
1491
2119
|
* @param width Viewport width
|
|
1492
2120
|
* @param height Viewport height
|
|
1493
2121
|
*/
|
|
1494
|
-
updateViewport(e,
|
|
1495
|
-
this.uniforms.viewport.value.set(e,
|
|
2122
|
+
updateViewport(e, t) {
|
|
2123
|
+
this.uniforms.viewport.value.set(e, t);
|
|
1496
2124
|
}
|
|
1497
2125
|
/**
|
|
1498
|
-
* Set
|
|
1499
|
-
* @param texture Texture containing positions
|
|
2126
|
+
* Set the main packed geometry texture (RGBA32UI)
|
|
1500
2127
|
*/
|
|
1501
|
-
|
|
1502
|
-
this.uniforms.
|
|
2128
|
+
setPackedGeometry(e) {
|
|
2129
|
+
this.uniforms.packedGeometry.value = e;
|
|
1503
2130
|
}
|
|
1504
2131
|
/**
|
|
1505
|
-
* Set
|
|
1506
|
-
* @param texture Texture containing rotation and scale data
|
|
2132
|
+
* Set the packed color texture (RGBA8)
|
|
1507
2133
|
*/
|
|
1508
|
-
|
|
1509
|
-
this.uniforms.
|
|
2134
|
+
setPackedColor(e) {
|
|
2135
|
+
this.uniforms.packedColor.value = e;
|
|
1510
2136
|
}
|
|
1511
2137
|
/**
|
|
1512
|
-
* Set
|
|
1513
|
-
* @param texture Texture containing colors
|
|
2138
|
+
* Set order texture for sorting
|
|
1514
2139
|
*/
|
|
1515
|
-
|
|
1516
|
-
this.uniforms.
|
|
2140
|
+
setOrderTexture(e) {
|
|
2141
|
+
this.uniforms.splatOrder.value = e;
|
|
1517
2142
|
}
|
|
1518
2143
|
/**
|
|
1519
|
-
* Set
|
|
1520
|
-
* @param texture Texture containing sort order
|
|
2144
|
+
* Set the ranges needed to decompress the packed floats
|
|
1521
2145
|
*/
|
|
1522
|
-
|
|
1523
|
-
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);
|
|
1524
2148
|
}
|
|
1525
2149
|
/**
|
|
1526
2150
|
* Set number of splats to render
|
|
@@ -1530,48 +2154,40 @@ class Ve extends l.ShaderMaterial {
|
|
|
1530
2154
|
this.uniforms.numSplats.value = e;
|
|
1531
2155
|
}
|
|
1532
2156
|
}
|
|
1533
|
-
const
|
|
2157
|
+
const de = class de extends h.Mesh {
|
|
1534
2158
|
// Match shader constant
|
|
1535
2159
|
/**
|
|
1536
2160
|
* Create a new SplatMesh for rendering Gaussian splats
|
|
1537
2161
|
* @param splatData The splat data to render
|
|
1538
2162
|
* @param options Rendering options
|
|
1539
2163
|
*/
|
|
1540
|
-
constructor(
|
|
1541
|
-
const
|
|
1542
|
-
super(
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
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());
|
|
1552
2176
|
// Cached inverse matrix
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
const
|
|
1562
|
-
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);
|
|
1563
2187
|
});
|
|
1564
|
-
this.geometry =
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
}, this.textureManager = new De(o), this.sorter = new Pe();
|
|
1568
|
-
let a = this.createChunks() || void 0;
|
|
1569
|
-
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(
|
|
1570
|
-
this.textureManager.orderTexture,
|
|
1571
|
-
this.splatData.positions,
|
|
1572
|
-
a ?? void 0,
|
|
1573
|
-
!this.options.keepSplatData
|
|
1574
|
-
), 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);
|
|
1575
2191
|
}
|
|
1576
2192
|
/**
|
|
1577
2193
|
* Creates the instanced geometry for rendering splats.
|
|
@@ -1579,8 +2195,8 @@ const se = class se extends l.Mesh {
|
|
|
1579
2195
|
* @param instanceSize Number of splats per instance.
|
|
1580
2196
|
* @returns InstancedBufferGeometry
|
|
1581
2197
|
*/
|
|
1582
|
-
static createInstancedGeometry(
|
|
1583
|
-
const
|
|
2198
|
+
static createInstancedGeometry(t, r) {
|
|
2199
|
+
const s = Math.ceil(t / r), a = new h.BufferGeometry(), o = new Float32Array([
|
|
1584
2200
|
// x, y, splat_index_in_instance
|
|
1585
2201
|
-1,
|
|
1586
2202
|
-1,
|
|
@@ -1594,24 +2210,24 @@ const se = class se extends l.Mesh {
|
|
|
1594
2210
|
-1,
|
|
1595
2211
|
1,
|
|
1596
2212
|
0
|
|
1597
|
-
]), i = new Uint16Array([0, 1, 2, 0, 2, 3]),
|
|
1598
|
-
for (let
|
|
1599
|
-
const
|
|
1600
|
-
for (let
|
|
1601
|
-
|
|
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;
|
|
1602
2218
|
}
|
|
1603
|
-
const
|
|
1604
|
-
for (let
|
|
1605
|
-
const
|
|
1606
|
-
|
|
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;
|
|
1607
2223
|
}
|
|
1608
|
-
|
|
1609
|
-
const
|
|
1610
|
-
|
|
1611
|
-
const
|
|
1612
|
-
for (let
|
|
1613
|
-
|
|
1614
|
-
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;
|
|
1615
2231
|
}
|
|
1616
2232
|
/**
|
|
1617
2233
|
* Create chunks data (bounding box min/max) for the sorter.
|
|
@@ -1620,14 +2236,14 @@ const se = class se extends l.Mesh {
|
|
|
1620
2236
|
createChunks() {
|
|
1621
2237
|
if (!this.splatData)
|
|
1622
2238
|
return null;
|
|
1623
|
-
const
|
|
1624
|
-
return
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
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
|
|
1631
2247
|
]);
|
|
1632
2248
|
}
|
|
1633
2249
|
/**
|
|
@@ -1635,17 +2251,17 @@ const se = class se extends l.Mesh {
|
|
|
1635
2251
|
* @param width Viewport width
|
|
1636
2252
|
* @param height Viewport height
|
|
1637
2253
|
*/
|
|
1638
|
-
updateViewport(
|
|
1639
|
-
|
|
2254
|
+
updateViewport(t, r) {
|
|
2255
|
+
t === this._vpW && r === this._vpH || (this._vpW = t, this._vpH = r, this.material.updateViewport(t, r));
|
|
1640
2256
|
}
|
|
1641
2257
|
/**
|
|
1642
2258
|
* Sorts splats based on camera position and direction.
|
|
1643
2259
|
* @param camera The camera to sort against.
|
|
1644
2260
|
*/
|
|
1645
|
-
sort(
|
|
1646
|
-
|
|
1647
|
-
const
|
|
1648
|
-
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));
|
|
1649
2265
|
}
|
|
1650
2266
|
/**
|
|
1651
2267
|
* THREE.js hook called before rendering the object.
|
|
@@ -1656,8 +2272,8 @@ const se = class se extends l.Mesh {
|
|
|
1656
2272
|
*/
|
|
1657
2273
|
// prettier-ignore
|
|
1658
2274
|
// @ts-expect-error scene is not used
|
|
1659
|
-
onBeforeRender(
|
|
1660
|
-
this.sort(
|
|
2275
|
+
onBeforeRender(t, r, s) {
|
|
2276
|
+
this.sort(s), t.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
|
|
1661
2277
|
}
|
|
1662
2278
|
/**
|
|
1663
2279
|
* Dispose of resources
|
|
@@ -1667,39 +2283,51 @@ const se = class se extends l.Mesh {
|
|
|
1667
2283
|
}
|
|
1668
2284
|
};
|
|
1669
2285
|
/** Number of splats combined into a single instanced draw call. */
|
|
1670
|
-
|
|
1671
|
-
let
|
|
1672
|
-
const
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
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
|
|
1677
2294
|
}) => {
|
|
1678
|
-
|
|
1679
|
-
const
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
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);
|
|
1685
2304
|
}
|
|
1686
2305
|
), () => {
|
|
1687
|
-
|
|
2306
|
+
t && console.debug("SPLAT: releasing mesh for", n), zt(f);
|
|
1688
2307
|
};
|
|
1689
|
-
}, [
|
|
1690
|
-
},
|
|
1691
|
-
const
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
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;
|
|
1696
2323
|
};
|
|
1697
|
-
function
|
|
1698
|
-
const e =
|
|
1699
|
-
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)));
|
|
1700
2327
|
}
|
|
1701
2328
|
export {
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
2329
|
+
st as PlyLoader,
|
|
2330
|
+
St as SogsLoader,
|
|
2331
|
+
Ft as Splat,
|
|
2332
|
+
Te as SplatMesh
|
|
1705
2333
|
};
|