@three-blocks/devtools 11.0.0 → 11.1.0-alpha.394.gd927ae9c8e86

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 (77) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/NOTICE +26 -0
  3. package/README.md +117 -170
  4. package/dist/asset-optimize-YJGWKD4Y.js +1 -0
  5. package/dist/asset-transforms-ZVZ4RD4L.js +11 -0
  6. package/dist/browser/shader-capture.js +2 -2
  7. package/dist/browser-smoke-4MYMHKWB.js +1 -0
  8. package/dist/chunk-4SVF5BRM.js +2 -0
  9. package/dist/chunk-7X4DHW36.js +1 -0
  10. package/dist/chunk-BBODS5RH.js +5 -0
  11. package/dist/{chunk-IILE5RBI.js → chunk-CMMYXGQ3.js} +1 -2
  12. package/dist/chunk-DCLDEPPB.js +253 -0
  13. package/dist/{chunk-5L2VS3BN.js → chunk-ECQE4D2U.js} +1 -2
  14. package/dist/chunk-IWQV456Z.js +3 -0
  15. package/dist/chunk-LSH64HEU.js +80 -0
  16. package/dist/{chunk-X5OFYHIY.js → chunk-MIJXPQPM.js} +2 -3
  17. package/dist/chunk-NDIPQLTU.js +16 -0
  18. package/dist/{chunk-NPLE7PPF.js → chunk-NJITVI23.js} +1 -2
  19. package/dist/chunk-O5FU2ASS.js +16 -0
  20. package/dist/chunk-QQKHDH26.js +1 -0
  21. package/dist/chunk-S5LI2C2H.js +5 -0
  22. package/dist/chunk-SBUKHO24.js +1 -0
  23. package/dist/chunk-TK566QET.js +1 -0
  24. package/dist/{chunk-65VEJRRT.js → chunk-WNSGAV6N.js} +1 -2
  25. package/dist/chunk-ZG3LO3VB.js +1 -0
  26. package/dist/{chunk-UDUICSME.js → chunk-ZTHZE36A.js} +1 -1
  27. package/dist/cli.d.ts +1 -0
  28. package/dist/cli.js +26 -26
  29. package/dist/environment-bake-ON5I27N7.js +1 -0
  30. package/dist/index.d.ts +24 -12
  31. package/dist/index.js +1 -279
  32. package/dist/{shader-autowire-SPE5DM2X.js → shader-autowire-D2EOG6GF.js} +1 -2
  33. package/dist/shader-browser-6ICBHK3S.js +1 -0
  34. package/dist/shader-capture-server.d.ts +1 -1
  35. package/dist/shader-capture-server.js +1 -1
  36. package/dist/{shader-config-EOFU5D3Y.js → shader-config-AKZEKIRB.js} +1 -2
  37. package/dist/{shader-parity-QXJWR6OZ.js → shader-parity-7DEPQEDI.js} +1 -1
  38. package/dist/{shader-project-runner-S2AID2RJ.js → shader-project-runner-NV4GKHDX.js} +1 -2
  39. package/dist/shader-watch-JBUA4LP5.js +1 -0
  40. package/dist/shader-workflow-5EHHR32D.js +1 -0
  41. package/dist/status-GDVSLQWV.js +1 -0
  42. package/dist/text-atlas-YYWV7S6F.js +1 -0
  43. package/dist/transform.cjs +1 -1
  44. package/dist/transform.js +1 -1
  45. package/dist/webpack-loader.cjs +1 -1
  46. package/dist/webpack-loader.js +1 -1
  47. package/node/index.d.mts +70 -0
  48. package/node/index.mjs +407 -0
  49. package/node/ipc.mjs +31 -0
  50. package/node/layout.mjs +546 -0
  51. package/node/loader.mjs +103 -0
  52. package/node/media.mjs +454 -0
  53. package/node/recording.mjs +67 -0
  54. package/node/worker.mjs +1314 -0
  55. package/package.json +27 -11
  56. package/dist/asset-optimize-GG72JCOX.js +0 -6
  57. package/dist/browser-smoke-KFF7XV7F.js +0 -254
  58. package/dist/chunk-45AVKQQK.js +0 -80
  59. package/dist/chunk-5FT6AZD6.js +0 -82
  60. package/dist/chunk-7N6TU4JG.js +0 -17
  61. package/dist/chunk-EI7MMDWY.js +0 -1
  62. package/dist/chunk-HOZDD6PW.js +0 -2
  63. package/dist/chunk-LKXY5YU2.js +0 -17
  64. package/dist/chunk-MIUIIPS4.js +0 -1
  65. package/dist/chunk-NF4RFSUJ.js +0 -18
  66. package/dist/chunk-QJFPNM6W.js +0 -2
  67. package/dist/chunk-ZT6T2W4B.js +0 -2
  68. package/dist/chunk-ZZLAZ7GJ.js +0 -6
  69. package/dist/environment-bake-BGMGFAVK.js +0 -4
  70. package/dist/shader-browser-H5CB2ZQX.js +0 -2
  71. package/dist/shader-browser-UXXR6QI2.js +0 -1
  72. package/dist/shader-parity-XPKQQK26.js +0 -2
  73. package/dist/shader-watch-EORZ2SEC.js +0 -2
  74. package/dist/shader-workflow-7NQFDQI5.js +0 -2
  75. package/dist/status-PTBB4SW2.js +0 -2
  76. package/dist/text-atlas-UORTLOQJ.js +0 -2
  77. /package/dist/{chunk-TRHSN2DJ.cjs → chunk-LMLJIVNY.cjs} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @three-blocks/devtools
2
2
 
3
+ ## 11.1.0-alpha.394.gd927ae9c8e86
4
+
5
+ - Packages: This alpha contains no user-facing changes.
6
+
7
+ - Packages: Built from `d927ae9c8e86`.
8
+
9
+
10
+ ## 11.1.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 02f3072: Devtools: Run shader captures and project checks in Node with fewer dependencies.
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [02f3072]
19
+ - three-blocks@0.12.1
20
+
3
21
  ## 11.0.0
4
22
 
5
23
  ### Patch Changes
package/NOTICE CHANGED
@@ -22,3 +22,29 @@ and implementation source. This reservation does not limit statutory exceptions
22
22
  or permissions in LICENSE. Public documentation at
23
23
  https://threejs-blocks.com/llms.txt may be used by assistants to help people use
24
24
  the documented public API.
25
+
26
+ Bundled third-party software
27
+ ============================
28
+
29
+ glTF Transform: Copyright (c) 2024 Don McCurdy
30
+ gl-matrix: Copyright (c) 2015-2025, Brandon Jones, Colin MacKenzie IV.
31
+
32
+ These components are distributed under the MIT License:
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ of this software and associated documentation files (the "Software"), to deal
36
+ in the Software without restriction, including without limitation the rights
37
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ copies of the Software, and to permit persons to whom the Software is
39
+ furnished to do so, subject to the following conditions:
40
+
41
+ The above copyright notice and this permission notice shall be included in all
42
+ copies or substantial portions of the Software.
43
+
44
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50
+ SOFTWARE.
package/README.md CHANGED
@@ -1,17 +1,22 @@
1
1
  # @three-blocks/devtools
2
2
 
3
- `@three-blocks/devtools` is the public, account-free command engine behind `npx three-blocks`. It captures and verifies WebGPU shaders and eligible shaders from `WebGPURenderer`'s WebGL fallback, generates text atlases, bakes environment lighting, optimizes GLB, texture, and HDR assets to meshopt + KTX2, and checks browser integrations. The runtime overlay and shader hydrator ship from `three-blocks/devtools` and `three-blocks/shaders` in the core package.
3
+ The account-free command engine behind `npx three-blocks`: shader precompilation,
4
+ text atlases, environment lighting, asset optimization, and integration checks.
5
+ The runtime overlay and shader hydrator ship in `three-blocks/devtools` and
6
+ `three-blocks/shaders`.
4
7
 
5
- ## Add Devtools to a Vite app
8
+ Captures and checks run in isolated Node.js processes with native ANGLE/WebGL,
9
+ Dawn/WebGPU, worker threads, and native media decoding. No browser installation
10
+ is needed. Image preparation uses Skia; PNG and JPEG captures use dedicated decoders.
6
11
 
7
- The Three Blocks starter already installs and configures this package. An adopted project installs it once; every `npx three-blocks` command in this document runs the project's own copy:
12
+ ## Set up a project
13
+
14
+ The Three Blocks starter includes this setup. For an existing Vite app:
8
15
 
9
16
  ```bash
10
17
  npm install --save-dev @three-blocks/devtools
11
18
  ```
12
19
 
13
- Add `threeBlocks()` beside your existing Vite plugins:
14
-
15
20
  ```typescript
16
21
  import { defineConfig } from "vite";
17
22
  import { threeBlocks } from "three-blocks/vite";
@@ -21,7 +26,7 @@ export default defineConfig(({ mode }) => ({
21
26
  }));
22
27
  ```
23
28
 
24
- Register the page-owned `WebGPURenderer` once:
29
+ Register your page-owned renderer once:
25
30
 
26
31
  ```typescript
27
32
  import { registerDevtools } from "three-blocks/devtools";
@@ -29,132 +34,58 @@ import { registerDevtools } from "three-blocks/devtools";
29
34
  registerDevtools({ renderer });
30
35
  ```
31
36
 
32
- Open the development overlay and click **Capture** for the current scene. Use the command for a route matrix, automated regeneration, or continuous integration (CI):
37
+ Click **Capture** in the development overlay, or run:
33
38
 
34
39
  ```bash
35
40
  npx three-blocks shaders capture
36
41
  ```
37
42
 
