[Bf-blender-cvs] [fe513a5b61c] master: Operator: Add 'use_dissolve_ortho_edges' option for Extrude

Germano Cavalcante noreply at git.blender.org
Wed Apr 15 17:02:11 CEST 2020


Commit: fe513a5b61ca0d8abac08f95b07103510a4626cb
Author: Germano Cavalcante
Date:   Wed Apr 15 11:54:41 2020 -0300
Branches: master
https://developer.blender.org/rBfe513a5b61ca0d8abac08f95b07103510a4626cb

Operator: Add 'use_dissolve_ortho_edges' option for Extrude

===================================================================

M	source/blender/bmesh/intern/bmesh_opdefines.c
M	source/blender/bmesh/operators/bmo_extrude.c
M	source/blender/editors/mesh/editmesh_extrude.c

===================================================================

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);



More information about the Bf-blender-cvs mailing list