Fix T69792: Auto-merge split faces creates faces with unrelated wire edges.

This commit is contained in:
Germano Cavalcante 2019-09-12 10:52:03 -03:00
parent 62c820cdaa
commit c168092014
Notes: blender-bot 2023-02-14 11:35:46 +01:00
Referenced by issue #69792, Auto-merge split faces creates faces with unrelated wire edges.
1 changed files with 57 additions and 25 deletions

View File

@ -120,32 +120,35 @@ struct EDBMSplitEdgeData {
};
static bool edbm_vert_pair_share_best_splittable_face_cb(BMFace *f,
BMLoop *UNUSED(l_a),
BMLoop *UNUSED(l_b),
BMLoop *l_a,
BMLoop *l_b,
void *userdata)
{
struct EDBMSplitBestFaceData *data = userdata;
float no[3], min = FLT_MAX, max = -FLT_MAX;
float no[3];
copy_v3_v3(no, f->no);
BMVert *verts[2] = {NULL};
float min = dot_v3v3(l_a->v->co, no);
float max = dot_v3v3(l_b->v->co, no);
if (min > max) {
SWAP(float, min, max);
}
BMVert *v_test = l_b->v;
BMEdge **e_iter = &data->edgenet[0];
for (int i = data->edgenet_len; i--; e_iter++) {
BMIter iter;
BMVert *v;
BM_ITER_ELEM (v, &iter, *e_iter, BM_VERTS_OF_EDGE) {
if (!ELEM(v, verts[0], verts[1])) {
float dot = dot_v3v3(v->co, no);
if (dot < min) {
min = dot;
}
if (dot > max) {
max = dot;
}
}
int verts_len = data->edgenet_len - 1;
for (int i = verts_len; i--; e_iter++) {
v_test = BM_edge_other_vert(*e_iter, v_test);
if (!BM_face_point_inside_test(f, v_test->co)) {
return false;
}
float dot = dot_v3v3(v_test->co, no);
if (dot < min) {
min = dot;
}
if (dot > max) {
max = dot;
}
verts[0] = (*e_iter)->v1;
verts[1] = (*e_iter)->v2;
}
const float test_face_range_on_normal_axis = max - min;
@ -179,10 +182,8 @@ static bool edbm_vert_pair_share_splittable_face_cb(BMFace *UNUSED(f),
return false;
}
static void edbm_automerge_weld_linked_wire_edges_into_linked_faces(BMesh *bm,
BMVert *v,
BMEdge **r_edgenet[],
int *r_edgenet_alloc_len)
static void edbm_automerge_weld_linked_wire_edges_into_linked_faces(
BMesh *bm, BMVert *v, const float epsilon, BMEdge **r_edgenet[], int *r_edgenet_alloc_len)
{
BMEdge **edgenet = *r_edgenet;
int edgenet_alloc_len = *r_edgenet_alloc_len;
@ -206,15 +207,26 @@ static void edbm_automerge_weld_linked_wire_edges_into_linked_faces(BMesh *bm,
BMEdge *e_next = BM_DISK_EDGE_NEXT(e, v_other);
if (e_next == e) {
/* Vert is wire_endpoint */
/* Vert is wire_endpoint. */
edgenet_len = 0;
break;
}
BMEdge *e_test = e_next;
while ((e_test = BM_DISK_EDGE_NEXT(e_test, v_other)) != e) {
if (e_test->l) {
/* Vert is linked to a face. */
goto l_break;
}
}
e = e_next;
}
BMLoop *dummy;
BMFace *best_face;
l_break:
if (edgenet_len == 0) {
/* Nothing to do. */
continue;
@ -236,6 +248,25 @@ static void edbm_automerge_weld_linked_wire_edges_into_linked_faces(BMesh *bm,
BM_vert_pair_shared_face_cb(
v_other, v, true, edbm_vert_pair_share_best_splittable_face_cb, &data, &dummy, &dummy);
if (data.r_best_face) {
float no[3], min = FLT_MAX, max = -FLT_MAX;
copy_v3_v3(no, data.r_best_face->no);
BMVert *v_test;
BMIter f_iter;
BM_ITER_ELEM (v_test, &f_iter, data.r_best_face, BM_VERTS_OF_FACE) {
float dot = dot_v3v3(v_test->co, no);
if (dot < min) {
min = dot;
}
if (dot > max) {
max = dot;
}
}
float range = max - min + 2 * epsilon;
if (range < data.best_face_range_on_normal_axis) {
data.r_best_face = NULL;
}
}
best_face = data.r_best_face;
}
@ -498,7 +529,8 @@ void EDBM_automerge_and_split(Object *obedit,
GHASH_ITER (gh_iter, ghash_targetmap) {
v = BLI_ghashIterator_getValue(&gh_iter);
BLI_assert(BM_elem_flag_test(v, hflag) || hflag == BM_ELEM_TAG);
edbm_automerge_weld_linked_wire_edges_into_linked_faces(bm, v, &edgenet, &edgenet_alloc_len);
edbm_automerge_weld_linked_wire_edges_into_linked_faces(
bm, v, dist, &edgenet, &edgenet_alloc_len);
}
}