Differential D9642 Diff 31337 extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
Changeset View
Changeset View
Standalone View
Standalone View
extern/draco/draco/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc
- This file was moved from extern/draco/dracoenc/src/draco/compression/mesh/mesh_edgebreaker_encoder_impl.cc.
| Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| const MeshAttributeCornerTable * | const MeshAttributeCornerTable * | ||||
| MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetAttributeCornerTable( | MeshEdgebreakerEncoderImpl<TraversalEncoder>::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) { | ||||
| if (attribute_data_[i].attribute_index == att_id) { | if (attribute_data_[i].attribute_index == 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 TraversalEncoder> | template <class TraversalEncoder> | ||||
| const MeshAttributeIndicesEncodingData * | const MeshAttributeIndicesEncodingData * | ||||
| MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetAttributeEncodingData( | MeshEdgebreakerEncoderImpl<TraversalEncoder>::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) { | ||||
| if (attribute_data_[i].attribute_index == att_id) | if (attribute_data_[i].attribute_index == att_id) { | ||||
| return &attribute_data_[i].encoding_data; | return &attribute_data_[i].encoding_data; | ||||
| } | } | ||||
| } | |||||
| return &pos_encoding_data_; | return &pos_encoding_data_; | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| template <class TraverserT> | template <class TraverserT> | ||||
| std::unique_ptr<PointsSequencer> | std::unique_ptr<PointsSequencer> | ||||
| MeshEdgebreakerEncoderImpl<TraversalEncoder>::CreateVertexTraversalSequencer( | MeshEdgebreakerEncoderImpl<TraversalEncoder>::CreateVertexTraversalSequencer( | ||||
| MeshAttributeIndicesEncodingData *encoding_data) { | MeshAttributeIndicesEncodingData *encoding_data) { | ||||
| ▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | if (use_single_connectivity_ || | ||||
| att_traverser.Init(corner_table, att_observer); | att_traverser.Init(corner_table, att_observer); | ||||
| // Set order of corners to simulate the corner order of the decoder. | // Set order of corners to simulate the corner order of the decoder. | ||||
| traversal_sequencer->SetCornerOrder(processed_connectivity_corners_); | traversal_sequencer->SetCornerOrder(processed_connectivity_corners_); | ||||
| 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; | ||||
| } | |||||
| if (att_data_id == -1) { | if (att_data_id == -1) { | ||||
| pos_traversal_method_ = traversal_method; | pos_traversal_method_ = traversal_method; | ||||
| } else { | } else { | ||||
| attribute_data_[att_data_id].traversal_method = traversal_method; | attribute_data_[att_data_id].traversal_method = traversal_method; | ||||
| } | } | ||||
| std::unique_ptr<SequentialAttributeEncodersController> att_controller( | std::unique_ptr<SequentialAttributeEncodersController> att_controller( | ||||
| ▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { | ||||
| topology_split_event_data_.clear(); | topology_split_event_data_.clear(); | ||||
| face_to_split_symbol_map_.clear(); | face_to_split_symbol_map_.clear(); | ||||
| visited_holes_.clear(); | visited_holes_.clear(); | ||||
| vertex_hole_id_.assign(corner_table_->num_vertices(), -1); | vertex_hole_id_.assign(corner_table_->num_vertices(), -1); | ||||
| processed_connectivity_corners_.clear(); | processed_connectivity_corners_.clear(); | ||||
| processed_connectivity_corners_.reserve(corner_table_->num_faces()); | processed_connectivity_corners_.reserve(corner_table_->num_faces()); | ||||
| pos_encoding_data_.num_values = 0; | pos_encoding_data_.num_values = 0; | ||||
| if (!FindHoles()) | if (!FindHoles()) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to process mesh holes."); | return Status(Status::DRACO_ERROR, "Failed to process mesh holes."); | ||||
| } | |||||
| if (!InitAttributeData()) | if (!InitAttributeData()) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to initialize attribute data."); | return Status(Status::DRACO_ERROR, "Failed to initialize attribute data."); | ||||
| } | |||||
| const uint8_t num_attribute_data = | const uint8_t num_attribute_data = | ||||
| static_cast<uint8_t>(attribute_data_.size()); | static_cast<uint8_t>(attribute_data_.size()); | ||||
| encoder_->buffer()->Encode(num_attribute_data); | encoder_->buffer()->Encode(num_attribute_data); | ||||
| traversal_encoder_.SetNumAttributeData(num_attribute_data); | traversal_encoder_.SetNumAttributeData(num_attribute_data); | ||||
| const int num_corners = corner_table_->num_corners(); | const int num_corners = corner_table_->num_corners(); | ||||
| traversal_encoder_.Start(); | traversal_encoder_.Start(); | ||||
| std::vector<CornerIndex> init_face_connectivity_corners; | std::vector<CornerIndex> init_face_connectivity_corners; | ||||
| // Traverse the surface starting from each unvisited corner. | // Traverse the surface starting from each unvisited corner. | ||||
| for (int c_id = 0; c_id < num_corners; ++c_id) { | for (int c_id = 0; c_id < num_corners; ++c_id) { | ||||
| CornerIndex corner_index(c_id); | CornerIndex corner_index(c_id); | ||||
| const FaceIndex face_id = corner_table_->Face(corner_index); | const FaceIndex face_id = corner_table_->Face(corner_index); | ||||
| if (visited_faces_[face_id.value()]) | if (visited_faces_[face_id.value()]) { | ||||
| continue; // Face has been already processed. | continue; // Face has been already processed. | ||||
| if (corner_table_->IsDegenerated(face_id)) | } | ||||
| if (corner_table_->IsDegenerated(face_id)) { | |||||
| continue; // Ignore degenerated faces. | continue; // Ignore degenerated faces. | ||||
| } | |||||
| CornerIndex start_corner; | CornerIndex start_corner; | ||||
| const bool interior_config = | const bool interior_config = | ||||
| FindInitFaceConfiguration(face_id, &start_corner); | FindInitFaceConfiguration(face_id, &start_corner); | ||||
| traversal_encoder_.EncodeStartFaceConfiguration(interior_config); | traversal_encoder_.EncodeStartFaceConfiguration(interior_config); | ||||
| if (interior_config) { | if (interior_config) { | ||||
| // Select the correct vertex on the face as the root. | // Select the correct vertex on the face as the root. | ||||
| Show All 19 Lines | if (interior_config) { | ||||
| // as a TOPOLOGY_C face). | // as a TOPOLOGY_C face). | ||||
| init_face_connectivity_corners.push_back( | init_face_connectivity_corners.push_back( | ||||
| corner_table_->Next(corner_index)); | corner_table_->Next(corner_index)); | ||||
| const CornerIndex opp_id = | const CornerIndex opp_id = | ||||
| corner_table_->Opposite(corner_table_->Next(corner_index)); | corner_table_->Opposite(corner_table_->Next(corner_index)); | ||||
| const FaceIndex opp_face_id = corner_table_->Face(opp_id); | const FaceIndex opp_face_id = corner_table_->Face(opp_id); | ||||
| if (opp_face_id != kInvalidFaceIndex && | if (opp_face_id != kInvalidFaceIndex && | ||||
| !visited_faces_[opp_face_id.value()]) { | !visited_faces_[opp_face_id.value()]) { | ||||
| if (!EncodeConnectivityFromCorner(opp_id)) | if (!EncodeConnectivityFromCorner(opp_id)) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to encode mesh component."); | return Status(Status::DRACO_ERROR, | ||||
| "Failed to encode mesh component."); | |||||
| } | |||||
| } | } | ||||
| } else { | } else { | ||||
| // Boundary configuration. We start on a boundary rather than on a face. | // Boundary configuration. We start on a boundary rather than on a face. | ||||
| // First encode the hole that's opposite to the start_corner. | // First encode the hole that's opposite to the start_corner. | ||||
| EncodeHole(corner_table_->Next(start_corner), true); | EncodeHole(corner_table_->Next(start_corner), true); | ||||
| // Start processing the face opposite to the boundary edge (the face | // Start processing the face opposite to the boundary edge (the face | ||||
| // containing the start_corner). | // containing the start_corner). | ||||
| if (!EncodeConnectivityFromCorner(start_corner)) | if (!EncodeConnectivityFromCorner(start_corner)) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to encode mesh component."); | return Status(Status::DRACO_ERROR, "Failed to encode mesh component."); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| // Reverse the order of connectivity corners to match the order in which | // Reverse the order of connectivity corners to match the order in which | ||||
| // they are going to be decoded. | // they are going to be decoded. | ||||
| std::reverse(processed_connectivity_corners_.begin(), | std::reverse(processed_connectivity_corners_.begin(), | ||||
| processed_connectivity_corners_.end()); | processed_connectivity_corners_.end()); | ||||
| // Append the init face connectivity corners (which are processed in order by | // Append the init face connectivity corners (which are processed in order by | ||||
| // the decoder after the regular corners. | // the decoder after the regular corners. | ||||
| processed_connectivity_corners_.insert(processed_connectivity_corners_.end(), | processed_connectivity_corners_.insert(processed_connectivity_corners_.end(), | ||||
| init_face_connectivity_corners.begin(), | init_face_connectivity_corners.begin(), | ||||
| Show All 12 Lines | Status MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() { | ||||
| const uint32_t num_encoded_symbols = | const uint32_t num_encoded_symbols = | ||||
| static_cast<uint32_t>(traversal_encoder_.NumEncodedSymbols()); | static_cast<uint32_t>(traversal_encoder_.NumEncodedSymbols()); | ||||
| EncodeVarint(num_encoded_symbols, encoder_->buffer()); | EncodeVarint(num_encoded_symbols, encoder_->buffer()); | ||||
| // Encode the number of split symbols. | // Encode the number of split symbols. | ||||
| EncodeVarint(num_split_symbols_, encoder_->buffer()); | EncodeVarint(num_split_symbols_, encoder_->buffer()); | ||||
| // Append the traversal buffer. | // Append the traversal buffer. | ||||
| if (!EncodeSplitData()) | if (!EncodeSplitData()) { | ||||
| return Status(Status::DRACO_ERROR, "Failed to encode split data."); | return Status(Status::DRACO_ERROR, "Failed to encode split data."); | ||||
| } | |||||
| encoder_->buffer()->Encode(traversal_encoder_.buffer().data(), | encoder_->buffer()->Encode(traversal_encoder_.buffer().data(), | ||||
| traversal_encoder_.buffer().size()); | traversal_encoder_.buffer().size()); | ||||
| return OkStatus(); | return OkStatus(); | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeSplitData() { | bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::EncodeSplitData() { | ||||
| ▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | while (num_visited_faces < num_faces) { | ||||
| // faces. | // faces. | ||||
| const CornerIndex right_corner_id = GetRightCorner(corner_id); | const CornerIndex right_corner_id = GetRightCorner(corner_id); | ||||
| const CornerIndex left_corner_id = GetLeftCorner(corner_id); | const CornerIndex left_corner_id = GetLeftCorner(corner_id); | ||||
| const FaceIndex right_face_id = corner_table_->Face(right_corner_id); | const FaceIndex right_face_id = corner_table_->Face(right_corner_id); | ||||
| const FaceIndex left_face_id = corner_table_->Face(left_corner_id); | const FaceIndex left_face_id = corner_table_->Face(left_corner_id); | ||||
| if (IsRightFaceVisited(corner_id)) { | if (IsRightFaceVisited(corner_id)) { | ||||
| // Right face has been already visited. | // Right face has been already visited. | ||||
| // Check whether there is a topology split event. | // Check whether there is a topology split event. | ||||
| if (right_face_id != kInvalidFaceIndex) | if (right_face_id != kInvalidFaceIndex) { | ||||
| CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, | CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, | ||||
| face_id.value(), RIGHT_FACE_EDGE, | face_id.value(), RIGHT_FACE_EDGE, | ||||
| right_face_id.value()); | right_face_id.value()); | ||||
| } | |||||
| if (IsLeftFaceVisited(corner_id)) { | if (IsLeftFaceVisited(corner_id)) { | ||||
| // Both neighboring faces are visited. End reached. | // Both neighboring faces are visited. End reached. | ||||
| // Check whether there is a topology split event on the left face. | // Check whether there is a topology split event on the left face. | ||||
| if (left_face_id != kInvalidFaceIndex) | if (left_face_id != kInvalidFaceIndex) { | ||||
| CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, | CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, | ||||
| face_id.value(), LEFT_FACE_EDGE, | face_id.value(), LEFT_FACE_EDGE, | ||||
| left_face_id.value()); | left_face_id.value()); | ||||
| } | |||||
| traversal_encoder_.EncodeSymbol(TOPOLOGY_E); | traversal_encoder_.EncodeSymbol(TOPOLOGY_E); | ||||
| corner_traversal_stack_.pop_back(); | corner_traversal_stack_.pop_back(); | ||||
| break; // Break from the while (num_visited_faces < num_faces) loop. | break; // Break from the while (num_visited_faces < num_faces) loop. | ||||
| } else { | } else { | ||||
| traversal_encoder_.EncodeSymbol(TOPOLOGY_R); | traversal_encoder_.EncodeSymbol(TOPOLOGY_R); | ||||
| // Go to the left face. | // Go to the left face. | ||||
| corner_id = left_corner_id; | corner_id = left_corner_id; | ||||
| } | } | ||||
| } else { | } else { | ||||
| // Right face was not visited. | // Right face was not visited. | ||||
| if (IsLeftFaceVisited(corner_id)) { | if (IsLeftFaceVisited(corner_id)) { | ||||
| // Check whether there is a topology split event on the left face. | // Check whether there is a topology split event on the left face. | ||||
| if (left_face_id != kInvalidFaceIndex) | if (left_face_id != kInvalidFaceIndex) { | ||||
| CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, | CheckAndStoreTopologySplitEvent(last_encoded_symbol_id_, | ||||
| face_id.value(), LEFT_FACE_EDGE, | face_id.value(), LEFT_FACE_EDGE, | ||||
| left_face_id.value()); | left_face_id.value()); | ||||
| } | |||||
| traversal_encoder_.EncodeSymbol(TOPOLOGY_L); | traversal_encoder_.EncodeSymbol(TOPOLOGY_L); | ||||
| // Left face visited, go to the right one. | // Left face visited, go to the right one. | ||||
| corner_id = right_corner_id; | corner_id = right_corner_id; | ||||
| } else { | } else { | ||||
| traversal_encoder_.EncodeSymbol(TOPOLOGY_S); | traversal_encoder_.EncodeSymbol(TOPOLOGY_S); | ||||
| ++num_split_symbols_; | ++num_split_symbols_; | ||||
| // Both neighboring faces are unvisited, we need to visit both of | // Both neighboring faces are unvisited, we need to visit both of | ||||
| // them. | // them. | ||||
| ▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | CornerIndex MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetLeftCorner( | ||||
| return corner_table_->Opposite(prev_corner_id); | return corner_table_->Opposite(prev_corner_id); | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::IsRightFaceVisited( | bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::IsRightFaceVisited( | ||||
| CornerIndex corner_id) const { | CornerIndex corner_id) const { | ||||
| const CornerIndex next_corner_id = corner_table_->Next(corner_id); | const CornerIndex next_corner_id = corner_table_->Next(corner_id); | ||||
| const CornerIndex opp_corner_id = corner_table_->Opposite(next_corner_id); | const CornerIndex opp_corner_id = corner_table_->Opposite(next_corner_id); | ||||
| if (opp_corner_id != kInvalidCornerIndex) | if (opp_corner_id != kInvalidCornerIndex) { | ||||
| return visited_faces_[corner_table_->Face(opp_corner_id).value()]; | return visited_faces_[corner_table_->Face(opp_corner_id).value()]; | ||||
| } | |||||
| // Else we are on a boundary. | // Else we are on a boundary. | ||||
| return true; | return true; | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::IsLeftFaceVisited( | bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::IsLeftFaceVisited( | ||||
| CornerIndex corner_id) const { | CornerIndex corner_id) const { | ||||
| const CornerIndex prev_corner_id = corner_table_->Previous(corner_id); | const CornerIndex prev_corner_id = corner_table_->Previous(corner_id); | ||||
| const CornerIndex opp_corner_id = corner_table_->Opposite(prev_corner_id); | const CornerIndex opp_corner_id = corner_table_->Opposite(prev_corner_id); | ||||
| if (opp_corner_id != kInvalidCornerIndex) | if (opp_corner_id != kInvalidCornerIndex) { | ||||
| return visited_faces_[corner_table_->Face(opp_corner_id).value()]; | return visited_faces_[corner_table_->Face(opp_corner_id).value()]; | ||||
| } | |||||
| // Else we are on a boundary. | // Else we are on a boundary. | ||||
| return true; | return true; | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::FindHoles() { | bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::FindHoles() { | ||||
| // TODO(ostava): Add more error checking for invalid geometry data. | // TODO(ostava): Add more error checking for invalid geometry data. | ||||
| const int num_corners = corner_table_->num_corners(); | const int num_corners = corner_table_->num_corners(); | ||||
| // Go over all corners and detect non-visited open boundaries | // Go over all corners and detect non-visited open boundaries | ||||
| for (CornerIndex i(0); i < num_corners; ++i) { | for (CornerIndex i(0); i < num_corners; ++i) { | ||||
| if (corner_table_->IsDegenerated(corner_table_->Face(i))) | if (corner_table_->IsDegenerated(corner_table_->Face(i))) { | ||||
| continue; // Don't process corners assigned to degenerated faces. | continue; // Don't process corners assigned to degenerated faces. | ||||
| } | |||||
| if (corner_table_->Opposite(i) == kInvalidCornerIndex) { | if (corner_table_->Opposite(i) == kInvalidCornerIndex) { | ||||
| // No opposite corner means no opposite face, so the opposite edge | // No opposite corner means no opposite face, so the opposite edge | ||||
| // of the corner is an open boundary. | // of the corner is an open boundary. | ||||
| // Check whether we have already traversed the boundary. | // Check whether we have already traversed the boundary. | ||||
| VertexIndex boundary_vert_id = | VertexIndex boundary_vert_id = | ||||
| corner_table_->Vertex(corner_table_->Next(i)); | corner_table_->Vertex(corner_table_->Next(i)); | ||||
| if (vertex_hole_id_[boundary_vert_id.value()] != -1) { | if (vertex_hole_id_[boundary_vert_id.value()] != -1) { | ||||
| // The start vertex of the boundary edge is already assigned to an | // The start vertex of the boundary edge is already assigned to an | ||||
| Show All 23 Lines | bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::FindHoles() { | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| int MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetSplitSymbolIdOnFace( | int MeshEdgebreakerEncoderImpl<TraversalEncoder>::GetSplitSymbolIdOnFace( | ||||
| int face_id) const { | int face_id) const { | ||||
| auto it = face_to_split_symbol_map_.find(face_id); | auto it = face_to_split_symbol_map_.find(face_id); | ||||
| if (it == face_to_split_symbol_map_.end()) | if (it == face_to_split_symbol_map_.end()) { | ||||
| return -1; | return -1; | ||||
| } | |||||
| return it->second; | return it->second; | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| void MeshEdgebreakerEncoderImpl< | void MeshEdgebreakerEncoderImpl< | ||||
| TraversalEncoder>::CheckAndStoreTopologySplitEvent(int src_symbol_id, | TraversalEncoder>::CheckAndStoreTopologySplitEvent(int src_symbol_id, | ||||
| int /* src_face_id */, | int /* src_face_id */, | ||||
| EdgeFaceName src_edge, | EdgeFaceName src_edge, | ||||
| int neighbor_face_id) { | int neighbor_face_id) { | ||||
| const int symbol_id = GetSplitSymbolIdOnFace(neighbor_face_id); | const int symbol_id = GetSplitSymbolIdOnFace(neighbor_face_id); | ||||
| if (symbol_id == -1) | if (symbol_id == -1) { | ||||
| return; // Not a split symbol, no topology split event could happen. | return; // Not a split symbol, no topology split event could happen. | ||||
| } | |||||
| TopologySplitEventData event_data; | TopologySplitEventData event_data; | ||||
| event_data.split_symbol_id = symbol_id; | event_data.split_symbol_id = symbol_id; | ||||
| event_data.source_symbol_id = src_symbol_id; | event_data.source_symbol_id = src_symbol_id; | ||||
| event_data.source_edge = src_edge; | event_data.source_edge = src_edge; | ||||
| topology_split_event_data_.push_back(event_data); | topology_split_event_data_.push_back(event_data); | ||||
| } | } | ||||
| template <class TraversalEncoder> | template <class TraversalEncoder> | ||||
| bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::InitAttributeData() { | bool MeshEdgebreakerEncoderImpl<TraversalEncoder>::InitAttributeData() { | ||||
| if (use_single_connectivity_) | if (use_single_connectivity_) { | ||||
| return true; // All attributes use the same connectivity. | return true; // All attributes use the same connectivity. | ||||
| } | |||||
| const int num_attributes = mesh_->num_attributes(); | const int num_attributes = mesh_->num_attributes(); | ||||
| // Ignore the position attribute. It's decoded separately. | // Ignore the position attribute. It's decoded separately. | ||||
| attribute_data_.resize(num_attributes - 1); | attribute_data_.resize(num_attributes - 1); | ||||
| if (num_attributes == 1) | if (num_attributes == 1) { | ||||
| return true; | return true; | ||||
| } | |||||
| int data_index = 0; | int data_index = 0; | ||||
| for (int i = 0; i < num_attributes; ++i) { | for (int i = 0; i < num_attributes; ++i) { | ||||
| const int32_t att_index = i; | const int32_t att_index = i; | ||||
| if (mesh_->attribute(att_index)->attribute_type() == | if (mesh_->attribute(att_index)->attribute_type() == | ||||
| GeometryAttribute::POSITION) | GeometryAttribute::POSITION) { | ||||
| continue; | continue; | ||||
| } | |||||
| const PointAttribute *const att = mesh_->attribute(att_index); | const PointAttribute *const att = mesh_->attribute(att_index); | ||||
| attribute_data_[data_index].attribute_index = att_index; | attribute_data_[data_index].attribute_index = att_index; | ||||
| attribute_data_[data_index] | attribute_data_[data_index] | ||||
| .encoding_data.encoded_attribute_value_index_to_corner_map.clear(); | .encoding_data.encoded_attribute_value_index_to_corner_map.clear(); | ||||
| attribute_data_[data_index] | attribute_data_[data_index] | ||||
| .encoding_data.encoded_attribute_value_index_to_corner_map.reserve( | .encoding_data.encoded_attribute_value_index_to_corner_map.reserve( | ||||
| corner_table_->num_corners()); | corner_table_->num_corners()); | ||||
| attribute_data_[data_index].encoding_data.num_values = 0; | attribute_data_[data_index].encoding_data.num_values = 0; | ||||
| Show All 15 Lines | bool MeshEdgebreakerEncoderImpl< | ||||
| // 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); | ||||
| visited_faces_[src_face_id.value()] = true; | visited_faces_[src_face_id.value()] = true; | ||||
| 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) { | ||||
| continue; // Don't encode attribute seams on boundary edges. | continue; // Don't encode attribute seams on boundary edges. | ||||
| } | |||||
| const FaceIndex opp_face_id = corner_table_->Face(opp_corner); | const FaceIndex opp_face_id = corner_table_->Face(opp_corner); | ||||
| // Don't encode edges when the opposite face has been already processed. | // Don't encode edges when the opposite face has been already processed. | ||||
| if (visited_faces_[opp_face_id.value()]) | if (visited_faces_[opp_face_id.value()]) { | ||||
| continue; | continue; | ||||
| } | |||||
| 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.IsCornerOppositeToSeamEdge( | if (attribute_data_[i].connectivity_data.IsCornerOppositeToSeamEdge( | ||||
| corners[c])) { | corners[c])) { | ||||
| traversal_encoder_.EncodeAttributeSeam(i, true); | traversal_encoder_.EncodeAttributeSeam(i, true); | ||||
| } else { | } else { | ||||
| traversal_encoder_.EncodeAttributeSeam(i, false); | traversal_encoder_.EncodeAttributeSeam(i, false); | ||||
| } | } | ||||
| Show All 12 Lines | |||||