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
diff options
context:
space:
mode:
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.h210
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_