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