@draco-rust/decoder 0.2.0 → 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.
- package/README.md +9 -3
- package/index.d.ts +21 -25
- package/index.js +12 -7
- package/index_bg.wasm +0 -0
- package/index_bg.wasm.d.ts +1 -1
- package/legacy/index.d.ts +21 -25
- package/legacy/index.js +12 -7
- package/legacy/index_bg.wasm +0 -0
- package/legacy/index_bg.wasm.d.ts +1 -1
- package/legacy/pool-core.d.ts +44 -0
- package/legacy/pool-core.js +250 -0
- package/legacy/pool.d.ts +6 -29
- package/legacy/pool.js +15 -184
- package/legacy/tasks.js +2 -0
- package/legacy/worker.js +24 -10
- package/mesh/index.d.ts +21 -25
- package/mesh/index.js +12 -7
- package/mesh/index_bg.wasm +0 -0
- package/mesh/index_bg.wasm.d.ts +1 -1
- package/mesh/pool-core.d.ts +44 -0
- package/mesh/pool-core.js +250 -0
- package/mesh/pool.d.ts +6 -29
- package/mesh/pool.js +15 -184
- package/mesh/tasks.js +2 -0
- package/mesh/worker.js +24 -10
- package/package.json +2 -2
- package/point-cloud/index.d.ts +21 -25
- package/point-cloud/index.js +12 -7
- package/point-cloud/index_bg.wasm +0 -0
- package/point-cloud/index_bg.wasm.d.ts +1 -1
- package/point-cloud/pool-core.d.ts +44 -0
- package/point-cloud/pool-core.js +250 -0
- package/point-cloud/pool.d.ts +6 -29
- package/point-cloud/pool.js +15 -184
- package/point-cloud/tasks.js +2 -0
- package/point-cloud/worker.js +24 -10
- package/pool-core.d.ts +44 -0
- package/pool-core.js +250 -0
- package/pool.d.ts +6 -29
- package/pool.js +15 -184
- package/tasks.js +2 -0
- package/worker.js +24 -10
package/mesh/pool.d.ts
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
|
-
import type { DracoAttributeRequest, DracoDecodeResult } from './index.js';
|
|
1
|
+
import type { DracoAttributeRequest, DracoDecodeOptions, DracoDecodeResult } from './index.js';
|
|
2
|
+
import type { Pool, PoolOptions, TaskOptions } from './pool-core.js';
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
/**
|
|
5
|
-
* How many workers to run at most; they start as work arrives. Defaults to
|
|
6
|
-
* one less than the cores, between one and four. `0` decodes on the calling
|
|
7
|
-
* thread, as does an environment without workers.
|
|
8
|
-
*/
|
|
9
|
-
workers?: number;
|
|
10
|
-
/**
|
|
11
|
-
* The entry's wasm, when it is not next to this module where the pool looks
|
|
12
|
-
* for it: a URL, a `Response`, the bytes, or a compiled module.
|
|
13
|
-
*/
|
|
14
|
-
wasm?: string | URL | Response | BufferSource | WebAssembly.Module;
|
|
15
|
-
}
|
|
4
|
+
export type DecoderPoolOptions = PoolOptions;
|
|
16
5
|
|
|
17
|
-
export interface DecodeOptions {
|
|
18
|
-
/**
|
|
19
|
-
* Hand the stream's buffer to the worker instead of copying it, leaving it
|
|
20
|
-
* detached here. For a buffer nothing else reads afterwards.
|
|
21
|
-
*/
|
|
22
|
-
transfer?: boolean;
|
|
23
|
-
}
|
|
6
|
+
export interface DecodeOptions extends DracoDecodeOptions, TaskOptions {}
|
|
24
7
|
|
|
25
|
-
export interface DecoderPool {
|
|
8
|
+
export interface DecoderPool extends Pool {
|
|
26
9
|
/**
|
|
27
10
|
* `decode_draco` on a worker. A stream that does not decode resolves with
|
|
28
11
|
* `success: false`, as `decode_draco` returns it; a worker that fails rejects
|
|
@@ -33,13 +16,7 @@ export interface DecoderPool {
|
|
|
33
16
|
attributes?: DracoAttributeRequest[],
|
|
34
17
|
options?: DecodeOptions,
|
|
35
18
|
): Promise<DracoDecodeResult>;
|
|
36
|
-
/** Compiles the wasm and starts one worker ahead of the first decode. */
|
|
37
|
-
preload(): Promise<void>;
|
|
38
|
-
/** Changes the worker limit; idle workers past it stop now, busy ones when done. */
|
|
39
|
-
setWorkerLimit(workers: number): void;
|
|
40
|
-
readonly workerLimit: number;
|
|
41
|
-
/** Stops every worker and rejects what they held. */
|
|
42
|
-
dispose(): void;
|
|
43
19
|
}
|
|
44
20
|
|
|
45
21
|
export function createDecoderPool(options?: DecoderPoolOptions): DecoderPool;
|
|
22
|
+
export { createDecoderPool as createPool };
|
package/mesh/pool.js
CHANGED
|
@@ -1,193 +1,24 @@
|
|
|
1
|
-
// Decoding off the calling thread
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
// decode copies nothing it does not have to.
|
|
5
|
-
import init, { decode_draco } from './index.js';
|
|
1
|
+
// Decoding off the calling thread, on the shared pool: decode_draco on a
|
|
2
|
+
// worker, with the stream copied over unless the caller hands it away.
|
|
3
|
+
import { createPool as createTaskPool } from './pool-core.js';
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const defaultWorkers = () =>
|
|
10
|
-
Math.max(1, Math.min(4, (globalThis.navigator?.hardwareConcurrency ?? 4) - 1));
|
|
11
|
-
|
|
12
|
-
const builtin = (name) =>
|
|
13
|
-
typeof process !== 'undefined' && typeof process.getBuiltinModule === 'function'
|
|
14
|
-
? process.getBuiltinModule(name)
|
|
15
|
-
: undefined;
|
|
16
|
-
|
|
17
|
-
async function compile(wasm) {
|
|
18
|
-
if (wasm instanceof WebAssembly.Module) return wasm;
|
|
19
|
-
let source = wasm ?? new URL('./index_bg.wasm', import.meta.url);
|
|
20
|
-
if (typeof source === 'string' || source instanceof URL) {
|
|
21
|
-
const url = new URL(source, import.meta.url);
|
|
22
|
-
// Node's fetch does not read files.
|
|
23
|
-
const fs = url.protocol === 'file:' ? builtin('node:fs/promises') : undefined;
|
|
24
|
-
if (fs) return WebAssembly.compile(await fs.readFile(url));
|
|
25
|
-
source = await fetch(url);
|
|
26
|
-
}
|
|
27
|
-
if (typeof Response !== 'undefined' && source instanceof Response) {
|
|
28
|
-
if (!source.ok) throw new Error(`failed to fetch ${source.url}: ${source.status}`);
|
|
29
|
-
if (source.headers.get('content-type') === 'application/wasm') {
|
|
30
|
-
return WebAssembly.compileStreaming(source);
|
|
31
|
-
}
|
|
32
|
-
source = await source.arrayBuffer();
|
|
33
|
-
}
|
|
34
|
-
return WebAssembly.compile(source);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** What the pool needs of a worker, the same over a Web Worker and a Node
|
|
38
|
-
* worker thread. */
|
|
39
|
-
function spawn(blobUrl) {
|
|
40
|
-
if (typeof Worker === 'function') {
|
|
41
|
-
const url = new URL('./worker.js', import.meta.url);
|
|
42
|
-
// A bundler recognises this exact form and emits the worker as a chunk.
|
|
43
|
-
const worker =
|
|
44
|
-
typeof location === 'undefined' || url.origin === location.origin
|
|
45
|
-
? new Worker(new URL('./worker.js', import.meta.url), { type: 'module' })
|
|
46
|
-
: new Worker(blobUrl(url), { type: 'module' });
|
|
47
|
-
return {
|
|
48
|
-
post: (message, transfer) => worker.postMessage(message, transfer),
|
|
49
|
-
listen: (onMessage, onError) => {
|
|
50
|
-
worker.addEventListener('message', (event) => onMessage(event.data));
|
|
51
|
-
worker.addEventListener('error', (event) => {
|
|
52
|
-
event.preventDefault();
|
|
53
|
-
onError(new Error(event.message || 'the decoder worker failed'));
|
|
54
|
-
});
|
|
55
|
-
worker.addEventListener('messageerror', () => onError(new Error('a decode result could not be read')));
|
|
56
|
-
},
|
|
57
|
-
busy: () => {},
|
|
58
|
-
terminate: () => worker.terminate(),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
const threads = builtin('node:worker_threads');
|
|
62
|
-
if (!threads) return null;
|
|
63
|
-
const worker = new threads.Worker(new URL('./worker.js', import.meta.url));
|
|
64
|
-
// An idle worker does not keep Node running; one with work does.
|
|
65
|
-
worker.unref();
|
|
66
|
-
return {
|
|
67
|
-
post: (message, transfer) => worker.postMessage(message, transfer),
|
|
68
|
-
listen: (onMessage, onError) => {
|
|
69
|
-
worker.on('message', onMessage);
|
|
70
|
-
worker.on('error', onError);
|
|
71
|
-
worker.on('exit', (code) => onError(new Error(`the decoder worker exited with code ${code}`)));
|
|
72
|
-
},
|
|
73
|
-
busy: (busy) => (busy ? worker.ref() : worker.unref()),
|
|
74
|
-
terminate: () => worker.terminate(),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const workersAvailable = () =>
|
|
79
|
-
typeof Worker === 'function' || builtin('node:worker_threads') !== undefined;
|
|
5
|
+
const bytesOf = (data) =>
|
|
6
|
+
ArrayBuffer.isView(data) ? new Uint8Array(data.buffer, data.byteOffset, data.byteLength) : new Uint8Array(data);
|
|
80
7
|
|
|
81
8
|
export function createDecoderPool(options = {}) {
|
|
82
|
-
|
|
83
|
-
let compiled = null;
|
|
84
|
-
let local = null;
|
|
85
|
-
let blob = null;
|
|
86
|
-
let disposed = false;
|
|
87
|
-
let nextId = 0;
|
|
88
|
-
const slots = [];
|
|
89
|
-
|
|
90
|
-
const load = () => (compiled ??= compile(options.wasm));
|
|
91
|
-
// A worker script must share the page's origin. From a CDN, a worker made
|
|
92
|
-
// here imports it instead, which a module worker may do across origins.
|
|
93
|
-
const blobUrl = (url) =>
|
|
94
|
-
(blob ??= URL.createObjectURL(
|
|
95
|
-
new Blob([`import ${JSON.stringify(url.href)};`], { type: 'text/javascript' }),
|
|
96
|
-
));
|
|
97
|
-
|
|
98
|
-
function retire(slot, error) {
|
|
99
|
-
const at = slots.indexOf(slot);
|
|
100
|
-
if (at >= 0) slots.splice(at, 1);
|
|
101
|
-
slot.worker.terminate();
|
|
102
|
-
for (const { reject } of slot.pending.values()) reject(error);
|
|
103
|
-
slot.pending.clear();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function open(module) {
|
|
107
|
-
const worker = spawn(blobUrl);
|
|
108
|
-
if (!worker) return null;
|
|
109
|
-
const slot = { worker, pending: new Map() };
|
|
110
|
-
worker.listen(
|
|
111
|
-
(message) => {
|
|
112
|
-
const task = slot.pending.get(message.id);
|
|
113
|
-
if (!task) return;
|
|
114
|
-
slot.pending.delete(message.id);
|
|
115
|
-
if (slot.pending.size === 0) {
|
|
116
|
-
worker.busy(false);
|
|
117
|
-
if (slots.indexOf(slot) >= limit) retire(slot);
|
|
118
|
-
}
|
|
119
|
-
if ('error' in message) task.reject(new Error(message.error));
|
|
120
|
-
else task.resolve(message.result);
|
|
121
|
-
},
|
|
122
|
-
// A worker that fails takes only its own tasks down; the next decode
|
|
123
|
-
// starts another.
|
|
124
|
-
(error) => {
|
|
125
|
-
if (slots.includes(slot)) retire(slot, error);
|
|
126
|
-
},
|
|
127
|
-
);
|
|
128
|
-
worker.post({ type: 'init', module });
|
|
129
|
-
slots.push(slot);
|
|
130
|
-
return slot;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/** The least loaded worker, or a new one while every worker is busy and
|
|
134
|
-
* the limit allows another. */
|
|
135
|
-
function pick(module) {
|
|
136
|
-
let best = null;
|
|
137
|
-
for (const slot of slots.slice(0, limit)) {
|
|
138
|
-
if (!best || slot.pending.size < best.pending.size) best = slot;
|
|
139
|
-
}
|
|
140
|
-
if ((!best || best.pending.size > 0) && slots.length < limit) return open(module) ?? best;
|
|
141
|
-
return best;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const onThisThread = () =>
|
|
145
|
-
(local ??= load().then((module) => init({ module_or_path: module })));
|
|
146
|
-
|
|
147
|
-
async function decode(data, attributes, { transfer = false } = {}) {
|
|
148
|
-
if (disposed) throw new Error('the decoder pool was disposed');
|
|
149
|
-
const bytes = ArrayBuffer.isView(data)
|
|
150
|
-
? new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
151
|
-
: new Uint8Array(data);
|
|
152
|
-
if (limit > 0 && workersAvailable()) {
|
|
153
|
-
const module = await load();
|
|
154
|
-
if (disposed) throw new Error('the decoder pool was disposed');
|
|
155
|
-
const slot = pick(module);
|
|
156
|
-
if (slot) {
|
|
157
|
-
const id = nextId++;
|
|
158
|
-
const sent = transfer ? bytes : bytes.slice();
|
|
159
|
-
return new Promise((resolve, reject) => {
|
|
160
|
-
slot.pending.set(id, { resolve, reject });
|
|
161
|
-
slot.worker.busy(true);
|
|
162
|
-
slot.worker.post({ id, data: sent, attributes }, [sent.buffer]);
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
await onThisThread();
|
|
167
|
-
return decode_draco(bytes, attributes);
|
|
168
|
-
}
|
|
169
|
-
|
|
9
|
+
const pool = createTaskPool(options);
|
|
170
10
|
return {
|
|
171
|
-
decode,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const module = await load();
|
|
175
|
-
if (!disposed && slots.length === 0) open(module);
|
|
176
|
-
} else {
|
|
177
|
-
await onThisThread();
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
setWorkerLimit(workers) {
|
|
181
|
-
limit = workers;
|
|
182
|
-
for (const slot of slots.slice(limit)) if (slot.pending.size === 0) retire(slot);
|
|
11
|
+
decode(data, attributes, { transfer = false, signal, index } = {}) {
|
|
12
|
+
const decodeOptions = index === undefined ? undefined : { index };
|
|
13
|
+
return pool.run('decode_draco', [bytesOf(data), attributes, decodeOptions], { transfer, signal });
|
|
183
14
|
},
|
|
15
|
+
preload: () => pool.preload(),
|
|
16
|
+
setWorkerLimit: (workers) => pool.setWorkerLimit(workers),
|
|
184
17
|
get workerLimit() {
|
|
185
|
-
return
|
|
186
|
-
},
|
|
187
|
-
dispose() {
|
|
188
|
-
disposed = true;
|
|
189
|
-
for (const slot of [...slots]) retire(slot, new Error('the decoder pool was disposed'));
|
|
190
|
-
if (blob) URL.revokeObjectURL(blob);
|
|
18
|
+
return pool.workerLimit;
|
|
191
19
|
},
|
|
20
|
+
dispose: () => pool.dispose(),
|
|
192
21
|
};
|
|
193
22
|
}
|
|
23
|
+
|
|
24
|
+
export { createDecoderPool as createPool };
|
package/mesh/tasks.js
ADDED
package/mesh/worker.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
// A
|
|
2
|
-
//
|
|
3
|
-
// transfer. Runs as a Web Worker and as a Node
|
|
4
|
-
|
|
1
|
+
// A pool worker. The pool sends it the compiled module once, then tasks by
|
|
2
|
+
// name from this entry's `tasks.js`; it answers each with its result, handing
|
|
3
|
+
// every array in it back by transfer. Runs as a Web Worker and as a Node
|
|
4
|
+
// worker thread.
|
|
5
|
+
import init from './index.js';
|
|
6
|
+
import * as tasks from './tasks.js';
|
|
5
7
|
|
|
6
8
|
const web = typeof self !== 'undefined' && typeof self.postMessage === 'function';
|
|
7
9
|
const port = web ? self : process.getBuiltinModule('node:worker_threads').parentPort;
|
|
@@ -10,18 +12,30 @@ const listen = (handler) =>
|
|
|
10
12
|
|
|
11
13
|
let ready = null;
|
|
12
14
|
|
|
15
|
+
/** Every buffer in a result, except the module's own memory, which stays. */
|
|
16
|
+
function buffersOf(value, memory, found = new Set()) {
|
|
17
|
+
if (ArrayBuffer.isView(value)) {
|
|
18
|
+
if (value.buffer instanceof ArrayBuffer && value.buffer !== memory) found.add(value.buffer);
|
|
19
|
+
} else if (value instanceof ArrayBuffer) {
|
|
20
|
+
if (value !== memory) found.add(value);
|
|
21
|
+
} else if (Array.isArray(value)) {
|
|
22
|
+
for (const item of value) buffersOf(item, memory, found);
|
|
23
|
+
} else if (value !== null && typeof value === 'object') {
|
|
24
|
+
for (const item of Object.values(value)) buffersOf(item, memory, found);
|
|
25
|
+
}
|
|
26
|
+
return found;
|
|
27
|
+
}
|
|
28
|
+
|
|
13
29
|
listen(async (message) => {
|
|
14
30
|
if (message.type === 'init') {
|
|
15
31
|
ready = init({ module_or_path: message.module });
|
|
16
32
|
return;
|
|
17
33
|
}
|
|
18
|
-
const { id,
|
|
34
|
+
const { id, task, args } = message;
|
|
19
35
|
try {
|
|
20
|
-
await ready;
|
|
21
|
-
const result =
|
|
22
|
-
|
|
23
|
-
if (result.index) transfer.push(result.index.buffer);
|
|
24
|
-
port.postMessage({ id, result }, transfer);
|
|
36
|
+
const { memory } = await ready;
|
|
37
|
+
const result = await tasks[task](...args);
|
|
38
|
+
port.postMessage({ id, result }, [...buffersOf(result, memory.buffer)]);
|
|
25
39
|
} catch (error) {
|
|
26
40
|
port.postMessage({ id, error: String(error?.message ?? error) });
|
|
27
41
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draco-rust/decoder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Draco geometry decoder in WebAssembly, a safe Rust port of Google Draco: meshes, point clouds and older bitstreams, each as its own small entry.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"draco",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"directory": "web/npm/decoder"
|
|
25
25
|
},
|
|
26
26
|
"draco-rust": {
|
|
27
|
-
"commit": "
|
|
27
|
+
"commit": "4b72cfc8",
|
|
28
28
|
"draco-core": "2.3.2",
|
|
29
29
|
"draco-io": "0.6.0",
|
|
30
30
|
"draco-gltf": "0.7.0"
|
package/point-cloud/index.d.ts
CHANGED
|
@@ -35,41 +35,37 @@ export interface DracoAttribute {
|
|
|
35
35
|
normalized: boolean;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export interface DracoDecodeOptions {
|
|
39
|
+
/**
|
|
40
|
+
* The index's array: `"Uint32Array"`, the default, or `"auto"`, which uses a
|
|
41
|
+
* `Uint16Array` when every point number fits, at most 65536 points, and
|
|
42
|
+
* halves what a worker sends back.
|
|
43
|
+
*/
|
|
44
|
+
index?: "Uint32Array" | "auto";
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
export interface DracoDecodeResult {
|
|
39
48
|
success: boolean;
|
|
40
49
|
error?: string;
|
|
41
50
|
warnings: string[];
|
|
42
51
|
geometry?: "mesh" | "point_cloud";
|
|
43
52
|
/** Triangle corners for a mesh, `null` for a point cloud. */
|
|
44
|
-
index: Uint32Array | null;
|
|
53
|
+
index: Uint32Array | Uint16Array | null;
|
|
45
54
|
attributes: DracoAttribute[];
|
|
46
55
|
}
|
|
47
56
|
|
|
48
|
-
|
|
49
|
-
|
|
50
57
|
/**
|
|
51
|
-
* Decodes a Draco stream and returns its attributes as typed arrays
|
|
52
|
-
*
|
|
53
|
-
*
|
|
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 }`.
|
|
58
|
+
* Decodes a Draco stream and returns its attributes as typed arrays: every
|
|
59
|
+
* attribute in its own type, or the ones `attributes` requests, converted as
|
|
60
|
+
* upstream's `GetAttributeDataArrayForAllPoints` converts them.
|
|
71
61
|
*/
|
|
72
|
-
export function decode_draco(
|
|
62
|
+
export function decode_draco(
|
|
63
|
+
data: Uint8Array,
|
|
64
|
+
attributes?: DracoAttributeRequest[],
|
|
65
|
+
options?: DracoDecodeOptions,
|
|
66
|
+
): DracoDecodeResult;
|
|
67
|
+
|
|
68
|
+
|
|
73
69
|
|
|
74
70
|
/**
|
|
75
71
|
* Install the panic hook, so a panic reads as a message rather than a trap.
|
|
@@ -95,7 +91,7 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
|
|
|
95
91
|
|
|
96
92
|
export interface InitOutput {
|
|
97
93
|
readonly memory: WebAssembly.Memory;
|
|
98
|
-
readonly decode_draco: (a: number, b: number, c: number) => number;
|
|
94
|
+
readonly decode_draco: (a: number, b: number, c: number, d: number) => number;
|
|
99
95
|
readonly init: () => void;
|
|
100
96
|
readonly parse_drc_bytes: (a: number, b: number) => number;
|
|
101
97
|
readonly supported_extensions: (a: number) => void;
|
package/point-cloud/index.js
CHANGED
|
@@ -18,17 +18,22 @@
|
|
|
18
18
|
*
|
|
19
19
|
* The result is `{ success, error, warnings, geometry, index, attributes }`,
|
|
20
20
|
* where `geometry` is `"mesh"` or `"point_cloud"` as the stream's header says,
|
|
21
|
-
* `index`
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* `index` the triangle corners for a mesh and `null` for a point cloud, and
|
|
22
|
+
* each attribute `{ name, uniqueId, semantic, array, itemSize, normalized }`.
|
|
23
|
+
* The index is a `Uint32Array`, or with `options.index` set to `"auto"` a
|
|
24
|
+
* `Uint16Array` where the points number at most 65536.
|
|
25
|
+
*
|
|
26
|
+
* Its TypeScript declaration is written by hand in the section above, where
|
|
27
|
+
* the trailing parameters can be optional.
|
|
24
28
|
* @param {Uint8Array} data
|
|
25
|
-
* @param {
|
|
26
|
-
* @
|
|
29
|
+
* @param {any} attributes
|
|
30
|
+
* @param {object | null} [options]
|
|
31
|
+
* @returns {any}
|
|
27
32
|
*/
|
|
28
|
-
export function decode_draco(data, attributes) {
|
|
33
|
+
export function decode_draco(data, attributes, options) {
|
|
29
34
|
const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_export);
|
|
30
35
|
const len0 = WASM_VECTOR_LEN;
|
|
31
|
-
const ret = wasm.decode_draco(ptr0, len0, addHeapObject(attributes));
|
|
36
|
+
const ret = wasm.decode_draco(ptr0, len0, addHeapObject(attributes), isLikeNone(options) ? 0 : addHeapObject(options));
|
|
32
37
|
return takeObject(ret);
|
|
33
38
|
}
|
|
34
39
|
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
|
-
export const decode_draco: (a: number, b: number, c: number) => number;
|
|
4
|
+
export const decode_draco: (a: number, b: number, c: number, d: number) => number;
|
|
5
5
|
export const init: () => void;
|
|
6
6
|
export const parse_drc_bytes: (a: number, b: number) => number;
|
|
7
7
|
export const supported_extensions: (a: number) => void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface PoolOptions {
|
|
2
|
+
/**
|
|
3
|
+
* How many workers to run at most; they start as work arrives. Defaults to
|
|
4
|
+
* one less than the cores, between one and four. `0` runs on the calling
|
|
5
|
+
* thread, as does an environment without workers.
|
|
6
|
+
*/
|
|
7
|
+
workers?: number;
|
|
8
|
+
/**
|
|
9
|
+
* The entry's wasm, when it is not next to this module where the pool looks
|
|
10
|
+
* for it: a URL, a `Response`, the bytes, or a compiled module.
|
|
11
|
+
*/
|
|
12
|
+
wasm?: string | URL | Response | BufferSource | WebAssembly.Module;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface TaskOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Hand the input's buffers to the worker instead of copying them, leaving
|
|
18
|
+
* them detached here. For buffers nothing else reads afterwards.
|
|
19
|
+
*/
|
|
20
|
+
transfer?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Abandons the task: the promise rejects with the signal's reason at once.
|
|
23
|
+
* A task a worker has already started still runs to its end, and its result
|
|
24
|
+
* is dropped; one not yet sent is never sent.
|
|
25
|
+
*/
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface Pool {
|
|
30
|
+
/** Compiles the wasm and starts one worker ahead of the first task. */
|
|
31
|
+
preload(): Promise<void>;
|
|
32
|
+
/** Changes the worker limit; idle workers past it stop now, busy ones when done. */
|
|
33
|
+
setWorkerLimit(workers: number): void;
|
|
34
|
+
readonly workerLimit: number;
|
|
35
|
+
/** Stops every worker and rejects what they held. */
|
|
36
|
+
dispose(): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface TaskPool extends Pool {
|
|
40
|
+
/** Runs the task `tasks.js` exports under `name` on a worker. */
|
|
41
|
+
run(name: string, args?: unknown[], options?: TaskOptions): Promise<any>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function createPool(options?: PoolOptions): TaskPool;
|