Fix T48683: Knife cut creates hole

BM_face_split_edgenet wasn't correctly detecting boundary vertices to walk over,
since vertices may be attached to boundary edges not part of the newly created face.
This commit is contained in:
Campbell Barton 2016-06-21 07:54:46 +10:00
parent ed225d4517
commit a170607578
Notes: blender-bot 2023-02-14 08:06:35 +01:00
Referenced by issue #48683, Knife create a hole in the face cutted.
1 changed files with 57 additions and 5 deletions

View File

@ -97,6 +97,10 @@ static BMLoop *bm_edge_flagged_radial_first(BMEdge *e)
return NULL;
}
/**
* \note Be sure to update #bm_face_split_edgenet_find_loop_pair_exists
* when making changed to edge picking logic.
*/
static bool bm_face_split_edgenet_find_loop_pair(
BMVert *v_init, const float face_normal[3],
BMEdge *e_pair[2])
@ -189,6 +193,58 @@ static bool bm_face_split_edgenet_find_loop_pair(
return true;
}
/**
* A reduced version of #bm_face_split_edgenet_find_loop_pair
* that only checks if it would return true.
*
* \note There is no use in caching resulting edges here,
* since between this check and running #bm_face_split_edgenet_find_loop,
* the selected edges may have had faces attached.
*/
static bool bm_face_split_edgenet_find_loop_pair_exists(
BMVert *v_init)
{
int edges_boundary_len = 0;
int edges_wire_len = 0;
{
BMEdge *e, *e_first;
e = e_first = v_init->e;
do {
if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
const unsigned int count = bm_edge_flagged_radial_count(e);
if (count == 1) {
edges_boundary_len++;
}
else if (count == 0) {
edges_wire_len++;
}
}
} while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first);
}
/* first edge should always be boundary */
if (edges_boundary_len == 0) {
return false;
}
/* attempt one boundary and one wire, or 2 boundary */
if (edges_wire_len == 0) {
if (edges_boundary_len >= 2) {
/* pass */
}
else {
/* one boundary and no wire */
return false;
}
}
else {
/* pass */
}
return true;
}
static bool bm_face_split_edgenet_find_loop_walk(
BMVert *v_init, const float face_normal[3],
/* cache to avoid realloc every time */
@ -450,7 +506,6 @@ bool BM_face_split_edgenet(
}
if (f_new) {
bool l_prev_is_boundary;
BLI_array_append(face_arr, f_new);
copy_v3_v3(f_new->no, f->no);
@ -466,13 +521,10 @@ bool BM_face_split_edgenet(
/* add new verts to keep finding loops for
* (verts between boundary and manifold edges) */
l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
l_prev_is_boundary = (bm_edge_flagged_radial_count(l_iter->prev->e) == 1);
do {
bool l_iter_is_boundary = (bm_edge_flagged_radial_count(l_iter->e) == 1);
if (l_prev_is_boundary != l_iter_is_boundary) {
if (bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) {
STACK_PUSH(vert_queue, l_iter->v);
}
l_prev_is_boundary = l_iter_is_boundary;
} while ((l_iter = l_iter->next) != l_first);
}
}