@draco-rust/decoder 0.1.0 → 0.1.2

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
@@ -11,10 +11,14 @@ Each entry is a separate module. A bundler includes only the one you import.
11
11
 
12
12
  | import | decodes | gzip |
13
13
  |---|---|---|
14
- | `@draco-rust/decoder` | meshes and point clouds | ~87 KiB |
15
- | `@draco-rust/decoder/mesh` | meshes only, which is all glTF's `KHR_draco_mesh_compression` allows | ~72 KiB |
16
- | `@draco-rust/decoder/point-cloud` | point clouds only (scans, splats) | ~58 KiB |
17
- | `@draco-rust/decoder/legacy` | meshes and point clouds, plus bitstreams older than 2.2 | ~97 KiB |
14
+ | `@draco-rust/decoder` | meshes and point clouds | ~92 KiB |
15
+ | `@draco-rust/decoder/mesh` | meshes only, which is all glTF's `KHR_draco_mesh_compression` allows | ~77 KiB |
16
+ | `@draco-rust/decoder/point-cloud` | point clouds only (scans, splats) | ~63 KiB |
17
+ | `@draco-rust/decoder/legacy` | meshes and point clouds, plus bitstreams older than 2.2 | ~103 KiB |
18
+
19
+ Each entry also has a worker pool and a three.js loader of its own, which use
20
+ that entry's module: `@draco-rust/decoder/pool` and `@draco-rust/decoder/three`,
21
+ or `@draco-rust/decoder/mesh/pool`, `@draco-rust/decoder/mesh/three` and so on.
18
22
 
19
23
  ## Usage
20
24
 
@@ -36,6 +40,77 @@ triangle corners, which is empty for a point cloud. `normals` and `uvs` are
36
40
  such attribute. Attributes the stream carries beyond those are in
37
41
  `meshes[0].extras`, and `result.warnings` says what was not interpreted.
38
42
 
43
+ ### Attributes the way a loader asks for them
44
+
45
+ `decode_draco` returns every attribute as a typed array, or the ones a loader
46
+ asks for, converted to the array type it needs. Upstream Draco's decoder makes
47
+ the same conversions, and this one matches it byte for byte, refusing where it
48
+ refuses.
49
+
50
+ ```js
51
+ import init, { decode_draco } from "@draco-rust/decoder/mesh";
52
+
53
+ await init();
54
+ // By unique id, as glTF's KHR_draco_mesh_compression names them, or by type.
55
+ const result = decode_draco(bytes, [
56
+ { name: "position", id: 0, type: "Float32Array" },
57
+ { name: "color", semantic: "COLOR", type: "Uint16Array" },
58
+ ]);
59
+ if (!result.success) throw new Error(result.error);
60
+ const { index, attributes } = result; // attributes[i]: { name, array, itemSize, normalized, ... }
61
+ ```
62
+
63
+ Without the second argument every attribute comes back in its own type.
64
+
65
+ ### On workers
66
+
67
+ Decoding runs on the calling thread. `createDecoderPool` runs it on workers
68
+ instead, so a page stays responsive while several streams decode at once:
69
+
70
+ ```js
71
+ import { createDecoderPool } from "@draco-rust/decoder/mesh/pool";
72
+
73
+ const pool = createDecoderPool({ workers: 4 }); // default: cores - 1, at most 4
74
+ const result = await pool.decode(bytes, requests); // what decode_draco returns
75
+ pool.dispose();
76
+ ```
77
+
78
+ The workers start as work arrives, and the wasm is compiled once for all of
79
+ them. The stream is copied to the worker; `pool.decode(bytes, requests, {
80
+ transfer: true })` hands over the buffer itself instead. The pool runs on Web
81
+ Workers, on Node's worker threads (Node 20.16 and later), and from a CDN. With
82
+ `workers: 0`, or where there are no workers, it decodes on the calling thread.
83
+ A bundler that follows `new URL("./worker.js", import.meta.url)`, as Vite and
84
+ webpack do, emits the worker on its own.
85
+
86
+ ### With three.js
87
+
88
+ `createDracoLoader` stands in for three.js's `DRACOLoader`, on the pool. It
89
+ takes three's classes rather than importing three, so it builds with your own
90
+ copy:
91
+
92
+ ```js
93
+ import * as THREE from "three";
94
+ import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
95
+ import { createDracoLoader } from "@draco-rust/decoder/mesh/three";
96
+
97
+ const gltfLoader = new GLTFLoader();
98
+ gltfLoader.setDRACOLoader(createDracoLoader(THREE));
99
+ const gltf = await gltfLoader.loadAsync("model.glb");
100
+ ```
101
+
102
+ For a `.drc` file, `await loader.parseAsync(arrayBuffer)` returns a
103
+ `BufferGeometry`, and `parse(buffer, onLoad, onError)` works as DRACOLoader's
104
+ does. Vertex colours from a `.drc` file are converted from sRGB, as
105
+ DRACOLoader converts them, and an attribute whose items are not a multiple of
106
+ four bytes is padded and interleaved, as DRACOLoader pads it since r181. The
107
+ geometry is the one DRACOLoader builds, byte for byte, with one difference: an
108
+ attribute that does not convert to the type asked for -- a negative value
109
+ into a `Uint16Array`, say -- is an error here, where DRACOLoader fills the
110
+ attribute with whatever its failed conversion left in memory. `setWorkerLimit`,
111
+ `preload` and `dispose` are there too. In TypeScript, `setDRACOLoader` expects the `DRACOLoader` class, so cast
112
+ the loader: `createDracoLoader(THREE) as unknown as DRACOLoader`.
113
+
39
114
  ### From a CDN, without a bundler
