Differential D9642 Diff 31357 extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc
Changeset View
Changeset View
Standalone View
Standalone View
extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc
- This file was moved from extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_decoder_impl.cc.
| Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| const MeshAttributeCornerTable * | const MeshAttributeCornerTable * | ||||
| MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeCornerTable( | MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeCornerTable( | ||||
| int att_id) const { | int att_id) const { | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| const int decoder_id = attribute_data_[i].decoder_id; | const int decoder_id = attribute_data_[i].decoder_id; | ||||
| if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) | if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) { | ||||
| continue; | continue; | ||||
| } | |||||
| const AttributesDecoderInterface *const dec = | const AttributesDecoderInterface *const dec = | ||||
| decoder_->attributes_decoder(decoder_id); | decoder_->attributes_decoder(decoder_id); | ||||
| for (int j = 0; j < dec->GetNumAttributes(); ++j) { | for (int j = 0; j < dec->GetNumAttributes(); ++j) { | ||||
| if (dec->GetAttributeId(j) == att_id) { | if (dec->GetAttributeId(j) == att_id) { | ||||
| if (attribute_data_[i].is_connectivity_used) | if (attribute_data_[i].is_connectivity_used) { | ||||
| return &attribute_data_[i].connectivity_data; | return &attribute_data_[i].connectivity_data; | ||||
| } | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| const MeshAttributeIndicesEncodingData * | const MeshAttributeIndicesEncodingData * | ||||
| MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeEncodingData( | MeshEdgebreakerDecoderImpl<TraversalDecoder>::GetAttributeEncodingData( | ||||
| int att_id) const { | int att_id) const { | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| const int decoder_id = attribute_data_[i].decoder_id; | const int decoder_id = attribute_data_[i].decoder_id; | ||||
| if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) | if (decoder_id < 0 || decoder_id >= decoder_->num_attributes_decoders()) { | ||||
| continue; | continue; | ||||
| } | |||||
| const AttributesDecoderInterface *const dec = | const AttributesDecoderInterface *const dec = | ||||
| decoder_->attributes_decoder(decoder_id); | decoder_->attributes_decoder(decoder_id); | ||||
| for (int j = 0; j < dec->GetNumAttributes(); ++j) { | for (int j = 0; j < dec->GetNumAttributes(); ++j) { | ||||
| if (dec->GetAttributeId(j) == att_id) | if (dec->GetAttributeId(j) == att_id) { | ||||
| return &attribute_data_[i].encoding_data; | return &attribute_data_[i].encoding_data; | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| return &pos_encoding_data_; | return &pos_encoding_data_; | ||||
| } | } | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| template <class TraverserT> | template <class TraverserT> | ||||
| std::unique_ptr<PointsSequencer> | std::unique_ptr<PointsSequencer> | ||||
| MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateVertexTraversalSequencer( | MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateVertexTraversalSequencer( | ||||
| MeshAttributeIndicesEncodingData *encoding_data) { | MeshAttributeIndicesEncodingData *encoding_data) { | ||||
| Show All 13 Lines | MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateVertexTraversalSequencer( | ||||
| traversal_sequencer->SetTraverser(att_traverser); | traversal_sequencer->SetTraverser(att_traverser); | ||||
| return std::move(traversal_sequencer); | return std::move(traversal_sequencer); | ||||
| } | } | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder( | bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder( | ||||
| int32_t att_decoder_id) { | int32_t att_decoder_id) { | ||||
| int8_t att_data_id; | int8_t att_data_id; | ||||
| if (!decoder_->buffer()->Decode(&att_data_id)) | if (!decoder_->buffer()->Decode(&att_data_id)) { | ||||
| return false; | return false; | ||||
| } | |||||
| uint8_t decoder_type; | uint8_t decoder_type; | ||||
| if (!decoder_->buffer()->Decode(&decoder_type)) | if (!decoder_->buffer()->Decode(&decoder_type)) { | ||||
| return false; | return false; | ||||
| } | |||||
| if (att_data_id >= 0) { | if (att_data_id >= 0) { | ||||
| if (att_data_id >= attribute_data_.size()) { | if (att_data_id >= attribute_data_.size()) { | ||||
| return false; // Unexpected attribute data. | return false; // Unexpected attribute data. | ||||
| } | } | ||||
| // Ensure that the attribute data is not mapped to a different attributes | // Ensure that the attribute data is not mapped to a different attributes | ||||
| // decoder already. | // decoder already. | ||||
| if (attribute_data_[att_data_id].decoder_id >= 0) | if (attribute_data_[att_data_id].decoder_id >= 0) { | ||||
| return false; | return false; | ||||
| } | |||||
| attribute_data_[att_data_id].decoder_id = att_decoder_id; | attribute_data_[att_data_id].decoder_id = att_decoder_id; | ||||
| } else { | } else { | ||||
| // Assign the attributes decoder to |pos_encoding_data_|. | // Assign the attributes decoder to |pos_encoding_data_|. | ||||
| if (pos_data_decoder_id_ >= 0) | if (pos_data_decoder_id_ >= 0) { | ||||
| return false; // Some other decoder is already using the data. Error. | return false; // Some other decoder is already using the data. Error. | ||||
| } | |||||
| pos_data_decoder_id_ = att_decoder_id; | pos_data_decoder_id_ = att_decoder_id; | ||||
| } | } | ||||
| MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST; | MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST; | ||||
| if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) { | if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) { | ||||
| uint8_t traversal_method_encoded; | uint8_t traversal_method_encoded; | ||||
| if (!decoder_->buffer()->Decode(&traversal_method_encoded)) | if (!decoder_->buffer()->Decode(&traversal_method_encoded)) { | ||||
| return false; | return false; | ||||
| } | |||||
| traversal_method = | traversal_method = | ||||
| static_cast<MeshTraversalMethod>(traversal_method_encoded); | static_cast<MeshTraversalMethod>(traversal_method_encoded); | ||||
| } | } | ||||
| const Mesh *mesh = decoder_->mesh(); | const Mesh *mesh = decoder_->mesh(); | ||||
| std::unique_ptr<PointsSequencer> sequencer; | std::unique_ptr<PointsSequencer> sequencer; | ||||
| if (decoder_type == MESH_VERTEX_ATTRIBUTE) { | if (decoder_type == MESH_VERTEX_ATTRIBUTE) { | ||||
| Show All 17 Lines | if (decoder_type == MESH_VERTEX_ATTRIBUTE) { | ||||
| } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) { | } else if (traversal_method == MESH_TRAVERSAL_DEPTH_FIRST) { | ||||
| typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver; | typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver; | ||||
| typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser; | typedef DepthFirstTraverser<CornerTable, AttObserver> AttTraverser; | ||||
| sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data); | sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data); | ||||
| } else { | } else { | ||||
| return false; // Unsupported method | return false; // Unsupported method | ||||
| } | } | ||||
| } else { | } else { | ||||
| if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) | if (traversal_method != MESH_TRAVERSAL_DEPTH_FIRST) { | ||||
| return false; // Unsupported method. | return false; // Unsupported method. | ||||
| if (att_data_id < 0) | } | ||||
| if (att_data_id < 0) { | |||||
| return false; // Attribute data must be specified. | return false; // Attribute data must be specified. | ||||
| } | |||||
| // Per-corner attribute decoder. | // Per-corner attribute decoder. | ||||
| typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable> | typedef MeshAttributeIndicesEncodingObserver<MeshAttributeCornerTable> | ||||
| AttObserver; | AttObserver; | ||||
| typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver> | typedef DepthFirstTraverser<MeshAttributeCornerTable, AttObserver> | ||||
| AttTraverser; | AttTraverser; | ||||
| Show All 10 Lines | if (decoder_type == MESH_VERTEX_ATTRIBUTE) { | ||||
| AttTraverser att_traverser; | AttTraverser att_traverser; | ||||
| att_traverser.Init(corner_table, att_observer); | att_traverser.Init(corner_table, att_observer); | ||||
| traversal_sequencer->SetTraverser(att_traverser); | traversal_sequencer->SetTraverser(att_traverser); | ||||
| sequencer = std::move(traversal_sequencer); | sequencer = std::move(traversal_sequencer); | ||||
| } | } | ||||
| if (!sequencer) | if (!sequencer) { | ||||
| return false; | return false; | ||||
| } | |||||
| std::unique_ptr<SequentialAttributeDecodersController> att_controller( | std::unique_ptr<SequentialAttributeDecodersController> att_controller( | ||||
| new SequentialAttributeDecodersController(std::move(sequencer))); | new SequentialAttributeDecodersController(std::move(sequencer))); | ||||
| return decoder_->SetAttributesDecoder(att_decoder_id, | return decoder_->SetAttributesDecoder(att_decoder_id, | ||||
| std::move(att_controller)); | std::move(att_controller)); | ||||
| } | } | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { | bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() { | ||||
| num_new_vertices_ = 0; | num_new_vertices_ = 0; | ||||
| new_to_parent_vertex_map_.clear(); | new_to_parent_vertex_map_.clear(); | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | ||||
| uint32_t num_new_verts; | uint32_t num_new_verts; | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_->buffer()->Decode(&num_new_verts)) | if (!decoder_->buffer()->Decode(&num_new_verts)) { | ||||
| return false; | return false; | ||||
| } | |||||
| } else { | } else { | ||||
| if (!DecodeVarint(&num_new_verts, decoder_->buffer())) | if (!DecodeVarint(&num_new_verts, decoder_->buffer())) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| num_new_vertices_ = num_new_verts; | num_new_vertices_ = num_new_verts; | ||||
| } | } | ||||
| #endif | #endif | ||||
| uint32_t num_encoded_vertices; | uint32_t num_encoded_vertices; | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_->buffer()->Decode(&num_encoded_vertices)) | if (!decoder_->buffer()->Decode(&num_encoded_vertices)) { | ||||
| return false; | return false; | ||||
| } | |||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) | if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer())) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| num_encoded_vertices_ = num_encoded_vertices; | num_encoded_vertices_ = num_encoded_vertices; | ||||
| uint32_t num_faces; | uint32_t num_faces; | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_->buffer()->Decode(&num_faces)) | if (!decoder_->buffer()->Decode(&num_faces)) { | ||||
| return false; | return false; | ||||
| } | |||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| if (!DecodeVarint(&num_faces, decoder_->buffer())) | if (!DecodeVarint(&num_faces, decoder_->buffer())) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) | } | ||||
| if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3) { | |||||
| return false; // Draco cannot handle this many faces. | return false; // Draco cannot handle this many faces. | ||||
| } | |||||
| if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) { | if (static_cast<uint32_t>(num_encoded_vertices_) > num_faces * 3) { | ||||
| return false; // There cannot be more vertices than 3 * num_faces. | return false; // There cannot be more vertices than 3 * num_faces. | ||||
| } | } | ||||
| uint8_t num_attribute_data; | uint8_t num_attribute_data; | ||||
| if (!decoder_->buffer()->Decode(&num_attribute_data)) | if (!decoder_->buffer()->Decode(&num_attribute_data)) { | ||||
| return false; | return false; | ||||
| } | |||||
| uint32_t num_encoded_symbols; | uint32_t num_encoded_symbols; | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_->buffer()->Decode(&num_encoded_symbols)) | if (!decoder_->buffer()->Decode(&num_encoded_symbols)) { | ||||
| return false; | return false; | ||||
| } | |||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) | if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer())) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| if (num_faces < num_encoded_symbols) { | if (num_faces < num_encoded_symbols) { | ||||
| // Number of faces needs to be the same or greater than the number of | // Number of faces needs to be the same or greater than the number of | ||||
| // symbols (it can be greater because the initial face may not be encoded as | // symbols (it can be greater because the initial face may not be encoded as | ||||
| // a symbol). | // a symbol). | ||||
| return false; | return false; | ||||
| } | } | ||||
| const uint32_t max_encoded_faces = | const uint32_t max_encoded_faces = | ||||
| num_encoded_symbols + (num_encoded_symbols / 3); | num_encoded_symbols + (num_encoded_symbols / 3); | ||||
| if (num_faces > max_encoded_faces) { | if (num_faces > max_encoded_faces) { | ||||
| // Faces can only be 1 1/3 times bigger than number of encoded symbols. This | // Faces can only be 1 1/3 times bigger than number of encoded symbols. This | ||||
| // could only happen if all new encoded components started with interior | // could only happen if all new encoded components started with interior | ||||
| // triangles. E.g. A mesh with multiple tetrahedrons. | // triangles. E.g. A mesh with multiple tetrahedrons. | ||||
| return false; | return false; | ||||
| } | } | ||||
| uint32_t num_encoded_split_symbols; | uint32_t num_encoded_split_symbols; | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) | if (!decoder_->buffer()->Decode(&num_encoded_split_symbols)) { | ||||
| return false; | return false; | ||||
| } | |||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) | if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer())) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| if (num_encoded_split_symbols > num_encoded_symbols) { | if (num_encoded_split_symbols > num_encoded_symbols) { | ||||
| return false; // Split symbols are a sub-set of all symbols. | return false; // Split symbols are a sub-set of all symbols. | ||||
| } | } | ||||
| // Decode topology (connectivity). | // Decode topology (connectivity). | ||||
| vertex_traversal_length_.clear(); | vertex_traversal_length_.clear(); | ||||
| corner_table_ = std::unique_ptr<CornerTable>(new CornerTable()); | corner_table_ = std::unique_ptr<CornerTable>(new CornerTable()); | ||||
| if (corner_table_ == nullptr) | if (corner_table_ == nullptr) { | ||||
| return false; | return false; | ||||
| } | |||||
| processed_corner_ids_.clear(); | processed_corner_ids_.clear(); | ||||
| processed_corner_ids_.reserve(num_faces); | processed_corner_ids_.reserve(num_faces); | ||||
| processed_connectivity_corners_.clear(); | processed_connectivity_corners_.clear(); | ||||
| processed_connectivity_corners_.reserve(num_faces); | processed_connectivity_corners_.reserve(num_faces); | ||||
| topology_split_data_.clear(); | topology_split_data_.clear(); | ||||
| hole_event_data_.clear(); | hole_event_data_.clear(); | ||||
| init_face_configurations_.clear(); | init_face_configurations_.clear(); | ||||
| init_corners_.clear(); | init_corners_.clear(); | ||||
| last_symbol_id_ = -1; | last_symbol_id_ = -1; | ||||
| last_face_id_ = -1; | last_face_id_ = -1; | ||||
| last_vert_id_ = -1; | last_vert_id_ = -1; | ||||
| attribute_data_.clear(); | attribute_data_.clear(); | ||||
| // Add one attribute data for each attribute decoder. | // Add one attribute data for each attribute decoder. | ||||
| attribute_data_.resize(num_attribute_data); | attribute_data_.resize(num_attribute_data); | ||||
| if (!corner_table_->Reset(num_faces, | if (!corner_table_->Reset( | ||||
| num_encoded_vertices_ + num_encoded_split_symbols)) | num_faces, num_encoded_vertices_ + num_encoded_split_symbols)) { | ||||
| return false; | return false; | ||||
| } | |||||
| // Start with all vertices marked as holes (boundaries). | // Start with all vertices marked as holes (boundaries). | ||||
| // Only vertices decoded with TOPOLOGY_C symbol (and the initial face) will | // Only vertices decoded with TOPOLOGY_C symbol (and the initial face) will | ||||
| // be marked as non hole vertices. We need to allocate the array larger | // be marked as non hole vertices. We need to allocate the array larger | ||||
| // because split symbols can create extra vertices during the decoding | // because split symbols can create extra vertices during the decoding | ||||
| // process (these extra vertices are then eliminated during deduplication). | // process (these extra vertices are then eliminated during deduplication). | ||||
| is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true); | is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true); | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| int32_t topology_split_decoded_bytes = -1; | int32_t topology_split_decoded_bytes = -1; | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | ||||
| uint32_t encoded_connectivity_size; | uint32_t encoded_connectivity_size; | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) | if (!decoder_->buffer()->Decode(&encoded_connectivity_size)) { | ||||
| return false; | return false; | ||||
| } | |||||
| } else { | } else { | ||||
| if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) | if (!DecodeVarint(&encoded_connectivity_size, decoder_->buffer())) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| if (encoded_connectivity_size == 0 || | if (encoded_connectivity_size == 0 || | ||||
| encoded_connectivity_size > decoder_->buffer()->remaining_size()) | encoded_connectivity_size > decoder_->buffer()->remaining_size()) { | ||||
| return false; | return false; | ||||
| } | |||||
| DecoderBuffer event_buffer; | DecoderBuffer event_buffer; | ||||
| event_buffer.Init( | event_buffer.Init( | ||||
| decoder_->buffer()->data_head() + encoded_connectivity_size, | decoder_->buffer()->data_head() + encoded_connectivity_size, | ||||
| decoder_->buffer()->remaining_size() - encoded_connectivity_size, | decoder_->buffer()->remaining_size() - encoded_connectivity_size, | ||||
| decoder_->buffer()->bitstream_version()); | decoder_->buffer()->bitstream_version()); | ||||
| // Decode hole and topology split events. | // Decode hole and topology split events. | ||||
| topology_split_decoded_bytes = | topology_split_decoded_bytes = | ||||
| DecodeHoleAndTopologySplitEvents(&event_buffer); | DecodeHoleAndTopologySplitEvents(&event_buffer); | ||||
| if (topology_split_decoded_bytes == -1) | if (topology_split_decoded_bytes == -1) { | ||||
| return false; | return false; | ||||
| } | |||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) | if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| traversal_decoder_.Init(this); | traversal_decoder_.Init(this); | ||||
| // Add one extra vertex for each split symbol. | // Add one extra vertex for each split symbol. | ||||
| traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ + | traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ + | ||||
| num_encoded_split_symbols); | num_encoded_split_symbols); | ||||
| traversal_decoder_.SetNumAttributeData(num_attribute_data); | traversal_decoder_.SetNumAttributeData(num_attribute_data); | ||||
| DecoderBuffer traversal_end_buffer; | DecoderBuffer traversal_end_buffer; | ||||
| if (!traversal_decoder_.Start(&traversal_end_buffer)) | if (!traversal_decoder_.Start(&traversal_end_buffer)) { | ||||
| return false; | return false; | ||||
| } | |||||
| const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols); | const int num_connectivity_verts = DecodeConnectivity(num_encoded_symbols); | ||||
| if (num_connectivity_verts == -1) | if (num_connectivity_verts == -1) { | ||||
| return false; | return false; | ||||
| } | |||||
| // Set the main buffer to the end of the traversal. | // Set the main buffer to the end of the traversal. | ||||
| decoder_->buffer()->Init(traversal_end_buffer.data_head(), | decoder_->buffer()->Init(traversal_end_buffer.data_head(), | ||||
| traversal_end_buffer.remaining_size(), | traversal_end_buffer.remaining_size(), | ||||
| decoder_->buffer()->bitstream_version()); | decoder_->buffer()->bitstream_version()); | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | ||||
| // Skip topology split data that was already decoded earlier. | // Skip topology split data that was already decoded earlier. | ||||
| decoder_->buffer()->Advance(topology_split_decoded_bytes); | decoder_->buffer()->Advance(topology_split_decoded_bytes); | ||||
| } | } | ||||
| #endif | #endif | ||||
| // Decode connectivity of non-position attributes. | // Decode connectivity of non-position attributes. | ||||
| if (attribute_data_.size() > 0) { | if (attribute_data_.size() > 0) { | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) { | ||||
| for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) { | for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) { | ||||
| if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) | if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | |||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) { | for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) { | ||||
| if (!DecodeAttributeConnectivitiesOnFace(ci)) | if (!DecodeAttributeConnectivitiesOnFace(ci)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| traversal_decoder_.Done(); | traversal_decoder_.Done(); | ||||
| // Decode attribute connectivity. | // Decode attribute connectivity. | ||||
| // Prepare data structure for decoding non-position attribute connectivity. | // Prepare data structure for decoding non-position attribute connectivity. | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get()); | attribute_data_[i].connectivity_data.InitEmpty(corner_table_.get()); | ||||
| // Add all seams. | // Add all seams. | ||||
| for (int32_t c : attribute_data_[i].attribute_seam_corners) { | for (int32_t c : attribute_data_[i].attribute_seam_corners) { | ||||
| attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c)); | attribute_data_[i].connectivity_data.AddSeamEdge(CornerIndex(c)); | ||||
| } | } | ||||
| // Recompute vertices from the newly added seam edges. | // Recompute vertices from the newly added seam edges. | ||||
| attribute_data_[i].connectivity_data.RecomputeVertices(nullptr, nullptr); | attribute_data_[i].connectivity_data.RecomputeVertices(nullptr, nullptr); | ||||
| } | } | ||||
| pos_encoding_data_.Init(corner_table_->num_vertices()); | pos_encoding_data_.Init(corner_table_->num_vertices()); | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| // For non-position attributes, preallocate the vertex to value mapping | // For non-position attributes, preallocate the vertex to value mapping | ||||
| // using the maximum number of vertices from the base corner table and the | // using the maximum number of vertices from the base corner table and the | ||||
| // attribute corner table (since the attribute decoder may use either of | // attribute corner table (since the attribute decoder may use either of | ||||
| // it). | // it). | ||||
| int32_t att_connectivity_verts = | int32_t att_connectivity_verts = | ||||
| attribute_data_[i].connectivity_data.num_vertices(); | attribute_data_[i].connectivity_data.num_vertices(); | ||||
| if (att_connectivity_verts < corner_table_->num_vertices()) | if (att_connectivity_verts < corner_table_->num_vertices()) { | ||||
| att_connectivity_verts = corner_table_->num_vertices(); | att_connectivity_verts = corner_table_->num_vertices(); | ||||
| } | |||||
| attribute_data_[i].encoding_data.Init(att_connectivity_verts); | attribute_data_[i].encoding_data.Init(att_connectivity_verts); | ||||
| } | } | ||||
| if (!AssignPointsToCorners(num_connectivity_verts)) | if (!AssignPointsToCorners(num_connectivity_verts)) { | ||||
| return false; | return false; | ||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() { | bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::OnAttributesDecoded() { | ||||
| return true; | return true; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | if (symbol == TOPOLOGY_C) { | ||||
| // *-------v-------* | // *-------v-------* | ||||
| // \b /x\ a/ | // \b /x\ a/ | ||||
| // \ / \ / | // \ / \ / | ||||
| // \ / C \ / | // \ / C \ / | ||||
| // *.......* | // *.......* | ||||
| // Find the corner "b" from the corner "a" which is the corner on the | // Find the corner "b" from the corner "a" which is the corner on the | ||||
| // top of the active stack. | // top of the active stack. | ||||
| if (active_corner_stack.empty()) | if (active_corner_stack.empty()) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| const CornerIndex corner_a = active_corner_stack.back(); | const CornerIndex corner_a = active_corner_stack.back(); | ||||
| const VertexIndex vertex_x = | const VertexIndex vertex_x = | ||||
| corner_table_->Vertex(corner_table_->Next(corner_a)); | corner_table_->Vertex(corner_table_->Next(corner_a)); | ||||
| const CornerIndex corner_b = | const CornerIndex corner_b = | ||||
| corner_table_->Next(corner_table_->LeftMostCorner(vertex_x)); | corner_table_->Next(corner_table_->LeftMostCorner(vertex_x)); | ||||
| // New tip corner. | // New tip corner. | ||||
| Show All 24 Lines | if (symbol == TOPOLOGY_C) { | ||||
| // /a\ / \ | // /a\ / \ | ||||
| // / \ / \ | // / \ / \ | ||||
| // / \ / \ | // / \ / \ | ||||
| // *-------v-------* | // *-------v-------* | ||||
| // .l r. | // .l r. | ||||
| // . . | // . . | ||||
| // . . | // . . | ||||
| // * | // * | ||||
| if (active_corner_stack.empty()) | if (active_corner_stack.empty()) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| const CornerIndex corner_a = active_corner_stack.back(); | const CornerIndex corner_a = active_corner_stack.back(); | ||||
| // First corner on the new face is either corner "l" or "r". | // First corner on the new face is either corner "l" or "r". | ||||
| const CornerIndex corner(3 * face.value()); | const CornerIndex corner(3 * face.value()); | ||||
| CornerIndex opp_corner, corner_l, corner_r; | CornerIndex opp_corner, corner_l, corner_r; | ||||
| if (symbol == TOPOLOGY_R) { | if (symbol == TOPOLOGY_R) { | ||||
| // "r" is the new first corner. | // "r" is the new first corner. | ||||
| opp_corner = corner + 2; | opp_corner = corner + 2; | ||||
| corner_l = corner + 1; | corner_l = corner + 1; | ||||
| corner_r = corner; | corner_r = corner; | ||||
| } else { | } else { | ||||
| // "l" is the new first corner. | // "l" is the new first corner. | ||||
| opp_corner = corner + 1; | opp_corner = corner + 1; | ||||
| corner_l = corner; | corner_l = corner; | ||||
| corner_r = corner + 2; | corner_r = corner + 2; | ||||
| } | } | ||||
| SetOppositeCorners(opp_corner, corner_a); | SetOppositeCorners(opp_corner, corner_a); | ||||
| // Update vertex mapping. | // Update vertex mapping. | ||||
| const VertexIndex new_vert_index = corner_table_->AddNewVertex(); | const VertexIndex new_vert_index = corner_table_->AddNewVertex(); | ||||
| if (corner_table_->num_vertices() > max_num_vertices) | if (corner_table_->num_vertices() > max_num_vertices) { | ||||
| return -1; // Unexpected number of decoded vertices. | return -1; // Unexpected number of decoded vertices. | ||||
| } | |||||
| corner_table_->MapCornerToVertex(opp_corner, new_vert_index); | corner_table_->MapCornerToVertex(opp_corner, new_vert_index); | ||||
| corner_table_->SetLeftMostCorner(new_vert_index, opp_corner); | corner_table_->SetLeftMostCorner(new_vert_index, opp_corner); | ||||
| const VertexIndex vertex_r = | const VertexIndex vertex_r = | ||||
| corner_table_->Vertex(corner_table_->Previous(corner_a)); | corner_table_->Vertex(corner_table_->Previous(corner_a)); | ||||
| corner_table_->MapCornerToVertex(corner_r, vertex_r); | corner_table_->MapCornerToVertex(corner_r, vertex_r); | ||||
| // Update left-most corner on the vertex on the |corner_r|. | // Update left-most corner on the vertex on the |corner_r|. | ||||
| Show All 9 Lines | if (symbol == TOPOLOGY_C) { | ||||
| // "n" need to be merged into a single vertex. | // "n" need to be merged into a single vertex. | ||||
| // | // | ||||
| // *-------v-------* | // *-------v-------* | ||||
| // \a p/x\n b/ | // \a p/x\n b/ | ||||
| // \ / \ / | // \ / \ / | ||||
| // \ / S \ / | // \ / S \ / | ||||
| // *.......* | // *.......* | ||||
| // | // | ||||
| if (active_corner_stack.empty()) | if (active_corner_stack.empty()) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| const CornerIndex corner_b = active_corner_stack.back(); | const CornerIndex corner_b = active_corner_stack.back(); | ||||
| active_corner_stack.pop_back(); | active_corner_stack.pop_back(); | ||||
| // Corner "a" can correspond either to a normal active edge, or to an edge | // Corner "a" can correspond either to a normal active edge, or to an edge | ||||
| // created from the topology split event. | // created from the topology split event. | ||||
| const auto it = topology_split_active_corners.find(symbol_id); | const auto it = topology_split_active_corners.find(symbol_id); | ||||
| if (it != topology_split_active_corners.end()) { | if (it != topology_split_active_corners.end()) { | ||||
| // Topology split event. Move the retrieved edge to the stack. | // Topology split event. Move the retrieved edge to the stack. | ||||
| active_corner_stack.push_back(it->second); | active_corner_stack.push_back(it->second); | ||||
| } | } | ||||
| if (active_corner_stack.empty()) | if (active_corner_stack.empty()) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| const CornerIndex corner_a = active_corner_stack.back(); | const CornerIndex corner_a = active_corner_stack.back(); | ||||
| if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex || | if (corner_table_->Opposite(corner_a) != kInvalidCornerIndex || | ||||
| corner_table_->Opposite(corner_b) != kInvalidCornerIndex) { | corner_table_->Opposite(corner_b) != kInvalidCornerIndex) { | ||||
| // One of the corners is already opposite to an existing face, which | // One of the corners is already opposite to an existing face, which | ||||
| // should not happen unless the input was tempered with. | // should not happen unless the input was tempered with. | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| Show All 25 Lines | if (symbol == TOPOLOGY_C) { | ||||
| // connected to it in the CCW direction. | // connected to it in the CCW direction. | ||||
| while (corner_n != kInvalidCornerIndex) { | while (corner_n != kInvalidCornerIndex) { | ||||
| corner_table_->MapCornerToVertex(corner_n, vertex_p); | corner_table_->MapCornerToVertex(corner_n, vertex_p); | ||||
| corner_n = corner_table_->SwingLeft(corner_n); | corner_n = corner_table_->SwingLeft(corner_n); | ||||
| } | } | ||||
| // Make sure the old vertex n is now mapped to an invalid corner (make it | // Make sure the old vertex n is now mapped to an invalid corner (make it | ||||
| // isolated). | // isolated). | ||||
| corner_table_->MakeVertexIsolated(vertex_n); | corner_table_->MakeVertexIsolated(vertex_n); | ||||
| if (remove_invalid_vertices) | if (remove_invalid_vertices) { | ||||
| invalid_vertices.push_back(vertex_n); | invalid_vertices.push_back(vertex_n); | ||||
| } | |||||
| active_corner_stack.back() = corner; | active_corner_stack.back() = corner; | ||||
| } else if (symbol == TOPOLOGY_E) { | } else if (symbol == TOPOLOGY_E) { | ||||
| const CornerIndex corner(3 * face.value()); | const CornerIndex corner(3 * face.value()); | ||||
| const VertexIndex first_vert_index = corner_table_->AddNewVertex(); | const VertexIndex first_vert_index = corner_table_->AddNewVertex(); | ||||
| // Create three new vertices at the corners of the new face. | // Create three new vertices at the corners of the new face. | ||||
| corner_table_->MapCornerToVertex(corner, first_vert_index); | corner_table_->MapCornerToVertex(corner, first_vert_index); | ||||
| corner_table_->MapCornerToVertex(corner + 1, | corner_table_->MapCornerToVertex(corner + 1, | ||||
| corner_table_->AddNewVertex()); | corner_table_->AddNewVertex()); | ||||
| corner_table_->MapCornerToVertex(corner + 2, | corner_table_->MapCornerToVertex(corner + 2, | ||||
| corner_table_->AddNewVertex()); | corner_table_->AddNewVertex()); | ||||
| if (corner_table_->num_vertices() > max_num_vertices) | if (corner_table_->num_vertices() > max_num_vertices) { | ||||
| return -1; // Unexpected number of decoded vertices. | return -1; // Unexpected number of decoded vertices. | ||||
| } | |||||
| corner_table_->SetLeftMostCorner(first_vert_index, corner); | corner_table_->SetLeftMostCorner(first_vert_index, corner); | ||||
| corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1); | corner_table_->SetLeftMostCorner(first_vert_index + 1, corner + 1); | ||||
| corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2); | corner_table_->SetLeftMostCorner(first_vert_index + 2, corner + 2); | ||||
| // Add the tip corner to the active stack. | // Add the tip corner to the active stack. | ||||
| active_corner_stack.push_back(corner); | active_corner_stack.push_back(corner); | ||||
| check_topology_split = true; | check_topology_split = true; | ||||
| } else { | } else { | ||||
| Show All 13 Lines | if (check_topology_split) { | ||||
| // corresponding TOPOLOGY_S event is decoded. | // corresponding TOPOLOGY_S event is decoded. | ||||
| // Symbol id used by the encoder (reverse). | // Symbol id used by the encoder (reverse). | ||||
| const int encoder_symbol_id = num_symbols - symbol_id - 1; | const int encoder_symbol_id = num_symbols - symbol_id - 1; | ||||
| EdgeFaceName split_edge; | EdgeFaceName split_edge; | ||||
| int encoder_split_symbol_id; | int encoder_split_symbol_id; | ||||
| while (IsTopologySplit(encoder_symbol_id, &split_edge, | while (IsTopologySplit(encoder_symbol_id, &split_edge, | ||||
| &encoder_split_symbol_id)) { | &encoder_split_symbol_id)) { | ||||
| if (encoder_split_symbol_id < 0) | if (encoder_split_symbol_id < 0) { | ||||
| return -1; // Wrong split symbol id. | return -1; // Wrong split symbol id. | ||||
| } | |||||
| // Symbol was part of a topology split. Now we need to determine which | // Symbol was part of a topology split. Now we need to determine which | ||||
| // edge should be added to the active edges stack. | // edge should be added to the active edges stack. | ||||
| const CornerIndex act_top_corner = active_corner_stack.back(); | const CornerIndex act_top_corner = active_corner_stack.back(); | ||||
| // The current symbol has one active edge (stored in act_top_corner) and | // The current symbol has one active edge (stored in act_top_corner) and | ||||
| // two remaining inactive edges that are attached to it. | // two remaining inactive edges that are attached to it. | ||||
| // * | // * | ||||
| // / \ | // / \ | ||||
| // left_edge / \ right_edge | // left_edge / \ right_edge | ||||
| Show All 11 Lines | if (check_topology_split) { | ||||
| // Convert the encoder split symbol id to decoder symbol id. | // Convert the encoder split symbol id to decoder symbol id. | ||||
| const int decoder_split_symbol_id = | const int decoder_split_symbol_id = | ||||
| num_symbols - encoder_split_symbol_id - 1; | num_symbols - encoder_split_symbol_id - 1; | ||||
| topology_split_active_corners[decoder_split_symbol_id] = | topology_split_active_corners[decoder_split_symbol_id] = | ||||
| new_active_corner; | new_active_corner; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (corner_table_->num_vertices() > max_num_vertices) | if (corner_table_->num_vertices() > max_num_vertices) { | ||||
| return -1; // Unexpected number of decoded vertices. | return -1; // Unexpected number of decoded vertices. | ||||
| } | |||||
| // Decode start faces and connect them to the faces from the active stack. | // Decode start faces and connect them to the faces from the active stack. | ||||
| while (active_corner_stack.size() > 0) { | while (active_corner_stack.size() > 0) { | ||||
| const CornerIndex corner = active_corner_stack.back(); | const CornerIndex corner = active_corner_stack.back(); | ||||
| active_corner_stack.pop_back(); | active_corner_stack.pop_back(); | ||||
| const bool interior_face = | const bool interior_face = | ||||
| traversal_decoder_.DecodeStartFaceConfiguration(); | traversal_decoder_.DecodeStartFaceConfiguration(); | ||||
| if (interior_face) { | if (interior_face) { | ||||
| // The start face is interior, we need to find three corners that are | // The start face is interior, we need to find three corners that are | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | while (active_corner_stack.size() > 0) { | ||||
| } else { | } else { | ||||
| // The initial face wasn't interior and the traversal had to start from | // The initial face wasn't interior and the traversal had to start from | ||||
| // an open boundary. In this case no new face is added, but we need to | // an open boundary. In this case no new face is added, but we need to | ||||
| // keep record about the first opposite corner to this boundary. | // keep record about the first opposite corner to this boundary. | ||||
| init_face_configurations_.push_back(false); | init_face_configurations_.push_back(false); | ||||
| init_corners_.push_back(corner); | init_corners_.push_back(corner); | ||||
| } | } | ||||
| } | } | ||||
| if (num_faces != corner_table_->num_faces()) | if (num_faces != corner_table_->num_faces()) { | ||||
| return -1; // Unexpected number of decoded faces. | return -1; // Unexpected number of decoded faces. | ||||
| } | |||||
| int num_vertices = corner_table_->num_vertices(); | int num_vertices = corner_table_->num_vertices(); | ||||
| // If any vertex was marked as isolated, we want to remove it from the corner | // If any vertex was marked as isolated, we want to remove it from the corner | ||||
| // table to ensure that all vertices in range <0, num_vertices> are valid. | // table to ensure that all vertices in range <0, num_vertices> are valid. | ||||
| for (const VertexIndex invalid_vert : invalid_vertices) { | for (const VertexIndex invalid_vert : invalid_vertices) { | ||||
| // Find the last valid vertex and swap it with the isolated vertex. | // Find the last valid vertex and swap it with the isolated vertex. | ||||
| VertexIndex src_vert(num_vertices - 1); | VertexIndex src_vert(num_vertices - 1); | ||||
| while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) { | while (corner_table_->LeftMostCorner(src_vert) == kInvalidCornerIndex) { | ||||
| // The last vertex is invalid, proceed to the previous one. | // The last vertex is invalid, proceed to the previous one. | ||||
| src_vert = VertexIndex(--num_vertices - 1); | src_vert = VertexIndex(--num_vertices - 1); | ||||
| } | } | ||||
| if (src_vert < invalid_vert) | if (src_vert < invalid_vert) { | ||||
| continue; // No need to swap anything. | continue; // No need to swap anything. | ||||
| } | |||||
| // Remap all corners mapped to |src_vert| to |invalid_vert|. | // Remap all corners mapped to |src_vert| to |invalid_vert|. | ||||
| VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert); | VertexCornersIterator<CornerTable> vcit(corner_table_.get(), src_vert); | ||||
| for (; !vcit.End(); ++vcit) { | for (; !vcit.End(); ++vcit) { | ||||
| const CornerIndex cid = vcit.Corner(); | const CornerIndex cid = vcit.Corner(); | ||||
| corner_table_->MapCornerToVertex(cid, invalid_vert); | corner_table_->MapCornerToVertex(cid, invalid_vert); | ||||
| } | } | ||||
| corner_table_->SetLeftMostCorner(invalid_vert, | corner_table_->SetLeftMostCorner(invalid_vert, | ||||
| Show All 13 Lines | |||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| int32_t | int32_t | ||||
| MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( | MeshEdgebreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents( | ||||
| DecoderBuffer *decoder_buffer) { | DecoderBuffer *decoder_buffer) { | ||||
| // Prepare a new decoder from the provided buffer offset. | // Prepare a new decoder from the provided buffer offset. | ||||
| uint32_t num_topology_splits; | uint32_t num_topology_splits; | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_buffer->Decode(&num_topology_splits)) | if (!decoder_buffer->Decode(&num_topology_splits)) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| if (!DecodeVarint(&num_topology_splits, decoder_buffer)) | if (!DecodeVarint(&num_topology_splits, decoder_buffer)) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| } | |||||
| if (num_topology_splits > 0) { | if (num_topology_splits > 0) { | ||||
| if (num_topology_splits > static_cast<uint32_t>(corner_table_->num_faces())) | if (num_topology_splits > | ||||
| static_cast<uint32_t>(corner_table_->num_faces())) { | |||||
| return -1; | return -1; | ||||
| } | |||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) { | ||||
| for (uint32_t i = 0; i < num_topology_splits; ++i) { | for (uint32_t i = 0; i < num_topology_splits; ++i) { | ||||
| TopologySplitEventData event_data; | TopologySplitEventData event_data; | ||||
| if (!decoder_buffer->Decode(&event_data.split_symbol_id)) | if (!decoder_buffer->Decode(&event_data.split_symbol_id)) { | ||||
| return -1; | return -1; | ||||
| if (!decoder_buffer->Decode(&event_data.source_symbol_id)) | } | ||||
| if (!decoder_buffer->Decode(&event_data.source_symbol_id)) { | |||||
| return -1; | return -1; | ||||
| } | |||||
| uint8_t edge_data; | uint8_t edge_data; | ||||
| if (!decoder_buffer->Decode(&edge_data)) | if (!decoder_buffer->Decode(&edge_data)) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| event_data.source_edge = edge_data & 1; | event_data.source_edge = edge_data & 1; | ||||
| topology_split_data_.push_back(event_data); | topology_split_data_.push_back(event_data); | ||||
| } | } | ||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| // Decode source and split symbol ids using delta and varint coding. See | // Decode source and split symbol ids using delta and varint coding. See | ||||
| // description in mesh_edgebreaker_encoder_impl.cc for more details. | // description in mesh_edgebreaker_encoder_impl.cc for more details. | ||||
| int last_source_symbol_id = 0; | int last_source_symbol_id = 0; | ||||
| for (uint32_t i = 0; i < num_topology_splits; ++i) { | for (uint32_t i = 0; i < num_topology_splits; ++i) { | ||||
| TopologySplitEventData event_data; | TopologySplitEventData event_data; | ||||
| uint32_t delta; | uint32_t delta; | ||||
| DecodeVarint<uint32_t>(&delta, decoder_buffer); | DecodeVarint<uint32_t>(&delta, decoder_buffer); | ||||
| event_data.source_symbol_id = delta + last_source_symbol_id; | event_data.source_symbol_id = delta + last_source_symbol_id; | ||||
| DecodeVarint<uint32_t>(&delta, decoder_buffer); | DecodeVarint<uint32_t>(&delta, decoder_buffer); | ||||
| if (delta > event_data.source_symbol_id) | if (delta > event_data.source_symbol_id) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| event_data.split_symbol_id = | event_data.split_symbol_id = | ||||
| event_data.source_symbol_id - static_cast<int32_t>(delta); | event_data.source_symbol_id - static_cast<int32_t>(delta); | ||||
| last_source_symbol_id = event_data.source_symbol_id; | last_source_symbol_id = event_data.source_symbol_id; | ||||
| topology_split_data_.push_back(event_data); | topology_split_data_.push_back(event_data); | ||||
| } | } | ||||
| // Split edges are decoded from a direct bit decoder. | // Split edges are decoded from a direct bit decoder. | ||||
| decoder_buffer->StartBitDecoding(false, nullptr); | decoder_buffer->StartBitDecoding(false, nullptr); | ||||
| for (uint32_t i = 0; i < num_topology_splits; ++i) { | for (uint32_t i = 0; i < num_topology_splits; ++i) { | ||||
| uint32_t edge_data; | uint32_t edge_data; | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) { | ||||
| decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data); | decoder_buffer->DecodeLeastSignificantBits32(2, &edge_data); | ||||
| } else { | } else { | ||||
| decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data); | decoder_buffer->DecodeLeastSignificantBits32(1, &edge_data); | ||||
| } | } | ||||
| TopologySplitEventData &event_data = topology_split_data_[i]; | TopologySplitEventData &event_data = topology_split_data_[i]; | ||||
| event_data.source_edge = edge_data & 1; | event_data.source_edge = edge_data & 1; | ||||
| } | } | ||||
| decoder_buffer->EndBitDecoding(); | decoder_buffer->EndBitDecoding(); | ||||
| } | } | ||||
| } | } | ||||
| uint32_t num_hole_events = 0; | uint32_t num_hole_events = 0; | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) { | ||||
| if (!decoder_buffer->Decode(&num_hole_events)) | if (!decoder_buffer->Decode(&num_hole_events)) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) { | } else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) { | ||||
| if (!DecodeVarint(&num_hole_events, decoder_buffer)) | if (!DecodeVarint(&num_hole_events, decoder_buffer)) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| } | |||||
| #endif | #endif | ||||
| if (num_hole_events > 0) { | if (num_hole_events > 0) { | ||||
| #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | #ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED | ||||
| if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) { | if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) { | ||||
| for (uint32_t i = 0; i < num_hole_events; ++i) { | for (uint32_t i = 0; i < num_hole_events; ++i) { | ||||
| HoleEventData event_data; | HoleEventData event_data; | ||||
| if (!decoder_buffer->Decode(&event_data)) | if (!decoder_buffer->Decode(&event_data)) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| hole_event_data_.push_back(event_data); | hole_event_data_.push_back(event_data); | ||||
| } | } | ||||
| } else | } else | ||||
| #endif | #endif | ||||
| { | { | ||||
| // Decode hole symbol ids using delta and varint coding. | // Decode hole symbol ids using delta and varint coding. | ||||
| int last_symbol_id = 0; | int last_symbol_id = 0; | ||||
| Show All 26 Lines | if (opp_corner == kInvalidCornerIndex) { | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | ||||
| } | } | ||||
| continue; | continue; | ||||
| } | } | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i); | const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i); | ||||
| if (is_seam) | if (is_seam) { | ||||
| attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| #endif | #endif | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| bool MeshEdgebreakerDecoderImpl< | bool MeshEdgebreakerDecoderImpl< | ||||
| TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) { | TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) { | ||||
| // Three corners of the face. | // Three corners of the face. | ||||
| const CornerIndex corners[3] = {corner, corner_table_->Next(corner), | const CornerIndex corners[3] = {corner, corner_table_->Next(corner), | ||||
| corner_table_->Previous(corner)}; | corner_table_->Previous(corner)}; | ||||
| const FaceIndex src_face_id = corner_table_->Face(corner); | const FaceIndex src_face_id = corner_table_->Face(corner); | ||||
| for (int c = 0; c < 3; ++c) { | for (int c = 0; c < 3; ++c) { | ||||
| const CornerIndex opp_corner = corner_table_->Opposite(corners[c]); | const CornerIndex opp_corner = corner_table_->Opposite(corners[c]); | ||||
| if (opp_corner == kInvalidCornerIndex) { | if (opp_corner == kInvalidCornerIndex) { | ||||
| // Don't decode attribute seams on boundary edges (every boundary edge | // Don't decode attribute seams on boundary edges (every boundary edge | ||||
| // is automatically an attribute seam). | // is automatically an attribute seam). | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | ||||
| } | } | ||||
| continue; | continue; | ||||
| } | } | ||||
| const FaceIndex opp_face_id = corner_table_->Face(opp_corner); | const FaceIndex opp_face_id = corner_table_->Face(opp_corner); | ||||
| // Don't decode edges when the opposite face has been already processed. | // Don't decode edges when the opposite face has been already processed. | ||||
| if (opp_face_id < src_face_id) | if (opp_face_id < src_face_id) { | ||||
| continue; | continue; | ||||
| } | |||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i); | const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i); | ||||
| if (is_seam) | if (is_seam) { | ||||
| attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | attribute_data_[i].attribute_seam_corners.push_back(corners[c].value()); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| template <class TraversalDecoder> | template <class TraversalDecoder> | ||||
| bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners( | bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners( | ||||
| int num_connectivity_verts) { | int num_connectivity_verts) { | ||||
| // Map between the existing and deduplicated point ids. | // Map between the existing and deduplicated point ids. | ||||
| // Note that at this point we have one point id for each corner of the | // Note that at this point we have one point id for each corner of the | ||||
| Show All 21 Lines | bool MeshEdgebreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners( | ||||
| // Map between point id and an associated corner id. Only one corner for | // Map between point id and an associated corner id. Only one corner for | ||||
| // each point is stored. The corners are used to sample the attribute values | // each point is stored. The corners are used to sample the attribute values | ||||
| // in the last stage of the deduplication. | // in the last stage of the deduplication. | ||||
| std::vector<int32_t> point_to_corner_map; | std::vector<int32_t> point_to_corner_map; | ||||
| // Map between every corner and their new point ids. | // Map between every corner and their new point ids. | ||||
| std::vector<int32_t> corner_to_point_map(corner_table_->num_corners()); | std::vector<int32_t> corner_to_point_map(corner_table_->num_corners()); | ||||
| for (int v = 0; v < corner_table_->num_vertices(); ++v) { | for (int v = 0; v < corner_table_->num_vertices(); ++v) { | ||||
| CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v)); | CornerIndex c = corner_table_->LeftMostCorner(VertexIndex(v)); | ||||
| if (c == kInvalidCornerIndex) | if (c == kInvalidCornerIndex) { | ||||
| continue; // Isolated vertex. | continue; // Isolated vertex. | ||||
| } | |||||
| CornerIndex deduplication_first_corner = c; | CornerIndex deduplication_first_corner = c; | ||||
| if (is_vert_hole_[v]) { | if (is_vert_hole_[v]) { | ||||
| // If the vertex is on a boundary, start deduplication from the left most | // If the vertex is on a boundary, start deduplication from the left most | ||||
| // corner that is guaranteed to lie on the boundary. | // corner that is guaranteed to lie on the boundary. | ||||
| deduplication_first_corner = c; | deduplication_first_corner = c; | ||||
| } else { | } else { | ||||
| // If we are not on the boundary we need to find the first seam (of any | // If we are not on the boundary we need to find the first seam (of any | ||||
| // attribute). | // attribute). | ||||
| for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | for (uint32_t i = 0; i < attribute_data_.size(); ++i) { | ||||
| if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) | if (!attribute_data_[i].connectivity_data.IsCornerOnSeam(c)) { | ||||
| continue; // No seam for this attribute, ignore it. | continue; // No seam for this attribute, ignore it. | ||||
| } | |||||
| // Else there needs to be at least one seam edge. | // Else there needs to be at least one seam edge. | ||||
| // At this point, we use identity mapping between corners and point ids. | // At this point, we use identity mapping between corners and point ids. | ||||
| const VertexIndex vert_id = | const VertexIndex vert_id = | ||||
| attribute_data_[i].connectivity_data.Vertex(c); | attribute_data_[i].connectivity_data.Vertex(c); | ||||
| CornerIndex act_c = corner_table_->SwingRight(c); | CornerIndex act_c = corner_table_->SwingRight(c); | ||||
| bool seam_found = false; | bool seam_found = false; | ||||
| while (act_c != c) { | while (act_c != c) { | ||||
| if (act_c == kInvalidCornerIndex) | if (act_c == kInvalidCornerIndex) { | ||||
| return false; | return false; | ||||
| } | |||||
| if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) { | if (attribute_data_[i].connectivity_data.Vertex(act_c) != vert_id) { | ||||
| // Attribute seam found. Stop. | // Attribute seam found. Stop. | ||||
| deduplication_first_corner = act_c; | deduplication_first_corner = act_c; | ||||
| seam_found = true; | seam_found = true; | ||||
| break; | break; | ||||
| } | } | ||||
| act_c = corner_table_->SwingRight(act_c); | act_c = corner_table_->SwingRight(act_c); | ||||
| } | } | ||||
| if (seam_found) | if (seam_found) { | ||||
| break; // No reason to process other attributes if we found a seam. | break; // No reason to process other attributes if we found a seam. | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| // Do a deduplication pass over the corners on the processed vertex. | // Do a deduplication pass over the corners on the processed vertex. | ||||
| // At this point each corner corresponds to one point id and our goal is to | // At this point each corner corresponds to one point id and our goal is to | ||||
| // merge similar points into a single point id. | // merge similar points into a single point id. | ||||
| // We do a single pass in a clockwise direction over the corners and we add | // We do a single pass in a clockwise direction over the corners and we add | ||||
| // a new point id whenever one of the attributes change. | // a new point id whenever one of the attributes change. | ||||
| c = deduplication_first_corner; | c = deduplication_first_corner; | ||||
| // Create a new point. | // Create a new point. | ||||
| ▲ Show 20 Lines • Show All 50 Lines • Show Last 20 Lines | |||||