@kalyptos/narcissus 0.1.3 → 0.2.1

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