GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
mesh_edgebreaker_traversal_predictive_encoder.h
Go to the documentation of this file.
1// Copyright 2016 The Draco Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15#ifndef DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_ENCODER_H_
16#define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_ENCODER_H_
17
19
20namespace draco {
21
22// Encoder that tries to predict the edgebreaker traversal symbols based on the
23// vertex valences of the unencoded portion of the mesh. The current prediction
24// scheme assumes that each vertex has valence 6 which can be used to predict
25// the symbol preceding the one that is currently encoded. Predictions are
26// encoded using an arithmetic coding which can lead to less than 1 bit per
27// triangle encoding for highly regular meshes.
30 public:
32 : corner_table_(nullptr),
33 prev_symbol_(-1),
34 num_split_symbols_(0),
35 last_corner_(kInvalidCornerIndex),
36 num_symbols_(0) {}
37
40 return false;
41 }
42 corner_table_ = encoder->GetCornerTable();
43 // Initialize valences of all vertices.
44 vertex_valences_.resize(corner_table_->num_vertices());
45 for (uint32_t i = 0; i < vertex_valences_.size(); ++i) {
46 vertex_valences_[i] = corner_table_->Valence(VertexIndex(i));
47 }
48 return true;
49 }
50
51 inline void NewCornerReached(CornerIndex corner) { last_corner_ = corner; }
52
53 inline int32_t ComputePredictedSymbol(VertexIndex pivot) {
54 const int valence = vertex_valences_[pivot.value()];
55 if (valence < 0) {
56 // This situation can happen only for split vertices. Returning
57 // TOPOLOGY_INVALID always cases misprediction.
58 return TOPOLOGY_INVALID;
59 }
60 if (valence < 6) {
61 return TOPOLOGY_R;
62 }
63 return TOPOLOGY_C;
64 }
65
67 ++num_symbols_;
68 // Update valences on the mesh. And compute the predicted preceding symbol.
69 // Note that the valences are computed for the so far unencoded part of the
70 // mesh. Adding a new symbol either reduces valences on the vertices or
71 // leaves the valence unchanged.
72 int32_t predicted_symbol = -1;
73 const CornerIndex next = corner_table_->Next(last_corner_);
74 const CornerIndex prev = corner_table_->Previous(last_corner_);
75 switch (symbol) {
76 case TOPOLOGY_C:
77 // Compute prediction.
78 predicted_symbol = ComputePredictedSymbol(corner_table_->Vertex(next));
80 case TOPOLOGY_S:
81 // Update valences.
82 vertex_valences_[corner_table_->Vertex(next).value()] -= 1;
83 vertex_valences_[corner_table_->Vertex(prev).value()] -= 1;
84 if (symbol == TOPOLOGY_S) {
85 // Whenever we reach a split symbol, mark its tip vertex as invalid by
86 // setting the valence to a negative value. Any prediction that will
87 // use this vertex will then cause a misprediction. This is currently
88 // necessary because the decoding works in the reverse direction and
89 // the decoder doesn't know about these vertices until the split
90 // symbol is decoded at which point two vertices are merged into one.
91 // This can be most likely solved on the encoder side by splitting the
92 // tip vertex into two, but since split symbols are relatively rare,
93 // it's probably not worth doing it.
94 vertex_valences_[corner_table_->Vertex(last_corner_).value()] = -1;
95 ++num_split_symbols_;
96 }
97 break;
98 case TOPOLOGY_R:
99 // Compute prediction.
100 predicted_symbol = ComputePredictedSymbol(corner_table_->Vertex(next));
101 // Update valences.
102 vertex_valences_[corner_table_->Vertex(last_corner_).value()] -= 1;
103 vertex_valences_[corner_table_->Vertex(next).value()] -= 1;
104 vertex_valences_[corner_table_->Vertex(prev).value()] -= 2;
105 break;
106 case TOPOLOGY_L:
107 vertex_valences_[corner_table_->Vertex(last_corner_).value()] -= 1;
108 vertex_valences_[corner_table_->Vertex(next).value()] -= 2;
109 vertex_valences_[corner_table_->Vertex(prev).value()] -= 1;
110 break;
111 case TOPOLOGY_E:
112 vertex_valences_[corner_table_->Vertex(last_corner_).value()] -= 2;
113 vertex_valences_[corner_table_->Vertex(next).value()] -= 2;
114 vertex_valences_[corner_table_->Vertex(prev).value()] -= 2;
115 break;
116 default:
117 break;
118 }
119 // Flag used when it's necessary to explicitly store the previous symbol.
120 bool store_prev_symbol = true;
121 if (predicted_symbol != -1) {
122 if (predicted_symbol == prev_symbol_) {
123 predictions_.push_back(true);
124 store_prev_symbol = false;
125 } else if (prev_symbol_ != -1) {
126 predictions_.push_back(false);
127 }
128 }
129 if (store_prev_symbol && prev_symbol_ != -1) {
131 static_cast<EdgebreakerTopologyBitPattern>(prev_symbol_));
132 }
133 prev_symbol_ = symbol;
134 }
135
136 void Done() {
137 // We still need to store the last encoded symbol.
138 if (prev_symbol_ != -1) {
140 static_cast<EdgebreakerTopologyBitPattern>(prev_symbol_));
141 }
142 // Store the init face configurations and the explicitly encoded symbols.
144 // Encode the number of split symbols.
145 GetOutputBuffer()->Encode(num_split_symbols_);
146 // Store the predictions.
147 BinaryEncoder prediction_encoder;
148 prediction_encoder.StartEncoding();
149 for (int i = static_cast<int>(predictions_.size()) - 1; i >= 0; --i) {
150 prediction_encoder.EncodeBit(predictions_[i]);
151 }
152 prediction_encoder.EndEncoding(GetOutputBuffer());
153 }
154
155 int NumEncodedSymbols() const { return num_symbols_; }
156
157 private:
158 const CornerTable *corner_table_;
159 std::vector<int> vertex_valences_;
160 std::vector<bool> predictions_;
161 // Previously encoded symbol.
162 int32_t prev_symbol_;
163 // The total number of encoded split symbols.
164 int32_t num_split_symbols_;
165 CornerIndex last_corner_;
166 // Explicitly count the number of encoded symbols.
167 int num_symbols_;
168};
169
170} // namespace draco
171
172#endif // DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_ENCODER_H_
Definition corner_table.h:53
bool Encode(const T &data)
Definition encoder_buffer.h:60
Definition mesh_edgebreaker_encoder_impl_interface.h:33
virtual const CornerTable * GetCornerTable() const =0
void Done()
Definition mesh_edgebreaker_traversal_encoder.h:83
EncoderBuffer * GetOutputBuffer()
Definition mesh_edgebreaker_traversal_encoder.h:120
MeshEdgebreakerTraversalEncoder()
Definition mesh_edgebreaker_traversal_encoder.h:33
bool Init(MeshEdgebreakerEncoderImplInterface *encoder)
Definition mesh_edgebreaker_traversal_encoder.h:37
void EncodeSymbol(EdgebreakerTopologyBitPattern symbol)
Definition mesh_edgebreaker_traversal_encoder.h:70
void Done()
Definition mesh_edgebreaker_traversal_predictive_encoder.h:136
void EncodeSymbol(EdgebreakerTopologyBitPattern symbol)
Definition mesh_edgebreaker_traversal_predictive_encoder.h:66
MeshEdgebreakerTraversalPredictiveEncoder()
Definition mesh_edgebreaker_traversal_predictive_encoder.h:31
bool Init(MeshEdgebreakerEncoderImplInterface *encoder)
Definition mesh_edgebreaker_traversal_predictive_encoder.h:38
int NumEncodedSymbols() const
Definition mesh_edgebreaker_traversal_predictive_encoder.h:155
void NewCornerReached(CornerIndex corner)
Definition mesh_edgebreaker_traversal_predictive_encoder.h:51
int32_t ComputePredictedSymbol(VertexIndex pivot)
Definition mesh_edgebreaker_traversal_predictive_encoder.h:53
void EndEncoding(EncoderBuffer *target_buffer)
Definition rans_bit_encoder.cc:75
void EncodeBit(bool bit)
Definition rans_bit_encoder.cc:31
void StartEncoding()
Definition rans_bit_encoder.cc:29
#define FALLTHROUGH_INTENDED
Definition macros.h:54
Definition attribute_octahedron_transform.cc:21
VertexIndex VertexIndex
Definition mesh_edgebreaker_encoder_impl.cc:37
RAnsBitEncoder BinaryEncoder
Definition mesh_edgebreaker_traversal_encoder.h:25
CornerIndex CornerIndex
Definition mesh_edgebreaker_encoder_impl.cc:35
EdgebreakerTopologyBitPattern
Definition mesh_edgebreaker_shared.h:53
@ TOPOLOGY_INVALID
Definition mesh_edgebreaker_shared.h:64
@ TOPOLOGY_R
Definition mesh_edgebreaker_shared.h:57
@ TOPOLOGY_S
Definition mesh_edgebreaker_shared.h:55
@ TOPOLOGY_L
Definition mesh_edgebreaker_shared.h:56
@ TOPOLOGY_E
Definition mesh_edgebreaker_shared.h:58
@ TOPOLOGY_C
Definition mesh_edgebreaker_shared.h:54