@kalyptos/narcissus 0.1.0 → 0.1.2

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.
@@ -1,4 +1,4 @@
1
- import { F as e, I as t, c as n, l as r, m as i, u as a } from "./format-CxKTIugr.js";
1
+ import { F as e, I as t, c as n, l as r, m as i, u as a } from "./format-C3Vn0c2b.js";
2
2
  import { t as o } from "./ports-DZRKjdYD.js";
3
3
  import { t as s } from "./http-DL7R39Nc.js";
4
4
  //#region src/engine/gpu/layout.ts
@@ -56,42 +56,36 @@ var m = 19, h = 1024, g = class {
56
56
  capacity;
57
57
  #e;
58
58
  #t = /* @__PURE__ */ new Map();
59
- #n = /* @__PURE__ */ new Set();
60
- #r;
61
- #i;
59
+ #n = null;
60
+ #r = null;
61
+ #i = /* @__PURE__ */ new Set();
62
62
  #a;
63
- #o = [
63
+ #o;
64
+ #s = 0;
65
+ #c;
66
+ #l = [
64
67
  0,
65
68
  0,
66
69
  0
67
70
  ];
68
- #s;
69
- #c;
70
- #l = new g();
71
71
  #u;
72
72
  #d;
73
73
  #f = new g();
74
74
  #p;
75
+ #m;
76
+ #h = new g();
77
+ #g;
78
+ #_ = [];
75
79
  constructor(e, t) {
76
80
  this.capacity = t, this.#e = e;
77
- let n = this.slots, r = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, i = (t, n) => e.createBuffer({
78
- label: t,
79
- size: n,
80
- usage: r
81
- });
82
- this.geometry = i("pool geometry", t * 4 * 4), this.colour = i("pool colour", t * 3 * 4), this.pages = i("pool pages", n * 36 * 4), this.clusters = i("pool clusters", n * 12 * 4), this.list = i("pool list", n * 4), this.#r = new Uint8Array(n), this.#i = n, this.#a = Array.from({ length: n }, (e, t) => n - 1 - t), this.#s = new Uint32Array(n * 36), this.#c = new Float32Array(this.#s.buffer), this.#u = new Uint32Array(n * 12), this.#d = new Float32Array(this.#u.buffer), this.#p = new Uint32Array(n);
81
+ let n = this.slots;
82
+ this.#y(), 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);
83
83
  }
84
84
  get slots() {
85
85
  return this.capacity / 256;
86
86
  }
87
87
  get bytes() {
88
- return [
89
- this.geometry,
90
- this.colour,
91
- this.pages,
92
- this.clusters,
93
- this.list
94
- ].reduce((e, t) => e + t.size, 0);
88
+ return this.#v().reduce((e, t) => e + t.size, 0);
95
89
  }
