@speridlabs/visus 2.0.0 → 2.1.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 +4 -3
- package/dist/main.es.js +361 -360
- package/dist/main.umd.js +6 -6
- package/dist/react.es.js +553 -552
- package/package.json +8 -2
package/dist/main.es.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
var pt = Object.defineProperty;
|
|
2
|
-
var
|
|
3
|
-
var h = (k, t,
|
|
2
|
+
var ft = (k, t, o) => t in k ? pt(k, t, { enumerable: !0, configurable: !0, writable: !0, value: o }) : k[t] = o;
|
|
3
|
+
var h = (k, t, o) => ft(k, typeof t != "symbol" ? t + "" : t, o);
|
|
4
4
|
import * as a from "three";
|
|
5
|
-
class
|
|
5
|
+
class ct {
|
|
6
6
|
constructor() {
|
|
7
7
|
h(this, "min", new a.Vector3(1 / 0, 1 / 0, 1 / 0));
|
|
8
8
|
h(this, "max", new a.Vector3(-1 / 0, -1 / 0, -1 / 0));
|
|
@@ -56,11 +56,11 @@ class lt {
|
|
|
56
56
|
* @returns New bounding box with the same values
|
|
57
57
|
*/
|
|
58
58
|
clone() {
|
|
59
|
-
const t = new
|
|
59
|
+
const t = new ct();
|
|
60
60
|
return t.min.copy(this.min), t.max.copy(this.max), t.center.copy(this.center), t.halfExtents.copy(this.halfExtents), t;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
class
|
|
63
|
+
class mt {
|
|
64
64
|
// TODO: there is no sh spherical harmonics
|
|
65
65
|
constructor(t = 0) {
|
|
66
66
|
h(this, "numSplats", 0);
|
|
@@ -69,12 +69,11 @@ class xt {
|
|
|
69
69
|
h(this, "scales");
|
|
70
70
|
h(this, "colors");
|
|
71
71
|
h(this, "opacities");
|
|
72
|
-
h(this, "
|
|
73
|
-
h(this, "boundingBox", new lt());
|
|
72
|
+
h(this, "boundingBox", new ct());
|
|
74
73
|
this.numSplats = t, this.allocateBuffers(t);
|
|
75
74
|
}
|
|
76
75
|
allocateBuffers(t) {
|
|
77
|
-
this.positions = new Float32Array(t * 3), this.rotations = new Float32Array(t * 4), this.scales = new Float32Array(t * 3), this.colors = new Float32Array(t * 3), this.opacities = new Float32Array(t)
|
|
76
|
+
this.positions = new Float32Array(t * 3), this.rotations = new Float32Array(t * 4), this.scales = new Float32Array(t * 3), this.colors = new Float32Array(t * 3), this.opacities = new Float32Array(t);
|
|
78
77
|
}
|
|
79
78
|
/**
|
|
80
79
|
* Set data for a specific splat
|
|
@@ -85,13 +84,13 @@ class xt {
|
|
|
85
84
|
* @param color Color
|
|
86
85
|
* @param opacity Opacity value
|
|
87
86
|
*/
|
|
88
|
-
setSplat(t,
|
|
87
|
+
setSplat(t, o, e, s, r, n) {
|
|
89
88
|
if (t >= this.numSplats)
|
|
90
89
|
throw new Error(
|
|
91
90
|
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
92
91
|
);
|
|
93
|
-
const i = t * 3, l = t * 4, x = t * 3,
|
|
94
|
-
this.positions[i] =
|
|
92
|
+
const i = t * 3, l = t * 4, x = t * 3, b = t * 3;
|
|
93
|
+
this.positions[i] = o.x, this.positions[i + 1] = o.y, this.positions[i + 2] = o.z, this.rotations[l] = e.x, this.rotations[l + 1] = e.y, this.rotations[l + 2] = e.z, this.rotations[l + 3] = e.w, this.scales[x] = s.x, this.scales[x + 1] = s.y, this.scales[x + 2] = s.z, this.colors[b] = r.r, this.colors[b + 1] = r.g, this.colors[b + 2] = r.b, this.opacities[t] = n;
|
|
95
94
|
}
|
|
96
95
|
/**
|
|
97
96
|
* Get a splat's data
|
|
@@ -103,12 +102,12 @@ class xt {
|
|
|
103
102
|
throw new Error(
|
|
104
103
|
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
105
104
|
);
|
|
106
|
-
const
|
|
105
|
+
const o = t * 3, e = t * 4, s = t * 3, r = t * 3;
|
|
107
106
|
return {
|
|
108
107
|
position: new a.Vector3(
|
|
109
|
-
this.positions[
|
|
110
|
-
this.positions[
|
|
111
|
-
this.positions[
|
|
108
|
+
this.positions[o],
|
|
109
|
+
this.positions[o + 1],
|
|
110
|
+
this.positions[o + 2]
|
|
112
111
|
),
|
|
113
112
|
rotation: new a.Quaternion(
|
|
114
113
|
this.rotations[e],
|
|
@@ -118,9 +117,9 @@ class xt {
|
|
|
118
117
|
),
|
|
119
118
|
// Convert log scale back to linear scale for external use
|
|
120
119
|
scale: new a.Vector3(
|
|
121
|
-
Math.exp(this.scales[
|
|
122
|
-
Math.exp(this.scales[
|
|
123
|
-
Math.exp(this.scales[
|
|
120
|
+
Math.exp(this.scales[s]),
|
|
121
|
+
Math.exp(this.scales[s + 1]),
|
|
122
|
+
Math.exp(this.scales[s + 2])
|
|
124
123
|
),
|
|
125
124
|
color: new a.Color(
|
|
126
125
|
this.colors[r],
|
|
@@ -137,8 +136,8 @@ class xt {
|
|
|
137
136
|
calculateBoundingBox() {
|
|
138
137
|
this.boundingBox.reset();
|
|
139
138
|
const t = new a.Vector3();
|
|
140
|
-
for (let
|
|
141
|
-
const e =
|
|
139
|
+
for (let o = 0; o < this.numSplats; o++) {
|
|
140
|
+
const e = o * 3;
|
|
142
141
|
t.set(
|
|
143
142
|
this.positions[e],
|
|
144
143
|
this.positions[e + 1],
|
|
@@ -157,7 +156,7 @@ class xt {
|
|
|
157
156
|
"position",
|
|
158
157
|
new a.BufferAttribute(this.positions, 3)
|
|
159
158
|
);
|
|
160
|
-
const
|
|
159
|
+
const o = new Float32Array(this.numSplats * 3), e = new a.Quaternion(), s = new a.Euler();
|
|
161
160
|
for (let r = 0; r < this.numSplats; r++) {
|
|
162
161
|
const n = r * 4, i = r * 3;
|
|
163
162
|
e.set(
|
|
@@ -165,11 +164,11 @@ class xt {
|
|
|
165
164
|
this.rotations[n + 1],
|
|
166
165
|
this.rotations[n + 2],
|
|
167
166
|
this.rotations[n + 3]
|
|
168
|
-
),
|
|
167
|
+
), s.setFromQuaternion(e), o[i] = s.x, o[i + 1] = s.y, o[i + 2] = s.z;
|
|
169
168
|
}
|
|
170
169
|
return t.setAttribute(
|
|
171
170
|
"rotation",
|
|
172
|
-
new a.BufferAttribute(
|
|
171
|
+
new a.BufferAttribute(o, 3)
|
|
173
172
|
), t.setAttribute(
|
|
174
173
|
"scale",
|
|
175
174
|
new a.BufferAttribute(this.scales, 3)
|
|
@@ -182,7 +181,7 @@ class xt {
|
|
|
182
181
|
), t;
|
|
183
182
|
}
|
|
184
183
|
}
|
|
185
|
-
class
|
|
184
|
+
class xt extends a.EventDispatcher {
|
|
186
185
|
constructor() {
|
|
187
186
|
super();
|
|
188
187
|
h(this, "worker");
|
|
@@ -192,59 +191,60 @@ class yt extends a.EventDispatcher {
|
|
|
192
191
|
h(this, "chunks", null);
|
|
193
192
|
h(this, "lastCameraPosition", new a.Vector3());
|
|
194
193
|
h(this, "lastCameraDirection", new a.Vector3());
|
|
195
|
-
const
|
|
194
|
+
const o = this.createWorkerCode(), e = new Blob([o], { type: "application/javascript" });
|
|
196
195
|
this.worker = new Worker(URL.createObjectURL(e)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
197
196
|
}
|
|
198
197
|
/**
|
|
199
198
|
* Handles messages received from the sorting worker.
|
|
200
199
|
* @param event The message event from the worker.
|
|
201
200
|
*/
|
|
202
|
-
onWorkerMessage(
|
|
201
|
+
onWorkerMessage(o) {
|
|
203
202
|
if (!this.orderTexture || !this.orderTexture.image)
|
|
204
203
|
return console.error("SplatSorter: Order texture not initialized!");
|
|
205
|
-
const { order: e, count:
|
|
204
|
+
const { order: e, count: s } = o.data, r = this.orderTexture.image.data;
|
|
206
205
|
if (!(r instanceof Uint32Array))
|
|
207
206
|
return console.error(
|
|
208
207
|
"SplatSorter: Order texture data is not a Uint32Array!"
|
|
209
208
|
);
|
|
210
209
|
r.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
|
|
211
210
|
const n = r.buffer.slice(0), i = { order: n };
|
|
212
|
-
this.worker.postMessage(i, [n]), this.dispatchEvent({ type: "updated", count:
|
|
211
|
+
this.worker.postMessage(i, [n]), this.dispatchEvent({ type: "updated", count: s });
|
|
213
212
|
}
|
|
214
213
|
/**
|
|
215
214
|
* Initializes the sorter with necessary data and textures.
|
|
216
215
|
* @param orderTexture The THREE.DataTexture (R32UI) to store the sorted splat indices.
|
|
217
216
|
* @param centers A Float32Array containing the center position (x, y, z) for each splat.
|
|
218
217
|
* @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
|
|
218
|
+
* @param transferOwnership Optional: If true, transfers ownership of centers buffer to worker (saves memory, main thread loses access). Default: false.
|
|
219
219
|
*/
|
|
220
|
-
init(
|
|
221
|
-
if (!
|
|
220
|
+
init(o, e, s, r = !1) {
|
|
221
|
+
if (!o || !(o.image.data instanceof Uint32Array))
|
|
222
222
|
throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
|
|
223
223
|
if (!e || e.length % 3 !== 0)
|
|
224
224
|
throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");
|
|
225
|
-
if (
|
|
225
|
+
if (o.image.data.length < e.length / 3)
|
|
226
226
|
throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
|
|
227
|
-
const
|
|
228
|
-
this.orderTexture =
|
|
229
|
-
const
|
|
230
|
-
for (let
|
|
227
|
+
const n = e.length / 3;
|
|
228
|
+
this.orderTexture = o, r ? this.centers = null : this.centers = e.slice();
|
|
229
|
+
const i = this.orderTexture.image.data;
|
|
230
|
+
for (let u = 0; u < n; u++) i[u] = u;
|
|
231
231
|
this.orderTexture.needsUpdate = !0;
|
|
232
|
-
const
|
|
233
|
-
order:
|
|
234
|
-
centers:
|
|
235
|
-
},
|
|
236
|
-
|
|
237
|
-
|
|
232
|
+
const l = i.buffer.slice(0), x = r ? e.buffer : e.buffer.slice(0), b = {
|
|
233
|
+
order: l,
|
|
234
|
+
centers: x
|
|
235
|
+
}, C = [
|
|
236
|
+
l,
|
|
237
|
+
x
|
|
238
238
|
];
|
|
239
|
-
if (
|
|
240
|
-
this.chunks =
|
|
241
|
-
const
|
|
242
|
-
|
|
239
|
+
if (s) {
|
|
240
|
+
this.chunks = s.slice();
|
|
241
|
+
const u = this.chunks.buffer.slice(0);
|
|
242
|
+
b.chunks = u, C.push(u);
|
|
243
243
|
}
|
|
244
|
-
this.worker.postMessage(
|
|
244
|
+
this.worker.postMessage(b, C), queueMicrotask(() => {
|
|
245
245
|
this.dispatchEvent({
|
|
246
246
|
type: "updated",
|
|
247
|
-
count:
|
|
247
|
+
count: n
|
|
248
248
|
});
|
|
249
249
|
});
|
|
250
250
|
}
|
|
@@ -253,50 +253,50 @@ class yt extends a.EventDispatcher {
|
|
|
253
253
|
* The sorter will only consider splats whose original indices are present in the mapping.
|
|
254
254
|
* @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
|
|
255
255
|
*/
|
|
256
|
-
setMapping(
|
|
256
|
+
setMapping(o) {
|
|
257
257
|
if (!this.centers)
|
|
258
258
|
return console.warn(
|
|
259
259
|
"SplatSorter: Cannot set mapping before initialization."
|
|
260
260
|
);
|
|
261
261
|
let e;
|
|
262
|
-
const
|
|
263
|
-
if (!
|
|
262
|
+
const s = [];
|
|
263
|
+
if (!o) {
|
|
264
264
|
const l = this.centers.buffer.slice(0);
|
|
265
265
|
return e = {
|
|
266
266
|
centers: l,
|
|
267
267
|
mapping: null
|
|
268
|
-
},
|
|
268
|
+
}, s.push(l), this.worker.postMessage(e, s);
|
|
269
269
|
}
|
|
270
|
-
const r = new Float32Array(
|
|
271
|
-
for (let l = 0; l <
|
|
272
|
-
const x =
|
|
270
|
+
const r = new Float32Array(o.length * 3);
|
|
271
|
+
for (let l = 0; l < o.length; l++) {
|
|
272
|
+
const x = o[l];
|
|
273
273
|
if (x * 3 + 2 >= this.centers.length) {
|
|
274
274
|
console.warn(
|
|
275
275
|
`SplatSorter: Mapping index ${x} out of bounds.`
|
|
276
276
|
);
|
|
277
277
|
continue;
|
|
278
278
|
}
|
|
279
|
-
const
|
|
280
|
-
r[
|
|
279
|
+
const b = x * 3, C = l * 3;
|
|
280
|
+
r[C + 0] = this.centers[b + 0], r[C + 1] = this.centers[b + 1], r[C + 2] = this.centers[b + 2];
|
|
281
281
|
}
|
|
282
|
-
const n = r.buffer.slice(0), i =
|
|
282
|
+
const n = r.buffer.slice(0), i = o.buffer.slice(0);
|
|
283
283
|
e = {
|
|
284
284
|
centers: n,
|
|
285
285
|
mapping: i
|
|
286
|
-
},
|
|
286
|
+
}, s.push(n, i), this.worker.postMessage(e, s);
|
|
287
287
|
}
|
|
288
288
|
/**
|
|
289
289
|
* Updates the camera parameters used for sorting.
|
|
290
290
|
* @param position The camera's position in the sorter's local coordinate space.
|
|
291
291
|
* @param direction The camera's forward direction in the sorter's local coordinate space.
|
|
292
292
|
*/
|
|
293
|
-
setCamera(
|
|
294
|
-
const
|
|
295
|
-
if (!
|
|
293
|
+
setCamera(o, e) {
|
|
294
|
+
const s = this.lastCameraPosition.distanceToSquared(o) > 1e-7, r = this.lastCameraDirection.dot(e) < 0.9999;
|
|
295
|
+
if (!s && !r)
|
|
296
296
|
return;
|
|
297
|
-
this.lastCameraPosition.copy(
|
|
297
|
+
this.lastCameraPosition.copy(o), this.lastCameraDirection.copy(e);
|
|
298
298
|
const n = {
|
|
299
|
-
cameraPosition: { x:
|
|
299
|
+
cameraPosition: { x: o.x, y: o.y, z: o.z },
|
|
300
300
|
cameraDirection: { x: e.x, y: e.y, z: e.z }
|
|
301
301
|
};
|
|
302
302
|
this.worker.postMessage(n);
|
|
@@ -313,21 +313,21 @@ class yt extends a.EventDispatcher {
|
|
|
313
313
|
*/
|
|
314
314
|
createWorkerCode() {
|
|
315
315
|
return `(${(function() {
|
|
316
|
-
let e = null,
|
|
317
|
-
const
|
|
316
|
+
let e = null, s = null, r = null, n = null, i = null, l = null, x = !1;
|
|
317
|
+
const b = { x: 0, y: 0, z: 0 }, C = { x: 0, y: 0, z: 0 }, u = { x: 0, y: 0, z: 0 }, g = { x: 0, y: 0, z: 0 };
|
|
318
318
|
let v = null, S = null;
|
|
319
|
-
const
|
|
320
|
-
for (;
|
|
321
|
-
const
|
|
322
|
-
if (
|
|
323
|
-
else if (
|
|
324
|
-
else return
|
|
319
|
+
const I = 32, R = new Array(I).fill(0), Y = new Array(I).fill(0), W = new Array(I).fill(0), ot = (w, d, P) => {
|
|
320
|
+
for (; w <= d; ) {
|
|
321
|
+
const M = d + w >> 1, f = P(M);
|
|
322
|
+
if (f > 0) w = M + 1;
|
|
323
|
+
else if (f < 0) d = M - 1;
|
|
324
|
+
else return M;
|
|
325
325
|
}
|
|
326
|
-
return ~
|
|
327
|
-
},
|
|
328
|
-
if (!e || !
|
|
326
|
+
return ~w;
|
|
327
|
+
}, L = () => {
|
|
328
|
+
if (!e || !s || !i || !l)
|
|
329
329
|
return;
|
|
330
|
-
if (
|
|
330
|
+
if (s.length === 0) {
|
|
331
331
|
const c = {
|
|
332
332
|
order: e.buffer,
|
|
333
333
|
count: 0
|
|
@@ -335,127 +335,127 @@ class yt extends a.EventDispatcher {
|
|
|
335
335
|
self.postMessage(c, [e.buffer]), e = null;
|
|
336
336
|
return;
|
|
337
337
|
}
|
|
338
|
-
const
|
|
339
|
-
if (!x && !j && !
|
|
338
|
+
const w = i.x, d = i.y, P = i.z, M = l.x, f = l.y, A = l.z, T = 1e-4, j = Math.abs(w - b.x) > T || Math.abs(d - b.y) > T || Math.abs(P - b.z) > T, J = Math.abs(M - C.x) > T || Math.abs(f - C.y) > T || Math.abs(A - C.z) > T;
|
|
339
|
+
if (!x && !j && !J)
|
|
340
340
|
return;
|
|
341
|
-
x = !1,
|
|
342
|
-
let
|
|
341
|
+
x = !1, b.x = w, b.y = d, b.z = P, C.x = M, C.y = f, C.z = A;
|
|
342
|
+
let $ = 1 / 0, D = -1 / 0;
|
|
343
343
|
for (let c = 0; c < 8; ++c) {
|
|
344
|
-
const
|
|
345
|
-
|
|
344
|
+
const y = c & 1 ? u.x : g.x, B = c & 2 ? u.y : g.y, m = c & 4 ? u.z : g.z, z = y * M + B * f + m * A;
|
|
345
|
+
$ = Math.min($, z), D = Math.max(D, z);
|
|
346
346
|
}
|
|
347
|
-
const
|
|
347
|
+
const _ = s.length / 3, N = D - $, E = (1 << Math.max(
|
|
348
348
|
10,
|
|
349
|
-
Math.min(20, Math.ceil(Math.log2(
|
|
349
|
+
Math.min(20, Math.ceil(Math.log2(_ / 4)))
|
|
350
350
|
)) + 1;
|
|
351
|
-
if ((!v || v.length !==
|
|
352
|
-
for (let c = 0; c <
|
|
353
|
-
S[0] =
|
|
351
|
+
if ((!v || v.length !== _) && (v = new Uint32Array(_)), !S || S.length !== E ? S = new Uint32Array(E) : S.fill(0), N < 1e-7) {
|
|
352
|
+
for (let c = 0; c < _; ++c) v[c] = 0;
|
|
353
|
+
S[0] = _;
|
|
354
354
|
} else if (r && r.length > 0) {
|
|
355
355
|
const c = r.length / 6;
|
|
356
|
-
|
|
357
|
-
for (let
|
|
358
|
-
const
|
|
356
|
+
R.fill(0);
|
|
357
|
+
for (let m = 0; m < c; ++m) {
|
|
358
|
+
const z = m * 6, U = r[z + 0], V = r[z + 1], O = r[z + 2], F = r[z + 3], q = U * M + V * f + O * A - $, X = q - F, Z = q + F, K = Math.max(
|
|
359
359
|
0,
|
|
360
|
-
Math.floor(
|
|
361
|
-
),
|
|
362
|
-
|
|
363
|
-
Math.ceil(
|
|
360
|
+
Math.floor(X * I / N)
|
|
361
|
+
), Q = Math.min(
|
|
362
|
+
I,
|
|
363
|
+
Math.ceil(Z * I / N)
|
|
364
364
|
);
|
|
365
|
-
for (let H =
|
|
366
|
-
|
|
365
|
+
for (let H = K; H < Q; ++H)
|
|
366
|
+
R[H]++;
|
|
367
367
|
}
|
|
368
|
-
let
|
|
369
|
-
for (let
|
|
370
|
-
|
|
371
|
-
for (let
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const
|
|
375
|
-
for (let
|
|
376
|
-
const
|
|
368
|
+
let y = 0;
|
|
369
|
+
for (let m = 0; m < I; ++m) y += R[m];
|
|
370
|
+
W[0] = 0, Y[0] = 0;
|
|
371
|
+
for (let m = 1; m < I; ++m)
|
|
372
|
+
W[m - 1] = R[m - 1] / y * E >>> 0, Y[m] = Y[m - 1] + W[m - 1];
|
|
373
|
+
W[I - 1] = R[I - 1] / y * E >>> 0;
|
|
374
|
+
const B = N / I;
|
|
375
|
+
for (let m = 0; m < _; ++m) {
|
|
376
|
+
const z = m * 3, U = s[z + 0], V = s[z + 1], O = s[z + 2], F = U * M + V * f + O * A, X = (D - F) / B, Z = Math.max(
|
|
377
377
|
0,
|
|
378
378
|
Math.min(
|
|
379
|
-
|
|
380
|
-
Math.floor(
|
|
379
|
+
I - 1,
|
|
380
|
+
Math.floor(X)
|
|
381
381
|
)
|
|
382
|
-
),
|
|
383
|
-
v[
|
|
382
|
+
), K = X - Z, Q = Y[Z] + W[Z] * K >>> 0, H = Math.min(Q, E - 1);
|
|
383
|
+
v[m] = H, S[H]++;
|
|
384
384
|
}
|
|
385
385
|
} else {
|
|
386
|
-
const c = (
|
|
387
|
-
for (let
|
|
388
|
-
const
|
|
389
|
-
v[
|
|
386
|
+
const c = (E - 1) / N;
|
|
387
|
+
for (let y = 0; y < _; ++y) {
|
|
388
|
+
const B = y * 3, m = s[B + 0], z = s[B + 1], U = s[B + 2], V = m * M + z * f + U * A, F = (D - V) * c >>> 0, q = Math.min(F, E - 1);
|
|
389
|
+
v[y] = q, S[q]++;
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
|
-
for (let c = 1; c <
|
|
392
|
+
for (let c = 1; c < E; c++)
|
|
393
393
|
S[c] += S[c - 1];
|
|
394
|
-
for (let c =
|
|
395
|
-
const
|
|
396
|
-
e[
|
|
394
|
+
for (let c = _ - 1; c >= 0; c--) {
|
|
395
|
+
const y = v[c], B = --S[y];
|
|
396
|
+
e[B] = n ? n[c] : c;
|
|
397
397
|
}
|
|
398
|
-
const
|
|
398
|
+
const st = w * M + d * f + P * A, tt = (c) => {
|
|
399
399
|
if (!e) return -1 / 0;
|
|
400
|
-
const
|
|
401
|
-
if (!
|
|
400
|
+
const y = e[c], B = y;
|
|
401
|
+
if (!s || B * 3 + 2 >= s.length)
|
|
402
402
|
return -1 / 0;
|
|
403
|
-
const
|
|
404
|
-
return
|
|
403
|
+
const m = B * 3;
|
|
404
|
+
return s[m] * M + s[m + 1] * f + s[m + 2] * A - st;
|
|
405
405
|
};
|
|
406
|
-
let
|
|
407
|
-
if (
|
|
406
|
+
let et = _;
|
|
407
|
+
if (_ > 0 && tt(_ - 1) < 0) {
|
|
408
408
|
const c = ot(
|
|
409
409
|
0,
|
|
410
|
-
|
|
411
|
-
|
|
410
|
+
_ - 1,
|
|
411
|
+
tt
|
|
412
412
|
);
|
|
413
|
-
|
|
413
|
+
et = c < 0 ? ~c : c;
|
|
414
414
|
}
|
|
415
|
-
const
|
|
415
|
+
const p = {
|
|
416
416
|
order: e.buffer,
|
|
417
|
-
count:
|
|
417
|
+
count: et
|
|
418
418
|
};
|
|
419
|
-
self.postMessage(
|
|
419
|
+
self.postMessage(p, [e.buffer]), e = null;
|
|
420
420
|
};
|
|
421
|
-
self.onmessage = (
|
|
422
|
-
const d =
|
|
421
|
+
self.onmessage = (w) => {
|
|
422
|
+
const d = w.data;
|
|
423
423
|
d.order && (e = new Uint32Array(d.order));
|
|
424
|
-
let
|
|
425
|
-
if (d.centers && (
|
|
424
|
+
let P = !1;
|
|
425
|
+
if (d.centers && (s = new Float32Array(d.centers), P = !0, x = !0), Object.prototype.hasOwnProperty.call(d, "mapping") && (n = d.mapping ? new Uint32Array(d.mapping) : null, x = !0), d.chunks) {
|
|
426
426
|
if (r = new Float32Array(d.chunks), r.length > 0 && r[3] > 0)
|
|
427
|
-
for (let
|
|
428
|
-
const
|
|
429
|
-
r[
|
|
430
|
-
(
|
|
427
|
+
for (let M = 0; M < r.length / 6; ++M) {
|
|
428
|
+
const f = M * 6, A = r[f + 0], T = r[f + 1], j = r[f + 2], J = r[f + 3], $ = r[f + 4], D = r[f + 5];
|
|
429
|
+
r[f + 0] = (A + J) * 0.5, r[f + 1] = (T + $) * 0.5, r[f + 2] = (j + D) * 0.5, r[f + 3] = Math.sqrt(
|
|
430
|
+
(J - A) ** 2 + ($ - T) ** 2 + (D - j) ** 2
|
|
431
431
|
) * 0.5;
|
|
432
432
|
}
|
|
433
433
|
x = !0;
|
|
434
434
|
}
|
|
435
|
-
if (
|
|
436
|
-
|
|
437
|
-
for (let
|
|
438
|
-
const
|
|
439
|
-
|
|
435
|
+
if (P && s && s.length > 0) {
|
|
436
|
+
u.x = g.x = s[0], u.y = g.y = s[1], u.z = g.z = s[2];
|
|
437
|
+
for (let M = 1; M < s.length / 3; M++) {
|
|
438
|
+
const f = M * 3;
|
|
439
|
+
u.x = Math.min(u.x, s[f + 0]), g.x = Math.max(g.x, s[f + 0]), u.y = Math.min(u.y, s[f + 1]), g.y = Math.max(g.y, s[f + 1]), u.z = Math.min(u.z, s[f + 2]), g.z = Math.max(g.z, s[f + 2]);
|
|
440
440
|
}
|
|
441
|
-
} else
|
|
442
|
-
d.cameraPosition && (i = d.cameraPosition), d.cameraDirection && (l = d.cameraDirection),
|
|
441
|
+
} else P && s && s.length === 0 && (u.x = g.x = u.y = g.y = u.z = g.z = 0);
|
|
442
|
+
d.cameraPosition && (i = d.cameraPosition), d.cameraDirection && (l = d.cameraDirection), L();
|
|
443
443
|
};
|
|
444
444
|
}).toString()})();`;
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
|
-
const
|
|
448
|
-
const
|
|
449
|
-
return
|
|
447
|
+
const yt = (k, t) => {
|
|
448
|
+
const o = ht(k), e = ht(t);
|
|
449
|
+
return o | e << 16;
|
|
450
450
|
};
|
|
451
|
-
function
|
|
451
|
+
function ht(k) {
|
|
452
452
|
const t = new Float32Array([k]), e = new Int32Array(t.buffer)[0];
|
|
453
|
-
let
|
|
453
|
+
let s = e >> 16 & 32768, r = e >> 12 & 2047;
|
|
454
454
|
const n = e >> 23 & 255;
|
|
455
|
-
return n < 103 ?
|
|
455
|
+
return n < 103 ? s : n > 142 ? (s |= 31744, s |= (n === 255 ? 0 : 1) && e & 8388607, s) : n < 113 ? (r |= 2048, s |= (r >> 114 - n) + (r >> 113 - n & 1), s) : (s |= n - 112 << 10 | r >> 1, s += r & 1, s);
|
|
456
456
|
}
|
|
457
|
-
const
|
|
458
|
-
class
|
|
457
|
+
const gt = new ArrayBuffer(4), ut = new DataView(gt), vt = (k) => (ut.setUint32(0, k, !0), ut.getFloat32(0, !0));
|
|
458
|
+
class wt {
|
|
459
459
|
/**
|
|
460
460
|
* Create a new TextureManager for a set of splats
|
|
461
461
|
* @param splatData The splat data to manage textures for
|
|
@@ -470,8 +470,8 @@ class bt {
|
|
|
470
470
|
h(this, "orderTexture");
|
|
471
471
|
h(this, "textureWidth");
|
|
472
472
|
h(this, "textureHeight");
|
|
473
|
-
const
|
|
474
|
-
this.textureWidth = Math.ceil(Math.sqrt(
|
|
473
|
+
const o = t.numSplats;
|
|
474
|
+
this.textureWidth = Math.ceil(Math.sqrt(o)), this.textureHeight = Math.ceil(o / this.textureWidth), this.transformA = this.createTransformATexture(t), this.transformB = this.createTransformBTexture(t), this.colorTexture = this.createColorTexture(t), this.orderTexture = this.createOrderTexture(o);
|
|
475
475
|
}
|
|
476
476
|
/**
|
|
477
477
|
* Create the transform A texture (positions and quaternion w component)
|
|
@@ -479,16 +479,16 @@ class bt {
|
|
|
479
479
|
* @returns DataTexture containing position data
|
|
480
480
|
*/
|
|
481
481
|
createTransformATexture(t) {
|
|
482
|
-
const
|
|
482
|
+
const o = t.numSplats, e = new Float32Array(
|
|
483
483
|
this.textureWidth * this.textureHeight * 4
|
|
484
484
|
);
|
|
485
|
-
for (let r = 0; r <
|
|
485
|
+
for (let r = 0; r < o; r++) {
|
|
486
486
|
const n = r * 4, i = r * 3, l = r * 4;
|
|
487
487
|
e[n] = t.positions[i], e[n + 1] = t.positions[i + 1], e[n + 2] = t.positions[i + 2];
|
|
488
|
-
const x = t.rotations[l + 0],
|
|
489
|
-
e[n + 3] =
|
|
488
|
+
const x = t.rotations[l + 0], b = t.rotations[l + 1], C = yt(x, b);
|
|
489
|
+
e[n + 3] = vt(C);
|
|
490
490
|
}
|
|
491
|
-
const
|
|
491
|
+
const s = new a.DataTexture(
|
|
492
492
|
e,
|
|
493
493
|
this.textureWidth,
|
|
494
494
|
this.textureHeight,
|
|
@@ -496,7 +496,7 @@ class bt {
|
|
|
496
496
|
a.FloatType
|
|
497
497
|
// Store as Float32, shader will reinterpret bits
|
|
498
498
|
);
|
|
499
|
-
return
|
|
499
|
+
return s.needsUpdate = !0, s.magFilter = a.NearestFilter, s.minFilter = a.NearestFilter, s;
|
|
500
500
|
}
|
|
501
501
|
/**
|
|
502
502
|
* Create the transform B texture (scale and rotation xyz)
|
|
@@ -504,21 +504,21 @@ class bt {
|
|
|
504
504
|
* @returns DataTexture containing scale and rotation data
|
|
505
505
|
*/
|
|
506
506
|
createTransformBTexture(t) {
|
|
507
|
-
const
|
|
507
|
+
const o = t.numSplats, e = new Float32Array(
|
|
508
508
|
this.textureWidth * this.textureHeight * 4
|
|
509
509
|
);
|
|
510
|
-
for (let r = 0; r <
|
|
510
|
+
for (let r = 0; r < o; r++) {
|
|
511
511
|
const n = r * 4, i = r * 3, l = r * 4;
|
|
512
512
|
e[n] = t.scales[i], e[n + 1] = t.scales[i + 1], e[n + 2] = t.scales[i + 2], e[n + 3] = t.rotations[l + 2];
|
|
513
513
|
}
|
|
514
|
-
const
|
|
514
|
+
const s = new a.DataTexture(
|
|
515
515
|
e,
|
|
516
516
|
this.textureWidth,
|
|
517
517
|
this.textureHeight,
|
|
518
518
|
a.RGBAFormat,
|
|
519
519
|
a.FloatType
|
|
520
520
|
);
|
|
521
|
-
return
|
|
521
|
+
return s.needsUpdate = !0, s.magFilter = a.NearestFilter, s.minFilter = a.NearestFilter, s;
|
|
522
522
|
}
|
|
523
523
|
/**
|
|
524
524
|
* Create the color texture (RGB and opacity)
|
|
@@ -526,21 +526,21 @@ class bt {
|
|
|
526
526
|
* @returns DataTexture containing color data
|
|
527
527
|
*/
|
|
528
528
|
createColorTexture(t) {
|
|
529
|
-
const
|
|
529
|
+
const o = t.numSplats, e = new Float32Array(
|
|
530
530
|
this.textureWidth * this.textureHeight * 4
|
|
531
531
|
);
|
|
532
|
-
for (let r = 0; r <
|
|
532
|
+
for (let r = 0; r < o; r++) {
|
|
533
533
|
const n = r * 4, i = r * 3;
|
|
534
534
|
e[n] = t.colors[i], e[n + 1] = t.colors[i + 1], e[n + 2] = t.colors[i + 2], e[n + 3] = t.opacities[r];
|
|
535
535
|
}
|
|
536
|
-
const
|
|
536
|
+
const s = new a.DataTexture(
|
|
537
537
|
e,
|
|
538
538
|
this.textureWidth,
|
|
539
539
|
this.textureHeight,
|
|
540
540
|
a.RGBAFormat,
|
|
541
541
|
a.FloatType
|
|
542
542
|
);
|
|
543
|
-
return
|
|
543
|
+
return s.needsUpdate = !0, s;
|
|
544
544
|
}
|
|
545
545
|
/**
|
|
546
546
|
* Create the order texture for sorting
|
|
@@ -548,11 +548,11 @@ class bt {
|
|
|
548
548
|
* @returns DataTexture for storing order indices
|
|
549
549
|
*/
|
|
550
550
|
createOrderTexture(t) {
|
|
551
|
-
const
|
|
552
|
-
for (let
|
|
553
|
-
s
|
|
551
|
+
const o = new Uint32Array(this.textureWidth * this.textureHeight);
|
|
552
|
+
for (let s = 0; s < t; s++)
|
|
553
|
+
o[s] = s;
|
|
554
554
|
const e = new a.DataTexture(
|
|
555
|
-
|
|
555
|
+
o,
|
|
556
556
|
this.textureWidth,
|
|
557
557
|
this.textureHeight,
|
|
558
558
|
a.RedIntegerFormat,
|
|
@@ -564,7 +564,7 @@ class bt {
|
|
|
564
564
|
this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
|
|
565
565
|
}
|
|
566
566
|
}
|
|
567
|
-
const
|
|
567
|
+
const bt = (
|
|
568
568
|
/* glsl */
|
|
569
569
|
`
|
|
570
570
|
precision highp float;
|
|
@@ -822,7 +822,7 @@ void main(void) {
|
|
|
822
822
|
vUv = clippedCornerOffset;
|
|
823
823
|
}
|
|
824
824
|
`
|
|
825
|
-
),
|
|
825
|
+
), Mt = (
|
|
826
826
|
/* glsl */
|
|
827
827
|
`
|
|
828
828
|
precision highp float;
|
|
@@ -856,9 +856,9 @@ void main(void) {
|
|
|
856
856
|
}
|
|
857
857
|
`
|
|
858
858
|
);
|
|
859
|
-
class
|
|
859
|
+
class Ct extends a.ShaderMaterial {
|
|
860
860
|
constructor(t = {}) {
|
|
861
|
-
const
|
|
861
|
+
const o = {
|
|
862
862
|
// Textures (values set via methods)
|
|
863
863
|
transformA: { value: null },
|
|
864
864
|
transformB: { value: null },
|
|
@@ -871,9 +871,9 @@ class St extends a.ShaderMaterial {
|
|
|
871
871
|
// Max splats to render (updated by sorter)
|
|
872
872
|
};
|
|
873
873
|
super({
|
|
874
|
-
vertexShader:
|
|
875
|
-
fragmentShader:
|
|
876
|
-
uniforms:
|
|
874
|
+
vertexShader: bt,
|
|
875
|
+
fragmentShader: Mt,
|
|
876
|
+
uniforms: o,
|
|
877
877
|
transparent: !0,
|
|
878
878
|
blending: a.CustomBlending,
|
|
879
879
|
// Premultiplied alpha blending:
|
|
@@ -904,8 +904,8 @@ class St extends a.ShaderMaterial {
|
|
|
904
904
|
* @param width Viewport width
|
|
905
905
|
* @param height Viewport height
|
|
906
906
|
*/
|
|
907
|
-
updateViewport(t,
|
|
908
|
-
this.uniforms.viewport.value.set(t,
|
|
907
|
+
updateViewport(t, o) {
|
|
908
|
+
this.uniforms.viewport.value.set(t, o);
|
|
909
909
|
}
|
|
910
910
|
/**
|
|
911
911
|
* Set transform texture A (positions)
|
|
@@ -943,16 +943,16 @@ class St extends a.ShaderMaterial {
|
|
|
943
943
|
this.uniforms.numSplats.value = t;
|
|
944
944
|
}
|
|
945
945
|
}
|
|
946
|
-
const
|
|
946
|
+
const rt = class rt extends a.Mesh {
|
|
947
947
|
// Match shader constant
|
|
948
948
|
/**
|
|
949
949
|
* Create a new SplatMesh for rendering Gaussian splats
|
|
950
950
|
* @param splatData The splat data to render
|
|
951
951
|
* @param options Rendering options
|
|
952
952
|
*/
|
|
953
|
-
constructor(
|
|
954
|
-
const
|
|
955
|
-
super(r,
|
|
953
|
+
constructor(o, e = {}) {
|
|
954
|
+
const s = new Ct(e), r = rt.createInstancedGeometry(o.numSplats, rt.INSTANCE_SIZE);
|
|
955
|
+
super(r, s);
|
|
956
956
|
h(this, "sorter");
|
|
957
957
|
h(this, "splatData");
|
|
958
958
|
h(this, "options");
|
|
@@ -970,20 +970,21 @@ const et = class et extends a.Mesh {
|
|
|
970
970
|
h(this, "_camDirW", new a.Vector3());
|
|
971
971
|
h(this, "_camPosL", new a.Vector3());
|
|
972
972
|
h(this, "_camDirL", new a.Vector3());
|
|
973
|
-
h(this, "onSorterUpdated", (
|
|
974
|
-
const e =
|
|
975
|
-
this.geometry.instanceCount = Math.ceil(e /
|
|
973
|
+
h(this, "onSorterUpdated", (o) => {
|
|
974
|
+
const e = o.count;
|
|
975
|
+
this.geometry.instanceCount = Math.ceil(e / rt.INSTANCE_SIZE), this.material.setNumSplats(e);
|
|
976
976
|
});
|
|
977
|
-
this.geometry = r, this.material =
|
|
977
|
+
this.geometry = r, this.material = s, this.splatData = o, this.frustumCulled = !1, this.options = {
|
|
978
978
|
autoSort: !0,
|
|
979
979
|
...e
|
|
980
|
-
}, this.textureManager = new
|
|
980
|
+
}, this.textureManager = new wt(o), this.sorter = new xt();
|
|
981
981
|
let n = this.createChunks() || void 0;
|
|
982
982
|
n === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), n = void 0, this.sorter.addEventListener("updated", this.onSorterUpdated), this.sorter.init(
|
|
983
983
|
this.textureManager.orderTexture,
|
|
984
|
-
this.splatData.
|
|
985
|
-
n ?? void 0
|
|
986
|
-
|
|
984
|
+
this.splatData.positions,
|
|
985
|
+
n ?? void 0,
|
|
986
|
+
!this.options.keepSplatData
|
|
987
|
+
), 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 a.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere), this.options.keepSplatData || (this.splatData = null);
|
|
987
988
|
}
|
|
988
989
|
/**
|
|
989
990
|
* Creates the instanced geometry for rendering splats.
|
|
@@ -991,8 +992,8 @@ const et = class et extends a.Mesh {
|
|
|
991
992
|
* @param instanceSize Number of splats per instance.
|
|
992
993
|
* @returns InstancedBufferGeometry
|
|
993
994
|
*/
|
|
994
|
-
static createInstancedGeometry(
|
|
995
|
-
const
|
|
995
|
+
static createInstancedGeometry(o, e) {
|
|
996
|
+
const s = Math.ceil(o / e), r = new a.BufferGeometry(), n = new Float32Array([
|
|
996
997
|
// x, y, splat_index_in_instance
|
|
997
998
|
-1,
|
|
998
999
|
-1,
|
|
@@ -1007,37 +1008,39 @@ const et = class et extends a.Mesh {
|
|
|
1007
1008
|
1,
|
|
1008
1009
|
0
|
|
1009
1010
|
]), i = new Uint16Array([0, 1, 2, 0, 2, 3]), l = new Float32Array(4 * 3 * e);
|
|
1010
|
-
for (let
|
|
1011
|
-
const
|
|
1011
|
+
for (let u = 0; u < e; u++) {
|
|
1012
|
+
const g = u * 4 * 3;
|
|
1012
1013
|
for (let v = 0; v < 4; v++)
|
|
1013
|
-
l[
|
|
1014
|
+
l[g + v * 3 + 0] = n[v * 3 + 0], l[g + v * 3 + 1] = n[v * 3 + 1], l[g + v * 3 + 2] = u;
|
|
1014
1015
|
}
|
|
1015
1016
|
const x = new Uint32Array(6 * e);
|
|
1016
|
-
for (let
|
|
1017
|
-
const
|
|
1018
|
-
x[
|
|
1017
|
+
for (let u = 0; u < e; u++) {
|
|
1018
|
+
const g = u * 6, v = u * 4;
|
|
1019
|
+
x[g + 0] = i[0] + v, x[g + 1] = i[1] + v, x[g + 2] = i[2] + v, x[g + 3] = i[3] + v, x[g + 4] = i[4] + v, x[g + 5] = i[5] + v;
|
|
1019
1020
|
}
|
|
1020
1021
|
r.setAttribute("position", new a.BufferAttribute(l, 3)), r.setIndex(new a.BufferAttribute(x, 1));
|
|
1021
|
-
const
|
|
1022
|
-
|
|
1023
|
-
const
|
|
1024
|
-
for (let
|
|
1025
|
-
|
|
1026
|
-
return
|
|
1022
|
+
const b = new a.InstancedBufferGeometry();
|
|
1023
|
+
b.index = r.index, b.setAttribute("position", r.getAttribute("position"));
|
|
1024
|
+
const C = new Uint32Array(s);
|
|
1025
|
+
for (let u = 0; u < s; u++)
|
|
1026
|
+
C[u] = u * e;
|
|
1027
|
+
return b.setAttribute("splatInstanceIndex", new a.InstancedBufferAttribute(C, 1, !1)), b.instanceCount = 0, b;
|
|
1027
1028
|
}
|
|
1028
1029
|
/**
|
|
1029
1030
|
* Create chunks data (bounding box min/max) for the sorter.
|
|
1030
1031
|
* @returns Float32Array containing chunk data [minX, minY, minZ, maxX, maxY, maxZ] or null.
|
|
1031
1032
|
*/
|
|
1032
1033
|
createChunks() {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1034
|
+
if (!this.splatData)
|
|
1035
|
+
return null;
|
|
1036
|
+
const o = this.splatData.boundingBox;
|
|
1037
|
+
return o.min.x === 1 / 0 || o.max.x === -1 / 0 ? null : new Float32Array([
|
|
1038
|
+
o.min.x,
|
|
1039
|
+
o.min.y,
|
|
1040
|
+
o.min.z,
|
|
1041
|
+
o.max.x,
|
|
1042
|
+
o.max.y,
|
|
1043
|
+
o.max.z
|
|
1041
1044
|
]);
|
|
1042
1045
|
}
|
|
1043
1046
|
/**
|
|
@@ -1045,17 +1048,17 @@ const et = class et extends a.Mesh {
|
|
|
1045
1048
|
* @param width Viewport width
|
|
1046
1049
|
* @param height Viewport height
|
|
1047
1050
|
*/
|
|
1048
|
-
updateViewport(
|
|
1049
|
-
|
|
1051
|
+
updateViewport(o, e) {
|
|
1052
|
+
o === this._vpW && e === this._vpH || (this._vpW = o, this._vpH = e, this.material.updateViewport(o, e));
|
|
1050
1053
|
}
|
|
1051
1054
|
/**
|
|
1052
1055
|
* Sorts splats based on camera position and direction.
|
|
1053
1056
|
* @param camera The camera to sort against.
|
|
1054
1057
|
*/
|
|
1055
|
-
sort(
|
|
1056
|
-
|
|
1057
|
-
const e = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6,
|
|
1058
|
-
this.options.autoSort && (e ||
|
|
1058
|
+
sort(o) {
|
|
1059
|
+
o.getWorldPosition(this._camPosW), o.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);
|
|
1060
|
+
const e = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6, s = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
|
|
1061
|
+
this.options.autoSort && (e || s) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
|
|
1059
1062
|
}
|
|
1060
1063
|
/**
|
|
1061
1064
|
* THREE.js hook called before rendering the object.
|
|
@@ -1066,8 +1069,8 @@ const et = class et extends a.Mesh {
|
|
|
1066
1069
|
*/
|
|
1067
1070
|
// prettier-ignore
|
|
1068
1071
|
// @ts-expect-error scene is not used
|
|
1069
|
-
onBeforeRender(
|
|
1070
|
-
this.sort(
|
|
1072
|
+
onBeforeRender(o, e, s) {
|
|
1073
|
+
this.sort(s), o.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
|
|
1071
1074
|
}
|
|
1072
1075
|
/**
|
|
1073
1076
|
* Dispose of resources
|
|
@@ -1077,29 +1080,29 @@ const et = class et extends a.Mesh {
|
|
|
1077
1080
|
}
|
|
1078
1081
|
};
|
|
1079
1082
|
/** Number of splats combined into a single instanced draw call. */
|
|
1080
|
-
h(
|
|
1081
|
-
let
|
|
1082
|
-
class
|
|
1083
|
-
constructor(
|
|
1084
|
-
super(
|
|
1083
|
+
h(rt, "INSTANCE_SIZE", 128);
|
|
1084
|
+
let dt = rt;
|
|
1085
|
+
class At extends a.Loader {
|
|
1086
|
+
constructor(o) {
|
|
1087
|
+
super(o);
|
|
1085
1088
|
h(this, "requestId", 0);
|
|
1086
1089
|
h(this, "worker");
|
|
1087
1090
|
h(this, "pendingCallbacks", /* @__PURE__ */ new Map());
|
|
1088
|
-
const e = this.createWorkerCode(),
|
|
1089
|
-
this.worker = new Worker(URL.createObjectURL(
|
|
1091
|
+
const e = this.createWorkerCode(), s = new Blob([e], { type: "application/javascript" });
|
|
1092
|
+
this.worker = new Worker(URL.createObjectURL(s)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
1090
1093
|
}
|
|
1091
1094
|
/**
|
|
1092
1095
|
* Handles messages received from the parsing worker
|
|
1093
1096
|
* @param event The message event from the worker
|
|
1094
1097
|
*/
|
|
1095
|
-
onWorkerMessage(
|
|
1096
|
-
const { requestId: e, error:
|
|
1098
|
+
onWorkerMessage(o) {
|
|
1099
|
+
const { requestId: e, error: s, result: r } = o.data, n = this.pendingCallbacks.get(e);
|
|
1097
1100
|
if (!n) return console.warn(`PlyLoader: Received response for unknown request ${e}`);
|
|
1098
|
-
if (this.pendingCallbacks.delete(e),
|
|
1101
|
+
if (this.pendingCallbacks.delete(e), s) return n.reject(new Error(s));
|
|
1099
1102
|
if (!r) return n.reject(new Error("Worker returned no result"));
|
|
1100
1103
|
try {
|
|
1101
|
-
const i = new
|
|
1102
|
-
i.numSplats = r.numSplats, i.positions = new Float32Array(r.positions), i.rotations = new Float32Array(r.rotations), i.scales = new Float32Array(r.scales), i.colors = new Float32Array(r.colors), i.opacities = new Float32Array(r.opacities), i.
|
|
1104
|
+
const i = new mt(0);
|
|
1105
|
+
i.numSplats = r.numSplats, i.positions = new Float32Array(r.positions), i.rotations = new Float32Array(r.rotations), i.scales = new Float32Array(r.scales), i.colors = new Float32Array(r.colors), i.opacities = new Float32Array(r.opacities), i.boundingBox.min.set(
|
|
1103
1106
|
r.boundingBox.minX,
|
|
1104
1107
|
r.boundingBox.minY,
|
|
1105
1108
|
r.boundingBox.minZ
|
|
@@ -1119,18 +1122,18 @@ class zt extends a.Loader {
|
|
|
1119
1122
|
* @param onProgress Optional progress callback
|
|
1120
1123
|
* @param onError Optional error callback
|
|
1121
1124
|
*/
|
|
1122
|
-
load(
|
|
1125
|
+
load(o, e, s, r) {
|
|
1123
1126
|
const n = new a.FileLoader(this.manager);
|
|
1124
1127
|
n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
|
|
1125
|
-
|
|
1128
|
+
o,
|
|
1126
1129
|
(i) => {
|
|
1127
1130
|
this.parseAsync(i).then((l) => {
|
|
1128
1131
|
e && e(l);
|
|
1129
1132
|
}).catch((l) => {
|
|
1130
|
-
r ? r(l) : console.error(l), this.manager.itemError(
|
|
1133
|
+
r ? r(l) : console.error(l), this.manager.itemError(o);
|
|
1131
1134
|
});
|
|
1132
1135
|
},
|
|
1133
|
-
|
|
1136
|
+
s,
|
|
1134
1137
|
r
|
|
1135
1138
|
);
|
|
1136
1139
|
}
|
|
@@ -1140,19 +1143,19 @@ class zt extends a.Loader {
|
|
|
1140
1143
|
* @param onProgress Optional progress callback
|
|
1141
1144
|
* @returns A Promise that resolves with the parsed SplatData
|
|
1142
1145
|
*/
|
|
1143
|
-
loadAsync(
|
|
1144
|
-
return new Promise((
|
|
1146
|
+
loadAsync(o, e) {
|
|
1147
|
+
return new Promise((s, r) => {
|
|
1145
1148
|
const n = new a.FileLoader(this.manager);
|
|
1146
1149
|
n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
|
|
1147
|
-
|
|
1150
|
+
o,
|
|
1148
1151
|
(i) => {
|
|
1149
|
-
this.parseAsync(i).then(
|
|
1150
|
-
r(l), this.manager.itemError(
|
|
1152
|
+
this.parseAsync(i).then(s).catch((l) => {
|
|
1153
|
+
r(l), this.manager.itemError(o);
|
|
1151
1154
|
});
|
|
1152
1155
|
},
|
|
1153
1156
|
e,
|
|
1154
1157
|
(i) => {
|
|
1155
|
-
r(i), this.manager.itemError(
|
|
1158
|
+
r(i), this.manager.itemError(o);
|
|
1156
1159
|
}
|
|
1157
1160
|
);
|
|
1158
1161
|
});
|
|
@@ -1162,15 +1165,15 @@ class zt extends a.Loader {
|
|
|
1162
1165
|
* @param buffer ArrayBuffer containing PLY data
|
|
1163
1166
|
* @returns Promise that resolves with parsed SplatData
|
|
1164
1167
|
*/
|
|
1165
|
-
parseAsync(
|
|
1166
|
-
return new Promise((e,
|
|
1168
|
+
parseAsync(o) {
|
|
1169
|
+
return new Promise((e, s) => {
|
|
1167
1170
|
const r = this.requestId++;
|
|
1168
|
-
this.pendingCallbacks.set(r, { resolve: e, reject:
|
|
1171
|
+
this.pendingCallbacks.set(r, { resolve: e, reject: s });
|
|
1169
1172
|
const n = {
|
|
1170
1173
|
requestId: r,
|
|
1171
|
-
buffer:
|
|
1174
|
+
buffer: o
|
|
1172
1175
|
};
|
|
1173
|
-
this.worker.postMessage(n, [
|
|
1176
|
+
this.worker.postMessage(n, [o]);
|
|
1174
1177
|
});
|
|
1175
1178
|
}
|
|
1176
1179
|
/**
|
|
@@ -1185,8 +1188,8 @@ class zt extends a.Loader {
|
|
|
1185
1188
|
*/
|
|
1186
1189
|
createWorkerCode() {
|
|
1187
1190
|
return `(${(function() {
|
|
1188
|
-
self.onmessage = (
|
|
1189
|
-
const { requestId: r, buffer: n } =
|
|
1191
|
+
self.onmessage = (s) => {
|
|
1192
|
+
const { requestId: r, buffer: n } = s.data;
|
|
1190
1193
|
try {
|
|
1191
1194
|
const i = e(n), l = {
|
|
1192
1195
|
requestId: r,
|
|
@@ -1197,8 +1200,7 @@ class zt extends a.Loader {
|
|
|
1197
1200
|
i.rotations,
|
|
1198
1201
|
i.scales,
|
|
1199
1202
|
i.colors,
|
|
1200
|
-
i.opacities
|
|
1201
|
-
i.centers
|
|
1203
|
+
i.opacities
|
|
1202
1204
|
]);
|
|
1203
1205
|
} catch (i) {
|
|
1204
1206
|
const l = {
|
|
@@ -1208,25 +1210,25 @@ class zt extends a.Loader {
|
|
|
1208
1210
|
self.postMessage(l);
|
|
1209
1211
|
}
|
|
1210
1212
|
};
|
|
1211
|
-
function e(
|
|
1212
|
-
const r = new TextDecoder(), n = new Uint8Array(
|
|
1213
|
+
function e(s) {
|
|
1214
|
+
const r = new TextDecoder(), n = new Uint8Array(s), i = [112, 108, 121, 10], l = `
|
|
1213
1215
|
end_header
|
|
1214
1216
|
`;
|
|
1215
|
-
for (let
|
|
1216
|
-
if (n[
|
|
1217
|
+
for (let p = 0; p < i.length; p++)
|
|
1218
|
+
if (n[p] !== i[p])
|
|
1217
1219
|
throw new Error(
|
|
1218
1220
|
"Invalid PLY file: Missing magic bytes"
|
|
1219
1221
|
);
|
|
1220
1222
|
let x = 0;
|
|
1221
|
-
for (let
|
|
1222
|
-
let
|
|
1223
|
-
for (let
|
|
1224
|
-
if (n[
|
|
1225
|
-
|
|
1223
|
+
for (let p = 0; p < n.length - l.length; p++) {
|
|
1224
|
+
let c = !0;
|
|
1225
|
+
for (let y = 0; y < l.length; y++)
|
|
1226
|
+
if (n[p + y] !== l.charCodeAt(y)) {
|
|
1227
|
+
c = !1;
|
|
1226
1228
|
break;
|
|
1227
1229
|
}
|
|
1228
|
-
if (
|
|
1229
|
-
x =
|
|
1230
|
+
if (c) {
|
|
1231
|
+
x = p + l.length;
|
|
1230
1232
|
break;
|
|
1231
1233
|
}
|
|
1232
1234
|
}
|
|
@@ -1234,163 +1236,162 @@ end_header
|
|
|
1234
1236
|
throw new Error(
|
|
1235
1237
|
"Invalid PLY file: Could not find end of header"
|
|
1236
1238
|
);
|
|
1237
|
-
const
|
|
1239
|
+
const C = r.decode(
|
|
1238
1240
|
n.subarray(0, x)
|
|
1239
1241
|
).split(`
|
|
1240
|
-
`),
|
|
1241
|
-
let
|
|
1242
|
-
for (let
|
|
1243
|
-
const
|
|
1244
|
-
if (
|
|
1245
|
-
const
|
|
1246
|
-
switch (
|
|
1242
|
+
`), u = [];
|
|
1243
|
+
let g = null;
|
|
1244
|
+
for (let p = 1; p < C.length; p++) {
|
|
1245
|
+
const c = C[p].trim();
|
|
1246
|
+
if (c === "" || c === "end_header") continue;
|
|
1247
|
+
const y = c.split(" ");
|
|
1248
|
+
switch (y[0]) {
|
|
1247
1249
|
case "format":
|
|
1248
|
-
|
|
1250
|
+
g = y[1];
|
|
1249
1251
|
break;
|
|
1250
1252
|
case "element":
|
|
1251
|
-
|
|
1252
|
-
name:
|
|
1253
|
-
count: parseInt(
|
|
1253
|
+
u.push({
|
|
1254
|
+
name: y[1],
|
|
1255
|
+
count: parseInt(y[2], 10),
|
|
1254
1256
|
properties: []
|
|
1255
1257
|
});
|
|
1256
1258
|
break;
|
|
1257
1259
|
case "property":
|
|
1258
|
-
if (
|
|
1260
|
+
if (u.length === 0)
|
|
1259
1261
|
throw new Error(
|
|
1260
1262
|
"Invalid PLY file: Property without element"
|
|
1261
1263
|
);
|
|
1262
|
-
|
|
1263
|
-
type:
|
|
1264
|
-
name:
|
|
1264
|
+
u[u.length - 1].properties.push({
|
|
1265
|
+
type: y[1],
|
|
1266
|
+
name: y[2]
|
|
1265
1267
|
});
|
|
1266
1268
|
break;
|
|
1267
1269
|
}
|
|
1268
1270
|
}
|
|
1269
|
-
if (
|
|
1270
|
-
throw new Error(`Unsupported PLY format: ${
|
|
1271
|
-
const v =
|
|
1271
|
+
if (g !== "binary_little_endian")
|
|
1272
|
+
throw new Error(`Unsupported PLY format: ${g}`);
|
|
1273
|
+
const v = u.find((p) => p.name === "vertex");
|
|
1272
1274
|
if (!v)
|
|
1273
1275
|
throw new Error(
|
|
1274
1276
|
"Invalid PLY file: No vertex element found"
|
|
1275
1277
|
);
|
|
1276
|
-
const S = v.count,
|
|
1277
|
-
let
|
|
1278
|
-
const
|
|
1279
|
-
(
|
|
1280
|
-
),
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1278
|
+
const S = v.count, I = new Float32Array(S * 3), R = new Float32Array(S * 4), Y = new Float32Array(S * 3), W = new Float32Array(S * 3), ot = new Float32Array(S), L = new DataView(s);
|
|
1279
|
+
let w = x;
|
|
1280
|
+
const d = (p) => v.properties.findIndex(
|
|
1281
|
+
(c) => c.name === p
|
|
1282
|
+
), P = d("x"), M = d("y"), f = d("z"), A = [
|
|
1283
|
+
d("rot_0"),
|
|
1284
|
+
d("rot_1"),
|
|
1285
|
+
d("rot_2"),
|
|
1286
|
+
d("rot_3")
|
|
1287
|
+
], T = [
|
|
1288
|
+
d("scale_0"),
|
|
1289
|
+
d("scale_1"),
|
|
1290
|
+
d("scale_2")
|
|
1285
1291
|
], j = [
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
],
|
|
1290
|
-
M("f_dc_0"),
|
|
1291
|
-
M("f_dc_1"),
|
|
1292
|
-
M("f_dc_2")
|
|
1293
|
-
], O = M("opacity");
|
|
1292
|
+
d("f_dc_0"),
|
|
1293
|
+
d("f_dc_1"),
|
|
1294
|
+
d("f_dc_2")
|
|
1295
|
+
], J = d("opacity");
|
|
1294
1296
|
if ([
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1297
|
+
P,
|
|
1298
|
+
M,
|
|
1299
|
+
f,
|
|
1300
|
+
...A,
|
|
1298
1301
|
...T,
|
|
1299
1302
|
...j,
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
].some((c) => c === -1))
|
|
1303
|
+
J
|
|
1304
|
+
].some((p) => p === -1))
|
|
1303
1305
|
throw new Error(
|
|
1304
1306
|
"Invalid PLY file: Missing required properties"
|
|
1305
1307
|
);
|
|
1306
|
-
const
|
|
1307
|
-
if (
|
|
1308
|
-
const
|
|
1309
|
-
return
|
|
1308
|
+
const D = 0.28209479177387814, _ = (p) => {
|
|
1309
|
+
if (p > 0) return 1 / (1 + Math.exp(-p));
|
|
1310
|
+
const c = Math.exp(p);
|
|
1311
|
+
return c / (1 + c);
|
|
1310
1312
|
};
|
|
1311
|
-
let
|
|
1312
|
-
for (let
|
|
1313
|
-
const
|
|
1314
|
-
for (let
|
|
1315
|
-
const
|
|
1316
|
-
let
|
|
1317
|
-
switch (
|
|
1313
|
+
let N = 1 / 0, nt = 1 / 0, E = 1 / 0, st = -1 / 0, tt = -1 / 0, et = -1 / 0;
|
|
1314
|
+
for (let p = 0; p < S; p++) {
|
|
1315
|
+
const c = [];
|
|
1316
|
+
for (let at = 0; at < v.properties.length; at++) {
|
|
1317
|
+
const lt = v.properties[at].type;
|
|
1318
|
+
let G;
|
|
1319
|
+
switch (lt) {
|
|
1318
1320
|
case "char":
|
|
1319
|
-
|
|
1321
|
+
G = L.getInt8(w), w += 1;
|
|
1320
1322
|
break;
|
|
1321
1323
|
case "uchar":
|
|
1322
|
-
|
|
1324
|
+
G = L.getUint8(w), w += 1;
|
|
1323
1325
|
break;
|
|
1324
1326
|
case "short":
|
|
1325
|
-
|
|
1327
|
+
G = L.getInt16(w, !0), w += 2;
|
|
1326
1328
|
break;
|
|
1327
1329
|
case "ushort":
|
|
1328
|
-
|
|
1330
|
+
G = L.getUint16(w, !0), w += 2;
|
|
1329
1331
|
break;
|
|
1330
1332
|
case "int":
|
|
1331
|
-
|
|
1333
|
+
G = L.getInt32(w, !0), w += 4;
|
|
1332
1334
|
break;
|
|
1333
1335
|
case "uint":
|
|
1334
|
-
|
|
1336
|
+
G = L.getUint32(w, !0), w += 4;
|
|
1335
1337
|
break;
|
|
1336
1338
|
case "float":
|
|
1337
|
-
|
|
1339
|
+
G = L.getFloat32(w, !0), w += 4;
|
|
1338
1340
|
break;
|
|
1339
1341
|
case "double":
|
|
1340
|
-
|
|
1342
|
+
G = L.getFloat64(w, !0), w += 8;
|
|
1341
1343
|
break;
|
|
1342
1344
|
default:
|
|
1343
1345
|
throw new Error(
|
|
1344
|
-
`Unsupported property type: ${
|
|
1346
|
+
`Unsupported property type: ${lt}`
|
|
1345
1347
|
);
|
|
1346
1348
|
}
|
|
1347
|
-
|
|
1349
|
+
c.push(G);
|
|
1348
1350
|
}
|
|
1349
|
-
const
|
|
1350
|
-
z
|
|
1351
|
-
let U =
|
|
1352
|
-
const
|
|
1353
|
-
U * U +
|
|
1351
|
+
const y = c[P], B = c[M], m = c[f], z = p * 3;
|
|
1352
|
+
I[z] = y, I[z + 1] = B, I[z + 2] = m, N = Math.min(N, y), nt = Math.min(nt, B), E = Math.min(E, m), st = Math.max(st, y), tt = Math.max(tt, B), et = Math.max(et, m);
|
|
1353
|
+
let U = c[A[1]], V = c[A[2]], O = c[A[3]], F = c[A[0]];
|
|
1354
|
+
const q = Math.sqrt(
|
|
1355
|
+
U * U + V * V + O * O + F * F
|
|
1354
1356
|
);
|
|
1355
|
-
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
const
|
|
1359
|
-
Y[
|
|
1360
|
-
let
|
|
1361
|
-
|
|
1362
|
-
const
|
|
1363
|
-
|
|
1357
|
+
q > 0 && (U /= q, V /= q, O /= q, F /= q), F < 0 && (U = -U, V = -V, O = -O, F = -F);
|
|
1358
|
+
const X = p * 4;
|
|
1359
|
+
R[X] = U, R[X + 1] = V, R[X + 2] = O, R[X + 3] = F;
|
|
1360
|
+
const Z = p * 3;
|
|
1361
|
+
Y[Z] = c[T[0]], Y[Z + 1] = c[T[1]], Y[Z + 2] = c[T[2]];
|
|
1362
|
+
let K = 0.5 + c[j[0]] * D, Q = 0.5 + c[j[1]] * D, H = 0.5 + c[j[2]] * D;
|
|
1363
|
+
K = Math.max(0, Math.min(1, K)), Q = Math.max(0, Math.min(1, Q)), H = Math.max(0, Math.min(1, H));
|
|
1364
|
+
const it = p * 3;
|
|
1365
|
+
W[it] = K, W[it + 1] = Q, W[it + 2] = H, ot[p] = _(c[J]);
|
|
1364
1366
|
}
|
|
1365
1367
|
return {
|
|
1366
1368
|
numSplats: S,
|
|
1367
|
-
positions:
|
|
1368
|
-
rotations:
|
|
1369
|
+
positions: I.buffer,
|
|
1370
|
+
rotations: R.buffer,
|
|
1369
1371
|
scales: Y.buffer,
|
|
1370
|
-
colors:
|
|
1372
|
+
colors: W.buffer,
|
|
1371
1373
|
opacities: ot.buffer,
|
|
1372
|
-
centers: K.buffer,
|
|
1373
1374
|
boundingBox: {
|
|
1374
|
-
minX:
|
|
1375
|
-
minY:
|
|
1376
|
-
minZ:
|
|
1377
|
-
maxX:
|
|
1375
|
+
minX: N,
|
|
1376
|
+
minY: nt,
|
|
1377
|
+
minZ: E,
|
|
1378
|
+
maxX: st,
|
|
1378
1379
|
maxY: tt,
|
|
1379
|
-
maxZ:
|
|
1380
|
+
maxZ: et
|
|
1380
1381
|
}
|
|
1381
1382
|
};
|
|
1382
1383
|
}
|
|
1383
1384
|
}).toString()})();`;
|
|
1384
1385
|
}
|
|
1385
1386
|
}
|
|
1386
|
-
const
|
|
1387
|
+
const zt = "0.3.0";
|
|
1387
1388
|
export {
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1389
|
+
ct as BoundingBox,
|
|
1390
|
+
At as PlyLoader,
|
|
1391
|
+
mt as SplatData,
|
|
1392
|
+
Ct as SplatMaterial,
|
|
1393
|
+
dt as SplatMesh,
|
|
1394
|
+
xt as SplatSorter,
|
|
1395
|
+
wt as TextureManager,
|
|
1396
|
+
zt as VERSION
|
|
1396
1397
|
};
|