GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
depth_first_traverser.h
Go to the documentation of this file.
1// Copyright 2016 The Draco Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15#ifndef DRACO_COMPRESSION_MESH_TRAVERSER_DEPTH_FIRST_TRAVERSER_H_
16#define DRACO_COMPRESSION_MESH_TRAVERSER_DEPTH_FIRST_TRAVERSER_H_
17
18#include <vector>
19
22
23namespace draco {
24
25// Basic traverser that traverses a mesh in a DFS like fashion using the
26// CornerTable data structure. The necessary bookkeeping is available via the
27// TraverserBase. Callbacks are handled through template argument
28// TraversalObserverT.
29//
30// TraversalObserverT can perform an action on a traversal event such as newly
31// visited face, or corner, but it does not affect the traversal itself.
32//
33// Concept TraversalObserverT requires:
34//
35// public:
36// void OnNewFaceVisited(FaceIndex face);
37// - Called whenever a previously unvisited face is reached.
38//
39// void OnNewVertexVisited(VertexIndex vert, CornerIndex corner)
40// - Called when a new vertex is visited. |corner| is used to indicate the
41// which of the vertex's corners has been reached.
42
43template <class CornerTableT, class TraversalObserverT>
45 : public TraverserBase<CornerTableT, TraversalObserverT> {
46 public:
47 typedef CornerTableT CornerTable;
48 typedef TraversalObserverT TraversalObserver;
50
52
53 // Called before any traversing starts.
55
56 // Called when all the traversing is done.
58
60 if (this->IsFaceVisited(corner_id)) {
61 return true; // Already traversed.
62 }
63
64 corner_traversal_stack_.clear();
65 corner_traversal_stack_.push_back(corner_id);
66 // For the first face, check the remaining corners as they may not be
67 // processed yet.
68 const VertexIndex next_vert =
69 this->corner_table()->Vertex(this->corner_table()->Next(corner_id));
70 const VertexIndex prev_vert =
71 this->corner_table()->Vertex(this->corner_table()->Previous(corner_id));
72 if (next_vert == kInvalidVertexIndex || prev_vert == kInvalidVertexIndex) {
73 return false;
74 }
75 if (!this->IsVertexVisited(next_vert)) {
76 this->MarkVertexVisited(next_vert);
77 this->traversal_observer().OnNewVertexVisited(
78 next_vert, this->corner_table()->Next(corner_id));
79 }
80 if (!this->IsVertexVisited(prev_vert)) {
81 this->MarkVertexVisited(prev_vert);
82 this->traversal_observer().OnNewVertexVisited(
83 prev_vert, this->corner_table()->Previous(corner_id));
84 }
85
86 // Start the actual traversal.
87 while (!corner_traversal_stack_.empty()) {
88 // Currently processed corner.
89 corner_id = corner_traversal_stack_.back();
90 FaceIndex face_id(corner_id.value() / 3);
91 // Make sure the face hasn't been visited yet.
92 if (corner_id == kInvalidCornerIndex || this->IsFaceVisited(face_id)) {
93 // This face has been already traversed.
94 corner_traversal_stack_.pop_back();
95 continue;
96 }
97 while (true) {
98 this->MarkFaceVisited(face_id);
99 this->traversal_observer().OnNewFaceVisited(face_id);
100 const VertexIndex vert_id = this->corner_table()->Vertex(corner_id);
101 if (vert_id == kInvalidVertexIndex) {
102 return false;
103 }
104 if (!this->IsVertexVisited(vert_id)) {
105 const bool on_boundary = this->corner_table()->IsOnBoundary(vert_id);
106 this->MarkVertexVisited(vert_id);
107 this->traversal_observer().OnNewVertexVisited(vert_id, corner_id);
108 if (!on_boundary) {
109 corner_id = this->corner_table()->GetRightCorner(corner_id);
110 face_id = FaceIndex(corner_id.value() / 3);
111 continue;
112 }
113 }
114 // The current vertex has been already visited or it was on a boundary.
115 // We need to determine whether we can visit any of it's neighboring
116 // faces.
117 const CornerIndex right_corner_id =
118 this->corner_table()->GetRightCorner(corner_id);
119 const CornerIndex left_corner_id =
120 this->corner_table()->GetLeftCorner(corner_id);
121 const FaceIndex right_face_id(
122 (right_corner_id == kInvalidCornerIndex
123 ? kInvalidFaceIndex
124 : FaceIndex(right_corner_id.value() / 3)));
125 const FaceIndex left_face_id(
126 (left_corner_id == kInvalidCornerIndex
127 ? kInvalidFaceIndex
128 : FaceIndex(left_corner_id.value() / 3)));
129 if (this->IsFaceVisited(right_face_id)) {
130 // Right face has been already visited.
131 if (this->IsFaceVisited(left_face_id)) {
132 // Both neighboring faces are visited. End reached.
133 corner_traversal_stack_.pop_back();
134 break; // Break from the while (true) loop.
135 } else {
136 // Go to the left face.
137 corner_id = left_corner_id;
138 face_id = left_face_id;
139 }
140 } else {
141 // Right face was not visited.
142 if (this->IsFaceVisited(left_face_id)) {
143 // Left face visited, go to the right one.
144 corner_id = right_corner_id;
145 face_id = right_face_id;
146 } else {
147 // Both neighboring faces are unvisited, we need to visit both of
148 // them.
149
150 // Split the traversal.
151 // First make the top of the current corner stack point to the left
152 // face (this one will be processed second).
153 corner_traversal_stack_.back() = left_corner_id;
154 // Add a new corner to the top of the stack (right face needs to
155 // be traversed first).
156 corner_traversal_stack_.push_back(right_corner_id);
157 // Break from the while (true) loop.
158 break;
159 }
160 }
161 }
162 }
163 return true;
164 }
165
166 private:
167 std::vector<CornerIndex> corner_traversal_stack_;
168};
169
170} // namespace draco
171
172#endif // DRACO_COMPRESSION_MESH_TRAVERSER_DEPTH_FIRST_TRAVERSER_H_
CornerTableT CornerTable
Definition depth_first_traverser.h:47
void OnTraversalStart()
Definition depth_first_traverser.h:54
DepthFirstTraverser()
Definition depth_first_traverser.h:51
TraversalObserverT TraversalObserver
Definition depth_first_traverser.h:48
void OnTraversalEnd()
Definition depth_first_traverser.h:57
TraverserBase< CornerTable, TraversalObserver > Base
Definition depth_first_traverser.h:49
bool TraverseFromCorner(CornerIndex corner_id)
Definition depth_first_traverser.h:59
const CornerTable * corner_table() const
Definition traverser_base.h:70
bool IsVertexVisited(VertexIndex vert_id) const
Definition traverser_base.h:63
const TraversalObserverT & traversal_observer() const
Definition traverser_base.h:71
bool IsFaceVisited(FaceIndex face_id) const
Definition traverser_base.h:45
void MarkVertexVisited(VertexIndex vert_id)
Definition traverser_base.h:66
void MarkFaceVisited(FaceIndex face_id)
Definition traverser_base.h:60
TraverserBase()
Definition traverser_base.h:32
Definition attribute_octahedron_transform.cc:21
VertexIndex VertexIndex
Definition mesh_edgebreaker_encoder_impl.cc:37
CornerIndex CornerIndex
Definition mesh_edgebreaker_encoder_impl.cc:35
FaceIndex FaceIndex
Definition mesh_edgebreaker_encoder_impl.cc:36