96
90
  has(e) {
97
91
  let t = this.#t.get(e);
@@ -101,120 +95,181 @@ var m = 19, h = 1024, g = class {
101
95
  return this.#t.has(e);
102
96
  }
103
97
  *ids() {
104
- for (let [e, t] of this.#t) t.page === null && (yield e);
98
+ for (let e = this.#n; e; e = e.next) e.page === null && (yield e.id);
105
99
  }
106
100
  add(e, n, r, i) {
107
101
  if (this.#t.has(e)) return !0;
108
102
  let a = c(n.count) / 256;
109
- if (!this.#m(a, i)) return !1;
110
- let o = t.origin;
111
- return this.#t.set(e, {
103
+ if (!this.#S(a, i)) return !1;
104
+ let o = t.origin, s = {
105
+ id: e,
106
+ previous: null,
107
+ next: null,
112
108
  page: n,
113
- slots: this.#v(a),
114
- table: this.#a.pop(),
109
+ slots: this.#E(a),
110
+ active: [],
111
+ mask: 0,
112
+ table: this.#c.pop(),
115
113
  base: [
116
114
  n.params[o] + r[0],
117
115
  n.params[o + 1] + r[1],
118
116
  n.params[o + 2]
119
117
  ],
120
118
  factors: 0
121
- }), this.#n.add(e), !0;
119
+ };
120
+ return this.#t.set(e, s), this.#x(s), this.#i.add(e), !0;
122
121
  }
123
122
  remove(e) {
124
123
  let t = this.#t.get(e);
125
124
  if (t) {
126
- this.#t.delete(e), this.#n.delete(e);
127
- for (let e of t.slots) this.#r[e] = 0;
128
- this.#i += t.slots.length, this.#a.push(t.table), t.page === null && t.factors !== 0 && this.#_(t, 0);
125
+ this.#b(t), this.#t.delete(e), this.#i.delete(e);
126
+ for (let e of t.slots) this.#a[e] = 0;
127
+ 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.#T(t, 0);
129
128
  }
130
129
  }
131
130
  clear() {
132
131
  for (let e of this.#t.keys()) this.remove(e);
133
132
  }
134
133
  get queued() {
135
- return this.#n.size;
134
+ return this.#i.size;
136
135
  }
137
136
  upload(e) {
138
137
  let t = 0;
139
- for (let n of this.#n) {
138
+ for (let n of this.#i) {
140
139
  if (t >= e) break;
141
- t += this.#h(this.#t.get(n)), this.#n.delete(n);
140
+ t += this.#C(this.#t.get(n)), this.#i.delete(n);
142
141
  }
143
142
  return t;
144
143
  }
145
144
  draw(e) {
146
- let t = 0;
147
- for (let { id: n, factors: r } of e) {
148
- let e = this.#t.get(n);
149
- e && e.page === null && (e.factors !== r && this.#_(e, r), this.#t.delete(n), this.#t.set(n, e), this.#p.set(e.slots, t), t += e.slots.length);
145
+ let t = 0, n = 0, r = !1;
146
+ for (let { id: i, factors: a } of e) {
147
+ let e = this.#t.get(i);
148
+ if (!e || e.page !== null) continue;
149
+ let o = e.active;
150
+ e.factors !== a && this.#T(e, a), r ||= o !== e.active, this.#x(e), r ||= this.#_[n] !== e, this.#_[n++] = e, r && this.#g.set(e.active, t), t += e.active.length;
150
151
  }
151
- this.listed = t;
152
- let n = this.#e.queue;
153
- this.#l.flush(n, this.pages, this.#s), this.#f.flush(n, this.clusters, this.#u), n.writeBuffer(this.list, 0, this.#p, 0, t);
152
+ r ||= this.#_.length !== n, this.#_.length = n, this.listed = t;
153
+ let i = this.#e.queue;
154
+ 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);
154
155
  }
155
156
  setOrigin(e) {
156
- this.#o = [
157
+ this.#l = [
157
158
  e[0],
158
159
  e[1],
159
160
  e[2]
160
161
  ];
161
- for (let e of this.#t.values()) e.page === null && this.#g(e);
162
- this.#e.queue.writeBuffer(this.pages, 0, this.#s), this.#l.clear();
162
+ for (let e of this.#t.values()) e.page === null && this.#w(e);
163
+ this.#e.queue.writeBuffer(this.pages, 0, this.#u), this.#f.clear();
164
+ }
165
+ grow(e) {
166
+ if (e <= this.capacity) return;
167
+ let t = this.slots, n = this.#v();
168
+ this.capacity = e, this.#y();
169
+ let r = this.#e.createCommandEncoder({ label: "pool grow" });
170
+ this.#v().forEach((e, t) => r.copyBufferToBuffer(n[t], 0, e, 0, n[t].size)), this.#e.queue.submit([r.finish()]);
171
+ for (let e of n) e.destroy();
172
+ let i = this.slots, a = new Uint8Array(i);
173
+ a.set(this.#a), this.#a = a, this.#o += i - t;
174
+ for (let e = i - 1; e >= t; e--) this.#c.push(e);
175
+ let o = new Uint32Array(i * 36);
176
+ o.set(this.#u), this.#u = o, this.#d = new Float32Array(o.buffer);
177
+ let s = new Uint32Array(i * 12);
178
+ s.set(this.#p), this.#p = s, this.#m = new Float32Array(s.buffer);
179
+ let c = new Uint32Array(i);
180
+ c.set(this.#g), this.#g = c;
163
181
  }
164
182
  destroy() {
165
- let e = [
183
+ for (let e of this.#v()) e.destroy();
184
+ }
185
+ #v() {
186
+ return [
166
187
  this.geometry,
167
188
  this.colour,
168
189
  this.pages,
169
190
  this.clusters,
170
191
  this.list
171
192
  ];
172
- for (let t of e) t.destroy();
173
193
  }
174
- #m(e, t) {
175
- let n = this.#i;
194
+ #y() {
195
+ let { capacity: e, slots: t } = this, n = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC, r = (e, t) => this.#e.createBuffer({
196
+ label: e,
197
+ size: t,
198
+ usage: n
199
+ });
200
+ 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);
201
+ }
202
+ #b(e) {
203
+ 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;
204
+ }
205
+ #x(e) {
206
+ this.#r !== e && (this.#b(e), e.previous = this.#r, this.#r ? this.#r.next = e : this.#n = e, this.#r = e);
207
+ }
208
+ #S(e, t) {
209
+ let n = this.#o;
176
210
  if (n >= e) return !0;
177
211
  let r = [];
178
- for (let [i, a] of this.#t) if (!(a.page !== null || t(i)) && (r.push(i), n += a.slots.length, n >= e)) break;
212
+ for (let i = this.#n; i && !(!(i.page !== null || t(i.id)) && (r.push(i.id), n += i.slots.length, n >= e)); i = i.next);
179
213
  if (n < e) return !1;
180
214
  for (let e of r) this.remove(e);
181
215
  return !0;
182
216
  }
183
- #h(e) {
184
- let n = e.page, { slots: r } = e, i = this.#e.queue, a = r.length, o = this.#u, s = this.#d;
217
+ #C(e) {
218
+ let n = e.page, { slots: r } = e, i = this.#e.queue, a = r.length, o = this.#p, s = this.#m;
185
219
  for (let t = 0; t < a; t++) {
186
220
  let i = r[t] * 12;
187
- o.fill(0, i, i + 12), o[i] = e.table, o[i + 1] = r[t] * 256, o[i + 2] = t * 256, o[i + 3] = Math.max(0, Math.min(256, n.count - t * 256)), s.set(n.clusters.subarray(t * 6, t * 6 + 3), i + 4), s.set(n.clusters.subarray(t * 6 + 3, t * 6 + 6), i + 8);
221
+ o.fill(0, i, i + 12), o[i] = e.table, o[i + 1] = r[t] * 256, o[i + 2] = t * 256, o[i + 3] = Math.max(0, Math.min(256, n.count - t * 256));
222
+ for (let e = 0; e < 3; e++) s[i + 4 + e] = n.clusters[t * 6 + e], s[i + 8 + e] = n.clusters[t * 6 + 3 + e];
188
223
  }
189
224
  for (let e = 0; e < a;) {
190
225
  let t = 1;
191
226
  for (; e + t < a && r[e + t] === r[e] + t;) t++;
192
227
  let o = e * 256, s = Math.min((e + t) * 256, n.count) - o, c = r[e] * 256;
193
- 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.#f.mark(r[e] * 12, (r[e] + t) * 12), e += t;
228
+ 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;
194
229
  }
195
- let c = e.table * 36, l = this.#s, u = this.#c, d = n.params, [f, p, m] = n.quadrants;
196
- return l.fill(0, c, c + 36), this.#g(e), l[c + 3] = n.count, u.set(d.subarray(t.step, t.step + 3), c + 4), l[c + 7] = f, u.set(d.subarray(t.scaleMin, t.scaleMin + 3), c + 8), l[c + 11] = p, u.set(d.subarray(t.scaleMax, t.scaleMax + 3), c + 12), l[c + 15] = m, u.set(d.subarray(t.dcMin, t.dcMin + 3), c + 16), u.set(d.subarray(t.dcMax, t.dcMax + 3), c + 20), u.set(d.subarray(t.shScale, t.shScale + 9), c + 24), this.#l.mark(c, c + 36), e.page = null, n.count * 7 * 4 + a * 12 * 4 + 144;
230
+ let c = e.table * 36, l = this.#u, u = this.#d, d = n.params, [f, p, m] = n.quadrants;
231
+ return l.fill(0, c, c + 36), this.#w(e), l[c + 3] = n.count, u.set(d.subarray(t.step, t.step + 3), c + 4), l[c + 7] = f, u.set(d.subarray(t.scaleMin, t.scaleMin + 3), c + 8), l[c + 11] = p, u.set(d.subarray(t.scaleMax, t.scaleMax + 3), c + 12), l[c + 15] = m, u.set(d.subarray(t.dcMin, t.dcMin + 3), c + 16), u.set(d.subarray(t.dcMax, t.dcMax + 3), c + 20), u.set(d.subarray(t.shScale, t.shScale + 9), c + 24), this.#f.mark(c, c + 36), e.page = null, n.count * 7 * 4 + a * 12 * 4 + 144;
197
232
  }
198
- #g(e) {
233
+ #w(e) {
199
234
  let t = e.table * 36;
200
- for (let n = 0; n < 3; n++) this.#c[t + n] = e.base[n] - this.#o[n];
235
+ for (let n = 0; n < 3; n++) this.#d[t + n] = e.base[n] - this.#l[n];
201
236
  }
202
- #_(e, t) {
237
+ #T(e, t) {
238
+ let n = 0;
239
+ for (let e = 0; e < 4; e++) t >>> 8 * e & 255 && (n |= 1 << e);
240
+ if (n !== e.mask) {
241
+ if (e.mask = n, n === 15 && this.#u[e.table * 36 + 3] > 0) e.active = e.slots;
242
+ else {
243
+ let t = [], r = e.table * 36, i = 0, a = -1;
244
+ for (let o = 0; o < 4; o++) {
245
+ let s = this.#u[r + (o === 3 ? 3 : 7 + 4 * o)];
246
+ if (n & 1 << o && s > i) for (let n = Math.max(a + 1, Math.floor(i / 256)); n < Math.ceil(s / 256); n++) t.push(e.slots[n]), a = n;
247
+ i = s;
248
+ }
249
+ e.active = t;
250
+ }
251
+ }
203
252
  e.factors = t;
204
- let n = e.table * 36 + m;
205
- this.#s[n] = t, this.#l.mark(n, n + 1);
206
- }
207
- #v(e) {
208
- let t = this.#r, n = -1;
209
- for (let r = 0, i = 0; r < t.length; r++) if (i = t[r] ? 0 : i + 1, i === e) {
210
- n = r - e + 1;
211
- break;
253
+ let r = e.table * 36 + m;
254
+ this.#u[r] = t, this.#f.mark(r, r + 1);
255
+ }
256
+ #E(e) {
257
+ let t = this.#a, n = -1;
258
+ for (let r = this.#s; r <= t.length - e;) {
259
+ let i = r;
260
+ for (; i < r + e && !t[i];) i++;
261
+ if (i === r + e) {
262
+ n = r;
263
+ break;
264
+ }
265
+ if (r = t.indexOf(0, i + 1), r < 0) break;
212
266
  }
213
267
  let r = [];
214
268
  if (n >= 0) for (let t = n; t < n + e; t++) r.push(t);
215
- else for (let n = 0; r.length < e; n++) t[n] || r.push(n);
269
+ else for (let n = this.#s; r.length < e; n = t.indexOf(0, n + 1)) r.push(n);
216
270
  for (let e of r) t[e] = 1;
217
- return this.#i -= e, r;
271
+ let i = t.indexOf(0, this.#s);
272
+ return this.#s = i < 0 ? t.length : i, this.#o -= e, r;
218
273
  }
219
274
  };
220
275
  //#endregion
@@ -271,12 +326,14 @@ function T(e, t, n) {
271
326
  r("work", (l.list + n) * 4, i | GPUBufferUsage.INDIRECT),
272
327
  r("projected", t * 6 * 4, i),
273
328
  r("sort", t * 16, i),
274
- r("plugins", 256, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST)
275
- ], [o, s, c, u, d] = a;
329
+ r("plugins", 256, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST),
330
+ r("visible clusters", 4, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST)
331
+ ], [o, s, c, u, d, f] = a;
276
332
  return {
277
333
  capacity: t,
278
334
  uniforms: o,
279
335
  work: s,
336
+ visible: f,
280
337
  projected: c,
281
338
  sort: u,
282
339
  plugins: d,
@@ -306,7 +363,7 @@ function D(e, t, n, r) {
306
363
  }
307
364
  //#endregion
308
365
  //#region src/engine/gpu/common.wgsl?raw
309
- var O = "// 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 pad: 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 pad0: u32,\n boxMax: vec3f,\n pad1: 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", k = "// 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// some quadrant the cluster's splats overlap has a nonzero factor\nfn lit(page: Page, cluster: Cluster) -> bool {\n var starts = array<u32, 5>(0u, page.q1, page.q2, page.q3, page.count);\n let end = cluster.first + cluster.count;\n for (var k = 0u; k < 4u; k++) {\n let overlaps = max(starts[k], cluster.first) < min(starts[k + 1u], end);\n if (overlaps && extractBits(page.factors, 8u * k, 8u) != 0u) {\n return true;\n }\n }\n return false;\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) || !lit(page, cluster)) {\n return;\n }\n atomicStore(&work[WORK_LIST + atomicAdd(&work[WORK_VISIBLE], 1u)], slot);\n}\n", A = 64, j = class {
366
+ var O = "// 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 pad: 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 pad0: u32,\n boxMax: vec3f,\n pad1: 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", k = "// 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", A = 64, j = class {
310
367
  #e;
311
368
  #t;
312
369
  #n;
@@ -344,10 +401,10 @@ var O = "// shared by every engine pass; sizes and word offsets mirror format/sp
344
401
  label: "cull",
345
402
  timestampWrites: t
346
403
  });
347
- n.setBindGroup(0, this.#n), n.setPipeline(this.#t), n.dispatchWorkgroups(Math.ceil(this.#e.listed / A)), n.end();
404
+ n.setBindGroup(0, this.#n), n.setPipeline(this.#t), this.#e.listed && n.dispatchWorkgroups(Math.ceil(this.#e.listed / A)), n.end();
348
405
  }
349
- }, M = "// 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 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", ee = 32, te = .5, ne = 1;
350
- function re(e) {
406
+ }, M = "// 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 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", N = 32, ee = .5, te = 1;
407
+ function ne(e) {
351
408
  let t = new Uint32Array(e.length);
352
409
  for (let n = 0; n < e.length; n++) {
353
410
  let r = e[n];
@@ -355,7 +412,7 @@ function re(e) {
355
412
  }
356
413
  return new Float32Array(t.buffer);
357
414
  }
358
- var ie = class {
415
+ var re = class {
359
416
  #e;
360
417
  #t;
361
418
  #n;
@@ -385,7 +442,7 @@ var ie = class {
385
442
  encode(e, t, n, r, i) {
386
443
  let a = this.#e, o = this.#t, { listed: s } = o, c = r * r * 4, l = a.createBuffer({
387
444
  label: "heights area",
388
- size: ee,
445
+ size: N,
389
446
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
390
447
  }), u = a.createBuffer({
391
448
  label: "heights",
@@ -395,14 +452,14 @@ var ie = class {
395
452
  label: "heights readback",
396
453
  size: c,
397
454
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
398
- }), p = /* @__PURE__ */ new ArrayBuffer(ee);
455
+ }), p = /* @__PURE__ */ new ArrayBuffer(N);
399
456
  new Float32Array(p).set([
400
457
  t,
401
458
  n,
402
459
  0,
403
460
  0,
404
- te,
405
- ne
461
+ ee,
462
+ te
406
463
  ]), new Uint32Array(p).set([r, s], 2), a.queue.writeBuffer(l, 0, p);
407
464
  let m = [
408
465
  l,
@@ -415,11 +472,11 @@ var ie = class {
415
472
  label: "heights",
416
473
  timestampWrites: i
417
474
  });
418
- return g.setPipeline(this.#r), g.setBindGroup(0, h), s > 0 && g.dispatchWorkgroups(...d(s)), g.end(), e.copyBufferToBuffer(u, 0, f, 0, c), () => f.mapAsync(GPUMapMode.READ).then(() => re(new Uint32Array(f.getMappedRange())), () => null).finally(() => {
475
+ return g.setPipeline(this.#r), g.setBindGroup(0, h), s > 0 && g.dispatchWorkgroups(...d(s)), g.end(), e.copyBufferToBuffer(u, 0, f, 0, c), () => f.mapAsync(GPUMapMode.READ).then(() => ne(new Uint32Array(f.getMappedRange())), () => null).finally(() => {
419
476
  l.destroy(), u.destroy(), f.destroy();
420
477
  });
421
478
  }
422
- }, ae = "@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", oe = class {
479
+ }, ie = "@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", ae = class {
423
480
  #e;
424
481
  #t;
425
482
  #n;
@@ -428,7 +485,7 @@ var ie = class {
428
485
  constructor(e, t, n, r) {
429
486
  let i = e.createShaderModule({
430
487
  label: t,
431
- code: ae + n
488
+ code: ie + n
432
489
  });
433
490
  this.#e = e, this.#t = t, this.#n = e.createRenderPipeline({
434
491
  label: t,
@@ -463,15 +520,17 @@ var ie = class {
463
520
  });
464
521
  r.setPipeline(this.#n), r.setBindGroup(0, this.#i), r.draw(3), r.end();
465
522
  }
466
- }, se = "// 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", ce = (e, t) => new oe(e, "present", se, t), le = "// one workgroup per visible cluster, one thread per splat; shade() follows, generated with the hooks\n\n// ndc reach past the frustum, so splats centred just outside still cover the edge\nconst GUARD: f32 = 1.3;\n\n@group(0) @binding(0) var<uniform> uniforms: FrameUniforms;\n@group(0) @binding(1) var<uniform> plugins: array<vec4f, 16>;\n@group(0) @binding(2) var<storage, read> geometry: array<vec4u>;\n@group(0) @binding(3) var<storage, read> colours: array<u32>;\n@group(0) @binding(4) var<storage, read> pages: array<Page>;\n@group(0) @binding(5) var<storage, read> clusters: array<Cluster>;\n@group(0) @binding(6) var<storage, read_write> work: array<atomic<u32>>;\n@group(0) @binding(7) var<storage, read_write> projected: array<Projected>;\n// keys in [0, capacity), values in [capacity, 2 capacity)\n@group(0) @binding(8) var<storage, read_write> sort: array<u32>;\n\nvar<workgroup> visible: u32;\nvar<workgroup> kept: atomic<u32>;\nvar<workgroup> base: u32;\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// 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 let page = pages[cluster.page];\n let rec = cluster.slot + t;\n let 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 // decode\n var s: Splat;\n let q = vec3f(f32(g.x & 0xffffu), f32(g.x >> 16u), f32(g.y & 0xffffu));\n s.position = page.origin + q * page.step;\n s.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 s.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 d = normalize(s.position - uniforms.camera);\n s.colour = max(0.5 + C0 * dc + C1 * (-d.y * m0 + d.z * m1 - d.x * m2), vec3f(0.0));\n s.depth = -(uniforms.view * vec4f(s.position, 1.0)).z;\n\n shade(&s);\n if (s.opacity < 1.0 / 255.0) {\n return false;\n }\n\n // project\n let viewPos = (uniforms.view * vec4f(s.position, 1.0)).xyz;\n let depth = -viewPos.z;\n if (depth < uniforms.near || depth > uniforms.far) {\n return false;\n }\n let clip = uniforms.proj * vec4f(viewPos, 1.0);\n let ndc = clip.xy / clip.w;\n if (any(abs(ndc) > vec2f(GUARD))) {\n return false;\n }\n\n // ewa: view-space covariance wm wm^T through the jacobian of the pixel projection\n let r = rotate(rotation(g));\n let m = mat3x3f(r[0] * s.scale.x, r[1] * s.scale.y, r[2] * s.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 let a = dot(u, u) + uniforms.lowPass;\n let b = dot(u, v);\n let c = dot(v, v) + uniforms.lowPass;\n let mid = 0.5 * (a + c);\n let rad = length(vec2f(0.5 * (a - c), b));\n let major = sqrt(mid + rad);\n if (3.0 * major < 0.5) {\n return false;\n }\n let minor = sqrt(max(mid - rad, 0.0));\n let angle = 0.5 * atan2(2.0 * b, a - c);\n let axis = vec2f(cos(angle), sin(angle));\n // the quad raster draws; a centre inside the guard band can still miss the screen\n let centre = (ndc * 0.5 + 0.5) * uniforms.viewport;\n let extent = reach(s.opacity) * (abs(axis) * major + abs(axis.yx) * minor);\n if (any(centre + extent < vec2f(0.0)) || any(centre - extent > uniforms.viewport)) {\n return false;\n }\n\n *dest = Projected(\n centre,\n vec2u(pack2x16float(axis * major), pack2x16float(vec2f(-axis.y, axis.x) * minor)),\n vec2u(pack2x16float(s.colour.rg), pack2x16float(vec2f(s.colour.b, s.opacity)))\n );\n let span = clamp(log(depth / uniforms.near) / log(uniforms.far / uniforms.near), 0.0, 1.0);\n *key = u32((1.0 - span) * f32((1u << KEY_BITS) - 1u));\n return true;\n}\n\n@compute @workgroup_size(256)\nfn project(@builtin(workgroup_id) wid: vec3u, @builtin(local_invocation_index) t: u32) {\n if (t == 0u) {\n visible = atomicLoad(&work[WORK_VISIBLE]);\n }\n let index = wid.y * GROUPS_X + wid.x;\n if (index >= workgroupUniformLoad(&visible)) {\n return;\n }\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 workgroup\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], atomicLoad(&kept));\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", ue = class {
523
+ }, oe = "// 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 ae(e, "present", oe, t), ce = "// workgroups loop over visible clusters, one thread per splat\n\n// ndc reach past the frustum, so splats centred just outside still cover the edge\nconst GUARD: f32 = 1.3;\n\n@group(0) @binding(0) var<uniform> uniforms: FrameUniforms;\n@group(0) @binding(1) var<uniform> plugins: array<vec4f, 16>;\n@group(0) @binding(2) var<storage, read> geometry: array<vec4u>;\n@group(0) @binding(3) var<storage, read> colours: array<u32>;\n@group(0) @binding(4) var<storage, read> pages: array<Page>;\n@group(0) @binding(5) var<storage, read> clusters: array<Cluster>;\n@group(0) @binding(6) var<storage, read_write> work: array<atomic<u32>>;\n@group(0) @binding(7) var<storage, read_write> projected: array<Projected>;\n// keys in [0, capacity), values in [capacity, 2 capacity)\n@group(0) @binding(8) var<storage, read_write> sort: array<u32>;\n\n@group(0) @binding(9) var<uniform> visible: u32;\nvar<workgroup> kept: atomic<u32>;\nvar<workgroup> base: u32;\n\n// 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// 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 let page = pages[cluster.page];\n let rec = cluster.slot + t;\n let 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 // decode\n var s: Splat;\n let q = vec3f(f32(g.x & 0xffffu), f32(g.x >> 16u), f32(g.y & 0xffffu));\n s.position = page.origin + q * page.step;\n s.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 s.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 d = normalize(s.position - uniforms.camera);\n s.colour = max(0.5 + C0 * dc + C1 * (-d.y * m0 + d.z * m1 - d.x * m2), vec3f(0.0));\n s.depth = -(uniforms.view * vec4f(s.position, 1.0)).z;\n\n shade(&s);\n if (s.opacity < 1.0 / 255.0) {\n return false;\n }\n\n // project\n let viewPos = (uniforms.view * vec4f(s.position, 1.0)).xyz;\n let depth = -viewPos.z;\n if (depth < uniforms.near || depth > uniforms.far) {\n return false;\n }\n let clip = uniforms.proj * vec4f(viewPos, 1.0);\n let ndc = clip.xy / clip.w;\n if (any(abs(ndc) > vec2f(GUARD))) {\n return false;\n }\n\n // ewa: view-space covariance wm wm^T through the jacobian of the pixel projection\n let r = rotate(rotation(g));\n let m = mat3x3f(r[0] * s.scale.x, r[1] * s.scale.y, r[2] * s.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 let a = dot(u, u) + uniforms.lowPass;\n let b = dot(u, v);\n let c = dot(v, v) + uniforms.lowPass;\n let mid = 0.5 * (a + c);\n let rad = length(vec2f(0.5 * (a - c), b));\n let major = sqrt(mid + rad);\n if (3.0 * major < 0.5) {\n return false;\n }\n let minor = sqrt(max(mid - rad, 0.0));\n let angle = 0.5 * atan2(2.0 * b, a - c);\n let axis = vec2f(cos(angle), sin(angle));\n // the quad raster draws; a centre inside the guard band can still miss the screen\n let centre = (ndc * 0.5 + 0.5) * uniforms.viewport;\n let extent = reach(s.opacity) * (abs(axis) * major + abs(axis.yx) * minor);\n if (any(centre + extent < vec2f(0.0)) || any(centre - extent > uniforms.viewport)) {\n return false;\n }\n\n *dest = Projected(\n centre,\n vec2u(pack2x16float(axis * major), pack2x16float(vec2f(-axis.y, axis.x) * minor)),\n vec2u(pack2x16float(s.colour.rg), pack2x16float(vec2f(s.colour.b, s.opacity)))\n );\n let span = clamp(log(depth / uniforms.near) / log(uniforms.far / uniforms.near), 0.0, 1.0);\n *key = u32((1.0 - span) * f32((1u << KEY_BITS) - 1u));\n return true;\n}\n\n@compute @workgroup_size(256)\nfn project(\n @builtin(workgroup_id) wid: vec3u,\n @builtin(num_workgroups) groups: vec3u,\n @builtin(local_invocation_index) t: u32\n) {\n for (var index = wid.y * groups.x + wid.x; index < visible; index += groups.x * groups.y) {\n let cluster = clusters[atomicLoad(&work[WORK_LIST + index])];\n var splat: Projected;\n var key = 0u;\n var keep = false;\n if (t < cluster.count) {\n keep = shown(cluster, t, &splat, &key);\n }\n\n // one global atomic per cluster\n var rank = 0u;\n if (keep) {\n rank = atomicAdd(&kept, 1u);\n }\n workgroupBarrier();\n if (t == 0u) {\n base = atomicAdd(&work[WORK_PROJECTED], atomicExchange(&kept, 0u));\n }\n let i = workgroupUniformLoad(&base) + rank;\n let capacity = arrayLength(&projected);\n if (keep && i < capacity) {\n projected[i] = splat;\n sort[i] = key;\n sort[capacity + i] = i;\n }\n }\n}\n", le = class {
467
524
  #e;
468
525
  #t;
469
526
  #n;
470
527
  #r = [];
471
528
  #i;
472
529
  #a;
530
+ #o;
531
+ #s;
473
532
  constructor(e, t, n) {
474
- this.#e = e, this.#a = t;
533
+ this.#e = e, this.#a = t, this.#o = n.work, this.#s = n.visible;
475
534
  let r = E(e, "project", GPUShaderStage.COMPUTE, [
476
535
  "uniform",
477
536
  "uniform",
@@ -481,7 +540,8 @@ var ie = class {
481
540
  "read-only-storage",
482
541
  "storage",
483
542
  "storage",
484
- "storage"
543
+ "storage",
544
+ "uniform"
485
545
  ]);
486
546
  this.#t = e.createPipelineLayout({ bindGroupLayouts: [r] });
487
547
  let i = [
@@ -493,27 +553,29 @@ var ie = class {
493
553
  t.clusters,
494
554
  n.work,
495
555
  n.projected,
496
- n.sort
556
+ n.sort,
557
+ n.visible
497
558
  ];
498
559
  this.#i = D(e, "project", r, i);
499
560
  }
500
561
  hooks(e) {
501
562
  this.#r = e, this.#n = void 0;
502
563
  }
503
- encode(e, t) {
504
- let n = Math.max(1, this.#a.listed), r = e.beginComputePass({
564
+ encode(e, t, n) {
565
+ e.copyBufferToBuffer(this.#o, l.visible * 4, this.#s, 0, 4);
566
+ let r = Math.max(1, Math.min(128, this.#a.listed, t ? Math.max(32, Math.ceil(t / 16)) : 128)), i = e.beginComputePass({
505
567
  label: "project",
506
- timestampWrites: t
568
+ timestampWrites: n
507
569
  });
508
- r.setPipeline(this.#n ??= this.#o()), r.setBindGroup(0, this.#i), r.dispatchWorkgroups(...d(n)), r.end();
570
+ i.setPipeline(this.#n ??= this.#c()), i.setBindGroup(0, this.#i), i.dispatchWorkgroups(r), i.end();
509
571
  }
510
- #o() {
572
+ #c() {
511
573
  let e = this.#r, t = e.map(({ shade: e, slot: t }) => {
512
574
  let n = Array.from({ length: e.uniforms }, (e, n) => `plugins[${t + n}]`);
513
575
  return `\t${e.name}(s, array<vec4f, ${e.uniforms}>(${n.join(", ")}));`;
514
576
  }), n = [
515
577
  O,
516
- le,
578
+ ce,
517
579
  ...e.map(({ shade: e }) => e.wgsl),
518
580
  "fn shade(s: ptr<function, Splat>) {",
519
581
  ...t,
@@ -531,10 +593,10 @@ var ie = class {
531
593
  }
532
594
  });
533
595
  }
534
- }, de = "// 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", fe = "rgb10a2unorm", pe = "depth16unorm", me = {
596
+ }, ue = "// 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", de = "rgb10a2unorm", fe = "depth16unorm", pe = {
535
597
  srcFactor: "one",
536
598
  dstFactor: "one-minus-src-alpha"
537
- }, he = class {
599
+ }, me = class {
538
600
  #e;
539
601
  #t;
540
602
  #n;
@@ -567,7 +629,7 @@ var ie = class {
567
629
  ]);
568
630
  let a = e.createShaderModule({
569
631
  label: "raster",
570
- code: O + de
632
+ code: O + ue
571
633
  }), o = e.createPipelineLayout({ bindGroupLayouts: [i] }), s = (t, n) => e.createRenderPipeline({
572
634
  label: `raster ${t}`,
573
635
  layout: o,
@@ -579,10 +641,10 @@ var ie = class {
579
641
  module: a,
580
642
  entryPoint: "fs",
581
643
  targets: [{
582
- format: fe,
644
+ format: de,
583
645
  blend: {
584
- color: me,
585
- alpha: me
646
+ color: pe,
647
+ alpha: pe
586
648
  }
587
649
  }]
588
650
  },
@@ -590,7 +652,7 @@ var ie = class {
590
652
  depthStencil: n
591
653
  });
592
654
  this.#n = s("Colour"), this.#r = s("Depth", {
593
- format: pe,
655
+ format: fe,
594
656
  depthWriteEnabled: !0,
595
657
  depthCompare: "always"
596
658
  });
@@ -618,7 +680,7 @@ var ie = class {
618
680
  this.#t.destroy();
619
681
  }
620
682
  };
621
- function ge(e, t, n, r, i, a, o) {
683
+ function he(e, t, n, r, i, a, o) {
622
684
  let { width: s, height: c } = n, l = Math.ceil(s * 2 / 256) * 256, u = e.createBuffer({
623
685
  label: "pick",
624
686
  size: l * c,
@@ -636,7 +698,7 @@ function ge(e, t, n, r, i, a, o) {
636
698
  }
637
699
  //#endregion
638
700
  //#region src/engine/gpu/sort.wgsl?raw
639
- var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan, a stable scatter; no spin-waits\n\nconst THREADS: u32 = 256u;\nconst ITEMS: u32 = 4u;\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> sk: array<u32, BLOCK>;\nvar<workgroup> sv: array<u32, BLOCK>;\nvar<workgroup> counts: array<vec4u, THREADS>;\nvar<workgroup> starts: array<u32, DIGITS>;\nvar<workgroup> offsets: array<u32, DIGITS>;\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 let block = wid.y * groups.x + wid.x;\n if (block >= state.blocks) {\n return;\n }\n atomicStore(&bins[t], 0u);\n workgroupBarrier();\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 hist[block * DIGITS + t] = atomicLoad(&bins[t]);\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 workgroupBarrier();\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 block = wid.y * groups.x + wid.x;\n if (block >= state.blocks) {\n return;\n }\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 offsets[t] = hist[block * DIGITS + t];\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 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;\n workgroupBarrier();\n for (var o = 1u; o < THREADS; o *= 2u) {\n var x = vec4u(0u);\n if (t >= o) {\n x = counts[t - o];\n }\n workgroupBarrier();\n counts[t] += x;\n workgroupBarrier();\n }\n let total = counts[THREADS - 1u];\n let prior = counts[t] - mine;\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}\n", ve = 1024, ye = 64, be = 256, N = 3, P = 256, xe = 32, Se = class {
701
+ var ge = "// 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", P = 1024, _e = 64, ve = 256, F = 3, I = 256, ye = 32, be = class {
640
702
  keys;
641
703
  values;
642
704
  bytes;
@@ -646,25 +708,24 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
646
708
  #r;
647
709
  #i;
648
710
  #a;
649
- #o;
650
711
  constructor(e, t) {
651
712
  let { capacity: n } = t;
652
713
  this.keys = n * 8, this.values = n * 12;
653
- let r = Math.max(1, Math.ceil(n / ve));
654
- this.#a = d(r), this.#o = Math.ceil(r / ye);
655
- let i = (t, n, r) => e.createBuffer({
714
+ let r = Math.max(1, Math.ceil(n / P));
715
+ this.#a = r;
716
+ let i = Math.ceil(r / _e), a = (t, n, r) => e.createBuffer({
656
717
  label: t,
657
718
  size: n,
658
719
  usage: r
659
- }), a = GPUBufferUsage.STORAGE, o = i("sort params", N * P, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST), s = i("sort histograms", r * be * 4, a), c = i("sort chunk sums", this.#o * be * 4, a), u = i("sort state", 12, a);
720
+ }), o = GPUBufferUsage.STORAGE, s = a("sort params", F * I, GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST), c = a("sort histograms", r * ve * 4, o), u = a("sort chunk sums", (i * ve + 1) * 4, o), d = a("sort state", 12, o);
660
721
  this.#e = [
661
- o,
662
722
  s,
663
723
  c,
664
- u
724
+ u,
725
+ d
665
726
  ], this.bytes = this.#e.reduce((e, t) => e + t.size, 0);
666
- let f = new Uint32Array(N * P / 4);
667
- for (let e = 0; e < N; e++) {
727
+ let f = new Uint32Array(F * I / 4);
728
+ for (let e = 0; e < F; e++) {
668
729
  let [t, r] = e % 2 ? [2 * n, 0] : [0, 2 * n];
669
730
  f.set([
670
731
  8 * e,
@@ -673,9 +734,9 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
673
734
  n,
674
735
  l.projected,
675
736
  l.drawArgs
676
- ], e * P / 4);
737
+ ], e * I / 4);
677
738
  }
678
- e.queue.writeBuffer(o, 0, f);
739
+ e.queue.writeBuffer(s, 0, f);
679
740
  let p = (e, t) => ({
680
741
  binding: e,
681
742
  visibility: GPUShaderStage.COMPUTE,
@@ -695,7 +756,7 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
695
756
  ]
696
757
  }), g = e.createShaderModule({
697
758
  label: "sort",
698
- code: O + _e
759
+ code: O + ge
699
760
  }), _ = (t, n) => e.createComputePipeline({
700
761
  label: `sort ${t}`,
701
762
  layout: e.createPipelineLayout({ bindGroupLayouts: [n] }),
@@ -712,9 +773,9 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
712
773
  "scatter"
713
774
  ].map((e) => _(e, m));
714
775
  let v = (e) => ({
715
- buffer: o,
716
- offset: e * P,
717
- size: xe
776
+ buffer: s,
777
+ offset: e * I,
778
+ size: ye
718
779
  });
719
780
  this.#r = e.createBindGroup({
720
781
  label: "sort prepare",
@@ -726,14 +787,14 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
726
787
  },
727
788
  {
728
789
  binding: 5,
729
- resource: { buffer: u }
790
+ resource: { buffer: d }
730
791
  },
731
792
  {
732
793
  binding: 6,
733
794
  resource: { buffer: t.work }
734
795
  }
735
796
  ]
736
- }), this.#i = Array.from({ length: N }, (n, r) => e.createBindGroup({
797
+ }), this.#i = Array.from({ length: F }, (n, r) => e.createBindGroup({
737
798
  label: `sort pass ${r}`,
738
799
  layout: m,
739
800
  entries: [
@@ -747,32 +808,32 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
747
808
  },
748
809
  {
749
810
  binding: 2,
750
- resource: { buffer: s }
811
+ resource: { buffer: c }
751
812
  },
752
813
  {
753
814
  binding: 3,
754
- resource: { buffer: c }
815
+ resource: { buffer: u }
755
816
  },
756
817
  {
757
818
  binding: 4,
758
- resource: { buffer: u }
819
+ resource: { buffer: d }
759
820
  }
760
821
  ]
761
822
  }));
762
823
  }
763
- encode(e, t) {
764
- let [n, r, i, a, o] = this.#n, s = this.#a, c = e.beginComputePass({
824
+ encode(e, t, n, r) {
825
+ let [i, a, o, s, c] = this.#n, l = Math.max(1, Math.min(this.#a, Math.ceil(t / P))), u = Math.max(l / 16, (n || t) / P), f = d(Math.min(Math.ceil(l / 4), Math.ceil(u))), p = Math.ceil(l / _e), m = e.beginComputePass({
765
826
  label: "sort",
766
- timestampWrites: t
827
+ timestampWrites: r
767
828
  });