40
115
 
41
116
  ```js
@@ -61,9 +136,9 @@ For a subpath entry, resolve its own file, for example
61
136
 
62
137
  - Runs in every browser with WebAssembly, in Node 20.6 and later, in Deno and
63
138
  in Bun.
64
- - Decoding happens on the calling thread. Call it from a Web Worker to keep a
65
- page responsive.
139
+ - `parse_drc_bytes` and `decode_draco` decode on the calling thread; the pool
140
+ decodes on workers.
66
141
  - Licensed under Apache-2.0, like Draco.
67
142
  ## This build
68
143
 
69
- `@draco-rust/decoder@0.1.0` was built from draco-rust commit `40227fd4`, with draco-core 2.3.0, draco-io 0.5.2, draco-gltf 0.6.0.
144
+ `@draco-rust/decoder@0.1.2` was built from draco-rust commit `6bc95d5c`, with draco-core 2.3.2, draco-io 0.6.0, draco-gltf 0.7.0.
package/index.d.ts CHANGED
@@ -1,6 +1,76 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
3
 
4
+ /** The name of a typed array `decode_draco` can convert an attribute to. */
5
+ export type DracoArrayType =
6
+ | "Int8Array" | "Uint8Array" | "Int16Array" | "Uint16Array"
7
+ | "Int32Array" | "Uint32Array" | "Float32Array";
8
+
9
+ /** A Draco attribute type, as `semantic` names it. */
10
+ export type DracoSemantic = "POSITION" | "NORMAL" | "COLOR" | "TEX_COORD" | "GENERIC";
11
+
12
+ /**
13
+ * One attribute to decode: by `id`, its unique id, or by `semantic`, the first
14
+ * attribute of that type. `name` is handed back unchanged.
15
+ */
16
+ export interface DracoAttributeRequest {
17
+ name?: string;
18
+ id?: number;
19
+ semantic?: DracoSemantic;
20
+ type?: DracoArrayType;
21
+ }
22
+
23
+ /** The typed arrays an attribute can come back in. */
24
+ export type DracoArray =
25
+ | Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array
26
+ | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
27
+
28
+ export interface DracoAttribute {
29
+ /** The request's `name`, or else the name the stream's metadata gives it. */
30
+ name?: string;
31
+ uniqueId: number;
32
+ semantic: DracoSemantic;
33
+ array: DracoArray;
34
+ itemSize: number;
35
+ normalized: boolean;
36
+ }
37
+
38
+ export interface DracoDecodeResult {
39
+ success: boolean;
40
+ error?: string;
41
+ warnings: string[];
42
+ geometry?: "mesh" | "point_cloud";
43
+ /** Triangle corners for a mesh, `null` for a point cloud. */
44
+ index: Uint32Array | null;
45
+ attributes: DracoAttribute[];
46
+ }
47
+
48
+
49
+
50
+ /**
51
+ * Decodes a Draco stream and returns its attributes as typed arrays.
52
+ *
53
+ * `attributes` is `undefined` for every attribute in its own component type,
54
+ * or an array of requests `{ name, id, semantic, type }`:
55
+ *
56
+ * - `id`, a unique id, finds that attribute, as glTF's
57
+ * `KHR_draco_mesh_compression` names them; a missing one is an error.
58
+ * - `semantic` (`"POSITION"`, `"NORMAL"`, `"COLOR"`, `"TEX_COORD"` or
59
+ * `"GENERIC"`) finds the first attribute of that type instead, as a `.drc`
60
+ * file is read; a missing one is left out.
61
+ * - `type`, a typed array's name such as `"Float32Array"` or
62
+ * `"Uint16Array"`, converts the values the way upstream's
63
+ * `GetAttributeDataArrayForAllPoints` does; without it the values keep
64
+ * their own type. A value the type cannot hold is an error.
65
+ *
66
+ * The result is `{ success, error, warnings, geometry, index, attributes }`,
67
+ * where `geometry` is `"mesh"` or `"point_cloud"` as the stream's header says,
68
+ * `index` a `Uint32Array` of triangle corners for a mesh and `null` for a
69
+ * point cloud, and each attribute `{ name, uniqueId, semantic, array,
70
+ * itemSize, normalized }`.
71
+ */
72
+ export function decode_draco(data: Uint8Array, attributes: DracoAttributeRequest[] | undefined): DracoDecodeResult;
73
+
4
74
  /**
5
75
  * Install the panic hook, so a panic reads as a message rather than a trap.
6
76
  */
@@ -24,36 +94,38 @@ export function version(): string;
24
94
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
25
95
 
26
96
  export interface InitOutput {
27
- readonly memory: WebAssembly.Memory;
28
- readonly parse_drc_bytes: (a: number, b: number) => number;
29
- readonly supported_extensions: (a: number) => void;
30
- readonly version: (a: number) => void;
31
- readonly init: () => void;
32
- readonly __wbindgen_export: (a: number) => void;
33
- readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
34
- readonly __wbindgen_export2: (a: number, b: number, c: number) => void;
35
- readonly __wbindgen_export3: (a: number, b: number) => number;
36
- readonly __wbindgen_start: () => void;
97
+ readonly memory: WebAssembly.Memory;
98
+ readonly decode_draco: (a: number, b: number, c: number) => number;
99
+ readonly init: () => void;
100
+ readonly parse_drc_bytes: (a: number, b: number) => number;
101
+ readonly supported_extensions: (a: number) => void;
102
+ readonly version: (a: number) => void;
103
+ readonly __wbindgen_export: (a: number, b: number) => number;
104
+ readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
105
+ readonly __wbindgen_export3: (a: number) => void;
106
+ readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
107
+ readonly __wbindgen_export4: (a: number, b: number, c: number) => void;
108
+ readonly __wbindgen_start: () => void;
37
109
  }
38
110
 
39
111
  export type SyncInitInput = BufferSource | WebAssembly.Module;
40
112
 
41
113
  /**
42
- * Instantiates the given `module`, which can either be bytes or
43
- * a precompiled `WebAssembly.Module`.
44
- *
45
- * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
46
- *
47
- * @returns {InitOutput}
48
- */
114
+ * Instantiates the given `module`, which can either be bytes or
115
+ * a precompiled `WebAssembly.Module`.
116
+ *
117
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
118
+ *
119
+ * @returns {InitOutput}
120
+ */
49
121
  export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
50
122
 
51
123
  /**
52
- * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
53
- * for everything else, calls `WebAssembly.instantiate` directly.
54
- *
55
- * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
56
- *
57
- * @returns {Promise<InitOutput>}
58
- */
124
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
125
+ * for everything else, calls `WebAssembly.instantiate` directly.
126
+ *
127
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
128
+ *
129
+ * @returns {Promise<InitOutput>}
130
+ */
59
131
  export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;