diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d3bb90..9c1cbf8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ endif() # DRACO ExternalProject_Add(Draco GIT_REPOSITORY https://github.com/google/draco - GIT_TAG 1.2.5 + GIT_TAG 1.3.1 PREFIX draco INSTALL_DIR CMAKE_ARGS diff --git a/src/Raw2Gltf.cpp b/src/Raw2Gltf.cpp index 708ca1b..6931ac4 100644 --- a/src/Raw2Gltf.cpp +++ b/src/Raw2Gltf.cpp @@ -827,7 +827,7 @@ ModelData *Raw2Gltf( && surfaceModel.GetVertexCount() > 65535); std::shared_ptr primitive; - if (options.useDraco) { + if (options.draco.enabled) { int triangleCount = surfaceModel.GetTriangleCount(); // initialize Draco mesh with vertex index information @@ -943,17 +943,29 @@ ModelData *Raw2Gltf( primitive->AddTarget(pAcc.get(), nAcc.get(), tAcc.get()); } } - if (options.useDraco) { + if (options.draco.enabled) { // Set up the encoder. draco::Encoder encoder; - // TODO: generalize / allow configuration - encoder.SetSpeedOptions(5, 5); - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 14); - encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, 10); - encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, 10); - encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, 8); - encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, 8); + if (options.draco.compressionLevel != -1) { + int dracoSpeed = 10 - options.draco.compressionLevel; + encoder.SetSpeedOptions(dracoSpeed, dracoSpeed); + } + if (options.draco.quantBitsPosition != -1) { + encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, options.draco.quantBitsPosition); + } + if (options.draco.quantBitsTexCoord != -1) { + encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, options.draco.quantBitsTexCoord); + } + if (options.draco.quantBitsNormal != -1) { + encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, options.draco.quantBitsNormal); + } + if (options.draco.quantBitsColor != -1) { + encoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, options.draco.quantBitsColor); + } + if (options.draco.quantBitsGeneric != -1) { + encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, options.draco.quantBitsGeneric); + } draco::EncoderBuffer dracoBuffer; draco::Status status = encoder.EncodeMeshToBuffer(*primitive->dracoMesh, &dracoBuffer); @@ -1070,7 +1082,7 @@ ModelData *Raw2Gltf( if (options.useKHRMatUnlit) { extensionsUsed.push_back(KHR_MATERIALS_CMN_UNLIT); } - if (options.useDraco) { + if (options.draco.enabled) { extensionsUsed.push_back(KHR_DRACO_MESH_COMPRESSION); extensionsRequired.push_back(KHR_DRACO_MESH_COMPRESSION); } diff --git a/src/RawModel.h b/src/RawModel.h index ce3ab67..4fbf4d1 100644 --- a/src/RawModel.h +++ b/src/RawModel.h @@ -46,8 +46,18 @@ struct GltfOptions bool outputBinary { false }; /** If non-binary, whether to inline all resources, for a single (large) .glTF file. */ bool embedResources { false }; - /** Whether to use KHR_draco_mesh_compression to minimize static geometry size. */ - bool useDraco { false }; + + /** Whether and how to use KHR_draco_mesh_compression to minimize static geometry size. */ + struct { + bool enabled = false; + int compressionLevel = -1; + int quantBitsPosition = -1; + int quantBitsTexCoord = -1; + int quantBitsNormal = -1; + int quantBitsColor = -1; + int quantBitsGeneric = -1; + } draco; + /** Whether to use KHR_materials_unlit to extend materials definitions. */ bool useKHRMatUnlit { false }; /** Whether to populate the pbrMetallicRoughness substruct in materials. */ diff --git a/src/main.cpp b/src/main.cpp index 021d9b7..d608dd7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,7 +63,25 @@ int main(int argc, char *argv[]) cxxopts::value>()) ( "d,draco", "Apply Draco mesh compression to geometries.", - cxxopts::value(gltfOptions.useDraco)) + cxxopts::value(gltfOptions.draco.enabled)) + ( + "draco-compression-level", "The compression level to tune Draco to, from 0 to 10. (default: 7)", + cxxopts::value(gltfOptions.draco.compressionLevel)) + ( + "draco-bits-for-positions", "How many bits to quantize position to. (default: 14)", + cxxopts::value(gltfOptions.draco.quantBitsPosition)) + ( + "draco-bits-for-uv", "How many bits to quantize UV coordinates to. (default: 10)", + cxxopts::value(gltfOptions.draco.quantBitsTexCoord)) + ( + "draco-bits-for-normals", "How many bits to quantize normals to. (default: 10)", + cxxopts::value(gltfOptions.draco.quantBitsNormal)) + ( + "draco-bits-for-colors", "How many bits to quantize color to. (default: 8)", + cxxopts::value(gltfOptions.draco.quantBitsColor)) + ( + "draco-bits-for-other", "How many bits to quantize other vertex attributes to to. (default: 8)", + cxxopts::value(gltfOptions.draco.quantBitsGeneric)) ( "compute-normals", "When to compute normals for vertices (never|broken|missing|always).", cxxopts::value>()) @@ -125,6 +143,12 @@ int main(int argc, char *argv[]) gltfOptions.usePBRMetRough = true; } + if (gltfOptions.draco.compressionLevel != -1 && + (gltfOptions.draco.compressionLevel < 1 || gltfOptions.draco.compressionLevel > 10)) { + fmt::printf("Draco compression level must lie in [1, 10].\n"); + return 0; + } + if (options.count("flip-u") > 0) { texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0f - uv[0], uv[1]); }); }