768
- c.setPipeline(this.#t), c.setBindGroup(0, this.#r), c.dispatchWorkgroups(1);
769
- for (let e of this.#i) c.setBindGroup(0, e), c.setPipeline(n), c.dispatchWorkgroups(...s), c.setPipeline(r), c.dispatchWorkgroups(this.#o), c.setPipeline(i), c.dispatchWorkgroups(1), c.setPipeline(a), c.dispatchWorkgroups(this.#o), c.setPipeline(o), c.dispatchWorkgroups(...s);
770
- c.end();
829
+ m.setPipeline(this.#t), m.setBindGroup(0, this.#r), m.dispatchWorkgroups(1);
830
+ for (let e of this.#i) m.setBindGroup(0, e), m.setPipeline(i), m.dispatchWorkgroups(...f), m.setPipeline(a), m.dispatchWorkgroups(p), m.setPipeline(o), m.dispatchWorkgroups(1), m.setPipeline(s), m.dispatchWorkgroups(p), m.setPipeline(c), m.dispatchWorkgroups(...f);
831
+ m.end();
771
832
  }
772
833
  destroy() {
773
834
  for (let e of this.#e) e.destroy();
774
835
  }
775
- }, Ce = class {
836
+ }, xe = class {
776
837
  ms = {};
777
838
  #e;
778
839
  #t;
@@ -799,7 +860,7 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
799
860
  }
800
861
  writes(e) {
801
862
  let t = this.#t;
802
- if (!t) return;
863
+ if (!t || this.#i) return;
803
864
  let n = this.#e.indexOf(e);
804
865
  return {
805
866
  querySet: t,
@@ -823,14 +884,14 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
823
884
  destroy() {
824
885
  this.#t?.destroy(), this.#n?.destroy(), this.#r?.destroy();
825
886
  }
826
- }, we = [
887
+ }, Se = [
827
888
  "cull",
828
889
  "project",
829
890
  "sort",
830
891
  "raster",
831
892
  "heights",
832
893
  "post"
833
- ], F = {
894
+ ], L = {
834
895
  view: 0,
835
896
  proj: 16,
836
897
  viewProj: 32,
@@ -843,7 +904,7 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
843
904
  far: 81,
844
905
  lowPass: 82,
845
906
  clusters: 83
846
- }, Te = class {
907
+ }, Ce = class {
847
908
  #e;
848
909
  #t;
849
910
  #n;
@@ -869,11 +930,12 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
869
930
  #S;
870
931
  #C = !1;
871
932
  #w = 0;
933
+ #T = 0;
872
934
  constructor(e, t, n, r) {
873
935
  let { device: i } = e;
874
- this.#e = i, this.#t = t, this.#n = e.format, this.#r = n, this.#i = T(i, r, n.slots), this.#a = new j(i, n, this.#i), this.#o = new ue(i, n, this.#i), this.#s = new Se(i, this.#i), this.#c = new he(i, this.#i, this.#s), this.#u = new ie(i, n), this.#d = new Ce(i, e.timestamps, we), this.#S = i.createBuffer({
875
- label: "drawn readback",
876
- size: 4,
936
+ this.#e = i, this.#t = t, this.#n = e.format, this.#r = n, this.#i = T(i, r, n.slots), this.#a = new j(i, n, this.#i), this.#o = new le(i, n, this.#i), this.#s = new be(i, this.#i), this.#c = new me(i, this.#i, this.#s), this.#u = new re(i, n), this.#d = new xe(i, e.timestamps, Se), this.#S = i.createBuffer({
937
+ label: "counts readback",
938
+ size: (l.projected + 1) * 4,
877
939
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
878
940
  }), this.#b = Math.max(1, t.canvas.width), this.#x = Math.max(1, t.canvas.height);
879
941
  }
@@ -883,9 +945,9 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
883
945
  shade: e,
884
946
  slot: 0
885
947
  };
886
- return this.#g.push(t), this.#T(), () => {
948
+ return this.#g.push(t), this.#E(), () => {
887
949
  let e = this.#g.indexOf(t);
888
- e < 0 || (this.#g.splice(e, 1), this.#T());
950
+ e < 0 || (this.#g.splice(e, 1), this.#E());
889
951
  };
890
952
  }
891
953
  post(e) {
@@ -899,16 +961,16 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
899
961
  };
900
962
  }
901
963
  resize(e, t) {
902
- (e !== this.#b || t !== this.#x) && (this.#b = e, this.#x = t, this.#A());
964
+ (e !== this.#b || t !== this.#x) && (this.#b = e, this.#x = t, this.#j());
903
965
  }
904
966
  render(e, t, n, r, i) {
905
- let a = this.#e, o = this.#d, s = this.#_, c = this.#O(this.#D("colour", fe)), u = r.length > 0 || s.some(({ post: e }) => e.depth), d = this.#k("depth", pe, u), f = d ? this.#O(d) : null, p = [this.#k("ping", this.#n, s.length > 1), this.#k("pong", this.#n, s.length > 2)];
906
- this.#E(e, t);
967
+ let a = this.#e, o = this.#d, s = this.#_, c = this.#k(this.#O("colour", de)), u = r.length > 0 || s.some(({ post: e }) => e.depth), d = this.#A("depth", fe, u), f = d ? this.#k(d) : null, p = [this.#A("ping", this.#n, s.length > 1), this.#A("pong", this.#n, s.length > 2)];
968
+ this.#D(e, t);
907
969
  let m = a.createCommandEncoder({ label: "frame" });
908
- m.clearBuffer(this.#i.work, 0, l.list * 4), this.#a.encode(m, o.writes("cull")), this.#o.encode(m, o.writes("project")), this.#s.encode(m, o.writes("sort")), this.#c.encode(m, c, f, n, o.writes("raster"));
970
+ m.clearBuffer(this.#i.work, 0, l.list * 4), this.#a.encode(m, o.writes("cull")), this.#o.encode(m, this.#T, o.writes("project")), this.#s.encode(m, this.#r.listed * 256, this.#w, o.writes("sort")), this.#c.encode(m, c, f, n, o.writes("raster"));
909
971
  let h = d ? r.map(({ x: t, y: n, resolve: r }) => ({
910
972
  resolve: r,
911
- read: ge(a, m, d, t, n, e.near, e.far)
973
+ read: he(a, m, d, t, n, e.near, e.far)
912
974
  })) : [], g = i.map(({ x: e, y: t, cells: n, resolve: r }, i) => ({
913
975
  resolve: r,
914
976
  read: this.#u.encode(m, e, t, n, i ? void 0 : o.writes("heights"))
@@ -921,11 +983,11 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
921
983
  } }).end();
922
984
  }
923
985
  let v = this.#t.getCurrentTexture().createView();
924
- if (!s.length) this.#l ??= ce(a, this.#n), this.#l.encode(m, [c], v);
986
+ if (!s.length) this.#l ??= se(a, this.#n), this.#l.encode(m, [c], v);
925
987
  else {
926
988
  let t = c;
927
989
  s.forEach(({ post: n, pass: r }, i) => {
928
- let a = i === s.length - 1 ? v : this.#O(p[i % 2]);
990
+ let a = i === s.length - 1 ? v : this.#k(p[i % 2]);
929
991
  r.run(m, e, t, n.depth ? f : null, a), t = a;
930
992
  });
931
993
  }
@@ -938,7 +1000,7 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
938
1000
  }
939
1001
  o.resolve(m);
940
1002
  let y = !this.#C;
941
- y && m.copyBufferToBuffer(this.#i.work, l.projected * 4, this.#S, 0, 4), a.queue.submit([m.finish()]), o.read(), y && this.#j();
1003
+ y && m.copyBufferToBuffer(this.#i.work, 0, this.#S, 0, this.#S.size), a.queue.submit([m.finish()]), o.read(), y && this.#M();
942
1004
  for (let { resolve: e, read: t } of h) t().then(e);
943
1005
  for (let { resolve: e, read: t } of g) t().then(e);
944
1006
  return a.queue.onSubmittedWorkDone();
@@ -955,20 +1017,20 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
955
1017
  }
956
1018
  destroy() {
957
1019
  for (let { pass: e } of this.#_.splice(0)) e.destroy();
958
- this.#A(), this.#i.destroy(), this.#s.destroy(), this.#c.destroy(), this.#d.destroy(), this.#S.destroy();
1020
+ this.#j(), this.#i.destroy(), this.#s.destroy(), this.#c.destroy(), this.#d.destroy(), this.#S.destroy();
959
1021
  }
960
- #T() {
1022
+ #E() {
961
1023
  let e = 0;
962
1024
  for (let t of this.#g) t.slot = e, e += t.shade.uniforms;
963
1025
  this.#o.hooks(this.#g);
964
1026
  }
965
- #E(e, t) {
1027
+ #D(e, t) {
966
1028
  let n = this.#f, [r, i] = [this.#b, this.#x];
967
- n.set(e.view, F.view), n.set(e.proj, F.proj), n.set(S(this.#m, e.proj, e.view), F.viewProj), n.set(t, F.planes), n.set(e.camera.subarray(0, 3), F.camera), n[F.time] = e.time, n.set([r, i], F.viewport), n.set([e.proj[0] * r / 2, e.proj[5] * i / 2], F.focal), n[F.near] = e.near, n[F.far] = e.far, n[F.lowPass] = f, this.#p[F.clusters] = this.#r.listed, this.#e.queue.writeBuffer(this.#i.uniforms, 0, n);
1029
+ n.set(e.view, L.view), n.set(e.proj, L.proj), n.set(S(this.#m, e.proj, e.view), L.viewProj), n.set(t, L.planes), n.set(e.camera.subarray(0, 3), L.camera), n[L.time] = e.time, n.set([r, i], L.viewport), n.set([e.proj[0] * r / 2, e.proj[5] * i / 2], L.focal), n[L.near] = e.near, n[L.far] = e.far, n[L.lowPass] = f, this.#p[L.clusters] = this.#r.listed, this.#e.queue.writeBuffer(this.#i.uniforms, 0, n);
968
1030
  for (let { shade: t, slot: n } of this.#g) t.update(e, this.#h.subarray(n * 4, (n + t.uniforms) * 4));
969
- this.#e.queue.writeBuffer(this.#i.plugins, 0, this.#h);
1031
+ this.#g.length && this.#e.queue.writeBuffer(this.#i.plugins, 0, this.#h);
970
1032
  }
971
- #D(e, t) {
1033
+ #O(e, t) {
972
1034
  let n = this.#v[e];
973
1035
  return n || (n = this.#e.createTexture({
974
1036
  label: e,
@@ -977,27 +1039,27 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
977
1039
  usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC
978
1040
  }), this.#v[e] = n), n;
979
1041
  }
980
- #O(e) {
1042
+ #k(e) {
981
1043
  let t = this.#y.get(e);
982
1044
  return t || this.#y.set(e, t = e.createView()), t;
983
1045
  }
984
- #k(e, t, n) {
985
- if (n) return this.#D(e, t);
1046
+ #A(e, t, n) {
1047
+ if (n) return this.#O(e, t);
986
1048
  this.#v[e]?.destroy(), delete this.#v[e];
987
1049
  }
988
- #A() {
1050
+ #j() {
989
1051
  for (let e of Object.values(this.#v)) e?.destroy();
990
1052
  this.#v = {};
991
1053
  }
992
- #j() {
1054
+ #M() {
993
1055
  this.#C = !0;
994
1056
  let e = this.#S;
995
1057
  e.mapAsync(GPUMapMode.READ).then(() => {
996
- let t = new Uint32Array(e.getMappedRange())[0];
997
- this.#w = Math.min(t, this.#i.capacity), e.unmap();
1058
+ let t = new Uint32Array(e.getMappedRange());
1059
+ this.#T = t[l.visible], this.#w = Math.min(t[l.projected], this.#i.capacity), e.unmap();
998
1060
  }).catch(() => {}).finally(() => this.#C = !1);
999
1061
  }
1000
- }, Ee = [
1062
+ }, we = [
1001
1063
  [0, 1],
1002
1064
  [0, -1],
1003
1065
  [1, 1],
@@ -1005,199 +1067,52 @@ var _e = "// lsd radix sort, 8 bits a pass: block digit counts, a two-level scan
1005
1067
  [2, 0],
1006
1068
  [2, -1]
1007
1069
  ];
1008
- function De(e, t) {
1070
+ function Te(e, t) {
1009
1071
  let n = (e, n) => t[n * 4 + e];
1010
- return Ee.forEach(([t, r], i) => {
1072
+ return we.forEach(([t, r], i) => {
1011
1073
  for (let a = 0; a < 4; a++) e[i * 4 + a] = r ? n(3, a) + r * n(t, a) : n(t, a);
1012
1074
  let a = Math.hypot(e[i * 4], e[i * 4 + 1], e[i * 4 + 2]) || 1;
1013
1075
  for (let t = 0; t < 4; t++) e[i * 4 + t] /= a;
1014
1076
  }), e;
1015
1077
  }
1016
- //#endregion
1017
- //#region src/engine/plan/footprint.ts
1018
- function Oe(e, t, n, r) {
1019
- let i = (e * e + e * t + t * t + n * n + n * r + r * r) / 3;
1020
- return 1 + 15 * Math.max(0, 1 - i) ** 2;
1021
- }
1022
- function ke(e, t, n, r, i, a, o, s = 1, c = {
1023
- pixels: 0,
1024
- weight: 1
1025
- }) {
1026
- let l = (e[0] + e[3]) / 2, u = (e[1] + e[4]) / 2, d = (e[2] + e[5]) / 2, f = (e[3] - e[0]) / 2, p = (e[4] - e[1]) / 2, m = (e[5] - e[2]) / 2, h = t[0] * l + t[4] * u + t[8] * d + t[12], g = t[1] * l + t[5] * u + t[9] * d + t[13], _ = -(t[2] * l + t[6] * u + t[10] * d + t[14]), v = Math.abs(t[0]) * f + Math.abs(t[4]) * p + Math.abs(t[8]) * m, y = Math.abs(t[1]) * f + Math.abs(t[5]) * p + Math.abs(t[9]) * m, b = Math.abs(t[2]) * f + Math.abs(t[6]) * p + Math.abs(t[10]) * m;
1027
- if (c.pixels = 0, c.weight = 1, _ + b < a || _ - b > o) return c;
1028
- let x = Math.max(a, _ - b), S = Math.max(a, _ + b), C = i * n / r, w = Math.min((h - v) / x, (h - v) / S) / C, T = Math.max((h + v) / x, (h + v) / S) / C, E = Math.min((g - y) / x, (g - y) / S) / i, D = Math.max((g + y) / x, (g + y) / S) / i;
1029
- if (T < -s || w > s || D < -s || E > s) return c;
1030
- let O = Math.max(-s, w), k = Math.min(s, T), A = Math.max(-s, E), j = Math.min(s, D), M = (T - w) * (D - E), ee = (k - O) * (j - A);
1031
- return M <= 0 || ee <= 0 || (c.pixels = M * n * r / 4, c.weight = Oe(O, k, A, j)), c;
1032
- }
1033
- //#endregion
1034
- //#region src/engine/plan/cut.ts
1035
- var Ae = 1 / .8 ** 2, je = 1500, Me = 1.1, Ne = class {
1036
- #e = /* @__PURE__ */ new Map();
1037
- #t = /* @__PURE__ */ new Map();
1038
- #n = /* @__PURE__ */ new Float64Array(6);
1039
- #r = {
1040
- pixels: 0,
1041
- weight: 1
1042
- };
1043
- plan(e, t, n, r) {
1044
- let { budget: i, capacity: a, now: o, predicted: s } = r, l = [], u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map(), p = new Fe(), m = 0, h = 0, g = /* @__PURE__ */ new Set(), _ = /* @__PURE__ */ new Set(), v = (e, t) => {
1045
- let r = e.row.count;
1046
- l.push(e), h += c(r), t.shown && (m += r, _.add(e.id)), t.near && g.add(e.id);
1047
- let i = this.#e.get(e.id), a = i !== void 0, s = t.pixels * t.weight, u = s / Math.max(1, r);
1048
- t.pixels > 0 && f.set(e.id, u);
1049
- let d = o - (this.#t.get(e.id) ?? -Infinity) <= je, v = a && !t.shown && d ? i : null;
1050
- (r < s * (a ? Ae : 1) || v !== null) && Pe(e, n) && p.push({
1051
- page: e,
1052
- shown: t.shown,
1053
- held: v,
1054
- ratio: u
1055
- });
1056
- };
1057
- for (let n of e.roots) v(n, this.#i(n, t, s));
1058
- let y = !1;
1059
- for (; p.size;) {
1060
- let { page: e, shown: n, held: r } = p.pop(), l = [], f = 0;
1061
- if (e.children.forEach((e, n) => {
1062
- if (!e) return;
1063
- let i = this.#i(e, t, s);
1064
- i.pixels <= 0 && !((r ?? 0) & 1 << n) || (l.push({
1065
- child: e,
1066
- m: i
1067
- }), f |= 1 << n);
1068
- }), !l.length) continue;
1069
- let g = 0, _ = n ? -e.row.count : 0;
1070
- for (let { child: e, m: t } of l) g += c(e.row.count), t.shown && (_ += e.row.count);
1071
- if (h + g > a) break;
1072
- if (_ > 0 && (y || m + _ > i)) {
1073
- y = !0;
1074
- continue;
1075
- }
1076
- u.set(e.id, f);
1077
- let b = n ? o : this.#t.get(e.id);
1078
- b !== void 0 && d.set(e.id, b), n && (m -= e.row.count);
1079
- for (let { child: e, m: t } of l) v(e, t);
1080
- }
1081
- this.#e = u, this.#t = d;
1082
- let b = l.filter((e) => !u.has(e.id)), x = new Set(u.keys());
1083
- for (let e of b) x.add(e.id);
1084
- let S = [];
1085
- for (let t of e.wanted()) {
1086
- let e = -1;
1087
- for (let n of t.over) e = Math.max(e, f.get(n.id) ?? -1);
1088
- e >= 0 && S.push({
1089
- wanted: t,
1090
- rank: e
1091
- });
1092
- }
1093
- S.sort((e, t) => t.rank - e.rank);
1094
- let C = 0;
1095
- for (let e of b) _.has(e.id) && !n(e.id) && (C += e.row.count);
1096
- return {
1097
- cut: b,
1098
- load: b.filter((e) => !n(e.id) && (g.has(e.id) || !s && C === 0)),
1099
- idx: S.map((e) => e.wanted),
1100
- keep: x,
1101
- planned: m,
1102
- missing: C
1103
- };
1104
- }
1105
- #i(e, t, n) {
1106
- let r = this.#a(e, t, 1).pixels > 0, { pixels: i, weight: a } = this.#a(e, t, Me), o = r;
1107
- if (n) {
1108
- let t = this.#a(e, n, Me);
1109
- t.pixels > i && ({pixels: i, weight: a} = t), o ||= t.pixels > 0 && this.#a(e, n, 1).pixels > 0;
1110
- }
1111
- return {
1112
- shown: r,
1113
- near: o,
1114
- pixels: i,
1115
- weight: a
1116
- };
1117
- }
1118
- #a(e, t, n) {
1119
- let r = this.#n;
1120
- for (let n = 0; n < 6; n++) r[n] = e.box[n] - t.origin[n % 3];
1121
- let { width: i, height: a, tan: o, near: s, far: c } = t;
1122
- return ke(r, t.view, i, a, o, s, c, n, this.#r);
1123
- }
1124
- };
1125
- function Pe(e, t) {
1126
- let { children: n } = e;
1127
- return t(e.id) && !n.includes(void 0) && n.some((e) => e !== null);
1128
- }
1129
- var Fe = class {
1130
- #e = [];
1131
- get size() {
1132
- return this.#e.length;
1133
- }
1134
- push(e) {
1135
- let t = this.#e;
1136
- t.push(e);
1137
- let n = t.length - 1;
1138
- for (; n > 0;) {
1139
- let e = n - 1 >> 1;
1140
- if (!I(t[n], t[e])) break;
1141
- [t[n], t[e]] = [t[e], t[n]], n = e;
1142
- }
1143
- }
1144
- pop() {
1145
- let e = this.#e, t = e[0], n = e.pop();
1146
- if (e.length) {
1147
- e[0] = n;
1148
- let t = 0;
1149
- for (;;) {
1150
- let n = 2 * t + 1, r = t;
1151
- if (n < e.length && I(e[n], e[r]) && (r = n), n + 1 < e.length && I(e[n + 1], e[r]) && (r = n + 1), r === t) break;
1152
- [e[t], e[r]] = [e[r], e[t]], t = r;
1153
- }
1154
- }
1155
- return t;
1156
- }
1157
- };
1158
- function I(e, t) {
1159
- return e.shown === t.shown ? e.ratio > t.ratio : e.shown;
1160
- }
1161
- var L = .25, Ie = class {
1078
+ var R = .25, Ee = class {
1162
1079
  #e = /* @__PURE__ */ new Map();
1163
1080
  update(e, t, n, r) {
1164
- let i = this.#e, a = Le(e, t);
1165
- for (let [e, r] of i) t(r.page.id) ? r.held || (r.start !== null && n - r.start >= 250 && (r.start = null), a.has(e) || (r.frozen = Be(r, n), r.start = null, r.held = !0)) : i.delete(e);
1166
- let o = /* @__PURE__ */ new Set();
1081
+ let i = this.#e, a = De(e, t), o = -1;
1082
+ 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 = Ae(r, n), r.start = null, r.held = !0))) : i.delete(e);
1083
+ let s = /* @__PURE__ */ new Set();
1167
1084
  for (let [e, t] of a) {
1168
1085
  let r = i.get(e);
1169
- if (r) r.held && (r.held = !1, r.frozen < 255 && (r.start = n - r.frozen / 255 * 250, o.add(r)));
1086
+ if (r) r.held && (r.held = !1, r.frozen < 255 && (r.start = n - r.frozen / 255 * 250, s.add(r)));
1170
1087
  else {
1171
- let r = Re(t, e % 4, n);
1172
- i.set(e, r), o.add(r);
1088
+ let r = Oe(t, e % 4, n);
1089
+ o = Math.max(o, r.level), i.set(e, r), s.add(r);
1173
1090
  }
1174
1091
  }
1175
- let s = -1;
1176
- for (let e of i.values()) s = Math.max(s, e.level);
1177
1092
  let l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
1178
1093
  for (let e of i.values()) if (e.held) {
1179
1094
  l.set(e.cell, e);
1180
- for (let t = e.level, n = e.col, r = e.row; t <= s; t++, n >>= 1, r >>= 1) {
1181
- let i = R(t, n, r), a = u.get(i);
1095
+ for (let t = e.level, n = e.col, r = e.row; t <= o; t++, n >>= 1, r >>= 1) {
1096
+ let i = z(t, n, r), a = u.get(i);
1182
1097
  a ? a.push(e) : u.set(i, [e]);
1183
1098
  }
1184
1099
  }
1185
1100
  let d = (e) => {
1186
1101
  let t = [...u.get(e.cell) ?? []];
1187
- for (let n = e.level + 1, r = e.col >> 1, i = e.row >> 1; n <= s; n++, r >>= 1, i >>= 1) {
1188
- let e = l.get(R(n, r, i));
1102
+ for (let n = e.level + 1, r = e.col >> 1, i = e.row >> 1; n <= o; n++, r >>= 1, i >>= 1) {
1103
+ let e = l.get(z(n, r, i));
1189
1104
  e && t.push(e);
1190
1105
  }
1191
1106
  return t;
1192
1107
  }, f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), m = 0, h = 0, g = (e) => {
1193
1108
  p.has(e) || (p.add(e), h += c(e.row.count));
1194
1109
  };
1195
- for (let e of i.values()) if (!(e.held || e.start === null || o.has(e))) {
1110
+ for (let e of i.values()) if (!(e.held || e.start === null || s.has(e))) {
1196
1111
  m += e.splats;
1197
1112
  for (let t of d(e)) f.has(t) || (f.add(t), m += t.splats, g(t.page));
1198
1113
  }
1199
- let _ = L * r;
1200
- for (let e of o) {
1114
+ let _ = R * r;
1115
+ for (let e of s) {
1201
1116
  let t = d(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 + c(t.row.count), 0);
1202
1117
  if (m + n > _ || h + i > _) e.start = null;
1203
1118
  else {
@@ -1206,16 +1121,19 @@ var L = .25, Ie = class {
1206
1121
  for (let e of r) g(e);
1207
1122
  }
1208
1123
  }
1209
- for (let [e, t] of i) t.held && !f.has(t) && i.delete(e);
1210
1124
  let v = /* @__PURE__ */ new Map(), y = !1;
1211
- for (let e of i.values()) {
1212
- (e.held || e.start !== null) && (y = !0);
1213
- let t = Be(e, n);
1214
- if (!t) continue;
1215
- let r = v.get(e.page.id);
1216
- r ? r.factors = (r.factors | t << 8 * e.q) >>> 0 : v.set(e.page.id, {
1217
- id: e.page.id,
1218
- factors: t << 8 * e.q >>> 0
1125
+ for (let [e, t] of i) {
1126
+ if (t.held && !f.has(t)) {
1127
+ i.delete(e);
1128
+ continue;
1129
+ }
1130
+ (t.held || t.start !== null) && (y = !0);
1131
+ let r = Ae(t, n);
1132
+ if (!r) continue;
1133
+ let a = v.get(t.page.id);
1134
+ a ? a.factors = (a.factors | r << 8 * t.q) >>> 0 : v.set(t.page.id, {
1135
+ id: t.page.id,
1136
+ factors: r << 8 * t.q >>> 0
1219
1137
  });
1220
1138
  }
1221
1139
  return {
@@ -1224,19 +1142,19 @@ var L = .25, Ie = class {
1224
1142
  };
1225
1143
  }
1226
1144
  };
1227
- function Le(e, t) {
1145
+ function De(e, t) {
1228
1146
  let n = new Set(e), r = /* @__PURE__ */ new Set(), i = [];
1229
1147
  for (let t of e) for (let e = t; e && !r.has(e); e = e.parent) r.add(e), e.parent || i.push(e);
1230
1148
  let a = /* @__PURE__ */ new Map(), o = (e) => {
1231
1149
  for (let i = 0; i < 4; i++) {
1232
1150
  let s = e.children[i];
1233
- s && t(s.id) && r.has(s) ? o(s) : (s !== null || n.has(e)) && a.set(e.id * 4 + i, e);
1151
+ s && r.has(s) && t(s.id) ? o(s) : (s !== null || n.has(e)) && a.set(e.id * 4 + i, e);
1234
1152
  }
1235
1153
  };
1236
1154
  for (let e of i) t(e.id) && o(e);
1237
1155
  return a;
1238
1156
  }
1239
- function Re(t, n, r) {
1157
+ function Oe(t, n, r) {
1240
1158
  let i = e * 2 ** t.g, a = t.g - 1, o = 2 * (Math.round(t.unit.e / i) + t.row.i) + (n & 1), s = 2 * (Math.round(t.unit.n / i) + t.row.j) + (n >> 1);
1241
1159
  return {
1242
1160
  page: t,
@@ -1244,121 +1162,503 @@ function Re(t, n, r) {
1244
1162
  level: a,
1245
1163
  col: o,
1246
1164
  row: s,
1247
- cell: R(a, o, s),
1248
- splats: ze(t.row, n),
1165
+ cell: z(a, o, s),
1166
+ splats: ke(t.row, n),
1249
1167
  start: r,
1250
1168
  frozen: 0,
1251
1169
  held: !1
1252
1170
  };
1253
1171
  }
1254
- var R = (e, t, n) => ((e + 1) * 2 ** 21 + t) * 2 ** 21 + n;
1255
- function ze({ count: e, quadrants: t }, n) {
1172
+ var z = (e, t, n) => ((e + 1) * 2 ** 21 + t) * 2 ** 21 + n;
1173
+ function ke({ count: e, quadrants: t }, n) {
1256
1174
  return (n < 3 ? t[n] : e) - (n > 0 ? t[n - 1] : 0);
1257
1175
  }
1258
- function Be(e, t) {
1176
+ function Ae(e, t) {
1259
1177
  return e.held ? e.frozen : e.start === null ? 255 : Math.min(255, Math.round((t - e.start) / 250 * 255));
1260
1178
  }
1261
1179
  //#endregion
1262
- //#region src/engine/quality.ts
1263
- var Ve = 5e5, He = 2073600, Ue = [1, .85];
1264
- function We(e, t, n, r) {
1265
- return Math.min(n, Math.sqrt(He / Math.max(1, e * t))) * r;
1180
+ //#region src/engine/plan/footprint.ts
1181
+ var je = [
1182
+ 0,
1183
+ 0,
1184
+ 0
1185
+ ];
1186
+ function Me(e, t, n, r) {
1187
+ let i = (e * e + e * t + t * t + n * n + n * r + r * r) / 3;
1188
+ return 1 + 15 * Math.max(0, 1 - i) ** 2;
1266
1189
  }
1267
- function z(e, t) {
1268
- if (!e.length) return 0;
1269
- let n = [...e].sort((e, t) => e - t);
1270
- return n[Math.ceil(n.length * t) - 1];
1190
+ function Ne(e, t, n, r, i, a, o, s = 1, c = {
1191
+ shown: !1,
1192
+ pixels: 0,
1193
+ weight: 1
1194
+ }, l = je) {
1195
+ 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;
1196
+ if (c.pixels = 0, c.weight = 1, c.shown = !1, v + x < a || v - x > o) return c;
1197
+ let S = Math.max(a, v - x), C = Math.max(a, v + x), w = i * n / r;
1198
+ if (Math.abs(g) - y > s * w * C || Math.abs(_) - b > s * i * C) return c;
1199
+ 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;
1200
+ if (E < -s || T > s || O < -s || D > s) return c;
1201
+ 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);
1202
+ return N <= 0 || ee <= 0 || (c.shown = E > -1 && T < 1 && O > -1 && D < 1, c.pixels = N * n * r / 4, c.weight = Me(k, A, j, M)), c;
1271
1203
  }
1272
- var Ge = class {
1273
- #e = 0;
1274
- #t = [];
1275
- #n = -Infinity;
1276
- #r = 0;
1277
- #i = 0;
1278
- get scale() {
1279
- return Ue[this.#e];
1280
- }
1281
- full() {
1282
- this.#e = 0, this.#a();
1283
- }
1284
- #a() {
1285
- this.#t = [], this.#r = 0, this.#i = 0, this.#n = -Infinity;
1286
- }
1287
- sample(e, t, n) {
1288
- if (!n || t - this.#n > 250 || !Number.isFinite(e) || e <= 0) return this.#a(), this.#n = t, !1;
1289
- let r = Math.max(0, t - this.#n);
1290
- if (this.#n = t, this.#t.push({
1291
- time: t,
1292
- ms: e
1293
- }), this.#t = this.#t.filter((e) => t - e.time <= 1e3), this.#t.length < 20) return !1;
1294
- let i = z(this.#t.map((e) => e.ms), .9);
1295
- if (this.#r = i > 20 ? this.#r + r : 0, this.#i = i < 14 ? this.#i + r : 0, this.#r >= 2e3) {
1296
- if (this.#e < Ue.length - 1) this.#e++;
1297
- else return !1;
1298
- } else if (this.#i >= 5e3) {
1299
- if (this.#e > 0) this.#e--;
1300
- else return !1;
1301
- } else return !1;
1302
- return this.#a(), !0;
1303
- }
1304
- }, Ke = class {
1204
+ var B = /* @__PURE__ */ new Float64Array(6), Pe = {
1205
+ shown: !1,
1206
+ pixels: 0,
1207
+ weight: 1
1208
+ };
1209
+ function Fe(e, [t, n, r], i, a, o, s, c, l, u = je) {
1210
+ let d = r / 2, f = Math.max(0, t - e[0], n - e[1], e[3] - t - r, e[4] - n - r);
1211
+ B[2] = e[2], B[5] = e[5];
1212
+ let p = 0;
1213
+ for (let r = 0; r < 4; r++) {
1214
+ let m = t + (r & 1) * d, h = n + (r >> 1) * d;
1215
+ B[0] = Math.max(e[0], m - f), B[1] = Math.max(e[1], h - f), B[3] = Math.min(e[3], m + d + f), B[4] = Math.min(e[4], h + d + f), !(B[0] > B[3] || B[1] > B[4]) && Ne(B, i, a, o, s, c, l, 1, Pe, u).shown && (p |= 1 << r);
1216
+ }
1217
+ return p;
1218
+ }
1219
+ //#endregion
1220
+ //#region src/engine/world/tree.ts
1221
+ var V = (e, t, n) => (e * 256 + t) * 256 + n, Ie = class {
1222
+ roots = [];
1223
+ pages = /* @__PURE__ */ new Map();
1224
+ units = /* @__PURE__ */ new Map();
1305
1225
  #e;
1306
- #t = [];
1307
- #n = /* @__PURE__ */ new Set();
1308
- #r = /* @__PURE__ */ new Set();
1309
- #i = /* @__PURE__ */ new Set();
1310
- #a = /* @__PURE__ */ new Map();
1226
+ #t;
1227
+ #n = 0;
1228
+ #r = /* @__PURE__ */ new Map();
1229
+ #i = /* @__PURE__ */ new Map();
1311
1230
  constructor(e) {
1312
- this.#e = e;
1313
- }
1314
- want(e) {
1315
- this.#t = e, this.#n = new Set(e.map((e) => e.id));
1231
+ this.#e = new Set(e.roots.map(H)), this.#t = Math.max(...e.roots.map((e) => e.level));
1316
1232
  }
1317
- next() {
1318
- let e = [];
1319
- 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));
1320
- let t = [];
1321
- if (this.#r.size >= this.#e.concurrency) return {
1322
- start: t,
1323
- abort: e
1233
+ add(e, t) {
1234
+ let n = H(e), r = this.units.get(n);
1235
+ if (r) return r;
1236
+ let o = /* @__PURE__ */ new Map(), s = {
1237
+ level: e.level,
1238
+ e: e.e,
1239
+ n: e.n,
1240
+ idx: e,
1241
+ path: t,
1242
+ parent: null,
1243
+ pages: [],
1244
+ grid: o
1324
1245
  };
1325
- let n = /* @__PURE__ */ new Map();
1326
- for (let e of this.#t) {
1327
- if (this.#a.has(e.id)) continue;
1328
- let t = n.get(e.pack);
1329
- t ? t.push(e) : n.set(e.pack, [e]);
1246
+ for (let t of e.rows) {
1247
+ let n = t.box, r = {
1248
+ id: this.#n++,
1249
+ unit: s,
1250
+ row: t,
1251
+ g: t.g,
1252
+ box: Float64Array.of(e.e + n[0], e.n + n[1], n[2], e.e + n[3], e.n + n[4], n[5]),
1253
+ parent: null,
1254
+ children: [
1255
+ null,
1256
+ null,
1257
+ null,
1258
+ null
1259
+ ]
1260
+ };
1261
+ this.pages.set(r.id, r), s.pages.push(r), o.set(V(t.g, t.i, t.j), r);
1330
1262
  }
1331
- for (let e of n.values()) e.sort((e, t) => e.offset - t.offset);
1332
- for (let e of this.#t) {
1333
- if (this.#r.size >= this.#e.concurrency) break;
1334
- if (this.#a.has(e.id)) continue;
1335
- let r = this.#o(e, n.get(e.pack));
1336
- for (let e of r.pages) this.#a.set(e.id, r);
1337
- this.#r.add(r), t.push(r);
1263
+ this.units.set(n, s), this.#r.delete(n);
1264
+ for (let t = e.level + 1; t <= this.#t; t++) {
1265
+ let n = H(U(e, t));
1266
+ this.#i.set(n, (this.#i.get(n) ?? 0) + 1);
1338
1267
  }
1339
- return {
1340
- start: t,
1341
- abort: e
1342
- };
1343
- }
1344
- done(e) {
1345
- if (this.#r.delete(e)) {
1346
- this.#i.delete(e);
1347
- for (let t of e.pages) this.#a.get(t.id) === e && this.#a.delete(t.id);
1268
+ 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));
1269
+ for (let e of s.pages) {
1270
+ let { g: t, i: n, j: r } = e.row;
1271
+ c.has(t + 1) && (e.parent = o.get(V(t + 1, n >> 1, r >> 1)) ?? null);
1272
+ for (let i = 0; i < 4; i++) {
1273
+ let a = 2 * n + (i & 1), s = 2 * r + (i >> 1);
1274
+ c.has(t - 1) ? e.children[i] = o.get(V(t - 1, a, s)) ?? null : t === u && t > 0 && (e.children[i] = d.has((a >> 3) + 2 * (s >> 3)) ? void 0 : null);
1275
+ }
1348
1276
  }
1349
- }
1350
- get queued() {
1351
- let e = 0;
1352
- for (let t of this.#n) this.#a.has(t) || e++;
1353
- return e;
1354
- }
1355
- get loading() {
1356
- return this.#a.size;
1357
- }
1358
- #o(e, t) {
1359
- 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;
1360
- for (let e = a + 1; e < t.length; e++) {
1361
- let a = t[e];
1277
+ if (this.#e.has(n)) for (let e of s.pages) e.g === l && this.roots.push(e);
1278
+ else {
1279
+ let t = this.units.get(H(U(e, e.level + 1)));
1280
+ t && this.#o(t, s);
1281
+ }
1282
+ let f = a(s.idx);
1283
+ for (let { key: t } of f) {
1284
+ let n = t.level === e.level - 1 ? this.units.get(H(t)) : void 0;
1285
+ n && this.#o(s, n);
1286
+ }
1287
+ for (let { key: e, hash: t } of f) {
1288
+ let n = H(e);
1289
+ if (this.units.has(n)) continue;
1290
+ let r = this.#r.get(n);
1291
+ if (r && r.from <= s.level) continue;
1292
+ let a = this.#s(s, e), o = {
1293
+ ...e,
1294
+ path: i(e, t, "idx"),
1295
+ over: a
1296
+ };
1297
+ this.#r.set(n, {
1298
+ wanted: o,
1299
+ from: s.level
1300
+ });
1301
+ }
1302
+ return s;
1303
+ }
1304
+ wanted() {
1305
+ return Array.from(this.#r.values(), (e) => e.wanted);
1306
+ }
1307
+ ground(e, t) {
1308
+ for (let n of this.roots) {
1309
+ let [r, i, a] = W(n);
1310
+ if (e < r || e >= r + a || t < i || t >= i + a) continue;
1311
+ let o = n;
1312
+ for (;;) {
1313
+ let n = +(e >= r + a / 2), s = +(t >= i + a / 2), c = o.children[n + 2 * s];
1314
+ if (!c) return o.box[2];
1315
+ o = c, [r, i, a] = W(o);
1316
+ }
1317
+ }
1318
+ }
1319
+ async load(e, t, n) {
1320
+ for (;;) {
1321
+ let r = this.wanted().filter((n) => Le(n, e, t));
1322
+ if (r.length === 0) return;
1323
+ (await Promise.all(r.map((e) => n(e.path)))).forEach((e, t) => this.add(e, r[t].path));
1324
+ }
1325
+ }
1326
+ prune(e) {
1327
+ let t = [], n = [...this.units.values()].sort((e, t) => e.level - t.level);
1328
+ for (let r of n) {
1329
+ let n = H(r);
1330
+ if (this.#e.has(n) || this.#i.has(n) || r.pages.some((t) => e.has(t.id))) continue;
1331
+ for (let e of r.pages) this.pages.delete(e.id), t.push(e.id);
1332
+ let i = r.parent;
1333
+ if (i) {
1334
+ let e = 250 * 2 ** r.level, t = (r.e - i.e) / e, n = (r.n - i.n) / e, a = i.idx.children.some((e) => e.quadrant === t + 2 * n);
1335
+ for (let e of this.#s(i, r)) e.children.fill(a ? void 0 : null);
1336
+ }
1337
+ this.units.delete(n);
1338
+ for (let e = r.level + 1; e <= this.#t; e++) {
1339
+ let t = H(U(r, e)), n = this.#i.get(t) - 1;
1340
+ n ? this.#i.set(t, n) : this.#i.delete(t);
1341
+ }
1342
+ for (let { key: e } of a(r.idx)) this.#a(e);
1343
+ this.#a(r);
1344
+ }
1345
+ return t;
1346
+ }
1347
+ #a(e) {
1348
+ let t = H(e);
1349
+ this.#r.delete(t);
1350
+ for (let n = e.level + 1; n <= e.level + 3; n++) {
1351
+ let r = this.units.get(H(U(e, n)));
1352
+ if (!r) continue;
1353
+ let o = a(r.idx).find((e) => H(e.key) === t);
1354
+ if (!o) continue;
1355
+ let s = {
1356
+ level: e.level,
1357
+ e: e.e,
1358
+ n: e.n,
1359
+ path: i(o.key, o.hash, "idx"),
1360
+ over: this.#s(r, e)
1361
+ };
1362
+ this.#r.set(t, {
1363
+ wanted: s,
1364
+ from: r.level
1365
+ });
1366
+ return;
1367
+ }
1368
+ }
1369
+ #o(e, t) {
1370
+ t.parent = e;
1371
+ 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;
1372
+ for (let n of this.#s(e, t)) n.children.fill(null);
1373
+ for (let e of t.pages) {
1374
+ if (e.g !== n) continue;
1375
+ let t = 8 * i + e.row.i, r = 8 * a + e.row.j, s = o.get(V(n + 1, t >> 1, r >> 1)) ?? null;
1376
+ e.parent = s, s && (s.children[(t & 1) + 2 * (r & 1)] = e);
1377
+ }
1378
+ }
1379
+ #s(t, n) {
1380
+ let r = t.level + 1, i = e * 2 ** r, a = (n.e - t.e) / i, o = (n.n - t.n) / i, s = 250 * 2 ** n.level / i, c = [];
1381
+ for (let e = o; e < o + s; e++) for (let n = a; n < a + s; n++) {
1382
+ let i = t.grid.get(V(r, n, e));
1383
+ i && c.push(i);
1384
+ }
1385
+ return c;
1386
+ }
1387
+ };
1388
+ function H(e) {
1389
+ return `${e.level}/${e.e}/${e.n}`;
1390
+ }
1391
+ function U(e, t) {
1392
+ let n = 250 * 2 ** t;
1393
+ return {
1394
+ level: t,
1395
+ e: Math.floor(e.e / n) * n,
1396
+ n: Math.floor(e.n / n) * n
1397
+ };
1398
+ }
1399
+ function Le(e, t, n) {
1400
+ let r = 250 * 2 ** e.level;
1401
+ return t >= e.e && t < e.e + r && n >= e.n && n < e.n + r;
1402
+ }
1403
+ function W(t) {
1404
+ let n = e * 2 ** t.g;
1405
+ return [
1406
+ t.unit.e + t.row.i * n,
1407
+ t.unit.n + t.row.j * n,
1408
+ n
1409
+ ];
1410
+ }
1411
+ //#endregion
1412
+ //#region src/engine/plan/cut.ts
1413
+ var Re = 1 / .8 ** 2, ze = 1.1, Be = class {
1414
+ #e = /* @__PURE__ */ new Map();
1415
+ #t = /* @__PURE__ */ new Map();
1416
+ #n = {
1417
+ shown: !1,
1418
+ pixels: 0,
1419
+ weight: 1
1420
+ };
1421
+ plan(e, t, n, r) {
1422
+ let { budget: i, capacity: a, now: o, predicted: s } = r, l = [], u = [], d = [], f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = e.wanted(), h = /* @__PURE__ */ new Map(), g = new Ue(), _ = 0, v = 0, y = (e) => {
1423
+ let t = e.page, r = t.row.count;
1424
+ l.push(t), u.push(e.visible), d.push(e.near), v += c(r), _ += e.visible;
1425
+ let i = this.#e.get(t.id), a = i !== void 0, s = e.pixels * e.weight, f = s / Math.max(1, r);
1426
+ m.length && e.pixels > 0 && h.set(t.id, f);
1427
+ let p = a && !e.shown && o - (this.#t.get(t.id) ?? -Infinity) <= 1500 ? i : null;
1428
+ (r < s * (a ? Re : 1) || p !== null) && He(t, n) && g.push({
1429
+ page: t,
1430
+ shown: e.shown,
1431
+ held: p,
1432
+ visible: e.visible,
1433
+ ratio: f
1434
+ });
1435
+ };
1436
+ for (let n of e.roots) y(this.#r(n, t, s));
1437
+ let b = [];
1438
+ for (; g.size;) {
1439
+ let e = g.pop(), { page: n, shown: r, held: l } = e, u = [], d = 0;
1440
+ for (let e = 0; e < n.children.length; e++) {
1441
+ let r = n.children[e];
1442
+ if (!r) continue;
1443
+ let i = this.#r(r, t, s);
1444
+ i.pixels <= 0 && !((l ?? 0) & 1 << e) || (u.push(i), d |= 1 << e);
1445
+ }
1446
+ if (!u.length) continue;
1447
+ let m = 0, h = -e.visible;
1448
+ for (let e of u) m += c(e.page.row.count), h += e.visible;
1449
+ if (v + m > a) break;
1450
+ if (h > 0 && (b.length || _ + h > i)) {
1451
+ b.push(e);
1452
+ continue;
1453
+ }
1454
+ if (h < 0) for (let e of b.splice(0)) g.push(e);
1455
+ f.set(n.id, d);
1456
+ let x = r ? o : this.#t.get(n.id);
1457
+ x !== void 0 && p.set(n.id, x), _ -= e.visible;
1458
+ for (let e of u) y(e);
1459
+ }
1460
+ this.#e = f, this.#t = p;
1461
+ let x = [], S = [], C = new Set(f.keys()), w = 0;
1462
+ for (let e = 0; e < l.length; e++) {
1463
+ let t = l[e];
1464
+ f.has(t.id) || (x.push(t), C.add(t.id), n(t.id) || (w += u[e], S.push({
1465
+ page: t,
1466
+ near: d[e]
1467
+ })));
1468
+ }
1469
+ let T = [];
1470
+ for (let e of m) {
1471
+ let t = -1;
1472
+ for (let n of e.over) t = Math.max(t, h.get(n.id) ?? -1);
1473
+ t >= 0 && T.push({
1474
+ wanted: e,
1475
+ rank: t
1476
+ });
1477
+ }
1478
+ return T.sort((e, t) => t.rank - e.rank), {
1479
+ cut: x,
1480
+ load: S.filter(({ near: e }) => e || !s && w === 0).map(({ page: e }) => e),
1481
+ idx: T.map((e) => e.wanted),
1482
+ keep: C,
1483
+ planned: _,
1484
+ missing: w
1485
+ };
1486
+ }
1487
+ #r(e, t, n) {
1488
+ let r = this.#i(e, t, ze), i = r.shown, { pixels: a, weight: o } = r, s = i;
1489
+ if (n) {
1490
+ let t = this.#i(e, n, ze);
1491
+ t.pixels > a && ({pixels: a, weight: o} = t), s ||= t.shown;
1492
+ }
1493
+ return {
1494
+ page: e,
1495
+ shown: i,
1496
+ near: s,
1497
+ visible: i ? Ve(e, t) : 0,
1498
+ pixels: a,
1499
+ weight: o
1500
+ };
1501
+ }
1502
+ #i(e, t, n) {
1503
+ let { width: r, height: i, tan: a, near: o, far: s } = t;
1504
+ return Ne(e.box, t.view, r, i, a, o, s, n, this.#n, t.origin);
1505
+ }
1506
+ };
1507
+ function Ve(e, t) {
1508
+ let { width: n, height: r, tan: i, near: a, far: o, origin: s } = t, c = Fe(e.box, W(e), t.view, n, r, i, a, o, s), l = 0;
1509
+ for (let t = 0; t < 4; t++) c & 1 << t && (l += ke(e.row, t));
1510
+ return l;
1511
+ }
1512
+ function He(e, t) {
1513
+ let { children: n } = e;
1514
+ return e.g > 0 && t(e.id) && !n.includes(void 0) && n.some((e) => e !== null);
1515
+ }
1516
+ var Ue = class {
1517
+ #e = [];
1518
+ get size() {
1519
+ return this.#e.length;
1520
+ }
1521
+ push(e) {
1522
+ let t = this.#e;
1523
+ t.push(e);
1524
+ let n = t.length - 1;
1525
+ for (; n > 0;) {
1526
+ let r = n - 1 >> 1;
1527
+ if (!G(e, t[r])) break;
1528
+ t[n] = t[r], n = r;
1529
+ }
1530
+ t[n] = e;
1531
+ }
1532
+ pop() {
1533
+ let e = this.#e, t = e[0], n = e.pop();
1534
+ if (e.length) {
1535
+ let t = 0;
1536
+ for (; 2 * t + 1 < e.length;) {
1537
+ let r = 2 * t + 1;
1538
+ if (r + 1 < e.length && G(e[r + 1], e[r]) && r++, !G(e[r], n)) break;
1539
+ e[t] = e[r], t = r;
1540
+ }
1541
+ e[t] = n;
1542
+ }
1543
+ return t;
1544
+ }
1545
+ };
1546
+ function G(e, t) {
1547
+ return e.shown === t.shown ? e.ratio > t.ratio : e.shown;
1548
+ }
1549
+ //#endregion
1550
+ //#region src/engine/quality.ts
1551
+ var We = 5e5, Ge = 2073600, Ke = [1, .85], qe = 30, Je = 55, Ye = 2e3, Xe = 5e3, Ze = 5e5, Qe = .9;
1552
+ function $e(e, t, n, r) {
1553
+ return Math.min(n, Math.sqrt(Ge / Math.max(1, e * t))) * r;
1554
+ }
1555
+ function et(e, t) {
1556
+ if (!e.length) return 0;
1557
+ let n = [...e].sort((e, t) => e - t);
1558
+ return n[Math.ceil(n.length * t) - 1];
1559
+ }
1560
+ var tt = class {
1561
+ #e = 0;
1562
+ #t;
1563
+ #n;
1564
+ #r;
1565
+ #i = [];
1566
+ #a = -Infinity;
1567
+ #o = 0;
1568
+ #s = 0;
1569
+ constructor(e, [t, n] = [e, e]) {
1570
+ this.#n = t, this.#r = Math.max(t, n), this.#t = Math.min(this.#r, Math.max(this.#n, e));
1571
+ }
1572
+ get scale() {
1573
+ return Ke[this.#e];
1574
+ }
1575
+ get budget() {
1576
+ return this.#t;
1577
+ }
1578
+ full() {
1579
+ this.#e = 0, this.#c();
1580
+ }
1581
+ #c() {
1582
+ this.#i = [], this.#o = 0, this.#s = 0, this.#a = -Infinity;
1583
+ }
1584
+ sample(e, t, n, r) {
1585
+ if (!n || t - this.#a > Math.max(250, 2 * e) || !Number.isFinite(e) || e <= 0) return this.#c(), this.#a = t, !1;
1586
+ let i = Math.max(0, t - this.#a);
1587
+ if (this.#a = t, this.#i.push({
1588
+ time: t,
1589
+ ms: e
1590
+ }), this.#i = this.#i.filter((n) => t - n.time <= Math.max(1e3, 2 * e)), t - this.#i[0].time < 300) return !1;
1591
+ let a = this.#i.reduce((e, t) => e + t.ms, 0) / this.#i.length;
1592
+ if (this.#o = a > 1e3 / qe ? this.#o + i : 0, this.#s = a <= 1e3 / Je ? this.#s + i : 0, this.#o >= Ye) {
1593
+ let e = Math.floor(Math.min(.9, 1e3 / qe / a) * this.#t);
1594
+ if (this.#t > this.#n) this.#t = Math.max(this.#n, e);
1595
+ else if (this.#e < Ke.length - 1) this.#e++;
1596
+ else return !1;
1597
+ } else if (this.#s >= Xe) {
1598
+ if (this.#e > 0) this.#e--;
1599
+ else if (this.#t < this.#r && r >= Qe * this.#t) this.#t = Math.min(this.#r, this.#t + Ze);
1600
+ else return !1;
1601
+ } else return !1;
1602
+ return this.#c(), !0;
1603
+ }
1604
+ }, nt = class {
1605
+ #e;
1606
+ #t = [];
1607
+ #n = /* @__PURE__ */ new Set();
1608
+ #r = /* @__PURE__ */ new Set();
1609
+ #i = /* @__PURE__ */ new Set();
1610
+ #a = /* @__PURE__ */ new Map();
1611
+ constructor(e) {
1612
+ this.#e = e;
1613
+ }
1614
+ want(e) {
1615
+ this.#t = e, this.#n = new Set(e.map((e) => e.id));
1616
+ }
1617
+ next() {
1618
+ let e = [];
1619
+ 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));
1620
+ let t = [];
1621
+ if (this.#r.size >= this.#e.concurrency) return {
1622
+ start: t,
1623
+ abort: e
1624
+ };
1625
+ let n = /* @__PURE__ */ new Map();
1626
+ for (let e of this.#t) {
1627
+ if (this.#a.has(e.id)) continue;
1628
+ let t = n.get(e.pack);
1629
+ t ? t.push(e) : n.set(e.pack, [e]);
1630
+ }
1631
+ for (let e of n.values()) e.sort((e, t) => e.offset - t.offset);
1632
+ for (let e of this.#t) {
1633
+ if (this.#r.size >= this.#e.concurrency) break;
1634
+ if (this.#a.has(e.id)) continue;
1635
+ let r = this.#o(e, n.get(e.pack));
1636
+ for (let e of r.pages) this.#a.set(e.id, r);
1637
+ this.#r.add(r), t.push(r);
1638
+ }
1639
+ return {
1640
+ start: t,
1641
+ abort: e
1642
+ };
1643
+ }
1644
+ done(e) {
1645
+ if (this.#r.delete(e)) {
1646
+ this.#i.delete(e);
1647
+ for (let t of e.pages) this.#a.get(t.id) === e && this.#a.delete(t.id);
1648
+ }
1649
+ }
1650
+ get queued() {
1651
+ let e = 0;
1652
+ for (let t of this.#n) this.#a.has(t) || e++;
1653
+ return e;
1654
+ }
1655
+ get loading() {
1656
+ return this.#a.size;
1657
+ }
1658
+ #o(e, t) {
1659
+ 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;
1660
+ for (let e = a + 1; e < t.length; e++) {
1661
+ let a = t[e];
1362
1662
  if (this.#a.has(a.id)) continue;
1363
1663
  let l = Math.max(c, a.offset + a.length);
1364
1664
  if (a.offset - c > n || l - s > r || Math.floor(a.offset / r) !== i) break;
@@ -1380,12 +1680,12 @@ var Ge = class {
1380
1680
  pages: o
1381
1681
  };
1382
1682
  }
1383
- }, qe = {
1683
+ }, rt = {
1384
1684
  idx: 8,
1385
1685
  concurrency: 8,
1386
1686
  gap: 65536,
1387
1687
  span: 2097152
1388
- }, Je = 1e3, Ye = 3e4, Xe = 1e3, Ze = 2e3, Qe = class {
1688
+ }, it = 1e3, at = 3e4, ot = 1e3, st = 2e3, ct = class {
1389
1689
  #e;
1390
1690
  #t;
1391
1691
  #n;
@@ -1415,8 +1715,8 @@ var Ge = class {
1415
1715
  #y = -Infinity;
1416
1716
  #b = !1;
1417
1717
  #x = !1;
1418
- constructor(e, t, n, r, i, a = qe) {
1419
- this.#e = e, this.#t = t, this.#n = n, this.#r = r, this.#i = i, this.#a = a, this.#o = new Ke(a);
1718
+ constructor(e, t, n, r, i, a = rt) {
1719
+ this.#e = e, this.#t = t, this.#n = n, this.#r = r, this.#i = i, this.#a = a, this.#o = new nt(a);
1420
1720
  }
1421
1721
  update(e, t, n) {
1422
1722
  if (!this.#x) {
@@ -1483,7 +1783,7 @@ var Ge = class {
1483
1783
  let n = this.#e.pages.get(e);
1484
1784
  if (!n) return;
1485
1785
  let { keep: r } = this.#s, i = this.#c;
1486
- this.#n.add(e, t, [n.unit.e, n.unit.n], (e) => r.has(e) || i.has(e)) ? (this.#g.add(e), this.#m.delete(e) && this.#j(e)) : (this.#m.set(e, this.#u + Xe), this.#A(e, Xe)), this.#r();
1786
+ this.#n.add(e, t, [n.unit.e, n.unit.n], (e) => r.has(e) || i.has(e)) ? (this.#g.add(e), this.#m.delete(e) && this.#j(e)) : (this.#m.set(e, this.#u + ot), this.#A(e, ot)), this.#r();
1487
1787
  };
1488
1788
  #E(e) {
1489
1789
  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());
@@ -1497,7 +1797,7 @@ var Ge = class {
1497
1797
  this.#b = !0, this.#i();
1498
1798
  return;
1499
1799
  }
1500
- let n = this.#p.get(e), r = n ? Math.min(2 * n.delay, Ye) : Je;
1800
+ let n = this.#p.get(e), r = n ? Math.min(2 * n.delay, at) : it;
1501
1801
  this.#p.set(e, {
1502
1802
  delay: r,
1503
1803
  until: this.#u + r
@@ -1518,11 +1818,11 @@ var Ge = class {
1518
1818
  }
1519
1819
  #M() {
1520
1820
  let e = this.#u;
1521
- if (e - this.#y < Ze) return;
1821
+ if (e - this.#y < st) return;
1522
1822
  this.#y = e;
1523
1823
  for (let e of this.#g) this.#n.holds(e) || this.#g.delete(e);
1524
1824
  for (let [t, n] of this.#m) n <= e && this.#m.delete(t);
1525
- for (let [t, n] of this.#_) e - n >= Ze && this.#_.delete(t);
1825
+ for (let [t, n] of this.#_) e - n >= st && this.#_.delete(t);
1526
1826
  let { keep: t } = this.#s;
1527
1827
  if (this.#e.pages.size <= 2 * (this.#g.size + t.size)) return;
1528
1828
  let n = /* @__PURE__ */ new Set([
@@ -1547,7 +1847,7 @@ var Ge = class {
1547
1847
  };
1548
1848
  //#endregion
1549
1849
  //#region src/engine/stream/remote.ts
1550
- function $e(e, t) {
1850
+ function lt(e, t) {
1551
1851
  let n = /* @__PURE__ */ new Map();
1552
1852
  return (r) => {
1553
1853
  if ("unfetch" in r) return void n.get(r.unfetch)?.abort();
@@ -1570,29 +1870,29 @@ function $e(e, t) {
1570
1870
  }
1571
1871
  //#endregion
1572
1872
  //#region src/engine/stream/worker.ts?worker&inline
1573
- var et = "(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}async function O(e,t){return p(await A(e,t))}async function*k(e,t,n,r){let i=t.col===null?null:M(e,t.col,n),a=await j(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 A(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 j(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 M(e,t,n){let r=n.get(t);if(r)n.delete(t);else{let i=A(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 N(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 P(e,t){let n;try{n=await(await I()).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 z(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 L(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 R(n,i,r)&&(o(i,r.length),c())}}}async function F(e){let t=new Set(Array.from({length:e},(e,t)=>String(t)));try{let e=await I(),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 I(){return(await navigator.storage.getDirectory()).getDirectoryHandle(`cache`,{create:!0})}async function L(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 R(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 z(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 B(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 V=(e,t,n)=>Math.min(n,Math.max(t,e));function ee(e,t,n){return n>t?V(Math.round((e-t)/(n-t)*255),0,255):0}function te(e,t){return t>0?V(Math.round(e/t*127),-127,127):0}function H(e){return e&=1023,e=(e|e<<16)&50331903,e=(e|e<<8)&50393103,e=(e|e<<4)&51130563,(e|e<<2)&153391689}function ne(e,t,n){return H(e>>6)|H(t>>6)<<1|H(n>>6)<<2}function re(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 ie(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]=te(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 ae(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]=V(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+ne(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]),O=[0,0,0];for(let e=1;e<4;e++)O[e-1]=T.filter(t=>t<e).length;let k=u?re(u,n):/* @__PURE__ */ new Float32Array(9),{book:A,labels:j}=u?ie(u,n,k):{book:null,labels:null},M=A?A.length/9:0,N=17+(M>0?2:0),P=new Uint8Array(128+N*n+M*9),F=new DataView(P.buffer);F.setUint32(0,n,!0),O.forEach((e,t)=>F.setUint32(4+4*t,e,!0)),F.setUint16(16,M,!0),[...v,...y,...p,...m,...h,...g,...k].forEach((e,t)=>F.setFloat32(20+4*t,e,!0));let I=e=>128+e*n,L=new Float32Array([...d,...f]),R=/* @__PURE__ */ new Float64Array(4),z=/* @__PURE__ */ new Float64Array(3),B=[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]-B[n]<<16>>16,i=r<0?-2*r-1:2*r;B[n]=b[t*3+n],P[I(a.position+2*n)+e]=i&255,P[I(a.position+2*n+1)+e]=i>>8}P[I(a.alpha)+e]=V(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++)R[e]=o[t*4+e]/n;let r=0;for(let e=1;e<4;e++)Math.abs(R[e])>Math.abs(R[r])&&(r=e);let u=R[r]<0?-1:1;P[I(a.rotationIndex)+e]=r;for(let t=0,n=0;t<4;t++){if(t===r)continue;let i=Math.round((u*R[t]/Math.SQRT2+.5)*255);P[I(a.rotation+n++)+e]=V(i,0,255)}for(let n=0;n<3;n++)P[I(a.scale+n)+e]=ee(s[t*3+n],p[n],m[n]),P[I(a.dc+n)+e]=ee(l[t*3+n],h[n],g[n]);j&&(P[I(a.label)+e]=j[t]&255,P[I(a.label+1)+e]=j[t]>>8);let[d,f,_]=[0,1,2].map(e=>Math.exp(s[t*3+e]));x(R,d,f,_,z);for(let e=0;e<3;e++)L[e]=Math.min(L[e],i[t*3+e]-z[e]),L[3+e]=Math.max(L[3+e],i[t*3+e]+z[e])}return A&&P.set(new Uint8Array(A.buffer),I(N)),{payload:P,row:{g:t.g,i:t.i,j:t.j,count:n,quadrants:O,box:L,offset:0,length:0}}}function oe(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 se(e,t,n){for(let r=0;r<4;r++)e[t+r]=n.charCodeAt(r)}function U(e){return Uint8Array.from({length:8},(t,n)=>parseInt(e.slice(2*n,2*n+2),16))}async function ce(e,t){let n=await l(e),r=new Uint8Array(8+n.length);return se(r,0,t),new DataView(r.buffer).setUint16(4,1,!0),r.set(n,8),r}async function le(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(U(e.pack),12),o.setUint32(20,e.packSize,!0),e.col&&a.set(U(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)oe(o,s,e),s+=52;for(let e of n)o.setUint8(s,e.quadrant),a.set(U(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(U(e.idx),s+3),s+=11;return ce(a,i)}function ue(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 de(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}}let W=16384,fe=1408,pe=65535,G=324121,me=.4,he=[[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]],ge=he.reduce((e,[t,n,,r])=>e+t*(n+r),0),_e=Float32Array.from({length:fe*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}),K=new TextEncoder,ve={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,q(e,`idx`),`idx`)})),extent:{e:[44e4,9e5],n:[605e4,641e4],h:[0,80]}},ye=K.encode(JSON.stringify(ve));function be(){return async(t,n)=>{if(t.endsWith(`world.json`))return Se(ye,n);let r=g(t),i=t.slice(t.lastIndexOf(`.`)+1);if(!r||i!==`idx`&&i!==`pack`||!Ce(r)||r.hash!==q(r,i))throw new e(`no file ${t}`);return i===`idx`?Se(await ke(r),n):Ae(r,n,t)}}function xe(e,t){let n=30;for(let[r,i,a,o,s]of he)n+=r*Math.sin(i*e+a)*Math.sin(o*t+s);return n}function Se(e,t){return t?e.slice(t[0],t[1]):e.slice()}function q(e,t){return ue(K.encode(`${e.level}/${e.e}/${e.n}.${t}`))}function J(e,t,n){let{e:r,n:i}=ve.extent;return e<r[1]&&e+n>r[0]&&t<i[1]&&t+n>i[0]}function Ce({level:e,e:t,n}){let r=250*2**e;return e<=12&&t%r===0&&n%r===0&&J(t,n,r)}function we(e){return e===0?[1,0]:e===12?[16,15,14,13]:[e+1]}function Te(e){let t=0;for(let n=0;n<8;n++)t|=(e>>2*n&1)<<n;return t}function Ee(e){let t=[];for(let n of we(e.level)){let i=r*2**n,a=250*2**e.level/i;for(let r=0;r<a*a;r++){let a=Te(r),o=Te(r>>1);J(e.e+a*i,e.n+o*i,i)&&t.push({g:n,i:a,j:o})}}return t}function De(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};J(t.e,t.n,r)&&i.push({column:o,row:a,unit:t})}return i}function Oe(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=xe(e.e+(n+.5)*o,e.n+(i+.5)*o),d=ge*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=W/4;return{g:t,i:n,j:i,count:W,quadrants:[p,2*p,3*p],box:f,offset:a,length:G}}function ke(e){let t=Ee(e),n=[];for(let{column:t,row:r,unit:i}of De(e,1))n.push({quadrant:t+2*r,idx:q(i,`idx`)});let r=[];for(let t of[2,3])for(let{column:n,row:i,unit:a}of De(e,t))r.push({depth:t,column:n,row:i,idx:q(a,`idx`)});return le({level:e.level,e:e.e,n:e.n,pack:q(e,`pack`),packSize:t.length*324173+16,col:null,rows:t.map((t,n)=>Oe(e,t,n*G)),children:n,descendants:r})}function Ae(e,t,n){let r=Ee(e);if(!t||t[0]%G!=0||t[1]%G!=0||t[0]>=t[1]||t[1]>r.length*G)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+=G)je(Ne(e,r[(t[0]+n)/G]),i,n);return i}function je(e,t,n){let r=n;for(let n=0;n<e.length;n+=pe){let i=Math.min(pe,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 Me=e=>de(parseInt(ue(K.encode(e)).slice(8),16));function Ne(e,{g:t,i,j:a}){let o=W,s=r*2**t/128,c=Me(`${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+me*(2*c()-1))*s,o=(a*128+Math.floor(t/128)+.5+me*(2*c()-1))*s,h=xe(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%fe;m.set(_e.subarray(9*b,9*(b+1)),9*t)}return ae({count:o,position:l,rotation:u,scale:d,alpha:f,dc:p,sh:m},{g:t,i,j:a}).payload}let Y=2**20,X=self,Z,Pe=/* @__PURE__ */ new Map,Q=/* @__PURE__ */ new Map,Fe=B(e=>X.postMessage(e,[]));X.onmessage=({data:e})=>{`fetched`in e?Fe.take(e):e.type===`init`?(Z=Ie(e),Z.catch(()=>void 0)):e.type===`abort`?Q.get(e.id)?.abort():Re(e)};async function Ie(e){return e.source===`synthetic`?{fetch:be(),cache:await $({...e,cache:`none`}),base:e.base}:{fetch:e.source===`page`?Fe.fetch:t,cache:await $(e),base:e.base}}async function $({cache:e,shard:t,shards:n}){return e===`memory`?N(256*Y):e===`none`?{get:async()=>void 0,put:async()=>void 0}:(t===0&&F(n),await P(await Le()/n,t)??N(256*Y))}async function Le(){try{let{quota:e}=await navigator.storage.estimate();return Math.min(4096*Y,e===void 0?1/0:e/2)}catch{return 4096*Y}}async function Re(t){let{id:n}=t,r=new AbortController;Q.set(n,r);try{if(!Z)throw Error(`stream worker used before init`);let e=await Z;if(t.type===`idx`)X.postMessage({id:n,value:await O(e,t.path)},[]);else{for await(let i of k(e,t.batch,Pe,r.signal))X.postMessage({id:n,page:i},ze(i));X.postMessage({id:n,done:!0},[])}}catch(t){let r=t instanceof Error?t.message:String(t);X.postMessage({id:n,error:r,missing:t instanceof e},[])}finally{Q.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]}})();", tt = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", et], { type: "text/javascript;charset=utf-8" });
1574
- function nt(e) {
1873
+ var ut = "(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}async function O(e,t){return p(await A(e,t))}async function*k(e,t,n,r){let i=t.col===null?null:M(e,t.col,n),a=await j(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 A(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 j(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 M(e,t,n){let r=n.get(t);if(r)n.delete(t);else{let i=A(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 N(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 P(e,t){let n;try{n=await(await I()).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 z(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 L(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 R(n,i,r)&&(o(i,r.length),c())}}}async function F(e){let t=new Set(Array.from({length:e},(e,t)=>String(t)));try{let e=await I(),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 I(){return(await navigator.storage.getDirectory()).getDirectoryHandle(`cache`,{create:!0})}async function L(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 R(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 z(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 B(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 V=(e,t,n)=>Math.min(n,Math.max(t,e));function ee(e,t,n){return n>t?V(Math.round((e-t)/(n-t)*255),0,255):0}function te(e,t){return t>0?V(Math.round(e/t*127),-127,127):0}function H(e){return e&=1023,e=(e|e<<16)&50331903,e=(e|e<<8)&50393103,e=(e|e<<4)&51130563,(e|e<<2)&153391689}function ne(e,t,n){return H(e>>6)|H(t>>6)<<1|H(n>>6)<<2}function re(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 ie(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]=te(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 ae(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]=V(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+ne(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]),O=[0,0,0];for(let e=1;e<4;e++)O[e-1]=T.filter(t=>t<e).length;let k=u?re(u,n):/* @__PURE__ */ new Float32Array(9),{book:A,labels:j}=u?ie(u,n,k):{book:null,labels:null},M=A?A.length/9:0,N=17+(M>0?2:0),P=new Uint8Array(128+N*n+M*9),F=new DataView(P.buffer);F.setUint32(0,n,!0),O.forEach((e,t)=>F.setUint32(4+4*t,e,!0)),F.setUint16(16,M,!0),[...v,...y,...p,...m,...h,...g,...k].forEach((e,t)=>F.setFloat32(20+4*t,e,!0));let I=e=>128+e*n,L=new Float32Array([...d,...f]),R=/* @__PURE__ */ new Float64Array(4),z=/* @__PURE__ */ new Float64Array(3),B=[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]-B[n]<<16>>16,i=r<0?-2*r-1:2*r;B[n]=b[t*3+n],P[I(a.position+2*n)+e]=i&255,P[I(a.position+2*n+1)+e]=i>>8}P[I(a.alpha)+e]=V(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++)R[e]=o[t*4+e]/n;let r=0;for(let e=1;e<4;e++)Math.abs(R[e])>Math.abs(R[r])&&(r=e);let u=R[r]<0?-1:1;P[I(a.rotationIndex)+e]=r;for(let t=0,n=0;t<4;t++){if(t===r)continue;let i=Math.round((u*R[t]/Math.SQRT2+.5)*255);P[I(a.rotation+n++)+e]=V(i,0,255)}for(let n=0;n<3;n++)P[I(a.scale+n)+e]=ee(s[t*3+n],p[n],m[n]),P[I(a.dc+n)+e]=ee(l[t*3+n],h[n],g[n]);j&&(P[I(a.label)+e]=j[t]&255,P[I(a.label+1)+e]=j[t]>>8);let[d,f,_]=[0,1,2].map(e=>Math.exp(s[t*3+e]));x(R,d,f,_,z);for(let e=0;e<3;e++)L[e]=Math.min(L[e],i[t*3+e]-z[e]),L[3+e]=Math.max(L[3+e],i[t*3+e]+z[e])}return A&&P.set(new Uint8Array(A.buffer),I(N)),{payload:P,row:{g:t.g,i:t.i,j:t.j,count:n,quadrants:O,box:L,offset:0,length:0}}}function oe(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 se(e,t,n){for(let r=0;r<4;r++)e[t+r]=n.charCodeAt(r)}function U(e){return Uint8Array.from({length:8},(t,n)=>parseInt(e.slice(2*n,2*n+2),16))}async function ce(e,t){let n=await l(e),r=new Uint8Array(8+n.length);return se(r,0,t),new DataView(r.buffer).setUint16(4,1,!0),r.set(n,8),r}async function le(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(U(e.pack),12),o.setUint32(20,e.packSize,!0),e.col&&a.set(U(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)oe(o,s,e),s+=52;for(let e of n)o.setUint8(s,e.quadrant),a.set(U(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(U(e.idx),s+3),s+=11;return ce(a,i)}function ue(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 de(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}}let W=16384,fe=1408,pe=65535,G=324121,me=.4,he=[[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]],ge=he.reduce((e,[t,n,,r])=>e+t*(n+r),0),_e=Float32Array.from({length:fe*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}),K=new TextEncoder,ve={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,q(e,`idx`),`idx`)})),extent:{e:[44e4,9e5],n:[605e4,641e4],h:[0,80]}},ye=K.encode(JSON.stringify(ve));function be(){return async(t,n)=>{if(t.endsWith(`world.json`))return Se(ye,n);let r=g(t),i=t.slice(t.lastIndexOf(`.`)+1);if(!r||i!==`idx`&&i!==`pack`||!Ce(r)||r.hash!==q(r,i))throw new e(`no file ${t}`);return i===`idx`?Se(await ke(r),n):Ae(r,n,t)}}function xe(e,t){let n=30;for(let[r,i,a,o,s]of he)n+=r*Math.sin(i*e+a)*Math.sin(o*t+s);return n}function Se(e,t){return t?e.slice(t[0],t[1]):e.slice()}function q(e,t){return ue(K.encode(`${e.level}/${e.e}/${e.n}.${t}`))}function J(e,t,n){let{e:r,n:i}=ve.extent;return e<r[1]&&e+n>r[0]&&t<i[1]&&t+n>i[0]}function Ce({level:e,e:t,n}){let r=250*2**e;return e<=12&&t%r===0&&n%r===0&&J(t,n,r)}function we(e){return e===0?[1,0]:e===12?[16,15,14,13]:[e+1]}function Te(e){let t=0;for(let n=0;n<8;n++)t|=(e>>2*n&1)<<n;return t}function Ee(e){let t=[];for(let n of we(e.level)){let i=r*2**n,a=250*2**e.level/i;for(let r=0;r<a*a;r++){let a=Te(r),o=Te(r>>1);J(e.e+a*i,e.n+o*i,i)&&t.push({g:n,i:a,j:o})}}return t}function De(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};J(t.e,t.n,r)&&i.push({column:o,row:a,unit:t})}return i}function Oe(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=xe(e.e+(n+.5)*o,e.n+(i+.5)*o),d=ge*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=W/4;return{g:t,i:n,j:i,count:W,quadrants:[p,2*p,3*p],box:f,offset:a,length:G}}function ke(e){let t=Ee(e),n=[];for(let{column:t,row:r,unit:i}of De(e,1))n.push({quadrant:t+2*r,idx:q(i,`idx`)});let r=[];for(let t of[2,3])for(let{column:n,row:i,unit:a}of De(e,t))r.push({depth:t,column:n,row:i,idx:q(a,`idx`)});return le({level:e.level,e:e.e,n:e.n,pack:q(e,`pack`),packSize:t.length*324173+16,col:null,rows:t.map((t,n)=>Oe(e,t,n*G)),children:n,descendants:r})}function Ae(e,t,n){let r=Ee(e);if(!t||t[0]%G!=0||t[1]%G!=0||t[0]>=t[1]||t[1]>r.length*G)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+=G)je(Ne(e,r[(t[0]+n)/G]),i,n);return i}function je(e,t,n){let r=n;for(let n=0;n<e.length;n+=pe){let i=Math.min(pe,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 Me=e=>de(parseInt(ue(K.encode(e)).slice(8),16));function Ne(e,{g:t,i,j:a}){let o=W,s=r*2**t/128,c=Me(`${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+me*(2*c()-1))*s,o=(a*128+Math.floor(t/128)+.5+me*(2*c()-1))*s,h=xe(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%fe;m.set(_e.subarray(9*b,9*(b+1)),9*t)}return ae({count:o,position:l,rotation:u,scale:d,alpha:f,dc:p,sh:m},{g:t,i,j:a}).payload}let Y=2**20,X=self,Z,Pe=/* @__PURE__ */ new Map,Q=/* @__PURE__ */ new Map,Fe=B(e=>X.postMessage(e,[]));X.onmessage=({data:e})=>{`fetched`in e?Fe.take(e):e.type===`init`?(Z=Ie(e),Z.catch(()=>void 0)):e.type===`abort`?Q.get(e.id)?.abort():Re(e)};async function Ie(e){return e.source===`synthetic`?{fetch:be(),cache:await $({...e,cache:`none`}),base:e.base}:{fetch:e.source===`page`?Fe.fetch:t,cache:await $(e),base:e.base}}async function $({cache:e,shard:t,shards:n}){return e===`memory`?N(256*Y):e===`none`?{get:async()=>void 0,put:async()=>void 0}:(t===0&&F(n),await P(await Le()/n,t)??N(256*Y))}async function Le(){try{let{quota:e}=await navigator.storage.estimate();return Math.min(4096*Y,e===void 0?1/0:e/2)}catch{return 4096*Y}}async function Re(t){let{id:n}=t,r=new AbortController;Q.set(n,r);try{if(!Z)throw Error(`stream worker used before init`);let e=await Z;if(t.type===`idx`)X.postMessage({id:n,value:await O(e,t.path)},[]);else{for await(let i of k(e,t.batch,Pe,r.signal))X.postMessage({id:n,page:i},ze(i));X.postMessage({id:n,done:!0},[])}}catch(t){let r=t instanceof Error?t.message:String(t);X.postMessage({id:n,error:r,missing:t instanceof e},[])}finally{Q.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]}})();", dt = typeof self < "u" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", ut], { type: "text/javascript;charset=utf-8" });
1874
+ function ft(e) {
1575
1875
  let t;
1576
1876
  try {
1577
- if (t = tt && (self.URL || self.webkitURL).createObjectURL(tt), !t) throw "";
1877
+ if (t = dt && (self.URL || self.webkitURL).createObjectURL(dt), !t) throw "";
1578
1878
  let n = new Worker(t, { name: e?.name });
1579
1879
  return n.addEventListener("error", () => {
1580
1880
  (self.URL || self.webkitURL).revokeObjectURL(t);
1581
1881
  }), n;
1582
1882
  } catch {
1583
- return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(et), { name: e?.name });
1883
+ return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(ut), { name: e?.name });
1584
1884
  }
1585
1885
  }
1586
1886
  //#endregion
1587
1887
  //#region src/engine/stream/loader.ts
1588
- var rt = class {
1888
+ var pt = class {
1589
1889
  #e;
1590
1890
  #t = /* @__PURE__ */ new Map();
1591
1891
  #n = 0;
1592
1892
  constructor(e) {
1593
1893
  let { base: t, cache: n, source: r, workers: i } = e;
1594
1894
  this.#e = Array.from({ length: i }, (e, a) => {
1595
- let o = new nt(), s = { worker: o }, c = typeof r == "function" ? $e(r, (e, t) => o.postMessage(e, t)) : void 0;
1895
+ let o = new ft(), s = { worker: o }, c = typeof r == "function" ? lt(r, (e, t) => o.postMessage(e, t)) : void 0;
1596
1896
  o.onmessage = ({ data: e }) => {
1597
1897
  "id" in e ? this.#i(e) : c?.(e);
1598
1898
  }, o.onerror = () => this.#a(s);
@@ -1616,8 +1916,8 @@ var rt = class {
1616
1916
  return this.#r(this.#e[0], t);
1617
1917
  }
1618
1918
  batch(e, t, n) {
1619
- if (t.aborted) return Promise.reject(B());
1620
- let r = this.#e[it(`${e.pack}#${e.window}`, this.#e.length)], i = {
1919
+ if (t.aborted) return Promise.reject(K());
1920
+ let r = this.#e[mt(`${e.pack}#${e.window}`, this.#e.length)], i = {
1621
1921
  type: "batch",
1622
1922
  id: ++this.#n,
1623
1923
  batch: e
@@ -1626,7 +1926,7 @@ var rt = class {
1626
1926
  }
1627
1927
  destroy() {
1628
1928
  for (let { worker: e } of this.#e) e.terminate();
1629
- for (let e of this.#t.values()) e.reject(B());
1929
+ for (let e of this.#t.values()) e.reject(K());
1630
1930
  }
1631
1931
  #r(e, t, n, r) {
1632
1932
  if (e.error) return Promise.reject(e.error);
@@ -1638,7 +1938,7 @@ var rt = class {
1638
1938
  s(), e.worker.postMessage({
1639
1939
  type: "abort",
1640
1940
  id: i
1641
- }), o(B());
1941
+ }), o(K());
1642
1942
  };
1643
1943
  this.#t.set(i, {
1644
1944
  slot: e,
@@ -1661,237 +1961,56 @@ var rt = class {
1661
1961
  for (let t of this.#t.values()) t.slot === e && t.reject(e.error);
1662
1962
  }
1663
1963
  };
1664
- function it(e, t) {
1964
+ function mt(e, t) {
1665
1965
  let n = 2166136261;
1666
1966
  for (let t = 0; t < e.length; t++) n = Math.imul(n ^ e.charCodeAt(t), 16777619);
1667
1967
  return (n >>> 0) % t;
1668
1968
  }
1669
- function B() {
1969
+ function K() {
1670
1970
  return new DOMException("The request was aborted.", "AbortError");
1671
1971
  }
1672
1972
  //#endregion
1673
- //#region src/engine/world/tree.ts
1674
- var V = (e, t, n) => (e * 256 + t) * 256 + n, at = class {
1675
- roots = [];
1676
- pages = /* @__PURE__ */ new Map();
1677
- units = /* @__PURE__ */ new Map();
1678
- #e;
1679
- #t;
1680
- #n = 0;
1681
- #r = /* @__PURE__ */ new Map();
1682
- #i = /* @__PURE__ */ new Map();
1683
- constructor(e) {
1684
- this.#e = new Set(e.roots.map(H)), this.#t = Math.max(...e.roots.map((e) => e.level));
1685
- }
1686
- add(e, t) {
1687
- let n = H(e), r = this.units.get(n);
1688
- if (r) return r;
1689
- let o = /* @__PURE__ */ new Map(), s = {
1690
- level: e.level,
1691
- e: e.e,
1692
- n: e.n,
1693
- idx: e,
1694
- path: t,
1695
- parent: null,
1696
- pages: [],
1697
- grid: o
1698
- };
1699
- for (let t of e.rows) {
1700
- let n = t.box, r = {
1701
- id: this.#n++,
1702
- unit: s,
1703
- row: t,
1704
- g: t.g,
1705
- box: Float64Array.of(e.e + n[0], e.n + n[1], n[2], e.e + n[3], e.n + n[4], n[5]),
1706
- parent: null,
1707
- children: [
1708
- null,
1709
- null,
1710
- null,
1711
- null
1712
- ]
1713
- };
1714
- this.pages.set(r.id, r), s.pages.push(r), o.set(V(t.g, t.i, t.j), r);
1715
- }
1716
- this.units.set(n, s), this.#r.delete(n);
1717
- for (let t = e.level + 1; t <= this.#t; t++) {
1718
- let n = H(U(e, t));
1719
- this.#i.set(n, (this.#i.get(n) ?? 0) + 1);
1720
- }
1721
- 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));
1722
- for (let e of s.pages) {
1723
- let { g: t, i: n, j: r } = e.row;
1724
- c.has(t + 1) && (e.parent = o.get(V(t + 1, n >> 1, r >> 1)) ?? null);
1725
- for (let i = 0; i < 4; i++) {
1726
- let a = 2 * n + (i & 1), s = 2 * r + (i >> 1);
1727
- c.has(t - 1) ? e.children[i] = o.get(V(t - 1, a, s)) ?? null : t === u && t > 0 && (e.children[i] = d.has((a >> 3) + 2 * (s >> 3)) ? void 0 : null);
1728
- }
1729
- }
1730
- if (this.#e.has(n)) for (let e of s.pages) e.g === l && this.roots.push(e);
1731
- else {
1732
- let t = this.units.get(H(U(e, e.level + 1)));
1733
- t && this.#o(t, s);
1734
- }
1735
- let f = a(s.idx);
1736
- for (let { key: t } of f) {
1737
- let n = t.level === e.level - 1 ? this.units.get(H(t)) : void 0;
1738
- n && this.#o(s, n);
1739
- }
1740
- for (let { key: e, hash: t } of f) {
1741
- let n = H(e);
1742
- if (this.units.has(n)) continue;
1743
- let r = this.#r.get(n);
1744
- if (r && r.from <= s.level) continue;
1745
- let a = this.#s(s, e), o = {
1746
- ...e,
1747
- path: i(e, t, "idx"),
1748
- over: a
1749
- };
1750
- this.#r.set(n, {
1751
- wanted: o,
1752
- from: s.level
1753
- });
1754
- }
1755
- return s;
1756
- }
1757
- wanted() {
1758
- return Array.from(this.#r.values(), (e) => e.wanted);
1759
- }
1760
- ground(e, t) {
1761
- for (let n of this.roots) {
1762
- let [r, i, a] = ot(n);
1763
- if (e < r || e >= r + a || t < i || t >= i + a) continue;
1764
- let o = n;
1765
- for (;;) {
1766
- let n = +(e >= r + a / 2), s = +(t >= i + a / 2), c = o.children[n + 2 * s];
1767
- if (!c) return o.box[2];
1768
- o = c, [r, i, a] = ot(o);
1769
- }
1770
- }
1771
- }
1772
- prune(e) {
1773
- let t = [], n = [...this.units.values()].sort((e, t) => e.level - t.level);
1774
- for (let r of n) {
1775
- let n = H(r);
1776
- if (this.#e.has(n) || this.#i.has(n) || r.pages.some((t) => e.has(t.id))) continue;
1777
- for (let e of r.pages) this.pages.delete(e.id), t.push(e.id);
1778
- let i = r.parent;
1779
- if (i) {
1780
- let e = 250 * 2 ** r.level, t = (r.e - i.e) / e, n = (r.n - i.n) / e, a = i.idx.children.some((e) => e.quadrant === t + 2 * n);
1781
- for (let e of this.#s(i, r)) e.children.fill(a ? void 0 : null);
1782
- }
1783
- this.units.delete(n);
1784
- for (let e = r.level + 1; e <= this.#t; e++) {
1785
- let t = H(U(r, e)), n = this.#i.get(t) - 1;
1786
- n ? this.#i.set(t, n) : this.#i.delete(t);
1787
- }
1788
- for (let { key: e } of a(r.idx)) this.#a(e);
1789
- this.#a(r);
1790
- }
1791
- return t;
1792
- }
1793
- #a(e) {
1794
- let t = H(e);
1795
- this.#r.delete(t);
1796
- for (let n = e.level + 1; n <= e.level + 3; n++) {
1797
- let r = this.units.get(H(U(e, n)));
1798
- if (!r) continue;
1799
- let o = a(r.idx).find((e) => H(e.key) === t);
1800
- if (!o) continue;
1801
- let s = {
1802
- level: e.level,
1803
- e: e.e,
1804
- n: e.n,
1805
- path: i(o.key, o.hash, "idx"),
1806
- over: this.#s(r, e)
1807
- };
1808
- this.#r.set(t, {
1809
- wanted: s,
1810
- from: r.level
1811
- });
1812
- return;
1813
- }
1814
- }
1815
- #o(e, t) {
1816
- t.parent = e;
1817
- 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;
1818
- for (let n of this.#s(e, t)) n.children.fill(null);
1819
- for (let e of t.pages) {
1820
- if (e.g !== n) continue;
1821
- let t = 8 * i + e.row.i, r = 8 * a + e.row.j, s = o.get(V(n + 1, t >> 1, r >> 1)) ?? null;
1822
- e.parent = s, s && (s.children[(t & 1) + 2 * (r & 1)] = e);
1823
- }
1824
- }
1825
- #s(t, n) {
1826
- let r = t.level + 1, i = e * 2 ** r, a = (n.e - t.e) / i, o = (n.n - t.n) / i, s = 250 * 2 ** n.level / i, c = [];
1827
- for (let e = o; e < o + s; e++) for (let n = a; n < a + s; n++) {
1828
- let i = t.grid.get(V(r, n, e));
1829
- i && c.push(i);
1830
- }
1831
- return c;
1832
- }
1833
- };
1834
- function H(e) {
1835
- return `${e.level}/${e.e}/${e.n}`;
1836
- }
1837
- function U(e, t) {
1838
- let n = 250 * 2 ** t;
1839
- return {
1840
- level: t,
1841
- e: Math.floor(e.e / n) * n,
1842
- n: Math.floor(e.n / n) * n
1843
- };
1844
- }
1845
- function ot(t) {
1846
- let n = e * 2 ** t.g;
1847
- return [
1848
- t.unit.e + t.row.i * n,
1849
- t.unit.n + t.row.j * n,
1850
- n
1851
- ];
1852
- }
1853
- //#endregion
1854
1973
  //#region src/engine/engine.ts
1855
- var W = class extends Error {
1974
+ var ht = class extends Error {
1856
1975
  constructor() {
1857
1976
  super("This viewer needs WebGPU. Update to the latest Chrome, Edge, Safari or Firefox."), this.name = "NoWebGpu";
1858
1977
  }
1859
1978
  };
1860
- async function st(e, t) {
1979
+ async function gt(e, t) {
1861
1980
  let n = await p();
1862
- if (!n) throw new W();
1981
+ if (!n) throw new ht();
1863
1982
  let r = e.getContext("webgpu");
1864
- if (!r) throw n.device.destroy(), new W();
1983
+ if (!r) throw n.device.destroy(), new ht();
1865
1984
  r.configure({
1866
1985
  device: n.device,
1867
1986
  format: n.format,
1868
1987
  alphaMode: "opaque"
1869
1988
  }), (t.cache ?? "opfs") === "opfs" && navigator.storage?.persist().catch(() => !1);
1870
1989
  let { source: i = "http" } = t;
1871
- return new Ot(e, n, r, t, i === "synthetic" ? (await import("./synthetic-BZcHRI1P.js")).synthetic() : i === "http" ? s : i);
1990
+ return new Bt(e, n, r, t, i === "synthetic" ? (await import("./synthetic-BeGCzYIv.js")).synthetic() : i === "http" ? s : i);
1872
1991
  }
1873
- var G = .2, ct = 25165824, lt = 2.5, ut = 1 + L, dt = 1024, ft = 2048, pt = 100, mt = 2, K = 300, ht = 100, gt = 250, _t = 300, vt = 1e3, yt = 400, bt = 5e3, xt = 60, q = Math.PI / 180, St = "The viewer was closed.", Ct = "Another world was opened.";
1874
- function J(e, t) {
1992
+ var _t = .2, vt = 25165824, yt = 2.5, bt = 1 + R, xt = 1024, St = 2048, Ct = 100, wt = 2, Tt = 300, Et = 100, Dt = 250, Ot = 300, kt = 1e3, At = 400, jt = 5e3, Mt = 60, q = Math.PI / 180, Nt = "The viewer was closed.", Pt = "Another world was opened.";
1993
+ function Ft(e, t) {
1875
1994
  let n = Math.min(t.maxStorageBufferBindingSize, t.maxBufferSize), r = (t, r) => {
1876
1995
  let i = Math.ceil(e * t / 256) * 256;
1877
1996
  return Math.min(i, Math.floor(n / r / 256) * 256);
1878
1997
  };
1879
1998
  return {
1880
- pool: r(lt, 16),
1881
- frame: r(ut, 24)
1999
+ pool: r(yt, 16),
2000
+ frame: r(bt, 24)
1882
2001
  };
1883
2002
  }
1884
- function wt(e, t) {
2003
+ function It(e, t) {
1885
2004
  let [n, r, i] = t;
1886
- if (Math.hypot(n - e[0], r - e[1], i - e[2]) <= ft) return e;
1887
- let a = (e) => Math.round(e / dt) * dt;
2005
+ if (Math.hypot(n - e[0], r - e[1], i - e[2]) <= St) return e;
2006
+ let a = (e) => Math.round(e / xt) * xt;
1888
2007
  return [
1889
2008
  a(n),
1890
2009
  a(r),
1891
2010
  a(i)
1892
2011
  ];
1893
2012
  }
1894
- function Tt(e, t, n, r, i, a) {
2013
+ function Lt(e, t, n, r, i, a) {
1895
2014
  let o = 2 * e[0] / t[0] - 1, s = 1 - 2 * e[1] / t[1], c = [
1896
2015
  n * o / r[0],
1897
2016
  n * s / r[5],
@@ -1903,29 +2022,29 @@ function Tt(e, t, n, r, i, a) {
1903
2022
  d + a[2]
1904
2023
  ];
1905
2024
  }
1906
- function Et(e, t) {
2025
+ function Rt(e, t) {
1907
2026
  return [
1908
2027
  e.e - t[0],
1909
2028
  e.n - t[1],
1910
2029
  e.h - t[2]
1911
2030
  ];
1912
2031
  }
1913
- function Dt(e, t) {
1914
- e.push(t), e.length > xt && e.shift();
2032
+ function zt(e, t) {
2033
+ e.push(t), e.length > Mt && e.shift();
1915
2034
  }
1916
- var Ot = class {
2035
+ var Bt = class {
1917
2036
  #e;
1918
2037
  #t;
1919
2038
  #n;
1920
2039
  #r;
1921
2040
  #i;
1922
2041
  #a;
1923
- #o = new Ge();
2042
+ #o;
1924
2043
  #s;
1925
2044
  #c;
1926
2045
  #l;
1927
- #u = new Ne();
1928
- #d = new Ie();
2046
+ #u = new Be();
2047
+ #d = new Ee();
1929
2048
  #f = (e) => this.#s.has(e);
1930
2049
  #p = null;
1931
2050
  #m = null;
@@ -1969,7 +2088,7 @@ var Ot = class {
1969
2088
  #L = !1;
1970
2089
  #R = !1;
1971
2090
  #z = !1;
1972
- #B = 0;
2091
+ #B = [];
1973
2092
  #V = -Infinity;
1974
2093
  #H = -Infinity;
1975
2094
  #U = -Infinity;
@@ -1986,13 +2105,13 @@ var Ot = class {
1986
2105
  #ee = !1;
1987
2106
  #te = !1;
1988
2107
  constructor(e, t, n, r, i) {
1989
- this.#e = e, this.#t = t, this.#n = n, this.#r = r, this.#i = i, this.#a = { ...r.settings }, this.#O = [
2108
+ this.#e = e, this.#t = t, this.#n = n, this.#r = r, this.#i = i, this.#a = { ...r.settings }, this.#o = this.#re(), this.#O = [
1990
2109
  e.width,
1991
2110
  e.height,
1992
2111
  1
1993
2112
  ], this.#k = [Math.max(1, e.width), Math.max(1, e.height)];
1994
- let { pool: a, frame: o } = J(this.#ne, t.device.limits);
1995
- this.#s = new _(t.device, a), this.#c = new Te(t, n, this.#s, o), this.#l = o, t.device.lost.then((e) => {
2113
+ let { pool: a, frame: o } = Ft(this.#ne, t.device.limits);
2114
+ this.#s = new _(t.device, a), this.#c = new Ce(t, n, this.#s, o), this.#l = o, t.device.lost.then((e) => {
1996
2115
  if (!this.#ee) {
1997
2116
  this.#te = !0, cancelAnimationFrame(this.#A);
1998
2117
  for (let t of this.#Z) t(e.message || e.reason);
@@ -2000,53 +2119,54 @@ var Ot = class {
2000
2119
  });
2001
2120
  }
2002
2121
  async open(e) {
2003
- if (this.#ee) throw Error(St);
2122
+ if (this.#ee) throw Error(Nt);
2004
2123
  let t = ++this.#_, i = () => {
2005
- if (this.#ee) throw Error(St);
2006
- if (t !== this.#_) throw Error(Ct);
2124
+ if (this.#ee) throw Error(Nt);
2125
+ if (t !== this.#_) throw Error(Pt);
2007
2126
  }, { cache: a = "opfs", source: o = "http" } = this.#r;
2008
2127
  o === "http" && (e = new URL(e, document.baseURI).href);
2009
2128
  let s = await this.#i(e, null), c = r(JSON.parse(new TextDecoder().decode(s)));
2010
2129
  i();
2011
- let l = new rt({
2130
+ let l = new pt({
2012
2131
  base: n(e),
2013
2132
  workers: Math.min(6, Math.max(2, navigator.hardwareConcurrency - 2)),
2014
2133
  cache: a,
2015
2134
  source: o
2016
- }), u = new at(c);
2135
+ }), u = new Ie(c);
2017
2136
  try {
2018
2137
  let e = await Promise.all(c.roots.map((e) => l.idx(e.idx)));
2019
2138
  i(), e.forEach((e, t) => u.add(e, c.roots[t].idx));
2020
2139
  } catch (e) {
2021
2140
  throw l.destroy(), e;
2022
2141
  }
2023
- return this.#g?.destroy(), this.#g = null, this.#h?.destroy(), this.#p = e, this.#m = u, this.#h = l, this.#N = null, this.#u = new Ne(), this.#d = new Ie(), this.#s.clear(), this.#g = this.#ie(u, l), this.#I = !0, this.requestFrame(), c;
2142
+ return this.#g?.destroy(), this.#g = null, this.#h?.destroy(), this.#p = e, this.#m = u, this.#h = l, this.#N = null, this.#u = new Be(), this.#d = new Ee(), this.#s.clear(), this.#g = this.#oe(u, l), this.#I = !0, this.requestFrame(), c;
2024
2143
  }
2025
2144
  setCamera(e) {
2026
2145
  if (this.#ee) return;
2027
2146
  let t = performance.now(), n = t - this.#b, r = this.#y, i = this.#x;
2028
- if (n > gt) i.fill(0);
2147
+ if (n > Dt) i.fill(0);
2029
2148
  else if (n > 0) {
2030
- let t = 1 - Math.exp(-n / ht);
2149
+ let t = 1 - Math.exp(-n / Et);
2031
2150
  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]);
2032
2151
  }
2033
2152
  this.#b = t, this.#y = { ...e }, this.#F = !0, this.#$ || this.requestFrame();
2034
2153
  }
2035
2154
  configure(e) {
2036
2155
  if (this.#ee) return;
2156
+ let { budget: t, budgetRange: n } = this.#a;
2037
2157
  this.#a = {
2038
2158
  ...this.#a,
2039
2159
  ...e
2040
2160
  };
2041
- let { pool: t, frame: n } = J(this.#ne, this.#t.device.limits);
2042
- (t > this.#s.capacity || n > this.#l) && this.#re(t, n), this.#I = !0, this.requestFrame();
2161
+ let r = this.#a;
2162
+ (r.budget !== t || !((e, t) => e?.join() === t?.join())(r.budgetRange, n)) && (this.#o = this.#re(), this.#le()), this.#ie();
2043
2163
  }
2044
2164
  resize(e, t, n) {
2045
2165
  this.#ee || (this.#O = [
2046
2166
  e,
2047
2167
  t,
2048
2168
  n
2049
- ], this.#se());
2169
+ ], this.#le());
2050
2170
  }
2051
2171
  pick(e, t) {
2052
2172
  if (this.#ee || this.#te) return Promise.resolve(null);
@@ -2062,6 +2182,10 @@ var Ot = class {
2062
2182
  ground(e, t) {
2063
2183
  return this.#m?.ground(e, t);
2064
2184
  }
2185
+ async groundAt(e, t) {
2186
+ let n = this.#m, r = this.#h;
2187
+ if (n && r) return await n.load(e, t, (e) => r.idx(e)), this.#R = !0, this.requestFrame(), n.ground(e, t);
2188
+ }
2065
2189
  heights(e, t, n) {
2066
2190
  return this.#ee || this.#te ? Promise.resolve(null) : new Promise((r) => {
2067
2191
  this.#Y.push({
@@ -2075,8 +2199,8 @@ var Ot = class {
2075
2199
  stats() {
2076
2200
  let e = this.#s, t = this.#g, n = this.#c.stats();
2077
2201
  return {
2078
- frameMs: z(this.#W, .5),
2079
- cpuMs: z(this.#G, .5),
2202
+ frameMs: et(this.#W, .5),
2203
+ cpuMs: et(this.#G, .5),
2080
2204
  gpuMs: n.gpuMs,
2081
2205
  passes: n.passes,
2082
2206
  drawn: n.drawn,
@@ -2084,7 +2208,7 @@ var Ot = class {
2084
2208
  missing: this.#N?.missing ?? 0,
2085
2209
  pages: {
2086
2210
  resident: Array.from(e.ids()).length,
2087
- drawn: this.#B,
2211
+ drawn: this.#B.length,
2088
2212
  loading: t?.loading ?? 0,
2089
2213
  queued: t?.queued ?? 0
2090
2214
  },
@@ -2093,6 +2217,7 @@ var Ot = class {
2093
2217
  buffers: n.bytes
2094
2218
  },
2095
2219
  capacity: e.capacity,
2220
+ budget: this.#ne,
2096
2221
  scale: this.#o.scale,
2097
2222
  loading: t !== null && !t.idle
2098
2223
  };
@@ -2105,8 +2230,8 @@ var Ot = class {
2105
2230
  use(e) {
2106
2231
  if (this.#ee) return () => {};
2107
2232
  let t = e({
2108
- shade: (e) => this.#oe(this.#K, e, this.#c.shade(e)),
2109
- post: (e) => this.#oe(this.#q, e, this.#c.post(e))
2233
+ shade: (e) => this.#ce(this.#K, e, this.#c.shade(e)),
2234
+ post: (e) => this.#ce(this.#q, e, this.#c.post(e))
2110
2235
  });
2111
2236
  return () => {
2112
2237
  this.#ee || t();
@@ -2114,7 +2239,7 @@ var Ot = class {
2114
2239
  }
2115
2240
  warm() {
2116
2241
  let e = performance.now();
2117
- e - this.#V < vt || (this.#H = e + yt, this.requestFrame());
2242
+ e - this.#V < kt || (this.#H = e + At, this.requestFrame());
2118
2243
  }
2119
2244
  onFrame(e) {
2120
2245
  return this.#Q.add(e), () => this.#Q.delete(e);
@@ -2123,7 +2248,7 @@ var Ot = class {
2123
2248
  return this.#Z.add(e), () => this.#Z.delete(e);
2124
2249
  }
2125
2250
  requestFrame() {
2126
- this.#ee || this.#te || this.#r.manual || this.#A || (this.#A = requestAnimationFrame(this.#ce));
2251
+ this.#ee || this.#te || this.#r.manual || this.#A || (this.#A = requestAnimationFrame(this.#ue));
2127
2252
  }
2128
2253
  async step() {
2129
2254
  if (this.#ee || this.#te) return {
@@ -2131,7 +2256,7 @@ var Ot = class {
2131
2256
  gpuMs: 0,
2132
2257
  passes: {}
2133
2258
  };
2134
- let { done: e, cpuMs: t } = this.#le(!1);
2259
+ let { done: e, cpuMs: t } = this.#de(!1);
2135
2260
  await e;
2136
2261
  let { gpuMs: n, passes: r } = this.#c.stats();
2137
2262
  return {
@@ -2150,29 +2275,36 @@ var Ot = class {
2150
2275
  }
2151
2276
  }
2152
2277
  get #ne() {
2153
- let e = Math.floor(J(Infinity, this.#t.device.limits).frame / ut);
2154
- return Math.max(1, Math.min(this.#a.budget, e));
2278
+ return this.#o.budget;
2279
+ }
2280
+ #re() {
2281
+ let { budget: e, budgetRange: t = [e, e] } = this.#a, n = Math.floor(Ft(Infinity, this.#t.device.limits).frame / bt), r = (e) => Math.max(1, Math.min(e, n));
2282
+ return new tt(r(e), [r(t[0]), r(t[1])]);
2155
2283
  }
2156
- #re(e, t) {
2157
- this.#g?.destroy(), this.#g = null, this.#c.destroy(), this.#s.destroy(), this.#s = new _(this.#t.device, e), this.#s.setOrigin(this.#S);
2158
- let n = new Te(this.#t, this.#n, this.#s, t);
2284
+ #ie() {
2285
+ let { pool: e, frame: t } = Ft(this.#ne, this.#t.device.limits);
2286
+ (e > this.#s.capacity || t > this.#l) && this.#ae(e, t), this.#I = !0, this.requestFrame();
2287
+ }
2288
+ #ae(e, t) {
2289
+ this.#s.grow(e), this.#c.destroy();
2290
+ let n = new Ce(this.#t, this.#n, this.#s, t);
2159
2291
  n.resize(...this.#k);
2160
2292
  for (let e of this.#K) e.off = n.shade(e.hook);
2161
2293
  for (let e of this.#q) e.off = n.post(e.hook);
2162
- this.#c = n, this.#l = t, this.#m && this.#h && (this.#g = this.#ie(this.#m, this.#h)), this.#N = null, this.#I = !0, this.requestFrame();
2294
+ this.#c = n, this.#l = t;
2163
2295
  }
2164
- #ie(e, t) {
2165
- return new Qe(e, t, this.#s, () => {
2296
+ #oe(e, t) {
2297
+ return new ct(e, t, this.#s, () => {
2166
2298
  this.#R = !0, this.requestFrame();
2167
- }, this.#ae);
2299
+ }, this.#se);
2168
2300
  }
2169
- #ae = () => {
2301
+ #se = () => {
2170
2302
  let e = this.#p, t = this.#m;
2171
2303
  this.#v || this.#ee || e === null || (this.#v = !0, this.open(e).then(() => this.#v = !1, () => {
2172
- this.#v = !1, this.#m === t && setTimeout(this.#ae, bt);
2304
+ this.#v = !1, this.#m === t && setTimeout(this.#se, jt);
2173
2305
  }));
2174
2306
  };
2175
- #oe(e, t, n) {
2307
+ #ce(e, t, n) {
2176
2308
  let r = {
2177
2309
  hook: t,
2178
2310
  off: n
@@ -2182,105 +2314,105 @@ var Ot = class {
2182
2314
  this.#ee || t < 0 || (e.splice(t, 1), r.off(), this.requestFrame());
2183
2315
  };
2184
2316
  }
2185
- #se() {
2186
- let [e, t, n] = this.#O, r = We(e, t, n, this.#o.scale), i = Math.max(1, Math.round(e * r)), a = Math.max(1, Math.round(t * r));
2317
+ #le() {
2318
+ let [e, t, n] = this.#O, r = $e(e, t, n, this.#o.scale), i = Math.max(1, Math.round(e * r)), a = Math.max(1, Math.round(t * r));
2187
2319
  (i !== this.#k[0] || a !== this.#k[1]) && (this.#k = [i, a], this.#e.width = i, this.#e.height = a, this.#c.resize(i, a), this.#I = !0, this.requestFrame());
2188
2320
  }
2189
- #ce = (e) => {
2321
+ #ue = (e) => {
2190
2322
  if (this.#A = 0, !(this.#ee || this.#te)) {
2191
- if (this.#j >= mt) this.#M = !0;
2323
+ if (this.#j >= wt) this.#M = !0;
2192
2324
  else {
2193
2325
  this.#$ = !0;
2194
2326
  for (let t of this.#Q) t(e);
2195
- this.#$ = !1, this.#j++, this.#le(!0).done.finally(() => {
2327
+ this.#$ = !1, this.#j++, this.#de(!0).done.finally(() => {
2196
2328
  this.#j--, this.#M && (this.#M = !1, this.requestFrame());
2197
2329
  });
2198
2330
  }
2199
2331
  }
2200
2332
  };
2201
- #le(e) {
2333
+ #de(e) {
2202
2334
  let t = performance.now(), n = this.#o, r = this.#s, i = this.#y, [a, o] = this.#k, s = this.#a.viewDistance, c = this.#F;
2203
2335
  this.#F = !1;
2204
- let l = wt(this.#S, [
2336
+ let l = It(this.#S, [
2205
2337
  i.e,
2206
2338
  i.n,
2207
2339
  i.h
2208
2340
  ]);
2209
2341
  l !== this.#S && (this.#S = l, r.setOrigin(l));
2210
- let u = Et(i, l);
2211
- y(this.#C, u, i.yaw * q, i.pitch * q), b(this.#w, i.fov * q, a / o, G, s);
2342
+ let u = Rt(i, l);
2343
+ y(this.#C, u, i.yaw * q, i.pitch * q), b(this.#w, i.fov * q, a / o, _t, s);
2212
2344
  let d = {
2213
2345
  time: t,
2214
2346
  width: a,
2215
2347
  height: o,
2216
2348
  view: new Float32Array(this.#C),
2217
2349
  proj: new Float32Array(this.#w),
2218
- near: G,
2350
+ near: _t,
2219
2351
  far: s,
2220
2352
  camera: Float32Array.from(u),
2221
2353
  origin: l
2222
2354
  };
2223
- De(this.#D, S(this.#E, d.proj, d.view));
2224
- let f = this.#m, p = this.#g, m = this.#N;
2355
+ Te(this.#D, S(this.#E, d.proj, d.view));
2356
+ let f = this.#m, p = this.#g, m = this.#R || this.#I || this.#z, h = this.#N, g = h;
2225
2357
  if (f && p) {
2226
- let e = !p.idle && t - this.#P >= pt, n = this.#I || this.#R || this.#z || this.#L;
2227
- (!m || c || e || n) && (m = this.#ue(f, t, c));
2358
+ let e = !p.idle && t - this.#P >= Ct, n = this.#I || this.#R || this.#z || this.#L;
2359
+ (!g || c || e || n) && (g = this.#fe(f, t, c));
2228
2360
  }
2229
- let h = [], g = !1;
2230
- m && p && ({drawn: h, fading: g} = this.#d.update(m.cut, this.#f, t, this.#ne), p.update(m, new Set(h.map((e) => e.id)), t)), r.upload(ct) > 0 && (this.#R = !0), r.draw(h), this.#z = g, this.#B = h.length;
2231
- let _ = this.#J.splice(0).map((e) => this.#fe(e, d)), v = this.#Y.splice(0).map((e) => this.#pe(e, l)), x = this.#c.render(d, this.#D, this.#r.sky, _, v), C = performance.now() - t;
2232
- if (!this.#R && !this.#L && !g && r.queued === 0 && (!p || p.idle) && (!m || m.load.length === 0 && m.idx.length === 0) && this.#X.length) {
2361
+ let _ = this.#B, v = this.#z;
2362
+ 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.#ne)), p.update(g, new Set(_.map((e) => e.id)), t)), r.upload(vt) > 0 && (this.#R = !0), (_ !== this.#B || this.#R) && r.draw(_), this.#z = v, this.#B = _;
2363
+ let x = this.#J.splice(0).map((e) => this.#me(e, d)), C = this.#Y.splice(0).map((e) => this.#he(e, l)), w = this.#c.render(d, this.#D, this.#r.sky, x, C), T = performance.now() - t;
2364
+ if (!this.#R && !this.#L && !v && r.queued === 0 && (!p || p.idle) && (!g || g.load.length === 0 && g.idx.length === 0) && this.#X.length) {
2233
2365
  let e = this.#X.splice(0);
2234
- x.then(() => e.forEach((e) => e()));
2366
+ w.then(() => e.forEach((e) => e()));
2235
2367
  }
2236
- e && this.#me(t, C, c);
2237
- let w = t < this.#H;
2238
- return (r.queued > 0 || this.#R || this.#L || g || n.scale < 1 || w) && this.requestFrame(), {
2239
- done: x,
2240
- cpuMs: C
2368
+ e && this.#ge(t, T, c);
2369
+ let E = t < this.#H;
2370
+ return (r.queued > 0 || this.#R || this.#L || v || n.scale < 1 || E) && this.requestFrame(), {
2371
+ done: w,
2372
+ cpuMs: T
2241
2373
  };
2242
2374
  }
2243
- #ue(e, t, n) {
2375
+ #fe(e, t, n) {
2244
2376
  let r = this.#y, i = this.#s, [a, o] = this.#k, s = this.#o.scale, c = this.#ne, l = {
2245
2377
  origin: this.#S,
2246
2378
  width: a / s,
2247
2379
  height: o / s,
2248
2380
  tan: Math.tan(r.fov * q / 2),
2249
- near: G,
2381
+ near: _t,
2250
2382
  far: this.#a.viewDistance
2251
2383
  }, u = {
2252
2384
  ...l,
2253
2385
  view: this.#C
2254
2386
  }, d = {
2255
2387
  budget: c,
2256
- capacity: i.capacity - Math.ceil(L * c),
2388
+ capacity: i.capacity - Math.ceil(R * c),
2257
2389
  now: t,
2258
- predicted: n ? this.#de(l) : void 0
2390
+ predicted: n ? this.#pe(l) : void 0
2259
2391
  }, f = this.#u.plan(e, u, this.#f, d);
2260
2392
  return this.#N = f, this.#P = t, this.#I = !1, this.#L = d.predicted !== void 0, this.#R = !1, f;
2261
2393
  }
2262
- #de(e) {
2394
+ #pe(e) {
2263
2395
  let t = this.#x;
2264
2396
  if (t.every((e) => e === 0)) return;
2265
2397
  let n = this.#y, r = [
2266
- n.e + t[0] * K - e.origin[0],
2267
- n.n + t[1] * K - e.origin[1],
2268
- n.h + t[2] * K - e.origin[2]
2398
+ n.e + t[0] * Tt - e.origin[0],
2399
+ n.n + t[1] * Tt - e.origin[1],
2400
+ n.h + t[2] * Tt - e.origin[2]
2269
2401
  ];
2270
2402
  return {
2271
2403
  ...e,
2272
2404
  view: y(this.#T, r, n.yaw * q, n.pitch * q)
2273
2405
  };
2274
2406
  }
2275
- #fe({ x: e, y: t, resolve: n }, r) {
2276
- let i = this.#C.slice(), a = this.#S, o = [r.width, r.height], s = (n) => Tt([e, t], o, n, r.proj, i, a);
2407
+ #me({ x: e, y: t, resolve: n }, r) {
2408
+ let i = this.#C.slice(), a = this.#S, o = [r.width, r.height], s = (n) => Lt([e, t], o, n, r.proj, i, a);
2277
2409
  return {
2278
2410
  x: e,
2279
2411
  y: t,
2280
2412
  resolve: (e) => n(e === null ? null : s(e))
2281
2413
  };
2282
2414
  }
2283
- #pe({ west: e, south: t, cells: n, resolve: r }, i) {
2415
+ #he({ west: e, south: t, cells: n, resolve: r }, i) {
2284
2416
  return {
2285
2417
  x: e - i[0],
2286
2418
  y: t - i[1],
@@ -2291,21 +2423,23 @@ var Ot = class {
2291
2423
  }
2292
2424
  };
2293
2425
  }
2294
- #me(e, t, n) {
2295
- let r = this.#o, i = e - this.#V <= gt;
2296
- i && Dt(this.#W, e - this.#V), Dt(this.#G, t), this.#V = e, r.sample(this.#c.stats().gpuMs, e, i && n) && this.#se(), n ? this.#U = e : r.scale < 1 && e - this.#U > _t && (r.full(), this.#se());
2426
+ #ge(e, t, n) {
2427
+ let r = this.#o, { gpuMs: i } = this.#c.stats(), a = e - this.#V, o = a <= Math.max(Dt, 2 * i, 2 * t);
2428
+ o && zt(this.#W, a), zt(this.#G, t), this.#V = e;
2429
+ let s = r.budget;
2430
+ r.sample(a, e, o && n, this.#N?.planned ?? 0) && (this.#le(), r.budget !== s && this.#ie()), n ? this.#U = e : r.scale < 1 && e - this.#U > Ot && (r.full(), this.#le());
2297
2431
  }
2298
- }, kt = 45, At = {
2432
+ }, Vt = 45, Ht = {
2299
2433
  yaw: 0,
2300
2434
  pitch: -35,
2301
2435
  dist: 300
2302
- }, Y = {
2436
+ }, J = {
2303
2437
  pitch: [-90, -20],
2304
2438
  dist: [1, 2485],
2305
2439
  clearance: 10,
2306
2440
  floor: 50
2307
- }, jt = .1, X = Math.PI / 180, Mt = (e, [t, n]) => Math.min(n, Math.max(t, e)), Nt = (e) => (e % 360 + 360) % 360, Pt = (e, t) => (t - e + 540) % 360 - 180;
2308
- function Ft({ leaf: e, roots: t, extent: n }) {
2441
+ }, Ut = .1, Y = Math.PI / 180, Wt = (e, [t, n]) => Math.min(n, Math.max(t, e)), Gt = (e) => (e % 360 + 360) % 360, Kt = (e, t) => (t - e + 540) % 360 - 180;
2442
+ function qt({ leaf: e, roots: t, extent: n }) {
2309
2443
  let r = {
2310
2444
  e: (n.e[0] + n.e[1]) / 2,
2311
2445
  n: (n.n[0] + n.n[1]) / 2,
@@ -2322,7 +2456,7 @@ function Ft({ leaf: e, roots: t, extent: n }) {
2322
2456
  }
2323
2457
  return i;
2324
2458
  }
2325
- function It(e) {
2459
+ function Jt(e) {
2326
2460
  let t = e.split(",");
2327
2461
  if (t.length !== 6 || t.some((e) => e.trim() === "")) return null;
2328
2462
  let [n, r, i, a, o, s] = t.map(Number);
@@ -2342,7 +2476,7 @@ function It(e) {
2342
2476
  dist: s
2343
2477
  };
2344
2478
  }
2345
- function Lt(e) {
2479
+ function Yt(e) {
2346
2480
  let t = (e, t) => +e.toFixed(t);
2347
2481
  return [
2348
2482
  t(e.e, 2),
@@ -2353,19 +2487,19 @@ function Lt(e) {
2353
2487
  t(e.dist, 1)
2354
2488
  ].join(",");
2355
2489
  }
2356
- function Z(e, t, n = Y) {
2490
+ function X(e, t, n = J) {
2357
2491
  let r = {
2358
2492
  e: e.e,
2359
2493
  n: e.n,
2360
2494
  h: e.h,
2361
- yaw: Nt(e.yaw),
2362
- pitch: Mt(e.pitch, n.pitch),
2363
- dist: Mt(e.dist, n.dist)
2495
+ yaw: Gt(e.yaw),
2496
+ pitch: Wt(e.pitch, n.pitch),
2497
+ dist: Wt(e.dist, n.dist)
2364
2498
  };
2365
2499
  if (t) {
2366
- let e = Q(r), i = Math.max(n.floor, t(e.e, e.n) + n.clearance);
2500
+ let e = Z(r), i = Math.max(n.floor, t(e.e, e.n) + n.clearance);
2367
2501
  if (e.h < i) return {
2368
- ...Vt({
2502
+ ...$t({
2369
2503
  ...e,
2370
2504
  h: i
2371
2505
  }, r),
@@ -2374,42 +2508,42 @@ function Z(e, t, n = Y) {
2374
2508
  }
2375
2509
  return r;
2376
2510
  }
2377
- function Rt(e, t) {
2378
- let n = Math.cos(t * X);
2511
+ function Xt(e, t) {
2512
+ let n = Math.cos(t * Y);
2379
2513
  return {
2380
- e: Math.sin(e * X) * n,
2381
- n: Math.cos(e * X) * n,
2382
- h: Math.sin(t * X)
2514
+ e: Math.sin(e * Y) * n,
2515
+ n: Math.cos(e * Y) * n,
2516
+ h: Math.sin(t * Y)
2383
2517
  };
2384
2518
  }
2385
- function Q(e) {
2386
- let t = Rt(e.yaw, e.pitch);
2519
+ function Z(e) {
2520
+ let t = Xt(e.yaw, e.pitch);
2387
2521
  return {
2388
2522
  e: e.e - t.e * e.dist,
2389
2523
  n: e.n - t.n * e.dist,
2390
2524
  h: e.h - t.h * e.dist
2391
2525
  };
2392
2526
  }
2393
- function zt(e) {
2527
+ function Zt(e) {
2394
2528
  return {
2395
- ...Q(e),
2529
+ ...Z(e),
2396
2530
  yaw: e.yaw,
2397
2531
  pitch: e.pitch,
2398
2532
  fov: 45
2399
2533
  };
2400
2534
  }
2401
- function Bt(e, t, n) {
2402
- let r = Q(e), [i, a, o] = [
2535
+ function Qt(e, t, n) {
2536
+ let r = Z(e), [i, a, o] = [
2403
2537
  n.e - r.e,
2404
2538
  n.n - r.n,
2405
2539
  n.h - r.h
2406
- ], [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);
2540
+ ], [s, c] = [Math.sin(e.yaw * Y), Math.cos(e.yaw * Y)], [l, u] = [Math.sin(e.pitch * Y), Math.cos(e.pitch * Y)], d = i * s + a * c, f = 2 * Math.tan(t * Y / 2) * (d * u + o * l);
2407
2541
  return {
2408
2542
  x: (i * c - a * s) / f,
2409
2543
  y: (d * l - o * u) / f
2410
2544
  };
2411
2545
  }
2412
- function Vt(e, t) {
2546
+ function $t(e, t) {
2413
2547
  let [n, r, i] = [
2414
2548
  t.e - e.e,
2415
2549
  t.n - e.n,
@@ -2419,17 +2553,17 @@ function Vt(e, t) {
2419
2553
  e: t.e,
2420
2554
  n: t.n,
2421
2555
  h: t.h,
2422
- yaw: Nt(Math.atan2(n, r) / X),
2423
- pitch: Math.asin(i / a) / X,
2556
+ yaw: Gt(Math.atan2(n, r) / Y),
2557
+ pitch: Math.asin(i / a) / Y,
2424
2558
  dist: a
2425
2559
  };
2426
2560
  }
2427
- function Ht(e, t, n, r = Y) {
2428
- let i = Q(e), a = Z({
2561
+ function en(e, t, n, r = J) {
2562
+ let i = Z(e), a = X({
2429
2563
  ...e,
2430
2564
  yaw: t,
2431
2565
  pitch: n
2432
- }, void 0, r), o = Rt(a.yaw, a.pitch);
2566
+ }, void 0, r), o = Xt(a.yaw, a.pitch);
2433
2567
  return {
2434
2568
  ...a,
2435
2569
  e: i.e + o.e * a.dist,
@@ -2437,11 +2571,11 @@ function Ht(e, t, n, r = Y) {
2437
2571
  h: i.h + o.h * a.dist
2438
2572
  };
2439
2573
  }
2440
- function Ut(e) {
2441
- return e.dist * Math.max(Math.sin(-e.pitch * X), jt);
2574
+ function tn(e) {
2575
+ return e.dist * Math.max(Math.sin(-e.pitch * Y), Ut);
2442
2576
  }
2443
- function Wt(e, t, n, r) {
2444
- let [i, a] = [Math.sin(e.yaw * X), Math.cos(e.yaw * X)];
2577
+ function Q(e, t, n, r) {
2578
+ let [i, a] = [Math.sin(e.yaw * Y), Math.cos(e.yaw * Y)];
2445
2579
  return {
2446
2580
  ...e,
2447
2581
  e: e.e + t * a + n * i,
@@ -2449,30 +2583,30 @@ function Wt(e, t, n, r) {
2449
2583
  h: e.h + r
2450
2584
  };
2451
2585
  }
2452
- function Gt(e, t, n) {
2453
- return Wt(e, t, n * e.dist / Ut(e), 0);
2586
+ function nn(e, t, n) {
2587
+ return Q(e, t, n * e.dist / tn(e), 0);
2454
2588
  }
2455
- function Kt(e, t, n) {
2589
+ function rn(e, t, n) {
2456
2590
  return {
2457
2591
  e: e.e + (t.e - e.e) * n,
2458
2592
  n: e.n + (t.n - e.n) * n,
2459
2593
  h: e.h + (t.h - e.h) * n,
2460
- yaw: Nt(e.yaw + Pt(e.yaw, t.yaw) * n),
2594
+ yaw: Gt(e.yaw + Kt(e.yaw, t.yaw) * n),
2461
2595
  pitch: e.pitch + (t.pitch - e.pitch) * n,
2462
2596
  dist: e.dist * (t.dist / e.dist) ** n
2463
2597
  };
2464
2598
  }
2465
- function qt(e, t) {
2599
+ function an(e, t) {
2466
2600
  let n = e.dist * 1e-5;
2467
- 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(Pt(e.yaw, t.yaw)) < .001 && Math.abs(e.pitch - t.pitch) < .001;
2601
+ 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(Kt(e.yaw, t.yaw)) < .001 && Math.abs(e.pitch - t.pitch) < .001;
2468
2602
  }
2469
2603
  //#endregion
2470
2604
  //#region src/controls/controls.ts
2471
- var Jt = .2, Yt = .002, Xt = .005, Zt = .5, Qt = .05;
2472
- function $t(e, t) {
2605
+ var on = .2, sn = .002, cn = .005, ln = .5, un = .05;
2606
+ function dn(e, t) {
2473
2607
  return 2 * e * Math.tan(45 * Math.PI / 360) / Math.max(1, t);
2474
2608
  }
2475
- function en(e) {
2609
+ function fn(e) {
2476
2610
  let t = (t) => +!!e.has(t);
2477
2611
  return [
2478
2612
  t("KeyD") - t("KeyA") + t("ArrowRight") - t("ArrowLeft"),
@@ -2480,10 +2614,10 @@ function en(e) {
2480
2614
  t("KeyE") - t("KeyQ")
2481
2615
  ];
2482
2616
  }
2483
- function tn(e, t, n, r, i = Y) {
2484
- return qt(e, t) ? t : Z(Kt(e, t, 1 - Math.exp(-n / Qt)), r, i);
2617
+ function pn(e, t, n, r, i = J) {
2618
+ return an(e, t) ? t : X(rn(e, t, 1 - Math.exp(-n / un)), r, i);
2485
2619
  }
2486
- var nn = class {
2620
+ var mn = class {
2487
2621
  #e;
2488
2622
  #t;
2489
2623
  #n;
@@ -2500,7 +2634,7 @@ var nn = class {
2500
2634
  #p = /* @__PURE__ */ new Set();
2501
2635
  #m;
2502
2636
  #h = null;
2503
- constructor(e, t, n, r, i = Y) {
2637
+ constructor(e, t, n, r, i = J) {
2504
2638
  this.#e = e, this.#t = t, this.#n = n, this.#r = i, this.#d = this.#E(r), this.#f = this.#d, this.#m = t.onFrame(this.#T);
2505
2639
  let a = this.#i.signal;
2506
2640
  e.addEventListener("pointerdown", this.#g, { signal: a }), e.addEventListener("pointermove", this.#_, { signal: a });
@@ -2521,7 +2655,7 @@ var nn = class {
2521
2655
  return this.#p.add(e), () => this.#p.delete(e);
2522
2656
  }
2523
2657
  moveTo(e, t) {
2524
- let n = this.#d, r = Math.min(n.dist, At.dist);
2658
+ let n = this.#d, r = Math.min(n.dist, Ht.dist);
2525
2659
  this.#d = this.#E({
2526
2660
  ...n,
2527
2661
  e,
@@ -2548,7 +2682,7 @@ var nn = class {
2548
2682
  e.buttons & 6 || t && e.shiftKey ? $(this.#c, r, i) : t && $(this.#s, r, i);
2549
2683
  } else if (n) {
2550
2684
  let e = this.#C();
2551
- $(this.#c, e.x - n.x, e.y - n.y), this.#l += (n.d - e.d) * Xt;
2685
+ $(this.#c, e.x - n.x, e.y - n.y), this.#l += (n.d - e.d) * cn;
2552
2686
  } else $(this.#s, r, i);
2553
2687
  this.#w();
2554
2688
  };
@@ -2556,7 +2690,7 @@ var nn = class {
2556
2690
  this.#a.delete(e.pointerId);
2557
2691
  };
2558
2692
  #y = (e) => {
2559
- e.preventDefault(), this.#l += e.deltaY * Yt, this.#w();
2693
+ e.preventDefault(), this.#l += e.deltaY * sn, this.#w();
2560
2694
  };
2561
2695
  #b = (e) => {
2562
2696
  e.code === "KeyF" && !e.repeat && (this.#u = !this.#u), this.#o.add(e.code), this.#u && this.#w();
@@ -2568,7 +2702,7 @@ var nn = class {
2568
2702
  let t = await this.#t.pick(e.offsetX, e.offsetY);
2569
2703
  if (!t || this.#i.signal.aborted) return;
2570
2704
  let [n, r, i] = t;
2571
- this.#d = Z(Vt(Q(this.#f), {
2705
+ this.#d = X($t(Z(this.#f), {
2572
2706
  e: n,
2573
2707
  n: r,
2574
2708
  h: i
@@ -2591,43 +2725,43 @@ var nn = class {
2591
2725
  this.#h = e;
2592
2726
  let n = this.#d, [r, i] = this.#c;
2593
2727
  if (r || i) {
2594
- let e = $t(n.dist, this.#e.clientHeight);
2595
- n = Gt(n, -r * e, i * e);
2728
+ let e = dn(n.dist, this.#e.clientHeight);
2729
+ n = nn(n, -r * e, i * e);
2596
2730
  }
2597
2731
  let [a, o] = this.#s;
2598
2732
  if (a || o) {
2599
- let [e, t] = [n.yaw + a * Jt, n.pitch - o * Jt];
2600
- n = this.#u ? Ht(n, e, t, this.#r) : Z({
2733
+ let [e, t] = [n.yaw + a * on, n.pitch - o * on];
2734
+ n = this.#u ? en(n, e, t, this.#r) : X({
2601
2735
  ...n,
2602
2736
  yaw: e,
2603
2737
  pitch: t
2604
2738
  }, void 0, this.#r);
2605
2739
  }
2606
- this.#l && (n = Z({
2740
+ this.#l && (n = X({
2607
2741
  ...n,
2608
2742
  dist: n.dist * Math.exp(this.#l)
2609
2743
  }, void 0, this.#r)), this.#c = [0, 0], this.#s = [0, 0], this.#l = 0;
2610
- let [s, c, l] = en(this.#o), u = this.#u && (s !== 0 || l !== 0 || c !== 0);
2744
+ let [s, c, l] = fn(this.#o), u = this.#u && (s !== 0 || l !== 0 || c !== 0);
2611
2745
  if (u) {
2612
- let e = Zt * Ut(n) * t;
2613
- n = Wt(n, s * e, c * e, l * e);
2746
+ let e = ln * tn(n) * t;
2747
+ n = Q(n, s * e, c * e, l * e);
2614
2748
  }
2615
2749
  let d = this.#f;
2616
2750
  if (d !== n) {
2617
- this.#d = n = this.#E(n), this.#f = tn(d, n, t, this.#n, this.#r), this.#D();
2751
+ this.#d = n = this.#E(n), this.#f = pn(d, n, t, this.#n, this.#r), this.#D();
2618
2752
  for (let e of this.#p) e();
2619
2753
  }
2620
2754
  u || this.#f !== this.#d ? this.#w() : this.#h = null;
2621
2755
  };
2622
2756
  #E(e) {
2623
- return Z(e, this.#n, this.#r);
2757
+ return X(e, this.#n, this.#r);
2624
2758
  }
2625
2759
  #D() {
2626
- this.#t.setCamera(zt(this.#f));
2760
+ this.#t.setCamera(Zt(this.#f));
2627
2761
  }
2628
2762
  };
2629
2763
  function $(e, t, n) {
2630
2764
  e[0] += t, e[1] += n;
2631
2765
  }
2632
2766
  //#endregion
2633
- export { oe as S, qt as _, Q as a, st as b, Wt as c, Ht as d, Vt as f, Bt as g, It as h, Kt as i, Lt as l, Gt as m, kt as n, Z as o, Ft as p, Y as r, At as s, nn as t, Ut as u, zt as v, Ve as x, W as y };
2767
+ export { ae as S, an as _, Z as a, gt as b, Q as c, en as d, $t as f, Qt as g, Jt as h, rn as i, Yt as l, nn as m, Vt as n, X as o, qt as p, J as r, Ht as s, mn as t, tn as u, Zt as v, We as x, ht as y };