diff options
Diffstat (limited to 'extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc')
-rw-r--r-- | extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc new file mode 100644 index 00000000000..02ac7779ea3 --- /dev/null +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_encoder.cc @@ -0,0 +1,132 @@ +// Copyright 2016 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. +// +#include "draco/compression/mesh/mesh_sequential_encoder.h" + +#include <cstdlib> + +#include "draco/compression/attributes/linear_sequencer.h" +#include "draco/compression/attributes/sequential_attribute_encoders_controller.h" +#include "draco/compression/entropy/symbol_encoding.h" +#include "draco/core/varint_encoding.h" + +namespace draco { + +MeshSequentialEncoder::MeshSequentialEncoder() {} + +Status MeshSequentialEncoder::EncodeConnectivity() { + // Serialize indices. + const uint32_t num_faces = mesh()->num_faces(); + EncodeVarint(num_faces, buffer()); + EncodeVarint(static_cast<uint32_t>(mesh()->num_points()), buffer()); + + // We encode all attributes in the original (possibly duplicated) format. + // TODO(ostava): This may not be optimal if we have only one attribute or if + // all attributes share the same index mapping. + if (options()->GetGlobalBool("compress_connectivity", false)) { + // 0 = Encode compressed indices. + buffer()->Encode(static_cast<uint8_t>(0)); + if (!CompressAndEncodeIndices()) { + return Status(Status::DRACO_ERROR, "Failed to compress connectivity."); + } + } else { + // 1 = Encode indices directly. + buffer()->Encode(static_cast<uint8_t>(1)); + // Store vertex indices using a smallest data type that fits their range. + // TODO(ostava): This can be potentially improved by using a tighter + // fit that is not bound by a bit-length of any particular data type. + if (mesh()->num_points() < 256) { + // Serialize indices as uint8_t. + for (FaceIndex i(0); i < num_faces; ++i) { + const auto &face = mesh()->face(i); + buffer()->Encode(static_cast<uint8_t>(face[0].value())); + buffer()->Encode(static_cast<uint8_t>(face[1].value())); + buffer()->Encode(static_cast<uint8_t>(face[2].value())); + } + } else if (mesh()->num_points() < (1 << 16)) { + // Serialize indices as uint16_t. + for (FaceIndex i(0); i < num_faces; ++i) { + const auto &face = mesh()->face(i); + buffer()->Encode(static_cast<uint16_t>(face[0].value())); + buffer()->Encode(static_cast<uint16_t>(face[1].value())); + buffer()->Encode(static_cast<uint16_t>(face[2].value())); + } + } else if (mesh()->num_points() < (1 << 21)) { + // Serialize indices as varint. + for (FaceIndex i(0); i < num_faces; ++i) { + const auto &face = mesh()->face(i); + EncodeVarint(static_cast<uint32_t>(face[0].value()), buffer()); + EncodeVarint(static_cast<uint32_t>(face[1].value()), buffer()); + EncodeVarint(static_cast<uint32_t>(face[2].value()), buffer()); + } + } else { + // Serialize faces as uint32_t (default). + for (FaceIndex i(0); i < num_faces; ++i) { + const auto &face = mesh()->face(i); + buffer()->Encode(face); + } + } + } + return OkStatus(); +} + +bool MeshSequentialEncoder::GenerateAttributesEncoder(int32_t att_id) { + // Create only one attribute encoder that is going to encode all points in a + // linear sequence. + if (att_id == 0) { + // Create a new attribute encoder only for the first attribute. + AddAttributesEncoder(std::unique_ptr<AttributesEncoder>( + new SequentialAttributeEncodersController( + std::unique_ptr<PointsSequencer>( + new LinearSequencer(point_cloud()->num_points())), + att_id))); + } else { + // Reuse the existing attribute encoder for other attributes. + attributes_encoder(0)->AddAttributeId(att_id); + } + return true; +} + +bool MeshSequentialEncoder::CompressAndEncodeIndices() { + // Collect all indices to a buffer and encode them. + // Each new index is a difference from the previous value. + std::vector<uint32_t> indices_buffer; + int32_t last_index_value = 0; + const int num_faces = mesh()->num_faces(); + for (FaceIndex i(0); i < num_faces; ++i) { + const auto &face = mesh()->face(i); + for (int j = 0; j < 3; ++j) { + const int32_t index_value = face[j].value(); + const int32_t index_diff = index_value - last_index_value; + // Encode signed value to an unsigned one (put the sign to lsb pos). + const uint32_t encoded_val = + (abs(index_diff) << 1) | (index_diff < 0 ? 1 : 0); + indices_buffer.push_back(encoded_val); + last_index_value = index_value; + } + } + EncodeSymbols(indices_buffer.data(), static_cast<int>(indices_buffer.size()), + 1, nullptr, buffer()); + return true; +} + +void MeshSequentialEncoder::ComputeNumberOfEncodedPoints() { + set_num_encoded_points(mesh()->num_points()); +} + +void MeshSequentialEncoder::ComputeNumberOfEncodedFaces() { + set_num_encoded_faces(mesh()->num_faces()); +} + +} // namespace draco |