draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h
2016-12-12 16:39:06 -08:00

126 lines
4.5 KiB
C++

// 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_PREDICTIVE_DECODER_H_
#define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_DECODER_H_
#include "compression/mesh/mesh_edgebreaker_traversal_decoder.h"
namespace draco {
// Decoder for traversal encoded with the
// MeshEdgeBreakerTraversalPredictiveEncoder. The decoder maintains valences
// of the decoded portion of the traversed mesh and it uses them to predict
// symbols that are about to be decoded.
class MeshEdgeBreakerTraversalPredictiveDecoder
: public MeshEdgeBreakerTraversalDecoder {
public:
MeshEdgeBreakerTraversalPredictiveDecoder()
: corner_table_(nullptr),
num_vertices_(0),
last_symbol_(-1),
predicted_symbol_(-1) {}
void Init(MeshEdgeBreakerDecoderImplInterface *decoder) {
MeshEdgeBreakerTraversalDecoder::Init(decoder);
corner_table_ = decoder->GetCornerTable();
}
void SetNumEncodedVertices(int num_vertices) { num_vertices_ = num_vertices; }
DecoderBuffer Start() {
DecoderBuffer buffer = MeshEdgeBreakerTraversalDecoder::Start();
int32_t num_split_symbols;
buffer.Decode(&num_split_symbols);
// Add one vertex for each split symbol.
num_vertices_ += num_split_symbols;
// Set the valences of all initial vertices to 0.
vertex_valences_.resize(num_vertices_, 0);
prediction_decoder_.StartDecoding(&buffer);
return buffer;
}
inline uint32_t DecodeSymbol() {
// First check if we have a predicted symbol.
if (predicted_symbol_ != -1) {
// Double check that the predicted symbol was predicted correctly.
if (prediction_decoder_.DecodeNextBit()) {
last_symbol_ = predicted_symbol_;
return predicted_symbol_;
}
}
// We don't have a predicted symbol or the symbol was mis-predicted.
// Decode it directly.
last_symbol_ = MeshEdgeBreakerTraversalDecoder::DecodeSymbol();
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).value()] += 1;
vertex_valences_[corner_table_->Vertex(prev).value()] += 1;
break;
case TOPOLOGY_R:
vertex_valences_[corner_table_->Vertex(corner).value()] += 1;
vertex_valences_[corner_table_->Vertex(next).value()] += 1;
vertex_valences_[corner_table_->Vertex(prev).value()] += 2;
break;
case TOPOLOGY_L:
vertex_valences_[corner_table_->Vertex(corner).value()] += 1;
vertex_valences_[corner_table_->Vertex(next).value()] += 2;
vertex_valences_[corner_table_->Vertex(prev).value()] += 1;
break;
case TOPOLOGY_E:
vertex_valences_[corner_table_->Vertex(corner).value()] += 2;
vertex_valences_[corner_table_->Vertex(next).value()] += 2;
vertex_valences_[corner_table_->Vertex(prev).value()] += 2;
break;
default:
break;
}
// Compute the new predicted symbol.
if (last_symbol_ == TOPOLOGY_C || last_symbol_ == TOPOLOGY_R) {
const VertexIndex pivot =
corner_table_->Vertex(corner_table_->Next(corner));
if (vertex_valences_[pivot.value()] < 6) {
predicted_symbol_ = TOPOLOGY_R;
} else {
predicted_symbol_ = TOPOLOGY_C;
}
} else {
predicted_symbol_ = -1;
}
}
inline void MergeVertices(VertexIndex dest, VertexIndex source) {
// Update valences on the merged vertices.
vertex_valences_[dest.value()] += vertex_valences_[source.value()];
}
private:
const CornerTable *corner_table_;
int num_vertices_;
std::vector<int> vertex_valences_;
BinaryDecoder prediction_decoder_;
int last_symbol_;
int predicted_symbol_;
};
} // namespace draco
#endif // DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_DECODER_H_