diff options
Diffstat (limited to 'extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h')
-rw-r--r-- | extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h new file mode 100644 index 00000000000..621883a5f1f --- /dev/null +++ b/extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h @@ -0,0 +1,210 @@ +// 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. +// +#ifndef DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_VALENCE_DECODER_H_ +#define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_VALENCE_DECODER_H_ + +#include "draco/compression/entropy/symbol_decoding.h" +#include "draco/compression/mesh/mesh_edgebreaker_traversal_decoder.h" +#include "draco/core/varint_decoding.h" +#include "draco/draco_features.h" + +namespace draco { + +// Decoder for traversal encoded with MeshEdgebreakerTraversalValenceEncoder. +// The decoder maintains valences of the decoded portion of the traversed mesh +// and it uses them to select entropy context used for decoding of the actual +// symbols. +class MeshEdgebreakerTraversalValenceDecoder + : public MeshEdgebreakerTraversalDecoder { + public: + MeshEdgebreakerTraversalValenceDecoder() + : corner_table_(nullptr), + num_vertices_(0), + last_symbol_(-1), + active_context_(-1), + min_valence_(2), + max_valence_(7) {} + void Init(MeshEdgebreakerDecoderImplInterface *decoder) { + MeshEdgebreakerTraversalDecoder::Init(decoder); + corner_table_ = decoder->GetCornerTable(); + } + void SetNumEncodedVertices(int num_vertices) { num_vertices_ = num_vertices; } + + bool Start(DecoderBuffer *out_buffer) { +#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED + if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) { + if (!MeshEdgebreakerTraversalDecoder::DecodeTraversalSymbols()) { + return false; + } + } +#endif + if (!MeshEdgebreakerTraversalDecoder::DecodeStartFaces()) { + return false; + } + if (!MeshEdgebreakerTraversalDecoder::DecodeAttributeSeams()) { + return false; + } + *out_buffer = *buffer(); + +#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED + if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) { + uint32_t num_split_symbols; + if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 0)) { + if (!out_buffer->Decode(&num_split_symbols)) { + return false; + } + } else { + if (!DecodeVarint(&num_split_symbols, out_buffer)) { + return false; + } + } + if (num_split_symbols >= static_cast<uint32_t>(num_vertices_)) { + return false; + } + + int8_t mode; + if (!out_buffer->Decode(&mode)) { + return false; + } + if (mode == EDGEBREAKER_VALENCE_MODE_2_7) { + min_valence_ = 2; + max_valence_ = 7; + } else { + // Unsupported mode. + return false; + } + + } else +#endif + { + min_valence_ = 2; + max_valence_ = 7; + } + + if (num_vertices_ < 0) { + return false; + } + // Set the valences of all initial vertices to 0. + vertex_valences_.resize(num_vertices_, 0); + + const int num_unique_valences = max_valence_ - min_valence_ + 1; + + // Decode all symbols for all contexts. + context_symbols_.resize(num_unique_valences); + context_counters_.resize(context_symbols_.size()); + for (int i = 0; i < context_symbols_.size(); ++i) { + uint32_t num_symbols; + DecodeVarint<uint32_t>(&num_symbols, out_buffer); + if (num_symbols > 0) { + context_symbols_[i].resize(num_symbols); + DecodeSymbols(num_symbols, 1, out_buffer, context_symbols_[i].data()); + // All symbols are going to be processed from the back. + context_counters_[i] = num_symbols; + } + } + return true; + } + + inline uint32_t DecodeSymbol() { + // First check if we have a valid context. + if (active_context_ != -1) { + const int context_counter = --context_counters_[active_context_]; + if (context_counter < 0) { + return TOPOLOGY_INVALID; + } + const int symbol_id = context_symbols_[active_context_][context_counter]; + last_symbol_ = edge_breaker_symbol_to_topology_id[symbol_id]; + } else { +#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED + if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) { + // We don't have a predicted symbol or the symbol was mis-predicted. + // Decode it directly. + last_symbol_ = MeshEdgebreakerTraversalDecoder::DecodeSymbol(); + + } else +#endif + { + // The first symbol must be E. + last_symbol_ = TOPOLOGY_E; + } + } + return last_symbol_; + } + + inline void NewActiveCornerReached(CornerIndex corner) { + const CornerIndex next = corner_table_->Next(corner); + const CornerIndex prev = corner_table_->Previous(corner); + // Update valences. + switch (last_symbol_) { + case TOPOLOGY_C: + case TOPOLOGY_S: + vertex_valences_[corner_table_->Vertex(next)] += 1; + vertex_valences_[corner_table_->Vertex(prev)] += 1; + break; + case TOPOLOGY_R: + vertex_valences_[corner_table_->Vertex(corner)] += 1; + vertex_valences_[corner_table_->Vertex(next)] += 1; + vertex_valences_[corner_table_->Vertex(prev)] += 2; + break; + case TOPOLOGY_L: + vertex_valences_[corner_table_->Vertex(corner)] += 1; + vertex_valences_[corner_table_->Vertex(next)] += 2; + vertex_valences_[corner_table_->Vertex(prev)] += 1; + break; + case TOPOLOGY_E: + vertex_valences_[corner_table_->Vertex(corner)] += 2; + vertex_valences_[corner_table_->Vertex(next)] += 2; + vertex_valences_[corner_table_->Vertex(prev)] += 2; + break; + default: + break; + } + // Compute the new context that is going to be used to decode the next + // symbol. + const int active_valence = vertex_valences_[corner_table_->Vertex(next)]; + int clamped_valence; + if (active_valence < min_valence_) { + clamped_valence = min_valence_; + } else if (active_valence > max_valence_) { + clamped_valence = max_valence_; + } else { + clamped_valence = active_valence; + } + + active_context_ = (clamped_valence - min_valence_); + } + + inline void MergeVertices(VertexIndex dest, VertexIndex source) { + // Update valences on the merged vertices. + vertex_valences_[dest] += vertex_valences_[source]; + } + + private: + const CornerTable *corner_table_; + int num_vertices_; + IndexTypeVector<VertexIndex, int> vertex_valences_; + int last_symbol_; + int active_context_; + + int min_valence_; + int max_valence_; + std::vector<std::vector<uint32_t>> context_symbols_; + // Points to the active symbol in each context. + std::vector<int> context_counters_; +}; + +} // namespace draco + +#endif // DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_VALENCE_DECODER_H_ |