Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/extern
diff options
context:
space:
mode:
authorJim Eckerlein <UX3D-eckerlein>2022-06-17 19:38:41 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-06-17 20:40:01 +0300
commit33bad77043d3ec4b91bc302af69da8c7ba9dd204 (patch)
tree7a64d3c2e0b2ad3864f1581fe0c23e3f833c9e5d /extern
parent524a9e3db8102c89abf3b80cddaea60c314d67ae (diff)
Draco: update to version 1.5.2
Differential Revision: https://developer.blender.org/D15233
Diffstat (limited to 'extern')
-rw-r--r--extern/draco/README.blender4
-rw-r--r--extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc95
-rw-r--r--extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h31
-rw-r--r--extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc113
-rw-r--r--extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h38
-rw-r--r--extern/draco/draco/src/draco/attributes/attribute_transform.cc25
-rw-r--r--extern/draco/draco/src/draco/attributes/attribute_transform.h36
-rw-r--r--extern/draco/draco/src/draco/attributes/geometry_attribute.cc12
-rw-r--r--extern/draco/draco/src/draco/attributes/geometry_attribute.h42
-rw-r--r--extern/draco/draco/src/draco/attributes/point_attribute.cc43
-rw-r--r--extern/draco/draco/src/draco/attributes/point_attribute.h6
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc22
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc16
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc19
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc15
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h6
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h133
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h4
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h9
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h9
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h7
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc33
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h4
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h6
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h18
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h2
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc4
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc15
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc3
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc44
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h3
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc13
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc64
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h8
-rw-r--r--extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc19
-rw-r--r--extern/draco/draco/src/draco/compression/config/compression_shared.h3
-rw-r--r--extern/draco/draco/src/draco/compression/config/draco_options.h6
-rw-r--r--extern/draco/draco/src/draco/compression/decode.cc5
-rw-r--r--extern/draco/draco/src/draco/compression/encode_base.h8
-rw-r--r--extern/draco/draco/src/draco/compression/entropy/ans.h7
-rw-r--r--extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h9
-rw-r--r--extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h4
-rw-r--r--extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc2
-rw-r--r--extern/draco/draco/src/draco/compression/expert_encode.cc2
-rw-r--r--extern/draco/draco/src/draco/compression/expert_encode.h6
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc31
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc1
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc2
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h1
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h2
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h7
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc7
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc4
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h1
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h2
-rw-r--r--extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h2
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h5
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h5
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc27
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h4
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h3
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h3
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h2
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc10
-rw-r--r--extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc14
-rw-r--r--extern/draco/draco/src/draco/core/bounding_box.cc13
-rw-r--r--extern/draco/draco/src/draco/core/bounding_box.h42
-rw-r--r--extern/draco/draco/src/draco/core/cycle_timer.cc14
-rw-r--r--extern/draco/draco/src/draco/core/cycle_timer.h7
-rw-r--r--extern/draco/draco/src/draco/core/data_buffer.cc2
-rw-r--r--extern/draco/draco/src/draco/core/decoder_buffer.h12
-rw-r--r--extern/draco/draco/src/draco/core/draco_index_type_vector.h3
-rw-r--r--extern/draco/draco/src/draco/core/draco_version.h2
-rw-r--r--extern/draco/draco/src/draco/core/macros.h27
-rw-r--r--extern/draco/draco/src/draco/core/options.h2
-rw-r--r--extern/draco/draco/src/draco/core/status.h4
-rw-r--r--extern/draco/draco/src/draco/core/varint_decoding.h1
-rw-r--r--extern/draco/draco/src/draco/core/vector_d.h14
-rw-r--r--extern/draco/draco/src/draco/draco_features.h2
-rw-r--r--extern/draco/draco/src/draco/mesh/corner_table.cc7
-rw-r--r--extern/draco/draco/src/draco/mesh/mesh.h4
-rw-r--r--extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h6
-rw-r--r--extern/draco/draco/src/draco/mesh/mesh_cleanup.cc321
-rw-r--r--extern/draco/draco/src/draco/mesh/mesh_cleanup.h27
-rw-r--r--extern/draco/draco/src/draco/mesh/mesh_misc_functions.h1
-rw-r--r--extern/draco/draco/src/draco/mesh/mesh_stripifier.h8
-rw-r--r--extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc2
-rw-r--r--extern/draco/draco/src/draco/metadata/geometry_metadata.cc15
-rw-r--r--extern/draco/draco/src/draco/metadata/geometry_metadata.h2
-rw-r--r--extern/draco/draco/src/draco/metadata/metadata.cc8
-rw-r--r--extern/draco/draco/src/draco/metadata/metadata.h1
-rw-r--r--extern/draco/draco/src/draco/metadata/metadata_decoder.cc10
-rw-r--r--extern/draco/draco/src/draco/point_cloud/point_cloud.cc16
-rw-r--r--extern/draco/patches/blender.patch30
-rw-r--r--extern/draco/src/common.cpp28
-rw-r--r--extern/draco/src/common.h2
-rw-r--r--extern/draco/src/decoder.cpp74
-rw-r--r--extern/draco/src/decoder.h36
-rw-r--r--extern/draco/src/encoder.cpp97
-rw-r--r--extern/draco/src/encoder.h33
100 files changed, 1305 insertions, 674 deletions
diff --git a/extern/draco/README.blender b/extern/draco/README.blender
index b9c3bbb967d..a879ded978b 100644
--- a/extern/draco/README.blender
+++ b/extern/draco/README.blender
@@ -1,5 +1,5 @@
Project: Draco
URL: https://google.github.io/draco/
License: Apache 2.0
-Upstream version: 1.3.6
-Local modifications: None
+Upstream version: 1.5.2
+Local modifications: Apply patches/blender.patch
diff --git a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc
index 283a21251f4..51c3bb6c872 100644
--- a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc
+++ b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.cc
@@ -38,6 +38,46 @@ void AttributeOctahedronTransform::CopyToAttributeTransformData(
out_data->AppendParameterValue(quantization_bits_);
}
+bool AttributeOctahedronTransform::TransformAttribute(
+ const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
+ PointAttribute *target_attribute) {
+ return GeneratePortableAttribute(attribute, point_ids,
+ target_attribute->size(), target_attribute);
+}
+
+bool AttributeOctahedronTransform::InverseTransformAttribute(
+ const PointAttribute &attribute, PointAttribute *target_attribute) {
+ if (target_attribute->data_type() != DT_FLOAT32) {
+ return false;
+ }
+
+ const int num_points = target_attribute->size();
+ const int num_components = target_attribute->num_components();
+ if (num_components != 3) {
+ return false;
+ }
+ constexpr int kEntrySize = sizeof(float) * 3;
+ float att_val[3];
+ const int32_t *source_attribute_data = reinterpret_cast<const int32_t *>(
+ attribute.GetAddress(AttributeValueIndex(0)));
+ uint8_t *target_address =
+ target_attribute->GetAddress(AttributeValueIndex(0));
+ OctahedronToolBox octahedron_tool_box;
+ if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_)) {
+ return false;
+ }
+ for (uint32_t i = 0; i < num_points; ++i) {
+ const int32_t s = *source_attribute_data++;
+ const int32_t t = *source_attribute_data++;
+ octahedron_tool_box.QuantizedOctahedralCoordsToUnitVector(s, t, att_val);
+
+ // Store the decoded floating point values into the attribute buffer.
+ std::memcpy(target_address, att_val, kEntrySize);
+ target_address += kEntrySize;
+ }
+ return true;
+}
+
void AttributeOctahedronTransform::SetParameters(int quantization_bits) {
quantization_bits_ = quantization_bits;
}
@@ -51,38 +91,55 @@ bool AttributeOctahedronTransform::EncodeParameters(
return false;
}
-std::unique_ptr<PointAttribute>
-AttributeOctahedronTransform::GeneratePortableAttribute(
+bool AttributeOctahedronTransform::DecodeParameters(
+ const PointAttribute &attribute, DecoderBuffer *decoder_buffer) {
+ uint8_t quantization_bits;
+ if (!decoder_buffer->Decode(&quantization_bits)) {
+ return false;
+ }
+ quantization_bits_ = quantization_bits;
+ return true;
+}
+
+bool AttributeOctahedronTransform::GeneratePortableAttribute(
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
- int num_points) const {
+ int num_points, PointAttribute *target_attribute) const {
DRACO_DCHECK(is_initialized());
- // Allocate portable attribute.
- const int num_entries = static_cast<int>(point_ids.size());
- std::unique_ptr<PointAttribute> portable_attribute =
- InitPortableAttribute(num_entries, 2, num_points, attribute, true);
-
// Quantize all values in the order given by point_ids into portable
// attribute.
int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>(
- portable_attribute->GetAddress(AttributeValueIndex(0)));
+ target_attribute->GetAddress(AttributeValueIndex(0)));
float att_val[3];
int32_t dst_index = 0;
OctahedronToolBox converter;
if (!converter.SetQuantizationBits(quantization_bits_)) {
- return nullptr;
+ return false;
}
- for (uint32_t i = 0; i < point_ids.size(); ++i) {
- const AttributeValueIndex att_val_id = attribute.mapped_index(point_ids[i]);
- attribute.GetValue(att_val_id, att_val);
- // Encode the vector into a s and t octahedral coordinates.
- int32_t s, t;
- converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
- portable_attribute_data[dst_index++] = s;
- portable_attribute_data[dst_index++] = t;
+ if (!point_ids.empty()) {
+ for (uint32_t i = 0; i < point_ids.size(); ++i) {
+ const AttributeValueIndex att_val_id =
+ attribute.mapped_index(point_ids[i]);
+ attribute.GetValue(att_val_id, att_val);
+ // Encode the vector into a s and t octahedral coordinates.
+ int32_t s, t;
+ converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
+ portable_attribute_data[dst_index++] = s;
+ portable_attribute_data[dst_index++] = t;
+ }
+ } else {
+ for (PointIndex i(0); i < num_points; ++i) {
+ const AttributeValueIndex att_val_id = attribute.mapped_index(i);
+ attribute.GetValue(att_val_id, att_val);
+ // Encode the vector into a s and t octahedral coordinates.
+ int32_t s, t;
+ converter.FloatVectorToQuantizedOctahedralCoords(att_val, &s, &t);
+ portable_attribute_data[dst_index++] = s;
+ portable_attribute_data[dst_index++] = t;
+ }
}
- return portable_attribute;
+ return true;
}
} // namespace draco
diff --git a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h
index 6e4e74284f0..21a1725bb52 100644
--- a/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h
+++ b/extern/draco/draco/src/draco/attributes/attribute_octahedron_transform.h
@@ -37,19 +37,40 @@ class AttributeOctahedronTransform : public AttributeTransform {
void CopyToAttributeTransformData(
AttributeTransformData *out_data) const override;
+ bool TransformAttribute(const PointAttribute &attribute,
+ const std::vector<PointIndex> &point_ids,
+ PointAttribute *target_attribute) override;
+
+ bool InverseTransformAttribute(const PointAttribute &attribute,
+ PointAttribute *target_attribute) override;
+
// Set number of quantization bits.
void SetParameters(int quantization_bits);
// Encode relevant parameters into buffer.
- bool EncodeParameters(EncoderBuffer *encoder_buffer) const;
+ bool EncodeParameters(EncoderBuffer *encoder_buffer) const override;
+
+ bool DecodeParameters(const PointAttribute &attribute,
+ DecoderBuffer *decoder_buffer) override;
bool is_initialized() const { return quantization_bits_ != -1; }
int32_t quantization_bits() const { return quantization_bits_; }
- // Create portable attribute.
- std::unique_ptr<PointAttribute> GeneratePortableAttribute(
- const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
- int num_points) const;
+ protected:
+ DataType GetTransformedDataType(
+ const PointAttribute &attribute) const override {
+ return DT_UINT32;
+ }
+ int GetTransformedNumComponents(
+ const PointAttribute &attribute) const override {
+ return 2;
+ }
+
+ // Perform the actual transformation.
+ bool GeneratePortableAttribute(const PointAttribute &attribute,
+ const std::vector<PointIndex> &point_ids,
+ int num_points,
+ PointAttribute *target_attribute) const;
private:
int32_t quantization_bits_;
diff --git a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc
index daa634ed03f..a7f93a488d7 100644
--- a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc
+++ b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.cc
@@ -1,4 +1,3 @@
-
// Copyright 2017 The Draco Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -51,13 +50,74 @@ void AttributeQuantizationTransform::CopyToAttributeTransformData(
out_data->AppendParameterValue(range_);
}
-void AttributeQuantizationTransform::SetParameters(int quantization_bits,
+bool AttributeQuantizationTransform::TransformAttribute(
+ const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
+ PointAttribute *target_attribute) {
+ if (point_ids.empty()) {
+ GeneratePortableAttribute(attribute, target_attribute->size(),
+ target_attribute);
+ } else {
+ GeneratePortableAttribute(attribute, point_ids, target_attribute->size(),
+ target_attribute);
+ }
+ return true;
+}
+
+bool AttributeQuantizationTransform::InverseTransformAttribute(
+ const PointAttribute &attribute, PointAttribute *target_attribute) {
+ if (target_attribute->data_type() != DT_FLOAT32) {
+ return false;
+ }
+
+ // Convert all quantized values back to floats.
+ const int32_t max_quantized_value =
+ (1u << static_cast<uint32_t>(quantization_bits_)) - 1;
+ const int num_components = target_attribute->num_components();
+ const int entry_size = sizeof(float) * num_components;
+ const std::unique_ptr<float[]> att_val(new float[num_components]);
+ int quant_val_id = 0;
+ int out_byte_pos = 0;
+ Dequantizer dequantizer;
+ if (!dequantizer.Init(range_, max_quantized_value)) {
+ return false;
+ }
+ const int32_t *const source_attribute_data =
+ reinterpret_cast<const int32_t *>(
+ attribute.GetAddress(AttributeValueIndex(0)));
+
+ const int num_values = target_attribute->size();
+
+ for (uint32_t i = 0; i < num_values; ++i) {
+ for (int c = 0; c < num_components; ++c) {
+ float value =
+ dequantizer.DequantizeFloat(source_attribute_data[quant_val_id++]);
+ value = value + min_values_[c];
+ att_val[c] = value;
+ }
+ // Store the floating point value into the attribute buffer.
+ target_attribute->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
+ out_byte_pos += entry_size;
+ }
+ return true;
+}
+
+bool AttributeQuantizationTransform::IsQuantizationValid(
+ int quantization_bits) {
+ // Currently we allow only up to 30 bit quantization.
+ return quantization_bits >= 1 && quantization_bits <= 30;
+}
+
+bool AttributeQuantizationTransform::SetParameters(int quantization_bits,
const float *min_values,
int num_components,
float range) {
+ if (!IsQuantizationValid(quantization_bits)) {
+ return false;
+ }
quantization_bits_ = quantization_bits;
min_values_.assign(min_values, min_values + num_components);
range_ = range;
+ return true;
}
bool AttributeQuantizationTransform::ComputeParameters(
@@ -65,6 +125,9 @@ bool AttributeQuantizationTransform::ComputeParameters(
if (quantization_bits_ != -1) {
return false; // already initialized.
}
+ if (!IsQuantizationValid(quantization_bits)) {
+ return false;
+ }
quantization_bits_ = quantization_bits;
const int num_components = attribute.num_components();
@@ -121,20 +184,37 @@ bool AttributeQuantizationTransform::EncodeParameters(
return false;
}
-std::unique_ptr<PointAttribute>
-AttributeQuantizationTransform::GeneratePortableAttribute(
- const PointAttribute &attribute, int num_points) const {
+bool AttributeQuantizationTransform::DecodeParameters(
+ const PointAttribute &attribute, DecoderBuffer *decoder_buffer) {
+ min_values_.resize(attribute.num_components());
+ if (!decoder_buffer->Decode(&min_values_[0],
+ sizeof(float) * min_values_.size())) {
+ return false;
+ }
+ if (!decoder_buffer->Decode(&range_)) {
+ return false;
+ }
+ uint8_t quantization_bits;
+ if (!decoder_buffer->Decode(&quantization_bits)) {
+ return false;
+ }
+ if (!IsQuantizationValid(quantization_bits)) {
+ return false;
+ }
+ quantization_bits_ = quantization_bits;
+ return true;
+}
+
+void AttributeQuantizationTransform::GeneratePortableAttribute(
+ const PointAttribute &attribute, int num_points,
+ PointAttribute *target_attribute) const {
DRACO_DCHECK(is_initialized());
- // Allocate portable attribute.
- const int num_entries = num_points;
const int num_components = attribute.num_components();
- std::unique_ptr<PointAttribute> portable_attribute =
- InitPortableAttribute(num_entries, num_components, 0, attribute, true);
// Quantize all values using the order given by point_ids.
int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>(
- portable_attribute->GetAddress(AttributeValueIndex(0)));
+ target_attribute->GetAddress(AttributeValueIndex(0)));
const uint32_t max_quantized_value = (1 << (quantization_bits_)) - 1;
Quantizer quantizer;
quantizer.Init(range(), max_quantized_value);
@@ -149,24 +229,18 @@ AttributeQuantizationTransform::GeneratePortableAttribute(
portable_attribute_data[dst_index++] = q_val;
}
}
- return portable_attribute;
}
-std::unique_ptr<PointAttribute>
-AttributeQuantizationTransform::GeneratePortableAttribute(
+void AttributeQuantizationTransform::GeneratePortableAttribute(
const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
- int num_points) const {
+ int num_points, PointAttribute *target_attribute) const {
DRACO_DCHECK(is_initialized());
- // Allocate portable attribute.
- const int num_entries = static_cast<int>(point_ids.size());
const int num_components = attribute.num_components();
- std::unique_ptr<PointAttribute> portable_attribute = InitPortableAttribute(
- num_entries, num_components, num_points, attribute, true);
// Quantize all values using the order given by point_ids.
int32_t *const portable_attribute_data = reinterpret_cast<int32_t *>(
- portable_attribute->GetAddress(AttributeValueIndex(0)));
+ target_attribute->GetAddress(AttributeValueIndex(0)));
const uint32_t max_quantized_value = (1 << (quantization_bits_)) - 1;
Quantizer quantizer;
quantizer.Init(range(), max_quantized_value);
@@ -181,7 +255,6 @@ AttributeQuantizationTransform::GeneratePortableAttribute(
portable_attribute_data[dst_index++] = q_val;
}
}
- return portable_attribute;
}
} // namespace draco
diff --git a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h
index 934856f2db7..f1122b680ab 100644
--- a/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h
+++ b/extern/draco/draco/src/draco/attributes/attribute_quantization_transform.h
@@ -37,14 +37,24 @@ class AttributeQuantizationTransform : public AttributeTransform {
void CopyToAttributeTransformData(
AttributeTransformData *out_data) const override;
- void SetParameters(int quantization_bits, const float *min_values,
+ bool TransformAttribute(const PointAttribute &attribute,
+ const std::vector<PointIndex> &point_ids,
+ PointAttribute *target_attribute) override;
+
+ bool InverseTransformAttribute(const PointAttribute &attribute,
+ PointAttribute *target_attribute) override;
+
+ bool SetParameters(int quantization_bits, const float *min_values,
int num_components, float range);
bool ComputeParameters(const PointAttribute &attribute,
const int quantization_bits);
// Encode relevant parameters into buffer.
- bool EncodeParameters(EncoderBuffer *encoder_buffer) const;
+ bool EncodeParameters(EncoderBuffer *encoder_buffer) const override;
+
+ bool DecodeParameters(const PointAttribute &attribute,
+ DecoderBuffer *decoder_buffer) override;
int32_t quantization_bits() const { return quantization_bits_; }
float min_value(int axis) const { return min_values_[axis]; }
@@ -52,16 +62,30 @@ class AttributeQuantizationTransform : public AttributeTransform {
float range() const { return range_; }
bool is_initialized() const { return quantization_bits_ != -1; }
+ protected:
// Create portable attribute using 1:1 mapping between points in the input and
// output attribute.
- std::unique_ptr<PointAttribute> GeneratePortableAttribute(
- const PointAttribute &attribute, int num_points) const;
+ void GeneratePortableAttribute(const PointAttribute &attribute,
+ int num_points,
+ PointAttribute *target_attribute) const;
// Create portable attribute using custom mapping between input and output
// points.
- std::unique_ptr<PointAttribute> GeneratePortableAttribute(
- const PointAttribute &attribute, const std::vector<PointIndex> &point_ids,
- int num_points) const;
+ void GeneratePortableAttribute(const PointAttribute &attribute,
+ const std::vector<PointIndex> &point_ids,
+ int num_points,
+ PointAttribute *target_attribute) const;
+
+ DataType GetTransformedDataType(
+ const PointAttribute &attribute) const override {
+ return DT_UINT32;
+ }
+ int GetTransformedNumComponents(
+ const PointAttribute &attribute) const override {
+ return attribute.num_components();
+ }
+
+ static bool IsQuantizationValid(int quantization_bits);
private:
int32_t quantization_bits_;
diff --git a/extern/draco/draco/src/draco/attributes/attribute_transform.cc b/extern/draco/draco/src/draco/attributes/attribute_transform.cc
index 55af630ac07..fb2ed18297a 100644
--- a/extern/draco/draco/src/draco/attributes/attribute_transform.cc
+++ b/extern/draco/draco/src/draco/attributes/attribute_transform.cc
@@ -24,21 +24,18 @@ bool AttributeTransform::TransferToAttribute(PointAttribute *attribute) const {
return true;
}
-std::unique_ptr<PointAttribute> AttributeTransform::InitPortableAttribute(
- int num_entries, int num_components, int num_points,
- const PointAttribute &attribute, bool is_unsigned) const {
- const DataType dt = is_unsigned ? DT_UINT32 : DT_INT32;
- GeometryAttribute va;
- va.Init(attribute.attribute_type(), nullptr, num_components, dt, false,
+std::unique_ptr<PointAttribute> AttributeTransform::InitTransformedAttribute(
+ const PointAttribute &src_attribute, int num_entries) {
+ const int num_components = GetTransformedNumComponents(src_attribute);
+ const DataType dt = GetTransformedDataType(src_attribute);
+ GeometryAttribute ga;
+ ga.Init(src_attribute.attribute_type(), nullptr, num_components, dt, false,
num_components * DataTypeLength(dt), 0);
- std::unique_ptr<PointAttribute> portable_attribute(new PointAttribute(va));
- portable_attribute->Reset(num_entries);
- if (num_points) {
- portable_attribute->SetExplicitMapping(num_points);
- } else {
- portable_attribute->SetIdentityMapping();
- }
- return portable_attribute;
+ std::unique_ptr<PointAttribute> transformed_attribute(new PointAttribute(ga));
+ transformed_attribute->Reset(num_entries);
+ transformed_attribute->SetIdentityMapping();
+ transformed_attribute->set_unique_id(src_attribute.unique_id());
+ return transformed_attribute;
}
} // namespace draco
diff --git a/extern/draco/draco/src/draco/attributes/attribute_transform.h b/extern/draco/draco/src/draco/attributes/attribute_transform.h
index d746fbf6eea..62aad60db91 100644
--- a/extern/draco/draco/src/draco/attributes/attribute_transform.h
+++ b/extern/draco/draco/src/draco/attributes/attribute_transform.h
@@ -17,6 +17,8 @@
#include "draco/attributes/attribute_transform_data.h"
#include "draco/attributes/point_attribute.h"
+#include "draco/core/decoder_buffer.h"
+#include "draco/core/encoder_buffer.h"
namespace draco {
@@ -35,10 +37,38 @@ class AttributeTransform {
AttributeTransformData *out_data) const = 0;
bool TransferToAttribute(PointAttribute *attribute) const;
+ // Applies the transform to |attribute| and stores the result in
+ // |target_attribute|. |point_ids| is an optional vector that can be used to
+ // remap values during the transform.
+ virtual bool TransformAttribute(const PointAttribute &attribute,
+ const std::vector<PointIndex> &point_ids,
+ PointAttribute *target_attribute) = 0;
+
+ // Applies an inverse transform to |attribute| and stores the result in
+ // |target_attribute|. In this case, |attribute| is an attribute that was
+ // already transformed (e.g. quantized) and |target_attribute| is the
+ // attribute before the transformation.
+ virtual bool InverseTransformAttribute(const PointAttribute &attribute,
+ PointAttribute *target_attribute) = 0;
+
+ // Encodes all data needed by the transformation into the |encoder_buffer|.
+ virtual bool EncodeParameters(EncoderBuffer *encoder_buffer) const = 0;
+
+ // Decodes all data needed to transform |attribute| back to the original
+ // format.
+ virtual bool DecodeParameters(const PointAttribute &attribute,
+ DecoderBuffer *decoder_buffer) = 0;
+
+ // Initializes a transformed attribute that can be used as target in the
+ // TransformAttribute() function call.
+ virtual std::unique_ptr<PointAttribute> InitTransformedAttribute(
+ const PointAttribute &src_attribute, int num_entries);
+
protected:
- std::unique_ptr<PointAttribute> InitPortableAttribute(
- int num_entries, int num_components, int num_points,
- const PointAttribute &attribute, bool is_unsigned) const;
+ virtual DataType GetTransformedDataType(
+ const PointAttribute &attribute) const = 0;
+ virtual int GetTransformedNumComponents(
+ const PointAttribute &attribute) const = 0;
};
} // namespace draco
diff --git a/extern/draco/draco/src/draco/attributes/geometry_attribute.cc b/extern/draco/draco/src/draco/attributes/geometry_attribute.cc
index f7ed6a86915..b624784261d 100644
--- a/extern/draco/draco/src/draco/attributes/geometry_attribute.cc
+++ b/extern/draco/draco/src/draco/attributes/geometry_attribute.cc
@@ -43,10 +43,6 @@ void GeometryAttribute::Init(GeometryAttribute::Type attribute_type,
}
bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) {
- if (buffer_ == nullptr || src_att.buffer_ == nullptr) {
- return false;
- }
- buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size());
num_components_ = src_att.num_components_;
data_type_ = src_att.data_type_;
normalized_ = src_att.normalized_;
@@ -55,6 +51,14 @@ bool GeometryAttribute::CopyFrom(const GeometryAttribute &src_att) {
attribute_type_ = src_att.attribute_type_;
buffer_descriptor_ = src_att.buffer_descriptor_;
unique_id_ = src_att.unique_id_;
+ if (src_att.buffer_ == nullptr) {
+ buffer_ = nullptr;
+ } else {
+ if (buffer_ == nullptr) {
+ return false;
+ }
+ buffer_->Update(src_att.buffer_->data(), src_att.buffer_->data_size());
+ }
return true;
}
diff --git a/extern/draco/draco/src/draco/attributes/geometry_attribute.h b/extern/draco/draco/src/draco/attributes/geometry_attribute.h
index b94ba8e22dd..c5faccc1b83 100644
--- a/extern/draco/draco/src/draco/attributes/geometry_attribute.h
+++ b/extern/draco/draco/src/draco/attributes/geometry_attribute.h
@@ -21,6 +21,7 @@
#include "draco/attributes/geometry_indices.h"
#include "draco/core/data_buffer.h"
#include "draco/core/hash_utils.h"
+#include "draco/draco_features.h"
namespace draco {
@@ -51,6 +52,16 @@ class GeometryAttribute {
// predefined use case. Such attributes are often used for a shader specific
// data.
GENERIC,
+#ifdef DRACO_TRANSCODER_SUPPORTED
+ // TODO(ostava): Adding a new attribute would be bit-stream change for GLTF.
+ // Older decoders wouldn't know what to do with this attribute type. This
+ // should be open-sourced only when we are ready to increase our bit-stream
+ // version.
+ TANGENT,
+ MATERIAL,
+ JOINTS,
+ WEIGHTS,
+#endif
// Total number of different attribute types.
// Always keep behind all named attributes.
NAMED_ATTRIBUTES_COUNT,
@@ -111,6 +122,9 @@ class GeometryAttribute {
const int64_t byte_pos = GetBytePos(att_index);
return buffer_->data() + byte_pos;
}
+ inline bool IsAddressValid(const uint8_t *address) const {
+ return ((buffer_->data() + buffer_->data_size()) > address);
+ }
// Fills out_data with the raw value of the requested attribute entry.
// out_data must be at least byte_stride_ long.
@@ -263,7 +277,35 @@ class GeometryAttribute {
// Convert all components available in both the original and output formats.
for (int i = 0; i < std::min(num_components_, out_num_components); ++i) {
+ if (!IsAddressValid(src_address)) {
+ return false;
+ }
const T in_value = *reinterpret_cast<const T *>(src_address);
+
+ // Make sure the in_value fits within the range of values that OutT
+ // is able to represent. Perform the check only for integral types.
+ if (std::is_integral<T>::value && std::is_integral<OutT>::value) {
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4804)
+#endif
+#if defined(__GNUC__) && !defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wbool-compare"
+#endif
+ static constexpr OutT kOutMin =
+ std::is_signed<T>::value ? std::numeric_limits<OutT>::lowest() : 0;
+ if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) {
+ return false;
+ }
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+ }
+
out_value[i] = static_cast<OutT>(in_value);
// When converting integer to floating point, normalize the value if
// necessary.
diff --git a/extern/draco/draco/src/draco/attributes/point_attribute.cc b/extern/draco/draco/src/draco/attributes/point_attribute.cc
index b28f860c15d..e54ab54278f 100644
--- a/extern/draco/draco/src/draco/attributes/point_attribute.cc
+++ b/extern/draco/draco/src/draco/attributes/point_attribute.cc
@@ -222,4 +222,47 @@ AttributeValueIndex::ValueType PointAttribute::DeduplicateFormattedValues(
}
#endif
+#ifdef DRACO_TRANSCODER_SUPPORTED
+void PointAttribute::RemoveUnusedValues() {
+ if (is_mapping_identity()) {
+ return; // For identity mapping, all values are always used.
+ }
+ // For explicit mapping we need to check if any point is mapped to a value.
+ // If not we can delete the value.
+ IndexTypeVector<AttributeValueIndex, bool> is_value_used(size(), false);
+ int num_used_values = 0;
+ for (PointIndex pi(0); pi < indices_map_.size(); ++pi) {
+ const AttributeValueIndex avi = indices_map_[pi];
+ if (!is_value_used[avi]) {
+ is_value_used[avi] = true;
+ num_used_values++;
+ }
+ }
+ if (num_used_values == size()) {
+ return; // All values are used.
+ }
+
+ // Remap the values and update the point to value mapping.
+ IndexTypeVector<AttributeValueIndex, AttributeValueIndex>
+ old_to_new_value_map(size(), kInvalidAttributeValueIndex);
+ AttributeValueIndex new_avi(0);
+ for (AttributeValueIndex avi(0); avi < size(); ++avi) {
+ if (!is_value_used[avi]) {
+ continue;
+ }
+ if (avi != new_avi) {
+ SetAttributeValue(new_avi, GetAddress(avi));
+ }
+ old_to_new_value_map[avi] = new_avi++;
+ }
+
+ // Remap all points to the new attribute values.
+ for (PointIndex pi(0); pi < indices_map_.size(); ++pi) {
+ indices_map_[pi] = old_to_new_value_map[indices_map_[pi]];
+ }
+
+ num_unique_entries_ = num_used_values;
+}
+#endif
+
} // namespace draco
diff --git a/extern/draco/draco/src/draco/attributes/point_attribute.h b/extern/draco/draco/src/draco/attributes/point_attribute.h
index ee36620313e..d55c50c8a57 100644
--- a/extern/draco/draco/src/draco/attributes/point_attribute.h
+++ b/extern/draco/draco/src/draco/attributes/point_attribute.h
@@ -133,6 +133,12 @@ class PointAttribute : public GeometryAttribute {
return attribute_transform_data_.get();
}
+#ifdef DRACO_TRANSCODER_SUPPORTED
+ // Removes unused values from the attribute. Value is unused when no point
+ // is mapped to the value. Only applicable when the mapping is not identity.
+ void RemoveUnusedValues();
+#endif
+
private:
#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
template <typename T>
diff --git a/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc
index ce5b8b9c756..007dd2f4303 100644
--- a/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/attributes_decoder.cc
@@ -43,9 +43,18 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
return false;
}
}
+
+ // Check that decoded number of attributes is valid.
if (num_attributes == 0) {
return false;
}
+ if (num_attributes > 5 * in_buffer->remaining_size()) {
+ // The decoded number of attributes is unreasonably high, because at least
+ // five bytes of attribute descriptor data per attribute are expected.
+ return false;
+ }
+
+ // Decode attribute descriptor data.
point_attribute_ids_.resize(num_attributes);
PointCloud *pc = point_cloud_;
for (uint32_t i = 0; i < num_attributes; ++i) {
@@ -69,9 +78,14 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
if (data_type == DT_INVALID || data_type >= DT_TYPES_COUNT) {
return false;
}
- const DataType draco_dt = static_cast<DataType>(data_type);
- // Add the attribute to the point cloud
+ // Check decoded attribute descriptor data.
+ if (num_components == 0) {
+ return false;
+ }
+
+ // Add the attribute to the point cloud.
+ const DataType draco_dt = static_cast<DataType>(data_type);
GeometryAttribute ga;
ga.Init(static_cast<GeometryAttribute::Type>(att_type), nullptr,
num_components, draco_dt, normalized > 0,
@@ -90,7 +104,9 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
} else
#endif
{
- DecodeVarint(&unique_id, in_buffer);
+ if (!DecodeVarint(&unique_id, in_buffer)) {
+ return false;
+ }
ga.set_unique_id(unique_id);
}
const int att_id = pc->AddAttribute(
diff --git a/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc
index 797c62f30aa..480e3ff3436 100644
--- a/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/attributes_encoder.cc
@@ -15,14 +15,16 @@
#include "draco/compression/attributes/attributes_encoder.h"
#include "draco/core/varint_encoding.h"
+#include "draco/draco_features.h"
namespace draco {
AttributesEncoder::AttributesEncoder()
: point_cloud_encoder_(nullptr), point_cloud_(nullptr) {}
-AttributesEncoder::AttributesEncoder(int att_id) : AttributesEncoder() {
- AddAttributeId(att_id);
+AttributesEncoder::AttributesEncoder(int point_attrib_id)
+ : AttributesEncoder() {
+ AddAttributeId(point_attrib_id);
}
bool AttributesEncoder::Init(PointCloudEncoder *encoder, const PointCloud *pc) {
@@ -37,7 +39,15 @@ bool AttributesEncoder::EncodeAttributesEncoderData(EncoderBuffer *out_buffer) {
for (uint32_t i = 0; i < num_attributes(); ++i) {
const int32_t att_id = point_attribute_ids_[i];
const PointAttribute *const pa = point_cloud_->attribute(att_id);
- out_buffer->Encode(static_cast<uint8_t>(pa->attribute_type()));
+ GeometryAttribute::Type type = pa->attribute_type();
+#ifdef DRACO_TRANSCODER_SUPPORTED
+ // Attribute types TANGENT, MATERIAL, JOINTS, and WEIGHTS are not supported
+ // in the official bitstream. They will be encoded as GENERIC.
+ if (type > GeometryAttribute::GENERIC) {
+ type = GeometryAttribute::GENERIC;
+ }
+#endif
+ out_buffer->Encode(static_cast<uint8_t>(type));
out_buffer->Encode(static_cast<uint8_t>(pa->data_type()));
out_buffer->Encode(static_cast<uint8_t>(pa->num_components()));
out_buffer->Encode(static_cast<uint8_t>(pa->normalized()));
diff --git a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc
index 99469f94590..c7c96d77007 100644
--- a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_decoder.cc
@@ -72,7 +72,7 @@ class PointAttributeVectorOutputIterator {
Self &operator*() { return *this; }
// Still needed in some cases.
- // TODO(hemmer): remove.
+ // TODO(b/199760123): Remove.
// hardcoded to 3 based on legacy usage.
const Self &operator=(const VectorD<CoeffT, 3> &val) {
DRACO_DCHECK_EQ(attributes_.size(), 1); // Expect only ONE attribute.
@@ -278,8 +278,10 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
return false;
}
AttributeQuantizationTransform transform;
- transform.SetParameters(quantization_bits, min_value.data(),
- num_components, max_value_dif);
+ if (!transform.SetParameters(quantization_bits, min_value.data(),
+ num_components, max_value_dif)) {
+ return false;
+ }
const int num_transforms =
static_cast<int>(attribute_quantization_transforms_.size());
if (!transform.TransferToAttribute(
@@ -293,7 +295,9 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
// Decode transform data for signed integer attributes.
for (int i = 0; i < min_signed_values_.size(); ++i) {
int32_t val;
- DecodeVarint(&val, in_buffer);
+ if (!DecodeVarint(&val, in_buffer)) {
+ return false;
+ }
min_signed_values_[i] = val;
}
return true;
@@ -353,8 +357,9 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
return false;
}
if (6 < compression_level) {
- LOGE("KdTreeAttributesDecoder: compression level %i not supported.\n",
- compression_level);
+ DRACO_LOGE(
+ "KdTreeAttributesDecoder: compression level %i not supported.\n",
+ compression_level);
return false;
}
@@ -371,7 +376,7 @@ bool KdTreeAttributesDecoder::DecodeDataNeededByPortableTransforms(
GetDecoder()->point_cloud()->attribute(att_id);
attr->Reset(num_points);
attr->SetIdentityMapping();
- };
+ }
PointAttributeVectorOutputIterator<uint32_t> out_it(atts);
diff --git a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc
index 0f9c31565e5..b70deb9e01f 100644
--- a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.cc
@@ -71,16 +71,21 @@ bool KdTreeAttributesEncoder::TransformAttributesToPortableFormat() {
att->num_components(), range);
} else {
// Compute quantization settings from the attribute values.
- attribute_quantization_transform.ComputeParameters(*att,
- quantization_bits);
+ if (!attribute_quantization_transform.ComputeParameters(
+ *att, quantization_bits)) {
+ return false;
+ }
}
attribute_quantization_transforms_.push_back(
attribute_quantization_transform);
// Store the quantized attribute in an array that will be used when we do
// the actual encoding of the data.
- quantized_portable_attributes_.push_back(
- attribute_quantization_transform.GeneratePortableAttribute(
- *att, static_cast<int>(num_points)));
+ auto portable_att =
+ attribute_quantization_transform.InitTransformedAttribute(*att,
+ num_points);
+ attribute_quantization_transform.TransformAttribute(*att, {},
+ portable_att.get());
+ quantized_portable_attributes_.push_back(std::move(portable_att));
} else if (att->data_type() == DT_INT32 || att->data_type() == DT_INT16 ||
att->data_type() == DT_INT8) {
// For signed types, find the minimum value for each component. These
diff --git a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h
index 8b4c4e2faab..80748e0bf5d 100644
--- a/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h
+++ b/extern/draco/draco/src/draco/compression/attributes/kd_tree_attributes_encoder.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_
-#define DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_
+#ifndef DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_
+#define DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_
#include "draco/attributes/attribute_quantization_transform.h"
#include "draco/compression/attributes/attributes_encoder.h"
@@ -48,4 +48,4 @@ class KdTreeAttributesEncoder : public AttributesEncoder {
} // namespace draco
-#endif // DRACO_COMPRESSION_ATTRIBUTES_POINT_CLOUD_KD_TREE_ATTRIBUTES_ENCODER_H_
+#endif // DRACO_COMPRESSION_ATTRIBUTES_KD_TREE_ATTRIBUTES_ENCODER_H_
diff --git a/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h
index 32e27c711e3..be5ee5b09e3 100644
--- a/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h
+++ b/extern/draco/draco/src/draco/compression/attributes/normal_compression_utils.h
@@ -53,6 +53,7 @@ class OctahedronToolBox {
: quantization_bits_(-1),
max_quantized_value_(-1),
max_value_(-1),
+ dequantization_scale_(1.f),
center_value_(-1) {}
bool SetQuantizationBits(int32_t q) {
@@ -62,6 +63,7 @@ class OctahedronToolBox {
quantization_bits_ = q;
max_quantized_value_ = (1 << quantization_bits_) - 1;
max_value_ = max_quantized_value_ - 1;
+ dequantization_scale_ = 2.f / max_value_;
center_value_ = max_value_ / 2;
return true;
}
@@ -192,64 +194,11 @@ class OctahedronToolBox {
}
}
- // TODO(b/149328891): Change function to not use templates as |T| is only
- // float.
- template <typename T>
- void OctaherdalCoordsToUnitVector(T in_s, T in_t, T *out_vector) const {
- DRACO_DCHECK_GE(in_s, 0);
- DRACO_DCHECK_GE(in_t, 0);
- DRACO_DCHECK_LE(in_s, 1);
- DRACO_DCHECK_LE(in_t, 1);
- T s = in_s;
- T t = in_t;
- T spt = s + t;
- T smt = s - t;
- T x_sign = 1.0;
- if (spt >= 0.5 && spt <= 1.5 && smt >= -0.5 && smt <= 0.5) {
- // Right hemisphere. Don't do anything.
- } else {
- // Left hemisphere.
- x_sign = -1.0;
- if (spt <= 0.5) {
- s = 0.5 - in_t;
- t = 0.5 - in_s;
- } else if (spt >= 1.5) {
- s = 1.5 - in_t;
- t = 1.5 - in_s;
- } else if (smt <= -0.5) {
- s = in_t - 0.5;
- t = in_s + 0.5;
- } else {
- s = in_t + 0.5;
- t = in_s - 0.5;
- }
- spt = s + t;
- smt = s - t;
- }
- const T y = 2.0 * s - 1.0;
- const T z = 2.0 * t - 1.0;
- const T x = std::min(std::min(2.0 * spt - 1.0, 3.0 - 2.0 * spt),
- std::min(2.0 * smt + 1.0, 1.0 - 2.0 * smt)) *
- x_sign;
- // Normalize the computed vector.
- const T normSquared = x * x + y * y + z * z;
- if (normSquared < 1e-6) {
- out_vector[0] = 0;
- out_vector[1] = 0;
- out_vector[2] = 0;
- } else {
- const T d = 1.0 / std::sqrt(normSquared);
- out_vector[0] = x * d;
- out_vector[1] = y * d;
- out_vector[2] = z * d;
- }
- }
-
- template <typename T>
- void QuantizedOctaherdalCoordsToUnitVector(int32_t in_s, int32_t in_t,
- T *out_vector) const {
- T scale = 1.0 / static_cast<T>(max_value_);
- OctaherdalCoordsToUnitVector(in_s * scale, in_t * scale, out_vector);
+ inline void QuantizedOctahedralCoordsToUnitVector(int32_t in_s, int32_t in_t,
+ float *out_vector) const {
+ OctahedralCoordsToUnitVector(in_s * dequantization_scale_ - 1.f,
+ in_t * dequantization_scale_ - 1.f,
+ out_vector);
}
// |s| and |t| are expected to be signed values.
@@ -333,9 +282,77 @@ class OctahedronToolBox {
int32_t center_value() const { return center_value_; }
private:
+ inline void OctahedralCoordsToUnitVector(float in_s_scaled, float in_t_scaled,
+ float *out_vector) const {
+ // Background about the encoding:
+ // A normal is encoded in a normalized space <s, t> depicted below. The
+ // encoding correponds to an octahedron that is unwrapped to a 2D plane.
+ // During encoding, a normal is projected to the surface of the octahedron
+ // and the projection is then unwrapped to the 2D plane. Decoding is the
+ // reverse of this process.
+ // All points in the central diamond are located on triangles on the
+ // right "hemisphere" of the octahedron while all points outside of the
+ // diamond are on the left hemisphere (basically, they would have to be
+ // wrapped along the diagonal edges to form the octahedron). The central
+ // point corresponds to the right most vertex of the octahedron and all
+ // corners of the plane correspond to the left most vertex of the
+ // octahedron.
+ //
+ // t
+ // ^ *-----*-----*
+ // | | /|\ |
+ // | / | \ |
+ // | / | \ |
+ // | / | \ |
+ // *-----*---- *
+ // | \ | / |
+ // | \ | / |
+ // | \ | / |
+ // | \|/ |
+ // *-----*-----* --> s
+
+ // Note that the input |in_s_scaled| and |in_t_scaled| are already scaled to
+ // <-1, 1> range. This way, the central point is at coordinate (0, 0).
+ float y = in_s_scaled;
+ float z = in_t_scaled;
+
+ // Remaining coordinate can be computed by projecting the (y, z) values onto
+ // the surface of the octahedron.
+ const float x = 1.f - std::abs(y) - std::abs(z);
+
+ // |x| is essentially a signed distance from the diagonal edges of the
+ // diamond shown on the figure above. It is positive for all points in the
+ // diamond (right hemisphere) and negative for all points outside the
+ // diamond (left hemisphere). For all points on the left hemisphere we need
+ // to update their (y, z) coordinates to account for the wrapping along
+ // the edges of the diamond.
+ float x_offset = -x;
+ x_offset = x_offset < 0 ? 0 : x_offset;
+
+ // This will do nothing for the points on the right hemisphere but it will
+ // mirror the (y, z) location along the nearest diagonal edge of the
+ // diamond.
+ y += y < 0 ? x_offset : -x_offset;
+ z += z < 0 ? x_offset : -x_offset;
+
+ // Normalize the computed vector.
+ const float norm_squared = x * x + y * y + z * z;
+ if (norm_squared < 1e-6) {
+ out_vector[0] = 0;
+ out_vector[1] = 0;
+ out_vector[2] = 0;
+ } else {
+ const float d = 1.0f / std::sqrt(norm_squared);
+ out_vector[0] = x * d;
+ out_vector[1] = y * d;
+ out_vector[2] = z * d;
+ }
+ }
+
int32_t quantization_bits_;
int32_t max_quantized_value_;
int32_t max_value_;
+ float dequantization_scale_;
int32_t center_value_;
};
} // namespace draco
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h
index f712952556a..2960a5e71b4 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_data.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_COMPRESSION_ATTRIBUTES_MESH_PREDICTION_SCHEMES_PREDICTION_SCHEME_DATA_H_
-#define DRACO_COMPRESSION_ATTRIBUTES_MESH_PREDICTION_SCHEMES_PREDICTION_SCHEME_DATA_H_
+#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_DATA_H_
+#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_DATA_H_
#include "draco/mesh/corner_table.h"
#include "draco/mesh/mesh.h"
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h
index bf1a6146111..775eded6b55 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_predictor_area.h
@@ -69,7 +69,14 @@ class MeshPredictionSchemeGeometricNormalPredictorArea
// Computing cross product.
const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
- normal = normal + cross;
+
+ // Prevent signed integer overflows by doing math as unsigned.
+ auto normal_data = reinterpret_cast<uint64_t *>(normal.data());
+ auto cross_data = reinterpret_cast<const uint64_t *>(cross.data());
+ normal_data[0] = normal_data[0] + cross_data[0];
+ normal_data[1] = normal_data[1] + cross_data[1];
+ normal_data[2] = normal_data[2] + cross_data[2];
+
cit.Next();
}
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h
index 485d457ccf6..fd10fb524b3 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_shared.h
@@ -60,8 +60,13 @@ inline bool ComputeParallelogramPrediction(
const int v_next_off = vert_next * num_components;
const int v_prev_off = vert_prev * num_components;
for (int c = 0; c < num_components; ++c) {
- out_prediction[c] = (in_data[v_next_off + c] + in_data[v_prev_off + c]) -
- in_data[v_opp_off + c];
+ const int64_t in_data_next_off = in_data[v_next_off + c];
+ const int64_t in_data_prev_off = in_data[v_prev_off + c];
+ const int64_t in_data_opp_off = in_data[v_opp_off + c];
+ const int64_t result =
+ (in_data_next_off + in_data_prev_off) - in_data_opp_off;
+
+ out_prediction[c] = static_cast<DataTypeT>(result);
}
return true;
}
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h
index 5d8a5060133..f05e5ddd713 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_portable_predictor.h
@@ -156,6 +156,13 @@ bool MeshPredictionSchemeTexCoordsPortablePredictor<
const VectorD<int64_t, 2> x_uv =
n_uv * pn_norm2_squared + (cn_dot_pn * pn_uv);
+ const int64_t pn_absmax_element =
+ std::max(std::max(std::abs(pn[0]), std::abs(pn[1])), std::abs(pn[2]));
+ if (cn_dot_pn > std::numeric_limits<int64_t>::max() / pn_absmax_element) {
+ // return false if squared length calculation would overflow.
+ return false;
+ }
+
// Compute squared length of vector CX in position coordinate system:
const VectorD<int64_t, 3> x_pos =
next_pos + (cn_dot_pn * pn) / pn_norm2_squared;
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc
index 428340da013..60429d5c779 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc
@@ -18,34 +18,51 @@ namespace draco {
PredictionSchemeMethod SelectPredictionMethod(
int att_id, const PointCloudEncoder *encoder) {
- if (encoder->options()->GetSpeed() >= 10) {
+ return SelectPredictionMethod(att_id, *encoder->options(), encoder);
+}
+
+PredictionSchemeMethod SelectPredictionMethod(
+ int att_id, const EncoderOptions &options,
+ const PointCloudEncoder *encoder) {
+ if (options.GetSpeed() >= 10) {
// Selected fastest, though still doing some compression.
return PREDICTION_DIFFERENCE;
}
if (encoder->GetGeometryType() == TRIANGULAR_MESH) {
// Use speed setting to select the best encoding method.
const PointAttribute *const att = encoder->point_cloud()->attribute(att_id);
- if (att->attribute_type() == GeometryAttribute::TEX_COORD) {
- if (encoder->options()->GetSpeed() < 4) {
+ if (att->attribute_type() == GeometryAttribute::TEX_COORD &&
+ att->num_components() == 2) {
+ if (options.GetSpeed() < 4) {
// Use texture coordinate prediction for speeds 0, 1, 2, 3.
return MESH_PREDICTION_TEX_COORDS_PORTABLE;
}
}
if (att->attribute_type() == GeometryAttribute::NORMAL) {
#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
- if (encoder->options()->GetSpeed() < 4) {
+ if (options.GetSpeed() < 4) {
// Use geometric normal prediction for speeds 0, 1, 2, 3.
- return MESH_PREDICTION_GEOMETRIC_NORMAL;
+ // For this prediction, the position attribute needs to be either
+ // integer or quantized as well.
+ const int pos_att_id = encoder->point_cloud()->GetNamedAttributeId(
+ GeometryAttribute::POSITION);
+ const PointAttribute *const pos_att =
+ encoder->point_cloud()->GetNamedAttribute(
+ GeometryAttribute::POSITION);
+ if (pos_att && (IsDataTypeIntegral(pos_att->data_type()) ||
+ options.GetAttributeInt(pos_att_id, "quantization_bits",
+ -1) > 0)) {
+ return MESH_PREDICTION_GEOMETRIC_NORMAL;
+ }
}
#endif
return PREDICTION_DIFFERENCE; // default
}
// Handle other attribute types.
- if (encoder->options()->GetSpeed() >= 8) {
+ if (options.GetSpeed() >= 8) {
return PREDICTION_DIFFERENCE;
}
- if (encoder->options()->GetSpeed() >= 2 ||
- encoder->point_cloud()->num_points() < 40) {
+ if (options.GetSpeed() >= 2 || encoder->point_cloud()->num_points() < 40) {
// Parallelogram prediction is used for speeds 2 - 7 or when the overhead
// of using constrained multi-parallelogram would be too high.
return MESH_PREDICTION_PARALLELOGRAM;
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h
index 40a7683aa0d..b7e21224fad 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h
@@ -38,6 +38,10 @@ namespace draco {
PredictionSchemeMethod SelectPredictionMethod(int att_id,
const PointCloudEncoder *encoder);
+PredictionSchemeMethod SelectPredictionMethod(int att_id,
+ const EncoderOptions &options,
+ const PointCloudEncoder *encoder);
+
// Factory class for creating mesh prediction schemes.
template <typename DataTypeT>
struct MeshPredictionSchemeEncoderFactory {
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h
index ab64bce7114..37aa9f76a9c 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_interface.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_
-#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_
+#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_
+#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_interface.h"
#include "draco/core/encoder_buffer.h"
@@ -52,4 +52,4 @@ class PredictionSchemeTypedEncoderInterface
} // namespace draco
-#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODING_INTERFACE_H_
+#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_INTERFACE_H_
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h
index 0a14d0d9ba4..e100c738a6c 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_decoding_transform.h
@@ -36,9 +36,25 @@ class PredictionSchemeWrapDecodingTransform
inline void ComputeOriginalValue(const DataTypeT *predicted_vals,
const CorrTypeT *corr_vals,
DataTypeT *out_original_vals) const {
+ // For now we assume both |DataTypeT| and |CorrTypeT| are equal.
+ static_assert(std::is_same<DataTypeT, CorrTypeT>::value,
+ "Predictions and corrections must have the same type.");
+
+ // The only valid implementation right now is for int32_t.
+ static_assert(std::is_same<DataTypeT, int32_t>::value,
+ "Only int32_t is supported for predicted values.");
+
predicted_vals = this->ClampPredictedValue(predicted_vals);
+
+ // Perform the wrapping using unsigned coordinates to avoid potential signed
+ // integer overflows caused by malformed input.
+ const uint32_t *const uint_predicted_vals =
+ reinterpret_cast<const uint32_t *>(predicted_vals);
+ const uint32_t *const uint_corr_vals =
+ reinterpret_cast<const uint32_t *>(corr_vals);
for (int i = 0; i < this->num_components(); ++i) {
- out_original_vals[i] = predicted_vals[i] + corr_vals[i];
+ out_original_vals[i] =
+ static_cast<DataTypeT>(uint_predicted_vals[i] + uint_corr_vals[i]);
if (out_original_vals[i] > this->max_value()) {
out_original_vals[i] -= this->max_dif();
} else if (out_original_vals[i] < this->min_value()) {
diff --git a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h
index 26f61fbaf6a..979c63c3d11 100644
--- a/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h
+++ b/extern/draco/draco/src/draco/compression/attributes/prediction_schemes/prediction_scheme_wrap_transform_base.h
@@ -73,7 +73,7 @@ class PredictionSchemeWrapTransformBase {
return &clamped_value_[0];
}
- // TODO(hemmer): Consider refactoring to avoid this dummy.
+ // TODO(b/199760123): Consider refactoring to avoid this dummy.
int quantization_bits() const {
DRACO_DCHECK(false);
return -1;
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc
index 521935c1e99..7d5d1eeff26 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc
@@ -26,8 +26,8 @@ SequentialAttributeEncodersController::SequentialAttributeEncodersController(
: sequencer_(std::move(sequencer)) {}
SequentialAttributeEncodersController::SequentialAttributeEncodersController(
- std::unique_ptr<PointsSequencer> sequencer, int att_id)
- : AttributesEncoder(att_id), sequencer_(std::move(sequencer)) {}
+ std::unique_ptr<PointsSequencer> sequencer, int point_attrib_id)
+ : AttributesEncoder(point_attrib_id), sequencer_(std::move(sequencer)) {}
bool SequentialAttributeEncodersController::Init(PointCloudEncoder *encoder,
const PointCloud *pc) {
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc
index d01fb26aad4..17f32fc1612 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_decoder.cc
@@ -53,6 +53,11 @@ bool SequentialIntegerAttributeDecoder::DecodeValues(
if (!in_buffer->Decode(&prediction_transform_type)) {
return false;
}
+ // Check that decoded prediction scheme transform type is valid.
+ if (prediction_transform_type < PREDICTION_TRANSFORM_NONE ||
+ prediction_transform_type >= NUM_PREDICTION_SCHEME_TRANSFORM_TYPES) {
+ return false;
+ }
prediction_scheme_ = CreateIntPredictionScheme(
static_cast<PredictionSchemeMethod>(prediction_scheme_method),
static_cast<PredictionSchemeTransformType>(prediction_transform_type));
@@ -143,8 +148,9 @@ bool SequentialIntegerAttributeDecoder::DecodeIntegerValues(
return false;
}
for (size_t i = 0; i < num_values; ++i) {
- if (!in_buffer->Decode(portable_attribute_data + i, num_bytes))
+ if (!in_buffer->Decode(portable_attribute_data + i, num_bytes)) {
return false;
+ }
}
}
}
@@ -223,12 +229,13 @@ void SequentialIntegerAttributeDecoder::StoreTypedValues(uint32_t num_values) {
void SequentialIntegerAttributeDecoder::PreparePortableAttribute(
int num_entries, int num_components) {
- GeometryAttribute va;
- va.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32,
+ GeometryAttribute ga;
+ ga.Init(attribute()->attribute_type(), nullptr, num_components, DT_INT32,
false, num_components * DataTypeLength(DT_INT32), 0);
- std::unique_ptr<PointAttribute> port_att(new PointAttribute(va));
+ std::unique_ptr<PointAttribute> port_att(new PointAttribute(ga));
port_att->SetIdentityMapping();
port_att->Reset(num_entries);
+ port_att->set_unique_id(attribute()->unique_id());
SetPortableAttribute(std::move(port_att));
}
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc
index 2889e0521a0..e66a0a8a40a 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_integer_attribute_encoder.cc
@@ -81,6 +81,9 @@ bool SequentialIntegerAttributeEncoder::TransformAttributeToPortableFormat(
value_to_value_map[orig_att->mapped_index(point_ids[i])] =
AttributeValueIndex(i);
}
+ if (portable_att->is_mapping_identity()) {
+ portable_att->SetExplicitMapping(encoder()->point_cloud()->num_points());
+ }
// Go over all points of the original attribute and update the mapping in
// the portable attribute.
for (PointIndex i(0); i < encoder()->point_cloud()->num_points(); ++i) {
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc
index 017344393dc..de36c1c36f2 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.cc
@@ -14,18 +14,17 @@
//
#include "draco/compression/attributes/sequential_normal_attribute_decoder.h"
-#include "draco/attributes/attribute_octahedron_transform.h"
#include "draco/compression/attributes/normal_compression_utils.h"
namespace draco {
-SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder()
- : quantization_bits_(-1) {}
+SequentialNormalAttributeDecoder::SequentialNormalAttributeDecoder() {}
bool SequentialNormalAttributeDecoder::Init(PointCloudDecoder *decoder,
int attribute_id) {
- if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id))
+ if (!SequentialIntegerAttributeDecoder::Init(decoder, attribute_id)) {
return false;
+ }
// Currently, this encoder works only for 3-component normal vectors.
if (attribute()->num_components() != 3) {
return false;
@@ -41,11 +40,13 @@ bool SequentialNormalAttributeDecoder::DecodeIntegerValues(
const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
- uint8_t quantization_bits;
- if (!in_buffer->Decode(&quantization_bits)) {
+ // Note: in older bitstreams, we do not have a PortableAttribute() decoded
+ // at this stage so we cannot pass it down to the DecodeParameters() call.
+ // It still works fine for octahedral transform because it does not need to
+ // use any data from the attribute.
+ if (!octahedral_transform_.DecodeParameters(*attribute(), in_buffer)) {
return false;
}
- quantization_bits_ = quantization_bits;
}
#endif
return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
@@ -56,39 +57,20 @@ bool SequentialNormalAttributeDecoder::DecodeDataNeededByPortableTransform(
const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
if (decoder()->bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 0)) {
// For newer file version, decode attribute transform data here.
- uint8_t quantization_bits;
- if (!in_buffer->Decode(&quantization_bits)) {
+ if (!octahedral_transform_.DecodeParameters(*GetPortableAttribute(),
+ in_buffer)) {
return false;
}
- quantization_bits_ = quantization_bits;
}
// Store the decoded transform data in portable attribute.
- AttributeOctahedronTransform octahedral_transform;
- octahedral_transform.SetParameters(quantization_bits_);
- return octahedral_transform.TransferToAttribute(portable_attribute());
+ return octahedral_transform_.TransferToAttribute(portable_attribute());
}
bool SequentialNormalAttributeDecoder::StoreValues(uint32_t num_points) {
// Convert all quantized values back to floats.
- const int num_components = attribute()->num_components();
- const int entry_size = sizeof(float) * num_components;
- float att_val[3];
- int quant_val_id = 0;
- int out_byte_pos = 0;
- const int32_t *const portable_attribute_data = GetPortableAttributeData();
- OctahedronToolBox octahedron_tool_box;
- if (!octahedron_tool_box.SetQuantizationBits(quantization_bits_))
- return false;
- for (uint32_t i = 0; i < num_points; ++i) {
- const int32_t s = portable_attribute_data[quant_val_id++];
- const int32_t t = portable_attribute_data[quant_val_id++];
- octahedron_tool_box.QuantizedOctaherdalCoordsToUnitVector(s, t, att_val);
- // Store the decoded floating point value into the attribute buffer.
- attribute()->buffer()->Write(out_byte_pos, att_val, entry_size);
- out_byte_pos += entry_size;
- }
- return true;
+ return octahedral_transform_.InverseTransformAttribute(
+ *GetPortableAttribute(), attribute());
}
} // namespace draco
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h
index 860eacb4c84..8c2d801b763 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_decoder.h
@@ -15,6 +15,7 @@
#ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_
#define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_NORMAL_ATTRIBUTE_DECODER_H_
+#include "draco/attributes/attribute_octahedron_transform.h"
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h"
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_canonicalized_decoding_transform.h"
#include "draco/compression/attributes/prediction_schemes/prediction_scheme_normal_octahedron_decoding_transform.h"
@@ -42,7 +43,7 @@ class SequentialNormalAttributeDecoder
bool StoreValues(uint32_t num_points) override;
private:
- int32_t quantization_bits_;
+ AttributeOctahedronTransform octahedral_transform_;
std::unique_ptr<PredictionSchemeTypedDecoderInterface<int32_t>>
CreateIntPredictionScheme(
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc
index 23fa8bb7b39..3c5ef0ebcbc 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_normal_attribute_encoder.cc
@@ -20,8 +20,9 @@ namespace draco {
bool SequentialNormalAttributeEncoder::Init(PointCloudEncoder *encoder,
int attribute_id) {
- if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id))
+ if (!SequentialIntegerAttributeEncoder::Init(encoder, attribute_id)) {
return false;
+ }
// Currently this encoder works only for 3-component normal vectors.
if (attribute()->num_components() != 3) {
return false;
@@ -44,9 +45,13 @@ bool SequentialNormalAttributeEncoder::EncodeDataNeededByPortableTransform(
bool SequentialNormalAttributeEncoder::PrepareValues(
const std::vector<PointIndex> &point_ids, int num_points) {
- SetPortableAttribute(
- attribute_octahedron_transform_.GeneratePortableAttribute(
- *(attribute()), point_ids, num_points));
+ auto portable_att = attribute_octahedron_transform_.InitTransformedAttribute(
+ *(attribute()), point_ids.size());
+ if (!attribute_octahedron_transform_.TransformAttribute(
+ *(attribute()), point_ids, portable_att.get())) {
+ return false;
+ }
+ SetPortableAttribute(std::move(portable_att));
return true;
}
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc
index bf925c4a595..3d306e7dae6 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.cc
@@ -14,13 +14,12 @@
//
#include "draco/compression/attributes/sequential_quantization_attribute_decoder.h"
-#include "draco/attributes/attribute_quantization_transform.h"
#include "draco/core/quantization_utils.h"
namespace draco {
-SequentialQuantizationAttributeDecoder::SequentialQuantizationAttributeDecoder()
- : quantization_bits_(-1), max_value_dif_(0.f) {}
+SequentialQuantizationAttributeDecoder::
+ SequentialQuantizationAttributeDecoder() {}
bool SequentialQuantizationAttributeDecoder::Init(PointCloudDecoder *decoder,
int attribute_id) {
@@ -59,62 +58,31 @@ bool SequentialQuantizationAttributeDecoder::
}
// Store the decoded transform data in portable attribute;
- AttributeQuantizationTransform transform;
- transform.SetParameters(quantization_bits_, min_value_.get(),
- attribute()->num_components(), max_value_dif_);
- return transform.TransferToAttribute(portable_attribute());
+ return quantization_transform_.TransferToAttribute(portable_attribute());
}
-bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_values) {
- return DequantizeValues(num_values);
+bool SequentialQuantizationAttributeDecoder::StoreValues(uint32_t num_points) {
+ return DequantizeValues(num_points);
}
bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() {
- const int num_components = attribute()->num_components();
- min_value_ = std::unique_ptr<float[]>(new float[num_components]);
- if (!decoder()->buffer()->Decode(min_value_.get(),
- sizeof(float) * num_components)) {
- return false;
- }
- if (!decoder()->buffer()->Decode(&max_value_dif_)) {
- return false;
+ // Get attribute used as source for decoding.
+ auto att = GetPortableAttribute();
+ if (att == nullptr) {
+ // This should happen only in the backward compatibility mode. It will still
+ // work fine for this case because the only thing the quantization transform
+ // cares about is the number of components that is the same for both source
+ // and target attributes.
+ att = attribute();
}
- uint8_t quantization_bits;
- if (!decoder()->buffer()->Decode(&quantization_bits) ||
- quantization_bits > 31) {
- return false;
- }
- quantization_bits_ = quantization_bits;
- return true;
+ return quantization_transform_.DecodeParameters(*att, decoder()->buffer());
}
bool SequentialQuantizationAttributeDecoder::DequantizeValues(
uint32_t num_values) {
// Convert all quantized values back to floats.
- const int32_t max_quantized_value =
- (1u << static_cast<uint32_t>(quantization_bits_)) - 1;
- const int num_components = attribute()->num_components();
- const int entry_size = sizeof(float) * num_components;
- const std::unique_ptr<float[]> att_val(new float[num_components]);
- int quant_val_id = 0;
- int out_byte_pos = 0;
- Dequantizer dequantizer;
- if (!dequantizer.Init(max_value_dif_, max_quantized_value)) {
- return false;
- }
- const int32_t *const portable_attribute_data = GetPortableAttributeData();
- for (uint32_t i = 0; i < num_values; ++i) {
- for (int c = 0; c < num_components; ++c) {
- float value =
- dequantizer.DequantizeFloat(portable_attribute_data[quant_val_id++]);
- value = value + min_value_[c];
- att_val[c] = value;
- }
- // Store the floating point value into the attribute buffer.
- attribute()->buffer()->Write(out_byte_pos, att_val.get(), entry_size);
- out_byte_pos += entry_size;
- }
- return true;
+ return quantization_transform_.InverseTransformAttribute(
+ *GetPortableAttribute(), attribute());
}
} // namespace draco
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h
index c0b7637a750..ad372dcd8a6 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_decoder.h
@@ -15,6 +15,7 @@
#ifndef DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_
#define DRACO_COMPRESSION_ATTRIBUTES_SEQUENTIAL_QUANTIZATION_ATTRIBUTE_DECODER_H_
+#include "draco/attributes/attribute_quantization_transform.h"
#include "draco/compression/attributes/sequential_integer_attribute_decoder.h"
#include "draco/draco_features.h"
@@ -43,12 +44,7 @@ class SequentialQuantizationAttributeDecoder
virtual bool DequantizeValues(uint32_t num_values);
private:
- // Max number of quantization bits used to encode each component of the
- // attribute.
- int32_t quantization_bits_;
-
- std::unique_ptr<float[]> min_value_;
- float max_value_dif_;
+ AttributeQuantizationTransform quantization_transform_;
};
} // namespace draco
diff --git a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc
index cd5b8b141e0..d3666f7a411 100644
--- a/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/attributes/sequential_quantization_attribute_encoder.cc
@@ -50,9 +50,11 @@ bool SequentialQuantizationAttributeEncoder::Init(PointCloudEncoder *encoder,
&quantization_origin[0]);
const float range = encoder->options()->GetAttributeFloat(
attribute_id, "quantization_range", 1.f);
- attribute_quantization_transform_.SetParameters(
- quantization_bits, quantization_origin.data(),
- attribute->num_components(), range);
+ if (!attribute_quantization_transform_.SetParameters(
+ quantization_bits, quantization_origin.data(),
+ attribute->num_components(), range)) {
+ return false;
+ }
} else {
// Compute quantization settings from the attribute values.
if (!attribute_quantization_transform_.ComputeParameters(
@@ -70,9 +72,14 @@ bool SequentialQuantizationAttributeEncoder::
bool SequentialQuantizationAttributeEncoder::PrepareValues(
const std::vector<PointIndex> &point_ids, int num_points) {
- SetPortableAttribute(
- attribute_quantization_transform_.GeneratePortableAttribute(
- *(attribute()), point_ids, num_points));
+ auto portable_attribute =
+ attribute_quantization_transform_.InitTransformedAttribute(
+ *attribute(), point_ids.size());
+ if (!attribute_quantization_transform_.TransformAttribute(
+ *(attribute()), point_ids, portable_attribute.get())) {
+ return false;
+ }
+ SetPortableAttribute(std::move(portable_attribute));
return true;
}
diff --git a/extern/draco/draco/src/draco/compression/config/compression_shared.h b/extern/draco/draco/src/draco/compression/config/compression_shared.h
index 40061d3cd48..c43f303bd15 100644
--- a/extern/draco/draco/src/draco/compression/config/compression_shared.h
+++ b/extern/draco/draco/src/draco/compression/config/compression_shared.h
@@ -42,6 +42,7 @@ enum EncodedGeometryType {
INVALID_GEOMETRY_TYPE = -1,
POINT_CLOUD = 0,
TRIANGULAR_MESH,
+ NUM_ENCODED_GEOMETRY_TYPES
};
// List of encoding methods for point clouds.
@@ -105,6 +106,8 @@ enum PredictionSchemeTransformType {
// Specialized transform for normal coordinates using canonicalized inverted
// tiles.
PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED = 3,
+ // The number of valid (non-negative) prediction scheme transform types.
+ NUM_PREDICTION_SCHEME_TRANSFORM_TYPES
};
// List of all mesh traversal methods supported by Draco framework.
diff --git a/extern/draco/draco/src/draco/compression/config/draco_options.h b/extern/draco/draco/src/draco/compression/config/draco_options.h
index 0d1247b2ad1..2bd4a3b6761 100644
--- a/extern/draco/draco/src/draco/compression/config/draco_options.h
+++ b/extern/draco/draco/src/draco/compression/config/draco_options.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
-#define DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
+#ifndef DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
+#define DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
#include <map>
#include <memory>
@@ -246,4 +246,4 @@ void DracoOptions<AttributeKeyT>::SetAttributeOptions(
} // namespace draco
-#endif // DRACO_SRC_DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
+#endif // DRACO_COMPRESSION_CONFIG_DRACO_OPTIONS_H_
diff --git a/extern/draco/draco/src/draco/compression/decode.cc b/extern/draco/draco/src/draco/compression/decode.cc
index ab70ef1ec60..92ae4ff66f9 100644
--- a/extern/draco/draco/src/draco/compression/decode.cc
+++ b/extern/draco/draco/src/draco/compression/decode.cc
@@ -56,7 +56,10 @@ StatusOr<EncodedGeometryType> Decoder::GetEncodedGeometryType(
DecoderBuffer *in_buffer) {
DecoderBuffer temp_buffer(*in_buffer);
DracoHeader header;
- DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header))
+ DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header));
+ if (header.encoder_type >= NUM_ENCODED_GEOMETRY_TYPES) {
+ return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
+ }
return static_cast<EncodedGeometryType>(header.encoder_type);
}
diff --git a/extern/draco/draco/src/draco/compression/encode_base.h b/extern/draco/draco/src/draco/compression/encode_base.h
index 0c63a972bf4..6211efc221b 100644
--- a/extern/draco/draco/src/draco/compression/encode_base.h
+++ b/extern/draco/draco/src/draco/compression/encode_base.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_
-#define DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_
+#ifndef DRACO_COMPRESSION_ENCODE_BASE_H_
+#define DRACO_COMPRESSION_ENCODE_BASE_H_
#include "draco/attributes/geometry_attribute.h"
#include "draco/compression/config/compression_shared.h"
@@ -98,7 +98,7 @@ class EncoderBase {
"Invalid prediction scheme for attribute type.");
}
}
- // TODO(hemmer): Try to enable more prediction schemes for normals.
+ // TODO(b/199760123): Try to enable more prediction schemes for normals.
if (att_type == GeometryAttribute::NORMAL) {
if (!(prediction_scheme == PREDICTION_DIFFERENCE ||
prediction_scheme == MESH_PREDICTION_GEOMETRIC_NORMAL)) {
@@ -128,4 +128,4 @@ void EncoderBase<EncoderOptionsT>::SetTrackEncodedProperties(bool flag) {
} // namespace draco
-#endif // DRACO_SRC_DRACO_COMPRESSION_ENCODE_BASE_H_
+#endif // DRACO_COMPRESSION_ENCODE_BASE_H_
diff --git a/extern/draco/draco/src/draco/compression/entropy/ans.h b/extern/draco/draco/src/draco/compression/entropy/ans.h
index c765256b96e..313546fee20 100644
--- a/extern/draco/draco/src/draco/compression/entropy/ans.h
+++ b/extern/draco/draco/src/draco/compression/entropy/ans.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_CORE_ANS_H_
-#define DRACO_CORE_ANS_H_
+#ifndef DRACO_COMPRESSION_ENTROPY_ANS_H_
+#define DRACO_COMPRESSION_ENTROPY_ANS_H_
// An implementation of Asymmetric Numeral Systems (rANS).
// See http://arxiv.org/abs/1311.2540v2 for more information on rANS.
// This file is based off libvpx's ans.h.
@@ -391,7 +391,6 @@ class RAnsEncoder {
ans_.buf[ans_.buf_offset++] = ans_.state % DRACO_ANS_IO_BASE;
ans_.state /= DRACO_ANS_IO_BASE;
}
- // TODO(ostava): The division and multiplication should be optimized.
ans_.state =
(ans_.state / p) * rans_precision + ans_.state % p + sym->cum_prob;
}
@@ -524,4 +523,4 @@ class RAnsDecoder {
} // namespace draco
-#endif // DRACO_CORE_ANS_H_
+#endif // DRACO_COMPRESSION_ENTROPY_ANS_H_
diff --git a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h
index 0a68e29fe26..cd4271193bf 100644
--- a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h
+++ b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_coding.h
@@ -31,11 +31,10 @@ constexpr int ComputeRAnsUnclampedPrecision(int symbols_bit_length) {
// our rANS library (which is between 12 to 20 bits).
constexpr int ComputeRAnsPrecisionFromUniqueSymbolsBitLength(
int symbols_bit_length) {
- return ComputeRAnsUnclampedPrecision(symbols_bit_length) < 12
- ? 12
- : ComputeRAnsUnclampedPrecision(symbols_bit_length) > 20
- ? 20
- : ComputeRAnsUnclampedPrecision(symbols_bit_length);
+ return ComputeRAnsUnclampedPrecision(symbols_bit_length) < 12 ? 12
+ : ComputeRAnsUnclampedPrecision(symbols_bit_length) > 20
+ ? 20
+ : ComputeRAnsUnclampedPrecision(symbols_bit_length);
}
// Compute approximate frequency table size needed for storing the provided
diff --git a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h
index 4e07ec87123..4b738b50a9d 100644
--- a/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h
+++ b/extern/draco/draco/src/draco/compression/entropy/rans_symbol_encoder.h
@@ -125,8 +125,8 @@ bool RAnsSymbolEncoder<unique_symbols_bit_length_t>::Create(
for (int i = 0; i < num_symbols; ++i) {
sorted_probabilities[i] = i;
}
- std::sort(sorted_probabilities.begin(), sorted_probabilities.end(),
- ProbabilityLess(&probability_table_));
+ std::stable_sort(sorted_probabilities.begin(), sorted_probabilities.end(),
+ ProbabilityLess(&probability_table_));
if (total_rans_prob < rans_precision_) {
// This happens rather infrequently, just add the extra needed precision
// to the most frequent symbol.
diff --git a/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc
index 93d29971c89..79e81181830 100644
--- a/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc
+++ b/extern/draco/draco/src/draco/compression/entropy/symbol_decoding.cc
@@ -72,7 +72,7 @@ bool DecodeTaggedSymbols(uint32_t num_values, int num_components,
int value_id = 0;
for (uint32_t i = 0; i < num_values; i += num_components) {
// Decode the tag.
- const int bit_length = tag_decoder.DecodeSymbol();
+ const uint32_t bit_length = tag_decoder.DecodeSymbol();
// Decode the actual value.
for (int j = 0; j < num_components; ++j) {
uint32_t val;
diff --git a/extern/draco/draco/src/draco/compression/expert_encode.cc b/extern/draco/draco/src/draco/compression/expert_encode.cc
index 4c70a72a765..f9aec15eb27 100644
--- a/extern/draco/draco/src/draco/compression/expert_encode.cc
+++ b/extern/draco/draco/src/draco/compression/expert_encode.cc
@@ -67,7 +67,7 @@ Status ExpertEncoder::EncodePointCloudToBuffer(const PointCloud &pc,
kd_tree_possible = false;
}
if (kd_tree_possible && att->data_type() == DT_FLOAT32 &&
- options().GetAttributeInt(0, "quantization_bits", -1) <= 0) {
+ options().GetAttributeInt(i, "quantization_bits", -1) <= 0) {
kd_tree_possible = false; // Quantization not enabled.
}
if (!kd_tree_possible) {
diff --git a/extern/draco/draco/src/draco/compression/expert_encode.h b/extern/draco/draco/src/draco/compression/expert_encode.h
index a1aa7b8b3a8..ea59393d3d2 100644
--- a/extern/draco/draco/src/draco/compression/expert_encode.h
+++ b/extern/draco/draco/src/draco/compression/expert_encode.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_
-#define DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_
+#ifndef DRACO_COMPRESSION_EXPERT_ENCODE_H_
+#define DRACO_COMPRESSION_EXPERT_ENCODE_H_
#include "draco/compression/config/compression_shared.h"
#include "draco/compression/config/encoder_options.h"
@@ -144,4 +144,4 @@ class ExpertEncoder : public EncoderBase<EncoderOptions> {
} // namespace draco
-#endif // DRACO_SRC_DRACO_COMPRESSION_EXPERT_ENCODE_H_
+#endif // DRACO_COMPRESSION_EXPERT_ENCODE_H_
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc
index 50d1971c15b..6d22e2f2a32 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc
@@ -162,6 +162,10 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder(
if (!decoder_->buffer()->Decode(&traversal_method_encoded)) {
return false;
}
+ // Check that decoded traversal method is valid.
+ if (traversal_method_encoded >= NUM_TRAVERSAL_METHODS) {
+ return false;
+ }
traversal_method =
static_cast<MeshTraversalMethod>(traversal_method_encoded);
}
@@ -450,7 +454,7 @@ bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
#endif
// Decode connectivity of non-position attributes.
- if (attribute_data_.size() > 0) {
+ if (!attribute_data_.empty()) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
@@ -577,11 +581,16 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity(
SetOppositeCorners(corner_b, corner + 2);
// Update vertex mapping.
- corner_table_->MapCornerToVertex(corner, vertex_x);
- corner_table_->MapCornerToVertex(
- corner + 1, corner_table_->Vertex(corner_table_->Next(corner_b)));
const VertexIndex vert_a_prev =
corner_table_->Vertex(corner_table_->Previous(corner_a));
+ const VertexIndex vert_b_next =
+ corner_table_->Vertex(corner_table_->Next(corner_b));
+ if (vertex_x == vert_a_prev || vertex_x == vert_b_next) {
+ // Encoding is invalid, because face vertices are degenerate.
+ return -1;
+ }
+ corner_table_->MapCornerToVertex(corner, vertex_x);
+ corner_table_->MapCornerToVertex(corner + 1, vert_b_next);
corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
// Mark the vertex |x| as interior.
@@ -791,7 +800,7 @@ int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity(
return -1; // Unexpected number of decoded vertices.
}
// Decode start faces and connect them to the faces from the active stack.
- while (active_corner_stack.size() > 0) {
+ while (!active_corner_stack.empty()) {
const CornerIndex corner = active_corner_stack.back();
active_corner_stack.pop_back();
const bool interior_face =
@@ -952,9 +961,13 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
for (uint32_t i = 0; i < num_topology_splits; ++i) {
TopologySplitEventData event_data;
uint32_t delta;
- DecodeVarint<uint32_t>(&delta, decoder_buffer);
+ if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
+ return -1;
+ }
event_data.source_symbol_id = delta + last_source_symbol_id;
- DecodeVarint<uint32_t>(&delta, decoder_buffer);
+ if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
+ return -1;
+ }
if (delta > event_data.source_symbol_id) {
return -1;
}
@@ -1009,7 +1022,9 @@ MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
for (uint32_t i = 0; i < num_hole_events; ++i) {
HoleEventData event_data;
uint32_t delta;
- DecodeVarint<uint32_t>(&delta, decoder_buffer);
+ if (!DecodeVarint<uint32_t>(&delta, decoder_buffer)) {
+ return -1;
+ }
event_data.symbol_id = delta + last_symbol_id;
last_symbol_id = event_data.symbol_id;
hole_event_data_.push_back(event_data);
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc
index 5aff5d8cc10..a7f381480f1 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc
@@ -31,7 +31,6 @@ bool MeshEdgebreakerEncoder::InitializeEncoder() {
impl_ = nullptr;
// For tiny meshes it's usually better to use the basic edgebreaker as the
// overhead of the predictive one may turn out to be too big.
- // TODO(b/111065939): Check if this can be improved.
const bool is_tiny_mesh = mesh()->num_faces() < 1000;
int selected_edgebreaker_method =
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
index 0791dc6705a..4bf6aa92070 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
@@ -408,7 +408,7 @@ Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
init_face_connectivity_corners.begin(),
init_face_connectivity_corners.end());
// Encode connectivity for all non-position attributes.
- if (attribute_data_.size() > 0) {
+ if (!attribute_data_.empty()) {
// Use the same order of corner that will be used by the decoder.
visited_faces_.assign(mesh_->num_faces(), false);
for (CornerIndex ci : processed_connectivity_corners_) {
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h
index fb33771637e..979e1d373d8 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h
@@ -177,7 +177,6 @@ class MeshEdgebreakerEncoderImpl : public MeshEdgebreakerEncoderImplInterface {
uint32_t num_split_symbols_;
// Struct holding data used for encoding each non-position attribute.
- // TODO(ostava): This should be probably renamed to something better.
struct AttributeData {
AttributeData() : attribute_index(-1), is_connectivity_used(true) {}
int attribute_index;
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h
index cb3c29dd669..c650bc35210 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_shared.h
@@ -50,8 +50,6 @@ namespace draco {
// \ / S \ / / E \
// *-------* *-------*
//
-// TODO(ostava): Get rid of the topology bit pattern. It's important only for
-// encoding but the algorithms should use EdgebreakerSymbol instead.
enum EdgebreakerTopologyBitPattern {
TOPOLOGY_C = 0x0, // 0
TOPOLOGY_S = 0x1, // 1 0 0
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h
index 621883a5f1f..c00373727df 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h
@@ -106,7 +106,12 @@ class MeshEdgebreakerTraversalValenceDecoder
context_counters_.resize(context_symbols_.size());
for (int i = 0; i < context_symbols_.size(); ++i) {
uint32_t num_symbols;
- DecodeVarint<uint32_t>(&num_symbols, out_buffer);
+ if (!DecodeVarint<uint32_t>(&num_symbols, out_buffer)) {
+ return false;
+ }
+ if (num_symbols > static_cast<uint32_t>(corner_table_->num_faces())) {
+ return false;
+ }
if (num_symbols > 0) {
context_symbols_[i].resize(num_symbols);
DecodeSymbols(num_symbols, 1, out_buffer, context_symbols_[i].data());
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc
index 53f5e8651b8..fbc7383eef1 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc
@@ -53,6 +53,11 @@ bool MeshSequentialDecoder::DecodeConnectivity() {
if (faces_64 > 0xffffffff / 3) {
return false;
}
+ if (faces_64 > buffer()->remaining_size() / 3) {
+ // The number of faces is unreasonably high, because face indices do not
+ // fit in the remaining size of the buffer.
+ return false;
+ }
if (points_64 > faces_64 * 3) {
return false;
}
@@ -91,7 +96,7 @@ bool MeshSequentialDecoder::DecodeConnectivity() {
}
mesh()->AddFace(face);
}
- } else if (mesh()->num_points() < (1 << 21) &&
+ } else if (num_points < (1 << 21) &&
bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 2)) {
// Decode indices as uint32_t.
for (uint32_t i = 0; i < num_faces; ++i) {
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc
index 02ac7779ea3..fd8b1139253 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc
@@ -32,8 +32,6 @@ Status MeshSequentialEncoder::EncodeConnectivity() {
EncodeVarint(static_cast<uint32_t>(mesh()->num_points()), buffer());
// We encode all attributes in the original (possibly duplicated) format.
- // TODO(ostava): This may not be optimal if we have only one attribute or if
- // all attributes share the same index mapping.
if (options()->GetGlobalBool("compress_connectivity", false)) {
// 0 = Encode compressed indices.
buffer()->Encode(static_cast<uint8_t>(0));
@@ -44,8 +42,6 @@ Status MeshSequentialEncoder::EncodeConnectivity() {
// 1 = Encode indices directly.
buffer()->Encode(static_cast<uint8_t>(1));
// Store vertex indices using a smallest data type that fits their range.
- // TODO(ostava): This can be potentially improved by using a tighter
- // fit that is not bound by a bit-length of any particular data type.
if (mesh()->num_points() < 256) {
// Serialize indices as uint8_t.
for (FaceIndex i(0); i < num_faces; ++i) {
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h
index 672609642b0..6e2b05877ab 100644
--- a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h
+++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.h
@@ -33,7 +33,6 @@ namespace draco {
// Class that encodes mesh data using a simple binary representation of mesh's
// connectivity and geometry.
-// TODO(ostava): Use a better name.
class MeshSequentialEncoder : public MeshEncoder {
public:
MeshSequentialEncoder();
diff --git a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h
index e66dd14b238..dd9738ba2d5 100644
--- a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h
+++ b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h
@@ -25,7 +25,7 @@ namespace draco {
// values based on the traversal of the encoded mesh. The class should be used
// as the TraversalObserverT member of a Traverser class such as the
// DepthFirstTraverser (depth_first_traverser.h).
-// TODO(hemmer): rename to AttributeIndicesCodingTraverserObserver
+// TODO(b/199760123): Rename to AttributeIndicesCodingTraverserObserver.
template <class CornerTableT>
class MeshAttributeIndicesEncodingObserver {
public:
diff --git a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h
index ebe1d5f7a9e..e55c93a7969 100644
--- a/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h
+++ b/extern/draco/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h
@@ -25,7 +25,7 @@ namespace draco {
// Sequencer that generates point sequence in an order given by a deterministic
// traversal on the mesh surface. Note that all attributes encoded with this
// sequence must share the same connectivity.
-// TODO(hemmer): Consider refactoring such that this is an observer.
+// TODO(b/199760123): Consider refactoring such that this is an observer.
template <class TraverserT>
class MeshTraversalSequencer : public PointsSequencer {
public:
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h
index 87bc2b7ef3e..fa1b1e203e5 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h
+++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h
@@ -227,7 +227,7 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal(
std::stack<Status> status_stack;
status_stack.push(init_status);
- // TODO(hemmer): use preallocated vector instead of stack.
+ // TODO(b/199760123): Use preallocated vector instead of stack.
while (!status_stack.empty()) {
const DecodingStatus status = status_stack.top();
status_stack.pop();
@@ -263,7 +263,8 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodeInternal(
// Fast decoding of remaining bits if number of points is 1 or 2.
if (num_remaining_points <= 2) {
- // TODO(hemmer): axes_ not necessary, remove would change bitstream!
+ // TODO(b/199760123): |axes_| not necessary, remove would change
+ // bitstream!
axes_[0] = axis;
for (uint32_t i = 1; i < dimension_; i++) {
axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h
index 14fa32d7083..65b3d07a6ad 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h
+++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_encoder.h
@@ -280,7 +280,7 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal(
std::stack<Status> status_stack;
status_stack.push(init_status);
- // TODO(hemmer): use preallocated vector instead of stack.
+ // TODO(b/199760123): Use preallocated vector instead of stack.
while (!status_stack.empty()) {
Status status = status_stack.top();
status_stack.pop();
@@ -305,7 +305,8 @@ void DynamicIntegerPointsKdTreeEncoder<compression_level_t>::EncodeInternal(
// Fast encoding of remaining bits if number of points is 1 or 2.
// Doing this also for 2 gives a slight additional speed up.
if (num_remaining_points <= 2) {
- // TODO(hemmer): axes_ not necessary, remove would change bitstream!
+ // TODO(b/199760123): |axes_| not necessary, remove would change
+ // bitstream!
axes_[0] = axis;
for (uint32_t i = 1; i < dimension_; i++) {
axes_[i] = DRACO_INCREMENT_MOD(axes_[i - 1], dimension_);
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc
index 9e8d895f176..dffaa4c8d20 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.cc
@@ -69,18 +69,29 @@ FloatPointsTreeDecoder::FloatPointsTreeDecoder()
bool FloatPointsTreeDecoder::DecodePointCloudKdTreeInternal(
DecoderBuffer *buffer, std::vector<Point3ui> *qpoints) {
- if (!buffer->Decode(&qinfo_.quantization_bits)) return false;
- if (qinfo_.quantization_bits > 31) return false;
- if (!buffer->Decode(&qinfo_.range)) return false;
- if (!buffer->Decode(&num_points_)) return false;
- if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_)
+ if (!buffer->Decode(&qinfo_.quantization_bits)) {
return false;
- if (!buffer->Decode(&compression_level_)) return false;
+ }
+ if (qinfo_.quantization_bits > 31) {
+ return false;
+ }
+ if (!buffer->Decode(&qinfo_.range)) {
+ return false;
+ }
+ if (!buffer->Decode(&num_points_)) {
+ return false;
+ }
+ if (num_points_from_header_ > 0 && num_points_ != num_points_from_header_) {
+ return false;
+ }
+ if (!buffer->Decode(&compression_level_)) {
+ return false;
+ }
// Only allow compression level in [0..6].
if (6 < compression_level_) {
- LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n",
- compression_level_);
+ DRACO_LOGE("FloatPointsTreeDecoder: compression level %i not supported.\n",
+ compression_level_);
return false;
}
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h
index 26ba94f1f59..44c1b3d3a97 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h
+++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/float_points_tree_encoder.h
@@ -44,7 +44,7 @@ namespace draco {
// there are more leading zeros, which is then compressed better by the
// arithmetic encoding.
-// TODO(hemmer): Remove class because it duplicates quantization code.
+// TODO(b/199760123): Remove class because it duplicates quantization code.
class FloatPointsTreeEncoder {
public:
explicit FloatPointsTreeEncoder(PointCloudCompressionMethod method);
@@ -91,7 +91,7 @@ bool FloatPointsTreeEncoder::EncodePointCloud(InputIteratorT points_begin,
// Collect necessary data for encoding.
num_points_ = std::distance(points_begin, points_end);
- // TODO(hemmer): Extend quantization tools to make this more automatic.
+ // TODO(b/199760123): Extend quantization tools to make this more automatic.
// Compute range of points for quantization
std::vector<Point3ui> qpoints;
qpoints.reserve(num_points_);
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h
index 94e523cadaf..bc31af58613 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h
+++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_decoder.h
@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-// TODO(hemmer): Make this a wrapper using DynamicIntegerPointsKdTreeDecoder.
+// TODO(b/199760123): Make this a wrapper using
+// DynamicIntegerPointsKdTreeDecoder.
//
// See integer_points_kd_tree_encoder.h for documentation.
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h
index b8811092ed7..654f14a7866 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h
+++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/integer_points_kd_tree_encoder.h
@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-// TODO(hemmer): Make this a wrapper using DynamicIntegerPointsKdTreeEncoder.
+// TODO(b/199760123): Make this a wrapper using
+// DynamicIntegerPointsKdTreeEncoder.
#ifndef DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_INTEGER_POINTS_KD_TREE_ENCODER_H_
#define DRACO_COMPRESSION_POINT_CLOUD_ALGORITHMS_INTEGER_POINTS_KD_TREE_ENCODER_H_
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h
index 01943ad9e6c..04aa1d95e11 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h
+++ b/extern/draco/draco/src/draco/compression/point_cloud/algorithms/quantize_points_3.h
@@ -22,7 +22,7 @@
namespace draco {
-// TODO(hemmer): Make this a stable bounding box.
+// TODO(b/199760123): Make this a stable bounding box.
struct QuantizationInfo {
uint32_t quantization_bits;
float range;
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc
index 5196edf960c..85f7bc94e33 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc
+++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_decoder.cc
@@ -88,7 +88,9 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options,
const uint8_t max_supported_minor_version =
header.encoder_type == POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor
: kDracoMeshBitstreamVersionMinor;
+
// Check for version compatibility.
+#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (version_major_ < 1 || version_major_ > max_supported_major_version) {
return Status(Status::UNKNOWN_VERSION, "Unknown major version.");
}
@@ -96,6 +98,14 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options,
version_minor_ > max_supported_minor_version) {
return Status(Status::UNKNOWN_VERSION, "Unknown minor version.");
}
+#else
+ if (version_major_ != max_supported_major_version) {
+ return Status(Status::UNKNOWN_VERSION, "Unsupported major version.");
+ }
+ if (version_minor_ != max_supported_minor_version) {
+ return Status(Status::UNKNOWN_VERSION, "Unsupported minor version.");
+ }
+#endif
buffer_->set_bitstream_version(
DRACO_BITSTREAM_VERSION(version_major_, version_minor_));
diff --git a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc
index b4b0ee94093..a1fda8d5a50 100644
--- a/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc
+++ b/extern/draco/draco/src/draco/compression/point_cloud/point_cloud_encoder.cc
@@ -62,12 +62,14 @@ Status PointCloudEncoder::EncodeHeader() {
buffer_->Encode("DRACO", 5);
// Version (major, minor).
const uint8_t encoder_type = GetGeometryType();
- const uint8_t version_major = encoder_type == POINT_CLOUD
- ? kDracoPointCloudBitstreamVersionMajor
- : kDracoMeshBitstreamVersionMajor;
- const uint8_t version_minor = encoder_type == POINT_CLOUD
- ? kDracoPointCloudBitstreamVersionMinor
- : kDracoMeshBitstreamVersionMinor;
+ uint8_t version_major, version_minor;
+ version_major = encoder_type == POINT_CLOUD
+ ? kDracoPointCloudBitstreamVersionMajor
+ : kDracoMeshBitstreamVersionMajor;
+ version_minor = encoder_type == POINT_CLOUD
+ ? kDracoPointCloudBitstreamVersionMinor
+ : kDracoMeshBitstreamVersionMinor;
+
buffer_->Encode(version_major);
buffer_->Encode(version_minor);
// Type of the encoder (point cloud, mesh, ...).
diff --git a/extern/draco/draco/src/draco/core/bounding_box.cc b/extern/draco/draco/src/draco/core/bounding_box.cc
index d95b1e90759..be0d209d857 100644
--- a/extern/draco/draco/src/draco/core/bounding_box.cc
+++ b/extern/draco/draco/src/draco/core/bounding_box.cc
@@ -16,8 +16,15 @@
namespace draco {
-BoundingBox::BoundingBox(const Vector3f &min_point_in,
- const Vector3f &max_point_in)
- : min_point_(min_point_in), max_point_(max_point_in) {}
+BoundingBox::BoundingBox()
+ : BoundingBox(Vector3f(std::numeric_limits<float>::max(),
+ std::numeric_limits<float>::max(),
+ std::numeric_limits<float>::max()),
+ Vector3f(std::numeric_limits<float>::lowest(),
+ std::numeric_limits<float>::lowest(),
+ std::numeric_limits<float>::lowest())) {}
+
+BoundingBox::BoundingBox(const Vector3f &min_point, const Vector3f &max_point)
+ : min_point_(min_point), max_point_(max_point) {}
} // namespace draco
diff --git a/extern/draco/draco/src/draco/core/bounding_box.h b/extern/draco/draco/src/draco/core/bounding_box.h
index 1c20fad8bf2..31ba2d68340 100644
--- a/extern/draco/draco/src/draco/core/bounding_box.h
+++ b/extern/draco/draco/src/draco/core/bounding_box.h
@@ -19,22 +19,27 @@
namespace draco {
-// Class for detecting the bounding box of a point_cloud or mesh.
-// Use the minimum point and the maximum point to define the bounding box.
-// TODO(xiaoxumeng): Change the class of BoundingBox to a template, similar to
-// draco/src/draco/core/vector_d.h
+// Class for computing the bounding box of points in 3D space.
class BoundingBox {
public:
- // Initialization
- BoundingBox(const Vector3f &min_point_in, const Vector3f &max_point_in);
+ // Creates bounding box object with minimum and maximum points initialized to
+ // the largest positive and the smallest negative values, respectively. The
+ // resulting abstract bounding box effectively has no points and can be
+ // updated by providing any point to Update() method.
+ BoundingBox();
- inline const Vector3f &min_point() const { return min_point_; }
- inline const Vector3f &max_point() const { return max_point_; }
+ // Creates bounding box object with minimum and maximum points initialized to
+ // |min_point| and |max_point|, respectively.
+ BoundingBox(const Vector3f &min_point, const Vector3f &max_point);
- // Conditionally updates the bounding box.
- // TODO(xiaoxumeng): Change the function to a template function and change the
- // argument to an iterator.
- inline void update_bounding_box(const Vector3f &new_point) {
+ // Returns the minimum point of the bounding box.
+ inline const Vector3f &GetMinPoint() const { return min_point_; }
+
+ // Returns the maximum point of the bounding box.
+ inline const Vector3f &GetMaxPoint() const { return max_point_; }
+
+ // Conditionally updates the bounding box with a given |new_point|.
+ void Update(const Vector3f &new_point) {
for (int i = 0; i < 3; i++) {
if (new_point[i] < min_point_[i]) {
min_point_[i] = new_point[i];
@@ -45,6 +50,19 @@ class BoundingBox {
}
}
+ // Updates bounding box with minimum and maximum points of the |other|
+ // bounding box.
+ void Update(const BoundingBox &other) {
+ Update(other.GetMinPoint());
+ Update(other.GetMaxPoint());
+ }
+
+ // Returns the size of the bounding box along each axis.
+ Vector3f Size() const { return max_point_ - min_point_; }
+
+ // Returns the center of the bounding box.
+ Vector3f Center() const { return (min_point_ + max_point_) / 2; }
+
private:
Vector3f min_point_;
Vector3f max_point_;
diff --git a/extern/draco/draco/src/draco/core/cycle_timer.cc b/extern/draco/draco/src/draco/core/cycle_timer.cc
index 94b4b28b2f9..58df4df77de 100644
--- a/extern/draco/draco/src/draco/core/cycle_timer.cc
+++ b/extern/draco/draco/src/draco/core/cycle_timer.cc
@@ -17,31 +17,31 @@
namespace draco {
void DracoTimer::Start() {
#ifdef _WIN32
- QueryPerformanceCounter(&tv_start);
+ QueryPerformanceCounter(&tv_start_);
#else
- gettimeofday(&tv_start, nullptr);
+ gettimeofday(&tv_start_, nullptr);
#endif
}
void DracoTimer::Stop() {
#ifdef _WIN32
- QueryPerformanceCounter(&tv_end);
+ QueryPerformanceCounter(&tv_end_);
#else
- gettimeofday(&tv_end, nullptr);
+ gettimeofday(&tv_end_, nullptr);
#endif
}
int64_t DracoTimer::GetInMs() {
#ifdef _WIN32
LARGE_INTEGER elapsed = {0};
- elapsed.QuadPart = tv_end.QuadPart - tv_start.QuadPart;
+ elapsed.QuadPart = tv_end_.QuadPart - tv_start_.QuadPart;
LARGE_INTEGER frequency = {0};
QueryPerformanceFrequency(&frequency);
return elapsed.QuadPart * 1000 / frequency.QuadPart;
#else
- const int64_t seconds = (tv_end.tv_sec - tv_start.tv_sec) * 1000;
- const int64_t milliseconds = (tv_end.tv_usec - tv_start.tv_usec) / 1000;
+ const int64_t seconds = (tv_end_.tv_sec - tv_start_.tv_sec) * 1000;
+ const int64_t milliseconds = (tv_end_.tv_usec - tv_start_.tv_usec) / 1000;
return seconds + milliseconds;
#endif
}
diff --git a/extern/draco/draco/src/draco/core/cycle_timer.h b/extern/draco/draco/src/draco/core/cycle_timer.h
index 172f1c2e9b5..f480cc9d389 100644
--- a/extern/draco/draco/src/draco/core/cycle_timer.h
+++ b/extern/draco/draco/src/draco/core/cycle_timer.h
@@ -20,9 +20,10 @@
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
-typedef LARGE_INTEGER timeval;
+typedef LARGE_INTEGER DracoTimeVal;
#else
#include <sys/time.h>
+typedef timeval DracoTimeVal;
#endif
#include <cinttypes>
@@ -39,8 +40,8 @@ class DracoTimer {
int64_t GetInMs();
private:
- timeval tv_start;
- timeval tv_end;
+ DracoTimeVal tv_start_;
+ DracoTimeVal tv_end_;
};
typedef DracoTimer CycleTimer;
diff --git a/extern/draco/draco/src/draco/core/data_buffer.cc b/extern/draco/draco/src/draco/core/data_buffer.cc
index f0b43d67dbd..96a3787987c 100644
--- a/extern/draco/draco/src/draco/core/data_buffer.cc
+++ b/extern/draco/draco/src/draco/core/data_buffer.cc
@@ -52,7 +52,7 @@ void DataBuffer::Resize(int64_t size) {
}
void DataBuffer::WriteDataToStream(std::ostream &stream) {
- if (data_.size() == 0) {
+ if (data_.empty()) {
return;
}
stream.write(reinterpret_cast<char *>(data_.data()), data_.size());
diff --git a/extern/draco/draco/src/draco/core/decoder_buffer.h b/extern/draco/draco/src/draco/core/decoder_buffer.h
index 0559abbe415..be98e52d60e 100644
--- a/extern/draco/draco/src/draco/core/decoder_buffer.h
+++ b/extern/draco/draco/src/draco/core/decoder_buffer.h
@@ -54,12 +54,11 @@ class DecoderBuffer {
// Decodes up to 32 bits into out_val. Can be called only in between
// StartBitDecoding and EndBitDecoding. Otherwise returns false.
- bool DecodeLeastSignificantBits32(int nbits, uint32_t *out_value) {
+ bool DecodeLeastSignificantBits32(uint32_t nbits, uint32_t *out_value) {
if (!bit_decoder_active()) {
return false;
}
- bit_decoder_.GetBits(nbits, out_value);
- return true;
+ return bit_decoder_.GetBits(nbits, out_value);
}
// Decodes an arbitrary data type.
@@ -158,9 +157,10 @@ class DecoderBuffer {
inline void ConsumeBits(int k) { bit_offset_ += k; }
// Returns |nbits| bits in |x|.
- inline bool GetBits(int32_t nbits, uint32_t *x) {
- DRACO_DCHECK_GE(nbits, 0);
- DRACO_DCHECK_LE(nbits, 32);
+ inline bool GetBits(uint32_t nbits, uint32_t *x) {
+ if (nbits > 32) {
+ return false;
+ }
uint32_t value = 0;
for (int32_t bit = 0; bit < nbits; ++bit) {
value |= GetBit() << bit;
diff --git a/extern/draco/draco/src/draco/core/draco_index_type_vector.h b/extern/draco/draco/src/draco/core/draco_index_type_vector.h
index d47ab3b04eb..0fefc43b23d 100644
--- a/extern/draco/draco/src/draco/core/draco_index_type_vector.h
+++ b/extern/draco/draco/src/draco/core/draco_index_type_vector.h
@@ -28,7 +28,6 @@ namespace draco {
// draco_index_type.h .
// TODO(ostava): Make the interface more complete. It's currently missing
// features such as iterators.
-// TODO(vytyaz): Add more unit tests for this class.
template <class IndexTypeT, class ValueTypeT>
class IndexTypeVector {
public:
@@ -56,7 +55,7 @@ class IndexTypeVector {
void push_back(ValueTypeT &&val) { vector_.push_back(std::move(val)); }
template <typename... Args>
- void emplace_back(Args &&... args) {
+ void emplace_back(Args &&...args) {
vector_.emplace_back(std::forward<Args>(args)...);
}
diff --git a/extern/draco/draco/src/draco/core/draco_version.h b/extern/draco/draco/src/draco/core/draco_version.h
index ffd7948c64d..5f2676ad7e9 100644
--- a/extern/draco/draco/src/draco/core/draco_version.h
+++ b/extern/draco/draco/src/draco/core/draco_version.h
@@ -18,7 +18,7 @@
namespace draco {
// Draco version is comprised of <major>.<minor>.<revision>.
-static const char kDracoVersion[] = "1.3.6";
+static const char kDracoVersion[] = "1.5.2";
const char *Version() { return kDracoVersion; }
diff --git a/extern/draco/draco/src/draco/core/macros.h b/extern/draco/draco/src/draco/core/macros.h
index 89b706e53a5..64647d129d5 100644
--- a/extern/draco/draco/src/draco/core/macros.h
+++ b/extern/draco/draco/src/draco/core/macros.h
@@ -21,11 +21,13 @@
#ifdef ANDROID_LOGGING
#include <android/log.h>
#define LOG_TAG "draco"
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define DRACO_LOGI(...) \
+ __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define DRACO_LOGE(...) \
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#else
-#define LOGI printf
-#define LOGE printf
+#define DRACO_LOGI printf
+#define DRACO_LOGE printf
#endif
#include <iostream>
@@ -88,6 +90,10 @@ namespace draco {
#define DRACO_MACROS_IMPL_CONCAT_INNER_(x, y) x##y
#define DRACO_MACROS_IMPL_CONCAT_(x, y) DRACO_MACROS_IMPL_CONCAT_INNER_(x, y)
+#define DRACO_MACROS_IMPL_CONCAT_INNER_3_(x, y, z) x##y##z
+#define DRACO_MACROS_IMPL_CONCAT_3_(x, y, z) \
+ DRACO_MACROS_IMPL_CONCAT_INNER_3_(x, y, z)
+
// Expand the n-th argument of the macro. Used to select an argument based on
// the number of entries in a variadic macro argument. Example usage:
//
@@ -98,13 +104,20 @@ namespace draco {
// #define VARIADIC_MACRO(...)
// DRACO_SELECT_NTH_FROM_3(__VA_ARGS__, FUNC_3, FUNC_2, FUNC_1) __VA_ARGS__
//
-#define DRACO_SELECT_NTH_FROM_2(_1, _2, NAME) NAME
-#define DRACO_SELECT_NTH_FROM_3(_1, _2, _3, NAME) NAME
-#define DRACO_SELECT_NTH_FROM_4(_1, _2, _3, _4, NAME) NAME
+#define DRACO_SELECT_NTH_FROM_2(_1, _2, NAME, ...) NAME
+#define DRACO_SELECT_NTH_FROM_3(_1, _2, _3, NAME, ...) NAME
+#define DRACO_SELECT_NTH_FROM_4(_1, _2, _3, _4, NAME, ...) NAME
// Macro that converts the Draco bit-stream into one uint16_t number.
// Useful mostly when checking version numbers.
#define DRACO_BITSTREAM_VERSION(MAJOR, MINOR) \
((static_cast<uint16_t>(MAJOR) << 8) | MINOR)
+// Macro that converts the uint16_t Draco bit-stream number into the major
+// and minor components respectively.
+#define DRACO_BISTREAM_VERSION_MAJOR(VERSION) \
+ (static_cast<uint8_t>(VERSION >> 8))
+#define DRACO_BISTREAM_VERSION_MINOR(VERSION) \
+ (static_cast<uint8_t>(VERSION & 0xFF))
+
#endif // DRACO_CORE_MACROS_H_
diff --git a/extern/draco/draco/src/draco/core/options.h b/extern/draco/draco/src/draco/core/options.h
index 1bc4dc0fb7b..9dc22ce16c2 100644
--- a/extern/draco/draco/src/draco/core/options.h
+++ b/extern/draco/draco/src/draco/core/options.h
@@ -71,8 +71,6 @@ class Options {
private:
// All entries are internally stored as strings and converted to the desired
// return type based on the used Get* method.
- // TODO(ostava): Consider adding type safety mechanism that would prevent
- // unsafe operations such as a conversion from vector to int.
std::map<std::string, std::string> options_;
};
diff --git a/extern/draco/draco/src/draco/core/status.h b/extern/draco/draco/src/draco/core/status.h
index 449ad8566de..ee7f43ee59c 100644
--- a/extern/draco/draco/src/draco/core/status.h
+++ b/extern/draco/draco/src/draco/core/status.h
@@ -15,6 +15,7 @@
#ifndef DRACO_CORE_STATUS_H_
#define DRACO_CORE_STATUS_H_
+#include <ostream>
#include <string>
namespace draco {
@@ -61,6 +62,9 @@ inline std::ostream &operator<<(std::ostream &os, const Status &status) {
}
inline Status OkStatus() { return Status(Status::OK); }
+inline Status ErrorStatus(const std::string &msg) {
+ return Status(Status::DRACO_ERROR, msg);
+}
// Evaluates an expression that returns draco::Status. If the status is not OK,
// the macro returns the status object.
diff --git a/extern/draco/draco/src/draco/core/varint_decoding.h b/extern/draco/draco/src/draco/core/varint_decoding.h
index 4e86df732e0..cff47e930b4 100644
--- a/extern/draco/draco/src/draco/core/varint_decoding.h
+++ b/extern/draco/draco/src/draco/core/varint_decoding.h
@@ -58,6 +58,7 @@ bool DecodeVarintUnsigned(int depth, IntTypeT *out_val, DecoderBuffer *buffer) {
// Decodes a specified integer as varint. Note that the IntTypeT must be the
// same as the one used in the corresponding EncodeVarint() call.
+// out_val is undefined if this returns false.
template <typename IntTypeT>
bool DecodeVarint(IntTypeT *out_val, DecoderBuffer *buffer) {
if (std::is_unsigned<IntTypeT>::value) {
diff --git a/extern/draco/draco/src/draco/core/vector_d.h b/extern/draco/draco/src/draco/core/vector_d.h
index bed97304feb..a0ec2dedf2e 100644
--- a/extern/draco/draco/src/draco/core/vector_d.h
+++ b/extern/draco/draco/src/draco/core/vector_d.h
@@ -20,6 +20,7 @@
#include <algorithm>
#include <array>
#include <cmath>
+#include <limits>
#include "draco/core/macros.h"
@@ -33,7 +34,7 @@ class VectorD {
typedef ScalarT Scalar;
typedef VectorD<Scalar, dimension_t> Self;
- // TODO(hemmer): Deprecate.
+ // TODO(b/199760123): Deprecate.
typedef ScalarT CoefficientType;
VectorD() {
@@ -44,7 +45,7 @@ class VectorD {
// The following constructor does not compile in opt mode, which for now led
// to the constructors further down, which is not ideal.
- // TODO(hemmer): fix constructor below and remove others.
+ // TODO(b/199760123): Fix constructor below and remove others.
// template <typename... Args>
// explicit VectorD(Args... args) : v_({args...}) {}
@@ -110,7 +111,7 @@ class VectorD {
Scalar &operator[](int i) { return v_[i]; }
const Scalar &operator[](int i) const { return v_[i]; }
- // TODO(hemmer): remove.
+ // TODO(b/199760123): Remove.
// Similar to interface of Eigen library.
Scalar &operator()(int i) { return v_[i]; }
const Scalar &operator()(int i) const { return v_[i]; }
@@ -236,7 +237,12 @@ class VectorD {
Scalar AbsSum() const {
Scalar result(0);
for (int i = 0; i < dimension; ++i) {
- result += std::abs(v_[i]);
+ Scalar next_value = std::abs(v_[i]);
+ if (result > std::numeric_limits<Scalar>::max() - next_value) {
+ // Return the max if adding would have caused an overflow.
+ return std::numeric_limits<Scalar>::max();
+ }
+ result += next_value;
}
return result;
}
diff --git a/extern/draco/draco/src/draco/draco_features.h b/extern/draco/draco/src/draco/draco_features.h
index 27e3d7f136a..d0a630e5465 100644
--- a/extern/draco/draco/src/draco/draco_features.h
+++ b/extern/draco/draco/src/draco/draco_features.h
@@ -4,7 +4,5 @@
#define DRACO_MESH_COMPRESSION_SUPPORTED
#define DRACO_NORMAL_ENCODING_SUPPORTED
#define DRACO_STANDARD_EDGEBREAKER_SUPPORTED
-#define DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
-#define DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
#endif // DRACO_FEATURES_H_
diff --git a/extern/draco/draco/src/draco/mesh/corner_table.cc b/extern/draco/draco/src/draco/mesh/corner_table.cc
index 6066e58bd8b..3f92f651ab6 100644
--- a/extern/draco/draco/src/draco/mesh/corner_table.cc
+++ b/extern/draco/draco/src/draco/mesh/corner_table.cc
@@ -66,12 +66,13 @@ bool CornerTable::Reset(int num_faces, int num_vertices) {
if (num_faces < 0 || num_vertices < 0) {
return false;
}
- if (static_cast<unsigned int>(num_faces) >
+ const unsigned int num_faces_unsigned = num_faces;
+ if (num_faces_unsigned >
std::numeric_limits<CornerIndex::ValueType>::max() / 3) {
return false;
}
- corner_to_vertex_map_.assign(num_faces * 3, kInvalidVertexIndex);
- opposite_corners_.assign(num_faces * 3, kInvalidCornerIndex);
+ corner_to_vertex_map_.assign(num_faces_unsigned * 3, kInvalidVertexIndex);
+ opposite_corners_.assign(num_faces_unsigned * 3, kInvalidCornerIndex);
vertex_corners_.reserve(num_vertices);
valence_cache_.ClearValenceCache();
valence_cache_.ClearValenceCacheInaccurate();
diff --git a/extern/draco/draco/src/draco/mesh/mesh.h b/extern/draco/draco/src/draco/mesh/mesh.h
index f4506da81c9..b1577c03986 100644
--- a/extern/draco/draco/src/draco/mesh/mesh.h
+++ b/extern/draco/draco/src/draco/mesh/mesh.h
@@ -119,6 +119,10 @@ class Mesh : public PointCloud {
const std::vector<PointIndex> &unique_point_ids) override;
#endif
+ // Exposes |faces_|. Use |faces_| at your own risk. DO NOT store the
+ // reference: the |faces_| object is destroyed with the mesh.
+ IndexTypeVector<FaceIndex, Face> &faces() { return faces_; }
+
private:
// Mesh specific per-attribute data.
std::vector<AttributeData> attribute_data_;
diff --git a/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h
index 7dad25cf1d2..6f02453d2d4 100644
--- a/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h
+++ b/extern/draco/draco/src/draco/mesh/mesh_attribute_corner_table.h
@@ -130,6 +130,12 @@ class MeshAttributeCornerTable {
return false;
}
+ bool IsDegenerated(FaceIndex face) const {
+ // Introducing seams can't change the degeneracy of the individual faces,
+ // therefore we can delegate the check to the original |corner_table_|.
+ return corner_table_->IsDegenerated(face);
+ }
+
bool no_interior_seams() const { return no_interior_seams_; }
const CornerTable *corner_table() const { return corner_table_; }
diff --git a/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc b/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc
index 773c1e18fe6..bc44c831c4e 100644
--- a/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc
+++ b/extern/draco/draco/src/draco/mesh/mesh_cleanup.cc
@@ -14,25 +14,42 @@
//
#include "draco/mesh/mesh_cleanup.h"
+#include <unordered_set>
+
+#include "draco/core/hash_utils.h"
+
namespace draco {
-bool MeshCleanup::operator()(Mesh *mesh, const MeshCleanupOptions &options) {
- if (!options.remove_degenerated_faces && !options.remove_unused_attributes) {
- return true; // Nothing to cleanup.
+Status MeshCleanup::Cleanup(Mesh *mesh, const MeshCleanupOptions &options) {
+ if (!options.remove_degenerated_faces && !options.remove_unused_attributes &&
+ !options.remove_duplicate_faces && !options.make_geometry_manifold) {
+ return OkStatus(); // Nothing to cleanup.
}
const PointAttribute *const pos_att =
mesh->GetNamedAttribute(GeometryAttribute::POSITION);
if (pos_att == nullptr) {
- return false;
+ return Status(Status::DRACO_ERROR, "Missing position attribute.");
}
- // Array that is going to store whether a corresponding point is used.
- std::vector<bool> is_point_used;
+
+ if (options.remove_degenerated_faces) {
+ RemoveDegeneratedFaces(mesh);
+ }
+
+ if (options.remove_duplicate_faces) {
+ RemoveDuplicateFaces(mesh);
+ }
+
if (options.remove_unused_attributes) {
- is_point_used.resize(mesh->num_points(), false);
+ RemoveUnusedAttributes(mesh);
}
+ return OkStatus();
+}
+
+void MeshCleanup::RemoveDegeneratedFaces(Mesh *mesh) {
+ const PointAttribute *const pos_att =
+ mesh->GetNamedAttribute(GeometryAttribute::POSITION);
FaceIndex::ValueType num_degenerated_faces = 0;
- PointIndex::ValueType num_new_points = 0;
// Array for storing position indices on a face.
std::array<AttributeValueIndex, 3> pos_indices;
for (FaceIndex f(0); f < mesh->num_faces(); ++f) {
@@ -40,149 +57,195 @@ bool MeshCleanup::operator()(Mesh *mesh, const MeshCleanupOptions &options) {
for (int p = 0; p < 3; ++p) {
pos_indices[p] = pos_att->mapped_index(face[p]);
}
- bool is_face_valid = true;
- if (options.remove_degenerated_faces) {
- if (pos_indices[0] == pos_indices[1] ||
- pos_indices[0] == pos_indices[2] ||
- pos_indices[1] == pos_indices[2]) {
- ++num_degenerated_faces;
- is_face_valid = false;
- } else if (num_degenerated_faces > 0) {
- // Copy the face to its new location.
- mesh->SetFace(f - num_degenerated_faces, face);
- }
- }
- if (options.remove_unused_attributes && is_face_valid) {
- for (int p = 0; p < 3; ++p) {
- if (!is_point_used[face[p].value()]) {
- is_point_used[face[p].value()] = true;
- ++num_new_points;
- }
- }
+ if (pos_indices[0] == pos_indices[1] || pos_indices[0] == pos_indices[2] ||
+ pos_indices[1] == pos_indices[2]) {
+ ++num_degenerated_faces;
+ } else if (num_degenerated_faces > 0) {
+ // Copy the face to its new location.
+ mesh->SetFace(f - num_degenerated_faces, face);
}
}
if (num_degenerated_faces > 0) {
mesh->SetNumFaces(mesh->num_faces() - num_degenerated_faces);
}
- if (options.remove_unused_attributes) {
- bool points_changed = false;
- const PointIndex::ValueType num_original_points = mesh->num_points();
- // Map from old points to the new ones.
- IndexTypeVector<PointIndex, PointIndex> point_map(num_original_points);
- if (num_new_points < static_cast<int>(mesh->num_points())) {
- // Some of the points were removed. We need to remap the old points to the
- // new ones.
- num_new_points = 0;
- for (PointIndex i(0); i < num_original_points; ++i) {
- if (is_point_used[i.value()]) {
- point_map[i] = num_new_points++;
- } else {
- point_map[i] = kInvalidPointIndex;
- }
+}
+
+void MeshCleanup::RemoveDuplicateFaces(Mesh *mesh) {
+ const PointAttribute *const pos_att =
+ mesh->GetNamedAttribute(GeometryAttribute::POSITION);
+
+ typedef std::array<AttributeValueIndex::ValueType, 3> PosTriplet;
+ PosTriplet pos_indices;
+ std::unordered_set<PosTriplet, HashArray<PosTriplet>> is_face_used;
+
+ uint32_t num_duplicate_faces = 0;
+ for (FaceIndex fi(0); fi < mesh->num_faces(); ++fi) {
+ const auto f = mesh->face(fi);
+ for (int c = 0; c < 3; ++c) {
+ pos_indices[c] = pos_att->mapped_index(f[c]).value();
+ }
+ // Shift the position indices until the smallest index is the first one.
+ while (pos_indices[0] > pos_indices[1] || pos_indices[0] > pos_indices[2]) {
+ // Shift to the left.
+ std::swap(pos_indices[0], pos_indices[1]);
+ std::swap(pos_indices[1], pos_indices[2]);
+ }
+ // Check if have encountered the same position triplet on a different face.
+ if (is_face_used.find(pos_indices) != is_face_used.end()) {
+ // Duplicate face. Ignore it.
+ num_duplicate_faces++;
+ } else {
+ // Insert new face to the set.
+ is_face_used.insert(pos_indices);
+ if (num_duplicate_faces > 0) {
+ // Copy the face to its new location.
+ mesh->SetFace(fi - num_duplicate_faces, f);
}
- // Go over faces and update their points.
- for (FaceIndex f(0); f < mesh->num_faces(); ++f) {
- Mesh::Face face = mesh->face(f);
- for (int p = 0; p < 3; ++p) {
- face[p] = point_map[face[p]];
- }
- mesh->SetFace(f, face);
+ }
+ }
+ if (num_duplicate_faces > 0) {
+ mesh->SetNumFaces(mesh->num_faces() - num_duplicate_faces);
+ }
+}
+
+void MeshCleanup::RemoveUnusedAttributes(Mesh *mesh) {
+ // Array that is going to store whether a corresponding point is used.
+ std::vector<bool> is_point_used;
+ PointIndex::ValueType num_new_points = 0;
+ is_point_used.resize(mesh->num_points(), false);
+ for (FaceIndex f(0); f < mesh->num_faces(); ++f) {
+ const Mesh::Face &face = mesh->face(f);
+ for (int p = 0; p < 3; ++p) {
+ if (!is_point_used[face[p].value()]) {
+ is_point_used[face[p].value()] = true;
+ ++num_new_points;
}
- // Set the new number of points.
- mesh->set_num_points(num_new_points);
- points_changed = true;
- } else {
- // No points were removed. Initialize identity map between the old and new
- // points.
- for (PointIndex i(0); i < num_original_points; ++i) {
- point_map[i] = i;
+ }
+ }
+
+ bool points_changed = false;
+ const PointIndex::ValueType num_original_points = mesh->num_points();
+ // Map from old points to the new ones.
+ IndexTypeVector<PointIndex, PointIndex> point_map(num_original_points);
+ if (num_new_points < static_cast<int>(mesh->num_points())) {
+ // Some of the points were removed. We need to remap the old points to the
+ // new ones.
+ num_new_points = 0;
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ if (is_point_used[i.value()]) {
+ point_map[i] = num_new_points++;
+ } else {
+ point_map[i] = kInvalidPointIndex;
+ }
+ }
+ // Go over faces and update their points.
+ for (FaceIndex f(0); f < mesh->num_faces(); ++f) {
+ Mesh::Face face = mesh->face(f);
+ for (int p = 0; p < 3; ++p) {
+ face[p] = point_map[face[p]];
}
+ mesh->SetFace(f, face);
}
+ // Set the new number of points.
+ mesh->set_num_points(num_new_points);
+ points_changed = true;
+ } else {
+ // No points were removed. Initialize identity map between the old and new
+ // points.
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ point_map[i] = i;
+ }
+ }
- // Update index mapping for attributes.
- IndexTypeVector<AttributeValueIndex, uint8_t> is_att_index_used;
- IndexTypeVector<AttributeValueIndex, AttributeValueIndex> att_index_map;
- for (int a = 0; a < mesh->num_attributes(); ++a) {
- PointAttribute *const att = mesh->attribute(a);
- // First detect which attribute entries are used (included in a point).
- is_att_index_used.assign(att->size(), 0);
- att_index_map.clear();
- AttributeValueIndex::ValueType num_used_entries = 0;
- for (PointIndex i(0); i < num_original_points; ++i) {
- if (point_map[i] != kInvalidPointIndex) {
- const AttributeValueIndex entry_id = att->mapped_index(i);
- if (!is_att_index_used[entry_id]) {
- is_att_index_used[entry_id] = 1;
- ++num_used_entries;
- }
+ // Update index mapping for attributes.
+ IndexTypeVector<AttributeValueIndex, uint8_t> is_att_index_used;
+ IndexTypeVector<AttributeValueIndex, AttributeValueIndex> att_index_map;
+ for (int a = 0; a < mesh->num_attributes(); ++a) {
+ PointAttribute *const att = mesh->attribute(a);
+ // First detect which attribute entries are used (included in a point).
+ is_att_index_used.assign(att->size(), 0);
+ att_index_map.clear();
+ AttributeValueIndex::ValueType num_used_entries = 0;
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ if (point_map[i] != kInvalidPointIndex) {
+ const AttributeValueIndex entry_id = att->mapped_index(i);
+ if (!is_att_index_used[entry_id]) {
+ is_att_index_used[entry_id] = 1;
+ ++num_used_entries;
}
}
- bool att_indices_changed = false;
- // If there are some unused attribute entries, remap the attribute values
- // in the attribute buffer.
- if (num_used_entries < static_cast<int>(att->size())) {
- att_index_map.resize(att->size());
- num_used_entries = 0;
- for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size());
- ++i) {
- if (is_att_index_used[i]) {
- att_index_map[i] = num_used_entries;
- if (i > num_used_entries) {
- const uint8_t *const src_add = att->GetAddress(i);
- att->buffer()->Write(
- att->GetBytePos(AttributeValueIndex(num_used_entries)),
- src_add, att->byte_stride());
- }
- ++num_used_entries;
+ }
+ bool att_indices_changed = false;
+ // If there are some unused attribute entries, remap the attribute values
+ // in the attribute buffer.
+ if (num_used_entries < static_cast<int>(att->size())) {
+ att_index_map.resize(att->size());
+ num_used_entries = 0;
+ for (AttributeValueIndex i(0); i < static_cast<uint32_t>(att->size());
+ ++i) {
+ if (is_att_index_used[i]) {
+ att_index_map[i] = num_used_entries;
+ if (i > num_used_entries) {
+ const uint8_t *const src_add = att->GetAddress(i);
+ att->buffer()->Write(
+ att->GetBytePos(AttributeValueIndex(num_used_entries)), src_add,
+ att->byte_stride());
}
+ ++num_used_entries;
}
- // Update the number of unique entries in the vertex buffer.
- att->Resize(num_used_entries);
- att_indices_changed = true;
}
- // If either the points or attribute indices have changed, we need to
- // update the attribute index mapping.
- if (points_changed || att_indices_changed) {
- if (att->is_mapping_identity()) {
- // The mapping was identity. It'll remain identity only if the
- // number of point and attribute indices is still the same.
- if (num_used_entries != static_cast<int>(mesh->num_points())) {
- // We need to create an explicit mapping.
- // First we need to initialize the explicit map to the original
- // number of points to recreate the original identity map.
- att->SetExplicitMapping(num_original_points);
- // Set the entries of the explicit map to identity.
- for (PointIndex::ValueType i = 0; i < num_original_points; ++i) {
- att->SetPointMapEntry(PointIndex(i), AttributeValueIndex(i));
- }
+ // Update the number of unique entries in the vertex buffer.
+ att->Resize(num_used_entries);
+ att_indices_changed = true;
+ }
+ // If either the points or attribute indices have changed, we need to
+ // update the attribute index mapping.
+ if (points_changed || att_indices_changed) {
+ if (att->is_mapping_identity()) {
+ // The mapping was identity. It'll remain identity only if the
+ // number of point and attribute indices is still the same.
+ if (num_used_entries != static_cast<int>(mesh->num_points())) {
+ // We need to create an explicit mapping.
+ // First we need to initialize the explicit map to the original
+ // number of points to recreate the original identity map.
+ att->SetExplicitMapping(num_original_points);
+ // Set the entries of the explicit map to identity.
+ for (PointIndex::ValueType i = 0; i < num_original_points; ++i) {
+ att->SetPointMapEntry(PointIndex(i), AttributeValueIndex(i));
}
}
- if (!att->is_mapping_identity()) {
- // Explicit mapping between points and local attribute indices.
- for (PointIndex i(0); i < num_original_points; ++i) {
- // The new point id that maps to the currently processed attribute
- // entry.
- const PointIndex new_point_id = point_map[i];
- if (new_point_id == kInvalidPointIndex) {
- continue;
- }
- // Index of the currently processed attribute entry in the original
- // mesh.
- const AttributeValueIndex original_entry_index =
- att->mapped_index(i);
- // New index of the same entry after unused entries were removed.
- const AttributeValueIndex new_entry_index =
- att_index_map[original_entry_index];
- att->SetPointMapEntry(new_point_id, new_entry_index);
+ }
+ if (!att->is_mapping_identity()) {
+ // Explicit mapping between points and local attribute indices.
+ for (PointIndex i(0); i < num_original_points; ++i) {
+ // The new point id that maps to the currently processed attribute
+ // entry.
+ const PointIndex new_point_id = point_map[i];
+ if (new_point_id == kInvalidPointIndex) {
+ continue;
}
- // If the number of points changed, we need to set a new explicit map
- // size.
- att->SetExplicitMapping(mesh->num_points());
+ // Index of the currently processed attribute entry in the original
+ // mesh.
+ const AttributeValueIndex original_entry_index = att->mapped_index(i);
+ // New index of the same entry after unused entries were removed.
+ const AttributeValueIndex new_entry_index =
+ att_indices_changed ? att_index_map[original_entry_index]
+ : original_entry_index;
+
+ // Update the mapping. Note that the new point index is always smaller
+ // than the processed index |i|, making this operation safe.
+ att->SetPointMapEntry(new_point_id, new_entry_index);
}
+ // If the number of points changed, we need to set a new explicit map
+ // size.
+ att->SetExplicitMapping(mesh->num_points());
}
}
}
- return true;
+}
+
+Status MeshCleanup::MakeGeometryManifold(Mesh *mesh) {
+ return Status(Status::DRACO_ERROR, "Unsupported function.");
}
} // namespace draco
diff --git a/extern/draco/draco/src/draco/mesh/mesh_cleanup.h b/extern/draco/draco/src/draco/mesh/mesh_cleanup.h
index b56129dce58..0acdc2ae5b8 100644
--- a/extern/draco/draco/src/draco/mesh/mesh_cleanup.h
+++ b/extern/draco/draco/src/draco/mesh/mesh_cleanup.h
@@ -15,27 +15,44 @@
#ifndef DRACO_MESH_MESH_CLEANUP_H_
#define DRACO_MESH_MESH_CLEANUP_H_
+#include "draco/core/status.h"
#include "draco/mesh/mesh.h"
namespace draco {
// Options used by the MeshCleanup class.
struct MeshCleanupOptions {
- MeshCleanupOptions()
- : remove_degenerated_faces(true), remove_unused_attributes(true) {}
// If true, the cleanup tool removes any face where two or more vertices
// share the same position index.
- bool remove_degenerated_faces;
+ bool remove_degenerated_faces = true;
+
+ // If true, the cleanup tool removes all duplicate faces. A pair of faces is
+ // duplicate if both faces share the same position indices on all vertices
+ // (that is, position values have to be duduplicated). Note that all
+ // non-position properties are currently ignored.
+ bool remove_duplicate_faces = true;
+
// If true, the cleanup tool removes any unused attribute value or unused
// point id. For example, it can be used to remove isolated vertices.
- bool remove_unused_attributes;
+ bool remove_unused_attributes = true;
+
+ // If true, the cleanup tool splits vertices along non-manifold edges and
+ // vertices. This ensures that the connectivity defined by position indices
+ // is manifold.
+ bool make_geometry_manifold = false;
};
// Tool that can be used for removing bad or unused data from draco::Meshes.
class MeshCleanup {
public:
// Performs in-place cleanup of the input mesh according to the input options.
- bool operator()(Mesh *mesh, const MeshCleanupOptions &options);
+ static Status Cleanup(Mesh *mesh, const MeshCleanupOptions &options);
+
+ private:
+ static void RemoveDegeneratedFaces(Mesh *mesh);
+ static void RemoveDuplicateFaces(Mesh *mesh);
+ static void RemoveUnusedAttributes(Mesh *mesh);
+ static Status MakeGeometryManifold(Mesh *mesh);
};
} // namespace draco
diff --git a/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h
index b450bc80cd8..0a3bcf49782 100644
--- a/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h
+++ b/extern/draco/draco/src/draco/mesh/mesh_misc_functions.h
@@ -67,7 +67,6 @@ inline bool IsCornerOppositeToAttributeSeam(CornerIndex ci,
// Interpolates an attribute value on a face using given barycentric
// coordinates. InterpolatedVectorT should be a VectorD that corresponds to the
// values stored in the attribute.
-// TODO(ostava): Find a better place for this.
template <typename InterpolatedVectorT>
InterpolatedVectorT ComputeInterpolatedAttributeValueOnMeshFace(
const Mesh &mesh, const PointAttribute &attribute, FaceIndex fi,
diff --git a/extern/draco/draco/src/draco/mesh/mesh_stripifier.h b/extern/draco/draco/src/draco/mesh/mesh_stripifier.h
index 0c298f48e86..8e8d8d9f21f 100644
--- a/extern/draco/draco/src/draco/mesh/mesh_stripifier.h
+++ b/extern/draco/draco/src/draco/mesh/mesh_stripifier.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-#ifndef DRACO_SRC_DRACO_MESH_MESH_STRIPIFIER_H_
-#define DRACO_SRC_DRACO_MESH_MESH_STRIPIFIER_H_
+#ifndef DRACO_MESH_MESH_STRIPIFIER_H_
+#define DRACO_MESH_MESH_STRIPIFIER_H_
#include "draco/mesh/mesh_misc_functions.h"
@@ -71,8 +71,6 @@ class MeshStripifier {
mesh_ = &mesh;
num_strips_ = 0;
num_encoded_faces_ = 0;
- // TODO(ostava): We may be able to avoid computing the corner table if we
- // already have it stored somewhere.
corner_table_ = CreateCornerTableFromPositionAttribute(mesh_);
if (corner_table_ == nullptr) {
return false;
@@ -257,4 +255,4 @@ bool MeshStripifier::GenerateTriangleStripsWithDegenerateTriangles(
} // namespace draco
-#endif // DRACO_SRC_DRACO_MESH_MESH_STRIPIFIER_H_
+#endif // DRACO_MESH_MESH_STRIPIFIER_H_
diff --git a/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc
index 60b0c50b8d5..cb767f871a9 100644
--- a/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc
+++ b/extern/draco/draco/src/draco/mesh/triangle_soup_mesh_builder.cc
@@ -41,8 +41,6 @@ void TriangleSoupMeshBuilder::SetAttributeValuesForFace(
att->SetAttributeValue(AttributeValueIndex(start_index), corner_value_0);
att->SetAttributeValue(AttributeValueIndex(start_index + 1), corner_value_1);
att->SetAttributeValue(AttributeValueIndex(start_index + 2), corner_value_2);
- // TODO(ostava): The below code should be called only for one attribute.
- // It will work OK even for multiple attributes, but it's redundant.
mesh_->SetFace(face_id,
{{PointIndex(start_index), PointIndex(start_index + 1),
PointIndex(start_index + 2)}});
diff --git a/extern/draco/draco/src/draco/metadata/geometry_metadata.cc b/extern/draco/draco/src/draco/metadata/geometry_metadata.cc
index b83898140ae..b6a882c0b1b 100644
--- a/extern/draco/draco/src/draco/metadata/geometry_metadata.cc
+++ b/extern/draco/draco/src/draco/metadata/geometry_metadata.cc
@@ -18,6 +18,19 @@
namespace draco {
+AttributeMetadata::AttributeMetadata(const AttributeMetadata &metadata)
+ : Metadata(metadata) {
+ att_unique_id_ = metadata.att_unique_id_;
+}
+
+GeometryMetadata::GeometryMetadata(const GeometryMetadata &metadata)
+ : Metadata(metadata) {
+ for (size_t i = 0; i < metadata.att_metadatas_.size(); ++i) {
+ att_metadatas_.push_back(std::unique_ptr<AttributeMetadata>(
+ new AttributeMetadata(*metadata.att_metadatas_[i])));
+ }
+}
+
const AttributeMetadata *GeometryMetadata::GetAttributeMetadataByStringEntry(
const std::string &entry_name, const std::string &entry_value) const {
for (auto &&att_metadata : att_metadatas_) {
@@ -35,7 +48,7 @@ const AttributeMetadata *GeometryMetadata::GetAttributeMetadataByStringEntry(
bool GeometryMetadata::AddAttributeMetadata(
std::unique_ptr<AttributeMetadata> att_metadata) {
- if (!att_metadata.get()) {
+ if (!att_metadata) {
return false;
}
att_metadatas_.push_back(std::move(att_metadata));
diff --git a/extern/draco/draco/src/draco/metadata/geometry_metadata.h b/extern/draco/draco/src/draco/metadata/geometry_metadata.h
index ec7ecb9ee68..531bdef2540 100644
--- a/extern/draco/draco/src/draco/metadata/geometry_metadata.h
+++ b/extern/draco/draco/src/draco/metadata/geometry_metadata.h
@@ -25,6 +25,7 @@ namespace draco {
class AttributeMetadata : public Metadata {
public:
AttributeMetadata() : att_unique_id_(0) {}
+ AttributeMetadata(const AttributeMetadata &metadata);
explicit AttributeMetadata(const Metadata &metadata)
: Metadata(metadata), att_unique_id_(0) {}
@@ -57,6 +58,7 @@ struct AttributeMetadataHasher {
class GeometryMetadata : public Metadata {
public:
GeometryMetadata() {}
+ GeometryMetadata(const GeometryMetadata &metadata);
explicit GeometryMetadata(const Metadata &metadata) : Metadata(metadata) {}
const AttributeMetadata *GetAttributeMetadataByStringEntry(
diff --git a/extern/draco/draco/src/draco/metadata/metadata.cc b/extern/draco/draco/src/draco/metadata/metadata.cc
index 9141907ed71..51b4e93a328 100644
--- a/extern/draco/draco/src/draco/metadata/metadata.cc
+++ b/extern/draco/draco/src/draco/metadata/metadata.cc
@@ -122,6 +122,14 @@ const Metadata *Metadata::GetSubMetadata(const std::string &name) const {
return sub_ptr->second.get();
}
+Metadata *Metadata::sub_metadata(const std::string &name) {
+ auto sub_ptr = sub_metadatas_.find(name);
+ if (sub_ptr == sub_metadatas_.end()) {
+ return nullptr;
+ }
+ return sub_ptr->second.get();
+}
+
void Metadata::RemoveEntry(const std::string &name) {
// Actually just remove "name", no need to check if it exists.
auto entry_ptr = entries_.find(name);
diff --git a/extern/draco/draco/src/draco/metadata/metadata.h b/extern/draco/draco/src/draco/metadata/metadata.h
index 56d05e46a3e..12c1ba97439 100644
--- a/extern/draco/draco/src/draco/metadata/metadata.h
+++ b/extern/draco/draco/src/draco/metadata/metadata.h
@@ -147,6 +147,7 @@ class Metadata {
bool AddSubMetadata(const std::string &name,
std::unique_ptr<Metadata> sub_metadata);
const Metadata *GetSubMetadata(const std::string &name) const;
+ Metadata *sub_metadata(const std::string &name);
void RemoveEntry(const std::string &name);
diff --git a/extern/draco/draco/src/draco/metadata/metadata_decoder.cc b/extern/draco/draco/src/draco/metadata/metadata_decoder.cc
index e664e4fa524..a8e66f854cf 100644
--- a/extern/draco/draco/src/draco/metadata/metadata_decoder.cc
+++ b/extern/draco/draco/src/draco/metadata/metadata_decoder.cc
@@ -78,8 +78,10 @@ bool MetadataDecoder::DecodeMetadata(Metadata *metadata) {
std::unique_ptr<Metadata> sub_metadata =
std::unique_ptr<Metadata>(new Metadata());
metadata = sub_metadata.get();
- mp.parent_metadata->AddSubMetadata(sub_metadata_name,
- std::move(sub_metadata));
+ if (!mp.parent_metadata->AddSubMetadata(sub_metadata_name,
+ std::move(sub_metadata))) {
+ return false;
+ }
}
if (metadata == nullptr) {
return false;
@@ -98,6 +100,10 @@ bool MetadataDecoder::DecodeMetadata(Metadata *metadata) {
if (!DecodeVarint(&num_sub_metadata, buffer_)) {
return false;
}
+ if (num_sub_metadata > buffer_->remaining_size()) {
+ // The decoded number of metadata items is unreasonably high.
+ return false;
+ }
for (uint32_t i = 0; i < num_sub_metadata; ++i) {
metadata_stack.push_back({metadata, nullptr});
}
diff --git a/extern/draco/draco/src/draco/point_cloud/point_cloud.cc b/extern/draco/draco/src/draco/point_cloud/point_cloud.cc
index 8eb638f80d4..55ad6670da5 100644
--- a/extern/draco/draco/src/draco/point_cloud/point_cloud.cc
+++ b/extern/draco/draco/src/draco/point_cloud/point_cloud.cc
@@ -241,7 +241,7 @@ void PointCloud::ApplyPointIdDeduplication(
bool PointCloud::DeduplicateAttributeValues() {
// Go over all attributes and create mapping between duplicate entries.
if (num_points() == 0) {
- return false; // Unexpected attribute size.
+ return true; // Nothing to deduplicate.
}
// Deduplicate all attributes.
for (int32_t att_id = 0; att_id < num_attributes(); ++att_id) {
@@ -253,17 +253,11 @@ bool PointCloud::DeduplicateAttributeValues() {
}
#endif
-// TODO(xiaoxumeng): Consider to cash the BBox.
+// TODO(b/199760503): Consider to cache the BBox.
BoundingBox PointCloud::ComputeBoundingBox() const {
- BoundingBox bounding_box =
- BoundingBox(Vector3f(std::numeric_limits<float>::max(),
- std::numeric_limits<float>::max(),
- std::numeric_limits<float>::max()),
- Vector3f(-std::numeric_limits<float>::max(),
- -std::numeric_limits<float>::max(),
- -std::numeric_limits<float>::max()));
+ BoundingBox bounding_box;
auto pc_att = GetNamedAttribute(GeometryAttribute::POSITION);
- // TODO(xiaoxumeng): Make the BoundingBox a template type, it may not be easy
+ // TODO(b/199760503): Make the BoundingBox a template type, it may not be easy
// because PointCloud is not a template.
// Or simply add some preconditioning here to make sure the position attribute
// is valid, because the current code works only if the position attribute is
@@ -274,7 +268,7 @@ BoundingBox PointCloud::ComputeBoundingBox() const {
for (AttributeValueIndex i(0); i < static_cast<uint32_t>(pc_att->size());
++i) {
pc_att->GetValue(i, &p[0]);
- bounding_box.update_bounding_box(p);
+ bounding_box.Update(p);
}
return bounding_box;
}
diff --git a/extern/draco/patches/blender.patch b/extern/draco/patches/blender.patch
new file mode 100644
index 00000000000..de39260367b
--- /dev/null
+++ b/extern/draco/patches/blender.patch
@@ -0,0 +1,30 @@
+diff --git a/draco/src/draco/attributes/geometry_attribute.h b/draco/src/draco/attributes/geometry_attribute.h
+index fd478a4..c1c0148 100644
+--- a/draco/src/draco/attributes/geometry_attribute.h
++++ b/draco/src/draco/attributes/geometry_attribute.h
+@@ -285,11 +285,25 @@ class GeometryAttribute {
+ // Make sure the in_value fits within the range of values that OutT
+ // is able to represent. Perform the check only for integral types.
+ if (std::is_integral<T>::value && std::is_integral<OutT>::value) {
++#ifdef _MSC_VER
++# pragma warning(push)
++# pragma warning(disable:4804)
++#endif
++#if defined(__GNUC__) && !defined(__clang__)
++# pragma GCC diagnostic push
++# pragma GCC diagnostic ignored "-Wbool-compare"
++#endif
+ static constexpr OutT kOutMin =
+ std::is_signed<T>::value ? std::numeric_limits<OutT>::lowest() : 0;
+ if (in_value < kOutMin || in_value > std::numeric_limits<OutT>::max()) {
+ return false;
+ }
++#ifdef __GNUC__
++# pragma GCC diagnostic pop
++#endif
++#ifdef _MSC_VER
++# pragma warning(pop)
++#endif
+ }
+
+ out_value[i] = static_cast<OutT>(in_value);
diff --git a/extern/draco/src/common.cpp b/extern/draco/src/common.cpp
index 6f98d8db7ef..3a11c126ece 100644
--- a/extern/draco/src/common.cpp
+++ b/extern/draco/src/common.cpp
@@ -54,20 +54,20 @@ size_t getComponentByteLength(size_t componentType)
{
switch (componentType)
{
- case ComponentType::Byte:
- case ComponentType::UnsignedByte:
- return 1;
-
- case ComponentType::Short:
- case ComponentType::UnsignedShort:
- return 2;
-
- case ComponentType::UnsignedInt:
- case ComponentType::Float:
- return 4;
-
- default:
- return 0;
+ case ComponentType::Byte:
+ case ComponentType::UnsignedByte:
+ return 1;
+
+ case ComponentType::Short:
+ case ComponentType::UnsignedShort:
+ return 2;
+
+ case ComponentType::UnsignedInt:
+ case ComponentType::Float:
+ return 4;
+
+ default:
+ return 0;
}
}
diff --git a/extern/draco/src/common.h b/extern/draco/src/common.h
index beaf7d91adb..eef50596350 100644
--- a/extern/draco/src/common.h
+++ b/extern/draco/src/common.h
@@ -33,7 +33,7 @@
#define API(returnType) extern "C" returnType
#endif
-enum ComponentType: size_t
+enum ComponentType : size_t
{
Byte = 5120,
UnsignedByte = 5121,
diff --git a/extern/draco/src/decoder.cpp b/extern/draco/src/decoder.cpp
index 3f3e03bd9f2..e5ec2b65e6c 100644
--- a/extern/draco/src/decoder.cpp
+++ b/extern/draco/src/decoder.cpp
@@ -17,7 +17,6 @@
* @date 2020-11-18
*/
-
#include "decoder.h"
#include <memory>
@@ -30,7 +29,8 @@
#define LOG_PREFIX "DracoDecoder | "
-struct Decoder {
+struct Decoder
+{
std::unique_ptr<draco::Mesh> mesh;
std::vector<uint8_t> indexBuffer;
std::map<uint32_t, std::vector<uint8_t>> buffers;
@@ -54,20 +54,20 @@ bool decoderDecode(Decoder *decoder, void *data, size_t byteLength)
draco::Decoder dracoDecoder;
draco::DecoderBuffer dracoDecoderBuffer;
dracoDecoderBuffer.Init(reinterpret_cast<char *>(data), byteLength);
-
+
auto decoderStatus = dracoDecoder.DecodeMeshFromBuffer(&dracoDecoderBuffer);
if (!decoderStatus.ok())
{
printf(LOG_PREFIX "Error during Draco decoding: %s\n", decoderStatus.status().error_msg());
return false;
}
-
+
decoder->mesh = std::move(decoderStatus).value();
decoder->vertexCount = decoder->mesh->num_points();
decoder->indexCount = decoder->mesh->num_faces() * 3;
-
+
printf(LOG_PREFIX "Decoded %" PRIu32 " vertices, %" PRIu32 " indices\n", decoder->vertexCount, decoder->indexCount);
-
+
return true;
}
@@ -83,32 +83,32 @@ uint32_t decoderGetIndexCount(Decoder *decoder)
bool decoderAttributeIsNormalized(Decoder *decoder, uint32_t id)
{
- const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id);
+ const draco::PointAttribute *attribute = decoder->mesh->GetAttributeByUniqueId(id);
return attribute != nullptr && attribute->normalized();
}
bool decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType)
{
- const draco::PointAttribute* attribute = decoder->mesh->GetAttributeByUniqueId(id);
-
+ const draco::PointAttribute *attribute = decoder->mesh->GetAttributeByUniqueId(id);
+
if (attribute == nullptr)
{
printf(LOG_PREFIX "Attribute with id=%" PRIu32 " does not exist in Draco data\n", id);
return false;
}
-
+
size_t stride = getAttributeStride(componentType, dataType);
-
+
std::vector<uint8_t> decodedData;
decodedData.resize(stride * decoder->vertexCount);
-
+
for (uint32_t i = 0; i < decoder->vertexCount; ++i)
{
auto index = attribute->mapped_index(draco::PointIndex(i));
uint8_t *value = decodedData.data() + i * stride;
-
+
bool converted = false;
-
+
switch (componentType)
{
case ComponentType::Byte:
@@ -139,7 +139,7 @@ bool decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, c
return false;
}
}
-
+
decoder->buffers[id] = decodedData;
return true;
}
@@ -166,13 +166,13 @@ void decoderCopyAttribute(Decoder *decoder, size_t id, void *output)
}
}
-template<class T>
+template <class T>
void decodeIndices(Decoder *decoder)
{
std::vector<uint8_t> decodedIndices;
decodedIndices.resize(decoder->indexCount * sizeof(T));
T *typedView = reinterpret_cast<T *>(decodedIndices.data());
-
+
for (uint32_t faceIndex = 0; faceIndex < decoder->mesh->num_faces(); ++faceIndex)
{
const draco::Mesh::Face &face = decoder->mesh->face(draco::FaceIndex(faceIndex));
@@ -180,7 +180,7 @@ void decodeIndices(Decoder *decoder)
typedView[faceIndex * 3 + 1] = face[1].value();
typedView[faceIndex * 3 + 2] = face[2].value();
}
-
+
decoder->indexBuffer = decodedIndices;
}
@@ -188,26 +188,26 @@ bool decoderReadIndices(Decoder *decoder, size_t indexComponentType)
{
switch (indexComponentType)
{
- case ComponentType::Byte:
- decodeIndices<int8_t>(decoder);
- break;
- case ComponentType::UnsignedByte:
- decodeIndices<uint8_t>(decoder);
- break;
- case ComponentType::Short:
- decodeIndices<int16_t>(decoder);
- break;
- case ComponentType::UnsignedShort:
- decodeIndices<uint16_t>(decoder);
- break;
- case ComponentType::UnsignedInt:
- decodeIndices<uint32_t>(decoder);
- break;
- default:
- printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType);
- return false;
+ case ComponentType::Byte:
+ decodeIndices<int8_t>(decoder);
+ break;
+ case ComponentType::UnsignedByte:
+ decodeIndices<uint8_t>(decoder);
+ break;
+ case ComponentType::Short:
+ decodeIndices<int16_t>(decoder);
+ break;
+ case ComponentType::UnsignedShort:
+ decodeIndices<uint16_t>(decoder);
+ break;
+ case ComponentType::UnsignedInt:
+ decodeIndices<uint32_t>(decoder);
+ break;
+ default:
+ printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType);
+ return false;
}
-
+
return true;
}
diff --git a/extern/draco/src/decoder.h b/extern/draco/src/decoder.h
index 914eb776e8f..c154b426c59 100644
--- a/extern/draco/src/decoder.h
+++ b/extern/draco/src/decoder.h
@@ -28,26 +28,38 @@
struct Decoder;
-API(Decoder *) decoderCreate();
+API(Decoder *)
+decoderCreate();
-API(void) decoderRelease(Decoder *decoder);
+API(void)
+decoderRelease(Decoder *decoder);
-API(bool) decoderDecode(Decoder *decoder, void *data, size_t byteLength);
+API(bool)
+decoderDecode(Decoder *decoder, void *data, size_t byteLength);
-API(uint32_t) decoderGetVertexCount(Decoder *decoder);
+API(uint32_t)
+decoderGetVertexCount(Decoder *decoder);
-API(uint32_t) decoderGetIndexCount(Decoder *decoder);
+API(uint32_t)
+decoderGetIndexCount(Decoder *decoder);
-API(bool) decoderAttributeIsNormalized(Decoder *decoder, uint32_t id);
+API(bool)
+decoderAttributeIsNormalized(Decoder *decoder, uint32_t id);
-API(bool) decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType);
+API(bool)
+decoderReadAttribute(Decoder *decoder, uint32_t id, size_t componentType, char *dataType);
-API(size_t) decoderGetAttributeByteLength(Decoder *decoder, size_t id);
+API(size_t)
+decoderGetAttributeByteLength(Decoder *decoder, size_t id);
-API(void) decoderCopyAttribute(Decoder *decoder, size_t id, void *output);
+API(void)
+decoderCopyAttribute(Decoder *decoder, size_t id, void *output);
-API(bool) decoderReadIndices(Decoder *decoder, size_t indexComponentType);
+API(bool)
+decoderReadIndices(Decoder *decoder, size_t indexComponentType);
-API(size_t) decoderGetIndicesByteLength(Decoder *decoder);
+API(size_t)
+decoderGetIndicesByteLength(Decoder *decoder);
-API(void) decoderCopyIndices(Decoder *decoder, void *output);
+API(void)
+decoderCopyIndices(Decoder *decoder, void *output);
diff --git a/extern/draco/src/encoder.cpp b/extern/draco/src/encoder.cpp
index ff7570ecfcd..34282ced8c6 100644
--- a/extern/draco/src/encoder.cpp
+++ b/extern/draco/src/encoder.cpp
@@ -59,7 +59,8 @@ void encoderRelease(Encoder *encoder)
delete encoder;
}
-void encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel) {
+void encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel)
+{
encoder->compressionLevel = compressionLevel;
}
@@ -75,7 +76,7 @@ void encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t no
bool encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder)
{
printf(LOG_PREFIX "Preserve triangle order: %s\n", preserveTriangleOrder ? "yes" : "no");
-
+
draco::Encoder dracoEncoder;
int speed = 10 - static_cast<int>(encoder->compressionLevel);
@@ -87,12 +88,12 @@ bool encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder)
dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::COLOR, encoder->quantization.color);
dracoEncoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, encoder->quantization.generic);
dracoEncoder.SetTrackEncodedProperties(true);
-
+
if (preserveTriangleOrder)
{
dracoEncoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING);
}
-
+
auto encoderStatus = dracoEncoder.EncodeMeshToBuffer(encoder->mesh, &encoder->encoderBuffer);
if (encoderStatus.ok())
{
@@ -130,20 +131,19 @@ void encoderCopy(Encoder *encoder, uint8_t *data)
memcpy(data, encoder->encoderBuffer.data(), encoder->encoderBuffer.size());
}
-template<class T>
+template <class T>
void encodeIndices(Encoder *encoder, uint32_t indexCount, T *indices)
{
int face_count = indexCount / 3;
encoder->mesh.SetNumFaces(static_cast<size_t>(face_count));
encoder->rawSize += indexCount * sizeof(T);
-
+
for (int i = 0; i < face_count; ++i)
{
draco::Mesh::Face face = {
draco::PointIndex(indices[3 * i + 0]),
draco::PointIndex(indices[3 * i + 1]),
- draco::PointIndex(indices[3 * i + 2])
- };
+ draco::PointIndex(indices[3 * i + 2])};
encoder->mesh.SetFace(draco::FaceIndex(static_cast<uint32_t>(i)), face);
}
}
@@ -152,23 +152,23 @@ void encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t ind
{
switch (indexComponentType)
{
- case ComponentType::Byte:
- encodeIndices(encoder, indexCount, reinterpret_cast<int8_t *>(indices));
- break;
- case ComponentType::UnsignedByte:
- encodeIndices(encoder, indexCount, reinterpret_cast<uint8_t *>(indices));
- break;
- case ComponentType::Short:
- encodeIndices(encoder, indexCount, reinterpret_cast<int16_t *>(indices));
- break;
- case ComponentType::UnsignedShort:
- encodeIndices(encoder, indexCount, reinterpret_cast<uint16_t *>(indices));
- break;
- case ComponentType::UnsignedInt:
- encodeIndices(encoder, indexCount, reinterpret_cast<uint32_t *>(indices));
- break;
- default:
- printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType);
+ case ComponentType::Byte:
+ encodeIndices(encoder, indexCount, reinterpret_cast<int8_t *>(indices));
+ break;
+ case ComponentType::UnsignedByte:
+ encodeIndices(encoder, indexCount, reinterpret_cast<uint8_t *>(indices));
+ break;
+ case ComponentType::Short:
+ encodeIndices(encoder, indexCount, reinterpret_cast<int16_t *>(indices));
+ break;
+ case ComponentType::UnsignedShort:
+ encodeIndices(encoder, indexCount, reinterpret_cast<uint16_t *>(indices));
+ break;
+ case ComponentType::UnsignedInt:
+ encodeIndices(encoder, indexCount, reinterpret_cast<uint32_t *>(indices));
+ break;
+ default:
+ printf(LOG_PREFIX "Index component type %zu not supported\n", indexComponentType);
}
}
@@ -190,7 +190,7 @@ draco::GeometryAttribute::Type getAttributeSemantics(char *attribute)
{
return draco::GeometryAttribute::COLOR;
}
-
+
return draco::GeometryAttribute::GENERIC;
}
@@ -198,37 +198,38 @@ draco::DataType getDataType(size_t componentType)
{
switch (componentType)
{
- case ComponentType::Byte:
- return draco::DataType::DT_INT8;
-
- case ComponentType::UnsignedByte:
- return draco::DataType::DT_UINT8;
-
- case ComponentType::Short:
- return draco::DataType::DT_INT16;
-
- case ComponentType::UnsignedShort:
- return draco::DataType::DT_UINT16;
-
- case ComponentType::UnsignedInt:
- return draco::DataType::DT_UINT32;
-
- case ComponentType::Float:
- return draco::DataType::DT_FLOAT32;
-
- default:
- return draco::DataType::DT_INVALID;
+ case ComponentType::Byte:
+ return draco::DataType::DT_INT8;
+
+ case ComponentType::UnsignedByte:
+ return draco::DataType::DT_UINT8;
+
+ case ComponentType::Short:
+ return draco::DataType::DT_INT16;
+
+ case ComponentType::UnsignedShort:
+ return draco::DataType::DT_UINT16;
+
+ case ComponentType::UnsignedInt:
+ return draco::DataType::DT_UINT32;
+
+ case ComponentType::Float:
+ return draco::DataType::DT_FLOAT32;
+
+ default:
+ return draco::DataType::DT_INVALID;
}
}
-API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data)
+API(uint32_t)
+encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data)
{
auto buffer = std::make_unique<draco::DataBuffer>();
uint32_t count = encoder->mesh.num_points();
size_t componentCount = getNumberOfComponents(dataType);
size_t stride = getAttributeStride(componentType, dataType);
draco::DataType dracoDataType = getDataType(componentType);
-
+
draco::GeometryAttribute::Type semantics = getAttributeSemantics(attributeName);
draco::GeometryAttribute attribute;
attribute.Init(semantics, &*buffer, componentCount, getDataType(componentType), false, stride, 0);
diff --git a/extern/draco/src/encoder.h b/extern/draco/src/encoder.h
index 2f7f21a469b..c6fdc30295b 100644
--- a/extern/draco/src/encoder.h
+++ b/extern/draco/src/encoder.h
@@ -28,24 +28,35 @@
struct Encoder;
-API(Encoder *) encoderCreate(uint32_t vertexCount);
+API(Encoder *)
+encoderCreate(uint32_t vertexCount);
-API(void) encoderRelease(Encoder *encoder);
+API(void)
+encoderRelease(Encoder *encoder);
-API(void) encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel);
+API(void)
+encoderSetCompressionLevel(Encoder *encoder, uint32_t compressionLevel);
-API(void) encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic);
+API(void)
+encoderSetQuantizationBits(Encoder *encoder, uint32_t position, uint32_t normal, uint32_t uv, uint32_t color, uint32_t generic);
-API(bool) encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder);
+API(bool)
+encoderEncode(Encoder *encoder, uint8_t preserveTriangleOrder);
-API(uint64_t) encoderGetByteLength(Encoder *encoder);
+API(uint64_t)
+encoderGetByteLength(Encoder *encoder);
-API(void) encoderCopy(Encoder *encoder, uint8_t *data);
+API(void)
+encoderCopy(Encoder *encoder, uint8_t *data);
-API(void) encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices);
+API(void)
+encoderSetIndices(Encoder *encoder, size_t indexComponentType, uint32_t indexCount, void *indices);
-API(uint32_t) encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data);
+API(uint32_t)
+encoderSetAttribute(Encoder *encoder, char *attributeName, size_t componentType, char *dataType, void *data);
-API(uint32_t) encoderGetEncodedVertexCount(Encoder *encoder);
+API(uint32_t)
+encoderGetEncodedVertexCount(Encoder *encoder);
-API(uint32_t) encoderGetEncodedIndexCount(Encoder *encoder);
+API(uint32_t)
+encoderGetEncodedIndexCount(Encoder *encoder);