mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-08-14 11:45:59 +08:00
Improved Javascript decoder size + bugfixing
Changes: 1. Javascript decoder can now be built separately for meshes and point clouds. Together with other optimizations this results in about 33% smaller Javascript for mesh decoder. (pre-built javascript for meshes and point clouds is included). 2. Fixing bug in our symbol_encoder that resulted in failed encoding for certain cases when there were around 1<<18 symbols. 3. Changing default setting of our draco_encoder app to -cl 7
This commit is contained in:
parent
e85b83b16a
commit
59b297b18a
@ -9,6 +9,8 @@ include("${draco_root}/cmake/compiler_flags.cmake")
|
|||||||
# Draco requires C++11 support.
|
# Draco requires C++11 support.
|
||||||
require_cxx_flag_nomsvc("-std=c++11")
|
require_cxx_flag_nomsvc("-std=c++11")
|
||||||
|
|
||||||
|
option(ENABLE_POINT_CLOUD_COMPRESSION "" ON)
|
||||||
|
option(ENABLE_MESH_COMPRESSION "" ON)
|
||||||
option(ENABLE_STANDARD_EDGEBREAKER "" ON)
|
option(ENABLE_STANDARD_EDGEBREAKER "" ON)
|
||||||
option(ENABLE_PREDICTIVE_EDGEBREAKER "" ON)
|
option(ENABLE_PREDICTIVE_EDGEBREAKER "" ON)
|
||||||
option(ENABLE_EXTRA_WARNINGS "" OFF)
|
option(ENABLE_EXTRA_WARNINGS "" OFF)
|
||||||
@ -17,6 +19,12 @@ option(ENABLE_WERROR "" OFF)
|
|||||||
option(ENABLE_WEXTRA "" OFF)
|
option(ENABLE_WEXTRA "" OFF)
|
||||||
option(IGNORE_EMPTY_BUILD_TYPE "" OFF)
|
option(IGNORE_EMPTY_BUILD_TYPE "" OFF)
|
||||||
|
|
||||||
|
if (ENABLE_POINT_CLOUD_COMPRESSION)
|
||||||
|
add_cxx_preproc_definition("DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED")
|
||||||
|
endif ()
|
||||||
|
if (ENABLE_MESH_COMPRESSION)
|
||||||
|
add_cxx_preproc_definition("DRACO_MESH_COMPRESSION_SUPPORTED")
|
||||||
|
endif ()
|
||||||
if (ENABLE_STANDARD_EDGEBREAKER)
|
if (ENABLE_STANDARD_EDGEBREAKER)
|
||||||
add_cxx_preproc_definition("DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
|
add_cxx_preproc_definition("DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
|
||||||
endif ()
|
endif ()
|
||||||
@ -412,6 +420,11 @@ if (EMSCRIPTEN)
|
|||||||
add_compiler_flag_if_supported("-s ALLOW_MEMORY_GROWTH=1")
|
add_compiler_flag_if_supported("-s ALLOW_MEMORY_GROWTH=1")
|
||||||
add_compiler_flag_if_supported("--memory-init-file 0")
|
add_compiler_flag_if_supported("--memory-init-file 0")
|
||||||
add_compiler_flag_if_supported("-fno-omit-frame-pointer")
|
add_compiler_flag_if_supported("-fno-omit-frame-pointer")
|
||||||
|
add_compiler_flag_if_supported(-s MODULARIZE=1)
|
||||||
|
add_compiler_flag_if_supported(-s EXPORT_NAME="'DracoModule'")
|
||||||
|
add_compiler_flag_if_supported(--llvm-lto 1)
|
||||||
|
add_compiler_flag_if_supported(-s NO_FILESYSTEM=1)
|
||||||
|
add_compiler_flag_if_supported(-s ELIMINATE_DUPLICATE_FUNCTIONS=1)
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE STREQUAL "")
|
if (CMAKE_BUILD_TYPE STREQUAL "")
|
||||||
# Force -O3 when no build type is specified.
|
# Force -O3 when no build type is specified.
|
||||||
@ -504,6 +517,18 @@ else ()
|
|||||||
$<TARGET_OBJECTS:draco_mesh>
|
$<TARGET_OBJECTS:draco_mesh>
|
||||||
$<TARGET_OBJECTS:draco_point_cloud>
|
$<TARGET_OBJECTS:draco_point_cloud>
|
||||||
$<TARGET_OBJECTS:draco_points_decoder>)
|
$<TARGET_OBJECTS:draco_points_decoder>)
|
||||||
|
add_library(dracoenc
|
||||||
|
${draco_version_sources}
|
||||||
|
$<TARGET_OBJECTS:draco_compression_attributes_encoder>
|
||||||
|
$<TARGET_OBJECTS:draco_compression_attributes_pred_schemes>
|
||||||
|
$<TARGET_OBJECTS:draco_compression_config>
|
||||||
|
$<TARGET_OBJECTS:draco_compression_encode>
|
||||||
|
$<TARGET_OBJECTS:draco_compression_mesh_encoder>
|
||||||
|
$<TARGET_OBJECTS:draco_compression_point_cloud_encoder>
|
||||||
|
$<TARGET_OBJECTS:draco_core>
|
||||||
|
$<TARGET_OBJECTS:draco_mesh>
|
||||||
|
$<TARGET_OBJECTS:draco_point_cloud>
|
||||||
|
$<TARGET_OBJECTS:draco_points_encoder>)
|
||||||
add_library(draco
|
add_library(draco
|
||||||
${draco_version_sources}
|
${draco_version_sources}
|
||||||
$<TARGET_OBJECTS:draco_compression_attributes_decoder>
|
$<TARGET_OBJECTS:draco_compression_attributes_decoder>
|
||||||
|
@ -12,14 +12,26 @@ LD=emcc
|
|||||||
DRACO_CONFIG ?= full
|
DRACO_CONFIG ?= full
|
||||||
|
|
||||||
# Full config - all features included.
|
# Full config - all features included.
|
||||||
DRACO_FULL_CONFIG_DEFINES := -DDRACO_STANDARD_EDGEBREAKER_SUPPORTED
|
DRACO_FULL_MESH_CONFIG_DEFINES := -DDRACO_MESH_COMPRESSION_SUPPORTED
|
||||||
DRACO_FULL_CONFIG_DEFINES += -DDRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED
|
DRACO_FULL_MESH_CONFIG_DEFINES += -DDRACO_STANDARD_EDGEBREAKER_SUPPORTED
|
||||||
|
DRACO_FULL_MESH_CONFIG_DEFINES += -DDRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED
|
||||||
|
|
||||||
|
DRACO_FULL_POINT_CLOUD_CONFIG_DEFINES := -DDRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
|
||||||
|
|
||||||
|
DRACO_FULL_CONFIG_DEFINES := $(DRACO_FULL_MESH_CONFIG_DEFINES)
|
||||||
|
DRACO_FULL_CONFIG_DEFINES += $(DRACO_FULL_POINT_CLOUD_CONFIG_DEFINES)
|
||||||
|
|
||||||
# Default limited config with only some core features enabled.
|
# Default limited config with only some core features enabled.
|
||||||
DRACO_LIMITED_CONFIG_DEFINES := -DDRACO_STANDARD_EDGEBREAKER_SUPPORTED
|
DRACO_LIMITED_CONFIG_DEFINES := -DDRACO_STANDARD_EDGEBREAKER_SUPPORTED
|
||||||
|
DRACO_LIMITED_CONFIG_DEFINES += -DDRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
|
||||||
|
DRACO_LIMITED_CONFIG_DEFINES += -DDRACO_MESH_COMPRESSION_SUPPORTED
|
||||||
|
|
||||||
ifeq ($(DRACO_CONFIG), limited)
|
ifeq ($(DRACO_CONFIG), limited)
|
||||||
DRACO_CONFIG_DEFINES := $(DRACO_LIMITED_CONFIG_DEFINES)
|
DRACO_CONFIG_DEFINES := $(DRACO_LIMITED_CONFIG_DEFINES)
|
||||||
|
else ifeq ($(DRACO_CONFIG), full_mesh)
|
||||||
|
DRACO_CONFIG_DEFINES := $(DRACO_FULL_MESH_CONFIG_DEFINES)
|
||||||
|
else ifeq ($(DRACO_CONFIG), full_point_cloud)
|
||||||
|
DRACO_CONFIG_DEFINES := $(DRACO_FULL_POINT_CLOUD_CONFIG_DEFINES)
|
||||||
else
|
else
|
||||||
DRACO_CONFIG_DEFINES := $(DRACO_FULL_CONFIG_DEFINES)
|
DRACO_CONFIG_DEFINES := $(DRACO_FULL_CONFIG_DEFINES)
|
||||||
endif
|
endif
|
||||||
@ -47,6 +59,8 @@ ALL_C_OPTS := -std=c++11
|
|||||||
|
|
||||||
# Options for speed.
|
# Options for speed.
|
||||||
ALL_C_OPTS += -O3
|
ALL_C_OPTS += -O3
|
||||||
|
ALL_C_OPTS += --llvm-lto 1 -s NO_FILESYSTEM=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1
|
||||||
|
ALL_C_OPTS += -s EXPORTED_RUNTIME_METHODS=[]
|
||||||
|
|
||||||
# Options for debug
|
# Options for debug
|
||||||
#ALL_C_OPTS += -g -s DEMANGLE_SUPPORT=1
|
#ALL_C_OPTS += -g -s DEMANGLE_SUPPORT=1
|
||||||
|
@ -100,9 +100,11 @@ bool SequentialIntegerAttributeEncoder::EncodeValues(
|
|||||||
if (encoder() == nullptr || encoder()->options()->GetGlobalBool(
|
if (encoder() == nullptr || encoder()->options()->GetGlobalBool(
|
||||||
"use_built_in_attribute_compression", true)) {
|
"use_built_in_attribute_compression", true)) {
|
||||||
out_buffer->Encode(static_cast<uint8_t>(1));
|
out_buffer->Encode(static_cast<uint8_t>(1));
|
||||||
EncodeSymbols(reinterpret_cast<uint32_t *>(values_.data()),
|
if (!EncodeSymbols(reinterpret_cast<uint32_t *>(values_.data()),
|
||||||
point_ids.size() * num_components, num_components,
|
point_ids.size() * num_components, num_components,
|
||||||
out_buffer);
|
out_buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// No compression. Just store the raw integer values, using the number of
|
// No compression. Just store the raw integer values, using the number of
|
||||||
// bytes as needed.
|
// bytes as needed.
|
||||||
|
@ -15,10 +15,16 @@
|
|||||||
#include "compression/decode.h"
|
#include "compression/decode.h"
|
||||||
|
|
||||||
#include "compression/config/compression_shared.h"
|
#include "compression/config/compression_shared.h"
|
||||||
|
|
||||||
|
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
|
||||||
#include "compression/mesh/mesh_edgebreaker_decoder.h"
|
#include "compression/mesh/mesh_edgebreaker_decoder.h"
|
||||||
#include "compression/mesh/mesh_sequential_decoder.h"
|
#include "compression/mesh/mesh_sequential_decoder.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
|
||||||
#include "compression/point_cloud/point_cloud_kd_tree_decoder.h"
|
#include "compression/point_cloud/point_cloud_kd_tree_decoder.h"
|
||||||
#include "compression/point_cloud/point_cloud_sequential_decoder.h"
|
#include "compression/point_cloud/point_cloud_sequential_decoder.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace draco {
|
namespace draco {
|
||||||
|
|
||||||
@ -56,6 +62,7 @@ EncodedGeometryType GetEncodedGeometryType(DecoderBuffer *in_buffer) {
|
|||||||
return geom_type;
|
return geom_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
|
||||||
std::unique_ptr<PointCloudDecoder> CreatePointCloudDecoder(int8_t method) {
|
std::unique_ptr<PointCloudDecoder> CreatePointCloudDecoder(int8_t method) {
|
||||||
if (method == POINT_CLOUD_SEQUENTIAL_ENCODING) {
|
if (method == POINT_CLOUD_SEQUENTIAL_ENCODING) {
|
||||||
return std::unique_ptr<PointCloudDecoder>(
|
return std::unique_ptr<PointCloudDecoder>(
|
||||||
@ -65,7 +72,9 @@ std::unique_ptr<PointCloudDecoder> CreatePointCloudDecoder(int8_t method) {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
|
||||||
std::unique_ptr<MeshDecoder> CreateMeshDecoder(uint8_t method) {
|
std::unique_ptr<MeshDecoder> CreateMeshDecoder(uint8_t method) {
|
||||||
if (method == MESH_SEQUENTIAL_ENCODING) {
|
if (method == MESH_SEQUENTIAL_ENCODING) {
|
||||||
return std::unique_ptr<MeshDecoder>(new MeshSequentialDecoder());
|
return std::unique_ptr<MeshDecoder>(new MeshSequentialDecoder());
|
||||||
@ -74,6 +83,7 @@ std::unique_ptr<MeshDecoder> CreateMeshDecoder(uint8_t method) {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
|
std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
|
||||||
DecoderBuffer *in_buffer) {
|
DecoderBuffer *in_buffer) {
|
||||||
@ -82,6 +92,7 @@ std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
|
|||||||
if (!ParseHeader(in_buffer, &encoder_type, &method))
|
if (!ParseHeader(in_buffer, &encoder_type, &method))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (encoder_type == POINT_CLOUD) {
|
if (encoder_type == POINT_CLOUD) {
|
||||||
|
#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
|
||||||
std::unique_ptr<PointCloudDecoder> decoder =
|
std::unique_ptr<PointCloudDecoder> decoder =
|
||||||
CreatePointCloudDecoder(method);
|
CreatePointCloudDecoder(method);
|
||||||
if (!decoder)
|
if (!decoder)
|
||||||
@ -90,7 +101,9 @@ std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
|
|||||||
if (!decoder->Decode(in_buffer, point_cloud.get()))
|
if (!decoder->Decode(in_buffer, point_cloud.get()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return point_cloud;
|
return point_cloud;
|
||||||
|
#endif
|
||||||
} else if (encoder_type == TRIANGULAR_MESH) {
|
} else if (encoder_type == TRIANGULAR_MESH) {
|
||||||
|
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
|
||||||
std::unique_ptr<MeshDecoder> decoder = CreateMeshDecoder(method);
|
std::unique_ptr<MeshDecoder> decoder = CreateMeshDecoder(method);
|
||||||
if (!decoder)
|
if (!decoder)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -98,11 +111,13 @@ std::unique_ptr<PointCloud> DecodePointCloudFromBuffer(
|
|||||||
if (!decoder->Decode(in_buffer, mesh.get()))
|
if (!decoder->Decode(in_buffer, mesh.get()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return std::move(mesh);
|
return std::move(mesh);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Mesh> DecodeMeshFromBuffer(DecoderBuffer *in_buffer) {
|
std::unique_ptr<Mesh> DecodeMeshFromBuffer(DecoderBuffer *in_buffer) {
|
||||||
|
#ifdef DRACO_MESH_COMPRESSION_SUPPORTED
|
||||||
EncodedGeometryType encoder_type;
|
EncodedGeometryType encoder_type;
|
||||||
int8_t method;
|
int8_t method;
|
||||||
if (!ParseHeader(in_buffer, &encoder_type, &method))
|
if (!ParseHeader(in_buffer, &encoder_type, &method))
|
||||||
@ -117,6 +132,9 @@ std::unique_ptr<Mesh> DecodeMeshFromBuffer(DecoderBuffer *in_buffer) {
|
|||||||
if (!decoder->Decode(in_buffer, mesh.get()))
|
if (!decoder->Decode(in_buffer, mesh.get()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return mesh;
|
return mesh;
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace draco
|
} // namespace draco
|
||||||
|
@ -94,7 +94,7 @@ TEST_F(SymbolCodingTest, TestOneSymbol) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SymbolCodingTest, TestBitLengthsl) {
|
TEST_F(SymbolCodingTest, TestBitLengths) {
|
||||||
// This test verifies that SymbolCoding successfully encodes symbols of
|
// This test verifies that SymbolCoding successfully encodes symbols of
|
||||||
// various bitlengths
|
// various bitlengths
|
||||||
EncoderBuffer eb;
|
EncoderBuffer eb;
|
||||||
@ -116,4 +116,21 @@ TEST_F(SymbolCodingTest, TestBitLengthsl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolCodingTest, TestLargeNumberCondition) {
|
||||||
|
// This test verifies that SymbolCoding successfully encodes large symbols
|
||||||
|
// that are on the boundary between raw scheme and tagged scheme (18 bits).
|
||||||
|
EncoderBuffer eb;
|
||||||
|
constexpr int num_symbols = 1000000;
|
||||||
|
const std::vector<uint32_t> in(num_symbols, 1 << 18);
|
||||||
|
ASSERT_TRUE(EncodeSymbols(in.data(), in.size(), 1, &eb));
|
||||||
|
|
||||||
|
std::vector<uint32_t> out(in.size());
|
||||||
|
DecoderBuffer db;
|
||||||
|
db.Init(eb.data(), eb.size());
|
||||||
|
ASSERT_TRUE(DecodeSymbols(in.size(), 1, &db, &out[0]));
|
||||||
|
for (uint32_t i = 0; i < in.size(); ++i) {
|
||||||
|
ASSERT_EQ(in[i], out[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace draco
|
} // namespace draco
|
||||||
|
@ -133,8 +133,7 @@ bool EncodeSymbols(const uint32_t *symbols, int num_values, int num_components,
|
|||||||
|
|
||||||
// The maximum bit length of a single entry value that we can encode using
|
// The maximum bit length of a single entry value that we can encode using
|
||||||
// the raw scheme.
|
// the raw scheme.
|
||||||
|
const int max_value_bit_length = bits::MostSignificantBit(max_value) + 1;
|
||||||
const int max_value_bit_length = bits::MostSignificantBit(max_value);
|
|
||||||
|
|
||||||
if (tagged_scheme_total_bits < raw_scheme_total_bits ||
|
if (tagged_scheme_total_bits < raw_scheme_total_bits ||
|
||||||
max_value_bit_length > kMaxRawEncodingBitLength) {
|
max_value_bit_length > kMaxRawEncodingBitLength) {
|
||||||
@ -266,7 +265,7 @@ bool EncodeRawSymbols(const uint32_t *symbols, int num_values,
|
|||||||
max_value_bits = bits::MostSignificantBit(max_entry_value);
|
max_value_bits = bits::MostSignificantBit(max_entry_value);
|
||||||
}
|
}
|
||||||
const int max_value_bit_length = max_value_bits + 1;
|
const int max_value_bit_length = max_value_bits + 1;
|
||||||
// Currently, we don't support encoding of values larger than 2^20.
|
// Currently, we don't support encoding of values larger than 2^18.
|
||||||
if (max_value_bit_length > kMaxRawEncodingBitLength)
|
if (max_value_bit_length > kMaxRawEncodingBitLength)
|
||||||
return false;
|
return false;
|
||||||
target_buffer->Encode(static_cast<uint8_t>(max_value_bit_length));
|
target_buffer->Encode(static_cast<uint8_t>(max_value_bit_length));
|
||||||
|
File diff suppressed because one or more lines are too long
25
javascript/draco_mesh_decoder.js
Normal file
25
javascript/draco_mesh_decoder.js
Normal file
File diff suppressed because one or more lines are too long
26
javascript/draco_point_cloud_decoder.js
Normal file
26
javascript/draco_point_cloud_decoder.js
Normal file
File diff suppressed because one or more lines are too long
@ -40,7 +40,7 @@ Options::Options()
|
|||||||
pos_quantization_bits(14),
|
pos_quantization_bits(14),
|
||||||
tex_coords_quantization_bits(12),
|
tex_coords_quantization_bits(12),
|
||||||
normals_quantization_bits(10),
|
normals_quantization_bits(10),
|
||||||
compression_level(5) {}
|
compression_level(7) {}
|
||||||
|
|
||||||
void Usage() {
|
void Usage() {
|
||||||
printf("Usage: draco_encoder [options] -i input\n");
|
printf("Usage: draco_encoder [options] -i input\n");
|
||||||
@ -63,7 +63,7 @@ void Usage() {
|
|||||||
"attribute, default=10.\n");
|
"attribute, default=10.\n");
|
||||||
printf(
|
printf(
|
||||||
" -cl <value> compression level [0-10], most=10, least=0, "
|
" -cl <value> compression level [0-10], most=10, least=0, "
|
||||||
"default=5.\n");
|
"default=7.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int StringToInt(const std::string &s) {
|
int StringToInt(const std::string &s) {
|
||||||
@ -246,7 +246,18 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PrintOptions(*pc.get(), options);
|
PrintOptions(*pc.get(), options);
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
if (mesh && mesh->num_faces() > 0)
|
if (mesh && mesh->num_faces() > 0)
|
||||||
return EncodeMeshToFile(*mesh, encoder_options, options.output);
|
ret = EncodeMeshToFile(*mesh, encoder_options, options.output);
|
||||||
return EncodePointCloudToFile(*pc.get(), encoder_options, options.output);
|
else
|
||||||
|
ret = EncodePointCloudToFile(*pc.get(), encoder_options, options.output);
|
||||||
|
|
||||||
|
if (ret != -1 && options.compression_level < 10) {
|
||||||
|
printf(
|
||||||
|
"For better compression, increase the compression level '-cl' (up to "
|
||||||
|
"10).\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user