diff options
Diffstat (limited to 'extern/draco/src/draco-compressor.cpp')
-rw-r--r-- | extern/draco/src/draco-compressor.cpp | 362 |
1 files changed, 147 insertions, 215 deletions
diff --git a/extern/draco/src/draco-compressor.cpp b/extern/draco/src/draco-compressor.cpp index 3262a2c4d4d..4ae528888fe 100644 --- a/extern/draco/src/draco-compressor.cpp +++ b/extern/draco/src/draco-compressor.cpp @@ -13,234 +13,147 @@ */ /** - * Implemententation for the Draco exporter from the C++ side. - * - * The python side uses the CTypes libary to open the DLL, load function - * pointers add pass the data to the compressor as raw bytes. - * - * The compressor intercepts the regular GLTF exporter after data has been - * gathered and right before the data is converted to a JSON representation, - * which is going to be written out. - * - * The original uncompressed data is removed and replaces an extension, - * pointing to the newly created buffer containing the compressed data. - * * @author Jim Eckerlein <eckerlein@ux3d.io> - * @date 2019-01-15 + * @date 2019-11-29 */ -#include <iostream> -#include <fstream> +#include "draco-compressor.h" + #include <memory> -#include <sstream> +#include <vector> #include "draco/mesh/mesh.h" -#include "draco/point_cloud/point_cloud.h" -#include "draco/core/vector_d.h" -#include "draco/io/mesh_io.h" +#include "draco/core/encoder_buffer.h" #include "draco/compression/encode.h" -#if defined(_MSC_VER) -#define DLL_EXPORT(retType) extern "C" __declspec(dllexport) retType __cdecl -#else -#define DLL_EXPORT(retType) extern "C" retType -#endif - -const char *logTag = "DRACO-COMPRESSOR"; - /** - * This tuple is opaquely exposed to Python through a pointer. - * It encapsulates the complete current compressor state. - * - * A single instance is only intended to compress a single primitive. + * Prefix used for logging messages. */ -struct DracoCompressor { +const char *logTag = "DRACO-COMPRESSOR"; - /** - * All positions, normals and texture coordinates are appended to this mesh. - */ +struct DracoCompressor { draco::Mesh mesh; - /** - * One data buffer per attribute. - */ + // One data buffer per attribute. std::vector<std::unique_ptr<draco::DataBuffer>> buffers; - /** - * The buffer the mesh is compressed into. - */ + // The buffer the mesh is compressed into. draco::EncoderBuffer encoderBuffer; - /** - * The id Draco assigns to the position attribute. - * Required to be reported in the GLTF file. - */ - uint32_t positionAttributeId = (uint32_t) -1; - - /** - * The id Draco assigns to the normal attribute. - * Required to be reported in the GLTF file. - */ - uint32_t normalAttributeId = (uint32_t) -1; - - /** - * The ids Draco assigns to the texture coordinate attributes. - * Required to be reported in the GLTF file. - */ - std::vector<uint32_t> texCoordAttributeIds; - - /** - * Level of compression [0-10]. - * Higher values mean slower encoding. - */ + // Level of compression [0-10]. + // Higher values mean slower encoding. uint32_t compressionLevel = 7; - uint32_t quantizationBitsPosition = 14; - uint32_t quantizationBitsNormal = 10; - uint32_t quantizationBitsTexCoord = 12; + struct { + uint32_t positions = 14; + uint32_t normals = 10; + uint32_t uvs = 12; + uint32_t generic = 12; + } quantization; }; -draco::GeometryAttribute createAttribute( - draco::GeometryAttribute::Type type, - draco::DataBuffer &buffer, - uint8_t components -) { - draco::GeometryAttribute attribute; - attribute.Init( - type, - &buffer, - components, - draco::DataType::DT_FLOAT32, - false, - sizeof(float) * components, - 0 - ); - return attribute; -} - -DLL_EXPORT(DracoCompressor *) createCompressor() { +DracoCompressor *create_compressor() { return new DracoCompressor; } -DLL_EXPORT(void) setCompressionLevel( - DracoCompressor *compressor, - uint32_t compressionLevel +void set_compression_level( + DracoCompressor *const compressor, + uint32_t const compressionLevel ) { compressor->compressionLevel = compressionLevel; } -DLL_EXPORT(void) setPositionQuantizationBits( - DracoCompressor *compressor, - uint32_t quantizationBitsPosition +void set_position_quantization( + DracoCompressor *const compressor, + uint32_t const quantizationBitsPosition ) { - compressor->quantizationBitsPosition = quantizationBitsPosition; + compressor->quantization.positions = quantizationBitsPosition; } -DLL_EXPORT(void) setNormalQuantizationBits( - DracoCompressor *compressor, - uint32_t quantizationBitsNormal +void set_normal_quantization( + DracoCompressor *const compressor, + uint32_t const quantizationBitsNormal ) { - compressor->quantizationBitsNormal = quantizationBitsNormal; + compressor->quantization.normals = quantizationBitsNormal; } -DLL_EXPORT(void) setTexCoordQuantizationBits( - DracoCompressor *compressor, - uint32_t quantizationBitsTexCoord +void set_uv_quantization( + DracoCompressor *const compressor, + uint32_t const quantizationBitsTexCoord ) { - compressor->quantizationBitsTexCoord = quantizationBitsTexCoord; + compressor->quantization.uvs = quantizationBitsTexCoord; } -DLL_EXPORT(bool) compress( - DracoCompressor *compressor +void set_generic_quantization( + DracoCompressor *const compressor, + uint32_t const bits ) { - printf("%s: Compressing primitive:\n", logTag); - printf("%s: Compression level [0-10]: %d\n", logTag, compressor->compressionLevel); - printf("%s: Position quantization bits: %d\n", logTag, compressor->quantizationBitsPosition); - printf("%s: Normal quantization bits: %d\n", logTag, compressor->quantizationBitsNormal); - printf("%s: Position quantization bits: %d\n", logTag, compressor->quantizationBitsTexCoord); + compressor->quantization.generic = bits; +} +bool compress( + DracoCompressor *const compressor +) { draco::Encoder encoder; - encoder.SetSpeedOptions(10 - compressor->compressionLevel, 10 - compressor->compressionLevel); - encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantizationBitsPosition); - encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, compressor->quantizationBitsNormal); - encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, compressor->quantizationBitsTexCoord); - - draco::Status result = encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer); + encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel); + encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions); + encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, compressor->quantization.normals); + encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, compressor->quantization.uvs); + encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, compressor->quantization.generic); - if(!result.ok()) { - printf("%s: Could not compress mesh: %s\n", logTag, result.error_msg()); - return false; - } - else { - return true; - } + return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok(); } -/** - * Returns the size of the compressed data in bytes. - */ -DLL_EXPORT(uint64_t) compressedSize( - DracoCompressor *compressor +bool compress_morphed( + DracoCompressor *const compressor ) { - return compressor->encoderBuffer.size(); -} + draco::Encoder encoder; -/** - * Copies the compressed mesh into the given byte buffer. - * @param[o_data] A Python `bytes` object. - * - */ -DLL_EXPORT(void) copyToBytes( - DracoCompressor *compressor, - uint8_t *o_data -) { - memcpy(o_data, compressor->encoderBuffer.data(), compressedSize(compressor)); -} + encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel); -DLL_EXPORT(uint32_t) getPositionAttributeId( - DracoCompressor *compressor -) { - return compressor->positionAttributeId; -} + // For some reason, `EncodeMeshToBuffer` crashes when not disabling prediction or when enabling quantization + // for attributes other position. + encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions); + encoder.SetAttributePredictionScheme(draco::GeometryAttribute::POSITION, draco::PREDICTION_NONE); + encoder.SetAttributePredictionScheme(draco::GeometryAttribute::NORMAL, draco::PREDICTION_NONE); + encoder.SetAttributePredictionScheme(draco::GeometryAttribute::TEX_COORD, draco::PREDICTION_NONE); + encoder.SetAttributePredictionScheme(draco::GeometryAttribute::GENERIC, draco::PREDICTION_NONE); -DLL_EXPORT(uint32_t) getNormalAttributeId( - DracoCompressor *compressor -) { - return compressor->normalAttributeId; + // Enforce triangle order preservation. + encoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING); + + return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok(); } -DLL_EXPORT(uint32_t) getTexCoordAttributeIdCount( - DracoCompressor *compressor +uint64_t get_compressed_size( + DracoCompressor const *const compressor ) { - return (uint32_t) compressor->texCoordAttributeIds.size(); + return compressor->encoderBuffer.size(); } -DLL_EXPORT(uint32_t) getTexCoordAttributeId( - DracoCompressor *compressor, - uint32_t index +void copy_to_bytes( + DracoCompressor const *const compressor, + uint8_t *const o_data ) { - return compressor->texCoordAttributeIds[index]; + memcpy(o_data, compressor->encoderBuffer.data(), compressor->encoderBuffer.size()); } -/** - * Releases all memory allocated by the compressor. - */ -DLL_EXPORT(void) disposeCompressor( - DracoCompressor *compressor +void destroy_compressor( + DracoCompressor *const compressor ) { delete compressor; } template<class T> -void setFaces( - draco::Mesh &mesh, - int numIndices, - T *indices +void set_faces_impl( + draco::Mesh &mesh, + int const index_count, + T const *const indices ) { - mesh.SetNumFaces((size_t) numIndices / 3); + mesh.SetNumFaces((size_t) index_count / 3); - for (int i = 0; i < numIndices; i += 3) + for (int i = 0; i < index_count; i += 3) { const auto a = draco::PointIndex(indices[i]); const auto b = draco::PointIndex(indices[i + 1]); @@ -249,97 +162,116 @@ void setFaces( } } -DLL_EXPORT(void) setFaces( - DracoCompressor *compressor, - uint32_t numIndices, - uint32_t bytesPerIndex, - void *indices +void set_faces( + DracoCompressor *const compressor, + uint32_t const index_count, + uint32_t const index_byte_length, + uint8_t const *const indices ) { - switch (bytesPerIndex) + switch (index_byte_length) { case 1: { - setFaces(compressor->mesh, numIndices, (uint8_t *) indices); + set_faces_impl(compressor->mesh, index_count, (uint8_t *) indices); break; } case 2: { - setFaces(compressor->mesh, numIndices, (uint16_t *) indices); + set_faces_impl(compressor->mesh, index_count, (uint16_t *) indices); break; } case 4: { - setFaces(compressor->mesh, numIndices, (uint32_t *) indices); + set_faces_impl(compressor->mesh, index_count, (uint32_t *) indices); break; } default: { - printf("%s: Unsupported index size %d\n", logTag, bytesPerIndex); + printf("%s: Unsupported index size %d\n", logTag, index_byte_length); break; } } } -void addFloatAttribute( - DracoCompressor *compressor, - draco::GeometryAttribute::Type type, - uint32_t count, - uint8_t componentCount, - float *source +uint32_t add_attribute_to_mesh( + DracoCompressor *const compressor, + draco::GeometryAttribute::Type const semantics, + draco::DataType const data_type, + uint32_t const count, + uint8_t const component_count, + uint8_t const component_size, + uint8_t const *const data ) { auto buffer = std::make_unique<draco::DataBuffer>(); - const auto attribute = createAttribute(type, *buffer, componentCount); + draco::GeometryAttribute attribute; - const auto id = (const uint32_t) compressor->mesh.AddAttribute(attribute, false, count); - compressor->mesh.attribute(id)->SetIdentityMapping(); + attribute.Init( + semantics, + &*buffer, + component_count, + data_type, + false, + component_size * component_count, + 0 + ); - switch (type) - { - case draco::GeometryAttribute::POSITION: - compressor->positionAttributeId = id; - break; - case draco::GeometryAttribute::NORMAL: - compressor->normalAttributeId = id; - break; - case draco::GeometryAttribute::TEX_COORD: - compressor->texCoordAttributeIds.push_back(id); - break; - default: - break; - } + auto const id = (uint32_t)compressor->mesh.AddAttribute(attribute, true, count); for (uint32_t i = 0; i < count; i++) { compressor->mesh.attribute(id)->SetAttributeValue( - draco::AttributeValueIndex(i), - source + i * componentCount + draco::AttributeValueIndex(i), + data + i * component_count * component_size ); } compressor->buffers.emplace_back(std::move(buffer)); + + return id; +} + +uint32_t add_positions_f32( + DracoCompressor *const compressor, + uint32_t const count, + uint8_t const *const data +) { + return add_attribute_to_mesh(compressor, draco::GeometryAttribute::POSITION, + draco::DT_FLOAT32, count, 3, sizeof(float), data); +} + +uint32_t add_normals_f32( + DracoCompressor *const compressor, + uint32_t const count, + uint8_t const *const data +) { + return add_attribute_to_mesh(compressor, draco::GeometryAttribute::NORMAL, + draco::DT_FLOAT32, count, 3, sizeof(float), data); } -DLL_EXPORT(void) addPositionAttribute( - DracoCompressor *compressor, - uint32_t count, - float *source +uint32_t add_uvs_f32( + DracoCompressor *const compressor, + uint32_t const count, + uint8_t const *const data ) { - addFloatAttribute(compressor, draco::GeometryAttribute::POSITION, count, 3, source); + return add_attribute_to_mesh(compressor, draco::GeometryAttribute::TEX_COORD, + draco::DT_FLOAT32, count, 2, sizeof(float), data); } -DLL_EXPORT(void) addNormalAttribute( - DracoCompressor *compressor, - uint32_t count, - float *source +uint32_t add_joints_u16( + DracoCompressor *compressor, + uint32_t const count, + uint8_t const *const data ) { - addFloatAttribute(compressor, draco::GeometryAttribute::NORMAL, count, 3, source); + return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC, + draco::DT_UINT16, count, 4, sizeof(uint16_t), data); } -DLL_EXPORT(void) addTexCoordAttribute( - DracoCompressor *compressor, - uint32_t count, - float *source +uint32_t add_weights_f32( + DracoCompressor *compressor, + uint32_t const count, + uint8_t const *const data ) { - addFloatAttribute(compressor, draco::GeometryAttribute::TEX_COORD, count, 2, source); + return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC, + draco::DT_FLOAT32, count, 4, sizeof(float), data); } |