@speridlabs/visus 1.0.2 → 1.0.4
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 +328 -320
- package/dist/main.es.js +530 -671
- package/dist/main.umd.js +6 -6
- package/dist/react.es.js +606 -747
- 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 lt = Object.defineProperty;
|
|
2
|
+
var ht = (I, t, s) => t in I ? lt(I, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : I[t] = s;
|
|
3
|
+
var c = (I, t, s) => ht(I, typeof t != "symbol" ? t + "" : t, s);
|
|
4
|
+
import * as n from "three";
|
|
5
|
+
class et {
|
|
6
6
|
constructor() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
c(this, "min", new n.Vector3(1 / 0, 1 / 0, 1 / 0));
|
|
8
|
+
c(this, "max", new n.Vector3(-1 / 0, -1 / 0, -1 / 0));
|
|
9
|
+
c(this, "center", new n.Vector3());
|
|
10
10
|
/** Half extents (size/2) */
|
|
11
|
-
|
|
11
|
+
c(this, "halfExtents", new n.Vector3());
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Reset the bounding box to its initial state
|
|
@@ -20,15 +20,15 @@ class te {
|
|
|
20
20
|
* Expand the bounding box to include the given point
|
|
21
21
|
* @param point Point to include in the bounding box
|
|
22
22
|
*/
|
|
23
|
-
expandByPoint(
|
|
24
|
-
this.min.x = Math.min(this.min.x,
|
|
23
|
+
expandByPoint(t) {
|
|
24
|
+
this.min.x = Math.min(this.min.x, t.x), this.min.y = Math.min(this.min.y, t.y), this.min.z = Math.min(this.min.z, t.z), this.max.x = Math.max(this.max.x, t.x), this.max.y = Math.max(this.max.y, t.y), this.max.z = Math.max(this.max.z, t.z), this.updateDerived();
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Expand this bounding box to include another bounding box
|
|
28
28
|
* @param box Bounding box to include
|
|
29
29
|
*/
|
|
30
|
-
expandByBox(
|
|
31
|
-
this.min.x = Math.min(this.min.x,
|
|
30
|
+
expandByBox(t) {
|
|
31
|
+
this.min.x = Math.min(this.min.x, t.min.x), this.min.y = Math.min(this.min.y, t.min.y), this.min.z = Math.min(this.min.z, t.min.z), this.max.x = Math.max(this.max.x, t.max.x), this.max.y = Math.max(this.max.y, t.max.y), this.max.z = Math.max(this.max.z, t.max.z), this.updateDerived();
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Update the center and half extents based on min/max
|
|
@@ -41,40 +41,40 @@ class te {
|
|
|
41
41
|
* @param point Point to check
|
|
42
42
|
* @returns True if the point is inside the box
|
|
43
43
|
*/
|
|
44
|
-
containsPoint(
|
|
45
|
-
return
|
|
44
|
+
containsPoint(t) {
|
|
45
|
+
return t.x >= this.min.x && t.x <= this.max.x && t.y >= this.min.y && t.y <= this.max.y && t.z >= this.min.z && t.z <= this.max.z;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* Create a Three.js Box3 from this bounding box
|
|
49
49
|
* @returns THREE.Box3 representation
|
|
50
50
|
*/
|
|
51
51
|
toBox3() {
|
|
52
|
-
return new
|
|
52
|
+
return new n.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
|
|
60
|
-
return
|
|
59
|
+
const t = new et();
|
|
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
|
-
constructor(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.numSplats =
|
|
65
|
+
constructor(t = 0) {
|
|
66
|
+
c(this, "numSplats", 0);
|
|
67
|
+
c(this, "positions");
|
|
68
|
+
c(this, "rotations");
|
|
69
|
+
c(this, "scales");
|
|
70
|
+
c(this, "colors");
|
|
71
|
+
c(this, "opacities");
|
|
72
|
+
c(this, "centers");
|
|
73
|
+
c(this, "boundingBox", new et());
|
|
74
|
+
this.numSplats = t, this.allocateBuffers(t);
|
|
75
75
|
}
|
|
76
|
-
allocateBuffers(
|
|
77
|
-
this.positions = new Float32Array(
|
|
76
|
+
allocateBuffers(t) {
|
|
77
|
+
this.positions = new Float32Array(t * 3), this.rotations = new Float32Array(t * 4), this.scales = new Float32Array(t * 3), this.colors = new Float32Array(t * 3), this.opacities = new Float32Array(t), this.centers = new Float32Array(t * 3);
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
80
|
* Set data for a specific splat
|
|
@@ -85,49 +85,49 @@ class de {
|
|
|
85
85
|
* @param color Color
|
|
86
86
|
* @param opacity Opacity value
|
|
87
87
|
*/
|
|
88
|
-
setSplat(
|
|
89
|
-
if (
|
|
88
|
+
setSplat(t, s, e, r, o, i) {
|
|
89
|
+
if (t >= this.numSplats)
|
|
90
90
|
throw new Error(
|
|
91
|
-
`Splat index out of bounds: ${
|
|
91
|
+
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
92
92
|
);
|
|
93
|
-
const a =
|
|
94
|
-
this.positions[a] =
|
|
93
|
+
const a = t * 3, d = t * 4, f = t * 3, v = t * 3;
|
|
94
|
+
this.positions[a] = s.x, this.positions[a + 1] = s.y, this.positions[a + 2] = s.z, this.rotations[d] = e.x, this.rotations[d + 1] = e.y, this.rotations[d + 2] = e.z, this.rotations[d + 3] = e.w, this.scales[f] = r.x, this.scales[f + 1] = r.y, this.scales[f + 2] = r.z, this.colors[v] = o.r, this.colors[v + 1] = o.g, this.colors[v + 2] = o.b, this.opacities[t] = i, this.centers[a] = s.x, this.centers[a + 1] = s.y, this.centers[a + 2] = s.z;
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Get a splat's data
|
|
98
98
|
* @param index Splat index
|
|
99
99
|
* @returns Object containing splat data (linear scale)
|
|
100
100
|
*/
|
|
101
|
-
getSplat(
|
|
102
|
-
if (
|
|
101
|
+
getSplat(t) {
|
|
102
|
+
if (t >= this.numSplats)
|
|
103
103
|
throw new Error(
|
|
104
|
-
`Splat index out of bounds: ${
|
|
104
|
+
`Splat index out of bounds: ${t} >= ${this.numSplats}`
|
|
105
105
|
);
|
|
106
|
-
const
|
|
106
|
+
const s = t * 3, e = t * 4, r = t * 3, o = t * 3;
|
|
107
107
|
return {
|
|
108
|
-
position: new
|
|
109
|
-
this.positions[
|
|
110
|
-
this.positions[
|
|
111
|
-
this.positions[
|
|
108
|
+
position: new n.Vector3(
|
|
109
|
+
this.positions[s],
|
|
110
|
+
this.positions[s + 1],
|
|
111
|
+
this.positions[s + 2]
|
|
112
112
|
),
|
|
113
|
-
rotation: new
|
|
114
|
-
this.rotations[
|
|
115
|
-
this.rotations[
|
|
116
|
-
this.rotations[
|
|
117
|
-
this.rotations[
|
|
113
|
+
rotation: new n.Quaternion(
|
|
114
|
+
this.rotations[e],
|
|
115
|
+
this.rotations[e + 1],
|
|
116
|
+
this.rotations[e + 2],
|
|
117
|
+
this.rotations[e + 3]
|
|
118
118
|
),
|
|
119
119
|
// Convert log scale back to linear scale for external use
|
|
120
|
-
scale: new
|
|
120
|
+
scale: new n.Vector3(
|
|
121
121
|
Math.exp(this.scales[r]),
|
|
122
122
|
Math.exp(this.scales[r + 1]),
|
|
123
123
|
Math.exp(this.scales[r + 2])
|
|
124
124
|
),
|
|
125
|
-
color: new
|
|
126
|
-
this.colors[
|
|
127
|
-
this.colors[
|
|
128
|
-
this.colors[
|
|
125
|
+
color: new n.Color(
|
|
126
|
+
this.colors[o],
|
|
127
|
+
this.colors[o + 1],
|
|
128
|
+
this.colors[o + 2]
|
|
129
129
|
),
|
|
130
|
-
opacity: this.opacities[
|
|
130
|
+
opacity: this.opacities[t]
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
@@ -136,14 +136,14 @@ class de {
|
|
|
136
136
|
*/
|
|
137
137
|
calculateBoundingBox() {
|
|
138
138
|
this.boundingBox.reset();
|
|
139
|
-
const
|
|
140
|
-
for (let
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
this.positions[
|
|
144
|
-
this.positions[
|
|
145
|
-
this.positions[
|
|
146
|
-
), this.boundingBox.expandByPoint(
|
|
139
|
+
const t = new n.Vector3();
|
|
140
|
+
for (let s = 0; s < this.numSplats; s++) {
|
|
141
|
+
const e = s * 3;
|
|
142
|
+
t.set(
|
|
143
|
+
this.positions[e],
|
|
144
|
+
this.positions[e + 1],
|
|
145
|
+
this.positions[e + 2]
|
|
146
|
+
), this.boundingBox.expandByPoint(t);
|
|
147
147
|
}
|
|
148
148
|
return this.boundingBox;
|
|
149
149
|
}
|
|
@@ -152,64 +152,64 @@ class de {
|
|
|
152
152
|
* This is for visualization/debugging purposes only, not for rendering
|
|
153
153
|
*/
|
|
154
154
|
createDebugGeometry() {
|
|
155
|
-
const
|
|
156
|
-
|
|
155
|
+
const t = new n.BufferGeometry();
|
|
156
|
+
t.setAttribute(
|
|
157
157
|
"position",
|
|
158
|
-
new
|
|
158
|
+
new n.BufferAttribute(this.positions, 3)
|
|
159
159
|
);
|
|
160
|
-
const
|
|
161
|
-
for (let
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
this.rotations[
|
|
165
|
-
this.rotations[
|
|
166
|
-
this.rotations[
|
|
167
|
-
this.rotations[
|
|
168
|
-
), r.setFromQuaternion(
|
|
160
|
+
const s = new Float32Array(this.numSplats * 3), e = new n.Quaternion(), r = new n.Euler();
|
|
161
|
+
for (let o = 0; o < this.numSplats; o++) {
|
|
162
|
+
const i = o * 4, a = o * 3;
|
|
163
|
+
e.set(
|
|
164
|
+
this.rotations[i],
|
|
165
|
+
this.rotations[i + 1],
|
|
166
|
+
this.rotations[i + 2],
|
|
167
|
+
this.rotations[i + 3]
|
|
168
|
+
), r.setFromQuaternion(e), s[a] = r.x, s[a + 1] = r.y, s[a + 2] = r.z;
|
|
169
169
|
}
|
|
170
|
-
return
|
|
170
|
+
return t.setAttribute(
|
|
171
171
|
"rotation",
|
|
172
|
-
new
|
|
173
|
-
),
|
|
172
|
+
new n.BufferAttribute(s, 3)
|
|
173
|
+
), t.setAttribute(
|
|
174
174
|
"scale",
|
|
175
|
-
new
|
|
176
|
-
),
|
|
175
|
+
new n.BufferAttribute(this.scales, 3)
|
|
176
|
+
), t.setAttribute(
|
|
177
177
|
"color",
|
|
178
|
-
new
|
|
179
|
-
),
|
|
178
|
+
new n.BufferAttribute(this.colors, 3)
|
|
179
|
+
), t.setAttribute(
|
|
180
180
|
"opacity",
|
|
181
|
-
new
|
|
182
|
-
),
|
|
181
|
+
new n.BufferAttribute(this.opacities, 1)
|
|
182
|
+
), t;
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
|
-
class
|
|
185
|
+
class dt extends n.EventDispatcher {
|
|
186
186
|
constructor() {
|
|
187
187
|
super();
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
c(this, "worker");
|
|
189
|
+
c(this, "centers", null);
|
|
190
|
+
c(this, "orderTexture", null);
|
|
191
191
|
/** Bounding box data for optimization */
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
this.worker = new Worker(URL.createObjectURL(
|
|
192
|
+
c(this, "chunks", null);
|
|
193
|
+
c(this, "lastCameraPosition", new n.Vector3());
|
|
194
|
+
c(this, "lastCameraDirection", new n.Vector3());
|
|
195
|
+
const s = this.createWorkerCode(), e = new Blob([s], { type: "application/javascript" });
|
|
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(s) {
|
|
203
203
|
if (!this.orderTexture || !this.orderTexture.image)
|
|
204
204
|
return console.error("SplatSorter: Order texture not initialized!");
|
|
205
|
-
const { order:
|
|
206
|
-
if (!(
|
|
205
|
+
const { order: e, count: r } = s.data, o = this.orderTexture.image.data;
|
|
206
|
+
if (!(o 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(a, [
|
|
210
|
+
o.set(new Uint32Array(e)), this.orderTexture.needsUpdate = !0;
|
|
211
|
+
const i = o.buffer.slice(0), a = { order: i };
|
|
212
|
+
this.worker.postMessage(a, [i]), this.dispatchEvent({ type: "updated", count: r });
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
215
|
* Initializes the sorter with necessary data and textures.
|
|
@@ -217,84 +217,89 @@ class he extends i.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(s, e, r) {
|
|
221
|
+
if (!s || !(s.image.data instanceof Uint32Array))
|
|
222
222
|
throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");
|
|
223
|
-
if (!
|
|
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 (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
|
|
228
|
-
this.orderTexture =
|
|
229
|
-
const
|
|
230
|
-
for (let
|
|
227
|
+
const o = e.length / 3;
|
|
228
|
+
this.orderTexture = s, this.centers = e.slice();
|
|
229
|
+
const i = this.orderTexture.image.data;
|
|
230
|
+
for (let g = 0; g < o; g++) i[g] = g;
|
|
231
231
|
this.orderTexture.needsUpdate = !0;
|
|
232
|
-
const a =
|
|
232
|
+
const a = i.buffer.slice(0), d = this.centers.buffer.slice(0), f = {
|
|
233
233
|
order: a,
|
|
234
|
-
centers:
|
|
235
|
-
},
|
|
234
|
+
centers: d
|
|
235
|
+
}, v = [
|
|
236
236
|
a,
|
|
237
|
-
|
|
237
|
+
d
|
|
238
238
|
];
|
|
239
239
|
if (r) {
|
|
240
240
|
this.chunks = r.slice();
|
|
241
|
-
const
|
|
242
|
-
f.chunks =
|
|
241
|
+
const g = this.chunks.buffer.slice(0);
|
|
242
|
+
f.chunks = g, v.push(g);
|
|
243
243
|
}
|
|
244
|
-
this.worker.postMessage(f,
|
|
244
|
+
this.worker.postMessage(f, v), queueMicrotask(() => {
|
|
245
|
+
this.dispatchEvent({
|
|
246
|
+
type: "updated",
|
|
247
|
+
count: o
|
|
248
|
+
});
|
|
249
|
+
});
|
|
245
250
|
}
|
|
246
251
|
/**
|
|
247
252
|
* Applies an optional mapping to filter or reorder splats before sorting.
|
|
248
253
|
* The sorter will only consider splats whose original indices are present in the mapping.
|
|
249
254
|
* @param mapping A Uint32Array where each element is the *original* index of a splat to include, or null to reset mapping.
|
|
250
255
|
*/
|
|
251
|
-
setMapping(
|
|
256
|
+
setMapping(s) {
|
|
252
257
|
if (!this.centers)
|
|
253
258
|
return console.warn(
|
|
254
259
|
"SplatSorter: Cannot set mapping before initialization."
|
|
255
260
|
);
|
|
256
|
-
let
|
|
261
|
+
let e;
|
|
257
262
|
const r = [];
|
|
258
|
-
if (!
|
|
259
|
-
const
|
|
260
|
-
return
|
|
261
|
-
centers:
|
|
263
|
+
if (!s) {
|
|
264
|
+
const d = this.centers.buffer.slice(0);
|
|
265
|
+
return e = {
|
|
266
|
+
centers: d,
|
|
262
267
|
mapping: null
|
|
263
|
-
}, r.push(
|
|
268
|
+
}, r.push(d), this.worker.postMessage(e, r);
|
|
264
269
|
}
|
|
265
|
-
const
|
|
266
|
-
for (let
|
|
267
|
-
const f =
|
|
270
|
+
const o = new Float32Array(s.length * 3);
|
|
271
|
+
for (let d = 0; d < s.length; d++) {
|
|
272
|
+
const f = s[d];
|
|
268
273
|
if (f * 3 + 2 >= this.centers.length) {
|
|
269
274
|
console.warn(
|
|
270
275
|
`SplatSorter: Mapping index ${f} out of bounds.`
|
|
271
276
|
);
|
|
272
277
|
continue;
|
|
273
278
|
}
|
|
274
|
-
const
|
|
275
|
-
|
|
279
|
+
const v = f * 3, g = d * 3;
|
|
280
|
+
o[g + 0] = this.centers[v + 0], o[g + 1] = this.centers[v + 1], o[g + 2] = this.centers[v + 2];
|
|
276
281
|
}
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
centers:
|
|
282
|
+
const i = o.buffer.slice(0), a = s.buffer.slice(0);
|
|
283
|
+
e = {
|
|
284
|
+
centers: i,
|
|
280
285
|
mapping: a
|
|
281
|
-
}, r.push(
|
|
286
|
+
}, r.push(i, a), this.worker.postMessage(e, r);
|
|
282
287
|
}
|
|
283
288
|
/**
|
|
284
289
|
* Updates the camera parameters used for sorting.
|
|
285
290
|
* @param position The camera's position in the sorter's local coordinate space.
|
|
286
291
|
* @param direction The camera's forward direction in the sorter's local coordinate space.
|
|
287
292
|
*/
|
|
288
|
-
setCamera(
|
|
289
|
-
const r = this.lastCameraPosition.distanceToSquared(
|
|
290
|
-
if (!r && !
|
|
293
|
+
setCamera(s, e) {
|
|
294
|
+
const r = this.lastCameraPosition.distanceToSquared(s) > 1e-7, o = this.lastCameraDirection.dot(e) < 0.9999;
|
|
295
|
+
if (!r && !o)
|
|
291
296
|
return;
|
|
292
|
-
this.lastCameraPosition.copy(
|
|
293
|
-
const
|
|
294
|
-
cameraPosition: { x:
|
|
295
|
-
cameraDirection: { x:
|
|
297
|
+
this.lastCameraPosition.copy(s), this.lastCameraDirection.copy(e);
|
|
298
|
+
const i = {
|
|
299
|
+
cameraPosition: { x: s.x, y: s.y, z: s.z },
|
|
300
|
+
cameraDirection: { x: e.x, y: e.y, z: e.z }
|
|
296
301
|
};
|
|
297
|
-
this.worker.postMessage(
|
|
302
|
+
this.worker.postMessage(i);
|
|
298
303
|
}
|
|
299
304
|
/**
|
|
300
305
|
* Terminates the Web Worker and cleans up resources.
|
|
@@ -308,232 +313,232 @@ class he extends i.EventDispatcher {
|
|
|
308
313
|
*/
|
|
309
314
|
createWorkerCode() {
|
|
310
315
|
return `(${(function() {
|
|
311
|
-
let
|
|
312
|
-
const
|
|
313
|
-
let
|
|
314
|
-
const
|
|
315
|
-
for (;
|
|
316
|
-
const
|
|
317
|
-
if (
|
|
318
|
-
else if (
|
|
319
|
-
else return
|
|
316
|
+
let e = null, r = null, o = null, i = null, a = null, d = null, f = !1;
|
|
317
|
+
const v = { x: 0, y: 0, z: 0 }, g = { x: 0, y: 0, z: 0 }, p = { x: 0, y: 0, z: 0 }, h = { x: 0, y: 0, z: 0 };
|
|
318
|
+
let l = null, b = null;
|
|
319
|
+
const _ = 32, O = new Array(_).fill(0), q = new Array(_).fill(0), E = new Array(_).fill(0), R = (k, S, F) => {
|
|
320
|
+
for (; k <= S; ) {
|
|
321
|
+
const M = S + k >> 1, m = F(M);
|
|
322
|
+
if (m > 0) k = M + 1;
|
|
323
|
+
else if (m < 0) S = M - 1;
|
|
324
|
+
else return M;
|
|
320
325
|
}
|
|
321
|
-
return ~
|
|
326
|
+
return ~k;
|
|
322
327
|
}, W = () => {
|
|
323
|
-
if (!
|
|
328
|
+
if (!e || !r || !a || !d)
|
|
324
329
|
return;
|
|
325
330
|
if (r.length === 0) {
|
|
326
|
-
const
|
|
327
|
-
order:
|
|
331
|
+
const y = {
|
|
332
|
+
order: e.buffer,
|
|
328
333
|
count: 0
|
|
329
334
|
};
|
|
330
|
-
self.postMessage(
|
|
335
|
+
self.postMessage(y, [e.buffer]), e = null;
|
|
331
336
|
return;
|
|
332
337
|
}
|
|
333
|
-
const
|
|
334
|
-
if (!f && !
|
|
338
|
+
const k = a.x, S = a.y, F = a.z, M = d.x, m = d.y, C = d.z, V = 1e-4, P = Math.abs(k - v.x) > V || Math.abs(S - v.y) > V || Math.abs(F - v.z) > V, x = Math.abs(M - g.x) > V || Math.abs(m - g.y) > V || Math.abs(C - g.z) > V;
|
|
339
|
+
if (!f && !P && !x)
|
|
335
340
|
return;
|
|
336
|
-
f = !1,
|
|
337
|
-
let
|
|
338
|
-
for (let
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
+
f = !1, v.x = k, v.y = S, v.z = F, g.x = M, g.y = m, g.z = C;
|
|
342
|
+
let u = 1 / 0, z = -1 / 0;
|
|
343
|
+
for (let y = 0; y < 8; ++y) {
|
|
344
|
+
const B = y & 1 ? p.x : h.x, U = y & 2 ? p.y : h.y, w = y & 4 ? p.z : h.z, D = B * M + U * m + w * C;
|
|
345
|
+
u = Math.min(u, D), z = Math.max(z, D);
|
|
341
346
|
}
|
|
342
|
-
const
|
|
347
|
+
const T = r.length / 3, L = z - u, A = (1 << Math.max(
|
|
343
348
|
10,
|
|
344
|
-
Math.min(20, Math.ceil(Math.log2(
|
|
349
|
+
Math.min(20, Math.ceil(Math.log2(T / 4)))
|
|
345
350
|
)) + 1;
|
|
346
|
-
if ((!
|
|
347
|
-
for (let
|
|
348
|
-
|
|
349
|
-
} else if (
|
|
350
|
-
const
|
|
351
|
+
if ((!l || l.length !== T) && (l = new Uint32Array(T)), !b || b.length !== A ? b = new Uint32Array(A) : b.fill(0), L < 1e-7) {
|
|
352
|
+
for (let y = 0; y < T; ++y) l[y] = 0;
|
|
353
|
+
b[0] = T;
|
|
354
|
+
} else if (o && o.length > 0) {
|
|
355
|
+
const y = o.length / 6;
|
|
351
356
|
O.fill(0);
|
|
352
|
-
for (let
|
|
353
|
-
const D =
|
|
357
|
+
for (let w = 0; w < y; ++w) {
|
|
358
|
+
const D = w * 6, X = o[D + 0], Z = o[D + 1], $ = o[D + 2], H = o[D + 3], Y = X * M + Z * m + $ * C - u, J = Y - H, G = Y + H, Q = Math.max(
|
|
354
359
|
0,
|
|
355
|
-
Math.floor(
|
|
356
|
-
),
|
|
357
|
-
|
|
358
|
-
Math.ceil(
|
|
360
|
+
Math.floor(J * _ / L)
|
|
361
|
+
), tt = Math.min(
|
|
362
|
+
_,
|
|
363
|
+
Math.ceil(G * _ / L)
|
|
359
364
|
);
|
|
360
|
-
for (let
|
|
361
|
-
O[
|
|
365
|
+
for (let N = Q; N < tt; ++N)
|
|
366
|
+
O[N]++;
|
|
362
367
|
}
|
|
363
|
-
let
|
|
364
|
-
for (let
|
|
365
|
-
|
|
366
|
-
for (let
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const
|
|
370
|
-
for (let
|
|
371
|
-
const D =
|
|
368
|
+
let B = 0;
|
|
369
|
+
for (let w = 0; w < _; ++w) B += O[w];
|
|
370
|
+
E[0] = 0, q[0] = 0;
|
|
371
|
+
for (let w = 1; w < _; ++w)
|
|
372
|
+
E[w - 1] = O[w - 1] / B * A >>> 0, q[w] = q[w - 1] + E[w - 1];
|
|
373
|
+
E[_ - 1] = O[_ - 1] / B * A >>> 0;
|
|
374
|
+
const U = L / _;
|
|
375
|
+
for (let w = 0; w < T; ++w) {
|
|
376
|
+
const D = w * 3, X = r[D + 0], Z = r[D + 1], $ = r[D + 2], H = X * M + Z * m + $ * C, J = (z - H) / U, G = Math.max(
|
|
372
377
|
0,
|
|
373
378
|
Math.min(
|
|
374
|
-
|
|
375
|
-
Math.floor(
|
|
379
|
+
_ - 1,
|
|
380
|
+
Math.floor(J)
|
|
376
381
|
)
|
|
377
|
-
), Q =
|
|
378
|
-
|
|
382
|
+
), Q = J - G, tt = q[G] + E[G] * Q >>> 0, N = Math.min(tt, A - 1);
|
|
383
|
+
l[w] = N, b[N]++;
|
|
379
384
|
}
|
|
380
385
|
} else {
|
|
381
|
-
const
|
|
382
|
-
for (let
|
|
383
|
-
const
|
|
384
|
-
|
|
386
|
+
const y = (A - 1) / L;
|
|
387
|
+
for (let B = 0; B < T; ++B) {
|
|
388
|
+
const U = B * 3, w = r[U + 0], D = r[U + 1], X = r[U + 2], Z = w * M + D * m + X * C, H = (z - Z) * y >>> 0, Y = Math.min(H, A - 1);
|
|
389
|
+
l[B] = Y, b[Y]++;
|
|
385
390
|
}
|
|
386
391
|
}
|
|
387
|
-
for (let
|
|
388
|
-
|
|
389
|
-
for (let
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
+
for (let y = 1; y < A; y++)
|
|
393
|
+
b[y] += b[y - 1];
|
|
394
|
+
for (let y = T - 1; y >= 0; y--) {
|
|
395
|
+
const B = l[y], U = --b[B];
|
|
396
|
+
e[U] = i ? i[y] : y;
|
|
392
397
|
}
|
|
393
|
-
const
|
|
394
|
-
if (!
|
|
395
|
-
const
|
|
396
|
-
if (!r ||
|
|
398
|
+
const at = k * M + S * m + F * C, rt = (y) => {
|
|
399
|
+
if (!e) return -1 / 0;
|
|
400
|
+
const B = e[y], U = B;
|
|
401
|
+
if (!r || U * 3 + 2 >= r.length)
|
|
397
402
|
return -1 / 0;
|
|
398
|
-
const
|
|
399
|
-
return r[
|
|
403
|
+
const w = U * 3;
|
|
404
|
+
return r[w] * M + r[w + 1] * m + r[w + 2] * C - at;
|
|
400
405
|
};
|
|
401
|
-
let
|
|
402
|
-
if (
|
|
403
|
-
const
|
|
406
|
+
let st = T;
|
|
407
|
+
if (T > 0 && rt(T - 1) < 0) {
|
|
408
|
+
const y = R(
|
|
404
409
|
0,
|
|
405
|
-
|
|
406
|
-
|
|
410
|
+
T - 1,
|
|
411
|
+
rt
|
|
407
412
|
);
|
|
408
|
-
|
|
413
|
+
st = y < 0 ? ~y : y;
|
|
409
414
|
}
|
|
410
|
-
const
|
|
411
|
-
order:
|
|
412
|
-
count:
|
|
415
|
+
const ct = {
|
|
416
|
+
order: e.buffer,
|
|
417
|
+
count: st
|
|
413
418
|
};
|
|
414
|
-
self.postMessage(
|
|
419
|
+
self.postMessage(ct, [e.buffer]), e = null;
|
|
415
420
|
};
|
|
416
|
-
self.onmessage = (
|
|
417
|
-
const
|
|
418
|
-
|
|
421
|
+
self.onmessage = (k) => {
|
|
422
|
+
const S = k.data;
|
|
423
|
+
S.order && (e = new Uint32Array(S.order));
|
|
419
424
|
let F = !1;
|
|
420
|
-
if (
|
|
421
|
-
if (
|
|
422
|
-
for (let
|
|
423
|
-
const
|
|
424
|
-
|
|
425
|
-
(
|
|
425
|
+
if (S.centers && (r = new Float32Array(S.centers), F = !0, f = !0), Object.prototype.hasOwnProperty.call(S, "mapping") && (i = S.mapping ? new Uint32Array(S.mapping) : null, f = !0), S.chunks) {
|
|
426
|
+
if (o = new Float32Array(S.chunks), o.length > 0 && o[3] > 0)
|
|
427
|
+
for (let M = 0; M < o.length / 6; ++M) {
|
|
428
|
+
const m = M * 6, C = o[m + 0], V = o[m + 1], P = o[m + 2], x = o[m + 3], u = o[m + 4], z = o[m + 5];
|
|
429
|
+
o[m + 0] = (C + x) * 0.5, o[m + 1] = (V + u) * 0.5, o[m + 2] = (P + z) * 0.5, o[m + 3] = Math.sqrt(
|
|
430
|
+
(x - C) ** 2 + (u - V) ** 2 + (z - P) ** 2
|
|
426
431
|
) * 0.5;
|
|
427
432
|
}
|
|
428
433
|
f = !0;
|
|
429
434
|
}
|
|
430
435
|
if (F && r && r.length > 0) {
|
|
431
|
-
|
|
432
|
-
for (let
|
|
433
|
-
const
|
|
434
|
-
|
|
436
|
+
p.x = h.x = r[0], p.y = h.y = r[1], p.z = h.z = r[2];
|
|
437
|
+
for (let M = 1; M < r.length / 3; M++) {
|
|
438
|
+
const m = M * 3;
|
|
439
|
+
p.x = Math.min(p.x, r[m + 0]), h.x = Math.max(h.x, r[m + 0]), p.y = Math.min(p.y, r[m + 1]), h.y = Math.max(h.y, r[m + 1]), p.z = Math.min(p.z, r[m + 2]), h.z = Math.max(h.z, r[m + 2]);
|
|
435
440
|
}
|
|
436
|
-
} else F && r && r.length === 0 && (
|
|
437
|
-
|
|
441
|
+
} else F && r && r.length === 0 && (p.x = h.x = p.y = h.y = p.z = h.z = 0);
|
|
442
|
+
S.cameraPosition && (a = S.cameraPosition), S.cameraDirection && (d = S.cameraDirection), W();
|
|
438
443
|
};
|
|
439
444
|
}).toString()})();`;
|
|
440
445
|
}
|
|
441
446
|
}
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
return
|
|
447
|
+
const pt = (I, t) => {
|
|
448
|
+
const s = ot(I), e = ot(t);
|
|
449
|
+
return s | e << 16;
|
|
445
450
|
};
|
|
446
|
-
function
|
|
447
|
-
const
|
|
448
|
-
let r =
|
|
449
|
-
const
|
|
450
|
-
return
|
|
451
|
+
function ot(I) {
|
|
452
|
+
const t = new Float32Array([I]), e = new Int32Array(t.buffer)[0];
|
|
453
|
+
let r = e >> 16 & 32768, o = e >> 12 & 2047;
|
|
454
|
+
const i = e >> 23 & 255;
|
|
455
|
+
return i < 103 ? r : i > 142 ? (r |= 31744, r |= (i === 255 ? 0 : 1) && e & 8388607, r) : i < 113 ? (o |= 2048, r |= (o >> 114 - i) + (o >> 113 - i & 1), r) : (r |= i - 112 << 10 | o >> 1, r += o & 1, r);
|
|
451
456
|
}
|
|
452
|
-
const
|
|
453
|
-
class
|
|
457
|
+
const ft = new ArrayBuffer(4), nt = new DataView(ft), mt = (I) => (nt.setUint32(0, I, !0), nt.getFloat32(0, !0));
|
|
458
|
+
class xt {
|
|
454
459
|
/**
|
|
455
460
|
* Create a new TextureManager for a set of splats
|
|
456
461
|
* @param splatData The splat data to manage textures for
|
|
457
462
|
*/
|
|
458
|
-
constructor(
|
|
459
|
-
|
|
463
|
+
constructor(t) {
|
|
464
|
+
c(this, "transformA");
|
|
460
465
|
// position xyz and rotation quaternion y,z components
|
|
461
|
-
|
|
466
|
+
c(this, "transformB");
|
|
462
467
|
// rotation quaternion x and scale xyz
|
|
463
|
-
|
|
468
|
+
c(this, "colorTexture");
|
|
464
469
|
// color an opacity
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const
|
|
469
|
-
this.textureWidth = Math.ceil(Math.sqrt(
|
|
470
|
+
c(this, "orderTexture");
|
|
471
|
+
c(this, "textureWidth");
|
|
472
|
+
c(this, "textureHeight");
|
|
473
|
+
const s = t.numSplats;
|
|
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);
|
|
470
475
|
}
|
|
471
476
|
/**
|
|
472
477
|
* Create the transform A texture (positions and quaternion w component)
|
|
473
478
|
* @param splatData The splat data
|
|
474
479
|
* @returns DataTexture containing position data
|
|
475
480
|
*/
|
|
476
|
-
createTransformATexture(
|
|
477
|
-
const
|
|
481
|
+
createTransformATexture(t) {
|
|
482
|
+
const s = t.numSplats, e = new Float32Array(
|
|
478
483
|
this.textureWidth * this.textureHeight * 4
|
|
479
484
|
);
|
|
480
|
-
for (let
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
const f =
|
|
484
|
-
|
|
485
|
+
for (let o = 0; o < s; o++) {
|
|
486
|
+
const i = o * 4, a = o * 3, d = o * 4;
|
|
487
|
+
e[i] = t.positions[a], e[i + 1] = t.positions[a + 1], e[i + 2] = t.positions[a + 2];
|
|
488
|
+
const f = t.rotations[d + 0], v = t.rotations[d + 1], g = pt(f, v);
|
|
489
|
+
e[i + 3] = mt(g);
|
|
485
490
|
}
|
|
486
|
-
const r = new
|
|
487
|
-
|
|
491
|
+
const r = new n.DataTexture(
|
|
492
|
+
e,
|
|
488
493
|
this.textureWidth,
|
|
489
494
|
this.textureHeight,
|
|
490
|
-
|
|
491
|
-
|
|
495
|
+
n.RGBAFormat,
|
|
496
|
+
n.FloatType
|
|
492
497
|
// Store as Float32, shader will reinterpret bits
|
|
493
498
|
);
|
|
494
|
-
return r.needsUpdate = !0, r.magFilter =
|
|
499
|
+
return r.needsUpdate = !0, r.magFilter = n.NearestFilter, r.minFilter = n.NearestFilter, r;
|
|
495
500
|
}
|
|
496
501
|
/**
|
|
497
502
|
* Create the transform B texture (scale and rotation xyz)
|
|
498
503
|
* @param splatData The splat data
|
|
499
504
|
* @returns DataTexture containing scale and rotation data
|
|
500
505
|
*/
|
|
501
|
-
createTransformBTexture(
|
|
502
|
-
const
|
|
506
|
+
createTransformBTexture(t) {
|
|
507
|
+
const s = t.numSplats, e = new Float32Array(
|
|
503
508
|
this.textureWidth * this.textureHeight * 4
|
|
504
509
|
);
|
|
505
|
-
for (let
|
|
506
|
-
const
|
|
507
|
-
|
|
510
|
+
for (let o = 0; o < s; o++) {
|
|
511
|
+
const i = o * 4, a = o * 3, d = o * 4;
|
|
512
|
+
e[i] = t.scales[a], e[i + 1] = t.scales[a + 1], e[i + 2] = t.scales[a + 2], e[i + 3] = t.rotations[d + 2];
|
|
508
513
|
}
|
|
509
|
-
const r = new
|
|
510
|
-
|
|
514
|
+
const r = new n.DataTexture(
|
|
515
|
+
e,
|
|
511
516
|
this.textureWidth,
|
|
512
517
|
this.textureHeight,
|
|
513
|
-
|
|
514
|
-
|
|
518
|
+
n.RGBAFormat,
|
|
519
|
+
n.FloatType
|
|
515
520
|
);
|
|
516
|
-
return r.needsUpdate = !0, r.magFilter =
|
|
521
|
+
return r.needsUpdate = !0, r.magFilter = n.NearestFilter, r.minFilter = n.NearestFilter, r;
|
|
517
522
|
}
|
|
518
523
|
/**
|
|
519
524
|
* Create the color texture (RGB and opacity)
|
|
520
525
|
* @param splatData The splat data
|
|
521
526
|
* @returns DataTexture containing color data
|
|
522
527
|
*/
|
|
523
|
-
createColorTexture(
|
|
524
|
-
const
|
|
528
|
+
createColorTexture(t) {
|
|
529
|
+
const s = t.numSplats, e = new Float32Array(
|
|
525
530
|
this.textureWidth * this.textureHeight * 4
|
|
526
531
|
);
|
|
527
|
-
for (let
|
|
528
|
-
const
|
|
529
|
-
|
|
532
|
+
for (let o = 0; o < s; o++) {
|
|
533
|
+
const i = o * 4, a = o * 3;
|
|
534
|
+
e[i] = t.colors[a], e[i + 1] = t.colors[a + 1], e[i + 2] = t.colors[a + 2], e[i + 3] = t.opacities[o];
|
|
530
535
|
}
|
|
531
|
-
const r = new
|
|
532
|
-
|
|
536
|
+
const r = new n.DataTexture(
|
|
537
|
+
e,
|
|
533
538
|
this.textureWidth,
|
|
534
539
|
this.textureHeight,
|
|
535
|
-
|
|
536
|
-
|
|
540
|
+
n.RGBAFormat,
|
|
541
|
+
n.FloatType
|
|
537
542
|
);
|
|
538
543
|
return r.needsUpdate = !0, r;
|
|
539
544
|
}
|
|
@@ -542,24 +547,24 @@ class xe {
|
|
|
542
547
|
* @param numSplats Number of splats
|
|
543
548
|
* @returns DataTexture for storing order indices
|
|
544
549
|
*/
|
|
545
|
-
createOrderTexture(
|
|
546
|
-
const
|
|
547
|
-
for (let r = 0; r <
|
|
548
|
-
|
|
549
|
-
const
|
|
550
|
-
|
|
550
|
+
createOrderTexture(t) {
|
|
551
|
+
const s = new Uint32Array(this.textureWidth * this.textureHeight);
|
|
552
|
+
for (let r = 0; r < t; r++)
|
|
553
|
+
s[r] = r;
|
|
554
|
+
const e = new n.DataTexture(
|
|
555
|
+
s,
|
|
551
556
|
this.textureWidth,
|
|
552
557
|
this.textureHeight,
|
|
553
|
-
|
|
554
|
-
|
|
558
|
+
n.RedIntegerFormat,
|
|
559
|
+
n.UnsignedIntType
|
|
555
560
|
);
|
|
556
|
-
return
|
|
561
|
+
return e.needsUpdate = !0, e;
|
|
557
562
|
}
|
|
558
563
|
dispose() {
|
|
559
564
|
this.transformA.dispose(), this.transformB.dispose(), this.colorTexture.dispose(), this.orderTexture.dispose();
|
|
560
565
|
}
|
|
561
566
|
}
|
|
562
|
-
const
|
|
567
|
+
const yt = (
|
|
563
568
|
/* glsl */
|
|
564
569
|
`
|
|
565
570
|
precision highp float;
|
|
@@ -817,7 +822,7 @@ void main(void) {
|
|
|
817
822
|
vUv = clippedCornerOffset;
|
|
818
823
|
}
|
|
819
824
|
`
|
|
820
|
-
),
|
|
825
|
+
), gt = (
|
|
821
826
|
/* glsl */
|
|
822
827
|
`
|
|
823
828
|
precision highp float;
|
|
@@ -851,146 +856,134 @@ void main(void) {
|
|
|
851
856
|
}
|
|
852
857
|
`
|
|
853
858
|
);
|
|
854
|
-
class
|
|
855
|
-
constructor(
|
|
856
|
-
const
|
|
859
|
+
class vt extends n.ShaderMaterial {
|
|
860
|
+
constructor(t = {}) {
|
|
861
|
+
const s = {
|
|
857
862
|
// Textures (values set via methods)
|
|
858
863
|
transformA: { value: null },
|
|
859
864
|
transformB: { value: null },
|
|
860
865
|
splatColor: { value: null },
|
|
861
866
|
splatOrder: { value: null },
|
|
862
867
|
// Other uniforms
|
|
863
|
-
viewport: { value: new
|
|
868
|
+
viewport: { value: new n.Vector2(1, 1) },
|
|
864
869
|
// Will be updated
|
|
865
870
|
numSplats: { value: 0 }
|
|
866
871
|
// Max splats to render (updated by sorter)
|
|
867
872
|
};
|
|
868
873
|
super({
|
|
869
|
-
vertexShader:
|
|
870
|
-
fragmentShader:
|
|
871
|
-
uniforms:
|
|
874
|
+
vertexShader: yt,
|
|
875
|
+
fragmentShader: gt,
|
|
876
|
+
uniforms: s,
|
|
872
877
|
transparent: !0,
|
|
873
|
-
blending:
|
|
878
|
+
blending: n.CustomBlending,
|
|
874
879
|
// Premultiplied alpha blending:
|
|
875
880
|
// color = src_color * src_alpha + dst_color * (1 - src_alpha)
|
|
876
881
|
// alpha = src_alpha * 1 + dst_alpha * (1 - src_alpha)
|
|
877
|
-
blendSrc:
|
|
882
|
+
blendSrc: n.OneFactor,
|
|
878
883
|
// Using ONE because shader outputs premultiplied color (color * alpha)
|
|
879
|
-
blendDst:
|
|
880
|
-
blendSrcAlpha:
|
|
884
|
+
blendDst: n.OneMinusSrcAlphaFactor,
|
|
885
|
+
blendSrcAlpha: n.OneFactor,
|
|
881
886
|
// source alpha comes from shader
|
|
882
|
-
blendDstAlpha:
|
|
883
|
-
blendEquation:
|
|
884
|
-
blendEquationAlpha:
|
|
887
|
+
blendDstAlpha: n.OneMinusSrcAlphaFactor,
|
|
888
|
+
blendEquation: n.AddEquation,
|
|
889
|
+
blendEquationAlpha: n.AddEquation,
|
|
885
890
|
depthTest: !0,
|
|
886
891
|
depthWrite: !1,
|
|
887
892
|
// Disable depth write for transparency
|
|
888
|
-
side:
|
|
893
|
+
side: n.DoubleSide,
|
|
889
894
|
// Render both sides (or CULLFACE_NONE equivalent)
|
|
890
895
|
// Optional settings from constructor
|
|
891
|
-
alphaTest:
|
|
896
|
+
alphaTest: t.alphaTest !== void 0 ? t.alphaTest : 0,
|
|
892
897
|
// Typically 0 for blending
|
|
893
|
-
toneMapped:
|
|
898
|
+
toneMapped: t.toneMapped !== void 0 ? t.toneMapped : !1
|
|
894
899
|
// prettier-ignore
|
|
895
|
-
}),
|
|
900
|
+
}), t.alphaHash && (this.alphaHash = !0, this.depthWrite = !0, this.blending = n.NoBlending);
|
|
896
901
|
}
|
|
897
902
|
/**
|
|
898
903
|
* Update the viewport size
|
|
899
904
|
* @param width Viewport width
|
|
900
905
|
* @param height Viewport height
|
|
901
906
|
*/
|
|
902
|
-
updateViewport(
|
|
903
|
-
this.uniforms.viewport.value.set(
|
|
907
|
+
updateViewport(t, s) {
|
|
908
|
+
this.uniforms.viewport.value.set(t, s);
|
|
904
909
|
}
|
|
905
910
|
/**
|
|
906
911
|
* Set transform texture A (positions)
|
|
907
912
|
* @param texture Texture containing positions
|
|
908
913
|
*/
|
|
909
|
-
setTransformA(
|
|
910
|
-
this.uniforms.transformA.value =
|
|
914
|
+
setTransformA(t) {
|
|
915
|
+
this.uniforms.transformA.value = t;
|
|
911
916
|
}
|
|
912
917
|
/**
|
|
913
918
|
* Set transform texture B (rotation, scale)
|
|
914
919
|
* @param texture Texture containing rotation and scale data
|
|
915
920
|
*/
|
|
916
|
-
setTransformB(
|
|
917
|
-
this.uniforms.transformB.value =
|
|
921
|
+
setTransformB(t) {
|
|
922
|
+
this.uniforms.transformB.value = t;
|
|
918
923
|
}
|
|
919
924
|
/**
|
|
920
925
|
* Set color texture
|
|
921
926
|
* @param texture Texture containing colors
|
|
922
927
|
*/
|
|
923
|
-
setColorTexture(
|
|
924
|
-
this.uniforms.splatColor.value =
|
|
928
|
+
setColorTexture(t) {
|
|
929
|
+
this.uniforms.splatColor.value = t;
|
|
925
930
|
}
|
|
926
931
|
/**
|
|
927
932
|
* Set order texture
|
|
928
933
|
* @param texture Texture containing sort order
|
|
929
934
|
*/
|
|
930
|
-
setOrderTexture(
|
|
931
|
-
this.uniforms.splatOrder.value =
|
|
935
|
+
setOrderTexture(t) {
|
|
936
|
+
this.uniforms.splatOrder.value = t;
|
|
932
937
|
}
|
|
933
938
|
/**
|
|
934
939
|
* Set number of splats to render
|
|
935
940
|
* @param count Number of splats
|
|
936
941
|
*/
|
|
937
|
-
setNumSplats(
|
|
938
|
-
this.uniforms.numSplats.value =
|
|
942
|
+
setNumSplats(t) {
|
|
943
|
+
this.uniforms.numSplats.value = t;
|
|
939
944
|
}
|
|
940
945
|
}
|
|
941
|
-
const
|
|
946
|
+
const j = class j extends n.Mesh {
|
|
942
947
|
// Match shader constant
|
|
943
948
|
/**
|
|
944
949
|
* Create a new SplatMesh for rendering Gaussian splats
|
|
945
950
|
* @param splatData The splat data to render
|
|
946
951
|
* @param options Rendering options
|
|
947
952
|
*/
|
|
948
|
-
constructor(
|
|
949
|
-
const r = (
|
|
950
|
-
r
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
);
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
953
|
+
constructor(s, e = {}) {
|
|
954
|
+
const r = new vt(e), o = j.createInstancedGeometry(s.numSplats, j.INSTANCE_SIZE);
|
|
955
|
+
super(o, r);
|
|
956
|
+
c(this, "sorter");
|
|
957
|
+
c(this, "splatData");
|
|
958
|
+
c(this, "options");
|
|
959
|
+
c(this, "textureManager");
|
|
960
|
+
c(this, "material");
|
|
961
|
+
c(this, "geometry");
|
|
962
|
+
c(this, "lastCameraPositionLocal", new n.Vector3());
|
|
963
|
+
c(this, "lastCameraDirectionLocal", new n.Vector3());
|
|
964
|
+
c(this, "invModelMatrix", new n.Matrix4());
|
|
965
|
+
// Cached inverse matrix
|
|
966
|
+
c(this, "_vpW", -1);
|
|
967
|
+
c(this, "_vpH", -1);
|
|
968
|
+
c(this, "_size", new n.Vector2());
|
|
969
|
+
c(this, "_camPosW", new n.Vector3());
|
|
970
|
+
c(this, "_camDirW", new n.Vector3());
|
|
971
|
+
c(this, "_camPosL", new n.Vector3());
|
|
972
|
+
c(this, "_camDirL", new n.Vector3());
|
|
973
|
+
c(this, "onSorterUpdated", (s) => {
|
|
974
|
+
const e = s.count;
|
|
975
|
+
this.geometry.instanceCount = Math.ceil(e / j.INSTANCE_SIZE), this.material.setNumSplats(e);
|
|
976
|
+
});
|
|
977
|
+
this.geometry = o, this.material = r, this.splatData = s, this.frustumCulled = !1, this.options = {
|
|
978
|
+
autoSort: !0,
|
|
979
|
+
...e
|
|
980
|
+
}, this.textureManager = new xt(s), this.sorter = new dt();
|
|
981
|
+
let i = this.createChunks() || void 0;
|
|
982
|
+
i === null && console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."), i = void 0, this.sorter.addEventListener("updated", this.onSorterUpdated), this.sorter.init(
|
|
977
983
|
this.textureManager.orderTexture,
|
|
978
984
|
this.splatData.centers,
|
|
979
|
-
|
|
980
|
-
), this.
|
|
981
|
-
"updated",
|
|
982
|
-
(c) => {
|
|
983
|
-
const f = c.count;
|
|
984
|
-
r && console.debug(
|
|
985
|
-
"[6/8] MESH SplatMesh: sorter updated, rendering",
|
|
986
|
-
f,
|
|
987
|
-
"splats"
|
|
988
|
-
), this.geometry.instanceCount = Math.ceil(f / N.INSTANCE_SIZE), this.material.setNumSplats(f);
|
|
989
|
-
}
|
|
990
|
-
), r && console.debug("[7/8] MESH SplatMesh: setting up material textures"), 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 = t.boundingBox.toBox3(), this.geometry.boundingSphere = new i.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere), r && console.debug(
|
|
991
|
-
"[8/8] MESH SplatMesh: mesh initialization complete, bounding box:",
|
|
992
|
-
t.boundingBox
|
|
993
|
-
);
|
|
985
|
+
i ?? 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 n.Sphere(), this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere);
|
|
994
987
|
}
|
|
995
988
|
/**
|
|
996
989
|
* Creates the instanced geometry for rendering splats.
|
|
@@ -998,16 +991,8 @@ const N = class N extends i.Mesh {
|
|
|
998
991
|
* @param instanceSize Number of splats per instance.
|
|
999
992
|
* @returns InstancedBufferGeometry
|
|
1000
993
|
*/
|
|
1001
|
-
static createInstancedGeometry(
|
|
1002
|
-
const r = (
|
|
1003
|
-
r && console.debug(
|
|
1004
|
-
"MESH createInstancedGeometry: creating geometry for",
|
|
1005
|
-
t,
|
|
1006
|
-
"splats,",
|
|
1007
|
-
n,
|
|
1008
|
-
"instances"
|
|
1009
|
-
);
|
|
1010
|
-
const s = new i.BufferGeometry(), a = new Float32Array([
|
|
994
|
+
static createInstancedGeometry(s, e) {
|
|
995
|
+
const r = Math.ceil(s / e), o = new n.BufferGeometry(), i = new Float32Array([
|
|
1011
996
|
// x, y, splat_index_in_instance
|
|
1012
997
|
-1,
|
|
1013
998
|
-1,
|
|
@@ -1021,79 +1006,56 @@ const N = class N extends i.Mesh {
|
|
|
1021
1006
|
-1,
|
|
1022
1007
|
1,
|
|
1023
1008
|
0
|
|
1024
|
-
]),
|
|
1025
|
-
for (let
|
|
1026
|
-
const
|
|
1027
|
-
for (let
|
|
1028
|
-
|
|
1009
|
+
]), a = new Uint16Array([0, 1, 2, 0, 2, 3]), d = new Float32Array(4 * 3 * e);
|
|
1010
|
+
for (let p = 0; p < e; p++) {
|
|
1011
|
+
const h = p * 4 * 3;
|
|
1012
|
+
for (let l = 0; l < 4; l++)
|
|
1013
|
+
d[h + l * 3 + 0] = i[l * 3 + 0], d[h + l * 3 + 1] = i[l * 3 + 1], d[h + l * 3 + 2] = p;
|
|
1029
1014
|
}
|
|
1030
|
-
const
|
|
1031
|
-
for (let
|
|
1032
|
-
const
|
|
1033
|
-
|
|
1015
|
+
const f = new Uint32Array(6 * e);
|
|
1016
|
+
for (let p = 0; p < e; p++) {
|
|
1017
|
+
const h = p * 6, l = p * 4;
|
|
1018
|
+
f[h + 0] = a[0] + l, f[h + 1] = a[1] + l, f[h + 2] = a[2] + l, f[h + 3] = a[3] + l, f[h + 4] = a[4] + l, f[h + 5] = a[5] + l;
|
|
1034
1019
|
}
|
|
1035
|
-
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
const
|
|
1039
|
-
for (let
|
|
1040
|
-
|
|
1041
|
-
return
|
|
1042
|
-
"MESH createInstancedGeometry: geometry created with",
|
|
1043
|
-
x.attributes.position.count,
|
|
1044
|
-
"vertices"
|
|
1045
|
-
), x;
|
|
1020
|
+
o.setAttribute("position", new n.BufferAttribute(d, 3)), o.setIndex(new n.BufferAttribute(f, 1));
|
|
1021
|
+
const v = new n.InstancedBufferGeometry();
|
|
1022
|
+
v.index = o.index, v.setAttribute("position", o.getAttribute("position"));
|
|
1023
|
+
const g = new Uint32Array(r);
|
|
1024
|
+
for (let p = 0; p < r; p++)
|
|
1025
|
+
g[p] = p * e;
|
|
1026
|
+
return v.setAttribute("splatInstanceIndex", new n.InstancedBufferAttribute(g, 1, !1)), v.instanceCount = 0, v;
|
|
1046
1027
|
}
|
|
1047
1028
|
/**
|
|
1048
1029
|
* Create chunks data (bounding box min/max) for the sorter.
|
|
1049
1030
|
* @returns Float32Array containing chunk data [minX, minY, minZ, maxX, maxY, maxZ] or null.
|
|
1050
1031
|
*/
|
|
1051
1032
|
createChunks() {
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
o.min.z,
|
|
1061
|
-
o.max.x,
|
|
1062
|
-
o.max.y,
|
|
1063
|
-
o.max.z
|
|
1033
|
+
const s = this.splatData.boundingBox;
|
|
1034
|
+
return s.min.x === 1 / 0 || s.max.x === -1 / 0 ? null : new Float32Array([
|
|
1035
|
+
s.min.x,
|
|
1036
|
+
s.min.y,
|
|
1037
|
+
s.min.z,
|
|
1038
|
+
s.max.x,
|
|
1039
|
+
s.max.y,
|
|
1040
|
+
s.max.z
|
|
1064
1041
|
]);
|
|
1065
|
-
return t && console.debug(
|
|
1066
|
-
"MESH createChunks: created chunks with bounding box",
|
|
1067
|
-
o
|
|
1068
|
-
), r;
|
|
1069
1042
|
}
|
|
1070
1043
|
/**
|
|
1071
1044
|
* Update the viewport size
|
|
1072
1045
|
* @param width Viewport width
|
|
1073
1046
|
* @param height Viewport height
|
|
1074
1047
|
*/
|
|
1075
|
-
updateViewport(
|
|
1076
|
-
|
|
1077
|
-
"MESH updateViewport: updating viewport to",
|
|
1078
|
-
t,
|
|
1079
|
-
"x",
|
|
1080
|
-
o
|
|
1081
|
-
), this.material.updateViewport(t, o);
|
|
1048
|
+
updateViewport(s, e) {
|
|
1049
|
+
s === this._vpW && e === this._vpH || (this._vpW = s, this._vpH = e, this.material.updateViewport(s, e));
|
|
1082
1050
|
}
|
|
1083
1051
|
/**
|
|
1084
1052
|
* Sorts splats based on camera position and direction.
|
|
1085
1053
|
* @param camera The camera to sort against.
|
|
1086
1054
|
*/
|
|
1087
|
-
sort(
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
this.options.autoSort && (c || f) && (o && console.debug(
|
|
1092
|
-
"MESH sort: camera changed, triggering sort. Position changed:",
|
|
1093
|
-
c,
|
|
1094
|
-
"Direction changed:",
|
|
1095
|
-
f
|
|
1096
|
-
), this.lastCameraPositionLocal.copy(s), this.lastCameraDirectionLocal.copy(a), this.sorter.setCamera(s, a));
|
|
1055
|
+
sort(s) {
|
|
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, r = this.lastCameraDirectionLocal.dot(this._camDirL) < 0.999;
|
|
1058
|
+
this.options.autoSort && (e || r) && (this.lastCameraPositionLocal.copy(this._camPosL), this.lastCameraDirectionLocal.copy(this._camDirL), this.sorter.setCamera(this._camPosL, this._camDirL));
|
|
1097
1059
|
}
|
|
1098
1060
|
/**
|
|
1099
1061
|
* THREE.js hook called before rendering the object.
|
|
@@ -1104,30 +1066,20 @@ const N = class N extends i.Mesh {
|
|
|
1104
1066
|
*/
|
|
1105
1067
|
// prettier-ignore
|
|
1106
1068
|
// @ts-expect-error scene is not used
|
|
1107
|
-
onBeforeRender(
|
|
1108
|
-
this.sort(r);
|
|
1109
|
-
const n = t.getSize(new i.Vector2());
|
|
1110
|
-
let { width: s, height: a } = n;
|
|
1111
|
-
const c = t.xr;
|
|
1112
|
-
if (c.enabled && c.isPresenting) {
|
|
1113
|
-
const f = c.getCamera().cameras[0].view;
|
|
1114
|
-
f && (s = f.width, a = f.height);
|
|
1115
|
-
}
|
|
1116
|
-
this.updateViewport(s, a);
|
|
1069
|
+
onBeforeRender(s, e, r) {
|
|
1070
|
+
this.sort(r), s.getSize(this._size), this.updateViewport(this._size.x, this._size.y);
|
|
1117
1071
|
}
|
|
1118
1072
|
/**
|
|
1119
1073
|
* Dispose of resources
|
|
1120
1074
|
*/
|
|
1121
1075
|
dispose() {
|
|
1122
|
-
|
|
1123
|
-
t && console.debug("MESH dispose: cleaning up mesh resources"), this.sorter.dispose(), this.geometry.dispose(), this.material.dispose(), this.textureManager.dispose(), t && console.debug("MESH dispose: mesh resources cleaned up");
|
|
1076
|
+
this.sorter.removeEventListener("updated", this.onSorterUpdated), this.sorter.dispose(), this.geometry.dispose(), this.material.dispose(), this.textureManager.dispose();
|
|
1124
1077
|
}
|
|
1125
1078
|
};
|
|
1126
|
-
// Cached inverse matrix
|
|
1127
1079
|
/** Number of splats combined into a single instanced draw call. */
|
|
1128
|
-
|
|
1129
|
-
let
|
|
1130
|
-
class
|
|
1080
|
+
c(j, "INSTANCE_SIZE", 128);
|
|
1081
|
+
let it = j;
|
|
1082
|
+
class bt extends n.Loader {
|
|
1131
1083
|
/**
|
|
1132
1084
|
* Load a PLY file with Gaussian Splat data
|
|
1133
1085
|
* @param url URL of the PLY file
|
|
@@ -1135,22 +1087,21 @@ class be extends i.Loader {
|
|
|
1135
1087
|
* @param onProgress Optional progress callback
|
|
1136
1088
|
* @param onError Optional error callback
|
|
1137
1089
|
*/
|
|
1138
|
-
load(
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
(a) => {
|
|
1090
|
+
load(t, s, e, r) {
|
|
1091
|
+
const o = new n.FileLoader(this.manager);
|
|
1092
|
+
o.setResponseType("arraybuffer"), o.setRequestHeader(this.requestHeader), o.setPath(this.path), o.setWithCredentials(this.withCredentials), o.load(
|
|
1093
|
+
t,
|
|
1094
|
+
(i) => {
|
|
1144
1095
|
try {
|
|
1145
|
-
if (
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1096
|
+
if (s) {
|
|
1097
|
+
const a = this.parse(i);
|
|
1098
|
+
s(a);
|
|
1148
1099
|
}
|
|
1149
|
-
} catch (
|
|
1150
|
-
r ? r(
|
|
1100
|
+
} catch (a) {
|
|
1101
|
+
r ? r(a) : console.error(a), this.manager.itemError(t);
|
|
1151
1102
|
}
|
|
1152
1103
|
},
|
|
1153
|
-
|
|
1104
|
+
e,
|
|
1154
1105
|
r
|
|
1155
1106
|
);
|
|
1156
1107
|
}
|
|
@@ -1160,22 +1111,22 @@ class be extends i.Loader {
|
|
|
1160
1111
|
* @param onProgress Optional progress callback
|
|
1161
1112
|
* @returns A Promise that resolves with the parsed SplatData
|
|
1162
1113
|
*/
|
|
1163
|
-
loadAsync(
|
|
1164
|
-
return new Promise((
|
|
1165
|
-
const
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
(
|
|
1114
|
+
loadAsync(t, s) {
|
|
1115
|
+
return new Promise((e, r) => {
|
|
1116
|
+
const o = new n.FileLoader(this.manager);
|
|
1117
|
+
o.setResponseType("arraybuffer"), o.setRequestHeader(this.requestHeader), o.setPath(this.path), o.setWithCredentials(this.withCredentials), o.load(
|
|
1118
|
+
t,
|
|
1119
|
+
(i) => {
|
|
1169
1120
|
try {
|
|
1170
|
-
const a = this.parse(
|
|
1171
|
-
|
|
1121
|
+
const a = this.parse(i);
|
|
1122
|
+
e(a);
|
|
1172
1123
|
} catch (a) {
|
|
1173
|
-
r(a), this.manager.itemError(
|
|
1124
|
+
r(a), this.manager.itemError(t);
|
|
1174
1125
|
}
|
|
1175
1126
|
},
|
|
1176
|
-
|
|
1177
|
-
(
|
|
1178
|
-
r(
|
|
1127
|
+
s,
|
|
1128
|
+
(i) => {
|
|
1129
|
+
r(i), this.manager.itemError(t);
|
|
1179
1130
|
}
|
|
1180
1131
|
);
|
|
1181
1132
|
});
|
|
@@ -1185,264 +1136,172 @@ class be extends i.Loader {
|
|
|
1185
1136
|
* @param buffer ArrayBuffer containing PLY data
|
|
1186
1137
|
* @returns Parsed SplatData
|
|
1187
1138
|
*/
|
|
1188
|
-
parse(
|
|
1189
|
-
const
|
|
1190
|
-
t && console.debug(
|
|
1191
|
-
"[2/12] LOADER PlyLoader: starting parse, buffer size:",
|
|
1192
|
-
e.byteLength
|
|
1193
|
-
);
|
|
1194
|
-
const o = new TextDecoder(), r = new Uint8Array(e), n = [112, 108, 121, 10], s = `
|
|
1139
|
+
parse(t) {
|
|
1140
|
+
const s = new TextDecoder(), e = new Uint8Array(t), r = [112, 108, 121, 10], o = `
|
|
1195
1141
|
end_header
|
|
1196
1142
|
`;
|
|
1197
|
-
for (let
|
|
1198
|
-
if (
|
|
1143
|
+
for (let x = 0; x < r.length; x++)
|
|
1144
|
+
if (e[x] !== r[x])
|
|
1199
1145
|
throw new Error("Invalid PLY file: Missing magic bytes");
|
|
1200
|
-
|
|
1201
|
-
let
|
|
1202
|
-
|
|
1203
|
-
let
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
h = !1;
|
|
1146
|
+
let i = 0;
|
|
1147
|
+
for (let x = 0; x < e.length - o.length; x++) {
|
|
1148
|
+
let u = !0;
|
|
1149
|
+
for (let z = 0; z < o.length; z++)
|
|
1150
|
+
if (e[x + z] !== o.charCodeAt(z)) {
|
|
1151
|
+
u = !1;
|
|
1207
1152
|
break;
|
|
1208
1153
|
}
|
|
1209
|
-
if (
|
|
1210
|
-
|
|
1154
|
+
if (u) {
|
|
1155
|
+
i = x + o.length;
|
|
1211
1156
|
break;
|
|
1212
1157
|
}
|
|
1213
1158
|
}
|
|
1214
|
-
if (
|
|
1159
|
+
if (i === 0)
|
|
1215
1160
|
throw new Error("Invalid PLY file: Could not find end of header");
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
)
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
let x = null;
|
|
1225
|
-
for (let l = 1; l < f.length; l++) {
|
|
1226
|
-
const h = f[l].trim();
|
|
1227
|
-
if (h === "" || h === "end_header") continue;
|
|
1228
|
-
const w = h.split(" ");
|
|
1229
|
-
switch (w[0]) {
|
|
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 z = u.split(" ");
|
|
1168
|
+
switch (z[0]) {
|
|
1230
1169
|
case "format":
|
|
1231
|
-
|
|
1232
|
-
"[6/12] LOADER PlyLoader: format detected:",
|
|
1233
|
-
x
|
|
1234
|
-
);
|
|
1170
|
+
v = z[1];
|
|
1235
1171
|
break;
|
|
1236
1172
|
case "element":
|
|
1237
|
-
|
|
1238
|
-
name:
|
|
1239
|
-
count: parseInt(
|
|
1173
|
+
f.push({
|
|
1174
|
+
name: z[1],
|
|
1175
|
+
count: parseInt(z[2], 10),
|
|
1240
1176
|
properties: []
|
|
1241
|
-
})
|
|
1242
|
-
"[6/12] LOADER PlyLoader: element found:",
|
|
1243
|
-
w[1],
|
|
1244
|
-
"count:",
|
|
1245
|
-
w[2]
|
|
1246
|
-
);
|
|
1177
|
+
});
|
|
1247
1178
|
break;
|
|
1248
1179
|
case "property":
|
|
1249
|
-
if (
|
|
1180
|
+
if (f.length === 0)
|
|
1250
1181
|
throw new Error(
|
|
1251
1182
|
"Invalid PLY file: Property without element"
|
|
1252
1183
|
);
|
|
1253
|
-
|
|
1254
|
-
type:
|
|
1255
|
-
name:
|
|
1184
|
+
f[f.length - 1].properties.push({
|
|
1185
|
+
type: z[1],
|
|
1186
|
+
name: z[2],
|
|
1256
1187
|
storage: null
|
|
1257
|
-
})
|
|
1258
|
-
"[6/12] LOADER PlyLoader: property found:",
|
|
1259
|
-
w[2],
|
|
1260
|
-
"type:",
|
|
1261
|
-
w[1]
|
|
1262
|
-
);
|
|
1188
|
+
});
|
|
1263
1189
|
break;
|
|
1264
1190
|
}
|
|
1265
1191
|
}
|
|
1266
|
-
if (
|
|
1267
|
-
throw new Error(`Unsupported PLY format: ${
|
|
1268
|
-
const
|
|
1269
|
-
if (!
|
|
1192
|
+
if (v !== "binary_little_endian")
|
|
1193
|
+
throw new Error(`Unsupported PLY format: ${v}`);
|
|
1194
|
+
const g = f.find((x) => x.name === "vertex");
|
|
1195
|
+
if (!g)
|
|
1270
1196
|
throw new Error("Invalid PLY file: No vertex element found");
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
"
|
|
1278
|
-
|
|
1279
|
-
"
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
let u = a;
|
|
1283
|
-
const M = (l) => v.properties.findIndex((h) => h.name === l), O = M("x"), H = M("y"), R = M("z"), P = [
|
|
1284
|
-
M("rot_0"),
|
|
1285
|
-
M("rot_1"),
|
|
1286
|
-
M("rot_2"),
|
|
1287
|
-
M("rot_3")
|
|
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), _ = 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")
|
|
1288
1208
|
], W = [
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
],
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
M("f_dc_2")
|
|
1296
|
-
], A = M("opacity");
|
|
1297
|
-
if (t && console.debug("[9/12] LOADER PlyLoader: property indices:", {
|
|
1298
|
-
position: [O, H, R],
|
|
1299
|
-
rotation: P,
|
|
1300
|
-
scale: W,
|
|
1301
|
-
color: B,
|
|
1302
|
-
opacity: A
|
|
1303
|
-
}), [
|
|
1209
|
+
b("f_dc_0"),
|
|
1210
|
+
b("f_dc_1"),
|
|
1211
|
+
b("f_dc_2")
|
|
1212
|
+
], k = b("opacity");
|
|
1213
|
+
if ([
|
|
1214
|
+
_,
|
|
1304
1215
|
O,
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
...
|
|
1216
|
+
q,
|
|
1217
|
+
...E,
|
|
1218
|
+
...R,
|
|
1308
1219
|
...W,
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
].some((l) => l === -1))
|
|
1220
|
+
k
|
|
1221
|
+
].some((x) => x === -1))
|
|
1312
1222
|
throw new Error("Invalid PLY file: Missing required properties");
|
|
1313
|
-
const
|
|
1314
|
-
if (
|
|
1315
|
-
const
|
|
1316
|
-
return
|
|
1317
|
-
};
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
t && l % 1e4 === 0 && console.debug(
|
|
1325
|
-
`[10/12] LOADER PlyLoader: processing splat ${l}/${v.count} (${(l / v.count * 100).toFixed(1)}%)`
|
|
1326
|
-
);
|
|
1327
|
-
const h = [];
|
|
1328
|
-
for (let q = 0; q < v.properties.length; q++) {
|
|
1329
|
-
const L = v.properties[q].type;
|
|
1330
|
-
let U;
|
|
1331
|
-
switch (L) {
|
|
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(), C = 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 T = 0; T < g.properties.length; T++) {
|
|
1231
|
+
const K = g.properties[T].type;
|
|
1232
|
+
let A;
|
|
1233
|
+
switch (K) {
|
|
1332
1234
|
case "char":
|
|
1333
|
-
|
|
1235
|
+
A = h.getInt8(l), l += 1;
|
|
1334
1236
|
break;
|
|
1335
1237
|
case "uchar":
|
|
1336
|
-
|
|
1238
|
+
A = h.getUint8(l), l += 1;
|
|
1337
1239
|
break;
|
|
1338
1240
|
case "short":
|
|
1339
|
-
|
|
1241
|
+
A = h.getInt16(l, !0), l += 2;
|
|
1340
1242
|
break;
|
|
1341
1243
|
case "ushort":
|
|
1342
|
-
|
|
1244
|
+
A = h.getUint16(l, !0), l += 2;
|
|
1343
1245
|
break;
|
|
1344
1246
|
case "int":
|
|
1345
|
-
|
|
1247
|
+
A = h.getInt32(l, !0), l += 4;
|
|
1346
1248
|
break;
|
|
1347
1249
|
case "uint":
|
|
1348
|
-
|
|
1250
|
+
A = h.getUint32(l, !0), l += 4;
|
|
1349
1251
|
break;
|
|
1350
1252
|
case "float":
|
|
1351
|
-
|
|
1253
|
+
A = h.getFloat32(l, !0), l += 4;
|
|
1352
1254
|
break;
|
|
1353
1255
|
case "double":
|
|
1354
|
-
|
|
1256
|
+
A = h.getFloat64(l, !0), l += 8;
|
|
1355
1257
|
break;
|
|
1356
1258
|
default:
|
|
1357
|
-
throw new Error(`Unsupported property type: ${
|
|
1259
|
+
throw new Error(`Unsupported property type: ${K}`);
|
|
1358
1260
|
}
|
|
1359
|
-
|
|
1261
|
+
u.push(A);
|
|
1360
1262
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
),
|
|
1366
|
-
|
|
1263
|
+
m.set(
|
|
1264
|
+
u[_],
|
|
1265
|
+
u[O],
|
|
1266
|
+
u[q]
|
|
1267
|
+
), C.set(
|
|
1268
|
+
u[E[1]],
|
|
1367
1269
|
// PLY stores rot 1,2,3,0 (x,y,z,w)
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
).normalize(),
|
|
1372
|
-
|
|
1373
|
-
{
|
|
1374
|
-
original: [
|
|
1375
|
-
h[P[0]],
|
|
1376
|
-
h[P[1]],
|
|
1377
|
-
h[P[2]],
|
|
1378
|
-
h[P[3]]
|
|
1379
|
-
],
|
|
1380
|
-
processed: [
|
|
1381
|
-
I.x,
|
|
1382
|
-
I.y,
|
|
1383
|
-
I.z,
|
|
1384
|
-
I.w
|
|
1385
|
-
]
|
|
1386
|
-
}
|
|
1387
|
-
), V.set(
|
|
1388
|
-
h[W[0]],
|
|
1270
|
+
u[E[2]],
|
|
1271
|
+
u[E[3]],
|
|
1272
|
+
u[E[0]]
|
|
1273
|
+
).normalize(), C.w < 0 && (C.x = -C.x, C.y = -C.y, C.z = -C.z, C.w = -C.w), V.set(
|
|
1274
|
+
u[R[0]],
|
|
1389
1275
|
// Read directly assuming it's log scale
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
),
|
|
1393
|
-
0.5 +
|
|
1394
|
-
0.5 +
|
|
1395
|
-
0.5 +
|
|
1396
|
-
),
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
I.y,
|
|
1403
|
-
I.z,
|
|
1404
|
-
I.w
|
|
1405
|
-
],
|
|
1406
|
-
scale: [V.x, V.y, V.z],
|
|
1407
|
-
color: [E.r, E.g, E.b],
|
|
1408
|
-
opacity: w
|
|
1409
|
-
}), d.setSplat(
|
|
1410
|
-
l,
|
|
1411
|
-
_,
|
|
1412
|
-
I,
|
|
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 z = M(u[k]);
|
|
1284
|
+
p.setSplat(
|
|
1285
|
+
x,
|
|
1286
|
+
m,
|
|
1287
|
+
C,
|
|
1413
1288
|
V,
|
|
1414
1289
|
// Pass log scale directly
|
|
1415
|
-
|
|
1416
|
-
|
|
1290
|
+
P,
|
|
1291
|
+
z
|
|
1417
1292
|
);
|
|
1418
1293
|
}
|
|
1419
|
-
return
|
|
1420
|
-
"[11/12] LOADER PlyLoader: finished parsing all splats, calculating bounding box"
|
|
1421
|
-
), d.calculateBoundingBox(), t && console.debug(
|
|
1422
|
-
"[12/12] LOADER PlyLoader: parsing complete, bounding box:",
|
|
1423
|
-
{
|
|
1424
|
-
min: [
|
|
1425
|
-
d.boundingBox.min.x,
|
|
1426
|
-
d.boundingBox.min.y,
|
|
1427
|
-
d.boundingBox.min.z
|
|
1428
|
-
],
|
|
1429
|
-
max: [
|
|
1430
|
-
d.boundingBox.max.x,
|
|
1431
|
-
d.boundingBox.max.y,
|
|
1432
|
-
d.boundingBox.max.z
|
|
1433
|
-
]
|
|
1434
|
-
}
|
|
1435
|
-
), d;
|
|
1294
|
+
return p.calculateBoundingBox(), p;
|
|
1436
1295
|
}
|
|
1437
1296
|
}
|
|
1438
|
-
const
|
|
1297
|
+
const Mt = "0.3.0";
|
|
1439
1298
|
export {
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1299
|
+
et as BoundingBox,
|
|
1300
|
+
bt as PlyLoader,
|
|
1301
|
+
ut as SplatData,
|
|
1302
|
+
vt as SplatMaterial,
|
|
1303
|
+
it as SplatMesh,
|
|
1304
|
+
dt as SplatSorter,
|
|
1305
|
+
xt as TextureManager,
|
|
1306
|
+
Mt as VERSION
|
|
1448
1307
|
};
|