An open API service indexing awesome lists of open source software.

https://github.com/mrdoob/draco.js

A small, drop-in, pure-JavaScript Draco mesh loader for three.js.
https://github.com/mrdoob/draco.js

3d draco geometry gltf loader mesh-compression threejs webgl

Last synced: about 7 hours ago
JSON representation

A small, drop-in, pure-JavaScript Draco mesh loader for three.js.

Awesome Lists containing this project

README

          

# Draco.js

A pure-JavaScript [Draco](https://github.com/google/draco) mesh **loader** for
three.js. It's a drop-in `DRACOLoader` that decodes Draco-compressed triangle
meshes — both the EdgeBreaker connectivity used by glTF's
`KHR_draco_mesh_compression` and Draco's sequential connectivity — directly in
JavaScript.

**[Live demo →](https://mrdoob.github.io/draco.js/)**

Why a JS port instead of the official WASM build?

- **Small** — ~22 KB gzipped (69 KB minified), vs ~100 KB gzipped for the
`draco3d` WASM decoder + glue (~4.6× smaller).
- **Simple to ship** — one ES module. No `.wasm` fetch, no worker/glue setup,
no cross-origin or CSP headaches.
- **Fast** — on substantial meshes it's within ~1.0–1.4× of the WASM decoder,
and effectively at parity on the largest ones, with byte-for-byte identical
output (see [Correctness](#correctness)).

On the largest meshes (e.g. a 358k-face glTF) the two are about even; WASM keeps
a lead of up to ~1.35× on smaller and mid-size meshes. You trade, at most, a
modest amount of decode speed for a much smaller, simpler-to-deploy loader.

This trade pays off most on spotty mobile connections, where transferring
~100 KB takes much longer than ~20 KB. Even when JS parsing is slower than WASM,
the model often **displays sooner** end-to-end: the network savings outweigh the
extra decode time.

## Status

Targets **Draco bitstream version 2.2** — what current Draco encoders and glTF
exporters produce.

Not implemented:

- **Point-cloud decoding** (sequential and KD-tree) — only triangle meshes are
decoded.
- **Metadata content** — geometry metadata is parsed (so metadata-bearing files
still decode correctly) but is not surfaced on the returned geometry.
- **Older bitstreams** (< 2.2) — not a support goal, though many still decode.

## Usage

`DRACOLoader` is a drop-in replacement for three.js's own `DRACOLoader` — plug it
into `GLTFLoader` the usual way. There's no decoder path or WASM to configure
(`setDecoderPath` / `setDecoderConfig` are accepted but do nothing).

```js
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from './build/DRACOLoader.js';

const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader( new DRACOLoader() );

gltfLoader.load( 'model.glb', ( gltf ) => scene.add( gltf.scene ) );
```

It can also load standalone `.drc` files:

```js
const geometry = await new DRACOLoader().loadAsync( 'model.drc' ); // BufferGeometry
```

## Build

`npm run build` bundles `src/DRACOLoader.js` (via Rollup) into `build/DRACOLoader.js`
(readable ESM) and `build/DRACOLoader.min.js` (minified), with `three` kept
external. Prebuilt copies are checked in.

## Correctness

Output is **byte-for-byte identical** to Google's reference `draco3d` WASM
decoder. `npm run verify` decodes every sample with both and compares
element-by-element — face indices and every per-point attribute value match
exactly (`eps 0`) across all 260 test primitives. `npm run bench` separately
times decoding and guards against output regressions via a sha256 of the
decoded geometry.

## Project layout

```
src/ decoder source, mirroring draco/src/draco/ file-for-file
build/ bundled output (build/DRACOLoader.js + .min.js)
tools/ bench.mjs (timing + regression) and verify-wasm.mjs (WASM parity)
libs/ three.js's WASM Draco loader, vendored for the comparison
samples/ .drc and Draco-compressed .glb test models
index.html JS-vs-WASM comparison viewer
```

## Credits

- Decoder logic is a port of [Google Draco](https://github.com/google/draco)
(Apache-2.0); it mirrors the original C++ file structure.
- `DRACOLoader.js` follows the API of three.js's
[`DRACOLoader`](https://github.com/mrdoob/three.js/blob/dev/examples/jsm/loaders/DRACOLoader.js)
(MIT) so it drops into `GLTFLoader` unchanged.