@draco-rust/gltf
v0.3.0
Published
glTF and GLB reading, validation, writing and Draco compression in WebAssembly, with a lossless document model.
Maintainers
Readme
@draco-rust/gltf
Reads and writes glTF 2.0 and GLB in WebAssembly, including Draco geometry
(KHR_draco_mesh_compression), with a lossless document model: JSON the code
does not understand survives a round trip unchanged. It is part of
draco-rust and drives the
converter.
Entries
Each entry is a separate module. A bundler includes only the one you import.
| import | what it adds | gzip |
|---|---|---|
| @draco-rust/gltf | read glTF and GLB, decode Draco, read any accessor (animations, skins, morph targets), raw buffers | ~124 KiB |
| @draco-rust/gltf/validate | as above, plus strict validation of references, the node tree and POSITION bounds, for files you do not trust | ~152 KiB |
| @draco-rust/gltf/writer | as above, plus writing geometry, GLB output and Draco compression | ~261 KiB |
Usage
import init, { GltfAsset } from "@draco-rust/gltf";
await init();
const asset = new GltfAsset(glbBytes, "2.0"); // or "2.1" for the draft profile
for (let mesh = 0; mesh < asset.meshCount(); mesh++) {
for (let p = 0; p < asset.primitiveCount(mesh); p++) {
const geometry = asset.readPrimitive(mesh, p); // Draco or not, the same result
// geometry.attributeSemantic(i), attributeBytes(i), indexBytes(), ...
}
}For a .gltf with external files, pass the files by URI:
GltfAsset.withResources(jsonBytes, { "scene.bin": binBytes }, "2.0").
readPrimitives(pairs) reads many primitives in one call, and
asset.json() and asset.glb(2) write the document back out.
asset.jsonAt("/nodes/0/translation") reads one value by JSON Pointer, the
form KHR_animation_pointer uses, as JSON bytes, or undefined when nothing
is there.
On workers
GltfAsset and the geometry it reads are wasm objects, which stay on the
thread that made them. The pool reads a whole file on a worker instead and
returns plain arrays: the document's JSON and every primitive of every mesh,
Draco-compressed or not, decoded.
import { createPool } from "@draco-rust/gltf/pool"; // or /validate/pool, /writer/pool
const pool = createPool();
const { json, meshes } = await pool.read(glbBytes);
// meshes[m][p] = { mode, attributes: [{ semantic, count, components, componentType, normalized, bytes }], index }
const summary = await pool.inspect(glbBytes); // what inspect_gltf returns
pool.dispose();A .gltf with external files takes them as pool.read(jsonBytes, { resources }),
the way GltfAsset.withResources does, and profile picks "2.0" or "2.1".
The workers start as work arrives, and the wasm is compiled once for all of
them. Inputs are copied to the worker, or handed over with { transfer: true };
{ signal } takes an AbortSignal, which rejects the promise at once. A task
a worker has started still runs to its end and its result is dropped. With
workers: 0, or where there are no workers, the pool runs on the calling
thread. It works on Web Workers, Node's worker threads (Node 20.16 and later)
and from a CDN, as the decoder's does.
For loading from a CDN or in Node, see the
decoder's README; the same
init options apply, with this package's index_bg.wasm files.
Licensed under Apache-2.0.
This build
@draco-rust/[email protected] was built from draco-rust commit 4b72cfc8, with draco-core 2.3.2, draco-io 0.6.0, draco-gltf 0.7.0.