38
- The first command-line capture creates `three-blocks.shaders.json` with a default `/` route when the project has no shader configuration. Capture writes a committed source artifact under `.three-blocks/shaders/` and a browser manifest under `public/three-blocks/shaders/`. `registerDevtools()` loads the matching manifest before the first shader build. Use `installShaderCache()` only when the app owns custom manifest transport.
39
-
40
- For Next.js, webpack, Rollup, or esbuild, the capture command detects the bundler and checks its provider adapter. Missing wiring produces an exact configuration diff and requires confirmation. Review that diff before using `--yes` in a noninteractive shell. The command starts a project-local Next.js server or builds and serves `dist/`, `build/`, or `out/`.
41
-
42
- Use `--driver static --serve build_directory` for a nonstandard build directory. Use `--url http://localhost:3000` to attach to a transformed server you started. Explicit driver and URL choices never edit bundler configuration.
43
-
44
- The overlay changes from **Live** to **Precompiled** after a fresh capture loads. Each capture writes a receipt-matched estimate to `.three-blocks/shaders/timing.local.json`; `--commit-timing` also writes a shareable, hardware-labelled `timing.json`. `shaders test` replaces the local estimate with a median from repeated runs. The overlay reports skipped Three Shading Language (TSL) builds and estimated TSL work avoided only while timing matches the current receipt.
45
-
46
- The default capture backend is `both`. Set `"backend": "webgpu"` or `"backend":
47
- "webgl"` to keep one lane, or select a lane explicitly:
43
+ The first capture creates `three-blocks.shaders.json` for `/`. It writes source
44
+ artifacts to `.three-blocks/shaders/` and runtime manifests to
45
+ `public/three-blocks/shaders/`. Commit both. `registerDevtools()` loads the active
46
+ backend's manifest before the first shader build. Apps with custom transport can
47
+ use `installShaderCache()`.
48
+
49
+ The overlay shows **Live** or **Precompiled**, switches between WebGPU and WebGL,
50
+ and displays timing only when it matches the current receipt. Capture writes a
51
+ local estimate; `shaders test` replaces it with repeated measurements.
52
+ `--commit-timing` writes a shareable, hardware-labelled `timing.json`.
53
+
54
+ ## Commands
55
+
56
+ Run these through your project's installed package. All commands support `--json`
57
+ and `--reporter json`; `--root project_path` selects a different project.
58
+
59
+ | Command | Purpose |
60
+ | --- | --- |
61
+ | `npx three-blocks status` | Worker, asset, shader, and text state |
62
+ | `npx three-blocks shaders status --check` | GPU-free freshness verification |
63
+ | `npx three-blocks shaders capture --if-stale` | Capture changed scenes and optimize public GLB/HDR assets |
64
+ | `npx three-blocks shaders test --parity-only` | One live/precompiled correctness pair per scene |
65
+ | `npx three-blocks shaders test` | Parity, repeated timing, and published-page checks |
66
+ | `npx three-blocks text generate` | MSDF atlases and receipts |
67
+ | `npx three-blocks text status` | Text checksums and glyph coverage |
68
+ | `npx three-blocks environment bake --size 256` | Prefiltered environment KTX2 |
69
+ | `npx three-blocks optimize` | GLB, texture, and HDR compression to meshopt/KTX2 |
70
+ | `npx three-blocks assets status --check` | Optimized-asset receipt verification |
71
+ | `npx three-blocks browser smoke --route /` | Development readiness and HMR in Node |
72
+ | `npx three-blocks browser preview --route /` | Build and verify the production preview in Node |
73
+
74
+ During development, use live compilation while editing and capture through the
75
+ overlay when ready. Reserve batch capture for an explicit request or a final
76
+ release check. A GPU-free CI gate is:
48
77
 
