@kalyptos/narcissus 0.1.3 → 0.2.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 +1 -0
- package/dist/cli/main.js +1 -1
- package/dist/controls/controls.d.ts +10 -2
- package/dist/controls/pose.d.ts +8 -1
- package/dist/controls-Dlxyn7yr.js +3516 -0
- package/dist/element/index.js +1 -1
- package/dist/engine/engine.d.ts +34 -3
- package/dist/engine/gpu/masks.d.ts +26 -0
- package/dist/engine/gpu/overlay.d.ts +21 -0
- package/dist/engine/gpu/pick.d.ts +26 -0
- package/dist/engine/gpu/pool.d.ts +10 -2
- package/dist/engine/gpu/project.d.ts +5 -0
- package/dist/engine/gpu/raster.d.ts +0 -5
- package/dist/engine/gpu/renderer.d.ts +8 -8
- package/dist/engine/index.d.ts +5 -2
- package/dist/engine/layer.d.ts +26 -0
- package/dist/engine/mask.d.ts +18 -0
- package/dist/engine/math/frustum.d.ts +5 -2
- package/dist/engine/math/prism.d.ts +13 -0
- package/dist/engine/overlay.d.ts +28 -0
- package/dist/engine/stream/feed.d.ts +2 -0
- package/dist/engine/types.d.ts +8 -0
- package/dist/format/encode.d.ts +8 -0
- package/dist/format/idx.d.ts +2 -0
- package/dist/format/index.d.ts +2 -1
- package/dist/format/index.js +1 -1
- package/dist/{format-C3Vn0c2b.js → format-CbtEy9NS.js} +352 -139
- package/dist/index.d.ts +1 -0
- package/dist/index.js +30 -29
- package/dist/synthetic-DO8oIw_x.js +212 -0
- package/dist/tools/index.js +1 -1
- package/dist/tools-DnfuHeoO.js +227 -0
- package/package.json +1 -1
- package/dist/controls-IBLB-RWS.js +0 -2773
- package/dist/synthetic-BeGCzYIv.js +0 -383
- package/dist/tools-NykPVccD.js +0 -242
|
@@ -0,0 +1,3516 @@
|
|
|
1
|
+
import { B as e, b as t, f as n, h as r, m as i, p as a, s as o, y as s, z as c } from "./format-CbtEy9NS.js";
|
|
2
|
+
import { t as l } from "./ports-DZRKjdYD.js";
|
|
3
|
+
import { t as u } from "./http-DL7R39Nc.js";
|
|
4
|
+
//#region src/engine/gpu/layout.ts
|
|
5
|
+
var d = (e) => Math.max(1, Math.ceil(e / 256)) * 256, f = {
|
|
6
|
+
visible: 0,
|
|
7
|
+
projected: 4,
|
|
8
|
+
drawArgs: 8,
|
|
9
|
+
list: 16
|
|
10
|
+
}, p = 65535, m = (e) => [Math.min(e, p), Math.ceil(e / p)], h = .075;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/engine/gpu/device.ts
|
|
13
|
+
async function g() {
|
|
14
|
+
if (!navigator.gpu) return null;
|
|
15
|
+
let e = await navigator.gpu.requestAdapter({ powerPreference: "high-performance" });
|
|
16
|
+
if (!e) return null;
|
|
17
|
+
let t = e.features.has("timestamp-query");
|
|
18
|
+
return {
|
|
19
|
+
device: await e.requestDevice({
|
|
20
|
+
requiredFeatures: t ? ["timestamp-query"] : [],
|
|
21
|
+
requiredLimits: {
|
|
22
|
+
maxStorageBufferBindingSize: e.limits.maxStorageBufferBindingSize,
|
|
23
|
+
maxBufferSize: e.limits.maxBufferSize
|
|
24
|
+
}
|
|
25
|
+
}),
|
|
26
|
+
timestamps: t,
|
|
27
|
+
format: navigator.gpu.getPreferredCanvasFormat()
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _(e, t, n) {
|
|
31
|
+
let r = !1, i = e.length / 2;
|
|
32
|
+
for (let a = 0, o = i - 1; a < i; o = a++) {
|
|
33
|
+
let i = e[2 * a], s = e[2 * a + 1], c = e[2 * o], l = e[2 * o + 1];
|
|
34
|
+
s > n != l > n && t < (c - i) * (n - s) / (l - s) + i && (r = !r);
|
|
35
|
+
}
|
|
36
|
+
return r;
|
|
37
|
+
}
|
|
38
|
+
function v(e, t, n, r, i, a, o, s) {
|
|
39
|
+
let c = 0, l = 1, u = n - e, d = r - t;
|
|
40
|
+
for (let [n, r] of [
|
|
41
|
+
[-u, e - i],
|
|
42
|
+
[u, o - e],
|
|
43
|
+
[-d, t - a],
|
|
44
|
+
[d, s - t]
|
|
45
|
+
]) {
|
|
46
|
+
if (n === 0) {
|
|
47
|
+
if (r < 0) return !1;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
let e = r / n;
|
|
51
|
+
if (n < 0 ? c = Math.max(c, e) : l = Math.min(l, e), c > l) return !1;
|
|
52
|
+
}
|
|
53
|
+
return !0;
|
|
54
|
+
}
|
|
55
|
+
function y(e, t, n) {
|
|
56
|
+
let { polygon: r, z: i } = e;
|
|
57
|
+
if (n[2] < i[0] || t[2] > i[1]) return 0;
|
|
58
|
+
let a = r.length / 2;
|
|
59
|
+
for (let e = 0, i = a - 1; e < a; i = e++) {
|
|
60
|
+
let [a, o, s, c] = [
|
|
61
|
+
r[2 * e],
|
|
62
|
+
r[2 * e + 1],
|
|
63
|
+
r[2 * i],
|
|
64
|
+
r[2 * i + 1]
|
|
65
|
+
];
|
|
66
|
+
if (v(a, o, s, c, t[0], t[1], n[0], n[1])) return 2;
|
|
67
|
+
}
|
|
68
|
+
return _(r, t[0], t[1]) ? t[2] >= i[0] && n[2] <= i[1] ? 1 : 2 : 0;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/engine/gpu/buffers.ts
|
|
72
|
+
function b(e, t, n) {
|
|
73
|
+
let r = (t, n, r) => e.createBuffer({
|
|
74
|
+
label: t,
|
|
75
|
+
size: n,
|
|
76
|
+
usage: r
|
|
77
|
+
}), i = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, a = [
|
|
78
|
+
r("frame uniforms", 336, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST),
|
|
79
|
+
r("work", (f.list + n) * 4, i | GPUBufferUsage.INDIRECT),
|
|
80
|
+
r("projected", t * 6 * 4, i),
|
|
81
|
+
r("sort", t * 16, i),
|
|
82
|
+
r("plugins", 256, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST),
|
|
83
|
+
r("visible clusters", 4, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST)
|
|
84
|
+
], [o, s, c, l, u, d] = a;
|
|
85
|
+
return {
|
|
86
|
+
capacity: t,
|
|
87
|
+
uniforms: o,
|
|
88
|
+
work: s,
|
|
89
|
+
visible: d,
|
|
90
|
+
projected: c,
|
|
91
|
+
sort: l,
|
|
92
|
+
plugins: u,
|
|
93
|
+
bytes: a.reduce((e, t) => e + t.size, 0),
|
|
94
|
+
destroy: () => a.forEach((e) => e.destroy())
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function x(e, t, n, r) {
|
|
98
|
+
return e.createBindGroupLayout({
|
|
99
|
+
label: t,
|
|
100
|
+
entries: r.map((e, t) => ({
|
|
101
|
+
binding: t,
|
|
102
|
+
visibility: n,
|
|
103
|
+
buffer: { type: e }
|
|
104
|
+
}))
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function S(e, t, n, r) {
|
|
108
|
+
return e.createBindGroup({
|
|
109
|
+
label: t,
|
|
110
|
+
layout: n,
|
|
111
|
+
entries: r.map((e, t) => ({
|
|
112
|
+
binding: t,
|
|
113
|
+
resource: { buffer: e }
|
|
114
|
+
}))
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/engine/gpu/masks.ts
|
|
119
|
+
var C = 8, w = 3e38, T = class {
|
|
120
|
+
layout;
|
|
121
|
+
#e;
|
|
122
|
+
#t;
|
|
123
|
+
#n = null;
|
|
124
|
+
#r = /* @__PURE__ */ new Map();
|
|
125
|
+
#i = 0;
|
|
126
|
+
#a = [
|
|
127
|
+
0,
|
|
128
|
+
0,
|
|
129
|
+
0
|
|
130
|
+
];
|
|
131
|
+
#o = [];
|
|
132
|
+
constructor(e) {
|
|
133
|
+
this.#e = e, this.layout = x(e, "masks", GPUShaderStage.COMPUTE, ["read-only-storage"]), this.#t = this.#s(64);
|
|
134
|
+
}
|
|
135
|
+
get group() {
|
|
136
|
+
return this.#n ??= S(this.#e, "masks", this.layout, [this.#t]);
|
|
137
|
+
}
|
|
138
|
+
get size() {
|
|
139
|
+
return this.#r.size;
|
|
140
|
+
}
|
|
141
|
+
add(e, t) {
|
|
142
|
+
let { polygon: n } = e, r = [
|
|
143
|
+
Infinity,
|
|
144
|
+
Infinity,
|
|
145
|
+
-Infinity,
|
|
146
|
+
-Infinity
|
|
147
|
+
];
|
|
148
|
+
for (let e = 0; e < n.length; e += 2) r[0] = Math.min(r[0], n[e]), r[1] = Math.min(r[1], n[e + 1]), r[2] = Math.max(r[2], n[e]), r[3] = Math.max(r[3], n[e + 1]);
|
|
149
|
+
return this.#r.set(++this.#i, {
|
|
150
|
+
prism: e,
|
|
151
|
+
targets: t,
|
|
152
|
+
enabled: !0,
|
|
153
|
+
area: r
|
|
154
|
+
}), this.#i;
|
|
155
|
+
}
|
|
156
|
+
enable(e, t) {
|
|
157
|
+
let n = this.#r.get(e);
|
|
158
|
+
n && (n.enabled = t);
|
|
159
|
+
}
|
|
160
|
+
delete(e) {
|
|
161
|
+
this.#r.delete(e);
|
|
162
|
+
}
|
|
163
|
+
area(e) {
|
|
164
|
+
return this.#r.get(e)?.area;
|
|
165
|
+
}
|
|
166
|
+
relate(e, t, n, r) {
|
|
167
|
+
for (let [i, { prism: a, targets: o, enabled: s, area: c }] of this.#r) {
|
|
168
|
+
if (!s || !o.has(e) || n[0] < c[0] || n[1] < c[1] || t[0] > c[2] || t[1] > c[3]) continue;
|
|
169
|
+
let l = y(a, t, n);
|
|
170
|
+
if (l === 1) return !0;
|
|
171
|
+
l === 2 && r.push(i);
|
|
172
|
+
}
|
|
173
|
+
return !1;
|
|
174
|
+
}
|
|
175
|
+
setOrigin(e) {
|
|
176
|
+
this.#a = e;
|
|
177
|
+
}
|
|
178
|
+
get listBase() {
|
|
179
|
+
let e = this.#r.size * C;
|
|
180
|
+
for (let { prism: t } of this.#r.values()) e += t.polygon.length;
|
|
181
|
+
return e;
|
|
182
|
+
}
|
|
183
|
+
write(e = this.#o) {
|
|
184
|
+
this.#o = e;
|
|
185
|
+
let t = new Uint32Array(this.listBase + e.length), n = new Float32Array(t.buffer), [r, i, a] = this.#a, o = /* @__PURE__ */ new Map(), s = this.#r.size * C, c = 0;
|
|
186
|
+
for (let [e, { prism: l, area: u }] of this.#r) {
|
|
187
|
+
let { polygon: d, z: f } = l, p = c * C;
|
|
188
|
+
n.set([
|
|
189
|
+
u[0] - r,
|
|
190
|
+
u[1] - i,
|
|
191
|
+
u[2] - r,
|
|
192
|
+
u[3] - i
|
|
193
|
+
], p), n[p + 4] = Number.isFinite(f[0]) ? f[0] - a : -3e38, n[p + 5] = Number.isFinite(f[1]) ? f[1] - a : w, t[p + 6] = s, t[p + 7] = d.length / 2;
|
|
194
|
+
for (let e = 0; e < d.length; e += 2) n[s++] = d[e] - r, n[s++] = d[e + 1] - i;
|
|
195
|
+
o.set(e, c++);
|
|
196
|
+
}
|
|
197
|
+
for (let n = 0; n < e.length; n++) t[s + n] = o.get(e[n]) ?? 0;
|
|
198
|
+
t.byteLength > this.#t.size && (this.#t.destroy(), this.#t = this.#s(t.byteLength), this.#n = null), t.length && this.#e.queue.writeBuffer(this.#t, 0, t);
|
|
199
|
+
}
|
|
200
|
+
destroy() {
|
|
201
|
+
this.#t.destroy();
|
|
202
|
+
}
|
|
203
|
+
#s(e) {
|
|
204
|
+
return this.#e.createBuffer({
|
|
205
|
+
label: "masks",
|
|
206
|
+
size: Math.max(256, 2 ** Math.ceil(Math.log2(e))),
|
|
207
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}, E = 19, D = 23, O = 7, k = 11, A = [], j = 1024, M = class {
|
|
211
|
+
#e = [];
|
|
212
|
+
mark(e, t) {
|
|
213
|
+
this.#e.push([e, t]);
|
|
214
|
+
}
|
|
215
|
+
clear() {
|
|
216
|
+
this.#e = [];
|
|
217
|
+
}
|
|
218
|
+
flush(e, t, n) {
|
|
219
|
+
let r = this.#e.sort((e, t) => e[0] - t[0]);
|
|
220
|
+
this.#e = [];
|
|
221
|
+
for (let i = 0; i < r.length;) {
|
|
222
|
+
let a = r[i][0], o = r[i++][1];
|
|
223
|
+
for (; i < r.length && r[i][0] <= o + j;) o = Math.max(o, r[i++][1]);
|
|
224
|
+
e.writeBuffer(t, a * 4, n, a, o - a);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}, ee = class {
|
|
228
|
+
geometry;
|
|
229
|
+
colour;
|
|
230
|
+
pages;
|
|
231
|
+
clusters;
|
|
232
|
+
list;
|
|
233
|
+
listed = 0;
|
|
234
|
+
capacity;
|
|
235
|
+
masks;
|
|
236
|
+
#e;
|
|
237
|
+
#t = /* @__PURE__ */ new Map();
|
|
238
|
+
#n = null;
|
|
239
|
+
#r = null;
|
|
240
|
+
#i = /* @__PURE__ */ new Set();
|
|
241
|
+
#a;
|
|
242
|
+
#o;
|
|
243
|
+
#s = 0;
|
|
244
|
+
#c;
|
|
245
|
+
#l = [
|
|
246
|
+
0,
|
|
247
|
+
0,
|
|
248
|
+
0
|
|
249
|
+
];
|
|
250
|
+
#u;
|
|
251
|
+
#d;
|
|
252
|
+
#f = new M();
|
|
253
|
+
#p;
|
|
254
|
+
#m;
|
|
255
|
+
#h = new M();
|
|
256
|
+
#g;
|
|
257
|
+
#_ = [];
|
|
258
|
+
#v;
|
|
259
|
+
#y;
|
|
260
|
+
#b = !1;
|
|
261
|
+
constructor(e, t) {
|
|
262
|
+
this.capacity = t, this.masks = new T(e), this.#e = e;
|
|
263
|
+
let n = this.slots;
|
|
264
|
+
this.#S(), this.#a = new Uint8Array(n), this.#o = n, this.#c = Array.from({ length: n }, (e, t) => n - 1 - t), this.#u = new Uint32Array(n * 36), this.#d = new Float32Array(this.#u.buffer), this.#p = new Uint32Array(n * 12), this.#m = new Float32Array(this.#p.buffer), this.#g = new Uint32Array(n), this.#v = new Uint8Array(n), this.#y = Array(n).fill(A);
|
|
265
|
+
}
|
|
266
|
+
get slots() {
|
|
267
|
+
return this.capacity / 256;
|
|
268
|
+
}
|
|
269
|
+
get bytes() {
|
|
270
|
+
return this.#x().reduce((e, t) => e + t.size, 0);
|
|
271
|
+
}
|
|
272
|
+
has(e) {
|
|
273
|
+
let t = this.#t.get(e);
|
|
274
|
+
return t !== void 0 && t.page === null;
|
|
275
|
+
}
|
|
276
|
+
holds(e) {
|
|
277
|
+
return this.#t.has(e);
|
|
278
|
+
}
|
|
279
|
+
*ids() {
|
|
280
|
+
for (let e = this.#n; e; e = e.next) e.page === null && (yield e.id);
|
|
281
|
+
}
|
|
282
|
+
add(t, n, r, i, a = 0) {
|
|
283
|
+
if (this.#t.has(t)) return !0;
|
|
284
|
+
let o = d(n.count) / 256;
|
|
285
|
+
if (!this.#T(o, i)) return !1;
|
|
286
|
+
let s = e.origin, c = {
|
|
287
|
+
id: t,
|
|
288
|
+
previous: null,
|
|
289
|
+
next: null,
|
|
290
|
+
page: n,
|
|
291
|
+
slots: this.#N(o),
|
|
292
|
+
active: [],
|
|
293
|
+
mask: 0,
|
|
294
|
+
table: this.#c.pop(),
|
|
295
|
+
base: [
|
|
296
|
+
n.params[s] + r[0],
|
|
297
|
+
n.params[s + 1] + r[1],
|
|
298
|
+
n.params[s + 2]
|
|
299
|
+
],
|
|
300
|
+
factors: 0,
|
|
301
|
+
layer: a
|
|
302
|
+
};
|
|
303
|
+
return this.#t.set(t, c), this.#w(c), this.#i.add(t), !0;
|
|
304
|
+
}
|
|
305
|
+
remove(e) {
|
|
306
|
+
let t = this.#t.get(e);
|
|
307
|
+
if (t) {
|
|
308
|
+
this.#C(t), this.#t.delete(e), this.#i.delete(e);
|
|
309
|
+
for (let e of t.slots) this.#a[e] = 0, this.#v[e] = 0, this.#y[e].length && (this.#b = !0), this.#y[e] = A;
|
|
310
|
+
this.#s = Math.min(this.#s, t.slots[0]), this.#o += t.slots.length, this.#c.push(t.table), t.page === null && t.factors !== 0 && this.#O(t, 0);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
clear() {
|
|
314
|
+
for (let e of this.#t.values()) e.layer === 0 && this.remove(e.id);
|
|
315
|
+
}
|
|
316
|
+
get queued() {
|
|
317
|
+
return this.#i.size;
|
|
318
|
+
}
|
|
319
|
+
upload(e) {
|
|
320
|
+
let t = 0;
|
|
321
|
+
for (let n of this.#i) {
|
|
322
|
+
if (t >= e) break;
|
|
323
|
+
t += this.#E(this.#t.get(n)), this.#i.delete(n);
|
|
324
|
+
}
|
|
325
|
+
return t;
|
|
326
|
+
}
|
|
327
|
+
draw(e) {
|
|
328
|
+
let t = 0, n = 0, r = !1;
|
|
329
|
+
for (let { id: i, factors: a } of e) {
|
|
330
|
+
let e = this.#t.get(i);
|
|
331
|
+
if (!e || e.page !== null) continue;
|
|
332
|
+
let o = e.active;
|
|
333
|
+
(e.factors !== a || e.mask < 0) && this.#O(e, a), r ||= o !== e.active, this.#w(e), r ||= this.#_[n] !== e, this.#_[n++] = e, r && this.#g.set(e.active, t), t += e.active.length;
|
|
334
|
+
}
|
|
335
|
+
r ||= this.#_.length !== n, this.#_.length = n, this.listed = t, this.#b && this.#M();
|
|
336
|
+
let i = this.#e.queue;
|
|
337
|
+
this.#f.flush(i, this.pages, this.#u), this.#h.flush(i, this.clusters, this.#p), r && t && i.writeBuffer(this.list, 0, this.#g, 0, t);
|
|
338
|
+
}
|
|
339
|
+
setOrigin(e) {
|
|
340
|
+
this.#l = [
|
|
341
|
+
e[0],
|
|
342
|
+
e[1],
|
|
343
|
+
e[2]
|
|
344
|
+
];
|
|
345
|
+
for (let e of this.#t.values()) e.page === null && this.#D(e);
|
|
346
|
+
this.#e.queue.writeBuffer(this.pages, 0, this.#u), this.#f.clear(), this.masks.setOrigin(this.#l), this.masks.size && this.masks.write();
|
|
347
|
+
}
|
|
348
|
+
addMask(e, t) {
|
|
349
|
+
let n = this.masks.add(e, t);
|
|
350
|
+
return this.#k(this.masks.area(n)), n;
|
|
351
|
+
}
|
|
352
|
+
enableMask(e, t) {
|
|
353
|
+
this.masks.enable(e, t), this.#k(this.masks.area(e));
|
|
354
|
+
}
|
|
355
|
+
deleteMask(e) {
|
|
356
|
+
let t = this.masks.area(e);
|
|
357
|
+
this.masks.delete(e), this.#k(t);
|
|
358
|
+
}
|
|
359
|
+
grow(e) {
|
|
360
|
+
if (e <= this.capacity) return;
|
|
361
|
+
let t = this.slots, n = this.#x();
|
|
362
|
+
this.capacity = e, this.#S();
|
|
363
|
+
let r = this.#e.createCommandEncoder({ label: "pool grow" });
|
|
364
|
+
this.#x().forEach((e, t) => r.copyBufferToBuffer(n[t], 0, e, 0, n[t].size)), this.#e.queue.submit([r.finish()]);
|
|
365
|
+
for (let e of n) e.destroy();
|
|
366
|
+
let i = this.slots, a = new Uint8Array(i);
|
|
367
|
+
a.set(this.#a), this.#a = a, this.#o += i - t;
|
|
368
|
+
for (let e = i - 1; e >= t; e--) this.#c.push(e);
|
|
369
|
+
let o = new Uint32Array(i * 36);
|
|
370
|
+
o.set(this.#u), this.#u = o, this.#d = new Float32Array(o.buffer);
|
|
371
|
+
let s = new Uint32Array(i * 12);
|
|
372
|
+
s.set(this.#p), this.#p = s, this.#m = new Float32Array(s.buffer);
|
|
373
|
+
let c = new Uint32Array(i);
|
|
374
|
+
c.set(this.#g), this.#g = c;
|
|
375
|
+
let l = new Uint8Array(i);
|
|
376
|
+
l.set(this.#v), this.#v = l;
|
|
377
|
+
for (let e = t; e < i; e++) this.#y.push(A);
|
|
378
|
+
}
|
|
379
|
+
destroy() {
|
|
380
|
+
for (let e of this.#x()) e.destroy();
|
|
381
|
+
this.masks.destroy();
|
|
382
|
+
}
|
|
383
|
+
#x() {
|
|
384
|
+
return [
|
|
385
|
+
this.geometry,
|
|
386
|
+
this.colour,
|
|
387
|
+
this.pages,
|
|
388
|
+
this.clusters,
|
|
389
|
+
this.list
|
|
390
|
+
];
|
|
391
|
+
}
|
|
392
|
+
#S() {
|
|
393
|
+
let { capacity: e, slots: t } = this, n = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, r = (e, t) => this.#e.createBuffer({
|
|
394
|
+
label: e,
|
|
395
|
+
size: t,
|
|
396
|
+
usage: n
|
|
397
|
+
});
|
|
398
|
+
this.geometry = r("pool geometry", e * 4 * 4), this.colour = r("pool colour", e * 3 * 4), this.pages = r("pool pages", t * 36 * 4), this.clusters = r("pool clusters", t * 12 * 4), this.list = r("pool list", t * 4);
|
|
399
|
+
}
|
|
400
|
+
#C(e) {
|
|
401
|
+
e.previous ? e.previous.next = e.next : this.#n === e && (this.#n = e.next), e.next ? e.next.previous = e.previous : this.#r === e && (this.#r = e.previous), e.previous = null, e.next = null;
|
|
402
|
+
}
|
|
403
|
+
#w(e) {
|
|
404
|
+
this.#r !== e && (this.#C(e), e.previous = this.#r, this.#r ? this.#r.next = e : this.#n = e, this.#r = e);
|
|
405
|
+
}
|
|
406
|
+
#T(e, t) {
|
|
407
|
+
let n = this.#o;
|
|
408
|
+
if (n >= e) return !0;
|
|
409
|
+
let r = [];
|
|
410
|
+
for (let i = this.#n; i && !(!(i.page !== null || i.layer !== 0 || t(i.id)) && (r.push(i.id), n += i.slots.length, n >= e)); i = i.next);
|
|
411
|
+
if (n < e) return !1;
|
|
412
|
+
for (let e of r) this.remove(e);
|
|
413
|
+
return !0;
|
|
414
|
+
}
|
|
415
|
+
#E(t) {
|
|
416
|
+
let n = t.page, { slots: r } = t, i = this.#e.queue, a = r.length, o = this.#p, s = this.#m;
|
|
417
|
+
for (let e = 0; e < a; e++) {
|
|
418
|
+
let i = r[e] * 12;
|
|
419
|
+
o.fill(0, i, i + 12), o[i] = t.table, o[i + 1] = r[e] * 256, o[i + 2] = e * 256, o[i + 3] = Math.max(0, Math.min(256, n.count - e * 256));
|
|
420
|
+
for (let t = 0; t < 3; t++) s[i + 4 + t] = n.clusters[e * 6 + t], s[i + 8 + t] = n.clusters[e * 6 + 3 + t];
|
|
421
|
+
}
|
|
422
|
+
for (let e = 0; e < a;) {
|
|
423
|
+
let t = 1;
|
|
424
|
+
for (; e + t < a && r[e + t] === r[e] + t;) t++;
|
|
425
|
+
let o = e * 256, s = Math.min((e + t) * 256, n.count) - o, c = r[e] * 256;
|
|
426
|
+
i.writeBuffer(this.geometry, c * 4 * 4, n.geometry, o * 4, s * 4), i.writeBuffer(this.colour, c * 3 * 4, n.colour, o * 3, s * 3), this.#h.mark(r[e] * 12, (r[e] + t) * 12), e += t;
|
|
427
|
+
}
|
|
428
|
+
let c = t.table * 36, l = this.#u, u = this.#d, d = n.params, [f, p, m] = n.quadrants;
|
|
429
|
+
return l.fill(0, c, c + 36), this.#D(t), l[c + 3] = n.count, u.set(d.subarray(e.step, e.step + 3), c + 4), l[c + 7] = f, u.set(d.subarray(e.scaleMin, e.scaleMin + 3), c + 8), l[c + 11] = p, u.set(d.subarray(e.scaleMax, e.scaleMax + 3), c + 12), l[c + 15] = m, u.set(d.subarray(e.dcMin, e.dcMin + 3), c + 16), u.set(d.subarray(e.dcMax, e.dcMax + 3), c + 20), l[c + D] = t.layer, u.set(d.subarray(e.shScale, e.shScale + 9), c + 24), this.#f.mark(c, c + 36), t.page = null, this.masks.size && this.#j(t), n.count * 7 * 4 + a * 12 * 4 + 144;
|
|
430
|
+
}
|
|
431
|
+
#D(e) {
|
|
432
|
+
let t = e.table * 36;
|
|
433
|
+
for (let n = 0; n < 3; n++) this.#d[t + n] = e.base[n] - this.#l[n];
|
|
434
|
+
}
|
|
435
|
+
#O(e, t) {
|
|
436
|
+
let n = 0;
|
|
437
|
+
for (let e = 0; e < 4; e++) t >>> 8 * e & 255 && (n |= 1 << e);
|
|
438
|
+
if (n !== e.mask) {
|
|
439
|
+
e.mask = n;
|
|
440
|
+
let t = this.#v;
|
|
441
|
+
if (n === 15 && this.#u[e.table * 36 + 3] > 0) e.active = e.slots.some((e) => t[e]) ? e.slots.filter((e) => !t[e]) : e.slots;
|
|
442
|
+
else {
|
|
443
|
+
let r = [], i = e.table * 36, a = 0, o = -1;
|
|
444
|
+
for (let s = 0; s < 4; s++) {
|
|
445
|
+
let c = this.#u[i + (s === 3 ? 3 : 7 + 4 * s)];
|
|
446
|
+
if (n & 1 << s && c > a) for (let n = Math.max(o + 1, Math.floor(a / 256)); n < Math.ceil(c / 256); n++) t[e.slots[n]] || r.push(e.slots[n]), o = n;
|
|
447
|
+
a = c;
|
|
448
|
+
}
|
|
449
|
+
e.active = r;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
e.factors = t;
|
|
453
|
+
let r = e.table * 36 + E;
|
|
454
|
+
this.#u[r] = t, this.#f.mark(r, r + 1);
|
|
455
|
+
}
|
|
456
|
+
#k(e) {
|
|
457
|
+
let t = [
|
|
458
|
+
0,
|
|
459
|
+
0,
|
|
460
|
+
0
|
|
461
|
+
], n = [
|
|
462
|
+
0,
|
|
463
|
+
0,
|
|
464
|
+
0
|
|
465
|
+
];
|
|
466
|
+
for (let r of this.#t.values()) r.page === null && r.slots.some((i) => (this.#A(r, i, t, n), n[0] >= e[0] && n[1] >= e[1] && t[0] <= e[2] && t[1] <= e[3])) && this.#j(r);
|
|
467
|
+
this.#b = !0;
|
|
468
|
+
}
|
|
469
|
+
#A(e, t, n, r) {
|
|
470
|
+
let i = this.#m, a = t * 12;
|
|
471
|
+
for (let t = 0; t < 3; t++) n[t] = e.base[t] + i[a + 4 + t], r[t] = e.base[t] + i[a + 8 + t];
|
|
472
|
+
}
|
|
473
|
+
#j(e) {
|
|
474
|
+
let t = [
|
|
475
|
+
0,
|
|
476
|
+
0,
|
|
477
|
+
0
|
|
478
|
+
], n = [
|
|
479
|
+
0,
|
|
480
|
+
0,
|
|
481
|
+
0
|
|
482
|
+
];
|
|
483
|
+
for (let r of e.slots) {
|
|
484
|
+
this.#A(e, r, t, n);
|
|
485
|
+
let i = [], a = +!!this.masks.relate(e.layer, t, n, i), o = this.#y[r];
|
|
486
|
+
a !== this.#v[r] && (e.mask = -1), this.#v[r] = a, (o.length || i.length) && (this.#b = !0), this.#y[r] = i.length ? i : A;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
#M() {
|
|
490
|
+
this.#b = !1;
|
|
491
|
+
let e = this.#p, t = [], n = this.masks.listBase;
|
|
492
|
+
for (let r = 0; r < this.#y.length; r++) {
|
|
493
|
+
let i = this.#y[r], a = r * 12, o = i.length ? n : 0;
|
|
494
|
+
(e[a + O] !== o || e[a + k] !== i.length) && (e[a + O] = o, e[a + k] = i.length, this.#h.mark(a, a + 12));
|
|
495
|
+
for (let e of i) t.push(e);
|
|
496
|
+
n += i.length;
|
|
497
|
+
}
|
|
498
|
+
this.masks.write(t);
|
|
499
|
+
}
|
|
500
|
+
#N(e) {
|
|
501
|
+
let t = this.#a, n = -1;
|
|
502
|
+
for (let r = this.#s; r <= t.length - e;) {
|
|
503
|
+
let i = r;
|
|
504
|
+
for (; i < r + e && !t[i];) i++;
|
|
505
|
+
if (i === r + e) {
|
|
506
|
+
n = r;
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
if (r = t.indexOf(0, i + 1), r < 0) break;
|
|
510
|
+
}
|
|
511
|
+
let r = [];
|
|
512
|
+
if (n >= 0) for (let t = n; t < n + e; t++) r.push(t);
|
|
513
|
+
else for (let n = this.#s; r.length < e; n = t.indexOf(0, n + 1)) r.push(n);
|
|
514
|
+
for (let e of r) t[e] = 1;
|
|
515
|
+
let i = t.indexOf(0, this.#s);
|
|
516
|
+
return this.#s = i < 0 ? t.length : i, this.#o -= e, r;
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
//#endregion
|
|
520
|
+
//#region src/engine/math/mat4.ts
|
|
521
|
+
function te(e, t) {
|
|
522
|
+
let n = Math.cos(t);
|
|
523
|
+
return [
|
|
524
|
+
Math.sin(e) * n,
|
|
525
|
+
Math.cos(e) * n,
|
|
526
|
+
Math.sin(t)
|
|
527
|
+
];
|
|
528
|
+
}
|
|
529
|
+
function ne(e, t, n, r) {
|
|
530
|
+
let [i, a, o] = te(n, r), s = Math.cos(n), c = -Math.sin(n), l = c * o, u = -s * o, d = s * a - c * i;
|
|
531
|
+
return e[0] = s, e[1] = l, e[2] = -i, e[3] = 0, e[4] = c, e[5] = u, e[6] = -a, e[7] = 0, e[8] = 0, e[9] = d, e[10] = -o, e[11] = 0, e[12] = -(s * t[0] + c * t[1]), e[13] = -(l * t[0] + u * t[1] + d * t[2]), e[14] = i * t[0] + a * t[1] + o * t[2], e[15] = 1, e;
|
|
532
|
+
}
|
|
533
|
+
function re(e, t, n, r, i) {
|
|
534
|
+
let a = 1 / Math.tan(t / 2);
|
|
535
|
+
return e.fill(0), e[0] = a / n, e[5] = a, e[10] = i / (r - i), e[11] = -1, e[14] = r * i / (r - i), e;
|
|
536
|
+
}
|
|
537
|
+
var ie = /* @__PURE__ */ new Float64Array(16);
|
|
538
|
+
function N(e, t, n) {
|
|
539
|
+
for (let e = 0; e < 4; e++) for (let r = 0; r < 4; r++) {
|
|
540
|
+
let i = 0;
|
|
541
|
+
for (let a = 0; a < 4; a++) i += t[a * 4 + r] * n[e * 4 + a];
|
|
542
|
+
ie[e * 4 + r] = i;
|
|
543
|
+
}
|
|
544
|
+
return e.set(ie), e;
|
|
545
|
+
}
|
|
546
|
+
function ae(e, t) {
|
|
547
|
+
let [n, r, i, a, o, s, c, l, u, d, f, p, m, h, g, _] = t, v = n * s - r * o, y = n * c - i * o, b = n * l - a * o, x = r * c - i * s, S = r * l - a * s, C = i * l - a * c, w = u * h - d * m, T = u * g - f * m, E = u * _ - p * m, D = d * g - f * h, O = d * _ - p * h, k = f * _ - p * g, A = v * k - y * O + b * D + x * E - S * T + C * w;
|
|
548
|
+
if (!A) return null;
|
|
549
|
+
let j = 1 / A;
|
|
550
|
+
return e[0] = (s * k - c * O + l * D) * j, e[1] = (i * O - r * k - a * D) * j, e[2] = (h * C - g * S + _ * x) * j, e[3] = (f * S - d * C - p * x) * j, e[4] = (c * E - o * k - l * T) * j, e[5] = (n * k - i * E + a * T) * j, e[6] = (g * b - m * C - _ * y) * j, e[7] = (u * C - f * b + p * y) * j, e[8] = (o * O - s * E + l * w) * j, e[9] = (r * E - n * O - a * w) * j, e[10] = (m * S - h * b + _ * v) * j, e[11] = (d * b - u * S - p * v) * j, e[12] = (s * T - o * D - c * w) * j, e[13] = (n * D - r * T + i * w) * j, e[14] = (h * y - m * x - g * v) * j, e[15] = (u * x - d * y + f * v) * j, e;
|
|
551
|
+
}
|
|
552
|
+
function oe(e, t) {
|
|
553
|
+
let [n, r, i] = t;
|
|
554
|
+
return [
|
|
555
|
+
e[0] * n + e[4] * r + e[8] * i + e[12],
|
|
556
|
+
e[1] * n + e[5] * r + e[9] * i + e[13],
|
|
557
|
+
e[2] * n + e[6] * r + e[10] * i + e[14],
|
|
558
|
+
e[3] * n + e[7] * r + e[11] * i + e[15]
|
|
559
|
+
];
|
|
560
|
+
}
|
|
561
|
+
//#endregion
|
|
562
|
+
//#region src/engine/gpu/common.wgsl?raw
|
|
563
|
+
var P = "// shared by every engine pass; sizes and word offsets mirror format/spec.ts\n\nconst KEY_BITS: u32 = 24u;\n// word offsets in the work buffer, layout.ts WORK\nconst WORK_VISIBLE: u32 = 0u;\nconst WORK_PROJECTED: u32 = 4u;\nconst WORK_LIST: u32 = 16u;\n// workgroups a dispatch row holds\nconst GROUPS_X: u32 = 65535u;\nconst C0: f32 = 0.28209479177387814;\nconst C1: f32 = 0.4886025119029199;\n\n// floating-origin ENU frame; camera looks down -z of view space\nstruct FrameUniforms {\n view: mat4x4f,\n proj: mat4x4f,\n viewProj: mat4x4f,\n // inside when dot(plane.xyz, p) + plane.w >= 0\n planes: array<vec4f, 6>,\n camera: vec3f,\n time: f32,\n // render target pixels\n viewport: vec2f,\n focal: vec2f,\n near: f32,\n far: f32,\n lowPass: f32,\n // drawn cluster ids in the pool's list\n clusters: u32,\n}\n\n// one resident page; dc and sh ranges are after the colour correction\nstruct Page {\n origin: vec3f,\n count: u32,\n step: vec3f,\n q1: u32,\n scaleMin: vec3f,\n q2: u32,\n scaleMax: vec3f,\n q3: u32,\n dcMin: vec3f,\n // quadrant k opacity 0-255 at bits 8k\n factors: u32,\n dcMax: vec3f,\n // 0 for the world, else the layer that holds the page\n layer: u32,\n shScale: array<vec4f, 3>,\n}\n\n// up to CLUSTER consecutive splats of one page in one pool slot\nstruct Cluster {\n page: u32,\n // first pool record\n slot: u32,\n // index in the page of its first splat\n first: u32,\n count: u32,\n // extents relative to the page origin\n boxMin: vec3f,\n // word in masks.wgsl's buffer of the list of masks that may hide some of its splats\n maskList: u32,\n boxMax: vec3f,\n maskCount: u32,\n}\n\n// a splat on screen; pixels with y up from the bottom-left of the target\nstruct Projected {\n centre: vec2f,\n // pack2x16float: 1-sigma major axis xy, 1-sigma minor axis xy\n axes: vec2u,\n // pack2x16float: r g, b opacity\n colour: vec2u,\n}\n\n// what a shade hook may change; position in the floating-origin frame, depth in view metres\nstruct Splat {\n position: vec3f,\n depth: f32,\n colour: vec3f,\n opacity: f32,\n scale: vec3f,\n}\n\n// the byte of word at bit, 0 to 1\nfn fraction(word: u32, bit: u32) -> f32 {\n return f32(extractBits(word, bit, 8u)) / 255.0;\n}\n\n// sigmas out to where a gaussian of opacity falls under 1/255, at most 3; the quad raster draws\nfn reach(opacity: f32) -> f32 {\n return min(3.0, sqrt(max(2.0 * log(255.0 * opacity), 0.0)));\n}\n", se = "// one thread per listed cluster\n\n@group(0) @binding(0) var<uniform> uniforms: FrameUniforms;\n@group(0) @binding(1) var<storage, read> pages: array<Page>;\n@group(0) @binding(2) var<storage, read> clusters: array<Cluster>;\n@group(0) @binding(3) var<storage, read> list: array<u32>;\n@group(0) @binding(4) var<storage, read_write> work: array<atomic<u32>>;\n\n// false only when the box lies wholly outside one plane\nfn inside(lo: vec3f, hi: vec3f) -> bool {\n for (var p = 0u; p < 6u; p++) {\n let plane = uniforms.planes[p];\n let corner = select(lo, hi, plane.xyz >= vec3f(0.0));\n if (dot(plane.xyz, corner) + plane.w < 0.0) {\n return false;\n }\n }\n return true;\n}\n\n@compute @workgroup_size(64)\nfn cull(@builtin(global_invocation_id) id: vec3u) {\n if (id.x >= uniforms.clusters) {\n return;\n }\n let slot = list[id.x];\n let cluster = clusters[slot];\n let page = pages[cluster.page];\n if (!inside(page.origin + cluster.boxMin, page.origin + cluster.boxMax)) {\n return;\n }\n atomicStore(&work[WORK_LIST + atomicAdd(&work[WORK_VISIBLE], 1u)], slot);\n}\n", ce = 64, le = class {
|
|
564
|
+
#e;
|
|
565
|
+
#t;
|
|
566
|
+
#n;
|
|
567
|
+
constructor(e, t, n) {
|
|
568
|
+
this.#e = t;
|
|
569
|
+
let r = x(e, "cull", GPUShaderStage.COMPUTE, [
|
|
570
|
+
"uniform",
|
|
571
|
+
"read-only-storage",
|
|
572
|
+
"read-only-storage",
|
|
573
|
+
"read-only-storage",
|
|
574
|
+
"storage"
|
|
575
|
+
]), i = e.createShaderModule({
|
|
576
|
+
label: "cull",
|
|
577
|
+
code: `${P}\n${se}`
|
|
578
|
+
});
|
|
579
|
+
this.#t = e.createComputePipeline({
|
|
580
|
+
label: "cull",
|
|
581
|
+
layout: e.createPipelineLayout({ bindGroupLayouts: [r] }),
|
|
582
|
+
compute: {
|
|
583
|
+
module: i,
|
|
584
|
+
entryPoint: "cull"
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
let a = [
|
|
588
|
+
n.uniforms,
|
|
589
|
+
t.pages,
|
|
590
|
+
t.clusters,
|
|
591
|
+
t.list,
|
|
592
|
+
n.work
|
|
593
|
+
];
|
|
594
|
+
this.#n = S(e, "cull", r, a);
|
|
595
|
+
}
|
|
596
|
+
encode(e, t) {
|
|
597
|
+
let n = e.beginComputePass({
|
|
598
|
+
label: "cull",
|
|
599
|
+
timestampWrites: t
|
|
600
|
+
});
|
|
601
|
+
n.setBindGroup(0, this.#n), n.setPipeline(this.#t), this.#e.listed && n.dispatchWorkgroups(Math.ceil(this.#e.listed / ce)), n.end();
|
|
602
|
+
}
|
|
603
|
+
}, ue = "// prisms that hide splats by centre; masks.ts writes the records, their vertices, then the clusters' lists\n\n// words of a record: min x y, max x y, min z, max z (f32), first vertex word, vertices\nconst MASK_WORDS: u32 = 8u;\n\n@group(1) @binding(0) var<storage, read> masks: array<u32>;\n\nfn maskFloat(k: u32) -> f32 {\n return bitcast<f32>(masks[k]);\n}\n\n// p, floating-origin frame, inside a mask of the cluster's list: its polygon by the even-odd rule and its z range\nfn masked(cluster: Cluster, p: vec3f) -> bool {\n for (var k = 0u; k < cluster.maskCount; k++) {\n let m = masks[cluster.maskList + k] * MASK_WORDS;\n if (p.x < maskFloat(m) || p.y < maskFloat(m + 1u) || p.x > maskFloat(m + 2u) ||\n p.y > maskFloat(m + 3u) || p.z < maskFloat(m + 4u) || p.z > maskFloat(m + 5u)) {\n continue;\n }\n let first = masks[m + 6u];\n let n = masks[m + 7u];\n var odd = false;\n var b = vec2f(maskFloat(first + 2u * n - 2u), maskFloat(first + 2u * n - 1u));\n for (var i = 0u; i < n; i++) {\n let a = vec2f(maskFloat(first + 2u * i), maskFloat(first + 2u * i + 1u));\n if ((a.y > p.y) != (b.y > p.y) && p.x < (b.x - a.x) * (p.y - a.y) / (b.y - a.y) + a.x) {\n odd = !odd;\n }\n b = a;\n }\n if (odd) {\n return true;\n }\n }\n return false;\n}\n", de = "// the top of the solid drawn splats over a square of 1 m cells; one workgroup per listed cluster\n\nconst GROUP: u32 = 64u;\n\nstruct Area {\n // south-west corner, floating-origin frame\n corner: vec2f,\n cells: u32,\n clusters: u32,\n // least opacity and largest scale in metres of a splat that counts\n opacity: f32,\n scale: f32,\n}\n\n@group(0) @binding(0) var<uniform> area: Area;\n@group(0) @binding(1) var<storage, read> pages: array<Page>;\n@group(0) @binding(2) var<storage, read> clusters: array<Cluster>;\n@group(0) @binding(3) var<storage, read> list: array<u32>;\n@group(0) @binding(4) var<storage, read> geometry: array<vec4u>;\n@group(0) @binding(5) var<storage, read_write> tops: array<atomic<u32>>;\n\n// order-preserving bits of z, never 0, which marks an empty cell\nfn ordered(z: f32) -> u32 {\n let bits = bitcast<u32>(z);\n return select(bits | 0x80000000u, ~bits, z < 0.0);\n}\n\n@compute @workgroup_size(64)\nfn heights(@builtin(workgroup_id) wid: vec3u, @builtin(local_invocation_index) t: u32) {\n let index = wid.y * GROUPS_X + wid.x;\n if (index >= area.clusters) {\n return;\n }\n let cluster = clusters[list[index]];\n let page = pages[cluster.page];\n let size = f32(area.cells);\n let lo = page.origin.xy + cluster.boxMin.xy - area.corner;\n let hi = page.origin.xy + cluster.boxMax.xy - area.corner;\n if (any(hi < vec2f(0.0)) || any(lo >= vec2f(size))) {\n return;\n }\n for (var k = t; k < cluster.count; k += GROUP) {\n let g = geometry[cluster.slot + k];\n let i = cluster.first + k;\n let quadrant = u32(i >= page.q1) + u32(i >= page.q2) + u32(i >= page.q3);\n let opacity = fraction(g.y, 16u) * fraction(page.factors, 8u * quadrant);\n let level = vec3f(fraction(g.z, 24u), fraction(g.w, 0u), fraction(g.w, 8u));\n let scale = exp(mix(page.scaleMin, page.scaleMax, level));\n if (opacity < area.opacity || max(scale.x, max(scale.y, scale.z)) > area.scale) {\n continue;\n }\n let q = vec3f(f32(g.x & 0xffffu), f32(g.x >> 16u), f32(g.y & 0xffffu));\n let p = page.origin + q * page.step;\n if (masked(cluster, p)) {\n continue;\n }\n let cell = floor(p.xy - area.corner);\n if (any(cell < vec2f(0.0)) || any(cell >= vec2f(size))) {\n continue;\n }\n let c = vec2u(cell);\n atomicMax(&tops[c.y * area.cells + c.x], ordered(p.z));\n }\n}\n", fe = 32, pe = .5, me = 1;
|
|
604
|
+
function he(e) {
|
|
605
|
+
let t = new Uint32Array(e.length);
|
|
606
|
+
for (let n = 0; n < e.length; n++) {
|
|
607
|
+
let r = e[n];
|
|
608
|
+
t[n] = r === 0 ? 2143289344 : r & 2147483648 ? r & 2147483647 : ~r >>> 0;
|
|
609
|
+
}
|
|
610
|
+
return new Float32Array(t.buffer);
|
|
611
|
+
}
|
|
612
|
+
var ge = class {
|
|
613
|
+
#e;
|
|
614
|
+
#t;
|
|
615
|
+
#n;
|
|
616
|
+
#r;
|
|
617
|
+
constructor(e, t) {
|
|
618
|
+
this.#e = e, this.#t = t, this.#n = x(e, "heights", GPUShaderStage.COMPUTE, [
|
|
619
|
+
"uniform",
|
|
620
|
+
"read-only-storage",
|
|
621
|
+
"read-only-storage",
|
|
622
|
+
"read-only-storage",
|
|
623
|
+
"read-only-storage",
|
|
624
|
+
"storage"
|
|
625
|
+
]);
|
|
626
|
+
let n = `${P}\n${ue}\n${de}`, r = e.createShaderModule({
|
|
627
|
+
label: "heights",
|
|
628
|
+
code: n
|
|
629
|
+
});
|
|
630
|
+
this.#r = e.createComputePipeline({
|
|
631
|
+
label: "heights",
|
|
632
|
+
layout: e.createPipelineLayout({ bindGroupLayouts: [this.#n, t.masks.layout] }),
|
|
633
|
+
compute: {
|
|
634
|
+
module: r,
|
|
635
|
+
entryPoint: "heights"
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
encode(e, t, n, r, i) {
|
|
640
|
+
let a = this.#e, o = this.#t, { listed: s } = o, c = r * r * 4, l = a.createBuffer({
|
|
641
|
+
label: "heights area",
|
|
642
|
+
size: fe,
|
|
643
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
644
|
+
}), u = a.createBuffer({
|
|
645
|
+
label: "heights",
|
|
646
|
+
size: c,
|
|
647
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
648
|
+
}), d = a.createBuffer({
|
|
649
|
+
label: "heights readback",
|
|
650
|
+
size: c,
|
|
651
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
652
|
+
}), f = /* @__PURE__ */ new ArrayBuffer(fe);
|
|
653
|
+
new Float32Array(f).set([
|
|
654
|
+
t,
|
|
655
|
+
n,
|
|
656
|
+
0,
|
|
657
|
+
0,
|
|
658
|
+
pe,
|
|
659
|
+
me
|
|
660
|
+
]), new Uint32Array(f).set([r, s], 2), a.queue.writeBuffer(l, 0, f);
|
|
661
|
+
let p = [
|
|
662
|
+
l,
|
|
663
|
+
o.pages,
|
|
664
|
+
o.clusters,
|
|
665
|
+
o.list,
|
|
666
|
+
o.geometry,
|
|
667
|
+
u
|
|
668
|
+
], h = S(a, "heights", this.#n, p), g = e.beginComputePass({
|
|
669
|
+
label: "heights",
|
|
670
|
+
timestampWrites: i
|
|
671
|
+
});
|
|
672
|
+
return g.setPipeline(this.#r), g.setBindGroup(0, h), g.setBindGroup(1, o.masks.group), s > 0 && g.dispatchWorkgroups(...m(s)), g.end(), e.copyBufferToBuffer(u, 0, d, 0, c), () => d.mapAsync(GPUMapMode.READ).then(() => he(new Uint32Array(d.getMappedRange())), () => null).finally(() => {
|
|
673
|
+
l.destroy(), u.destroy(), d.destroy();
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
}, _e = "@vertex\nfn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {\n // one triangle over the whole target\n let p = vec2f(f32((i << 1u) & 2u), f32(i & 2u));\n return vec4f(p * 2.0 - 1.0, 0.0, 1.0);\n}\n", ve = class {
|
|
677
|
+
#e;
|
|
678
|
+
#t;
|
|
679
|
+
#n;
|
|
680
|
+
#r = [];
|
|
681
|
+
#i;
|
|
682
|
+
constructor(e, t, n, r) {
|
|
683
|
+
let i = e.createShaderModule({
|
|
684
|
+
label: t,
|
|
685
|
+
code: _e + n
|
|
686
|
+
});
|
|
687
|
+
this.#e = e, this.#t = t, this.#n = e.createRenderPipeline({
|
|
688
|
+
label: t,
|
|
689
|
+
layout: "auto",
|
|
690
|
+
vertex: {
|
|
691
|
+
module: i,
|
|
692
|
+
entryPoint: "vs"
|
|
693
|
+
},
|
|
694
|
+
fragment: {
|
|
695
|
+
module: i,
|
|
696
|
+
entryPoint: "fs",
|
|
697
|
+
targets: [{ format: r }]
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
encode(e, t, n) {
|
|
702
|
+
(!this.#i || t.some((e, t) => e !== this.#r[t])) && (this.#r = t, this.#i = this.#e.createBindGroup({
|
|
703
|
+
label: this.#t,
|
|
704
|
+
layout: this.#n.getBindGroupLayout(0),
|
|
705
|
+
entries: t.map((e, t) => ({
|
|
706
|
+
binding: t,
|
|
707
|
+
resource: e
|
|
708
|
+
}))
|
|
709
|
+
}));
|
|
710
|
+
let r = e.beginRenderPass({
|
|
711
|
+
label: this.#t,
|
|
712
|
+
colorAttachments: [{
|
|
713
|
+
view: n,
|
|
714
|
+
loadOp: "clear",
|
|
715
|
+
storeOp: "store"
|
|
716
|
+
}]
|
|
717
|
+
});
|
|
718
|
+
r.setPipeline(this.#n), r.setBindGroup(0, this.#i), r.draw(3), r.end();
|
|
719
|
+
}
|
|
720
|
+
}, ye = "// the finished colour target onto the canvas, opaque\n\n@group(0) @binding(0) var scene: texture_2d<f32>;\n\n@fragment\nfn fs(@builtin(position) coord: vec4f) -> @location(0) vec4f {\n return vec4f(textureLoad(scene, vec2i(coord.xy), 0).rgb, 1.0);\n}\n", be = (e, t) => new ve(e, "present", ye, t), xe = "// workgroups loop over visible clusters, one thread per splat\n\n// ndc reach past the frustum, so splats centred just outside still cover the edge\nconst GUARD: f32 = 1.3;\n\n@group(0) @binding(0) var<uniform> uniforms: FrameUniforms;\n@group(0) @binding(1) var<uniform> plugins: array<vec4f, 16>;\n@group(0) @binding(2) var<storage, read> geometry: array<vec4u>;\n@group(0) @binding(3) var<storage, read> colours: array<u32>;\n@group(0) @binding(4) var<storage, read> pages: array<Page>;\n@group(0) @binding(5) var<storage, read> clusters: array<Cluster>;\n@group(0) @binding(6) var<storage, read_write> work: array<atomic<u32>>;\n@group(0) @binding(7) var<storage, read_write> projected: array<Projected>;\n// keys in [0, capacity), values in [capacity, 2 capacity)\n@group(0) @binding(8) var<storage, read_write> sort: array<u32>;\n\n@group(0) @binding(9) var<uniform> visible: u32;\nvar<workgroup> kept: atomic<u32>;\nvar<workgroup> base: u32;\n\n// false when splat t of the cluster cannot show; else its Projected and sort key\nfn shown(cluster: Cluster, t: u32, dest: ptr<function, Projected>, key: ptr<function, u32>) -> bool {\n var s: Splat;\n var g: vec4u;\n if (!decode(cluster, t, &s, &g)) {\n return false;\n }\n shade(&s);\n if (s.opacity < 1.0 / 255.0) {\n return false;\n }\n\n // project\n let viewPos = (uniforms.view * vec4f(s.position, 1.0)).xyz;\n let depth = -viewPos.z;\n if (depth < uniforms.near || depth > uniforms.far) {\n return false;\n }\n let clip = uniforms.proj * vec4f(viewPos, 1.0);\n let ndc = clip.xy / clip.w;\n if (any(abs(ndc) > vec2f(GUARD))) {\n return false;\n }\n\n let cov = covariance(g, s.scale, viewPos);\n let a = cov.x;\n let b = cov.y;\n let c = cov.z;\n let mid = 0.5 * (a + c);\n let rad = length(vec2f(0.5 * (a - c), b));\n let major = sqrt(mid + rad);\n if (3.0 * major < 0.5) {\n return false;\n }\n let minor = sqrt(max(mid - rad, 0.0));\n let angle = 0.5 * atan2(2.0 * b, a - c);\n let axis = vec2f(cos(angle), sin(angle));\n // the quad raster draws; a centre inside the guard band can still miss the screen\n let centre = (ndc * 0.5 + 0.5) * uniforms.viewport;\n let extent = reach(s.opacity) * (abs(axis) * major + abs(axis.yx) * minor);\n if (any(centre + extent < vec2f(0.0)) || any(centre - extent > uniforms.viewport)) {\n return false;\n }\n\n *dest = Projected(\n centre,\n vec2u(pack2x16float(axis * major), pack2x16float(vec2f(-axis.y, axis.x) * minor)),\n vec2u(pack2x16float(s.colour.rg), pack2x16float(vec2f(s.colour.b, s.opacity)))\n );\n let span = clamp(log(depth / uniforms.near) / log(uniforms.far / uniforms.near), 0.0, 1.0);\n *key = u32((1.0 - span) * f32((1u << KEY_BITS) - 1u));\n return true;\n}\n\n@compute @workgroup_size(256)\nfn project(\n @builtin(workgroup_id) wid: vec3u,\n @builtin(num_workgroups) groups: vec3u,\n @builtin(local_invocation_index) t: u32\n) {\n for (var index = wid.y * groups.x + wid.x; index < visible; index += groups.x * groups.y) {\n let cluster = clusters[atomicLoad(&work[WORK_LIST + index])];\n var splat: Projected;\n var key = 0u;\n var keep = false;\n if (t < cluster.count) {\n keep = shown(cluster, t, &splat, &key);\n }\n\n // one global atomic per cluster\n var rank = 0u;\n if (keep) {\n rank = atomicAdd(&kept, 1u);\n }\n workgroupBarrier();\n if (t == 0u) {\n base = atomicAdd(&work[WORK_PROJECTED], atomicExchange(&kept, 0u));\n }\n let i = workgroupUniformLoad(&base) + rank;\n let capacity = arrayLength(&projected);\n if (keep && i < capacity) {\n projected[i] = splat;\n sort[i] = key;\n sort[capacity + i] = i;\n }\n }\n}\n", Se = "// a pool splat decoded and its screen covariance, shared by project and pick; each declares the\n// uniforms, geometry, colours and pages bindings these read\n\n// i8 over 127, sign-extended by extractBits on i32\nfn code(word: u32, bit: u32) -> f32 {\n return f32(extractBits(i32(word), bit, 8u)) / 127.0;\n}\n\n// smallest three: w x y z with the largest at the stored index\nfn rotation(g: vec4u) -> vec4f {\n let v = (vec3f(fraction(g.z, 0u), fraction(g.z, 8u), fraction(g.z, 16u)) - 0.5) * sqrt(2.0);\n let big = sqrt(max(0.0, 1.0 - dot(v, v)));\n switch extractBits(g.y, 24u, 8u) {\n case 0u: {\n return normalize(vec4f(big, v));\n }\n case 1u: {\n return normalize(vec4f(v.x, big, v.yz));\n }\n case 2u: {\n return normalize(vec4f(v.xy, big, v.z));\n }\n default: {\n return normalize(vec4f(v, big));\n }\n }\n}\n\nfn rotate(q: vec4f) -> mat3x3f {\n let w = q.x;\n let x = q.y;\n let y = q.z;\n let z = q.w;\n return mat3x3f(\n 1.0 - 2.0 * (y * y + z * z), 2.0 * (x * y + w * z), 2.0 * (x * z - w * y),\n 2.0 * (x * y - w * z), 1.0 - 2.0 * (x * x + z * z), 2.0 * (y * z + w * x),\n 2.0 * (x * z + w * y), 2.0 * (y * z - w * x), 1.0 - 2.0 * (x * x + y * y)\n );\n}\n\n// splat t of a cluster in the floating-origin frame, its record in g; false when a mask hides it\nfn decode(cluster: Cluster, t: u32, s: ptr<function, Splat>, g: ptr<function, vec4u>) -> bool {\n let page = pages[cluster.page];\n let rec = cluster.slot + t;\n *g = geometry[rec];\n let w0 = colours[rec * 3u];\n let w1 = colours[rec * 3u + 1u];\n let w2 = colours[rec * 3u + 2u];\n let i = cluster.first + t;\n let quadrant = u32(i >= page.q1) + u32(i >= page.q2) + u32(i >= page.q3);\n\n var d: Splat;\n let q = vec3f(f32((*g).x & 0xffffu), f32((*g).x >> 16u), f32((*g).y & 0xffffu));\n d.position = page.origin + q * page.step;\n if (masked(cluster, d.position)) {\n return false;\n }\n d.opacity = fraction((*g).y, 16u) * fraction(page.factors, 8u * quadrant);\n let level = vec3f(fraction((*g).z, 24u), fraction((*g).w, 0u), fraction((*g).w, 8u));\n d.scale = exp(mix(page.scaleMin, page.scaleMax, level));\n let dc = mix(page.dcMin, page.dcMax, vec3f(fraction(w0, 0u), fraction(w0, 8u), fraction(w0, 16u)));\n // sh[c][m] at 3c + m, gathered per m across the colours\n let k = page.shScale;\n let m0 = vec3f(code(w0, 24u), code(w1, 16u), code(w2, 8u)) * vec3f(k[0].x, k[0].w, k[1].z);\n let m1 = vec3f(code(w1, 0u), code(w1, 24u), code(w2, 16u)) * vec3f(k[0].y, k[1].x, k[1].w);\n let m2 = vec3f(code(w1, 8u), code(w2, 0u), code(w2, 24u)) * vec3f(k[0].z, k[1].y, k[2].x);\n let toward = normalize(d.position - uniforms.camera);\n d.colour = max(0.5 + C0 * dc + C1 * (-toward.y * m0 + toward.z * m1 - toward.x * m2), vec3f(0.0));\n d.depth = -(uniforms.view * vec4f(d.position, 1.0)).z;\n *s = d;\n return true;\n}\n\n// ewa: view-space covariance wm wm^T through the jacobian of the pixel projection, as a b c in px²\nfn covariance(g: vec4u, scale: vec3f, viewPos: vec3f) -> vec3f {\n let depth = -viewPos.z;\n let r = rotate(rotation(g));\n let m = mat3x3f(r[0] * scale.x, r[1] * scale.y, r[2] * scale.z);\n let w = mat3x3f(uniforms.view[0].xyz, uniforms.view[1].xyz, uniforms.view[2].xyz);\n let wm = w * m;\n let focal = uniforms.focal;\n let j0 = vec3f(focal.x / depth, 0.0, focal.x * viewPos.x / (depth * depth));\n let j1 = vec3f(0.0, focal.y / depth, focal.y * viewPos.y / (depth * depth));\n let u = j0 * wm;\n let v = j1 * wm;\n return vec3f(dot(u, u) + uniforms.lowPass, dot(u, v), dot(v, v) + uniforms.lowPass);\n}\n", Ce = class {
|
|
721
|
+
#e;
|
|
722
|
+
#t;
|
|
723
|
+
#n;
|
|
724
|
+
#r = [];
|
|
725
|
+
#i;
|
|
726
|
+
#a;
|
|
727
|
+
#o;
|
|
728
|
+
#s;
|
|
729
|
+
constructor(e, t, n) {
|
|
730
|
+
this.#e = e, this.#a = t, this.#o = n.work, this.#s = n.visible;
|
|
731
|
+
let r = x(e, "project", GPUShaderStage.COMPUTE, [
|
|
732
|
+
"uniform",
|
|
733
|
+
"uniform",
|
|
734
|
+
"read-only-storage",
|
|
735
|
+
"read-only-storage",
|
|
736
|
+
"read-only-storage",
|
|
737
|
+
"read-only-storage",
|
|
738
|
+
"storage",
|
|
739
|
+
"storage",
|
|
740
|
+
"storage",
|
|
741
|
+
"uniform"
|
|
742
|
+
]);
|
|
743
|
+
this.#t = e.createPipelineLayout({ bindGroupLayouts: [r, t.masks.layout] });
|
|
744
|
+
let i = [
|
|
745
|
+
n.uniforms,
|
|
746
|
+
n.plugins,
|
|
747
|
+
t.geometry,
|
|
748
|
+
t.colour,
|
|
749
|
+
t.pages,
|
|
750
|
+
t.clusters,
|
|
751
|
+
n.work,
|
|
752
|
+
n.projected,
|
|
753
|
+
n.sort,
|
|
754
|
+
n.visible
|
|
755
|
+
];
|
|
756
|
+
this.#i = S(e, "project", r, i);
|
|
757
|
+
}
|
|
758
|
+
hooks(e) {
|
|
759
|
+
this.#r = e, this.#n = void 0;
|
|
760
|
+
}
|
|
761
|
+
encode(e, t, n) {
|
|
762
|
+
e.copyBufferToBuffer(this.#o, f.visible * 4, this.#s, 0, 4);
|
|
763
|
+
let r = Math.max(1, Math.min(128, this.#a.listed, t ? Math.max(32, Math.ceil(t / 16)) : 128)), i = e.beginComputePass({
|
|
764
|
+
label: "project",
|
|
765
|
+
timestampWrites: n
|
|
766
|
+
});
|
|
767
|
+
i.setPipeline(this.#n ??= this.#c()), i.setBindGroup(0, this.#i), i.setBindGroup(1, this.#a.masks.group), i.dispatchWorkgroups(r), i.end();
|
|
768
|
+
}
|
|
769
|
+
#c() {
|
|
770
|
+
let e = we([
|
|
771
|
+
P,
|
|
772
|
+
ue,
|
|
773
|
+
Se,
|
|
774
|
+
xe
|
|
775
|
+
], this.#r), t = this.#e.createShaderModule({
|
|
776
|
+
label: "project",
|
|
777
|
+
code: e
|
|
778
|
+
});
|
|
779
|
+
return this.#e.createComputePipeline({
|
|
780
|
+
label: "project",
|
|
781
|
+
layout: this.#t,
|
|
782
|
+
compute: {
|
|
783
|
+
module: t,
|
|
784
|
+
entryPoint: "project"
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
function we(e, t) {
|
|
790
|
+
let n = t.map(({ shade: e, slot: t }) => {
|
|
791
|
+
let n = Array.from({ length: e.uniforms }, (e, n) => `plugins[${t + n}]`);
|
|
792
|
+
return `\t${e.name}(s, array<vec4f, ${e.uniforms}>(${n.join(", ")}));`;
|
|
793
|
+
});
|
|
794
|
+
return [
|
|
795
|
+
...e,
|
|
796
|
+
...t.map(({ shade: e }) => e.wgsl),
|
|
797
|
+
"fn shade(s: ptr<function, Splat>) {",
|
|
798
|
+
...n,
|
|
799
|
+
"}"
|
|
800
|
+
].join("\n");
|
|
801
|
+
}
|
|
802
|
+
//#endregion
|
|
803
|
+
//#region src/engine/gpu/overlay.wgsl?raw
|
|
804
|
+
var Te = "// host graphics over the frame: capsules in screen space from a to b, a marker where a is b\n\n// share of the view depth an occluding fragment may lie behind the splats, so a line on the ground clears their fringe\nconst SLACK: f32 = 0.02;\n\nstruct Capsule {\n @location(0) a: vec3f,\n @location(1) b: vec3f,\n // pixels\n @location(2) radius: f32,\n @location(3) colour: vec4f,\n @location(4) occlude: u32,\n}\n\nstruct Fragment {\n @builtin(position) position: vec4f,\n // target pixels from the top-left, of the ends\n @location(0) @interpolate(flat) a: vec2f,\n @location(1) @interpolate(flat) b: vec2f,\n // view depth of the ends\n @location(2) @interpolate(flat) depths: vec2f,\n @location(3) @interpolate(flat) radius: f32,\n @location(4) @interpolate(flat) colour: vec4f,\n @location(5) @interpolate(flat) occlude: u32,\n}\n\n@group(0) @binding(0) var<uniform> uniforms: FrameUniforms;\n@group(0) @binding(1) var depth: texture_depth_2d;\n\nfn pixel(view: vec3f) -> vec2f {\n let clip = uniforms.proj * vec4f(view, 1.0);\n let ndc = clip.xy / clip.w;\n return vec2f(ndc.x * 0.5 + 0.5, 0.5 - ndc.y * 0.5) * uniforms.viewport;\n}\n\n@vertex\nfn vs(@builtin(vertex_index) v: u32, c: Capsule) -> Fragment {\n var a = (uniforms.view * vec4f(c.a, 1.0)).xyz;\n var b = (uniforms.view * vec4f(c.b, 1.0)).xyz;\n var out: Fragment;\n // cut the part behind the near plane; nothing left draws nothing\n let near = -uniforms.near;\n if (a.z > near && b.z > near) {\n out.position = vec4f(2.0, 2.0, 0.0, 1.0);\n return out;\n }\n if (a.z > near) {\n a = mix(b, a, (near - b.z) / (a.z - b.z));\n } else if (b.z > near) {\n b = mix(a, b, (near - a.z) / (b.z - a.z));\n }\n let pa = pixel(a);\n let pb = pixel(b);\n let span = pb - pa;\n let along = select(vec2f(1.0, 0.0), normalize(span), dot(span, span) > 1e-6);\n let across = vec2f(-along.y, along.x);\n let r = c.radius + 1.0;\n let corner = select(pa - along * r, pb + along * r, (v & 1u) == 1u) + across * r * select(-1.0, 1.0, v > 1u);\n out.position = vec4f(corner.x / uniforms.viewport.x * 2.0 - 1.0, 1.0 - corner.y / uniforms.viewport.y * 2.0, 0.0, 1.0);\n out.a = pa;\n out.b = pb;\n out.depths = vec2f(-a.z, -b.z);\n out.radius = c.radius;\n out.colour = c.colour;\n out.occlude = c.occlude;\n return out;\n}\n\n@fragment\nfn fs(f: Fragment) -> @location(0) vec4f {\n let p = f.position.xy;\n let span = f.b - f.a;\n let t = select(0.0, clamp(dot(p - f.a, span) / dot(span, span), 0.0, 1.0), dot(span, span) > 1e-6);\n let coverage = clamp(f.radius - distance(p, f.a + span * t) + 0.5, 0.0, 1.0);\n if (coverage <= 0.0) {\n discard;\n }\n if (f.occlude != 0u) {\n // screen-linear in 1 / depth along a segment\n let here = 1.0 / mix(1.0 / f.depths.x, 1.0 / f.depths.y, t);\n let stored = textureLoad(depth, vec2i(p), 0);\n let scene = uniforms.near * pow(uniforms.far / uniforms.near, stored);\n if (stored < 1.0 && here > scene * (1.0 + SLACK)) {\n discard;\n }\n }\n let a = f.colour.a * coverage;\n return vec4f(f.colour.rgb * a, a);\n}\n", Ee = 36, De = {
|
|
805
|
+
srcFactor: "one",
|
|
806
|
+
dstFactor: "one-minus-src-alpha"
|
|
807
|
+
}, Oe = class {
|
|
808
|
+
#e;
|
|
809
|
+
#t;
|
|
810
|
+
#n;
|
|
811
|
+
#r = null;
|
|
812
|
+
#i = 0;
|
|
813
|
+
#a;
|
|
814
|
+
#o;
|
|
815
|
+
constructor(e, t, n) {
|
|
816
|
+
this.#e = e, this.#t = n;
|
|
817
|
+
let r = e.createShaderModule({
|
|
818
|
+
label: "overlay",
|
|
819
|
+
code: P + Te
|
|
820
|
+
}), i = [
|
|
821
|
+
{
|
|
822
|
+
shaderLocation: 0,
|
|
823
|
+
offset: 0,
|
|
824
|
+
format: "float32x3"
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
shaderLocation: 1,
|
|
828
|
+
offset: 12,
|
|
829
|
+
format: "float32x3"
|
|
830
|
+
},
|
|
831
|
+
{
|
|
832
|
+
shaderLocation: 2,
|
|
833
|
+
offset: 24,
|
|
834
|
+
format: "float32"
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
shaderLocation: 3,
|
|
838
|
+
offset: 28,
|
|
839
|
+
format: "unorm8x4"
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
shaderLocation: 4,
|
|
843
|
+
offset: 32,
|
|
844
|
+
format: "uint32"
|
|
845
|
+
}
|
|
846
|
+
];
|
|
847
|
+
this.#n = e.createRenderPipeline({
|
|
848
|
+
label: "overlay",
|
|
849
|
+
layout: "auto",
|
|
850
|
+
vertex: {
|
|
851
|
+
module: r,
|
|
852
|
+
entryPoint: "vs",
|
|
853
|
+
buffers: [{
|
|
854
|
+
arrayStride: Ee,
|
|
855
|
+
stepMode: "instance",
|
|
856
|
+
attributes: i
|
|
857
|
+
}]
|
|
858
|
+
},
|
|
859
|
+
fragment: {
|
|
860
|
+
module: r,
|
|
861
|
+
entryPoint: "fs",
|
|
862
|
+
targets: [{
|
|
863
|
+
format: t,
|
|
864
|
+
blend: {
|
|
865
|
+
color: De,
|
|
866
|
+
alpha: De
|
|
867
|
+
}
|
|
868
|
+
}]
|
|
869
|
+
},
|
|
870
|
+
primitive: { topology: "triangle-strip" }
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
get count() {
|
|
874
|
+
return this.#i;
|
|
875
|
+
}
|
|
876
|
+
set(e, t) {
|
|
877
|
+
if (this.#i = e.length, !e.length) return;
|
|
878
|
+
let n = /* @__PURE__ */ new ArrayBuffer(e.length * Ee), r = new Float32Array(n), i = new Uint32Array(n), a = new Uint8Array(n);
|
|
879
|
+
e.forEach(({ a: e, b: n, radius: o, colour: s, occlude: c }, l) => {
|
|
880
|
+
let u = l * Ee / 4;
|
|
881
|
+
for (let i = 0; i < 3; i++) r[u + i] = e[i] - t[i], r[u + 3 + i] = n[i] - t[i];
|
|
882
|
+
r[u + 6] = o, s.forEach((e, t) => a[(u + 7) * 4 + t] = Math.round(Math.min(1, Math.max(0, e)) * 255)), i[u + 8] = +!!c;
|
|
883
|
+
}), (!this.#r || this.#r.size < n.byteLength) && (this.#r?.destroy(), this.#r = this.#e.createBuffer({
|
|
884
|
+
label: "overlay",
|
|
885
|
+
size: 2 ** Math.ceil(Math.log2(n.byteLength)),
|
|
886
|
+
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
887
|
+
})), this.#e.queue.writeBuffer(this.#r, 0, n);
|
|
888
|
+
}
|
|
889
|
+
encode(e, t, n) {
|
|
890
|
+
if (!this.#i) return;
|
|
891
|
+
n !== this.#a && (this.#a = n, this.#o = this.#e.createBindGroup({
|
|
892
|
+
label: "overlay",
|
|
893
|
+
layout: this.#n.getBindGroupLayout(0),
|
|
894
|
+
entries: [{
|
|
895
|
+
binding: 0,
|
|
896
|
+
resource: { buffer: this.#t }
|
|
897
|
+
}, {
|
|
898
|
+
binding: 1,
|
|
899
|
+
resource: n
|
|
900
|
+
}]
|
|
901
|
+
}));
|
|
902
|
+
let r = e.beginRenderPass({
|
|
903
|
+
label: "overlay",
|
|
904
|
+
colorAttachments: [{
|
|
905
|
+
view: t,
|
|
906
|
+
loadOp: "load",
|
|
907
|
+
storeOp: "store"
|
|
908
|
+
}]
|
|
909
|
+
});
|
|
910
|
+
r.setPipeline(this.#n), r.setBindGroup(0, this.#o), r.setVertexBuffer(0, this.#r), r.draw(4, this.#i), r.end();
|
|
911
|
+
}
|
|
912
|
+
destroy() {
|
|
913
|
+
this.#r?.destroy();
|
|
914
|
+
}
|
|
915
|
+
}, ke = [
|
|
916
|
+
[
|
|
917
|
+
0,
|
|
918
|
+
-1,
|
|
919
|
+
1
|
|
920
|
+
],
|
|
921
|
+
[
|
|
922
|
+
0,
|
|
923
|
+
1,
|
|
924
|
+
-1
|
|
925
|
+
],
|
|
926
|
+
[
|
|
927
|
+
1,
|
|
928
|
+
-1,
|
|
929
|
+
1
|
|
930
|
+
],
|
|
931
|
+
[
|
|
932
|
+
1,
|
|
933
|
+
1,
|
|
934
|
+
-1
|
|
935
|
+
],
|
|
936
|
+
[
|
|
937
|
+
2,
|
|
938
|
+
0,
|
|
939
|
+
1
|
|
940
|
+
],
|
|
941
|
+
[
|
|
942
|
+
2,
|
|
943
|
+
1,
|
|
944
|
+
-1
|
|
945
|
+
]
|
|
946
|
+
];
|
|
947
|
+
function Ae(e, t, n) {
|
|
948
|
+
return ke.forEach(([r, i, a], o) => {
|
|
949
|
+
let s = n?.[o] ?? i;
|
|
950
|
+
for (let n = 0; n < 4; n++) e[o * 4 + n] = a * (t[n * 4 + r] - s * t[n * 4 + 3]);
|
|
951
|
+
let c = Math.hypot(e[o * 4], e[o * 4 + 1], e[o * 4 + 2]) || 1;
|
|
952
|
+
for (let t = 0; t < 4; t++) e[o * 4 + t] /= c;
|
|
953
|
+
}), e;
|
|
954
|
+
}
|
|
955
|
+
function je(e, t, n) {
|
|
956
|
+
for (let r = 0; r < 24; r += 4) {
|
|
957
|
+
let i = e[r] >= 0 ? n[0] : t[0], a = e[r + 1] >= 0 ? n[1] : t[1], o = e[r + 2] >= 0 ? n[2] : t[2];
|
|
958
|
+
if (e[r] * i + e[r + 1] * a + e[r + 2] * o + e[r + 3] < 0) return !1;
|
|
959
|
+
}
|
|
960
|
+
return !0;
|
|
961
|
+
}
|
|
962
|
+
//#endregion
|
|
963
|
+
//#region src/engine/gpu/pick.wgsl?raw
|
|
964
|
+
var Me = "// the nearest solid splat under one pixel, over the last frame's visible clusters\n\n// workgroups of the dispatch, pick.ts's GROUPS; each loops over the visible clusters\nconst PICK_GROUPS: u32 = 256u;\n// least alpha at the pixel of a splat that counts as the surface\nconst SOLID: f32 = 0.5;\n\nstruct Probe {\n // target pixel, y up from the bottom-left\n pixel: vec2f,\n // the pixel's frustum sides; inside when dot(plane.xyz, p) + plane.w >= 0\n planes: array<vec4f, 4>,\n}\n\n@group(0) @binding(0) var<uniform> uniforms: FrameUniforms;\n@group(0) @binding(1) var<uniform> plugins: array<vec4f, 16>;\n@group(0) @binding(2) var<storage, read> geometry: array<vec4u>;\n@group(0) @binding(3) var<storage, read> colours: array<u32>;\n@group(0) @binding(4) var<storage, read> pages: array<Page>;\n@group(0) @binding(5) var<storage, read> clusters: array<Cluster>;\n@group(0) @binding(6) var<storage, read> work: array<u32>;\n@group(0) @binding(7) var<uniform> probe: Probe;\n// view depth bits of the nearest hit, then its layer, then its normal\n@group(0) @binding(8) var<storage, read_write> hit: array<atomic<u32>>;\n\n// false only when the box lies wholly outside one side of the pixel\nfn under(lo: vec3f, hi: vec3f) -> bool {\n for (var p = 0u; p < 4u; p++) {\n let plane = probe.planes[p];\n let corner = select(lo, hi, plane.xyz >= vec3f(0.0));\n if (dot(plane.xyz, corner) + plane.w < 0.0) {\n return false;\n }\n }\n return true;\n}\n\n// splat t of the cluster draws the pixel solid; its view depth and decoded splat then\nfn covers(cluster: Cluster, t: u32, s: ptr<function, Splat>, g: ptr<function, vec4u>) -> bool {\n if (!decode(cluster, t, s, g)) {\n return false;\n }\n shade(s);\n let viewPos = (uniforms.view * vec4f((*s).position, 1.0)).xyz;\n let depth = -viewPos.z;\n if ((*s).opacity < SOLID || depth < uniforms.near || depth > uniforms.far) {\n return false;\n }\n let clip = uniforms.proj * vec4f(viewPos, 1.0);\n let centre = (clip.xy / clip.w * 0.5 + 0.5) * uniforms.viewport;\n let cov = covariance(*g, (*s).scale, viewPos);\n let d = probe.pixel - centre;\n let power = (cov.z * d.x * d.x - 2.0 * cov.y * d.x * d.y + cov.x * d.y * d.y) / (cov.x * cov.z - cov.y * cov.y);\n (*s).depth = depth;\n return (*s).opacity * exp(-0.5 * power) >= SOLID;\n}\n\n// the cluster of visible index under the pixel, or none\nfn candidate(index: u32, cluster: ptr<function, Cluster>) -> bool {\n *cluster = clusters[work[WORK_LIST + index]];\n let page = pages[(*cluster).page];\n return under(page.origin + (*cluster).boxMin, page.origin + (*cluster).boxMax);\n}\n\n@compute @workgroup_size(256)\nfn nearest(@builtin(workgroup_id) wid: vec3u, @builtin(local_invocation_index) t: u32) {\n for (var index = wid.x; index < work[WORK_VISIBLE]; index += PICK_GROUPS) {\n var cluster: Cluster;\n var s: Splat;\n var g: vec4u;\n if (candidate(index, &cluster) && t < cluster.count && covers(cluster, t, &s, &g)) {\n atomicMin(&hit[0], bitcast<u32>(s.depth));\n }\n }\n}\n\n// the splat at the nearest depth writes its layer and its thinnest axis, toward the camera\n@compute @workgroup_size(256)\nfn surface(@builtin(workgroup_id) wid: vec3u, @builtin(local_invocation_index) t: u32) {\n let nearest = atomicLoad(&hit[0]);\n for (var index = wid.x; index < work[WORK_VISIBLE]; index += PICK_GROUPS) {\n var cluster: Cluster;\n var s: Splat;\n var g: vec4u;\n if (candidate(index, &cluster) && t < cluster.count && covers(cluster, t, &s, &g) &&\n bitcast<u32>(s.depth) == nearest) {\n let r = rotate(rotation(g));\n let k = select(select(2u, 1u, s.scale.y <= s.scale.z), 0u,\n s.scale.x <= s.scale.y && s.scale.x <= s.scale.z);\n let normal = r[k] * sign(dot(r[k], uniforms.camera - s.position) + 1e-20);\n atomicStore(&hit[1], pages[cluster.page].layer);\n atomicStore(&hit[2], bitcast<u32>(normal.x));\n atomicStore(&hit[3], bitcast<u32>(normal.y));\n atomicStore(&hit[4], bitcast<u32>(normal.z));\n }\n }\n}\n", Ne = 256, Pe = 80, Fe = 4294967295, Ie = new Uint32Array([
|
|
965
|
+
Fe,
|
|
966
|
+
0,
|
|
967
|
+
0,
|
|
968
|
+
0,
|
|
969
|
+
0
|
|
970
|
+
]), Le = class {
|
|
971
|
+
#e;
|
|
972
|
+
#t;
|
|
973
|
+
#n;
|
|
974
|
+
#r;
|
|
975
|
+
#i;
|
|
976
|
+
#a = [];
|
|
977
|
+
#o = /* @__PURE__ */ new Float32Array(16);
|
|
978
|
+
#s = /* @__PURE__ */ new Float32Array(24);
|
|
979
|
+
#c = new Float32Array(Pe / 4);
|
|
980
|
+
#l;
|
|
981
|
+
#u;
|
|
982
|
+
#d;
|
|
983
|
+
constructor(e, t, n) {
|
|
984
|
+
this.#e = e, this.#t = t, this.#n = x(e, "pick", GPUShaderStage.COMPUTE, [
|
|
985
|
+
"uniform",
|
|
986
|
+
"uniform",
|
|
987
|
+
"read-only-storage",
|
|
988
|
+
"read-only-storage",
|
|
989
|
+
"read-only-storage",
|
|
990
|
+
"read-only-storage",
|
|
991
|
+
"read-only-storage",
|
|
992
|
+
"uniform",
|
|
993
|
+
"storage"
|
|
994
|
+
]), this.#r = e.createPipelineLayout({ bindGroupLayouts: [this.#n, t.masks.layout] }), this.#l = e.createBuffer({
|
|
995
|
+
label: "pick probe",
|
|
996
|
+
size: Pe,
|
|
997
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
998
|
+
}), this.#u = e.createBuffer({
|
|
999
|
+
label: "pick",
|
|
1000
|
+
size: 20,
|
|
1001
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST
|
|
1002
|
+
});
|
|
1003
|
+
let { uniforms: r, plugins: i, work: a } = n, o = [
|
|
1004
|
+
r,
|
|
1005
|
+
i,
|
|
1006
|
+
t.geometry,
|
|
1007
|
+
t.colour,
|
|
1008
|
+
t.pages,
|
|
1009
|
+
t.clusters
|
|
1010
|
+
];
|
|
1011
|
+
this.#d = S(e, "pick", this.#n, [
|
|
1012
|
+
...o,
|
|
1013
|
+
a,
|
|
1014
|
+
this.#l,
|
|
1015
|
+
this.#u
|
|
1016
|
+
]);
|
|
1017
|
+
}
|
|
1018
|
+
hooks(e) {
|
|
1019
|
+
this.#a = e, this.#i = void 0;
|
|
1020
|
+
}
|
|
1021
|
+
run(e, t, n) {
|
|
1022
|
+
let r = this.#e, i = this.#t, a = r.createBuffer({
|
|
1023
|
+
label: "pick readback",
|
|
1024
|
+
size: 20,
|
|
1025
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
1026
|
+
}), o = this.#c, s = n.height - t;
|
|
1027
|
+
o.set([e, s], 0), o.set(this.#f(e, s, n), 4), r.queue.writeBuffer(this.#l, 0, o), r.queue.writeBuffer(this.#u, 0, Ie);
|
|
1028
|
+
let c = this.#i ??= this.#p(), l = r.createCommandEncoder({ label: "pick" }), u = l.beginComputePass({ label: "pick" });
|
|
1029
|
+
return u.setBindGroup(0, this.#d), u.setBindGroup(1, i.masks.group), u.setPipeline(c.nearest), u.dispatchWorkgroups(Ne), u.setPipeline(c.surface), u.dispatchWorkgroups(Ne), u.end(), l.copyBufferToBuffer(this.#u, 0, a, 0, 20), r.queue.submit([l.finish()]), a.mapAsync(GPUMapMode.READ).then(() => {
|
|
1030
|
+
let e = new Uint32Array(a.getMappedRange());
|
|
1031
|
+
if (e[0] === Fe) return null;
|
|
1032
|
+
let t = new Float32Array(e.buffer), n = [
|
|
1033
|
+
t[2],
|
|
1034
|
+
t[3],
|
|
1035
|
+
t[4]
|
|
1036
|
+
];
|
|
1037
|
+
return {
|
|
1038
|
+
depth: t[0],
|
|
1039
|
+
layer: e[1],
|
|
1040
|
+
normal: n
|
|
1041
|
+
};
|
|
1042
|
+
}, () => null).finally(() => a.destroy());
|
|
1043
|
+
}
|
|
1044
|
+
destroy() {
|
|
1045
|
+
this.#l.destroy(), this.#u.destroy();
|
|
1046
|
+
}
|
|
1047
|
+
#f(e, t, n) {
|
|
1048
|
+
let r = (e, t) => 2 * e / t - 1, i = N(this.#o, n.proj, n.view), a = [
|
|
1049
|
+
r(e - .5, n.width),
|
|
1050
|
+
r(e + .5, n.width),
|
|
1051
|
+
r(t - .5, n.height),
|
|
1052
|
+
r(t + .5, n.height)
|
|
1053
|
+
];
|
|
1054
|
+
return Ae(this.#s, i, a), this.#s.subarray(0, 16);
|
|
1055
|
+
}
|
|
1056
|
+
#p() {
|
|
1057
|
+
let e = we([
|
|
1058
|
+
P,
|
|
1059
|
+
ue,
|
|
1060
|
+
Se,
|
|
1061
|
+
Me
|
|
1062
|
+
], this.#a), t = this.#e.createShaderModule({
|
|
1063
|
+
label: "pick",
|
|
1064
|
+
code: e
|
|
1065
|
+
}), n = (e) => this.#e.createComputePipeline({
|
|
1066
|
+
label: `pick ${e}`,
|
|
1067
|
+
layout: this.#r,
|
|
1068
|
+
compute: {
|
|
1069
|
+
module: t,
|
|
1070
|
+
entryPoint: e
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
return {
|
|
1074
|
+
nearest: n("nearest"),
|
|
1075
|
+
surface: n("surface")
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
}, Re = "// sorted splats as screen quads, premultiplied over what lies behind them\n\n// word offsets of the sorted keys and values in the sort buffer\nstruct Sorted {\n keys: u32,\n values: u32,\n}\n\nstruct Corner {\n @builtin(position) position: vec4f,\n // offset from the centre in sigmas\n @location(0) uv: vec2f,\n @location(1) colour: vec4f,\n}\n\n@group(0) @binding(0) var<uniform> frame: FrameUniforms;\n@group(0) @binding(1) var<storage, read> projected: array<Projected>;\n@group(0) @binding(2) var<storage, read> sort: array<u32>;\n@group(0) @binding(3) var<uniform> sorted: Sorted;\n\nfn corner(v: u32, i: u32) -> Corner {\n let p = projected[sort[sorted.values + i]];\n let major = unpack2x16float(p.axes.x);\n let minor = unpack2x16float(p.axes.y);\n let colour = vec4f(unpack2x16float(p.colour.x), unpack2x16float(p.colour.y));\n let r = reach(colour.a);\n let uv = vec2f(f32(v & 1u), f32(v >> 1u)) * 2.0 - 1.0;\n let pixel = p.centre + (major * uv.x + minor * uv.y) * r;\n return Corner(vec4f(pixel / frame.viewport * 2.0 - 1.0, 0.0, 1.0), uv * r, colour);\n}\n\nfn alpha(uv: vec2f, opacity: f32) -> f32 {\n return opacity * exp(-0.5 * dot(uv, uv));\n}\n\n@vertex\nfn vsColour(@builtin(vertex_index) v: u32, @builtin(instance_index) i: u32) -> Corner {\n return corner(v, i);\n}\n\n@vertex\nfn vsDepth(@builtin(vertex_index) v: u32, @builtin(instance_index) i: u32) -> Corner {\n var c = corner(v, i);\n // inverse of the key: the span from near to far in log depth\n c.position.z = 1.0 - f32(sort[sorted.keys + i]) / f32((1u << KEY_BITS) - 1u);\n return c;\n}\n\n@fragment\nfn fs(c: Corner) -> @location(0) vec4f {\n let a = alpha(c.uv, c.colour.a);\n if (a < 1.0 / 255.0) {\n discard;\n }\n return vec4f(c.colour.rgb * a, a);\n}\n", ze = "rgb10a2unorm", Be = "depth16unorm", Ve = {
|
|
1079
|
+
srcFactor: "one",
|
|
1080
|
+
dstFactor: "one-minus-src-alpha"
|
|
1081
|
+
}, He = class {
|
|
1082
|
+
#e;
|
|
1083
|
+
#t;
|
|
1084
|
+
#n;
|
|
1085
|
+
#r;
|
|
1086
|
+
#i;
|
|
1087
|
+
constructor(e, t, n) {
|
|
1088
|
+
this.#e = t.work, this.#t = e.createBuffer({
|
|
1089
|
+
label: "raster sorted",
|
|
1090
|
+
size: 16,
|
|
1091
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
1092
|
+
});
|
|
1093
|
+
let r = new Uint32Array([
|
|
1094
|
+
n.keys / 4,
|
|
1095
|
+
n.values / 4,
|
|
1096
|
+
0,
|
|
1097
|
+
0
|
|
1098
|
+
]);
|
|
1099
|
+
e.queue.writeBuffer(this.#t, 0, r);
|
|
1100
|
+
let i = x(e, "raster", GPUShaderStage.VERTEX, [
|
|
1101
|
+
"uniform",
|
|
1102
|
+
"read-only-storage",
|
|
1103
|
+
"read-only-storage",
|
|
1104
|
+
"uniform"
|
|
1105
|
+
]);
|
|
1106
|
+
this.#i = S(e, "raster", i, [
|
|
1107
|
+
t.uniforms,
|
|
1108
|
+
t.projected,
|
|
1109
|
+
t.sort,
|
|
1110
|
+
this.#t
|
|
1111
|
+
]);
|
|
1112
|
+
let a = e.createShaderModule({
|
|
1113
|
+
label: "raster",
|
|
1114
|
+
code: P + Re
|
|
1115
|
+
}), o = e.createPipelineLayout({ bindGroupLayouts: [i] }), s = (t, n) => e.createRenderPipeline({
|
|
1116
|
+
label: `raster ${t}`,
|
|
1117
|
+
layout: o,
|
|
1118
|
+
vertex: {
|
|
1119
|
+
module: a,
|
|
1120
|
+
entryPoint: `vs${t}`
|
|
1121
|
+
},
|
|
1122
|
+
fragment: {
|
|
1123
|
+
module: a,
|
|
1124
|
+
entryPoint: "fs",
|
|
1125
|
+
targets: [{
|
|
1126
|
+
format: ze,
|
|
1127
|
+
blend: {
|
|
1128
|
+
color: Ve,
|
|
1129
|
+
alpha: Ve
|
|
1130
|
+
}
|
|
1131
|
+
}]
|
|
1132
|
+
},
|
|
1133
|
+
primitive: { topology: "triangle-strip" },
|
|
1134
|
+
depthStencil: n
|
|
1135
|
+
});
|
|
1136
|
+
this.#n = s("Colour"), this.#r = s("Depth", {
|
|
1137
|
+
format: Be,
|
|
1138
|
+
depthWriteEnabled: !0,
|
|
1139
|
+
depthCompare: "always"
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
encode(e, t, n, r, i) {
|
|
1143
|
+
let a = e.beginRenderPass({
|
|
1144
|
+
label: "raster",
|
|
1145
|
+
colorAttachments: [{
|
|
1146
|
+
view: t,
|
|
1147
|
+
loadOp: "clear",
|
|
1148
|
+
clearValue: [...r, 1],
|
|
1149
|
+
storeOp: "store"
|
|
1150
|
+
}],
|
|
1151
|
+
depthStencilAttachment: n ? {
|
|
1152
|
+
view: n,
|
|
1153
|
+
depthClearValue: 1,
|
|
1154
|
+
depthLoadOp: "clear",
|
|
1155
|
+
depthStoreOp: "store"
|
|
1156
|
+
} : void 0,
|
|
1157
|
+
timestampWrites: i
|
|
1158
|
+
});
|
|
1159
|
+
a.setPipeline(n ? this.#r : this.#n), a.setBindGroup(0, this.#i), a.drawIndirect(this.#e, f.drawArgs * 4), a.end();
|
|
1160
|
+
}
|
|
1161
|
+
destroy() {
|
|
1162
|
+
this.#t.destroy();
|
|
1163
|
+
}
|
|
1164
|
+
}, Ue = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan, a stable scatter; no spin-waits\n\nconst THREADS: u32 = 128u;\nconst ITEMS: u32 = 8u;\nconst BLOCK: u32 = 1024u;\n// blocks per scan chunk\nconst CHUNK: u32 = 64u;\nconst DIGITS: u32 = 256u;\n\nstruct SortParams {\n shift: u32,\n // word offsets of the keys read and written; their values follow capacity words later\n src: u32,\n dst: u32,\n capacity: u32,\n // word offsets in the work buffer\n projected: u32,\n drawArgs: u32,\n}\n\nstruct SortState {\n count: u32,\n blocks: u32,\n chunks: u32,\n}\n\n@group(0) @binding(0) var<uniform> params: SortParams;\n@group(0) @binding(1) var<storage, read_write> data: array<u32>;\n// block-major: count, then exclusive global offset, of digit d in block b at b DIGITS + d\n@group(0) @binding(2) var<storage, read_write> hist: array<u32>;\n// chunk-major sums of hist, then their exclusive global offsets\n@group(0) @binding(3) var<storage, read_write> sums: array<u32>;\n@group(0) @binding(4) var<storage, read> state: SortState;\n@group(0) @binding(5) var<storage, read_write> stateOut: SortState;\n@group(0) @binding(6) var<storage, read_write> work: array<u32>;\n\nvar<workgroup> bins: array<atomic<u32>, DIGITS>;\nvar<workgroup> totals: array<u32, DIGITS>;\nvar<workgroup> bitValues: atomic<u32>;\nvar<workgroup> activeBits: u32;\nvar<workgroup> sk: array<u32, BLOCK>;\nvar<workgroup> sv: array<u32, BLOCK>;\n// three 10-bit counts; the fourth follows from the number of items\nvar<workgroup> counts: array<u32, THREADS * 2u>;\nvar<workgroup> tail: u32;\nvar<workgroup> starts: array<u32, DIGITS>;\nvar<workgroup> offsets: array<u32, DIGITS>;\n\nfn unpack(packed: u32, count: u32) -> vec4u {\n let a = packed & 1023u;\n let b = (packed >> 10u) & 1023u;\n let c = (packed >> 20u) & 1023u;\n return vec4u(a, b, c, count - a - b - c);\n}\n\nfn digit(key: u32) -> u32 {\n return (key >> params.shift) & 0xffu;\n}\n\n@compute @workgroup_size(1)\nfn prepare() {\n let count = min(work[params.projected], params.capacity);\n let blocks = (count + BLOCK - 1u) / BLOCK;\n work[params.drawArgs] = 4u;\n work[params.drawArgs + 1u] = count;\n work[params.drawArgs + 2u] = 0u;\n work[params.drawArgs + 3u] = 0u;\n stateOut = SortState(count, blocks, (blocks + CHUNK - 1u) / CHUNK);\n}\n\n@compute @workgroup_size(THREADS)\nfn histogram(\n @builtin(workgroup_id) wid: vec3u,\n @builtin(num_workgroups) groups: vec3u,\n @builtin(local_invocation_index) t: u32\n) {\n for (var block = wid.y * groups.x + wid.x; block < state.blocks; block += groups.x * groups.y) {\n let head = block * BLOCK;\n for (var k = 0u; k < ITEMS; k++) {\n let i = head + k * THREADS + t;\n if (i < state.count) {\n atomicAdd(&bins[digit(data[params.src + i])], 1u);\n }\n }\n workgroupBarrier();\n for (var d = t; d < DIGITS; d += THREADS) {\n hist[block * DIGITS + d] = atomicExchange(&bins[d], 0u);\n }\n workgroupBarrier();\n }\n}\n\n@compute @workgroup_size(DIGITS)\nfn reduce(@builtin(workgroup_id) wid: vec3u, @builtin(local_invocation_index) t: u32) {\n let end = min((wid.x + 1u) * CHUNK, state.blocks);\n var sum = 0u;\n for (var b = wid.x * CHUNK; b < end; b++) {\n sum += hist[b * DIGITS + t];\n }\n sums[wid.x * DIGITS + t] = sum;\n}\n\n@compute @workgroup_size(DIGITS)\nfn top(@builtin(local_invocation_index) t: u32) {\n var run = 0u;\n for (var c = 0u; c < state.chunks; c++) {\n let x = sums[c * DIGITS + t];\n sums[c * DIGITS + t] = run;\n run += x;\n }\n totals[t] = run;\n // a bit varies only when both zero and one occur in nonempty digits\n if (run > 0u) {\n atomicOr(&bitValues, t | ((255u ^ t) << 8u));\n }\n workgroupBarrier();\n if (t == 0u) {\n let values = atomicLoad(&bitValues);\n sums[arrayLength(&sums) - 1u] = values & (values >> 8u);\n }\n for (var o = 1u; o < DIGITS; o *= 2u) {\n var x = 0u;\n if (t >= o) {\n x = totals[t - o];\n }\n workgroupBarrier();\n totals[t] += x;\n workgroupBarrier();\n }\n let base = totals[t] - run;\n for (var c = 0u; c < state.chunks; c++) {\n sums[c * DIGITS + t] += base;\n }\n}\n\n@compute @workgroup_size(DIGITS)\nfn down(@builtin(workgroup_id) wid: vec3u, @builtin(local_invocation_index) t: u32) {\n let end = min((wid.x + 1u) * CHUNK, state.blocks);\n var run = sums[wid.x * DIGITS + t];\n for (var b = wid.x * CHUNK; b < end; b++) {\n let x = hist[b * DIGITS + t];\n hist[b * DIGITS + t] = run;\n run += x;\n }\n}\n\n@compute @workgroup_size(THREADS)\nfn scatter(\n @builtin(workgroup_id) wid: vec3u,\n @builtin(num_workgroups) groups: vec3u,\n @builtin(local_invocation_index) t: u32\n) {\n let first = wid.y * groups.x + wid.x;\n if (first >= state.blocks) {\n return;\n }\n if (t == 0u) {\n activeBits = sums[arrayLength(&sums) - 1u];\n }\n let bits = workgroupUniformLoad(&activeBits);\n for (var block = first; block < state.blocks; block += groups.x * groups.y) {\n let head = block * BLOCK;\n let valid = min(BLOCK, state.count - head);\n // padding has digit 255 at every shift, so it sorts behind the valid keys and is never written\n for (var k = 0u; k < ITEMS; k++) {\n let i = k * THREADS + t;\n var key = 0xffffffffu;\n var value = 0u;\n if (i < valid) {\n key = data[params.src + head + i];\n value = data[params.src + params.capacity + head + i];\n }\n sk[i] = key;\n sv[i] = value;\n }\n for (var d = t; d < DIGITS; d += THREADS) {\n offsets[d] = hist[block * DIGITS + d];\n }\n workgroupBarrier();\n\n // stable local sort by the digit, two bits a split; thread t owns positions t ITEMS + k\n for (var bit = 0u; bit < 8u; bit += 2u) {\n if ((bits & (3u << bit)) == 0u) {\n continue;\n }\n var keys: array<u32, ITEMS>;\n var values: array<u32, ITEMS>;\n var before: array<u32, ITEMS>;\n var mine = vec4u(0u);\n for (var k = 0u; k < ITEMS; k++) {\n keys[k] = sk[t * ITEMS + k];\n values[k] = sv[t * ITEMS + k];\n let b = (keys[k] >> (params.shift + bit)) & 3u;\n before[k] = mine[b];\n mine[b] += 1u;\n }\n counts[t] = mine.x | (mine.y << 10u) | (mine.z << 20u);\n if (t == THREADS - 1u) {\n tail = counts[t];\n }\n workgroupBarrier();\n // separate reads and writes need only one barrier per scan step\n var source = 0u;\n for (var o = 1u; o < THREADS; o *= 2u) {\n var x = counts[source + t];\n if (t >= o) {\n x += counts[source + t - o];\n }\n let dest = source ^ THREADS;\n counts[dest + t] = x;\n workgroupBarrier();\n source = dest;\n }\n // prefixes stop at 1016 items, so no count carries into its neighbour\n let total = unpack(counts[source + THREADS - 2u], BLOCK - ITEMS) + unpack(tail, ITEMS);\n var prior = vec4u(0u);\n if (t > 0u) {\n prior = unpack(counts[source + t - 1u], t * ITEMS);\n }\n let base = vec4u(0u, total.x, total.x + total.y, total.x + total.y + total.z);\n for (var k = 0u; k < ITEMS; k++) {\n let b = (keys[k] >> (params.shift + bit)) & 3u;\n let p = base[b] + prior[b] + before[k];\n sk[p] = keys[k];\n sv[p] = values[k];\n }\n workgroupBarrier();\n }\n\n for (var k = 0u; k < ITEMS; k++) {\n let i = t * ITEMS + k;\n let d = digit(sk[i]);\n if (i == 0u || digit(sk[i - 1u]) != d) {\n starts[d] = i;\n }\n }\n workgroupBarrier();\n for (var k = 0u; k < ITEMS; k++) {\n let i = k * THREADS + t;\n if (i < valid) {\n let d = digit(sk[i]);\n let slot = offsets[d] + i - starts[d];\n data[params.dst + slot] = sk[i];\n data[params.dst + params.capacity + slot] = sv[i];\n }\n }\n workgroupBarrier();\n }\n}\n", We = 1024, Ge = 64, Ke = 256, F = 3, I = 256, qe = 32, Je = class {
|
|
1165
|
+
keys;
|
|
1166
|
+
values;
|
|
1167
|
+
bytes;
|
|
1168
|
+
#e;
|
|
1169
|
+
#t;
|
|
1170
|
+
#n;
|
|
1171
|
+
#r;
|
|
1172
|
+
#i;
|
|
1173
|
+
#a;
|
|
1174
|
+
constructor(e, t) {
|
|
1175
|
+
let { capacity: n } = t;
|
|
1176
|
+
this.keys = n * 8, this.values = n * 12;
|
|
1177
|
+
let r = Math.max(1, Math.ceil(n / We));
|
|
1178
|
+
this.#a = r;
|
|
1179
|
+
let i = Math.ceil(r / Ge), a = (t, n, r) => e.createBuffer({
|
|
1180
|
+
label: t,
|
|
1181
|
+
size: n,
|
|
1182
|
+
usage: r
|
|
1183
|
+
}), o = GPUBufferUsage.STORAGE, s = a("sort params", F * I, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST), c = a("sort histograms", r * Ke * 4, o), l = a("sort chunk sums", (i * Ke + 1) * 4, o), u = a("sort state", 12, o);
|
|
1184
|
+
this.#e = [
|
|
1185
|
+
s,
|
|
1186
|
+
c,
|
|
1187
|
+
l,
|
|
1188
|
+
u
|
|
1189
|
+
], this.bytes = this.#e.reduce((e, t) => e + t.size, 0);
|
|
1190
|
+
let d = new Uint32Array(F * I / 4);
|
|
1191
|
+
for (let e = 0; e < F; e++) {
|
|
1192
|
+
let [t, r] = e % 2 ? [2 * n, 0] : [0, 2 * n];
|
|
1193
|
+
d.set([
|
|
1194
|
+
8 * e,
|
|
1195
|
+
t,
|
|
1196
|
+
r,
|
|
1197
|
+
n,
|
|
1198
|
+
f.projected,
|
|
1199
|
+
f.drawArgs
|
|
1200
|
+
], e * I / 4);
|
|
1201
|
+
}
|
|
1202
|
+
e.queue.writeBuffer(s, 0, d);
|
|
1203
|
+
let p = (e, t) => ({
|
|
1204
|
+
binding: e,
|
|
1205
|
+
visibility: GPUShaderStage.COMPUTE,
|
|
1206
|
+
buffer: { type: t }
|
|
1207
|
+
}), m = x(e, "sort", GPUShaderStage.COMPUTE, [
|
|
1208
|
+
"uniform",
|
|
1209
|
+
"storage",
|
|
1210
|
+
"storage",
|
|
1211
|
+
"storage",
|
|
1212
|
+
"read-only-storage"
|
|
1213
|
+
]), h = e.createBindGroupLayout({
|
|
1214
|
+
label: "sort prepare",
|
|
1215
|
+
entries: [
|
|
1216
|
+
p(0, "uniform"),
|
|
1217
|
+
p(5, "storage"),
|
|
1218
|
+
p(6, "storage")
|
|
1219
|
+
]
|
|
1220
|
+
}), g = e.createShaderModule({
|
|
1221
|
+
label: "sort",
|
|
1222
|
+
code: P + Ue
|
|
1223
|
+
}), _ = (t, n) => e.createComputePipeline({
|
|
1224
|
+
label: `sort ${t}`,
|
|
1225
|
+
layout: e.createPipelineLayout({ bindGroupLayouts: [n] }),
|
|
1226
|
+
compute: {
|
|
1227
|
+
module: g,
|
|
1228
|
+
entryPoint: t
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
this.#t = _("prepare", h), this.#n = [
|
|
1232
|
+
"histogram",
|
|
1233
|
+
"reduce",
|
|
1234
|
+
"top",
|
|
1235
|
+
"down",
|
|
1236
|
+
"scatter"
|
|
1237
|
+
].map((e) => _(e, m));
|
|
1238
|
+
let v = (e) => ({
|
|
1239
|
+
buffer: s,
|
|
1240
|
+
offset: e * I,
|
|
1241
|
+
size: qe
|
|
1242
|
+
});
|
|
1243
|
+
this.#r = e.createBindGroup({
|
|
1244
|
+
label: "sort prepare",
|
|
1245
|
+
layout: h,
|
|
1246
|
+
entries: [
|
|
1247
|
+
{
|
|
1248
|
+
binding: 0,
|
|
1249
|
+
resource: v(0)
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
binding: 5,
|
|
1253
|
+
resource: { buffer: u }
|
|
1254
|
+
},
|
|
1255
|
+
{
|
|
1256
|
+
binding: 6,
|
|
1257
|
+
resource: { buffer: t.work }
|
|
1258
|
+
}
|
|
1259
|
+
]
|
|
1260
|
+
}), this.#i = Array.from({ length: F }, (n, r) => e.createBindGroup({
|
|
1261
|
+
label: `sort pass ${r}`,
|
|
1262
|
+
layout: m,
|
|
1263
|
+
entries: [
|
|
1264
|
+
{
|
|
1265
|
+
binding: 0,
|
|
1266
|
+
resource: v(r)
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
binding: 1,
|
|
1270
|
+
resource: { buffer: t.sort }
|
|
1271
|
+
},
|
|
1272
|
+
{
|
|
1273
|
+
binding: 2,
|
|
1274
|
+
resource: { buffer: c }
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
binding: 3,
|
|
1278
|
+
resource: { buffer: l }
|
|
1279
|
+
},
|
|
1280
|
+
{
|
|
1281
|
+
binding: 4,
|
|
1282
|
+
resource: { buffer: u }
|
|
1283
|
+
}
|
|
1284
|
+
]
|
|
1285
|
+
}));
|
|
1286
|
+
}
|
|
1287
|
+
encode(e, t, n, r) {
|
|
1288
|
+
let [i, a, o, s, c] = this.#n, l = Math.max(1, Math.min(this.#a, Math.ceil(t / We))), u = Math.max(l / 16, (n || t) / We), d = m(Math.min(Math.ceil(l / 4), Math.ceil(u))), f = Math.ceil(l / Ge), p = e.beginComputePass({
|
|
1289
|
+
label: "sort",
|
|
1290
|
+
timestampWrites: r
|
|
1291
|
+
});
|
|
1292
|
+
p.setPipeline(this.#t), p.setBindGroup(0, this.#r), p.dispatchWorkgroups(1);
|
|
1293
|
+
for (let e of this.#i) p.setBindGroup(0, e), p.setPipeline(i), p.dispatchWorkgroups(...d), p.setPipeline(a), p.dispatchWorkgroups(f), p.setPipeline(o), p.dispatchWorkgroups(1), p.setPipeline(s), p.dispatchWorkgroups(f), p.setPipeline(c), p.dispatchWorkgroups(...d);
|
|
1294
|
+
p.end();
|
|
1295
|
+
}
|
|
1296
|
+
destroy() {
|
|
1297
|
+
for (let e of this.#e) e.destroy();
|
|
1298
|
+
}
|
|
1299
|
+
}, Ye = class {
|
|
1300
|
+
ms = {};
|
|
1301
|
+
#e;
|
|
1302
|
+
#t;
|
|
1303
|
+
#n;
|
|
1304
|
+
#r;
|
|
1305
|
+
#i = !1;
|
|
1306
|
+
#a = !1;
|
|
1307
|
+
constructor(e, t, n) {
|
|
1308
|
+
if (this.#e = n, !t) return;
|
|
1309
|
+
let r = n.length * 2;
|
|
1310
|
+
this.#t = e.createQuerySet({
|
|
1311
|
+
label: "timing",
|
|
1312
|
+
type: "timestamp",
|
|
1313
|
+
count: r
|
|
1314
|
+
}), this.#n = e.createBuffer({
|
|
1315
|
+
label: "timing resolved",
|
|
1316
|
+
size: r * 8,
|
|
1317
|
+
usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC
|
|
1318
|
+
}), this.#r = e.createBuffer({
|
|
1319
|
+
label: "timing readback",
|
|
1320
|
+
size: r * 8,
|
|
1321
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
writes(e) {
|
|
1325
|
+
let t = this.#t;
|
|
1326
|
+
if (!t || this.#i) return;
|
|
1327
|
+
let n = this.#e.indexOf(e);
|
|
1328
|
+
return {
|
|
1329
|
+
querySet: t,
|
|
1330
|
+
beginningOfPassWriteIndex: 2 * n,
|
|
1331
|
+
endOfPassWriteIndex: 2 * n + 1
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
resolve(e) {
|
|
1335
|
+
!this.#t || !this.#n || !this.#r || this.#i || (e.resolveQuerySet(this.#t, 0, this.#e.length * 2, this.#n, 0), e.copyBufferToBuffer(this.#n, 0, this.#r, 0, this.#r.size), this.#a = !0);
|
|
1336
|
+
}
|
|
1337
|
+
read() {
|
|
1338
|
+
let e = this.#r;
|
|
1339
|
+
!e || this.#i || !this.#a || (this.#i = !0, this.#a = !1, e.mapAsync(GPUMapMode.READ).then(() => {
|
|
1340
|
+
let t = new BigUint64Array(e.getMappedRange());
|
|
1341
|
+
this.#e.forEach((e, n) => {
|
|
1342
|
+
let [r, i] = [t[2 * n], t[2 * n + 1]];
|
|
1343
|
+
this.ms[e] = i > r ? Number(i - r) / 1e6 : 0;
|
|
1344
|
+
}), e.unmap();
|
|
1345
|
+
}).catch(() => {}).finally(() => this.#i = !1));
|
|
1346
|
+
}
|
|
1347
|
+
destroy() {
|
|
1348
|
+
this.#t?.destroy(), this.#n?.destroy(), this.#r?.destroy();
|
|
1349
|
+
}
|
|
1350
|
+
}, Xe = [
|
|
1351
|
+
"cull",
|
|
1352
|
+
"project",
|
|
1353
|
+
"sort",
|
|
1354
|
+
"raster",
|
|
1355
|
+
"heights",
|
|
1356
|
+
"post"
|
|
1357
|
+
], L = {
|
|
1358
|
+
view: 0,
|
|
1359
|
+
proj: 16,
|
|
1360
|
+
viewProj: 32,
|
|
1361
|
+
planes: 48,
|
|
1362
|
+
camera: 72,
|
|
1363
|
+
time: 75,
|
|
1364
|
+
viewport: 76,
|
|
1365
|
+
focal: 78,
|
|
1366
|
+
near: 80,
|
|
1367
|
+
far: 81,
|
|
1368
|
+
lowPass: 82,
|
|
1369
|
+
clusters: 83
|
|
1370
|
+
}, Ze = class {
|
|
1371
|
+
#e;
|
|
1372
|
+
#t;
|
|
1373
|
+
#n;
|
|
1374
|
+
#r;
|
|
1375
|
+
#i;
|
|
1376
|
+
#a;
|
|
1377
|
+
#o;
|
|
1378
|
+
#s;
|
|
1379
|
+
#c;
|
|
1380
|
+
#l;
|
|
1381
|
+
#u;
|
|
1382
|
+
#d;
|
|
1383
|
+
#f;
|
|
1384
|
+
#p;
|
|
1385
|
+
#m = /* @__PURE__ */ new Float32Array(84);
|
|
1386
|
+
#h = new Uint32Array(this.#m.buffer);
|
|
1387
|
+
#g = /* @__PURE__ */ new Float32Array(16);
|
|
1388
|
+
#_ = /* @__PURE__ */ new Float32Array(64);
|
|
1389
|
+
#v = [];
|
|
1390
|
+
#y = [];
|
|
1391
|
+
#b = {};
|
|
1392
|
+
#x = /* @__PURE__ */ new WeakMap();
|
|
1393
|
+
#S;
|
|
1394
|
+
#C;
|
|
1395
|
+
#w;
|
|
1396
|
+
#T = !1;
|
|
1397
|
+
#E = 0;
|
|
1398
|
+
#D = 0;
|
|
1399
|
+
constructor(e, t, n, r) {
|
|
1400
|
+
let { device: i } = e;
|
|
1401
|
+
this.#e = i, this.#t = t, this.#n = e.format, this.#r = n, this.#i = b(i, r, n.slots), this.#a = new le(i, n, this.#i), this.#o = new Ce(i, n, this.#i), this.#s = new Je(i, this.#i), this.#c = new He(i, this.#i, this.#s), this.#u = new ge(i, n), this.#d = new Le(i, n, this.#i), this.#f = new Oe(i, e.format, this.#i.uniforms), this.#p = new Ye(i, e.timestamps, Xe), this.#w = i.createBuffer({
|
|
1402
|
+
label: "counts readback",
|
|
1403
|
+
size: (f.projected + 1) * 4,
|
|
1404
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
1405
|
+
}), this.#S = Math.max(1, t.canvas.width), this.#C = Math.max(1, t.canvas.height);
|
|
1406
|
+
}
|
|
1407
|
+
shade(e) {
|
|
1408
|
+
if (this.#v.reduce((e, { shade: t }) => e + t.uniforms, 0) + e.uniforms > 16) throw Error("Shade hooks may use 16 uniform slots in all.");
|
|
1409
|
+
let t = {
|
|
1410
|
+
shade: e,
|
|
1411
|
+
slot: 0
|
|
1412
|
+
};
|
|
1413
|
+
return this.#v.push(t), this.#O(), () => {
|
|
1414
|
+
let e = this.#v.indexOf(t);
|
|
1415
|
+
e < 0 || (this.#v.splice(e, 1), this.#O());
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
post(e) {
|
|
1419
|
+
let t = {
|
|
1420
|
+
post: e,
|
|
1421
|
+
pass: e.setup(this.#e, this.#n)
|
|
1422
|
+
}, n = e.order ?? 0, r = this.#y.findIndex(({ post: e }) => (e.order ?? 0) > n);
|
|
1423
|
+
return this.#y.splice(r < 0 ? this.#y.length : r, 0, t), () => {
|
|
1424
|
+
let e = this.#y.indexOf(t);
|
|
1425
|
+
e < 0 || (this.#y.splice(e, 1), t.pass.destroy());
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
resize(e, t) {
|
|
1429
|
+
(e !== this.#S || t !== this.#C) && (this.#S = e, this.#C = t, this.#N());
|
|
1430
|
+
}
|
|
1431
|
+
pick(e, t, n) {
|
|
1432
|
+
return this.#d.run(e, t, n);
|
|
1433
|
+
}
|
|
1434
|
+
overlay(e, t) {
|
|
1435
|
+
this.#f.set(e, t);
|
|
1436
|
+
}
|
|
1437
|
+
render(e, t, n, r) {
|
|
1438
|
+
let i = this.#e, a = this.#p, o = this.#y, s = this.#j(this.#A("colour", ze)), c = this.#f.count > 0, l = c || o.some(({ post: e }) => e.depth), u = this.#M("depth", Be, l), d = u ? this.#j(u) : null, p = [this.#M("ping", this.#n, o.length > 1), this.#M("pong", this.#n, o.length > 2)];
|
|
1439
|
+
this.#k(e, t);
|
|
1440
|
+
let m = i.createCommandEncoder({ label: "frame" });
|
|
1441
|
+
m.clearBuffer(this.#i.work, 0, f.list * 4), this.#a.encode(m, a.writes("cull")), this.#o.encode(m, this.#D, a.writes("project")), this.#s.encode(m, this.#r.listed * 256, this.#E, a.writes("sort")), this.#c.encode(m, s, d, n, a.writes("raster"));
|
|
1442
|
+
let h = r.map(({ x: e, y: t, cells: n, resolve: r }, i) => ({
|
|
1443
|
+
resolve: r,
|
|
1444
|
+
read: this.#u.encode(m, e, t, n, i ? void 0 : a.writes("heights"))
|
|
1445
|
+
})), g = a.writes("post");
|
|
1446
|
+
if (g) {
|
|
1447
|
+
let { querySet: e, beginningOfPassWriteIndex: t } = g;
|
|
1448
|
+
m.beginComputePass({ timestampWrites: {
|
|
1449
|
+
querySet: e,
|
|
1450
|
+
beginningOfPassWriteIndex: t
|
|
1451
|
+
} }).end();
|
|
1452
|
+
}
|
|
1453
|
+
let _ = this.#t.getCurrentTexture().createView();
|
|
1454
|
+
if (!o.length) this.#l ??= be(i, this.#n), this.#l.encode(m, [s], _);
|
|
1455
|
+
else {
|
|
1456
|
+
let t = s;
|
|
1457
|
+
o.forEach(({ post: n, pass: r }, i) => {
|
|
1458
|
+
let a = i === o.length - 1 ? _ : this.#j(p[i % 2]);
|
|
1459
|
+
r.run(m, e, t, n.depth ? d : null, a), t = a;
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
if (c && this.#f.encode(m, _, d), g) {
|
|
1463
|
+
let { querySet: e, endOfPassWriteIndex: t } = g;
|
|
1464
|
+
m.beginComputePass({ timestampWrites: {
|
|
1465
|
+
querySet: e,
|
|
1466
|
+
endOfPassWriteIndex: t
|
|
1467
|
+
} }).end();
|
|
1468
|
+
}
|
|
1469
|
+
a.resolve(m);
|
|
1470
|
+
let v = !this.#T;
|
|
1471
|
+
v && m.copyBufferToBuffer(this.#i.work, 0, this.#w, 0, this.#w.size), i.queue.submit([m.finish()]), a.read(), v && this.#P();
|
|
1472
|
+
for (let { resolve: e, read: t } of h) t().then(e);
|
|
1473
|
+
return i.queue.onSubmittedWorkDone();
|
|
1474
|
+
}
|
|
1475
|
+
stats() {
|
|
1476
|
+
let e = { ...this.#p.ms }, t = this.#i.bytes + this.#s.bytes;
|
|
1477
|
+
for (let e of Object.values(this.#b)) e && (t += e.width * e.height * (e.format === "depth16unorm" ? 2 : 4));
|
|
1478
|
+
return {
|
|
1479
|
+
gpuMs: Object.values(e).reduce((e, t) => e + t, 0),
|
|
1480
|
+
passes: e,
|
|
1481
|
+
drawn: this.#E,
|
|
1482
|
+
bytes: t
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
destroy() {
|
|
1486
|
+
for (let { pass: e } of this.#y.splice(0)) e.destroy();
|
|
1487
|
+
this.#N(), this.#i.destroy(), this.#s.destroy(), this.#c.destroy(), this.#d.destroy(), this.#f.destroy(), this.#p.destroy(), this.#w.destroy();
|
|
1488
|
+
}
|
|
1489
|
+
#O() {
|
|
1490
|
+
let e = 0;
|
|
1491
|
+
for (let t of this.#v) t.slot = e, e += t.shade.uniforms;
|
|
1492
|
+
this.#o.hooks(this.#v), this.#d.hooks(this.#v);
|
|
1493
|
+
}
|
|
1494
|
+
#k(e, t) {
|
|
1495
|
+
let n = this.#m, [r, i] = [this.#S, this.#C];
|
|
1496
|
+
n.set(e.view, L.view), n.set(e.proj, L.proj), n.set(N(this.#g, e.proj, e.view), L.viewProj), n.set(t, L.planes), n.set(e.camera.subarray(0, 3), L.camera), n[L.time] = e.time, n.set([r, i], L.viewport), n.set([e.proj[0] * r / 2, e.proj[5] * i / 2], L.focal), n[L.near] = e.near, n[L.far] = e.far, n[L.lowPass] = h, this.#h[L.clusters] = this.#r.listed, this.#e.queue.writeBuffer(this.#i.uniforms, 0, n);
|
|
1497
|
+
for (let { shade: t, slot: n } of this.#v) t.update(e, this.#_.subarray(n * 4, (n + t.uniforms) * 4));
|
|
1498
|
+
this.#v.length && this.#e.queue.writeBuffer(this.#i.plugins, 0, this.#_);
|
|
1499
|
+
}
|
|
1500
|
+
#A(e, t) {
|
|
1501
|
+
let n = this.#b[e];
|
|
1502
|
+
return n || (n = this.#e.createTexture({
|
|
1503
|
+
label: e,
|
|
1504
|
+
size: [this.#S, this.#C],
|
|
1505
|
+
format: t,
|
|
1506
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC
|
|
1507
|
+
}), this.#b[e] = n), n;
|
|
1508
|
+
}
|
|
1509
|
+
#j(e) {
|
|
1510
|
+
let t = this.#x.get(e);
|
|
1511
|
+
return t || this.#x.set(e, t = e.createView()), t;
|
|
1512
|
+
}
|
|
1513
|
+
#M(e, t, n) {
|
|
1514
|
+
if (n) return this.#A(e, t);
|
|
1515
|
+
this.#b[e]?.destroy(), delete this.#b[e];
|
|
1516
|
+
}
|
|
1517
|
+
#N() {
|
|
1518
|
+
for (let e of Object.values(this.#b)) e?.destroy();
|
|
1519
|
+
this.#b = {};
|
|
1520
|
+
}
|
|
1521
|
+
#P() {
|
|
1522
|
+
this.#T = !0;
|
|
1523
|
+
let e = this.#w;
|
|
1524
|
+
e.mapAsync(GPUMapMode.READ).then(() => {
|
|
1525
|
+
let t = new Uint32Array(e.getMappedRange());
|
|
1526
|
+
this.#D = t[f.visible], this.#E = Math.min(t[f.projected], this.#i.capacity), e.unmap();
|
|
1527
|
+
}).catch(() => {}).finally(() => this.#T = !1);
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
//#endregion
|
|
1531
|
+
//#region src/engine/layer.ts
|
|
1532
|
+
async function Qe(e, n) {
|
|
1533
|
+
let i = await r(async (t, n) => e.subarray(t, n), e.length);
|
|
1534
|
+
if (i.length === 0) throw Error("the pack holds no pages");
|
|
1535
|
+
let a = Math.min(...i.map((e) => e.g));
|
|
1536
|
+
return Promise.all(i.filter((e) => e.g === a).map(async (r) => {
|
|
1537
|
+
let i = await t(e.subarray(r.offset, r.offset + r.length)), a = Float64Array.from(r.box, (e, t) => e + (t % 3 < 2 ? n[t % 3] : 0));
|
|
1538
|
+
return {
|
|
1539
|
+
page: o(i, null),
|
|
1540
|
+
box: a
|
|
1541
|
+
};
|
|
1542
|
+
}));
|
|
1543
|
+
}
|
|
1544
|
+
function $e(e) {
|
|
1545
|
+
let t = (t) => [Math.min(...e.map((e) => e[t])), Math.max(...e.map((e) => e[t + 3]))];
|
|
1546
|
+
return {
|
|
1547
|
+
e: t(0),
|
|
1548
|
+
n: t(1),
|
|
1549
|
+
h: t(2)
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
var et = class {
|
|
1553
|
+
#e = /* @__PURE__ */ new Map();
|
|
1554
|
+
update(e, t, n, r) {
|
|
1555
|
+
let i = this.#e, a = tt(e, t), o = -1;
|
|
1556
|
+
for (let [e, r] of i) t(r.page.id) ? (o = Math.max(o, r.level), !r.held && (r.start !== null && n - r.start >= 250 && (r.start = null), a.has(e) || (r.frozen = R(r, n), r.start = null, r.out = null, r.covered = !1, r.held = !0))) : i.delete(e);
|
|
1557
|
+
let s = /* @__PURE__ */ new Set();
|
|
1558
|
+
for (let [e, t] of a) {
|
|
1559
|
+
let r = i.get(e);
|
|
1560
|
+
if (!r) {
|
|
1561
|
+
let r = nt(t, e % 4, n);
|
|
1562
|
+
o = Math.max(o, r.level), i.set(e, r), s.add(r);
|
|
1563
|
+
} else if (r.held) {
|
|
1564
|
+
let e = R(r, n);
|
|
1565
|
+
r.held = !1, r.out = null, e < 255 && (r.start = n - e / 255 * 250, s.add(r));
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map();
|
|
1569
|
+
for (let e of i.values()) if (e.held) {
|
|
1570
|
+
c.set(e.cell, e);
|
|
1571
|
+
for (let t = e.level, n = e.col, r = e.row; t <= o; t++, n >>= 1, r >>= 1) {
|
|
1572
|
+
let i = rt(t, n, r), a = l.get(i);
|
|
1573
|
+
a ? a.push(e) : l.set(i, [e]);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
let u = (e) => {
|
|
1577
|
+
let t = [...l.get(e.cell) ?? []];
|
|
1578
|
+
for (let n = e.level + 1, r = e.col >> 1, i = e.row >> 1; n <= o; n++, r >>= 1, i >>= 1) {
|
|
1579
|
+
let e = c.get(rt(n, r, i));
|
|
1580
|
+
e && t.push(e);
|
|
1581
|
+
}
|
|
1582
|
+
return t;
|
|
1583
|
+
}, f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), m = 0, h = 0, g = (e) => {
|
|
1584
|
+
p.has(e) || (p.add(e), h += d(e.row.count));
|
|
1585
|
+
};
|
|
1586
|
+
for (let e of i.values()) if (!(e.held || e.start === null || s.has(e))) {
|
|
1587
|
+
m += e.splats;
|
|
1588
|
+
for (let t of u(e)) f.has(t) || (f.add(t), m += t.splats, g(t.page));
|
|
1589
|
+
}
|
|
1590
|
+
for (let e of i.values()) e.held && e.out !== null && !f.has(e) && (m += e.splats);
|
|
1591
|
+
let _ = 1 * r;
|
|
1592
|
+
for (let e of s) {
|
|
1593
|
+
let t = u(e).filter((e) => !f.has(e)), n = t.reduce((e, t) => e + t.splats, e.splats), r = new Set(t.map((e) => e.page).filter((e) => !p.has(e))), i = [...r].reduce((e, t) => e + d(t.row.count), 0);
|
|
1594
|
+
if (m + n > _ || h + i > _) e.start = null;
|
|
1595
|
+
else {
|
|
1596
|
+
m += n;
|
|
1597
|
+
for (let e of t) f.add(e);
|
|
1598
|
+
for (let e of r) g(e);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
let v = /* @__PURE__ */ new Map(), y = !1;
|
|
1602
|
+
for (let [e, t] of i) {
|
|
1603
|
+
if (t.held && f.has(t)) t.out !== null && (t.frozen = R(t, n)), t.out = null, t.covered = !0;
|
|
1604
|
+
else if (t.held && (t.covered && t.out === null && (t.out = n), !t.covered || R(t, n) === 0)) {
|
|
1605
|
+
i.delete(e);
|
|
1606
|
+
continue;
|
|
1607
|
+
}
|
|
1608
|
+
(t.held || t.start !== null) && (y = !0);
|
|
1609
|
+
let r = R(t, n);
|
|
1610
|
+
if (!r) continue;
|
|
1611
|
+
let a = v.get(t.page.id);
|
|
1612
|
+
a ? a.factors = (a.factors | r << 8 * t.q) >>> 0 : v.set(t.page.id, {
|
|
1613
|
+
id: t.page.id,
|
|
1614
|
+
factors: r << 8 * t.q >>> 0
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
return {
|
|
1618
|
+
drawn: [...v.values()],
|
|
1619
|
+
fading: y
|
|
1620
|
+
};
|
|
1621
|
+
}
|
|
1622
|
+
};
|
|
1623
|
+
function tt(e, t) {
|
|
1624
|
+
let n = new Set(e), r = /* @__PURE__ */ new Set(), i = [];
|
|
1625
|
+
for (let t of e) for (let e = t; e && !r.has(e); e = e.parent) r.add(e), e.parent || i.push(e);
|
|
1626
|
+
let a = /* @__PURE__ */ new Map(), o = (e) => {
|
|
1627
|
+
for (let i = 0; i < 4; i++) {
|
|
1628
|
+
let s = e.children[i];
|
|
1629
|
+
s && r.has(s) && t(s.id) ? o(s) : (s !== null || n.has(e)) && a.set(e.id * 4 + i, e);
|
|
1630
|
+
}
|
|
1631
|
+
};
|
|
1632
|
+
for (let e of i) t(e.id) && o(e);
|
|
1633
|
+
return a;
|
|
1634
|
+
}
|
|
1635
|
+
function nt(e, t, n) {
|
|
1636
|
+
let r = c * 2 ** e.g, i = e.g - 1, a = 2 * (Math.round(e.unit.e / r) + e.row.i) + (t & 1), o = 2 * (Math.round(e.unit.n / r) + e.row.j) + (t >> 1);
|
|
1637
|
+
return {
|
|
1638
|
+
page: e,
|
|
1639
|
+
q: t,
|
|
1640
|
+
level: i,
|
|
1641
|
+
col: a,
|
|
1642
|
+
row: o,
|
|
1643
|
+
cell: rt(i, a, o),
|
|
1644
|
+
splats: it(e.row, t),
|
|
1645
|
+
start: n,
|
|
1646
|
+
frozen: 0,
|
|
1647
|
+
out: null,
|
|
1648
|
+
covered: !1,
|
|
1649
|
+
held: !1
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
var rt = (e, t, n) => ((e + 1) * 2 ** 21 + t) * 2 ** 21 + n;
|
|
1653
|
+
function it({ count: e, quadrants: t }, n) {
|
|
1654
|
+
return (n < 3 ? t[n] : e) - (n > 0 ? t[n - 1] : 0);
|
|
1655
|
+
}
|
|
1656
|
+
function R(e, t) {
|
|
1657
|
+
return e.held ? e.out === null ? e.frozen : Math.max(0, Math.round(e.frozen * (1 - (t - e.out) / 250))) : e.start === null ? 255 : Math.min(255, Math.round((t - e.start) / 250 * 255));
|
|
1658
|
+
}
|
|
1659
|
+
//#endregion
|
|
1660
|
+
//#region src/engine/plan/footprint.ts
|
|
1661
|
+
var at = [
|
|
1662
|
+
0,
|
|
1663
|
+
0,
|
|
1664
|
+
0
|
|
1665
|
+
];
|
|
1666
|
+
function ot(e, t, n, r) {
|
|
1667
|
+
let i = (e * e + e * t + t * t + n * n + n * r + r * r) / 3;
|
|
1668
|
+
return 1 + 15 * Math.max(0, 1 - i) ** 2;
|
|
1669
|
+
}
|
|
1670
|
+
function st(e, t, n, r, i, a, o, s = 1, c = {
|
|
1671
|
+
shown: !1,
|
|
1672
|
+
pixels: 0,
|
|
1673
|
+
weight: 1
|
|
1674
|
+
}, l = at) {
|
|
1675
|
+
let u = (e[0] + e[3]) / 2 - l[0], d = (e[1] + e[4]) / 2 - l[1], f = (e[2] + e[5]) / 2 - l[2], p = (e[3] - e[0]) / 2, m = (e[4] - e[1]) / 2, h = (e[5] - e[2]) / 2, g = t[0] * u + t[4] * d + t[8] * f + t[12], _ = t[1] * u + t[5] * d + t[9] * f + t[13], v = -(t[2] * u + t[6] * d + t[10] * f + t[14]), y = Math.abs(t[0]) * p + Math.abs(t[4]) * m + Math.abs(t[8]) * h, b = Math.abs(t[1]) * p + Math.abs(t[5]) * m + Math.abs(t[9]) * h, x = Math.abs(t[2]) * p + Math.abs(t[6]) * m + Math.abs(t[10]) * h;
|
|
1676
|
+
if (c.pixels = 0, c.weight = 1, c.shown = !1, v + x < a || v - x > o) return c;
|
|
1677
|
+
let S = Math.max(a, v - x), C = Math.max(a, v + x), w = i * n / r;
|
|
1678
|
+
if (Math.abs(g) - y > s * w * C || Math.abs(_) - b > s * i * C) return c;
|
|
1679
|
+
let T = Math.min((g - y) / S, (g - y) / C) / w, E = Math.max((g + y) / S, (g + y) / C) / w, D = Math.min((_ - b) / S, (_ - b) / C) / i, O = Math.max((_ + b) / S, (_ + b) / C) / i;
|
|
1680
|
+
if (E < -s || T > s || O < -s || D > s) return c;
|
|
1681
|
+
let k = Math.max(-s, T), A = Math.min(s, E), j = Math.max(-s, D), M = Math.min(s, O), ee = (E - T) * (O - D), te = (A - k) * (M - j);
|
|
1682
|
+
return ee <= 0 || te <= 0 || (c.shown = E > -1 && T < 1 && O > -1 && D < 1, c.pixels = ee * n * r / 4, c.weight = ot(k, A, j, M)), c;
|
|
1683
|
+
}
|
|
1684
|
+
var z = /* @__PURE__ */ new Float64Array(6), ct = {
|
|
1685
|
+
shown: !1,
|
|
1686
|
+
pixels: 0,
|
|
1687
|
+
weight: 1
|
|
1688
|
+
};
|
|
1689
|
+
function lt(e, [t, n, r], i, a, o, s, c, l, u = at) {
|
|
1690
|
+
let d = r / 2, f = Math.max(0, t - e[0], n - e[1], e[3] - t - r, e[4] - n - r);
|
|
1691
|
+
z[2] = e[2], z[5] = e[5];
|
|
1692
|
+
let p = 0;
|
|
1693
|
+
for (let r = 0; r < 4; r++) {
|
|
1694
|
+
let m = t + (r & 1) * d, h = n + (r >> 1) * d;
|
|
1695
|
+
z[0] = Math.max(e[0], m - f), z[1] = Math.max(e[1], h - f), z[3] = Math.min(e[3], m + d + f), z[4] = Math.min(e[4], h + d + f), !(z[0] > z[3] || z[1] > z[4]) && st(z, i, a, o, s, c, l, 1, ct, u).shown && (p |= 1 << r);
|
|
1696
|
+
}
|
|
1697
|
+
return p;
|
|
1698
|
+
}
|
|
1699
|
+
//#endregion
|
|
1700
|
+
//#region src/engine/world/tree.ts
|
|
1701
|
+
var B = (e, t, n) => (e * 256 + t) * 256 + n, ut = class {
|
|
1702
|
+
roots = [];
|
|
1703
|
+
pages = /* @__PURE__ */ new Map();
|
|
1704
|
+
units = /* @__PURE__ */ new Map();
|
|
1705
|
+
#e;
|
|
1706
|
+
#t;
|
|
1707
|
+
#n = 0;
|
|
1708
|
+
#r = /* @__PURE__ */ new Map();
|
|
1709
|
+
#i = /* @__PURE__ */ new Map();
|
|
1710
|
+
constructor(e) {
|
|
1711
|
+
this.#e = new Set(e.roots.map(V)), this.#t = Math.max(...e.roots.map((e) => e.level));
|
|
1712
|
+
}
|
|
1713
|
+
add(e, t) {
|
|
1714
|
+
let n = V(e), r = this.units.get(n);
|
|
1715
|
+
if (r) return r;
|
|
1716
|
+
let a = /* @__PURE__ */ new Map(), o = {
|
|
1717
|
+
level: e.level,
|
|
1718
|
+
e: e.e,
|
|
1719
|
+
n: e.n,
|
|
1720
|
+
idx: e,
|
|
1721
|
+
path: t,
|
|
1722
|
+
parent: null,
|
|
1723
|
+
pages: [],
|
|
1724
|
+
grid: a
|
|
1725
|
+
};
|
|
1726
|
+
for (let t of e.rows) {
|
|
1727
|
+
let n = t.box, r = {
|
|
1728
|
+
id: this.#n++,
|
|
1729
|
+
unit: o,
|
|
1730
|
+
row: t,
|
|
1731
|
+
g: t.g,
|
|
1732
|
+
box: Float64Array.of(e.e + n[0], e.n + n[1], n[2], e.e + n[3], e.n + n[4], n[5]),
|
|
1733
|
+
parent: null,
|
|
1734
|
+
children: [
|
|
1735
|
+
null,
|
|
1736
|
+
null,
|
|
1737
|
+
null,
|
|
1738
|
+
null
|
|
1739
|
+
]
|
|
1740
|
+
};
|
|
1741
|
+
this.pages.set(r.id, r), o.pages.push(r), a.set(B(t.g, t.i, t.j), r);
|
|
1742
|
+
}
|
|
1743
|
+
this.units.set(n, o), this.#r.delete(n);
|
|
1744
|
+
for (let t = e.level + 1; t <= this.#t; t++) {
|
|
1745
|
+
let n = V(H(e, t));
|
|
1746
|
+
this.#i.set(n, (this.#i.get(n) ?? 0) + 1);
|
|
1747
|
+
}
|
|
1748
|
+
let c = new Set(e.rows.map((e) => e.g)), l = Math.max(...c), u = e.level === 0 ? 0 : e.level + 1, d = new Set(e.children.map((e) => e.quadrant));
|
|
1749
|
+
for (let e of o.pages) {
|
|
1750
|
+
let { g: t, i: n, j: r } = e.row;
|
|
1751
|
+
c.has(t + 1) && (e.parent = a.get(B(t + 1, n >> 1, r >> 1)) ?? null);
|
|
1752
|
+
for (let i = 0; i < 4; i++) {
|
|
1753
|
+
let o = 2 * n + (i & 1), s = 2 * r + (i >> 1);
|
|
1754
|
+
c.has(t - 1) ? e.children[i] = a.get(B(t - 1, o, s)) ?? null : t === u && t > 0 && (e.children[i] = d.has((o >> 3) + 2 * (s >> 3)) ? void 0 : null);
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
if (this.#e.has(n)) for (let e of o.pages) e.g === l && this.roots.push(e);
|
|
1758
|
+
else {
|
|
1759
|
+
let t = this.units.get(V(H(e, e.level + 1)));
|
|
1760
|
+
t && this.#o(t, o);
|
|
1761
|
+
}
|
|
1762
|
+
let f = i(o.idx);
|
|
1763
|
+
for (let { key: t } of f) {
|
|
1764
|
+
let n = t.level === e.level - 1 ? this.units.get(V(t)) : void 0;
|
|
1765
|
+
n && this.#o(o, n);
|
|
1766
|
+
}
|
|
1767
|
+
for (let { key: e, hash: t } of f) {
|
|
1768
|
+
let n = V(e);
|
|
1769
|
+
if (this.units.has(n)) continue;
|
|
1770
|
+
let r = this.#r.get(n);
|
|
1771
|
+
if (r && r.from <= o.level) continue;
|
|
1772
|
+
let i = this.#s(o, e), a = {
|
|
1773
|
+
...e,
|
|
1774
|
+
path: s(e, t, "idx"),
|
|
1775
|
+
over: i
|
|
1776
|
+
};
|
|
1777
|
+
this.#r.set(n, {
|
|
1778
|
+
wanted: a,
|
|
1779
|
+
from: o.level
|
|
1780
|
+
});
|
|
1781
|
+
}
|
|
1782
|
+
return o;
|
|
1783
|
+
}
|
|
1784
|
+
wanted() {
|
|
1785
|
+
return Array.from(this.#r.values(), (e) => e.wanted);
|
|
1786
|
+
}
|
|
1787
|
+
ground(e, t) {
|
|
1788
|
+
for (let n of this.roots) {
|
|
1789
|
+
let [r, i, a] = ft(n);
|
|
1790
|
+
if (e < r || e >= r + a || t < i || t >= i + a) continue;
|
|
1791
|
+
let o = n;
|
|
1792
|
+
for (;;) {
|
|
1793
|
+
let n = +(e >= r + a / 2), s = +(t >= i + a / 2), c = o.children[n + 2 * s];
|
|
1794
|
+
if (!c) return o.box[2];
|
|
1795
|
+
o = c, [r, i, a] = ft(o);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
async load(e, t, n) {
|
|
1800
|
+
for (;;) {
|
|
1801
|
+
let r = this.wanted().filter((n) => dt(n, e, t));
|
|
1802
|
+
if (r.length === 0) return;
|
|
1803
|
+
(await Promise.all(r.map((e) => n(e.path)))).forEach((e, t) => this.add(e, r[t].path));
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
prune(e) {
|
|
1807
|
+
let t = [], n = [...this.units.values()].sort((e, t) => e.level - t.level);
|
|
1808
|
+
for (let r of n) {
|
|
1809
|
+
let n = V(r);
|
|
1810
|
+
if (this.#e.has(n) || this.#i.has(n) || r.pages.some((t) => e.has(t.id))) continue;
|
|
1811
|
+
for (let e of r.pages) this.pages.delete(e.id), t.push(e.id);
|
|
1812
|
+
let a = r.parent;
|
|
1813
|
+
if (a) {
|
|
1814
|
+
let e = 250 * 2 ** r.level, t = (r.e - a.e) / e, n = (r.n - a.n) / e, i = a.idx.children.some((e) => e.quadrant === t + 2 * n);
|
|
1815
|
+
for (let e of this.#s(a, r)) e.children.fill(i ? void 0 : null);
|
|
1816
|
+
}
|
|
1817
|
+
this.units.delete(n);
|
|
1818
|
+
for (let e = r.level + 1; e <= this.#t; e++) {
|
|
1819
|
+
let t = V(H(r, e)), n = this.#i.get(t) - 1;
|
|
1820
|
+
n ? this.#i.set(t, n) : this.#i.delete(t);
|
|
1821
|
+
}
|
|
1822
|
+
for (let { key: e } of i(r.idx)) this.#a(e);
|
|
1823
|
+
this.#a(r);
|
|
1824
|
+
}
|
|
1825
|
+
return t;
|
|
1826
|
+
}
|
|
1827
|
+
#a(e) {
|
|
1828
|
+
let t = V(e);
|
|
1829
|
+
this.#r.delete(t);
|
|
1830
|
+
for (let n = e.level + 1; n <= e.level + 3; n++) {
|
|
1831
|
+
let r = this.units.get(V(H(e, n)));
|
|
1832
|
+
if (!r) continue;
|
|
1833
|
+
let a = i(r.idx).find((e) => V(e.key) === t);
|
|
1834
|
+
if (!a) continue;
|
|
1835
|
+
let o = {
|
|
1836
|
+
level: e.level,
|
|
1837
|
+
e: e.e,
|
|
1838
|
+
n: e.n,
|
|
1839
|
+
path: s(a.key, a.hash, "idx"),
|
|
1840
|
+
over: this.#s(r, e)
|
|
1841
|
+
};
|
|
1842
|
+
this.#r.set(t, {
|
|
1843
|
+
wanted: o,
|
|
1844
|
+
from: r.level
|
|
1845
|
+
});
|
|
1846
|
+
return;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
#o(e, t) {
|
|
1850
|
+
t.parent = e;
|
|
1851
|
+
let n = t.level + 1, r = 250 * 2 ** t.level, i = (t.e - e.e) / r, a = (t.n - e.n) / r, o = e.grid;
|
|
1852
|
+
for (let n of this.#s(e, t)) n.children.fill(null);
|
|
1853
|
+
for (let e of t.pages) {
|
|
1854
|
+
if (e.g !== n) continue;
|
|
1855
|
+
let t = 8 * i + e.row.i, r = 8 * a + e.row.j, s = o.get(B(n + 1, t >> 1, r >> 1)) ?? null;
|
|
1856
|
+
e.parent = s, s && (s.children[(t & 1) + 2 * (r & 1)] = e);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
#s(e, t) {
|
|
1860
|
+
let n = e.level + 1, r = c * 2 ** n, i = (t.e - e.e) / r, a = (t.n - e.n) / r, o = 250 * 2 ** t.level / r, s = [];
|
|
1861
|
+
for (let t = a; t < a + o; t++) for (let r = i; r < i + o; r++) {
|
|
1862
|
+
let i = e.grid.get(B(n, r, t));
|
|
1863
|
+
i && s.push(i);
|
|
1864
|
+
}
|
|
1865
|
+
return s;
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
function V(e) {
|
|
1869
|
+
return `${e.level}/${e.e}/${e.n}`;
|
|
1870
|
+
}
|
|
1871
|
+
function H(e, t) {
|
|
1872
|
+
let n = 250 * 2 ** t;
|
|
1873
|
+
return {
|
|
1874
|
+
level: t,
|
|
1875
|
+
e: Math.floor(e.e / n) * n,
|
|
1876
|
+
n: Math.floor(e.n / n) * n
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
function dt(e, t, n) {
|
|
1880
|
+
let r = 250 * 2 ** e.level;
|
|
1881
|
+
return t >= e.e && t < e.e + r && n >= e.n && n < e.n + r;
|
|
1882
|
+
}
|
|
1883
|
+
function ft(e) {
|
|
1884
|
+
let t = c * 2 ** e.g;
|
|
1885
|
+
return [
|
|
1886
|
+
e.unit.e + e.row.i * t,
|
|
1887
|
+
e.unit.n + e.row.j * t,
|
|
1888
|
+
t
|
|
1889
|
+
];
|
|
1890
|
+
}
|
|
1891
|
+
//#endregion
|
|
1892
|
+
//#region src/engine/plan/cut.ts
|
|
1893
|
+
var pt = 1 / .8 ** 2, mt = 1.1, ht = class {
|
|
1894
|
+
#e = /* @__PURE__ */ new Map();
|
|
1895
|
+
#t = /* @__PURE__ */ new Map();
|
|
1896
|
+
#n = {
|
|
1897
|
+
shown: !1,
|
|
1898
|
+
pixels: 0,
|
|
1899
|
+
weight: 1
|
|
1900
|
+
};
|
|
1901
|
+
plan(e, t, n, r) {
|
|
1902
|
+
let { budget: i, capacity: a, now: o, predicted: s } = r, c = [], l = [], u = [], f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = e.wanted(), h = /* @__PURE__ */ new Map(), g = new vt(), _ = 0, v = 0, y = (e) => {
|
|
1903
|
+
let t = e.page, r = t.row.count;
|
|
1904
|
+
c.push(t), l.push(e.visible), u.push(e.near), v += d(r), _ += e.visible;
|
|
1905
|
+
let i = this.#e.get(t.id), a = i !== void 0, s = e.pixels * e.weight, f = s / Math.max(1, r);
|
|
1906
|
+
m.length && e.pixels > 0 && h.set(t.id, f);
|
|
1907
|
+
let p = a && !e.shown && o - (this.#t.get(t.id) ?? -Infinity) <= 1500 ? i : null;
|
|
1908
|
+
(r < s * (a ? pt : 1) || p !== null) && _t(t, n) && g.push({
|
|
1909
|
+
page: t,
|
|
1910
|
+
shown: e.shown,
|
|
1911
|
+
held: p,
|
|
1912
|
+
visible: e.visible,
|
|
1913
|
+
ratio: f
|
|
1914
|
+
});
|
|
1915
|
+
};
|
|
1916
|
+
for (let n of e.roots) y(this.#r(n, t, s));
|
|
1917
|
+
let b = [];
|
|
1918
|
+
for (; g.size;) {
|
|
1919
|
+
let e = g.pop(), { page: n, shown: r, held: c } = e, l = [], u = 0;
|
|
1920
|
+
for (let e = 0; e < n.children.length; e++) {
|
|
1921
|
+
let r = n.children[e];
|
|
1922
|
+
if (!r) continue;
|
|
1923
|
+
let i = this.#r(r, t, s);
|
|
1924
|
+
i.pixels <= 0 && !((c ?? 0) & 1 << e) || (l.push(i), u |= 1 << e);
|
|
1925
|
+
}
|
|
1926
|
+
if (!l.length) continue;
|
|
1927
|
+
let m = 0, h = -e.visible;
|
|
1928
|
+
for (let e of l) m += d(e.page.row.count), h += e.visible;
|
|
1929
|
+
if (v + m > a) break;
|
|
1930
|
+
if (h > 0 && (b.length || _ + h > i)) {
|
|
1931
|
+
b.push(e);
|
|
1932
|
+
continue;
|
|
1933
|
+
}
|
|
1934
|
+
if (h < 0) for (let e of b.splice(0)) g.push(e);
|
|
1935
|
+
f.set(n.id, u);
|
|
1936
|
+
let x = r ? o : this.#t.get(n.id);
|
|
1937
|
+
x !== void 0 && p.set(n.id, x), _ -= e.visible;
|
|
1938
|
+
for (let e of l) y(e);
|
|
1939
|
+
}
|
|
1940
|
+
this.#e = f, this.#t = p;
|
|
1941
|
+
let x = [], S = [], C = new Set(f.keys()), w = 0;
|
|
1942
|
+
for (let e = 0; e < c.length; e++) {
|
|
1943
|
+
let t = c[e];
|
|
1944
|
+
f.has(t.id) || (x.push(t), C.add(t.id), n(t.id) || (w += l[e], S.push({
|
|
1945
|
+
page: t,
|
|
1946
|
+
near: u[e]
|
|
1947
|
+
})));
|
|
1948
|
+
}
|
|
1949
|
+
let T = [];
|
|
1950
|
+
for (let e of m) {
|
|
1951
|
+
let t = -1;
|
|
1952
|
+
for (let n of e.over) t = Math.max(t, h.get(n.id) ?? -1);
|
|
1953
|
+
t >= 0 && T.push({
|
|
1954
|
+
wanted: e,
|
|
1955
|
+
rank: t
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1958
|
+
return T.sort((e, t) => t.rank - e.rank), {
|
|
1959
|
+
cut: x,
|
|
1960
|
+
load: S.filter(({ near: e }) => e || !s && w === 0).map(({ page: e }) => e),
|
|
1961
|
+
idx: T.map((e) => e.wanted),
|
|
1962
|
+
keep: C,
|
|
1963
|
+
planned: _,
|
|
1964
|
+
missing: w
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1967
|
+
#r(e, t, n) {
|
|
1968
|
+
let r = this.#i(e, t, mt), i = r.shown, { pixels: a, weight: o } = r, s = i;
|
|
1969
|
+
if (n) {
|
|
1970
|
+
let t = this.#i(e, n, mt);
|
|
1971
|
+
t.pixels > a && ({pixels: a, weight: o} = t), s ||= t.shown;
|
|
1972
|
+
}
|
|
1973
|
+
return {
|
|
1974
|
+
page: e,
|
|
1975
|
+
shown: i,
|
|
1976
|
+
near: s,
|
|
1977
|
+
visible: i ? gt(e, t) : 0,
|
|
1978
|
+
pixels: a,
|
|
1979
|
+
weight: o
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
#i(e, t, n) {
|
|
1983
|
+
let { width: r, height: i, tan: a, near: o, far: s } = t;
|
|
1984
|
+
return st(e.box, t.view, r, i, a, o, s, n, this.#n, t.origin);
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
function gt(e, t) {
|
|
1988
|
+
let { width: n, height: r, tan: i, near: a, far: o, origin: s } = t, c = lt(e.box, ft(e), t.view, n, r, i, a, o, s), l = 0;
|
|
1989
|
+
for (let t = 0; t < 4; t++) c & 1 << t && (l += it(e.row, t));
|
|
1990
|
+
return l;
|
|
1991
|
+
}
|
|
1992
|
+
function _t(e, t) {
|
|
1993
|
+
let { children: n } = e;
|
|
1994
|
+
return e.g > 0 && t(e.id) && !n.includes(void 0) && n.some((e) => e !== null);
|
|
1995
|
+
}
|
|
1996
|
+
var vt = class {
|
|
1997
|
+
#e = [];
|
|
1998
|
+
get size() {
|
|
1999
|
+
return this.#e.length;
|
|
2000
|
+
}
|
|
2001
|
+
push(e) {
|
|
2002
|
+
let t = this.#e;
|
|
2003
|
+
t.push(e);
|
|
2004
|
+
let n = t.length - 1;
|
|
2005
|
+
for (; n > 0;) {
|
|
2006
|
+
let r = n - 1 >> 1;
|
|
2007
|
+
if (!U(e, t[r])) break;
|
|
2008
|
+
t[n] = t[r], n = r;
|
|
2009
|
+
}
|
|
2010
|
+
t[n] = e;
|
|
2011
|
+
}
|
|
2012
|
+
pop() {
|
|
2013
|
+
let e = this.#e, t = e[0], n = e.pop();
|
|
2014
|
+
if (e.length) {
|
|
2015
|
+
let t = 0;
|
|
2016
|
+
for (; 2 * t + 1 < e.length;) {
|
|
2017
|
+
let r = 2 * t + 1;
|
|
2018
|
+
if (r + 1 < e.length && U(e[r + 1], e[r]) && r++, !U(e[r], n)) break;
|
|
2019
|
+
e[t] = e[r], t = r;
|
|
2020
|
+
}
|
|
2021
|
+
e[t] = n;
|
|
2022
|
+
}
|
|
2023
|
+
return t;
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2026
|
+
function U(e, t) {
|
|
2027
|
+
return e.shown === t.shown ? e.ratio > t.ratio : e.shown;
|
|
2028
|
+
}
|
|
2029
|
+
//#endregion
|
|
2030
|
+
//#region src/engine/quality.ts
|
|
2031
|
+
var yt = 5e5, bt = 2073600, xt = [1, .85], St = 30, Ct = 55, wt = 2e3, Tt = 5e3, Et = 5e5, Dt = .9;
|
|
2032
|
+
function Ot(e, t, n, r) {
|
|
2033
|
+
return Math.min(n, Math.sqrt(bt / Math.max(1, e * t))) * r;
|
|
2034
|
+
}
|
|
2035
|
+
function kt(e, t) {
|
|
2036
|
+
if (!e.length) return 0;
|
|
2037
|
+
let n = [...e].sort((e, t) => e - t);
|
|
2038
|
+
return n[Math.ceil(n.length * t) - 1];
|
|
2039
|
+
}
|
|
2040
|
+
var At = class {
|
|
2041
|
+
#e = 0;
|
|
2042
|
+
#t;
|
|
2043
|
+
#n;
|
|
2044
|
+
#r;
|
|
2045
|
+
#i = [];
|
|
2046
|
+
#a = -Infinity;
|
|
2047
|
+
#o = 0;
|
|
2048
|
+
#s = 0;
|
|
2049
|
+
constructor(e, [t, n] = [e, e]) {
|
|
2050
|
+
this.#n = t, this.#r = Math.max(t, n), this.#t = Math.min(this.#r, Math.max(this.#n, e));
|
|
2051
|
+
}
|
|
2052
|
+
get scale() {
|
|
2053
|
+
return xt[this.#e];
|
|
2054
|
+
}
|
|
2055
|
+
get budget() {
|
|
2056
|
+
return this.#t;
|
|
2057
|
+
}
|
|
2058
|
+
full() {
|
|
2059
|
+
this.#e = 0, this.#c();
|
|
2060
|
+
}
|
|
2061
|
+
#c() {
|
|
2062
|
+
this.#i = [], this.#o = 0, this.#s = 0, this.#a = -Infinity;
|
|
2063
|
+
}
|
|
2064
|
+
sample(e, t, n, r) {
|
|
2065
|
+
if (!n || t - this.#a > Math.max(250, 2 * e) || !Number.isFinite(e) || e <= 0) return this.#c(), this.#a = t, !1;
|
|
2066
|
+
let i = Math.max(0, t - this.#a);
|
|
2067
|
+
if (this.#a = t, this.#i.push({
|
|
2068
|
+
time: t,
|
|
2069
|
+
ms: e
|
|
2070
|
+
}), this.#i = this.#i.filter((n) => t - n.time <= Math.max(1e3, 2 * e)), t - this.#i[0].time < 300) return !1;
|
|
2071
|
+
let a = this.#i.reduce((e, t) => e + t.ms, 0) / this.#i.length;
|
|
2072
|
+
if (this.#o = a > 1e3 / St ? this.#o + i : 0, this.#s = a <= 1e3 / Ct ? this.#s + i : 0, this.#o >= wt) {
|
|
2073
|
+
let e = Math.floor(Math.min(.9, 1e3 / St / a) * this.#t);
|
|
2074
|
+
if (this.#t > this.#n) this.#t = Math.max(this.#n, e);
|
|
2075
|
+
else if (this.#e < xt.length - 1) this.#e++;
|
|
2076
|
+
else return !1;
|
|
2077
|
+
} else if (this.#s >= Tt) {
|
|
2078
|
+
if (this.#e > 0) this.#e--;
|
|
2079
|
+
else if (this.#t < this.#r && r >= Dt * this.#t) this.#t = Math.min(this.#r, this.#t + Et);
|
|
2080
|
+
else return !1;
|
|
2081
|
+
} else return !1;
|
|
2082
|
+
return this.#c(), !0;
|
|
2083
|
+
}
|
|
2084
|
+
}, jt = class {
|
|
2085
|
+
#e;
|
|
2086
|
+
#t = [];
|
|
2087
|
+
#n = /* @__PURE__ */ new Set();
|
|
2088
|
+
#r = /* @__PURE__ */ new Set();
|
|
2089
|
+
#i = /* @__PURE__ */ new Set();
|
|
2090
|
+
#a = /* @__PURE__ */ new Map();
|
|
2091
|
+
constructor(e) {
|
|
2092
|
+
this.#e = e;
|
|
2093
|
+
}
|
|
2094
|
+
want(e) {
|
|
2095
|
+
this.#t = e, this.#n = new Set(e.map((e) => e.id));
|
|
2096
|
+
}
|
|
2097
|
+
next() {
|
|
2098
|
+
let e = [];
|
|
2099
|
+
for (let t of this.#r) this.#i.has(t) || t.pages.some((e) => this.#n.has(e.id)) || (this.#i.add(t), e.push(t));
|
|
2100
|
+
let t = [];
|
|
2101
|
+
if (this.#r.size >= this.#e.concurrency) return {
|
|
2102
|
+
start: t,
|
|
2103
|
+
abort: e
|
|
2104
|
+
};
|
|
2105
|
+
let n = /* @__PURE__ */ new Map();
|
|
2106
|
+
for (let e of this.#t) {
|
|
2107
|
+
if (this.#a.has(e.id)) continue;
|
|
2108
|
+
let t = n.get(e.pack);
|
|
2109
|
+
t ? t.push(e) : n.set(e.pack, [e]);
|
|
2110
|
+
}
|
|
2111
|
+
for (let e of n.values()) e.sort((e, t) => e.offset - t.offset);
|
|
2112
|
+
for (let e of this.#t) {
|
|
2113
|
+
if (this.#r.size >= this.#e.concurrency) break;
|
|
2114
|
+
if (this.#a.has(e.id)) continue;
|
|
2115
|
+
let r = this.#o(e, n.get(e.pack));
|
|
2116
|
+
for (let e of r.pages) this.#a.set(e.id, r);
|
|
2117
|
+
this.#r.add(r), t.push(r);
|
|
2118
|
+
}
|
|
2119
|
+
return {
|
|
2120
|
+
start: t,
|
|
2121
|
+
abort: e
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
done(e) {
|
|
2125
|
+
if (this.#r.delete(e)) {
|
|
2126
|
+
this.#i.delete(e);
|
|
2127
|
+
for (let t of e.pages) this.#a.get(t.id) === e && this.#a.delete(t.id);
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
get queued() {
|
|
2131
|
+
let e = 0;
|
|
2132
|
+
for (let t of this.#n) this.#a.has(t) || e++;
|
|
2133
|
+
return e;
|
|
2134
|
+
}
|
|
2135
|
+
get loading() {
|
|
2136
|
+
return this.#a.size;
|
|
2137
|
+
}
|
|
2138
|
+
#o(e, t) {
|
|
2139
|
+
let { gap: n, span: r } = this.#e, i = Math.floor(e.offset / r), a = t.indexOf(e), o = [e], s = e.offset, c = e.offset + e.length;
|
|
2140
|
+
for (let e = a + 1; e < t.length; e++) {
|
|
2141
|
+
let a = t[e];
|
|
2142
|
+
if (this.#a.has(a.id)) continue;
|
|
2143
|
+
let l = Math.max(c, a.offset + a.length);
|
|
2144
|
+
if (a.offset - c > n || l - s > r || Math.floor(a.offset / r) !== i) break;
|
|
2145
|
+
o.push(a), c = l;
|
|
2146
|
+
}
|
|
2147
|
+
for (let e = a - 1; e >= 0; e--) {
|
|
2148
|
+
let a = t[e];
|
|
2149
|
+
if (!this.#a.has(a.id)) {
|
|
2150
|
+
if (s - (a.offset + a.length) > n || c - a.offset > r || Math.floor(a.offset / r) !== i) break;
|
|
2151
|
+
o.unshift(a), s = a.offset;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
return {
|
|
2155
|
+
pack: e.pack,
|
|
2156
|
+
col: e.col,
|
|
2157
|
+
start: s,
|
|
2158
|
+
end: c,
|
|
2159
|
+
window: i,
|
|
2160
|
+
pages: o
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
}, Mt = {
|
|
2164
|
+
idx: 8,
|
|
2165
|
+
concurrency: 8,
|
|
2166
|
+
gap: 65536,
|
|
2167
|
+
span: 2097152
|
|
2168
|
+
}, Nt = 1e3, Pt = 3e4, Ft = 1e3, It = 2e3, Lt = class {
|
|
2169
|
+
#e;
|
|
2170
|
+
#t;
|
|
2171
|
+
#n;
|
|
2172
|
+
#r;
|
|
2173
|
+
#i;
|
|
2174
|
+
#a;
|
|
2175
|
+
#o;
|
|
2176
|
+
#s = {
|
|
2177
|
+
cut: [],
|
|
2178
|
+
load: [],
|
|
2179
|
+
idx: [],
|
|
2180
|
+
keep: /* @__PURE__ */ new Set(),
|
|
2181
|
+
planned: 0,
|
|
2182
|
+
missing: 0
|
|
2183
|
+
};
|
|
2184
|
+
#c = /* @__PURE__ */ new Set();
|
|
2185
|
+
#l = [];
|
|
2186
|
+
#u = 0;
|
|
2187
|
+
#d = /* @__PURE__ */ new Set();
|
|
2188
|
+
#f = /* @__PURE__ */ new Map();
|
|
2189
|
+
#p = /* @__PURE__ */ new Map();
|
|
2190
|
+
#m = /* @__PURE__ */ new Map();
|
|
2191
|
+
#h = /* @__PURE__ */ new Map();
|
|
2192
|
+
#g = /* @__PURE__ */ new Set();
|
|
2193
|
+
#_ = /* @__PURE__ */ new Map();
|
|
2194
|
+
#v = [];
|
|
2195
|
+
#y = -Infinity;
|
|
2196
|
+
#b = !1;
|
|
2197
|
+
#x = !1;
|
|
2198
|
+
constructor(e, t, n, r, i, a = Mt) {
|
|
2199
|
+
this.#e = e, this.#t = t, this.#n = n, this.#r = r, this.#i = i, this.#a = a, this.#o = new jt(a);
|
|
2200
|
+
}
|
|
2201
|
+
update(e, t, n) {
|
|
2202
|
+
if (!this.#x) {
|
|
2203
|
+
this.#s = e, this.#c = t, this.#u = n;
|
|
2204
|
+
for (let e of this.#v) this.#_.set(e, n);
|
|
2205
|
+
this.#v = [], this.#S(), this.#l = this.#C(), this.#o.want(this.#l), this.#w(), this.#M();
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
protects = (e) => this.#s.keep.has(e) || this.#c.has(e);
|
|
2209
|
+
get loading() {
|
|
2210
|
+
return this.#d.size + this.#f.size;
|
|
2211
|
+
}
|
|
2212
|
+
get queued() {
|
|
2213
|
+
return this.#o.queued;
|
|
2214
|
+
}
|
|
2215
|
+
get idle() {
|
|
2216
|
+
if (this.#d.size > 0 || this.#f.size > 0 || this.#n.queued > 0) return !1;
|
|
2217
|
+
let { idx: e, load: t } = this.#s;
|
|
2218
|
+
return e.length === 0 && t.every(({ id: e }) => this.#n.holds(e));
|
|
2219
|
+
}
|
|
2220
|
+
destroy() {
|
|
2221
|
+
this.#x = !0;
|
|
2222
|
+
for (let e of this.#f.values()) e.abort();
|
|
2223
|
+
this.#f.clear(), this.#d.clear();
|
|
2224
|
+
for (let e of this.#h.values()) clearTimeout(e);
|
|
2225
|
+
this.#h.clear();
|
|
2226
|
+
}
|
|
2227
|
+
#S() {
|
|
2228
|
+
if (!this.#b) for (let { path: e } of this.#s.idx) {
|
|
2229
|
+
if (this.#d.size >= this.#a.idx) break;
|
|
2230
|
+
this.#d.has(e) || this.#F(e) || (this.#d.add(e), this.#t.idx(e).then((t) => {
|
|
2231
|
+
this.#x || (this.#d.delete(e), this.#k(e), this.#v.push(this.#e.add(t, e)), this.#r());
|
|
2232
|
+
}, (t) => {
|
|
2233
|
+
this.#x || (this.#d.delete(e), this.#O(e, t));
|
|
2234
|
+
}));
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
#C() {
|
|
2238
|
+
let e = [];
|
|
2239
|
+
for (let { id: t, unit: n, row: r } of this.#s.load) {
|
|
2240
|
+
let { idx: i } = n, a = s(n, i.pack, "pack");
|
|
2241
|
+
if (!this.#N(t, a)) continue;
|
|
2242
|
+
let o = i.col ? s(n, i.col, "col") : null;
|
|
2243
|
+
e.push({
|
|
2244
|
+
id: t,
|
|
2245
|
+
pack: a,
|
|
2246
|
+
col: o,
|
|
2247
|
+
offset: r.offset,
|
|
2248
|
+
length: r.length
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
return e;
|
|
2252
|
+
}
|
|
2253
|
+
#w() {
|
|
2254
|
+
if (this.#b) return;
|
|
2255
|
+
let { start: e, abort: t } = this.#o.next();
|
|
2256
|
+
for (let e of t) this.#f.get(e)?.abort();
|
|
2257
|
+
for (let t of e) {
|
|
2258
|
+
let e = new AbortController();
|
|
2259
|
+
this.#f.set(t, e), this.#t.batch(t, e.signal, this.#T).then(() => this.#E(t), (e) => this.#D(t, e));
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
#T = ({ id: e, page: t }) => {
|
|
2263
|
+
if (this.#x) return;
|
|
2264
|
+
let n = this.#e.pages.get(e);
|
|
2265
|
+
n && (this.#n.add(e, t, [n.unit.e, n.unit.n], this.protects) ? (this.#g.add(e), this.#m.delete(e) && this.#j(e)) : (this.#m.set(e, this.#u + Ft), this.#A(e, Ft)), this.#r());
|
|
2266
|
+
};
|
|
2267
|
+
#E(e) {
|
|
2268
|
+
this.#x || (this.#f.delete(e), this.#k(e.pack), this.#l = this.#l.filter((e) => this.#N(e.id, e.pack)), this.#o.want(this.#l), this.#o.done(e), this.#w(), this.#r());
|
|
2269
|
+
}
|
|
2270
|
+
#D(e, t) {
|
|
2271
|
+
this.#x || (this.#f.delete(e), this.#o.done(e), t instanceof DOMException && t.name === "AbortError" || this.#O(e.pack, t));
|
|
2272
|
+
}
|
|
2273
|
+
#O(e, t) {
|
|
2274
|
+
if (t instanceof l) {
|
|
2275
|
+
if (this.#b) return;
|
|
2276
|
+
this.#b = !0, this.#i();
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
let n = this.#p.get(e), r = n ? Math.min(2 * n.delay, Pt) : Nt;
|
|
2280
|
+
this.#p.set(e, {
|
|
2281
|
+
delay: r,
|
|
2282
|
+
until: this.#u + r
|
|
2283
|
+
}), this.#A(e, r);
|
|
2284
|
+
}
|
|
2285
|
+
#k(e) {
|
|
2286
|
+
this.#p.delete(e), this.#j(e);
|
|
2287
|
+
}
|
|
2288
|
+
#A(e, t) {
|
|
2289
|
+
clearTimeout(this.#h.get(e));
|
|
2290
|
+
let n = setTimeout(() => {
|
|
2291
|
+
this.#h.delete(e), this.#r();
|
|
2292
|
+
}, t);
|
|
2293
|
+
this.#h.set(e, n);
|
|
2294
|
+
}
|
|
2295
|
+
#j(e) {
|
|
2296
|
+
clearTimeout(this.#h.get(e)), this.#h.delete(e);
|
|
2297
|
+
}
|
|
2298
|
+
#M() {
|
|
2299
|
+
let e = this.#u;
|
|
2300
|
+
if (e - this.#y < It) return;
|
|
2301
|
+
this.#y = e;
|
|
2302
|
+
for (let e of this.#g) this.#n.holds(e) || this.#g.delete(e);
|
|
2303
|
+
for (let [t, n] of this.#m) n <= e && this.#m.delete(t);
|
|
2304
|
+
for (let [t, n] of this.#_) e - n >= It && this.#_.delete(t);
|
|
2305
|
+
let { keep: t } = this.#s;
|
|
2306
|
+
if (this.#e.pages.size <= 2 * (this.#g.size + t.size)) return;
|
|
2307
|
+
let n = /* @__PURE__ */ new Set([
|
|
2308
|
+
...t,
|
|
2309
|
+
...this.#c,
|
|
2310
|
+
...this.#g
|
|
2311
|
+
]);
|
|
2312
|
+
for (let e of this.#_.keys()) for (let { id: t } of e.pages) n.add(t);
|
|
2313
|
+
for (let e of this.#e.prune(n)) this.#n.holds(e) && this.#n.remove(e);
|
|
2314
|
+
}
|
|
2315
|
+
#N(e, t) {
|
|
2316
|
+
return !this.#e.pages.has(e) || this.#n.holds(e) ? !1 : !this.#P(e) && !this.#F(t);
|
|
2317
|
+
}
|
|
2318
|
+
#P(e) {
|
|
2319
|
+
let t = this.#m.get(e);
|
|
2320
|
+
return t !== void 0 && this.#u < t;
|
|
2321
|
+
}
|
|
2322
|
+
#F(e) {
|
|
2323
|
+
let t = this.#p.get(e);
|
|
2324
|
+
return t !== void 0 && this.#u < t.until;
|
|
2325
|
+
}
|
|
2326
|
+
};
|
|
2327
|
+
//#endregion
|
|
2328
|
+
//#region src/engine/stream/remote.ts
|
|
2329
|
+
function Rt(e, t) {
|
|
2330
|
+
let n = /* @__PURE__ */ new Map();
|
|
2331
|
+
return (r) => {
|
|
2332
|
+
if ("unfetch" in r) return void n.get(r.unfetch)?.abort();
|
|
2333
|
+
let i = r.fetch, a = new AbortController();
|
|
2334
|
+
n.set(i, a), (async () => e(r.url, r.range, a.signal))().then((e) => {
|
|
2335
|
+
let n = e.slice();
|
|
2336
|
+
t({
|
|
2337
|
+
fetched: i,
|
|
2338
|
+
bytes: n
|
|
2339
|
+
}, [n.buffer]);
|
|
2340
|
+
}, (e) => {
|
|
2341
|
+
let n = e instanceof Error ? e.message : String(e);
|
|
2342
|
+
t({
|
|
2343
|
+
fetched: i,
|
|
2344
|
+
error: n,
|
|
2345
|
+
missing: e instanceof l
|
|
2346
|
+
}, []);
|
|
2347
|
+
}).finally(() => n.delete(i));
|
|
2348
|
+
};
|
|
2349
|
+
}
|
|
2350
|
+
//#endregion
|
|
2351
|
+
//#region src/engine/stream/worker.ts?worker&inline
|
|
2352
|
+
var zt = "(function(){var e=class extends Error{name=`Missing`};let t=async(t,n,r)=>{let i=await fetch(t,n?{signal:r,headers:{Range:`bytes=${n[0]}-${n[1]-1}`}}:{signal:r});if(i.status===404)throw new e(`http 404 for ${t}`);if(i.status!==200&&i.status!==206)throw Error(`http ${i.status} for ${t}`);let a=new Uint8Array(await i.arrayBuffer());return n&&i.status===200?a.slice(n[0],n[1]):a},n=.28209479177387814,r=15.625,i=`GMIX`,a={position:0,alpha:6,rotationIndex:7,rotation:8,scale:11,dc:14,label:17},o={origin:0,step:3,scaleMin:6,scaleMax:9,dcMin:12,dcMax:15,shScale:18};async function s(e,t){let n=new ReadableStream({start(t){t.enqueue(e),t.close()}}).pipeThrough(t);return new Uint8Array(await new Response(n).arrayBuffer())}function c(e){return s(e,new DecompressionStream(`deflate-raw`))}function l(e){return s(e,new CompressionStream(`deflate-raw`))}async function u(e,t,n){let r=new DataView(e.buffer,e.byteOffset,e.byteLength);if(e.length<8||String.fromCharCode(...e.subarray(0,4))!==t)throw Error(`not a ${n} file`);let i=r.getUint16(4,!0);if(i!==1)throw Error(`${n} version ${i}; narcissus reads 1`);let a;try{a=await c(e.subarray(8))}catch{throw Error(`${n} body is not a valid deflate stream`)}return new DataView(a.buffer,a.byteOffset,a.byteLength)}function d(e,t){let n=``;for(let r=0;r<8;r++){let i=e.getUint8(t+r);n+=i.toString(16).padStart(2,`0`)}return n}function f(e,t){let n=/* @__PURE__ */ new Float32Array(6);for(let r=0;r<6;r++)n[r]=e.getFloat32(t+20+4*r,!0);return{g:e.getUint8(t),i:e.getUint8(t+1),j:e.getUint8(t+2),count:e.getUint32(t+4,!0),quadrants:[e.getUint32(t+8,!0),e.getUint32(t+12,!0),e.getUint32(t+16,!0)],box:n,offset:e.getUint32(t+44,!0),length:e.getUint32(t+48,!0)}}async function p(e){let t=await u(e,i,`.idx`);if(t.byteLength<40)throw Error(`.idx header is cut off`);let n=t.getUint16(32,!0),r=t.getUint8(34),a=t.getUint16(36,!0),o=40+n*52+r*9+a*11;if(t.byteLength!==o)throw Error(`.idx holds ${t.byteLength} bytes, its counts need ${o}`);let s=d(t,24),c={level:t.getUint8(0),e:t.getInt32(4,!0),n:t.getInt32(8,!0),pack:d(t,12),packSize:t.getUint32(20,!0),col:s===`0000000000000000`?null:s,rows:[],children:[],descendants:[]},l=40;for(let e=0;e<n;e++,l+=52)c.rows.push(f(t,l));for(let e=0;e<r;e++,l+=9)c.children.push({quadrant:t.getUint8(l),idx:d(t,l+1)});for(let e=0;e<a;e++,l+=11)c.descendants.push({depth:t.getUint8(l),column:t.getUint8(l+1),row:t.getUint8(l+2),idx:d(t,l+3)});return c}function m(e,t,n){return`u/${e.level}/${e.e}/${e.n}.${t}.${n}`}let h=/(?:^|\\/)u\\/(\\d+)\\/(-?\\d+)\\/(-?\\d+)\\.([0-9a-f]{16})\\.(?:idx|pack|col)$/;function g(e){let t=h.exec(e);return t?{level:Number(t[1]),e:Number(t[2]),n:Number(t[3]),hash:t[4]}:null}async function _(e){let t=await u(e,`GMCL`,`.col`);if(t.byteLength<60)throw Error(`.col header is cut off`);let n=t.getUint16(0,!0),r=60+12*n*n;if(t.byteLength!==r)throw Error(`.col holds ${t.byteLength} bytes, ${n} nodes need ${r}`);let i=new Float32Array(12*n*n),a=60;for(let e=0;e<12;e++){let r=t.getFloat32(12+4*e,!0)/127;for(let o=0;o<n;o++){let s=0;for(let c=0;c<n;c++,a++)s=s+t.getInt8(a)<<24>>24,i[(e*n+o)*n+c]=s*r}}return{n,pitch:t.getFloat32(4,!0),margin:t.getFloat32(8,!0),values:i}}function v(e,t,n,r){let{n:i,pitch:a,margin:o,values:s}=e,c=i-1,l=Math.min(Math.max((t+o)/a-.5,0),c),u=Math.min(Math.max((n+o)/a-.5,0),c),d=Math.min(Math.floor(l),Math.max(c-1,0)),f=Math.min(Math.floor(u),Math.max(c-1,0)),p=Math.min(d+1,c),m=Math.min(f+1,c),h=l-d,g=u-f,_=(1-h)*(1-g),v=h*(1-g),y=(1-h)*g,b=h*g,x=i*i;for(let e=0,t=0;e<12;e++,t+=x)r[e]=s[t+f*i+d]*_+s[t+f*i+p]*v+s[t+m*i+d]*y+s[t+m*i+p]*b;return r}let y=Float64Array.from({length:256},(e,t)=>(t/255-.5)*Math.SQRT2);function b(e,t,n,r,i){let a=y[t],o=y[n],s=y[r];i[e]=Math.sqrt(Math.max(0,1-a*a-o*o-s*s)),i[e>0?0:1]=a,i[e>1?1:2]=o,i[e>2?2:3]=s}function x(e,t,n,r,i){let a=e[0],o=e[1],s=e[2],c=e[3],l=t*t,u=n*n,d=r*r,f=1-2*(s*s+c*c),p=2*(o*s-a*c),m=2*(o*c+a*s),h=2*(o*s+a*c),g=1-2*(o*o+c*c),_=2*(s*c-a*o),v=2*(o*c-a*s),y=2*(s*c+a*o),b=1-2*(o*o+s*s);i[0]=3*Math.sqrt(f*f*l+p*p*u+m*m*d),i[1]=3*Math.sqrt(h*h*l+g*g*u+_*_*d),i[2]=3*Math.sqrt(v*v*l+y*y*u+b*b*d)}function S(e){if(e.length<128)throw Error(`page payload is shorter than its header`);return new DataView(e.buffer,e.byteOffset,e.byteLength)}function C(e){let t=S(e),n=t.getUint32(0,!0),r=t.getUint16(16,!0),i=128+(17+(r>0?2:0))*n,a=i+r*9;if(e.length!==a)throw Error(`page payload holds ${e.length} bytes, its header needs ${a}`);return{view:t,count:n,k:r,book:i}}function w(e){return[e.getUint32(4,!0),e.getUint32(8,!0),e.getUint32(12,!0)]}function T(e,t){let{view:n,count:r,k:i,book:s}=C(e),c=/* @__PURE__ */ new Float32Array(27);for(let e=0;e<27;e++)c[e]=n.getFloat32(20+4*e,!0);i===0&&c.fill(0,o.shScale);let l=new Uint32Array(r*4),u=new Float32Array(Math.ceil(r/256)*6),d=/* @__PURE__ */ new Float64Array(768);for(let e=0;e<3;e++){let t=c[o.scaleMin+e],n=c[o.scaleMax+e]-t;for(let r=0;r<256;r++)d[e*256+r]=Math.exp(t+r/255*n)}let f=c[o.step],p=c[o.step+1],m=c[o.step+2],h=128+a.position*r,g=128+a.alpha*r,_=128+a.rotationIndex*r,v=128+a.rotation*r,y=128+a.scale*r,S=/* @__PURE__ */ new Float64Array(4),T=/* @__PURE__ */ new Float64Array(3),O=0,k=0,A=0;for(let t=0,n=0;n<r;t++){let i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,C=-1/0;for(let t=Math.min(n+256,r);n<t;n++){let t=e[h+n]|e[h+r+n]<<8;O=O+(t>>>1^-(t&1))&65535,t=e[h+2*r+n]|e[h+3*r+n]<<8,k=k+(t>>>1^-(t&1))&65535,t=e[h+4*r+n]|e[h+5*r+n]<<8,A=A+(t>>>1^-(t&1))&65535;let u=e[_+n],w=e[v+n],E=e[v+r+n],D=e[v+2*r+n],j=e[y+n],M=e[y+r+n],N=e[y+2*r+n],P=n*4;l[P]=O|k<<16,l[P+1]=A|e[g+n]<<16|u<<24,l[P+2]=w|E<<8|D<<16|j<<24,l[P+3]=M|N<<8,b(u,w,E,D,S),x(S,d[j],d[256+M],d[512+N],T);let F=O*f,I=k*p,L=A*m;i=Math.min(i,F-T[0]),a=Math.min(a,I-T[1]),o=Math.min(o,L-T[2]),s=Math.max(s,F+T[0]),c=Math.max(c,I+T[1]),C=Math.max(C,L+T[2])}u.set([i,a,o,s,c,C],t*6)}let j=t?D(e,r,i,s,l,c,t):E(e,r,i,s);return{count:r,quadrants:w(n),geometry:l,colour:j,params:c,clusters:u}}function E(e,t,n,r){let i=new Uint32Array(t*3),o=128+a.dc*t,s=128+a.label*t;for(let a=0;a<t;a++){let c=a*3;if(i[c]=e[o+a]|e[o+t+a]<<8|e[o+2*t+a]<<16,n===0)continue;let l=r+(e[s+a]|e[s+t+a]<<8)*9;i[c]|=e[l]<<24,i[c+1]=e[l+1]|e[l+2]<<8|e[l+3]<<16|e[l+4]<<24,i[c+2]=e[l+5]|e[l+6]<<8|e[l+7]<<16|e[l+8]<<24}return i}function D(e,t,r,i,s,c,l){let u=128+a.dc*t,d=128+a.label*t,f=new Int8Array(e.buffer,e.byteOffset+i,r*9),p=new Float32Array(t*3),m=new Float32Array(t*9),h=[1/0,1/0,1/0],g=[-1/0,-1/0,-1/0],_=/* @__PURE__ */ new Float32Array(9),y=/* @__PURE__ */ new Float32Array(12),b=c[o.origin],x=c[o.origin+1],S=c[o.step],C=c[o.step+1],w=/* @__PURE__ */ new Float64Array(768);for(let e=0;e<3;e++){let t=c[o.dcMin+e],n=c[o.dcMax+e]-t;for(let r=0;r<256;r++)w[e*256+r]=t+r/255*n}let T=new Float64Array(Math.max(r,1)*9);for(let e=0;e<r*9;e++)T[e]=f[e]/127*c[o.shScale+e%9];for(let i=0;i<t;i++){let a=s[i*4];v(l,b+(a&65535)*S,x+(a>>>16)*C,y);for(let r=0;r<3;r++){let a=i*3+r;p[a]=w[r*256+e[u+r*t+i]]+y[r]/n,h[r]=Math.min(h[r],p[a]),g[r]=Math.max(g[r],p[a])}let o=r>0?(e[d+i]|e[d+t+i]<<8)*9:0;for(let e=0;e<9;e++){let t=i*9+e;m[t]=T[o+e]+y[3+e],_[e]=Math.max(_[e],Math.abs(m[t]))}}for(let e=0;e<3;e++)c[o.dcMin+e]=t>0?h[e]:0,c[o.dcMax+e]=t>0?g[e]:0;c.set(_,o.shScale);let E=[0,1,2].map(e=>{let t=c[o.dcMax+e]-c[o.dcMin+e];return t>0?255/t:0}),D=Array.from(_,e=>e>0?127/e:0),O=[0,1,2].map(e=>c[o.dcMin+e]),k=new Uint32Array(t*3),A=new Uint8Array(k.buffer);for(let e=0;e<t;e++){let t=e*4*3;for(let n=0;n<3;n++){let r=Math.round((p[e*3+n]-O[n])*E[n]);A[t+n]=Math.min(255,Math.max(0,r))}for(let n=0;n<9;n++){let r=Math.round(m[e*9+n]*D[n]);A[t+3+n]=Math.min(127,Math.max(-127,r))}}return k}let O=(e,t,n)=>Math.min(n,Math.max(t,e));function k(e,t,n){return n>t?O(Math.round((e-t)/(n-t)*255),0,255):0}function A(e,t){return t>0?O(Math.round(e/t*127),-127,127):0}function j(e){return e&=1023,e=(e|e<<16)&50331903,e=(e|e<<8)&50393103,e=(e|e<<4)&51130563,(e|e<<2)&153391689}function M(e,t,n){return j(e>>6)|j(t>>6)<<1|j(n>>6)<<2}function N(e,t){let n=/* @__PURE__ */ new Float32Array(9);for(let r=0;r<t;r++)for(let t=0;t<9;t++)n[t]=Math.max(n[t],Math.abs(e[r*9+t]));return n}function P(e,t,n){let r=new Int8Array(t*9);for(let i=0;i<t;i++)for(let t=0;t<9;t++)r[i*9+t]=A(e[i*9+t],n[t]);let i=e=>r.subarray(e*9,(e+1)*9),a=/* @__PURE__ */ new Map,o=[],s=new Uint16Array(t);for(let e=0;e<t;e++){let t=i(e).join(),n=a.get(t);n===void 0&&(n=o.length,a.set(t,n),o.push(e)),s[e]=n}if(o.length>2048){let e=o.length/256,n=Array.from({length:256},(t,n)=>o[Math.floor(n*e)]);o.splice(0,o.length,...n);for(let e=0;e<t;e++){let t=1/0;for(let n=0;n<256;n++){let i=0;for(let t=0;t<9;t++)i+=(r[e*9+t]-r[o[n]*9+t])**2;i<t&&(t=i,s[e]=n)}}}let c=new Int8Array(o.length*9);return o.forEach((e,t)=>c.set(i(e),t*9)),{book:c,labels:s}}function F(e,t){let{count:n,position:i,rotation:o,scale:s,alpha:c,dc:l,sh:u}=e,d=[1/0,1/0,1/0],f=[-1/0,-1/0,-1/0],p=[...d],m=[...f],h=[...d],g=[...f];for(let e=0;e<n;e++)for(let t=0;t<3;t++)d[t]=Math.min(d[t],i[e*3+t]),f[t]=Math.max(f[t],i[e*3+t]),p[t]=Math.min(p[t],s[e*3+t]),m[t]=Math.max(m[t],s[e*3+t]),h[t]=Math.min(h[t],l[e*3+t]),g[t]=Math.max(g[t],l[e*3+t]);let _=5e-4*2**t.g,v=Float32Array.from(d),y=Float32Array.from(d,(e,t)=>Math.max(_,(f[t]-e)/65535)),b=new Uint16Array(n*3);for(let e=0;e<n;e++)for(let t=0;t<3;t++){let n=(i[e*3+t]-v[t])/y[t];b[e*3+t]=O(Math.round(n),0,65535)}let S=r*2**t.g,C=(t.i+.5)*S,w=(t.j+.5)*S,T=new Uint8Array(n),E=new Float64Array(n);for(let e=0;e<n;e++){let t=+(i[e*3]>=C),n=+(i[e*3+1]>=w);T[e]=t+2*n,E[e]=T[e]*2**30+M(b[e*3],b[e*3+1],b[e*3+2])}let D=Uint32Array.from({length:n},(e,t)=>t).sort((e,t)=>E[e]-E[t]),A=[0,0,0];for(let e=1;e<4;e++)A[e-1]=T.filter(t=>t<e).length;let j=u?N(u,n):/* @__PURE__ */ new Float32Array(9),{book:F,labels:I}=u?P(u,n,j):{book:null,labels:null},L=F?F.length/9:0,R=17+(L>0?2:0),z=new Uint8Array(128+R*n+L*9),B=new DataView(z.buffer);B.setUint32(0,n,!0),A.forEach((e,t)=>B.setUint32(4+4*t,e,!0)),B.setUint16(16,L,!0),[...v,...y,...p,...m,...h,...g,...j].forEach((e,t)=>B.setFloat32(20+4*t,e,!0));let V=e=>128+e*n,H=new Float32Array([...d,...f]),U=/* @__PURE__ */ new Float64Array(4),W=/* @__PURE__ */ new Float64Array(3),G=[0,0,0];for(let e=0;e<n;e++){let t=D[e];for(let n=0;n<3;n++){let r=b[t*3+n]-G[n]<<16>>16,i=r<0?-2*r-1:2*r;G[n]=b[t*3+n],z[V(a.position+2*n)+e]=i&255,z[V(a.position+2*n+1)+e]=i>>8}z[V(a.alpha)+e]=O(Math.round(c[t]*255),0,255);let n=Math.hypot(...o.subarray(t*4,t*4+4));for(let e=0;e<4;e++)U[e]=o[t*4+e]/n;let r=0;for(let e=1;e<4;e++)Math.abs(U[e])>Math.abs(U[r])&&(r=e);let u=U[r]<0?-1:1;z[V(a.rotationIndex)+e]=r;for(let t=0,n=0;t<4;t++){if(t===r)continue;let i=Math.round((u*U[t]/Math.SQRT2+.5)*255);z[V(a.rotation+n++)+e]=O(i,0,255)}for(let n=0;n<3;n++)z[V(a.scale+n)+e]=k(s[t*3+n],p[n],m[n]),z[V(a.dc+n)+e]=k(l[t*3+n],h[n],g[n]);I&&(z[V(a.label)+e]=I[t]&255,z[V(a.label+1)+e]=I[t]>>8);let[d,f,_]=[0,1,2].map(e=>Math.exp(s[t*3+e]));x(U,d,f,_,W);for(let e=0;e<3;e++)H[e]=Math.min(H[e],i[t*3+e]-W[e]),H[3+e]=Math.max(H[3+e],i[t*3+e]+W[e])}return F&&z.set(new Uint8Array(F.buffer),V(R)),{payload:z,row:{g:t.g,i:t.i,j:t.j,count:n,quadrants:A,box:H,offset:0,length:0}}}function I(e,t,n){e.setUint8(t,n.g),e.setUint8(t+1,n.i),e.setUint8(t+2,n.j),e.setUint32(t+4,n.count,!0),n.quadrants.forEach((n,r)=>e.setUint32(t+8+4*r,n,!0)),n.box.forEach((n,r)=>e.setFloat32(t+20+4*r,n,!0)),e.setUint32(t+44,n.offset,!0),e.setUint32(t+48,n.length,!0)}function L(e,t,n){for(let r=0;r<4;r++)e[t+r]=n.charCodeAt(r)}function R(e){return Uint8Array.from({length:8},(t,n)=>parseInt(e.slice(2*n,2*n+2),16))}async function z(e,t){let n=await l(e),r=new Uint8Array(8+n.length);return L(r,0,t),new DataView(r.buffer).setUint16(4,1,!0),r.set(n,8),r}async function B(e){let{rows:t,children:n,descendants:r}=e,a=new Uint8Array(40+t.length*52+n.length*9+r.length*11),o=new DataView(a.buffer);o.setUint8(0,e.level),o.setInt32(4,e.e,!0),o.setInt32(8,e.n,!0),a.set(R(e.pack),12),o.setUint32(20,e.packSize,!0),e.col&&a.set(R(e.col),24),o.setUint16(32,t.length,!0),o.setUint8(34,n.length),o.setUint16(36,r.length,!0);let s=40;for(let e of t)I(o,s,e),s+=52;for(let e of n)o.setUint8(s,e.quadrant),a.set(R(e.idx),s+1),s+=9;for(let e of r)o.setUint8(s,e.depth),o.setUint8(s+1,e.column),o.setUint8(s+2,e.row),a.set(R(e.idx),s+3),s+=11;return z(a,i)}function V(e){let t=3421674724,n=2216829733;for(let r=0;r<e.length;r++){n=(n^e[r])>>>0;let i=n*435;t=t*435+(n<<8>>>0)+Math.floor(i/4294967296)>>>0,n=i>>>0}return t.toString(16).padStart(8,`0`)+n.toString(16).padStart(8,`0`)}function H(e){return()=>{e=e+1831565813|0;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/2**32}}async function U(e,t){return p(await G(e,t))}async function*W(e,t,n,r){let i=t.col===null?null:te(e,t.col,n),a=await ee(e,t,r),o=await i;for(let[e,n]of t.pages.entries()){let t=await c(a[e]);r?.throwIfAborted(),yield{id:n.id,page:T(t,o)}}}async function G(e,t){let n=await e.cache.get(t);if(n)return n;let r=await e.fetch(e.base+t,null);return e.cache.put(t,r),r}async function ee(e,t,n){let r=t.pages.map(e=>`${t.pack}#${e.offset}+${e.length}`),i=await Promise.all(r.map(t=>e.cache.get(t)));if(n?.throwIfAborted(),i.every(e=>e!==void 0))return i;let a=await e.fetch(e.base+t.pack,[t.start,t.end],n);if(a.length!==t.end-t.start)throw Error(`${t.pack}: ${a.length} bytes for ${t.start}-${t.end}`);return t.pages.map((n,o)=>{let s=a.slice(n.offset-t.start,n.offset-t.start+n.length);return i[o]||e.cache.put(r[o],s),s})}function te(e,t,n){let r=n.get(t);if(r)n.delete(t);else{let i=G(e,t).then(_);i.catch(()=>{n.get(t)===i&&n.delete(t)}),r=i}if(n.set(t,r),n.size>64){let[e]=n.keys();n.delete(e)}return r}function ne(e){let t=/* @__PURE__ */ new Map,n=0;return{async get(e){let n=t.get(e);return n&&(t.delete(e),t.set(e,n)),n},async put(r,i){let a=t.get(r);if(a&&(t.delete(r),n-=a.length),!(i.length>e)){t.set(r,i),n+=i.length;for(let[r,i]of t){if(n<=e)break;t.delete(r),n-=i.length}}}}}async function re(e,t){let n;try{n=await(await ae()).getDirectoryHandle(String(t),{create:!0})}catch{return null}let r=/* @__PURE__ */ new Map,i=0,a=!1,o=(e,t)=>{i+=t-(r.get(e)??0),r.delete(e),r.set(e,t)},s=e=>{i-=r.get(e)??0,r.delete(e)},c=()=>{if(a)for(let[t,a]of r){if(i<=e)break;r.delete(t),i-=a,n.removeEntry(t).catch(()=>void 0)}};return ce(n).then(e=>{let t=[...r];r.clear(),i=0;for(let{name:t,size:n}of e.sort((e,t)=>e.time-t.time))o(t,n);for(let[e,n]of t)o(e,n);a=!0,c()}),{async get(e){let t=encodeURIComponent(e);if(a&&!r.has(t))return;let i=await oe(n,t);return i?o(t,i.length):s(t),i},async put(t,r){if(r.length===0||r.length>e)return;let i=encodeURIComponent(t);await se(n,i,r)&&(o(i,r.length),c())}}}async function ie(e){let t=new Set(Array.from({length:e},(e,t)=>String(t)));try{let e=await ae(),n=[];for await(let[r,i]of e.entries())(i.kind!==`directory`||!t.has(r))&&n.push(r);let r={recursive:!0};for(let t of n)await e.removeEntry(t,r).catch(()=>void 0)}catch{}}async function ae(){return(await navigator.storage.getDirectory()).getDirectoryHandle(`cache`,{create:!0})}async function oe(e,t){try{let n=await(await e.getFileHandle(t)).getFile();return n.size>0?new Uint8Array(await n.arrayBuffer()):void 0}catch{return}}async function se(e,t,n){let r;try{return r=await(await e.getFileHandle(t,{create:!0})).createWritable(),await r.write(n),await r.close(),!0}catch{return r?.abort().catch(()=>void 0),!1}}async function ce(e){let t=[];try{for await(let[n,r]of e.entries()){if(r.kind!==`file`)continue;let e=await r.getFile().catch(()=>null);e&&t.push({name:n,size:e.size,time:e.lastModified})}}catch{}return t}function le(t){let n=/* @__PURE__ */ new Map,r=0;return{fetch:(i,a,o)=>new Promise((s,c)=>{if(o?.aborted)return c(o.reason);let l=++r,u=()=>{n.delete(l),t({unfetch:l}),c(o.reason)};n.set(l,t=>{o?.removeEventListener(`abort`,u),`bytes`in t?s(t.bytes):c(t.missing?new e(t.error):Error(t.error))}),o?.addEventListener(`abort`,u,{once:!0}),t({fetch:l,url:i,range:a})}),take(e){let t=n.get(e.fetched);n.delete(e.fetched),t?.(e)}}}let K=16384,ue=1408,de=65535,q=324121,fe=.4,pe=[[12,1/7e3,0,1/9e3,.7],[9,1/2300,1.1,1/3100,.4],[6,1/800,.3,1/1100,2],[3,1/150,.9,1/210,1.7]],me=pe.reduce((e,[t,n,,r])=>e+t*(n+r),0),he=Float32Array.from({length:ue*9},(e,t)=>{let n=Math.floor(t/9),r=t%9,i=(n*(37+2*r)+11*r)%255-127;return r===0&&(i=n%255-127),r===1&&(i=20*Math.floor(n/255)-50),i/127*.04}),J=new TextEncoder,ge={version:1,crs:`synthetic`,height:`synthetic`,leaf:250,roots:[512e4,6144e3].map(e=>({level:12,e:0,n:e})).map(e=>({...e,idx:m(e,Y(e,`idx`),`idx`)})),extent:{e:[44e4,9e5],n:[605e4,641e4],h:[0,80]}},_e=J.encode(JSON.stringify(ge));function ve(){return async(t,n)=>{if(t.endsWith(`world.json`))return be(_e,n);let r=g(t),i=t.slice(t.lastIndexOf(`.`)+1);if(!r||i!==`idx`&&i!==`pack`||!xe(r)||r.hash!==Y(r,i))throw new e(`no file ${t}`);return i===`idx`?be(await De(r),n):Oe(r,n,t)}}function ye(e,t){let n=30;for(let[r,i,a,o,s]of pe)n+=r*Math.sin(i*e+a)*Math.sin(o*t+s);return n}function be(e,t){return t?e.slice(t[0],t[1]):e.slice()}function Y(e,t){return V(J.encode(`${e.level}/${e.e}/${e.n}.${t}`))}function X(e,t,n){let{e:r,n:i}=ge.extent;return e<r[1]&&e+n>r[0]&&t<i[1]&&t+n>i[0]}function xe({level:e,e:t,n}){let r=250*2**e;return e<=12&&t%r===0&&n%r===0&&X(t,n,r)}function Se(e){return e===0?[1,0]:e===12?[16,15,14,13]:[e+1]}function Ce(e){let t=0;for(let n=0;n<8;n++)t|=(e>>2*n&1)<<n;return t}function we(e){let t=[];for(let n of Se(e.level)){let i=r*2**n,a=250*2**e.level/i;for(let r=0;r<a*a;r++){let a=Ce(r),o=Ce(r>>1);X(e.e+a*i,e.n+o*i,i)&&t.push({g:n,i:a,j:o})}}return t}function Te(e,t){let n=e.level-t,r=250*2**n,i=[];for(let a=0;n>=0&&a<2**t;a++)for(let o=0;o<2**t;o++){let t={level:n,e:e.e+o*r,n:e.n+a*r};X(t.e,t.n,r)&&i.push({column:o,row:a,unit:t})}return i}function Ee(e,{g:t,i:n,j:i},a){let o=r*2**t,s=o/128,c=3*1.2*s,l=1.17*s,u=ye(e.e+(n+.5)*o,e.n+(i+.5)*o),d=me*o/2,f=Float32Array.of(n*o-c,i*o-c,Math.max(0,u-d)-l,(n+1)*o+c,(i+1)*o+c,Math.min(60,u+d)+l),p=K/4;return{g:t,i:n,j:i,count:K,quadrants:[p,2*p,3*p],box:f,offset:a,length:q}}function De(e){let t=we(e),n=[];for(let{column:t,row:r,unit:i}of Te(e,1))n.push({quadrant:t+2*r,idx:Y(i,`idx`)});let r=[];for(let t of[2,3])for(let{column:n,row:i,unit:a}of Te(e,t))r.push({depth:t,column:n,row:i,idx:Y(a,`idx`)});return B({level:e.level,e:e.e,n:e.n,pack:Y(e,`pack`),packSize:t.length*324173+16,col:null,rows:t.map((t,n)=>Ee(e,t,n*q)),children:n,descendants:r})}function Oe(e,t,n){let r=we(e);if(!t||t[0]%q!=0||t[1]%q!=0||t[0]>=t[1]||t[1]>r.length*q)throw Error(`${n}: the synthetic world serves whole pages only`);let i=new Uint8Array(t[1]-t[0]);for(let n=0;n<i.length;n+=q)ke(je(e,r[(t[0]+n)/q]),i,n);return i}function ke(e,t,n){let r=n;for(let n=0;n<e.length;n+=de){let i=Math.min(de,e.length-n);t[r]=+(n+i===e.length),t[r+1]=i&255,t[r+2]=i>>8,t[r+3]=~i&255,t[r+4]=~i>>8&255,t.set(e.subarray(n,n+i),r+5),r+=5+i}}let Ae=e=>H(parseInt(V(J.encode(e)).slice(8),16));function je(e,{g:t,i,j:a}){let o=K,s=r*2**t/128,c=Ae(`${e.level}/${e.e}/${e.n}/${t}/${i}/${a}`),l=new Float64Array(3*o),u=new Float32Array(4*o),d=new Float32Array(3*o),f=new Float32Array(o),p=new Float32Array(3*o),m=new Float32Array(9*o);for(let t=0;t<o;t++){let r=(i*128+t%128+.5+fe*(2*c()-1))*s,o=(a*128+Math.floor(t/128)+.5+fe*(2*c()-1))*s,h=ye(e.e+r,e.n+o);l[3*t]=r,l[3*t+1]=o,l[3*t+2]=h;let g=Math.PI*c(),_=.1/2*(2*c()-1);u[4*t]=Math.cos(g)*Math.cos(_),u[4*t+1]=Math.cos(g)*Math.sin(_),u[4*t+2]=Math.sin(g)*Math.sin(_),u[4*t+3]=Math.sin(g)*Math.cos(_);for(let e=0;e<2;e++)d[3*t+e]=Math.log(s*(.6+.6*c()));d[3*t+2]=Math.log(s*.15*(.5+.5*c())),f[t]=.35+.65*c();let v=h/60,y=.5+.5*Math.sin((e.e+r)/410)*Math.sin((e.n+o)/330);p[3*t]=(.32+.2*v+.1*y-.5)/n,p[3*t+1]=(.42+.15*y-.1*v-.5)/n,p[3*t+2]=(.25+.1*v+.04*c()-.5)/n;let b=t%ue;m.set(he.subarray(9*b,9*(b+1)),9*t)}return F({count:o,position:l,rotation:u,scale:d,alpha:f,dc:p,sh:m},{g:t,i,j:a}).payload}let Z=2**20,Q=self,$,Me=/* @__PURE__ */ new Map,Ne=/* @__PURE__ */ new Map,Pe=le(e=>Q.postMessage(e,[]));Q.onmessage=({data:e})=>{`fetched`in e?Pe.take(e):e.type===`init`?($=Fe(e),$.catch(()=>void 0)):e.type===`abort`?Ne.get(e.id)?.abort():Re(e)};async function Fe(e){return e.source===`synthetic`?{fetch:ve(),cache:await Ie({...e,cache:`none`}),base:e.base}:{fetch:e.source===`page`?Pe.fetch:t,cache:await Ie(e),base:e.base}}async function Ie({cache:e,shard:t,shards:n}){return e===`memory`?ne(256*Z):e===`none`?{get:async()=>void 0,put:async()=>void 0}:(t===0&&ie(n),await re(await Le()/n,t)??ne(256*Z))}async function Le(){try{let{quota:e}=await navigator.storage.estimate();return Math.min(4096*Z,e===void 0?1/0:e/2)}catch{return 4096*Z}}async function Re(t){let{id:n}=t,r=new AbortController;Ne.set(n,r);try{if(!$)throw Error(`stream worker used before init`);let e=await $;if(t.type===`idx`)Q.postMessage({id:n,value:await U(e,t.path)},[]);else{for await(let i of W(e,t.batch,Me,r.signal))Q.postMessage({id:n,page:i},ze(i));Q.postMessage({id:n,done:!0},[])}}catch(t){let r=t instanceof Error?t.message:String(t);Q.postMessage({id:n,error:r,missing:t instanceof e},[])}finally{Ne.delete(n)}}function ze({page:e}){let t=/* @__PURE__ */ new Set;for(let n of[e.geometry,e.colour,e.params,e.clusters])t.add(n.buffer);return[...t]}})();", Bt = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", zt], { type: "text/javascript;charset=utf-8" });
|
|
2353
|
+
function Vt(e) {
|
|
2354
|
+
let t;
|
|
2355
|
+
try {
|
|
2356
|
+
if (t = Bt && (self.URL || self.webkitURL).createObjectURL(Bt), !t) throw "";
|
|
2357
|
+
let n = new Worker(t, { name: e?.name });
|
|
2358
|
+
return n.addEventListener("error", () => {
|
|
2359
|
+
(self.URL || self.webkitURL).revokeObjectURL(t);
|
|
2360
|
+
}), n;
|
|
2361
|
+
} catch {
|
|
2362
|
+
return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(zt), { name: e?.name });
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
//#endregion
|
|
2366
|
+
//#region src/engine/stream/loader.ts
|
|
2367
|
+
var Ht = class {
|
|
2368
|
+
#e;
|
|
2369
|
+
#t = /* @__PURE__ */ new Map();
|
|
2370
|
+
#n = 0;
|
|
2371
|
+
constructor(e) {
|
|
2372
|
+
let { base: t, cache: n, source: r, workers: i } = e;
|
|
2373
|
+
this.#e = Array.from({ length: i }, (e, a) => {
|
|
2374
|
+
let o = new Vt(), s = { worker: o }, c = typeof r == "function" ? Rt(r, (e, t) => o.postMessage(e, t)) : void 0;
|
|
2375
|
+
o.onmessage = ({ data: e }) => {
|
|
2376
|
+
"id" in e ? this.#i(e) : c?.(e);
|
|
2377
|
+
}, o.onerror = () => this.#a(s);
|
|
2378
|
+
let l = {
|
|
2379
|
+
type: "init",
|
|
2380
|
+
base: t,
|
|
2381
|
+
cache: n,
|
|
2382
|
+
source: typeof r == "function" ? "page" : r,
|
|
2383
|
+
shard: a,
|
|
2384
|
+
shards: i
|
|
2385
|
+
};
|
|
2386
|
+
return o.postMessage(l), s;
|
|
2387
|
+
});
|
|
2388
|
+
}
|
|
2389
|
+
idx(e) {
|
|
2390
|
+
let t = {
|
|
2391
|
+
type: "idx",
|
|
2392
|
+
id: ++this.#n,
|
|
2393
|
+
path: e
|
|
2394
|
+
};
|
|
2395
|
+
return this.#r(this.#e[0], t);
|
|
2396
|
+
}
|
|
2397
|
+
batch(e, t, n) {
|
|
2398
|
+
if (t.aborted) return Promise.reject(Wt());
|
|
2399
|
+
let r = this.#e[Ut(`${e.pack}#${e.window}`, this.#e.length)], i = {
|
|
2400
|
+
type: "batch",
|
|
2401
|
+
id: ++this.#n,
|
|
2402
|
+
batch: e
|
|
2403
|
+
};
|
|
2404
|
+
return this.#r(r, i, t, n);
|
|
2405
|
+
}
|
|
2406
|
+
destroy() {
|
|
2407
|
+
for (let { worker: e } of this.#e) e.terminate();
|
|
2408
|
+
for (let e of this.#t.values()) e.reject(Wt());
|
|
2409
|
+
}
|
|
2410
|
+
#r(e, t, n, r) {
|
|
2411
|
+
if (e.error) return Promise.reject(e.error);
|
|
2412
|
+
let { id: i } = t;
|
|
2413
|
+
return new Promise((a, o) => {
|
|
2414
|
+
let s = () => {
|
|
2415
|
+
this.#t.delete(i), n?.removeEventListener("abort", c);
|
|
2416
|
+
}, c = () => {
|
|
2417
|
+
s(), e.worker.postMessage({
|
|
2418
|
+
type: "abort",
|
|
2419
|
+
id: i
|
|
2420
|
+
}), o(Wt());
|
|
2421
|
+
};
|
|
2422
|
+
this.#t.set(i, {
|
|
2423
|
+
slot: e,
|
|
2424
|
+
page: r,
|
|
2425
|
+
resolve: (e) => {
|
|
2426
|
+
s(), a(e);
|
|
2427
|
+
},
|
|
2428
|
+
reject: (e) => {
|
|
2429
|
+
s(), o(e);
|
|
2430
|
+
}
|
|
2431
|
+
}), n?.addEventListener("abort", c, { once: !0 }), e.worker.postMessage(t);
|
|
2432
|
+
});
|
|
2433
|
+
}
|
|
2434
|
+
#i(e) {
|
|
2435
|
+
let t = this.#t.get(e.id);
|
|
2436
|
+
t && ("page" in e ? t.page?.(e.page) : "error" in e ? t.reject(e.missing ? new l(e.error) : Error(e.error)) : t.resolve("value" in e ? e.value : void 0));
|
|
2437
|
+
}
|
|
2438
|
+
#a(e) {
|
|
2439
|
+
e.error = /* @__PURE__ */ Error("a stream worker failed");
|
|
2440
|
+
for (let t of this.#t.values()) t.slot === e && t.reject(e.error);
|
|
2441
|
+
}
|
|
2442
|
+
};
|
|
2443
|
+
function Ut(e, t) {
|
|
2444
|
+
let n = 2166136261;
|
|
2445
|
+
for (let t = 0; t < e.length; t++) n = Math.imul(n ^ e.charCodeAt(t), 16777619);
|
|
2446
|
+
return (n >>> 0) % t;
|
|
2447
|
+
}
|
|
2448
|
+
function Wt() {
|
|
2449
|
+
return new DOMException("The request was aborted.", "AbortError");
|
|
2450
|
+
}
|
|
2451
|
+
//#endregion
|
|
2452
|
+
//#region src/engine/engine.ts
|
|
2453
|
+
var Gt = class extends Error {
|
|
2454
|
+
constructor() {
|
|
2455
|
+
super("This viewer needs WebGPU. Update to the latest Chrome, Edge, Safari or Firefox."), this.name = "NoWebGpu";
|
|
2456
|
+
}
|
|
2457
|
+
};
|
|
2458
|
+
async function Kt(e, t) {
|
|
2459
|
+
let n = await g();
|
|
2460
|
+
if (!n) throw new Gt();
|
|
2461
|
+
let r = e.getContext("webgpu");
|
|
2462
|
+
if (!r) throw n.device.destroy(), new Gt();
|
|
2463
|
+
r.configure({
|
|
2464
|
+
device: n.device,
|
|
2465
|
+
format: n.format,
|
|
2466
|
+
alphaMode: "opaque"
|
|
2467
|
+
}), (t.cache ?? "opfs") === "opfs" && navigator.storage?.persist().catch(() => !1);
|
|
2468
|
+
let { source: i = "http" } = t;
|
|
2469
|
+
return new vn(e, n, r, t, i === "synthetic" ? (await import("./synthetic-DO8oIw_x.js")).synthetic() : i === "http" ? u : i);
|
|
2470
|
+
}
|
|
2471
|
+
var W = .2, qt = 25165824, Jt = 3.25, Yt = 2, Xt = 1024, Zt = 2048, Qt = 100, $t = 2, en = 300, tn = 100, nn = 250, rn = 300, an = 1e3, on = 400, sn = 5e3, cn = 60, G = Math.PI / 180, K = "The viewer was closed.", ln = "The layers hold more splats than this device can.", un = [
|
|
2472
|
+
1,
|
|
2473
|
+
1,
|
|
2474
|
+
1,
|
|
2475
|
+
1
|
|
2476
|
+
], dn = "Another world was opened.";
|
|
2477
|
+
function q(e, t) {
|
|
2478
|
+
let n = Math.min(t.maxStorageBufferBindingSize, t.maxBufferSize), r = (t, r) => {
|
|
2479
|
+
let i = Math.ceil(e * t / 256) * 256;
|
|
2480
|
+
return Math.min(i, Math.floor(n / r / 256) * 256);
|
|
2481
|
+
};
|
|
2482
|
+
return {
|
|
2483
|
+
pool: r(Jt, 16),
|
|
2484
|
+
frame: r(Yt, 24)
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
function fn(e, t) {
|
|
2488
|
+
let [n, r, i] = t;
|
|
2489
|
+
if (Math.hypot(n - e[0], r - e[1], i - e[2]) <= Zt) return e;
|
|
2490
|
+
let a = (e) => Math.round(e / Xt) * Xt;
|
|
2491
|
+
return [
|
|
2492
|
+
a(n),
|
|
2493
|
+
a(r),
|
|
2494
|
+
a(i)
|
|
2495
|
+
];
|
|
2496
|
+
}
|
|
2497
|
+
function pn(e, t, n, r, i, a) {
|
|
2498
|
+
let o = 2 * e[0] / t[0] - 1, s = 1 - 2 * e[1] / t[1], c = [
|
|
2499
|
+
n * o / r[0],
|
|
2500
|
+
n * s / r[5],
|
|
2501
|
+
-n
|
|
2502
|
+
], [l, u, d] = oe(ae(/* @__PURE__ */ new Float64Array(16), i), c);
|
|
2503
|
+
return [
|
|
2504
|
+
l + a[0],
|
|
2505
|
+
u + a[1],
|
|
2506
|
+
d + a[2]
|
|
2507
|
+
];
|
|
2508
|
+
}
|
|
2509
|
+
function mn(e) {
|
|
2510
|
+
if (!e.length || !e.every((e) => e.length === 3 && e.every(Number.isFinite))) throw Error("Give at least one point, each three finite numbers.");
|
|
2511
|
+
return e;
|
|
2512
|
+
}
|
|
2513
|
+
function hn(e, t) {
|
|
2514
|
+
return [
|
|
2515
|
+
e.e - t[0],
|
|
2516
|
+
e.n - t[1],
|
|
2517
|
+
e.h - t[2]
|
|
2518
|
+
];
|
|
2519
|
+
}
|
|
2520
|
+
function gn(e, t) {
|
|
2521
|
+
e.push(t), e.length > cn && e.shift();
|
|
2522
|
+
}
|
|
2523
|
+
function _n({ visible: e, opacity: t }) {
|
|
2524
|
+
return e ? Math.round(t * 255) * 16843009 >>> 0 : 0;
|
|
2525
|
+
}
|
|
2526
|
+
var vn = class {
|
|
2527
|
+
#e;
|
|
2528
|
+
#t;
|
|
2529
|
+
#n;
|
|
2530
|
+
#r;
|
|
2531
|
+
#i;
|
|
2532
|
+
#a;
|
|
2533
|
+
#o;
|
|
2534
|
+
#s;
|
|
2535
|
+
#c;
|
|
2536
|
+
#l;
|
|
2537
|
+
#u = new ht();
|
|
2538
|
+
#d = new et();
|
|
2539
|
+
#f = (e) => this.#s.has(e);
|
|
2540
|
+
#p = null;
|
|
2541
|
+
#m = null;
|
|
2542
|
+
#h = null;
|
|
2543
|
+
#g = null;
|
|
2544
|
+
#_ = 0;
|
|
2545
|
+
#v = !1;
|
|
2546
|
+
#y = /* @__PURE__ */ new Map();
|
|
2547
|
+
#b = 0;
|
|
2548
|
+
#x = 0;
|
|
2549
|
+
#S = 0;
|
|
2550
|
+
#C = /* @__PURE__ */ new WeakMap();
|
|
2551
|
+
#w = !1;
|
|
2552
|
+
#T = /* @__PURE__ */ new Map();
|
|
2553
|
+
#E = 0;
|
|
2554
|
+
#D = !1;
|
|
2555
|
+
#O = {
|
|
2556
|
+
e: 0,
|
|
2557
|
+
n: 0,
|
|
2558
|
+
h: 0,
|
|
2559
|
+
yaw: 0,
|
|
2560
|
+
pitch: 0,
|
|
2561
|
+
fov: 45
|
|
2562
|
+
};
|
|
2563
|
+
#k = -Infinity;
|
|
2564
|
+
#A = [
|
|
2565
|
+
0,
|
|
2566
|
+
0,
|
|
2567
|
+
0
|
|
2568
|
+
];
|
|
2569
|
+
#j = [
|
|
2570
|
+
0,
|
|
2571
|
+
0,
|
|
2572
|
+
0
|
|
2573
|
+
];
|
|
2574
|
+
#M = /* @__PURE__ */ new Float64Array(16);
|
|
2575
|
+
#N = /* @__PURE__ */ new Float64Array(16);
|
|
2576
|
+
#P = /* @__PURE__ */ new Float64Array(16);
|
|
2577
|
+
#F = /* @__PURE__ */ new Float64Array(16);
|
|
2578
|
+
#I = /* @__PURE__ */ new Float32Array(24);
|
|
2579
|
+
#L;
|
|
2580
|
+
#R;
|
|
2581
|
+
#z = 0;
|
|
2582
|
+
#B = 0;
|
|
2583
|
+
#V = !1;
|
|
2584
|
+
#H = null;
|
|
2585
|
+
#U = -Infinity;
|
|
2586
|
+
#W = !0;
|
|
2587
|
+
#G = !0;
|
|
2588
|
+
#K = !1;
|
|
2589
|
+
#q = !1;
|
|
2590
|
+
#J = !1;
|
|
2591
|
+
#Y = [];
|
|
2592
|
+
#X = -Infinity;
|
|
2593
|
+
#Z = -Infinity;
|
|
2594
|
+
#Q = -Infinity;
|
|
2595
|
+
#$ = [];
|
|
2596
|
+
#ee = [];
|
|
2597
|
+
#te = [];
|
|
2598
|
+
#ne = [];
|
|
2599
|
+
#re = [];
|
|
2600
|
+
#ie = null;
|
|
2601
|
+
#ae = [];
|
|
2602
|
+
#oe = [];
|
|
2603
|
+
#se = /* @__PURE__ */ new Set();
|
|
2604
|
+
#ce = /* @__PURE__ */ new Set();
|
|
2605
|
+
#le = /* @__PURE__ */ new Set();
|
|
2606
|
+
#ue = {
|
|
2607
|
+
planned: 0,
|
|
2608
|
+
missing: 0,
|
|
2609
|
+
loading: !1
|
|
2610
|
+
};
|
|
2611
|
+
#de = !1;
|
|
2612
|
+
#fe = !1;
|
|
2613
|
+
#pe = !1;
|
|
2614
|
+
constructor(e, t, n, r, i) {
|
|
2615
|
+
this.#e = e, this.#t = t, this.#n = n, this.#r = r, this.#i = i, this.#a = { ...r.settings }, this.#o = this.#he(), this.#L = [
|
|
2616
|
+
e.width,
|
|
2617
|
+
e.height,
|
|
2618
|
+
1
|
|
2619
|
+
], this.#R = [Math.max(1, e.width), Math.max(1, e.height)];
|
|
2620
|
+
let { pool: a, frame: o } = q(this.#me, t.device.limits);
|
|
2621
|
+
this.#s = new ee(t.device, a), this.#c = new Ze(t, n, this.#s, o), this.#l = o, t.device.lost.then((e) => {
|
|
2622
|
+
if (!this.#fe) {
|
|
2623
|
+
this.#pe = !0, cancelAnimationFrame(this.#z);
|
|
2624
|
+
for (let t of this.#se) t(e.message || e.reason);
|
|
2625
|
+
}
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
async open(e) {
|
|
2629
|
+
if (this.#fe) throw Error(K);
|
|
2630
|
+
let t = ++this.#_, r = () => {
|
|
2631
|
+
if (this.#fe) throw Error(K);
|
|
2632
|
+
if (t !== this.#_) throw Error(dn);
|
|
2633
|
+
}, { cache: i = "opfs", source: o = "http" } = this.#r;
|
|
2634
|
+
o === "http" && (e = new URL(e, document.baseURI).href);
|
|
2635
|
+
let s = await this.#i(e, null), c = a(JSON.parse(new TextDecoder().decode(s)));
|
|
2636
|
+
r();
|
|
2637
|
+
let l = new Ht({
|
|
2638
|
+
base: n(e),
|
|
2639
|
+
workers: Math.min(6, Math.max(2, navigator.hardwareConcurrency - 2)),
|
|
2640
|
+
cache: i,
|
|
2641
|
+
source: o
|
|
2642
|
+
}), u = new ut(c);
|
|
2643
|
+
try {
|
|
2644
|
+
let e = await Promise.all(c.roots.map((e) => l.idx(e.idx)));
|
|
2645
|
+
r(), e.forEach((e, t) => u.add(e, c.roots[t].idx));
|
|
2646
|
+
} catch (e) {
|
|
2647
|
+
throw l.destroy(), e;
|
|
2648
|
+
}
|
|
2649
|
+
return this.#g?.destroy(), this.#g = null, this.#h?.destroy(), this.#p = e, this.#m = u, this.#h = l, this.#H = null, this.#u = new ht(), this.#d = new et(), this.#s.clear(), this.#g = this.#ve(u, l), this.#G = !0, this.requestFrame(), c;
|
|
2650
|
+
}
|
|
2651
|
+
async addLayer(e, t) {
|
|
2652
|
+
if (this.#fe) throw Error(K);
|
|
2653
|
+
let n = await Qe("bytes" in e ? e.bytes : await this.#i(e.url, null), t);
|
|
2654
|
+
if (this.#fe) throw Error(K);
|
|
2655
|
+
let r = n.reduce((e, { page: t }) => e + d(t.count), 0), i = this.#t.device.limits;
|
|
2656
|
+
if (q(this.#me, i).pool + this.#S + r > q(Infinity, i).pool) throw Error(ln);
|
|
2657
|
+
this.#S += r, this.#ge();
|
|
2658
|
+
let a = ++this.#b, o = (e) => this.#g?.protects(e) ?? !1, s = () => this.#be(), c = !0, l = 1, u = () => {
|
|
2659
|
+
if (!(this.#fe || !this.#y.delete(a))) {
|
|
2660
|
+
for (let { id: e } of p.pages) this.#s.remove(e);
|
|
2661
|
+
this.#S -= r, s();
|
|
2662
|
+
}
|
|
2663
|
+
}, f = {
|
|
2664
|
+
splats: n.reduce((e, { page: t }) => e + t.count, 0),
|
|
2665
|
+
box: $e(n.map(({ box: e }) => e)),
|
|
2666
|
+
get visible() {
|
|
2667
|
+
return c;
|
|
2668
|
+
},
|
|
2669
|
+
set visible(e) {
|
|
2670
|
+
c = e, s();
|
|
2671
|
+
},
|
|
2672
|
+
get opacity() {
|
|
2673
|
+
return l;
|
|
2674
|
+
},
|
|
2675
|
+
set opacity(e) {
|
|
2676
|
+
l = Math.min(1, Math.max(0, e)), s();
|
|
2677
|
+
},
|
|
2678
|
+
remove: u
|
|
2679
|
+
}, p = {
|
|
2680
|
+
layer: f,
|
|
2681
|
+
pages: []
|
|
2682
|
+
};
|
|
2683
|
+
this.#y.set(a, p);
|
|
2684
|
+
for (let { page: e, box: r } of n) {
|
|
2685
|
+
let n = --this.#x;
|
|
2686
|
+
if (!this.#s.add(n, e, t, o, a)) throw u(), Error(ln);
|
|
2687
|
+
p.pages.push({
|
|
2688
|
+
id: n,
|
|
2689
|
+
count: e.count,
|
|
2690
|
+
box: r
|
|
2691
|
+
});
|
|
2692
|
+
}
|
|
2693
|
+
return s(), this.#C.set(f, a), f;
|
|
2694
|
+
}
|
|
2695
|
+
addMask({ polygon: e, z: t = [-Infinity, Infinity], targets: n }) {
|
|
2696
|
+
if (this.#fe) throw Error(K);
|
|
2697
|
+
if (e.length < 3 || !e.flat().every(Number.isFinite)) throw Error("A mask needs three or more corners, each two finite numbers.");
|
|
2698
|
+
let r = new Set(n.map((e) => e === "world" ? 0 : this.#C.get(e) ?? -1)), i = this.#s, a = {
|
|
2699
|
+
polygon: Float64Array.from(e.flat()),
|
|
2700
|
+
z: [t[0], t[1]]
|
|
2701
|
+
}, o = i.addMask(a, r), s = !0, c = !1, l = () => {
|
|
2702
|
+
this.#fe || (this.#w = !0, this.requestFrame());
|
|
2703
|
+
};
|
|
2704
|
+
return l(), {
|
|
2705
|
+
get enabled() {
|
|
2706
|
+
return s;
|
|
2707
|
+
},
|
|
2708
|
+
set enabled(e) {
|
|
2709
|
+
c || e === s || (s = e, i.enableMask(o, e), l());
|
|
2710
|
+
},
|
|
2711
|
+
remove() {
|
|
2712
|
+
c || (c = !0, i.deleteMask(o), l());
|
|
2713
|
+
}
|
|
2714
|
+
};
|
|
2715
|
+
}
|
|
2716
|
+
addLine(e, t = {}) {
|
|
2717
|
+
let { colour: n = un, width: r = 2, closed: i = !1, occlude: a = !0 } = t, o = (e) => {
|
|
2718
|
+
mn(e);
|
|
2719
|
+
let t = i && e.length > 2 ? [...e, e[0]] : e;
|
|
2720
|
+
return (t.length > 1 ? t.slice(1).map((e, n) => [t[n], e]) : [[t[0], t[0]]]).map(([e, t]) => ({
|
|
2721
|
+
a: e,
|
|
2722
|
+
b: t,
|
|
2723
|
+
radius: r / 2,
|
|
2724
|
+
colour: n,
|
|
2725
|
+
occlude: a
|
|
2726
|
+
}));
|
|
2727
|
+
}, s = ++this.#E, c = () => {
|
|
2728
|
+
this.#D = !0, this.requestFrame();
|
|
2729
|
+
};
|
|
2730
|
+
return this.#T.set(s, o(e)), c(), {
|
|
2731
|
+
set: (e) => {
|
|
2732
|
+
let t = o(e);
|
|
2733
|
+
this.#T.has(s) && (this.#T.set(s, t), c());
|
|
2734
|
+
},
|
|
2735
|
+
remove: () => {
|
|
2736
|
+
this.#T.delete(s) && c();
|
|
2737
|
+
}
|
|
2738
|
+
};
|
|
2739
|
+
}
|
|
2740
|
+
addMarker(e, t = {}) {
|
|
2741
|
+
let { size: n = 12, ...r } = t, i = this.addLine([e], {
|
|
2742
|
+
...r,
|
|
2743
|
+
width: n
|
|
2744
|
+
});
|
|
2745
|
+
return {
|
|
2746
|
+
set: (e) => i.set([e]),
|
|
2747
|
+
remove: i.remove
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
toScreen([e, t, n]) {
|
|
2751
|
+
let r = this.#O, [i, a] = this.#L, o = this.#j, s = ne(/* @__PURE__ */ new Float64Array(16), hn(r, o), r.yaw * G, r.pitch * G), c = re(/* @__PURE__ */ new Float64Array(16), r.fov * G, i / Math.max(1, a), W, this.#a.viewDistance), [l, u, , d] = oe(N(/* @__PURE__ */ new Float64Array(16), c, s), [
|
|
2752
|
+
e - o[0],
|
|
2753
|
+
t - o[1],
|
|
2754
|
+
n - o[2]
|
|
2755
|
+
]);
|
|
2756
|
+
return d <= 0 ? null : [(l / d * .5 + .5) * i, (.5 - u / d * .5) * a];
|
|
2757
|
+
}
|
|
2758
|
+
setCamera(e) {
|
|
2759
|
+
if (this.#fe) return;
|
|
2760
|
+
let t = performance.now(), n = t - this.#k, r = this.#O, i = this.#A;
|
|
2761
|
+
if (n > nn) i.fill(0);
|
|
2762
|
+
else if (n > 0) {
|
|
2763
|
+
let t = 1 - Math.exp(-n / tn);
|
|
2764
|
+
i[0] += t * ((e.e - r.e) / n - i[0]), i[1] += t * ((e.n - r.n) / n - i[1]), i[2] += t * ((e.h - r.h) / n - i[2]);
|
|
2765
|
+
}
|
|
2766
|
+
this.#k = t, this.#O = { ...e }, this.#W = !0, this.#de || this.requestFrame();
|
|
2767
|
+
}
|
|
2768
|
+
configure(e) {
|
|
2769
|
+
if (this.#fe) return;
|
|
2770
|
+
let { budget: t, budgetRange: n } = this.#a;
|
|
2771
|
+
this.#a = {
|
|
2772
|
+
...this.#a,
|
|
2773
|
+
...e
|
|
2774
|
+
};
|
|
2775
|
+
let r = this.#a;
|
|
2776
|
+
(r.budget !== t || !((e, t) => e?.join() === t?.join())(r.budgetRange, n)) && (this.#o = this.#he(), this.#we()), this.#ge();
|
|
2777
|
+
}
|
|
2778
|
+
resize(e, t, n) {
|
|
2779
|
+
this.#fe || (this.#L = [
|
|
2780
|
+
e,
|
|
2781
|
+
t,
|
|
2782
|
+
n
|
|
2783
|
+
], this.#we());
|
|
2784
|
+
}
|
|
2785
|
+
pick(e, t) {
|
|
2786
|
+
return this.#fe || this.#pe ? Promise.resolve(null) : new Promise((n) => {
|
|
2787
|
+
this.#re.push({
|
|
2788
|
+
x: e,
|
|
2789
|
+
y: t,
|
|
2790
|
+
resolve: n
|
|
2791
|
+
}), this.#ie ? this.#ke() : this.requestFrame();
|
|
2792
|
+
});
|
|
2793
|
+
}
|
|
2794
|
+
ground(e, t) {
|
|
2795
|
+
return this.#m?.ground(e, t);
|
|
2796
|
+
}
|
|
2797
|
+
async groundAt(e, t) {
|
|
2798
|
+
let n = this.#m, r = this.#h;
|
|
2799
|
+
if (n && r) return await n.load(e, t, (e) => r.idx(e)), this.#q = !0, this.requestFrame(), n.ground(e, t);
|
|
2800
|
+
}
|
|
2801
|
+
heights(e, t, n) {
|
|
2802
|
+
return this.#fe || this.#pe ? Promise.resolve(null) : new Promise((r) => {
|
|
2803
|
+
this.#ae.push({
|
|
2804
|
+
west: e,
|
|
2805
|
+
south: t,
|
|
2806
|
+
cells: n,
|
|
2807
|
+
resolve: r
|
|
2808
|
+
}), this.requestFrame();
|
|
2809
|
+
});
|
|
2810
|
+
}
|
|
2811
|
+
stats() {
|
|
2812
|
+
let e = this.#s, t = this.#g, n = this.#c.stats();
|
|
2813
|
+
return {
|
|
2814
|
+
frameMs: kt(this.#$, .5),
|
|
2815
|
+
cpuMs: kt(this.#ee, .5),
|
|
2816
|
+
gpuMs: n.gpuMs,
|
|
2817
|
+
passes: n.passes,
|
|
2818
|
+
drawn: n.drawn,
|
|
2819
|
+
...this.#Ae(),
|
|
2820
|
+
pages: {
|
|
2821
|
+
resident: Array.from(e.ids()).length,
|
|
2822
|
+
drawn: this.#Y.length,
|
|
2823
|
+
loading: t?.loading ?? 0,
|
|
2824
|
+
queued: t?.queued ?? 0
|
|
2825
|
+
},
|
|
2826
|
+
memory: {
|
|
2827
|
+
pool: e.bytes,
|
|
2828
|
+
buffers: n.bytes
|
|
2829
|
+
},
|
|
2830
|
+
capacity: e.capacity,
|
|
2831
|
+
budget: this.#me,
|
|
2832
|
+
scale: this.#o.scale
|
|
2833
|
+
};
|
|
2834
|
+
}
|
|
2835
|
+
idle() {
|
|
2836
|
+
return this.#fe ? Promise.resolve() : new Promise((e) => {
|
|
2837
|
+
this.#oe.push(e), this.requestFrame();
|
|
2838
|
+
});
|
|
2839
|
+
}
|
|
2840
|
+
use(e) {
|
|
2841
|
+
if (this.#fe) return () => {};
|
|
2842
|
+
let t = e({
|
|
2843
|
+
shade: (e) => this.#Ce(this.#te, e, this.#c.shade(e)),
|
|
2844
|
+
post: (e) => this.#Ce(this.#ne, e, this.#c.post(e))
|
|
2845
|
+
});
|
|
2846
|
+
return () => {
|
|
2847
|
+
this.#fe || t();
|
|
2848
|
+
};
|
|
2849
|
+
}
|
|
2850
|
+
warm() {
|
|
2851
|
+
let e = performance.now();
|
|
2852
|
+
e - this.#X < an || (this.#Z = e + on, this.requestFrame());
|
|
2853
|
+
}
|
|
2854
|
+
onFrame(e) {
|
|
2855
|
+
return this.#ce.add(e), () => this.#ce.delete(e);
|
|
2856
|
+
}
|
|
2857
|
+
onProgress(e) {
|
|
2858
|
+
return this.#le.add(e), () => this.#le.delete(e);
|
|
2859
|
+
}
|
|
2860
|
+
onLost(e) {
|
|
2861
|
+
return this.#se.add(e), () => this.#se.delete(e);
|
|
2862
|
+
}
|
|
2863
|
+
requestFrame() {
|
|
2864
|
+
this.#fe || this.#pe || this.#r.manual || this.#z || (this.#z = requestAnimationFrame(this.#Te));
|
|
2865
|
+
}
|
|
2866
|
+
async step() {
|
|
2867
|
+
if (this.#fe || this.#pe) return {
|
|
2868
|
+
cpuMs: 0,
|
|
2869
|
+
gpuMs: 0,
|
|
2870
|
+
passes: {}
|
|
2871
|
+
};
|
|
2872
|
+
let { done: e, cpuMs: t } = this.#Ee(!1);
|
|
2873
|
+
await e;
|
|
2874
|
+
let { gpuMs: n, passes: r } = this.#c.stats();
|
|
2875
|
+
return {
|
|
2876
|
+
cpuMs: t,
|
|
2877
|
+
gpuMs: n,
|
|
2878
|
+
passes: r
|
|
2879
|
+
};
|
|
2880
|
+
}
|
|
2881
|
+
destroy() {
|
|
2882
|
+
if (!this.#fe) {
|
|
2883
|
+
this.#fe = !0, cancelAnimationFrame(this.#z), this.#g?.destroy(), this.#h?.destroy(), this.#c.destroy(), this.#s.destroy(), this.#y.clear();
|
|
2884
|
+
for (let { resolve: e } of this.#re.splice(0)) e(null);
|
|
2885
|
+
for (let { resolve: e } of this.#ae.splice(0)) e(null);
|
|
2886
|
+
for (let e of this.#oe.splice(0)) e();
|
|
2887
|
+
this.#t.device.destroy();
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
get #me() {
|
|
2891
|
+
return this.#o.budget;
|
|
2892
|
+
}
|
|
2893
|
+
#he() {
|
|
2894
|
+
let { budget: e, budgetRange: t = [e, e] } = this.#a, n = Math.floor(q(Infinity, this.#t.device.limits).frame / Yt), r = (e) => Math.max(1, Math.min(e, n));
|
|
2895
|
+
return new At(r(e), [r(t[0]), r(t[1])]);
|
|
2896
|
+
}
|
|
2897
|
+
#ge() {
|
|
2898
|
+
let { pool: e, frame: t } = q(this.#me, this.#t.device.limits), n = e + this.#S;
|
|
2899
|
+
(n > this.#s.capacity || t > this.#l) && this.#_e(n, t), this.#G = !0, this.requestFrame();
|
|
2900
|
+
}
|
|
2901
|
+
#_e(e, t) {
|
|
2902
|
+
this.#s.grow(e), this.#c.destroy();
|
|
2903
|
+
let n = new Ze(this.#t, this.#n, this.#s, t);
|
|
2904
|
+
n.resize(...this.#R);
|
|
2905
|
+
for (let e of this.#te) e.off = n.shade(e.hook);
|
|
2906
|
+
for (let e of this.#ne) e.off = n.post(e.hook);
|
|
2907
|
+
this.#c = n, this.#l = t, this.#ie = null, this.#D = !0;
|
|
2908
|
+
}
|
|
2909
|
+
#ve(e, t) {
|
|
2910
|
+
return new Lt(e, t, this.#s, () => {
|
|
2911
|
+
this.#q = !0, this.requestFrame();
|
|
2912
|
+
}, this.#ye);
|
|
2913
|
+
}
|
|
2914
|
+
#ye = () => {
|
|
2915
|
+
let e = this.#p, t = this.#m;
|
|
2916
|
+
this.#v || this.#fe || e === null || (this.#v = !0, this.open(e).then(() => this.#v = !1, () => {
|
|
2917
|
+
this.#v = !1, this.#m === t && setTimeout(this.#ye, sn);
|
|
2918
|
+
}));
|
|
2919
|
+
};
|
|
2920
|
+
#be() {
|
|
2921
|
+
this.#w = !0, this.#G = !0, this.requestFrame();
|
|
2922
|
+
}
|
|
2923
|
+
#xe() {
|
|
2924
|
+
let e = this.#j, t = [
|
|
2925
|
+
0,
|
|
2926
|
+
0,
|
|
2927
|
+
0
|
|
2928
|
+
], n = [
|
|
2929
|
+
0,
|
|
2930
|
+
0,
|
|
2931
|
+
0
|
|
2932
|
+
], r = 0;
|
|
2933
|
+
for (let { layer: i, pages: a } of this.#y.values()) if (_n(i)) for (let { count: i, box: o } of a) {
|
|
2934
|
+
for (let r = 0; r < 3; r++) t[r] = o[r] - e[r], n[r] = o[r + 3] - e[r];
|
|
2935
|
+
je(this.#I, t, n) && (r += i);
|
|
2936
|
+
}
|
|
2937
|
+
return r;
|
|
2938
|
+
}
|
|
2939
|
+
#Se() {
|
|
2940
|
+
let e = [];
|
|
2941
|
+
for (let { layer: t, pages: n } of this.#y.values()) {
|
|
2942
|
+
let r = _n(t);
|
|
2943
|
+
if (r) for (let { id: t } of n) e.push({
|
|
2944
|
+
id: t,
|
|
2945
|
+
factors: r
|
|
2946
|
+
});
|
|
2947
|
+
}
|
|
2948
|
+
return e;
|
|
2949
|
+
}
|
|
2950
|
+
#Ce(e, t, n) {
|
|
2951
|
+
let r = {
|
|
2952
|
+
hook: t,
|
|
2953
|
+
off: n
|
|
2954
|
+
};
|
|
2955
|
+
return e.push(r), this.requestFrame(), () => {
|
|
2956
|
+
let t = e.indexOf(r);
|
|
2957
|
+
this.#fe || t < 0 || (e.splice(t, 1), r.off(), this.requestFrame());
|
|
2958
|
+
};
|
|
2959
|
+
}
|
|
2960
|
+
#we() {
|
|
2961
|
+
let [e, t, n] = this.#L, r = Ot(e, t, n, this.#o.scale), i = Math.max(1, Math.round(e * r)), a = Math.max(1, Math.round(t * r));
|
|
2962
|
+
(i !== this.#R[0] || a !== this.#R[1]) && (this.#R = [i, a], this.#e.width = i, this.#e.height = a, this.#c.resize(i, a), this.#G = !0, this.#D = !0, this.requestFrame());
|
|
2963
|
+
}
|
|
2964
|
+
#Te = (e) => {
|
|
2965
|
+
if (this.#z = 0, !(this.#fe || this.#pe)) {
|
|
2966
|
+
if (this.#B >= $t) this.#V = !0;
|
|
2967
|
+
else {
|
|
2968
|
+
this.#de = !0;
|
|
2969
|
+
for (let t of this.#ce) t(e);
|
|
2970
|
+
this.#de = !1, this.#B++, this.#Ee(!0).done.finally(() => {
|
|
2971
|
+
this.#B--, this.#V && (this.#V = !1, this.requestFrame());
|
|
2972
|
+
});
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
};
|
|
2976
|
+
#Ee(e) {
|
|
2977
|
+
let t = performance.now(), n = this.#o, r = this.#s, i = this.#O, [a, o] = this.#R, s = this.#a.viewDistance, c = this.#W;
|
|
2978
|
+
this.#W = !1;
|
|
2979
|
+
let l = fn(this.#j, [
|
|
2980
|
+
i.e,
|
|
2981
|
+
i.n,
|
|
2982
|
+
i.h
|
|
2983
|
+
]);
|
|
2984
|
+
l !== this.#j && (this.#j = l, r.setOrigin(l), this.#D = !0);
|
|
2985
|
+
let u = hn(i, l);
|
|
2986
|
+
ne(this.#M, u, i.yaw * G, i.pitch * G), re(this.#N, i.fov * G, a / o, W, s);
|
|
2987
|
+
let d = {
|
|
2988
|
+
time: t,
|
|
2989
|
+
width: a,
|
|
2990
|
+
height: o,
|
|
2991
|
+
view: new Float32Array(this.#M),
|
|
2992
|
+
proj: new Float32Array(this.#N),
|
|
2993
|
+
near: W,
|
|
2994
|
+
far: s,
|
|
2995
|
+
camera: Float32Array.from(u),
|
|
2996
|
+
origin: l
|
|
2997
|
+
};
|
|
2998
|
+
Ae(this.#I, N(this.#F, d.proj, d.view));
|
|
2999
|
+
let f = this.#m, p = this.#g, m = this.#q || this.#G || this.#J, h = this.#H, g = h;
|
|
3000
|
+
if (f && p) {
|
|
3001
|
+
let e = !p.idle && t - this.#U >= Qt, n = this.#G || this.#q || this.#J || this.#K;
|
|
3002
|
+
(!g || c || e || n) && (g = this.#De(f, t, c));
|
|
3003
|
+
}
|
|
3004
|
+
let _ = this.#Y, v = this.#J;
|
|
3005
|
+
if (g && p && (g !== h && (m || !h || g.cut.length !== h.cut.length || g.cut.some((e, t) => e !== h.cut[t])) && ({drawn: _, fading: v} = this.#d.update(g.cut, this.#f, t, this.#me)), p.update(g, new Set(_.map((e) => e.id)), t)), r.upload(qt) > 0 && (this.#q = !0), _ !== this.#Y || this.#q || this.#w) {
|
|
3006
|
+
this.#w = !1;
|
|
3007
|
+
let e = this.#Se();
|
|
3008
|
+
r.draw(e.length ? _.concat(e) : _);
|
|
3009
|
+
}
|
|
3010
|
+
if (this.#J = v, this.#Y = _, this.#D) {
|
|
3011
|
+
this.#D = !1;
|
|
3012
|
+
let e = a / Math.max(1, this.#L[0]), t = [...this.#T.values()].flat().map((t) => ({
|
|
3013
|
+
...t,
|
|
3014
|
+
radius: t.radius * e
|
|
3015
|
+
}));
|
|
3016
|
+
this.#c.overlay(t, l);
|
|
3017
|
+
}
|
|
3018
|
+
let y = this.#ae.splice(0).map((e) => this.#Me(e, l)), b = this.#c.render(d, this.#I, this.#r.sky, y);
|
|
3019
|
+
this.#ie = d, this.#re.length && this.#ke();
|
|
3020
|
+
let x = performance.now() - t;
|
|
3021
|
+
if (!this.#q && !this.#K && !v && r.queued === 0 && (!p || p.idle) && (!g || g.load.length === 0 && g.idx.length === 0) && this.#oe.length) {
|
|
3022
|
+
let e = this.#oe.splice(0);
|
|
3023
|
+
b.then(() => e.forEach((e) => e()));
|
|
3024
|
+
}
|
|
3025
|
+
e && this.#Ne(t, x, c), this.#je();
|
|
3026
|
+
let S = t < this.#Z;
|
|
3027
|
+
return (r.queued > 0 || this.#q || this.#K || v || n.scale < 1 || S) && this.requestFrame(), {
|
|
3028
|
+
done: b,
|
|
3029
|
+
cpuMs: x
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
3032
|
+
#De(e, t, n) {
|
|
3033
|
+
let r = this.#O, i = this.#s, [a, o] = this.#R, s = this.#o.scale, c = this.#me, l = {
|
|
3034
|
+
origin: this.#j,
|
|
3035
|
+
width: a / s,
|
|
3036
|
+
height: o / s,
|
|
3037
|
+
tan: Math.tan(r.fov * G / 2),
|
|
3038
|
+
near: W,
|
|
3039
|
+
far: this.#a.viewDistance
|
|
3040
|
+
}, u = {
|
|
3041
|
+
...l,
|
|
3042
|
+
view: this.#M
|
|
3043
|
+
}, d = {
|
|
3044
|
+
budget: Math.max(0, c - this.#xe()),
|
|
3045
|
+
capacity: i.capacity - Math.ceil(1 * c) - this.#S,
|
|
3046
|
+
now: t,
|
|
3047
|
+
predicted: n ? this.#Oe(l) : void 0
|
|
3048
|
+
}, f = this.#u.plan(e, u, this.#f, d);
|
|
3049
|
+
return this.#H = f, this.#U = t, this.#G = !1, this.#K = d.predicted !== void 0, this.#q = !1, f;
|
|
3050
|
+
}
|
|
3051
|
+
#Oe(e) {
|
|
3052
|
+
let t = this.#A;
|
|
3053
|
+
if (t.every((e) => e === 0)) return;
|
|
3054
|
+
let n = this.#O, r = [
|
|
3055
|
+
n.e + t[0] * en - e.origin[0],
|
|
3056
|
+
n.n + t[1] * en - e.origin[1],
|
|
3057
|
+
n.h + t[2] * en - e.origin[2]
|
|
3058
|
+
];
|
|
3059
|
+
return {
|
|
3060
|
+
...e,
|
|
3061
|
+
view: ne(this.#P, r, n.yaw * G, n.pitch * G)
|
|
3062
|
+
};
|
|
3063
|
+
}
|
|
3064
|
+
#ke() {
|
|
3065
|
+
let e = this.#ie, t = this.#M.slice(), [n, r] = this.#L, i = [e.width, e.height];
|
|
3066
|
+
for (let { x: a, y: o, resolve: s } of this.#re.splice(0)) {
|
|
3067
|
+
let c = [a * i[0] / Math.max(1, n), o * i[1] / Math.max(1, r)], l = (n) => n && {
|
|
3068
|
+
point: pn(c, i, n.depth, e.proj, t, e.origin),
|
|
3069
|
+
normal: n.normal,
|
|
3070
|
+
layer: this.#y.get(n.layer)?.layer ?? null
|
|
3071
|
+
};
|
|
3072
|
+
this.#c.pick(c[0], c[1], e).then((e) => s(l(e)));
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
#Ae() {
|
|
3076
|
+
let e = this.#g;
|
|
3077
|
+
return {
|
|
3078
|
+
planned: this.#H?.planned ?? 0,
|
|
3079
|
+
missing: this.#H?.missing ?? 0,
|
|
3080
|
+
loading: e !== null && !e.idle
|
|
3081
|
+
};
|
|
3082
|
+
}
|
|
3083
|
+
#je() {
|
|
3084
|
+
let e = this.#Ae(), t = this.#ue;
|
|
3085
|
+
if (e.planned !== t.planned || e.missing !== t.missing || e.loading !== t.loading) {
|
|
3086
|
+
this.#ue = e;
|
|
3087
|
+
for (let t of this.#le) t(e);
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
#Me({ west: e, south: t, cells: n, resolve: r }, i) {
|
|
3091
|
+
return {
|
|
3092
|
+
x: e - i[0],
|
|
3093
|
+
y: t - i[1],
|
|
3094
|
+
cells: n,
|
|
3095
|
+
resolve: (e) => {
|
|
3096
|
+
if (e) for (let t = 0; t < e.length; t++) e[t] += i[2];
|
|
3097
|
+
r(e);
|
|
3098
|
+
}
|
|
3099
|
+
};
|
|
3100
|
+
}
|
|
3101
|
+
#Ne(e, t, n) {
|
|
3102
|
+
let r = this.#o, { gpuMs: i } = this.#c.stats(), a = e - this.#X, o = a <= Math.max(nn, 2 * i, 2 * t);
|
|
3103
|
+
o && gn(this.#$, a), gn(this.#ee, t), this.#X = e;
|
|
3104
|
+
let s = r.budget;
|
|
3105
|
+
r.sample(a, e, o && n, this.#H?.planned ?? 0) && (this.#we(), r.budget !== s && this.#ge()), n ? this.#Q = e : r.scale < 1 && e - this.#Q > rn && (r.full(), this.#we());
|
|
3106
|
+
}
|
|
3107
|
+
}, yn = 45, bn = {
|
|
3108
|
+
yaw: 0,
|
|
3109
|
+
pitch: -35,
|
|
3110
|
+
dist: 300
|
|
3111
|
+
}, J = {
|
|
3112
|
+
pitch: [-90, -20],
|
|
3113
|
+
dist: [1, 2485],
|
|
3114
|
+
clearance: 10,
|
|
3115
|
+
floor: 50
|
|
3116
|
+
}, xn = .1, Y = Math.PI / 180, Sn = 1.1, Cn = [600, 2500], wn = 300, Tn = .5, En = (e, [t, n]) => Math.min(n, Math.max(t, e)), Dn = (e) => (e % 360 + 360) % 360, On = (e, t) => (t - e + 540) % 360 - 180;
|
|
3117
|
+
function kn({ leaf: e, roots: t, extent: n }) {
|
|
3118
|
+
let r = {
|
|
3119
|
+
e: (n.e[0] + n.e[1]) / 2,
|
|
3120
|
+
n: (n.n[0] + n.n[1]) / 2,
|
|
3121
|
+
h: n.h[0]
|
|
3122
|
+
}, i = r, a = Infinity;
|
|
3123
|
+
for (let o of t) {
|
|
3124
|
+
let t = e * 2 ** o.level, [s, c] = [Math.max(o.e, n.e[0]), Math.min(o.e + t, n.e[1])], [l, u] = [Math.max(o.n, n.n[0]), Math.min(o.n + t, n.n[1])], d = Math.hypot(Math.max(s - r.e, 0, r.e - c), Math.max(l - r.n, 0, r.n - u));
|
|
3125
|
+
if (d === 0) return r;
|
|
3126
|
+
d < a && (a = d, i = {
|
|
3127
|
+
e: (s + c) / 2,
|
|
3128
|
+
n: (l + u) / 2,
|
|
3129
|
+
h: n.h[0]
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
return i;
|
|
3133
|
+
}
|
|
3134
|
+
function An(e) {
|
|
3135
|
+
let t = e.split(",");
|
|
3136
|
+
if (t.length !== 6 || t.some((e) => e.trim() === "")) return null;
|
|
3137
|
+
let [n, r, i, a, o, s] = t.map(Number);
|
|
3138
|
+
return ![
|
|
3139
|
+
n,
|
|
3140
|
+
r,
|
|
3141
|
+
i,
|
|
3142
|
+
a,
|
|
3143
|
+
o,
|
|
3144
|
+
s
|
|
3145
|
+
].every(Number.isFinite) || s <= 0 ? null : {
|
|
3146
|
+
e: n,
|
|
3147
|
+
n: r,
|
|
3148
|
+
h: i,
|
|
3149
|
+
yaw: a,
|
|
3150
|
+
pitch: o,
|
|
3151
|
+
dist: s
|
|
3152
|
+
};
|
|
3153
|
+
}
|
|
3154
|
+
function jn(e) {
|
|
3155
|
+
let t = (e, t) => +e.toFixed(t);
|
|
3156
|
+
return [
|
|
3157
|
+
t(e.e, 2),
|
|
3158
|
+
t(e.n, 2),
|
|
3159
|
+
t(e.h, 2),
|
|
3160
|
+
t(e.yaw, 1),
|
|
3161
|
+
t(e.pitch, 1),
|
|
3162
|
+
t(e.dist, 1)
|
|
3163
|
+
].join(",");
|
|
3164
|
+
}
|
|
3165
|
+
function X(e, t, n = J) {
|
|
3166
|
+
let r = {
|
|
3167
|
+
e: e.e,
|
|
3168
|
+
n: e.n,
|
|
3169
|
+
h: e.h,
|
|
3170
|
+
yaw: Dn(e.yaw),
|
|
3171
|
+
pitch: En(e.pitch, n.pitch),
|
|
3172
|
+
dist: En(e.dist, n.dist)
|
|
3173
|
+
};
|
|
3174
|
+
if (t) {
|
|
3175
|
+
let e = Z(r), i = Math.max(n.floor, t(e.e, e.n) + n.clearance);
|
|
3176
|
+
if (e.h < i) return {
|
|
3177
|
+
...Fn({
|
|
3178
|
+
...e,
|
|
3179
|
+
h: i
|
|
3180
|
+
}, r),
|
|
3181
|
+
yaw: r.yaw
|
|
3182
|
+
};
|
|
3183
|
+
}
|
|
3184
|
+
return r;
|
|
3185
|
+
}
|
|
3186
|
+
function Mn(e, t) {
|
|
3187
|
+
let n = Math.cos(t * Y);
|
|
3188
|
+
return {
|
|
3189
|
+
e: Math.sin(e * Y) * n,
|
|
3190
|
+
n: Math.cos(e * Y) * n,
|
|
3191
|
+
h: Math.sin(t * Y)
|
|
3192
|
+
};
|
|
3193
|
+
}
|
|
3194
|
+
function Z(e) {
|
|
3195
|
+
let t = Mn(e.yaw, e.pitch);
|
|
3196
|
+
return {
|
|
3197
|
+
e: e.e - t.e * e.dist,
|
|
3198
|
+
n: e.n - t.n * e.dist,
|
|
3199
|
+
h: e.h - t.h * e.dist
|
|
3200
|
+
};
|
|
3201
|
+
}
|
|
3202
|
+
function Nn(e) {
|
|
3203
|
+
return {
|
|
3204
|
+
...Z(e),
|
|
3205
|
+
yaw: e.yaw,
|
|
3206
|
+
pitch: e.pitch,
|
|
3207
|
+
fov: 45
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
function Pn(e, t, n) {
|
|
3211
|
+
let r = Z(e), [i, a, o] = [
|
|
3212
|
+
n.e - r.e,
|
|
3213
|
+
n.n - r.n,
|
|
3214
|
+
n.h - r.h
|
|
3215
|
+
], [s, c] = [Math.sin(e.yaw * Y), Math.cos(e.yaw * Y)], [l, u] = [Math.sin(e.pitch * Y), Math.cos(e.pitch * Y)], d = i * s + a * c, f = 2 * Math.tan(t * Y / 2) * (d * u + o * l);
|
|
3216
|
+
return {
|
|
3217
|
+
x: (i * c - a * s) / f,
|
|
3218
|
+
y: (d * l - o * u) / f
|
|
3219
|
+
};
|
|
3220
|
+
}
|
|
3221
|
+
function Fn(e, t) {
|
|
3222
|
+
let [n, r, i] = [
|
|
3223
|
+
t.e - e.e,
|
|
3224
|
+
t.n - e.n,
|
|
3225
|
+
t.h - e.h
|
|
3226
|
+
], a = Math.hypot(n, r, i);
|
|
3227
|
+
return {
|
|
3228
|
+
e: t.e,
|
|
3229
|
+
n: t.n,
|
|
3230
|
+
h: t.h,
|
|
3231
|
+
yaw: Dn(Math.atan2(n, r) / Y),
|
|
3232
|
+
pitch: Math.asin(i / a) / Y,
|
|
3233
|
+
dist: a
|
|
3234
|
+
};
|
|
3235
|
+
}
|
|
3236
|
+
function In(e, t, n, r = J) {
|
|
3237
|
+
let i = Z(e), a = X({
|
|
3238
|
+
...e,
|
|
3239
|
+
yaw: t,
|
|
3240
|
+
pitch: n
|
|
3241
|
+
}, void 0, r), o = Mn(a.yaw, a.pitch);
|
|
3242
|
+
return {
|
|
3243
|
+
...a,
|
|
3244
|
+
e: i.e + o.e * a.dist,
|
|
3245
|
+
n: i.n + o.n * a.dist,
|
|
3246
|
+
h: i.h + o.h * a.dist
|
|
3247
|
+
};
|
|
3248
|
+
}
|
|
3249
|
+
function Ln(e) {
|
|
3250
|
+
return e.dist * Math.max(Math.sin(-e.pitch * Y), xn);
|
|
3251
|
+
}
|
|
3252
|
+
function Rn(e, t, n, r) {
|
|
3253
|
+
let [i, a] = [Math.sin(e.yaw * Y), Math.cos(e.yaw * Y)];
|
|
3254
|
+
return {
|
|
3255
|
+
...e,
|
|
3256
|
+
e: e.e + t * a + n * i,
|
|
3257
|
+
n: e.n - t * i + n * a,
|
|
3258
|
+
h: e.h + r
|
|
3259
|
+
};
|
|
3260
|
+
}
|
|
3261
|
+
function zn(e, t, n) {
|
|
3262
|
+
return Rn(e, t, n * e.dist / Ln(e), 0);
|
|
3263
|
+
}
|
|
3264
|
+
function Q(e, t, n) {
|
|
3265
|
+
return {
|
|
3266
|
+
e: e.e + (t.e - e.e) * n,
|
|
3267
|
+
n: e.n + (t.n - e.n) * n,
|
|
3268
|
+
h: e.h + (t.h - e.h) * n,
|
|
3269
|
+
yaw: Dn(e.yaw + On(e.yaw, t.yaw) * n),
|
|
3270
|
+
pitch: e.pitch + (t.pitch - e.pitch) * n,
|
|
3271
|
+
dist: e.dist * (t.dist / e.dist) ** n
|
|
3272
|
+
};
|
|
3273
|
+
}
|
|
3274
|
+
function Bn(e, t) {
|
|
3275
|
+
let n = ([e, t]) => (e + t) / 2, r = Math.hypot(e.e[1] - e.e[0], e.n[1] - e.n[0], e.h[1] - e.h[0]) / 2;
|
|
3276
|
+
return {
|
|
3277
|
+
e: n(e.e),
|
|
3278
|
+
n: n(e.n),
|
|
3279
|
+
h: n(e.h),
|
|
3280
|
+
yaw: t.yaw,
|
|
3281
|
+
pitch: t.pitch,
|
|
3282
|
+
dist: Sn * r / Math.sin(45 * Y / 2)
|
|
3283
|
+
};
|
|
3284
|
+
}
|
|
3285
|
+
function Vn(e, t) {
|
|
3286
|
+
let n = Math.hypot(t.e - e.e, t.n - e.n), r = Math.log1p(n / Math.min(e.dist, t.dist)) + Math.abs(Math.log(t.dist / e.dist)), i = Math.log1p(Tn * n / Math.max(e.dist, t.dist));
|
|
3287
|
+
return {
|
|
3288
|
+
ms: En(Cn[0] + wn * r, Cn),
|
|
3289
|
+
at(n) {
|
|
3290
|
+
if (n <= 0) return e;
|
|
3291
|
+
if (n >= 1) return t;
|
|
3292
|
+
let r = n * n * (3 - 2 * n), a = Q(e, t, r);
|
|
3293
|
+
return {
|
|
3294
|
+
...a,
|
|
3295
|
+
dist: a.dist * Math.exp(4 * i * r * (1 - r))
|
|
3296
|
+
};
|
|
3297
|
+
}
|
|
3298
|
+
};
|
|
3299
|
+
}
|
|
3300
|
+
function Hn(e, t) {
|
|
3301
|
+
let n = e.dist * 1e-5;
|
|
3302
|
+
return Math.abs(e.e - t.e) < n && Math.abs(e.n - t.n) < n && Math.abs(e.h - t.h) < n && Math.abs(e.dist - t.dist) < n && Math.abs(On(e.yaw, t.yaw)) < .001 && Math.abs(e.pitch - t.pitch) < .001;
|
|
3303
|
+
}
|
|
3304
|
+
//#endregion
|
|
3305
|
+
//#region src/controls/controls.ts
|
|
3306
|
+
var Un = .2, Wn = .002, Gn = .005, Kn = .5, qn = .05;
|
|
3307
|
+
function Jn(e, t) {
|
|
3308
|
+
return 2 * e * Math.tan(45 * Math.PI / 360) / Math.max(1, t);
|
|
3309
|
+
}
|
|
3310
|
+
function Yn(e) {
|
|
3311
|
+
let t = (t) => +!!e.has(t);
|
|
3312
|
+
return [
|
|
3313
|
+
t("KeyD") - t("KeyA") + t("ArrowRight") - t("ArrowLeft"),
|
|
3314
|
+
t("KeyW") - t("KeyS") + t("ArrowUp") - t("ArrowDown"),
|
|
3315
|
+
t("KeyE") - t("KeyQ")
|
|
3316
|
+
];
|
|
3317
|
+
}
|
|
3318
|
+
function Xn(e, t, n, r, i = J) {
|
|
3319
|
+
return Hn(e, t) ? t : X(Q(e, t, 1 - Math.exp(-n / qn)), r, i);
|
|
3320
|
+
}
|
|
3321
|
+
var Zn = class {
|
|
3322
|
+
enabled = !0;
|
|
3323
|
+
#e;
|
|
3324
|
+
#t;
|
|
3325
|
+
#n;
|
|
3326
|
+
#r;
|
|
3327
|
+
#i = new AbortController();
|
|
3328
|
+
#a = /* @__PURE__ */ new Map();
|
|
3329
|
+
#o = /* @__PURE__ */ new Set();
|
|
3330
|
+
#s = [0, 0];
|
|
3331
|
+
#c = [0, 0];
|
|
3332
|
+
#l = 0;
|
|
3333
|
+
#u = !1;
|
|
3334
|
+
#d;
|
|
3335
|
+
#f;
|
|
3336
|
+
#p = null;
|
|
3337
|
+
#m = /* @__PURE__ */ new Set();
|
|
3338
|
+
#h;
|
|
3339
|
+
#g = null;
|
|
3340
|
+
constructor(e, t, n, r, i = J) {
|
|
3341
|
+
this.#e = e, this.#t = t, this.#n = n, this.#r = i, this.#d = this.#j(r), this.#f = this.#d, this.#h = t.onFrame(this.#D);
|
|
3342
|
+
let a = this.#i.signal;
|
|
3343
|
+
e.addEventListener("pointerdown", this.#_, { signal: a }), e.addEventListener("pointermove", this.#v, { signal: a });
|
|
3344
|
+
for (let t of [
|
|
3345
|
+
"pointerup",
|
|
3346
|
+
"pointercancel",
|
|
3347
|
+
"lostpointercapture"
|
|
3348
|
+
]) e.addEventListener(t, this.#y, { signal: a });
|
|
3349
|
+
e.addEventListener("wheel", this.#b, {
|
|
3350
|
+
passive: !1,
|
|
3351
|
+
signal: a
|
|
3352
|
+
}), e.addEventListener("dblclick", this.#C, { signal: a }), e.addEventListener("contextmenu", (e) => e.preventDefault(), { signal: a }), window.addEventListener("keydown", this.#x, { signal: a }), window.addEventListener("keyup", this.#S, { signal: a }), window.addEventListener("blur", () => this.#o.clear(), { signal: a }), this.#M();
|
|
3353
|
+
}
|
|
3354
|
+
get pose() {
|
|
3355
|
+
return { ...this.#f };
|
|
3356
|
+
}
|
|
3357
|
+
onChange(e) {
|
|
3358
|
+
return this.#m.add(e), () => this.#m.delete(e);
|
|
3359
|
+
}
|
|
3360
|
+
moveTo(e, t) {
|
|
3361
|
+
let n = this.#d, r = Math.min(n.dist, bn.dist);
|
|
3362
|
+
this.#O(this.#j({
|
|
3363
|
+
...n,
|
|
3364
|
+
e,
|
|
3365
|
+
n: t,
|
|
3366
|
+
h: this.#n(e, t),
|
|
3367
|
+
dist: r
|
|
3368
|
+
}));
|
|
3369
|
+
}
|
|
3370
|
+
jump(e) {
|
|
3371
|
+
this.#k(!1), this.#d = this.#f = this.#j({
|
|
3372
|
+
...this.#f,
|
|
3373
|
+
...e
|
|
3374
|
+
}), this.#A();
|
|
3375
|
+
}
|
|
3376
|
+
flyTo(e, t = {}) {
|
|
3377
|
+
let { signal: n } = t;
|
|
3378
|
+
if (n?.aborted || this.#i.signal.aborted) return Promise.resolve(!1);
|
|
3379
|
+
this.#k(!1);
|
|
3380
|
+
let r = this.#f;
|
|
3381
|
+
this.#d = r;
|
|
3382
|
+
let i = () => this.#k(!1);
|
|
3383
|
+
return new Promise((t) => {
|
|
3384
|
+
this.#p = {
|
|
3385
|
+
path: Vn(r, this.#j({
|
|
3386
|
+
...r,
|
|
3387
|
+
...e
|
|
3388
|
+
})),
|
|
3389
|
+
start: null,
|
|
3390
|
+
land: (e) => {
|
|
3391
|
+
n?.removeEventListener("abort", i), t(e);
|
|
3392
|
+
}
|
|
3393
|
+
}, n?.addEventListener("abort", i), this.#E();
|
|
3394
|
+
});
|
|
3395
|
+
}
|
|
3396
|
+
destroy() {
|
|
3397
|
+
this.#k(!1), this.#i.abort(), this.#h(), this.#m.clear();
|
|
3398
|
+
}
|
|
3399
|
+
#_ = (e) => {
|
|
3400
|
+
this.#w(e) && (this.#e.setPointerCapture(e.pointerId), this.#a.set(e.pointerId, {
|
|
3401
|
+
x: e.clientX,
|
|
3402
|
+
y: e.clientY
|
|
3403
|
+
}));
|
|
3404
|
+
};
|
|
3405
|
+
#v = (e) => {
|
|
3406
|
+
if (!this.#w(e)) return;
|
|
3407
|
+
let t = this.#a.get(e.pointerId);
|
|
3408
|
+
if (!t) return this.#t.warm();
|
|
3409
|
+
let n = this.#T(), [r, i] = [e.clientX - t.x, e.clientY - t.y];
|
|
3410
|
+
if (t.x = e.clientX, t.y = e.clientY, e.pointerType === "mouse") {
|
|
3411
|
+
let t = !!(e.buttons & 1);
|
|
3412
|
+
e.buttons & 6 || t && e.shiftKey ? $(this.#c, r, i) : t && $(this.#s, r, i);
|
|
3413
|
+
} else if (n) {
|
|
3414
|
+
let e = this.#T();
|
|
3415
|
+
$(this.#c, e.x - n.x, e.y - n.y), this.#l += (n.d - e.d) * Gn;
|
|
3416
|
+
} else $(this.#s, r, i);
|
|
3417
|
+
this.#E();
|
|
3418
|
+
};
|
|
3419
|
+
#y = (e) => {
|
|
3420
|
+
this.#a.delete(e.pointerId);
|
|
3421
|
+
};
|
|
3422
|
+
#b = (e) => {
|
|
3423
|
+
this.#w(e) && (e.preventDefault(), this.#l += e.deltaY * Wn, this.#E());
|
|
3424
|
+
};
|
|
3425
|
+
#x = (e) => {
|
|
3426
|
+
this.#w(e) && (e.code === "KeyF" && !e.repeat && (this.#u = !this.#u), this.#o.add(e.code), this.#u && this.#E());
|
|
3427
|
+
};
|
|
3428
|
+
#S = (e) => {
|
|
3429
|
+
this.#o.delete(e.code);
|
|
3430
|
+
};
|
|
3431
|
+
#C = async (e) => {
|
|
3432
|
+
if (!this.#w(e)) return;
|
|
3433
|
+
let t = await this.#t.pick(e.offsetX, e.offsetY);
|
|
3434
|
+
if (!t || this.#i.signal.aborted) return;
|
|
3435
|
+
let [n, r, i] = t.point, a = Fn(Z(this.#f), {
|
|
3436
|
+
e: n,
|
|
3437
|
+
n: r,
|
|
3438
|
+
h: i
|
|
3439
|
+
});
|
|
3440
|
+
this.#O(X(a, void 0, this.#r));
|
|
3441
|
+
};
|
|
3442
|
+
#w(e) {
|
|
3443
|
+
return this.enabled && !e.defaultPrevented;
|
|
3444
|
+
}
|
|
3445
|
+
#T() {
|
|
3446
|
+
if (this.#a.size < 2) return null;
|
|
3447
|
+
let [e, t] = this.#a.values();
|
|
3448
|
+
return {
|
|
3449
|
+
x: (e.x + t.x) / 2,
|
|
3450
|
+
y: (e.y + t.y) / 2,
|
|
3451
|
+
d: Math.hypot(e.x - t.x, e.y - t.y)
|
|
3452
|
+
};
|
|
3453
|
+
}
|
|
3454
|
+
#E() {
|
|
3455
|
+
this.#i.signal.aborted || this.#t.requestFrame();
|
|
3456
|
+
}
|
|
3457
|
+
#D = (e) => {
|
|
3458
|
+
let t = this.#g === null ? 1 / 60 : Math.min(.1, (e - this.#g) / 1e3);
|
|
3459
|
+
this.#g = e;
|
|
3460
|
+
let n = this.#d, [r, i] = this.#c;
|
|
3461
|
+
if (r || i) {
|
|
3462
|
+
let e = Jn(n.dist, this.#e.clientHeight);
|
|
3463
|
+
n = zn(n, -r * e, i * e);
|
|
3464
|
+
}
|
|
3465
|
+
let [a, o] = this.#s;
|
|
3466
|
+
if (a || o) {
|
|
3467
|
+
let [e, t] = [n.yaw + a * Un, n.pitch - o * Un];
|
|
3468
|
+
n = this.#u ? In(n, e, t, this.#r) : X({
|
|
3469
|
+
...n,
|
|
3470
|
+
yaw: e,
|
|
3471
|
+
pitch: t
|
|
3472
|
+
}, void 0, this.#r);
|
|
3473
|
+
}
|
|
3474
|
+
this.#l && (n = X({
|
|
3475
|
+
...n,
|
|
3476
|
+
dist: n.dist * Math.exp(this.#l)
|
|
3477
|
+
}, void 0, this.#r)), this.#c = [0, 0], this.#s = [0, 0], this.#l = 0;
|
|
3478
|
+
let [s, c, l] = Yn(this.#o), u = this.enabled && this.#u && (s !== 0 || l !== 0 || c !== 0);
|
|
3479
|
+
if (u) {
|
|
3480
|
+
let e = Kn * Ln(n) * t;
|
|
3481
|
+
n = Rn(n, s * e, c * e, l * e);
|
|
3482
|
+
}
|
|
3483
|
+
let d = this.#f;
|
|
3484
|
+
n !== this.#d && this.#k(!1);
|
|
3485
|
+
let f = this.#p;
|
|
3486
|
+
if (f) {
|
|
3487
|
+
f.start ??= e;
|
|
3488
|
+
let t = Math.min(1, (e - f.start) / f.path.ms);
|
|
3489
|
+
this.#d = this.#f = this.#j(f.path.at(t)), t === 1 && this.#k(!0);
|
|
3490
|
+
} else d !== n && (this.#d = n = this.#j(n), this.#f = Xn(d, n, t, this.#n, this.#r));
|
|
3491
|
+
this.#f !== d && this.#A(), u || this.#p || this.#f !== this.#d ? this.#E() : this.#g = null;
|
|
3492
|
+
};
|
|
3493
|
+
#O(e) {
|
|
3494
|
+
this.#k(!1), this.#d = e, this.#E();
|
|
3495
|
+
}
|
|
3496
|
+
#k(e) {
|
|
3497
|
+
let t = this.#p;
|
|
3498
|
+
this.#p = null, t?.land(e);
|
|
3499
|
+
}
|
|
3500
|
+
#A() {
|
|
3501
|
+
this.#M();
|
|
3502
|
+
let e = this.pose;
|
|
3503
|
+
for (let t of this.#m) t(e);
|
|
3504
|
+
}
|
|
3505
|
+
#j(e) {
|
|
3506
|
+
return X(e, this.#n, this.#r);
|
|
3507
|
+
}
|
|
3508
|
+
#M() {
|
|
3509
|
+
this.#t.setCamera(Nn(this.#f));
|
|
3510
|
+
}
|
|
3511
|
+
};
|
|
3512
|
+
function $(e, t, n) {
|
|
3513
|
+
e[0] += t, e[1] += n;
|
|
3514
|
+
}
|
|
3515
|
+
//#endregion
|
|
3516
|
+
export { yt as C, Kt as S, An as _, Z as a, Nn as b, Bn as c, jn as d, Ln as f, zn as g, kn as h, Q as i, Vn as l, Fn as m, yn as n, X as o, In as p, J as r, bn as s, Zn as t, Rn as u, Pn as v, ve as w, Gt as x, Hn as y };
|