diff options
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 1 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_extrude.c | 65 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_extrude.c | 18 |
3 files changed, 80 insertions, 4 deletions
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 4fa7bf64834..45666a21a2c 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1046,6 +1046,7 @@ static BMOpDefine bmo_extrude_face_region_def = { {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */ + {"use_dissolve_ortho_edges", BMO_OP_SLOT_BOOL}, /* Dissolve edges whose faces form a flat surface. */ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 7a7f4a14db3..3c63f4a60d6 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -39,6 +39,7 @@ enum { EXT_INPUT = 1, EXT_KEEP = 2, EXT_DEL = 4, + EXT_TAG = 8, }; #define VERT_MARK 1 @@ -335,6 +336,8 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in, "use_normal_from_adjacent"); + const bool use_dissolve_ortho_edges = BMO_slot_bool_get(op->slots_in, + "use_dissolve_ortho_edges"); /* initialize our sub-operators */ BMO_op_initf(bm, @@ -442,6 +445,24 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } + BMVert **dissolve_verts = NULL; + int dissolve_verts_len = 0; + float average_normal[3]; + if (use_dissolve_ortho_edges) { + /* Calc average normal. */ + zero_v3(average_normal); + BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) { + add_v3_v3(average_normal, f->no); + } + if (normalize_v3(average_normal) == 0.0f) { + average_normal[2] = 1.0f; + } + + /* Allocate array to store possible vertices that will be dissolved. */ + int boundary_verts_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out"); + dissolve_verts = MEM_mallocN((size_t)boundary_verts_len * sizeof(*dissolve_verts), __func__); + } + BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out"); slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); @@ -483,6 +504,16 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } + BMFace *join_face = NULL; + if (use_dissolve_ortho_edges) { + if (BM_edge_is_boundary(e)) { + join_face = e->l->f; + if (fabs(dot_v3v3(average_normal, join_face->no)) > 0.0001f) { + join_face = NULL; + } + } + } + bool edge_normal_flip; if (use_normal_from_adjacent == false) { /* Orient loop to give same normal as a loop of 'e_new' @@ -541,7 +572,22 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); #endif - bm_extrude_copy_face_loop_attributes(bm, f); + if (join_face) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + if (!BMO_elem_flag_test(bm, v1, EXT_TAG)) { + BMO_elem_flag_enable(bm, v1, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v1; + } + if (!BMO_elem_flag_test(bm, v2, EXT_TAG)) { + BMO_elem_flag_enable(bm, v2, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v2; + } + bmesh_kernel_join_face_kill_edge(bm, join_face, f, e); + } + else { + bm_extrude_copy_face_loop_attributes(bm, f); + } } /* link isolated vert */ @@ -559,6 +605,23 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE); } + if (dissolve_verts) { + BMVert **v_iter = &dissolve_verts[0]; + for (int i = dissolve_verts_len; i--; v_iter++) { + v = *v_iter; + e = v->e; + BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); + if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) { + /* Lose edge or BMVert is edge pair. */ + BM_edge_collapse(bm, e, v, true, false); + } + else { + BLI_assert(!BM_vert_is_edge_pair(v)); + } + } + MEM_freeN(dissolve_verts); + } + /* cleanup */ if (delorig) { BMO_op_finish(bm, &delop); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 23f622ac359..bf6c5a2f829 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -226,6 +226,7 @@ static bool edbm_extrude_ex(Object *obedit, char htype, const char hflag, const bool use_normal_flip, + const bool use_dissolve_ortho_edges, const bool use_mirror, const bool use_select_history) { @@ -241,6 +242,7 @@ static bool edbm_extrude_ex(Object *obedit, BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); BMO_slot_bool_set(extop.slots_in, "use_normal_flip", use_normal_flip); + BMO_slot_bool_set(extop.slots_in, "use_dissolve_ortho_edges", use_dissolve_ortho_edges); BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history); BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag); @@ -312,7 +314,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) mul_v3_m3v3(offset_local, tmat, offset); for (int a = 0; a < steps; a++) { - edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, true); + edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false, true); BMO_op_callf( em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT); } @@ -359,6 +361,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) { const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip"); + const bool use_dissolve_ortho_edges = RNA_boolean_get(op->ptr, "use_dissolve_ortho_edges"); const char htype = edbm_extrude_htype_from_em_select(em); enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr; bool changed = false; @@ -401,7 +404,14 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) case NONE: return false; case ELEM_FLAG: - changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true); + changed = edbm_extrude_ex(obedit, + em, + htype, + BM_ELEM_SELECT, + use_normal_flip, + use_dissolve_ortho_edges, + true, + true); break; case VERT_ONLY: changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT); @@ -465,6 +475,7 @@ void MESH_OT_extrude_region(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -519,6 +530,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -840,7 +852,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w } } - edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, true, true); + edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, false, true, true); EDBM_op_callf( vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat); EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, ofs); |