diff options
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.c | 60 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.h | 3 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 11 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 2 |
4 files changed, 53 insertions, 23 deletions
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index dc42d86d800..09a39c05565 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1395,32 +1395,49 @@ void BM_lnorspace_err(BMesh *bm) static void bm_loop_normal_mark_indiv_do_loop(BMLoop *l, BLI_bitmap *loops, MLoopNorSpaceArray *lnor_spacearr, - int *totloopsel) + int *totloopsel, + const bool do_all_loops_of_vert) { if (l != NULL) { const int l_idx = BM_elem_index_get(l); - if (!BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) { + if (!BLI_BITMAP_TEST(loops, l_idx)) { /* If vert and face selected share a loop, mark it for editing. */ BLI_BITMAP_ENABLE(loops, l_idx); (*totloopsel)++; - /* Mark all loops in same loop normal space (aka smooth fan). */ - if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) { - for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) { - const int lfan_idx = BM_elem_index_get((BMLoop *)node->link); + if (do_all_loops_of_vert) { + /* If required, also mark all loops shared by that vertex. + * This is needed when loop spaces may change + * (i.e. when some faces or edges might change of smooth/sharp status). */ + BMIter liter; + BMLoop *lfan; + BM_ITER_ELEM (lfan, &liter, l->v, BM_LOOPS_OF_VERT) { + const int lfan_idx = BM_elem_index_get(lfan); if (!BLI_BITMAP_TEST(loops, lfan_idx)) { BLI_BITMAP_ENABLE(loops, lfan_idx); (*totloopsel)++; } } } + else { + /* Mark all loops in same loop normal space (aka smooth fan). */ + if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) { + for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) { + const int lfan_idx = BM_elem_index_get((BMLoop *)node->link); + if (!BLI_BITMAP_TEST(loops, lfan_idx)) { + BLI_BITMAP_ENABLE(loops, lfan_idx); + (*totloopsel)++; + } + } + } + } } } } /* Mark the individual clnors to be edited, if multiple selection methods are used. */ -static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) +static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops, const bool do_all_loops_of_vert) { BMEditSelection *ese, *ese_prev; int totloopsel = 0; @@ -1451,19 +1468,22 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) BM_face_vert_share_loop((BMFace *)ese->ele, (BMVert *)ese_prev->ele), loops, bm->lnor_spacearr, - &totloopsel); + &totloopsel, + do_all_loops_of_vert); } else if (ese_prev->htype == BM_EDGE) { BMEdge *e = (BMEdge *)ese_prev->ele; bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v1), loops, bm->lnor_spacearr, - &totloopsel); + &totloopsel, + do_all_loops_of_vert); bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v2), loops, bm->lnor_spacearr, - &totloopsel); + &totloopsel, + do_all_loops_of_vert); } } } @@ -1478,7 +1498,8 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); + bm_loop_normal_mark_indiv_do_loop( + l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); } } } @@ -1491,15 +1512,18 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); + bm_loop_normal_mark_indiv_do_loop( + l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects * *two* loops in each of its faces. We have to find the other one too. */ if (BM_vert_in_edge(e, l->next->v)) { - bm_loop_normal_mark_indiv_do_loop(l->next, loops, bm->lnor_spacearr, &totloopsel); + bm_loop_normal_mark_indiv_do_loop( + l->next, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); } else { BLI_assert(BM_vert_in_edge(e, l->prev->v)); - bm_loop_normal_mark_indiv_do_loop(l->prev, loops, bm->lnor_spacearr, &totloopsel); + bm_loop_normal_mark_indiv_do_loop( + l->prev, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); } } } @@ -1513,7 +1537,8 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); + bm_loop_normal_mark_indiv_do_loop( + l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); } } } @@ -1546,7 +1571,8 @@ static void loop_normal_editdata_init( lnor_ed->loc = v->co; } -BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm) +BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm, + const bool do_all_loops_of_vert) { BMLoop *l; BMVert *v; @@ -1570,7 +1596,7 @@ BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm) BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__); /* This function define loop normals to edit, based on selection modes and history. */ - totloopsel = bm_loop_normal_mark_indiv(bm, loops); + totloopsel = bm_loop_normal_mark_indiv(bm, loops, do_all_loops_of_vert); if (totloopsel) { BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN( diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index d0cf50a7894..83575552acc 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -67,7 +67,8 @@ void BM_lnorspace_err(BMesh *bm); #endif /* Loop Generics */ -struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm); +struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm, + const bool do_all_loops_of_vert); void BM_loop_normal_editdata_array_free(struct BMLoopNorEditDataArray *lnors_ed_arr); int BM_total_loop_select(BMesh *bm); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index c4216d81317..c196a66332d 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -7689,7 +7689,7 @@ static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); - BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); op->customdata = lnors_ed_arr; @@ -8246,7 +8246,10 @@ static int normals_split_merge(bContext *C, const bool do_merge) BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); - BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL; + /* Note that we need temp lnor editing data for all loops of all affected vertices, since by + * setting some faces/edges as smooth we are going to change clnors spaces... See also T65809. */ + BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm, true) : + NULL; mesh_set_smooth_faces(em, do_merge); @@ -8573,7 +8576,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); - BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; float *normal_vector = scene->toolsettings->normal_vector; @@ -8867,7 +8870,7 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op) BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); - BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 9019b21997f..5b3f7d85b43 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4784,7 +4784,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm) { - BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false); // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; tc->custom.mode.data = lnors_ed_arr; |