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>2019-12-05 21:11:53 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-12-05 21:12:10 +0300
commit9febff7e14c564fc560f48626817350a1bf8086f (patch)
tree36ea267182f0b243bd412ff5a2379ef6ee56ca8b /extern
parent05ef758f46ae30b6d3a9e35fa8a2558d1216bee9 (diff)
glTF: upgrade Draco to version 1.3.5 and add mesh skinning support
This will fix exporting meshes with armatures using Draco compression, like: https://github.com/KhronosGroup/glTF-Blender-IO/issues/617 Differential Revision: https://developer.blender.org/D6342
Diffstat (limited to 'extern')
-rw-r--r--extern/draco/CMakeLists.txt2
-rw-r--r--extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.cc5
-rw-r--r--extern/draco/dracoenc/src/draco/attributes/geometry_indices.h6
-rw-r--r--extern/draco/dracoenc/src/draco/attributes/point_attribute.cc2
-rw-r--r--extern/draco/dracoenc/src/draco/attributes/point_attribute.h4
-rw-r--r--extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h9
-rw-r--r--extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h17
-rw-r--r--extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc4
-rw-r--r--extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc6
-rw-r--r--extern/draco/dracoenc/src/draco/compression/decode.cc14
-rw-r--r--extern/draco/dracoenc/src/draco/compression/decode.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/encode_base.h19
-rw-r--r--extern/draco/dracoenc/src/draco/compression/entropy/ans.h189
-rw-r--r--extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_coding.h4
-rw-r--r--extern/draco/dracoenc/src/draco/compression/expert_encode.cc10
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc6
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc16
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.cc7
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.h4
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc4
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.cc6
-rw-r--r--extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h5
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h8
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc12
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc13
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc4
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h2
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc4
-rw-r--r--extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h2
-rw-r--r--extern/draco/dracoenc/src/draco/core/data_buffer.cc1
-rw-r--r--extern/draco/dracoenc/src/draco/core/draco_test_utils.cc2
-rw-r--r--extern/draco/dracoenc/src/draco/core/draco_test_utils.h5
-rw-r--r--extern/draco/dracoenc/src/draco/core/draco_types.cc17
-rw-r--r--extern/draco/dracoenc/src/draco/core/draco_types.h5
-rw-r--r--extern/draco/dracoenc/src/draco/core/draco_version.h2
-rw-r--r--extern/draco/dracoenc/src/draco/core/macros.h17
-rw-r--r--extern/draco/dracoenc/src/draco/core/math_utils.h2
-rw-r--r--extern/draco/dracoenc/src/draco/core/math_utils_test.cc3
-rw-r--r--extern/draco/dracoenc/src/draco/core/options.cc6
-rw-r--r--extern/draco/dracoenc/src/draco/core/options.h5
-rw-r--r--extern/draco/dracoenc/src/draco/core/status.h2
-rw-r--r--extern/draco/dracoenc/src/draco/core/status_or.h81
-rw-r--r--extern/draco/dracoenc/src/draco/core/status_test.cc4
-rw-r--r--extern/draco/dracoenc/src/draco/core/vector_d.h173
-rw-r--r--extern/draco/dracoenc/src/draco/core/vector_d_test.cc72
-rw-r--r--extern/draco/dracoenc/src/draco/io/mesh_io.cc33
-rw-r--r--extern/draco/dracoenc/src/draco/io/mesh_io.h8
-rw-r--r--extern/draco/dracoenc/src/draco/io/obj_decoder.cc48
-rw-r--r--extern/draco/dracoenc/src/draco/io/obj_encoder.h2
-rw-r--r--extern/draco/dracoenc/src/draco/io/parser_utils.cc2
-rw-r--r--extern/draco/dracoenc/src/draco/io/ply_decoder.cc76
-rw-r--r--extern/draco/dracoenc/src/draco/io/ply_decoder.h18
-rw-r--r--extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc5
-rw-r--r--extern/draco/dracoenc/src/draco/io/ply_reader.cc60
-rw-r--r--extern/draco/dracoenc/src/draco/io/ply_reader.h11
-rw-r--r--extern/draco/dracoenc/src/draco/io/ply_reader_test.cc15
-rw-r--r--extern/draco/dracoenc/src/draco/io/point_cloud_io.cc7
-rw-r--r--extern/draco/dracoenc/src/draco/mesh/corner_table.cc107
-rw-r--r--extern/draco/dracoenc/src/draco/mesh/corner_table.h9
-rw-r--r--extern/draco/dracoenc/src/draco/mesh/mesh.cc2
-rw-r--r--extern/draco/dracoenc/src/draco/mesh/mesh.h6
-rw-r--r--extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.h19
-rw-r--r--extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.cc4
-rw-r--r--extern/draco/dracoenc/src/draco/metadata/metadata.h28
-rw-r--r--extern/draco/dracoenc/src/draco/metadata/metadata_encoder.cc7
-rw-r--r--extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc6
-rw-r--r--extern/draco/dracoenc/src/draco/point_cloud/point_cloud.cc31
-rw-r--r--extern/draco/dracoenc/src/draco/point_cloud/point_cloud.h15
-rw-r--r--extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.cc6
-rw-r--r--extern/draco/dracoenc/src/draco/tools/draco_decoder.cc6
-rw-r--r--extern/draco/dracoenc/src/draco/tools/draco_encoder.cc2
-rw-r--r--extern/draco/src/draco-compressor.cpp362
-rw-r--r--extern/draco/src/draco-compressor.h173
81 files changed, 1208 insertions, 659 deletions
diff --git a/extern/draco/CMakeLists.txt b/extern/draco/CMakeLists.txt
index c51af24c9a4..1355766960a 100644
--- a/extern/draco/CMakeLists.txt
+++ b/extern/draco/CMakeLists.txt
@@ -24,6 +24,6 @@ set(CMAKE_CXX_STANDARD 14)
add_subdirectory(dracoenc)
# Build blender-draco-exporter module.
-add_library(extern_draco SHARED src/draco-compressor.cpp)
+add_library(extern_draco SHARED src/draco-compressor.cpp src/draco-compressor.h)
target_include_directories(extern_draco PUBLIC dracoenc/src)
target_link_libraries(extern_draco PUBLIC dracoenc)
diff --git a/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.cc b/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.cc
index 41193f1452f..237becefc61 100644
--- a/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.cc
+++ b/extern/draco/dracoenc/src/draco/attributes/attribute_quantization_transform.cc
@@ -92,6 +92,11 @@ bool AttributeQuantizationTransform::ComputeParameters(
range_ = dif;
}
+ // In case all values are the same, initialize the range to unit length. This
+ // will ensure that all values are quantized properly to the same value.
+ if (range_ == 0.f)
+ range_ = 1.f;
+
return true;
}
diff --git a/extern/draco/dracoenc/src/draco/attributes/geometry_indices.h b/extern/draco/dracoenc/src/draco/attributes/geometry_indices.h
index 5244056f0aa..80e43e30a13 100644
--- a/extern/draco/dracoenc/src/draco/attributes/geometry_indices.h
+++ b/extern/draco/dracoenc/src/draco/attributes/geometry_indices.h
@@ -28,11 +28,11 @@ DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, AttributeValueIndex)
// Index of a point in a PointCloud.
DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, PointIndex)
// Vertex index in a Mesh or CornerTable.
-DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, VertexIndex);
+DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, VertexIndex)
// Corner index that identifies a corner in a Mesh or CornerTable.
-DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, CornerIndex);
+DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, CornerIndex)
// Face index for Mesh and CornerTable.
-DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, FaceIndex);
+DEFINE_NEW_DRACO_INDEX_TYPE(uint32_t, FaceIndex)
// Constants denoting invalid indices.
static constexpr AttributeValueIndex kInvalidAttributeValueIndex(
diff --git a/extern/draco/dracoenc/src/draco/attributes/point_attribute.cc b/extern/draco/dracoenc/src/draco/attributes/point_attribute.cc
index 4428f332b93..0c4e8e1c738 100644
--- a/extern/draco/dracoenc/src/draco/attributes/point_attribute.cc
+++ b/extern/draco/dracoenc/src/draco/attributes/point_attribute.cc
@@ -64,7 +64,7 @@ bool PointAttribute::Reset(size_t num_attribute_values) {
return true;
}
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
AttributeValueIndex::ValueType PointAttribute::DeduplicateValues(
const GeometryAttribute &in_att) {
return DeduplicateValues(in_att, AttributeValueIndex(0));
diff --git a/extern/draco/dracoenc/src/draco/attributes/point_attribute.h b/extern/draco/dracoenc/src/draco/attributes/point_attribute.h
index dffde50356d..46e58a40aa1 100644
--- a/extern/draco/dracoenc/src/draco/attributes/point_attribute.h
+++ b/extern/draco/dracoenc/src/draco/attributes/point_attribute.h
@@ -105,7 +105,7 @@ class PointAttribute : public GeometryAttribute {
return GetValue(mapped_index(point_index), out_data);
}
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
// Deduplicate |in_att| values into |this| attribute. |in_att| can be equal
// to |this|.
// Returns -1 if the deduplication failed.
@@ -130,7 +130,7 @@ class PointAttribute : public GeometryAttribute {
}
private:
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
template <typename T>
AttributeValueIndex::ValueType DeduplicateTypedValues(
const GeometryAttribute &in_att, AttributeValueIndex in_att_offset);
diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector.h b/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector.h
index 4148770fe77..ce99c8014d7 100644
--- a/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector.h
+++ b/extern/draco/dracoenc/src/draco/compression/attributes/point_d_vector.h
@@ -42,7 +42,7 @@ class PseudoPointD {
// Specifically copies referenced memory
void swap(PseudoPointD &other) noexcept {
- for (auto dim = 0; dim < dimension_; dim += 1)
+ for (internal_t dim = 0; dim < dimension_; dim += 1)
std::swap(mem_[dim], other.mem_[dim]);
}
diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h
index 3a00bda943c..db835554385 100644
--- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h
+++ b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_decoder_factory.h
@@ -21,7 +21,9 @@
#include "draco/draco_features.h"
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_decoder.h"
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_decoder.h"
+#endif
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_decoder.h"
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_decoder.h"
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_decoder.h"
@@ -82,16 +84,20 @@ struct MeshPredictionSchemeDecoderFactory {
new MeshPredictionSchemeTexCoordsPortableDecoder<
DataTypeT, TransformT, MeshDataT>(attribute, transform,
mesh_data));
- } else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
+ }
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
+ else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeGeometricNormalDecoder<
DataTypeT, TransformT, MeshDataT>(attribute, transform,
mesh_data));
}
+#endif
return nullptr;
}
};
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
// Operator () specialized for normal octahedron transforms. These transforms
// are currently used only by the geometric normal prediction scheme (the
// transform is also used by delta coding, but delta predictor is not
@@ -128,6 +134,7 @@ struct MeshPredictionSchemeDecoderFactory {
return nullptr;
}
};
+#endif
template <class TransformT, class MeshDataT>
std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>> operator()(
diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc
index 3144bdb9a6b..6b74e571c6d 100644
--- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc
+++ b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.cc
@@ -32,10 +32,12 @@ PredictionSchemeMethod SelectPredictionMethod(
}
}
if (att->attribute_type() == GeometryAttribute::NORMAL) {
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
if (encoder->options()->GetSpeed() < 4) {
// Use geometric normal prediction for speeds 0, 1, 2, 3.
return MESH_PREDICTION_GEOMETRIC_NORMAL;
}
+#endif
return PREDICTION_DIFFERENCE; // default
}
// Handle other attribute types.
diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h
index cde5ba2435f..4cc40010773 100644
--- a/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h
+++ b/extern/draco/dracoenc/src/draco/compression/attributes/prediction_schemes/prediction_scheme_encoder_factory.h
@@ -19,7 +19,9 @@
#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_ENCODER_FACTORY_H_
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_constrained_multi_parallelogram_encoder.h"
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_geometric_normal_encoder.h"
+#endif
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_multi_parallelogram_encoder.h"
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_parallelogram_encoder.h"
#include "draco/compression/attributes/prediction_schemes/mesh_prediction_scheme_tex_coords_encoder.h"
@@ -49,32 +51,25 @@ struct MeshPredictionSchemeEncoderFactory {
new MeshPredictionSchemeParallelogramEncoder<DataTypeT, TransformT,
MeshDataT>(
attribute, transform, mesh_data));
- } else if (method == MESH_PREDICTION_MULTI_PARALLELOGRAM) {
- return std::unique_ptr<PredictionSchemeEncoder<DataTypeT, TransformT>>(
- new MeshPredictionSchemeMultiParallelogramEncoder<
- DataTypeT, TransformT, MeshDataT>(attribute, transform,
- mesh_data));
} else if (method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM) {
return std::unique_ptr<PredictionSchemeEncoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeConstrainedMultiParallelogramEncoder<
DataTypeT, TransformT, MeshDataT>(attribute, transform,
mesh_data));
- } else if (method == MESH_PREDICTION_TEX_COORDS_DEPRECATED) {
- return std::unique_ptr<PredictionSchemeEncoder<DataTypeT, TransformT>>(
- new MeshPredictionSchemeTexCoordsEncoder<DataTypeT, TransformT,
- MeshDataT>(
- attribute, transform, mesh_data));
} else if (method == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
return std::unique_ptr<PredictionSchemeEncoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeTexCoordsPortableEncoder<
DataTypeT, TransformT, MeshDataT>(attribute, transform,
mesh_data));
- } else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
+ }
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
+ else if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
return std::unique_ptr<PredictionSchemeEncoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeGeometricNormalEncoder<DataTypeT, TransformT,
MeshDataT>(
attribute, transform, mesh_data));
}
+#endif
return nullptr;
}
};
diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc b/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc
index fcd295039f6..2676eb7905c 100644
--- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc
+++ b/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_decoders_controller.cc
@@ -13,7 +13,9 @@
// limitations under the License.
//
#include "draco/compression/attributes/sequential_attribute_decoders_controller.h"
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
#include "draco/compression/attributes/sequential_normal_attribute_decoder.h"
+#endif
#include "draco/compression/attributes/sequential_quantization_attribute_decoder.h"
#include "draco/compression/config/compression_shared.h"
@@ -123,9 +125,11 @@ SequentialAttributeDecodersController::CreateSequentialDecoder(
case SEQUENTIAL_ATTRIBUTE_ENCODER_QUANTIZATION:
return std::unique_ptr<SequentialAttributeDecoder>(
new SequentialQuantizationAttributeDecoder());
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
case SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS:
return std::unique_ptr<SequentialNormalAttributeDecoder>(
new SequentialNormalAttributeDecoder());
+#endif
default:
break;
}
diff --git a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc b/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc
index 467508b226f..b40cef842ae 100644
--- a/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc
+++ b/extern/draco/dracoenc/src/draco/compression/attributes/sequential_attribute_encoders_controller.cc
@@ -13,7 +13,9 @@
// limitations under the License.
//
#include "draco/compression/attributes/sequential_attribute_encoders_controller.h"
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
#include "draco/compression/attributes/sequential_normal_attribute_encoder.h"
+#endif
#include "draco/compression/attributes/sequential_quantization_attribute_encoder.h"
#include "draco/compression/point_cloud/point_cloud_encoder.h"
@@ -121,15 +123,19 @@ SequentialAttributeEncodersController::CreateSequentialEncoder(int i) {
case DT_FLOAT32:
if (encoder()->options()->GetAttributeInt(att_id, "quantization_bits",
-1) > 0) {
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
if (att->attribute_type() == GeometryAttribute::NORMAL) {
// We currently only support normals with float coordinates
// and must be quantized.
return std::unique_ptr<SequentialAttributeEncoder>(
new SequentialNormalAttributeEncoder());
} else {
+#endif
return std::unique_ptr<SequentialAttributeEncoder>(
new SequentialQuantizationAttributeEncoder());
+#ifdef DRACO_NORMAL_ENCODING_SUPPORTED
}
+#endif
}
break;
default:
diff --git a/extern/draco/dracoenc/src/draco/compression/decode.cc b/extern/draco/dracoenc/src/draco/compression/decode.cc
index a9ac2d5025f..ab70ef1ec60 100644
--- a/extern/draco/dracoenc/src/draco/compression/decode.cc
+++ b/extern/draco/dracoenc/src/draco/compression/decode.cc
@@ -37,7 +37,7 @@ StatusOr<std::unique_ptr<PointCloudDecoder>> CreatePointCloudDecoder(
} else if (method == POINT_CLOUD_KD_TREE_ENCODING) {
return std::unique_ptr<PointCloudDecoder>(new PointCloudKdTreeDecoder());
}
- return Status(Status::ERROR, "Unsupported encoding method.");
+ return Status(Status::DRACO_ERROR, "Unsupported encoding method.");
}
#endif
@@ -48,7 +48,7 @@ StatusOr<std::unique_ptr<MeshDecoder>> CreateMeshDecoder(uint8_t method) {
} else if (method == MESH_EDGEBREAKER_ENCODING) {
return std::unique_ptr<MeshDecoder>(new MeshEdgebreakerDecoder());
}
- return Status(Status::ERROR, "Unsupported encoding method.");
+ return Status(Status::DRACO_ERROR, "Unsupported encoding method.");
}
#endif
@@ -77,7 +77,7 @@ StatusOr<std::unique_ptr<PointCloud>> Decoder::DecodePointCloudFromBuffer(
return static_cast<std::unique_ptr<PointCloud>>(std::move(mesh));
#endif
}
- return Status(Status::ERROR, "Unsupported geometry type.");
+ return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
}
StatusOr<std::unique_ptr<Mesh>> Decoder::DecodeMeshFromBuffer(
@@ -94,7 +94,7 @@ Status Decoder::DecodeBufferToGeometry(DecoderBuffer *in_buffer,
DracoHeader header;
DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header))
if (header.encoder_type != POINT_CLOUD) {
- return Status(Status::ERROR, "Input is not a point cloud.");
+ return Status(Status::DRACO_ERROR, "Input is not a point cloud.");
}
DRACO_ASSIGN_OR_RETURN(std::unique_ptr<PointCloudDecoder> decoder,
CreatePointCloudDecoder(header.encoder_method))
@@ -102,7 +102,7 @@ Status Decoder::DecodeBufferToGeometry(DecoderBuffer *in_buffer,
DRACO_RETURN_IF_ERROR(decoder->Decode(options_, in_buffer, out_geometry))
return OkStatus();
#else
- return Status(Status::ERROR, "Unsupported geometry type.");
+ return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
#endif
}
@@ -113,7 +113,7 @@ Status Decoder::DecodeBufferToGeometry(DecoderBuffer *in_buffer,
DracoHeader header;
DRACO_RETURN_IF_ERROR(PointCloudDecoder::DecodeHeader(&temp_buffer, &header))
if (header.encoder_type != TRIANGULAR_MESH) {
- return Status(Status::ERROR, "Input is not a mesh.");
+ return Status(Status::DRACO_ERROR, "Input is not a mesh.");
}
DRACO_ASSIGN_OR_RETURN(std::unique_ptr<MeshDecoder> decoder,
CreateMeshDecoder(header.encoder_method))
@@ -121,7 +121,7 @@ Status Decoder::DecodeBufferToGeometry(DecoderBuffer *in_buffer,
DRACO_RETURN_IF_ERROR(decoder->Decode(options_, in_buffer, out_geometry))
return OkStatus();
#else
- return Status(Status::ERROR, "Unsupported geometry type.");
+ return Status(Status::DRACO_ERROR, "Unsupported geometry type.");
#endif
}
diff --git a/extern/draco/dracoenc/src/draco/compression/decode.h b/extern/draco/dracoenc/src/draco/compression/decode.h
index 9e24ce8d5d6..0216d72586a 100644
--- a/extern/draco/dracoenc/src/draco/compression/decode.h
+++ b/extern/draco/dracoenc/src/draco/compression/decode.h
@@ -20,7 +20,7 @@
#include "draco/compression/config/compression_shared.h"
#include "draco/compression/config/decoder_options.h"
#include "draco/core/decoder_buffer.h"
-#include "draco/core/statusor.h"
+#include "draco/core/status_or.h"
#include "draco/mesh/mesh.h"
namespace draco {
diff --git a/extern/draco/dracoenc/src/draco/compression/encode_base.h b/extern/draco/dracoenc/src/draco/compression/encode_base.h
index fa263f8fa3d..451d970eb6f 100644
--- a/extern/draco/dracoenc/src/draco/compression/encode_base.h
+++ b/extern/draco/dracoenc/src/draco/compression/encode_base.h
@@ -68,23 +68,28 @@ class EncoderBase {
Status CheckPredictionScheme(GeometryAttribute::Type att_type,
int prediction_scheme) const {
// Out of bound checks:
- if (prediction_scheme < 0)
- return Status(Status::ERROR, "Invalid prediction scheme requested.");
+ if (prediction_scheme < PREDICTION_NONE)
+ return Status(Status::DRACO_ERROR,
+ "Invalid prediction scheme requested.");
if (prediction_scheme >= NUM_PREDICTION_SCHEMES)
- return Status(Status::ERROR, "Invalid prediction scheme requested.");
+ return Status(Status::DRACO_ERROR,
+ "Invalid prediction scheme requested.");
// Deprecated prediction schemes:
if (prediction_scheme == MESH_PREDICTION_TEX_COORDS_DEPRECATED)
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"MESH_PREDICTION_TEX_COORDS_DEPRECATED is deprecated.");
+ if (prediction_scheme == MESH_PREDICTION_MULTI_PARALLELOGRAM)
+ return Status(Status::DRACO_ERROR,
+ "MESH_PREDICTION_MULTI_PARALLELOGRAM is deprecated.");
// Attribute specific checks:
if (prediction_scheme == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
if (att_type != GeometryAttribute::TEX_COORD)
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Invalid prediction scheme for attribute type.");
}
if (prediction_scheme == MESH_PREDICTION_GEOMETRIC_NORMAL) {
if (att_type != GeometryAttribute::NORMAL) {
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Invalid prediction scheme for attribute type.");
}
}
@@ -92,7 +97,7 @@ class EncoderBase {
if (att_type == GeometryAttribute::NORMAL) {
if (!(prediction_scheme == PREDICTION_DIFFERENCE ||
prediction_scheme == MESH_PREDICTION_GEOMETRIC_NORMAL)) {
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Invalid prediction scheme for attribute type.");
}
}
diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/ans.h b/extern/draco/dracoenc/src/draco/compression/entropy/ans.h
index 40b08ed33c6..310ae256667 100644
--- a/extern/draco/dracoenc/src/draco/compression/entropy/ans.h
+++ b/extern/draco/dracoenc/src/draco/compression/entropy/ans.h
@@ -20,29 +20,29 @@
#include <vector>
-#define ANS_DIVIDE_BY_MULTIPLY 1
-#if ANS_DIVIDE_BY_MULTIPLY
+#define DRACO_ANS_DIVIDE_BY_MULTIPLY 1
+#if DRACO_ANS_DIVIDE_BY_MULTIPLY
#include "draco/core/divide.h"
#endif
#include "draco/core/macros.h"
namespace draco {
-#if ANS_DIVIDE_BY_MULTIPLY
+#if DRACO_ANS_DIVIDE_BY_MULTIPLY
-#define ANS_DIVREM(quotient, remainder, dividend, divisor) \
- do { \
- quotient = fastdiv(dividend, divisor); \
- remainder = dividend - quotient * divisor; \
+#define DRACO_ANS_DIVREM(quotient, remainder, dividend, divisor) \
+ do { \
+ quotient = fastdiv(dividend, divisor); \
+ remainder = dividend - quotient * divisor; \
} while (0)
-#define ANS_DIV(dividend, divisor) fastdiv(dividend, divisor)
+#define DRACO_ANS_DIV(dividend, divisor) fastdiv(dividend, divisor)
#else
-#define ANS_DIVREM(quotient, remainder, dividend, divisor) \
- do { \
- quotient = dividend / divisor; \
- remainder = dividend % divisor; \
+#define DRACO_ANS_DIVREM(quotient, remainder, dividend, divisor) \
+ do { \
+ quotient = dividend / divisor; \
+ remainder = dividend % divisor; \
} while (0)
-#define ANS_DIV(dividend, divisor) ((dividend) / (divisor))
+#define DRACO_ANS_DIV(dividend, divisor) ((dividend) / (divisor))
#endif
struct AnsCoder {
@@ -60,13 +60,9 @@ struct AnsDecoder {
};
typedef uint8_t AnsP8;
-#define ans_p8_precision 256u
-#define ans_p8_shift 8
-#define ans_p10_precision 1024u
-
-#define l_base (ans_p10_precision * 4) // l_base % precision must be 0
-#define io_base 256
-// Range I = { l_base, l_base + 1, ..., l_base * io_base - 1 }
+#define DRACO_ANS_P8_PRECISION 256u
+#define DRACO_ANS_L_BASE (4096u)
+#define DRACO_ANS_IO_BASE 256
static uint32_t mem_get_le16(const void *vmem) {
uint32_t val;
@@ -126,14 +122,14 @@ static inline void ans_write_init(struct AnsCoder *const ans,
uint8_t *const buf) {
ans->buf = buf;
ans->buf_offset = 0;
- ans->state = l_base;
+ ans->state = DRACO_ANS_L_BASE;
}
static inline int ans_write_end(struct AnsCoder *const ans) {
uint32_t state;
- DRACO_DCHECK_GE(ans->state, l_base);
- DRACO_DCHECK_LT(ans->state, l_base * io_base);
- state = ans->state - l_base;
+ DRACO_DCHECK_GE(ans->state, DRACO_ANS_L_BASE);
+ DRACO_DCHECK_LT(ans->state, DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE);
+ state = ans->state - DRACO_ANS_L_BASE;
if (state < (1 << 6)) {
ans->buf[ans->buf_offset] = (0x00 << 6) + state;
return ans->buf_offset + 1;
@@ -149,43 +145,44 @@ static inline int ans_write_end(struct AnsCoder *const ans) {
}
}
-// rABS with descending spread
-// p or p0 takes the place of l_s from the paper
-// ans_p8_precision is m
+// rABS with descending spread.
+// p or p0 takes the place of l_s from the paper.
+// DRACO_ANS_P8_PRECISION is m.
static inline void rabs_desc_write(struct AnsCoder *ans, int val, AnsP8 p0) {
- const AnsP8 p = ans_p8_precision - p0;
+ const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
const unsigned l_s = val ? p : p0;
unsigned quot, rem;
- if (ans->state >= l_base / ans_p8_precision * io_base * l_s) {
- ans->buf[ans->buf_offset++] = ans->state % io_base;
- ans->state /= io_base;
+ if (ans->state >=
+ DRACO_ANS_L_BASE / DRACO_ANS_P8_PRECISION * DRACO_ANS_IO_BASE * l_s) {
+ ans->buf[ans->buf_offset++] = ans->state % DRACO_ANS_IO_BASE;
+ ans->state /= DRACO_ANS_IO_BASE;
}
- ANS_DIVREM(quot, rem, ans->state, l_s);
- ans->state = quot * ans_p8_precision + rem + (val ? 0 : p);
+ DRACO_ANS_DIVREM(quot, rem, ans->state, l_s);
+ ans->state = quot * DRACO_ANS_P8_PRECISION + rem + (val ? 0 : p);
}
-#define ANS_IMPL1 0
+#define DRACO_ANS_IMPL1 0
#define UNPREDICTABLE(x) x
static inline int rabs_desc_read(struct AnsDecoder *ans, AnsP8 p0) {
int val;
-#if ANS_IMPL1
+#if DRACO_ANS_IMPL1
unsigned l_s;
#else
unsigned quot, rem, x, xn;
#endif
- const AnsP8 p = ans_p8_precision - p0;
- if (ans->state < l_base && ans->buf_offset > 0) {
- ans->state = ans->state * io_base + ans->buf[--ans->buf_offset];
+ const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
+ if (ans->state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
+ ans->state = ans->state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
}
-#if ANS_IMPL1
- val = ans->state % ans_p8_precision < p;
+#if DRACO_ANS_IMPL1
+ val = ans->state % DRACO_ANS_P8_PRECISION < p;
l_s = val ? p : p0;
- ans->state = (ans->state / ans_p8_precision) * l_s +
- ans->state % ans_p8_precision - (!val * p);
+ ans->state = (ans->state / DRACO_ANS_P8_PRECISION) * l_s +
+ ans->state % DRACO_ANS_P8_PRECISION - (!val * p);
#else
x = ans->state;
- quot = x / ans_p8_precision;
- rem = x % ans_p8_precision;
+ quot = x / DRACO_ANS_P8_PRECISION;
+ rem = x % DRACO_ANS_P8_PRECISION;
xn = quot * p;
val = rem < p;
if (UNPREDICTABLE(val)) {
@@ -198,41 +195,42 @@ static inline int rabs_desc_read(struct AnsDecoder *ans, AnsP8 p0) {
return val;
}
-// rABS with ascending spread
-// p or p0 takes the place of l_s from the paper
-// ans_p8_precision is m
+// rABS with ascending spread.
+// p or p0 takes the place of l_s from the paper.
+// DRACO_ANS_P8_PRECISION is m.
static inline void rabs_asc_write(struct AnsCoder *ans, int val, AnsP8 p0) {
- const AnsP8 p = ans_p8_precision - p0;
+ const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
const unsigned l_s = val ? p : p0;
unsigned quot, rem;
- if (ans->state >= l_base / ans_p8_precision * io_base * l_s) {
- ans->buf[ans->buf_offset++] = ans->state % io_base;
- ans->state /= io_base;
+ if (ans->state >=
+ DRACO_ANS_L_BASE / DRACO_ANS_P8_PRECISION * DRACO_ANS_IO_BASE * l_s) {
+ ans->buf[ans->buf_offset++] = ans->state % DRACO_ANS_IO_BASE;
+ ans->state /= DRACO_ANS_IO_BASE;
}
- ANS_DIVREM(quot, rem, ans->state, l_s);
- ans->state = quot * ans_p8_precision + rem + (val ? p0 : 0);
+ DRACO_ANS_DIVREM(quot, rem, ans->state, l_s);
+ ans->state = quot * DRACO_ANS_P8_PRECISION + rem + (val ? p0 : 0);
}
static inline int rabs_asc_read(struct AnsDecoder *ans, AnsP8 p0) {
int val;
-#if ANS_IMPL1
+#if DRACO_ANS_IMPL1
unsigned l_s;
#else
unsigned quot, rem, x, xn;
#endif
- const AnsP8 p = ans_p8_precision - p0;
- if (ans->state < l_base) {
- ans->state = ans->state * io_base + ans->buf[--ans->buf_offset];
+ const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
+ if (ans->state < DRACO_ANS_L_BASE) {
+ ans->state = ans->state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
}
-#if ANS_IMPL1
- val = ans->state % ans_p8_precision < p;
+#if DRACO_ANS_IMPL1
+ val = ans->state % DRACO_ANS_P8_PRECISION < p;
l_s = val ? p : p0;
- ans->state = (ans->state / ans_p8_precision) * l_s +
- ans->state % ans_p8_precision - (!val * p);
+ ans->state = (ans->state / DRACO_ANS_P8_PRECISION) * l_s +
+ ans->state % DRACO_ANS_P8_PRECISION - (!val * p);
#else
x = ans->state;
- quot = x / ans_p8_precision;
- rem = x % ans_p8_precision;
+ quot = x / DRACO_ANS_P8_PRECISION;
+ rem = x % DRACO_ANS_P8_PRECISION;
xn = quot * p;
val = rem >= p0;
if (UNPREDICTABLE(val)) {
@@ -248,32 +246,34 @@ static inline int rabs_asc_read(struct AnsDecoder *ans, AnsP8 p0) {
#define rabs_read rabs_desc_read
#define rabs_write rabs_desc_write
-// uABS with normalization
+// uABS with normalization.
static inline void uabs_write(struct AnsCoder *ans, int val, AnsP8 p0) {
- AnsP8 p = ans_p8_precision - p0;
+ AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
const unsigned l_s = val ? p : p0;
- while (ans->state >= l_base / ans_p8_precision * io_base * l_s) {
- ans->buf[ans->buf_offset++] = ans->state % io_base;
- ans->state /= io_base;
+ while (ans->state >=
+ DRACO_ANS_L_BASE / DRACO_ANS_P8_PRECISION * DRACO_ANS_IO_BASE * l_s) {
+ ans->buf[ans->buf_offset++] = ans->state % DRACO_ANS_IO_BASE;
+ ans->state /= DRACO_ANS_IO_BASE;
}
if (!val)
- ans->state = ANS_DIV(ans->state * ans_p8_precision, p0);
+ ans->state = DRACO_ANS_DIV(ans->state * DRACO_ANS_P8_PRECISION, p0);
else
- ans->state = ANS_DIV((ans->state + 1) * ans_p8_precision + p - 1, p) - 1;
+ ans->state =
+ DRACO_ANS_DIV((ans->state + 1) * DRACO_ANS_P8_PRECISION + p - 1, p) - 1;
}
static inline int uabs_read(struct AnsDecoder *ans, AnsP8 p0) {
- AnsP8 p = ans_p8_precision - p0;
+ AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
int s;
// unsigned int xp1;
unsigned xp, sp;
unsigned state = ans->state;
- while (state < l_base && ans->buf_offset > 0) {
- state = state * io_base + ans->buf[--ans->buf_offset];
+ while (state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
+ state = state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
}
sp = state * p;
- // xp1 = (sp + p) / ans_p8_precision;
- xp = sp / ans_p8_precision;
+ // xp1 = (sp + p) / DRACO_ANS_P8_PRECISION;
+ xp = sp / DRACO_ANS_P8_PRECISION;
// s = xp1 - xp;
s = (sp & 0xFF) >= p0;
if (UNPREDICTABLE(s))
@@ -286,8 +286,8 @@ static inline int uabs_read(struct AnsDecoder *ans, AnsP8 p0) {
static inline int uabs_read_bit(struct AnsDecoder *ans) {
int s;
unsigned state = ans->state;
- while (state < l_base && ans->buf_offset > 0) {
- state = state * io_base + ans->buf[--ans->buf_offset];
+ while (state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
+ state = state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
}
s = static_cast<int>(state & 1);
ans->state = state >> 1;
@@ -317,23 +317,23 @@ static inline int ans_read_init(struct AnsDecoder *const ans,
} else {
return 1;
}
- ans->state += l_base;
- if (ans->state >= l_base * io_base)
+ ans->state += DRACO_ANS_L_BASE;
+ if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE)
return 1;
return 0;
}
static inline int ans_read_end(struct AnsDecoder *const ans) {
- return ans->state == l_base;
+ return ans->state == DRACO_ANS_L_BASE;
}
static inline int ans_reader_has_error(const struct AnsDecoder *const ans) {
- return ans->state < l_base && ans->buf_offset == 0;
+ return ans->state < DRACO_ANS_L_BASE && ans->buf_offset == 0;
}
struct rans_sym {
uint32_t prob;
- uint32_t cum_prob; // not-inclusive
+ uint32_t cum_prob; // not-inclusive.
};
// Class for performing rANS encoding using a desired number of precision bits.
@@ -356,7 +356,7 @@ class RAnsEncoder {
inline int write_end() {
uint32_t state;
DRACO_DCHECK_GE(ans_.state, l_rans_base);
- DRACO_DCHECK_LT(ans_.state, l_rans_base * io_base);
+ DRACO_DCHECK_LT(ans_.state, l_rans_base * DRACO_ANS_IO_BASE);
state = ans_.state - l_rans_base;
if (state < (1 << 6)) {
ans_.buf[ans_.buf_offset] = (0x00 << 6) + state;
@@ -376,14 +376,14 @@ class RAnsEncoder {
}
}
- // rANS with normalization
- // sym->prob takes the place of l_s from the paper
- // rans_precision is m
+ // rANS with normalization.
+ // sym->prob takes the place of l_s from the paper.
+ // rans_precision is m.
inline void rans_write(const struct rans_sym *const sym) {
const uint32_t p = sym->prob;
- while (ans_.state >= l_rans_base / rans_precision * io_base * p) {
- ans_.buf[ans_.buf_offset++] = ans_.state % io_base;
- ans_.state /= io_base;
+ while (ans_.state >= l_rans_base / rans_precision * DRACO_ANS_IO_BASE * p) {
+ 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 =
@@ -399,7 +399,7 @@ class RAnsEncoder {
struct rans_dec_sym {
uint32_t val;
uint32_t prob;
- uint32_t cum_prob; // not-inclusive
+ uint32_t cum_prob; // not-inclusive.
};
// Class for performing rANS decoding using a desired number of precision bits.
@@ -439,7 +439,7 @@ class RAnsDecoder {
return 1;
}
ans_.state += l_rans_base;
- if (ans_.state >= l_rans_base * io_base)
+ if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE)
return 1;
return 0;
}
@@ -455,7 +455,7 @@ class RAnsDecoder {
unsigned quo;
struct rans_dec_sym sym;
while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
- ans_.state = ans_.state * io_base + ans_.buf[--ans_.buf_offset];
+ ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
}
// |rans_precision| is a power of two compile time constant, and the below
// division and modulo are going to be optimized by the compiler.
@@ -507,7 +507,10 @@ class RAnsDecoder {
AnsDecoder ans_;
};
-#undef ANS_DIVREM
+#undef DRACO_ANS_DIVREM
+#undef DRACO_ANS_P8_PRECISION
+#undef DRACO_ANS_L_BASE
+#undef DRACO_ANS_IO_BASE
} // namespace draco
diff --git a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_coding.h b/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_coding.h
index 8d06644a9b9..0a68e29fe26 100644
--- a/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_coding.h
+++ b/extern/draco/dracoenc/src/draco/compression/entropy/rans_symbol_coding.h
@@ -40,8 +40,8 @@ constexpr int ComputeRAnsPrecisionFromUniqueSymbolsBitLength(
// Compute approximate frequency table size needed for storing the provided
// symbols.
-static int64_t ApproximateRAnsFrequencyTableBits(int32_t max_value,
- int num_unique_symbols) {
+static inline int64_t ApproximateRAnsFrequencyTableBits(
+ int32_t max_value, int num_unique_symbols) {
// Approximate number of bits for storing zero frequency entries using the
// run length encoding (with max length of 64).
const int64_t table_zero_frequency_bits =
diff --git a/extern/draco/dracoenc/src/draco/compression/expert_encode.cc b/extern/draco/dracoenc/src/draco/compression/expert_encode.cc
index f62d16630cb..112e6ae3d3e 100644
--- a/extern/draco/dracoenc/src/draco/compression/expert_encode.cc
+++ b/extern/draco/dracoenc/src/draco/compression/expert_encode.cc
@@ -16,8 +16,10 @@
#include "draco/compression/mesh/mesh_edgebreaker_encoder.h"
#include "draco/compression/mesh/mesh_sequential_encoder.h"
+#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
#include "draco/compression/point_cloud/point_cloud_kd_tree_encoder.h"
#include "draco/compression/point_cloud/point_cloud_sequential_encoder.h"
+#endif
namespace draco {
@@ -29,7 +31,7 @@ ExpertEncoder::ExpertEncoder(const Mesh &mesh)
Status ExpertEncoder::EncodeToBuffer(EncoderBuffer *out_buffer) {
if (point_cloud_ == nullptr)
- return Status(Status::ERROR, "Invalid input geometry.");
+ return Status(Status::DRACO_ERROR, "Invalid input geometry.");
if (mesh_ == nullptr) {
return EncodePointCloudToBuffer(*point_cloud_, out_buffer);
}
@@ -38,6 +40,7 @@ Status ExpertEncoder::EncodeToBuffer(EncoderBuffer *out_buffer) {
Status ExpertEncoder::EncodePointCloudToBuffer(const PointCloud &pc,
EncoderBuffer *out_buffer) {
+#ifdef DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED
std::unique_ptr<PointCloudEncoder> encoder;
const int encoding_method = options().GetGlobalInt("encoding_method", -1);
@@ -74,7 +77,7 @@ Status ExpertEncoder::EncodePointCloudToBuffer(const PointCloud &pc,
} else if (encoding_method == POINT_CLOUD_KD_TREE_ENCODING) {
// Encoding method was explicitly specified but we cannot use it for
// the given input (some of the checks above failed).
- return Status(Status::ERROR, "Invalid encoding method.");
+ return Status(Status::DRACO_ERROR, "Invalid encoding method.");
}
}
if (!encoder) {
@@ -87,6 +90,9 @@ Status ExpertEncoder::EncodePointCloudToBuffer(const PointCloud &pc,
set_num_encoded_points(encoder->num_encoded_points());
set_num_encoded_faces(0);
return OkStatus();
+#else
+ return Status(Status::DRACO_ERROR, "Point cloud encoding is not enabled.");
+#endif
}
Status ExpertEncoder::EncodeMeshToBuffer(const Mesh &m,
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc
index ad87f9403af..54fd55a483c 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.cc
@@ -31,9 +31,7 @@ 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(ostava): For now we have a set limit for forcing the basic edgebreaker
- // based on the number of faces, but a more complex heuristic may be used if
- // needed.
+ // TODO(b/111065939): Check if this can be improved.
const bool is_tiny_mesh = mesh()->num_faces() < 1000;
int selected_edgebreaker_method =
@@ -81,7 +79,7 @@ bool MeshEdgebreakerEncoder::EncodeAttributesEncoderIdentifier(
return true;
}
-bool MeshEdgebreakerEncoder::EncodeConnectivity() {
+Status MeshEdgebreakerEncoder::EncodeConnectivity() {
return impl_->EncodeConnectivity();
}
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.h b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.h
index 78615fb0287..70d4d5061a7 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder.h
@@ -51,7 +51,7 @@ class MeshEdgebreakerEncoder : public MeshEncoder {
protected:
bool InitializeEncoder() override;
- bool EncodeConnectivity() override;
+ Status EncodeConnectivity() override;
bool GenerateAttributesEncoder(int32_t att_id) override;
bool EncodeAttributesEncoderIdentifier(int32_t att_encoder_id) override;
void ComputeNumberOfEncodedPoints() override;
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
index 89e6f0b5b12..f69ec993f9e 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
@@ -263,7 +263,7 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::
}
template <class TraversalEncoder>
-bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
+Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
// To encode the mesh, we need face connectivity data stored in a corner
// table. To compute the connectivity we must use indices associated with
// POSITION attribute, because they define which edges can be connected
@@ -279,7 +279,7 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
corner_table_->num_faces() == corner_table_->NumDegeneratedFaces()) {
// Failed to construct the corner table.
// TODO(ostava): Add better error reporting.
- return false;
+ return Status(Status::DRACO_ERROR, "All triangles are degenerate.");
}
traversal_encoder_.Init(this);
@@ -317,10 +317,10 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
pos_encoding_data_.num_values = 0;
if (!FindHoles())
- return false;
+ return Status(Status::DRACO_ERROR, "Failed to process mesh holes.");
if (!InitAttributeData())
- return false;
+ return Status(Status::DRACO_ERROR, "Failed to initialize attribute data.");
const uint8_t num_attribute_data =
static_cast<uint8_t>(attribute_data_.size());
@@ -376,7 +376,7 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
if (opp_face_id != kInvalidFaceIndex &&
!visited_faces_[opp_face_id.value()]) {
if (!EncodeConnectivityFromCorner(opp_id))
- return false;
+ return Status(Status::DRACO_ERROR, "Failed to encode mesh component.");
}
} else {
// Boundary configuration. We start on a boundary rather than on a face.
@@ -385,7 +385,7 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
// Start processing the face opposite to the boundary edge (the face
// containing the start_corner).
if (!EncodeConnectivityFromCorner(start_corner))
- return false;
+ return Status(Status::DRACO_ERROR, "Failed to encode mesh component.");
}
}
// Reverse the order of connectivity corners to match the order in which
@@ -417,11 +417,11 @@ bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
// Append the traversal buffer.
if (!EncodeSplitData())
- return false;
+ return Status(Status::DRACO_ERROR, "Failed to encode split data.");
encoder_->buffer()->Encode(traversal_encoder_.buffer().data(),
traversal_encoder_.buffer().size());
- return true;
+ return OkStatus();
}
template <class TraversalEncoder>
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h
index 997bd1565e3..fb33771637e 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.h
@@ -45,7 +45,7 @@ class MeshEdgebreakerEncoderImpl : public MeshEdgebreakerEncoderImplInterface {
bool GenerateAttributesEncoder(int32_t att_id) override;
bool EncodeAttributesEncoderIdentifier(int32_t att_encoder_id) override;
- bool EncodeConnectivity() override;
+ Status EncodeConnectivity() override;
const CornerTable *GetCornerTable() const override {
return corner_table_.get();
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h
index 8da3541ec86..627d5126296 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl_interface.h
@@ -41,7 +41,7 @@ class MeshEdgebreakerEncoderImplInterface {
int att_id) const = 0;
virtual bool GenerateAttributesEncoder(int32_t att_id) = 0;
virtual bool EncodeAttributesEncoderIdentifier(int32_t att_encoder_id) = 0;
- virtual bool EncodeConnectivity() = 0;
+ virtual Status EncodeConnectivity() = 0;
// Returns corner table of the encoded mesh.
virtual const CornerTable *GetCornerTable() const = 0;
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.cc b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.cc
index 19d1355a443..2da5de1fc82 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.cc
@@ -23,12 +23,11 @@ void MeshEncoder::SetMesh(const Mesh &m) {
SetPointCloud(m);
}
-bool MeshEncoder::EncodeGeometryData() {
- if (!EncodeConnectivity())
- return false;
+Status MeshEncoder::EncodeGeometryData() {
+ DRACO_RETURN_IF_ERROR(EncodeConnectivity());
if (options()->GetGlobalBool("store_number_of_encoded_faces", false))
ComputeNumberOfEncodedFaces();
- return true;
+ return OkStatus();
}
} // namespace draco
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.h b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.h
index 41387d569c6..30ec4fa3492 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder.h
@@ -61,10 +61,10 @@ class MeshEncoder : public PointCloudEncoder {
const Mesh *mesh() const { return mesh_; }
protected:
- bool EncodeGeometryData() override;
+ Status EncodeGeometryData() override;
// Needs to be implemented by the derived classes.
- virtual bool EncodeConnectivity() = 0;
+ virtual Status EncodeConnectivity() = 0;
// Computes and sets the num_encoded_faces_ for the encoder.
virtual void ComputeNumberOfEncodedFaces() = 0;
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc
index e67861a2ec2..9f056fc22e3 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_encoder_test.cc
@@ -87,7 +87,7 @@ TEST_P(MeshEncoderTest, EncodeGoldenMesh) {
}
}
-INSTANTIATE_TEST_CASE_P(MeshEncoderTests, MeshEncoderTest,
- ::testing::Values("sequential", "edgebreaker"));
+INSTANTIATE_TEST_SUITE_P(MeshEncoderTests, MeshEncoderTest,
+ ::testing::Values("sequential", "edgebreaker"));
} // namespace draco
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.cc b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.cc
index 44b3b20b63c..b53ff0c25a6 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.cc
@@ -25,7 +25,7 @@ namespace draco {
MeshSequentialEncoder::MeshSequentialEncoder() {}
-bool MeshSequentialEncoder::EncodeConnectivity() {
+Status MeshSequentialEncoder::EncodeConnectivity() {
// Serialize indices.
const uint32_t num_faces = mesh()->num_faces();
EncodeVarint(num_faces, buffer());
@@ -38,7 +38,7 @@ bool MeshSequentialEncoder::EncodeConnectivity() {
// 0 = Encode compressed indices.
buffer()->Encode(static_cast<uint8_t>(0));
if (!CompressAndEncodeIndices())
- return false;
+ return Status(Status::DRACO_ERROR, "Failed to compress connectivity.");
} else {
// 1 = Encode indices directly.
buffer()->Encode(static_cast<uint8_t>(1));
@@ -77,7 +77,7 @@ bool MeshSequentialEncoder::EncodeConnectivity() {
}
}
}
- return true;
+ return OkStatus();
}
bool MeshSequentialEncoder::GenerateAttributesEncoder(int32_t att_id) {
diff --git a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.h b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.h
index 47a4fec837c..672609642b0 100644
--- a/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/mesh/mesh_sequential_encoder.h
@@ -42,7 +42,7 @@ class MeshSequentialEncoder : public MeshEncoder {
}
protected:
- bool EncodeConnectivity() override;
+ Status EncodeConnectivity() override;
bool GenerateAttributesEncoder(int32_t att_id) override;
void ComputeNumberOfEncodedPoints() override;
void ComputeNumberOfEncodedFaces() override;
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h b/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h
index e220a2ab166..61a153560ae 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/dynamic_integer_points_kd_tree_decoder.h
@@ -95,8 +95,11 @@ class DynamicIntegerPointsKdTreeDecoder {
// Decodes a integer point cloud from |buffer|.
template <class OutputIteratorT>
bool DecodePoints(DecoderBuffer *buffer, OutputIteratorT &oit);
+
+#ifndef DRACO_OLD_GCC
template <class OutputIteratorT>
bool DecodePoints(DecoderBuffer *buffer, OutputIteratorT &&oit);
+#endif // DRACO_OLD_GCC
const uint32_t dimension() const { return dimension_; }
@@ -138,6 +141,7 @@ class DynamicIntegerPointsKdTreeDecoder {
};
// Decodes a point cloud from |buffer|.
+#ifndef DRACO_OLD_GCC
template <int compression_level_t>
template <class OutputIteratorT>
bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodePoints(
@@ -145,6 +149,7 @@ bool DynamicIntegerPointsKdTreeDecoder<compression_level_t>::DecodePoints(
OutputIteratorT local = std::forward<OutputIteratorT>(oit);
return DecodePoints(buffer, local);
}
+#endif // DRACO_OLD_GCC
template <int compression_level_t>
template <class OutputIteratorT>
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h b/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h
index 80be0c9d373..d3425696a5a 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/float_points_tree_decoder.h
@@ -33,8 +33,12 @@ class FloatPointsTreeDecoder {
// Decodes a point cloud from |buffer|.
template <class OutputIteratorT>
bool DecodePointCloud(DecoderBuffer *buffer, OutputIteratorT &out);
+
+#ifndef DRACO_OLD_GCC
template <class OutputIteratorT>
bool DecodePointCloud(DecoderBuffer *buffer, OutputIteratorT &&out);
+#endif // DRACO_OLD_GCC
+
// Initializes a DecoderBuffer from |data|, and calls function above.
template <class OutputIteratorT>
bool DecodePointCloud(const char *data, size_t data_size,
@@ -72,12 +76,16 @@ class FloatPointsTreeDecoder {
uint32_t compression_level_;
};
+#ifndef DRACO_OLD_GCC
+// TODO(vytyaz): Reenable once USD migrates from GCC 4.8 to a higher version
+// that can disambiguate calls to overloaded methods taking rvalue reference.
template <class OutputIteratorT>
bool FloatPointsTreeDecoder::DecodePointCloud(DecoderBuffer *buffer,
OutputIteratorT &&out) {
OutputIteratorT local = std::forward<OutputIteratorT>(out);
return DecodePointCloud(buffer, local);
}
+#endif // DRACO_OLD_GCC
template <class OutputIteratorT>
bool FloatPointsTreeDecoder::DecodePointCloud(DecoderBuffer *buffer,
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h b/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h
index 18307b57209..9541c966856 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/algorithms/point_cloud_compression_method.h
@@ -23,7 +23,7 @@ enum PointCloudCompressionMethod {
// Generalized version of Encoding using the Octree method by Olivier
// Devillers to d dimensions.
// "Progressive lossless compression of arbitrary simplicial complexes"
- // http://dx.doi.org/10.1145/566570.566591
+ // https://doi.org/10.1145/566570.566591
KDTREE = 1,
RESERVED_POINT_CLOUD_METHOD_2 = 2, // Reserved for internal use.
RESERVED_POINT_CLOUD_METHOD_3 = 0, // Reserved for internal use.
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc
index 5f3bff4bbc9..cf5d997e67a 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_decoder.cc
@@ -31,7 +31,7 @@ Status PointCloudDecoder::DecodeHeader(DecoderBuffer *buffer,
if (!buffer->Decode(out_header->draco_string, 5))
return Status(Status::IO_ERROR, kIoErrorMsg);
if (memcmp(out_header->draco_string, "DRACO", 5) != 0)
- return Status(Status::ERROR, "Not a Draco file.");
+ return Status(Status::DRACO_ERROR, "Not a Draco file.");
if (!buffer->Decode(&(out_header->version_major)))
return Status(Status::IO_ERROR, kIoErrorMsg);
if (!buffer->Decode(&(out_header->version_minor)))
@@ -50,7 +50,7 @@ Status PointCloudDecoder::DecodeMetadata() {
std::unique_ptr<GeometryMetadata>(new GeometryMetadata());
MetadataDecoder metadata_decoder;
if (!metadata_decoder.DecodeGeometryMetadata(buffer_, metadata.get()))
- return Status(Status::ERROR, "Failed to decode metadata.");
+ return Status(Status::DRACO_ERROR, "Failed to decode metadata.");
point_cloud_->AddMetadata(std::move(metadata));
return OkStatus();
}
@@ -66,7 +66,7 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options,
// Sanity check that we are really using the right decoder (mostly for cases
// where the Decode method was called manually outside of our main API.
if (header.encoder_type != GetGeometryType())
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Using incompatible decoder for the input geometry.");
// TODO(ostava): We should check the method as well, but currently decoders
// don't expose the decoding method id.
@@ -93,11 +93,11 @@ Status PointCloudDecoder::Decode(const DecoderOptions &options,
DRACO_RETURN_IF_ERROR(DecodeMetadata())
}
if (!InitializeDecoder())
- return Status(Status::ERROR, "Failed to initialize the decoder.");
+ return Status(Status::DRACO_ERROR, "Failed to initialize the decoder.");
if (!DecodeGeometryData())
- return Status(Status::ERROR, "Failed to decode geometry data.");
+ return Status(Status::DRACO_ERROR, "Failed to decode geometry data.");
if (!DecodePointAttributes())
- return Status(Status::ERROR, "Failed to decode point attributes.");
+ return Status(Status::DRACO_ERROR, "Failed to decode point attributes.");
return OkStatus();
}
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc
index edf0e4ab20a..986706582f0 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.cc
@@ -36,17 +36,16 @@ Status PointCloudEncoder::Encode(const EncoderOptions &options,
attributes_encoder_ids_order_.clear();
if (!point_cloud_)
- return Status(Status::ERROR, "Invalid input geometry.");
+ return Status(Status::DRACO_ERROR, "Invalid input geometry.");
DRACO_RETURN_IF_ERROR(EncodeHeader())
DRACO_RETURN_IF_ERROR(EncodeMetadata())
if (!InitializeEncoder())
- return Status(Status::ERROR, "Failed to initialize encoder.");
+ return Status(Status::DRACO_ERROR, "Failed to initialize encoder.");
if (!EncodeEncoderData())
- return Status(Status::ERROR, "Failed to encode internal data.");
- if (!EncodeGeometryData())
- return Status(Status::ERROR, "Failed to encode geometry data.");
+ return Status(Status::DRACO_ERROR, "Failed to encode internal data.");
+ DRACO_RETURN_IF_ERROR(EncodeGeometryData());
if (!EncodePointAttributes())
- return Status(Status::ERROR, "Failed to encode point attributes.");
+ return Status(Status::DRACO_ERROR, "Failed to encode point attributes.");
if (options.GetGlobalBool("store_number_of_encoded_points", false))
ComputeNumberOfEncodedPoints();
return OkStatus();
@@ -87,7 +86,7 @@ Status PointCloudEncoder::EncodeMetadata() {
MetadataEncoder metadata_encoder;
if (!metadata_encoder.EncodeGeometryMetadata(buffer_,
point_cloud_->GetMetadata())) {
- return Status(Status::ERROR, "Failed to encode metadata.");
+ return Status(Status::DRACO_ERROR, "Failed to encode metadata.");
}
return OkStatus();
}
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.h b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.h
index b15d1401a57..8883f17a789 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_encoder.h
@@ -85,7 +85,7 @@ class PointCloudEncoder {
virtual bool EncodeEncoderData() { return true; }
// Encodes any global geometry data (such as the number of points).
- virtual bool EncodeGeometryData() { return true; }
+ virtual Status EncodeGeometryData() { return OkStatus(); }
// encode all attribute values. The attribute encoders are sorted to resolve
// any attribute dependencies and all the encoded data is stored into the
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc
index 7ecfca2b456..6d0446baad1 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.cc
@@ -17,10 +17,10 @@
namespace draco {
-bool PointCloudKdTreeEncoder::EncodeGeometryData() {
+Status PointCloudKdTreeEncoder::EncodeGeometryData() {
const int32_t num_points = point_cloud()->num_points();
buffer()->Encode(num_points);
- return true;
+ return OkStatus();
}
bool PointCloudKdTreeEncoder::GenerateAttributesEncoder(int32_t att_id) {
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h
index 98bc3d67fde..6acbb949d40 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_kd_tree_encoder.h
@@ -35,7 +35,7 @@ class PointCloudKdTreeEncoder : public PointCloudEncoder {
}
protected:
- bool EncodeGeometryData() override;
+ Status EncodeGeometryData() override;
bool GenerateAttributesEncoder(int32_t att_id) override;
void ComputeNumberOfEncodedPoints() override;
};
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc
index 9b92994b7a6..fa7b6fd905c 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.cc
@@ -19,10 +19,10 @@
namespace draco {
-bool PointCloudSequentialEncoder::EncodeGeometryData() {
+Status PointCloudSequentialEncoder::EncodeGeometryData() {
const int32_t num_points = point_cloud()->num_points();
buffer()->Encode(num_points);
- return true;
+ return OkStatus();
}
bool PointCloudSequentialEncoder::GenerateAttributesEncoder(int32_t att_id) {
diff --git a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h
index f73b5a551e4..40d8edcdbb0 100644
--- a/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h
+++ b/extern/draco/dracoenc/src/draco/compression/point_cloud/point_cloud_sequential_encoder.h
@@ -33,7 +33,7 @@ class PointCloudSequentialEncoder : public PointCloudEncoder {
}
protected:
- bool EncodeGeometryData() override;
+ Status EncodeGeometryData() override;
bool GenerateAttributesEncoder(int32_t att_id) override;
void ComputeNumberOfEncodedPoints() override;
};
diff --git a/extern/draco/dracoenc/src/draco/core/data_buffer.cc b/extern/draco/dracoenc/src/draco/core/data_buffer.cc
index 3b57367bbf1..867760a6fcc 100644
--- a/extern/draco/dracoenc/src/draco/core/data_buffer.cc
+++ b/extern/draco/dracoenc/src/draco/core/data_buffer.cc
@@ -13,6 +13,7 @@
// limitations under the License.
//
#include "draco/core/data_buffer.h"
+#include <algorithm>
namespace draco {
diff --git a/extern/draco/dracoenc/src/draco/core/draco_test_utils.cc b/extern/draco/dracoenc/src/draco/core/draco_test_utils.cc
index fa225576d9c..a39e19f6b15 100644
--- a/extern/draco/dracoenc/src/draco/core/draco_test_utils.cc
+++ b/extern/draco/dracoenc/src/draco/core/draco_test_utils.cc
@@ -48,7 +48,7 @@ bool GenerateGoldenFile(const std::string &golden_file_name, const void *data,
bool CompareGoldenFile(const std::string &golden_file_name, const void *data,
int data_size) {
const std::string golden_path = GetTestFileFullPath(golden_file_name);
- std::ifstream in_file(golden_path);
+ std::ifstream in_file(golden_path, std::ios::binary);
if (!in_file || data_size < 0)
return false;
const char *const data_c8 = static_cast<const char *>(data);
diff --git a/extern/draco/dracoenc/src/draco/core/draco_test_utils.h b/extern/draco/dracoenc/src/draco/core/draco_test_utils.h
index 2ed93cd960b..3113a5d2676 100644
--- a/extern/draco/dracoenc/src/draco/core/draco_test_utils.h
+++ b/extern/draco/dracoenc/src/draco/core/draco_test_utils.h
@@ -53,6 +53,11 @@ inline std::unique_ptr<Mesh> ReadMeshFromTestFile(const std::string &file_name,
const std::string path = GetTestFileFullPath(file_name);
return ReadMeshFromFile(path, use_metadata).value();
}
+inline std::unique_ptr<Mesh> ReadMeshFromTestFile(const std::string &file_name,
+ const Options &options) {
+ const std::string path = GetTestFileFullPath(file_name);
+ return ReadMeshFromFile(path, options).value();
+}
inline std::unique_ptr<PointCloud> ReadPointCloudFromTestFile(
const std::string &file_name) {
diff --git a/extern/draco/dracoenc/src/draco/core/draco_types.cc b/extern/draco/dracoenc/src/draco/core/draco_types.cc
index 45b22470057..9bde05fda80 100644
--- a/extern/draco/dracoenc/src/draco/core/draco_types.cc
+++ b/extern/draco/dracoenc/src/draco/core/draco_types.cc
@@ -41,4 +41,21 @@ int32_t DataTypeLength(DataType dt) {
}
}
+bool IsDataTypeIntegral(DataType dt) {
+ switch (dt) {
+ case DT_INT8:
+ case DT_UINT8:
+ case DT_INT16:
+ case DT_UINT16:
+ case DT_INT32:
+ case DT_UINT32:
+ case DT_INT64:
+ case DT_UINT64:
+ case DT_BOOL:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace draco
diff --git a/extern/draco/dracoenc/src/draco/core/draco_types.h b/extern/draco/dracoenc/src/draco/core/draco_types.h
index 4a34d7045a3..f5a21e4f1d0 100644
--- a/extern/draco/dracoenc/src/draco/core/draco_types.h
+++ b/extern/draco/dracoenc/src/draco/core/draco_types.h
@@ -41,6 +41,11 @@ enum DataType {
int32_t DataTypeLength(DataType dt);
+// Equivalent to std::is_integral for draco::DataType. Returns true for all
+// signed and unsigned integer types (including DT_BOOL). Returns false
+// otherwise.
+bool IsDataTypeIntegral(DataType dt);
+
} // namespace draco
#endif // DRACO_CORE_DRACO_TYPES_H_
diff --git a/extern/draco/dracoenc/src/draco/core/draco_version.h b/extern/draco/dracoenc/src/draco/core/draco_version.h
index 45dce22a1d8..9d3a67e4f8e 100644
--- a/extern/draco/dracoenc/src/draco/core/draco_version.h
+++ b/extern/draco/dracoenc/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.4";
+static const char kDracoVersion[] = "1.3.5";
const char *Version() { return kDracoVersion; }
diff --git a/extern/draco/dracoenc/src/draco/core/macros.h b/extern/draco/dracoenc/src/draco/core/macros.h
index e968cbb330b..09819e63969 100644
--- a/extern/draco/dracoenc/src/draco/core/macros.h
+++ b/extern/draco/dracoenc/src/draco/core/macros.h
@@ -32,12 +32,27 @@
#include <iostream>
namespace draco {
+#ifndef DISALLOW_COPY_AND_ASSIGN
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName &) = delete; \
void operator=(const TypeName &) = delete;
+#endif
+
+#ifndef FALLTHROUGH_INTENDED
+#if defined(__clang__) && defined(__has_warning)
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
+#endif
+#elif defined(__GNUC__) && __GNUC__ >= 7
+#define FALLTHROUGH_INTENDED [[gnu::fallthrough]]
+#endif
+// If FALLTHROUGH_INTENDED is still not defined, define it.
#ifndef FALLTHROUGH_INTENDED
-#define FALLTHROUGH_INTENDED void(0);
+#define FALLTHROUGH_INTENDED \
+ do { \
+ } while (0)
+#endif
#endif
#ifndef LOG
diff --git a/extern/draco/dracoenc/src/draco/core/math_utils.h b/extern/draco/dracoenc/src/draco/core/math_utils.h
index 6bf237d4560..50cf5d57199 100644
--- a/extern/draco/dracoenc/src/draco/core/math_utils.h
+++ b/extern/draco/dracoenc/src/draco/core/math_utils.h
@@ -17,6 +17,8 @@
#include <inttypes.h>
+#include "draco/core/vector_d.h"
+
#define DRACO_INCREMENT_MOD(I, M) (((I) == ((M)-1)) ? 0 : ((I) + 1))
// Returns floor(sqrt(x)) where x is an integer number. The main intend of this
diff --git a/extern/draco/dracoenc/src/draco/core/math_utils_test.cc b/extern/draco/dracoenc/src/draco/core/math_utils_test.cc
index b12b3431e66..8c255d04680 100644
--- a/extern/draco/dracoenc/src/draco/core/math_utils_test.cc
+++ b/extern/draco/dracoenc/src/draco/core/math_utils_test.cc
@@ -1,9 +1,12 @@
#include "draco/core/math_utils.h"
+#include <cmath>
#include <random>
#include "draco/core/draco_test_base.h"
+using draco::Vector3f;
+
TEST(MathUtils, Mod) { EXPECT_EQ(DRACO_INCREMENT_MOD(1, 1 << 1), 0); }
TEST(MathUtils, IntSqrt) {
diff --git a/extern/draco/dracoenc/src/draco/core/options.cc b/extern/draco/dracoenc/src/draco/core/options.cc
index c4f6d6a66aa..a9ce14b9837 100644
--- a/extern/draco/dracoenc/src/draco/core/options.cc
+++ b/extern/draco/dracoenc/src/draco/core/options.cc
@@ -16,11 +16,17 @@
#include <cstdlib>
#include <string>
+#include <utility>
namespace draco {
Options::Options() {}
+void Options::MergeAndReplace(const Options &other_options) {
+ for (const auto &item : other_options.options_)
+ options_[item.first] = item.second;
+}
+
void Options::SetInt(const std::string &name, int val) {
options_[name] = std::to_string(val);
}
diff --git a/extern/draco/dracoenc/src/draco/core/options.h b/extern/draco/dracoenc/src/draco/core/options.h
index 0e69844911d..4995299633c 100644
--- a/extern/draco/dracoenc/src/draco/core/options.h
+++ b/extern/draco/dracoenc/src/draco/core/options.h
@@ -28,6 +28,11 @@ namespace draco {
class Options {
public:
Options();
+
+ // Merges |other_options| on top of the existing options of this instance
+ // replacing all entries that are present in both options instances.
+ void MergeAndReplace(const Options &other_options);
+
void SetInt(const std::string &name, int val);
void SetFloat(const std::string &name, float val);
void SetBool(const std::string &name, bool val);
diff --git a/extern/draco/dracoenc/src/draco/core/status.h b/extern/draco/dracoenc/src/draco/core/status.h
index 0a483f09369..9ac3def7cd1 100644
--- a/extern/draco/dracoenc/src/draco/core/status.h
+++ b/extern/draco/dracoenc/src/draco/core/status.h
@@ -25,7 +25,7 @@ class Status {
public:
enum Code {
OK = 0,
- ERROR = -1, // Used for general errors.
+ DRACO_ERROR = -1, // Used for general errors.
IO_ERROR = -2, // Error when handling input or output stream.
INVALID_PARAMETER = -3, // Invalid parameter passed to a function.
UNSUPPORTED_VERSION = -4, // Input not compatible with the current version.
diff --git a/extern/draco/dracoenc/src/draco/core/status_or.h b/extern/draco/dracoenc/src/draco/core/status_or.h
new file mode 100644
index 00000000000..156b9bc02a7
--- /dev/null
+++ b/extern/draco/dracoenc/src/draco/core/status_or.h
@@ -0,0 +1,81 @@
+// Copyright 2017 The Draco Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef DRACO_CORE_STATUS_OR_H_
+#define DRACO_CORE_STATUS_OR_H_
+
+#include "draco/core/macros.h"
+#include "draco/core/status.h"
+
+namespace draco {
+
+// Class StatusOr is used to wrap a Status along with a value of a specified
+// type |T|. StatusOr is intended to be returned from functions in situations
+// where it is desirable to carry over more information about the potential
+// errors encountered during the function execution. If there are not errors,
+// the caller can simply use the return value, otherwise the Status object
+// provides more info about the encountered problem.
+template <class T>
+class StatusOr {
+ public:
+ StatusOr() {}
+ // Note: Constructors are intentionally not explicit to allow returning
+ // Status or the return value directly from functions.
+ StatusOr(const StatusOr &) = default;
+ StatusOr(StatusOr &&) = default;
+ StatusOr(const Status &status) : status_(status) {}
+ StatusOr(const T &value) : status_(OkStatus()), value_(value) {}
+ StatusOr(T &&value) : status_(OkStatus()), value_(std::move(value)) {}
+ StatusOr(const Status &status, const T &value)
+ : status_(status), value_(value) {}
+
+ const Status &status() const { return status_; }
+ const T &value() const & { return value_; }
+ const T &&value() const && { return std::move(value_); }
+ T &&value() && { return std::move(value_); }
+
+ // For consistency with existing Google StatusOr API we also include
+ // ValueOrDie() that currently returns the value().
+ const T &ValueOrDie() const & { return value(); }
+ T &&ValueOrDie() && { return std::move(value()); }
+
+ bool ok() const { return status_.ok(); }
+
+ private:
+ Status status_;
+ T value_;
+};
+
+// In case StatusOr<T> is ok(), this macro assigns value stored in StatusOr<T>
+// to |lhs|, otherwise it returns the error Status.
+//
+// DRACO_ASSIGN_OR_RETURN(lhs, expression)
+//
+#define DRACO_ASSIGN_OR_RETURN(lhs, expression) \
+ DRACO_ASSIGN_OR_RETURN_IMPL_(DRACO_MACROS_IMPL_CONCAT_(_statusor, __LINE__), \
+ lhs, expression, _status)
+
+// The actual implementation of the above macro.
+#define DRACO_ASSIGN_OR_RETURN_IMPL_(statusor, lhs, expression, error_expr) \
+ auto statusor = (expression); \
+ if (!statusor.ok()) { \
+ auto _status = std::move(statusor.status()); \
+ (void)_status; /* error_expression may not use it */ \
+ return error_expr; \
+ } \
+ lhs = std::move(statusor).value();
+
+} // namespace draco
+
+#endif // DRACO_CORE_STATUS_OR_H_
diff --git a/extern/draco/dracoenc/src/draco/core/status_test.cc b/extern/draco/dracoenc/src/draco/core/status_test.cc
index 451ebe2bfab..c1ad4ab30f4 100644
--- a/extern/draco/dracoenc/src/draco/core/status_test.cc
+++ b/extern/draco/dracoenc/src/draco/core/status_test.cc
@@ -27,8 +27,8 @@ class StatusTest : public ::testing::Test {
TEST_F(StatusTest, TestStatusOutput) {
// Tests that the Status can be stored in a provided std::ostream.
- const draco::Status status(draco::Status::ERROR, "Error msg.");
- ASSERT_EQ(status.code(), draco::Status::ERROR);
+ const draco::Status status(draco::Status::DRACO_ERROR, "Error msg.");
+ ASSERT_EQ(status.code(), draco::Status::DRACO_ERROR);
std::stringstream str;
str << status;
diff --git a/extern/draco/dracoenc/src/draco/core/vector_d.h b/extern/draco/dracoenc/src/draco/core/vector_d.h
index 57dcd102663..189517f3928 100644
--- a/extern/draco/dracoenc/src/draco/core/vector_d.h
+++ b/extern/draco/dracoenc/src/draco/core/vector_d.h
@@ -24,16 +24,20 @@
namespace draco {
// D-dimensional vector class with basic operations.
-template <class CoeffT, int dimension_t>
+template <class ScalarT, int dimension_t>
class VectorD {
public:
- typedef VectorD<CoeffT, dimension_t> Self;
- typedef CoeffT CoefficientType;
static constexpr int dimension = dimension_t;
+ typedef ScalarT Scalar;
+ typedef VectorD<Scalar, dimension_t> Self;
+
+ // TODO(hemmer): Deprecate.
+ typedef ScalarT CoefficientType;
+
VectorD() {
- for (int i = 0; i < dimension_t; ++i)
- (*this)[i] = CoeffT(0);
+ for (int i = 0; i < dimension; ++i)
+ (*this)[i] = Scalar(0);
}
// The following constructor does not compile in opt mode, which for now led
@@ -42,58 +46,75 @@ class VectorD {
// template <typename... Args>
// explicit VectorD(Args... args) : v_({args...}) {}
- VectorD(const CoeffT &c0, const CoeffT &c1) : v_({{c0, c1}}) {
- DRACO_DCHECK_EQ(dimension_t, 2);
+ VectorD(const Scalar &c0, const Scalar &c1) : v_({{c0, c1}}) {
+ DRACO_DCHECK_EQ(dimension, 2);
v_[0] = c0;
v_[1] = c1;
}
- VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2)
+ VectorD(const Scalar &c0, const Scalar &c1, const Scalar &c2)
: v_({{c0, c1, c2}}) {
- DRACO_DCHECK_EQ(dimension_t, 3);
+ DRACO_DCHECK_EQ(dimension, 3);
}
- VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2,
- const CoeffT &c3)
+ VectorD(const Scalar &c0, const Scalar &c1, const Scalar &c2,
+ const Scalar &c3)
: v_({{c0, c1, c2, c3}}) {
- DRACO_DCHECK_EQ(dimension_t, 4);
+ DRACO_DCHECK_EQ(dimension, 4);
}
- VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2,
- const CoeffT &c3, const CoeffT &c4)
+ VectorD(const Scalar &c0, const Scalar &c1, const Scalar &c2,
+ const Scalar &c3, const Scalar &c4)
: v_({{c0, c1, c2, c3, c4}}) {
- DRACO_DCHECK_EQ(dimension_t, 5);
+ DRACO_DCHECK_EQ(dimension, 5);
}
- VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2,
- const CoeffT &c3, const CoeffT &c4, const CoeffT &c5)
+ VectorD(const Scalar &c0, const Scalar &c1, const Scalar &c2,
+ const Scalar &c3, const Scalar &c4, const Scalar &c5)
: v_({{c0, c1, c2, c3, c4, c5}}) {
- DRACO_DCHECK_EQ(dimension_t, 6);
+ DRACO_DCHECK_EQ(dimension, 6);
}
- VectorD(const CoeffT &c0, const CoeffT &c1, const CoeffT &c2,
- const CoeffT &c3, const CoeffT &c4, const CoeffT &c5,
- const CoeffT &c6)
+ VectorD(const Scalar &c0, const Scalar &c1, const Scalar &c2,
+ const Scalar &c3, const Scalar &c4, const Scalar &c5,
+ const Scalar &c6)
: v_({{c0, c1, c2, c3, c4, c5, c6}}) {
- DRACO_DCHECK_EQ(dimension_t, 7);
+ DRACO_DCHECK_EQ(dimension, 7);
}
VectorD(const Self &o) {
- for (int i = 0; i < dimension_t; ++i)
+ for (int i = 0; i < dimension; ++i)
(*this)[i] = o[i];
}
- CoeffT &operator[](int i) { return v_[i]; }
- const CoeffT &operator[](int i) const { return v_[i]; }
+ // Constructs the vector from another vector with a different data type or a
+ // different number of components. If the |src_vector| has more components
+ // than |this| vector, the excess components are truncated. If the
+ // |src_vector| has fewer components than |this| vector, the remaining
+ // components are padded with 0.
+ // Note that the constructor is intentionally explicit to avoid accidental
+ // conversions between different vector types.
+ template <class OtherScalarT, int other_dimension_t>
+ explicit VectorD(const VectorD<OtherScalarT, other_dimension_t> &src_vector) {
+ for (int i = 0; i < dimension; ++i) {
+ if (i < other_dimension_t)
+ v_[i] = Scalar(src_vector[i]);
+ else
+ v_[i] = Scalar(0);
+ }
+ }
+
+ Scalar &operator[](int i) { return v_[i]; }
+ const Scalar &operator[](int i) const { return v_[i]; }
// TODO(hemmer): remove.
// Similar to interface of Eigen library.
- CoeffT &operator()(int i) { return v_[i]; }
- const CoeffT &operator()(int i) const { return v_[i]; }
+ Scalar &operator()(int i) { return v_[i]; }
+ const Scalar &operator()(int i) const { return v_[i]; }
// Unary operators.
Self operator-() const {
Self ret;
- for (int i = 0; i < dimension_t; ++i) {
+ for (int i = 0; i < dimension; ++i) {
ret[i] = -(*this)[i];
}
return ret;
@@ -102,7 +123,7 @@ class VectorD {
// Binary operators.
Self operator+(const Self &o) const {
Self ret;
- for (int i = 0; i < dimension_t; ++i) {
+ for (int i = 0; i < dimension; ++i) {
ret[i] = (*this)[i] + o[i];
}
return ret;
@@ -110,30 +131,46 @@ class VectorD {
Self operator-(const Self &o) const {
Self ret;
- for (int i = 0; i < dimension_t; ++i) {
+ for (int i = 0; i < dimension; ++i) {
ret[i] = (*this)[i] - o[i];
}
return ret;
}
- Self operator*(const CoeffT &o) const {
+ Self operator*(const Scalar &o) const {
Self ret;
- for (int i = 0; i < dimension_t; ++i) {
+ for (int i = 0; i < dimension; ++i) {
ret[i] = (*this)[i] * o;
}
return ret;
}
- Self operator/(const CoeffT &o) const {
+ Self operator/(const Scalar &o) const {
Self ret;
- for (int i = 0; i < dimension_t; ++i) {
+ for (int i = 0; i < dimension; ++i) {
ret[i] = (*this)[i] / o;
}
return ret;
}
+ Self operator+(const Scalar &o) const {
+ Self ret;
+ for (int i = 0; i < dimension; ++i) {
+ ret[i] = (*this)[i] + o;
+ }
+ return ret;
+ }
+
+ Self operator-(const Scalar &o) const {
+ Self ret;
+ for (int i = 0; i < dimension; ++i) {
+ ret[i] = (*this)[i] - o;
+ }
+ return ret;
+ }
+
bool operator==(const Self &o) const {
- for (int i = 0; i < dimension_t; ++i) {
+ for (int i = 0; i < dimension; ++i) {
if ((*this)[i] != o[i])
return false;
}
@@ -143,67 +180,75 @@ class VectorD {
bool operator!=(const Self &x) const { return !((*this) == x); }
bool operator<(const Self &x) const {
- for (int i = 0; i < dimension_t - 1; ++i) {
+ for (int i = 0; i < dimension - 1; ++i) {
if (v_[i] < x.v_[i])
return true;
if (v_[i] > x.v_[i])
return false;
}
// Only one check needed for the last dimension.
- if (v_[dimension_t - 1] < x.v_[dimension_t - 1])
+ if (v_[dimension - 1] < x.v_[dimension - 1])
return true;
return false;
}
// Functions.
- CoeffT SquaredNorm() const { return this->Dot(*this); }
+ Scalar SquaredNorm() const { return this->Dot(*this); }
// Computes L1, the sum of absolute values of all entries.
- CoeffT AbsSum() const {
- CoeffT result(0);
- for (int i = 0; i < dimension_t; ++i) {
+ Scalar AbsSum() const {
+ Scalar result(0);
+ for (int i = 0; i < dimension; ++i) {
result += std::abs(v_[i]);
}
return result;
}
- CoeffT Dot(const Self &o) const {
- CoeffT ret(0);
- for (int i = 0; i < dimension_t; ++i) {
+ Scalar Dot(const Self &o) const {
+ Scalar ret(0);
+ for (int i = 0; i < dimension; ++i) {
ret += (*this)[i] * o[i];
}
return ret;
}
void Normalize() {
- const CoeffT magnitude = std::sqrt(this->SquaredNorm());
+ const Scalar magnitude = std::sqrt(this->SquaredNorm());
if (magnitude == 0) {
return;
}
- for (int i = 0; i < dimension_t; ++i) {
+ for (int i = 0; i < dimension; ++i) {
(*this)[i] /= magnitude;
}
}
- CoeffT *data() { return &(v_[0]); }
+ const Scalar &MaxCoeff() const {
+ return *std::max_element(v_.begin(), v_.end());
+ }
+
+ const Scalar &MinCoeff() const {
+ return *std::min_element(v_.begin(), v_.end());
+ }
+
+ Scalar *data() { return &(v_[0]); }
private:
- std::array<CoeffT, dimension_t> v_;
+ std::array<Scalar, dimension> v_;
};
// Scalar multiplication from the other side too.
-template <class CoeffT, int dimension_t>
-VectorD<CoeffT, dimension_t> operator*(const CoeffT &o,
- const VectorD<CoeffT, dimension_t> &v) {
+template <class ScalarT, int dimension_t>
+VectorD<ScalarT, dimension_t> operator*(
+ const ScalarT &o, const VectorD<ScalarT, dimension_t> &v) {
return v * o;
}
// Calculates the squared distance between two points.
-template <class CoeffT, int dimension_t>
-CoeffT SquaredDistance(const VectorD<CoeffT, dimension_t> &v1,
- const VectorD<CoeffT, dimension_t> &v2) {
- CoeffT difference;
- CoeffT squared_distance = 0;
+template <class ScalarT, int dimension_t>
+ScalarT SquaredDistance(const VectorD<ScalarT, dimension_t> &v1,
+ const VectorD<ScalarT, dimension_t> &v2) {
+ ScalarT difference;
+ ScalarT squared_distance = 0;
// Check each index separately so difference is never negative and underflow
// is avoided for unsigned types.
for (int i = 0; i < dimension_t; ++i) {
@@ -218,22 +263,22 @@ CoeffT SquaredDistance(const VectorD<CoeffT, dimension_t> &v1,
}
// Global function computing the cross product of two 3D vectors.
-template <class CoeffT>
-VectorD<CoeffT, 3> CrossProduct(const VectorD<CoeffT, 3> &u,
- const VectorD<CoeffT, 3> &v) {
+template <class ScalarT>
+VectorD<ScalarT, 3> CrossProduct(const VectorD<ScalarT, 3> &u,
+ const VectorD<ScalarT, 3> &v) {
// Preventing accidental use with uint32_t and the like.
- static_assert(std::is_signed<CoeffT>::value,
- "CoeffT must be a signed type. ");
- VectorD<CoeffT, 3> r;
+ static_assert(std::is_signed<ScalarT>::value,
+ "ScalarT must be a signed type. ");
+ VectorD<ScalarT, 3> r;
r[0] = (u[1] * v[2]) - (u[2] * v[1]);
r[1] = (u[2] * v[0]) - (u[0] * v[2]);
r[2] = (u[0] * v[1]) - (u[1] * v[0]);
return r;
}
-template <class CoeffT, int dimension_t>
+template <class ScalarT, int dimension_t>
inline std::ostream &operator<<(
- std::ostream &out, const draco::VectorD<CoeffT, dimension_t> &vec) {
+ std::ostream &out, const draco::VectorD<ScalarT, dimension_t> &vec) {
for (int i = 0; i < dimension_t - 1; ++i) {
out << vec[i] << " ";
}
diff --git a/extern/draco/dracoenc/src/draco/core/vector_d_test.cc b/extern/draco/dracoenc/src/draco/core/vector_d_test.cc
index 967043bb926..bc2bdadaa9f 100644
--- a/extern/draco/dracoenc/src/draco/core/vector_d_test.cc
+++ b/extern/draco/dracoenc/src/draco/core/vector_d_test.cc
@@ -32,20 +32,17 @@ typedef draco::Vector5ui Vector5ui;
typedef draco::VectorD<int32_t, 3> Vector3i;
typedef draco::VectorD<int32_t, 4> Vector4i;
-class VectorDTest : public ::testing::Test {
- protected:
- template <class CoeffT, int dimension_t>
- void TestSquaredDistance(const draco::VectorD<CoeffT, dimension_t> v1,
- const draco::VectorD<CoeffT, dimension_t> v2,
- const CoeffT result) {
- CoeffT squared_distance = SquaredDistance(v1, v2);
- ASSERT_EQ(squared_distance, result);
- squared_distance = SquaredDistance(v2, v1);
- ASSERT_EQ(squared_distance, result);
- }
-};
+template <class CoeffT, int dimension_t>
+void TestSquaredDistance(const draco::VectorD<CoeffT, dimension_t> v1,
+ const draco::VectorD<CoeffT, dimension_t> v2,
+ const CoeffT result) {
+ CoeffT squared_distance = SquaredDistance(v1, v2);
+ ASSERT_EQ(squared_distance, result);
+ squared_distance = SquaredDistance(v2, v1);
+ ASSERT_EQ(squared_distance, result);
+}
-TEST_F(VectorDTest, TestOperators) {
+TEST(VectorDTest, TestOperators) {
{
const Vector3f v;
ASSERT_EQ(v[0], 0);
@@ -58,10 +55,8 @@ TEST_F(VectorDTest, TestOperators) {
ASSERT_EQ(v[2], 3);
Vector3f w = v;
- bool comp = (v == w);
- ASSERT_TRUE(comp);
- comp = (v != w);
- ASSERT_TRUE(!comp);
+ ASSERT_TRUE(v == w);
+ ASSERT_FALSE(v != w);
ASSERT_EQ(w[0], 1);
ASSERT_EQ(w[1], 2);
ASSERT_EQ(w[2], 3);
@@ -81,10 +76,15 @@ TEST_F(VectorDTest, TestOperators) {
ASSERT_EQ(w[1], 2);
ASSERT_EQ(w[2], 3);
+ // Scalar multiplication from left and right.
w = v * 2.f;
ASSERT_EQ(w[0], 2);
ASSERT_EQ(w[1], 4);
ASSERT_EQ(w[2], 6);
+ w = 2.f * v;
+ ASSERT_EQ(w[0], 2);
+ ASSERT_EQ(w[1], 4);
+ ASSERT_EQ(w[2], 6);
ASSERT_EQ(v.SquaredNorm(), 14);
ASSERT_EQ(v.Dot(v), 14);
@@ -109,7 +109,7 @@ TEST_F(VectorDTest, TestOperators) {
}
}
-TEST_F(VectorDTest, TestSquaredDistance) {
+TEST(VectorDTest, TestSquaredDistance) {
// Test Vector2f: float, 2D.
Vector2f v1_2f(5.5, 10.5);
Vector2f v2_2f(3.5, 15.5);
@@ -158,7 +158,8 @@ TEST_F(VectorDTest, TestSquaredDistance) {
result_ui = 158;
TestSquaredDistance(v1_5ui, v2_5ui, result_ui);
}
-TEST_F(VectorDTest, TestCrossProduct3D) {
+
+TEST(VectorDTest, TestCrossProduct3D) {
const Vector3i e1(1, 0, 0);
const Vector3i e2(0, 1, 0);
const Vector3i e3(0, 0, 1);
@@ -181,7 +182,7 @@ TEST_F(VectorDTest, TestCrossProduct3D) {
ASSERT_EQ(0, v2.Dot(orth));
}
-TEST_F(VectorDTest, TestAbsSum) {
+TEST(VectorDTest, TestAbsSum) {
// Testing const of function and zero.
const Vector3i v(0, 0, 0);
ASSERT_EQ(v.AbsSum(), 0);
@@ -194,7 +195,18 @@ TEST_F(VectorDTest, TestAbsSum) {
ASSERT_EQ(Vector4i(-2, 4, -8, 3).AbsSum(), 17);
}
-TEST_F(VectorDTest, TestOstream) {
+TEST(VectorDTest, TestMinMaxCoeff) {
+ // Test verifies that MinCoeff() and MaxCoeff() functions work as intended.
+ const Vector4i vi(-10, 5, 2, 3);
+ ASSERT_EQ(vi.MinCoeff(), -10);
+ ASSERT_EQ(vi.MaxCoeff(), 5);
+
+ const Vector3f vf(6.f, 1000.f, -101.f);
+ ASSERT_EQ(vf.MinCoeff(), -101.f);
+ ASSERT_EQ(vf.MaxCoeff(), 1000.f);
+}
+
+TEST(VectorDTest, TestOstream) {
// Tests that the vector can be stored in a provided std::ostream.
const draco::VectorD<int64_t, 3> vector(1, 2, 3);
std::stringstream str;
@@ -202,4 +214,22 @@ TEST_F(VectorDTest, TestOstream) {
ASSERT_EQ(str.str(), "1 2 3 ");
}
+TEST(VectorDTest, TestConvertConstructor) {
+ // Tests that a vector can be constructed from another vector with a different
+ // type.
+ const draco::VectorD<int64_t, 3> vector(1, 2, 3);
+
+ const draco::VectorD<float, 3> vector3f(vector);
+ ASSERT_EQ(vector3f, draco::Vector3f(1.f, 2.f, 3.f));
+
+ const draco::VectorD<float, 2> vector2f(vector);
+ ASSERT_EQ(vector2f, draco::Vector2f(1.f, 2.f));
+
+ const draco::VectorD<float, 4> vector4f(vector3f);
+ ASSERT_EQ(vector4f, draco::Vector4f(1.f, 2.f, 3.f, 0.f));
+
+ const draco::VectorD<double, 1> vector1d(vector3f);
+ ASSERT_EQ(vector1d[0], 1.0);
+}
+
} // namespace
diff --git a/extern/draco/dracoenc/src/draco/io/mesh_io.cc b/extern/draco/dracoenc/src/draco/io/mesh_io.cc
index 807dcfbe06b..5e2f9f51d7a 100644
--- a/extern/draco/dracoenc/src/draco/io/mesh_io.cc
+++ b/extern/draco/dracoenc/src/draco/io/mesh_io.cc
@@ -16,37 +16,33 @@
#include <fstream>
+#include "draco/io/file_utils.h"
#include "draco/io/obj_decoder.h"
-#include "draco/io/parser_utils.h"
#include "draco/io/ply_decoder.h"
namespace draco {
-namespace {
-
-// Returns the file extension in lowercase if present, else ""
-inline std::string LowercaseFileExtension(const std::string &filename) {
- size_t pos = filename.find_last_of('.');
- if (pos == std::string::npos || pos >= filename.length() - 1)
- return "";
- return parser::ToLower(filename.substr(pos + 1));
-}
-
-} // namespace
-
StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name) {
- return ReadMeshFromFile(file_name, false);
+ const Options options;
+ return ReadMeshFromFile(file_name, options);
}
StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name,
bool use_metadata) {
+ Options options;
+ options.SetBool("use_metadata", use_metadata);
+ return ReadMeshFromFile(file_name, options);
+}
+
+StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name,
+ const Options &options) {
std::unique_ptr<Mesh> mesh(new Mesh());
// Analyze file extension.
const std::string extension = LowercaseFileExtension(file_name);
if (extension == "obj") {
// Wavefront OBJ file format.
ObjDecoder obj_decoder;
- obj_decoder.set_use_metadata(use_metadata);
+ obj_decoder.set_use_metadata(options.GetBool("use_metadata", false));
const Status obj_status = obj_decoder.DecodeFromFile(file_name, mesh.get());
if (!obj_status.ok())
return obj_status;
@@ -55,8 +51,7 @@ StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name,
if (extension == "ply") {
// Wavefront PLY file format.
PlyDecoder ply_decoder;
- if (!ply_decoder.DecodeFromFile(file_name, mesh.get()))
- return Status(Status::ERROR, "Unknown error.");
+ DRACO_RETURN_IF_ERROR(ply_decoder.DecodeFromFile(file_name, mesh.get()));
return std::move(mesh);
}
@@ -64,9 +59,9 @@ StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name,
// draco encoding methods.
std::ifstream is(file_name.c_str(), std::ios::binary);
if (!is)
- return Status(Status::ERROR, "Invalid input stream.");
+ return Status(Status::DRACO_ERROR, "Invalid input stream.");
if (!ReadMeshFromStream(&mesh, is).good())
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Unknown error."); // Error reading the stream.
return std::move(mesh);
}
diff --git a/extern/draco/dracoenc/src/draco/io/mesh_io.h b/extern/draco/dracoenc/src/draco/io/mesh_io.h
index 7649a736265..15cfbb30b97 100644
--- a/extern/draco/dracoenc/src/draco/io/mesh_io.h
+++ b/extern/draco/dracoenc/src/draco/io/mesh_io.h
@@ -18,6 +18,7 @@
#include "draco/compression/config/compression_shared.h"
#include "draco/compression/decode.h"
#include "draco/compression/expert_encode.h"
+#include "draco/core/options.h"
namespace draco {
@@ -89,6 +90,13 @@ StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name);
StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name,
bool use_metadata);
+// Reads a mesh from a file. Reading is configured with |options|:
+// use_metadata : Read obj file info like material names and object names into
+// metadata. Default is false.
+// Returns nullptr with an error status if the decoding failed.
+StatusOr<std::unique_ptr<Mesh>> ReadMeshFromFile(const std::string &file_name,
+ const Options &options);
+
} // namespace draco
#endif // DRACO_MESH_MESH_IO_H_
diff --git a/extern/draco/dracoenc/src/draco/io/obj_decoder.cc b/extern/draco/dracoenc/src/draco/io/obj_decoder.cc
index 5aaa9f72888..88f470f8b4a 100644
--- a/extern/draco/dracoenc/src/draco/io/obj_decoder.cc
+++ b/extern/draco/dracoenc/src/draco/io/obj_decoder.cc
@@ -18,6 +18,7 @@
#include <cmath>
#include <fstream>
+#include "draco/io/file_utils.h"
#include "draco/io/parser_utils.h"
#include "draco/metadata/geometry_metadata.h"
@@ -103,12 +104,12 @@ Status ObjDecoder::DecodeInternal() {
// Ensure the number of all entries is same for all attributes.
if (num_positions_ == 0)
- return Status(Status::ERROR, "No position attribute");
+ return Status(Status::DRACO_ERROR, "No position attribute");
if (num_tex_coords_ > 0 && num_tex_coords_ != num_positions_)
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Invalid number of texture coordinates for a point cloud");
if (num_normals_ > 0 && num_normals_ != num_positions_)
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Invalid number of normals for a point cloud");
out_mesh_ = nullptr; // Treat the output geometry as a point cloud.
@@ -151,12 +152,13 @@ Status ObjDecoder::DecodeInternal() {
}
if (num_materials_ > 0 && num_obj_faces_ > 0) {
GeometryAttribute va;
+ const auto geometry_attribute_type = GeometryAttribute::GENERIC;
if (num_materials_ < 256) {
- va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT8, false, 1, 0);
+ va.Init(geometry_attribute_type, nullptr, 1, DT_UINT8, false, 1, 0);
} else if (num_materials_ < (1 << 16)) {
- va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT16, false, 2, 0);
+ va.Init(geometry_attribute_type, nullptr, 1, DT_UINT16, false, 2, 0);
} else {
- va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT32, false, 4, 0);
+ va.Init(geometry_attribute_type, nullptr, 1, DT_UINT32, false, 4, 0);
}
material_att_id_ =
out_point_cloud_->AddAttribute(va, false, num_materials_);
@@ -234,10 +236,13 @@ Status ObjDecoder::DecodeInternal() {
out_mesh_->SetFace(i, face);
}
}
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
if (deduplicate_input_values_) {
out_point_cloud_->DeduplicateAttributeValues();
}
+#endif
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
out_point_cloud_->DeduplicatePointIds();
#endif
return status;
@@ -298,7 +303,7 @@ bool ObjDecoder::ParseVertexPosition(Status *status) {
for (int i = 0; i < 3; ++i) {
parser::SkipWhitespace(buffer());
if (!parser::ParseFloat(buffer(), val + i)) {
- *status = Status(Status::ERROR, "Failed to parse a float number");
+ *status = Status(Status::DRACO_ERROR, "Failed to parse a float number");
// The definition is processed so return true.
return true;
}
@@ -326,7 +331,7 @@ bool ObjDecoder::ParseNormal(Status *status) {
for (int i = 0; i < 3; ++i) {
parser::SkipWhitespace(buffer());
if (!parser::ParseFloat(buffer(), val + i)) {
- *status = Status(Status::ERROR, "Failed to parse a float number");
+ *status = Status(Status::DRACO_ERROR, "Failed to parse a float number");
// The definition is processed so return true.
return true;
}
@@ -354,7 +359,7 @@ bool ObjDecoder::ParseTexCoord(Status *status) {
for (int i = 0; i < 2; ++i) {
parser::SkipWhitespace(buffer());
if (!parser::ParseFloat(buffer(), val + i)) {
- *status = Status(Status::ERROR, "Failed to parse a float number");
+ *status = Status(Status::DRACO_ERROR, "Failed to parse a float number");
// The definition is processed so return true.
return true;
}
@@ -385,7 +390,7 @@ bool ObjDecoder::ParseFace(Status *status) {
if (i == 3) {
break; // It's OK if there is no fourth vertex index.
}
- *status = Status(Status::ERROR, "Failed to parse vertex indices");
+ *status = Status(Status::DRACO_ERROR, "Failed to parse vertex indices");
return true;
}
++num_valid_indices;
@@ -430,7 +435,8 @@ bool ObjDecoder::ParseFace(Status *status) {
}
}
if (num_indices < 3 || num_indices > 4) {
- *status = Status(Status::ERROR, "Invalid number of indices on a face");
+ *status =
+ Status(Status::DRACO_ERROR, "Invalid number of indices on a face");
return false;
}
// Either one or two new triangles.
@@ -455,7 +461,7 @@ bool ObjDecoder::ParseMaterialLib(Status *status) {
parser::SkipWhitespace(&line_buffer);
material_file_name_.clear();
if (!parser::ParseString(&line_buffer, &material_file_name_)) {
- *status = Status(Status::ERROR, "Failed to parse material file name");
+ *status = Status(Status::DRACO_ERROR, "Failed to parse material file name");
return true;
}
parser::SkipLine(&line_buffer);
@@ -492,6 +498,7 @@ bool ObjDecoder::ParseMaterial(Status * /* status */) {
// will be added to the list.
last_material_id_ = num_materials_;
material_name_to_id_[mat_name] = num_materials_++;
+
return true;
}
last_material_id_ = it->second;
@@ -626,15 +633,7 @@ void ObjDecoder::MapPointToVertexIndices(
bool ObjDecoder::ParseMaterialFile(const std::string &file_name,
Status *status) {
- // Get the correct path to the |file_name| using the folder from
- // |input_file_name_| as the root folder.
- const auto pos = input_file_name_.find_last_of("/\\");
- std::string full_path;
- if (pos != std::string::npos) {
- full_path = input_file_name_.substr(0, pos + 1);
- }
- full_path += file_name;
-
+ const std::string full_path = GetFullPath(file_name, input_file_name_);
std::ifstream file(full_path, std::ios::binary);
if (!file)
return false;
@@ -676,15 +675,14 @@ bool ObjDecoder::ParseMaterialFileDefinition(Status * /* status */) {
std::string str;
if (!parser::ParseString(buffer(), &str))
return false;
- if (str.compare("newmtl") == 0) {
+ if (str == "newmtl") {
parser::SkipWhitespace(buffer());
parser::ParseLine(buffer(), &str);
- if (str.length() == 0)
+ if (str.empty())
return false;
// Add new material to our map.
material_name_to_id_[str] = num_materials_++;
}
- parser::SkipLine(buffer());
return true;
}
diff --git a/extern/draco/dracoenc/src/draco/io/obj_encoder.h b/extern/draco/dracoenc/src/draco/io/obj_encoder.h
index 352a04774c2..509d39baf39 100644
--- a/extern/draco/dracoenc/src/draco/io/obj_encoder.h
+++ b/extern/draco/dracoenc/src/draco/io/obj_encoder.h
@@ -15,6 +15,8 @@
#ifndef DRACO_IO_OBJ_ENCODER_H_
#define DRACO_IO_OBJ_ENCODER_H_
+#include <unordered_map>
+
#include "draco/core/encoder_buffer.h"
#include "draco/mesh/mesh.h"
diff --git a/extern/draco/dracoenc/src/draco/io/parser_utils.cc b/extern/draco/dracoenc/src/draco/io/parser_utils.cc
index e68abb1f263..0a22ba114ab 100644
--- a/extern/draco/dracoenc/src/draco/io/parser_utils.cc
+++ b/extern/draco/dracoenc/src/draco/io/parser_utils.cc
@@ -128,7 +128,7 @@ bool ParseFloat(DecoderBuffer *buffer, float *value) {
return false;
// Apply exponent scaling to value.
- v *= pow(10.0, exponent);
+ v *= pow(static_cast<double>(10.0), exponent);
}
}
diff --git a/extern/draco/dracoenc/src/draco/io/ply_decoder.cc b/extern/draco/dracoenc/src/draco/io/ply_decoder.cc
index 01a97e3dacc..69a1c546cf7 100644
--- a/extern/draco/dracoenc/src/draco/io/ply_decoder.cc
+++ b/extern/draco/dracoenc/src/draco/io/ply_decoder.cc
@@ -17,28 +17,30 @@
#include <fstream>
#include "draco/core/macros.h"
+#include "draco/core/status.h"
#include "draco/io/ply_property_reader.h"
namespace draco {
PlyDecoder::PlyDecoder() : out_mesh_(nullptr), out_point_cloud_(nullptr) {}
-bool PlyDecoder::DecodeFromFile(const std::string &file_name, Mesh *out_mesh) {
+Status PlyDecoder::DecodeFromFile(const std::string &file_name,
+ Mesh *out_mesh) {
out_mesh_ = out_mesh;
return DecodeFromFile(file_name, static_cast<PointCloud *>(out_mesh));
}
-bool PlyDecoder::DecodeFromFile(const std::string &file_name,
- PointCloud *out_point_cloud) {
+Status PlyDecoder::DecodeFromFile(const std::string &file_name,
+ PointCloud *out_point_cloud) {
std::ifstream file(file_name, std::ios::binary);
if (!file)
- return false;
+ return Status(Status::IO_ERROR, "Couldn't open file");
// Read the whole file into a buffer.
auto pos0 = file.tellg();
file.seekg(0, std::ios::end);
auto file_size = file.tellg() - pos0;
if (file_size == 0)
- return false;
+ return Status(Status::IO_ERROR, "Zero file size");
file.seekg(0, std::ios::beg);
std::vector<char> data(file_size);
file.read(&data[0], file_size);
@@ -47,44 +49,46 @@ bool PlyDecoder::DecodeFromFile(const std::string &file_name,
return DecodeFromBuffer(&buffer_, out_point_cloud);
}
-bool PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh) {
+Status PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh) {
out_mesh_ = out_mesh;
return DecodeFromBuffer(buffer, static_cast<PointCloud *>(out_mesh));
}
-bool PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer,
- PointCloud *out_point_cloud) {
+Status PlyDecoder::DecodeFromBuffer(DecoderBuffer *buffer,
+ PointCloud *out_point_cloud) {
out_point_cloud_ = out_point_cloud;
buffer_.Init(buffer->data_head(), buffer->remaining_size());
return DecodeInternal();
}
-bool PlyDecoder::DecodeInternal() {
+Status PlyDecoder::DecodeInternal() {
PlyReader ply_reader;
- if (!ply_reader.Read(buffer()))
- return false;
+ DRACO_RETURN_IF_ERROR(ply_reader.Read(buffer()));
// First, decode the connectivity data.
- if (out_mesh_ && !DecodeFaceData(ply_reader.GetElementByName("face")))
- return false;
+ if (out_mesh_)
+ DRACO_RETURN_IF_ERROR(DecodeFaceData(ply_reader.GetElementByName("face")));
// Decode all attributes.
- if (!DecodeVertexData(ply_reader.GetElementByName("vertex")))
- return false;
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+ DRACO_RETURN_IF_ERROR(
+ DecodeVertexData(ply_reader.GetElementByName("vertex")));
// In case there are no faces this is just a point cloud which does
// not require deduplication.
if (out_mesh_ && out_mesh_->num_faces() != 0) {
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
if (!out_point_cloud_->DeduplicateAttributeValues())
- return false;
+ return Status(Status::DRACO_ERROR,
+ "Could not deduplicate attribute values");
+#endif
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
out_point_cloud_->DeduplicatePointIds();
- }
#endif
- return true;
+ }
+ return OkStatus();
}
-bool PlyDecoder::DecodeFaceData(const PlyElement *face_element) {
+Status PlyDecoder::DecodeFaceData(const PlyElement *face_element) {
// We accept point clouds now.
if (face_element == nullptr) {
- return true;
+ return Status(Status::INVALID_PARAMETER, "face_element is null");
}
const int64_t num_faces = face_element->num_entries();
out_mesh_->SetNumFaces(num_faces);
@@ -95,7 +99,7 @@ bool PlyDecoder::DecodeFaceData(const PlyElement *face_element) {
vertex_indices = face_element->GetPropertyByName("vertex_index");
}
if (vertex_indices == nullptr || !vertex_indices->is_list()) {
- return false; // No faces defined.
+ return Status(Status::DRACO_ERROR, "No faces defined");
}
PlyPropertyReader<PointIndex::ValueType> vertex_index_reader(vertex_indices);
@@ -114,7 +118,7 @@ bool PlyDecoder::DecodeFaceData(const PlyElement *face_element) {
face_index++;
}
out_mesh_->SetNumFaces(face_index.value());
- return true;
+ return OkStatus();
}
template <typename DataTypeT>
@@ -138,9 +142,9 @@ bool PlyDecoder::ReadPropertiesToAttribute(
return true;
}
-bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
+Status PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
if (vertex_element == nullptr)
- return false;
+ return Status(Status::INVALID_PARAMETER, "vertex_element is null");
// TODO(ostava): For now, try to load x,y,z vertices and red,green,blue,alpha
// colors. We need to add other properties later.
const PlyProperty *const x_prop = vertex_element->GetPropertyByName("x");
@@ -149,7 +153,7 @@ bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
if (!x_prop || !y_prop || !z_prop) {
// Currently, we require 3 vertex coordinates (this should be generalized
// later on).
- return false;
+ return Status(Status::INVALID_PARAMETER, "x, y, or z property is missing");
}
const PointIndex::ValueType num_vertices = vertex_element->num_entries();
out_point_cloud_->set_num_points(num_vertices);
@@ -158,12 +162,14 @@ bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
// All properties must have the same type.
if (x_prop->data_type() != y_prop->data_type() ||
y_prop->data_type() != z_prop->data_type()) {
- return false;
+ return Status(Status::INVALID_PARAMETER,
+ "x, y, and z properties must have the same type");
}
// TODO(ostava): For now assume the position types are float32 or int32.
const DataType dt = x_prop->data_type();
if (dt != DT_FLOAT32 && dt != DT_INT32)
- return false;
+ return Status(Status::INVALID_PARAMETER,
+ "x, y, and z properties must be of type float32 or int32");
GeometryAttribute va;
va.Init(GeometryAttribute::POSITION, nullptr, 3, dt, false,
@@ -232,7 +238,8 @@ bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
// TODO(ostava): For now ensure the data type of all components is uint8.
DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8);
if (p->data_type() != DT_UINT8)
- return false;
+ return Status(Status::INVALID_PARAMETER,
+ "Type of 'red' property must be uint8");
color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>(
new PlyPropertyReader<uint8_t>(p)));
}
@@ -241,7 +248,8 @@ bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
// TODO(ostava): For now ensure the data type of all components is uint8.
DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8);
if (p->data_type() != DT_UINT8)
- return false;
+ return Status(Status::INVALID_PARAMETER,
+ "Type of 'green' property must be uint8");
color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>(
new PlyPropertyReader<uint8_t>(p)));
}
@@ -250,7 +258,8 @@ bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
// TODO(ostava): For now ensure the data type of all components is uint8.
DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8);
if (p->data_type() != DT_UINT8)
- return false;
+ return Status(Status::INVALID_PARAMETER,
+ "Type of 'blue' property must be uint8");
color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>(
new PlyPropertyReader<uint8_t>(p)));
}
@@ -259,7 +268,8 @@ bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
// TODO(ostava): For now ensure the data type of all components is uint8.
DRACO_DCHECK_EQ(true, p->data_type() == DT_UINT8);
if (p->data_type() != DT_UINT8)
- return false;
+ return Status(Status::INVALID_PARAMETER,
+ "Type of 'alpha' property must be uint8");
color_readers.push_back(std::unique_ptr<PlyPropertyReader<uint8_t>>(
new PlyPropertyReader<uint8_t>(p)));
}
@@ -279,7 +289,7 @@ bool PlyDecoder::DecodeVertexData(const PlyElement *vertex_element) {
}
}
- return true;
+ return OkStatus();
}
} // namespace draco
diff --git a/extern/draco/dracoenc/src/draco/io/ply_decoder.h b/extern/draco/dracoenc/src/draco/io/ply_decoder.h
index 60a48de730e..9e667ab192f 100644
--- a/extern/draco/dracoenc/src/draco/io/ply_decoder.h
+++ b/extern/draco/dracoenc/src/draco/io/ply_decoder.h
@@ -20,6 +20,7 @@
#include "draco/draco_features.h"
#include "draco/core/decoder_buffer.h"
+#include "draco/core/status.h"
#include "draco/io/ply_reader.h"
#include "draco/mesh/mesh.h"
@@ -35,21 +36,20 @@ class PlyDecoder {
PlyDecoder();
// Decodes an obj file stored in the input file.
- // Returns nullptr if the decoding failed.
- bool DecodeFromFile(const std::string &file_name, Mesh *out_mesh);
- bool DecodeFromFile(const std::string &file_name,
- PointCloud *out_point_cloud);
+ Status DecodeFromFile(const std::string &file_name, Mesh *out_mesh);
+ Status DecodeFromFile(const std::string &file_name,
+ PointCloud *out_point_cloud);
- bool DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh);
- bool DecodeFromBuffer(DecoderBuffer *buffer, PointCloud *out_point_cloud);
+ Status DecodeFromBuffer(DecoderBuffer *buffer, Mesh *out_mesh);
+ Status DecodeFromBuffer(DecoderBuffer *buffer, PointCloud *out_point_cloud);
protected:
- bool DecodeInternal();
+ Status DecodeInternal();
DecoderBuffer *buffer() { return &buffer_; }
private:
- bool DecodeFaceData(const PlyElement *face_element);
- bool DecodeVertexData(const PlyElement *vertex_element);
+ Status DecodeFaceData(const PlyElement *face_element);
+ Status DecodeVertexData(const PlyElement *vertex_element);
template <typename DataTypeT>
bool ReadPropertiesToAttribute(
diff --git a/extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc b/extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc
index 39a52274ce6..647324ea904 100644
--- a/extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc
+++ b/extern/draco/dracoenc/src/draco/io/ply_decoder_test.cc
@@ -26,8 +26,11 @@ class PlyDecoderTest : public ::testing::Test {
const std::string path = GetTestFileFullPath(file_name);
PlyDecoder decoder;
std::unique_ptr<Geometry> geometry(new Geometry());
- if (!decoder.DecodeFromFile(path, geometry.get()))
+ Status status = decoder.DecodeFromFile(path, geometry.get());
+ if (!status.ok()) {
+ LOG(DRACO_ERROR) << "Failed to decode " << file_name << ": " << status;
return nullptr;
+ }
return geometry;
}
diff --git a/extern/draco/dracoenc/src/draco/io/ply_reader.cc b/extern/draco/dracoenc/src/draco/io/ply_reader.cc
index f924550e23f..772c4381176 100644
--- a/extern/draco/dracoenc/src/draco/io/ply_reader.cc
+++ b/extern/draco/dracoenc/src/draco/io/ply_reader.cc
@@ -17,6 +17,7 @@
#include <array>
#include <regex>
+#include "draco/core/status.h"
#include "draco/io/parser_utils.h"
#include "draco/io/ply_property_writer.h"
@@ -34,13 +35,11 @@ PlyElement::PlyElement(const std::string &name, int64_t num_entries)
PlyReader::PlyReader() : format_(kLittleEndian) {}
-bool PlyReader::Read(DecoderBuffer *buffer) {
- error_message_.clear();
+Status PlyReader::Read(DecoderBuffer *buffer) {
std::string value;
// The first line needs to by "ply".
if (!parser::ParseString(buffer, &value) || value != "ply") {
- error_message_ = "Not a valid ply file.";
- return false;
+ return Status(Status::INVALID_PARAMETER, "Not a valid ply file");
}
parser::SkipLine(buffer);
@@ -52,52 +51,49 @@ bool PlyReader::Read(DecoderBuffer *buffer) {
format = words[1];
version = words[2];
} else {
- error_message_ = "Missing or wrong format line.";
- return false;
+ return Status(Status::INVALID_PARAMETER, "Missing or wrong format line");
}
if (version != "1.0") {
- error_message_ = "Unsupported PLY version.";
- return false; // Wrong version.
+ return Status(Status::UNSUPPORTED_VERSION, "Unsupported PLY version");
}
if (format == "binary_big_endian") {
- error_message_ =
- "Unsupported format. Currently we support only ascii and"
- " binary_little_endian format.";
- return false;
+ return Status(Status::UNSUPPORTED_VERSION,
+ "Unsupported format. Currently we support only ascii and"
+ " binary_little_endian format.");
}
if (format == "ascii") {
format_ = kAscii;
} else {
format_ = kLittleEndian;
}
- if (!ParseHeader(buffer))
- return false;
- if (!ParsePropertiesData(buffer))
- return false;
- return true;
+ DRACO_RETURN_IF_ERROR(ParseHeader(buffer));
+ if (!ParsePropertiesData(buffer)) {
+ return Status(Status::INVALID_PARAMETER, "Couldn't parse properties");
+ }
+ return OkStatus();
}
-bool PlyReader::ParseHeader(DecoderBuffer *buffer) {
- while (error_message_.length() == 0 && !ParseEndHeader(buffer)) {
+Status PlyReader::ParseHeader(DecoderBuffer *buffer) {
+ while (true) {
+ DRACO_ASSIGN_OR_RETURN(bool end, ParseEndHeader(buffer));
+ if (end)
+ break;
if (ParseElement(buffer))
continue;
- if (ParseProperty(buffer))
+ DRACO_ASSIGN_OR_RETURN(bool property_parsed, ParseProperty(buffer));
+ if (property_parsed)
continue;
parser::SkipLine(buffer);
}
- if (error_message_.length() > 0) {
- printf("ERROR %s\n", error_message_.c_str());
- return false;
- }
- return true;
+ return OkStatus();
}
-bool PlyReader::ParseEndHeader(DecoderBuffer *buffer) {
+StatusOr<bool> PlyReader::ParseEndHeader(DecoderBuffer *buffer) {
parser::SkipWhitespace(buffer);
std::array<char, 10> c;
if (!buffer->Peek(&c)) {
- error_message_ = "End of file reached before the end_header.";
- return false;
+ return Status(Status::INVALID_PARAMETER,
+ "End of file reached before the end_header");
}
if (std::memcmp(&c[0], "end_header", 10) != 0)
return false;
@@ -126,7 +122,7 @@ bool PlyReader::ParseElement(DecoderBuffer *buffer) {
return true;
}
-bool PlyReader::ParseProperty(DecoderBuffer *buffer) {
+StatusOr<bool> PlyReader::ParseProperty(DecoderBuffer *buffer) {
if (elements_.empty())
return false; // Ignore properties if there is no active element.
DecoderBuffer line_buffer(*buffer);
@@ -154,15 +150,13 @@ bool PlyReader::ParseProperty(DecoderBuffer *buffer) {
}
const DataType data_type = GetDataTypeFromString(data_type_str);
if (data_type == DT_INVALID) {
- error_message_ = "Wrong property data type.";
- return true; // Parsed.
+ return Status(Status::INVALID_PARAMETER, "Wrong property data type");
}
DataType list_type = DT_INVALID;
if (property_list_search) {
list_type = GetDataTypeFromString(list_type_str);
if (list_type == DT_INVALID) {
- error_message_ = "Wrong property list type.";
- return true; // Parsed.
+ return Status(Status::INVALID_PARAMETER, "Wrong property list type");
}
}
elements_.back().AddProperty(
diff --git a/extern/draco/dracoenc/src/draco/io/ply_reader.h b/extern/draco/dracoenc/src/draco/io/ply_reader.h
index 8d0f21ff1cb..845ef2326ae 100644
--- a/extern/draco/dracoenc/src/draco/io/ply_reader.h
+++ b/extern/draco/dracoenc/src/draco/io/ply_reader.h
@@ -26,6 +26,8 @@
#include "draco/core/decoder_buffer.h"
#include "draco/core/draco_types.h"
+#include "draco/core/status.h"
+#include "draco/core/status_or.h"
namespace draco {
@@ -111,7 +113,7 @@ class PlyElement {
class PlyReader {
public:
PlyReader();
- bool Read(DecoderBuffer *buffer);
+ Status Read(DecoderBuffer *buffer);
const PlyElement *GetElementByName(const std::string &name) const {
const auto it = element_index_.find(name);
@@ -128,10 +130,10 @@ class PlyReader {
private:
enum Format { kLittleEndian = 0, kAscii };
- bool ParseHeader(DecoderBuffer *buffer);
- bool ParseEndHeader(DecoderBuffer *buffer);
+ Status ParseHeader(DecoderBuffer *buffer);
+ StatusOr<bool> ParseEndHeader(DecoderBuffer *buffer);
bool ParseElement(DecoderBuffer *buffer);
- bool ParseProperty(DecoderBuffer *buffer);
+ StatusOr<bool> ParseProperty(DecoderBuffer *buffer);
bool ParsePropertiesData(DecoderBuffer *buffer);
bool ParseElementData(DecoderBuffer *buffer, int element_index);
bool ParseElementDataAscii(DecoderBuffer *buffer, int element_index);
@@ -141,7 +143,6 @@ class PlyReader {
DataType GetDataTypeFromString(const std::string &name) const;
std::vector<PlyElement> elements_;
- std::string error_message_;
std::map<std::string, int> element_index_;
Format format_;
};
diff --git a/extern/draco/dracoenc/src/draco/io/ply_reader_test.cc b/extern/draco/dracoenc/src/draco/io/ply_reader_test.cc
index 98f9c601971..6804dc33de3 100644
--- a/extern/draco/dracoenc/src/draco/io/ply_reader_test.cc
+++ b/extern/draco/dracoenc/src/draco/io/ply_reader_test.cc
@@ -45,7 +45,8 @@ TEST_F(PlyReaderTest, TestReader) {
DecoderBuffer buf;
buf.Init(data.data(), data.size());
PlyReader reader;
- ASSERT_TRUE(reader.Read(&buf));
+ Status status = reader.Read(&buf);
+ ASSERT_TRUE(status.ok()) << status;
ASSERT_EQ(reader.num_elements(), 2);
ASSERT_EQ(reader.element(0).num_properties(), 7);
ASSERT_EQ(reader.element(1).num_properties(), 1);
@@ -68,13 +69,15 @@ TEST_F(PlyReaderTest, TestReaderAscii) {
DecoderBuffer buf;
buf.Init(data.data(), data.size());
PlyReader reader;
- ASSERT_TRUE(reader.Read(&buf));
+ Status status = reader.Read(&buf);
+ ASSERT_TRUE(status.ok()) << status;
const std::string file_name_ascii = "test_pos_color_ascii.ply";
const std::vector<char> data_ascii = ReadPlyFile(file_name_ascii);
buf.Init(data_ascii.data(), data_ascii.size());
PlyReader reader_ascii;
- ASSERT_TRUE(reader_ascii.Read(&buf));
+ status = reader_ascii.Read(&buf);
+ ASSERT_TRUE(status.ok()) << status;
ASSERT_EQ(reader.num_elements(), reader_ascii.num_elements());
ASSERT_EQ(reader.element(0).num_properties(),
reader_ascii.element(0).num_properties());
@@ -97,7 +100,8 @@ TEST_F(PlyReaderTest, TestReaderExtraWhitespace) {
DecoderBuffer buf;
buf.Init(data.data(), data.size());
PlyReader reader;
- ASSERT_TRUE(reader.Read(&buf));
+ Status status = reader.Read(&buf);
+ ASSERT_TRUE(status.ok()) << status;
ASSERT_EQ(reader.num_elements(), 2);
ASSERT_EQ(reader.element(0).num_properties(), 7);
@@ -121,7 +125,8 @@ TEST_F(PlyReaderTest, TestReaderMoreDataTypes) {
DecoderBuffer buf;
buf.Init(data.data(), data.size());
PlyReader reader;
- ASSERT_TRUE(reader.Read(&buf));
+ Status status = reader.Read(&buf);
+ ASSERT_TRUE(status.ok()) << status;
ASSERT_EQ(reader.num_elements(), 2);
ASSERT_EQ(reader.element(0).num_properties(), 7);
diff --git a/extern/draco/dracoenc/src/draco/io/point_cloud_io.cc b/extern/draco/dracoenc/src/draco/io/point_cloud_io.cc
index 068f7a139e4..e91142eaaea 100644
--- a/extern/draco/dracoenc/src/draco/io/point_cloud_io.cc
+++ b/extern/draco/dracoenc/src/draco/io/point_cloud_io.cc
@@ -40,8 +40,7 @@ StatusOr<std::unique_ptr<PointCloud>> ReadPointCloudFromFile(
if (extension == ".ply") {
// Wavefront PLY file format.
PlyDecoder ply_decoder;
- if (!ply_decoder.DecodeFromFile(file_name, pc.get()))
- return Status(Status::ERROR, "Unknown error.");
+ DRACO_RETURN_IF_ERROR(ply_decoder.DecodeFromFile(file_name, pc.get()));
return std::move(pc);
}
@@ -49,9 +48,9 @@ StatusOr<std::unique_ptr<PointCloud>> ReadPointCloudFromFile(
// draco encoding methods.
std::ifstream is(file_name.c_str(), std::ios::binary);
if (!is)
- return Status(Status::ERROR, "Invalid input stream.");
+ return Status(Status::DRACO_ERROR, "Invalid input stream.");
if (!ReadPointCloudFromStream(&pc, is).good())
- return Status(Status::ERROR,
+ return Status(Status::DRACO_ERROR,
"Unknown error."); // Error reading the stream.
return std::move(pc);
}
diff --git a/extern/draco/dracoenc/src/draco/mesh/corner_table.cc b/extern/draco/dracoenc/src/draco/mesh/corner_table.cc
index e4608fe8f9d..dcfd7967c0b 100644
--- a/extern/draco/dracoenc/src/draco/mesh/corner_table.cc
+++ b/extern/draco/dracoenc/src/draco/mesh/corner_table.cc
@@ -16,6 +16,7 @@
#include <limits>
+#include "draco/attributes/geometry_indices.h"
#include "draco/mesh/corner_table_iterators.h"
namespace draco {
@@ -46,6 +47,8 @@ bool CornerTable::Init(const IndexTypeVector<FaceIndex, FaceType> &faces) {
int num_vertices = -1;
if (!ComputeOppositeCorners(&num_vertices))
return false;
+ if (!BreakNonManifoldEdges())
+ return false;
if (!ComputeVertexCorners(num_vertices))
return false;
return true;
@@ -193,6 +196,110 @@ bool CornerTable::ComputeOppositeCorners(int *num_vertices) {
return true;
}
+bool CornerTable::BreakNonManifoldEdges() {
+ // This function detects and breaks non-manifold edges that are caused by
+ // folds in 1-ring neighborhood around a vertex. Non-manifold edges can occur
+ // when the 1-ring surface around a vertex self-intersects in a common edge.
+ // For example imagine a surface around a pivot vertex 0, where the 1-ring
+ // is defined by vertices |1, 2, 3, 1, 4|. The surface passes edge <0, 1>
+ // twice which would result in a non-manifold edge that needs to be broken.
+ // For now all faces connected to these non-manifold edges are disconnected
+ // resulting in open boundaries on the mesh. New vertices will be created
+ // automatically for each new disjoint patch in the ComputeVertexCorners()
+ // method.
+ // Note that all other non-manifold edges are implicitly handled by the
+ // function ComputeVertexCorners() that automatically creates new vertices
+ // on disjoint 1-ring surface patches.
+
+ std::vector<bool> visited_corners(num_corners(), false);
+ std::vector<std::pair<VertexIndex, CornerIndex>> sink_vertices;
+ bool mesh_connectivity_updated = false;
+ do {
+ mesh_connectivity_updated = false;
+ for (CornerIndex c(0); c < num_corners(); ++c) {
+ if (visited_corners[c.value()])
+ continue;
+ sink_vertices.clear();
+
+ // First swing all the way to find the left-most corner connected to the
+ // corner's vertex.
+ CornerIndex first_c = c;
+ CornerIndex current_c = c;
+ CornerIndex next_c;
+ while (next_c = SwingLeft(current_c),
+ next_c != first_c && next_c != kInvalidCornerIndex &&
+ !visited_corners[next_c.value()]) {
+ current_c = next_c;
+ }
+
+ first_c = current_c;
+
+ // Swing right from the first corner and check if all visited edges
+ // are unique.
+ do {
+ visited_corners[current_c.value()] = true;
+ // Each new edge is defined by the pivot vertex (that is the same for
+ // all faces) and by the sink vertex (that is the |next| vertex from the
+ // currently processed pivot corner. I.e., each edge is uniquely defined
+ // by the sink vertex index.
+ const CornerIndex sink_c = Next(current_c);
+ const VertexIndex sink_v = corner_to_vertex_map_[sink_c];
+
+ // Corner that defines the edge on the face.
+ const CornerIndex edge_corner = Previous(current_c);
+ bool vertex_connectivity_updated = false;
+ // Go over all processed edges (sink vertices). If the current sink
+ // vertex has been already encountered before it may indicate a
+ // non-manifold edge that needs to be broken.
+ for (auto &&attached_sink_vertex : sink_vertices) {
+ if (attached_sink_vertex.first == sink_v) {
+ // Sink vertex has been already processed.
+ const CornerIndex other_edge_corner = attached_sink_vertex.second;
+ const CornerIndex opp_edge_corner = Opposite(edge_corner);
+
+ if (opp_edge_corner == other_edge_corner) {
+ // We are closing the loop so no need to change the connectivity.
+ continue;
+ }
+
+ // Break the connectivity on the non-manifold edge.
+ // TODO(ostava): It may be possible to reconnect the faces in a way
+ // that the final surface would be manifold.
+ const CornerIndex opp_other_edge_corner =
+ Opposite(other_edge_corner);
+ if (opp_edge_corner != kInvalidCornerIndex)
+ SetOppositeCorner(opp_edge_corner, kInvalidCornerIndex);
+ if (opp_other_edge_corner != kInvalidCornerIndex)
+ SetOppositeCorner(opp_other_edge_corner, kInvalidCornerIndex);
+
+ SetOppositeCorner(edge_corner, kInvalidCornerIndex);
+ SetOppositeCorner(other_edge_corner, kInvalidCornerIndex);
+
+ vertex_connectivity_updated = true;
+ break;
+ }
+ }
+ if (vertex_connectivity_updated) {
+ // Because of the updated connectivity, not all corners connected to
+ // this vertex have been processed and we need to go over them again.
+ // TODO(ostava): This can be optimized as we don't really need to
+ // iterate over all corners.
+ mesh_connectivity_updated = true;
+ break;
+ }
+ // Insert new sink vertex information <sink vertex index, edge corner>.
+ std::pair<VertexIndex, CornerIndex> new_sink_vert;
+ new_sink_vert.first = corner_to_vertex_map_[Previous(current_c)];
+ new_sink_vert.second = sink_c;
+ sink_vertices.push_back(new_sink_vert);
+
+ current_c = SwingRight(current_c);
+ } while (current_c != first_c && current_c != kInvalidCornerIndex);
+ }
+ } while (mesh_connectivity_updated);
+ return true;
+}
+
bool CornerTable::ComputeVertexCorners(int num_vertices) {
DRACO_DCHECK(GetValenceCache().IsCacheEmpty());
num_original_vertices_ = num_vertices;
diff --git a/extern/draco/dracoenc/src/draco/mesh/corner_table.h b/extern/draco/dracoenc/src/draco/mesh/corner_table.h
index b916b995f66..704a7b1b5c4 100644
--- a/extern/draco/dracoenc/src/draco/mesh/corner_table.h
+++ b/extern/draco/dracoenc/src/draco/mesh/corner_table.h
@@ -51,7 +51,6 @@ namespace draco {
// non-manifold edges and vertices are automatically split.
class CornerTable {
public:
- // TODO(hemmer): rename to Face.
// Corner table face type.
typedef std::array<VertexIndex, 3> FaceType;
@@ -333,10 +332,14 @@ class CornerTable {
private:
// Computes opposite corners mapping from the data stored in
- // |corner_to_vertex_map_|. Any non-manifold edge will be split so the result
- // is always a 2-manifold surface.
+ // |corner_to_vertex_map_|.
bool ComputeOppositeCorners(int *num_vertices);
+ // Finds and breaks non-manifold edges in the 1-ring neighborhood around
+ // vertices (vertices themselves will be split in the ComputeVertexCorners()
+ // function if necessary).
+ bool BreakNonManifoldEdges();
+
// Computes the lookup map for going from a vertex to a corner. This method
// can handle non-manifold vertices by splitting them into multiple manifold
// vertices.
diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh.cc b/extern/draco/dracoenc/src/draco/mesh/mesh.cc
index dd37a88d1fa..a78a6ec96a8 100644
--- a/extern/draco/dracoenc/src/draco/mesh/mesh.cc
+++ b/extern/draco/dracoenc/src/draco/mesh/mesh.cc
@@ -27,7 +27,7 @@ using conditional_t = typename std::conditional<B, T, F>::type;
Mesh::Mesh() {}
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
void Mesh::ApplyPointIdDeduplication(
const IndexTypeVector<PointIndex, PointIndex> &id_map,
const std::vector<PointIndex> &unique_point_ids) {
diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh.h b/extern/draco/dracoenc/src/draco/mesh/mesh.h
index dd41f6cde4a..b8ca5353a81 100644
--- a/extern/draco/dracoenc/src/draco/mesh/mesh.h
+++ b/extern/draco/dracoenc/src/draco/mesh/mesh.h
@@ -17,11 +17,11 @@
#include <memory>
-#include "draco/draco_features.h"
-
#include "draco/attributes/geometry_indices.h"
#include "draco/core/hash_utils.h"
#include "draco/core/macros.h"
+#include "draco/core/status.h"
+#include "draco/draco_features.h"
#include "draco/point_cloud/point_cloud.h"
namespace draco {
@@ -109,7 +109,7 @@ class Mesh : public PointCloud {
};
protected:
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
// Extends the point deduplication to face corners. This method is called from
// the PointCloud::DeduplicatePointIds() and it remaps all point ids stored in
// |faces_| to the new deduplicated point ids using the map |id_map|.
diff --git a/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.h b/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.h
index fc038bd7445..b972109e679 100644
--- a/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.h
+++ b/extern/draco/dracoenc/src/draco/mesh/mesh_misc_functions.h
@@ -56,6 +56,25 @@ inline bool IsCornerOppositeToAttributeSeam(CornerIndex ci,
return false;
}
+// 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,
+ const std::array<float, 3> &barycentric_coord) {
+ const Mesh::Face &face = mesh.face(fi);
+ // Get values for all three corners of the face.
+ InterpolatedVectorT val[3];
+ for (int c = 0; c < 3; ++c) {
+ attribute.GetMappedValue(face[c], &(val[c][0]));
+ }
+ // Return an interpolated value.
+ return barycentric_coord[0] * val[0] + barycentric_coord[1] * val[1] +
+ barycentric_coord[2] * val[2];
+}
+
} // namespace draco
#endif // DRACO_MESH_MESH_MISC_FUNCTIONS_H_
diff --git a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.cc b/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.cc
index a21d5e77cf7..7a76745342b 100644
--- a/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.cc
+++ b/extern/draco/dracoenc/src/draco/mesh/triangle_soup_mesh_builder.cc
@@ -65,10 +65,12 @@ void TriangleSoupMeshBuilder::SetPerFaceAttributeValueForFace(
}
std::unique_ptr<Mesh> TriangleSoupMeshBuilder::Finalize() {
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
// First deduplicate attribute values.
if (!mesh_->DeduplicateAttributeValues())
return nullptr;
+#endif
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
// Also deduplicate vertex indices.
mesh_->DeduplicatePointIds();
#endif
diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata.h b/extern/draco/dracoenc/src/draco/metadata/metadata.h
index b4dd202c991..bf0be36f3b1 100644
--- a/extern/draco/dracoenc/src/draco/metadata/metadata.h
+++ b/extern/draco/dracoenc/src/draco/metadata/metadata.h
@@ -18,7 +18,7 @@
#include <cstring>
#include <memory>
#include <string>
-#include <unordered_map>
+#include <map>
#include <vector>
#include "draco/core/hash_utils.h"
@@ -101,27 +101,45 @@ class Metadata {
// accessing entries of common data types. For now, developers need to know
// the type of entries they are requesting.
void AddEntryInt(const std::string &name, int32_t value);
+
+ // Returns false if Metadata does not contain an entry with a key of |name|.
+ // This function does not guarantee that entry's type is int32_t.
bool GetEntryInt(const std::string &name, int32_t *value) const;
void AddEntryIntArray(const std::string &name,
const std::vector<int32_t> &value);
+
+ // Returns false if Metadata does not contain an entry with a key of |name|.
+ // This function does not guarantee that entry's type is a vector of int32_t.
bool GetEntryIntArray(const std::string &name,
std::vector<int32_t> *value) const;
void AddEntryDouble(const std::string &name, double value);
+
+ // Returns false if Metadata does not contain an entry with a key of |name|.
+ // This function does not guarantee that entry's type is double.
bool GetEntryDouble(const std::string &name, double *value) const;
void AddEntryDoubleArray(const std::string &name,
const std::vector<double> &value);
+
+ // Returns false if Metadata does not contain an entry with a key of |name|.
+ // This function does not guarantee that entry's type is a vector of double.
bool GetEntryDoubleArray(const std::string &name,
std::vector<double> *value) const;
void AddEntryString(const std::string &name, const std::string &value);
+
+ // Returns false if Metadata does not contain an entry with a key of |name|.
+ // This function does not guarantee that entry's type is std::string.
bool GetEntryString(const std::string &name, std::string *value) const;
// Add a blob of data as an entry.
void AddEntryBinary(const std::string &name,
const std::vector<uint8_t> &value);
+
+ // Returns false if Metadata does not contain an entry with a key of |name|.
+ // This function does not guarantee that entry's type is a vector of uint8_t.
bool GetEntryBinary(const std::string &name,
std::vector<uint8_t> *value) const;
@@ -132,10 +150,10 @@ class Metadata {
void RemoveEntry(const std::string &name);
int num_entries() const { return static_cast<int>(entries_.size()); }
- const std::unordered_map<std::string, EntryValue> &entries() const {
+ const std::map<std::string, EntryValue> &entries() const {
return entries_;
}
- const std::unordered_map<std::string, std::unique_ptr<Metadata>>
+ const std::map<std::string, std::unique_ptr<Metadata>>
&sub_metadatas() const {
return sub_metadatas_;
}
@@ -160,8 +178,8 @@ class Metadata {
return itr->second.GetValue(entry_value);
}
- std::unordered_map<std::string, EntryValue> entries_;
- std::unordered_map<std::string, std::unique_ptr<Metadata>> sub_metadatas_;
+ std::map<std::string, EntryValue> entries_;
+ std::map<std::string, std::unique_ptr<Metadata>> sub_metadatas_;
friend struct MetadataHasher;
};
diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.cc b/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.cc
index c98a334b003..6e85ce6f9d9 100644
--- a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/metadata/metadata_encoder.cc
@@ -20,8 +20,7 @@ namespace draco {
bool MetadataEncoder::EncodeMetadata(EncoderBuffer *out_buffer,
const Metadata *metadata) {
- const std::unordered_map<std::string, EntryValue> &entries =
- metadata->entries();
+ const std::map<std::string, EntryValue> &entries = metadata->entries();
// Encode number of entries.
EncodeVarint(static_cast<uint32_t>(metadata->num_entries()), out_buffer);
// Encode all entries.
@@ -33,8 +32,8 @@ bool MetadataEncoder::EncodeMetadata(EncoderBuffer *out_buffer,
EncodeVarint(data_size, out_buffer);
out_buffer->Encode(entry_value.data(), data_size);
}
- const std::unordered_map<std::string, std::unique_ptr<Metadata>>
- &sub_metadatas = metadata->sub_metadatas();
+ const std::map<std::string, std::unique_ptr<Metadata>> &sub_metadatas =
+ metadata->sub_metadatas();
// Encode number of sub-metadata
EncodeVarint(static_cast<uint32_t>(sub_metadatas.size()), out_buffer);
// Encode each sub-metadata
diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc b/extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc
index fbda6137c39..d8f7f2f6649 100644
--- a/extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc
+++ b/extern/draco/dracoenc/src/draco/metadata/metadata_encoder_test.cc
@@ -75,9 +75,9 @@ class MetadataEncoderTest : public ::testing::Test {
void CheckMetadatasAreEqual(const draco::Metadata &metadata0,
const draco::Metadata &metadata1) {
ASSERT_EQ(metadata0.num_entries(), metadata1.num_entries());
- const std::unordered_map<std::string, draco::EntryValue> &entries0 =
+ const std::map<std::string, draco::EntryValue> &entries0 =
metadata0.entries();
- const std::unordered_map<std::string, draco::EntryValue> &entries1 =
+ const std::map<std::string, draco::EntryValue> &entries1 =
metadata1.entries();
for (const auto &entry : entries0) {
const std::string &entry_name = entry.first;
@@ -90,7 +90,7 @@ class MetadataEncoderTest : public ::testing::Test {
// Check nested metadata.
ASSERT_EQ(metadata0.sub_metadatas().size(),
metadata1.sub_metadatas().size());
- const std::unordered_map<std::string, std::unique_ptr<draco::Metadata>>
+ const std::map<std::string, std::unique_ptr<draco::Metadata>>
&sub_metadatas0 = metadata0.sub_metadatas();
// Encode each sub-metadata
for (auto &&sub_metadata_entry0 : sub_metadatas0) {
diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.cc b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.cc
index 63eee27417e..9552654be16 100644
--- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.cc
+++ b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.cc
@@ -87,23 +87,32 @@ int PointCloud::AddAttribute(std::unique_ptr<PointAttribute> pa) {
int PointCloud::AddAttribute(
const GeometryAttribute &att, bool identity_mapping,
AttributeValueIndex::ValueType num_attribute_values) {
- const GeometryAttribute::Type type = att.attribute_type();
- if (type == GeometryAttribute::INVALID)
+ auto pa = CreateAttribute(att, identity_mapping, num_attribute_values);
+ if (!pa)
return -1;
- const int32_t att_id =
- AddAttribute(std::unique_ptr<PointAttribute>(new PointAttribute(att)));
+ const int32_t att_id = AddAttribute(std::move(pa));
+ return att_id;
+}
+
+std::unique_ptr<PointAttribute> PointCloud::CreateAttribute(
+ const GeometryAttribute &att, bool identity_mapping,
+ AttributeValueIndex::ValueType num_attribute_values) const {
+ if (att.attribute_type() == GeometryAttribute::INVALID)
+ return nullptr;
+ std::unique_ptr<PointAttribute> pa =
+ std::unique_ptr<PointAttribute>(new PointAttribute(att));
// Initialize point cloud specific attribute data.
if (!identity_mapping) {
// First create mapping between indices.
- attribute(att_id)->SetExplicitMapping(num_points_);
+ pa->SetExplicitMapping(num_points_);
} else {
- attribute(att_id)->SetIdentityMapping();
- attribute(att_id)->Resize(num_points_);
+ pa->SetIdentityMapping();
+ pa->Resize(num_points_);
}
if (num_attribute_values > 0) {
- attribute(att_id)->Reset(num_attribute_values);
+ pa->Reset(num_attribute_values);
}
- return att_id;
+ return pa;
}
void PointCloud::SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa) {
@@ -148,7 +157,7 @@ void PointCloud::DeleteAttribute(int att_id) {
}
}
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
void PointCloud::DeduplicatePointIds() {
// Hashing function for a single vertex.
auto point_hash = [this](PointIndex p) {
@@ -214,7 +223,9 @@ void PointCloud::ApplyPointIdDeduplication(
attribute(a)->SetExplicitMapping(num_unique_points);
}
}
+#endif
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
bool PointCloud::DeduplicateAttributeValues() {
// Go over all attributes and create mapping between duplicate entries.
if (num_points() == 0)
diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.h b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.h
index 0ea057dcf54..e15206f17c4 100644
--- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.h
+++ b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud.h
@@ -89,10 +89,17 @@ class PointCloud {
// PointAttribute::SetPointMapEntry() method. |num_attribute_values| can be
// used to specify the number of attribute values that are going to be
// stored in the newly created attribute. Returns attribute id of the newly
- // created attribute.
+ // created attribute or -1 in case of failure.
int AddAttribute(const GeometryAttribute &att, bool identity_mapping,
AttributeValueIndex::ValueType num_attribute_values);
+ // Creates and returns a new attribute or nullptr in case of failure. This
+ // method is similar to AddAttribute(), except that it returns the new
+ // attribute instead of adding it to the point cloud.
+ std::unique_ptr<PointAttribute> CreateAttribute(
+ const GeometryAttribute &att, bool identity_mapping,
+ AttributeValueIndex::ValueType num_attribute_values) const;
+
// Assigns an attribute id to a given PointAttribute. If an attribute with
// the same attribute id already exists, it is deleted.
virtual void SetAttribute(int att_id, std::unique_ptr<PointAttribute> pa);
@@ -101,11 +108,13 @@ class PointCloud {
// attribute ids of all subsequent attributes.
virtual void DeleteAttribute(int att_id);
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
// Deduplicates all attribute values (all attribute entries with the same
// value are merged into a single entry).
virtual bool DeduplicateAttributeValues();
+#endif
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
// Removes duplicate point ids (two point ids are duplicate when all of their
// attributes are mapped to the same entry ids).
virtual void DeduplicatePointIds();
@@ -173,7 +182,7 @@ class PointCloud {
void set_num_points(PointIndex::ValueType num) { num_points_ = num; }
protected:
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
// Applies id mapping of deduplicated points (called by DeduplicatePointIds).
virtual void ApplyPointIdDeduplication(
const IndexTypeVector<PointIndex, PointIndex> &id_map,
diff --git a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.cc b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.cc
index 455d9a931db..a0381631cfd 100644
--- a/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.cc
+++ b/extern/draco/dracoenc/src/draco/point_cloud/point_cloud_builder.cc
@@ -61,12 +61,14 @@ void PointCloudBuilder::SetAttributeValuesForAllPoints(
std::unique_ptr<PointCloud> PointCloudBuilder::Finalize(
bool deduplicate_points) {
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
if (deduplicate_points) {
+#ifdef DRACO_ATTRIBUTE_VALUES_DEDUPLICATION_SUPPORTED
point_cloud_->DeduplicateAttributeValues();
+#endif
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
point_cloud_->DeduplicatePointIds();
- }
#endif
+ }
return std::move(point_cloud_);
}
diff --git a/extern/draco/dracoenc/src/draco/tools/draco_decoder.cc b/extern/draco/dracoenc/src/draco/tools/draco_decoder.cc
index d96575223d7..5b06e8caa3b 100644
--- a/extern/draco/dracoenc/src/draco/tools/draco_decoder.cc
+++ b/extern/draco/dracoenc/src/draco/tools/draco_decoder.cc
@@ -134,7 +134,7 @@ int main(int argc, char **argv) {
}
// Save the decoded geometry into a file.
- // TODO(ostava): Currently only .ply and .obj are supported.
+ // TODO(fgalligan): Change extension code to look for '.'.
const std::string extension = draco::parser::ToLower(
options.output.size() >= 4
? options.output.substr(options.output.size() - 4)
@@ -167,7 +167,9 @@ int main(int argc, char **argv) {
}
}
} else {
- printf("Invalid extension of the output file. Use either .ply or .obj\n");
+ printf(
+ "Invalid extension of the output file. Use either .ply, .obj, or "
+ ".gltf\n");
return -1;
}
printf("Decoded geometry saved to %s (%" PRId64 " ms to decode)\n",
diff --git a/extern/draco/dracoenc/src/draco/tools/draco_encoder.cc b/extern/draco/dracoenc/src/draco/tools/draco_encoder.cc
index 05458fbbdf6..e44d0939048 100644
--- a/extern/draco/dracoenc/src/draco/tools/draco_encoder.cc
+++ b/extern/draco/dracoenc/src/draco/tools/draco_encoder.cc
@@ -316,7 +316,7 @@ int main(int argc, char **argv) {
pc->GetNamedAttributeId(draco::GeometryAttribute::GENERIC, 0));
}
}
-#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
+#ifdef DRACO_ATTRIBUTE_INDICES_DEDUPLICATION_SUPPORTED
// If any attribute has been deleted, run deduplication of point indices again
// as some points can be possibly combined.
if (options.tex_coords_deleted || options.normals_deleted ||
diff --git a/extern/draco/src/draco-compressor.cpp b/extern/draco/src/draco-compressor.cpp
index 3262a2c4d4d..4ae528888fe 100644
--- a/extern/draco/src/draco-compressor.cpp
+++ b/extern/draco/src/draco-compressor.cpp
@@ -13,234 +13,147 @@
*/
/**
- * Implemententation for the Draco exporter from the C++ side.
- *
- * The python side uses the CTypes libary to open the DLL, load function
- * pointers add pass the data to the compressor as raw bytes.
- *
- * The compressor intercepts the regular GLTF exporter after data has been
- * gathered and right before the data is converted to a JSON representation,
- * which is going to be written out.
- *
- * The original uncompressed data is removed and replaces an extension,
- * pointing to the newly created buffer containing the compressed data.
- *
* @author Jim Eckerlein <eckerlein@ux3d.io>
- * @date 2019-01-15
+ * @date 2019-11-29
*/
-#include <iostream>
-#include <fstream>
+#include "draco-compressor.h"
+
#include <memory>
-#include <sstream>
+#include <vector>
#include "draco/mesh/mesh.h"
-#include "draco/point_cloud/point_cloud.h"
-#include "draco/core/vector_d.h"
-#include "draco/io/mesh_io.h"
+#include "draco/core/encoder_buffer.h"
#include "draco/compression/encode.h"
-#if defined(_MSC_VER)
-#define DLL_EXPORT(retType) extern "C" __declspec(dllexport) retType __cdecl
-#else
-#define DLL_EXPORT(retType) extern "C" retType
-#endif
-
-const char *logTag = "DRACO-COMPRESSOR";
-
/**
- * This tuple is opaquely exposed to Python through a pointer.
- * It encapsulates the complete current compressor state.
- *
- * A single instance is only intended to compress a single primitive.
+ * Prefix used for logging messages.
*/
-struct DracoCompressor {
+const char *logTag = "DRACO-COMPRESSOR";
- /**
- * All positions, normals and texture coordinates are appended to this mesh.
- */
+struct DracoCompressor {
draco::Mesh mesh;
- /**
- * One data buffer per attribute.
- */
+ // One data buffer per attribute.
std::vector<std::unique_ptr<draco::DataBuffer>> buffers;
- /**
- * The buffer the mesh is compressed into.
- */
+ // The buffer the mesh is compressed into.
draco::EncoderBuffer encoderBuffer;
- /**
- * The id Draco assigns to the position attribute.
- * Required to be reported in the GLTF file.
- */
- uint32_t positionAttributeId = (uint32_t) -1;
-
- /**
- * The id Draco assigns to the normal attribute.
- * Required to be reported in the GLTF file.
- */
- uint32_t normalAttributeId = (uint32_t) -1;
-
- /**
- * The ids Draco assigns to the texture coordinate attributes.
- * Required to be reported in the GLTF file.
- */
- std::vector<uint32_t> texCoordAttributeIds;
-
- /**
- * Level of compression [0-10].
- * Higher values mean slower encoding.
- */
+ // Level of compression [0-10].
+ // Higher values mean slower encoding.
uint32_t compressionLevel = 7;
- uint32_t quantizationBitsPosition = 14;
- uint32_t quantizationBitsNormal = 10;
- uint32_t quantizationBitsTexCoord = 12;
+ struct {
+ uint32_t positions = 14;
+ uint32_t normals = 10;
+ uint32_t uvs = 12;
+ uint32_t generic = 12;
+ } quantization;
};
-draco::GeometryAttribute createAttribute(
- draco::GeometryAttribute::Type type,
- draco::DataBuffer &buffer,
- uint8_t components
-) {
- draco::GeometryAttribute attribute;
- attribute.Init(
- type,
- &buffer,
- components,
- draco::DataType::DT_FLOAT32,
- false,
- sizeof(float) * components,
- 0
- );
- return attribute;
-}
-
-DLL_EXPORT(DracoCompressor *) createCompressor() {
+DracoCompressor *create_compressor() {
return new DracoCompressor;
}
-DLL_EXPORT(void) setCompressionLevel(
- DracoCompressor *compressor,
- uint32_t compressionLevel
+void set_compression_level(
+ DracoCompressor *const compressor,
+ uint32_t const compressionLevel
) {
compressor->compressionLevel = compressionLevel;
}
-DLL_EXPORT(void) setPositionQuantizationBits(
- DracoCompressor *compressor,
- uint32_t quantizationBitsPosition
+void set_position_quantization(
+ DracoCompressor *const compressor,
+ uint32_t const quantizationBitsPosition
) {
- compressor->quantizationBitsPosition = quantizationBitsPosition;
+ compressor->quantization.positions = quantizationBitsPosition;
}
-DLL_EXPORT(void) setNormalQuantizationBits(
- DracoCompressor *compressor,
- uint32_t quantizationBitsNormal
+void set_normal_quantization(
+ DracoCompressor *const compressor,
+ uint32_t const quantizationBitsNormal
) {
- compressor->quantizationBitsNormal = quantizationBitsNormal;
+ compressor->quantization.normals = quantizationBitsNormal;
}
-DLL_EXPORT(void) setTexCoordQuantizationBits(
- DracoCompressor *compressor,
- uint32_t quantizationBitsTexCoord
+void set_uv_quantization(
+ DracoCompressor *const compressor,
+ uint32_t const quantizationBitsTexCoord
) {
- compressor->quantizationBitsTexCoord = quantizationBitsTexCoord;
+ compressor->quantization.uvs = quantizationBitsTexCoord;
}
-DLL_EXPORT(bool) compress(
- DracoCompressor *compressor
+void set_generic_quantization(
+ DracoCompressor *const compressor,
+ uint32_t const bits
) {
- printf("%s: Compressing primitive:\n", logTag);
- printf("%s: Compression level [0-10]: %d\n", logTag, compressor->compressionLevel);
- printf("%s: Position quantization bits: %d\n", logTag, compressor->quantizationBitsPosition);
- printf("%s: Normal quantization bits: %d\n", logTag, compressor->quantizationBitsNormal);
- printf("%s: Position quantization bits: %d\n", logTag, compressor->quantizationBitsTexCoord);
+ compressor->quantization.generic = bits;
+}
+bool compress(
+ DracoCompressor *const compressor
+) {
draco::Encoder encoder;
- encoder.SetSpeedOptions(10 - compressor->compressionLevel, 10 - compressor->compressionLevel);
- encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantizationBitsPosition);
- encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, compressor->quantizationBitsNormal);
- encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, compressor->quantizationBitsTexCoord);
-
- draco::Status result = encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer);
+ encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel);
+ encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions);
+ encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL, compressor->quantization.normals);
+ encoder.SetAttributeQuantization(draco::GeometryAttribute::TEX_COORD, compressor->quantization.uvs);
+ encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC, compressor->quantization.generic);
- if(!result.ok()) {
- printf("%s: Could not compress mesh: %s\n", logTag, result.error_msg());
- return false;
- }
- else {
- return true;
- }
+ return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok();
}
-/**
- * Returns the size of the compressed data in bytes.
- */
-DLL_EXPORT(uint64_t) compressedSize(
- DracoCompressor *compressor
+bool compress_morphed(
+ DracoCompressor *const compressor
) {
- return compressor->encoderBuffer.size();
-}
+ draco::Encoder encoder;
-/**
- * Copies the compressed mesh into the given byte buffer.
- * @param[o_data] A Python `bytes` object.
- *
- */
-DLL_EXPORT(void) copyToBytes(
- DracoCompressor *compressor,
- uint8_t *o_data
-) {
- memcpy(o_data, compressor->encoderBuffer.data(), compressedSize(compressor));
-}
+ encoder.SetSpeedOptions(10 - (int)compressor->compressionLevel, 10 - (int)compressor->compressionLevel);
-DLL_EXPORT(uint32_t) getPositionAttributeId(
- DracoCompressor *compressor
-) {
- return compressor->positionAttributeId;
-}
+ // For some reason, `EncodeMeshToBuffer` crashes when not disabling prediction or when enabling quantization
+ // for attributes other position.
+ encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, compressor->quantization.positions);
+ encoder.SetAttributePredictionScheme(draco::GeometryAttribute::POSITION, draco::PREDICTION_NONE);
+ encoder.SetAttributePredictionScheme(draco::GeometryAttribute::NORMAL, draco::PREDICTION_NONE);
+ encoder.SetAttributePredictionScheme(draco::GeometryAttribute::TEX_COORD, draco::PREDICTION_NONE);
+ encoder.SetAttributePredictionScheme(draco::GeometryAttribute::GENERIC, draco::PREDICTION_NONE);
-DLL_EXPORT(uint32_t) getNormalAttributeId(
- DracoCompressor *compressor
-) {
- return compressor->normalAttributeId;
+ // Enforce triangle order preservation.
+ encoder.SetEncodingMethod(draco::MESH_SEQUENTIAL_ENCODING);
+
+ return encoder.EncodeMeshToBuffer(compressor->mesh, &compressor->encoderBuffer).ok();
}
-DLL_EXPORT(uint32_t) getTexCoordAttributeIdCount(
- DracoCompressor *compressor
+uint64_t get_compressed_size(
+ DracoCompressor const *const compressor
) {
- return (uint32_t) compressor->texCoordAttributeIds.size();
+ return compressor->encoderBuffer.size();
}
-DLL_EXPORT(uint32_t) getTexCoordAttributeId(
- DracoCompressor *compressor,
- uint32_t index
+void copy_to_bytes(
+ DracoCompressor const *const compressor,
+ uint8_t *const o_data
) {
- return compressor->texCoordAttributeIds[index];
+ memcpy(o_data, compressor->encoderBuffer.data(), compressor->encoderBuffer.size());
}
-/**
- * Releases all memory allocated by the compressor.
- */
-DLL_EXPORT(void) disposeCompressor(
- DracoCompressor *compressor
+void destroy_compressor(
+ DracoCompressor *const compressor
) {
delete compressor;
}
template<class T>
-void setFaces(
- draco::Mesh &mesh,
- int numIndices,
- T *indices
+void set_faces_impl(
+ draco::Mesh &mesh,
+ int const index_count,
+ T const *const indices
) {
- mesh.SetNumFaces((size_t) numIndices / 3);
+ mesh.SetNumFaces((size_t) index_count / 3);
- for (int i = 0; i < numIndices; i += 3)
+ for (int i = 0; i < index_count; i += 3)
{
const auto a = draco::PointIndex(indices[i]);
const auto b = draco::PointIndex(indices[i + 1]);
@@ -249,97 +162,116 @@ void setFaces(
}
}
-DLL_EXPORT(void) setFaces(
- DracoCompressor *compressor,
- uint32_t numIndices,
- uint32_t bytesPerIndex,
- void *indices
+void set_faces(
+ DracoCompressor *const compressor,
+ uint32_t const index_count,
+ uint32_t const index_byte_length,
+ uint8_t const *const indices
) {
- switch (bytesPerIndex)
+ switch (index_byte_length)
{
case 1:
{
- setFaces(compressor->mesh, numIndices, (uint8_t *) indices);
+ set_faces_impl(compressor->mesh, index_count, (uint8_t *) indices);
break;
}
case 2:
{
- setFaces(compressor->mesh, numIndices, (uint16_t *) indices);
+ set_faces_impl(compressor->mesh, index_count, (uint16_t *) indices);
break;
}
case 4:
{
- setFaces(compressor->mesh, numIndices, (uint32_t *) indices);
+ set_faces_impl(compressor->mesh, index_count, (uint32_t *) indices);
break;
}
default:
{
- printf("%s: Unsupported index size %d\n", logTag, bytesPerIndex);
+ printf("%s: Unsupported index size %d\n", logTag, index_byte_length);
break;
}
}
}
-void addFloatAttribute(
- DracoCompressor *compressor,
- draco::GeometryAttribute::Type type,
- uint32_t count,
- uint8_t componentCount,
- float *source
+uint32_t add_attribute_to_mesh(
+ DracoCompressor *const compressor,
+ draco::GeometryAttribute::Type const semantics,
+ draco::DataType const data_type,
+ uint32_t const count,
+ uint8_t const component_count,
+ uint8_t const component_size,
+ uint8_t const *const data
) {
auto buffer = std::make_unique<draco::DataBuffer>();
- const auto attribute = createAttribute(type, *buffer, componentCount);
+ draco::GeometryAttribute attribute;
- const auto id = (const uint32_t) compressor->mesh.AddAttribute(attribute, false, count);
- compressor->mesh.attribute(id)->SetIdentityMapping();
+ attribute.Init(
+ semantics,
+ &*buffer,
+ component_count,
+ data_type,
+ false,
+ component_size * component_count,
+ 0
+ );
- switch (type)
- {
- case draco::GeometryAttribute::POSITION:
- compressor->positionAttributeId = id;
- break;
- case draco::GeometryAttribute::NORMAL:
- compressor->normalAttributeId = id;
- break;
- case draco::GeometryAttribute::TEX_COORD:
- compressor->texCoordAttributeIds.push_back(id);
- break;
- default:
- break;
- }
+ auto const id = (uint32_t)compressor->mesh.AddAttribute(attribute, true, count);
for (uint32_t i = 0; i < count; i++)
{
compressor->mesh.attribute(id)->SetAttributeValue(
- draco::AttributeValueIndex(i),
- source + i * componentCount
+ draco::AttributeValueIndex(i),
+ data + i * component_count * component_size
);
}
compressor->buffers.emplace_back(std::move(buffer));
+
+ return id;
+}
+
+uint32_t add_positions_f32(
+ DracoCompressor *const compressor,
+ uint32_t const count,
+ uint8_t const *const data
+) {
+ return add_attribute_to_mesh(compressor, draco::GeometryAttribute::POSITION,
+ draco::DT_FLOAT32, count, 3, sizeof(float), data);
+}
+
+uint32_t add_normals_f32(
+ DracoCompressor *const compressor,
+ uint32_t const count,
+ uint8_t const *const data
+) {
+ return add_attribute_to_mesh(compressor, draco::GeometryAttribute::NORMAL,
+ draco::DT_FLOAT32, count, 3, sizeof(float), data);
}
-DLL_EXPORT(void) addPositionAttribute(
- DracoCompressor *compressor,
- uint32_t count,
- float *source
+uint32_t add_uvs_f32(
+ DracoCompressor *const compressor,
+ uint32_t const count,
+ uint8_t const *const data
) {
- addFloatAttribute(compressor, draco::GeometryAttribute::POSITION, count, 3, source);
+ return add_attribute_to_mesh(compressor, draco::GeometryAttribute::TEX_COORD,
+ draco::DT_FLOAT32, count, 2, sizeof(float), data);
}
-DLL_EXPORT(void) addNormalAttribute(
- DracoCompressor *compressor,
- uint32_t count,
- float *source
+uint32_t add_joints_u16(
+ DracoCompressor *compressor,
+ uint32_t const count,
+ uint8_t const *const data
) {
- addFloatAttribute(compressor, draco::GeometryAttribute::NORMAL, count, 3, source);
+ return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC,
+ draco::DT_UINT16, count, 4, sizeof(uint16_t), data);
}
-DLL_EXPORT(void) addTexCoordAttribute(
- DracoCompressor *compressor,
- uint32_t count,
- float *source
+uint32_t add_weights_f32(
+ DracoCompressor *compressor,
+ uint32_t const count,
+ uint8_t const *const data
) {
- addFloatAttribute(compressor, draco::GeometryAttribute::TEX_COORD, count, 2, source);
+ return add_attribute_to_mesh(compressor, draco::GeometryAttribute::GENERIC,
+ draco::DT_FLOAT32, count, 4, sizeof(float), data);
}
diff --git a/extern/draco/src/draco-compressor.h b/extern/draco/src/draco-compressor.h
new file mode 100644
index 00000000000..fb6168a61af
--- /dev/null
+++ b/extern/draco/src/draco-compressor.h
@@ -0,0 +1,173 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * C++ library for the Draco compression feature inside the glTF-Blender-IO project.
+ *
+ * The python side uses the CTypes library to open the DLL, load function
+ * pointers add pass the data to the compressor as raw bytes.
+ *
+ * The compressor intercepts the regular glTF exporter after data has been
+ * gathered and right before the data is converted to a JSON representation,
+ * which is going to be written out.
+ *
+ * The original uncompressed data is removed and replaces an extension,
+ * pointing to the newly created buffer containing the compressed data.
+ *
+ * @author Jim Eckerlein <eckerlein@ux3d.io>
+ * @date 2019-11-29
+ */
+
+#include <cstdint>
+
+#if defined(_MSC_VER)
+#define DLL_EXPORT(retType) extern "C" __declspec(dllexport) retType __cdecl
+#else
+#define DLL_EXPORT(retType) extern "C" retType
+#endif
+
+/**
+ * This tuple is opaquely exposed to Python through a pointer.
+ * It encapsulates the complete current compressor state.
+ *
+ * A single instance is only intended to compress a single primitive.
+ */
+struct DracoCompressor;
+
+DLL_EXPORT(DracoCompressor *)
+create_compressor ();
+
+DLL_EXPORT(void)
+set_compression_level (
+ DracoCompressor *compressor,
+ uint32_t compressionLevel
+);
+
+DLL_EXPORT(void)
+set_position_quantization (
+ DracoCompressor *compressor,
+ uint32_t quantizationBitsPosition
+);
+
+DLL_EXPORT(void)
+set_normal_quantization (
+ DracoCompressor *compressor,
+ uint32_t quantizationBitsNormal
+);
+
+DLL_EXPORT(void)
+set_uv_quantization (
+ DracoCompressor *compressor,
+ uint32_t quantizationBitsTexCoord
+);
+
+DLL_EXPORT(void)
+set_generic_quantization (
+ DracoCompressor *compressor,
+ uint32_t bits
+);
+
+/// Compresses a mesh.
+/// Use `compress_morphed` when compressing primitives which have morph targets.
+DLL_EXPORT(bool)
+compress (
+ DracoCompressor *compressor
+);
+
+/// Compresses the mesh.
+/// Use this instead of `compress`, because this procedure takes into account that mesh triangles must not be reordered.
+DLL_EXPORT(bool)
+compress_morphed (
+ DracoCompressor *compressor
+);
+
+/**
+ * Returns the size of the compressed data in bytes.
+ */
+DLL_EXPORT(uint64_t)
+get_compressed_size (
+ DracoCompressor const *compressor
+);
+
+/**
+ * Copies the compressed mesh into the given byte buffer.
+ *
+ * @param[o_data] A Python `bytes` object.
+ */
+DLL_EXPORT(void)
+copy_to_bytes (
+ DracoCompressor const *compressor,
+ uint8_t *o_data
+);
+
+/**
+ * Releases all memory allocated by the compressor.
+ */
+DLL_EXPORT(void)
+destroy_compressor (
+ DracoCompressor *compressor
+);
+
+DLL_EXPORT(void)
+set_faces (
+ DracoCompressor *compressor,
+ uint32_t index_count,
+ uint32_t index_byte_length,
+ uint8_t const *indices
+);
+
+/// Adds a `float` position attribute to the current mesh.
+/// Returns the id Draco has assigned to this attribute.
+DLL_EXPORT(uint32_t)
+add_positions_f32 (
+ DracoCompressor *compressor,
+ uint32_t count,
+ uint8_t const *data
+);
+
+/// Adds a `float` normal attribute to the current mesh.
+/// Returns the id Draco has assigned to this attribute.
+DLL_EXPORT(uint32_t)
+add_normals_f32 (
+ DracoCompressor *compressor,
+ uint32_t count,
+ uint8_t const *data
+);
+
+/// Adds a `float` texture coordinate attribute to the current mesh.
+/// Returns the id Draco has assigned to this attribute.
+DLL_EXPORT(uint32_t)
+add_uvs_f32 (
+ DracoCompressor *compressor,
+ uint32_t count,
+ uint8_t const *data
+);
+
+/// Adds a `unsigned short` joint attribute to the current mesh.
+/// Returns the id Draco has assigned to this attribute.
+DLL_EXPORT(uint32_t)
+add_joints_u16 (
+ DracoCompressor *compressor,
+ uint32_t count,
+ uint8_t const *data
+);
+
+/// Adds a `float` weight attribute to the current mesh.
+/// Returns the id Draco has assigned to this attribute.
+DLL_EXPORT(uint32_t)
+add_weights_f32 (
+ DracoCompressor *compressor,
+ uint32_t count,
+ uint8_t const *data
+);