diff options
Diffstat (limited to 'extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc')
-rw-r--r-- | extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc new file mode 100644 index 00000000000..53f5e8651b8 --- /dev/null +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_sequential_decoder.cc @@ -0,0 +1,164 @@ +// 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_decoder.h" + +#include "draco/compression/attributes/linear_sequencer.h" +#include "draco/compression/attributes/sequential_attribute_decoders_controller.h" +#include "draco/compression/entropy/symbol_decoding.h" +#include "draco/core/varint_decoding.h" + +namespace draco { + +MeshSequentialDecoder::MeshSequentialDecoder() {} + +bool MeshSequentialDecoder::DecodeConnectivity() { + uint32_t num_faces; + uint32_t num_points; +#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED + if (bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { + if (!buffer()->Decode(&num_faces)) { + return false; + } + if (!buffer()->Decode(&num_points)) { + return false; + } + + } else +#endif + { + if (!DecodeVarint(&num_faces, buffer())) { + return false; + } + if (!DecodeVarint(&num_points, buffer())) { + return false; + } + } + + // Check that num_faces and num_points are valid values. + const uint64_t faces_64 = static_cast<uint64_t>(num_faces); + const uint64_t points_64 = static_cast<uint64_t>(num_points); + // Compressed sequential encoding can only handle (2^32 - 1) / 3 indices. + if (faces_64 > 0xffffffff / 3) { + return false; + } + if (points_64 > faces_64 * 3) { + return false; + } + uint8_t connectivity_method; + if (!buffer()->Decode(&connectivity_method)) { + return false; + } + if (connectivity_method == 0) { + if (!DecodeAndDecompressIndices(num_faces)) { + return false; + } + } else { + if (num_points < 256) { + // Decode indices as uint8_t. + for (uint32_t i = 0; i < num_faces; ++i) { + Mesh::Face face; + for (int j = 0; j < 3; ++j) { + uint8_t val; + if (!buffer()->Decode(&val)) { + return false; + } + face[j] = val; + } + mesh()->AddFace(face); + } + } else if (num_points < (1 << 16)) { + // Decode indices as uint16_t. + for (uint32_t i = 0; i < num_faces; ++i) { + Mesh::Face face; + for (int j = 0; j < 3; ++j) { + uint16_t val; + if (!buffer()->Decode(&val)) { + return false; + } + face[j] = val; + } + mesh()->AddFace(face); + } + } else if (mesh()->num_points() < (1 << 21) && + bitstream_version() >= DRACO_BITSTREAM_VERSION(2, 2)) { + // Decode indices as uint32_t. + for (uint32_t i = 0; i < num_faces; ++i) { + Mesh::Face face; + for (int j = 0; j < 3; ++j) { + uint32_t val; + if (!DecodeVarint(&val, buffer())) { + return false; + } + face[j] = val; + } + mesh()->AddFace(face); + } + } else { + // Decode faces as uint32_t (default). + for (uint32_t i = 0; i < num_faces; ++i) { + Mesh::Face face; + for (int j = 0; j < 3; ++j) { + uint32_t val; + if (!buffer()->Decode(&val)) { + return false; + } + face[j] = val; + } + mesh()->AddFace(face); + } + } + } + point_cloud()->set_num_points(num_points); + return true; +} + +bool MeshSequentialDecoder::CreateAttributesDecoder(int32_t att_decoder_id) { + // Always create the basic attribute decoder. + return SetAttributesDecoder( + att_decoder_id, + std::unique_ptr<AttributesDecoder>( + new SequentialAttributeDecodersController( + std::unique_ptr<PointsSequencer>( + new LinearSequencer(point_cloud()->num_points()))))); +} + +bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces) { + // Get decoded indices differences that were encoded with an entropy code. + std::vector<uint32_t> indices_buffer(num_faces * 3); + if (!DecodeSymbols(num_faces * 3, 1, buffer(), indices_buffer.data())) { + return false; + } + // Reconstruct the indices from the differences. + // See MeshSequentialEncoder::CompressAndEncodeIndices() for more details. + int32_t last_index_value = 0; + int vertex_index = 0; + for (uint32_t i = 0; i < num_faces; ++i) { + Mesh::Face face; + for (int j = 0; j < 3; ++j) { + const uint32_t encoded_val = indices_buffer[vertex_index++]; + int32_t index_diff = (encoded_val >> 1); + if (encoded_val & 1) { + index_diff = -index_diff; + } + const int32_t index_value = index_diff + last_index_value; + face[j] = index_value; + last_index_value = index_value; + } + mesh()->AddFace(face); + } + return true; +} + +} // namespace draco |