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 #include "draco/compression/mesh/mesh_edgebreaker_decoder_impl.h"
16
17 #include <algorithm>
18
19 #include "draco/compression/attributes/sequential_attribute_decoders_controller.h"
20 #include "draco/compression/mesh/mesh_edgebreaker_decoder.h"
21 #include "draco/compression/mesh/mesh_edgebreaker_traversal_predictive_decoder.h"
22 #include "draco/compression/mesh/mesh_edgebreaker_traversal_valence_decoder.h"
23 #include "draco/compression/mesh/traverser/depth_first_traverser.h"
24 #include "draco/compression/mesh/traverser/max_prediction_degree_traverser.h"
25 #include "draco/compression/mesh/traverser/mesh_attribute_indices_encoding_observer.h"
26 #include "draco/compression/mesh/traverser/mesh_traversal_sequencer.h"
27 #include "draco/compression/mesh/traverser/traverser_base.h"
28 #include "draco/mesh/corner_table_iterators.h"
29
30 namespace draco {
31
32 // Types of "free" edges that are used during topology decoding.
33 // A free edge is an edge that is connected to one face only.
34 // All edge types are stored in the opposite_corner_id_ array, where each
35 // edge "e" is uniquely identified by the opposite corner "C" in its parent
36 // triangle:
37 // *
38 // /C\
39 // / \
40 // / e \
41 // *-------*
42 // For more description about how the edges are used, see comment inside
43 // ZipConnectivity() method.
44
45 template <class TraversalDecoder>
MeshEdgebreakerDecoderImpl()46 MeshEdgebreakerDecoderImpl<TraversalDecoder>::MeshEdgebreakerDecoderImpl()
47 : decoder_(nullptr),
48 last_symbol_id_(-1),
49 last_vert_id_(-1),
50 last_face_id_(-1),
51 num_new_vertices_(0),
52 num_encoded_vertices_(0),
53 pos_data_decoder_id_(-1) {}
54
55 template <class TraversalDecoder>
Init(MeshEdgebreakerDecoder * decoder)56 bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::Init(
57 MeshEdgebreakerDecoder *decoder) {
58 decoder_ = decoder;
59 return true;
60 }
61
62 template <class TraversalDecoder>
63 const MeshAttributeCornerTable *
GetAttributeCornerTable(int att_id) const64 MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeCornerTable(
65 int att_id) const {
66 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
67 const int decoder_id = attribute_data_[i].decoder_id;
68 if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders())
69 continue;
70 const AttributesDecoderInterface *const dec =
71 decoder_->attributes_decoder(decoder_id);
72 for (int j = 0; j < dec->GetNumAttributes(); ++j) {
73 if (dec->GetAttributeId(j) == att_id) {
74 if (attribute_data_[i].is_connectivity_used)
75 return &attribute_data_[i].connectivity_data;
76 return nullptr;
77 }
78 }
79 }
80 return nullptr;
81 }
82
83 template <class TraversalDecoder>
84 const MeshAttributeIndicesEncodingData *
GetAttributeEncodingData(int att_id) const85 MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeEncodingData(
86 int att_id) const {
87 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
88 const int decoder_id = attribute_data_[i].decoder_id;
89 if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders())
90 continue;
91 const AttributesDecoderInterface *const dec =
92 decoder_->attributes_decoder(decoder_id);
93 for (int j = 0; j < dec->GetNumAttributes(); ++j) {
94 if (dec->GetAttributeId(j) == att_id)
95 return &attribute_data_[i].encoding_data;
96 }
97 }
98 return &pos_encoding_data_;
99 }
100
101 template <class TraversalDecoder>
102 template <class TraverserT>
103 std::unique_ptr<PointsSequencer>
CreateVertexTraversalSequencer(MeshAttributeIndicesEncodingData * encoding_data)104 MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateVertexTraversalSequencer(
105 MeshAttributeIndicesEncodingData *encoding_data) {
106 typedef typename TraverserT::TraversalObserver AttObserver;
107 typedef typename TraverserT::CornerTable CornerTable;
108
109 const Mesh *mesh = decoder_->mesh();
110 std::unique_ptr<MeshTraversalSequencer<TraverserT>> traversal_sequencer(
111 new MeshTraversalSequencer<TraverserT>(mesh, encoding_data));
112
113 AttObserver att_observer(corner_table_.get(), mesh, traversal_sequencer.get(),
114 encoding_data);
115
116 TraverserT att_traverser;
117 att_traverser.Init(corner_table_.get(), att_observer);
118
119 traversal_sequencer->SetTraverser(att_traverser);
120 return std::move(traversal_sequencer);
121 }
122
123 template <class TraversalDecoder>
CreateAttributesDecoder(int32_t att_decoder_id)124 bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder(
125 int32_t att_decoder_id) {
126 int8_t att_data_id;
127 if (!decoder_->buffer()->Decode(&att_data_id))
128 return false;
129 uint8_t decoder_type;
130 if (!decoder_->buffer()->Decode(&decoder_type))
131 return false;
132
133 if (att_data_id >= 0) {
134 if (att_data_id >= attribute_data_.size()) {
135 return false; // Unexpected attribute data.
136 }
137
138 // Ensure that the attribute data is not mapped to a different attributes
139 // decoder already.
140 if (attribute_data_[att_data_id].decoder_id >= 0)
141 return false;
142
143 attribute_data_[att_data_id].decoder_id = att_decoder_id;
144 } else {
145 // Assign the attributes decoder to |pos_encoding_data_|.
146 if (pos_data_decoder_id_ >= 0)
147 return false; // Some other decoder is already using the data. Error.
148 pos_data_decoder_id_ = att_decoder_id;
149 }
150
151 MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
152 if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
153 uint8_t traversal_method_encoded;
154 if (!decoder_->buffer()->Decode(&traversal_method_encoded))
155 return false;
156 traversal_method =
157 static_cast<MeshTraversalMethod>(traversal_method_encoded);
158 }
159
160 const Mesh *mesh = decoder_->mesh();
161 std::unique_ptr<PointsSequencer> sequencer;
162
163 if (decoder_type == MESH_VERTEX_ATTRIBUTE) {
164 // Per-vertex attribute decoder.
165
166 MeshAttributeIndicesEncodingData *encoding_data = nullptr;
167 if (att_data_id < 0) {
168 encoding_data = &pos_encoding_data_;
169 } else {
170 encoding_data = &attribute_data_[att_data_id].encoding_data;
171 // Mark the attribute connectivity data invalid to ensure it's not used
172 // later on.
173 attribute_data_[att_data_id].is_connectivity_used = false;
174 }
175 // Defining sequencer via a traversal scheme.
176 if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
177 typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
178 typedef MaxPredictionDegreeTraverser<CornerTable, AttObserver>
179 AttTraverser;
180 sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
181 } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) {
182 typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
183 typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser;
184 sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
185 } else {
186 return false; // Unsupported method
187 }
188 } else {
189 if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST)
190 return false; // Unsupported method.
191 if (att_data_id < 0)
192 return false; // Attribute data must be specified.
193
194 // Per-corner attribute decoder.
195
196 typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable>
197 AttObserver;
198 typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver>
199 AttTraverser;
200
201 MeshAttributeIndicesEncodingData *const encoding_data =
202 &attribute_data_[att_data_id].encoding_data;
203 const MeshAttributeCornerTable *const corner_table =
204 &attribute_data_[att_data_id].connectivity_data;
205
206 std::unique_ptr<MeshTraversalSequencer<AttTraverser>> traversal_sequencer(
207 new MeshTraversalSequencer<AttTraverser>(mesh, encoding_data));
208
209 AttObserver att_observer(corner_table, mesh, traversal_sequencer.get(),
210 encoding_data);
211
212 AttTraverser att_traverser;
213 att_traverser.Init(corner_table, att_observer);
214
215 traversal_sequencer->SetTraverser(att_traverser);
216 sequencer = std::move(traversal_sequencer);
217 }
218
219 if (!sequencer)
220 return false;
221
222 std::unique_ptr<SequentialAttributeDecodersController> att_controller(
223 new SequentialAttributeDecodersController(std::move(sequencer)));
224
225 return decoder_->SetAttributesDecoder(att_decoder_id,
226 std::move(att_controller));
227 }
228
229 template <class TraversalDecoder>
DecodeConnectivity()230 bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
231 num_new_vertices_ = 0;
232 new_to_parent_vertex_map_.clear();
233 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
234 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
235 uint32_t num_new_verts;
236 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
237 if (!decoder_->buffer()->Decode(&num_new_verts))
238 return false;
239 } else {
240 if (!DecodeVarint(&num_new_verts, decoder_->buffer()))
241 return false;
242 }
243 num_new_vertices_ = num_new_verts;
244 }
245 #endif
246
247 uint32_t num_encoded_vertices;
248 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
249 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
250 if (!decoder_->buffer()->Decode(&num_encoded_vertices))
251 return false;
252
253 } else
254 #endif
255 {
256 if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer()))
257 return false;
258 }
259 num_encoded_vertices_ = num_encoded_vertices;
260
261 uint32_t num_faces;
262 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
263 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
264 if (!decoder_->buffer()->Decode(&num_faces))
265 return false;
266
267 } else
268 #endif
269 {
270 if (!DecodeVarint(&num_faces, decoder_->buffer()))
271 return false;
272 }
273 if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3)
274 return false; // Draco cannot handle this many faces.
275
276 if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) {
277 return false; // There cannot be more vertices than 3 * num_faces.
278 }
279 uint8_t num_attribute_data;
280 if (!decoder_->buffer()->Decode(&num_attribute_data))
281 return false;
282
283 uint32_t num_encoded_symbols;
284 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
285 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
286 if (!decoder_->buffer()->Decode(&num_encoded_symbols))
287 return false;
288
289 } else
290 #endif
291 {
292 if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer()))
293 return false;
294 }
295
296 if (num_faces < num_encoded_symbols) {
297 // Number of faces needs to be the same or greater than the number of
298 // symbols (it can be greater because the initial face may not be encoded as
299 // a symbol).
300 return false;
301 }
302 const uint32_t max_encoded_faces =
303 num_encoded_symbols + (num_encoded_symbols / 3);
304 if (num_faces > max_encoded_faces) {
305 // Faces can only be 1 1/3 times bigger than number of encoded symbols. This
306 // could only happen if all new encoded components started with interior
307 // triangles. E.g. A mesh with multiple tetrahedrons.
308 return false;
309 }
310
311 uint32_t num_encoded_split_symbols;
312 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
313 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
314 if (!decoder_->buffer()->Decode(&num_encoded_split_symbols))
315 return false;
316
317 } else
318 #endif
319 {
320 if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer()))
321 return false;
322 }
323
324 if (num_encoded_split_symbols > num_encoded_symbols) {
325 return false; // Split symbols are a sub-set of all symbols.
326 }
327
328 // Decode topology (connectivity).
329 vertex_traversal_length_.clear();
330 corner_table_ = std::unique_ptr<CornerTable>(new CornerTable());
331 if (corner_table_ == nullptr)
332 return false;
333 processed_corner_ids_.clear();
334 processed_corner_ids_.reserve(num_faces);
335 processed_connectivity_corners_.clear();
336 processed_connectivity_corners_.reserve(num_faces);
337 topology_split_data_.clear();
338 hole_event_data_.clear();
339 init_face_configurations_.clear();
340 init_corners_.clear();
341
342 last_symbol_id_ = -1;
343 last_face_id_ = -1;
344 last_vert_id_ = -1;
345
346 attribute_data_.clear();
347 // Add one attribute data for each attribute decoder.
348 attribute_data_.resize(num_attribute_data);
349
350 if (!corner_table_->Reset(num_faces,
351 num_encoded_vertices_ + num_encoded_split_symbols))
352 return false;
353
354 // Start with all vertices marked as holes (boundaries).
355 // Only vertices decoded with TOPOLOGY_C symbol (and the initial face) will
356 // be marked as non hole vertices. We need to allocate the array larger
357 // because split symbols can create extra vertices during the decoding
358 // process (these extra vertices are then eliminated during deduplication).
359 is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
360
361 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
362 int32_t topology_split_decoded_bytes = -1;
363 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
364 uint32_t encoded_connectivity_size;
365 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
366 if (!decoder_->buffer()->Decode(&encoded_connectivity_size))
367 return false;
368 } else {
369 if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer()))
370 return false;
371 }
372 if (encoded_connectivity_size == 0 ||
373 encoded_connectivity_size > decoder_->buffer()->remaining_size())
374 return false;
375 DecoderBuffer event_buffer;
376 event_buffer.Init(
377 decoder_->buffer()->data_head() + encoded_connectivity_size,
378 decoder_->buffer()->remaining_size() - encoded_connectivity_size,
379 decoder_->buffer()->bitstream_version());
380 // Decode hole and topology split events.
381 topology_split_decoded_bytes =
382 DecodeHoleAndTopologySplitEvents(&event_buffer);
383 if (topology_split_decoded_bytes == -1)
384 return false;
385
386 } else
387 #endif
388 {
389 if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1)
390 return false;
391 }
392
393 traversal_decoder_.Init(this);
394 // Add one extra vertex for each split symbol.
395 traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
396 num_encoded_split_symbols);
397 traversal_decoder_.SetNumAttributeData(num_attribute_data);
398
399 DecoderBuffer traversal_end_buffer;
400 if (!traversal_decoder_.Start(&traversal_end_buffer))
401 return false;
402
403 const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols);
404 if (num_connectivity_verts == -1)
405 return false;
406
407 // Set the main buffer to the end of the traversal.
408 decoder_->buffer()->Init(traversal_end_buffer.data_head(),
409 traversal_end_buffer.remaining_size(),
410 decoder_->buffer()->bitstream_version());
411
412 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
413 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
414 // Skip topology split data that was already decoded earlier.
415 decoder_->buffer()->Advance(topology_split_decoded_bytes);
416 }
417 #endif
418
419 // Decode connectivity of non-position attributes.
420 if (attribute_data_.size() > 0) {
421 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
422 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
423 for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
424 if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci))
425 return false;
426 }
427
428 } else
429 #endif
430 {
431 for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
432 if (!DecodeAttributeConnectivitiesOnFace(ci))
433 return false;
434 }
435 }
436 }
437 traversal_decoder_.Done();
438
439 // Decode attribute connectivity.
440 // Prepare data structure for decoding non-position attribute connectivity.
441 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
442 attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get());
443 // Add all seams.
444 for (int32_t c : attribute_data_[i].attribute_seam_corners) {
445 attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c));
446 }
447 // Recompute vertices from the newly added seam edges.
448 attribute_data_[i].connectivity_data.RecomputeVertices(nullptr, nullptr);
449 }
450
451 pos_encoding_data_.Init(corner_table_->num_vertices());
452 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
453 // For non-position attributes, preallocate the vertex to value mapping
454 // using the maximum number of vertices from the base corner table and the
455 // attribute corner table (since the attribute decoder may use either of
456 // it).
457 int32_t att_connectivity_verts =
458 attribute_data_[i].connectivity_data.num_vertices();
459 if (att_connectivity_verts < corner_table_->num_vertices())
460 att_connectivity_verts = corner_table_->num_vertices();
461 attribute_data_[i].encoding_data.Init(att_connectivity_verts);
462 }
463 if (!AssignPointsToCorners(num_connectivity_verts))
464 return false;
465 return true;
466 }
467
468 template <class TraversalDecoder>
OnAttributesDecoded()469 bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() {
470 return true;
471 }
472
473 template <class TraversalDecoder>
DecodeConnectivity(int num_symbols)474 int MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity(
475 int num_symbols) {
476 // Algorithm does the reverse decoding of the symbols encoded with the
477 // edgebreaker method. The reverse decoding always keeps track of the active
478 // edge identified by its opposite corner (active corner). New faces are
479 // always added to this active edge. There may be multiple active corners at
480 // one time that either correspond to separate mesh components or to
481 // sub-components of one mesh that are going to be merged together using the
482 // TOPOLOGY_S symbol. We can store these active edges on a stack, because the
483 // decoder always processes only the latest active edge. TOPOLOGY_S then
484 // removes the top edge from the stack and TOPOLOGY_E adds a new edge to the
485 // stack.
486 std::vector<CornerIndex> active_corner_stack;
487
488 // Additional active edges may be added as a result of topology split events.
489 // They can be added in arbitrary order, but we always know the split symbol
490 // id they belong to, so we can address them using this symbol id.
491 std::unordered_map<int, CornerIndex> topology_split_active_corners;
492
493 // Vector used for storing vertices that were marked as isolated during the
494 // decoding process. Currently used only when the mesh doesn't contain any
495 // non-position connectivity data.
496 std::vector<VertexIndex> invalid_vertices;
497 const bool remove_invalid_vertices = attribute_data_.empty();
498
499 int max_num_vertices = static_cast<int>(is_vert_hole_.size());
500 int num_faces = 0;
501 for (int symbol_id = 0; symbol_id < num_symbols; ++symbol_id) {
502 const FaceIndex face(num_faces++);
503 // Used to flag cases where we need to look for topology split events.
504 bool check_topology_split = false;
505 const uint32_t symbol = traversal_decoder_.DecodeSymbol();
506 if (symbol == TOPOLOGY_C) {
507 // Create a new face between two edges on the open boundary.
508 // The first edge is opposite to the corner "a" from the image below.
509 // The other edge is opposite to the corner "b" that can be reached
510 // through a CCW traversal around the vertex "v".
511 // One new active boundary edge is created, opposite to the new corner
512 // "x".
513 //
514 // *-------*
515 // / \ / \
516 // / \ / \
517 // / \ / \
518 // *-------v-------*
519 // \b /x\ a/
520 // \ / \ /
521 // \ / C \ /
522 // *.......*
523
524 // Find the corner "b" from the corner "a" which is the corner on the
525 // top of the active stack.
526 if (active_corner_stack.empty())
527 return -1;
528
529 const CornerIndex corner_a = active_corner_stack.back();
530 const VertexIndex vertex_x =
531 corner_table_->Vertex(corner_table_->Next(corner_a));
532 const CornerIndex corner_b =
533 corner_table_->Next(corner_table_->LeftMostCorner(vertex_x));
534
535 // New tip corner.
536 const CornerIndex corner(3 * face.value());
537 // Update opposite corner mappings.
538 SetOppositeCorners(corner_a, corner + 1);
539 SetOppositeCorners(corner_b, corner + 2);
540
541 // Update vertex mapping.
542 corner_table_->MapCornerToVertex(corner, vertex_x);
543 corner_table_->MapCornerToVertex(
544 corner + 1, corner_table_->Vertex(corner_table_->Next(corner_b)));
545 const VertexIndex vert_a_prev =
546 corner_table_->Vertex(corner_table_->Previous(corner_a));
547 corner_table_->MapCornerToVertex(corner + 2, vert_a_prev);
548 corner_table_->SetLeftMostCorner(vert_a_prev, corner + 2);
549 // Mark the vertex |x| as interior.
550 is_vert_hole_[vertex_x.value()] = false;
551 // Update the corner on the active stack.
552 active_corner_stack.back() = corner;
553 } else if (symbol == TOPOLOGY_R || symbol == TOPOLOGY_L) {
554 // Create a new face extending from the open boundary edge opposite to the
555 // corner "a" from the image below. Two new boundary edges are created
556 // opposite to corners "r" and "l". New active corner is set to either "r"
557 // or "l" depending on the decoded symbol. One new vertex is created
558 // at the opposite corner to corner "a".
559 // *-------*
560 // /a\ / \
561 // / \ / \
562 // / \ / \
563 // *-------v-------*
564 // .l r.
565 // . .
566 // . .
567 // *
568 if (active_corner_stack.empty())
569 return -1;
570 const CornerIndex corner_a = active_corner_stack.back();
571
572 // First corner on the new face is either corner "l" or "r".
573 const CornerIndex corner(3 * face.value());
574 CornerIndex opp_corner, corner_l, corner_r;
575 if (symbol == TOPOLOGY_R) {
576 // "r" is the new first corner.
577 opp_corner = corner + 2;
578 corner_l = corner + 1;
579 corner_r = corner;
580 } else {
581 // "l" is the new first corner.
582 opp_corner = corner + 1;
583 corner_l = corner;
584 corner_r = corner + 2;
585 }
586 SetOppositeCorners(opp_corner, corner_a);
587 // Update vertex mapping.
588 const VertexIndex new_vert_index = corner_table_->AddNewVertex();
589
590 if (corner_table_->num_vertices() > max_num_vertices)
591 return -1; // Unexpected number of decoded vertices.
592
593 corner_table_->MapCornerToVertex(opp_corner, new_vert_index);
594 corner_table_->SetLeftMostCorner(new_vert_index, opp_corner);
595
596 const VertexIndex vertex_r =
597 corner_table_->Vertex(corner_table_->Previous(corner_a));
598 corner_table_->MapCornerToVertex(corner_r, vertex_r);
599 // Update left-most corner on the vertex on the |corner_r|.
600 corner_table_->SetLeftMostCorner(vertex_r, corner_r);
601
602 corner_table_->MapCornerToVertex(
603 corner_l, corner_table_->Vertex(corner_table_->Next(corner_a)));
604 active_corner_stack.back() = corner;
605 check_topology_split = true;
606 } else if (symbol == TOPOLOGY_S) {
607 // Create a new face that merges two last active edges from the active
608 // stack. No new vertex is created, but two vertices at corners "p" and
609 // "n" need to be merged into a single vertex.
610 //
611 // *-------v-------*
612 // \a p/x\n b/
613 // \ / \ /
614 // \ / S \ /
615 // *.......*
616 //
617 if (active_corner_stack.empty())
618 return -1;
619 const CornerIndex corner_b = active_corner_stack.back();
620 active_corner_stack.pop_back();
621
622 // Corner "a" can correspond either to a normal active edge, or to an edge
623 // created from the topology split event.
624 const auto it = topology_split_active_corners.find(symbol_id);
625 if (it != topology_split_active_corners.end()) {
626 // Topology split event. Move the retrieved edge to the stack.
627 active_corner_stack.push_back(it->second);
628 }
629 if (active_corner_stack.empty())
630 return -1;
631 const CornerIndex corner_a = active_corner_stack.back();
632
633 if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex ||
634 corner_table_->Opposite(corner_b) != kInvalidCornerIndex) {
635 // One of the corners is already opposite to an existing face, which
636 // should not happen unless the input was tempered with.
637 return -1;
638 }
639
640 // First corner on the new face is corner "x" from the image above.
641 const CornerIndex corner(3 * face.value());
642 // Update the opposite corner mapping.
643 SetOppositeCorners(corner_a, corner + 2);
644 SetOppositeCorners(corner_b, corner + 1);
645 // Update vertices. For the vertex at corner "x", use the vertex id from
646 // the corner "p".
647 const VertexIndex vertex_p =
648 corner_table_->Vertex(corner_table_->Previous(corner_a));
649 corner_table_->MapCornerToVertex(corner, vertex_p);
650 corner_table_->MapCornerToVertex(
651 corner + 1, corner_table_->Vertex(corner_table_->Next(corner_a)));
652 const VertexIndex vert_b_prev =
653 corner_table_->Vertex(corner_table_->Previous(corner_b));
654 corner_table_->MapCornerToVertex(corner + 2, vert_b_prev);
655 corner_table_->SetLeftMostCorner(vert_b_prev, corner + 2);
656 CornerIndex corner_n = corner_table_->Next(corner_b);
657 const VertexIndex vertex_n = corner_table_->Vertex(corner_n);
658 traversal_decoder_.MergeVertices(vertex_p, vertex_n);
659 // Update the left most corner on the newly merged vertex.
660 corner_table_->SetLeftMostCorner(vertex_p,
661 corner_table_->LeftMostCorner(vertex_n));
662
663 // Also update the vertex id at corner "n" and all corners that are
664 // connected to it in the CCW direction.
665 while (corner_n != kInvalidCornerIndex) {
666 corner_table_->MapCornerToVertex(corner_n, vertex_p);
667 corner_n = corner_table_->SwingLeft(corner_n);
668 }
669 // Make sure the old vertex n is now mapped to an invalid corner (make it
670 // isolated).
671 corner_table_->MakeVertexIsolated(vertex_n);
672 if (remove_invalid_vertices)
673 invalid_vertices.push_back(vertex_n);
674 active_corner_stack.back() = corner;
675 } else if (symbol == TOPOLOGY_E) {
676 const CornerIndex corner(3 * face.value());
677 const VertexIndex first_vert_index = corner_table_->AddNewVertex();
678 // Create three new vertices at the corners of the new face.
679 corner_table_->MapCornerToVertex(corner, first_vert_index);
680 corner_table_->MapCornerToVertex(corner + 1,
681 corner_table_->AddNewVertex());
682 corner_table_->MapCornerToVertex(corner + 2,
683 corner_table_->AddNewVertex());
684
685 if (corner_table_->num_vertices() > max_num_vertices)
686 return -1; // Unexpected number of decoded vertices.
687
688 corner_table_->SetLeftMostCorner(first_vert_index, corner);
689 corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1);
690 corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2);
691 // Add the tip corner to the active stack.
692 active_corner_stack.push_back(corner);
693 check_topology_split = true;
694 } else {
695 // Error. Unknown symbol decoded.
696 return -1;
697 }
698 // Inform the traversal decoder that a new corner has been reached.
699 traversal_decoder_.NewActiveCornerReached(active_corner_stack.back());
700
701 if (check_topology_split) {
702 // Check for topology splits happens only for TOPOLOGY_L, TOPOLOGY_R and
703 // TOPOLOGY_E symbols because those are the symbols that correspond to
704 // faces that can be directly connected a TOPOLOGY_S face through the
705 // topology split event.
706 // If a topology split is detected, we need to add a new active edge
707 // onto the active_corner_stack because it will be used later when the
708 // corresponding TOPOLOGY_S event is decoded.
709
710 // Symbol id used by the encoder (reverse).
711 const int encoder_symbol_id = num_symbols - symbol_id - 1;
712 EdgeFaceName split_edge;
713 int encoder_split_symbol_id;
714 while (IsTopologySplit(encoder_symbol_id, &split_edge,
715 &encoder_split_symbol_id)) {
716 if (encoder_split_symbol_id < 0)
717 return -1; // Wrong split symbol id.
718 // Symbol was part of a topology split. Now we need to determine which
719 // edge should be added to the active edges stack.
720 const CornerIndex act_top_corner = active_corner_stack.back();
721 // The current symbol has one active edge (stored in act_top_corner) and
722 // two remaining inactive edges that are attached to it.
723 // *
724 // / \
725 // left_edge / \ right_edge
726 // / \
727 // *.......*
728 // active_edge
729
730 CornerIndex new_active_corner;
731 if (split_edge == RIGHT_FACE_EDGE) {
732 new_active_corner = corner_table_->Next(act_top_corner);
733 } else {
734 new_active_corner = corner_table_->Previous(act_top_corner);
735 }
736 // Add the new active edge.
737 // Convert the encoder split symbol id to decoder symbol id.
738 const int decoder_split_symbol_id =
739 num_symbols - encoder_split_symbol_id - 1;
740 topology_split_active_corners[decoder_split_symbol_id] =
741 new_active_corner;
742 }
743 }
744 }
745 if (corner_table_->num_vertices() > max_num_vertices)
746 return -1; // Unexpected number of decoded vertices.
747 // Decode start faces and connect them to the faces from the active stack.
748 while (active_corner_stack.size() > 0) {
749 const CornerIndex corner = active_corner_stack.back();
750 active_corner_stack.pop_back();
751 const bool interior_face =
752 traversal_decoder_.DecodeStartFaceConfiguration();
753 if (interior_face) {
754 // The start face is interior, we need to find three corners that are
755 // opposite to it. The first opposite corner "a" is the corner from the
756 // top of the active corner stack and the remaining two corners "b" and
757 // "c" are then the next corners from the left-most corners of vertices
758 // "n" and "x" respectively.
759 //
760 // *-------*
761 // / \ / \
762 // / \ / \
763 // / \ / \
764 // *-------p-------*
765 // / \a . . c/ \
766 // / \ . . / \
767 // / \ . I . / \
768 // *-------n.......x------*
769 // \ / \ / \ /
770 // \ / \ / \ /
771 // \ / \b/ \ /
772 // *-------*-------*
773 //
774
775 if (num_faces >= corner_table_->num_faces()) {
776 return -1; // More faces than expected added to the mesh.
777 }
778
779 const CornerIndex corner_a = corner;
780 const VertexIndex vert_n =
781 corner_table_->Vertex(corner_table_->Next(corner_a));
782 const CornerIndex corner_b =
783 corner_table_->Next(corner_table_->LeftMostCorner(vert_n));
784
785 const VertexIndex vert_x =
786 corner_table_->Vertex(corner_table_->Next(corner_b));
787 const CornerIndex corner_c =
788 corner_table_->Next(corner_table_->LeftMostCorner(vert_x));
789
790 const VertexIndex vert_p =
791 corner_table_->Vertex(corner_table_->Next(corner_c));
792
793 const FaceIndex face(num_faces++);
794 // The first corner of the initial face is the corner opposite to "a".
795 const CornerIndex new_corner(3 * face.value());
796 SetOppositeCorners(new_corner, corner);
797 SetOppositeCorners(new_corner + 1, corner_b);
798 SetOppositeCorners(new_corner + 2, corner_c);
799
800 // Map new corners to existing vertices.
801 corner_table_->MapCornerToVertex(new_corner, vert_x);
802 corner_table_->MapCornerToVertex(new_corner + 1, vert_p);
803 corner_table_->MapCornerToVertex(new_corner + 2, vert_n);
804
805 // Mark all three vertices as interior.
806 for (int ci = 0; ci < 3; ++ci) {
807 is_vert_hole_[corner_table_->Vertex(new_corner + ci).value()] = false;
808 }
809
810 init_face_configurations_.push_back(true);
811 init_corners_.push_back(new_corner);
812 } else {
813 // The initial face wasn't interior and the traversal had to start from
814 // an open boundary. In this case no new face is added, but we need to
815 // keep record about the first opposite corner to this boundary.
816 init_face_configurations_.push_back(false);
817 init_corners_.push_back(corner);
818 }
819 }
820 if (num_faces != corner_table_->num_faces())
821 return -1; // Unexpected number of decoded faces.
822
823 int num_vertices = corner_table_->num_vertices();
824 // If any vertex was marked as isolated, we want to remove it from the corner
825 // table to ensure that all vertices in range <0, num_vertices> are valid.
826 for (const VertexIndex invalid_vert : invalid_vertices) {
827 // Find the last valid vertex and swap it with the isolated vertex.
828 VertexIndex src_vert(num_vertices - 1);
829 while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) {
830 // The last vertex is invalid, proceed to the previous one.
831 src_vert = VertexIndex(--num_vertices - 1);
832 }
833 if (src_vert < invalid_vert)
834 continue; // No need to swap anything.
835
836 // Remap all corners mapped to |src_vert| to |invalid_vert|.
837 VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert);
838 for (; !vcit.End(); ++vcit) {
839 const CornerIndex cid = vcit.Corner();
840 corner_table_->MapCornerToVertex(cid, invalid_vert);
841 }
842 corner_table_->SetLeftMostCorner(invalid_vert,
843 corner_table_->LeftMostCorner(src_vert));
844
845 // Make the |src_vert| invalid.
846 corner_table_->MakeVertexIsolated(src_vert);
847 is_vert_hole_[invalid_vert.value()] = is_vert_hole_[src_vert.value()];
848 is_vert_hole_[src_vert.value()] = false;
849
850 // The last vertex is now invalid.
851 num_vertices--;
852 }
853 return num_vertices;
854 }
855
856 template <class TraversalDecoder>
857 int32_t
DecodeHoleAndTopologySplitEvents(DecoderBuffer * decoder_buffer)858 MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
859 DecoderBuffer *decoder_buffer) {
860 // Prepare a new decoder from the provided buffer offset.
861 uint32_t num_topology_splits;
862 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
863 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
864 if (!decoder_buffer->Decode(&num_topology_splits))
865 return -1;
866
867 } else
868 #endif
869 {
870 if (!DecodeVarint(&num_topology_splits, decoder_buffer))
871 return -1;
872 }
873 if (num_topology_splits > 0) {
874 if (num_topology_splits > static_cast<uint32_t>(corner_table_->num_faces()))
875 return -1;
876 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
877 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
878 for (uint32_t i = 0; i < num_topology_splits; ++i) {
879 TopologySplitEventData event_data;
880 if (!decoder_buffer->Decode(&event_data.split_symbol_id))
881 return -1;
882 if (!decoder_buffer->Decode(&event_data.source_symbol_id))
883 return -1;
884 uint8_t edge_data;
885 if (!decoder_buffer->Decode(&edge_data))
886 return -1;
887 event_data.source_edge = edge_data & 1;
888 topology_split_data_.push_back(event_data);
889 }
890
891 } else
892 #endif
893 {
894 // Decode source and split symbol ids using delta and varint coding. See
895 // description in mesh_edgebreaker_encoder_impl.cc for more details.
896 int last_source_symbol_id = 0;
897 for (uint32_t i = 0; i < num_topology_splits; ++i) {
898 TopologySplitEventData event_data;
899 uint32_t delta;
900 DecodeVarint<uint32_t>(&delta, decoder_buffer);
901 event_data.source_symbol_id = delta + last_source_symbol_id;
902 DecodeVarint<uint32_t>(&delta, decoder_buffer);
903 if (delta > event_data.source_symbol_id)
904 return -1;
905 event_data.split_symbol_id =
906 event_data.source_symbol_id - static_cast<int32_t>(delta);
907 last_source_symbol_id = event_data.source_symbol_id;
908 topology_split_data_.push_back(event_data);
909 }
910 // Split edges are decoded from a direct bit decoder.
911 decoder_buffer->StartBitDecoding(false, nullptr);
912 for (uint32_t i = 0; i < num_topology_splits; ++i) {
913 uint32_t edge_data;
914 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
915 decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data);
916 } else {
917 decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data);
918 }
919 TopologySplitEventData &event_data = topology_split_data_[i];
920 event_data.source_edge = edge_data & 1;
921 }
922 decoder_buffer->EndBitDecoding();
923 }
924 }
925 uint32_t num_hole_events = 0;
926 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
927 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
928 if (!decoder_buffer->Decode(&num_hole_events))
929 return -1;
930 } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
931 if (!DecodeVarint(&num_hole_events, decoder_buffer))
932 return -1;
933 }
934 #endif
935 if (num_hole_events > 0) {
936 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
937 if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
938 for (uint32_t i = 0; i < num_hole_events; ++i) {
939 HoleEventData event_data;
940 if (!decoder_buffer->Decode(&event_data))
941 return -1;
942 hole_event_data_.push_back(event_data);
943 }
944
945 } else
946 #endif
947 {
948 // Decode hole symbol ids using delta and varint coding.
949 int last_symbol_id = 0;
950 for (uint32_t i = 0; i < num_hole_events; ++i) {
951 HoleEventData event_data;
952 uint32_t delta;
953 DecodeVarint<uint32_t>(&delta, decoder_buffer);
954 event_data.symbol_id = delta + last_symbol_id;
955 last_symbol_id = event_data.symbol_id;
956 hole_event_data_.push_back(event_data);
957 }
958 }
959 }
960 return static_cast<int32_t>(decoder_buffer->decoded_size());
961 }
962
963 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
964 template <class TraversalDecoder>
965 bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::
DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner)966 DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
967 // Three corners of the face.
968 const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
969 corner_table_->Previous(corner)};
970
971 for (int c = 0; c < 3; ++c) {
972 const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
973 if (opp_corner == kInvalidCornerIndex) {
974 // Don't decode attribute seams on boundary edges (every boundary edge
975 // is automatically an attribute seam).
976 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
977 attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
978 }
979 continue;
980 }
981
982 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
983 const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
984 if (is_seam)
985 attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
986 }
987 }
988 return true;
989 }
990 #endif
991
992 template <class TraversalDecoder>
993 bool MeshEdgebreakerDecoderImpl<
DecodeAttributeConnectivitiesOnFace(CornerIndex corner)994 TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
995 // Three corners of the face.
996 const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
997 corner_table_->Previous(corner)};
998
999 const FaceIndex src_face_id = corner_table_->Face(corner);
1000 for (int c = 0; c < 3; ++c) {
1001 const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
1002 if (opp_corner == kInvalidCornerIndex) {
1003 // Don't decode attribute seams on boundary edges (every boundary edge
1004 // is automatically an attribute seam).
1005 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
1006 attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
1007 }
1008 continue;
1009 }
1010 const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
1011 // Don't decode edges when the opposite face has been already processed.
1012 if (opp_face_id < src_face_id)
1013 continue;
1014
1015 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
1016 const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
1017 if (is_seam)
1018 attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
1019 }
1020 }
1021 return true;
1022 }
1023
1024 template <class TraversalDecoder>
AssignPointsToCorners(int num_connectivity_verts)1025 bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners(
1026 int num_connectivity_verts) {
1027 // Map between the existing and deduplicated point ids.
1028 // Note that at this point we have one point id for each corner of the
1029 // mesh so there is corner_table_->num_corners() point ids.
1030 decoder_->mesh()->SetNumFaces(corner_table_->num_faces());
1031
1032 if (attribute_data_.empty()) {
1033 // We have connectivity for position only. In this case all vertex indices
1034 // are equal to point indices.
1035 for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
1036 Mesh::Face face;
1037 const CornerIndex start_corner(3 * f.value());
1038 for (int c = 0; c < 3; ++c) {
1039 // Get the vertex index on the corner and use it as a point index.
1040 const int32_t vert_id = corner_table_->Vertex(start_corner + c).value();
1041 face[c] = vert_id;
1042 }
1043 decoder_->mesh()->SetFace(f, face);
1044 }
1045 decoder_->point_cloud()->set_num_points(num_connectivity_verts);
1046 return true;
1047 }
1048 // Else we need to deduplicate multiple attributes.
1049
1050 // Map between point id and an associated corner id. Only one corner for
1051 // each point is stored. The corners are used to sample the attribute values
1052 // in the last stage of the deduplication.
1053 std::vector<int32_t> point_to_corner_map;
1054 // Map between every corner and their new point ids.
1055 std::vector<int32_t> corner_to_point_map(corner_table_->num_corners());
1056 for (int v = 0; v < corner_table_->num_vertices(); ++v) {
1057 CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v));
1058 if (c == kInvalidCornerIndex)
1059 continue; // Isolated vertex.
1060 CornerIndex deduplication_first_corner = c;
1061 if (is_vert_hole_[v]) {
1062 // If the vertex is on a boundary, start deduplication from the left most
1063 // corner that is guaranteed to lie on the boundary.
1064 deduplication_first_corner = c;
1065 } else {
1066 // If we are not on the boundary we need to find the first seam (of any
1067 // attribute).
1068 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
1069 if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c))
1070 continue; // No seam for this attribute, ignore it.
1071 // Else there needs to be at least one seam edge.
1072
1073 // At this point, we use identity mapping between corners and point ids.
1074 const VertexIndex vert_id =
1075 attribute_data_[i].connectivity_data.Vertex(c);
1076 CornerIndex act_c = corner_table_->SwingRight(c);
1077 bool seam_found = false;
1078 while (act_c != c) {
1079 if (act_c == kInvalidCornerIndex)
1080 return false;
1081 if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) {
1082 // Attribute seam found. Stop.
1083 deduplication_first_corner = act_c;
1084 seam_found = true;
1085 break;
1086 }
1087 act_c = corner_table_->SwingRight(act_c);
1088 }
1089 if (seam_found)
1090 break; // No reason to process other attributes if we found a seam.
1091 }
1092 }
1093
1094 // Do a deduplication pass over the corners on the processed vertex.
1095 // At this point each corner corresponds to one point id and our goal is to
1096 // merge similar points into a single point id.
1097 // We do a single pass in a clockwise direction over the corners and we add
1098 // a new point id whenever one of the attributes change.
1099 c = deduplication_first_corner;
1100 // Create a new point.
1101 corner_to_point_map[c.value()] =
1102 static_cast<uint32_t>(point_to_corner_map.size());
1103 point_to_corner_map.push_back(c.value());
1104 // Traverse in CW direction.
1105 CornerIndex prev_c = c;
1106 c = corner_table_->SwingRight(c);
1107 while (c != kInvalidCornerIndex && c != deduplication_first_corner) {
1108 bool attribute_seam = false;
1109 for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
1110 if (attribute_data_[i].connectivity_data.Vertex(c) !=
1111 attribute_data_[i].connectivity_data.Vertex(prev_c)) {
1112 // Attribute index changed from the previous corner. We need to add a
1113 // new point here.
1114 attribute_seam = true;
1115 break;
1116 }
1117 }
1118 if (attribute_seam) {
1119 corner_to_point_map[c.value()] =
1120 static_cast<uint32_t>(point_to_corner_map.size());
1121 point_to_corner_map.push_back(c.value());
1122 } else {
1123 corner_to_point_map[c.value()] = corner_to_point_map[prev_c.value()];
1124 }
1125 prev_c = c;
1126 c = corner_table_->SwingRight(c);
1127 }
1128 }
1129 // Add faces.
1130 for (FaceIndex f(0); f < decoder_->mesh()->num_faces(); ++f) {
1131 Mesh::Face face;
1132 for (int c = 0; c < 3; ++c) {
1133 // Remap old points to the new ones.
1134 face[c] = corner_to_point_map[3 * f.value() + c];
1135 }
1136 decoder_->mesh()->SetFace(f, face);
1137 }
1138 decoder_->point_cloud()->set_num_points(
1139 static_cast<uint32_t>(point_to_corner_map.size()));
1140 return true;
1141 }
1142
1143 template class MeshEdgebreakerDecoderImpl<MeshEdgebreakerTraversalDecoder>;
1144 #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
1145 template class MeshEdgebreakerDecoderImpl<
1146 MeshEdgebreakerTraversalPredictiveDecoder>;
1147 #endif
1148 template class MeshEdgebreakerDecoderImpl<
1149 MeshEdgebreakerTraversalValenceDecoder>;
1150 } // namespace draco
1151