mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-06-04 11:25:44 +08:00
126 lines
4.5 KiB
C++
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_
|