mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-04-23 06:09:57 +08:00
231 lines
6.8 KiB
Markdown
231 lines
6.8 KiB
Markdown
|
|
## EdgeBreaker Traversal
|
|
|
|
### ParseEdgebreakerTraversalStandardSymbolData()
|
|
|
|
~~~~~
|
|
void ParseEdgebreakerTraversalStandardSymbolData() {
|
|
sz = eb_symbol_buffer_size varUI64
|
|
eb_symbol_buffer UI8[sz]
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### ParseEdgebreakerTraversalStandardFaceData()
|
|
|
|
~~~~~
|
|
void ParseEdgebreakerTraversalStandardFaceData() {
|
|
eb_start_face_buffer_prob_zero UI8
|
|
sz = eb_start_face_buffer_size varUI32
|
|
eb_start_face_buffer UI8[sz]
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### ParseEdgebreakerTraversalStandardAttributeConnectivityData()
|
|
|
|
~~~~~
|
|
void ParseEdgebreakerTraversalStandardAttributeConnectivityData() {
|
|
for (i = 0; i < num_attribute_data; ++i) {
|
|
attribute_connectivity_decoders_prob_zero[i] UI8
|
|
sz = attribute_connectivity_decoders_size[i] varUI32
|
|
attribute_connectivity_decoders_buffer[i] UI8[sz]
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### DecodeEdgebreakerTraversalStandardData()
|
|
|
|
~~~~~
|
|
void DecodeEdgebreakerTraversalStandardData() {
|
|
ParseEdgebreakerTraversalStandardSymbolData()
|
|
ParseEdgebreakerTraversalStandardFaceData()
|
|
ParseEdgebreakerTraversalStandardAttributeConnectivityData()
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### EdgebreakerTraversalStart()
|
|
|
|
~~~~~
|
|
void EdgebreakerTraversalStart() {
|
|
last_symbol_ = -1;
|
|
active_context_ = -1;
|
|
if (edgebreaker_traversal_type == STANDARD_EDGEBREAKER) {
|
|
DecodeEdgebreakerTraversalStandardData();
|
|
} else if (edgebreaker_traversal_type == VALENCE_EDGEBREAKER) {
|
|
EdgeBreakerTraversalValenceStart();
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### IsFaceVisited()
|
|
|
|
~~~~~
|
|
bool IsFaceVisited(face_id) {
|
|
if (face_id < 0)
|
|
return true; // Invalid faces are always considered as visited.
|
|
return is_face_visited_[face_id];
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### OnNewVertexVisited()
|
|
|
|
~~~~~
|
|
void OnNewVertexVisited(vertex, corner) {
|
|
encoded_attribute_value_index_to_corner_map[curr_att_dec].push_back(corner);
|
|
vertex_to_encoded_attribute_value_index_map[curr_att_dec][vertex] =
|
|
vertex_visited_point_ids[curr_att_dec];
|
|
vertex_visited_point_ids[curr_att_dec]++;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### EdgeBreakerTraverser_ProcessCorner()
|
|
|
|
~~~~~
|
|
void EdgeBreakerTraverser_ProcessCorner(corner_id) {
|
|
face = corner_id / 3;
|
|
if (IsFaceVisited(face))
|
|
return; // Already traversed.
|
|
corner_traversal_stack_.push_back(corner_id);
|
|
next_vert = face_to_vertex[1][face];
|
|
prev_vert = face_to_vertex[2][face];
|
|
if (!is_vertex_visited_[next_vert]) {
|
|
is_vertex_visited_[next_vert] = true;
|
|
next_c = Next(corner_id);
|
|
OnNewVertexVisited(next_vert, next_c);
|
|
}
|
|
if (!is_vertex_visited_[prev_vert]) {
|
|
is_vertex_visited_[prev_vert] = true;
|
|
prev_c = Previous(corner_id);
|
|
OnNewVertexVisited(prev_vert, prev_c);
|
|
}
|
|
while (!corner_traversal_stack_.empty()) {
|
|
corner_id = corner_traversal_stack_.back();
|
|
face_id = corner_id / 3;
|
|
if (corner_id < 0 || IsFaceVisited(face_id)) {
|
|
// This face has been already traversed.
|
|
corner_traversal_stack_.pop_back();
|
|
continue;
|
|
}
|
|
while (true) {
|
|
face_id = corner_id / 3;
|
|
is_face_visited_[face_id] = true;
|
|
vert_id = CornerToVert(0, corner_id);
|
|
if (!is_vertex_visited_[vert_id]) {
|
|
on_boundary = IsOnPositionBoundary(vert_id);
|
|
is_vertex_visited_[vert_id] = true;
|
|
OnNewVertexVisited(vert_id, corner_id);
|
|
if (!on_boundary) {
|
|
corner_id = GetRightCorner(corner_id);
|
|
continue;
|
|
}
|
|
}
|
|
right_corner_id = GetRightCorner(corner_id);
|
|
left_corner_id = GetLeftCorner(corner_id);
|
|
right_face_id = right_corner_id < 0 ? -1 : right_corner_id / 3;
|
|
left_face_id = left_corner_id < 0 ? -1 : left_corner_id / 3;
|
|
if (IsFaceVisited(right_face_id)) {
|
|
if (IsFaceVisited(left_face_id)) {
|
|
corner_traversal_stack_.pop_back();
|
|
break;
|
|
} else {
|
|
corner_id = left_corner_id;
|
|
}
|
|
} else {
|
|
if (IsFaceVisited(left_face_id)) {
|
|
corner_id = right_corner_id;
|
|
} else {
|
|
corner_traversal_stack_.back() = left_corner_id;
|
|
corner_traversal_stack_.push_back(right_corner_id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### EdgeBreakerAttributeTraverser_ProcessCorner()
|
|
|
|
~~~~~
|
|
void EdgeBreakerAttributeTraverser_ProcessCorner(corner_id) {
|
|
face = corner_id / 3;
|
|
if (IsFaceVisited(face))
|
|
return; // Already traversed.
|
|
corner_traversal_stack_.push_back(corner_id);
|
|
CornerToVerts(curr_att_dec, corner_id, &vert_id, &next_vert, &prev_vert);
|
|
if (!is_vertex_visited_[next_vert]) {
|
|
is_vertex_visited_[next_vert] = true;
|
|
next_c = Next(corner_id);
|
|
OnNewVertexVisited(next_vert, next_c);
|
|
}
|
|
if (!is_vertex_visited_[prev_vert]) {
|
|
is_vertex_visited_[prev_vert] = true;
|
|
prev_c = Previous(corner_id);
|
|
OnNewVertexVisited(prev_vert, prev_c);
|
|
}
|
|
while (!corner_traversal_stack_.empty()) {
|
|
corner_id = corner_traversal_stack_.back();
|
|
face_id = corner_id / 3;
|
|
if (corner_id < 0 || IsFaceVisited(face_id)) {
|
|
corner_traversal_stack_.pop_back();
|
|
continue;
|
|
}
|
|
while (true) {
|
|
face_id = corner_id / 3;
|
|
is_face_visited_[face_id] = true;
|
|
vert_id = CornerToVert(curr_att_dec, corner_id);
|
|
if (!is_vertex_visited_[vert_id]) {
|
|
on_seam = IsOnBoundary(curr_att_dec, vert_id);
|
|
pos_vert_id = CornerToVert(0, corner_id);
|
|
on_boundary = (on_seam) ? on_seam : IsOnPositionBoundary(pos_vert_id);
|
|
is_vertex_visited_[vert_id] = true;
|
|
OnNewVertexVisited(vert_id, corner_id);
|
|
if (!on_boundary) {
|
|
corner_id = GetRightCorner(corner_id);
|
|
continue;
|
|
}
|
|
}
|
|
next_c = Next(corner_id);
|
|
right_seam = IsCornerOppositeToSeamEdge(next_c);
|
|
right_corner_id = (right_seam) ? -1 : GetRightCorner(corner_id);
|
|
prev_c = Previous(corner_id);
|
|
left_seam = IsCornerOppositeToSeamEdge(prev_c);
|
|
left_corner_id = (left_seam) ? -1 : GetLeftCorner(corner_id);
|
|
right_face_id = right_corner_id < 0 ? -1 : right_corner_id / 3;
|
|
left_face_id = left_corner_id < 0 ? -1 : left_corner_id / 3;
|
|
if (IsFaceVisited(left_face_id)) {
|
|
corner_traversal_stack_.pop_back();
|
|
break;
|
|
} else {
|
|
corner_id = left_corner_id;
|
|
}
|
|
} else {
|
|
if (IsFaceVisited(left_face_id)) {
|
|
corner_id = right_corner_id;
|
|
} else {
|
|
corner_traversal_stack_.back() = left_corner_id;
|
|
corner_traversal_stack_.push_back(right_corner_id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|