Fixed a bug in the precomputation of the data for bucket fill that was triggering assert in TriangleSelector::neighbor_child().

This commit is contained in:
Lukáš Hejl 2021-12-03 07:50:15 +01:00
parent 60b8a8245c
commit 36b014a8dd
2 changed files with 26 additions and 47 deletions

View File

@ -358,8 +358,9 @@ void TriangleSelector::precompute_all_neighbors_recursive(const int facet_idx, c
assert(tr->children[i] < int(m_triangles.size()));
// Recursion, deep first search over the children of this triangle.
// All children of this triangle were created by splitting a single source triangle of the original mesh.
this->precompute_all_neighbors_recursive(tr->children[i], this->child_neighbors(*tr, neighbors, i),
this->child_neighbors_propagated(*tr, neighbors_propagated, i), neighbors_out,
const Vec3i child_neighbors = this->child_neighbors(*tr, neighbors, i);
this->precompute_all_neighbors_recursive(tr->children[i], child_neighbors,
this->child_neighbors_propagated(*tr, neighbors_propagated, i, child_neighbors), neighbors_out,
neighbors_propagated_out);
}
}
@ -784,33 +785,29 @@ Vec3i TriangleSelector::child_neighbors(const Triangle &tr, const Vec3i &neighbo
// Return neighbors of the ith child of a triangle given neighbors of the triangle.
// If such a neighbor doesn't exist, return the neighbor from the previous depth.
Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec3i &neighbors, int child_idx) const
Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec3i &neighbors_propagated, int child_idx, const Vec3i &child_neighbors) const
{
int i = tr.special_side();
int j = next_idx_modulo(i, 3);
int k = next_idx_modulo(j, 3);
Vec3i out;
auto replace_if_not_exists = [&out](int index_to_replace, int neighbor) {
Vec3i out = child_neighbors;
auto replace_if_not_exists = [&out, &neighbors_propagated](int index_to_replace, int neighbor_idx) {
if (out(index_to_replace) == -1)
out(index_to_replace) = neighbor;
out(index_to_replace) = neighbors_propagated(neighbor_idx);
};
switch (tr.number_of_split_sides()) {
case 1:
switch (child_idx) {
case 0:
out(0) = neighbors(i);
out(1) = this->neighbor_child(neighbors(j), tr.verts_idxs[k], tr.verts_idxs[j], Partition::Second);
replace_if_not_exists(1, neighbors(j));
out(2) = tr.children[1];
replace_if_not_exists(0, i);
replace_if_not_exists(1, j);
break;
default:
assert(child_idx == 1);
out(0) = this->neighbor_child(neighbors(j), tr.verts_idxs[k], tr.verts_idxs[j], Partition::First);
replace_if_not_exists(0, neighbors(j));
out(1) = neighbors(k);
out(2) = tr.children[0];
replace_if_not_exists(0, j);
replace_if_not_exists(1, k);
break;
}
break;
@ -818,25 +815,17 @@ Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec
case 2:
switch (child_idx) {
case 0:
out(0) = this->neighbor_child(neighbors(i), tr.verts_idxs[j], tr.verts_idxs[i], Partition::Second);
replace_if_not_exists(0, neighbors(i));
out(1) = tr.children[1];
out(2) = this->neighbor_child(neighbors(k), tr.verts_idxs[i], tr.verts_idxs[k], Partition::First);
replace_if_not_exists(2, neighbors(k));
replace_if_not_exists(0, i);
replace_if_not_exists(2, k);
break;
case 1:
assert(child_idx == 1);
out(0) = this->neighbor_child(neighbors(i), tr.verts_idxs[j], tr.verts_idxs[i], Partition::First);
replace_if_not_exists(0, neighbors(i));
out(1) = tr.children[2];
out(2) = tr.children[0];
replace_if_not_exists(0, i);
break;
default:
assert(child_idx == 2);
out(0) = neighbors(j);
out(1) = this->neighbor_child(neighbors(k), tr.verts_idxs[i], tr.verts_idxs[k], Partition::Second);
replace_if_not_exists(1, neighbors(k));
out(2) = tr.children[1];
replace_if_not_exists(0, j);
replace_if_not_exists(1, k);
break;
}
break;
@ -845,31 +834,19 @@ Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec
assert(tr.special_side() == 0);
switch (child_idx) {
case 0:
out(0) = this->neighbor_child(neighbors(0), tr.verts_idxs[1], tr.verts_idxs[0], Partition::Second);
replace_if_not_exists(0, neighbors(0));
out(1) = tr.children[3];
out(2) = this->neighbor_child(neighbors(2), tr.verts_idxs[0], tr.verts_idxs[2], Partition::First);
replace_if_not_exists(2, neighbors(2));
replace_if_not_exists(0, 0);
replace_if_not_exists(2, 2);
break;
case 1:
out(0) = this->neighbor_child(neighbors(0), tr.verts_idxs[1], tr.verts_idxs[0], Partition::First);
replace_if_not_exists(0, neighbors(0));
out(1) = this->neighbor_child(neighbors(1), tr.verts_idxs[2], tr.verts_idxs[1], Partition::Second);
replace_if_not_exists(1, neighbors(1));
out(2) = tr.children[3];
replace_if_not_exists(0, 0);
replace_if_not_exists(1, 1);
break;
case 2:
out(0) = this->neighbor_child(neighbors(1), tr.verts_idxs[2], tr.verts_idxs[1], Partition::First);
replace_if_not_exists(0, neighbors(1));
out(1) = this->neighbor_child(neighbors(2), tr.verts_idxs[0], tr.verts_idxs[2], Partition::Second);
replace_if_not_exists(1, neighbors(2));
out(2) = tr.children[3];
replace_if_not_exists(0, 1);
replace_if_not_exists(1, 2);
break;
default:
assert(child_idx == 3);
out(0) = tr.children[1];
out(1) = tr.children[2];
out(2) = tr.children[0];
break;
}
break;
@ -1527,7 +1504,9 @@ void TriangleSelector::get_seed_fill_contour_recursive(const int facet_idx, cons
assert(tr->children[i] < int(m_triangles.size()));
// Recursion, deep first search over the children of this triangle.
// All children of this triangle were created by splitting a single source triangle of the original mesh.
this->get_seed_fill_contour_recursive(tr->children[i], this->child_neighbors(*tr, neighbors, i), this->child_neighbors_propagated(*tr, neighbors_propagated, i), edges_out);
const Vec3i child_neighbors = this->child_neighbors(*tr, neighbors, i);
this->get_seed_fill_contour_recursive(tr->children[i], child_neighbors,
this->child_neighbors_propagated(*tr, neighbors_propagated, i, child_neighbors), edges_out);
}
}
} else if (tr->is_selected_by_seed_fill()) {

View File

@ -349,7 +349,7 @@ private:
int push_triangle(int a, int b, int c, int source_triangle, EnforcerBlockerType state = EnforcerBlockerType{0});
void perform_split(int facet_idx, const Vec3i &neighbors, EnforcerBlockerType old_state);
Vec3i child_neighbors(const Triangle &tr, const Vec3i &neighbors, int child_idx) const;
Vec3i child_neighbors_propagated(const Triangle &tr, const Vec3i &neighbors, int child_idx) const;
Vec3i child_neighbors_propagated(const Triangle &tr, const Vec3i &neighbors_propagated, int child_idx, const Vec3i &child_neighbors) const;
// Return child of itriangle at a CCW oriented side (vertexi, vertexj), either first or 2nd part.
// If itriangle == -1 or if the side sharing (vertexi, vertexj) is not split, return -1.
enum class Partition {