1<p align="center">
2<img width="350px" src="docs/artwork/draco3d-vert.svg" />
3</p>
4
5[![Build Status](https://github.com/google/draco/workflows/Build/badge.svg)](https://github.com/google/draco/actions?query=workflow%3ABuild)
6
7News
8=======
9### Version 1.4.3 release
10* Using the versioned www.gstatic.com WASM and Javascript decoders continues
11  to be recommended. To use v1.4.3, use this URL:
12  * https://www.gstatic.com/draco/versioned/decoders/1.4.3/*
13* Bug fixes
14
15### Version 1.4.1 release
16* Using the versioned www.gstatic.com WASM and Javascript decoders is now
17  recommended. To use v1.4.1, use this URL:
18  * https://www.gstatic.com/draco/versioned/decoders/1.4.1/*
19    * Replace the * with the files to load. E.g.
20    * https://www.gstatic.com/draco/versioned/decoders/1.4.1/draco_decoder.js
21  * This works with the v1.3.6 and v1.4.0 releases, and will work with future
22    Draco releases.
23* Bug fixes
24
25### Version 1.4.0 release
26* WASM and JavaScript decoders are hosted from a static URL.
27  * It is recommended to always pull your Draco WASM and JavaScript decoders from this URL:
28  * https://www.gstatic.com/draco/v1/decoders/*
29    * Replace * with the files to load. E.g.
30    * https://www.gstatic.com/draco/v1/decoders/draco_decoder_gltf.wasm
31  * Users will benefit from having the Draco decoder in cache as more sites start using the static URL
32* Changed npm modules to use WASM, which increased performance by ~200%.
33* Updated Emscripten to 2.0.
34  * This causes the Draco codec modules to return a promise instead of the module directly.
35  * Please see the example code on how to handle the promise.
36* Changed NORMAL quantization default to 8.
37* Added new array API to decoder and deprecated DecoderBuffer.
38  * See PR https://github.com/google/draco/issues/513 for more information.
39* Changed WASM/JavaScript behavior of catching exceptions.
40  * See issue https://github.com/google/draco/issues/629 for more information.
41* Code cleanup.
42* Emscripten builds now disable NODEJS_CATCH_EXIT and NODEJS_CATCH_REJECTION.
43  * Authors of a CLI tool might want to add their own error handlers.
44* Added Maya plugin builds.
45* Unity plugin builds updated.
46  * Builds are now stored as archives.
47  * Added iOS build.
48  * Unity users may want to look into https://github.com/atteneder/DracoUnity.
49* Bug fixes.
50
51### Version 1.3.6 release
52* WASM and JavaScript decoders are now hosted from a static URL
53  * It is recommended to always pull your Draco WASM and JavaScript decoders from this URL:
54  * https://www.gstatic.com/draco/v1/decoders/*
55    * Replace * with the files to load. E.g.
56    * https://www.gstatic.com/draco/v1/decoders/draco_decoder_gltf.wasm
57  * Users will benefit from having the Draco decoder in cache as more sites start using the static URL
58* Changed web examples to pull Draco decoders from static URL
59* Added new API to Draco WASM decoder, which increased performance by ~15%
60* Decreased Draco WASM decoder size by ~20%
61* Added support for generic and multiple attributes to Draco Unity plug-ins
62* Added new API to Draco Unity, which increased decoder performance by ~15%
63* Changed quantization defaults:
64  * POSITION: 11
65  * NORMAL: 7
66  * TEX_COORD: 10
67  * COLOR: 8
68  * GENERIC: 8
69* Code cleanup
70* Bug fixes
71
72### Version 1.3.5 release
73* Added option to build Draco for Universal Scene Description
74* Code cleanup
75* Bug fixes
76
77### Version 1.3.4 release
78* Released Draco Animation code
79* Fixes for Unity
80* Various file location and name changes
81
82### Version 1.3.3 release
83* Added ExpertEncoder to the Javascript API
84  * Allows developers to set quantization options per attribute id
85* Bug fixes
86
87### Version 1.3.2 release
88* Bug fixes
89
90### Version 1.3.1 release
91* Fix issue with multiple attributes when skipping an attribute transform
92
93### Version 1.3.0 release
94* Improved kD-tree based point cloud encoding
95  * Now applicable to point clouds with any number of attributes
96  * Support for all integer attribute types and quantized floating point types
97* Improved mesh compression up to 10% (on average ~2%)
98  * For meshes, the 1.3.0 bitstream is fully compatible with 1.2.x decoders
99* Improved Javascript API
100  * Added support for all signed and unsigned integer types
101  * Added support for point clouds to our Javascript encoder API
102* Added support for integer properties to the PLY decoder
103* Bug fixes
104
105### Previous releases
106https://github.com/google/draco/releases
107
108Description
109===========
110
111Draco is a library for compressing and decompressing 3D geometric [meshes] and
112[point clouds]. It is intended to improve the storage and transmission of 3D
113graphics.
114
115Draco was designed and built for compression efficiency and speed. The code
116supports compressing points, connectivity information, texture coordinates,
117color information, normals, and any other generic attributes associated with
118geometry. With Draco, applications using 3D graphics can be significantly
119smaller without compromising visual fidelity. For users, this means apps can
120now be downloaded faster, 3D graphics in the browser can load quicker, and VR
121and AR scenes can now be transmitted with a fraction of the bandwidth and
122rendered quickly.
123
124Draco is released as C++ source code that can be used to compress 3D graphics
125as well as C++ and Javascript decoders for the encoded data.
126
127
128_**Contents**_
129
130  * [Building](#building)
131  * [Usage](#usage)
132    * [Unity](#unity)
133    * [WASM and JavaScript Decoders](#WASM-and-JavaScript-Decoders)
134    * [Command Line Applications](#command-line-applications)
135    * [Encoding Tool](#encoding-tool)
136    * [Encoding Point Clouds](#encoding-point-clouds)
137    * [Decoding Tool](#decoding-tool)
138    * [C++ Decoder API](#c-decoder-api)
139    * [Javascript Encoder API](#javascript-encoder-api)
140    * [Javascript Decoder API](#javascript-decoder-api)
141    * [Javascript Decoder Performance](#javascript-decoder-performance)
142    * [Metadata API](#metadata-api)
143    * [NPM Package](#npm-package)
144    * [three.js Renderer Example](#threejs-renderer-example)
145  * [Support](#support)
146  * [License](#license)
147  * [References](#references)
148
149
150Building
151========
152See [BUILDING](BUILDING.md) for building instructions.
153
154
155Usage
156======
157
158Unity
159-----
160For the best information about using Unity with Draco please visit https://github.com/atteneder/DracoUnity
161
162For a simple example of using Unity with Draco see [README](unity/README.md) in the unity folder.
163
164WASM and JavaScript Decoders
165----------------------------
166
167It is recommended to always pull your Draco WASM and JavaScript decoders from:
168
169~~~~~ bash
170https://www.gstatic.com/draco/v1/decoders/
171~~~~~
172
173Users will benefit from having the Draco decoder in cache as more sites start using the static URL.
174
175Command Line Applications
176------------------------
177
178The default target created from the build files will be the `draco_encoder`
179and `draco_decoder` command line applications. For both applications, if you
180run them without any arguments or `-h`, the applications will output usage and
181options.
182
183Encoding Tool
184-------------
185
186`draco_encoder` will read OBJ or PLY files as input, and output Draco-encoded
187files. We have included Stanford's [Bunny] mesh for testing. The basic command
188line looks like this:
189
190~~~~~ bash
191./draco_encoder -i testdata/bun_zipper.ply -o out.drc
192~~~~~
193
194A value of `0` for the quantization parameter will not perform any quantization
195on the specified attribute. Any value other than `0` will quantize the input
196values for the specified attribute to that number of bits. For example:
197
198~~~~~ bash
199./draco_encoder -i testdata/bun_zipper.ply -o out.drc -qp 14
200~~~~~
201
202will quantize the positions to 14 bits (default is 11 for the position
203coordinates).
204
205In general, the more you quantize your attributes the better compression rate
206you will get. It is up to your project to decide how much deviation it will
207tolerate. In general, most projects can set quantization values of about `11`
208without any noticeable difference in quality.
209
210The compression level (`-cl`) parameter turns on/off different compression
211features.
212
213~~~~~ bash
214./draco_encoder -i testdata/bun_zipper.ply -o out.drc -cl 8
215~~~~~
216
217In general, the highest setting, `10`, will have the most compression but
218worst decompression speed. `0` will have the least compression, but best
219decompression speed. The default setting is `7`.
220
221Encoding Point Clouds
222---------------------
223
224You can encode point cloud data with `draco_encoder` by specifying the
225`-point_cloud` parameter. If you specify the `-point_cloud` parameter with a
226mesh input file, `draco_encoder` will ignore the connectivity data and encode
227the positions from the mesh file.
228
229~~~~~ bash
230./draco_encoder -point_cloud -i testdata/bun_zipper.ply -o out.drc
231~~~~~
232
233This command line will encode the mesh input as a point cloud, even though the
234input might not produce compression that is representative of other point
235clouds. Specifically, one can expect much better compression rates for larger
236and denser point clouds.
237
238Decoding Tool
239-------------
240
241`draco_decoder` will read Draco files as input, and output OBJ or PLY files.
242The basic command line looks like this:
243
244~~~~~ bash
245./draco_decoder -i in.drc -o out.obj
246~~~~~
247
248C++ Decoder API
249-------------
250
251If you'd like to add decoding to your applications you will need to include
252the `draco_dec` library. In order to use the Draco decoder you need to
253initialize a `DecoderBuffer` with the compressed data. Then call
254`DecodeMeshFromBuffer()` to return a decoded mesh object or call
255`DecodePointCloudFromBuffer()` to return a decoded `PointCloud` object. For
256example:
257
258~~~~~ cpp
259draco::DecoderBuffer buffer;
260buffer.Init(data.data(), data.size());
261
262const draco::EncodedGeometryType geom_type =
263    draco::GetEncodedGeometryType(&buffer);
264if (geom_type == draco::TRIANGULAR_MESH) {
265  unique_ptr<draco::Mesh> mesh = draco::DecodeMeshFromBuffer(&buffer);
266} else if (geom_type == draco::POINT_CLOUD) {
267  unique_ptr<draco::PointCloud> pc = draco::DecodePointCloudFromBuffer(&buffer);
268}
269~~~~~
270
271Please see [src/draco/mesh/mesh.h](src/draco/mesh/mesh.h) for the full `Mesh` class interface and
272[src/draco/point_cloud/point_cloud.h](src/draco/point_cloud/point_cloud.h) for the full `PointCloud` class interface.
273
274
275Javascript Encoder API
276----------------------
277The Javascript encoder is located in `javascript/draco_encoder.js`. The encoder
278API can be used to compress mesh and point cloud. In order to use the encoder,
279you need to first create an instance of `DracoEncoderModule`. Then use this
280instance to create `MeshBuilder` and `Encoder` objects. `MeshBuilder` is used
281to construct a mesh from geometry data that could be later compressed by
282`Encoder`. First create a mesh object using `new encoderModule.Mesh()` . Then,
283use `AddFacesToMesh()` to add indices to the mesh and use
284`AddFloatAttributeToMesh()` to add attribute data to the mesh, e.g. position,
285normal, color and texture coordinates. After a mesh is constructed, you could
286then use `EncodeMeshToDracoBuffer()` to compress the mesh. For example:
287
288~~~~~ js
289const mesh = {
290  indices : new Uint32Array(indices),
291  vertices : new Float32Array(vertices),
292  normals : new Float32Array(normals)
293};
294
295const encoderModule = DracoEncoderModule();
296const encoder = new encoderModule.Encoder();
297const meshBuilder = new encoderModule.MeshBuilder();
298const dracoMesh = new encoderModule.Mesh();
299
300const numFaces = mesh.indices.length / 3;
301const numPoints = mesh.vertices.length;
302meshBuilder.AddFacesToMesh(dracoMesh, numFaces, mesh.indices);
303
304meshBuilder.AddFloatAttributeToMesh(dracoMesh, encoderModule.POSITION,
305  numPoints, 3, mesh.vertices);
306if (mesh.hasOwnProperty('normals')) {
307  meshBuilder.AddFloatAttributeToMesh(
308    dracoMesh, encoderModule.NORMAL, numPoints, 3, mesh.normals);
309}
310if (mesh.hasOwnProperty('colors')) {
311  meshBuilder.AddFloatAttributeToMesh(
312    dracoMesh, encoderModule.COLOR, numPoints, 3, mesh.colors);
313}
314if (mesh.hasOwnProperty('texcoords')) {
315  meshBuilder.AddFloatAttributeToMesh(
316    dracoMesh, encoderModule.TEX_COORD, numPoints, 3, mesh.texcoords);
317}
318
319if (method === "edgebreaker") {
320  encoder.SetEncodingMethod(encoderModule.MESH_EDGEBREAKER_ENCODING);
321} else if (method === "sequential") {
322  encoder.SetEncodingMethod(encoderModule.MESH_SEQUENTIAL_ENCODING);
323}
324
325const encodedData = new encoderModule.DracoInt8Array();
326// Use default encoding setting.
327const encodedLen = encoder.EncodeMeshToDracoBuffer(dracoMesh,
328                                                   encodedData);
329encoderModule.destroy(dracoMesh);
330encoderModule.destroy(encoder);
331encoderModule.destroy(meshBuilder);
332
333~~~~~
334Please see [src/draco/javascript/emscripten/draco_web_encoder.idl](src/draco/javascript/emscripten/draco_web_encoder.idl) for the full API.
335
336Javascript Decoder API
337----------------------
338
339The Javascript decoder is located in [javascript/draco_decoder.js](javascript/draco_decoder.js). The
340Javascript decoder can decode mesh and point cloud. In order to use the
341decoder, you must first create an instance of `DracoDecoderModule`. The
342instance is then used to create `DecoderBuffer` and `Decoder` objects. Set
343the encoded data in the `DecoderBuffer`. Then call `GetEncodedGeometryType()`
344to identify the type of geometry, e.g. mesh or point cloud. Then call either
345`DecodeBufferToMesh()` or `DecodeBufferToPointCloud()`, which will return
346a Mesh object or a point cloud. For example:
347
348~~~~~ js
349// Create the Draco decoder.
350const decoderModule = DracoDecoderModule();
351const buffer = new decoderModule.DecoderBuffer();
352buffer.Init(byteArray, byteArray.length);
353
354// Create a buffer to hold the encoded data.
355const decoder = new decoderModule.Decoder();
356const geometryType = decoder.GetEncodedGeometryType(buffer);
357
358// Decode the encoded geometry.
359let outputGeometry;
360let status;
361if (geometryType == decoderModule.TRIANGULAR_MESH) {
362  outputGeometry = new decoderModule.Mesh();
363  status = decoder.DecodeBufferToMesh(buffer, outputGeometry);
364} else {
365  outputGeometry = new decoderModule.PointCloud();
366  status = decoder.DecodeBufferToPointCloud(buffer, outputGeometry);
367}
368
369// You must explicitly delete objects created from the DracoDecoderModule
370// or Decoder.
371decoderModule.destroy(outputGeometry);
372decoderModule.destroy(decoder);
373decoderModule.destroy(buffer);
374~~~~~
375
376Please see [src/draco/javascript/emscripten/draco_web_decoder.idl](src/draco/javascript/emscripten/draco_web_decoder.idl) for the full API.
377
378Javascript Decoder Performance
379------------------------------
380
381The Javascript decoder is built with dynamic memory. This will let the decoder
382work with all of the compressed data. But this option is not the fastest.
383Pre-allocating the memory sees about a 2x decoder speed improvement. If you
384know all of your project's memory requirements, you can turn on static memory
385by changing `CMakeLists.txt` accordingly.
386
387Metadata API
388------------
389Starting from v1.0, Draco provides metadata functionality for encoding data
390other than geometry. It could be used to encode any custom data along with the
391geometry. For example, we can enable metadata functionality to encode the name
392of attributes, name of sub-objects and customized information.
393For one mesh and point cloud, it can have one top-level geometry metadata class.
394The top-level metadata then can have hierarchical metadata. Other than that,
395the top-level metadata can have metadata for each attribute which is called
396attribute metadata. The attribute metadata should be initialized with the
397correspondent attribute id within the mesh. The metadata API is provided both
398in C++ and Javascript.
399For example, to add metadata in C++:
400
401~~~~~ cpp
402draco::PointCloud pc;
403// Add metadata for the geometry.
404std::unique_ptr<draco::GeometryMetadata> metadata =
405  std::unique_ptr<draco::GeometryMetadata>(new draco::GeometryMetadata());
406metadata->AddEntryString("description", "This is an example.");
407pc.AddMetadata(std::move(metadata));
408
409// Add metadata for attributes.
410draco::GeometryAttribute pos_att;
411pos_att.Init(draco::GeometryAttribute::POSITION, nullptr, 3,
412             draco::DT_FLOAT32, false, 12, 0);
413const uint32_t pos_att_id = pc.AddAttribute(pos_att, false, 0);
414
415std::unique_ptr<draco::AttributeMetadata> pos_metadata =
416    std::unique_ptr<draco::AttributeMetadata>(
417        new draco::AttributeMetadata(pos_att_id));
418pos_metadata->AddEntryString("name", "position");
419
420// Directly add attribute metadata to geometry.
421// You can do this without explicitly add |GeometryMetadata| to mesh.
422pc.AddAttributeMetadata(pos_att_id, std::move(pos_metadata));
423~~~~~
424
425To read metadata from a geometry in C++:
426
427~~~~~ cpp
428// Get metadata for the geometry.
429const draco::GeometryMetadata *pc_metadata = pc.GetMetadata();
430
431// Request metadata for a specific attribute.
432const draco::AttributeMetadata *requested_pos_metadata =
433  pc.GetAttributeMetadataByStringEntry("name", "position");
434~~~~~
435
436Please see [src/draco/metadata](src/draco/metadata) and [src/draco/point_cloud](src/draco/point_cloud) for the full API.
437
438NPM Package
439-----------
440Draco NPM NodeJS package is located in [javascript/npm/draco3d](javascript/npm/draco3d). Please see the
441doc in the folder for detailed usage.
442
443three.js Renderer Example
444-------------------------
445
446Here's an [example] of a geometric compressed with Draco loaded via a
447Javascript decoder using the `three.js` renderer.
448
449Please see the [javascript/example/README.md](javascript/example/README.md) file for more information.
450
451Support
452=======
453
454For questions/comments please email <draco-3d-discuss@googlegroups.com>
455
456If you have found an error in this library, please file an issue at
457<https://github.com/google/draco/issues>
458
459Patches are encouraged, and may be submitted by forking this project and
460submitting a pull request through GitHub. See [CONTRIBUTING] for more detail.
461
462License
463=======
464Licensed under the Apache License, Version 2.0 (the "License"); you may not
465use this file except in compliance with the License. You may obtain a copy of
466the License at
467
468<http://www.apache.org/licenses/LICENSE-2.0>
469
470Unless required by applicable law or agreed to in writing, software
471distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
472WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
473License for the specific language governing permissions and limitations under
474the License.
475
476References
477==========
478[example]:https://storage.googleapis.com/demos.webmproject.org/draco/draco_loader_throw.html
479[meshes]: https://en.wikipedia.org/wiki/Polygon_mesh
480[point clouds]: https://en.wikipedia.org/wiki/Point_cloud
481[Bunny]: https://graphics.stanford.edu/data/3Dscanrep/
482[CONTRIBUTING]: https://raw.githubusercontent.com/google/draco/master/CONTRIBUTING.md
483
484Bunny model from Stanford's graphic department <https://graphics.stanford.edu/data/3Dscanrep/>
485