49
78
  ```bash
50
- npx three-blocks shaders capture --backend both
51
- npx three-blocks shaders test --parity-only --backend webgl
52
- npx three-blocks shaders status --check --backend webgl
53
- ```
54
-
55
- Artifacts are symmetric: `.three-blocks/shaders/<scene>.<backend>.ts` and
56
- `public/three-blocks/shaders/<scene>.<backend>.json`. The receipt reports
57
- freshness per scene/backend, and the runtime loads only the active renderer's
58
- manifest.
59
-
60
- During development, the overlay's compact WebGPU/WebGL control reloads the page
61
- against either precompiled lane and reports the pooled WGSL/GLSL source size.
62
-
63
- This supports `WebGPURenderer` when it selects Three's WebGL fallback backend;
64
- the legacy standalone `WebGLRenderer` remains outside the provider seam.
65
- WebGL precompilation is render-only: compute, storage-buffer writes, subgroups,
66
- and PBO-backed storage reads stay on the live path with one warning. Required
67
- GLSL extensions are checked before hydration, so a capture from SwiftShader
68
- falls live instead of using incompatible source on another device.
69
-
70
- ### Three.js r185 compatibility patch
71
-
72
- Shader precompilation supports Three.js `>=0.185.0 <0.186.0`. Every adapter applies the same version-gated transform to `three/build/three.webgpu.js` in memory and never writes `node_modules`. Exact source anchors fail closed on unknown or partially patched builds. Run `npx three-blocks shaders` to see the compatibility versions the installed release requires; recapture older artifacts instead of editing them.
73
-
74
- The [Devtools guide](https://threejs-blocks.com/docs/tools/devtools) lists the released r185 patches behind that transform.
75
-
76
- ### Manual bundler adapters
77
-
78
- These are the manual equivalents of the diff that `shaders capture` offers.
79
-
80
- esbuild:
81
-
82
- ```typescript
83
- import { build } from "esbuild";
84
- import { createEsbuildShaderPlugin } from "@three-blocks/devtools/transform";
85
-
86
- await build({
87
- plugins: [createEsbuildShaderPlugin({ root: process.cwd() })],
88
- });
89
- ```
90
-
91
- Rollup:
92
-
93
- ```typescript
94
- import { createRollupShaderPlugin } from "@three-blocks/devtools/transform";
95
-
96
- export default {
97
- plugins: [createRollupShaderPlugin({ root: process.cwd() })],
98
- };
99
- ```
100
-
101
- webpack:
102
-
103
- ```typescript
104
- import { withThreeBlocksWebpack } from "@three-blocks/devtools/transform";
105
-
106
- export default withThreeBlocksWebpack({});
107
- ```
108
-
109
- Next.js:
110
-
111
- ```typescript
112
- import type { NextConfig } from "next";
113
- import { withThreeBlocksNext } from "@three-blocks/devtools/transform";
114
-
115
- const nextConfig: NextConfig = {
116
- // Your existing webpack callback is composed, not replaced.
117
- };
118
-
119
- export default withThreeBlocksNext(nextConfig);
79
+ npx three-blocks shaders test --skip-browser --mode strict
120
80
  ```
121
81
 
122
- The adapters always install the production provider hook. They add capture instrumentation only when `THREE_BLOCKS_SHADER_TOOL=1`; a tool-managed build or server sets that automatically. For a manually started webpack or Next.js server, set the variable yourself and run `npx three-blocks shaders capture --url http://localhost:3000`.
123
-
124
- ## Command reference
125
-
126
- Use `npx three-blocks` in applications. This package also exposes `three-blocks-devtools` for package-local and repository maintenance.
127
-
128
- | Command | Result |
129
- | --------------------------------------------- | --------------------------------------------------------------------------- |
130
- | `npx three-blocks status` | Report worker, asset, shader, and text state |
131
- | `npx three-blocks shaders` | Verify shader freshness without a browser or graphics processing unit (GPU) |
132
- | `npx three-blocks shaders capture --if-stale` | Capture changed scenes, write a local timing estimate, and optimize public GLB/HDR assets |
133
- | `npx three-blocks shaders test --parity-only` | Run one live and precompiled correctness pair per scene |
134
- | `npx three-blocks shaders test` | Run parity, repeated timing, and the published-page soak |
135
- | `npx three-blocks text generate` | Generate multi-channel signed distance field (MSDF) atlases and receipts |
136
- | `npx three-blocks text status` | Verify text assets and glyph coverage |
137
- | `npx three-blocks environment bake` | Bake a prefiltered environment KTX2 |
138
- | `npx three-blocks optimize` | Compress GLB, texture, or HDR inputs to meshopt + KTX2 with exact VRAM math |
139
- | `npx three-blocks assets status` | Re-verify the optimized-asset receipt (exit 1 with `--check` when stale) |
140
- | `npx three-blocks browser smoke` | Verify development readiness and hot module replacement (HMR) |
141
- | `npx three-blocks browser preview` | Build and verify the production preview |
142
-
143
- All commands support `--json` and `--reporter json`. `status` reads generated `three-blocks.json` metadata when present; adopted projects need only their shader or text configuration. Static status validates committed artifacts, compatibility versions, the installed `three-blocks/shaders` runtime closure, and discovered shader inputs. Browser evidence comes from the last `browser smoke` run and remains a dated verification, not live state.
144
-
145
- ### Precompile renderer shaders
146
-
147
- ```bash
148
- npx three-blocks shaders status --check
149
- npx three-blocks shaders capture --if-stale
150
- npx three-blocks shaders test --parity-only
151
- npx three-blocks shaders test
152
- ```
82
+ `--skip-browser` is the existing command spelling for static-only verification.
83
+ The default capture backend is `both`; `--backend webgpu` or `--backend webgl`
84
+ selects one lane. Each scene/backend has its own manifest and freshness result.
153
85
 
154
- During normal development, leave stale receipts on live compilation and capture from the
155
- overlay when ready. Reserve batch capture for an explicit request or final release check.
86
+ ## Capture contracts
156
87
 
157
- Add `three-blocks.shaders.json` when the project needs multiple routes, a semantic scene name, or an explicit readiness signal:
88
+ For multiple routes or explicit readiness, configure:
158
89
 
159
90
  ```json
160
91
  {
@@ -168,55 +99,71 @@ Add `three-blocks.shaders.json` when the project needs multiple routes, a semant
168
99
  }
169
100
  ```
170
101
 
171
- Readiness is optional. Its global may be `true` or a promise; a selector is also supported. With no override, the engine waits for its settled-frame and first-frame contract and assumes nothing about the application DOM.
172
-
173
- Capture observes real render and compute `NodeBuilder` states, then writes a deterministic pooled v3 manifest. WebGL receipts include render states and explicit live-fallback reasons for unsupported compute or PBO storage reads. The generated application owns no capture harness, and the tooling never writes to `node_modules`. Missing keys, stale receipts, unsupported Three.js versions, unavailable GLSL extensions, and hydration mismatches fail closed to live shader building.
174
-
175
- Artifact writes are transactional. `meta.json` records runtime, tool, schema, source-input, byte, and stage-coverage evidence. Relevant source changes during capture abort the write, and failures preserve the prior committed receipt. Explicit stable keys remain the clearest choice for conditional capture matrices; otherwise, capture assigns deterministic scene-scoped keys. Set `allowLiveBuilds: false` when every build must belong to the declared matrix.
176
-
177
- `shaders test` first repeats the GPU-free matrix inspection. Its browser gate proves that the live baseline builds every registered render pipeline and compute kernel. The fresh path must perform zero registered builds, report no misses, reach first-frame readiness, render non-black output, and match deterministic pixels.
178
-
179
- Successful scenes are checkpointed against their scene receipt and the shared runtime and tool contract. A later run can resume at the missing scene. `--parity-only` runs one live and precompiled pair without timing warmups, repeats, or the published-page soak. The default mode retains those measurements and production-page checks. A parity observation is bounded by the per-scene `timeoutMs`, 240 seconds by default. Failures write live, precompiled, and diff PNGs under `.three-blocks/shaders/parity/`.
180
-
181
- ### Verify a browser integration
182
-
183
- ```bash
184
- npx three-blocks browser smoke --route / --json
185
- npx three-blocks browser smoke --hmr src/offscreen/meshes/Scene.ts
186
- npx three-blocks browser preview --route /
187
- ```
188
-
189
- The smoke gate loads the project's Vite config on an ephemeral loopback port. It requires the visible OffscreenCanvas worker plus `workerReady`, `assetsReady`, and `compileEnd`. It also requires `textReady` when the Vite text configuration is enabled. Every configured Draco and KTX2 route is fetched, the lazy Meshopt decoder is initialized, and page or console errors fail the run. The gate checks the WebGPU screenshot and readable 2D panels for an all-black frame.
190
-
191
- The command reads the starter's built-in readiness check. Application tutorials describe the visible **Starting**, **Ready**, **Precompiled**, and **Live** states instead of this maintainer contract.
192
-
193
- `--hmr project_relative_module` emits a synthetic watcher change through Vite for an already loaded scene module. It runs the HMR graph without changing source and verifies that the browser acknowledges the update while lifecycle readiness remains stable.
194
-
195
- Only the two ambient diagnostics exported in `DOCUMENTED_BROWSER_NOISE` are filtered: Three Inspector's invalid `extensions.json` response and Chromium's experimental WebGPU notice.
196
-
197
- ### Bake environment lighting
198
-
199
- ```bash
200
- npx three-blocks environment bake --size 256
201
- npx three-blocks environment bake \
202
- --output src/assets/environment/studio.pmrem.ktx2 --json
203
- ```
204
-
205
- The browser entry renders Three.js `RoomEnvironment` through WebGPU and exports the PMREM CubeUV atlas. Node validates RGBA16F topology, compresses it with zstd at a deterministic level, decodes every level byte-for-byte, records the SHA-256 checksum, and transactionally replaces the KTX2 and JSON metadata pair. Size, time, upload, path, and file bounds are enforced. `--no-zstd` is an explicit compatibility opt-out.
206
-
207
- Both GPU commands accept `--root project_path` for integration workspaces that intentionally omit generated-project metadata. Generated projects are discovered automatically.
208
-
209
- ### Ship it
210
-
211
- Commit `.three-blocks/shaders/` and the generated public manifests, then add one GPU-free CI command:
212
-
213
- ```bash
214
- npx three-blocks shaders test --skip-browser --mode strict
215
- ```
216
-
217
- Use `--reporter json` for CI annotations. Run the full `shaders test` in an optional WebGPU lane. Production selects the hydration-only `three-blocks/devtools` condition. Overlay and statistics implementation bytes are absent, while the bounded `three-blocks/shaders` runtime remains. Opt into its local production console receipt with `threeBlocks({ stats: { production: true } })`; no telemetry leaves the app.
218
-
219
- Text artifacts remain `missing` or `invalid` until configured glyph coverage, checksums, orientation, and KTX2 decode round-trip validation succeed. No command performs account or entitlement checks.
102
+ Readiness can be a boolean global, a promise, or a selector. Without an override,
103
+ capture waits for settled-frame and first-frame readiness. Explicit stable keys
104
+ help with conditional scene matrices; otherwise capture assigns scene-scoped
105
+ keys. `allowLiveBuilds: false` requires every build to belong to the matrix.
106
+
107
+ The v3 manifest records actual render and compute NodeBuilder states. Receipt
108
+ writes are transactional; relevant source changes or capture failures preserve
109
+ the previous committed artifacts. Missing keys, stale receipts, incompatible
110
+ Three.js versions, unavailable GLSL extensions, and hydration mismatches fall
111
+ back to live shader building.
112
+
113
+ Parity requires a live baseline that builds every registered pipeline and
114
+ kernel, followed by zero registered builds, no misses, first-frame readiness,
115
+ non-black output, and matching deterministic pixels on the precompiled path.
116
+ Successful scenes are checkpointed against their receipts and shared tool/runtime
117
+ contract. Failures write live, precompiled, and diff PNGs to
118
+ `.three-blocks/shaders/parity/`. The default per-scene timeout is 240 seconds.
119
+
120
+ Shader precompilation supports Three.js `>=0.185.0 <0.186.0`. Adapters apply the
121
+ same version-gated transform in memory and never modify `node_modules`.
122
+ `npx three-blocks shaders` reports the installed compatibility requirements.
123
+ Unknown or partially patched builds fail closed; recapture older artifacts.
124
+
125
+ The supported WebGL path is `WebGPURenderer`'s fallback backend. Standalone
126
+ `WebGLRenderer` has no provider seam. Compute, storage writes, subgroups, and
127
+ PBO-backed storage reads stay live on WebGL, with a warning.
128
+
129
+ ## Other bundlers
130
+
131
+ Capture detects Next.js, webpack, Rollup, and esbuild. Missing adapter wiring
132
+ produces a configuration diff requiring confirmation; review it before using
133
+ `--yes` in automation. Manual adapter exports from `@three-blocks/devtools/transform`:
134
+
135
+ | Bundler | Adapter |
136
+ | --- | --- |
137
+ | esbuild | `createEsbuildShaderPlugin({ root: process.cwd() })` |
138
+ | Rollup | `createRollupShaderPlugin({ root: process.cwd() })` |
139
+ | webpack | `withThreeBlocksWebpack(config)` |
140
+ | Next.js | `withThreeBlocksNext(config)` |
141
+
142
+ Adapters always install the provider hook. Capture instrumentation requires
143
+ `THREE_BLOCKS_SHADER_TOOL=1`, set automatically for tool-managed servers.
144
+ Set it yourself when attaching to a manually started transformed server with
145
+ `--url http://localhost:3000`. For other output directories use
146
+ `--driver static --serve build_directory`. Explicit driver/URL choices do not
147
+ edit bundler configuration.
148
+
149
+ ## Integration and environment checks
150
+
151
+ Smoke starts Vite on loopback and verifies worker, asset, compile, and optional
152
+ text readiness; Draco/KTX2 routes; Meshopt initialization; and non-black rendered
153
+ output. Page and console errors fail the run apart from the explicitly documented
154
+ ambient-noise rules. `--hmr project_relative_module` triggers Vite's watcher
155
+ without editing source and verifies the update and lifecycle readiness.
156
+
157
+ Environment bake renders Three.js `RoomEnvironment` in Node, validates the RGBA16F
158
+ PMREM atlas, checks zstd round trips byte-for-byte, and transactionally replaces
159
+ the KTX2/metadata pair. Use `--output path` or `--no-zstd` when needed.
160
+
161
+ Production includes hydration without the development overlay/statistics code.
162
+ `threeBlocks({ stats: { production: true } })` enables a local console receipt;
163
+ no telemetry leaves the app. No Devtools command checks accounts or entitlements.
164
+
165
+ See the [Devtools guide](https://threejs-blocks.com/docs/tools/devtools) for full
166
+ integration examples, compatibility patches, and troubleshooting.
220
167
 
221
168
  ## License and Pro terms
222
169
 
@@ -0,0 +1 @@
1
+ export{a as ASSET_OPTIMIZE_VERSION,b as ASSET_RECEIPT_DIRECTORY,c as ASSET_RECEIPT_FILE,h as discoverPublicAssets,g as formatAssetOptimizeReport,j as formatAssetStatusReport,i as inspectAssets,f as optimizeAssets,e as presetForImageName,d as presetForTextureSlots,k as resetAssetOptimizeToolsForTests}from'./chunk-S5LI2C2H.js';import'./chunk-NDIPQLTU.js';import'./chunk-TK566QET.js';import'./chunk-NJITVI23.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
@@ -0,0 +1,11 @@
1
+ import {b,a,c}from'./chunk-7X4DHW36.js';import {Primitive,BufferUtils,Accessor,PropertyType,AnimationChannel,Document,Root,Scene,Texture,TextureInfo,ExtensionProperty,Material,ColorUtils,MathUtils,Node,PrimitiveTarget}from'@gltf-transform/core';import {loadImage,createCanvas}from'@napi-rs/canvas';import {KHRMeshQuantization,EXTMeshoptCompression}from'@gltf-transform/extensions';import'ktx-parse';var Ee=b((Vn,Te)=>{function at(e){for(var t=new Array(e),n=0;n<e;++n)t[n]=n;return t}a(at,"iota");Te.exports=at;});var Ne=b((Wn,Se)=>{Se.exports=function(e){return e!=null&&(Ie(e)||ct(e)||!!e._isBuffer)};function Ie(e){return !!e.constructor&&typeof e.constructor.isBuffer=="function"&&e.constructor.isBuffer(e)}a(Ie,"isBuffer");function ct(e){return typeof e.readFloatLE=="function"&&typeof e.slice=="function"&&Ie(e.slice(0,0))}a(ct,"isSlowBuffer");});var we=b((Yn,Me)=>{var lt=Ee(),ft=Ne(),ut=typeof Float64Array<"u";function gt(e,t){return e[0]-t[0]}a(gt,"compare1st");function pt(){var e=this.stride,t=new Array(e.length),n;for(n=0;n<t.length;++n)t[n]=[Math.abs(e[n]),n];t.sort(gt);var s=new Array(t.length);for(n=0;n<s.length;++n)s[n]=t[n][1];return s}a(pt,"order");function dt(e,t){var n=["View",t,"d",e].join("");t<0&&(n="View_Nil"+e);var s=e==="generic";if(t===-1){var r="function "+n+"(a){this.data=a;};var proto="+n+".prototype;proto.dtype='"+e+"';proto.index=function(){return -1};proto.size=0;proto.dimension=-1;proto.shape=proto.stride=proto.order=[];proto.lo=proto.hi=proto.transpose=proto.step=function(){return new "+n+"(this.data);};proto.get=proto.set=function(){};proto.pick=function(){return null};return function construct_"+n+"(a){return new "+n+"(a);}",A=new Function(r);return A()}else if(t===0){var r="function "+n+"(a,d) {this.data = a;this.offset = d};var proto="+n+".prototype;proto.dtype='"+e+"';proto.index=function(){return this.offset};proto.dimension=0;proto.size=1;proto.shape=proto.stride=proto.order=[];proto.lo=proto.hi=proto.transpose=proto.step=function "+n+"_copy() {return new "+n+"(this.data,this.offset)};proto.pick=function "+n+"_pick(){return TrivialArray(this.data);};proto.valueOf=proto.get=function "+n+"_get(){return "+(s?"this.data.get(this.offset)":"this.data[this.offset]")+"};proto.set=function "+n+"_set(v){return "+(s?"this.data.set(this.offset,v)":"this.data[this.offset]=v")+"};return function construct_"+n+"(a,b,c,d){return new "+n+"(a,d)}",A=new Function("TrivialArray",r);return A(H[e][0])}var r=["'use strict'"],i=lt(t),o=i.map(function(h){return "i"+h}),a="this.offset+"+i.map(function(h){return "this.stride["+h+"]*i"+h}).join("+"),l=i.map(function(h){return "b"+h}).join(","),g=i.map(function(h){return "c"+h}).join(",");r.push("function "+n+"(a,"+l+","+g+",d){this.data=a","this.shape=["+l+"]","this.stride=["+g+"]","this.offset=d|0}","var proto="+n+".prototype","proto.dtype='"+e+"'","proto.dimension="+t),r.push("Object.defineProperty(proto,'size',{get:function "+n+"_size(){return "+i.map(function(h){return "this.shape["+h+"]"}).join("*"),"}})"),t===1?r.push("proto.order=[0]"):(r.push("Object.defineProperty(proto,'order',{get:"),t<4?(r.push("function "+n+"_order(){"),t===2?r.push("return (Math.abs(this.stride[0])>Math.abs(this.stride[1]))?[1,0]:[0,1]}})"):t===3&&r.push("var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);if(s0>s1){if(s1>s2){return [2,1,0];}else if(s0>s2){return [1,2,0];}else{return [1,0,2];}}else if(s0>s2){return [2,0,1];}else if(s2>s1){return [0,1,2];}else{return [0,2,1];}}})")):r.push("ORDER})")),r.push("proto.set=function "+n+"_set("+o.join(",")+",v){"),s?r.push("return this.data.set("+a+",v)}"):r.push("return this.data["+a+"]=v}"),r.push("proto.get=function "+n+"_get("+o.join(",")+"){"),s?r.push("return this.data.get("+a+")}"):r.push("return this.data["+a+"]}"),r.push("proto.index=function "+n+"_index(",o.join(),"){return "+a+"}"),r.push("proto.hi=function "+n+"_hi("+o.join(",")+"){return new "+n+"(this.data,"+i.map(function(h){return ["(typeof i",h,"!=='number'||i",h,"<0)?this.shape[",h,"]:i",h,"|0"].join("")}).join(",")+","+i.map(function(h){return "this.stride["+h+"]"}).join(",")+",this.offset)}");var c=i.map(function(h){return "a"+h+"=this.shape["+h+"]"}),u=i.map(function(h){return "c"+h+"=this.stride["+h+"]"});r.push("proto.lo=function "+n+"_lo("+o.join(",")+"){var b=this.offset,d=0,"+c.join(",")+","+u.join(","));for(var f=0;f<t;++f)r.push("if(typeof i"+f+"==='number'&&i"+f+">=0){d=i"+f+"|0;b+=c"+f+"*d;a"+f+"-=d}");r.push("return new "+n+"(this.data,"+i.map(function(h){return "a"+h}).join(",")+","+i.map(function(h){return "c"+h}).join(",")+",b)}"),r.push("proto.step=function "+n+"_step("+o.join(",")+"){var "+i.map(function(h){return "a"+h+"=this.shape["+h+"]"}).join(",")+","+i.map(function(h){return "b"+h+"=this.stride["+h+"]"}).join(",")+",c=this.offset,d=0,ceil=Math.ceil");for(var f=0;f<t;++f)r.push("if(typeof i"+f+"==='number'){d=i"+f+"|0;if(d<0){c+=b"+f+"*(a"+f+"-1);a"+f+"=ceil(-a"+f+"/d)}else{a"+f+"=ceil(a"+f+"/d)}b"+f+"*=d}");r.push("return new "+n+"(this.data,"+i.map(function(h){return "a"+h}).join(",")+","+i.map(function(h){return "b"+h}).join(",")+",c)}");for(var d=new Array(t),m=new Array(t),f=0;f<t;++f)d[f]="a[i"+f+"]",m[f]="b[i"+f+"]";r.push("proto.transpose=function "+n+"_transpose("+o+"){"+o.map(function(h,N){return h+"=("+h+"===undefined?"+N+":"+h+"|0)"}).join(";"),"var a=this.shape,b=this.stride;return new "+n+"(this.data,"+d.join(",")+","+m.join(",")+",this.offset)}"),r.push("proto.pick=function "+n+"_pick("+o+"){var a=[],b=[],c=this.offset");for(var f=0;f<t;++f)r.push("if(typeof i"+f+"==='number'&&i"+f+">=0){c=(c+this.stride["+f+"]*i"+f+")|0}else{a.push(this.shape["+f+"]);b.push(this.stride["+f+"])}");r.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}"),r.push("return function construct_"+n+"(data,shape,stride,offset){return new "+n+"(data,"+i.map(function(h){return "shape["+h+"]"}).join(",")+","+i.map(function(h){return "stride["+h+"]"}).join(",")+",offset)}");var A=new Function("CTOR_LIST","ORDER",r.join(`
2
+ `));return A(H[e],pt)}a(dt,"compileConstructor");function ht(e){if(ft(e))return "buffer";if(ut)switch(Object.prototype.toString.call(e)){case "[object Float64Array]":return "float64";case "[object Float32Array]":return "float32";case "[object Int8Array]":return "int8";case "[object Int16Array]":return "int16";case "[object Int32Array]":return "int32";case "[object Uint8Array]":return "uint8";case "[object Uint16Array]":return "uint16";case "[object Uint32Array]":return "uint32";case "[object Uint8ClampedArray]":return "uint8_clamped";case "[object BigInt64Array]":return "bigint64";case "[object BigUint64Array]":return "biguint64"}return Array.isArray(e)?"array":"generic"}a(ht,"arrayDType");var H={float32:[],float64:[],int8:[],int16:[],int32:[],uint8:[],uint16:[],uint32:[],array:[],uint8_clamped:[],bigint64:[],biguint64:[],buffer:[],generic:[]};function mt(e,t,n,s){if(e===void 0){var g=H.array[0];return g([])}else typeof e=="number"&&(e=[e]);t===void 0&&(t=[e.length]);var r=t.length;if(n===void 0){n=new Array(r);for(var i=r-1,o=1;i>=0;--i)n[i]=o,o*=t[i];}if(s===void 0){s=0;for(var i=0;i<r;++i)n[i]<0&&(s-=(t[i]-1)*n[i]);}for(var a=ht(e),l=H[a];l.length<=r+1;)l.push(dt(a,l.length-1));var g=l[r+1];return g(e,t,n,s)}a(mt,"wrappedNDArrayCtor");Me.exports=mt;});async function ye(e){let t=await loadImage(e),n=createCanvas(t.width,t.height),s=n.getContext("2d");s.drawImage(t,0,0);let{data:r}=s.getImageData(0,0,t.width,t.height);return {shape:[t.width,t.height,4],data:r,get:a((i,o,a)=>r[(o*t.width+i)*4+a],"get")}}a(ye,"getPixels");c(we(),1);var{POINTS:Ns,LINES:Ms,LINE_STRIP:ws,LINE_LOOP:Rs,TRIANGLES:bs,TRIANGLE_STRIP:Cs,TRIANGLE_FAN:vs}=Primitive.Mode;function _(e,t){return Object.defineProperty(t,"name",{value:e}),t}a(_,"createTransform");function $(e,t){let n={...e};for(let s in t)t[s]!==void 0&&(n[s]=t[s]);return n}a($,"assignDefaults");var oe=class{static{a(this,"SetMap");}_map=new Map;get size(){return this._map.size}has(e){return this._map.has(e)}add(e,t){let n=this._map.get(e);return n||(n=new Set,this._map.set(e,n)),n.add(t),this}get(e){return this._map.get(e)||new Set}keys(){return this._map.keys()}};var Nt=new Intl.NumberFormat(void 0,{maximumFractionDigits:0});function Re(e){return Nt.format(e)}a(Re,"formatLong");function Mt(e,t,n=2){return (e>t?"\u2013":"+")+(Math.abs(e-t)/e*100).toFixed(n)+"%"}a(Mt,"formatDelta");function wt(e,t){return `${Re(e)} \u2192 ${Re(t)} (${Mt(e,t)})`}a(wt,"formatDeltaOp");function te(e){let t=[];for(let n of e.listAttributes())t.push(n);for(let n of e.listTargets())for(let s of n.listAttributes())t.push(s);return Array.from(new Set(t))}a(te,"deepListAttributes");function Rt(e){let t=e.getIndices(),n=te(e);e.dispose(),t&&!be(t)&&t.dispose();for(let s of n)be(s)||s.dispose();}a(Rt,"deepDisposePrimitive");function bt(e,t){if(e==null&&t==null)return true;if(e==null||t==null||e.length!==t.length)return false;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return false;return true}a(bt,"shallowEqualsArray");function X(e,t){return e.createAccessor(t.getName()).setArray(t.getArray()).setType(t.getType()).setBuffer(t.getBuffer()).setNormalized(t.getNormalized()).setSparse(t.getSparse())}a(X,"shallowCloneAccessor");function Ct(e,t=e){let n=Ve(e,t);for(let s=0;s<n.length;s++)n[s]=s;return n}a(Ct,"createIndices");function Ve(e,t=e){return t<=65534?new Uint16Array(e):new Uint32Array(e)}a(Ve,"createIndicesEmpty");function be(e){return e.listParents().some(t=>t.propertyType!==PropertyType.ROOT)}a(be,"isUsed");function Ke(e){for(let t in e)return false;return true}a(Ke,"isEmptyObject");function vt(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))}a(vt,"ceilPowerOfTwo$1");var Y=typeof Float32Array<"u"?Float32Array:Array;function Pt(e,t){var n=t[0],s=t[1],r=t[2],i=t[3],o=t[4],a=t[5],l=t[6],g=t[7],c=t[8],u=t[9],f=t[10],d=t[11],m=t[12],A=t[13],h=t[14],N=t[15],w=n*a-s*o,S=n*l-r*o,T=n*g-i*o,E=s*l-r*a,I=s*g-i*a,L=r*g-i*l,z=c*A-u*m,F=c*h-f*m,U=c*N-d*m,G=u*h-f*A,D=u*N-d*A,k=f*N-d*h,M=w*k-S*D+T*G+E*U-I*F+L*z;return M?(M=1/M,e[0]=(a*k-l*D+g*G)*M,e[1]=(r*D-s*k-i*G)*M,e[2]=(A*L-h*I+N*E)*M,e[3]=(f*I-u*L-d*E)*M,e[4]=(l*U-o*k-g*F)*M,e[5]=(n*k-r*U+i*F)*M,e[6]=(h*T-m*L-N*S)*M,e[7]=(c*L-f*T+d*S)*M,e[8]=(o*D-a*U+g*z)*M,e[9]=(s*U-n*D-i*z)*M,e[10]=(m*I-A*T+N*w)*M,e[11]=(u*T-c*I-d*w)*M,e[12]=(a*F-o*G-l*z)*M,e[13]=(n*G-s*F+r*z)*M,e[14]=(A*S-m*E-h*w)*M,e[15]=(c*E-u*S+f*w)*M,e):null}a(Pt,"invert$1");function me(e,t,n){var s=t[0],r=t[1],i=t[2],o=t[3],a=t[4],l=t[5],g=t[6],c=t[7],u=t[8],f=t[9],d=t[10],m=t[11],A=t[12],h=t[13],N=t[14],w=t[15],S=n[0],T=n[1],E=n[2],I=n[3];return e[0]=S*s+T*a+E*u+I*A,e[1]=S*r+T*l+E*f+I*h,e[2]=S*i+T*g+E*d+I*N,e[3]=S*o+T*c+E*m+I*w,S=n[4],T=n[5],E=n[6],I=n[7],e[4]=S*s+T*a+E*u+I*A,e[5]=S*r+T*l+E*f+I*h,e[6]=S*i+T*g+E*d+I*N,e[7]=S*o+T*c+E*m+I*w,S=n[8],T=n[9],E=n[10],I=n[11],e[8]=S*s+T*a+E*u+I*A,e[9]=S*r+T*l+E*f+I*h,e[10]=S*i+T*g+E*d+I*N,e[11]=S*o+T*c+E*m+I*w,S=n[12],T=n[13],E=n[14],I=n[15],e[12]=S*s+T*a+E*u+I*A,e[13]=S*r+T*l+E*f+I*h,e[14]=S*i+T*g+E*d+I*N,e[15]=S*o+T*c+E*m+I*w,e}a(me,"multiply$2");function xt(e,t){return e[0]=t[0],e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=t[1],e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=t[2],e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,e}a(xt,"fromScaling");function Ot(e,t,n,s){var r=t[0],i=t[1],o=t[2],a=t[3],l=r+r,g=i+i,c=o+o,u=r*l,f=r*g,d=r*c,m=i*g,A=i*c,h=o*c,N=a*l,w=a*g,S=a*c,T=s[0],E=s[1],I=s[2];return e[0]=(1-(m+h))*T,e[1]=(f+S)*T,e[2]=(d-w)*T,e[3]=0,e[4]=(f-S)*E,e[5]=(1-(u+h))*E,e[6]=(A+N)*E,e[7]=0,e[8]=(d+w)*I,e[9]=(A-N)*I,e[10]=(1-(u+m))*I,e[11]=0,e[12]=n[0],e[13]=n[1],e[14]=n[2],e[15]=1,e}a(Ot,"fromRotationTranslationScale");function j(e,t){let n=e.getAttribute("POSITION"),s=e.getIndices();switch(t){case "render":return s?s.getCount():n.getCount();case "render-cached":return s?new Set(s.getArray()).size:n.getCount();case "upload-naive":case "upload":return n.getCount();case "distinct":case "distinct-position":return _t(t);case "unused":return s?n.getCount()-new Set(s.getArray()).size:0;default:return $t(t)}}a(j,"getPrimitiveVertexCount");function _t(e){throw new Error(`Not implemented: ${e}`)}a(_t,"_assertNotImplemented");function $t(e){throw new Error(`Unexpected value: ${e}`)}a($t,"_assertUnreachable");var v=2**32-1,Lt=class{static{a(this,"VertexStream");}attributes=[];u8;u32;constructor(e){let t=0;for(let n of te(e))t+=this._initAttribute(n);this.u8=new Uint8Array(t),this.u32=new Uint32Array(this.u8.buffer);}_initAttribute(e){let t=e.getArray(),n=new Uint8Array(t.buffer,t.byteOffset,t.byteLength),s=e.getElementSize()*e.getComponentSize(),r=BufferUtils.padNumber(s);return this.attributes.push({u8:n,byteStride:s,paddedByteStride:r}),r}hash(e){let t=0;for(let{u8:n,byteStride:s,paddedByteStride:r}of this.attributes){for(let i=0;i<r;i++)i<s?this.u8[t+i]=n[e*s+i]:this.u8[t+i]=0;t+=r;}return zt(0,this.u32)}equal(e,t){for(let{u8:n,byteStride:s}of this.attributes)for(let r=0;r<s;r++)if(n[e*s+r]!==n[t*s+r])return false;return true}};function zt(e,t){for(let r=0,i=t.length;r<i;r++){let o=t[r];o=Math.imul(o,1540483477)>>>0,o=(o^o>>24)>>>0,o=Math.imul(o,1540483477)>>>0,e=Math.imul(e,1540483477)>>>0,e=(e^o)>>>0;}return e}a(zt,"murmurHash2");function Ft(e,t,n,s,r=v){let i=t-1,o=n.hash(s)&i;for(let a=0;a<=i;a++){let l=e[o];if(l===r||n.equal(l,s))return o;o=o+a+1&i;}throw new Error("Hash table full.")}a(Ft,"hashLookup");function We(e,t,n){let s=Document.fromGraph(e.getGraph());(!t||!n)&&([t,n]=Ut(e));let r=e.getIndices(),i=r?r.getArray():null,o=j(e,"render"),a=s.createAccessor(),l=o,g=Ve(l,n);for(let u=0;u<l;u++)g[u]=t[i?i[u]:u];e.setIndices(a.setArray(g));let c=te(e);for(let u of e.listAttributes()){let f=X(s,u);le(u,r,t,f,n),e.swap(u,f);}for(let u of e.listTargets())for(let f of u.listAttributes()){let d=X(s,f);le(f,r,t,d,n),u.swap(f,d);}r&&r.listParents().length===1&&r.dispose();for(let u of c)u.listParents().length===1&&u.dispose();return e}a(We,"compactPrimitive");function le(e,t,n,s,r){let i=e.getElementSize(),o=e.getArray(),a=t?t.getArray():null,l=t?t.getCount():e.getCount(),g=new o.constructor(r*i),c=new Uint8Array(r);for(let u=0;u<l;u++){let f=a?a[u]:u,d=n[f];if(!c[d]){for(let m=0;m<i;m++)g[d*i+m]=o[f*i+m];c[d]=1;}}return s.setArray(g)}a(le,"compactAttribute");function Ut(e){let t=j(e,"upload"),n=e.getIndices(),s=n?n.getArray():null;if(!n||!s)return [Ct(t,1e6),t];let r=new Uint32Array(t).fill(v),i=0;for(let o=0;o<s.length;o++){let a=s[o];r[a]===v&&(r[a]=i++);}return [r,i]}a(Ut,"createCompactPlan");function Gt(){var e=new Y(3);return Y!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e}a(Gt,"create$1");function Dt(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e[2]=t[2]*n[2],e}a(Dt,"multiply$1");function fe(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e}a(fe,"min");function ue(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e}a(ue,"max");function Ce(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e}a(Ce,"scale$1");function kt(e,t,n){var s=t[0],r=t[1],i=t[2],o=n[3]*s+n[7]*r+n[11]*i+n[15];return o=o||1,e[0]=(n[0]*s+n[4]*r+n[8]*i+n[12])/o,e[1]=(n[1]*s+n[5]*r+n[9]*i+n[13])/o,e[2]=(n[2]*s+n[6]*r+n[10]*i+n[14])/o,e}a(kt,"transformMat4");var Bt=Dt;(function(){var e=Gt();return function(t,n,s,r,i,o){var a,l;for(n||(n=3),s||(s=0),r?l=Math.min(r*n+s,t.length):l=t.length,a=s;a<l;a+=n)e[0]=t[a],e[1]=t[a+1],e[2]=t[a+2],i(e,e,o),t[a]=e[0],t[a+1]=e[1],t[a+2]=e[2];return t}})();var ge="weld",J={overwrite:true};function qt(e=J){let t=$(J,e);return _(ge,async n=>{let s=n.getLogger();if(n.hasExtension("KHR_mesh_primitive_restart"))throw new Error("weld: Missing support for KHR_mesh_primitive_restart.");for(let r of n.getRoot().listMeshes()){for(let i of r.listPrimitives())jt(i,t),j(i,"render")===0&&Rt(i);r.listPrimitives().length===0&&r.dispose();}s.debug(`${ge}: Complete.`);})}a(qt,"weld");function jt(e,t=J){let n=e.getGraph(),s=Document.fromGraph(n).getLogger(),r={...J,...t};if(e.getIndices()&&!r.overwrite||e.getMode()===Primitive.Mode.POINTS)return;let i=e.getAttribute("POSITION").getCount(),o=e.getIndices(),a=o?.getArray(),l=o?o.getCount():i,g=new Lt(e),c=vt(i+i/4),u=new Uint32Array(c).fill(v),f=new Uint32Array(i).fill(v),d=0;for(let m=0;m<l;m++){let A=a?a[m]:m;if(f[A]!==v)continue;let h=Ft(u,c,g,A,v),N=u[h];N===v?(u[h]=A,f[A]=d++):f[A]=f[N];}s.debug(`${ge}: ${wt(i,d)} vertices.`),We(e,f,d);}a(jt,"weldPrimitive");var{FLOAT:Ps}=Accessor.ComponentType;var{LINES:xs,LINE_STRIP:Os,LINE_LOOP:_s,TRIANGLES:$s,TRIANGLE_STRIP:Ls,TRIANGLE_FAN:zs}=Primitive.Mode;var x="dedup",ie={keepUniqueNames:false,propertyTypes:[PropertyType.ACCESSOR,PropertyType.MESH,PropertyType.TEXTURE,PropertyType.MATERIAL,PropertyType.SKIN]};function Xe(e=ie){let t=$(ie,e),n=new Set(t.propertyTypes);for(let s of t.propertyTypes)if(!ie.propertyTypes.includes(s))throw new Error(`${x}: Unsupported deduplication on type "${s}".`);return _(x,s=>{let r=s.getLogger();n.has(PropertyType.ACCESSOR)&&Ht(s),n.has(PropertyType.TEXTURE)&&Kt(s,t),n.has(PropertyType.MATERIAL)&&Wt(s,t),n.has(PropertyType.MESH)&&Vt(s,t),n.has(PropertyType.SKIN)&&Xt(s,t),r.debug(`${x}: Complete.`);})}a(Xe,"dedup");function Ht(e){let t=e.getLogger(),n=new Map,s=new Map,r=new Map,i=new Map,o=e.getRoot().listMeshes();o.forEach(u=>{u.listPrimitives().forEach(f=>{f.listAttributes().forEach(d=>a$1(d,s)),a$1(f.getIndices(),n);});});for(let u of e.getRoot().listAnimations())for(let f of u.listSamplers())a$1(f.getInput(),r),a$1(f.getOutput(),i);function a$1(u,f){if(!u)return;let d=[u.getCount(),u.getType(),u.getComponentType(),u.getNormalized(),u.getSparse()].join(":"),m=f.get(d);m||f.set(d,m=new Set),m.add(u);}a(a$1,"hashAccessor");function l(u,f){for(let d=0;d<u.length;d++){let m=u[d],A=BufferUtils.toView(m.getArray());if(!f.has(m))for(let h=d+1;h<u.length;h++){let N=u[h];f.has(N)||BufferUtils.equals(A,BufferUtils.toView(N.getArray()))&&f.set(N,m);}}}a(l,"detectDuplicates");let g=0,c=new Map;for(let u of [s,n,r,i])for(let f of u.values())g+=f.size,l(Array.from(f),c);t.debug(`${x}: Merged ${c.size} of ${g} accessors.`),o.forEach(u=>{u.listPrimitives().forEach(f=>{f.listAttributes().forEach(m=>{c.has(m)&&f.swap(m,c.get(m));});let d=f.getIndices();d&&c.has(d)&&f.swap(d,c.get(d));});});for(let u of e.getRoot().listAnimations())for(let f of u.listSamplers()){let d=f.getInput(),m=f.getOutput();d&&c.has(d)&&f.swap(d,c.get(d)),m&&c.has(m)&&f.swap(m,c.get(m));}Array.from(c.keys()).forEach(u=>u.dispose());}a(Ht,"dedupAccessors");function Vt(e,t){let n=e.getLogger(),s=e.getRoot(),r=new Map;s.listAccessors().forEach((a,l)=>r.set(a,l)),s.listMaterials().forEach((a,l)=>r.set(a,l));let i=s.listMeshes().length,o=new Map;for(let a of s.listMeshes()){let l=[];for(let c of a.listPrimitives())l.push(Ye(c,r));let g="";if(t.keepUniqueNames&&(g+=a.getName()+";"),g+=l.join(";"),o.has(g)){let c=o.get(g);a.listParents().forEach(u=>{u.propertyType!==PropertyType.ROOT&&u.swap(a,c);}),a.dispose();}else o.set(g,a);}n.debug(`${x}: Merged ${i-o.size} of ${i} meshes.`);}a(Vt,"dedupMeshes");function Kt(e,t){let n=e.getLogger(),s=e.getRoot(),r=s.listTextures(),i=new Map;for(let o=0;o<r.length;o++){let a=r[o],l=a.getImage();if(!i.has(a))for(let g=o+1;g<r.length;g++){let c=r[g],u=c.getImage();if(i.has(c)||a.getMimeType()!==c.getMimeType()||t.keepUniqueNames&&a.getName()!==c.getName())continue;let f=a.getSize(),d=c.getSize();!f||!d||f[0]===d[0]&&f[1]===d[1]&&(!l||!u||BufferUtils.equals(l,u)&&i.set(c,a));}}n.debug(`${x}: Merged ${i.size} of ${s.listTextures().length} textures.`),Array.from(i.entries()).forEach(([o,a])=>{o.listParents().forEach(l=>{l instanceof Root||l.swap(o,a);}),o.dispose();});}a(Kt,"dedupImages");function Wt(e,t){let n=e.getLogger(),s=e.getRoot().listMaterials(),r=new Map,i=new Map,o=new Set;t.keepUniqueNames||o.add("name");for(let a=0;a<s.length;a++){let l=s[a];if(!r.has(l)&&!ve(l,i))for(let g=a+1;g<s.length;g++){let c=s[g];r.has(c)||ve(c,i)||l.equals(c,o)&&r.set(c,l);}}n.debug(`${x}: Merged ${r.size} of ${s.length} materials.`),Array.from(r.entries()).forEach(([a,l])=>{a.listParents().forEach(g=>{g instanceof Root||g.swap(a,l);}),a.dispose();});}a(Wt,"dedupMaterials");function Xt(e,t){let n=e.getLogger(),s=e.getRoot().listSkins(),r=new Map,i=new Set(["joints"]);t.keepUniqueNames||i.add("name");for(let o=0;o<s.length;o++){let a=s[o];if(!r.has(a))for(let l=o+1;l<s.length;l++){let g=s[l];r.has(g)||a.equals(g,i)&&bt(a.listJoints(),g.listJoints())&&r.set(g,a);}}n.debug(`${x}: Merged ${r.size} of ${s.length} skins.`),Array.from(r.entries()).forEach(([o,a])=>{o.listParents().forEach(l=>{l instanceof Root||l.swap(o,a);}),o.dispose();});}a(Xt,"dedupSkins");function Ye(e,t){let n=[];for(let s of e.listSemantics()){let r=e.getAttribute(s);n.push(s+":"+t.get(r));}if(e instanceof Primitive){let s=e.getIndices();s&&n.push("indices:"+t.get(s));let r=e.getMaterial();r&&n.push("material:"+t.get(r)),n.push("mode:"+e.getMode());for(let i of e.listTargets())n.push("target:"+Ye(i,t));}return n.join(",")}a(Ye,"createPrimitiveKey");function ve(e,t){if(t.has(e))return t.get(e);let n=e.getGraph(),s=new Set,r=n.listParentEdges(e);for(;r.length>0;){let i=r.pop();if(i.getAttributes().modifyChild===true)return t.set(e,true),true;let o=i.getChild();if(!s.has(o))for(let a of n.listChildEdges(o))r.push(a);}return t.set(e,false),false}a(ve,"hasModifier");var{TEXTURE_INFO:Fs,ROOT:Us}=PropertyType;function Je(){var e=new Y(4);return Y!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0,e[3]=0),e}a(Je,"create");function Yt(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e[2]=t[2]+n[2],e[3]=t[3]+n[3],e}a(Yt,"add");function Jt(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e[2]=t[2]-n[2],e[3]=t[3]-n[3],e}a(Jt,"subtract");function Qt(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e[2]=t[2]*n[2],e[3]=t[3]*n[3],e}a(Qt,"multiply");function Zt(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e[3]=t[3]*n,e}a(Zt,"scale");function en(e){var t=e[0],n=e[1],s=e[2],r=e[3];return Math.sqrt(t*t+n*n+s*s+r*r)}a(en,"length");var Qe=Jt,tn=Qt,Ze=en;(function(){var e=Je();return function(t,n,s,r,i,o){var a,l;for(n||(n=4),s||(s=0),r?l=Math.min(r*n+s,t.length):l=t.length,a=s;a<l;a+=n)e[0]=t[a],e[1]=t[a+1],e[2]=t[a+2],e[3]=t[a+3],i(e,e,o),t[a]=e[0],t[a+1]=e[1],t[a+2]=e[2],t[a+3]=e[3];return t}})();var nn=/color|emissive|diffuse/i;function sn(e){return e.getGraph().listParentEdges(e).some(t=>t.getAttributes().isColor||nn.test(t.getName()))?"srgb":null}a(sn,"getTextureColorSpace");function rn(e){let t=e.getGraph(),n=new Set,s=new Set;function r(i){let o=new Set;for(let a of t.listChildEdges(i))a.getChild()instanceof Texture&&o.add(a.getName()+"Info");for(let a of t.listChildEdges(i)){let l=a.getChild();n.has(l)||(n.add(l),l instanceof TextureInfo&&o.has(a.getName())?s.add(l):l instanceof ExtensionProperty&&r(l));}}return a(r,"traverse"),r(e),Array.from(s)}a(rn,"listTextureInfoByMaterial");function et(e){let t=Document.fromGraph(e.getGraph()).getRoot(),n=e.getGraph().listParentEdges(e).filter(s=>s.getParent()!==t).map(s=>s.getName());return Array.from(new Set(n))}a(et,"listTextureSlots");var O="prune",pe=3/255,Pe={propertyTypes:[PropertyType.NODE,PropertyType.SKIN,PropertyType.MESH,PropertyType.CAMERA,PropertyType.PRIMITIVE,PropertyType.PRIMITIVE_TARGET,PropertyType.ANIMATION,PropertyType.MATERIAL,PropertyType.TEXTURE,PropertyType.ACCESSOR,PropertyType.BUFFER],keepLeaves:false,keepAttributes:false,keepIndices:false,keepSolidTextures:false,keepExtras:false};function Ae(e=Pe){let t=$(Pe,e),n=new Set(t.propertyTypes),s=t.keepExtras;return _(O,async r=>{let i=r.getLogger(),o=r.getRoot(),a$1=r.getGraph(),l=new on,g=a(c=>l.dispose(c.target),"onDispose");if(a$1.addEventListener("node:dispose",g),n.has(PropertyType.MESH))for(let c of o.listMeshes())c.listPrimitives().length>0||c.dispose();if(n.has(PropertyType.NODE)){if(!t.keepLeaves)for(let c of o.listScenes())tt(a$1,c,s);for(let c of o.listNodes())R(c,s);}if(n.has(PropertyType.SKIN))for(let c of o.listSkins())R(c,s);if(n.has(PropertyType.MESH))for(let c of o.listMeshes())R(c,s);if(n.has(PropertyType.CAMERA))for(let c of o.listCameras())R(c,s);if(n.has(PropertyType.PRIMITIVE)&&xe(a$1,PropertyType.PRIMITIVE,s),n.has(PropertyType.PRIMITIVE_TARGET)&&xe(a$1,PropertyType.PRIMITIVE_TARGET,s),!t.keepAttributes&&n.has(PropertyType.ACCESSOR)){let c=new Map;for(let u of o.listMeshes())for(let f of u.listPrimitives()){let d=f.getMaterial();if(!d)continue;let m=an(f,nt(r,f,d));Oe(f,m),f.listTargets().forEach(A=>Oe(A,m)),c.has(d)?c.get(d).add(f):c.set(d,new Set([f]));}for(let[u,f]of c)cn(u,Array.from(f));}if(n.has(PropertyType.ANIMATION))for(let c of o.listAnimations()){for(let u of c.listChannels())u.getTargetNode()||u.dispose();if(c.listChannels().length)c.listSamplers().forEach(u=>R(u,s));else {let u=c.listSamplers();R(c,s),u.forEach(f=>R(f,s));}}if(n.has(PropertyType.MATERIAL)&&o.listMaterials().forEach(c=>R(c,s)),n.has(PropertyType.TEXTURE)&&(o.listTextures().forEach(c=>R(c,s)),t.keepSolidTextures||await ln(r)),n.has(PropertyType.ACCESSOR)&&o.listAccessors().forEach(c=>R(c,s)),n.has(PropertyType.BUFFER)&&o.listBuffers().forEach(c=>R(c,s)),a$1.removeEventListener("node:dispose",g),l.empty())i.debug(`${O}: No unused properties found.`);else {let c=l.entries().map(([u,f])=>`${u} (${f})`).join(", ");i.info(`${O}: Removed types... ${c}`);}i.debug(`${O}: Complete.`);})}a(Ae,"prune");var on=class{static{a(this,"DisposeCounter");}disposed={};empty(){for(let e in this.disposed)return false;return true}entries(){return Object.entries(this.disposed)}dispose(e){this.disposed[e.propertyType]=this.disposed[e.propertyType]||0,this.disposed[e.propertyType]++;}};function R(e,t){let n=e.listParents().filter(r=>!(r instanceof Root||r instanceof AnimationChannel)),s=t&&!Ke(e.getExtras());!n.length&&!s&&e.dispose();}a(R,"treeShake");function xe(e,t,n){for(let s of e.listEdges()){let r=s.getParent();r.propertyType===t&&R(r,n);}}a(xe,"indirectTreeShake");function tt(e,t,n){if(t.listChildren().forEach(o=>tt(e,o,n)),t instanceof Scene)return;let s=e.listParentEdges(t).some(o=>{let a=o.getParent().propertyType;return a!==PropertyType.ROOT&&a!==PropertyType.SCENE&&a!==PropertyType.NODE}),r=e.listChildren(t).length===0,i=n&&!Ke(t.getExtras());r&&!s&&!i&&t.dispose();}a(tt,"nodeTreeShake");function Oe(e,t){for(let n of t)e.setAttribute(n,null);}a(Oe,"pruneAttributes");function an(e,t){let n=[];for(let s of e.listSemantics())(s==="NORMAL"&&!t.has(s)||s==="TANGENT"&&!t.has(s)||s.startsWith("TEXCOORD_")&&!t.has(s)||s.startsWith("COLOR_")&&s!=="COLOR_0")&&n.push(s);return n}a(an,"listUnusedSemantics");function nt(e,t,n,s=new Set){let r=e.getGraph().listChildEdges(n),i=new Set;for(let l of r)l.getChild()instanceof Texture&&i.add(l.getName());for(let l of r){let g=l.getName(),c=l.getChild();c instanceof TextureInfo&&i.has(g.replace(/Info$/,""))&&s.add(`TEXCOORD_${c.getTexCoord()}`),c instanceof Texture&&g.match(/normalTexture/i)&&s.add("TANGENT"),c instanceof ExtensionProperty&&nt(e,t,c,s);}let o=n instanceof Material&&!n.getExtension("KHR_materials_unlit"),a=t.getMode()===Primitive.Mode.POINTS;return o&&!a&&s.add("NORMAL"),s}a(nt,"listRequiredSemantics");function cn(e,t){let n=rn(e),s=new Set(n.map(l=>l.getTexCoord())),r=Array.from(s).sort(),i=new Map(r.map((l,g)=>[l,g])),o=new Map(r.map((l,g)=>[`TEXCOORD_${l}`,`TEXCOORD_${g}`]));for(let l of n){let g=l.getTexCoord();l.setTexCoord(i.get(g));}for(let l of t){let g=l.listSemantics().filter(c=>c.startsWith("TEXCOORD_")).sort();a$1(l,g),l.listTargets().forEach(c=>a$1(c,g));}function a$1(l,g){for(let c of g){let u=l.getAttribute(c);if(!u)continue;let f=o.get(c);f!==c&&(l.setAttribute(f,u),l.setAttribute(c,null));}}a(a$1,"updatePrim");}a(cn,"shiftTexCoords");async function ln(e){let t=e.getRoot(),n=e.getGraph(),s=e.getLogger(),r=t.listTextures().map(async i=>{let o=await un(i);if(!o)return;sn(i)==="srgb"&&ColorUtils.convertSRGBToLinear(o,o);let a=i.getName()||i.getURI(),l=i.getSize()?.join("x"),g=et(i);for(let c of n.listParentEdges(i)){let u=c.getParent();u!==t&&fn(u,o,c.getName(),s)&&c.dispose();}i.listParents().length===1&&(i.dispose(),s.debug(`${O}: Removed solid-color texture "${a}" (${l}px ${g.join(", ")})`));});await Promise.all(r);}a(ln,"pruneSolidTextures");function fn(e,t,n,s){if(e instanceof Material)switch(n){case "baseColorTexture":return e.setBaseColorFactor(tn(t,t,e.getBaseColorFactor())),true;case "emissiveTexture":return e.setEmissiveFactor(Bt([0,0,0],t.slice(0,3),e.getEmissiveFactor())),true;case "occlusionTexture":return Math.abs(t[0]-1)<=pe;case "metallicRoughnessTexture":return e.setRoughnessFactor(t[1]*e.getRoughnessFactor()),e.setMetallicFactor(t[2]*e.getMetallicFactor()),true;case "normalTexture":return Ze(Qe(Je(),t,[.5,.5,1,1]))<=pe}return s.warn(`${O}: Detected single-color ${n} texture. Pruning ${n} not yet supported.`),false}a(fn,"applyMaterialFactor");async function un(e){let t=await gn(e);if(!t)return null;let n=[1/0,1/0,1/0,1/0],s=[-1/0,-1/0,-1/0,-1/0],r=[0,0,0,0],[i,o]=t.shape;for(let a=0;a<i;a++){for(let l=0;l<o;l++)for(let g=0;g<4;g++)n[g]=Math.min(n[g],t.get(a,l,g)),s[g]=Math.max(s[g],t.get(a,l,g));if(Ze(Qe(r,s,n))/255>pe)return null}return Zt(r,Yt(r,s,n),.5/255)}a(un,"getTextureFactor");async function gn(e){try{return await ye(e.getImage(),e.getMimeType())}catch{return null}}a(gn,"maybeGetPixels");var{ROOT:Ds,NODE:ks,MESH:Bs,PRIMITIVE:qs,ACCESSOR:js}=PropertyType;function pn(e,t=1/0){if(Number.isFinite(t)&&t%4||t<=0)throw new Error("Limit must be positive multiple of four.");let n=e.getAttribute("POSITION").getCount(),s=e.listSemantics().filter(g=>g.startsWith("WEIGHTS_")).length,r=new Uint16Array(s*4),i=new Float32Array(s*4),o=new Float32Array(s*4),a=new Uint32Array(s*4),l=new Uint32Array(s*4);for(let g=0;g<n;g++){Q(e,g,"WEIGHTS",i),Q(e,g,"JOINTS",a);for(let c=0;c<s*4;c++)r[c]=c;r.sort((c,u)=>i[c]>i[u]?-1:1);for(let c=0;c<r.length;c++)o[c]=i[r[c]],l[c]=a[r[c]];Z(e,g,"WEIGHTS",o),Z(e,g,"JOINTS",l);}for(let g=s;g*4>t;g--){let c=e.getAttribute(`WEIGHTS_${g-1}`),u=e.getAttribute(`JOINTS_${g-1}`);e.setAttribute(`WEIGHTS_${g-1}`,null),e.setAttribute(`JOINTS_${g-1}`,null),c.listParents().length===1&&c.dispose(),u.listParents().length===1&&u.dispose();}dn(e);}a(pn,"sortPrimitiveWeights");function dn(e){if(!hn(e))return;let t=e.getAttribute("POSITION").getCount(),n=e.listSemantics().filter(u=>u.startsWith("WEIGHTS_")).length,s=e.getAttribute("WEIGHTS_0"),r=s.getArray(),i=s.getComponentType(),o=s.getNormalized(),a=o?i:void 0,l=o?MathUtils.decodeNormalizedInt(1,i):Number.EPSILON,g=new Uint32Array(n*4).fill(0),c=r.slice(0,n*4).fill(0);for(let u=0;u<t;u++){Q(e,u,"JOINTS",g),Q(e,u,"WEIGHTS",c,a);let f=_e(c,a);if(f!==0&&f!==1){if(Math.abs(1-f)>l)for(let d=0;d<c.length;d++)if(o){let m=MathUtils.decodeNormalizedInt(c[d],i);c[d]=MathUtils.encodeNormalizedInt(m/f,i);}else c[d]/=f;if(f=_e(c,a),o&&f!==1){for(let d=c.length-1;d>=0;d--)if(c[d]>0){let m=1-f;c[d]+=Math.sign(m)*MathUtils.encodeNormalizedInt(Math.abs(m),i);break}}}for(let d=c.length-1;d>=0;d--)c[d]===0&&(g[d]=0);Z(e,u,"JOINTS",g),Z(e,u,"WEIGHTS",c,a);}}a(dn,"normalizePrimitiveWeights");function Q(e,t,n,s,r){let i,o=[0,0,0,0];for(let a=0;i=e.getAttribute(`${n}_${a}`);a++){i.getElement(t,o);for(let l=0;l<4;l++)r?s[a*4+l]=MathUtils.encodeNormalizedInt(o[l],r):s[a*4+l]=o[l];}return s}a(Q,"getVertexArray");function Z(e,t,n,s,r){let i,o=[0,0,0,0];for(let a=0;i=e.getAttribute(`${n}_${a}`);a++){for(let l=0;l<4;l++)r?o[l]=MathUtils.decodeNormalizedInt(s[a*4+l],r):o[l]=s[a*4+l];i.setElement(t,o);}}a(Z,"setVertexArray");function _e(e,t){let n=0;for(let s=0;s<e.length;s++)t?n+=MathUtils.decodeNormalizedInt(e[s],t):n+=e[s];return n}a(_e,"sum");function hn(e){let t=e.listSemantics().filter(r=>r.startsWith("WEIGHTS_")).map(r=>e.getAttribute(r)),n=t.map(r=>r.getNormalized()),s=t.map(r=>r.getComponentType());return new Set(n).size===1&&new Set(s).size===1}a(hn,"isNormalizeSafe");var P="quantize",mn=[Int8Array,Int16Array,Int32Array],{TRANSLATION:An,ROTATION:yn,SCALE:Tn,WEIGHTS:En}=AnimationChannel.TargetPath,In=[An,yn,Tn],W={pattern:/.*/,quantizationVolume:"mesh",quantizePosition:14,quantizeNormal:10,quantizeTexcoord:12,quantizeColor:8,quantizeWeight:8,quantizeGeneric:12,normalizeWeights:true,cleanup:true};function Sn(e=W){let t=$(W,{patternTargets:e.pattern||W.pattern,...e});return _(P,async n=>{let s=n.getLogger(),r=n.getRoot();if(n.hasExtension("KHR_mesh_primitive_restart"))throw new Error("quantize: Missing support for KHR_mesh_primitive_restart.");let i;t.quantizationVolume==="scene"&&(i=Le(Pn(r.listMeshes().map(ze))));for(let o of n.getRoot().listMeshes()){t.quantizationVolume==="mesh"&&(i=Le(ze(o))),i&&t.pattern.test("POSITION")&&(Nn(n,o,i),Rn(o,1/i.scale));for(let a of o.listPrimitives()){j(a,"render")<j(a,"upload")/2&&We(a),$e(n,a,i,t);for(let l of a.listTargets())$e(n,l,i,t);}}r.listMeshes().flatMap(o=>o.listPrimitives()).some(st)&&n.createExtension(KHRMeshQuantization).setRequired(true),t.cleanup&&await n.transform(Ae({propertyTypes:[PropertyType.ACCESSOR,PropertyType.SKIN,PropertyType.MATERIAL],keepAttributes:true,keepIndices:true,keepLeaves:true,keepSolidTextures:true}),Xe({propertyTypes:[PropertyType.ACCESSOR,PropertyType.MATERIAL,PropertyType.SKIN],keepUniqueNames:true})),s.debug(`${P}: Complete.`);})}a(Sn,"quantize");function $e(e,t,n,s){let r=t instanceof PrimitiveTarget,i=e.getLogger();for(let o of t.listSemantics()){if(!r&&!s.pattern.test(o)||r&&!s.patternTargets.test(o))continue;let a=t.getAttribute(o),{bits:l,ctor:g}=Cn(o,a,i,s);if(!g)continue;if(l<8||l>16)throw new Error(`${P}: Requires bits = 8\u201316.`);if(a.getComponentSize()<=l/8)continue;let c=a.clone();if(o==="POSITION"){let u=n.scale,f=[];t instanceof Primitive?Pt(f,ne(n)):xt(f,[1/u,1/u,1/u]);for(let d=0,m=[0,0,0],A=c.getCount();d<A;d++)c.getElement(d,m),c.setElement(d,kt(m,m,f));}bn(c,g,l),t.setAttribute(o,c);}if(s.normalizeWeights&&t.getAttribute("WEIGHTS_0")&&pn(t,1/0),t instanceof Primitive&&t.getIndices()&&t.listAttributes().length&&t.listAttributes()[0].getCount()<65535){let o=t.getIndices();o.setArray(new Uint16Array(o.getArray()));}}a($e,"quantizePrimitive");function Le(e){let{min:t,max:n}=e,s=Math.max((n[0]-t[0])/2,(n[1]-t[1])/2,(n[2]-t[2])/2);return {offset:[t[0]+(n[0]-t[0])/2,t[1]+(n[1]-t[1])/2,t[2]+(n[2]-t[2])/2],scale:s}}a(Le,"getNodeTransform");function Nn(e,t,n){let s=ne(n);for(let r of t.listParents()){if(!(r instanceof Node))continue;let i=r.listParents().filter(f=>f instanceof AnimationChannel),o=i.some(f=>In.includes(f.getTargetPath())),a=r.listChildren().length>0,l=r.getSkin();if(l){r.setSkin(Mn(l,n));continue}let g=r.getExtension("EXT_mesh_gpu_instancing");if(g){r.setExtension("EXT_mesh_gpu_instancing",wn(e,g,n));continue}let c;a||o?(c=e.createNode("").setMesh(t),r.addChild(c).setMesh(null),i.filter(f=>f.getTargetPath()===En).forEach(f=>f.setTargetNode(c))):c=r;let u=c.getMatrix();me(u,u,s),c.setMatrix(u);}}a(Nn,"transformMeshParents");function Mn(e,t){e=e.clone();let n=ne(t),s=e.getInverseBindMatrices().clone(),r=[];for(let i=0,o=s.getCount();i<o;i++)s.getElement(i,r),me(r,r,n),s.setElement(i,r);return e.setInverseBindMatrices(s)}a(Mn,"transformSkin");function wn(e,t,n){if(!t.getAttribute("TRANSLATION")&&!t.getAttribute("ROTATION")&&!t.getAttribute("SCALE"))return t;t=t.clone();let s=t.getAttribute("TRANSLATION")?.clone(),r=t.getAttribute("ROTATION")?.clone(),i=t.getAttribute("SCALE")?.clone(),o=s||r||i,a=[0,0,0],l=[0,0,0,1],g=[1,1,1];!s&&n.offset&&(s=e.createAccessor().setType("VEC3").setArray(Ue(o.getCount(),a))),!i&&n.scale&&(i=e.createAccessor().setType("VEC3").setArray(Ue(o.getCount(),g)));let c=[0,0,0],u=[0,0,0,1],f=[1,1,1],d=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],m=ne(n);for(let A=0,h=o.getCount();A<h;A++)MathUtils.compose(s?s.getElement(A,c):a,r?r.getElement(A,u):l,i?i.getElement(A,f):g,d),me(d,d,m),MathUtils.decompose(d,c,u,f),s&&s.setElement(A,c),r&&r.setElement(A,u),i&&i.setElement(A,f);return s&&t.setAttribute("TRANSLATION",s),r&&t.setAttribute("ROTATION",r),i&&t.setAttribute("SCALE",i),t}a(wn,"transformBatch");function Rn(e,t){for(let n of e.listPrimitives()){let s=n.getMaterial();if(!s)continue;let r=s.getExtension("KHR_materials_volume");!r||r.getThicknessFactor()<=0||(r=r.clone().setThicknessFactor(r.getThicknessFactor()*t),s=s.clone().setExtension("KHR_materials_volume",r),n.setMaterial(s));}}a(Rn,"transformMeshMaterials");function bn(e,t,n){let s=new t(e.getArray().length),r=mn.includes(t)?1:0,i=n-r,o=t.BYTES_PER_ELEMENT*8-r,a=Math.pow(2,i)-1,l=o-i,g=2*i-o,c=[r>0?-1:0,1];for(let u=0,f=0,d=[];u<e.getCount();u++){e.getElement(u,d);for(let m=0;m<d.length;m++){let A=xn(d[m],c);A=Math.round(Math.abs(A)*a),A=A<<l|A>>g,s[f++]=A*Math.sign(d[m]);}}e.setArray(s).setNormalized(true).setSparse(false);}a(bn,"quantizeAttribute");function Cn(e,t,n,s){let r=t.getMinNormalized([]),i=t.getMaxNormalized([]),o,a;if(e==="POSITION")o=s.quantizePosition,a=o<=8?Int8Array:Int16Array;else if(e==="NORMAL"||e==="TANGENT")o=s.quantizeNormal,a=o<=8?Int8Array:Int16Array;else if(e.startsWith("COLOR_"))o=s.quantizeColor,a=o<=8?Uint8Array:Uint16Array;else if(e.startsWith("TEXCOORD_")){if(r.some(l=>l<0)||i.some(l=>l>1))return n.warn(`${P}: Skipping ${e}; out of [0,1] range.`),{bits:-1};o=s.quantizeTexcoord,a=o<=8?Uint8Array:Uint16Array;}else {if(e.startsWith("JOINTS_"))return o=Math.max(...t.getMax([]))<=255?8:16,a=o<=8?Uint8Array:Uint16Array,t.getComponentSize()>o/8&&t.setArray(new a(t.getArray())),{bits:-1};if(e.startsWith("WEIGHTS_")){if(r.some(l=>l<0)||i.some(l=>l>1))return n.warn(`${P}: Skipping ${e}; out of [0,1] range.`),{bits:-1};o=s.quantizeWeight,a=o<=8?Uint8Array:Uint16Array;}else if(e.startsWith("_")){if(r.some(l=>l<-1)||i.some(l=>l>1))return n.warn(`${P}: Skipping ${e}; out of [-1,1] range.`),{bits:-1};o=s.quantizeGeneric,a=r.some(l=>l<0)?a=o<=8?Int8Array:Int16Array:a=o<=8?Uint8Array:Uint16Array;}else throw new Error(`${P}: Unexpected semantic, "${e}".`)}return {bits:o,ctor:a}}a(Cn,"getQuantizationSettings");function ze(e){let t=[],n=[];for(let r of e.listPrimitives()){let i=r.getAttribute("POSITION");i&&t.push(i);for(let o of r.listTargets()){let a=o.getAttribute("POSITION");a&&n.push(a);}}if(t.length===0)throw new Error(`${P}: Missing "POSITION" attribute.`);let s=Fe(t,3);if(n.length>0){let{min:r,max:i}=Fe(n,3);fe(s.min,s.min,fe(r,Ce(r,r,2),[0,0,0])),ue(s.max,s.max,ue(i,Ce(i,i,2),[0,0,0]));}return s}a(ze,"getPositionQuantizationVolume");function vn(e,t){let n=t.getComponentSize();if(e==="POSITION"||e==="NORMAL"||e==="TANGENT")return n<4;if(e.startsWith("TEXCOORD_")){let s=t.getComponentType(),r=t.getNormalized();return n<4&&!(r&&s===Accessor.ComponentType.UNSIGNED_BYTE)&&!(r&&s===Accessor.ComponentType.UNSIGNED_SHORT)}return false}a(vn,"isQuantizedAttribute");function st(e){for(let t of e.listSemantics())if(vn(t,e.getAttribute("POSITION")))return true;return e.propertyType===PropertyType.PRIMITIVE?e.listTargets().some(st):false}a(st,"isQuantizedPrimitive");function Fe(e,t){let n=new Array(t).fill(1/0),s=new Array(t).fill(-1/0),r=[],i=[];for(let o of e){o.getMinNormalized(r),o.getMaxNormalized(i);for(let a=0;a<t;a++)n[a]=Math.min(n[a],r[a]),s[a]=Math.max(s[a],i[a]);}return {min:n,max:s}}a(Fe,"flatBounds");function Pn(e){let t=e[0];for(let n of e)fe(t.min,t.min,n.min),ue(t.max,t.max,n.max);return t}a(Pn,"expandBounds");function ne(e){return Ot([],[0,0,0,1],e.offset,[e.scale,e.scale,e.scale])}a(ne,"fromTransform");function xn(e,t){return Math.min(Math.max(e,t[0]),t[1])}a(xn,"clamp");function Ue(e,t){let n=t.length,s=new Float32Array(e*n);for(let r=0;r<e;r++)s.set(t,r*n);return s}a(Ue,"makeArray");var V="reorder",On={target:"size",cleanup:true};function _n(e){let t=$(On,e),n=t.encoder;if(!n)throw new Error(`${V}: encoder dependency required \u2014 install "meshoptimizer".`);return _(V,async s=>{let r=s.getLogger();if(s.hasExtension("KHR_mesh_primitive_restart"))throw new Error("reorder: Missing support for KHR_mesh_primitive_restart.");await n.ready;let i=$n(s);for(let o of i.indicesToAttributes.keys()){let a=o.getArray();a instanceof Uint32Array?a=a.slice():a=new Uint32Array(a);let[l,g]=n.reorderMesh(a,i.indicesToMode.get(o)===Primitive.Mode.TRIANGLES,t.target==="size"),c=X(s,o);c.setArray(g<=65534?new Uint16Array(a):a);for(let u of i.indicesToAttributes.get(o)){let f=X(s,u);le(u,o,l,f,g);for(let d of i.indicesToPrimitives.get(o)){d.getIndices()===o&&d.swap(o,c),d.swap(u,f);for(let m of d.listTargets())m.swap(u,f);}}}t.cleanup&&await s.transform(Ae({propertyTypes:[PropertyType.ACCESSOR],keepAttributes:true,keepIndices:true})),i.indicesToAttributes.size?r.debug(`${V}: Complete.`):r.warn(`${V}: No qualifying primitives found; may need to weld first.`);})}a(_n,"reorder");function $n(e){let t=new Map,n=new oe,s=new oe,r=new oe;for(let i of e.getRoot().listMeshes())for(let o of i.listPrimitives()){let a=o.getIndices();if(a){t.set(a,o.getMode()),n.add(a,o);for(let l of te(o))s.add(a,l),r.add(l,o);}}return {indicesToPrimitives:n,indicesToAttributes:s,indicesToMode:t,attributesToPrimitives:r}}a($n,"createLayoutPlan");var Ln={level:"high",...W},Ge="meshopt";function zn(e){let t=$(Ln,e),n=t.encoder;if(!n)throw new Error(`${Ge}: encoder dependency required \u2014 install "meshoptimizer".`);return _(Ge,async s=>{let r,i,o=t.quantizeNormal;if(s.getRoot().listAccessors().length!==0){if(s.hasExtension("KHR_mesh_primitive_restart"))throw new Error("meshopt: Missing support for KHR_mesh_primitive_restart.");t.level==="medium"?(r=/.*/,i=/.*/):(r=/^(POSITION|TEXCOORD|JOINTS|WEIGHTS|COLOR)(_\d+)?$/,i=/^(POSITION|TEXCOORD|JOINTS|WEIGHTS|COLOR|NORMAL|TANGENT)(_\d+)?$/,o=Math.min(o,8)),await s.transform(_n({encoder:n,target:"size"}),Sn({...t,pattern:r,patternTargets:i,quantizeNormal:o})),s.createExtension(EXTMeshoptCompression).setRequired(true).setEncoderOptions({method:t.level==="medium"?EXTMeshoptCompression.EncoderMethod.QUANTIZE:EXTMeshoptCompression.EncoderMethod.FILTER});}})}a(zn,"meshopt");var De;(function(e){e[e.STEP=0]="STEP",e[e.LERP=1]="LERP",e[e.SLERP=2]="SLERP";})(De||(De={}));var Fn=1e-6;function Un(e,t,n,s=1e-4){let r=t.length/e.length,i=new Array(r).fill(0),o=new Array(r).fill(0),a=new Array(r).fill(0),l=new Array(r).fill(0),g=e.length-1,c=1;for(let u=1;u<g;++u){let f=e[c-1],d=e[u],m=e[u+1],A=(d-f)/(m-f),h=false;if(d!==m&&(u!==1||d!==e[0]))if(B(t,c-1,l),B(t,u,o),B(t,u+1,a),n==="slerp"){let N=kn(i,l,a,A),w=Be(l,o)+Be(o,a);h=!K(o,N,s)||w+Number.EPSILON>=Math.PI;}else n==="lerp"?h=!K(o,Dn(i,l,a,A),s):n==="step"&&(h=!K(o,l)||!K(o,a));h&&(u!==c&&(e[c]=e[u],ke(t,c,B(t,u,i))),c++);}return g>0&&(e[c]=e[g],ke(t,c,B(t,g,i)),c++),c}a(Un,"resampleDebug");function B(e,t,n){for(let s=0,r=n.length;s<r;s++)n[s]=e[t*r+s];return n}a(B,"getElement");function ke(e,t,n){for(let s=0,r=n.length;s<r;s++)e[t*r+s]=n[s];}a(ke,"setElement");function K(e,t,n=0){if(e.length!==t.length)return false;for(let s=0;s<e.length;s++)if(Math.abs(e[s]-t[s])>n)return false;return true}a(K,"eq");function Gn(e,t,n){return e*(1-n)+t*n}a(Gn,"lerp");function Dn(e,t,n,s){for(let r=0;r<t.length;r++)e[r]=Gn(t[r],n[r],s);return e}a(Dn,"vlerp");function kn(e,t,n,s){let r=t[0],i=t[1],o=t[2],a=t[3],l=n[0],g=n[1],c=n[2],u=n[3],f,d,m,A,h;return d=r*l+i*g+o*c+a*u,d<0&&(d=-d,l=-l,g=-g,c=-c,u=-u),1-d>Fn?(f=Math.acos(d),m=Math.sin(f),A=Math.sin((1-s)*f)/m,h=Math.sin(s*f)/m):(A=1-s,h=s),e[0]=A*r+h*l,e[1]=A*i+h*g,e[2]=A*o+h*c,e[3]=A*a+h*u,e}a(kn,"slerp");function Be(e,t){let n=Bn(e,t);return Math.acos(2*n*n-1)}a(Be,"getAngle");function Bn(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]}a(Bn,"dot");({ready:Promise.resolve()});var{POINTS:Vs,LINES:Ks,LINE_STRIP:Ws,LINE_LOOP:Xs,TRIANGLES:Ys,TRIANGLE_STRIP:Js,TRIANGLE_FAN:Qs}=Primitive.Mode;/*! Bundled license information:
3
+
4
+ is-buffer/index.js:
5
+ (*!
6
+ * Determine if an object is a Buffer
7
+ *
8
+ * @author Feross Aboukhadijeh <https://feross.org>
9
+ * @license MIT
10
+ *)
11
+ */export{Xe as dedup,et as listTextureSlots,zn as meshopt,Ae as prune,qt as weld};