@drawcall/lod 0.1.2 → 0.3.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 (358) hide show
  1. package/README.md +13 -70
  2. package/dist/at.d.ts +2 -0
  3. package/dist/at.js +8 -0
  4. package/dist/at.js.map +1 -0
  5. package/dist/bake.d.ts +22 -0
  6. package/dist/bake.js +88 -0
  7. package/dist/bake.js.map +1 -0
  8. package/dist/baked/codec.d.ts +5 -5
  9. package/dist/baked/codec.js +58 -158
  10. package/dist/baked/codec.js.map +1 -1
  11. package/dist/baked/coverage.d.ts +6 -3
  12. package/dist/baked/coverage.js +6 -3
  13. package/dist/baked/coverage.js.map +1 -1
  14. package/dist/baked/fields.d.ts +9 -0
  15. package/dist/baked/fields.js +22 -0
  16. package/dist/baked/fields.js.map +1 -0
  17. package/dist/baked/index.d.ts +16 -6
  18. package/dist/baked/index.js +23 -21
  19. package/dist/baked/index.js.map +1 -1
  20. package/dist/baked/interior/faces.d.ts +4 -3
  21. package/dist/baked/interior/faces.js +13 -10
  22. package/dist/baked/interior/faces.js.map +1 -1
  23. package/dist/baked/interior/material.d.ts +7 -10
  24. package/dist/baked/interior/material.js +29 -36
  25. package/dist/baked/interior/material.js.map +1 -1
  26. package/dist/baked/interior/rooms.js +1 -1
  27. package/dist/baked/interior/rooms.js.map +1 -1
  28. package/dist/baked/low.d.ts +2 -2
  29. package/dist/baked/low.js +9 -8
  30. package/dist/baked/low.js.map +1 -1
  31. package/dist/baked/raster.js +6 -6
  32. package/dist/baked/raster.js.map +1 -1
  33. package/dist/baked/textures.d.ts +17 -0
  34. package/dist/baked/textures.js +95 -0
  35. package/dist/baked/textures.js.map +1 -0
  36. package/dist/baked/transfer.js +19 -18
  37. package/dist/baked/transfer.js.map +1 -1
  38. package/dist/baked/unwrap.js +4 -3
  39. package/dist/baked/unwrap.js.map +1 -1
  40. package/dist/baked/xatlas.js.map +1 -1
  41. package/dist/codec/container.d.ts +8 -0
  42. package/dist/codec/container.js +63 -0
  43. package/dist/codec/container.js.map +1 -0
  44. package/dist/codec/mesh.d.ts +8 -0
  45. package/dist/codec/mesh.js +220 -0
  46. package/dist/codec/mesh.js.map +1 -0
  47. package/dist/dispose.d.ts +11 -4
  48. package/dist/dispose.js +39 -12
  49. package/dist/dispose.js.map +1 -1
  50. package/dist/gpu.d.ts +39 -0
  51. package/dist/gpu.js +41 -0
  52. package/dist/gpu.js.map +1 -0
  53. package/dist/impostor/bake/atlas.d.ts +4 -4
  54. package/dist/impostor/bake/atlas.js +12 -12
  55. package/dist/impostor/bake/atlas.js.map +1 -1
  56. package/dist/impostor/bake/fit.d.ts +8 -0
  57. package/dist/impostor/bake/fit.js +28 -0
  58. package/dist/impostor/bake/fit.js.map +1 -0
  59. package/dist/impostor/bake/index.d.ts +23 -14
  60. package/dist/impostor/bake/index.js +42 -134
  61. package/dist/impostor/bake/index.js.map +1 -1
  62. package/dist/impostor/bake/materials.d.ts +3 -3
  63. package/dist/impostor/bake/materials.js +60 -12
  64. package/dist/impostor/bake/materials.js.map +1 -1
  65. package/dist/impostor/bake/sheet.d.ts +8 -0
  66. package/dist/impostor/bake/sheet.js +90 -0
  67. package/dist/impostor/bake/sheet.js.map +1 -0
  68. package/dist/impostor/bake/source.d.ts +2 -2
  69. package/dist/impostor/bake/source.js +8 -19
  70. package/dist/impostor/bake/source.js.map +1 -1
  71. package/dist/impostor/codec.d.ts +5 -11
  72. package/dist/impostor/codec.js +37 -121
  73. package/dist/impostor/codec.js.map +1 -1
  74. package/dist/impostor/impostor.d.ts +31 -7
  75. package/dist/impostor/impostor.js +21 -6
  76. package/dist/impostor/impostor.js.map +1 -1
  77. package/dist/impostor/ktx2/encode.d.ts +26 -0
  78. package/dist/impostor/ktx2/encode.js +117 -0
  79. package/dist/impostor/ktx2/encode.js.map +1 -0
  80. package/dist/impostor/ktx2/transcode.d.ts +3 -0
  81. package/dist/impostor/ktx2/transcode.js +99 -0
  82. package/dist/impostor/ktx2/transcode.js.map +1 -0
  83. package/dist/impostor/ktx2/uastc.d.ts +7 -0
  84. package/dist/impostor/ktx2/uastc.js +64 -0
  85. package/dist/impostor/ktx2/uastc.js.map +1 -0
  86. package/dist/impostor/ktx2/wasm/encoder.d.ts +4 -0
  87. package/dist/impostor/ktx2/wasm/encoder.js +10 -0
  88. package/dist/impostor/ktx2/wasm/encoder.js.map +1 -0
  89. package/dist/impostor/ktx2/wasm/transcoder.d.ts +3 -0
  90. package/dist/impostor/ktx2/wasm/transcoder.js +9 -0
  91. package/dist/impostor/ktx2/wasm/transcoder.js.map +1 -0
  92. package/dist/impostor/ktx2/worker.d.ts +1 -0
  93. package/dist/impostor/ktx2/worker.js +12 -0
  94. package/dist/impostor/ktx2/worker.js.map +1 -0
  95. package/dist/impostor/mesh/card.d.ts +3 -3
  96. package/dist/impostor/mesh/card.js +11 -8
  97. package/dist/impostor/mesh/card.js.map +1 -1
  98. package/dist/impostor/mesh/index.d.ts +10 -7
  99. package/dist/impostor/mesh/index.js +15 -18
  100. package/dist/impostor/mesh/index.js.map +1 -1
  101. package/dist/impostor/mesh/material.d.ts +24 -13
  102. package/dist/impostor/mesh/material.js +67 -51
  103. package/dist/impostor/mesh/material.js.map +1 -1
  104. package/dist/impostor/mesh/surface.d.ts +20 -16
  105. package/dist/impostor/mesh/surface.js +81 -58
  106. package/dist/impostor/mesh/surface.js.map +1 -1
  107. package/dist/impostor/mesh/textures.d.ts +3 -3
  108. package/dist/impostor/mesh/textures.js +24 -34
  109. package/dist/impostor/mesh/textures.js.map +1 -1
  110. package/dist/impostor/octahedral.d.ts +1 -8
  111. package/dist/impostor/octahedral.js +3 -18
  112. package/dist/impostor/octahedral.js.map +1 -1
  113. package/dist/index.d.ts +16 -10
  114. package/dist/index.js +14 -8
  115. package/dist/index.js.map +1 -1
  116. package/dist/instanced/camera.d.ts +46 -0
  117. package/dist/instanced/camera.js +70 -0
  118. package/dist/instanced/camera.js.map +1 -0
  119. package/dist/instanced/chunk.d.ts +97 -0
  120. package/dist/instanced/chunk.js +156 -0
  121. package/dist/instanced/chunk.js.map +1 -0
  122. package/dist/instanced/chunks.d.ts +60 -0
  123. package/dist/instanced/chunks.js +208 -0
  124. package/dist/instanced/chunks.js.map +1 -0
  125. package/dist/instanced/cull.d.ts +28 -0
  126. package/dist/instanced/cull.js +22 -0
  127. package/dist/instanced/cull.js.map +1 -0
  128. package/dist/instanced/index.d.ts +96 -92
  129. package/dist/instanced/index.js +229 -512
  130. package/dist/instanced/index.js.map +1 -1
  131. package/dist/instanced/key.d.ts +19 -0
  132. package/dist/instanced/key.js +45 -0
  133. package/dist/instanced/key.js.map +1 -0
  134. package/dist/instanced/levels.d.ts +60 -0
  135. package/dist/instanced/levels.js +130 -0
  136. package/dist/instanced/levels.js.map +1 -0
  137. package/dist/instanced/lists.d.ts +70 -0
  138. package/dist/instanced/lists.js +133 -0
  139. package/dist/instanced/lists.js.map +1 -0
  140. package/dist/instanced/measure.d.ts +28 -0
  141. package/dist/instanced/measure.js +203 -0
  142. package/dist/instanced/measure.js.map +1 -0
  143. package/dist/instanced/meshes.d.ts +46 -14
  144. package/dist/instanced/meshes.js +137 -22
  145. package/dist/instanced/meshes.js.map +1 -1
  146. package/dist/instanced/mirror.d.ts +20 -0
  147. package/dist/instanced/mirror.js +37 -0
  148. package/dist/instanced/mirror.js.map +1 -0
  149. package/dist/instanced/pages/buffers.d.ts +37 -0
  150. package/dist/instanced/pages/buffers.js +15 -0
  151. package/dist/instanced/pages/buffers.js.map +1 -0
  152. package/dist/instanced/pages/chunk.d.ts +51 -0
  153. package/dist/instanced/pages/chunk.js +81 -0
  154. package/dist/instanced/pages/chunk.js.map +1 -0
  155. package/dist/instanced/pages/index.d.ts +74 -0
  156. package/dist/instanced/pages/index.js +269 -0
  157. package/dist/instanced/pages/index.js.map +1 -0
  158. package/dist/instanced/pages/passes.d.ts +21 -0
  159. package/dist/instanced/pages/passes.js +52 -0
  160. package/dist/instanced/pages/passes.js.map +1 -0
  161. package/dist/instanced/pages/slots.d.ts +11 -0
  162. package/dist/instanced/pages/slots.js +90 -0
  163. package/dist/instanced/pages/slots.js.map +1 -0
  164. package/dist/instanced/pages/workgroup.d.ts +14 -0
  165. package/dist/instanced/pages/workgroup.js +38 -0
  166. package/dist/instanced/pages/workgroup.js.map +1 -0
  167. package/dist/instanced/raycast.d.ts +15 -0
  168. package/dist/instanced/raycast.js +46 -0
  169. package/dist/instanced/raycast.js.map +1 -0
  170. package/dist/instanced/rows.d.ts +108 -0
  171. package/dist/instanced/rows.js +209 -0
  172. package/dist/instanced/rows.js.map +1 -0
  173. package/dist/instanced/shape.d.ts +25 -0
  174. package/dist/instanced/shape.js +51 -0
  175. package/dist/instanced/shape.js.map +1 -0
  176. package/dist/instanced/sort.d.ts +63 -0
  177. package/dist/instanced/sort.js +162 -0
  178. package/dist/instanced/sort.js.map +1 -0
  179. package/dist/instanced/update.d.ts +30 -0
  180. package/dist/instanced/update.js +207 -0
  181. package/dist/instanced/update.js.map +1 -0
  182. package/dist/levels/bounds.d.ts +21 -0
  183. package/dist/levels/bounds.js +42 -0
  184. package/dist/levels/bounds.js.map +1 -0
  185. package/dist/levels/cameras.d.ts +48 -0
  186. package/dist/levels/cameras.js +122 -0
  187. package/dist/levels/cameras.js.map +1 -0
  188. package/dist/levels/compile/contexts.d.ts +30 -0
  189. package/dist/levels/compile/contexts.js +18 -0
  190. package/dist/levels/compile/contexts.js.map +1 -0
  191. package/dist/levels/compile/index.d.ts +39 -0
  192. package/dist/levels/compile/index.js +185 -0
  193. package/dist/levels/compile/index.js.map +1 -0
  194. package/dist/levels/compile/pipelines.d.ts +26 -0
  195. package/dist/levels/compile/pipelines.js +177 -0
  196. package/dist/levels/compile/pipelines.js.map +1 -0
  197. package/dist/levels/compiles.d.ts +29 -0
  198. package/dist/levels/compiles.js +50 -0
  199. package/dist/levels/compiles.js.map +1 -0
  200. package/dist/levels/draw.d.ts +102 -0
  201. package/dist/levels/draw.js +401 -0
  202. package/dist/levels/draw.js.map +1 -0
  203. package/dist/levels/fade.d.ts +69 -0
  204. package/dist/levels/fade.js +150 -0
  205. package/dist/levels/fade.js.map +1 -0
  206. package/dist/levels/index.d.ts +99 -0
  207. package/dist/levels/index.js +155 -0
  208. package/dist/levels/index.js.map +1 -0
  209. package/dist/levels/item.d.ts +38 -0
  210. package/dist/levels/item.js +97 -0
  211. package/dist/levels/item.js.map +1 -0
  212. package/dist/levels/load.d.ts +31 -0
  213. package/dist/levels/load.js +142 -0
  214. package/dist/levels/load.js.map +1 -0
  215. package/dist/levels/manager.d.ts +159 -0
  216. package/dist/levels/manager.js +339 -0
  217. package/dist/levels/manager.js.map +1 -0
  218. package/dist/{material.js → levels/material.js} +13 -7
  219. package/dist/levels/material.js.map +1 -0
  220. package/dist/levels/renderer.d.ts +29 -0
  221. package/dist/levels/renderer.js +41 -0
  222. package/dist/levels/renderer.js.map +1 -0
  223. package/dist/levels/requests.d.ts +49 -0
  224. package/dist/levels/requests.js +95 -0
  225. package/dist/levels/requests.js.map +1 -0
  226. package/dist/levels/screen.d.ts +14 -0
  227. package/dist/levels/screen.js +21 -0
  228. package/dist/levels/screen.js.map +1 -0
  229. package/dist/levels/wait.d.ts +27 -0
  230. package/dist/levels/wait.js +61 -0
  231. package/dist/levels/wait.js.map +1 -0
  232. package/dist/loader/build.d.ts +10 -0
  233. package/dist/loader/build.js +28 -0
  234. package/dist/loader/build.js.map +1 -0
  235. package/dist/loader/cache.d.ts +12 -15
  236. package/dist/loader/cache.js +64 -33
  237. package/dist/loader/cache.js.map +1 -1
  238. package/dist/loader/context.d.ts +46 -0
  239. package/dist/loader/context.js +91 -0
  240. package/dist/loader/context.js.map +1 -0
  241. package/dist/loader/dependencies.d.ts +32 -0
  242. package/dist/loader/dependencies.js +113 -0
  243. package/dist/loader/dependencies.js.map +1 -0
  244. package/dist/loader/index.d.ts +62 -0
  245. package/dist/loader/index.js +284 -0
  246. package/dist/loader/index.js.map +1 -0
  247. package/dist/loader/level.d.ts +41 -0
  248. package/dist/loader/level.js +140 -0
  249. package/dist/loader/level.js.map +1 -0
  250. package/dist/loader/request.d.ts +87 -0
  251. package/dist/loader/request.js +59 -0
  252. package/dist/loader/request.js.map +1 -0
  253. package/dist/loader/url.d.ts +16 -0
  254. package/dist/loader/url.js +35 -0
  255. package/dist/loader/url.js.map +1 -0
  256. package/dist/lod.d.ts +79 -49
  257. package/dist/lod.js +209 -153
  258. package/dist/lod.js.map +1 -1
  259. package/dist/meshopt.d.ts +6 -0
  260. package/dist/meshopt.js +19 -0
  261. package/dist/meshopt.js.map +1 -0
  262. package/dist/simplify/cards.d.ts +14 -0
  263. package/dist/simplify/cards.js +128 -0
  264. package/dist/simplify/cards.js.map +1 -0
  265. package/dist/{simplify.d.ts → simplify/index.d.ts} +7 -4
  266. package/dist/{simplify.js → simplify/index.js} +42 -22
  267. package/dist/simplify/index.js.map +1 -0
  268. package/dist/{bounds.d.ts → source/detail.d.ts} +4 -13
  269. package/dist/{bounds.js → source/detail.js} +62 -32
  270. package/dist/source/detail.js.map +1 -0
  271. package/dist/source/{error.d.ts → deviation.d.ts} +3 -3
  272. package/dist/source/{error.js → deviation.js} +12 -12
  273. package/dist/source/deviation.js.map +1 -0
  274. package/dist/source/{shading.d.ts → evaluator.d.ts} +10 -10
  275. package/dist/source/{shading.js → evaluator.js} +5 -5
  276. package/dist/source/evaluator.js.map +1 -0
  277. package/dist/source/{trace.d.ts → raycaster.d.ts} +6 -6
  278. package/dist/source/{trace.js → raycaster.js} +8 -8
  279. package/dist/source/raycaster.js.map +1 -0
  280. package/dist/source/{texels.d.ts → sampler.d.ts} +1 -1
  281. package/dist/source/{texels.js → sampler.js} +3 -3
  282. package/dist/source/sampler.js.map +1 -0
  283. package/dist/source/source.d.ts +2 -2
  284. package/dist/source/source.js +2 -2
  285. package/dist/source/source.js.map +1 -1
  286. package/dist/source/surface.js +1 -1
  287. package/dist/source/surface.js.map +1 -1
  288. package/dist/task.d.ts +6 -0
  289. package/dist/{pause.js → task.js} +5 -5
  290. package/dist/task.js.map +1 -0
  291. package/dist/three.d.ts +20 -19
  292. package/dist/three.js +29 -35
  293. package/dist/three.js.map +1 -1
  294. package/dist/tsl.d.ts +10 -14
  295. package/dist/tsl.js +12 -47
  296. package/dist/tsl.js.map +1 -1
  297. package/dist/typegpu.d.ts +37 -0
  298. package/dist/typegpu.js +37 -0
  299. package/dist/typegpu.js.map +1 -0
  300. package/dist/wind/bounds.js +2 -2
  301. package/dist/wind/bounds.js.map +1 -1
  302. package/dist/wind/hooks.d.ts +7 -4
  303. package/dist/wind/hooks.js +5 -2
  304. package/dist/wind/hooks.js.map +1 -1
  305. package/dist/wind/index.d.ts +4 -4
  306. package/dist/wind/index.js +43 -40
  307. package/dist/wind/index.js.map +1 -1
  308. package/dist/wind/sway.d.ts +4 -1
  309. package/dist/wind/sway.js +4 -1
  310. package/dist/wind/sway.js.map +1 -1
  311. package/package.json +24 -8
  312. package/skills/lod/SKILL.md +147 -108
  313. package/dist/bounds.js.map +0 -1
  314. package/dist/fade.d.ts +0 -44
  315. package/dist/fade.js +0 -78
  316. package/dist/fade.js.map +0 -1
  317. package/dist/impostor/cache.d.ts +0 -15
  318. package/dist/impostor/cache.js +0 -44
  319. package/dist/impostor/cache.js.map +0 -1
  320. package/dist/instanced/args.d.ts +0 -20
  321. package/dist/instanced/args.js +0 -77
  322. package/dist/instanced/args.js.map +0 -1
  323. package/dist/instanced/bounds.d.ts +0 -50
  324. package/dist/instanced/bounds.js +0 -271
  325. package/dist/instanced/bounds.js.map +0 -1
  326. package/dist/instanced/dirty.d.ts +0 -12
  327. package/dist/instanced/dirty.js +0 -61
  328. package/dist/instanced/dirty.js.map +0 -1
  329. package/dist/instanced/select.d.ts +0 -84
  330. package/dist/instanced/select.js +0 -264
  331. package/dist/instanced/select.js.map +0 -1
  332. package/dist/lazy.d.ts +0 -64
  333. package/dist/lazy.js +0 -187
  334. package/dist/lazy.js.map +0 -1
  335. package/dist/levels.d.ts +0 -72
  336. package/dist/levels.js +0 -146
  337. package/dist/levels.js.map +0 -1
  338. package/dist/loader/dispose.d.ts +0 -3
  339. package/dist/loader/dispose.js +0 -25
  340. package/dist/loader/dispose.js.map +0 -1
  341. package/dist/loader.d.ts +0 -99
  342. package/dist/loader.js +0 -234
  343. package/dist/loader.js.map +0 -1
  344. package/dist/material.js.map +0 -1
  345. package/dist/pause.d.ts +0 -6
  346. package/dist/pause.js.map +0 -1
  347. package/dist/renderer.d.ts +0 -21
  348. package/dist/renderer.js +0 -83
  349. package/dist/renderer.js.map +0 -1
  350. package/dist/simplify.js.map +0 -1
  351. package/dist/source/error.js.map +0 -1
  352. package/dist/source/shading.js.map +0 -1
  353. package/dist/source/texels.js.map +0 -1
  354. package/dist/source/trace.js.map +0 -1
  355. package/dist/view.d.ts +0 -30
  356. package/dist/view.js +0 -75
  357. package/dist/view.js.map +0 -1
  358. /package/dist/{material.d.ts → levels/material.d.ts} +0 -0
