@drawcall/lod 0.0.0-stage → 0.1.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.
Files changed (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -2
  3. package/dist/baked/codec.d.ts +10 -0
  4. package/dist/baked/codec.js +291 -0
  5. package/dist/baked/codec.js.map +1 -0
  6. package/dist/baked/index.d.ts +51 -0
  7. package/dist/baked/index.js +183 -0
  8. package/dist/baked/index.js.map +1 -0
  9. package/dist/baked/interior/faces.d.ts +26 -0
  10. package/dist/baked/interior/faces.js +105 -0
  11. package/dist/baked/interior/faces.js.map +1 -0
  12. package/dist/baked/interior/material.d.ts +31 -0
  13. package/dist/baked/interior/material.js +157 -0
  14. package/dist/baked/interior/material.js.map +1 -0
  15. package/dist/baked/interior/rooms.d.ts +22 -0
  16. package/dist/baked/interior/rooms.js +78 -0
  17. package/dist/baked/interior/rooms.js.map +1 -0
  18. package/dist/baked/low.d.ts +20 -0
  19. package/dist/baked/low.js +75 -0
  20. package/dist/baked/low.js.map +1 -0
  21. package/dist/baked/raster.d.ts +20 -0
  22. package/dist/baked/raster.js +71 -0
  23. package/dist/baked/raster.js.map +1 -0
  24. package/dist/baked/transfer.d.ts +36 -0
  25. package/dist/baked/transfer.js +243 -0
  26. package/dist/baked/transfer.js.map +1 -0
  27. package/dist/baked/unwrap.d.ts +9 -0
  28. package/dist/baked/unwrap.js +167 -0
  29. package/dist/baked/unwrap.js.map +1 -0
  30. package/dist/baked/xatlas.d.ts +2 -0
  31. package/dist/baked/xatlas.js +31 -0
  32. package/dist/baked/xatlas.js.map +1 -0
  33. package/dist/bounds.d.ts +33 -0
  34. package/dist/bounds.js +127 -0
  35. package/dist/bounds.js.map +1 -0
  36. package/dist/dispose.d.ts +5 -0
  37. package/dist/dispose.js +28 -0
  38. package/dist/dispose.js.map +1 -0
  39. package/dist/fade.d.ts +44 -0
  40. package/dist/fade.js +78 -0
  41. package/dist/fade.js.map +1 -0
  42. package/dist/impostor/bake/atlas.d.ts +51 -0
  43. package/dist/impostor/bake/atlas.js +190 -0
  44. package/dist/impostor/bake/atlas.js.map +1 -0
  45. package/dist/impostor/bake/index.d.ts +50 -0
  46. package/dist/impostor/bake/index.js +221 -0
  47. package/dist/impostor/bake/index.js.map +1 -0
  48. package/dist/impostor/bake/materials.d.ts +29 -0
  49. package/dist/impostor/bake/materials.js +156 -0
  50. package/dist/impostor/bake/materials.js.map +1 -0
  51. package/dist/impostor/bake/source.d.ts +3 -0
  52. package/dist/impostor/bake/source.js +23 -0
  53. package/dist/impostor/bake/source.js.map +1 -0
  54. package/dist/impostor/cache.d.ts +15 -0
  55. package/dist/impostor/cache.js +44 -0
  56. package/dist/impostor/cache.js.map +1 -0
  57. package/dist/impostor/codec.d.ts +14 -0
  58. package/dist/impostor/codec.js +137 -0
  59. package/dist/impostor/codec.js.map +1 -0
  60. package/dist/impostor/impostor.d.ts +67 -0
  61. package/dist/impostor/impostor.js +79 -0
  62. package/dist/impostor/impostor.js.map +1 -0
  63. package/dist/impostor/mesh/card.d.ts +38 -0
  64. package/dist/impostor/mesh/card.js +79 -0
  65. package/dist/impostor/mesh/card.js.map +1 -0
  66. package/dist/impostor/mesh/index.d.ts +66 -0
  67. package/dist/impostor/mesh/index.js +174 -0
  68. package/dist/impostor/mesh/index.js.map +1 -0
  69. package/dist/impostor/mesh/material.d.ts +63 -0
  70. package/dist/impostor/mesh/material.js +199 -0
  71. package/dist/impostor/mesh/material.js.map +1 -0
  72. package/dist/impostor/mesh/surface.d.ts +63 -0
  73. package/dist/impostor/mesh/surface.js +162 -0
  74. package/dist/impostor/mesh/surface.js.map +1 -0
  75. package/dist/impostor/mesh/textures.d.ts +4 -0
  76. package/dist/impostor/mesh/textures.js +37 -0
  77. package/dist/impostor/mesh/textures.js.map +1 -0
  78. package/dist/impostor/octahedral.d.ts +29 -0
  79. package/dist/impostor/octahedral.js +83 -0
  80. package/dist/impostor/octahedral.js.map +1 -0
  81. package/dist/index.d.ts +15 -0
  82. package/dist/index.js +16 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/instanced/args.d.ts +20 -0
  85. package/dist/instanced/args.js +77 -0
  86. package/dist/instanced/args.js.map +1 -0
  87. package/dist/instanced/bounds.d.ts +50 -0
  88. package/dist/instanced/bounds.js +271 -0
  89. package/dist/instanced/bounds.js.map +1 -0
  90. package/dist/instanced/dirty.d.ts +12 -0
  91. package/dist/instanced/dirty.js +61 -0
  92. package/dist/instanced/dirty.js.map +1 -0
  93. package/dist/instanced/index.d.ts +116 -0
  94. package/dist/instanced/index.js +573 -0
  95. package/dist/instanced/index.js.map +1 -0
  96. package/dist/instanced/meshes.d.ts +14 -0
  97. package/dist/instanced/meshes.js +54 -0
  98. package/dist/instanced/meshes.js.map +1 -0
  99. package/dist/instanced/select.d.ts +84 -0
  100. package/dist/instanced/select.js +264 -0
  101. package/dist/instanced/select.js.map +1 -0
  102. package/dist/lazy.d.ts +64 -0
  103. package/dist/lazy.js +187 -0
  104. package/dist/lazy.js.map +1 -0
  105. package/dist/levels.d.ts +72 -0
  106. package/dist/levels.js +146 -0
  107. package/dist/levels.js.map +1 -0
  108. package/dist/loader/cache.d.ts +15 -0
  109. package/dist/loader/cache.js +37 -0
  110. package/dist/loader/cache.js.map +1 -0
  111. package/dist/loader/dispose.d.ts +3 -0
  112. package/dist/loader/dispose.js +25 -0
  113. package/dist/loader/dispose.js.map +1 -0
  114. package/dist/loader.d.ts +99 -0
  115. package/dist/loader.js +234 -0
  116. package/dist/loader.js.map +1 -0
  117. package/dist/lod.d.ts +78 -0
  118. package/dist/lod.js +211 -0
  119. package/dist/lod.js.map +1 -0
  120. package/dist/material.d.ts +12 -0
  121. package/dist/material.js +52 -0
  122. package/dist/material.js.map +1 -0
  123. package/dist/pause.d.ts +6 -0
  124. package/dist/pause.js +20 -0
  125. package/dist/pause.js.map +1 -0
  126. package/dist/renderer.d.ts +21 -0
  127. package/dist/renderer.js +83 -0
  128. package/dist/renderer.js.map +1 -0
  129. package/dist/simplify.d.ts +24 -0
  130. package/dist/simplify.js +148 -0
  131. package/dist/simplify.js.map +1 -0
  132. package/dist/source/error.d.ts +14 -0
  133. package/dist/source/error.js +94 -0
  134. package/dist/source/error.js.map +1 -0
  135. package/dist/source/frame.d.ts +11 -0
  136. package/dist/source/frame.js +25 -0
  137. package/dist/source/frame.js.map +1 -0
  138. package/dist/source/shading.d.ts +96 -0
  139. package/dist/source/shading.js +224 -0
  140. package/dist/source/shading.js.map +1 -0
  141. package/dist/source/source.d.ts +23 -0
  142. package/dist/source/source.js +50 -0
  143. package/dist/source/source.js.map +1 -0
  144. package/dist/source/surface.d.ts +31 -0
  145. package/dist/source/surface.js +110 -0
  146. package/dist/source/surface.js.map +1 -0
  147. package/dist/source/texels.d.ts +45 -0
  148. package/dist/source/texels.js +191 -0
  149. package/dist/source/texels.js.map +1 -0
  150. package/dist/source/trace.d.ts +42 -0
  151. package/dist/source/trace.js +153 -0
  152. package/dist/source/trace.js.map +1 -0
  153. package/dist/three.d.ts +55 -0
  154. package/dist/three.js +103 -0
  155. package/dist/three.js.map +1 -0
  156. package/dist/tsl.d.ts +45 -0
  157. package/dist/tsl.js +99 -0
  158. package/dist/tsl.js.map +1 -0
  159. package/dist/view.d.ts +30 -0
  160. package/dist/view.js +75 -0
  161. package/dist/view.js.map +1 -0
  162. package/dist/wind/bounds.d.ts +3 -0
  163. package/dist/wind/bounds.js +47 -0
  164. package/dist/wind/bounds.js.map +1 -0
  165. package/dist/wind/hooks.d.ts +5 -0
  166. package/dist/wind/hooks.js +3 -0
  167. package/dist/wind/hooks.js.map +1 -0
  168. package/dist/wind/index.d.ts +57 -0
  169. package/dist/wind/index.js +196 -0
  170. package/dist/wind/index.js.map +1 -0
  171. package/dist/wind/sway.d.ts +29 -0
  172. package/dist/wind/sway.js +71 -0
  173. package/dist/wind/sway.js.map +1 -0
  174. package/package.json +69 -3
  175. package/skills/lod/SKILL.md +137 -0
@@ -0,0 +1,63 @@
1
+ import type { Node, Texture } from "three/webgpu";
2
+ import type { ImpostorLayout } from "../impostor.js";
3
+ import type { Card } from "./card.js";
4
+ /** What the surface of one impostor reads besides its card. */
5
+ export interface SurfaceInputs {
6
+ layout: ImpostorLayout;
7
+ centre: Node<"vec3">;
8
+ radius: Node<"float">;
9
+ halfSize: Node<"float">;
10
+ frames: Node<"float">;
11
+ /** atlas texels per frame side */
12
+ cell: number;
13
+ maps: {
14
+ base: Texture;
15
+ normalDepth: Texture;
16
+ orm: Texture;
17
+ emissive: Texture | null;
18
+ };
19
+ /** coverage below which a pixel is empty */
20
+ cutoff: number;
21
+ /** depth disagreement at which a frame's sample counts half in the blend */
22
+ tolerance: number;
23
+ /** mip bias of every atlas read */
24
+ mipBias: Node<"float">;
25
+ }
26
+ /** How a pass draws the surface. */
27
+ export interface Pass {
28
+ /** depth-parallax refinements per frame; 0 for none */
29
+ parallax: number;
30
+ /** whether the target is multisampled: coverage then goes to alpha-to-coverage */
31
+ multisampled: boolean;
32
+ /** whether to read the maps that only lighting needs */
33
+ lit: boolean;
34
+ }
35
+ export interface Surface {
36
+ /** colour and screen coverage */
37
+ color: Node<"vec4">;
38
+ /** whether the pixel is drawn: covered, and this draw's by its fade */
39
+ drawn: Node<"bool">;
40
+ /** the window depth of the resolved surface */
41
+ depth: Node<"float">;
42
+ /** where shadows are looked up: the surface, stopped short toward the camera by a depth step */
43
+ shadowPosition: Node<"vec3">;
44
+ /** lit passes only */
45
+ lit: {
46
+ /** unit view-space normal to shade with */
47
+ normal: Node<"vec3">;
48
+ /** `normal` × how far the normals it averages agree: see `cosine` */
49
+ spread: Node<"vec3">;
50
+ roughness: Node<"float">;
51
+ metalness: Node<"float">;
52
+ occlusion: Node<"float">;
53
+ emissive: Node<"vec3"> | null;
54
+ } | null;
55
+ }
56
+ export declare function buildSurface(inputs: SurfaceInputs, card: Card, pass: Pass): Surface;
57
+ /**
58
+ * The mean of saturate(dot(n, direction)) over the normals an averaged `normal` stands
59
+ * for, whose length is how far they agree. Fitted to normals spread over the half of the
60
+ * sphere that faces the camera (all a view shows of a surface), within 0.01: exact for
61
+ * light along the mean and at length 1, where it is the clamped cosine.
62
+ */
63
+ export declare function cosine(normal: Node<"vec3">, direction: Node<"vec3">): Node<"float">;
@@ -0,0 +1,162 @@
1
+ import { abs, cameraProjectionMatrix, cameraViewMatrix, ceil, clamp, dFdx, dFdy, dot, exp2, float, floor, fract, fwidth, length, log2, max, min, mix, normalize, screenCoordinate, select, sin, sqrt, step, texture, vec2, vec3, vec4, } from "three/tsl";
2
+ import { dither, keepsPixel } from "../../fade.js";
3
+ import { basisNode, decodeNode } from "../octahedral.js";
4
+ export function buildSurface(inputs, card, pass) {
5
+ const { layout, centre, radius, halfSize, frames, cell, maps, cutoff, tolerance, mipBias } = inputs;
6
+ const ray = normalize(card.ray).toVar();
7
+ // Where the view ray meets frame (col, row)'s plane: uv there, the uv shift per unit of
8
+ // height above the plane, the distance along the ray to the plane and the ray's slope.
9
+ const plane = (frame) => {
10
+ const n = decodeNode(layout, frame.div(frames.sub(1)));
11
+ const { tangent, bitangent } = basisNode(n);
12
+ const along = min(dot(ray, n), -1e-3).toVar();
13
+ const t = dot(centre.sub(card.point), n).div(along).toVar();
14
+ const hit = card.point.add(ray.mul(t)).sub(centre);
15
+ const uv = vec2(dot(hit, tangent), dot(hit, bitangent)).div(halfSize.mul(2)).add(0.5).toVar();
16
+ const slope = vec2(dot(ray, tangent), dot(ray, bitangent)).div(along).div(halfSize.mul(2));
17
+ return { uv, slope, t, along };
18
+ };
19
+ const planes = card.frames.map(plane);
20
+ const first = planes[0];
21
+ if (!first)
22
+ throw new Error("ImpostorMesh: no frames");
23
+ // Atlas texels per screen pixel and the gradients every atlas read uses. They come from
24
+ // the flat (pre-parallax) projection: parallax makes uv jump at depth edges, and the
25
+ // hardware gradients there would pick a far too coarse mip.
26
+ const dx = dFdx(first.uv);
27
+ const dy = dFdy(first.uv);
28
+ const texels = max(length(dx), length(dy)).mul(cell).toVar();
29
+ const bias = exp2(mipBias).toVar();
30
+ const gradX = dx.div(frames).mul(bias).toVar();
31
+ const gradY = dy.div(frames).mul(bias).toVar();
32
+ // Half a texel of the mip being read, in frame uv: reads stay that far inside their
33
+ // frame so filtering never reaches the neighbouring frame.
34
+ const inset = exp2(ceil(log2(max(texels.mul(bias), 1)))).mul(0.5 / cell).toVar();
35
+ const read = (map, uv) => texture(map, uv).grad(gradX, gradY);
36
+ const atlas = (frame, uv) => frame.add(clamp(uv, inset, inset.oneMinus())).div(frames);
37
+ const inside = (uv) => step(0, uv.x).mul(step(0, uv.y)).mul(step(uv.x, 1)).mul(step(uv.y, 1));
38
+ // Frame-local uv where the view ray meets the baked surface, its normal-depth texel
39
+ // there, and "run", the distance along the ray to it. "trust" falls toward 0 when the
40
+ // depth walk did not settle: the frame's surface there is not on this ray (the frame
41
+ // sees something the view does not), and blending it in would ghost.
42
+ const resolved = card.frames.map((frame, i) => {
43
+ const p = planes[i];
44
+ if (!p)
45
+ throw new Error("ImpostorMesh: no plane for a frame");
46
+ let uv = p.uv;
47
+ let texel = read(maps.normalDepth, atlas(frame, uv)).toVar();
48
+ let depth = texel.a;
49
+ let trust = float(1);
50
+ if (pass.parallax > 0) {
51
+ let previous = depth;
52
+ for (let k = 0; k < pass.parallax; k++) {
53
+ previous = depth;
54
+ uv = p.uv.add(p.slope.mul(depth.sub(0.5).mul(radius.mul(2)))).toVar();
55
+ texel = read(maps.normalDepth, atlas(frame, uv)).toVar();
56
+ depth = texel.a;
57
+ }
58
+ const miss = abs(depth.sub(previous)).div(tolerance);
59
+ trust = float(1).div(miss.mul(miss).add(1));
60
+ }
61
+ // Height above the frame plane, walked back along the ray.
62
+ const run = p.t.add(depth.sub(0.5).mul(radius.mul(2)).div(p.along));
63
+ return { at: atlas(frame, uv).toVar(), texel, trust, run, inside: inside(uv) };
64
+ });
65
+ const [r0, r1, r2] = resolved;
66
+ if (!r0 || !r1 || !r2)
67
+ throw new Error("ImpostorMesh: three frames expected");
68
+ // Every layer is weighted by barycentric weight × trust × that frame's coverage, so a
69
+ // frame that does not cover this pixel cannot bleed its colour, normal or depth into it.
70
+ const c0 = read(maps.base, r0.at).toVar();
71
+ const c1 = read(maps.base, r1.at).toVar();
72
+ const c2 = read(maps.base, r2.at).toVar();
73
+ const trusted = card.weights.mul(vec3(r0.trust, r1.trust, r2.trust));
74
+ const covered = trusted.mul(vec3(r0.inside, r1.inside, r2.inside)).mul(vec3(c0.a, c1.a, c2.a)).div(max(trusted.x.add(trusted.y).add(trusted.z), 1e-4));
75
+ const cover = covered.x.add(covered.y).add(covered.z).toVar();
76
+ const w = covered.div(max(cover, 1e-4)).toVar();
77
+ const blend = (a, b, c) => a.mul(w.x).add(b.mul(w.y)).add(c.mul(w.z));
78
+ const rgb = blend(c0, c1, c2).rgb;
79
+ // The resolved surface's distance along the ray, for depth and shadows.
80
+ const s = dot(vec3(r0.run, r1.run, r2.run), w).div(length(card.ray)).toVar();
81
+ const clip = cameraProjectionMatrix.mul(cameraViewMatrix).mul(vec4(card.worldPoint.add(card.worldRay.mul(s)), 1));
82
+ // Baked coverage to screen coverage. Magnified (a texel spans pixels), the edge is
83
+ // sharpened around the cutoff, centred on it. Minified, a texel already holds a pixel's
84
+ // worth of supersampled coverage, so it is kept and dithered: both alpha-to-coverage and
85
+ // a plain cutoff round fractional coverage away, erasing branches, wires and sparse
86
+ // foliage in the distance.
87
+ const minified = clamp(texels.sub(1), 0, 1);
88
+ const grain = dither(screenCoordinate.xy.add(17));
89
+ let alpha;
90
+ let covers;
91
+ if (pass.multisampled) {
92
+ const sharp = clamp(cover.sub(cutoff).div(max(fwidth(cover), 1e-4)).add(0.5), 0, 1);
93
+ // Dither by one sample step (4x MSAA), faded out toward 0 and 1 so empty stays empty
94
+ // and solid stays solid. Hardware alpha-to-coverage rounds to a sample count, some
95
+ // GPUs down, some to nearest; offsetting the noise by a quarter step keeps either
96
+ // within 1/8 sample, where centred noise loses coverage.
97
+ const dithered = clamp(cover.add(grain.sub(0.25).mul(0.25).mul(min(min(cover, cover.oneMinus()).mul(4), 1))), 0, 1);
98
+ alpha = mix(sharp, dithered, minified).toVar();
99
+ covers = alpha.greaterThan(0);
100
+ }
101
+ else {
102
+ alpha = float(1);
103
+ covers = cover.greaterThanEqual(mix(float(cutoff), grain, minified));
104
+ }
105
+ // The lit point stops short of the surface (toward the camera) by about a texel and a
106
+ // depth step: the shadow map holds the impostor as resolved from the light's frames,
107
+ // the receiver is resolved from the camera's, and they disagree by that much.
108
+ const short = s.sub(halfSize.mul(2 / cell).add(radius.mul(2 / 255)).div(length(card.ray)));
109
+ const surface = {
110
+ color: vec4(rgb, alpha),
111
+ drawn: covers.and(keepsPixel()),
112
+ depth: clip.z.div(clip.w),
113
+ shadowPosition: card.worldPoint.add(card.worldRay.mul(short)),
114
+ lit: null,
115
+ };
116
+ if (!pass.lit)
117
+ return surface;
118
+ const normal = (texel) => texel.rgb.mul(2).sub(1);
119
+ const mean = normal(r0.texel).mul(w.x).add(normal(r1.texel).mul(w.y)).add(normal(r2.texel).mul(w.z)).toVar();
120
+ const orm = blend(read(maps.orm, r0.at), read(maps.orm, r1.at), read(maps.orm, r2.at)).toVar();
121
+ const agreement = length(mean);
122
+ // Toksvig: the spread of the averaged normal widens the specular lobe, so distant
123
+ // foliage and bumpy rock stop sparkling.
124
+ const len = clamp(agreement, 1e-3, 1);
125
+ const roughness = sqrt(min(orm.g.mul(orm.g).add(len.oneMinus().div(len)), 1));
126
+ // orm.a is the share of the surface here that shades with the baked normal rather than
127
+ // its opposite (see Impostor): pick one with that probability, as the real surface shows
128
+ // them. The choice is fixed per texel of the mip being read (of the strongest frame), so
129
+ // it sits on the object like leaves do instead of crawling across the screen.
130
+ const strong = select(w.x.greaterThanEqual(max(w.y, w.z)), r0.at, select(w.y.greaterThanEqual(w.z), r1.at, r2.at));
131
+ const level = exp2(ceil(max(log2(max(texels, 1e-4)), 0)));
132
+ const texel = floor(strong.mul(cell).mul(frames).div(level));
133
+ const random = fract(sin(dot(texel, vec2(12.9898, 78.233))).mul(43758.5453));
134
+ const side = select(random.lessThan(orm.a), float(1), float(-1));
135
+ const shading = card.toView(mean).mul(side).toVar();
136
+ const emissive = maps.emissive ? blend(read(maps.emissive, r0.at), read(maps.emissive, r1.at), read(maps.emissive, r2.at)).rgb : null;
137
+ return {
138
+ ...surface,
139
+ lit: {
140
+ normal: shading,
141
+ // Averaged normals come out short where they disagree (within a texel, across mip
142
+ // levels and blended frames, all over foliage); lit by `cosine`.
143
+ spread: shading.mul(clamp(agreement, 0, 1)),
144
+ roughness,
145
+ metalness: orm.b,
146
+ occlusion: orm.r,
147
+ emissive,
148
+ },
149
+ };
150
+ }
151
+ /**
152
+ * The mean of saturate(dot(n, direction)) over the normals an averaged `normal` stands
153
+ * for, whose length is how far they agree. Fitted to normals spread over the half of the
154
+ * sphere that faces the camera (all a view shows of a surface), within 0.01: exact for
155
+ * light along the mean and at length 1, where it is the clamped cosine.
156
+ */
157
+ export function cosine(normal, direction) {
158
+ const along = dot(normal, direction);
159
+ const agree = dot(normal, normal);
160
+ return along.add(sqrt(along.mul(along).add(agree.oneMinus().mul(along.mul(along).div(max(agree, 1e-8)).oneMinus()).div(3)))).mul(0.5);
161
+ }
162
+ //# sourceMappingURL=surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.js","sourceRoot":"","sources":["../../../src/impostor/mesh/surface.ts"],"names":[],"mappings":"AACA,OAAO,EACL,GAAG,EACH,sBAAsB,EACtB,gBAAgB,EAChB,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,GAAG,EACH,GAAG,EACH,GAAG,EACH,SAAS,EACT,gBAAgB,EAChB,MAAM,EACN,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,IAAI,GACL,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAwDzD,MAAM,UAAU,YAAY,CAAC,MAAqB,EAAE,IAAU,EAAE,IAAU;IACxE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACpG,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;IAExC,wFAAwF;IACxF,uFAAuF;IACvF,MAAM,KAAK,GAAG,CAAC,KAAmB,EAAE,EAAE;QACpC,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAkB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7D,MAAM,CAAC,GAAkB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;QAC3E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;QAC9F,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAEvD,wFAAwF;IACxF,qFAAqF;IACrF,4DAA4D;IAC5D,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IAC/C,oFAAoF;IACpF,2DAA2D;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IACjF,MAAM,IAAI,GAAG,CAAC,GAAY,EAAE,EAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,CAAC,KAAmB,EAAE,EAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnH,MAAM,MAAM,GAAG,CAAC,EAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAE5G,oFAAoF;IACpF,sFAAsF;IACtF,qFAAqF;IACrF,qEAAqE;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC5C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC9D,IAAI,EAAE,GAAiB,CAAC,CAAC,EAAE,CAAC;QAC5B,IAAI,KAAK,GAAiB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QAC3E,IAAI,KAAK,GAAkB,KAAK,CAAC,CAAC,CAAC;QACnC,IAAI,KAAK,GAAkB,KAAK,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACtB,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,QAAQ,GAAG,KAAK,CAAC;gBACjB,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;gBACtE,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;gBACzD,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrD,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,2DAA2D;QAC3D,MAAM,GAAG,GAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACnF,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC;IAC9B,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAE9E,sFAAsF;IACtF,yFAAyF;IACzF,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACvJ,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAC9D,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,CAAC,CAAe,EAAE,CAAe,EAAE,CAAe,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChH,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC;IAElC,wEAAwE;IACxE,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAElH,mFAAmF;IACnF,wFAAwF;IACxF,yFAAyF;IACzF,oFAAoF;IACpF,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,IAAI,KAAoB,CAAC;IACzB,IAAI,MAAoB,CAAC;IACzB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpF,qFAAqF;QACrF,mFAAmF;QACnF,kFAAkF;QAClF,yDAAyD;QACzD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpH,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAC/C,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACjB,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,sFAAsF;IACtF,qFAAqF;IACrF,8EAA8E;IAC9E,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3F,MAAM,OAAO,GAAG;QACd,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QAC/B,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACzB,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC7D,GAAG,EAAE,IAAI;KACV,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,GAAG;QAAE,OAAO,OAAO,CAAC;IAE9B,MAAM,MAAM,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAC7G,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAC/F,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,kFAAkF;IAClF,yCAAyC;IACzC,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9E,uFAAuF;IACvF,yFAAyF;IACzF,yFAAyF;IACzF,8EAA8E;IAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnH,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAiB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACtI,OAAO;QACL,GAAG,OAAO;QACV,GAAG,EAAE;YACH,MAAM,EAAE,OAAO;YACf,kFAAkF;YAClF,iEAAiE;YACjE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3C,SAAS;YACT,SAAS,EAAE,GAAG,CAAC,CAAC;YAChB,SAAS,EAAE,GAAG,CAAC,CAAC;YAChB,QAAQ;SACT;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,MAAoB,EAAE,SAAuB;IAClE,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACxI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { DataTexture } from "three/webgpu";
2
+ import type { Impostor } from "../impostor.js";
3
+ export declare function acquireTextures(impostor: Impostor): DataTexture[];
4
+ export declare function releaseTextures(impostor: Impostor): void;
@@ -0,0 +1,37 @@
1
+ import { DataTexture, LinearFilter, LinearMipmapLinearFilter, NoColorSpace, RGBAFormat, SRGBColorSpace, UnsignedByteType } from "three/webgpu";
2
+ /** One set of GPU textures per impostor, shared by every mesh drawing it. */
3
+ const shared = new WeakMap();
4
+ export function acquireTextures(impostor) {
5
+ let entry = shared.get(impostor);
6
+ if (!entry) {
7
+ const textures = impostor.layers.map((levels, i) => {
8
+ const mipmaps = levels.map((data, m) => ({ data, width: impostor.size >> m, height: impostor.size >> m }));
9
+ const [first] = mipmaps;
10
+ if (!first)
11
+ throw new Error("ImpostorMesh: a layer has no mip levels");
12
+ const texture = new DataTexture(first.data, impostor.size, impostor.size, RGBAFormat, UnsignedByteType);
13
+ const map = impostor.maps[i];
14
+ texture.colorSpace = map === "base" || map === "emissive" ? SRGBColorSpace : NoColorSpace;
15
+ // The baked levels; the chain ends at one texel per frame.
16
+ texture.mipmaps = mipmaps;
17
+ texture.generateMipmaps = false;
18
+ texture.minFilter = LinearMipmapLinearFilter;
19
+ texture.magFilter = LinearFilter;
20
+ texture.needsUpdate = true;
21
+ return texture;
22
+ });
23
+ entry = { textures, users: 0 };
24
+ shared.set(impostor, entry);
25
+ }
26
+ entry.users++;
27
+ return entry.textures;
28
+ }
29
+ export function releaseTextures(impostor) {
30
+ const entry = shared.get(impostor);
31
+ if (!entry || --entry.users > 0)
32
+ return;
33
+ for (const texture of entry.textures)
34
+ texture.dispose();
35
+ shared.delete(impostor);
36
+ }
37
+ //# sourceMappingURL=textures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textures.js","sourceRoot":"","sources":["../../../src/impostor/mesh/textures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,wBAAwB,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAG/I,6EAA6E;AAC7E,MAAM,MAAM,GAAG,IAAI,OAAO,EAAwD,CAAC;AAEnF,MAAM,UAAU,eAAe,CAAC,QAAkB;IAChD,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACjD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3G,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;YACxB,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACvE,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;YACxG,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7B,OAAO,CAAC,UAAU,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC;YAC1F,2DAA2D;YAC3D,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;YAC1B,OAAO,CAAC,eAAe,GAAG,KAAK,CAAC;YAChC,OAAO,CAAC,SAAS,GAAG,wBAAwB,CAAC;YAC7C,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC;YACjC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;YAC3B,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,OAAO,KAAK,CAAC,QAAQ,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAkB;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC;QAAE,OAAO;IACxC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IACxD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { Node } from "three/webgpu";
2
+ import type { ImpostorLayout } from "./impostor.js";
3
+ export type Vec3 = [number, number, number];
4
+ /** Grid position in [0, 1]^2 to a unit direction. */
5
+ export declare function octDecode(layout: ImpostorLayout, u: number, v: number): Vec3;
6
+ /**
7
+ * Unit direction to grid position in [0, 1]^2. "hemi" clamps directions below the
8
+ * horizon onto it (straight down has no horizon point and maps to the zenith).
9
+ */
10
+ export declare function octEncode(layout: ImpostorLayout, d: Vec3): [number, number];
11
+ /** The direction frame (col, row) was baked from. */
12
+ export declare function frameDirection(layout: ImpostorLayout, frames: number, col: number, row: number): Vec3;
13
+ /**
14
+ * The image-plane axes of a view looking back along `n` (camera at +n): tangent is
15
+ * screen right, bitangent screen up. Up-aligned except straight above or below.
16
+ */
17
+ export declare function frameBasis(n: Vec3): {
18
+ tangent: Vec3;
19
+ bitangent: Vec3;
20
+ };
21
+ /** `octDecode` in the shaders, for `layout`: grid position to unit direction. */
22
+ export declare function decodeNode(layout: ImpostorLayout, uv: Node<"vec2">): Node<"vec3">;
23
+ /** `octEncode` in the shaders, for `layout`: unit direction to grid position. */
24
+ export declare function encodeNode(layout: ImpostorLayout, d: Node<"vec3">): Node<"vec2">;
25
+ /** `frameBasis` in the shaders: the image-plane axes of a view looking back along `n`. */
26
+ export declare function basisNode(n: Node<"vec3">): {
27
+ tangent: Node<"vec3">;
28
+ bitangent: Node<"vec3">;
29
+ };
@@ -0,0 +1,83 @@
1
+ import { abs, cross, float, max, normalize, select, step, vec2, vec3 } from "three/tsl";
2
+ // The octahedral maps. Frame (col, row) of an N x N atlas sits at grid point
3
+ // (col, row) / (N - 1), so the outer frames lie exactly on the edge of the map:
4
+ // the horizon for "hemi", the nadir seam for "full". The bake and the shader both
5
+ // derive every direction from these two functions; the node versions below mirror them.
6
+ /** Grid position in [0, 1]^2 to a unit direction. */
7
+ export function octDecode(layout, u, v) {
8
+ let [x, z] = layout === "hemi" ? [u - v, u + v - 1] : [u * 2 - 1, v * 2 - 1];
9
+ const y = 1 - Math.abs(x) - Math.abs(z);
10
+ if (layout === "full" && y < 0)
11
+ [x, z] = fold(x, z);
12
+ const length = Math.hypot(x, y, z);
13
+ return [x / length, y / length, z / length];
14
+ }
15
+ /**
16
+ * Unit direction to grid position in [0, 1]^2. "hemi" clamps directions below the
17
+ * horizon onto it (straight down has no horizon point and maps to the zenith).
18
+ */
19
+ export function octEncode(layout, d) {
20
+ const [dx, dy, dz] = d;
21
+ const y = layout === "hemi" ? Math.max(dy, 0) : dy;
22
+ const sum = Math.abs(dx) + Math.abs(y) + Math.abs(dz) || 1;
23
+ let [x, z] = [dx / sum, dz / sum];
24
+ if (layout === "hemi")
25
+ return [(1 + x + z) / 2, (1 + z - x) / 2];
26
+ if (y < 0)
27
+ [x, z] = fold(x, z);
28
+ return [(x + 1) / 2, (z + 1) / 2];
29
+ }
30
+ /** The lower half of the full octahedron, folded over the upper one's diagonal edges. */
31
+ function fold(x, z) {
32
+ return [(1 - Math.abs(z)) * signOf(x), (1 - Math.abs(x)) * signOf(z)];
33
+ }
34
+ function signOf(v) {
35
+ return v >= 0 ? 1 : -1;
36
+ }
37
+ /** The direction frame (col, row) was baked from. */
38
+ export function frameDirection(layout, frames, col, row) {
39
+ return octDecode(layout, col / (frames - 1), row / (frames - 1));
40
+ }
41
+ /**
42
+ * The image-plane axes of a view looking back along `n` (camera at +n): tangent is
43
+ * screen right, bitangent screen up. Up-aligned except straight above or below.
44
+ */
45
+ export function frameBasis(n) {
46
+ // Near the poles: x with n projected out, so the basis stays orthonormal. Else cross((0, 1, 0), n).
47
+ const t = Math.abs(n[1]) > 0.999 ? [1 - n[0] * n[0], -n[0] * n[1], -n[0] * n[2]] : [n[2], 0, -n[0]];
48
+ const length = Math.hypot(...t);
49
+ const tangent = [t[0] / length, t[1] / length, t[2] / length];
50
+ const bitangent = [n[1] * tangent[2] - n[2] * tangent[1], n[2] * tangent[0] - n[0] * tangent[2], n[0] * tangent[1] - n[1] * tangent[0]];
51
+ return { tangent, bitangent };
52
+ }
53
+ /** A node's sign as the maps use it: 1 at zero. */
54
+ const signOfNode = (v) => step(vec2(0, 0), v).mul(2).sub(1);
55
+ /** `octDecode` in the shaders, for `layout`: grid position to unit direction. */
56
+ export function decodeNode(layout, uv) {
57
+ if (layout === "hemi") {
58
+ const x = uv.x.sub(uv.y);
59
+ const z = uv.x.add(uv.y).sub(1);
60
+ return normalize(vec3(x, float(1).sub(abs(x)).sub(abs(z)), z));
61
+ }
62
+ const xz = uv.mul(2).sub(1);
63
+ const y = float(1).sub(abs(xz.x)).sub(abs(xz.y));
64
+ const folded = select(y.lessThan(0), vec2(1).sub(abs(xz.yx)).mul(signOfNode(xz)), xz);
65
+ return normalize(vec3(folded.x, y, folded.y));
66
+ }
67
+ /** `octEncode` in the shaders, for `layout`: unit direction to grid position. */
68
+ export function encodeNode(layout, d) {
69
+ if (layout === "hemi") {
70
+ const up = vec3(d.x, max(d.y, 0), d.z);
71
+ const n = up.div(max(abs(up.x).add(abs(up.y)).add(abs(up.z)), 1e-6));
72
+ return vec2(n.x.add(n.z).add(1), n.z.sub(n.x).add(1)).mul(0.5);
73
+ }
74
+ const n = d.div(abs(d.x).add(abs(d.y)).add(abs(d.z)));
75
+ const folded = select(n.y.lessThan(0), vec2(1).sub(abs(n.zx)).mul(signOfNode(n.xz)), n.xz);
76
+ return folded.mul(0.5).add(0.5);
77
+ }
78
+ /** `frameBasis` in the shaders: the image-plane axes of a view looking back along `n`. */
79
+ export function basisNode(n) {
80
+ const tangent = select(abs(n.y).greaterThan(0.999), normalize(vec3(1, 0, 0).sub(n.mul(n.x))), normalize(vec3(n.z, 0, n.x.negate())));
81
+ return { tangent, bitangent: cross(n, tangent) };
82
+ }
83
+ //# sourceMappingURL=octahedral.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"octahedral.js","sourceRoot":"","sources":["../../src/impostor/octahedral.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export { type LevelRequest, type LodRequest, type LodCacheOptions, LodLoader } from "./loader.js";
2
+ export { setViewportHeight } from "./view.js";
3
+ export { Lod } from "./lod.js";
4
+ export { LazyImpostor, type LazyImpostorOptions } from "./lazy.js";
5
+ export { cachedImpostor, type ImpostorCacheOptions } from "./impostor/cache.js";
6
+ export { Wind, type WindOptions, type SwayOptions } from "./wind/index.js";
7
+ export { InstancedLod } from "./instanced/index.js";
8
+ export { type LodLevel } from "./levels.js";
9
+ export { type SimplifyOptions, simplify } from "./simplify.js";
10
+ export { type BakeMeshOptions, bakeMesh } from "./baked/index.js";
11
+ export { encodeBakedMesh, decodeBakedMesh } from "./baked/codec.js";
12
+ export { type BakeImpostorOptions, bakeImpostor } from "./impostor/bake/index.js";
13
+ export { type ImpostorMeshOptions, ImpostorMesh } from "./impostor/mesh/index.js";
14
+ export { type Impostor, type ImpostorLayout, type ImpostorMap } from "./impostor/impostor.js";
15
+ export { decodeImpostor, decodeImpostorAsync, encodeImpostor } from "./impostor/codec.js";
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ export { LodLoader } from "./loader.js";
2
+ export { setViewportHeight } from "./view.js";
3
+ export { Lod } from "./lod.js";
4
+ export { LazyImpostor } from "./lazy.js";
5
+ export { cachedImpostor } from "./impostor/cache.js";
6
+ export { Wind } from "./wind/index.js";
7
+ export { InstancedLod } from "./instanced/index.js";
8
+ export {} from "./levels.js";
9
+ export { simplify } from "./simplify.js";
10
+ export { bakeMesh } from "./baked/index.js";
11
+ export { encodeBakedMesh, decodeBakedMesh } from "./baked/codec.js";
12
+ export { bakeImpostor } from "./impostor/bake/index.js";
13
+ export { ImpostorMesh } from "./impostor/mesh/index.js";
14
+ export {} from "./impostor/impostor.js";
15
+ export { decodeImpostor, decodeImpostorAsync, encodeImpostor } from "./impostor/codec.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4D,SAAS,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,YAAY,EAA4B,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,cAAc,EAA6B,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,IAAI,EAAsC,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAiB,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAwB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAwB,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAA4B,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAA4B,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAAwD,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { IndirectStorageBufferAttribute } from "three/webgpu";
2
+ /** Bytes per draw, including the unused final word of a non-indexed draw. */
3
+ export declare const ARGS_BYTES = 20;
4
+ export interface ArgsSlice {
5
+ readonly attribute: IndirectStorageBufferAttribute;
6
+ readonly offset: number;
7
+ dispose(): void;
8
+ }
9
+ /**
10
+ * Stable slices of fixed-size pages. Sharing the indirect buffer lets WebGPU batch
11
+ * draw validation; growing a page would replace buffers still used by meshes and kernels.
12
+ */
13
+ export declare class Args {
14
+ private readonly capacity;
15
+ private readonly pages;
16
+ constructor(capacity?: number);
17
+ take(values: Uint32Array): ArgsSlice;
18
+ private release;
19
+ }
20
+ export declare const args: Args;
@@ -0,0 +1,77 @@
1
+ import { IndirectStorageBufferAttribute } from "three/webgpu";
2
+ /** Bytes per draw, including the unused final word of a non-indexed draw. */
3
+ export const ARGS_BYTES = 20;
4
+ const PAGE_DRAWS = 4096;
5
+ // WebGPU's guaranteed maxStorageBufferBindingSize; a page is one storage binding.
6
+ const MAX_BYTES = 128 * 1024 * 1024;
7
+ /**
8
+ * Stable slices of fixed-size pages. Sharing the indirect buffer lets WebGPU batch
9
+ * draw validation; growing a page would replace buffers still used by meshes and kernels.
10
+ */
11
+ export class Args {
12
+ capacity;
13
+ pages = [];
14
+ constructor(capacity = PAGE_DRAWS) {
15
+ this.capacity = capacity;
16
+ if (!Number.isSafeInteger(capacity) || capacity < 1 || capacity * ARGS_BYTES > MAX_BYTES) {
17
+ throw new Error("InstancedLod: invalid indirect argument page capacity");
18
+ }
19
+ }
20
+ take(values) {
21
+ if (values.length % 5 !== 0 || values.byteLength > MAX_BYTES) {
22
+ throw new Error("InstancedLod: indirect arguments exceed a storage binding or contain an incomplete draw");
23
+ }
24
+ const count = Math.max(values.length / 5, 1);
25
+ let page = this.pages.find((page) => page.free.some((range) => range.count >= count));
26
+ if (!page) {
27
+ const capacity = Math.max(this.capacity, count);
28
+ page = { attribute: new IndirectStorageBufferAttribute(new Uint32Array(capacity * 5), 1), free: [{ first: 0, count: capacity }], users: 0 };
29
+ this.pages.push(page);
30
+ }
31
+ const range = page.free.find((range) => range.count >= count);
32
+ if (!range)
33
+ throw new Error("InstancedLod: no space in indirect argument page");
34
+ const first = range.first;
35
+ range.first += count;
36
+ range.count -= count;
37
+ if (range.count === 0)
38
+ page.free.splice(page.free.indexOf(range), 1);
39
+ page.users++;
40
+ // Keep a CPU mirror of the fixed fields, but never upload a live page again:
41
+ // its instance counts belong to the GPU. Handover writes all words of each slice.
42
+ page.attribute.array.set(values, first * 5);
43
+ const owned = page;
44
+ let disposed = false;
45
+ return {
46
+ attribute: page.attribute,
47
+ offset: first * ARGS_BYTES,
48
+ dispose: () => {
49
+ if (disposed)
50
+ return;
51
+ disposed = true;
52
+ this.release(owned, { first, count });
53
+ },
54
+ };
55
+ }
56
+ release(page, range) {
57
+ if (--page.users === 0) {
58
+ this.pages.splice(this.pages.indexOf(page), 1);
59
+ page.attribute.dispose();
60
+ return;
61
+ }
62
+ // Earlier submitted draws finish before a later handover overwrites a reused slice.
63
+ page.free.push(range);
64
+ page.free.sort((a, b) => a.first - b.first);
65
+ const merged = [];
66
+ for (const range of page.free) {
67
+ const previous = merged.at(-1);
68
+ if (previous && previous.first + previous.count === range.first)
69
+ previous.count += range.count;
70
+ else
71
+ merged.push(range);
72
+ }
73
+ page.free = merged;
74
+ }
75
+ }
76
+ export const args = new Args();
77
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/instanced/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { Matrix4, Sphere, Vector3 } from "three/webgpu";
2
+ import { type LodLevel } from "../levels.js";
3
+ export interface BoundsView {
4
+ eye: Vector3;
5
+ scale: number;
6
+ ortho: boolean;
7
+ fades: boolean;
8
+ forced: number | null;
9
+ }
10
+ /** Cached spatial blocks: instance edits refit leaves; moving views visit only blocks. */
11
+ export declare class Bounds {
12
+ private readonly matrices;
13
+ private readonly spheres;
14
+ private readonly source;
15
+ readonly sphere: Sphere;
16
+ /** Radius enclosing every placed level about source.center. */
17
+ private readonly geometry;
18
+ private readonly block;
19
+ private readonly leaves;
20
+ private readonly tree;
21
+ private readonly dirty;
22
+ private readonly radii;
23
+ private readonly errors;
24
+ private readonly unsafe;
25
+ private readonly levelBoxes;
26
+ private token;
27
+ private changed;
28
+ private complete;
29
+ private low;
30
+ private high;
31
+ private padding;
32
+ constructor(matrices: Float32Array, spheres: Float32Array, source: Sphere, sphere: Sphere, draws: number,
33
+ /** Radius enclosing every placed level about source.center. */
34
+ geometry?: {
35
+ readonly radius: number;
36
+ });
37
+ /** Measure changed matrices, retaining the GPU's max-axis radius for LOD selection. */
38
+ measure(start: number, end: number): void;
39
+ pad(padding: number): void;
40
+ /** Refit only edited leaves and their ancestors. No instance scan on view changes. */
41
+ refit(): void;
42
+ private leaf;
43
+ private join;
44
+ /** Level bounds plus a token only when every block has an unchanged solid choice. */
45
+ select(levels: readonly LodLevel[], view: BoundsView, reaches: Sphere[], measured: boolean, root: Matrix4): object | undefined;
46
+ private visit;
47
+ private interval;
48
+ }
49
+ /** Upper bound on the largest singular value, exact for orthogonal matrix axes. */
50
+ export declare function stretch(matrix: Matrix4): number;