/src/draco/src/draco/compression/mesh/traverser/mesh_traversal_sequencer.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2016 The Draco Authors. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | // |
15 | | #ifndef DRACO_COMPRESSION_MESH_TRAVERSER_MESH_TRAVERSAL_SEQUENCER_H_ |
16 | | #define DRACO_COMPRESSION_MESH_TRAVERSER_MESH_TRAVERSAL_SEQUENCER_H_ |
17 | | |
18 | | #include "draco/attributes/geometry_indices.h" |
19 | | #include "draco/compression/attributes/mesh_attribute_indices_encoding_data.h" |
20 | | #include "draco/compression/attributes/points_sequencer.h" |
21 | | #include "draco/mesh/mesh.h" |
22 | | |
23 | | namespace draco { |
24 | | |
25 | | // Sequencer that generates point sequence in an order given by a deterministic |
26 | | // traversal on the mesh surface. Note that all attributes encoded with this |
27 | | // sequence must share the same connectivity. |
28 | | // TODO(b/199760123): Consider refactoring such that this is an observer. |
29 | | template <class TraverserT> |
30 | | class MeshTraversalSequencer : public PointsSequencer { |
31 | | public: |
32 | | MeshTraversalSequencer(const Mesh *mesh, |
33 | | const MeshAttributeIndicesEncodingData *encoding_data) |
34 | 3.76k | : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {} draco::MeshTraversalSequencer<draco::MaxPredictionDegreeTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::MeshTraversalSequencer(draco::Mesh const*, draco::MeshAttributeIndicesEncodingData const*) Line | Count | Source | 34 | 600 | : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {} |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::MeshTraversalSequencer(draco::Mesh const*, draco::MeshAttributeIndicesEncodingData const*) Line | Count | Source | 34 | 1.41k | : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {} |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::MeshAttributeCornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::MeshAttributeCornerTable> > >::MeshTraversalSequencer(draco::Mesh const*, draco::MeshAttributeIndicesEncodingData const*) Line | Count | Source | 34 | 1.75k | : mesh_(mesh), encoding_data_(encoding_data), corner_order_(nullptr) {} |
|
35 | 3.76k | void SetTraverser(const TraverserT &t) { traverser_ = t; } draco::MeshTraversalSequencer<draco::MaxPredictionDegreeTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::SetTraverser(draco::MaxPredictionDegreeTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > const&) Line | Count | Source | 35 | 600 | void SetTraverser(const TraverserT &t) { traverser_ = t; } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::SetTraverser(draco::DepthFirstTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > const&) Line | Count | Source | 35 | 1.41k | void SetTraverser(const TraverserT &t) { traverser_ = t; } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::MeshAttributeCornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::MeshAttributeCornerTable> > >::SetTraverser(draco::DepthFirstTraverser<draco::MeshAttributeCornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::MeshAttributeCornerTable> > const&) Line | Count | Source | 35 | 1.75k | void SetTraverser(const TraverserT &t) { traverser_ = t; } |
|
36 | | |
37 | | // Function that can be used to set an order in which the mesh corners should |
38 | | // be processed. This is an optional flag used usually only by the encoder |
39 | | // to match the same corner order that is going to be used by the decoder. |
40 | | // Note that |corner_order| should contain only one corner per face (it can |
41 | | // have all corners but only the first encountered corner for each face is |
42 | | // going to be used to start a traversal). If the corner order is not set, the |
43 | | // corners are processed sequentially based on their ids. |
44 | | void SetCornerOrder(const std::vector<CornerIndex> &corner_order) { |
45 | | corner_order_ = &corner_order; |
46 | | } |
47 | | |
48 | 19.0k | bool UpdatePointToAttributeIndexMapping(PointAttribute *attribute) override { |
49 | 19.0k | const auto *corner_table = traverser_.corner_table(); |
50 | 19.0k | attribute->SetExplicitMapping(mesh_->num_points()); |
51 | 19.0k | const size_t num_faces = mesh_->num_faces(); |
52 | 19.0k | const size_t num_points = mesh_->num_points(); |
53 | 18.2M | for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) { |
54 | 18.1M | const auto &face = mesh_->face(f); |
55 | 72.7M | for (int p = 0; p < 3; ++p) { |
56 | 54.5M | const PointIndex point_id = face[p]; |
57 | 54.5M | const VertexIndex vert_id = |
58 | 54.5M | corner_table->Vertex(CornerIndex(3 * f.value() + p)); |
59 | 54.5M | if (vert_id == kInvalidVertexIndex) { |
60 | 0 | return false; |
61 | 0 | } |
62 | 54.5M | const AttributeValueIndex att_entry_id( |
63 | 54.5M | encoding_data_ |
64 | 54.5M | ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]); |
65 | 54.5M | if (point_id >= num_points || att_entry_id.value() >= num_points) { |
66 | | // There cannot be more attribute values than the number of points. |
67 | 0 | return false; |
68 | 0 | } |
69 | 54.5M | attribute->SetPointMapEntry(point_id, att_entry_id); |
70 | 54.5M | } |
71 | 18.1M | } |
72 | 19.0k | return true; |
73 | 19.0k | } draco::MeshTraversalSequencer<draco::MaxPredictionDegreeTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::UpdatePointToAttributeIndexMapping(draco::PointAttribute*) Line | Count | Source | 48 | 1.36k | bool UpdatePointToAttributeIndexMapping(PointAttribute *attribute) override { | 49 | 1.36k | const auto *corner_table = traverser_.corner_table(); | 50 | 1.36k | attribute->SetExplicitMapping(mesh_->num_points()); | 51 | 1.36k | const size_t num_faces = mesh_->num_faces(); | 52 | 1.36k | const size_t num_points = mesh_->num_points(); | 53 | 3.75M | for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) { | 54 | 3.75M | const auto &face = mesh_->face(f); | 55 | 15.0M | for (int p = 0; p < 3; ++p) { | 56 | 11.2M | const PointIndex point_id = face[p]; | 57 | 11.2M | const VertexIndex vert_id = | 58 | 11.2M | corner_table->Vertex(CornerIndex(3 * f.value() + p)); | 59 | 11.2M | if (vert_id == kInvalidVertexIndex) { | 60 | 0 | return false; | 61 | 0 | } | 62 | 11.2M | const AttributeValueIndex att_entry_id( | 63 | 11.2M | encoding_data_ | 64 | 11.2M | ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]); | 65 | 11.2M | if (point_id >= num_points || att_entry_id.value() >= num_points) { | 66 | | // There cannot be more attribute values than the number of points. | 67 | 0 | return false; | 68 | 0 | } | 69 | 11.2M | attribute->SetPointMapEntry(point_id, att_entry_id); | 70 | 11.2M | } | 71 | 3.75M | } | 72 | 1.36k | return true; | 73 | 1.36k | } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::UpdatePointToAttributeIndexMapping(draco::PointAttribute*) Line | Count | Source | 48 | 8.85k | bool UpdatePointToAttributeIndexMapping(PointAttribute *attribute) override { | 49 | 8.85k | const auto *corner_table = traverser_.corner_table(); | 50 | 8.85k | attribute->SetExplicitMapping(mesh_->num_points()); | 51 | 8.85k | const size_t num_faces = mesh_->num_faces(); | 52 | 8.85k | const size_t num_points = mesh_->num_points(); | 53 | 7.25M | for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) { | 54 | 7.24M | const auto &face = mesh_->face(f); | 55 | 28.9M | for (int p = 0; p < 3; ++p) { | 56 | 21.7M | const PointIndex point_id = face[p]; | 57 | 21.7M | const VertexIndex vert_id = | 58 | 21.7M | corner_table->Vertex(CornerIndex(3 * f.value() + p)); | 59 | 21.7M | if (vert_id == kInvalidVertexIndex) { | 60 | 0 | return false; | 61 | 0 | } | 62 | 21.7M | const AttributeValueIndex att_entry_id( | 63 | 21.7M | encoding_data_ | 64 | 21.7M | ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]); | 65 | 21.7M | if (point_id >= num_points || att_entry_id.value() >= num_points) { | 66 | | // There cannot be more attribute values than the number of points. | 67 | 0 | return false; | 68 | 0 | } | 69 | 21.7M | attribute->SetPointMapEntry(point_id, att_entry_id); | 70 | 21.7M | } | 71 | 7.24M | } | 72 | 8.85k | return true; | 73 | 8.85k | } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::MeshAttributeCornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::MeshAttributeCornerTable> > >::UpdatePointToAttributeIndexMapping(draco::PointAttribute*) Line | Count | Source | 48 | 8.82k | bool UpdatePointToAttributeIndexMapping(PointAttribute *attribute) override { | 49 | 8.82k | const auto *corner_table = traverser_.corner_table(); | 50 | 8.82k | attribute->SetExplicitMapping(mesh_->num_points()); | 51 | 8.82k | const size_t num_faces = mesh_->num_faces(); | 52 | 8.82k | const size_t num_points = mesh_->num_points(); | 53 | 7.18M | for (FaceIndex f(0); f < static_cast<uint32_t>(num_faces); ++f) { | 54 | 7.18M | const auto &face = mesh_->face(f); | 55 | 28.7M | for (int p = 0; p < 3; ++p) { | 56 | 21.5M | const PointIndex point_id = face[p]; | 57 | 21.5M | const VertexIndex vert_id = | 58 | 21.5M | corner_table->Vertex(CornerIndex(3 * f.value() + p)); | 59 | 21.5M | if (vert_id == kInvalidVertexIndex) { | 60 | 0 | return false; | 61 | 0 | } | 62 | 21.5M | const AttributeValueIndex att_entry_id( | 63 | 21.5M | encoding_data_ | 64 | 21.5M | ->vertex_to_encoded_attribute_value_index_map[vert_id.value()]); | 65 | 21.5M | if (point_id >= num_points || att_entry_id.value() >= num_points) { | 66 | | // There cannot be more attribute values than the number of points. | 67 | 0 | return false; | 68 | 0 | } | 69 | 21.5M | attribute->SetPointMapEntry(point_id, att_entry_id); | 70 | 21.5M | } | 71 | 7.18M | } | 72 | 8.82k | return true; | 73 | 8.82k | } |
|
74 | | |
75 | | protected: |
76 | 3.69k | bool GenerateSequenceInternal() override { |
77 | | // Preallocate memory for storing point indices. We expect the number of |
78 | | // points to be the same as the number of corner table vertices. |
79 | 3.69k | out_point_ids()->reserve(traverser_.corner_table()->num_vertices()); |
80 | | |
81 | 3.69k | traverser_.OnTraversalStart(); |
82 | 3.69k | if (corner_order_) { |
83 | 0 | for (uint32_t i = 0; i < corner_order_->size(); ++i) { |
84 | 0 | if (!ProcessCorner(corner_order_->at(i))) { |
85 | 0 | return false; |
86 | 0 | } |
87 | 0 | } |
88 | 3.69k | } else { |
89 | 3.69k | const int32_t num_faces = traverser_.corner_table()->num_faces(); |
90 | 8.62M | for (int i = 0; i < num_faces; ++i) { |
91 | 8.61M | if (!ProcessCorner(CornerIndex(3 * i))) { |
92 | 0 | return false; |
93 | 0 | } |
94 | 8.61M | } |
95 | 3.69k | } |
96 | 3.69k | traverser_.OnTraversalEnd(); |
97 | 3.69k | return true; |
98 | 3.69k | } draco::MeshTraversalSequencer<draco::MaxPredictionDegreeTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::GenerateSequenceInternal() Line | Count | Source | 76 | 581 | bool GenerateSequenceInternal() override { | 77 | | // Preallocate memory for storing point indices. We expect the number of | 78 | | // points to be the same as the number of corner table vertices. | 79 | 581 | out_point_ids()->reserve(traverser_.corner_table()->num_vertices()); | 80 | | | 81 | 581 | traverser_.OnTraversalStart(); | 82 | 581 | if (corner_order_) { | 83 | 0 | for (uint32_t i = 0; i < corner_order_->size(); ++i) { | 84 | 0 | if (!ProcessCorner(corner_order_->at(i))) { | 85 | 0 | return false; | 86 | 0 | } | 87 | 0 | } | 88 | 581 | } else { | 89 | 581 | const int32_t num_faces = traverser_.corner_table()->num_faces(); | 90 | 1.95M | for (int i = 0; i < num_faces; ++i) { | 91 | 1.95M | if (!ProcessCorner(CornerIndex(3 * i))) { | 92 | 0 | return false; | 93 | 0 | } | 94 | 1.95M | } | 95 | 581 | } | 96 | 581 | traverser_.OnTraversalEnd(); | 97 | 581 | return true; | 98 | 581 | } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::GenerateSequenceInternal() Line | Count | Source | 76 | 1.37k | bool GenerateSequenceInternal() override { | 77 | | // Preallocate memory for storing point indices. We expect the number of | 78 | | // points to be the same as the number of corner table vertices. | 79 | 1.37k | out_point_ids()->reserve(traverser_.corner_table()->num_vertices()); | 80 | | | 81 | 1.37k | traverser_.OnTraversalStart(); | 82 | 1.37k | if (corner_order_) { | 83 | 0 | for (uint32_t i = 0; i < corner_order_->size(); ++i) { | 84 | 0 | if (!ProcessCorner(corner_order_->at(i))) { | 85 | 0 | return false; | 86 | 0 | } | 87 | 0 | } | 88 | 1.37k | } else { | 89 | 1.37k | const int32_t num_faces = traverser_.corner_table()->num_faces(); | 90 | 3.07M | for (int i = 0; i < num_faces; ++i) { | 91 | 3.07M | if (!ProcessCorner(CornerIndex(3 * i))) { | 92 | 0 | return false; | 93 | 0 | } | 94 | 3.07M | } | 95 | 1.37k | } | 96 | 1.37k | traverser_.OnTraversalEnd(); | 97 | 1.37k | return true; | 98 | 1.37k | } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::MeshAttributeCornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::MeshAttributeCornerTable> > >::GenerateSequenceInternal() Line | Count | Source | 76 | 1.73k | bool GenerateSequenceInternal() override { | 77 | | // Preallocate memory for storing point indices. We expect the number of | 78 | | // points to be the same as the number of corner table vertices. | 79 | 1.73k | out_point_ids()->reserve(traverser_.corner_table()->num_vertices()); | 80 | | | 81 | 1.73k | traverser_.OnTraversalStart(); | 82 | 1.73k | if (corner_order_) { | 83 | 0 | for (uint32_t i = 0; i < corner_order_->size(); ++i) { | 84 | 0 | if (!ProcessCorner(corner_order_->at(i))) { | 85 | 0 | return false; | 86 | 0 | } | 87 | 0 | } | 88 | 1.73k | } else { | 89 | 1.73k | const int32_t num_faces = traverser_.corner_table()->num_faces(); | 90 | 3.58M | for (int i = 0; i < num_faces; ++i) { | 91 | 3.58M | if (!ProcessCorner(CornerIndex(3 * i))) { | 92 | 0 | return false; | 93 | 0 | } | 94 | 3.58M | } | 95 | 1.73k | } | 96 | 1.73k | traverser_.OnTraversalEnd(); | 97 | 1.73k | return true; | 98 | 1.73k | } |
|
99 | | |
100 | | private: |
101 | 8.61M | bool ProcessCorner(CornerIndex corner_id) { |
102 | 8.61M | return traverser_.TraverseFromCorner(corner_id); |
103 | 8.61M | } draco::MeshTraversalSequencer<draco::MaxPredictionDegreeTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::ProcessCorner(draco::IndexType<unsigned int, draco::CornerIndex_tag_type_>) Line | Count | Source | 101 | 1.95M | bool ProcessCorner(CornerIndex corner_id) { | 102 | 1.95M | return traverser_.TraverseFromCorner(corner_id); | 103 | 1.95M | } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::CornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::CornerTable> > >::ProcessCorner(draco::IndexType<unsigned int, draco::CornerIndex_tag_type_>) Line | Count | Source | 101 | 3.07M | bool ProcessCorner(CornerIndex corner_id) { | 102 | 3.07M | return traverser_.TraverseFromCorner(corner_id); | 103 | 3.07M | } |
draco::MeshTraversalSequencer<draco::DepthFirstTraverser<draco::MeshAttributeCornerTable, draco::MeshAttributeIndicesEncodingObserver<draco::MeshAttributeCornerTable> > >::ProcessCorner(draco::IndexType<unsigned int, draco::CornerIndex_tag_type_>) Line | Count | Source | 101 | 3.58M | bool ProcessCorner(CornerIndex corner_id) { | 102 | 3.58M | return traverser_.TraverseFromCorner(corner_id); | 103 | 3.58M | } |
|
104 | | |
105 | | TraverserT traverser_; |
106 | | const Mesh *mesh_; |
107 | | const MeshAttributeIndicesEncodingData *encoding_data_; |
108 | | const std::vector<CornerIndex> *corner_order_; |
109 | | }; |
110 | | |
111 | | } // namespace draco |
112 | | |
113 | | #endif // DRACO_COMPRESSION_MESH_TRAVERSER_MESH_TRAVERSAL_SEQUENCER_H_ |