@yali-engine/render 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bvh.d.ts +66 -0
- package/dist/bvh.js +493 -0
- package/dist/bvh.js.map +1 -0
- package/dist/camera.d.ts +34 -0
- package/dist/camera.js +66 -0
- package/dist/camera.js.map +1 -0
- package/dist/cluster-build.d.ts +46 -0
- package/dist/cluster-build.js +179 -0
- package/dist/cluster-build.js.map +1 -0
- package/dist/cluster-pages.d.ts +70 -0
- package/dist/cluster-pages.js +203 -0
- package/dist/cluster-pages.js.map +1 -0
- package/dist/cluster-stream.d.ts +83 -0
- package/dist/cluster-stream.js +226 -0
- package/dist/cluster-stream.js.map +1 -0
- package/dist/culled-draws.d.ts +30 -0
- package/dist/culled-draws.js +103 -0
- package/dist/culled-draws.js.map +1 -0
- package/dist/debug-lines.d.ts +51 -0
- package/dist/debug-lines.js +158 -0
- package/dist/debug-lines.js.map +1 -0
- package/dist/device-profile.d.ts +100 -0
- package/dist/device-profile.js +131 -0
- package/dist/device-profile.js.map +1 -0
- package/dist/device.d.ts +39 -0
- package/dist/device.js +79 -0
- package/dist/device.js.map +1 -0
- package/dist/environment.d.ts +60 -0
- package/dist/environment.js +204 -0
- package/dist/environment.js.map +1 -0
- package/dist/extract.d.ts +74 -0
- package/dist/extract.js +194 -0
- package/dist/extract.js.map +1 -0
- package/dist/frame-graph.d.ts +112 -0
- package/dist/frame-graph.js +226 -0
- package/dist/frame-graph.js.map +1 -0
- package/dist/gpu-health.d.ts +74 -0
- package/dist/gpu-health.js +106 -0
- package/dist/gpu-health.js.map +1 -0
- package/dist/gpu-timer.d.ts +26 -0
- package/dist/gpu-timer.js +93 -0
- package/dist/gpu-timer.js.map +1 -0
- package/dist/headless.d.ts +28 -0
- package/dist/headless.js +91 -0
- package/dist/headless.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/lights.d.ts +81 -0
- package/dist/lights.js +247 -0
- package/dist/lights.js.map +1 -0
- package/dist/matrix.d.ts +6 -0
- package/dist/matrix.js +59 -0
- package/dist/matrix.js.map +1 -0
- package/dist/meshes.d.ts +411 -0
- package/dist/meshes.js +545 -0
- package/dist/meshes.js.map +1 -0
- package/dist/meshlets-decoder.d.ts +20 -0
- package/dist/meshlets-decoder.js +47 -0
- package/dist/meshlets-decoder.js.map +1 -0
- package/dist/meshlets.d.ts +186 -0
- package/dist/meshlets.js +1040 -0
- package/dist/meshlets.js.map +1 -0
- package/dist/occlusion.d.ts +51 -0
- package/dist/occlusion.js +188 -0
- package/dist/occlusion.js.map +1 -0
- package/dist/pick-decoder.d.ts +19 -0
- package/dist/pick-decoder.js +45 -0
- package/dist/pick-decoder.js.map +1 -0
- package/dist/pick.d.ts +86 -0
- package/dist/pick.js +452 -0
- package/dist/pick.js.map +1 -0
- package/dist/pipeline-cache.d.ts +53 -0
- package/dist/pipeline-cache.js +96 -0
- package/dist/pipeline-cache.js.map +1 -0
- package/dist/post-options.d.ts +109 -0
- package/dist/post-options.js +23 -0
- package/dist/post-options.js.map +1 -0
- package/dist/post-shaders.gen.d.ts +40 -0
- package/dist/post-shaders.gen.js +43 -0
- package/dist/post-shaders.gen.js.map +1 -0
- package/dist/post.d.ts +101 -0
- package/dist/post.js +555 -0
- package/dist/post.js.map +1 -0
- package/dist/render-plugin.d.ts +239 -0
- package/dist/render-plugin.js +633 -0
- package/dist/render-plugin.js.map +1 -0
- package/dist/scene.d.ts +406 -0
- package/dist/scene.js +2005 -0
- package/dist/scene.js.map +1 -0
- package/dist/shaders.gen.d.ts +40 -0
- package/dist/shaders.gen.js +43 -0
- package/dist/shaders.gen.js.map +1 -0
- package/dist/shadows.d.ts +104 -0
- package/dist/shadows.js +227 -0
- package/dist/shadows.js.map +1 -0
- package/dist/staging-ring.d.ts +41 -0
- package/dist/staging-ring.js +125 -0
- package/dist/staging-ring.js.map +1 -0
- package/dist/textures.d.ts +165 -0
- package/dist/textures.js +361 -0
- package/dist/textures.js.map +1 -0
- package/dist/tonemap.d.ts +45 -0
- package/dist/tonemap.js +141 -0
- package/dist/tonemap.js.map +1 -0
- package/dist/viewport.d.ts +78 -0
- package/dist/viewport.js +130 -0
- package/dist/viewport.js.map +1 -0
- package/dist/webgl2/plugin.d.ts +40 -0
- package/dist/webgl2/plugin.js +190 -0
- package/dist/webgl2/plugin.js.map +1 -0
- package/dist/webgl2/program.d.ts +27 -0
- package/dist/webgl2/program.js +74 -0
- package/dist/webgl2/program.js.map +1 -0
- package/dist/webgl2/renderer.d.ts +128 -0
- package/dist/webgl2/renderer.js +976 -0
- package/dist/webgl2/renderer.js.map +1 -0
- package/dist/webgl2/shaders.glsl.gen.d.ts +27 -0
- package/dist/webgl2/shaders.glsl.gen.js +20 -0
- package/dist/webgl2/shaders.glsl.gen.js.map +1 -0
- package/dist/webgl2/textures.d.ts +11 -0
- package/dist/webgl2/textures.js +82 -0
- package/dist/webgl2/textures.js.map +1 -0
- package/dist/webgl2/webgl2.d.ts +1 -0
- package/dist/webgl2/webgl2.js +4 -0
- package/dist/webgl2/webgl2.js.map +1 -0
- package/dist/worker-mode.d.ts +85 -0
- package/dist/worker-mode.js +204 -0
- package/dist/worker-mode.js.map +1 -0
- package/package.json +47 -3
- package/README.md +0 -3
package/dist/pick.js
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { registerTransforms, YaliError } from '@yali-engine/core';
|
|
2
|
+
import { boxParents, buildBoxBvh, buildBvh, intersectAll, intersectBvh, refitBoxBvh, refitBoxes, refitBvh, walkBoxes } from "./bvh.js";
|
|
3
|
+
import { invert4 } from "./matrix.js";
|
|
4
|
+
import { bvhRequest } from "./pick-decoder.js";
|
|
5
|
+
/** Floats per stored vertex (position, normal, uv). */
|
|
6
|
+
const VERTEX_FLOATS = 8;
|
|
7
|
+
/** Meshes with fewer triangles are tested one by one (a tree saves nothing there). */
|
|
8
|
+
const BVH_MIN_TRIANGLES = 64;
|
|
9
|
+
/** Texels (vec4) per palette joint: the 3×4 matrix's rows. */
|
|
10
|
+
const PALETTE_TEXELS = 3;
|
|
11
|
+
/** Instances from which the broad phase walks a tree over them (ADR-0123). */
|
|
12
|
+
const TOP_MIN_INSTANCES = 32;
|
|
13
|
+
/** Refits of the top-level tree before it is rebuilt (moved boxes loosen it). */
|
|
14
|
+
const TOP_REFITS = 64;
|
|
15
|
+
/**
|
|
16
|
+
* CPU picking over every `render.Mesh` entity (ADR-0094): the ray against each instance's
|
|
17
|
+
* bounding sphere, then, nearest first, against its finest LOD's triangles in mesh space
|
|
18
|
+
* (Möller–Trumbore), skinned meshes posed by the current palette. Synchronous, exact, and
|
|
19
|
+
* the same on every backend (WebGPU, WebGL2, headless): no GPU readback, no id buffer.
|
|
20
|
+
* A mesh of 64+ triangles is walked through its own BVH (ADR-0114), built on its first pick
|
|
21
|
+
* (~2.5 µs per triangle) and kept; a skinned mesh's is refitted to each pick's pose.
|
|
22
|
+
*/
|
|
23
|
+
export class Picker {
|
|
24
|
+
world;
|
|
25
|
+
Mesh;
|
|
26
|
+
store;
|
|
27
|
+
/** The animation palette, for skinned meshes (`render.scene.paletteSource`). */
|
|
28
|
+
palette = () => null;
|
|
29
|
+
#query;
|
|
30
|
+
#candidates = [];
|
|
31
|
+
#inv = new Float64Array(16);
|
|
32
|
+
/** Per mesh id: its triangle hierarchy (rigid, in mesh space), and skinned meshes' (refitted per pick). */
|
|
33
|
+
#bvhs = new Map();
|
|
34
|
+
#skinnedBvhs = new Map();
|
|
35
|
+
/** Walk each mesh's BVH (ADR-0114; default on); off tests every triangle, as before (an A/B). */
|
|
36
|
+
bvh = true;
|
|
37
|
+
/**
|
|
38
|
+
* Trees built and their milliseconds, summed (ADR-0114); built on the pool (ADR-0123); the top-level
|
|
39
|
+
* tree's builds and refits.
|
|
40
|
+
*/
|
|
41
|
+
bvhStats = { built: 0, buildMs: 0, refits: 0, pooled: 0, topBuilds: 0, topRefits: 0 };
|
|
42
|
+
/** Walk a tree over the instances' bounds in the broad phase (ADR-0123; default on); off tests each instance, as before. */
|
|
43
|
+
topLevel = true;
|
|
44
|
+
#pool;
|
|
45
|
+
#poolMin;
|
|
46
|
+
/** Trees building on the pool, by mesh id (picks on those meshes test every triangle meanwhile). */
|
|
47
|
+
#building = new Map();
|
|
48
|
+
/**
|
|
49
|
+
* The chunks whose transforms, and those whose meshes, changed since the last pick (two queries: a query's
|
|
50
|
+
* `changed` needs all of its components), with the instance columns, so only they are gathered again.
|
|
51
|
+
*/
|
|
52
|
+
#movedQuery;
|
|
53
|
+
#remeshedQuery;
|
|
54
|
+
/**
|
|
55
|
+
* The instances as last gathered, a slot per row of every chunk in query order: its entity, mesh, skin,
|
|
56
|
+
* pose, bounding sphere (world, f64; radius −1 for a row with no drawable mesh) and box about `#anchor`.
|
|
57
|
+
*/
|
|
58
|
+
#inst = { count: 0, entity: [], mesh: new Uint32Array(0), skin: new Uint32Array(0), pos: new Float64Array(0), rot: new Float32Array(0), scale: new Float32Array(0), sphere: new Float64Array(0), boxes: new Float64Array(0) };
|
|
59
|
+
/** Each chunk's base (its identity), its first slot, by base; the layout last gathered. */
|
|
60
|
+
#chunkAt = new Map();
|
|
61
|
+
#chunkBases = [];
|
|
62
|
+
#chunkLengths = [];
|
|
63
|
+
/** Slots gathered again this pick (for the partial refit). */
|
|
64
|
+
#touched = new Uint32Array(64);
|
|
65
|
+
#anchor = [0, 0, 0];
|
|
66
|
+
#top = null;
|
|
67
|
+
#topUp = null;
|
|
68
|
+
#topRefits = 0;
|
|
69
|
+
#gathered = false;
|
|
70
|
+
constructor(world, Mesh, store, options = {}) {
|
|
71
|
+
this.world = world;
|
|
72
|
+
this.Mesh = Mesh;
|
|
73
|
+
this.store = store;
|
|
74
|
+
this.#pool = options.pool ?? null;
|
|
75
|
+
this.#poolMin = options.poolMinTriangles ?? 16384;
|
|
76
|
+
const { GlobalTransform } = registerTransforms(world);
|
|
77
|
+
const columns = [
|
|
78
|
+
[Mesh, 'mesh'],
|
|
79
|
+
[Mesh, 'skin'],
|
|
80
|
+
[GlobalTransform, 't'],
|
|
81
|
+
[GlobalTransform, 'r'],
|
|
82
|
+
[GlobalTransform, 's'],
|
|
83
|
+
];
|
|
84
|
+
this.#query = world.query({ with: [Mesh, GlobalTransform], columns });
|
|
85
|
+
this.#movedQuery = world.query({ with: [Mesh, GlobalTransform], changed: [GlobalTransform], columns });
|
|
86
|
+
this.#remeshedQuery = world.query({ with: [Mesh, GlobalTransform], changed: [Mesh], columns });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The ray through canvas point (`x`, `y`) — CSS pixels from the canvas' top left, in a
|
|
90
|
+
* canvas `width` × `height` CSS pixels — from `camera`'s eye: [origin (f64), direction].
|
|
91
|
+
*/
|
|
92
|
+
ray(camera, x, y, width, height) {
|
|
93
|
+
if (!(width > 0 && height > 0))
|
|
94
|
+
throw new YaliError('PICK_INVALID', `A ${width}×${height} canvas.`, 'Pick on a canvas with a size.');
|
|
95
|
+
const ndcX = (x / width) * 2 - 1;
|
|
96
|
+
const ndcY = 1 - (y / height) * 2;
|
|
97
|
+
if (!invert4(camera.uniform, this.#inv))
|
|
98
|
+
throw new YaliError('PICK_INVALID', 'The camera matrix cannot be inverted.', 'Call after the camera has been updated once.');
|
|
99
|
+
// Reverse-Z: depth 1 is the near plane; any depth lies on the same ray from the eye.
|
|
100
|
+
const m = this.#inv;
|
|
101
|
+
const px = m[0] * ndcX + m[4] * ndcY + m[8] + m[12];
|
|
102
|
+
const py = m[1] * ndcX + m[5] * ndcY + m[9] + m[13];
|
|
103
|
+
const pz = m[2] * ndcX + m[6] * ndcY + m[10] + m[14];
|
|
104
|
+
const pw = m[3] * ndcX + m[7] * ndcY + m[11] + m[15];
|
|
105
|
+
const dir = new Float64Array([px / pw, py / pw, pz / pw]);
|
|
106
|
+
const len = Math.hypot(dir[0], dir[1], dir[2]);
|
|
107
|
+
for (let i = 0; i < 3; i++)
|
|
108
|
+
dir[i] /= len;
|
|
109
|
+
return [Float64Array.from(camera.eye), dir];
|
|
110
|
+
}
|
|
111
|
+
/** The nearest `render.Mesh` hit along the ray, or null. `dir` need not be normalized. */
|
|
112
|
+
pick(origin, dir, o = {}) {
|
|
113
|
+
const dl = Math.hypot(dir[0], dir[1], dir[2]);
|
|
114
|
+
if (!(dl > 0))
|
|
115
|
+
throw new YaliError('PICK_INVALID', 'A pick ray with a zero direction.', 'Give a direction with a length.');
|
|
116
|
+
const d = [dir[0] / dl, dir[1] / dl, dir[2] / dl];
|
|
117
|
+
const max = o.maxDistance ?? Number.POSITIVE_INFINITY;
|
|
118
|
+
const cands = this.#candidates;
|
|
119
|
+
cands.length = 0;
|
|
120
|
+
// Broad phase: each instance's bounding sphere (the mesh's, scaled and moved), from the instances
|
|
121
|
+
// as gathered (again only when something changed), through a tree over them when there are many.
|
|
122
|
+
this.#gather();
|
|
123
|
+
const I = this.#inst;
|
|
124
|
+
const test = (i) => {
|
|
125
|
+
const cx = I.sphere[i * 4] - origin[0];
|
|
126
|
+
const cy = I.sphere[i * 4 + 1] - origin[1];
|
|
127
|
+
const cz = I.sphere[i * 4 + 2] - origin[2];
|
|
128
|
+
const rad = I.sphere[i * 4 + 3];
|
|
129
|
+
if (rad < 0)
|
|
130
|
+
return;
|
|
131
|
+
const along = cx * d[0] + cy * d[1] + cz * d[2];
|
|
132
|
+
const off2 = cx * cx + cy * cy + cz * cz - along * along;
|
|
133
|
+
if (off2 > rad * rad || along + rad < 0 || along - rad > max)
|
|
134
|
+
return;
|
|
135
|
+
const entity = I.entity[i];
|
|
136
|
+
if (o.filter && !o.filter(entity))
|
|
137
|
+
return;
|
|
138
|
+
cands.push({ entity, t: Math.max(0, along - Math.sqrt(rad * rad - off2)), mesh: I.mesh[i], skin: I.skin[i], pos: [I.pos[i * 3], I.pos[i * 3 + 1], I.pos[i * 3 + 2]], rot: [I.rot[i * 4], I.rot[i * 4 + 1], I.rot[i * 4 + 2], I.rot[i * 4 + 3]], scale: I.scale[i] || 1 });
|
|
139
|
+
};
|
|
140
|
+
const top = this.#topTree();
|
|
141
|
+
if (top) {
|
|
142
|
+
const a = this.#anchor;
|
|
143
|
+
walkBoxes(top, [origin[0] - a[0], origin[1] - a[1], origin[2] - a[2]], d, max, test);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
for (let i = 0; i < I.count; i++)
|
|
147
|
+
test(i);
|
|
148
|
+
}
|
|
149
|
+
if (cands.length === 0)
|
|
150
|
+
return null;
|
|
151
|
+
cands.sort((a, b) => a.t - b.t);
|
|
152
|
+
// Narrow phase, nearest sphere first: stop once the next sphere starts beyond the best hit.
|
|
153
|
+
let best = null;
|
|
154
|
+
let bestT = max;
|
|
155
|
+
const pal = cands.some((c) => c.skin > 0) ? this.palette() : null;
|
|
156
|
+
for (const c of cands) {
|
|
157
|
+
if (c.t > bestT)
|
|
158
|
+
break;
|
|
159
|
+
const g = this.store.geometry(c.mesh);
|
|
160
|
+
if (!g)
|
|
161
|
+
continue;
|
|
162
|
+
// The ray in mesh space: subtract, rotate back, scale down (positions are mesh units).
|
|
163
|
+
const inv = [-c.rot[0], -c.rot[1], -c.rot[2], c.rot[3]];
|
|
164
|
+
const lo = rotate(inv, [origin[0] - c.pos[0], origin[1] - c.pos[1], origin[2] - c.pos[2]]).map((v) => v / c.scale);
|
|
165
|
+
const ld = rotate(inv, d).map((v) => v / c.scale);
|
|
166
|
+
const verts = c.skin > 0 && g.skin && pal ? skinned(g.vertices, g.skin, pal, c.skin) : null;
|
|
167
|
+
const hit = this.#intersect(c.mesh, g.vertices, verts, g.indices, lo, ld, bestT);
|
|
168
|
+
if (hit && hit.t < bestT) {
|
|
169
|
+
bestT = hit.t;
|
|
170
|
+
const nw = rotate(c.rot, hit.normal);
|
|
171
|
+
const nl = Math.hypot(nw[0], nw[1], nw[2]) || 1;
|
|
172
|
+
const facing = nw[0] * d[0] + nw[1] * d[1] + nw[2] * d[2] > 0 ? -1 : 1;
|
|
173
|
+
best = {
|
|
174
|
+
entity: c.entity,
|
|
175
|
+
distance: hit.t,
|
|
176
|
+
point: [origin[0] + d[0] * hit.t, origin[1] + d[1] * hit.t, origin[2] + d[2] * hit.t],
|
|
177
|
+
normal: [(facing * nw[0]) / nl, (facing * nw[1]) / nl, (facing * nw[2]) / nl],
|
|
178
|
+
mesh: c.mesh,
|
|
179
|
+
triangle: hit.triangle,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return best;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Gathers every instance's pose, bounding sphere and box: all of them at the first pick and whenever the
|
|
187
|
+
* chunks' layout changed (an instance came or went), else only the chunks whose transforms or meshes
|
|
188
|
+
* changed, whose slots then refit the tree over the instances (ADR-0123).
|
|
189
|
+
*/
|
|
190
|
+
#gather() {
|
|
191
|
+
const q = this.#query;
|
|
192
|
+
const n = q.run();
|
|
193
|
+
let count = 0;
|
|
194
|
+
let same = this.#gathered && n === this.#chunkBases.length;
|
|
195
|
+
for (let k = 0; k < n; k++) {
|
|
196
|
+
const c = q.chunk(k);
|
|
197
|
+
count += c.length;
|
|
198
|
+
if (same && (c.base !== this.#chunkBases[k] || c.length !== this.#chunkLengths[k]))
|
|
199
|
+
same = false;
|
|
200
|
+
}
|
|
201
|
+
let I = this.#inst;
|
|
202
|
+
if (I.mesh.length < count) {
|
|
203
|
+
const cap = Math.max(count, I.mesh.length * 2);
|
|
204
|
+
I = this.#inst = { count: 0, entity: [], mesh: new Uint32Array(cap), skin: new Uint32Array(cap), pos: new Float64Array(cap * 3), rot: new Float32Array(cap * 4), scale: new Float32Array(cap), sphere: new Float64Array(cap * 4), boxes: new Float64Array(cap * 6) };
|
|
205
|
+
same = false;
|
|
206
|
+
}
|
|
207
|
+
if (!same) {
|
|
208
|
+
// Everything, and the change flags taken so the next pick sees only what changes after this one.
|
|
209
|
+
this.#movedQuery.run();
|
|
210
|
+
this.#remeshedQuery.run();
|
|
211
|
+
this.#gathered = true;
|
|
212
|
+
this.#chunkAt.clear();
|
|
213
|
+
this.#chunkBases.length = 0;
|
|
214
|
+
this.#chunkLengths.length = 0;
|
|
215
|
+
let at = 0;
|
|
216
|
+
for (let k = 0; k < n; k++) {
|
|
217
|
+
const c = q.chunk(k);
|
|
218
|
+
this.#chunkAt.set(c.base, at);
|
|
219
|
+
this.#chunkBases.push(c.base);
|
|
220
|
+
this.#chunkLengths.push(c.length);
|
|
221
|
+
this.#gatherChunk(c, at);
|
|
222
|
+
at += c.length;
|
|
223
|
+
}
|
|
224
|
+
I.count = at;
|
|
225
|
+
I.entity.length = at;
|
|
226
|
+
this.#top = null;
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
let touched = 0;
|
|
230
|
+
for (const changed of [this.#movedQuery, this.#remeshedQuery]) {
|
|
231
|
+
const m = changed.run();
|
|
232
|
+
for (let k = 0; k < m; k++) {
|
|
233
|
+
const c = changed.chunk(k);
|
|
234
|
+
const at = this.#chunkAt.get(c.base);
|
|
235
|
+
if (at === undefined)
|
|
236
|
+
continue;
|
|
237
|
+
this.#gatherChunk(c, at);
|
|
238
|
+
if (!this.#top)
|
|
239
|
+
continue;
|
|
240
|
+
if (this.#touched.length < touched + c.length) {
|
|
241
|
+
const t = new Uint32Array(Math.max(this.#touched.length * 2, touched + c.length));
|
|
242
|
+
t.set(this.#touched.subarray(0, touched));
|
|
243
|
+
this.#touched = t;
|
|
244
|
+
}
|
|
245
|
+
for (let i = 0; i < c.length; i++) {
|
|
246
|
+
this.#box(at + i);
|
|
247
|
+
this.#touched[touched++] = at + i;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (!this.#top || touched === 0)
|
|
252
|
+
return;
|
|
253
|
+
// Many moved: the whole tree is as cheap; a few: only their leaves and those above them.
|
|
254
|
+
const boxes = I.boxes.subarray(0, I.count * 6);
|
|
255
|
+
if (touched > I.count / 4)
|
|
256
|
+
refitBoxBvh(this.#top, boxes);
|
|
257
|
+
else
|
|
258
|
+
refitBoxes(this.#top, boxes, this.#topUp, this.#touched, touched);
|
|
259
|
+
this.bvhStats.topRefits++;
|
|
260
|
+
if (++this.#topRefits >= TOP_REFITS)
|
|
261
|
+
this.#top = null;
|
|
262
|
+
}
|
|
263
|
+
/** Chunk `c`'s rows into the slots from `at`. */
|
|
264
|
+
#gatherChunk(c, at) {
|
|
265
|
+
const I = this.#inst;
|
|
266
|
+
const mesh = c.u32(0);
|
|
267
|
+
const skin = c.u32(1);
|
|
268
|
+
const t = c.f64(2);
|
|
269
|
+
const r = c.f32(3);
|
|
270
|
+
const s = c.f32(4);
|
|
271
|
+
for (let i = 0; i < c.length; i++, at++) {
|
|
272
|
+
const entry = this.store.entries[mesh[i]];
|
|
273
|
+
I.entity[at] = c.entity(i);
|
|
274
|
+
I.mesh[at] = mesh[i];
|
|
275
|
+
I.skin[at] = skin[i];
|
|
276
|
+
I.pos[at * 3] = t[i * 3];
|
|
277
|
+
I.pos[at * 3 + 1] = t[i * 3 + 1];
|
|
278
|
+
I.pos[at * 3 + 2] = t[i * 3 + 2];
|
|
279
|
+
const qx = r[i * 4], qy = r[i * 4 + 1], qz = r[i * 4 + 2], qw = r[i * 4 + 3];
|
|
280
|
+
I.rot[at * 4] = qx;
|
|
281
|
+
I.rot[at * 4 + 1] = qy;
|
|
282
|
+
I.rot[at * 4 + 2] = qz;
|
|
283
|
+
I.rot[at * 4 + 3] = qw;
|
|
284
|
+
I.scale[at] = s[i];
|
|
285
|
+
if (!entry || entry.lods.length === 0) {
|
|
286
|
+
I.sphere[at * 4] = t[i * 3];
|
|
287
|
+
I.sphere[at * 4 + 1] = t[i * 3 + 1];
|
|
288
|
+
I.sphere[at * 4 + 2] = t[i * 3 + 2];
|
|
289
|
+
I.sphere[at * 4 + 3] = -1;
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const sc = Math.abs(s[i]) || 1;
|
|
293
|
+
// The bounding sphere's centre, rotated inline.
|
|
294
|
+
const ex = entry.center[0] * sc;
|
|
295
|
+
const ey = entry.center[1] * sc;
|
|
296
|
+
const ez = entry.center[2] * sc;
|
|
297
|
+
const tx = 2 * (qy * ez - qz * ey);
|
|
298
|
+
const ty = 2 * (qz * ex - qx * ez);
|
|
299
|
+
const tz = 2 * (qx * ey - qy * ex);
|
|
300
|
+
I.sphere[at * 4] = t[i * 3] + ex + qw * tx + (qy * tz - qz * ty);
|
|
301
|
+
I.sphere[at * 4 + 1] = t[i * 3 + 1] + ey + qw * ty + (qz * tx - qx * tz);
|
|
302
|
+
I.sphere[at * 4 + 2] = t[i * 3 + 2] + ez + qw * tz + (qx * ty - qy * tx);
|
|
303
|
+
I.sphere[at * 4 + 3] = entry.radius * sc;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/** Slot `i`'s box about the anchor (empty, far away, for a row with no drawable mesh). */
|
|
307
|
+
#box(i) {
|
|
308
|
+
const I = this.#inst;
|
|
309
|
+
const a = this.#anchor;
|
|
310
|
+
const rad = I.sphere[i * 4 + 3];
|
|
311
|
+
for (let k = 0; k < 3; k++) {
|
|
312
|
+
const c = I.sphere[i * 4 + k] - a[k];
|
|
313
|
+
I.boxes[i * 6 + k] = rad < 0 ? c : c - rad;
|
|
314
|
+
I.boxes[i * 6 + 3 + k] = rad < 0 ? c : c + rad;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/** The tree over the instances (built when missing, from their boxes), or null when too few or off. */
|
|
318
|
+
#topTree() {
|
|
319
|
+
const I = this.#inst;
|
|
320
|
+
if (!this.topLevel || I.count < TOP_MIN_INSTANCES)
|
|
321
|
+
return null;
|
|
322
|
+
if (!this.#top) {
|
|
323
|
+
this.#anchor = [I.sphere[0], I.sphere[1], I.sphere[2]];
|
|
324
|
+
for (let i = 0; i < I.count; i++)
|
|
325
|
+
this.#box(i);
|
|
326
|
+
this.#top = buildBoxBvh(I.boxes.subarray(0, I.count * 6));
|
|
327
|
+
this.#topUp = boxParents(this.#top);
|
|
328
|
+
this.#topRefits = 0;
|
|
329
|
+
this.bvhStats.topBuilds++;
|
|
330
|
+
}
|
|
331
|
+
return this.#top;
|
|
332
|
+
}
|
|
333
|
+
/** The mesh-space ray against mesh `mesh` (posed positions when given): through its BVH, or every triangle. */
|
|
334
|
+
#intersect(mesh, vertices, posed, indices, o, d, max) {
|
|
335
|
+
const P = posed ?? vertices;
|
|
336
|
+
const stride = posed ? 3 : VERTEX_FLOATS;
|
|
337
|
+
if (!this.bvh || indices.length / 3 < BVH_MIN_TRIANGLES)
|
|
338
|
+
return intersectAll(P, stride, indices, o, d, max);
|
|
339
|
+
const trees = posed ? this.#skinnedBvhs : this.#bvhs;
|
|
340
|
+
let tree = trees.get(mesh);
|
|
341
|
+
// A big rigid mesh builds on the pool (ADR-0123); until its tree arrives, every triangle.
|
|
342
|
+
if (!tree && !posed && this.#pool && indices.length / 3 >= this.#poolMin) {
|
|
343
|
+
void this.prepare(mesh);
|
|
344
|
+
return intersectAll(P, stride, indices, o, d, max);
|
|
345
|
+
}
|
|
346
|
+
if (!tree) {
|
|
347
|
+
const t0 = performance.now();
|
|
348
|
+
tree = buildBvh(P, stride, indices);
|
|
349
|
+
trees.set(mesh, tree);
|
|
350
|
+
this.bvhStats.built++;
|
|
351
|
+
this.bvhStats.buildMs += performance.now() - t0;
|
|
352
|
+
}
|
|
353
|
+
else if (posed) {
|
|
354
|
+
refitBvh(tree, P, stride, indices);
|
|
355
|
+
this.bvhStats.refits++;
|
|
356
|
+
}
|
|
357
|
+
return intersectBvh(tree, P, stride, indices, o, d, max);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Builds mesh `mesh`'s BVH ahead of its first pick: for a big mesh, call it during loading so no pick
|
|
361
|
+
* pays for it. With a pool, a mesh of `poolMinTriangles` or more builds on it (ADR-0123): the promise
|
|
362
|
+
* settles when its tree is in. If the pool fails, it builds here, once warned.
|
|
363
|
+
*/
|
|
364
|
+
prepare(mesh) {
|
|
365
|
+
const g = this.store.geometry(mesh);
|
|
366
|
+
if (!g || this.#bvhs.has(mesh) || g.indices.length / 3 < BVH_MIN_TRIANGLES)
|
|
367
|
+
return Promise.resolve();
|
|
368
|
+
const pending = this.#building.get(mesh);
|
|
369
|
+
if (pending)
|
|
370
|
+
return pending;
|
|
371
|
+
const t0 = performance.now();
|
|
372
|
+
const here = () => {
|
|
373
|
+
this.#bvhs.set(mesh, buildBvh(g.vertices, VERTEX_FLOATS, g.indices));
|
|
374
|
+
this.bvhStats.built++;
|
|
375
|
+
this.bvhStats.buildMs += performance.now() - t0;
|
|
376
|
+
};
|
|
377
|
+
if (!this.#pool || g.indices.length / 3 < this.#poolMin) {
|
|
378
|
+
here();
|
|
379
|
+
return Promise.resolve();
|
|
380
|
+
}
|
|
381
|
+
const job = this.#pool
|
|
382
|
+
.decode('pick-bvh', bvhRequest(g.vertices, VERTEX_FLOATS, g.indices))
|
|
383
|
+
.then((tree) => {
|
|
384
|
+
this.#bvhs.set(mesh, tree);
|
|
385
|
+
this.bvhStats.built++;
|
|
386
|
+
this.bvhStats.pooled++;
|
|
387
|
+
this.bvhStats.buildMs += performance.now() - t0;
|
|
388
|
+
})
|
|
389
|
+
.catch((err) => {
|
|
390
|
+
if (!this.#warned) {
|
|
391
|
+
this.#warned = true;
|
|
392
|
+
console.warn(`[yali] picking: building a mesh's tree on the main thread; the decode pool failed (${err instanceof Error ? err.message : String(err)}). Register decodePickBvh from @yali-engine/render/pick-decoder as 'pick-bvh' in the decode worker.`);
|
|
393
|
+
}
|
|
394
|
+
here();
|
|
395
|
+
})
|
|
396
|
+
.finally(() => this.#building.delete(mesh));
|
|
397
|
+
this.#building.set(mesh, job);
|
|
398
|
+
return job;
|
|
399
|
+
}
|
|
400
|
+
#warned = false;
|
|
401
|
+
/** Trees still building on the pool. */
|
|
402
|
+
get pending() {
|
|
403
|
+
return this.#building.size;
|
|
404
|
+
}
|
|
405
|
+
/** Settles when every tree building on the pool is in. */
|
|
406
|
+
async ready() {
|
|
407
|
+
await Promise.all([...this.#building.values()]);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/** `v` rotated by unit quaternion `q` (x, y, z, w). */
|
|
411
|
+
function rotate(q, v) {
|
|
412
|
+
const [x, y, z, w] = q;
|
|
413
|
+
const tx = 2 * (y * v[2] - z * v[1]);
|
|
414
|
+
const ty = 2 * (z * v[0] - x * v[2]);
|
|
415
|
+
const tz = 2 * (x * v[1] - y * v[0]);
|
|
416
|
+
return [v[0] + w * tx + (y * tz - z * ty), v[1] + w * ty + (z * tx - x * tz), v[2] + w * tz + (x * ty - y * tx)];
|
|
417
|
+
}
|
|
418
|
+
/** Positions posed by the palette (linear blend skinning, as `shaders/scene/skin.wesl`), 3 floats per vertex. */
|
|
419
|
+
function skinned(vertices, skin, pal, row) {
|
|
420
|
+
const count = vertices.length / VERTEX_FLOATS;
|
|
421
|
+
const out = new Float32Array(count * 3);
|
|
422
|
+
const p = pal.f32;
|
|
423
|
+
for (let v = 0; v < count; v++) {
|
|
424
|
+
const x = vertices[v * VERTEX_FLOATS];
|
|
425
|
+
const y = vertices[v * VERTEX_FLOATS + 1];
|
|
426
|
+
const z = vertices[v * VERTEX_FLOATS + 2];
|
|
427
|
+
let wsum = 0;
|
|
428
|
+
let ox = 0;
|
|
429
|
+
let oy = 0;
|
|
430
|
+
let oz = 0;
|
|
431
|
+
for (let j = 0; j < 4; j++) {
|
|
432
|
+
const w = skin[v * 8 + 4 + j] / 65535;
|
|
433
|
+
if (w === 0)
|
|
434
|
+
continue;
|
|
435
|
+
wsum += w;
|
|
436
|
+
const at = pal.at + (row - 1 + skin[v * 8 + j]) * PALETTE_TEXELS * 4;
|
|
437
|
+
ox += w * (p[at] * x + p[at + 1] * y + p[at + 2] * z + p[at + 3]);
|
|
438
|
+
oy += w * (p[at + 4] * x + p[at + 5] * y + p[at + 6] * z + p[at + 7]);
|
|
439
|
+
oz += w * (p[at + 8] * x + p[at + 9] * y + p[at + 10] * z + p[at + 11]);
|
|
440
|
+
}
|
|
441
|
+
if (wsum <= 0) {
|
|
442
|
+
ox = x;
|
|
443
|
+
oy = y;
|
|
444
|
+
oz = z;
|
|
445
|
+
}
|
|
446
|
+
out[v * 3] = ox;
|
|
447
|
+
out[v * 3 + 1] = oy;
|
|
448
|
+
out[v * 3 + 2] = oz;
|
|
449
|
+
}
|
|
450
|
+
return out;
|
|
451
|
+
}
|
|
452
|
+
//# sourceMappingURL=pick.js.map
|
package/dist/pick.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pick.js","sourceRoot":"","sources":["../src/pick.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** A linked shader from `shaders.gen.ts`: its WGSL and the build-time content hash. */
|
|
2
|
+
export interface LinkedShader {
|
|
3
|
+
readonly hash: string;
|
|
4
|
+
readonly wgsl: string;
|
|
5
|
+
}
|
|
6
|
+
/** Counters, for the inspector, MCP and tests. */
|
|
7
|
+
export interface PipelineCacheStats {
|
|
8
|
+
modules: number;
|
|
9
|
+
pipelines: number;
|
|
10
|
+
/** Requests answered from the cache (including in-flight compiles). */
|
|
11
|
+
hits: number;
|
|
12
|
+
misses: number;
|
|
13
|
+
}
|
|
14
|
+
/** A descriptor with the shader replaced by its linked source; the cache owns modules. */
|
|
15
|
+
export type CachedRenderDesc = Omit<GPURenderPipelineDescriptor, 'vertex' | 'fragment' | 'layout'> & {
|
|
16
|
+
vertex: Omit<GPUVertexState, 'module'> & {
|
|
17
|
+
shader: LinkedShader;
|
|
18
|
+
};
|
|
19
|
+
fragment?: Omit<GPUFragmentState, 'module'> & {
|
|
20
|
+
shader: LinkedShader;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
/** Compute counterpart of `CachedRenderDesc`. */
|
|
24
|
+
export type CachedComputeDesc = Omit<GPUComputePipelineDescriptor, 'compute' | 'layout'> & {
|
|
25
|
+
compute: Omit<GPUProgrammableStage, 'module'> & {
|
|
26
|
+
shader: LinkedShader;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Deduplicates shader modules (by the build-time hash) and pipelines (by everything that
|
|
31
|
+
* defines them), and creates pipelines asynchronously so nothing compiles on a frame
|
|
32
|
+
* (DESIGN.md §13). Concurrent requests for the same pipeline share one compile. One cache
|
|
33
|
+
* per device: after device loss, build a new one.
|
|
34
|
+
*
|
|
35
|
+
* WebGPU has no binary pipeline cache across sessions (DESIGN.md §22); this dedupes within
|
|
36
|
+
* one device's lifetime, and the browser's own cache does the rest.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* const cache = new PipelineCache(device);
|
|
40
|
+
* const draw = await cache.render({ vertex: { shader: instanceDraw, entryPoint: 'vs' }, ... });
|
|
41
|
+
*/
|
|
42
|
+
export declare class PipelineCache {
|
|
43
|
+
#private;
|
|
44
|
+
readonly device: GPUDevice;
|
|
45
|
+
readonly stats: PipelineCacheStats;
|
|
46
|
+
constructor(device: GPUDevice);
|
|
47
|
+
/** The module for a linked shader, compiled once and checked for errors. */
|
|
48
|
+
module(shader: LinkedShader, label?: string): Promise<GPUShaderModule>;
|
|
49
|
+
/** A render pipeline (layout `auto`), created once per distinct descriptor. */
|
|
50
|
+
render(desc: CachedRenderDesc): Promise<GPURenderPipeline>;
|
|
51
|
+
/** A compute pipeline (layout `auto`), created once per distinct descriptor. */
|
|
52
|
+
compute(desc: CachedComputeDesc): Promise<GPUComputePipeline>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { YaliError } from '@yali-engine/core';
|
|
2
|
+
/** Everything except labels and the shader source, in a stable order (DESIGN.md §13). */
|
|
3
|
+
function keyOf(kind, desc) {
|
|
4
|
+
return (kind +
|
|
5
|
+
JSON.stringify(desc, (k, v) => {
|
|
6
|
+
if (k === 'label')
|
|
7
|
+
return undefined;
|
|
8
|
+
if (k === 'shader')
|
|
9
|
+
return v.hash;
|
|
10
|
+
if (v && typeof v === 'object' && !Array.isArray(v)) {
|
|
11
|
+
return Object.fromEntries(Object.keys(v).sort().map((key) => [key, v[key]]));
|
|
12
|
+
}
|
|
13
|
+
return v;
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Deduplicates shader modules (by the build-time hash) and pipelines (by everything that
|
|
18
|
+
* defines them), and creates pipelines asynchronously so nothing compiles on a frame
|
|
19
|
+
* (DESIGN.md §13). Concurrent requests for the same pipeline share one compile. One cache
|
|
20
|
+
* per device: after device loss, build a new one.
|
|
21
|
+
*
|
|
22
|
+
* WebGPU has no binary pipeline cache across sessions (DESIGN.md §22); this dedupes within
|
|
23
|
+
* one device's lifetime, and the browser's own cache does the rest.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const cache = new PipelineCache(device);
|
|
27
|
+
* const draw = await cache.render({ vertex: { shader: instanceDraw, entryPoint: 'vs' }, ... });
|
|
28
|
+
*/
|
|
29
|
+
export class PipelineCache {
|
|
30
|
+
device;
|
|
31
|
+
stats = { modules: 0, pipelines: 0, hits: 0, misses: 0 };
|
|
32
|
+
#modules = new Map();
|
|
33
|
+
#pipelines = new Map();
|
|
34
|
+
constructor(device) {
|
|
35
|
+
this.device = device;
|
|
36
|
+
}
|
|
37
|
+
/** The module for a linked shader, compiled once and checked for errors. */
|
|
38
|
+
module(shader, label = shader.hash) {
|
|
39
|
+
let m = this.#modules.get(shader.hash);
|
|
40
|
+
if (!m) {
|
|
41
|
+
this.stats.modules++;
|
|
42
|
+
m = (async () => {
|
|
43
|
+
const module = this.device.createShaderModule({ label, code: shader.wgsl });
|
|
44
|
+
const info = await module.getCompilationInfo();
|
|
45
|
+
const errors = info.messages.filter((x) => x.type === 'error');
|
|
46
|
+
if (errors.length > 0) {
|
|
47
|
+
throw new YaliError('SHADER_COMPILE', `${label}: ${errors.map((e) => `${e.lineNum}:${e.linePos} ${e.message}`).join('; ')}`, 'Fix the WESL source and rerun tools/shaders-gen.mjs.');
|
|
48
|
+
}
|
|
49
|
+
return module;
|
|
50
|
+
})();
|
|
51
|
+
this.#modules.set(shader.hash, m);
|
|
52
|
+
}
|
|
53
|
+
return m;
|
|
54
|
+
}
|
|
55
|
+
/** A render pipeline (layout `auto`), created once per distinct descriptor. */
|
|
56
|
+
render(desc) {
|
|
57
|
+
const key = keyOf('render', desc);
|
|
58
|
+
return this.#get(key, async () => {
|
|
59
|
+
const { shader: vs, ...vertex } = desc.vertex;
|
|
60
|
+
let fragment;
|
|
61
|
+
if (desc.fragment) {
|
|
62
|
+
const { shader: fs, ...rest } = desc.fragment;
|
|
63
|
+
fragment = { ...rest, module: await this.module(fs, desc.label) };
|
|
64
|
+
}
|
|
65
|
+
const full = {
|
|
66
|
+
...desc,
|
|
67
|
+
layout: 'auto',
|
|
68
|
+
vertex: { ...vertex, module: await this.module(vs, desc.label) },
|
|
69
|
+
fragment,
|
|
70
|
+
};
|
|
71
|
+
return this.device.createRenderPipelineAsync(full);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** A compute pipeline (layout `auto`), created once per distinct descriptor. */
|
|
75
|
+
compute(desc) {
|
|
76
|
+
const key = keyOf('compute', desc);
|
|
77
|
+
return this.#get(key, async () => {
|
|
78
|
+
const { shader, ...compute } = desc.compute;
|
|
79
|
+
return this.device.createComputePipelineAsync({ ...desc, layout: 'auto', compute: { ...compute, module: await this.module(shader, desc.label) } });
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
#get(key, create) {
|
|
83
|
+
const hit = this.#pipelines.get(key);
|
|
84
|
+
if (hit) {
|
|
85
|
+
this.stats.hits++;
|
|
86
|
+
return hit;
|
|
87
|
+
}
|
|
88
|
+
this.stats.misses++;
|
|
89
|
+
this.stats.pipelines++;
|
|
90
|
+
const p = create();
|
|
91
|
+
this.#pipelines.set(key, p);
|
|
92
|
+
p.catch(() => this.#pipelines.delete(key)); // a failed compile can be retried
|
|
93
|
+
return p;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=pipeline-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-cache.js","sourceRoot":"","sources":["../src/pipeline-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AA4B9C,yFAAyF;AACzF,SAAS,KAAK,CAAC,IAAY,EAAE,IAAY;IACvC,OAAO,CACL,IAAI;QACJ,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC5B,IAAI,CAAC,KAAK,OAAO;gBAAE,OAAO,SAAS,CAAC;YACpC,IAAI,CAAC,KAAK,QAAQ;gBAAE,OAAQ,CAAkB,CAAC,IAAI,CAAC;YACpD,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAG,CAA6B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5G,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,aAAa;IACf,MAAM,CAAY;IAClB,KAAK,GAAuB,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACtF,QAAQ,GAAG,IAAI,GAAG,EAAoC,CAAC;IACvD,UAAU,GAAG,IAAI,GAAG,EAA2D,CAAC;IAEhF,YAAY,MAAiB;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,4EAA4E;IAC5E,MAAM,CAAC,MAAoB,EAAE,KAAK,GAAG,MAAM,CAAC,IAAI;QAC9C,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACrB,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;gBACd,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC5E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;gBAC/D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,IAAI,SAAS,CACjB,gBAAgB,EAChB,GAAG,KAAK,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACrF,sDAAsD,CACvD,CAAC;gBACJ,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC,CAAC,EAAE,CAAC;YACL,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,+EAA+E;IAC/E,MAAM,CAAC,IAAsB;QAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE;YAC/B,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;YAC9C,IAAI,QAAsC,CAAC;YAC3C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;gBAC9C,QAAQ,GAAG,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACpE,CAAC;YACD,MAAM,IAAI,GAAgC;gBACxC,GAAG,IAAI;gBACP,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;gBAChE,QAAQ;aACT,CAAC;YACF,OAAO,IAAI,CAAC,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC,CAA+B,CAAC;IACnC,CAAC;IAED,gFAAgF;IAChF,OAAO,CAAC,IAAuB;QAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE;YAC/B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;YAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,0BAA0B,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACrJ,CAAC,CAAgC,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,GAAW,EAAE,MAA6D;QAC7E,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,GAAG,CAAC;QACb,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,kCAAkC;QAC9E,OAAO,CAAC,CAAC;IACX,CAAC;CACF"}
|