@speridlabs/visus 1.0.3 → 2.0.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 +346 -328
- package/dist/main.es.js +572 -483
- package/dist/main.umd.js +6 -6
- package/dist/react.es.js +745 -656
- package/package.json +1 -1
package/dist/main.es.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import * as
|
|
5
|
-
class
|
|
1
|
+
var pt = Object.defineProperty;
|
|
2
|
+
var mt = (k, t, s) => t in k ? pt(k, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : k[t] = s;
|
|
3
|
+
var h = (k, t, s) => mt(k, typeof t != "symbol" ? t + "" : t, s);
|
|
4
|
+
import * as a from "three";
|
|
5
|
+
class lt {
|
|
6
6
|
constructor() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
h(this, "min", new a.Vector3(1 / 0, 1 / 0, 1 / 0));
|
|
8
|
+
h(this, "max", new a.Vector3(-1 / 0, -1 / 0, -1 / 0));
|
|
9
|
+
h(this, "center", new a.Vector3());
|
|
10
10
|
/** Half extents (size/2) */
|
|
11
|
-
|
|
11
|
+
h(this, "halfExtents", new a.Vector3());
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Reset the bounding box to its initial state
|
|
@@ -49,28 +49,28 @@ class et {
|
|
|
49
49
|
* @returns THREE.Box3 representation
|
|
50
50
|
*/
|
|
51
51
|
toBox3() {
|
|
52
|
-
return new
|
|
52
|
+
return new a.Box3().set(this.min, this.max);
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* Create a clone of this bounding box
|
|
56
56
|
* @returns New bounding box with the same values
|
|
57
57
|
*/
|
|
58
58
|
clone() {
|
|
59
|
-
const t = new
|
|
59
|
+
const t = new lt();
|
|
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 xt {
|
|
64
64
|
// TODO: there is no sh spherical harmonics
|
|
65
65
|
constructor(t = 0) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
h(this, "numSplats", 0);
|
|
67
|
+
h(this, "positions");
|
|
68
|
+
h(this, "rotations");
|
|
69
|
+
h(this, "scales");
|
|
70
|
+
h(this, "colors");
|
|
71
|
+
h(this, "opacities");
|
|
72
|
+
h(this, "centers");
|
|
73
|
+
h(this, "boundingBox", new lt());
|
|
74
74
|
this.numSplats = t, this.allocateBuffers(t);
|
|
75
75
|
}
|
|
76
76
|
allocateBuffers(t) {
|
|
@@ -85,13 +85,13 @@ class ut {
|
|
|
85
85
|
* @param color Color
|
|
86
86
|
* @param opacity Opacity value
|
|
87
87
|
*/
|
|
88
|
-
setSplat(t, s, e,
|
|
88
|
+
setSplat(t, s, e, o, r, n) {
|
|
89
89
|
if (t >= this.numSplats)
|
|
90
90
|
throw new Error(
|
|
91
91
|
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
92
92
|
);
|
|
93
|
-
const
|
|
94
|
-
this.positions[
|
|
93
|
+
const i = t * 3, l = t * 4, x = t * 3, w = t * 3;
|
|
94
|
+
this.positions[i] = s.x, this.positions[i + 1] = s.y, this.positions[i + 2] = s.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] = o.x, this.scales[x + 1] = o.y, this.scales[x + 2] = o.z, this.colors[w] = r.r, this.colors[w + 1] = r.g, this.colors[w + 2] = r.b, this.opacities[t] = n, this.centers[i] = s.x, this.centers[i + 1] = s.y, this.centers[i + 2] = s.z;
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Get a splat's data
|
|
@@ -103,29 +103,29 @@ class ut {
|
|
|
103
103
|
throw new Error(
|
|
104
104
|
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
105
105
|
);
|
|
106
|
-
const s = t * 3, e = t * 4,
|
|
106
|
+
const s = t * 3, e = t * 4, o = t * 3, r = t * 3;
|
|
107
107
|
return {
|
|
108
|
-
position: new
|
|
108
|
+
position: new a.Vector3(
|
|
109
109
|
this.positions[s],
|
|
110
110
|
this.positions[s + 1],
|
|
111
111
|
this.positions[s + 2]
|
|
112
112
|
),
|
|
113
|
-
rotation: new
|
|
113
|
+
rotation: new a.Quaternion(
|
|
114
114
|
this.rotations[e],
|
|
115
115
|
this.rotations[e + 1],
|
|
116
116
|
this.rotations[e + 2],
|
|
117
117
|
this.rotations[e + 3]
|
|
118
118
|
),
|
|
119
119
|
// Convert log scale back to linear scale for external use
|
|
120
|
-
scale: new
|
|
121
|
-
Math.exp(this.scales[
|
|
122
|
-
Math.exp(this.scales[
|
|
123
|
-
Math.exp(this.scales[
|
|
120
|
+
scale: new a.Vector3(
|
|
121
|
+
Math.exp(this.scales[o]),
|
|
122
|
+
Math.exp(this.scales[o + 1]),
|
|
123
|
+
Math.exp(this.scales[o + 2])
|
|
124
124
|
),
|
|
125
|
-
color: new
|
|
126
|
-
this.colors[
|
|
127
|
-
this.colors[
|
|
128
|
-
this.colors[
|
|
125
|
+
color: new a.Color(
|
|
126
|
+
this.colors[r],
|
|
127
|
+
this.colors[r + 1],
|
|
128
|
+
this.colors[r + 2]
|
|
129
129
|
),
|
|
130
130
|
opacity: this.opacities[t]
|
|
131
131
|
};
|
|
@@ -136,7 +136,7 @@ class ut {
|
|
|
136
136
|
*/
|
|
137
137
|
calculateBoundingBox() {
|
|
138
138
|
this.boundingBox.reset();
|
|
139
|
-
const t = new
|
|
139
|
+
const t = new a.Vector3();
|
|
140
140
|
for (let s = 0; s < this.numSplats; s++) {
|
|
141
141
|
const e = s * 3;
|
|
142
142
|
t.set(
|
|
@@ -152,46 +152,46 @@ class ut {
|
|
|
152
152
|
* This is for visualization/debugging purposes only, not for rendering
|
|
153
153
|
*/
|
|
154
154
|
createDebugGeometry() {
|
|
155
|
-
const t = new
|
|
155
|
+
const t = new a.BufferGeometry();
|
|
156
156
|
t.setAttribute(
|
|
157
157
|
"position",
|
|
158
|
-
new
|
|
158
|
+
new a.BufferAttribute(this.positions, 3)
|
|
159
159
|
);
|
|
160
|
-
const s = new Float32Array(this.numSplats * 3), e = new
|
|
161
|
-
for (let
|
|
162
|
-
const
|
|
160
|
+
const s = new Float32Array(this.numSplats * 3), e = new a.Quaternion(), o = new a.Euler();
|
|
161
|
+
for (let r = 0; r < this.numSplats; r++) {
|
|
162
|
+
const n = r * 4, i = r * 3;
|
|
163
163
|
e.set(
|
|
164
|
-
this.rotations[
|
|
165
|
-
this.rotations[
|
|
166
|
-
this.rotations[
|
|
167
|
-
this.rotations[
|
|
168
|
-
),
|
|
164
|
+
this.rotations[n],
|
|
165
|
+
this.rotations[n + 1],
|
|
166
|
+
this.rotations[n + 2],
|
|
167
|
+
this.rotations[n + 3]
|
|
168
|
+
), o.setFromQuaternion(e), s[i] = o.x, s[i + 1] = o.y, s[i + 2] = o.z;
|
|
169
169
|
}
|
|
170
170
|
return t.setAttribute(
|
|
171
171
|
"rotation",
|
|
172
|
-
new
|
|
172
|
+
new a.BufferAttribute(s, 3)
|
|
173
173
|
), t.setAttribute(
|
|
174
174
|
"scale",
|
|
175
|
-
new
|
|
175
|
+
new a.BufferAttribute(this.scales, 3)
|
|
176
176
|
), t.setAttribute(
|
|
177
177
|
"color",
|
|
178
|
-
new
|
|
178
|
+
new a.BufferAttribute(this.colors, 3)
|
|
179
179
|
), t.setAttribute(
|
|
180
180
|
"opacity",
|
|
181
|
-
new
|
|
181
|
+
new a.BufferAttribute(this.opacities, 1)
|
|
182
182
|
), t;
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
|
-
class
|
|
185
|
+
class yt extends a.EventDispatcher {
|
|
186
186
|
constructor() {
|
|
187
187
|
super();
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
h(this, "worker");
|
|
189
|
+
h(this, "centers", null);
|
|
190
|
+
h(this, "orderTexture", null);
|
|
191
191
|
/** Bounding box data for optimization */
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
h(this, "chunks", null);
|
|
193
|
+
h(this, "lastCameraPosition", new a.Vector3());
|
|
194
|
+
h(this, "lastCameraDirection", new a.Vector3());
|
|
195
195
|
const s = this.createWorkerCode(), e = new Blob([s], { type: "application/javascript" });
|
|
196
196
|
this.worker = new Worker(URL.createObjectURL(e)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
197
197
|
}
|
|
@@ -202,14 +202,14 @@ class dt extends n.EventDispatcher {
|
|
|
202
202
|
onWorkerMessage(s) {
|
|
203
203
|
if (!this.orderTexture || !this.orderTexture.image)
|
|
204
204
|
return console.error("SplatSorter: Order texture not initialized!");
|
|
205
|
-
const { order: e, count:
|
|
206
|
-
if (!(
|
|
205
|
+
const { order: e, count: o } = s.data, r = this.orderTexture.image.data;
|
|
206
|
+
if (!(r instanceof Uint32Array))
|
|
207
207
|
return console.error(
|
|
208
208
|
"SplatSorter: Order texture data is not a Uint32Array!"
|
|
209
209
|
);
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
this.worker.postMessage(
|
|
210
|
+
r.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
|
|
211
|
+
const n = r.buffer.slice(0), i = { order: n };
|
|
212
|
+
this.worker.postMessage(i, [n]), this.dispatchEvent({ type: "updated", count: o });
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
215
|
* Initializes the sorter with necessary data and textures.
|
|
@@ -217,34 +217,34 @@ class dt extends n.EventDispatcher {
|
|
|
217
217
|
* @param centers A Float32Array containing the center position (x, y, z) for each splat.
|
|
218
218
|
* @param chunks Optional: A Float32Array containing bounding box chunk data [minX, minY, minZ, maxX, maxY, maxZ, ...] for optimization.
|
|
219
219
|
*/
|
|
220
|
-
init(s, e,
|
|
220
|
+
init(s, e, o) {
|
|
221
221
|
if (!s || !(s.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
225
|
if (s.image.data.length < e.length / 3)
|
|
226
226
|
throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
|
|
227
|
-
const
|
|
227
|
+
const r = e.length / 3;
|
|
228
228
|
this.orderTexture = s, this.centers = e.slice();
|
|
229
|
-
const
|
|
230
|
-
for (let
|
|
229
|
+
const n = this.orderTexture.image.data;
|
|
230
|
+
for (let b = 0; b < r; b++) n[b] = b;
|
|
231
231
|
this.orderTexture.needsUpdate = !0;
|
|
232
|
-
const
|
|
233
|
-
order:
|
|
234
|
-
centers:
|
|
235
|
-
},
|
|
236
|
-
|
|
237
|
-
|
|
232
|
+
const i = n.buffer.slice(0), l = this.centers.buffer.slice(0), x = {
|
|
233
|
+
order: i,
|
|
234
|
+
centers: l
|
|
235
|
+
}, w = [
|
|
236
|
+
i,
|
|
237
|
+
l
|
|
238
238
|
];
|
|
239
|
-
if (
|
|
240
|
-
this.chunks =
|
|
241
|
-
const
|
|
242
|
-
|
|
239
|
+
if (o) {
|
|
240
|
+
this.chunks = o.slice();
|
|
241
|
+
const b = this.chunks.buffer.slice(0);
|
|
242
|
+
x.chunks = b, w.push(b);
|
|
243
243
|
}
|
|
244
|
-
this.worker.postMessage(
|
|
244
|
+
this.worker.postMessage(x, w), queueMicrotask(() => {
|
|
245
245
|
this.dispatchEvent({
|
|
246
246
|
type: "updated",
|
|
247
|
-
count:
|
|
247
|
+
count: r
|
|
248
248
|
});
|
|
249
249
|
});
|
|
250
250
|
}
|
|
@@ -259,31 +259,31 @@ class dt extends n.EventDispatcher {
|
|
|
259
259
|
"SplatSorter: Cannot set mapping before initialization."
|
|
260
260
|
);
|
|
261
261
|
let e;
|
|
262
|
-
const
|
|
262
|
+
const o = [];
|
|
263
263
|
if (!s) {
|
|
264
|
-
const
|
|
264
|
+
const l = this.centers.buffer.slice(0);
|
|
265
265
|
return e = {
|
|
266
|
-
centers:
|
|
266
|
+
centers: l,
|
|
267
267
|
mapping: null
|
|
268
|
-
},
|
|
268
|
+
}, o.push(l), this.worker.postMessage(e, o);
|
|
269
269
|
}
|
|
270
|
-
const
|
|
271
|
-
for (let
|
|
272
|
-
const
|
|
273
|
-
if (
|
|
270
|
+
const r = new Float32Array(s.length * 3);
|
|
271
|
+
for (let l = 0; l < s.length; l++) {
|
|
272
|
+
const x = s[l];
|
|
273
|
+
if (x * 3 + 2 >= this.centers.length) {
|
|
274
274
|
console.warn(
|
|
275
|
-
`SplatSorter: Mapping index ${
|
|
275
|
+
`SplatSorter: Mapping index ${x} out of bounds.`
|
|
276
276
|
);
|
|
277
277
|
continue;
|
|
278
278
|
}
|
|
279
|
-
const
|
|
280
|
-
|
|
279
|
+
const w = x * 3, b = l * 3;
|
|
280
|
+
r[b + 0] = this.centers[w + 0], r[b + 1] = this.centers[w + 1], r[b + 2] = this.centers[w + 2];
|
|
281
281
|
}
|
|
282
|
-
const
|
|
282
|
+
const n = r.buffer.slice(0), i = s.buffer.slice(0);
|
|
283
283
|
e = {
|
|
284
|
-
centers:
|
|
285
|
-
mapping:
|
|
286
|
-
},
|
|
284
|
+
centers: n,
|
|
285
|
+
mapping: i
|
|
286
|
+
}, o.push(n, i), this.worker.postMessage(e, o);
|
|
287
287
|
}
|
|
288
288
|
/**
|
|
289
289
|
* Updates the camera parameters used for sorting.
|
|
@@ -291,15 +291,15 @@ class dt extends n.EventDispatcher {
|
|
|
291
291
|
* @param direction The camera's forward direction in the sorter's local coordinate space.
|
|
292
292
|
*/
|
|
293
293
|
setCamera(s, e) {
|
|
294
|
-
const
|
|
295
|
-
if (!
|
|
294
|
+
const o = this.lastCameraPosition.distanceToSquared(s) > 1e-7, r = this.lastCameraDirection.dot(e) < 0.9999;
|
|
295
|
+
if (!o && !r)
|
|
296
296
|
return;
|
|
297
297
|
this.lastCameraPosition.copy(s), this.lastCameraDirection.copy(e);
|
|
298
|
-
const
|
|
298
|
+
const n = {
|
|
299
299
|
cameraPosition: { x: s.x, y: s.y, z: s.z },
|
|
300
300
|
cameraDirection: { x: e.x, y: e.y, z: e.z }
|
|
301
301
|
};
|
|
302
|
-
this.worker.postMessage(
|
|
302
|
+
this.worker.postMessage(n);
|
|
303
303
|
}
|
|
304
304
|
/**
|
|
305
305
|
* Terminates the Web Worker and cleans up resources.
|
|
@@ -313,163 +313,163 @@ class dt extends n.EventDispatcher {
|
|
|
313
313
|
*/
|
|
314
314
|
createWorkerCode() {
|
|
315
315
|
return `(${(function() {
|
|
316
|
-
let e = null,
|
|
317
|
-
const
|
|
318
|
-
let
|
|
319
|
-
const
|
|
320
|
-
for (;
|
|
321
|
-
const
|
|
322
|
-
if (m > 0)
|
|
323
|
-
else if (m < 0)
|
|
324
|
-
else return
|
|
316
|
+
let e = null, o = null, r = null, n = null, i = null, l = null, x = !1;
|
|
317
|
+
const w = { x: 0, y: 0, z: 0 }, b = { x: 0, y: 0, z: 0 }, f = { x: 0, y: 0, z: 0 }, y = { x: 0, y: 0, z: 0 };
|
|
318
|
+
let v = null, S = null;
|
|
319
|
+
const z = 32, V = new Array(z).fill(0), Y = new Array(z).fill(0), R = new Array(z).fill(0), ot = (A, d, M) => {
|
|
320
|
+
for (; A <= d; ) {
|
|
321
|
+
const C = d + A >> 1, m = M(C);
|
|
322
|
+
if (m > 0) A = C + 1;
|
|
323
|
+
else if (m < 0) d = C - 1;
|
|
324
|
+
else return C;
|
|
325
325
|
}
|
|
326
|
-
return ~
|
|
327
|
-
},
|
|
328
|
-
if (!e || !
|
|
326
|
+
return ~A;
|
|
327
|
+
}, K = () => {
|
|
328
|
+
if (!e || !o || !i || !l)
|
|
329
329
|
return;
|
|
330
|
-
if (
|
|
331
|
-
const
|
|
330
|
+
if (o.length === 0) {
|
|
331
|
+
const c = {
|
|
332
332
|
order: e.buffer,
|
|
333
333
|
count: 0
|
|
334
334
|
};
|
|
335
|
-
self.postMessage(
|
|
335
|
+
self.postMessage(c, [e.buffer]), e = null;
|
|
336
336
|
return;
|
|
337
337
|
}
|
|
338
|
-
const
|
|
339
|
-
if (!
|
|
338
|
+
const A = i.x, d = i.y, M = i.z, C = l.x, m = l.y, _ = l.z, T = 1e-4, j = Math.abs(A - w.x) > T || Math.abs(d - w.y) > T || Math.abs(M - w.z) > T, N = Math.abs(C - b.x) > T || Math.abs(m - b.y) > T || Math.abs(_ - b.z) > T;
|
|
339
|
+
if (!x && !j && !N)
|
|
340
340
|
return;
|
|
341
|
-
|
|
342
|
-
let
|
|
343
|
-
for (let
|
|
344
|
-
const
|
|
345
|
-
|
|
341
|
+
x = !1, w.x = A, w.y = d, w.z = M, b.x = C, b.y = m, b.z = _;
|
|
342
|
+
let O = 1 / 0, X = -1 / 0;
|
|
343
|
+
for (let c = 0; c < 8; ++c) {
|
|
344
|
+
const u = c & 1 ? f.x : y.x, g = c & 2 ? f.y : y.y, p = c & 4 ? f.z : y.z, I = u * C + g * m + p * _;
|
|
345
|
+
O = Math.min(O, I), X = Math.max(X, I);
|
|
346
346
|
}
|
|
347
|
-
const
|
|
347
|
+
const B = o.length / 3, G = X - O, D = (1 << Math.max(
|
|
348
348
|
10,
|
|
349
|
-
Math.min(20, Math.ceil(Math.log2(
|
|
349
|
+
Math.min(20, Math.ceil(Math.log2(B / 4)))
|
|
350
350
|
)) + 1;
|
|
351
|
-
if ((!
|
|
352
|
-
for (let
|
|
353
|
-
|
|
354
|
-
} else if (
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
for (let
|
|
358
|
-
const
|
|
351
|
+
if ((!v || v.length !== B) && (v = new Uint32Array(B)), !S || S.length !== D ? S = new Uint32Array(D) : S.fill(0), G < 1e-7) {
|
|
352
|
+
for (let c = 0; c < B; ++c) v[c] = 0;
|
|
353
|
+
S[0] = B;
|
|
354
|
+
} else if (r && r.length > 0) {
|
|
355
|
+
const c = r.length / 6;
|
|
356
|
+
V.fill(0);
|
|
357
|
+
for (let p = 0; p < c; ++p) {
|
|
358
|
+
const I = p * 6, E = r[I + 0], U = r[I + 1], q = r[I + 2], P = r[I + 3], F = E * C + U * m + q * _ - O, W = F - P, L = F + P, $ = Math.max(
|
|
359
359
|
0,
|
|
360
|
-
Math.floor(
|
|
361
|
-
),
|
|
362
|
-
|
|
363
|
-
Math.ceil(
|
|
360
|
+
Math.floor(W * z / G)
|
|
361
|
+
), J = Math.min(
|
|
362
|
+
z,
|
|
363
|
+
Math.ceil(L * z / G)
|
|
364
364
|
);
|
|
365
|
-
for (let
|
|
366
|
-
|
|
365
|
+
for (let H = $; H < J; ++H)
|
|
366
|
+
V[H]++;
|
|
367
367
|
}
|
|
368
|
-
let
|
|
369
|
-
for (let
|
|
370
|
-
|
|
371
|
-
for (let
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const
|
|
375
|
-
for (let
|
|
376
|
-
const
|
|
368
|
+
let u = 0;
|
|
369
|
+
for (let p = 0; p < z; ++p) u += V[p];
|
|
370
|
+
R[0] = 0, Y[0] = 0;
|
|
371
|
+
for (let p = 1; p < z; ++p)
|
|
372
|
+
R[p - 1] = V[p - 1] / u * D >>> 0, Y[p] = Y[p - 1] + R[p - 1];
|
|
373
|
+
R[z - 1] = V[z - 1] / u * D >>> 0;
|
|
374
|
+
const g = G / z;
|
|
375
|
+
for (let p = 0; p < B; ++p) {
|
|
376
|
+
const I = p * 3, E = o[I + 0], U = o[I + 1], q = o[I + 2], P = E * C + U * m + q * _, W = (X - P) / g, L = Math.max(
|
|
377
377
|
0,
|
|
378
378
|
Math.min(
|
|
379
|
-
|
|
380
|
-
Math.floor(
|
|
379
|
+
z - 1,
|
|
380
|
+
Math.floor(W)
|
|
381
381
|
)
|
|
382
|
-
),
|
|
383
|
-
|
|
382
|
+
), $ = W - L, J = Y[L] + R[L] * $ >>> 0, H = Math.min(J, D - 1);
|
|
383
|
+
v[p] = H, S[H]++;
|
|
384
384
|
}
|
|
385
385
|
} else {
|
|
386
|
-
const
|
|
387
|
-
for (let
|
|
388
|
-
const
|
|
389
|
-
|
|
386
|
+
const c = (D - 1) / G;
|
|
387
|
+
for (let u = 0; u < B; ++u) {
|
|
388
|
+
const g = u * 3, p = o[g + 0], I = o[g + 1], E = o[g + 2], U = p * C + I * m + E * _, P = (X - U) * c >>> 0, F = Math.min(P, D - 1);
|
|
389
|
+
v[u] = F, S[F]++;
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
|
-
for (let
|
|
393
|
-
|
|
394
|
-
for (let
|
|
395
|
-
const
|
|
396
|
-
e[
|
|
392
|
+
for (let c = 1; c < D; c++)
|
|
393
|
+
S[c] += S[c - 1];
|
|
394
|
+
for (let c = B - 1; c >= 0; c--) {
|
|
395
|
+
const u = v[c], g = --S[u];
|
|
396
|
+
e[g] = n ? n[c] : c;
|
|
397
397
|
}
|
|
398
|
-
const
|
|
398
|
+
const rt = A * C + d * m + M * _, Q = (c) => {
|
|
399
399
|
if (!e) return -1 / 0;
|
|
400
|
-
const
|
|
401
|
-
if (!
|
|
400
|
+
const u = e[c], g = u;
|
|
401
|
+
if (!o || g * 3 + 2 >= o.length)
|
|
402
402
|
return -1 / 0;
|
|
403
|
-
const
|
|
404
|
-
return
|
|
403
|
+
const p = g * 3;
|
|
404
|
+
return o[p] * C + o[p + 1] * m + o[p + 2] * _ - rt;
|
|
405
405
|
};
|
|
406
|
-
let
|
|
407
|
-
if (
|
|
408
|
-
const
|
|
406
|
+
let tt = B;
|
|
407
|
+
if (B > 0 && Q(B - 1) < 0) {
|
|
408
|
+
const c = ot(
|
|
409
409
|
0,
|
|
410
|
-
|
|
411
|
-
|
|
410
|
+
B - 1,
|
|
411
|
+
Q
|
|
412
412
|
);
|
|
413
|
-
|
|
413
|
+
tt = c < 0 ? ~c : c;
|
|
414
414
|
}
|
|
415
|
-
const
|
|
415
|
+
const st = {
|
|
416
416
|
order: e.buffer,
|
|
417
|
-
count:
|
|
417
|
+
count: tt
|
|
418
418
|
};
|
|
419
|
-
self.postMessage(
|
|
419
|
+
self.postMessage(st, [e.buffer]), e = null;
|
|
420
420
|
};
|
|
421
|
-
self.onmessage = (
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
let
|
|
425
|
-
if (
|
|
426
|
-
if (
|
|
427
|
-
for (let
|
|
428
|
-
const m =
|
|
429
|
-
|
|
430
|
-
(
|
|
421
|
+
self.onmessage = (A) => {
|
|
422
|
+
const d = A.data;
|
|
423
|
+
d.order && (e = new Uint32Array(d.order));
|
|
424
|
+
let M = !1;
|
|
425
|
+
if (d.centers && (o = new Float32Array(d.centers), M = !0, x = !0), Object.prototype.hasOwnProperty.call(d, "mapping") && (n = d.mapping ? new Uint32Array(d.mapping) : null, x = !0), d.chunks) {
|
|
426
|
+
if (r = new Float32Array(d.chunks), r.length > 0 && r[3] > 0)
|
|
427
|
+
for (let C = 0; C < r.length / 6; ++C) {
|
|
428
|
+
const m = C * 6, _ = r[m + 0], T = r[m + 1], j = r[m + 2], N = r[m + 3], O = r[m + 4], X = r[m + 5];
|
|
429
|
+
r[m + 0] = (_ + N) * 0.5, r[m + 1] = (T + O) * 0.5, r[m + 2] = (j + X) * 0.5, r[m + 3] = Math.sqrt(
|
|
430
|
+
(N - _) ** 2 + (O - T) ** 2 + (X - j) ** 2
|
|
431
431
|
) * 0.5;
|
|
432
432
|
}
|
|
433
|
-
|
|
433
|
+
x = !0;
|
|
434
434
|
}
|
|
435
|
-
if (
|
|
436
|
-
|
|
437
|
-
for (let
|
|
438
|
-
const m =
|
|
439
|
-
|
|
435
|
+
if (M && o && o.length > 0) {
|
|
436
|
+
f.x = y.x = o[0], f.y = y.y = o[1], f.z = y.z = o[2];
|
|
437
|
+
for (let C = 1; C < o.length / 3; C++) {
|
|
438
|
+
const m = C * 3;
|
|
439
|
+
f.x = Math.min(f.x, o[m + 0]), y.x = Math.max(y.x, o[m + 0]), f.y = Math.min(f.y, o[m + 1]), y.y = Math.max(y.y, o[m + 1]), f.z = Math.min(f.z, o[m + 2]), y.z = Math.max(y.z, o[m + 2]);
|
|
440
440
|
}
|
|
441
|
-
} else
|
|
442
|
-
|
|
441
|
+
} else M && o && o.length === 0 && (f.x = y.x = f.y = y.y = f.z = y.z = 0);
|
|
442
|
+
d.cameraPosition && (i = d.cameraPosition), d.cameraDirection && (l = d.cameraDirection), K();
|
|
443
443
|
};
|
|
444
444
|
}).toString()})();`;
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
|
-
const
|
|
448
|
-
const s =
|
|
447
|
+
const gt = (k, t) => {
|
|
448
|
+
const s = ut(k), e = ut(t);
|
|
449
449
|
return s | e << 16;
|
|
450
450
|
};
|
|
451
|
-
function
|
|
452
|
-
const t = new Float32Array([
|
|
453
|
-
let
|
|
454
|
-
const
|
|
455
|
-
return
|
|
451
|
+
function ut(k) {
|
|
452
|
+
const t = new Float32Array([k]), e = new Int32Array(t.buffer)[0];
|
|
453
|
+
let o = e >> 16 & 32768, r = e >> 12 & 2047;
|
|
454
|
+
const n = e >> 23 & 255;
|
|
455
|
+
return n < 103 ? o : n > 142 ? (o |= 31744, o |= (n === 255 ? 0 : 1) && e & 8388607, o) : n < 113 ? (r |= 2048, o |= (r >> 114 - n) + (r >> 113 - n & 1), o) : (o |= n - 112 << 10 | r >> 1, o += r & 1, o);
|
|
456
456
|
}
|
|
457
|
-
const
|
|
458
|
-
class
|
|
457
|
+
const vt = new ArrayBuffer(4), dt = new DataView(vt), wt = (k) => (dt.setUint32(0, k, !0), dt.getFloat32(0, !0));
|
|
458
|
+
class bt {
|
|
459
459
|
/**
|
|
460
460
|
* Create a new TextureManager for a set of splats
|
|
461
461
|
* @param splatData The splat data to manage textures for
|
|
462
462
|
*/
|
|
463
463
|
constructor(t) {
|
|
464
|
-
|
|
464
|
+
h(this, "transformA");
|
|
465
465
|
// position xyz and rotation quaternion y,z components
|
|
466
|
-
|
|
466
|
+
h(this, "transformB");
|
|
467
467
|
// rotation quaternion x and scale xyz
|
|
468
|
-
|
|
468
|
+
h(this, "colorTexture");
|
|
469
469
|
// color an opacity
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
470
|
+
h(this, "orderTexture");
|
|
471
|
+
h(this, "textureWidth");
|
|
472
|
+
h(this, "textureHeight");
|
|
473
473
|
const s = t.numSplats;
|
|
474
474
|
this.textureWidth = Math.ceil(Math.sqrt(s)), this.textureHeight = Math.ceil(s / this.textureWidth), this.transformA = this.createTransformATexture(t), this.transformB = this.createTransformBTexture(t), this.colorTexture = this.createColorTexture(t), this.orderTexture = this.createOrderTexture(s);
|
|
475
475
|
}
|
|
@@ -482,21 +482,21 @@ class xt {
|
|
|
482
482
|
const s = t.numSplats, e = new Float32Array(
|
|
483
483
|
this.textureWidth * this.textureHeight * 4
|
|
484
484
|
);
|
|
485
|
-
for (let
|
|
486
|
-
const
|
|
487
|
-
e[
|
|
488
|
-
const
|
|
489
|
-
e[
|
|
485
|
+
for (let r = 0; r < s; r++) {
|
|
486
|
+
const n = r * 4, i = r * 3, l = r * 4;
|
|
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], w = t.rotations[l + 1], b = gt(x, w);
|
|
489
|
+
e[n + 3] = wt(b);
|
|
490
490
|
}
|
|
491
|
-
const
|
|
491
|
+
const o = new a.DataTexture(
|
|
492
492
|
e,
|
|
493
493
|
this.textureWidth,
|
|
494
494
|
this.textureHeight,
|
|
495
|
-
|
|
496
|
-
|
|
495
|
+
a.RGBAFormat,
|
|
496
|
+
a.FloatType
|
|
497
497
|
// Store as Float32, shader will reinterpret bits
|
|
498
498
|
);
|
|
499
|
-
return
|
|
499
|
+
return o.needsUpdate = !0, o.magFilter = a.NearestFilter, o.minFilter = a.NearestFilter, o;
|
|
500
500
|
}
|
|
501
501
|
/**
|
|
502
502
|
* Create the transform B texture (scale and rotation xyz)
|
|
@@ -507,18 +507,18 @@ class xt {
|
|
|
507
507
|
const s = t.numSplats, e = new Float32Array(
|
|
508
508
|
this.textureWidth * this.textureHeight * 4
|
|
509
509
|
);
|
|
510
|
-
for (let
|
|
511
|
-
const
|
|
512
|
-
e[
|
|
510
|
+
for (let r = 0; r < s; r++) {
|
|
511
|
+
const n = r * 4, i = r * 3, l = r * 4;
|
|
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 o = new a.DataTexture(
|
|
515
515
|
e,
|
|
516
516
|
this.textureWidth,
|
|
517
517
|
this.textureHeight,
|
|
518
|
-
|
|
519
|
-
|
|
518
|
+
a.RGBAFormat,
|
|
519
|
+
a.FloatType
|
|
520
520
|
);
|
|
521
|
-
return
|
|
521
|
+
return o.needsUpdate = !0, o.magFilter = a.NearestFilter, o.minFilter = a.NearestFilter, o;
|
|
522
522
|
}
|
|
523
523
|
/**
|
|
524
524
|
* Create the color texture (RGB and opacity)
|
|
@@ -529,18 +529,18 @@ class xt {
|
|
|
529
529
|
const s = t.numSplats, e = new Float32Array(
|
|
530
530
|
this.textureWidth * this.textureHeight * 4
|
|
531
531
|
);
|
|
532
|
-
for (let
|
|
533
|
-
const
|
|
534
|
-
e[
|
|
532
|
+
for (let r = 0; r < s; r++) {
|
|
533
|
+
const n = r * 4, i = r * 3;
|
|
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 o = new a.DataTexture(
|
|
537
537
|
e,
|
|
538
538
|
this.textureWidth,
|
|
539
539
|
this.textureHeight,
|
|
540
|
-
|
|
541
|
-
|
|
540
|
+
a.RGBAFormat,
|
|
541
|
+
a.FloatType
|
|
542
542
|
);
|
|
543
|
-
return
|
|
543
|
+
return o.needsUpdate = !0, o;
|
|
544
544
|
}
|
|
545
545
|
/**
|
|
546
546
|
* Create the order texture for sorting
|
|
@@ -549,14 +549,14 @@ class xt {
|
|
|
549
549
|
*/
|
|
550
550
|
createOrderTexture(t) {
|
|
551
551
|
const s = new Uint32Array(this.textureWidth * this.textureHeight);
|
|
552
|
-
for (let
|
|
553
|
-
s[
|
|
554
|
-
const e = new
|
|
552
|
+
for (let o = 0; o < t; o++)
|
|
553
|
+
s[o] = o;
|
|
554
|
+
const e = new a.DataTexture(
|
|
555
555
|
s,
|
|
556
556
|
this.textureWidth,
|
|
557
557
|
this.textureHeight,
|
|
558
|
-
|
|
559
|
-
|
|
558
|
+
a.RedIntegerFormat,
|
|
559
|
+
a.UnsignedIntType
|
|
560
560
|
);
|
|
561
561
|
return e.needsUpdate = !0, e;
|
|
562
562
|
}
|
|
@@ -564,7 +564,7 @@ class xt {
|
|
|
564
564
|
this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
|
|
565
565
|
}
|
|
566
566
|
}
|
|
567
|
-
const
|
|
567
|
+
const Mt = (
|
|
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
|
+
), Ct = (
|
|
826
826
|
/* glsl */
|
|
827
827
|
`
|
|
828
828
|
precision highp float;
|
|
@@ -856,7 +856,7 @@ void main(void) {
|
|
|
856
856
|
}
|
|
857
857
|
`
|
|
858
858
|
);
|
|
859
|
-
class
|
|
859
|
+
class St extends a.ShaderMaterial {
|
|
860
860
|
constructor(t = {}) {
|
|
861
861
|
const s = {
|
|
862
862
|
// Textures (values set via methods)
|
|
@@ -865,39 +865,39 @@ class vt extends n.ShaderMaterial {
|
|
|
865
865
|
splatColor: { value: null },
|
|
866
866
|
splatOrder: { value: null },
|
|
867
867
|
// Other uniforms
|
|
868
|
-
viewport: { value: new
|
|
868
|
+
viewport: { value: new a.Vector2(1, 1) },
|
|
869
869
|
// Will be updated
|
|
870
870
|
numSplats: { value: 0 }
|
|
871
871
|
// Max splats to render (updated by sorter)
|
|
872
872
|
};
|
|
873
873
|
super({
|
|
874
|
-
vertexShader:
|
|
875
|
-
fragmentShader:
|
|
874
|
+
vertexShader: Mt,
|
|
875
|
+
fragmentShader: Ct,
|
|
876
876
|
uniforms: s,
|
|
877
877
|
transparent: !0,
|
|
878
|
-
blending:
|
|
878
|
+
blending: a.CustomBlending,
|
|
879
879
|
// Premultiplied alpha blending:
|
|
880
880
|
// color = src_color * src_alpha + dst_color * (1 - src_alpha)
|
|
881
881
|
// alpha = src_alpha * 1 + dst_alpha * (1 - src_alpha)
|
|
882
|
-
blendSrc:
|
|
882
|
+
blendSrc: a.OneFactor,
|
|
883
883
|
// Using ONE because shader outputs premultiplied color (color * alpha)
|
|
884
|
-
blendDst:
|
|
885
|
-
blendSrcAlpha:
|
|
884
|
+
blendDst: a.OneMinusSrcAlphaFactor,
|
|
885
|
+
blendSrcAlpha: a.OneFactor,
|
|
886
886
|
// source alpha comes from shader
|
|
887
|
-
blendDstAlpha:
|
|
888
|
-
blendEquation:
|
|
889
|
-
blendEquationAlpha:
|
|
887
|
+
blendDstAlpha: a.OneMinusSrcAlphaFactor,
|
|
888
|
+
blendEquation: a.AddEquation,
|
|
889
|
+
blendEquationAlpha: a.AddEquation,
|
|
890
890
|
depthTest: !0,
|
|
891
891
|
depthWrite: !1,
|
|
892
892
|
// Disable depth write for transparency
|
|
893
|
-
side:
|
|
893
|
+
side: a.DoubleSide,
|
|
894
894
|
// Render both sides (or CULLFACE_NONE equivalent)
|
|
895
895
|
// Optional settings from constructor
|
|
896
896
|
alphaTest: t.alphaTest !== void 0 ? t.alphaTest : 0,
|
|
897
897
|
// Typically 0 for blending
|
|
898
898
|
toneMapped: t.toneMapped !== void 0 ? t.toneMapped : !1
|
|
899
899
|
// prettier-ignore
|
|
900
|
-
}), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending =
|
|
900
|
+
}), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = a.NoBlending);
|
|
901
901
|
}
|
|
902
902
|
/**
|
|
903
903
|
* Update the viewport size
|
|
@@ -943,7 +943,7 @@ class vt extends n.ShaderMaterial {
|
|
|
943
943
|
this.uniforms.numSplats.value = t;
|
|
944
944
|
}
|
|
945
945
|
}
|
|
946
|
-
const
|
|
946
|
+
const et = class et extends a.Mesh {
|
|
947
947
|
// Match shader constant
|
|
948
948
|
/**
|
|
949
949
|
* Create a new SplatMesh for rendering Gaussian splats
|
|
@@ -951,39 +951,39 @@ const j = class j extends n.Mesh {
|
|
|
951
951
|
* @param options Rendering options
|
|
952
952
|
*/
|
|
953
953
|
constructor(s, e = {}) {
|
|
954
|
-
const
|
|
955
|
-
super(
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
954
|
+
const o = new St(e), r = et.createInstancedGeometry(s.numSplats, et.INSTANCE_SIZE);
|
|
955
|
+
super(r, o);
|
|
956
|
+
h(this, "sorter");
|
|
957
|
+
h(this, "splatData");
|
|
958
|
+
h(this, "options");
|
|
959
|
+
h(this, "textureManager");
|
|
960
|
+
h(this, "material");
|
|
961
|
+
h(this, "geometry");
|
|
962
|
+
h(this, "lastCameraPositionLocal", new a.Vector3());
|
|
963
|
+
h(this, "lastCameraDirectionLocal", new a.Vector3());
|
|
964
|
+
h(this, "invModelMatrix", new a.Matrix4());
|
|
965
965
|
// Cached inverse matrix
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
966
|
+
h(this, "_vpW", -1);
|
|
967
|
+
h(this, "_vpH", -1);
|
|
968
|
+
h(this, "_size", new a.Vector2());
|
|
969
|
+
h(this, "_camPosW", new a.Vector3());
|
|
970
|
+
h(this, "_camDirW", new a.Vector3());
|
|
971
|
+
h(this, "_camPosL", new a.Vector3());
|
|
972
|
+
h(this, "_camDirL", new a.Vector3());
|
|
973
|
+
h(this, "onSorterUpdated", (s) => {
|
|
974
974
|
const e = s.count;
|
|
975
|
-
this.geometry.instanceCount = Math.ceil(e /
|
|
975
|
+
this.geometry.instanceCount = Math.ceil(e / et.INSTANCE_SIZE), this.material.setNumSplats(e);
|
|
976
976
|
});
|
|
977
|
-
this.geometry =
|
|
977
|
+
this.geometry = r, this.material = o, this.splatData = s, this.frustumCulled = !1, this.options = {
|
|
978
978
|
autoSort: !0,
|
|
979
979
|
...e
|
|
980
|
-
}, this.textureManager = new
|
|
981
|
-
let
|
|
982
|
-
|
|
980
|
+
}, this.textureManager = new bt(s), this.sorter = new yt();
|
|
981
|
+
let n = this.createChunks() || void 0;
|
|
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
984
|
this.splatData.centers,
|
|
985
|
-
|
|
986
|
-
), this.material.setTransformA(this.textureManager.transformA), this.material.setTransformB(this.textureManager.transformB), this.material.setColorTexture(this.textureManager.colorTexture), this.material.setOrderTexture(this.textureManager.orderTexture), this.material.setNumSplats(0), this.geometry.boundingBox = s.boundingBox.toBox3(), this.geometry.boundingSphere = new
|
|
985
|
+
n ?? void 0
|
|
986
|
+
), this.material.setTransformA(this.textureManager.transformA), this.material.setTransformB(this.textureManager.transformB), this.material.setColorTexture(this.textureManager.colorTexture), this.material.setOrderTexture(this.textureManager.orderTexture), this.material.setNumSplats(0), this.geometry.boundingBox = s.boundingBox.toBox3(), this.geometry.boundingSphere = new a.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
|
|
987
987
|
}
|
|
988
988
|
/**
|
|
989
989
|
* Creates the instanced geometry for rendering splats.
|
|
@@ -992,7 +992,7 @@ const j = class j extends n.Mesh {
|
|
|
992
992
|
* @returns InstancedBufferGeometry
|
|
993
993
|
*/
|
|
994
994
|
static createInstancedGeometry(s, e) {
|
|
995
|
-
const
|
|
995
|
+
const o = Math.ceil(s / e), r = new a.BufferGeometry(), n = new Float32Array([
|
|
996
996
|
// x, y, splat_index_in_instance
|
|
997
997
|
-1,
|
|
998
998
|
-1,
|
|
@@ -1006,24 +1006,24 @@ const j = class j extends n.Mesh {
|
|
|
1006
1006
|
-1,
|
|
1007
1007
|
1,
|
|
1008
1008
|
0
|
|
1009
|
-
]),
|
|
1010
|
-
for (let
|
|
1011
|
-
const
|
|
1012
|
-
for (let
|
|
1013
|
-
|
|
1009
|
+
]), i = new Uint16Array([0, 1, 2, 0, 2, 3]), l = new Float32Array(4 * 3 * e);
|
|
1010
|
+
for (let f = 0; f < e; f++) {
|
|
1011
|
+
const y = f * 4 * 3;
|
|
1012
|
+
for (let v = 0; v < 4; v++)
|
|
1013
|
+
l[y + v * 3 + 0] = n[v * 3 + 0], l[y + v * 3 + 1] = n[v * 3 + 1], l[y + v * 3 + 2] = f;
|
|
1014
1014
|
}
|
|
1015
|
-
const
|
|
1016
|
-
for (let
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1015
|
+
const x = new Uint32Array(6 * e);
|
|
1016
|
+
for (let f = 0; f < e; f++) {
|
|
1017
|
+
const y = f * 6, v = f * 4;
|
|
1018
|
+
x[y + 0] = i[0] + v, x[y + 1] = i[1] + v, x[y + 2] = i[2] + v, x[y + 3] = i[3] + v, x[y + 4] = i[4] + v, x[y + 5] = i[5] + v;
|
|
1019
1019
|
}
|
|
1020
|
-
|
|
1021
|
-
const
|
|
1022
|
-
|
|
1023
|
-
const
|
|
1024
|
-
for (let
|
|
1025
|
-
|
|
1026
|
-
return
|
|
1020
|
+
r.setAttribute("position", new a.BufferAttribute(l, 3)), r.setIndex(new a.BufferAttribute(x, 1));
|
|
1021
|
+
const w = new a.InstancedBufferGeometry();
|
|
1022
|
+
w.index = r.index, w.setAttribute("position", r.getAttribute("position"));
|
|
1023
|
+
const b = new Uint32Array(o);
|
|
1024
|
+
for (let f = 0; f < o; f++)
|
|
1025
|
+
b[f] = f * e;
|
|
1026
|
+
return w.setAttribute("splatInstanceIndex", new a.InstancedBufferAttribute(b, 1, !1)), w.instanceCount = 0, w;
|
|
1027
1027
|
}
|
|
1028
1028
|
/**
|
|
1029
1029
|
* Create chunks data (bounding box min/max) for the sorter.
|
|
@@ -1054,8 +1054,8 @@ const j = class j extends n.Mesh {
|
|
|
1054
1054
|
*/
|
|
1055
1055
|
sort(s) {
|
|
1056
1056
|
s.getWorldPosition(this._camPosW), s.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);
|
|
1057
|
-
const e = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6,
|
|
1058
|
-
this.options.autoSort && (e ||
|
|
1057
|
+
const e = this.lastCameraPositionLocal.distanceToSquared(this._camPosL) > 1e-6, o = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
|
|
1058
|
+
this.options.autoSort && (e || o) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
|
|
1059
1059
|
}
|
|
1060
1060
|
/**
|
|
1061
1061
|
* THREE.js hook called before rendering the object.
|
|
@@ -1066,8 +1066,8 @@ const j = class j extends n.Mesh {
|
|
|
1066
1066
|
*/
|
|
1067
1067
|
// prettier-ignore
|
|
1068
1068
|
// @ts-expect-error scene is not used
|
|
1069
|
-
onBeforeRender(s, e,
|
|
1070
|
-
this.sort(
|
|
1069
|
+
onBeforeRender(s, e, o) {
|
|
1070
|
+
this.sort(o), s.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
|
|
1071
1071
|
}
|
|
1072
1072
|
/**
|
|
1073
1073
|
* Dispose of resources
|
|
@@ -1077,9 +1077,41 @@ const j = class j extends n.Mesh {
|
|
|
1077
1077
|
}
|
|
1078
1078
|
};
|
|
1079
1079
|
/** Number of splats combined into a single instanced draw call. */
|
|
1080
|
-
|
|
1081
|
-
let
|
|
1082
|
-
class
|
|
1080
|
+
h(et, "INSTANCE_SIZE", 128);
|
|
1081
|
+
let ft = et;
|
|
1082
|
+
class zt extends a.Loader {
|
|
1083
|
+
constructor(s) {
|
|
1084
|
+
super(s);
|
|
1085
|
+
h(this, "requestId", 0);
|
|
1086
|
+
h(this, "worker");
|
|
1087
|
+
h(this, "pendingCallbacks", /* @__PURE__ */ new Map());
|
|
1088
|
+
const e = this.createWorkerCode(), o = new Blob([e], { type: "application/javascript" });
|
|
1089
|
+
this.worker = new Worker(URL.createObjectURL(o)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Handles messages received from the parsing worker
|
|
1093
|
+
* @param event The message event from the worker
|
|
1094
|
+
*/
|
|
1095
|
+
onWorkerMessage(s) {
|
|
1096
|
+
const { requestId: e, error: o, result: r } = s.data, n = this.pendingCallbacks.get(e);
|
|
1097
|
+
if (!n) return console.warn(`PlyLoader: Received response for unknown request ${e}`);
|
|
1098
|
+
if (this.pendingCallbacks.delete(e), o) return n.reject(new Error(o));
|
|
1099
|
+
if (!r) return n.reject(new Error("Worker returned no result"));
|
|
1100
|
+
try {
|
|
1101
|
+
const i = new xt(0);
|
|
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.centers = new Float32Array(r.centers), i.boundingBox.min.set(
|
|
1103
|
+
r.boundingBox.minX,
|
|
1104
|
+
r.boundingBox.minY,
|
|
1105
|
+
r.boundingBox.minZ
|
|
1106
|
+
), i.boundingBox.max.set(
|
|
1107
|
+
r.boundingBox.maxX,
|
|
1108
|
+
r.boundingBox.maxY,
|
|
1109
|
+
r.boundingBox.maxZ
|
|
1110
|
+
), n.resolve(i);
|
|
1111
|
+
} catch (i) {
|
|
1112
|
+
n.reject(i);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1083
1115
|
/**
|
|
1084
1116
|
* Load a PLY file with Gaussian Splat data
|
|
1085
1117
|
* @param url URL of the PLY file
|
|
@@ -1087,21 +1119,18 @@ class bt extends n.Loader {
|
|
|
1087
1119
|
* @param onProgress Optional progress callback
|
|
1088
1120
|
* @param onError Optional error callback
|
|
1089
1121
|
*/
|
|
1090
|
-
load(
|
|
1091
|
-
const
|
|
1092
|
-
|
|
1093
|
-
|
|
1122
|
+
load(s, e, o, r) {
|
|
1123
|
+
const n = new a.FileLoader(this.manager);
|
|
1124
|
+
n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
|
|
1125
|
+
s,
|
|
1094
1126
|
(i) => {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
} catch (a) {
|
|
1101
|
-
r ? r(a) : console.error(a), this.manager.itemError(t);
|
|
1102
|
-
}
|
|
1127
|
+
this.parseAsync(i).then((l) => {
|
|
1128
|
+
e && e(l);
|
|
1129
|
+
}).catch((l) => {
|
|
1130
|
+
r ? r(l) : console.error(l), this.manager.itemError(s);
|
|
1131
|
+
});
|
|
1103
1132
|
},
|
|
1104
|
-
|
|
1133
|
+
o,
|
|
1105
1134
|
r
|
|
1106
1135
|
);
|
|
1107
1136
|
}
|
|
@@ -1111,197 +1140,257 @@ class bt extends n.Loader {
|
|
|
1111
1140
|
* @param onProgress Optional progress callback
|
|
1112
1141
|
* @returns A Promise that resolves with the parsed SplatData
|
|
1113
1142
|
*/
|
|
1114
|
-
loadAsync(
|
|
1115
|
-
return new Promise((
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1143
|
+
loadAsync(s, e) {
|
|
1144
|
+
return new Promise((o, r) => {
|
|
1145
|
+
const n = new a.FileLoader(this.manager);
|
|
1146
|
+
n.setResponseType("arraybuffer"), n.setRequestHeader(this.requestHeader), n.setPath(this.path), n.setWithCredentials(this.withCredentials), n.load(
|
|
1147
|
+
s,
|
|
1119
1148
|
(i) => {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
} catch (a) {
|
|
1124
|
-
r(a), this.manager.itemError(t);
|
|
1125
|
-
}
|
|
1149
|
+
this.parseAsync(i).then(o).catch((l) => {
|
|
1150
|
+
r(l), this.manager.itemError(s);
|
|
1151
|
+
});
|
|
1126
1152
|
},
|
|
1127
|
-
|
|
1153
|
+
e,
|
|
1128
1154
|
(i) => {
|
|
1129
|
-
r(i), this.manager.itemError(
|
|
1155
|
+
r(i), this.manager.itemError(s);
|
|
1130
1156
|
}
|
|
1131
1157
|
);
|
|
1132
1158
|
});
|
|
1133
1159
|
}
|
|
1134
1160
|
/**
|
|
1135
|
-
* Parse PLY buffer data
|
|
1161
|
+
* Parse PLY buffer data asynchronously using Web Worker
|
|
1136
1162
|
* @param buffer ArrayBuffer containing PLY data
|
|
1137
|
-
* @returns
|
|
1163
|
+
* @returns Promise that resolves with parsed SplatData
|
|
1138
1164
|
*/
|
|
1139
|
-
|
|
1140
|
-
|
|
1165
|
+
parseAsync(s) {
|
|
1166
|
+
return new Promise((e, o) => {
|
|
1167
|
+
const r = this.requestId++;
|
|
1168
|
+
this.pendingCallbacks.set(r, { resolve: e, reject: o });
|
|
1169
|
+
const n = {
|
|
1170
|
+
requestId: r,
|
|
1171
|
+
buffer: s
|
|
1172
|
+
};
|
|
1173
|
+
this.worker.postMessage(n, [s]);
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
/**
|
|
1177
|
+
* Terminate the Web Worker and clean up resources
|
|
1178
|
+
*/
|
|
1179
|
+
dispose() {
|
|
1180
|
+
this.worker && this.worker.terminate(), this.pendingCallbacks.clear();
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Creates the self-contained code for the parsing Web Worker
|
|
1184
|
+
* @returns A string containing the JavaScript code for the worker
|
|
1185
|
+
*/
|
|
1186
|
+
createWorkerCode() {
|
|
1187
|
+
return `(${(function() {
|
|
1188
|
+
self.onmessage = (o) => {
|
|
1189
|
+
const { requestId: r, buffer: n } = o.data;
|
|
1190
|
+
try {
|
|
1191
|
+
const i = e(n), l = {
|
|
1192
|
+
requestId: r,
|
|
1193
|
+
result: i
|
|
1194
|
+
};
|
|
1195
|
+
self.postMessage(l, [
|
|
1196
|
+
i.positions,
|
|
1197
|
+
i.rotations,
|
|
1198
|
+
i.scales,
|
|
1199
|
+
i.colors,
|
|
1200
|
+
i.opacities,
|
|
1201
|
+
i.centers
|
|
1202
|
+
]);
|
|
1203
|
+
} catch (i) {
|
|
1204
|
+
const l = {
|
|
1205
|
+
requestId: r,
|
|
1206
|
+
error: i instanceof Error ? i.message : String(i)
|
|
1207
|
+
};
|
|
1208
|
+
self.postMessage(l);
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
function e(o) {
|
|
1212
|
+
const r = new TextDecoder(), n = new Uint8Array(o), i = [112, 108, 121, 10], l = `
|
|
1141
1213
|
end_header
|
|
1142
1214
|
`;
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
throw new Error("Invalid PLY file: Missing magic bytes");
|
|
1146
|
-
let i = 0;
|
|
1147
|
-
for (let x = 0; x < e.length - o.length; x++) {
|
|
1148
|
-
let u = !0;
|
|
1149
|
-
for (let S = 0; S < o.length; S++)
|
|
1150
|
-
if (e[x + S] !== o.charCodeAt(S)) {
|
|
1151
|
-
u = !1;
|
|
1152
|
-
break;
|
|
1153
|
-
}
|
|
1154
|
-
if (u) {
|
|
1155
|
-
i = x + o.length;
|
|
1156
|
-
break;
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
if (i === 0)
|
|
1160
|
-
throw new Error("Invalid PLY file: Could not find end of header");
|
|
1161
|
-
const d = s.decode(e.subarray(0, i)).split(`
|
|
1162
|
-
`), f = [];
|
|
1163
|
-
let v = null;
|
|
1164
|
-
for (let x = 1; x < d.length; x++) {
|
|
1165
|
-
const u = d[x].trim();
|
|
1166
|
-
if (u === "" || u === "end_header") continue;
|
|
1167
|
-
const S = u.split(" ");
|
|
1168
|
-
switch (S[0]) {
|
|
1169
|
-
case "format":
|
|
1170
|
-
v = S[1];
|
|
1171
|
-
break;
|
|
1172
|
-
case "element":
|
|
1173
|
-
f.push({
|
|
1174
|
-
name: S[1],
|
|
1175
|
-
count: parseInt(S[2], 10),
|
|
1176
|
-
properties: []
|
|
1177
|
-
});
|
|
1178
|
-
break;
|
|
1179
|
-
case "property":
|
|
1180
|
-
if (f.length === 0)
|
|
1215
|
+
for (let c = 0; c < i.length; c++)
|
|
1216
|
+
if (n[c] !== i[c])
|
|
1181
1217
|
throw new Error(
|
|
1182
|
-
"Invalid PLY file:
|
|
1218
|
+
"Invalid PLY file: Missing magic bytes"
|
|
1183
1219
|
);
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
const g = f.find((x) => x.name === "vertex");
|
|
1195
|
-
if (!g)
|
|
1196
|
-
throw new Error("Invalid PLY file: No vertex element found");
|
|
1197
|
-
const p = new ut(g.count), h = new DataView(t);
|
|
1198
|
-
let l = i;
|
|
1199
|
-
const b = (x) => g.properties.findIndex((u) => u.name === x), T = b("x"), O = b("y"), q = b("z"), E = [
|
|
1200
|
-
b("rot_0"),
|
|
1201
|
-
b("rot_1"),
|
|
1202
|
-
b("rot_2"),
|
|
1203
|
-
b("rot_3")
|
|
1204
|
-
], R = [
|
|
1205
|
-
b("scale_0"),
|
|
1206
|
-
b("scale_1"),
|
|
1207
|
-
b("scale_2")
|
|
1208
|
-
], W = [
|
|
1209
|
-
b("f_dc_0"),
|
|
1210
|
-
b("f_dc_1"),
|
|
1211
|
-
b("f_dc_2")
|
|
1212
|
-
], k = b("opacity");
|
|
1213
|
-
if ([
|
|
1214
|
-
T,
|
|
1215
|
-
O,
|
|
1216
|
-
q,
|
|
1217
|
-
...E,
|
|
1218
|
-
...R,
|
|
1219
|
-
...W,
|
|
1220
|
-
k
|
|
1221
|
-
].some((x) => x === -1))
|
|
1222
|
-
throw new Error("Invalid PLY file: Missing required properties");
|
|
1223
|
-
const F = 0.28209479177387814, M = (x) => {
|
|
1224
|
-
if (x > 0) return 1 / (1 + Math.exp(-x));
|
|
1225
|
-
const u = Math.exp(x);
|
|
1226
|
-
return u / (1 + u);
|
|
1227
|
-
}, m = new n.Vector3(), B = new n.Quaternion(), V = new n.Vector3(), P = new n.Color();
|
|
1228
|
-
for (let x = 0; x < g.count; x++) {
|
|
1229
|
-
const u = [];
|
|
1230
|
-
for (let I = 0; I < g.properties.length; I++) {
|
|
1231
|
-
const K = g.properties[I].type;
|
|
1232
|
-
let z;
|
|
1233
|
-
switch (K) {
|
|
1234
|
-
case "char":
|
|
1235
|
-
z = h.getInt8(l), l += 1;
|
|
1236
|
-
break;
|
|
1237
|
-
case "uchar":
|
|
1238
|
-
z = h.getUint8(l), l += 1;
|
|
1239
|
-
break;
|
|
1240
|
-
case "short":
|
|
1241
|
-
z = h.getInt16(l, !0), l += 2;
|
|
1242
|
-
break;
|
|
1243
|
-
case "ushort":
|
|
1244
|
-
z = h.getUint16(l, !0), l += 2;
|
|
1245
|
-
break;
|
|
1246
|
-
case "int":
|
|
1247
|
-
z = h.getInt32(l, !0), l += 4;
|
|
1248
|
-
break;
|
|
1249
|
-
case "uint":
|
|
1250
|
-
z = h.getUint32(l, !0), l += 4;
|
|
1251
|
-
break;
|
|
1252
|
-
case "float":
|
|
1253
|
-
z = h.getFloat32(l, !0), l += 4;
|
|
1254
|
-
break;
|
|
1255
|
-
case "double":
|
|
1256
|
-
z = h.getFloat64(l, !0), l += 8;
|
|
1220
|
+
let x = 0;
|
|
1221
|
+
for (let c = 0; c < n.length - l.length; c++) {
|
|
1222
|
+
let u = !0;
|
|
1223
|
+
for (let g = 0; g < l.length; g++)
|
|
1224
|
+
if (n[c + g] !== l.charCodeAt(g)) {
|
|
1225
|
+
u = !1;
|
|
1226
|
+
break;
|
|
1227
|
+
}
|
|
1228
|
+
if (u) {
|
|
1229
|
+
x = c + l.length;
|
|
1257
1230
|
break;
|
|
1258
|
-
|
|
1259
|
-
throw new Error(`Unsupported property type: ${K}`);
|
|
1231
|
+
}
|
|
1260
1232
|
}
|
|
1261
|
-
|
|
1233
|
+
if (x === 0)
|
|
1234
|
+
throw new Error(
|
|
1235
|
+
"Invalid PLY file: Could not find end of header"
|
|
1236
|
+
);
|
|
1237
|
+
const b = r.decode(
|
|
1238
|
+
n.subarray(0, x)
|
|
1239
|
+
).split(`
|
|
1240
|
+
`), f = [];
|
|
1241
|
+
let y = null;
|
|
1242
|
+
for (let c = 1; c < b.length; c++) {
|
|
1243
|
+
const u = b[c].trim();
|
|
1244
|
+
if (u === "" || u === "end_header") continue;
|
|
1245
|
+
const g = u.split(" ");
|
|
1246
|
+
switch (g[0]) {
|
|
1247
|
+
case "format":
|
|
1248
|
+
y = g[1];
|
|
1249
|
+
break;
|
|
1250
|
+
case "element":
|
|
1251
|
+
f.push({
|
|
1252
|
+
name: g[1],
|
|
1253
|
+
count: parseInt(g[2], 10),
|
|
1254
|
+
properties: []
|
|
1255
|
+
});
|
|
1256
|
+
break;
|
|
1257
|
+
case "property":
|
|
1258
|
+
if (f.length === 0)
|
|
1259
|
+
throw new Error(
|
|
1260
|
+
"Invalid PLY file: Property without element"
|
|
1261
|
+
);
|
|
1262
|
+
f[f.length - 1].properties.push({
|
|
1263
|
+
type: g[1],
|
|
1264
|
+
name: g[2]
|
|
1265
|
+
});
|
|
1266
|
+
break;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
if (y !== "binary_little_endian")
|
|
1270
|
+
throw new Error(`Unsupported PLY format: ${y}`);
|
|
1271
|
+
const v = f.find((c) => c.name === "vertex");
|
|
1272
|
+
if (!v)
|
|
1273
|
+
throw new Error(
|
|
1274
|
+
"Invalid PLY file: No vertex element found"
|
|
1275
|
+
);
|
|
1276
|
+
const S = v.count, z = new Float32Array(S * 3), V = new Float32Array(S * 4), Y = new Float32Array(S * 3), R = new Float32Array(S * 3), ot = new Float32Array(S), K = new Float32Array(S * 3), A = new DataView(o);
|
|
1277
|
+
let d = x;
|
|
1278
|
+
const M = (c) => v.properties.findIndex(
|
|
1279
|
+
(u) => u.name === c
|
|
1280
|
+
), C = M("x"), m = M("y"), _ = M("z"), T = [
|
|
1281
|
+
M("rot_0"),
|
|
1282
|
+
M("rot_1"),
|
|
1283
|
+
M("rot_2"),
|
|
1284
|
+
M("rot_3")
|
|
1285
|
+
], j = [
|
|
1286
|
+
M("scale_0"),
|
|
1287
|
+
M("scale_1"),
|
|
1288
|
+
M("scale_2")
|
|
1289
|
+
], N = [
|
|
1290
|
+
M("f_dc_0"),
|
|
1291
|
+
M("f_dc_1"),
|
|
1292
|
+
M("f_dc_2")
|
|
1293
|
+
], O = M("opacity");
|
|
1294
|
+
if ([
|
|
1295
|
+
C,
|
|
1296
|
+
m,
|
|
1297
|
+
_,
|
|
1298
|
+
...T,
|
|
1299
|
+
...j,
|
|
1300
|
+
...N,
|
|
1301
|
+
O
|
|
1302
|
+
].some((c) => c === -1))
|
|
1303
|
+
throw new Error(
|
|
1304
|
+
"Invalid PLY file: Missing required properties"
|
|
1305
|
+
);
|
|
1306
|
+
const B = 0.28209479177387814, G = (c) => {
|
|
1307
|
+
if (c > 0) return 1 / (1 + Math.exp(-c));
|
|
1308
|
+
const u = Math.exp(c);
|
|
1309
|
+
return u / (1 + u);
|
|
1310
|
+
};
|
|
1311
|
+
let nt = 1 / 0, D = 1 / 0, rt = 1 / 0, Q = -1 / 0, tt = -1 / 0, st = -1 / 0;
|
|
1312
|
+
for (let c = 0; c < S; c++) {
|
|
1313
|
+
const u = [];
|
|
1314
|
+
for (let ct = 0; ct < v.properties.length; ct++) {
|
|
1315
|
+
const ht = v.properties[ct].type;
|
|
1316
|
+
let Z;
|
|
1317
|
+
switch (ht) {
|
|
1318
|
+
case "char":
|
|
1319
|
+
Z = A.getInt8(d), d += 1;
|
|
1320
|
+
break;
|
|
1321
|
+
case "uchar":
|
|
1322
|
+
Z = A.getUint8(d), d += 1;
|
|
1323
|
+
break;
|
|
1324
|
+
case "short":
|
|
1325
|
+
Z = A.getInt16(d, !0), d += 2;
|
|
1326
|
+
break;
|
|
1327
|
+
case "ushort":
|
|
1328
|
+
Z = A.getUint16(d, !0), d += 2;
|
|
1329
|
+
break;
|
|
1330
|
+
case "int":
|
|
1331
|
+
Z = A.getInt32(d, !0), d += 4;
|
|
1332
|
+
break;
|
|
1333
|
+
case "uint":
|
|
1334
|
+
Z = A.getUint32(d, !0), d += 4;
|
|
1335
|
+
break;
|
|
1336
|
+
case "float":
|
|
1337
|
+
Z = A.getFloat32(d, !0), d += 4;
|
|
1338
|
+
break;
|
|
1339
|
+
case "double":
|
|
1340
|
+
Z = A.getFloat64(d, !0), d += 8;
|
|
1341
|
+
break;
|
|
1342
|
+
default:
|
|
1343
|
+
throw new Error(
|
|
1344
|
+
`Unsupported property type: ${ht}`
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1347
|
+
u.push(Z);
|
|
1348
|
+
}
|
|
1349
|
+
const g = u[C], p = u[m], I = u[_], E = c * 3;
|
|
1350
|
+
z[E] = g, z[E + 1] = p, z[E + 2] = I, nt = Math.min(nt, g), D = Math.min(D, p), rt = Math.min(rt, I), Q = Math.max(Q, g), tt = Math.max(tt, p), st = Math.max(st, I);
|
|
1351
|
+
let U = u[T[1]], q = u[T[2]], P = u[T[3]], F = u[T[0]];
|
|
1352
|
+
const W = Math.sqrt(
|
|
1353
|
+
U * U + q * q + P * P + F * F
|
|
1354
|
+
);
|
|
1355
|
+
W > 0 && (U /= W, q /= W, P /= W, F /= W), F < 0 && (U = -U, q = -q, P = -P, F = -F);
|
|
1356
|
+
const L = c * 4;
|
|
1357
|
+
V[L] = U, V[L + 1] = q, V[L + 2] = P, V[L + 3] = F;
|
|
1358
|
+
const $ = c * 3;
|
|
1359
|
+
Y[$] = u[j[0]], Y[$ + 1] = u[j[1]], Y[$ + 2] = u[j[2]];
|
|
1360
|
+
let J = 0.5 + u[N[0]] * B, H = 0.5 + u[N[1]] * B, it = 0.5 + u[N[2]] * B;
|
|
1361
|
+
J = Math.max(0, Math.min(1, J)), H = Math.max(0, Math.min(1, H)), it = Math.max(0, Math.min(1, it));
|
|
1362
|
+
const at = c * 3;
|
|
1363
|
+
R[at] = J, R[at + 1] = H, R[at + 2] = it, ot[c] = G(u[O]), K[E] = g, K[E + 1] = p, K[E + 2] = I;
|
|
1364
|
+
}
|
|
1365
|
+
return {
|
|
1366
|
+
numSplats: S,
|
|
1367
|
+
positions: z.buffer,
|
|
1368
|
+
rotations: V.buffer,
|
|
1369
|
+
scales: Y.buffer,
|
|
1370
|
+
colors: R.buffer,
|
|
1371
|
+
opacities: ot.buffer,
|
|
1372
|
+
centers: K.buffer,
|
|
1373
|
+
boundingBox: {
|
|
1374
|
+
minX: nt,
|
|
1375
|
+
minY: D,
|
|
1376
|
+
minZ: rt,
|
|
1377
|
+
maxX: Q,
|
|
1378
|
+
maxY: tt,
|
|
1379
|
+
maxZ: st
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1262
1382
|
}
|
|
1263
|
-
|
|
1264
|
-
u[T],
|
|
1265
|
-
u[O],
|
|
1266
|
-
u[q]
|
|
1267
|
-
), B.set(
|
|
1268
|
-
u[E[1]],
|
|
1269
|
-
// PLY stores rot 1,2,3,0 (x,y,z,w)
|
|
1270
|
-
u[E[2]],
|
|
1271
|
-
u[E[3]],
|
|
1272
|
-
u[E[0]]
|
|
1273
|
-
).normalize(), V.set(
|
|
1274
|
-
u[R[0]],
|
|
1275
|
-
// Read directly assuming it's log scale
|
|
1276
|
-
u[R[1]],
|
|
1277
|
-
u[R[2]]
|
|
1278
|
-
), P.set(
|
|
1279
|
-
0.5 + u[W[0]] * F,
|
|
1280
|
-
0.5 + u[W[1]] * F,
|
|
1281
|
-
0.5 + u[W[2]] * F
|
|
1282
|
-
), P.r = Math.max(0, Math.min(1, P.r)), P.g = Math.max(0, Math.min(1, P.g)), P.b = Math.max(0, Math.min(1, P.b));
|
|
1283
|
-
const S = M(u[k]);
|
|
1284
|
-
p.setSplat(
|
|
1285
|
-
x,
|
|
1286
|
-
m,
|
|
1287
|
-
B,
|
|
1288
|
-
V,
|
|
1289
|
-
// Pass log scale directly
|
|
1290
|
-
P,
|
|
1291
|
-
S
|
|
1292
|
-
);
|
|
1293
|
-
}
|
|
1294
|
-
return p.calculateBoundingBox(), p;
|
|
1383
|
+
}).toString()})();`;
|
|
1295
1384
|
}
|
|
1296
1385
|
}
|
|
1297
|
-
const
|
|
1386
|
+
const kt = "0.3.0";
|
|
1298
1387
|
export {
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1388
|
+
lt as BoundingBox,
|
|
1389
|
+
zt as PlyLoader,
|
|
1390
|
+
xt as SplatData,
|
|
1391
|
+
St as SplatMaterial,
|
|
1392
|
+
ft as SplatMesh,
|
|
1393
|
+
yt as SplatSorter,
|
|
1394
|
+
bt as TextureManager,
|
|
1395
|
+
kt as VERSION
|
|
1307
1396
|
};
|