@speridlabs/visus 0.2.0 → 1.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/README.md +85 -117
- package/dist/main.d.ts +1 -1
- package/dist/main.es.js +385 -394
- package/dist/main.umd.js +42 -51
- package/dist/react.es.js +464 -473
- package/package.json +1 -1
package/dist/main.es.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var f = (
|
|
4
|
-
import * as
|
|
1
|
+
var lt = Object.defineProperty;
|
|
2
|
+
var ht = (A, t, n) => t in A ? lt(A, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : A[t] = n;
|
|
3
|
+
var f = (A, t, n) => ht(A, typeof t != "symbol" ? t + "" : t, n);
|
|
4
|
+
import * as i from "three";
|
|
5
5
|
class et {
|
|
6
6
|
constructor() {
|
|
7
|
-
f(this, "min", new
|
|
8
|
-
f(this, "max", new
|
|
9
|
-
f(this, "center", new
|
|
7
|
+
f(this, "min", new i.Vector3(1 / 0, 1 / 0, 1 / 0));
|
|
8
|
+
f(this, "max", new i.Vector3(-1 / 0, -1 / 0, -1 / 0));
|
|
9
|
+
f(this, "center", new i.Vector3());
|
|
10
10
|
/** Half extents (size/2) */
|
|
11
|
-
f(this, "halfExtents", new
|
|
11
|
+
f(this, "halfExtents", new i.Vector3());
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Reset the bounding box to its initial state
|
|
@@ -49,7 +49,7 @@ class et {
|
|
|
49
49
|
* @returns THREE.Box3 representation
|
|
50
50
|
*/
|
|
51
51
|
toBox3() {
|
|
52
|
-
return new
|
|
52
|
+
return new i.Box3().set(this.min, this.max);
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* Create a clone of this bounding box
|
|
@@ -60,7 +60,7 @@ class et {
|
|
|
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 ut {
|
|
64
64
|
// TODO: there is no sh spherical harmonics
|
|
65
65
|
constructor(t = 0) {
|
|
66
66
|
f(this, "numSplats", 0);
|
|
@@ -85,13 +85,13 @@ class ht {
|
|
|
85
85
|
* @param color Color
|
|
86
86
|
* @param opacity Opacity value
|
|
87
87
|
*/
|
|
88
|
-
setSplat(t,
|
|
88
|
+
setSplat(t, n, e, r, s, o) {
|
|
89
89
|
if (t >= this.numSplats)
|
|
90
90
|
throw new Error(
|
|
91
91
|
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
92
92
|
);
|
|
93
93
|
const a = t * 3, c = t * 4, h = t * 3, v = t * 3;
|
|
94
|
-
this.positions[a] =
|
|
94
|
+
this.positions[a] = n.x, this.positions[a + 1] = n.y, this.positions[a + 2] = n.z, this.rotations[c] = e.x, this.rotations[c + 1] = e.y, this.rotations[c + 2] = e.z, this.rotations[c + 3] = e.w, this.scales[h] = r.x, this.scales[h + 1] = r.y, this.scales[h + 2] = r.z, this.colors[v] = s.r, this.colors[v + 1] = s.g, this.colors[v + 2] = s.b, this.opacities[t] = o, this.centers[a] = n.x, this.centers[a + 1] = n.y, this.centers[a + 2] = n.z;
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Get a splat's data
|
|
@@ -103,26 +103,26 @@ class ht {
|
|
|
103
103
|
throw new Error(
|
|
104
104
|
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
105
105
|
);
|
|
106
|
-
const
|
|
106
|
+
const n = t * 3, e = t * 4, r = t * 3, s = t * 3;
|
|
107
107
|
return {
|
|
108
|
-
position: new
|
|
109
|
-
this.positions[
|
|
110
|
-
this.positions[
|
|
111
|
-
this.positions[
|
|
108
|
+
position: new i.Vector3(
|
|
109
|
+
this.positions[n],
|
|
110
|
+
this.positions[n + 1],
|
|
111
|
+
this.positions[n + 2]
|
|
112
112
|
),
|
|
113
|
-
rotation: new
|
|
113
|
+
rotation: new i.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 i.Vector3(
|
|
121
|
+
Math.exp(this.scales[r]),
|
|
122
|
+
Math.exp(this.scales[r + 1]),
|
|
123
|
+
Math.exp(this.scales[r + 2])
|
|
124
124
|
),
|
|
125
|
-
color: new
|
|
125
|
+
color: new i.Color(
|
|
126
126
|
this.colors[s],
|
|
127
127
|
this.colors[s + 1],
|
|
128
128
|
this.colors[s + 2]
|
|
@@ -136,9 +136,9 @@ class ht {
|
|
|
136
136
|
*/
|
|
137
137
|
calculateBoundingBox() {
|
|
138
138
|
this.boundingBox.reset();
|
|
139
|
-
const t = new
|
|
140
|
-
for (let
|
|
141
|
-
const e =
|
|
139
|
+
const t = new i.Vector3();
|
|
140
|
+
for (let n = 0; n < this.numSplats; n++) {
|
|
141
|
+
const e = n * 3;
|
|
142
142
|
t.set(
|
|
143
143
|
this.positions[e],
|
|
144
144
|
this.positions[e + 1],
|
|
@@ -152,37 +152,37 @@ class ht {
|
|
|
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 i.BufferGeometry();
|
|
156
156
|
t.setAttribute(
|
|
157
157
|
"position",
|
|
158
|
-
new
|
|
158
|
+
new i.BufferAttribute(this.positions, 3)
|
|
159
159
|
);
|
|
160
|
-
const
|
|
160
|
+
const n = new Float32Array(this.numSplats * 3), e = new i.Quaternion(), r = new i.Euler();
|
|
161
161
|
for (let s = 0; s < this.numSplats; s++) {
|
|
162
|
-
const
|
|
162
|
+
const o = s * 4, a = s * 3;
|
|
163
163
|
e.set(
|
|
164
|
-
this.rotations[
|
|
165
|
-
this.rotations[
|
|
166
|
-
this.rotations[
|
|
167
|
-
this.rotations[
|
|
168
|
-
),
|
|
164
|
+
this.rotations[o],
|
|
165
|
+
this.rotations[o + 1],
|
|
166
|
+
this.rotations[o + 2],
|
|
167
|
+
this.rotations[o + 3]
|
|
168
|
+
), r.setFromQuaternion(e), n[a] = r.x, n[a + 1] = r.y, n[a + 2] = r.z;
|
|
169
169
|
}
|
|
170
170
|
return t.setAttribute(
|
|
171
171
|
"rotation",
|
|
172
|
-
new
|
|
172
|
+
new i.BufferAttribute(n, 3)
|
|
173
173
|
), t.setAttribute(
|
|
174
174
|
"scale",
|
|
175
|
-
new
|
|
175
|
+
new i.BufferAttribute(this.scales, 3)
|
|
176
176
|
), t.setAttribute(
|
|
177
177
|
"color",
|
|
178
|
-
new
|
|
178
|
+
new i.BufferAttribute(this.colors, 3)
|
|
179
179
|
), t.setAttribute(
|
|
180
180
|
"opacity",
|
|
181
|
-
new
|
|
181
|
+
new i.BufferAttribute(this.opacities, 1)
|
|
182
182
|
), t;
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
|
-
class
|
|
185
|
+
class dt extends i.EventDispatcher {
|
|
186
186
|
constructor() {
|
|
187
187
|
super();
|
|
188
188
|
f(this, "worker");
|
|
@@ -190,26 +190,26 @@ class ut extends n.EventDispatcher {
|
|
|
190
190
|
f(this, "orderTexture", null);
|
|
191
191
|
/** Bounding box data for optimization */
|
|
192
192
|
f(this, "chunks", null);
|
|
193
|
-
f(this, "lastCameraPosition", new
|
|
194
|
-
f(this, "lastCameraDirection", new
|
|
195
|
-
const
|
|
193
|
+
f(this, "lastCameraPosition", new i.Vector3());
|
|
194
|
+
f(this, "lastCameraDirection", new i.Vector3());
|
|
195
|
+
const n = this.createWorkerCode(), e = new Blob([n], { type: "application/javascript" });
|
|
196
196
|
this.worker = new Worker(URL.createObjectURL(e)), this.worker.onmessage = this.onWorkerMessage.bind(this);
|
|
197
197
|
}
|
|
198
198
|
/**
|
|
199
199
|
* Handles messages received from the sorting worker.
|
|
200
200
|
* @param event The message event from the worker.
|
|
201
201
|
*/
|
|
202
|
-
onWorkerMessage(
|
|
202
|
+
onWorkerMessage(n) {
|
|
203
203
|
if (!this.orderTexture || !this.orderTexture.image)
|
|
204
204
|
return console.error("SplatSorter: Order texture not initialized!");
|
|
205
|
-
const { order: e, count:
|
|
205
|
+
const { order: e, count: r } = n.data, s = this.orderTexture.image.data;
|
|
206
206
|
if (!(s instanceof Uint32Array))
|
|
207
207
|
return console.error(
|
|
208
208
|
"SplatSorter: Order texture data is not a Uint32Array!"
|
|
209
209
|
);
|
|
210
210
|
s.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
|
|
211
|
-
const
|
|
212
|
-
this.worker.postMessage(a, [
|
|
211
|
+
const o = s.buffer.slice(0), a = { order: o };
|
|
212
|
+
this.worker.postMessage(a, [o]), this.dispatchEvent({ type: "updated", count: r });
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
215
|
* Initializes the sorter with necessary data and textures.
|
|
@@ -217,29 +217,29 @@ class ut 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(
|
|
221
|
-
if (!
|
|
220
|
+
init(n, e, r) {
|
|
221
|
+
if (!n || !(n.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 (n.image.data.length < e.length / 3)
|
|
226
226
|
throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");
|
|
227
227
|
const s = e.length / 3;
|
|
228
|
-
this.orderTexture =
|
|
229
|
-
const
|
|
230
|
-
for (let
|
|
228
|
+
this.orderTexture = n, this.centers = e.slice();
|
|
229
|
+
const o = this.orderTexture.image.data;
|
|
230
|
+
for (let y = 0; y < s; y++) o[y] = y;
|
|
231
231
|
this.orderTexture.needsUpdate = !0;
|
|
232
|
-
const a =
|
|
232
|
+
const a = o.buffer.slice(0), c = this.centers.buffer.slice(0), h = {
|
|
233
233
|
order: a,
|
|
234
234
|
centers: c
|
|
235
235
|
}, v = [
|
|
236
236
|
a,
|
|
237
237
|
c
|
|
238
238
|
];
|
|
239
|
-
if (
|
|
240
|
-
this.chunks =
|
|
241
|
-
const
|
|
242
|
-
h.chunks =
|
|
239
|
+
if (r) {
|
|
240
|
+
this.chunks = r.slice();
|
|
241
|
+
const y = this.chunks.buffer.slice(0);
|
|
242
|
+
h.chunks = y, v.push(y);
|
|
243
243
|
}
|
|
244
244
|
this.worker.postMessage(h, v);
|
|
245
245
|
}
|
|
@@ -248,53 +248,53 @@ class ut extends n.EventDispatcher {
|
|
|
248
248
|
* The sorter will only consider splats whose original indices are present in the mapping.
|
|
249
249
|
* @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
|
|
250
250
|
*/
|
|
251
|
-
setMapping(
|
|
251
|
+
setMapping(n) {
|
|
252
252
|
if (!this.centers)
|
|
253
253
|
return console.warn(
|
|
254
254
|
"SplatSorter: Cannot set mapping before initialization."
|
|
255
255
|
);
|
|
256
256
|
let e;
|
|
257
|
-
const
|
|
258
|
-
if (!
|
|
257
|
+
const r = [];
|
|
258
|
+
if (!n) {
|
|
259
259
|
const c = this.centers.buffer.slice(0);
|
|
260
260
|
return e = {
|
|
261
261
|
centers: c,
|
|
262
262
|
mapping: null
|
|
263
|
-
},
|
|
263
|
+
}, r.push(c), this.worker.postMessage(e, r);
|
|
264
264
|
}
|
|
265
|
-
const s = new Float32Array(
|
|
266
|
-
for (let c = 0; c <
|
|
267
|
-
const h =
|
|
265
|
+
const s = new Float32Array(n.length * 3);
|
|
266
|
+
for (let c = 0; c < n.length; c++) {
|
|
267
|
+
const h = n[c];
|
|
268
268
|
if (h * 3 + 2 >= this.centers.length) {
|
|
269
269
|
console.warn(
|
|
270
270
|
`SplatSorter: Mapping index ${h} out of bounds.`
|
|
271
271
|
);
|
|
272
272
|
continue;
|
|
273
273
|
}
|
|
274
|
-
const v = h * 3,
|
|
275
|
-
s[
|
|
274
|
+
const v = h * 3, y = c * 3;
|
|
275
|
+
s[y + 0] = this.centers[v + 0], s[y + 1] = this.centers[v + 1], s[y + 2] = this.centers[v + 2];
|
|
276
276
|
}
|
|
277
|
-
const
|
|
277
|
+
const o = s.buffer.slice(0), a = n.buffer.slice(0);
|
|
278
278
|
e = {
|
|
279
|
-
centers:
|
|
279
|
+
centers: o,
|
|
280
280
|
mapping: a
|
|
281
|
-
},
|
|
281
|
+
}, r.push(o, a), this.worker.postMessage(e, r);
|
|
282
282
|
}
|
|
283
283
|
/**
|
|
284
284
|
* Updates the camera parameters used for sorting.
|
|
285
285
|
* @param position The camera's position in the sorter's local coordinate space.
|
|
286
286
|
* @param direction The camera's forward direction in the sorter's local coordinate space.
|
|
287
287
|
*/
|
|
288
|
-
setCamera(
|
|
289
|
-
const
|
|
290
|
-
if (!
|
|
288
|
+
setCamera(n, e) {
|
|
289
|
+
const r = this.lastCameraPosition.distanceToSquared(n) > 1e-7, s = this.lastCameraDirection.dot(e) < 0.9999;
|
|
290
|
+
if (!r && !s)
|
|
291
291
|
return;
|
|
292
|
-
this.lastCameraPosition.copy(
|
|
293
|
-
const
|
|
294
|
-
cameraPosition: { x:
|
|
292
|
+
this.lastCameraPosition.copy(n), this.lastCameraDirection.copy(e);
|
|
293
|
+
const o = {
|
|
294
|
+
cameraPosition: { x: n.x, y: n.y, z: n.z },
|
|
295
295
|
cameraDirection: { x: e.x, y: e.y, z: e.z }
|
|
296
296
|
};
|
|
297
|
-
this.worker.postMessage(
|
|
297
|
+
this.worker.postMessage(o);
|
|
298
298
|
}
|
|
299
299
|
/**
|
|
300
300
|
* Terminates the Web Worker and cleans up resources.
|
|
@@ -308,148 +308,149 @@ class ut extends n.EventDispatcher {
|
|
|
308
308
|
*/
|
|
309
309
|
createWorkerCode() {
|
|
310
310
|
return `(${(function() {
|
|
311
|
-
let e = null,
|
|
312
|
-
const v = { x: 0, y: 0, z: 0 },
|
|
311
|
+
let e = null, r = null, s = null, o = null, a = null, c = null, h = !1;
|
|
312
|
+
const v = { x: 0, y: 0, z: 0 }, y = { x: 0, y: 0, z: 0 }, p = { x: 0, y: 0, z: 0 }, u = { x: 0, y: 0, z: 0 };
|
|
313
313
|
let l = null, b = null;
|
|
314
|
-
const
|
|
315
|
-
for (; F <=
|
|
316
|
-
const M =
|
|
314
|
+
const B = 32, O = new Array(B).fill(0), q = new Array(B).fill(0), E = new Array(B).fill(0), R = (F, S, D) => {
|
|
315
|
+
for (; F <= S; ) {
|
|
316
|
+
const M = S + F >> 1, m = D(M);
|
|
317
317
|
if (m > 0) F = M + 1;
|
|
318
|
-
else if (m < 0)
|
|
318
|
+
else if (m < 0) S = M - 1;
|
|
319
319
|
else return M;
|
|
320
320
|
}
|
|
321
321
|
return ~F;
|
|
322
322
|
}, W = () => {
|
|
323
|
-
if (!e || !
|
|
323
|
+
if (!e || !r || !a || !c)
|
|
324
324
|
return;
|
|
325
|
-
if (
|
|
326
|
-
const
|
|
325
|
+
if (r.length === 0) {
|
|
326
|
+
const g = {
|
|
327
327
|
order: e.buffer,
|
|
328
328
|
count: 0
|
|
329
329
|
};
|
|
330
|
-
self.postMessage(
|
|
330
|
+
self.postMessage(g, [e.buffer]), e = null;
|
|
331
331
|
return;
|
|
332
332
|
}
|
|
333
|
-
const F = a.x,
|
|
333
|
+
const F = a.x, S = a.y, D = a.z, M = c.x, m = c.y, C = c.z, _ = 1e-4, V = Math.abs(F - v.x) > _ || Math.abs(S - v.y) > _ || Math.abs(D - v.z) > _, x = Math.abs(M - y.x) > _ || Math.abs(m - y.y) > _ || Math.abs(C - y.z) > _;
|
|
334
334
|
if (!h && !V && !x)
|
|
335
335
|
return;
|
|
336
|
-
h = !1, v.x = F, v.y =
|
|
337
|
-
let d = 1 / 0,
|
|
338
|
-
for (let
|
|
339
|
-
const
|
|
340
|
-
d = Math.min(d,
|
|
336
|
+
h = !1, v.x = F, v.y = S, v.z = D, y.x = M, y.y = m, y.z = C;
|
|
337
|
+
let d = 1 / 0, z = -1 / 0;
|
|
338
|
+
for (let g = 0; g < 8; ++g) {
|
|
339
|
+
const k = g & 1 ? p.x : u.x, U = g & 2 ? p.y : u.y, w = g & 4 ? p.z : u.z, P = k * M + U * m + w * C;
|
|
340
|
+
d = Math.min(d, P), z = Math.max(z, P);
|
|
341
341
|
}
|
|
342
|
-
const
|
|
342
|
+
const T = r.length / 3, L = z - d, I = (1 << Math.max(
|
|
343
343
|
10,
|
|
344
|
-
Math.min(20, Math.ceil(Math.log2(
|
|
344
|
+
Math.min(20, Math.ceil(Math.log2(T / 4)))
|
|
345
345
|
)) + 1;
|
|
346
|
-
if ((!l || l.length !==
|
|
347
|
-
for (let
|
|
348
|
-
b[0] =
|
|
346
|
+
if ((!l || l.length !== T) && (l = new Uint32Array(T)), !b || b.length !== I ? b = new Uint32Array(I) : b.fill(0), L < 1e-7) {
|
|
347
|
+
for (let g = 0; g < T; ++g) l[g] = 0;
|
|
348
|
+
b[0] = T;
|
|
349
349
|
} else if (s && s.length > 0) {
|
|
350
|
-
const
|
|
350
|
+
const g = s.length / 6;
|
|
351
351
|
O.fill(0);
|
|
352
|
-
for (let w = 0; w <
|
|
353
|
-
const
|
|
352
|
+
for (let w = 0; w < g; ++w) {
|
|
353
|
+
const P = w * 6, Z = s[P + 0], G = s[P + 1], $ = s[P + 2], H = s[P + 3], Y = Z * M + G * m + $ * C - d, J = Y - H, X = Y + H, Q = Math.max(
|
|
354
354
|
0,
|
|
355
|
-
Math.floor(
|
|
355
|
+
Math.floor(J * B / L)
|
|
356
356
|
), tt = Math.min(
|
|
357
|
-
|
|
358
|
-
Math.ceil(
|
|
357
|
+
B,
|
|
358
|
+
Math.ceil(X * B / L)
|
|
359
359
|
);
|
|
360
|
-
for (let
|
|
361
|
-
O[
|
|
360
|
+
for (let N = Q; N < tt; ++N)
|
|
361
|
+
O[N]++;
|
|
362
362
|
}
|
|
363
|
-
let
|
|
364
|
-
for (let w = 0; w <
|
|
365
|
-
|
|
366
|
-
for (let w = 1; w <
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const U = L /
|
|
370
|
-
for (let w = 0; w <
|
|
371
|
-
const
|
|
363
|
+
let k = 0;
|
|
364
|
+
for (let w = 0; w < B; ++w) k += O[w];
|
|
365
|
+
E[0] = 0, q[0] = 0;
|
|
366
|
+
for (let w = 1; w < B; ++w)
|
|
367
|
+
E[w - 1] = O[w - 1] / k * I >>> 0, q[w] = q[w - 1] + E[w - 1];
|
|
368
|
+
E[B - 1] = O[B - 1] / k * I >>> 0;
|
|
369
|
+
const U = L / B;
|
|
370
|
+
for (let w = 0; w < T; ++w) {
|
|
371
|
+
const P = w * 3, Z = r[P + 0], G = r[P + 1], $ = r[P + 2], H = Z * M + G * m + $ * C, J = (z - H) / U, X = Math.max(
|
|
372
372
|
0,
|
|
373
373
|
Math.min(
|
|
374
|
-
|
|
375
|
-
Math.floor(
|
|
374
|
+
B - 1,
|
|
375
|
+
Math.floor(J)
|
|
376
376
|
)
|
|
377
|
-
),
|
|
378
|
-
l[w] =
|
|
377
|
+
), Q = J - X, tt = q[X] + E[X] * Q >>> 0, N = Math.min(tt, I - 1);
|
|
378
|
+
l[w] = N, b[N]++;
|
|
379
379
|
}
|
|
380
380
|
} else {
|
|
381
|
-
const
|
|
382
|
-
for (let
|
|
383
|
-
const U =
|
|
384
|
-
l[
|
|
381
|
+
const g = (I - 1) / L;
|
|
382
|
+
for (let k = 0; k < T; ++k) {
|
|
383
|
+
const U = k * 3, w = r[U + 0], P = r[U + 1], Z = r[U + 2], G = w * M + P * m + Z * C, H = (z - G) * g >>> 0, Y = Math.min(H, I - 1);
|
|
384
|
+
l[k] = Y, b[Y]++;
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
|
-
for (let
|
|
388
|
-
b[
|
|
389
|
-
for (let
|
|
390
|
-
const
|
|
391
|
-
e[U] =
|
|
387
|
+
for (let g = 1; g < I; g++)
|
|
388
|
+
b[g] += b[g - 1];
|
|
389
|
+
for (let g = T - 1; g >= 0; g--) {
|
|
390
|
+
const k = l[g], U = --b[k];
|
|
391
|
+
e[U] = o ? o[g] : g;
|
|
392
392
|
}
|
|
393
|
-
const
|
|
393
|
+
const at = F * M + S * m + D * C, rt = (g) => {
|
|
394
394
|
if (!e) return -1 / 0;
|
|
395
|
-
const
|
|
396
|
-
if (!
|
|
395
|
+
const k = e[g], U = k;
|
|
396
|
+
if (!r || U * 3 + 2 >= r.length)
|
|
397
397
|
return -1 / 0;
|
|
398
398
|
const w = U * 3;
|
|
399
|
-
return
|
|
399
|
+
return r[w] * M + r[w + 1] * m + r[w + 2] * C - at;
|
|
400
400
|
};
|
|
401
|
-
let st =
|
|
402
|
-
if (
|
|
403
|
-
const
|
|
401
|
+
let st = T;
|
|
402
|
+
if (T > 0 && rt(T - 1) < 0) {
|
|
403
|
+
const g = R(
|
|
404
404
|
0,
|
|
405
|
-
|
|
405
|
+
T - 1,
|
|
406
406
|
rt
|
|
407
407
|
);
|
|
408
|
-
st =
|
|
408
|
+
st = g < 0 ? ~g : g;
|
|
409
409
|
}
|
|
410
|
-
const
|
|
410
|
+
const ct = {
|
|
411
411
|
order: e.buffer,
|
|
412
412
|
count: st
|
|
413
413
|
};
|
|
414
|
-
self.postMessage(
|
|
414
|
+
self.postMessage(ct, [e.buffer]), e = null;
|
|
415
415
|
};
|
|
416
416
|
self.onmessage = (F) => {
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
let
|
|
420
|
-
if (
|
|
421
|
-
if (s = new Float32Array(
|
|
417
|
+
const S = F.data;
|
|
418
|
+
S.order && (e = new Uint32Array(S.order));
|
|
419
|
+
let D = !1;
|
|
420
|
+
if (S.centers && (r = new Float32Array(S.centers), D = !0, h = !0), Object.prototype.hasOwnProperty.call(S, "mapping") && (o = S.mapping ? new Uint32Array(S.mapping) : null, h = !0), S.chunks) {
|
|
421
|
+
if (s = new Float32Array(S.chunks), s.length > 0 && s[3] > 0)
|
|
422
422
|
for (let M = 0; M < s.length / 6; ++M) {
|
|
423
|
-
const m = M * 6,
|
|
424
|
-
s[m + 0] = (
|
|
425
|
-
(x -
|
|
423
|
+
const m = M * 6, C = s[m + 0], _ = s[m + 1], V = s[m + 2], x = s[m + 3], d = s[m + 4], z = s[m + 5];
|
|
424
|
+
s[m + 0] = (C + x) * 0.5, s[m + 1] = (_ + d) * 0.5, s[m + 2] = (V + z) * 0.5, s[m + 3] = Math.sqrt(
|
|
425
|
+
(x - C) ** 2 + (d - _) ** 2 + (z - V) ** 2
|
|
426
426
|
) * 0.5;
|
|
427
427
|
}
|
|
428
428
|
h = !0;
|
|
429
429
|
}
|
|
430
|
-
if (
|
|
431
|
-
p.x = u.x =
|
|
432
|
-
for (let M = 1; M <
|
|
430
|
+
if (D && r && r.length > 0) {
|
|
431
|
+
p.x = u.x = r[0], p.y = u.y = r[1], p.z = u.z = r[2];
|
|
432
|
+
for (let M = 1; M < r.length / 3; M++) {
|
|
433
433
|
const m = M * 3;
|
|
434
|
-
p.x = Math.min(p.x,
|
|
434
|
+
p.x = Math.min(p.x, r[m + 0]), u.x = Math.max(u.x, r[m + 0]), p.y = Math.min(p.y, r[m + 1]), u.y = Math.max(u.y, r[m + 1]), p.z = Math.min(p.z, r[m + 2]), u.z = Math.max(u.z, r[m + 2]);
|
|
435
435
|
}
|
|
436
|
-
} else
|
|
437
|
-
|
|
436
|
+
} else D && r && r.length === 0 && (p.x = u.x = p.y = u.y = p.z = u.z = 0);
|
|
437
|
+
S.cameraPosition && (a = S.cameraPosition), S.cameraDirection && (c = S.cameraDirection), W();
|
|
438
438
|
};
|
|
439
439
|
}).toString()})();`;
|
|
440
440
|
}
|
|
441
441
|
}
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return r <<
|
|
451
|
-
}
|
|
452
|
-
|
|
442
|
+
const ft = (A, t) => {
|
|
443
|
+
const n = nt(A), e = nt(t);
|
|
444
|
+
return n | e << 16;
|
|
445
|
+
};
|
|
446
|
+
function nt(A) {
|
|
447
|
+
const t = new Float32Array([A]), e = new Int32Array(t.buffer)[0];
|
|
448
|
+
let r = e >> 16 & 32768, s = e >> 12 & 2047;
|
|
449
|
+
const o = e >> 23 & 255;
|
|
450
|
+
return o < 103 ? r : o > 142 ? (r |= 31744, r |= (o === 255 ? 0 : 1) && e & 8388607, r) : o < 113 ? (s |= 2048, r |= (s >> 114 - o) + (s >> 113 - o & 1), r) : (r |= o - 112 << 10 | s >> 1, r += s & 1, r);
|
|
451
|
+
}
|
|
452
|
+
const pt = new ArrayBuffer(4), ot = new DataView(pt), mt = (A) => (ot.setUint32(0, A, !0), ot.getFloat32(0, !0));
|
|
453
|
+
class xt {
|
|
453
454
|
/**
|
|
454
455
|
* Create a new TextureManager for a set of splats
|
|
455
456
|
* @param splatData The splat data to manage textures for
|
|
@@ -464,8 +465,8 @@ class mt {
|
|
|
464
465
|
f(this, "orderTexture");
|
|
465
466
|
f(this, "textureWidth");
|
|
466
467
|
f(this, "textureHeight");
|
|
467
|
-
const
|
|
468
|
-
this.textureWidth = Math.ceil(Math.sqrt(
|
|
468
|
+
const n = t.numSplats;
|
|
469
|
+
this.textureWidth = Math.ceil(Math.sqrt(n)), this.textureHeight = Math.ceil(n / this.textureWidth), this.transformA = this.createTransformATexture(t), this.transformB = this.createTransformBTexture(t), this.colorTexture = this.createColorTexture(t), this.orderTexture = this.createOrderTexture(n);
|
|
469
470
|
}
|
|
470
471
|
/**
|
|
471
472
|
* Create the transform A texture (positions and quaternion w component)
|
|
@@ -473,24 +474,24 @@ class mt {
|
|
|
473
474
|
* @returns DataTexture containing position data
|
|
474
475
|
*/
|
|
475
476
|
createTransformATexture(t) {
|
|
476
|
-
const
|
|
477
|
+
const n = t.numSplats, e = new Float32Array(
|
|
477
478
|
this.textureWidth * this.textureHeight * 4
|
|
478
479
|
);
|
|
479
|
-
for (let s = 0; s <
|
|
480
|
-
const
|
|
481
|
-
e[
|
|
482
|
-
const h = t.rotations[c +
|
|
483
|
-
e[
|
|
480
|
+
for (let s = 0; s < n; s++) {
|
|
481
|
+
const o = s * 4, a = s * 3, c = s * 4;
|
|
482
|
+
e[o] = t.positions[a], e[o + 1] = t.positions[a + 1], e[o + 2] = t.positions[a + 2];
|
|
483
|
+
const h = t.rotations[c + 0], v = t.rotations[c + 1], y = ft(h, v);
|
|
484
|
+
e[o + 3] = mt(y);
|
|
484
485
|
}
|
|
485
|
-
const
|
|
486
|
+
const r = new i.DataTexture(
|
|
486
487
|
e,
|
|
487
488
|
this.textureWidth,
|
|
488
489
|
this.textureHeight,
|
|
489
|
-
|
|
490
|
-
|
|
490
|
+
i.RGBAFormat,
|
|
491
|
+
i.FloatType
|
|
491
492
|
// Store as Float32, shader will reinterpret bits
|
|
492
493
|
);
|
|
493
|
-
return
|
|
494
|
+
return r.needsUpdate = !0, r.magFilter = i.NearestFilter, r.minFilter = i.NearestFilter, r;
|
|
494
495
|
}
|
|
495
496
|
/**
|
|
496
497
|
* Create the transform B texture (scale and rotation xyz)
|
|
@@ -498,21 +499,21 @@ class mt {
|
|
|
498
499
|
* @returns DataTexture containing scale and rotation data
|
|
499
500
|
*/
|
|
500
501
|
createTransformBTexture(t) {
|
|
501
|
-
const
|
|
502
|
+
const n = t.numSplats, e = new Float32Array(
|
|
502
503
|
this.textureWidth * this.textureHeight * 4
|
|
503
504
|
);
|
|
504
|
-
for (let s = 0; s <
|
|
505
|
-
const
|
|
506
|
-
e[
|
|
505
|
+
for (let s = 0; s < n; s++) {
|
|
506
|
+
const o = s * 4, a = s * 3, c = s * 4;
|
|
507
|
+
e[o] = t.scales[a], e[o + 1] = t.scales[a + 1], e[o + 2] = t.scales[a + 2], e[o + 3] = t.rotations[c + 2];
|
|
507
508
|
}
|
|
508
|
-
const
|
|
509
|
+
const r = new i.DataTexture(
|
|
509
510
|
e,
|
|
510
511
|
this.textureWidth,
|
|
511
512
|
this.textureHeight,
|
|
512
|
-
|
|
513
|
-
|
|
513
|
+
i.RGBAFormat,
|
|
514
|
+
i.FloatType
|
|
514
515
|
);
|
|
515
|
-
return
|
|
516
|
+
return r.needsUpdate = !0, r.magFilter = i.NearestFilter, r.minFilter = i.NearestFilter, r;
|
|
516
517
|
}
|
|
517
518
|
/**
|
|
518
519
|
* Create the color texture (RGB and opacity)
|
|
@@ -520,21 +521,21 @@ class mt {
|
|
|
520
521
|
* @returns DataTexture containing color data
|
|
521
522
|
*/
|
|
522
523
|
createColorTexture(t) {
|
|
523
|
-
const
|
|
524
|
+
const n = t.numSplats, e = new Float32Array(
|
|
524
525
|
this.textureWidth * this.textureHeight * 4
|
|
525
526
|
);
|
|
526
|
-
for (let s = 0; s <
|
|
527
|
-
const
|
|
528
|
-
e[
|
|
527
|
+
for (let s = 0; s < n; s++) {
|
|
528
|
+
const o = s * 4, a = s * 3;
|
|
529
|
+
e[o] = t.colors[a], e[o + 1] = t.colors[a + 1], e[o + 2] = t.colors[a + 2], e[o + 3] = t.opacities[s];
|
|
529
530
|
}
|
|
530
|
-
const
|
|
531
|
+
const r = new i.DataTexture(
|
|
531
532
|
e,
|
|
532
533
|
this.textureWidth,
|
|
533
534
|
this.textureHeight,
|
|
534
|
-
|
|
535
|
-
|
|
535
|
+
i.RGBAFormat,
|
|
536
|
+
i.FloatType
|
|
536
537
|
);
|
|
537
|
-
return
|
|
538
|
+
return r.needsUpdate = !0, r;
|
|
538
539
|
}
|
|
539
540
|
/**
|
|
540
541
|
* Create the order texture for sorting
|
|
@@ -542,15 +543,15 @@ class mt {
|
|
|
542
543
|
* @returns DataTexture for storing order indices
|
|
543
544
|
*/
|
|
544
545
|
createOrderTexture(t) {
|
|
545
|
-
const
|
|
546
|
-
for (let
|
|
547
|
-
r
|
|
548
|
-
const e = new
|
|
549
|
-
|
|
546
|
+
const n = new Uint32Array(this.textureWidth * this.textureHeight);
|
|
547
|
+
for (let r = 0; r < t; r++)
|
|
548
|
+
n[r] = r;
|
|
549
|
+
const e = new i.DataTexture(
|
|
550
|
+
n,
|
|
550
551
|
this.textureWidth,
|
|
551
552
|
this.textureHeight,
|
|
552
|
-
|
|
553
|
-
|
|
553
|
+
i.RedIntegerFormat,
|
|
554
|
+
i.UnsignedIntType
|
|
554
555
|
);
|
|
555
556
|
return e.needsUpdate = !0, e;
|
|
556
557
|
}
|
|
@@ -558,7 +559,7 @@ class mt {
|
|
|
558
559
|
this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
|
|
559
560
|
}
|
|
560
561
|
}
|
|
561
|
-
const
|
|
562
|
+
const gt = (
|
|
562
563
|
/* glsl */
|
|
563
564
|
`
|
|
564
565
|
precision highp float;
|
|
@@ -596,61 +597,53 @@ varying vec2 vUv; // For gaussian calculation in fragment shader
|
|
|
596
597
|
|
|
597
598
|
// --- Helper Functions ---
|
|
598
599
|
|
|
599
|
-
//
|
|
600
|
-
vec2 unpackHalf2x16FromFloat(float packedFloat) {
|
|
601
|
-
uint packedUInt = floatBitsToUint(packedFloat);
|
|
602
|
-
uint y_bits = packedUInt >> 16;
|
|
603
|
-
uint z_bits = packedUInt & uint(0xFFFF);
|
|
604
|
-
|
|
605
|
-
// NOTE: This assumes packing used "packNormalizedFloatToUint16Pair"
|
|
606
|
-
// which maps [-1, 1] to [0, 65535]. Adjust if packing method changes.
|
|
607
|
-
float y = (float(y_bits) / 65535.0) * 2.0 - 1.0;
|
|
608
|
-
float z = (float(z_bits) / 65535.0) * 2.0 - 1.0;
|
|
609
|
-
return vec2(y, z);
|
|
610
|
-
}
|
|
600
|
+
// Use GLSL built-in unpackHalf2x16 for proper half-float unpacking
|
|
611
601
|
|
|
612
|
-
// Reconstruct quaternion from packed components (
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
float
|
|
602
|
+
// Reconstruct quaternion from packed components (xy_packed, z)
|
|
603
|
+
// Returns (w,x,y,z) format for quatToMat3 compatibility
|
|
604
|
+
vec4 unpackRotation(float xy_packed, float z) {
|
|
605
|
+
vec2 xy = unpackHalf2x16(floatBitsToUint(xy_packed));
|
|
606
|
+
float x = xy.x;
|
|
607
|
+
float y = xy.y;
|
|
617
608
|
float w_squared = 1.0 - x*x - y*y - z*z;
|
|
618
|
-
float w = (w_squared < 0.0) ? 0.0 : sqrt(w_squared);
|
|
619
|
-
return vec4(x, y, z
|
|
609
|
+
float w = (w_squared < 0.0) ? 0.0 : sqrt(w_squared);
|
|
610
|
+
return vec4(w, x, y, z); // Return (w,x,y,z)
|
|
620
611
|
}
|
|
621
612
|
|
|
622
613
|
// Convert quaternion to 3x3 rotation matrix
|
|
623
|
-
mat3 quatToMat3(vec4
|
|
624
|
-
|
|
625
|
-
float
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
float
|
|
614
|
+
mat3 quatToMat3(vec4 R) {
|
|
615
|
+
vec4 R2 = R + R;
|
|
616
|
+
float X = R2.x * R.w;
|
|
617
|
+
vec4 Y = R2.y * R;
|
|
618
|
+
vec4 Z = R2.z * R;
|
|
619
|
+
float W = R2.w * R.w;
|
|
629
620
|
|
|
630
621
|
return mat3(
|
|
631
|
-
1.0 -
|
|
632
|
-
|
|
633
|
-
|
|
622
|
+
1.0 - Z.z - W,
|
|
623
|
+
Y.z + X,
|
|
624
|
+
Y.w - Z.x,
|
|
625
|
+
Y.z - X,
|
|
626
|
+
1.0 - Y.y - W,
|
|
627
|
+
Z.w + Y.x,
|
|
628
|
+
Y.w + Z.x,
|
|
629
|
+
Z.w - Y.x,
|
|
630
|
+
1.0 - Y.y - Z.z
|
|
634
631
|
);
|
|
635
632
|
}
|
|
636
633
|
|
|
637
|
-
// Calculate model-space covariance components
|
|
634
|
+
// Calculate model-space covariance components
|
|
638
635
|
void getModelCovariance(vec3 scale, vec4 rotation, out vec3 covA, out vec3 covB) {
|
|
639
|
-
mat3
|
|
640
|
-
|
|
641
|
-
//
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
R[2][0] * scale.x, R[2][1] * scale.y, R[2][2] * scale.z // Row 2 = (R_row2 * S)
|
|
648
|
-
);
|
|
636
|
+
mat3 rot = quatToMat3(rotation);
|
|
637
|
+
|
|
638
|
+
// M = S * R (scale COLUMNS, then transpose)
|
|
639
|
+
mat3 M = transpose(mat3(
|
|
640
|
+
scale.x * rot[0], // scale.x * column 0
|
|
641
|
+
scale.y * rot[1], // scale.y * column 1
|
|
642
|
+
scale.z * rot[2] // scale.z * column 2
|
|
643
|
+
));
|
|
649
644
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2])); // Vrk[0][0], Vrk[0][1], Vrk[0][2]
|
|
653
|
-
covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2])); // Vrk[1][1], Vrk[1][2], Vrk[2][2]
|
|
645
|
+
covA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));
|
|
646
|
+
covB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));
|
|
654
647
|
}
|
|
655
648
|
|
|
656
649
|
// --- Main Function ---
|
|
@@ -679,7 +672,7 @@ void main(void) {
|
|
|
679
672
|
|
|
680
673
|
vec3 splatPosition = texTransformA.xyz;
|
|
681
674
|
vec3 splatLogScale = texTransformB.xyz; // Assume stored as log scale
|
|
682
|
-
vec4 splatRotation = unpackRotation(texTransformA.w, texTransformB.w); // Unpack rot
|
|
675
|
+
vec4 splatRotation = unpackRotation(texTransformA.w, texTransformB.w); // Unpack rot xy, z
|
|
683
676
|
vec3 splatColor = texColor.rgb;
|
|
684
677
|
float splatOpacity = texColor.a;
|
|
685
678
|
|
|
@@ -805,7 +798,6 @@ void main(void) {
|
|
|
805
798
|
// Apply clip to the corner offset *before* calculating screen space offset
|
|
806
799
|
vec2 clippedCornerOffset = cornerOffset * clip;
|
|
807
800
|
vec2 screenOffsetPixels = clippedCornerOffset.x * v1_scaled + clippedCornerOffset.y * v2_scaled;
|
|
808
|
-
//vec2 screenOffsetPixels = vec2(clippedCornerOffset.x, clippedCornerOffset.y);
|
|
809
801
|
|
|
810
802
|
// Convert pixel offset to clip space offset
|
|
811
803
|
vec2 clipOffset = screenOffsetPixels * (centerClip.w / viewport);
|
|
@@ -846,56 +838,56 @@ void main(void) {
|
|
|
846
838
|
}
|
|
847
839
|
`
|
|
848
840
|
);
|
|
849
|
-
class
|
|
841
|
+
class vt extends i.ShaderMaterial {
|
|
850
842
|
constructor(t = {}) {
|
|
851
|
-
const
|
|
843
|
+
const n = {
|
|
852
844
|
// Textures (values set via methods)
|
|
853
845
|
transformA: { value: null },
|
|
854
846
|
transformB: { value: null },
|
|
855
847
|
splatColor: { value: null },
|
|
856
848
|
splatOrder: { value: null },
|
|
857
849
|
// Other uniforms
|
|
858
|
-
viewport: { value: new
|
|
850
|
+
viewport: { value: new i.Vector2(1, 1) },
|
|
859
851
|
// Will be updated
|
|
860
852
|
numSplats: { value: 0 }
|
|
861
853
|
// Max splats to render (updated by sorter)
|
|
862
854
|
};
|
|
863
855
|
super({
|
|
864
|
-
vertexShader:
|
|
856
|
+
vertexShader: gt,
|
|
865
857
|
fragmentShader: yt,
|
|
866
|
-
uniforms:
|
|
858
|
+
uniforms: n,
|
|
867
859
|
transparent: !0,
|
|
868
|
-
blending:
|
|
860
|
+
blending: i.CustomBlending,
|
|
869
861
|
// Premultiplied alpha blending:
|
|
870
862
|
// color = src_color * src_alpha + dst_color * (1 - src_alpha)
|
|
871
863
|
// alpha = src_alpha * 1 + dst_alpha * (1 - src_alpha)
|
|
872
|
-
blendSrc:
|
|
864
|
+
blendSrc: i.OneFactor,
|
|
873
865
|
// Using ONE because shader outputs premultiplied color (color * alpha)
|
|
874
|
-
blendDst:
|
|
875
|
-
blendSrcAlpha:
|
|
866
|
+
blendDst: i.OneMinusSrcAlphaFactor,
|
|
867
|
+
blendSrcAlpha: i.OneFactor,
|
|
876
868
|
// source alpha comes from shader
|
|
877
|
-
blendDstAlpha:
|
|
878
|
-
blendEquation:
|
|
879
|
-
blendEquationAlpha:
|
|
869
|
+
blendDstAlpha: i.OneMinusSrcAlphaFactor,
|
|
870
|
+
blendEquation: i.AddEquation,
|
|
871
|
+
blendEquationAlpha: i.AddEquation,
|
|
880
872
|
depthTest: !0,
|
|
881
873
|
depthWrite: !1,
|
|
882
874
|
// Disable depth write for transparency
|
|
883
|
-
side:
|
|
875
|
+
side: i.DoubleSide,
|
|
884
876
|
// Render both sides (or CULLFACE_NONE equivalent)
|
|
885
877
|
// Optional settings from constructor
|
|
886
878
|
alphaTest: t.alphaTest !== void 0 ? t.alphaTest : 0,
|
|
887
879
|
// Typically 0 for blending
|
|
888
880
|
toneMapped: t.toneMapped !== void 0 ? t.toneMapped : !1
|
|
889
881
|
// prettier-ignore
|
|
890
|
-
}), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending =
|
|
882
|
+
}), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = i.NoBlending);
|
|
891
883
|
}
|
|
892
884
|
/**
|
|
893
885
|
* Update the viewport size
|
|
894
886
|
* @param width Viewport width
|
|
895
887
|
* @param height Viewport height
|
|
896
888
|
*/
|
|
897
|
-
updateViewport(t,
|
|
898
|
-
this.uniforms.viewport.value.set(t,
|
|
889
|
+
updateViewport(t, n) {
|
|
890
|
+
this.uniforms.viewport.value.set(t, n);
|
|
899
891
|
}
|
|
900
892
|
/**
|
|
901
893
|
* Set transform texture A (positions)
|
|
@@ -933,38 +925,38 @@ class gt extends n.ShaderMaterial {
|
|
|
933
925
|
this.uniforms.numSplats.value = t;
|
|
934
926
|
}
|
|
935
927
|
}
|
|
936
|
-
const
|
|
928
|
+
const j = class j extends i.Mesh {
|
|
937
929
|
// Match shader constant
|
|
938
930
|
/**
|
|
939
931
|
* Create a new SplatMesh for rendering Gaussian splats
|
|
940
932
|
* @param splatData The splat data to render
|
|
941
933
|
* @param options Rendering options
|
|
942
934
|
*/
|
|
943
|
-
constructor(
|
|
944
|
-
const
|
|
945
|
-
super(s,
|
|
935
|
+
constructor(n, e = {}) {
|
|
936
|
+
const r = new vt(e), s = j.createInstancedGeometry(n.numSplats, j.INSTANCE_SIZE);
|
|
937
|
+
super(s, r);
|
|
946
938
|
f(this, "sorter");
|
|
947
939
|
f(this, "splatData");
|
|
948
940
|
f(this, "options");
|
|
949
941
|
f(this, "textureManager");
|
|
950
942
|
f(this, "material");
|
|
951
943
|
f(this, "geometry");
|
|
952
|
-
f(this, "lastCameraPositionLocal", new
|
|
953
|
-
f(this, "lastCameraDirectionLocal", new
|
|
954
|
-
f(this, "invModelMatrix", new
|
|
955
|
-
this.geometry = s, this.material =
|
|
956
|
-
let
|
|
957
|
-
|
|
944
|
+
f(this, "lastCameraPositionLocal", new i.Vector3());
|
|
945
|
+
f(this, "lastCameraDirectionLocal", new i.Vector3());
|
|
946
|
+
f(this, "invModelMatrix", new i.Matrix4());
|
|
947
|
+
this.geometry = s, this.material = r, this.splatData = n, this.frustumCulled = !1, this.options = { autoSort: !0, ...e }, this.textureManager = new xt(n), this.sorter = new dt();
|
|
948
|
+
let o = this.createChunks() || void 0;
|
|
949
|
+
o === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), o = void 0, this.sorter.init(
|
|
958
950
|
this.textureManager.orderTexture,
|
|
959
951
|
this.splatData.centers,
|
|
960
|
-
|
|
952
|
+
o ?? void 0
|
|
961
953
|
), this.sorter.addEventListener(
|
|
962
954
|
"updated",
|
|
963
955
|
(a) => {
|
|
964
956
|
const c = a.count;
|
|
965
|
-
this.geometry.instanceCount = Math.ceil(c /
|
|
957
|
+
this.geometry.instanceCount = Math.ceil(c / j.INSTANCE_SIZE), this.material.setNumSplats(c);
|
|
966
958
|
}
|
|
967
|
-
), 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 =
|
|
959
|
+
), 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 = n.boundingBox.toBox3(), this.geometry.boundingSphere = new i.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
|
|
968
960
|
}
|
|
969
961
|
/**
|
|
970
962
|
* Creates the instanced geometry for rendering splats.
|
|
@@ -972,8 +964,8 @@ const Y = class Y extends n.Mesh {
|
|
|
972
964
|
* @param instanceSize Number of splats per instance.
|
|
973
965
|
* @returns InstancedBufferGeometry
|
|
974
966
|
*/
|
|
975
|
-
static createInstancedGeometry(
|
|
976
|
-
const
|
|
967
|
+
static createInstancedGeometry(n, e) {
|
|
968
|
+
const r = Math.ceil(n / e), s = new i.BufferGeometry(), o = new Float32Array([
|
|
977
969
|
// x, y, splat_index_in_instance
|
|
978
970
|
-1,
|
|
979
971
|
-1,
|
|
@@ -991,34 +983,34 @@ const Y = class Y extends n.Mesh {
|
|
|
991
983
|
for (let p = 0; p < e; p++) {
|
|
992
984
|
const u = p * 4 * 3;
|
|
993
985
|
for (let l = 0; l < 4; l++)
|
|
994
|
-
c[u + l * 3 + 0] =
|
|
986
|
+
c[u + l * 3 + 0] = o[l * 3 + 0], c[u + l * 3 + 1] = o[l * 3 + 1], c[u + l * 3 + 2] = p;
|
|
995
987
|
}
|
|
996
988
|
const h = new Uint32Array(6 * e);
|
|
997
989
|
for (let p = 0; p < e; p++) {
|
|
998
990
|
const u = p * 6, l = p * 4;
|
|
999
991
|
h[u + 0] = a[0] + l, h[u + 1] = a[1] + l, h[u + 2] = a[2] + l, h[u + 3] = a[3] + l, h[u + 4] = a[4] + l, h[u + 5] = a[5] + l;
|
|
1000
992
|
}
|
|
1001
|
-
s.setAttribute("position", new
|
|
1002
|
-
const v = new
|
|
993
|
+
s.setAttribute("position", new i.BufferAttribute(c, 3)), s.setIndex(new i.BufferAttribute(h, 1));
|
|
994
|
+
const v = new i.InstancedBufferGeometry();
|
|
1003
995
|
v.index = s.index, v.setAttribute("position", s.getAttribute("position"));
|
|
1004
|
-
const
|
|
1005
|
-
for (let p = 0; p <
|
|
1006
|
-
|
|
1007
|
-
return v.setAttribute("splatInstanceIndex", new
|
|
996
|
+
const y = new Uint32Array(r);
|
|
997
|
+
for (let p = 0; p < r; p++)
|
|
998
|
+
y[p] = p * e;
|
|
999
|
+
return v.setAttribute("splatInstanceIndex", new i.InstancedBufferAttribute(y, 1, !1)), v.instanceCount = 0, v;
|
|
1008
1000
|
}
|
|
1009
1001
|
/**
|
|
1010
1002
|
* Create chunks data (bounding box min/max) for the sorter.
|
|
1011
1003
|
* @returns Float32Array containing chunk data [minX, minY, minZ, maxX, maxY, maxZ] or null.
|
|
1012
1004
|
*/
|
|
1013
1005
|
createChunks() {
|
|
1014
|
-
const
|
|
1015
|
-
return
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1006
|
+
const n = this.splatData.boundingBox;
|
|
1007
|
+
return n.min.x === 1 / 0 || n.max.x === -1 / 0 ? null : new Float32Array([
|
|
1008
|
+
n.min.x,
|
|
1009
|
+
n.min.y,
|
|
1010
|
+
n.min.z,
|
|
1011
|
+
n.max.x,
|
|
1012
|
+
n.max.y,
|
|
1013
|
+
n.max.z
|
|
1022
1014
|
]);
|
|
1023
1015
|
}
|
|
1024
1016
|
/**
|
|
@@ -1026,18 +1018,18 @@ const Y = class Y extends n.Mesh {
|
|
|
1026
1018
|
* @param width Viewport width
|
|
1027
1019
|
* @param height Viewport height
|
|
1028
1020
|
*/
|
|
1029
|
-
updateViewport(
|
|
1030
|
-
this.material.updateViewport(
|
|
1021
|
+
updateViewport(n, e) {
|
|
1022
|
+
this.material.updateViewport(n, e);
|
|
1031
1023
|
}
|
|
1032
1024
|
/**
|
|
1033
1025
|
* Sorts splats based on camera position and direction.
|
|
1034
1026
|
* @param camera The camera to sort against.
|
|
1035
1027
|
*/
|
|
1036
|
-
sort(
|
|
1037
|
-
const e = new
|
|
1038
|
-
|
|
1039
|
-
const s = e.applyMatrix4(this.invModelMatrix),
|
|
1040
|
-
this.options.autoSort && (a || c) && (this.lastCameraPositionLocal.copy(s), this.lastCameraDirectionLocal.copy(
|
|
1028
|
+
sort(n) {
|
|
1029
|
+
const e = new i.Vector3(), r = new i.Vector3();
|
|
1030
|
+
n.getWorldPosition(e), n.getWorldDirection(r), this.invModelMatrix.copy(this.matrixWorld).invert();
|
|
1031
|
+
const s = e.applyMatrix4(this.invModelMatrix), o = r.transformDirection(this.invModelMatrix), a = this.lastCameraPositionLocal.distanceToSquared(s) > 1e-6, c = this.lastCameraDirectionLocal.dot(o) < 0.999;
|
|
1032
|
+
this.options.autoSort && (a || c) && (this.lastCameraPositionLocal.copy(s), this.lastCameraDirectionLocal.copy(o), this.sorter.setCamera(s, o));
|
|
1041
1033
|
}
|
|
1042
1034
|
/**
|
|
1043
1035
|
* THREE.js hook called before rendering the object.
|
|
@@ -1048,16 +1040,16 @@ const Y = class Y extends n.Mesh {
|
|
|
1048
1040
|
*/
|
|
1049
1041
|
// prettier-ignore
|
|
1050
1042
|
// @ts-expect-error scene is not used
|
|
1051
|
-
onBeforeRender(
|
|
1052
|
-
this.sort(
|
|
1053
|
-
const s =
|
|
1054
|
-
let { width:
|
|
1055
|
-
const c =
|
|
1043
|
+
onBeforeRender(n, e, r) {
|
|
1044
|
+
this.sort(r);
|
|
1045
|
+
const s = n.getSize(new i.Vector2());
|
|
1046
|
+
let { width: o, height: a } = s;
|
|
1047
|
+
const c = n.xr;
|
|
1056
1048
|
if (c.enabled && c.isPresenting) {
|
|
1057
1049
|
const h = c.getCamera().cameras[0].view;
|
|
1058
|
-
h && (
|
|
1050
|
+
h && (o = h.width, a = h.height);
|
|
1059
1051
|
}
|
|
1060
|
-
this.updateViewport(
|
|
1052
|
+
this.updateViewport(o, a);
|
|
1061
1053
|
}
|
|
1062
1054
|
/**
|
|
1063
1055
|
* Dispose of resources
|
|
@@ -1068,9 +1060,9 @@ const Y = class Y extends n.Mesh {
|
|
|
1068
1060
|
};
|
|
1069
1061
|
// Cached inverse matrix
|
|
1070
1062
|
/** Number of splats combined into a single instanced draw call. */
|
|
1071
|
-
f(
|
|
1072
|
-
let
|
|
1073
|
-
class
|
|
1063
|
+
f(j, "INSTANCE_SIZE", 128);
|
|
1064
|
+
let it = j;
|
|
1065
|
+
class bt extends i.Loader {
|
|
1074
1066
|
/**
|
|
1075
1067
|
* Load a PLY file with Gaussian Splat data
|
|
1076
1068
|
* @param url URL of the PLY file
|
|
@@ -1078,22 +1070,22 @@ class wt extends n.Loader {
|
|
|
1078
1070
|
* @param onProgress Optional progress callback
|
|
1079
1071
|
* @param onError Optional error callback
|
|
1080
1072
|
*/
|
|
1081
|
-
load(t,
|
|
1082
|
-
const s = new
|
|
1073
|
+
load(t, n, e, r) {
|
|
1074
|
+
const s = new i.FileLoader(this.manager);
|
|
1083
1075
|
s.setResponseType("arraybuffer"), s.setRequestHeader(this.requestHeader), s.setPath(this.path), s.setWithCredentials(this.withCredentials), s.load(
|
|
1084
1076
|
t,
|
|
1085
|
-
(
|
|
1077
|
+
(o) => {
|
|
1086
1078
|
try {
|
|
1087
|
-
if (
|
|
1088
|
-
const a = this.parse(
|
|
1089
|
-
|
|
1079
|
+
if (n) {
|
|
1080
|
+
const a = this.parse(o);
|
|
1081
|
+
n(a);
|
|
1090
1082
|
}
|
|
1091
1083
|
} catch (a) {
|
|
1092
|
-
|
|
1084
|
+
r ? r(a) : console.error(a), this.manager.itemError(t);
|
|
1093
1085
|
}
|
|
1094
1086
|
},
|
|
1095
1087
|
e,
|
|
1096
|
-
|
|
1088
|
+
r
|
|
1097
1089
|
);
|
|
1098
1090
|
}
|
|
1099
1091
|
/**
|
|
@@ -1102,22 +1094,22 @@ class wt extends n.Loader {
|
|
|
1102
1094
|
* @param onProgress Optional progress callback
|
|
1103
1095
|
* @returns A Promise that resolves with the parsed SplatData
|
|
1104
1096
|
*/
|
|
1105
|
-
loadAsync(t,
|
|
1106
|
-
return new Promise((e,
|
|
1107
|
-
const s = new
|
|
1097
|
+
loadAsync(t, n) {
|
|
1098
|
+
return new Promise((e, r) => {
|
|
1099
|
+
const s = new i.FileLoader(this.manager);
|
|
1108
1100
|
s.setResponseType("arraybuffer"), s.setRequestHeader(this.requestHeader), s.setPath(this.path), s.setWithCredentials(this.withCredentials), s.load(
|
|
1109
1101
|
t,
|
|
1110
|
-
(
|
|
1102
|
+
(o) => {
|
|
1111
1103
|
try {
|
|
1112
|
-
const a = this.parse(
|
|
1104
|
+
const a = this.parse(o);
|
|
1113
1105
|
e(a);
|
|
1114
1106
|
} catch (a) {
|
|
1115
|
-
|
|
1107
|
+
r(a), this.manager.itemError(t);
|
|
1116
1108
|
}
|
|
1117
1109
|
},
|
|
1118
|
-
|
|
1119
|
-
(
|
|
1120
|
-
o
|
|
1110
|
+
n,
|
|
1111
|
+
(o) => {
|
|
1112
|
+
r(o), this.manager.itemError(t);
|
|
1121
1113
|
}
|
|
1122
1114
|
);
|
|
1123
1115
|
});
|
|
@@ -1128,44 +1120,44 @@ class wt extends n.Loader {
|
|
|
1128
1120
|
* @returns Parsed SplatData
|
|
1129
1121
|
*/
|
|
1130
1122
|
parse(t) {
|
|
1131
|
-
const
|
|
1123
|
+
const n = new TextDecoder(), e = new Uint8Array(t), r = [112, 108, 121, 10], s = `
|
|
1132
1124
|
end_header
|
|
1133
1125
|
`;
|
|
1134
|
-
for (let x = 0; x <
|
|
1135
|
-
if (e[x] !==
|
|
1126
|
+
for (let x = 0; x < r.length; x++)
|
|
1127
|
+
if (e[x] !== r[x])
|
|
1136
1128
|
throw new Error("Invalid PLY file: Missing magic bytes");
|
|
1137
|
-
let
|
|
1129
|
+
let o = 0;
|
|
1138
1130
|
for (let x = 0; x < e.length - s.length; x++) {
|
|
1139
1131
|
let d = !0;
|
|
1140
|
-
for (let
|
|
1141
|
-
if (e[x +
|
|
1132
|
+
for (let z = 0; z < s.length; z++)
|
|
1133
|
+
if (e[x + z] !== s.charCodeAt(z)) {
|
|
1142
1134
|
d = !1;
|
|
1143
1135
|
break;
|
|
1144
1136
|
}
|
|
1145
1137
|
if (d) {
|
|
1146
|
-
|
|
1138
|
+
o = x + s.length;
|
|
1147
1139
|
break;
|
|
1148
1140
|
}
|
|
1149
1141
|
}
|
|
1150
|
-
if (
|
|
1142
|
+
if (o === 0)
|
|
1151
1143
|
throw new Error("Invalid PLY file: Could not find end of header");
|
|
1152
|
-
const c =
|
|
1153
|
-
e.slice(0,
|
|
1144
|
+
const c = n.decode(
|
|
1145
|
+
e.slice(0, o)
|
|
1154
1146
|
).split(`
|
|
1155
1147
|
`), h = [];
|
|
1156
1148
|
let v = null;
|
|
1157
1149
|
for (let x = 1; x < c.length; x++) {
|
|
1158
1150
|
const d = c[x].trim();
|
|
1159
1151
|
if (d === "" || d === "end_header") continue;
|
|
1160
|
-
const
|
|
1161
|
-
switch (
|
|
1152
|
+
const z = d.split(" ");
|
|
1153
|
+
switch (z[0]) {
|
|
1162
1154
|
case "format":
|
|
1163
|
-
v =
|
|
1155
|
+
v = z[1];
|
|
1164
1156
|
break;
|
|
1165
1157
|
case "element":
|
|
1166
1158
|
h.push({
|
|
1167
|
-
name:
|
|
1168
|
-
count: parseInt(
|
|
1159
|
+
name: z[1],
|
|
1160
|
+
count: parseInt(z[2], 10),
|
|
1169
1161
|
properties: []
|
|
1170
1162
|
});
|
|
1171
1163
|
break;
|
|
@@ -1175,8 +1167,8 @@ end_header
|
|
|
1175
1167
|
"Invalid PLY file: Property without element"
|
|
1176
1168
|
);
|
|
1177
1169
|
h[h.length - 1].properties.push({
|
|
1178
|
-
type:
|
|
1179
|
-
name:
|
|
1170
|
+
type: z[1],
|
|
1171
|
+
name: z[2],
|
|
1180
1172
|
storage: null
|
|
1181
1173
|
});
|
|
1182
1174
|
break;
|
|
@@ -1184,17 +1176,17 @@ end_header
|
|
|
1184
1176
|
}
|
|
1185
1177
|
if (v !== "binary_little_endian")
|
|
1186
1178
|
throw new Error(`Unsupported PLY format: ${v}`);
|
|
1187
|
-
const
|
|
1188
|
-
if (!
|
|
1179
|
+
const y = h.find((x) => x.name === "vertex");
|
|
1180
|
+
if (!y)
|
|
1189
1181
|
throw new Error("Invalid PLY file: No vertex element found");
|
|
1190
|
-
const p = new
|
|
1191
|
-
let l =
|
|
1192
|
-
const b = (x) =>
|
|
1182
|
+
const p = new ut(y.count), u = new DataView(t);
|
|
1183
|
+
let l = o;
|
|
1184
|
+
const b = (x) => y.properties.findIndex((d) => d.name === x), B = b("x"), O = b("y"), q = b("z"), E = [
|
|
1193
1185
|
b("rot_0"),
|
|
1194
1186
|
b("rot_1"),
|
|
1195
1187
|
b("rot_2"),
|
|
1196
1188
|
b("rot_3")
|
|
1197
|
-
],
|
|
1189
|
+
], R = [
|
|
1198
1190
|
b("scale_0"),
|
|
1199
1191
|
b("scale_1"),
|
|
1200
1192
|
b("scale_2")
|
|
@@ -1204,98 +1196,97 @@ end_header
|
|
|
1204
1196
|
b("f_dc_2")
|
|
1205
1197
|
], F = b("opacity");
|
|
1206
1198
|
if ([
|
|
1207
|
-
|
|
1199
|
+
B,
|
|
1208
1200
|
O,
|
|
1209
1201
|
q,
|
|
1210
|
-
...R,
|
|
1211
1202
|
...E,
|
|
1203
|
+
...R,
|
|
1212
1204
|
...W,
|
|
1213
1205
|
F
|
|
1214
1206
|
].some((x) => x === -1))
|
|
1215
1207
|
throw new Error("Invalid PLY file: Missing required properties");
|
|
1216
|
-
const
|
|
1208
|
+
const D = 0.28209479177387814, M = (x) => {
|
|
1217
1209
|
if (x > 0) return 1 / (1 + Math.exp(-x));
|
|
1218
1210
|
const d = Math.exp(x);
|
|
1219
1211
|
return d / (1 + d);
|
|
1220
|
-
}, m = new
|
|
1221
|
-
for (let x = 0; x <
|
|
1212
|
+
}, m = new i.Vector3(), C = new i.Quaternion(), _ = new i.Vector3(), V = new i.Color();
|
|
1213
|
+
for (let x = 0; x < y.count; x++) {
|
|
1222
1214
|
const d = [];
|
|
1223
|
-
for (let
|
|
1224
|
-
const
|
|
1225
|
-
let
|
|
1226
|
-
switch (
|
|
1215
|
+
for (let T = 0; T < y.properties.length; T++) {
|
|
1216
|
+
const K = y.properties[T].type;
|
|
1217
|
+
let I;
|
|
1218
|
+
switch (K) {
|
|
1227
1219
|
case "char":
|
|
1228
|
-
|
|
1220
|
+
I = u.getInt8(l), l += 1;
|
|
1229
1221
|
break;
|
|
1230
1222
|
case "uchar":
|
|
1231
|
-
|
|
1223
|
+
I = u.getUint8(l), l += 1;
|
|
1232
1224
|
break;
|
|
1233
1225
|
case "short":
|
|
1234
|
-
|
|
1226
|
+
I = u.getInt16(l, !0), l += 2;
|
|
1235
1227
|
break;
|
|
1236
1228
|
case "ushort":
|
|
1237
|
-
|
|
1229
|
+
I = u.getUint16(l, !0), l += 2;
|
|
1238
1230
|
break;
|
|
1239
1231
|
case "int":
|
|
1240
|
-
|
|
1232
|
+
I = u.getInt32(l, !0), l += 4;
|
|
1241
1233
|
break;
|
|
1242
1234
|
case "uint":
|
|
1243
|
-
|
|
1235
|
+
I = u.getUint32(l, !0), l += 4;
|
|
1244
1236
|
break;
|
|
1245
1237
|
case "float":
|
|
1246
|
-
|
|
1238
|
+
I = u.getFloat32(l, !0), l += 4;
|
|
1247
1239
|
break;
|
|
1248
1240
|
case "double":
|
|
1249
|
-
|
|
1241
|
+
I = u.getFloat64(l, !0), l += 8;
|
|
1250
1242
|
break;
|
|
1251
1243
|
default:
|
|
1252
|
-
throw new Error(`Unsupported property type: ${
|
|
1244
|
+
throw new Error(`Unsupported property type: ${K}`);
|
|
1253
1245
|
}
|
|
1254
|
-
d.push(
|
|
1246
|
+
d.push(I);
|
|
1255
1247
|
}
|
|
1256
1248
|
m.set(
|
|
1257
|
-
d[
|
|
1249
|
+
d[B],
|
|
1258
1250
|
d[O],
|
|
1259
1251
|
d[q]
|
|
1260
|
-
),
|
|
1261
|
-
// TODO: dangerous see if true
|
|
1262
|
-
d[R[1]],
|
|
1263
|
-
// PLY stores rot 1,2,3,0 (x,y,z,w)
|
|
1264
|
-
d[R[2]],
|
|
1265
|
-
d[R[3]],
|
|
1266
|
-
d[R[0]]
|
|
1267
|
-
).normalize(), P.set(
|
|
1268
|
-
d[E[0]],
|
|
1269
|
-
// Read directly assuming it's log scale
|
|
1252
|
+
), C.set(
|
|
1270
1253
|
d[E[1]],
|
|
1271
|
-
|
|
1254
|
+
// PLY stores rot 1,2,3,0 (x,y,z,w)
|
|
1255
|
+
d[E[2]],
|
|
1256
|
+
d[E[3]],
|
|
1257
|
+
d[E[0]]
|
|
1258
|
+
).normalize(), C.w < 0 && (C.x = -C.x, C.y = -C.y, C.z = -C.z, C.w = -C.w), _.set(
|
|
1259
|
+
d[R[0]],
|
|
1260
|
+
// Read directly assuming it's log scale
|
|
1261
|
+
d[R[1]],
|
|
1262
|
+
d[R[2]]
|
|
1272
1263
|
), V.set(
|
|
1273
|
-
0.5 + d[W[0]] *
|
|
1274
|
-
0.5 + d[W[1]] *
|
|
1275
|
-
0.5 + d[W[2]] *
|
|
1264
|
+
0.5 + d[W[0]] * D,
|
|
1265
|
+
0.5 + d[W[1]] * D,
|
|
1266
|
+
0.5 + d[W[2]] * D
|
|
1276
1267
|
), V.r = Math.max(0, Math.min(1, V.r)), V.g = Math.max(0, Math.min(1, V.g)), V.b = Math.max(0, Math.min(1, V.b));
|
|
1277
|
-
const
|
|
1268
|
+
const z = M(d[F]);
|
|
1278
1269
|
p.setSplat(
|
|
1279
1270
|
x,
|
|
1280
1271
|
m,
|
|
1281
|
-
|
|
1282
|
-
|
|
1272
|
+
C,
|
|
1273
|
+
_,
|
|
1283
1274
|
// Pass log scale directly
|
|
1284
1275
|
V,
|
|
1285
|
-
|
|
1276
|
+
z
|
|
1286
1277
|
);
|
|
1287
1278
|
}
|
|
1288
1279
|
return p.calculateBoundingBox(), p;
|
|
1289
1280
|
}
|
|
1290
1281
|
}
|
|
1291
|
-
const
|
|
1282
|
+
const Mt = "0.3.0";
|
|
1292
1283
|
export {
|
|
1293
1284
|
et as BoundingBox,
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1285
|
+
bt as PlyLoader,
|
|
1286
|
+
ut as SplatData,
|
|
1287
|
+
vt as SplatMaterial,
|
|
1288
|
+
it as SplatMesh,
|
|
1289
|
+
dt as SplatSorter,
|
|
1290
|
+
xt as TextureManager,
|
|
1291
|
+
Mt as VERSION
|
|
1301
1292
|
};
|