@@ -0,0 +1,62 @@
1
+ import { Loader, LoadingManager } from "three/webgpu";
2
+ import { type LodLevel } from "../levels/index.js";
3
+ import type { LodCacheOptions } from "./cache.js";
4
+ import { type LodRequest } from "./request.js";
5
+ /**
6
+ * Loads asset URLs through manager handlers, else with a GLTFLoader of its own, which decodes meshopt only: register
7
+ * a GLTFLoader configured with Draco or KTX2 decoders for models compressed with them, and a GLTSLoader for .glts
8
+ * sources.
9
+ *
10
+ * Impostor and interior bakes draw with a renderer of the loader's own, made at its first bake: `dispose` frees it.
11
+ */
12
+ export declare class LodLoader extends Loader<LodLevel[], LodRequest> {
13
+ private readonly cacheOptions?;
14
+ private gltf;
15
+ /**
16
+ * The renderer this loader bakes with, made at its first bake. Its own, not the app's: a canvas the size of a bake
17
+ * frame would draw that frame over the whole target (see `bakeImpostor`).
18
+ */
19
+ private renderer;
20
+ /** URLs whose builds this loader serves without saving, once it has warned why. */
21
+ private readonly uncached;
22
+ constructor(manager?: LoadingManager, cacheOptions?: LodCacheOptions | undefined);
23
+ load(request: LodRequest, onLoad: (levels: LodLevel[]) => void, _onProgress?: (event: ProgressEvent) => void, onError?: (error: unknown) => void): void;
24
+ /**
25
+ * Describes the ladder from the cache, else from its source, which the first level loaded then takes. Empty levels
26
+ * load with it, as does the source when it is the only drawable; other levels load when a camera needs them,
27
+ * including a coarse stand-in while its first detail arrives, and each derived level is cached on its own and built
28
+ * when first loaded. A level whose default threshold is measured from it is built with the ladder, as is every level
29
+ * in a `vite build` warmup.
30
+ *
31
+ * What the levels load is freed when the last Lod holding them is disposed (see `LodLevel.hold`), which spends them:
32
+ * a Lod made from them later throws, so call loadAsync again. Levels no Lod ever holds are never freed: they are
33
+ * yours until a Lod holds them.
34
+ */
35
+ loadAsync(request: LodRequest): Promise<LodLevel[]>;
36
+ /** The source's shape from its entry, else measured from the source and saved. */
37
+ private shape;
38
+ /**
39
+ * A deferred level's bytes from its entry, else built from `spare`, the ladder's source, or from a source of its own:
40
+ * the source level's carries onLevel effects. Disposes `spare` either way.
41
+ */
42
+ private levelBytes;
43
+ /**
44
+ * Build level `index` from `loaded`, and save it to `entry`, read before, when what it was built from can be validated
45
+ * later: what loading the source read, and what this build loads besides.
46
+ */
47
+ private persist;
48
+ /** The renderer this loader bakes with, made at its first bake. */
49
+ private bakeRenderer;
50
+ /**
51
+ * Free the renderer this loader made for its bakes; a bake under way fails. Levels it loaded stay as they are, and a
52
+ * later bake makes a new renderer.
53
+ */
54
+ dispose(): void;
55
+ /** Save `bytes` to `entry`, read before, when what they were built from can be validated later; warn once otherwise. */
56
+ private save;
57
+ /** Builds of `url` are served without saving from now on, after one warning naming why; a build warmup fails instead. */
58
+ private warnUncached;
59
+ /** The ladder's source, with what loading it read. */
60
+ private loadSource;
61
+ private loadAsset;
62
+ }
@@ -0,0 +1,284 @@
1
+ import { Box3, Group, Loader, LoadingManager, Vector3 } from "three/webgpu";
2
+ import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
3
+ import { MissingDependencyError } from "vitecache";
4
+ import { at } from "../at.js";
5
+ import { createBakeRenderer } from "../bake.js";
6
+ import { disposeRejected, disposeTree } from "../dispose.js";
7
+ import { framePixels } from "../impostor/impostor.js";
8
+ import { resolveThresholds } from "../levels/index.js";
9
+ import { meshoptDecoder } from "../meshopt.js";
10
+ import { isMesh, isObject3D, rejectSkinned } from "../three.js";
11
+ import { buildLevel } from "./build.js";
12
+ import { LodLoadContext } from "./context.js";
13
+ import { AssetDependencies, bundledModules } from "./dependencies.js";
14
+ import { decodeLevel, encodeLevel, encodeShape, placedBox, readLevel, readShape, shapeOf } from "./level.js";
15
+ import { auxiliary, cached, derived, levelEntry, normalize, shapeEntry, warmup } from "./request.js";
16
+ import { assetPath, isLocal } from "./url.js";
17
+ // The loader: it describes a ladder of levels from a source, builds each level when first loaded and caches it.
18
+ /**
19
+ * Loads asset URLs through manager handlers, else with a GLTFLoader of its own, which decodes meshopt only: register
20
+ * a GLTFLoader configured with Draco or KTX2 decoders for models compressed with them, and a GLTSLoader for .glts
21
+ * sources.
22
+ *
23
+ * Impostor and interior bakes draw with a renderer of the loader's own, made at its first bake: `dispose` frees it.
24
+ */
25
+ export class LodLoader extends Loader {
26
+ cacheOptions;
27
+ gltf;
28
+ /**
29
+ * The renderer this loader bakes with, made at its first bake. Its own, not the app's: a canvas the size of a bake
30
+ * frame would draw that frame over the whole target (see `bakeImpostor`).
31
+ */
32
+ renderer;
33
+ /** URLs whose builds this loader serves without saving, once it has warned why. */
34
+ uncached = new Set();
35
+ constructor(manager, cacheOptions) {
36
+ super(manager);
37
+ this.cacheOptions = cacheOptions;
38
+ }
39
+ load(request, onLoad, _onProgress, onError) {
40
+ this.loadAsync(request).then(onLoad, onError ?? ((error) => console.error(error)));
41
+ }
42
+ /**
43
+ * Describes the ladder from the cache, else from its source, which the first level loaded then takes. Empty levels
44
+ * load with it, as does the source when it is the only drawable; other levels load when a camera needs them,
45
+ * including a coarse stand-in while its first detail arrives, and each derived level is cached on its own and built
46
+ * when first loaded. A level whose default threshold is measured from it is built with the ladder, as is every level
47
+ * in a `vite build` warmup.
48
+ *
49
+ * What the levels load is freed when the last Lod holding them is disposed (see `LodLevel.hold`), which spends them:
50
+ * a Lod made from them later throws, so call loadAsync again. Levels no Lod ever holds are never freed: they are
51
+ * yours until a Lod holds them.
52
+ */
53
+ async loadAsync(request) {
54
+ const input = normalize(request, this.path);
55
+ const { url, levels: requests } = input;
56
+ // Only the inputs: what each build or the shape is saved with is captured by its own loads.
57
+ const dependencies = new AssetDependencies(input.urls, this.manager);
58
+ const context = new LodLoadContext(() => this.loadSource(url), input.onLevel);
59
+ this.manager.itemStart(url);
60
+ try {
61
+ // vitecache resolves only same-origin paths to project files, so other sources build uncached.
62
+ const modules = dependencies.requested.every(isLocal) ? await bundledModules(input.urls, this.manager) : undefined;
63
+ const ladder = { ...input, modules };
64
+ // A simplified or baked level's default threshold is measured from its deviation, so it is built with the ladder.
65
+ const eager = requests.flatMap((level, index) => level.type !== "empty" && (warmup || (level.type !== "impostor" && level.maxPixels === undefined)) ? [index + 1] : []);
66
+ const reads = await Promise.all(eager.map(async (index) => ({ index, ...(await cached(levelEntry(ladder, index, dependencies, this.cacheOptions))) })));
67
+ // Only what measures a default threshold: bytes no camera asked for are not held.
68
+ const measured = new Map();
69
+ for (const { index, entry, bytes } of reads) {
70
+ const level = bytes ?? (await this.persist(ladder, index, await context.source(), entry));
71
+ if (!bytes)
72
+ context.setBuilt(index, level);
73
+ measured.set(index, readLevel(level).level);
74
+ }
75
+ const shape = await this.shape(ladder, dependencies, () => context.source());
76
+ const box = placedBox(shape);
77
+ if (box.isEmpty())
78
+ throw new Error("LodLoader: the source has no visible geometry to measure");
79
+ const thresholds = resolveThresholds([
80
+ {},
81
+ ...requests.map((level, position) => ({
82
+ // An impostor's default is its frame's even when a warmup bakes it, as it is without one.
83
+ maxPixels: level.maxPixels ?? (level.type === "impostor" ? framePixels(level.resolution) : undefined),
84
+ measured: level.type === "impostor" ? undefined : measured.get(position + 1),
85
+ })),
86
+ ], shape.box.getSize(new Vector3()).length(), "LodLoader");
87
+ const { hold } = context;
88
+ // Every load runs once however often it is asked for: every Lod made from the levels and the levels reading the
89
+ // source's materials share one object. The source's starts synchronously, so it takes the spare before a coarser
90
+ // level demanded in the same tick.
91
+ const loadSource = once(async () => context.arrive((context.take() ?? (await this.loadSource(url))).source, 0, { materials: true }));
92
+ const materials = async () => {
93
+ const { object } = at(levels, 0);
94
+ return materialsOf(object ?? (await loadSource()));
95
+ };
96
+ const deferred = [
97
+ { load: loadSource, maxPixels: Infinity, box, hold },
98
+ ...requests.map((level, position) => {
99
+ const index = position + 1;
100
+ const maxPixels = at(thresholds, index);
101
+ if (level.type === "empty")
102
+ return { load: once(async () => context.arrive(new Group(), index, { materials: true })), maxPixels, box: new Box3(), hold };
103
+ const load = once(async () => {
104
+ const bytes = context.takeBuilt(index) ?? (await this.levelBytes(ladder, index, context.take()));
105
+ const object = await decodeLevel(level.type, readLevel(bytes), materials, level.type === "impostor" ? level.draw : undefined);
106
+ // A simplified level draws with the source level's materials, which that level frees.
107
+ return context.arrive(object, index, { materials: level.type !== "simplify" });
108
+ });
109
+ return { load, maxPixels, box: box.clone(), hold };
110
+ }),
111
+ ];
112
+ const levels = await preload(deferred);
113
+ return levels;
114
+ }
115
+ catch (error) {
116
+ context.fail();
117
+ this.manager.itemError(url);
118
+ throw error;
119
+ }
120
+ finally {
121
+ this.manager.itemEnd(url);
122
+ }
123
+ }
124
+ /** The source's shape from its entry, else measured from the source and saved. */
125
+ async shape(ladder, dependencies, loadSource) {
126
+ const { entry, bytes } = await cached(shapeEntry(ladder, dependencies, this.cacheOptions));
127
+ if (bytes)
128
+ return readShape(bytes);
129
+ const { source, dependencies: read } = await loadSource();
130
+ const shape = shapeOf(source);
131
+ await this.save(ladder.url, entry, encodeShape(shape), read);
132
+ return shape;
133
+ }
134
+ /**
135
+ * A deferred level's bytes from its entry, else built from `spare`, the ladder's source, or from a source of its own:
136
+ * the source level's carries onLevel effects. Disposes `spare` either way.
137
+ */
138
+ async levelBytes(ladder, index, spare) {
139
+ const { entry, bytes } = await cached(levelEntry(ladder, index, new AssetDependencies(ladder.urls, this.manager), this.cacheOptions));
140
+ if (bytes) {
141
+ if (spare)
142
+ disposeTree(spare.source);
143
+ return bytes;
144
+ }
145
+ const loaded = spare ?? (await this.loadSource(ladder.url));
146
+ try {
147
+ return await this.persist(ladder, index, loaded, entry);
148
+ }
149
+ finally {
150
+ disposeTree(loaded.source);
151
+ }
152
+ }
153
+ /**
154
+ * Build level `index` from `loaded`, and save it to `entry`, read before, when what it was built from can be validated
155
+ * later: what loading the source read, and what this build loads besides.
156
+ */
157
+ async persist(ladder, index, { source, dependencies: read }, entry) {
158
+ const { urls } = ladder;
159
+ const request = derived(ladder.levels, index);
160
+ const dependencies = new AssetDependencies(urls, this.manager).include(read);
161
+ const load = (name) => {
162
+ const asset = urls[auxiliary(index, name)];
163
+ return asset === undefined ? undefined : this.loadAsset(asset, dependencies);
164
+ };
165
+ let low, interior, built;
166
+ try {
167
+ rejectSkinned(source, "LodLoader");
168
+ low = await load("low");
169
+ interior = await load("interior");
170
+ built = await buildLevel(source, request, { low, interior }, () => this.bakeRenderer());
171
+ const bytes = await encodeLevel(built, request.type, shapeOf(source), materialsOf(source));
172
+ await this.save(ladder.url, entry, bytes, dependencies);
173
+ return bytes;
174
+ }
175
+ finally {
176
+ for (const object of [interior, low])
177
+ if (object)
178
+ disposeTree(object);
179
+ // A simplified level draws with the source's materials, which are freed with the source.
180
+ if (built)
181
+ disposeTree(built, { materials: request.type !== "simplify" });
182
+ }
183
+ }
184
+ /** The renderer this loader bakes with, made at its first bake. */
185
+ bakeRenderer() {
186
+ this.renderer ??= createBakeRenderer();
187
+ return this.renderer;
188
+ }
189
+ /**
190
+ * Free the renderer this loader made for its bakes; a bake under way fails. Levels it loaded stay as they are, and a
191
+ * later bake makes a new renderer.
192
+ */
193
+ dispose() {
194
+ const renderer = this.renderer;
195
+ this.renderer = undefined;
196
+ // A renderer that failed to initialise failed the bake that made it.
197
+ void renderer?.then((made) => made.dispose(), () => { });
198
+ }
199
+ /** Save `bytes` to `entry`, read before, when what they were built from can be validated later; warn once otherwise. */
200
+ async save(url, entry, bytes, dependencies) {
201
+ if (!entry)
202
+ return this.warnUncached(url, "it is not a same-origin path");
203
+ // Read now: GLTS sources go on reporting what they observe while levels are built.
204
+ const saved = dependencies.saved();
205
+ if ("reason" in saved)
206
+ return this.warnUncached(url, saved.reason);
207
+ if (this.uncached.has(url))
208
+ return;
209
+ try {
210
+ await entry.save(bytes, { dependencies: saved.dependencies });
211
+ }
212
+ catch (error) {
213
+ // A dependency without a backing file, such as a middleware URL or a package the app does not install, cannot be validated.
214
+ if (!(error instanceof MissingDependencyError))
215
+ throw error;
216
+ this.warnUncached(url, error.message);
217
+ }
218
+ }
219
+ /** Builds of `url` are served without saving from now on, after one warning naming why; a build warmup fails instead. */
220
+ warnUncached(url, reason) {
221
+ if (warmup)
222
+ throw new Error(`LodLoader: cannot precompute "${url}": ${reason}`);
223
+ if (this.uncached.has(url))
224
+ return;
225
+ this.uncached.add(url);
226
+ console.warn(`LodLoader: "${url}" is not cached by this loader: ${reason}`);
227
+ }
228
+ /** The ladder's source, with what loading it read. */
229
+ async loadSource(url) {
230
+ const dependencies = new AssetDependencies({ source: url }, this.manager);
231
+ return { source: await this.loadAsset(url, dependencies), dependencies };
232
+ }
233
+ async loadAsset(url, dependencies) {
234
+ const { path, extension } = assetPath(url);
235
+ const handler = this.manager.getHandler(path);
236
+ if (!handler && extension === "glts")
237
+ throw new Error(`LodLoader: cannot load "${url}": register a GLTSLoader for .glts on the loading manager`);
238
+ let result;
239
+ if (handler)
240
+ result = await handler.loadAsync(url);
241
+ else {
242
+ this.gltf ??= new GLTFLoader(this.manager).setMeshoptDecoder(meshoptDecoder());
243
+ const decoder = this.gltf.setCrossOrigin(this.crossOrigin).setWithCredentials(this.withCredentials).setRequestHeader(this.requestHeader);
244
+ result = await decoder.loadAsync(url);
245
+ }
246
+ const object = objectOf(result, url);
247
+ try {
248
+ dependencies.capture(url, object, result);
249
+ return object;
250
+ }
251
+ catch (error) {
252
+ disposeRejected(object);
253
+ throw error;
254
+ }
255
+ }
256
+ }
257
+ /** `load`, run once however often it is called: every call shares its promise. */
258
+ function once(load) {
259
+ let started;
260
+ return () => (started ??= load());
261
+ }
262
+ function materialsOf(object) {
263
+ const materials = [];
264
+ object.traverse((node) => {
265
+ if (isMesh(node))
266
+ for (const material of [node.material].flat())
267
+ materials.push(material);
268
+ });
269
+ return materials;
270
+ }
271
+ /** Loads what every camera draws before it picks a level: the empty levels, and the source if it is the only drawable. */
272
+ async function preload(levels) {
273
+ const drawable = levels.filter((level) => !level.box.isEmpty());
274
+ return Promise.all(levels.map(async (level) => level.box.isEmpty() || drawable.length === 1 ? { object: await level.load(), maxPixels: level.maxPixels, hold: level.hold } : level));
275
+ }
276
+ function objectOf(result, url) {
277
+ if (isObject3D(result))
278
+ return result;
279
+ const scene = typeof result === "object" && result !== null ? Reflect.get(result, "scene") : undefined;
280
+ if (isObject3D(scene))
281
+ return scene;
282
+ throw new Error(`LodLoader: the handler for "${url}" did not load an Object3D or a glTF`);
283
+ }
284
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loader/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { Box3, Matrix4, type Material, type Object3D } from "three/webgpu";
2
+ import { type ImpostorMeshOptions } from "../impostor/mesh/index.js";
3
+ import type { LodLevelRequest } from "./request.js";
4
+ /** A level the loader builds from the source and caches. */
5
+ export type Derived = Exclude<LodLevelRequest, {
6
+ type: "empty";
7
+ }>;
8
+ type Kind = Derived["type"];
9
+ /**
10
+ * The source's full-detail bounds in its own space and its placement. Every drawable level declares these bounds,
11
+ * so a ladder is described before its finer levels are built; each derived level must fit inside them.
12
+ */
13
+ export interface Shape {
14
+ box: Box3;
15
+ matrix: Matrix4;
16
+ }
17
+ export declare function shapeOf(source: Object3D): Shape;
18
+ /** `shape` on its own, as its cache entry holds it. */
19
+ export declare const encodeShape: (shape: Shape) => Uint8Array;
20
+ export declare const readShape: (bytes: Uint8Array) => Shape;
21
+ /** The bounds every drawable level declares, in the space of the Lod that holds it. */
22
+ export declare const placedBox: ({ box, matrix }: Shape) => Box3;
23
+ interface Metadata {
24
+ name: string;
25
+ deviation?: number;
26
+ texels?: number;
27
+ matrix: Matrix4;
28
+ matrixAutoUpdate: boolean;
29
+ castShadow: boolean;
30
+ receiveShadow: boolean;
31
+ }
32
+ export interface Entry {
33
+ shape: Shape;
34
+ level: Metadata;
35
+ payload: Uint8Array;
36
+ }
37
+ export declare function encodeLevel(object: Object3D, kind: Kind, shape: Shape, materials: readonly Material[]): Promise<Uint8Array>;
38
+ /** Decode a level placed as it was built; `materials` are the source's, which a simplified level draws with. */
39
+ export declare function decodeLevel(kind: Kind, { level, payload }: Entry, materials: () => Promise<Material[]>, draw: ImpostorMeshOptions | undefined): Promise<Object3D>;
40
+ export declare function readLevel(bytes: Uint8Array): Entry;
41
+ export {};
@@ -0,0 +1,140 @@
1
+ import { Box3, Matrix4 } from "three/webgpu";
2
+ import { decodeBakedMeshAsync, encodeBakedMeshAsync } from "../baked/codec.js";
3
+ import { boundingBox } from "../source/detail.js";
4
+ import { decodeImpostorAsync, encodeImpostorAsync } from "../impostor/codec.js";
5
+ import { ImpostorMesh } from "../impostor/mesh/index.js";
6
+ import { measure, recordDeviation } from "../levels/index.js";
7
+ import { isImpostorMesh, isMesh } from "../three.js";
8
+ import { decodeMeshAsync, encodeMeshAsync } from "../codec/mesh.js";
9
+ export function shapeOf(source) {
10
+ if (source.matrixAutoUpdate)
11
+ source.updateMatrix();
12
+ return { box: boundingBox(source), matrix: source.matrix.clone() };
13
+ }
14
+ /** `shape` on its own, as its cache entry holds it. */
15
+ export const encodeShape = (shape) => new TextEncoder().encode(JSON.stringify(shapeFields(shape)));
16
+ export const readShape = (bytes) => parseShape(object(JSON.parse(new TextDecoder().decode(bytes))));
17
+ const shapeFields = ({ box, matrix }) => ({ box: [...box.min.toArray(), ...box.max.toArray()], placement: matrix.toArray() });
18
+ function parseShape(meta) {
19
+ const box = new Box3().setFromArray(numbers(meta.box, 6));
20
+ if (box.isEmpty())
21
+ fail("empty source box");
22
+ return { box, matrix: new Matrix4().fromArray(numbers(meta.placement, 16)) };
23
+ }
24
+ /** The bounds every drawable level declares, in the space of the Lod that holds it. */
25
+ export const placedBox = ({ box, matrix }) => box.clone().applyMatrix4(matrix);
26
+ const MAGIC = 0x33444f4c;
27
+ export async function encodeLevel(object, kind, shape, materials) {
28
+ if (object.matrixAutoUpdate)
29
+ object.updateMatrix();
30
+ const box = boundingBox(object).applyMatrix4(object.matrix);
31
+ if (box.isEmpty())
32
+ throw new Error(`LodLoader: the ${kind} level draws nothing`);
33
+ const bounds = placedBox(shape);
34
+ // Rounding in welds and bakes may move a vertex by a hair.
35
+ if (!bounds
36
+ .clone()
37
+ .expandByScalar(bounds.getSize(box.min.clone()).length() * 1e-4)
38
+ .containsBox(box))
39
+ throw new Error(`LodLoader: the ${kind} level extends beyond the source's bounds; derived shapes, such as a low shell, must stay inside the source`);
40
+ const payload = await encodePayload(object, kind, materials);
41
+ const header = new TextEncoder().encode(JSON.stringify({
42
+ ...shapeFields(shape),
43
+ name: object.name,
44
+ ...measure(object),
45
+ matrix: object.matrix.toArray(),
46
+ matrixAutoUpdate: object.matrixAutoUpdate,
47
+ castShadow: object.castShadow,
48
+ receiveShadow: object.receiveShadow,
49
+ }));
50
+ const bytes = new Uint8Array(8 + header.length + payload.length);
51
+ const data = new DataView(bytes.buffer);
52
+ data.setUint32(0, MAGIC, true);
53
+ data.setUint32(4, header.length, true);
54
+ bytes.set(header, 8);
55
+ bytes.set(payload, 8 + header.length);
56
+ return bytes;
57
+ }
58
+ async function encodePayload(object, kind, materials) {
59
+ switch (kind) {
60
+ case "simplify":
61
+ return encodeMeshAsync(object, materials);
62
+ case "baked":
63
+ if (!isMesh(object))
64
+ throw new Error("LodLoader: baked level is not a mesh");
65
+ return encodeBakedMeshAsync(object);
66
+ case "impostor":
67
+ if (!isImpostorMesh(object))
68
+ throw new Error("LodLoader: impostor level is not an ImpostorMesh");
69
+ return encodeImpostorAsync(object.impostor);
70
+ }
71
+ }
72
+ /** Decode a level placed as it was built; `materials` are the source's, which a simplified level draws with. */
73
+ export async function decodeLevel(kind, { level, payload }, materials, draw) {
74
+ const object = kind === "simplify"
75
+ ? await decodeMeshAsync(payload, await materials())
76
+ : kind === "baked"
77
+ ? await decodeBakedMeshAsync(payload)
78
+ : new ImpostorMesh(await decodeImpostorAsync(payload), 1, draw);
79
+ object.name = level.name;
80
+ level.matrix.decompose(object.position, object.quaternion, object.scale);
81
+ object.matrix.copy(level.matrix);
82
+ object.matrixAutoUpdate = level.matrixAutoUpdate;
83
+ object.castShadow = level.castShadow;
84
+ object.receiveShadow = level.receiveShadow;
85
+ if (level.deviation !== undefined)
86
+ recordDeviation(object, level.deviation);
87
+ return object;
88
+ }
89
+ export function readLevel(bytes) {
90
+ if (bytes.length < 8)
91
+ fail("missing header");
92
+ const data = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
93
+ const length = data.getUint32(4, true);
94
+ if (data.getUint32(0, true) !== MAGIC || length > bytes.length - 8)
95
+ fail("invalid header");
96
+ const meta = object(JSON.parse(new TextDecoder().decode(bytes.subarray(8, 8 + length))));
97
+ if (typeof meta.name !== "string" ||
98
+ typeof meta.castShadow !== "boolean" ||
99
+ typeof meta.receiveShadow !== "boolean" ||
100
+ typeof meta.matrixAutoUpdate !== "boolean")
101
+ fail("invalid level settings");
102
+ const deviation = meta.deviation === undefined ? undefined : finite(meta.deviation);
103
+ if (deviation !== undefined && deviation < 0)
104
+ fail("negative deviation");
105
+ const texels = meta.texels === undefined ? undefined : finite(meta.texels);
106
+ if (texels !== undefined && texels <= 0)
107
+ fail("invalid texels");
108
+ return {
109
+ shape: parseShape(meta),
110
+ level: {
111
+ name: meta.name,
112
+ deviation,
113
+ texels,
114
+ matrix: new Matrix4().fromArray(numbers(meta.matrix, 16)),
115
+ matrixAutoUpdate: meta.matrixAutoUpdate,
116
+ castShadow: meta.castShadow,
117
+ receiveShadow: meta.receiveShadow,
118
+ },
119
+ payload: bytes.subarray(8 + length),
120
+ };
121
+ }
122
+ function object(value) {
123
+ if (typeof value !== "object" || value === null || Array.isArray(value))
124
+ fail("expected metadata object");
125
+ return Object.fromEntries(Object.entries(value));
126
+ }
127
+ function finite(value) {
128
+ if (typeof value !== "number" || !Number.isFinite(value))
129
+ fail("expected finite number");
130
+ return value;
131
+ }
132
+ function numbers(value, count) {
133
+ if (!Array.isArray(value) || value.length !== count)
134
+ fail(`expected ${count} numbers`);
135
+ return value.map(finite);
136
+ }
137
+ function fail(reason) {
138
+ throw new Error(`LodLoader: invalid cache (${reason})`);
139
+ }
140
+ //# sourceMappingURL=level.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"level.js","sourceRoot":"","sources":["../../src/loader/level.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import type { Object3D } from "three/webgpu";
2
+ import type { CacheEntry } from "vitecache";
3
+ import type { ImpostorMeshOptions } from "../impostor/mesh/index.js";
4
+ import type { BakeImpostorOptions } from "../impostor/bake/index.js";
5
+ import type { SimplifyOptions } from "../simplify/index.js";
6
+ import { type LodCacheOptions } from "./cache.js";
7
+ import type { Derived } from "./level.js";
8
+ import type { AssetDependencies } from "./dependencies.js";
9
+ /**
10
+ * Whether this runs in a production server-side build (`import.meta.env.PROD` and `SSR`), which precomputes assets
11
+ * into the deployed cache: every level is built and saved, and a level that cannot be saved fails the build.
12
+ */
13
+ export declare const warmup: boolean;
14
+ /**
15
+ * Levels derived from the source, finest first. Each derived level is built and persisted when it first loads; a
16
+ * simplified or baked level without `maxPixels` is built with the ladder, since its default threshold is measured from
17
+ * its deviation, and so is every level in a `vite build` warmup. An impostor's default is `framePixels` of its
18
+ * resolution: the threshold of a frame fitted to the source's bounding sphere, so the level before it draws smaller
19
+ * than it needs to. The frame the bake fits to the source is up to about 1.5 times tighter; give `maxPixels` to
20
+ * switch to the impostor sooner. Changing `maxPixels` or an impostor's `draw` reuses them, except an impostor's
21
+ * `maxPixels`, which also sizes its bake.
22
+ */
23
+ export type LodLevelRequest = ({
24
+ type: "simplify";
25
+ maxPixels?: number;
26
+ } & SimplifyOptions) | ({
27
+ type: "baked";
28
+ maxPixels?: number;
29
+ textureSize?: number;
30
+ /** Room geometry for window baking, as an asset URL relative to the source. */
31
+ interior?: string;
32
+ } & ({
33
+ /** Authored low shell to bake onto, as an asset URL relative to the source. */
34
+ low: string;
35
+ ratio?: never;
36
+ } | {
37
+ low?: never;
38
+ ratio?: number;
39
+ })) | ({
40
+ type: "impostor";
41
+ draw?: ImpostorMeshOptions;
42
+ } & BakeImpostorOptions) | {
43
+ type: "empty";
44
+ maxPixels: number;
45
+ };
46
+ /** A .glb, .gltf or .glts asset URL. Source and simplified levels load the original asset on demand. */
47
+ export type LodRequest = string | {
48
+ url: string;
49
+ levels?: readonly LodLevelRequest[];
50
+ /**
51
+ * Apply runtime effects when a level arrives, before draws compile. Does not change baked content or bounds.
52
+ * `index` is the returned ladder's: 0 is the source, and `levels[i]` arrives as `i + 1`. Set `castShadow` and
53
+ * `shadowSide` here: a level compiles its draws, shadow maps' included, before it arrives, so a shadow setting
54
+ * changed later compiles mid-frame.
55
+ */
56
+ onLevel?: (object: Object3D, index: number) => void | Promise<void>;
57
+ };
58
+ /** A normalized request, with the digests of its bundled modules when its levels are cacheable. */
59
+ export type Ladder = ReturnType<typeof normalize> & {
60
+ modules: Record<string, string> | undefined;
61
+ };
62
+ /** `request` with its URLs resolved against `path`, and every asset URL it builds from named as a dependency. */
63
+ export declare function normalize(request: LodRequest, path: string): {
64
+ url: string;
65
+ levels: readonly LodLevelRequest[];
66
+ urls: Record<string, string>;
67
+ /**
68
+ * Apply runtime effects when a level arrives, before draws compile. Does not change baked content or bounds.
69
+ * `index` is the returned ladder's: 0 is the source, and `levels[i]` arrives as `i + 1`. Set `castShadow` and
70
+ * `shadowSide` here: a level compiles its draws, shadow maps' included, before it arrives, so a shadow setting
71
+ * changed later compiles mid-frame.
72
+ */
73
+ onLevel?: (object: Object3D, index: number) => void | Promise<void>;
74
+ };
75
+ /** The request of ladder level `index`, which must be a derived level. */
76
+ export declare function derived(levels: readonly LodLevelRequest[], index: number): Derived;
77
+ /** The dependency name of the low or interior asset of the baked level at ladder index `level`. */
78
+ export declare const auxiliary: (level: number, name: "low" | "interior") => string;
79
+ /** Derived level `index`'s cache entry, keyed by the inputs it is built from; undefined when the ladder is not cacheable. */
80
+ export declare function levelEntry(ladder: Ladder, index: number, dependencies: AssetDependencies, options?: LodCacheOptions): CacheEntry | undefined;
81
+ /** The cache entry of the source's shape, which describes the ladder before any level is built. */
82
+ export declare function shapeEntry(ladder: Ladder, dependencies: AssetDependencies, options?: LodCacheOptions): CacheEntry | undefined;
83
+ /** `entry` and the bytes it holds, read: undefined when it holds none. */
84
+ export declare function cached(entry: CacheEntry | undefined): Promise<{
85
+ entry: CacheEntry | undefined;
86
+ bytes: Uint8Array | undefined;
87
+ }>;