minidraco 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,10 +21,29 @@ gltfLoader.setDRACOLoader(new MiniDRACOLoader())
21
21
  gltfLoader.load('model.glb', gltf => scene.add(gltf.scene))
22
22
  ```
23
23
 
24
- `MiniDRACOLoader` is API-compatible with `THREE.DRACOLoader` (`setDecoderPath` and friends are
25
- no-ops). Decoding runs in a pool of module workers (default 4, `setWorkerLimit(n)` to change,
26
- `0` to force synchronous main-thread decoding). If workers can't be spawned (SSR, exotic
27
- bundlers), it falls back to synchronous decoding automatically.
24
+ `MiniDRACOLoader` is a structural drop-in for `THREE.DRACOLoader`: it's assignable to it with no
25
+ cast on any three version (`setDecoderPath` and friends are no-ops), so
26
+ `gltfLoader.setDRACOLoader(new MiniDRACOLoader())` just type-checks.
27
+
28
+ Decoding runs in a pool of module workers by default (parallel across primitives, main thread
29
+ stays free). If workers can't be spawned (SSR, exotic bundlers), it falls back to synchronous
30
+ decoding automatically. Configure it at construction or with fluent setters:
31
+
32
+ ```ts
33
+ new MiniDRACOLoader({ workers: false }) // decode synchronously on the main thread
34
+ new MiniDRACOLoader({ workerLimit: 8 }) // pool size (default 4)
35
+ new MiniDRACOLoader(loadingManager) // a three.js LoadingManager, as usual
36
+
37
+ const loader = new MiniDRACOLoader()
38
+ loader.setWorkers(false) // ...or toggle later (same as setWorkerLimit(0))
39
+ ```
40
+
41
+ **Serving JS from a CDN origin** (Next.js `assetPrefix`, etc.) works out of the box: browsers
42
+ refuse to construct a Worker from a cross-origin script, so minidraco bootstraps the worker
43
+ through a same-origin blob module that imports the hashed CDN asset (a CORS request — your CDN
44
+ must send `Access-Control-Allow-Origin`, which it already does if you load models or fonts from
45
+ it). If even that fails, decoding falls back to the main thread rather than erroring.
46
+ `setWorkerUrl(url)` exists as a manual override for exotic setups.
28
47
 
29
48
  Or decode a raw Draco bitstream without Three.js:
30
49
 
@@ -48,24 +67,35 @@ const mesh = decodeDracoMesh(new Uint8Array(bytes))
48
67
 
49
68
  ## Performance
50
69
 
51
- Decoding the three production bundle GLBs in `example/public/models` (Apple Silicon, medians;
52
- `bun run bench` for the harness). Raw single-threaded decode, bun/JSC:
53
-
54
- | file (points / faces) | minidraco | draco.js | draco3d wasm |
55
- | ------------------------------------ | --------- | -------- | ------------ |
56
- | canine (1.1k / 0.5k) | 0.6 ms | 0.6 ms | 0.4 ms |
57
- | player (5.1k / 2.5k) | 1.9 ms | 1.7 ms | 1.2 ms |
58
- | static (291k / 221k, 488 primitives) | **50 ms** | 55 ms | 51 ms |
70
+ Full cross-decoder results — the production bundles plus the 17 sample models shipped with
71
+ [mrdoob/draco.js](https://github.com/mrdoob/draco.js) are in
72
+ [BENCH.md](https://github.com/verekia/minidraco/blob/main/BENCH.md), regenerated by
73
+ `bun run bench` (with machine-readable
74
+ [BENCH.json](https://github.com/verekia/minidraco/blob/main/BENCH.json) alongside for diffing
75
+ perf work). Highlights, decoding the production bundle GLBs in
76
+ `example/public/models` (Apple Silicon, medians). Raw single-threaded decode, bun/JSC:
77
+
78
+ | file (points / faces) | minidraco | draco.js | draco3d wasm |
79
+ | ---------------------------------------------- | --------- | -------- | ------------ |
80
+ | manablade-characters (5.1k / 2.5k) | 1.9 ms | 1.7 ms | 1.2 ms |
81
+ | manablade-static (291k / 221k, 488 primitives) | **50 ms** | 55 ms | 51 ms |
82
+
83
+ The `/bench` page of the example runs the same fair comparison in the browser (V8): a raw
84
+ single-threaded mode where all three decoders decode on the main thread, over the bundles plus
85
+ the draco.js sample models (synced locally by `bun dev`, never deployed). Browser runs — both
86
+ the single-threaded mode and the multi-threaded GLTFLoader wall clock — are tracked in
87
+ [BENCH.browser.json](https://github.com/verekia/minidraco/blob/main/BENCH.browser.json) via the
88
+ page's "Save to BENCH.browser.json" button (local dev only).
59
89
 
60
90
  In the browser the worker pool changes the story for real scenes — wall-clock
61
- `GLTFLoader.parse` of the 488-primitive static bundle (Chromium, warm loaders, `/bench` page of
62
- the example):
91
+ `GLTFLoader.parse` of the 488-primitive manablade-static bundle (Chromium, warm loaders, `/bench`
92
+ page of the example):
63
93
 
64
- | decoder | static bundle | main thread |
65
- | ------------------------ | ------------- | ----------- |
66
- | minidraco (4 workers) | ~51 ms | free |
67
- | draco.js (main thread) | ~72 ms | blocked |
68
- | draco3d wasm (4 workers) | ~23 ms | free |
94
+ | decoder | manablade-static | main thread |
95
+ | ------------------------ | ---------------- | ----------- |
96
+ | minidraco (4 workers) | ~51 ms | free |
97
+ | draco.js (main thread) | ~72 ms | blocked |
98
+ | draco3d wasm (4 workers) | ~23 ms | free |
69
99
 
70
100
  And unlike the wasm decoder there is nothing to host or fetch: the first decode doesn't pay the
71
101
  ~50–70 ms wasm download + compile + worker bootstrap, which typically makes minidraco the fastest
@@ -99,7 +129,7 @@ decode, while the JS decoders ship inside your existing bundle chunks.
99
129
  bun install
100
130
  bun dev # library watch build + example dev server
101
131
  bun run all # format check, lint, typecheck, warden, tests
102
- bun run bench # decoder comparison benchmark (bun)
132
+ bun run bench # decoder comparison benchmark (bun) — rewrites BENCH.md
103
133
  ```
104
134
 
105
135
  The test suite decodes every Draco primitive of the bundle GLBs with minidraco and the official
package/dist/index.d.ts CHANGED
@@ -25,6 +25,7 @@ declare class DecoderBuffer {
25
25
  decodeFloat32(): number | undefined;
26
26
  decodeUint64(): number | undefined;
27
27
  decodeBytes(size: number): Uint8Array | undefined;
28
+ decodeBytesView(size: number): Uint8Array | undefined;
28
29
  startBitDecoding(decodeSize: boolean): number | undefined;
29
30
  endBitDecoding(): void;
30
31
  decodeLeastSignificantBits32(nbits: number): number | undefined;
@@ -162,8 +163,6 @@ declare class Mesh extends PointCloud {
162
163
  elementType: number;
163
164
  }[];
164
165
  constructor();
165
- _ensureFaceCapacity(numFaces: number): void;
166
- addFace(face: ArrayLike<number>): void;
167
166
  setNumFaces(numFaces: number): void;
168
167
  numFaces(): number;
169
168
  face(faceId: number): number[];