GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
mesh_edgebreaker_decoder_impl.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_DECODER_IMPL_H_
16#define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_DECODER_IMPL_H_
17
18#include <unordered_map>
19#include <unordered_set>
20
29
30namespace draco {
31
32// Implementation of the edgebreaker decoder that decodes data encoded with the
33// MeshEdgebreakerEncoderImpl class. The implementation of the decoder is based
34// on the algorithm presented in Isenburg et al'02 "Spirale Reversi: Reverse
35// decoding of the Edgebreaker encoding". Note that the encoding is still based
36// on the standard edgebreaker method as presented in "3D Compression
37// Made Simple: Edgebreaker on a Corner-Table" by Rossignac at al.'01.
38// http://www.cc.gatech.edu/~jarek/papers/CornerTableSMI.pdf. One difference is
39// caused by the properties of the spirale reversi algorithm that decodes the
40// symbols from the last one to the first one. To make the decoding more
41// efficient, we encode all symbols in the reverse order, therefore the decoder
42// can process them one by one.
43// The main advantage of the spirale reversi method is that the partially
44// decoded mesh has valid connectivity data at any time during the decoding
45// process (valid with respect to the decoded portion of the mesh). The standard
46// Edgebreaker decoder used two passes (forward decoding + zipping) which not
47// only prevented us from having a valid connectivity but it was also slower.
48// The main benefit of having the valid connectivity is that we can use the
49// known connectivity to predict encoded symbols that can improve the
50// compression rate.
51template <class TraversalDecoderT>
53 public:
55 bool Init(MeshEdgebreakerDecoder *decoder) override;
56
58 int att_id) const override;
60 int att_id) const override;
61
62 bool CreateAttributesDecoder(int32_t att_decoder_id) override;
63 bool DecodeConnectivity() override;
64 bool OnAttributesDecoded() override;
65 MeshEdgebreakerDecoder *GetDecoder() const override { return decoder_; }
66 const CornerTable *GetCornerTable() const override {
67 return corner_table_.get();
68 }
69
70 private:
71 // Creates a vertex traversal sequencer for the specified |TraverserT| type.
72 template <class TraverserT>
73 std::unique_ptr<PointsSequencer> CreateVertexTraversalSequencer(
75
76 // Decodes connectivity between vertices (vertex indices).
77 // Returns the number of vertices created by the decoder or -1 on error.
78 int DecodeConnectivity(int num_symbols);
79
80 // Returns true if the current symbol was part of a topology split event. This
81 // means that the current face was connected to the left edge of a face
82 // encoded with the TOPOLOGY_S symbol. |out_symbol_edge| can be used to
83 // identify which edge of the source symbol was connected to the TOPOLOGY_S
84 // symbol.
85 bool IsTopologySplit(int encoder_symbol_id, EdgeFaceName *out_face_edge,
86 int *out_encoder_split_symbol_id) {
87 if (topology_split_data_.size() == 0) {
88 return false;
89 }
90 if (topology_split_data_.back().source_symbol_id >
91 static_cast<uint32_t>(encoder_symbol_id)) {
92 // Something is wrong; if the desired source symbol is greater than the
93 // current encoder_symbol_id, we missed it, or the input was tampered
94 // (|encoder_symbol_id| keeps decreasing).
95 // Return invalid symbol id to notify the decoder that there was an
96 // error.
97 *out_encoder_split_symbol_id = -1;
98 return true;
99 }
100 if (topology_split_data_.back().source_symbol_id != encoder_symbol_id) {
101 return false;
102 }
103 *out_face_edge =
104 static_cast<EdgeFaceName>(topology_split_data_.back().source_edge);
105 *out_encoder_split_symbol_id = topology_split_data_.back().split_symbol_id;
106 // Remove the latest split event.
107 topology_split_data_.pop_back();
108 return true;
109 }
110
111 // Decodes event data for hole and topology split events and stores them for
112 // future use.
113 // Returns the number of parsed bytes, or -1 on error.
114 int32_t DecodeHoleAndTopologySplitEvents(DecoderBuffer *decoder_buffer);
115
116 // Decodes all non-position attribute connectivity on the currently
117 // processed face.
118#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
119 bool DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner);
120#endif
121 bool DecodeAttributeConnectivitiesOnFace(CornerIndex corner);
122
123 // Initializes mapping between corners and point ids.
124 bool AssignPointsToCorners(int num_connectivity_verts);
125
126 bool IsFaceVisited(CornerIndex corner_id) const {
127 if (corner_id < 0) {
128 return true; // Invalid corner signalizes that the face does not exist.
129 }
130 return visited_faces_[corner_table_->Face(corner_id).value()];
131 }
132
133 void SetOppositeCorners(CornerIndex corner_0, CornerIndex corner_1) {
134 corner_table_->SetOppositeCorner(corner_0, corner_1);
135 corner_table_->SetOppositeCorner(corner_1, corner_0);
136 }
137
138 MeshEdgebreakerDecoder *decoder_;
139
140 std::unique_ptr<CornerTable> corner_table_;
141
142 // Stack used for storing corners that need to be traversed when decoding
143 // mesh vertices. New corner is added for each initial face and a split
144 // symbol, and one corner is removed when the end symbol is reached.
145 // Stored as member variable to prevent frequent memory reallocations when
146 // handling meshes with lots of disjoint components. Originally, we used
147 // recursive functions to handle this behavior, but that can cause stack
148 // memory overflow when compressing huge meshes.
149 std::vector<CornerIndex> corner_traversal_stack_;
150
151 // Array stores the number of visited visited for each mesh traversal.
152 std::vector<int> vertex_traversal_length_;
153
154 // List of decoded topology split events.
155 std::vector<TopologySplitEventData> topology_split_data_;
156
157 // List of decoded hole events.
158 std::vector<HoleEventData> hole_event_data_;
159
160 // Configuration of the initial face for each mesh component.
161 std::vector<bool> init_face_configurations_;
162
163 // Initial corner for each traversal.
164 std::vector<CornerIndex> init_corners_;
165
166 // Id of the last processed input symbol.
167 int last_symbol_id_;
168
169 // Id of the last decoded vertex.
170 int last_vert_id_;
171
172 // Id of the last decoded face.
173 int last_face_id_;
174
175 // Array for marking visited faces.
176 std::vector<bool> visited_faces_;
177 // Array for marking visited vertices.
178 std::vector<bool> visited_verts_;
179 // Array for marking vertices on open boundaries.
180 std::vector<bool> is_vert_hole_;
181
182 // The number of new vertices added by the encoder (because of non-manifold
183 // vertices on the input mesh).
184 // If there are no non-manifold edges/vertices on the input mesh, this should
185 // be 0.
186 int num_new_vertices_;
187 // For every newly added vertex, this array stores it's mapping to the
188 // parent vertex id of the encoded mesh.
189 std::unordered_map<int, int> new_to_parent_vertex_map_;
190 // The number of vertices that were encoded (can be different from the number
191 // of vertices of the input mesh).
192 int num_encoded_vertices_;
193
194 // Array for storing the encoded corner ids in the order their associated
195 // vertices were decoded.
196 std::vector<int32_t> processed_corner_ids_;
197
198 // Array storing corners in the order they were visited during the
199 // connectivity decoding (always storing the tip corner of each newly visited
200 // face).
201 std::vector<int> processed_connectivity_corners_;
202
203 MeshAttributeIndicesEncodingData pos_encoding_data_;
204
205 // Id of an attributes decoder that uses |pos_encoding_data_|.
206 int pos_data_decoder_id_;
207
208 // Data for non-position attributes used by the decoder.
209 struct AttributeData {
210 AttributeData() : decoder_id(-1), is_connectivity_used(true) {}
211 // Id of the attribute decoder that was used to decode this attribute data.
212 int decoder_id;
213 MeshAttributeCornerTable connectivity_data;
214 // Flag that can mark the connectivity_data invalid. In such case the base
215 // corner table of the mesh should be used instead.
216 bool is_connectivity_used;
217 MeshAttributeIndicesEncodingData encoding_data;
218 // Opposite corners to attribute seam edges.
219 std::vector<int32_t> attribute_seam_corners;
220 };
221 std::vector<AttributeData> attribute_data_;
222
223 TraversalDecoderT traversal_decoder_;
224};
225
226} // namespace draco
227
228#endif // DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_DECODER_IMPL_H_
Definition corner_table.h:53
Definition mesh_attribute_corner_table.h:30
Definition mesh_edgebreaker_decoder_impl_interface.h:28
bool DecodeConnectivity() override
Definition mesh_edgebreaker_decoder_impl.cc:248
MeshEdgebreakerDecoder * GetDecoder() const override
Definition mesh_edgebreaker_decoder_impl.h:65
const MeshAttributeCornerTable * GetAttributeCornerTable(int att_id) const override
Definition mesh_edgebreaker_decoder_impl.cc:66
const CornerTable * GetCornerTable() const override
Definition mesh_edgebreaker_decoder_impl.h:66
bool CreateAttributesDecoder(int32_t att_decoder_id) override
Definition mesh_edgebreaker_decoder_impl.cc:130
bool Init(MeshEdgebreakerDecoder *decoder) override
Definition mesh_edgebreaker_decoder_impl.cc:58
bool OnAttributesDecoded() override
Definition mesh_edgebreaker_decoder_impl.cc:515
MeshEdgebreakerDecoderImpl()
Definition mesh_edgebreaker_decoder_impl.cc:48
const MeshAttributeIndicesEncodingData * GetAttributeEncodingData(int att_id) const override
Definition mesh_edgebreaker_decoder_impl.cc:89
Definition mesh_edgebreaker_decoder.h:25
Definition attribute_octahedron_transform.cc:21
EdgeFaceName
Definition mesh_edgebreaker_shared.h:94
CornerIndex CornerIndex
Definition mesh_edgebreaker_encoder_impl.cc:35
Definition mesh_attribute_indices_encoding_data.h:27