Fix an assert trip in boolean tickled by D11272 example.

The face merging code in exact boolean made an assumption that
the tesselated original face was manifold except at the boundaries.
This should be true but sometimes (e.g., if the input faces have
self-intersection, as happens in the example), it is not.
This commit makes face merging tolerant of such a situation.
It might leave some stray edges from triangulation, but it should
only happen if the input is malformed.
Note: the input may be malformed if there were previous booleans
in the stack, since snapping the exact result to float coordinates
is not guaranteed to leave the mesh without defects.
This commit is contained in:
Howard Trickey 2022-07-10 14:50:17 -04:00
parent fad857f473
commit 6543290116
Notes: blender-bot 2023-02-14 08:38:11 +01:00
Referenced by commit 7f4ee97b9e, Revert "Fix an assert trip in boolean tickled by D11272 example."
1 changed files with 28 additions and 4 deletions

View File

@ -2966,6 +2966,11 @@ static std::ostream &operator<<(std::ostream &os, const FaceMergeState &fms)
* \a tris all have the same original face.
* Find the 2d edge/triangle topology for these triangles, but only the ones facing in the
* norm direction, and whether each edge is dissolvable or not.
* If we did the initial triangulation properly, and any Delaunay triangulations of interections
* properly, then each triangle edge should have at most one neighbor.
* However, there can be anonalies. For example, if an input face is self-intersecting, we fall
* back on the floating poing polyfill triangulation, which, after which all bets are off.
* Hence, try to be tolerant of such unexpected topology.
*/
static void init_face_merge_state(FaceMergeState *fms,
const Vector<int> &tris,
@ -3053,16 +3058,35 @@ static void init_face_merge_state(FaceMergeState *fms,
std::cout << "me.v1 == mf.vert[i] so set edge[" << me_index << "].left_face = " << f
<< "\n";
}
BLI_assert(me.left_face == -1);
fms->edge[me_index].left_face = f;
if (me.left_face != 1) {
/* Unexpected in the normal case: this means more than one triangle shares this
* edge in the same orientation. But be tolerant of this case. By making this
* edge not dissolvable, we'll avoid future problems due to this non-manifold topology.
*/
if (dbg_level > 1) {
std::cout << "me.left_face was already occupied, so triangulation wasn't good\n";
}
me.dissolvable = false;
}
else {
fms->edge[me_index].left_face = f;
}
}
else {
if (dbg_level > 1) {
std::cout << "me.v1 != mf.vert[i] so set edge[" << me_index << "].right_face = " << f
<< "\n";
}
BLI_assert(me.right_face == -1);
fms->edge[me_index].right_face = f;
if (me.right_face != -1) {
/* Unexpected, analogous to the me.left_face != -1 case above. */
if (dbg_level > 1) {
std::cout << "me.right_face was already occupied, so triangulation wasn't good\n";
}
me.dissolvable = false;
}
else {
fms->edge[me_index].right_face = f;
}
}
fms->face[f].edge.append(me_index);
}