Revision: 44090
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=44090
Author:   campbellbarton
Date:     2012-02-13 14:37:07 +0000 (Mon, 13 Feb 2012)
Log Message:
-----------
new bmesh tool - limited dissolve.

This is a kind of simplification/cleanup tool which joins adjacent faces and 
edges based on the angle.

I've written this as an exercise (since I havnt written a bmesh operator 
before), and because quite a few users were asking for the dissolve operator to 
be extended, but I think this kind of functionality needs its own operator.

access from specials menu and mesh menu.

notes
* this exposed a bug in angle_v3v3v3(). will merge fix into trunk after release.
* added utility function BM_vert_edge_angle(), to get the angle between 2 
connecting edges of a vert.

Modified Paths:
--------------
    branches/bmesh/blender/release/scripts/startup/bl_ui/space_view3d.py
    branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c
    branches/bmesh/blender/source/blender/bmesh/bmesh_queries.h
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_opdefines.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_operators_private.h
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_queries.c
    branches/bmesh/blender/source/blender/bmesh/operators/bmo_dissolve.c
    branches/bmesh/blender/source/blender/editors/mesh/bmesh_tools.c
    branches/bmesh/blender/source/blender/editors/mesh/mesh_intern.h
    branches/bmesh/blender/source/blender/editors/mesh/mesh_ops.c

Modified: branches/bmesh/blender/release/scripts/startup/bl_ui/space_view3d.py
===================================================================
--- branches/bmesh/blender/release/scripts/startup/bl_ui/space_view3d.py        
2012-02-13 13:23:23 UTC (rev 44089)
+++ branches/bmesh/blender/release/scripts/startup/bl_ui/space_view3d.py        
2012-02-13 14:37:07 UTC (rev 44090)
@@ -1476,6 +1476,7 @@
 
         layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude 
Region")
         layout.operator("view3d.edit_mesh_extrude_individual_move", 
text="Extrude Individual")
+        layout.operator("mesh.dissolve_limited")  # BMESH ONLY
         layout.operator("mesh.duplicate_move")
         layout.operator("mesh.delete", text="Delete...")
 
@@ -1511,6 +1512,7 @@
         """
         layout.operator("mesh.merge", text="Merge...")
         layout.operator("mesh.remove_doubles")
+        layout.operator("mesh.dissolve_limited")  # BMESH ONLY
         layout.operator("mesh.hide", text="Hide")
         layout.operator("mesh.reveal", text="Reveal")
         layout.operator("mesh.select_all").action = 'INVERT'

Modified: branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c
===================================================================
--- branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c  
2012-02-13 13:23:23 UTC (rev 44089)
+++ branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c  
2012-02-13 14:37:07 UTC (rev 44090)
@@ -118,7 +118,7 @@
 {
        float vec1[3], vec2[3];
 
-       sub_v3_v3v3(vec1, v2, v1);
+       sub_v3_v3v3(vec1, v1, v2); /* BMESH_TODO!!! merge this line into trunk, 
cant now, too close to release - campbell */
        sub_v3_v3v3(vec2, v2, v3);
        normalize_v3(vec1);
        normalize_v3(vec2);

Modified: branches/bmesh/blender/source/blender/bmesh/bmesh_queries.h
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/bmesh_queries.h 2012-02-13 
13:23:23 UTC (rev 44089)
+++ branches/bmesh/blender/source/blender/bmesh/bmesh_queries.h 2012-02-13 
14:37:07 UTC (rev 44090)
@@ -88,6 +88,10 @@
  * exactly two faces sharing the edge.*/
 float BM_edge_face_angle(struct BMesh *bm, struct BMEdge *e);
 
+/* returns angle of two faces surrounding edges.  note there must be
+ * exactly two edges sharing the vertex.*/
+float BM_vert_edge_angle(struct BMesh *bm, struct BMVert *v);
+
 /* checks overlapping of existing faces with the verts in varr. */
 int BM_face_exists_overlap(struct BMesh *bm, struct BMVert **varr, int len, 
struct BMFace **existface);
 

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_opdefines.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_opdefines.c        
2012-02-13 13:23:23 UTC (rev 44089)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_opdefines.c        
2012-02-13 14:37:07 UTC (rev 44090)
@@ -659,6 +659,15 @@
        BMO_OP_FLAG_UNTAN_MULTIRES
 };
 
+static BMOpDefine def_dissolvelimitop = {
+       "dissolvelimit",
+       {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */
+        {BMO_OP_SLOT_ELEMENT_BUF, "verts"},
+        {BMO_OP_SLOT_ELEMENT_BUF, "edges"},
+        {0} /* null-terminating sentine */},
+       dissolvelimit_exec,
+       BMO_OP_FLAG_UNTAN_MULTIRES
+};
 
 static BMOpDefine def_triangop = {
        "triangulate",
@@ -1075,6 +1084,7 @@
        &def_dissolveedgessop,
        &def_dissolveedgeloopsop,
        &def_dissolvevertsop,
+    &def_dissolvelimitop,
        &def_extrudefaceregion,
        &def_connectverts,
        //&def_makeprim,

Modified: 
branches/bmesh/blender/source/blender/bmesh/intern/bmesh_operators_private.h
===================================================================
--- 
branches/bmesh/blender/source/blender/bmesh/intern/bmesh_operators_private.h    
    2012-02-13 13:23:23 UTC (rev 44089)
+++ 
branches/bmesh/blender/source/blender/bmesh/intern/bmesh_operators_private.h    
    2012-02-13 14:37:07 UTC (rev 44090)
@@ -43,6 +43,7 @@
 void triangulate_exec(BMesh *bmesh, BMOperator *op);
 void dissolvefaces_exec(BMesh *bmesh, BMOperator *op);
 void dissolveverts_exec(BMesh *bmesh, BMOperator *op);
+void dissolvelimit_exec(BMesh *bmesh, BMOperator *op);
 void bmesh_make_fgons_exec(BMesh *bmesh, BMOperator *op);
 void extrude_edge_context_exec(BMesh *bm, BMOperator *op);
 void connectverts_exec(BMesh *bm, BMOperator *op);

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_queries.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_queries.c  
2012-02-13 13:23:23 UTC (rev 44089)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_queries.c  
2012-02-13 14:37:07 UTC (rev 44090)
@@ -517,11 +517,11 @@
        }
 }
 
-/**
+/*
  *                     BMESH FACE ANGLE
  *
- *  Calculates the angle between two faces. Assumes
- *  That face normals are correct.
+ *  Calculates the angle between two faces.
+ *  Assumes the face normals are correct.
  *
  *  Returns -
  *     Float.
@@ -532,7 +532,7 @@
        if (BM_edge_face_count(e) == 2) {
                BMLoop *l1 = e->l;
                BMLoop *l2 = e->l->radial_next;
-               return acosf(dot_v3v3(l1->f->no, l2->f->no));
+               return angle_normalized_v3v3(l1->f->no, l2->f->no);
        }
        else {
                return (float)M_PI / 2.0f; /* acos(0.0) */
@@ -540,6 +540,36 @@
 }
 
 /*
+ *                     BMESH FACE ANGLE
+ *
+ *  Calculates the angle a verts 2 edges.
+ *
+ *  Returns -
+ *     Float.
+ */
+float BM_vert_edge_angle(BMesh *UNUSED(bm), BMVert *v)
+{
+       BMEdge *e1, *e2;
+
+       /* saves BM_vert_edge_count(v) and and edge iterator,
+        * get the edges and count them both at once */
+
+       if ((e1 = v->e) &&
+               (e2 =  bmesh_disk_nextedge(e1, v)) &&
+           /* make sure we come full circle and only have 2 connected edges */
+               (e1 == bmesh_disk_nextedge(e2, v)))
+       {
+               BMVert *v1 = BM_edge_other_vert(e1, v);
+               BMVert *v2 = BM_edge_other_vert(e2, v);
+
+               return angle_v3v3v3(v1->co, v->co, v2->co);
+       }
+       else {
+               return (float)M_PI / 2.0f; /* acos(0.0) */
+       }
+}
+
+/*
  * BMESH EXIST FACE OVERLAPS
  *
  * Given a set of vertices (varr), find out if

Modified: branches/bmesh/blender/source/blender/bmesh/operators/bmo_dissolve.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/operators/bmo_dissolve.c        
2012-02-13 13:23:23 UTC (rev 44089)
+++ branches/bmesh/blender/source/blender/bmesh/operators/bmo_dissolve.c        
2012-02-13 14:37:07 UTC (rev 44090)
@@ -23,6 +23,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_array.h"
+#include "BLI_math.h"
 
 #include "bmesh.h"
 #include "bmesh_private.h"
@@ -397,6 +398,9 @@
 /* this code is for cleaning up two-edged faces, it shall become
  * it's own function one day */
 #if 0
+void dummy_exec(BMesh *bm, BMOperator *op)
+{
+       {
                /* clean up two-edged face */
                /* basic idea is to keep joining 2-edged faces until their
                 * gone.  this however relies on joining two 2-edged faces
@@ -456,5 +460,100 @@
                }
                if (oldlen == len) break;
                oldlen = len;
+       }
+}
 
 #endif
+
+/**/
+typedef struct DissolveElemWeight_t {
+       BMHeader *ele;
+       float weight;
+} DissolveElemWeight_t;
+
+static int dissolve_elem_cmp(const void *a1, const void *a2)
+{
+       const struct DissolveElemWeight_t *d1 = a1, *d2 = a2;
+
+       if      (d1->weight > d2->weight) return  1;
+       else if (d1->weight < d2->weight) return -1;
+       return 0;
+}
+
+void dissolvelimit_exec(BMesh *bm, BMOperator *op)
+{
+       BMOpSlot *einput = BMO_slot_get(op, "edges");
+       BMOpSlot *vinput = BMO_slot_get(op, "verts");
+       const float angle_max = (float)M_PI / 2.0f;
+       const float angle_limit = minf(angle_max, BMO_slot_float_get(op, 
"angle_limit"));
+       DissolveElemWeight_t *weight_elems = MEM_mallocN(MAX2(einput->len, 
vinput->len) *
+                                                        
sizeof(DissolveElemWeight_t), __func__);
+       int i, tot_found;
+
+       /* --- first edges --- */
+
+       /* go through and split edge */
+       for (i = 0, tot_found = 0; i < einput->len; i++) {
+               BMEdge *e = ((BMEdge **)einput->data.p)[i];
+               const float angle = BM_edge_face_angle(bm, e);
+
+               if (angle < angle_limit) {
+                       weight_elems[i].ele = (BMHeader *)e;
+                       weight_elems[i].weight = angle;
+                       tot_found++;
+               }
+               else {
+                       weight_elems[i].ele = NULL;
+                       weight_elems[i].weight = angle_max;
+               }
+       }
+
+       if (tot_found != 0) {
+               qsort(weight_elems, einput->len, sizeof(DissolveElemWeight_t), 
dissolve_elem_cmp);
+
+               for (i = 0; i < tot_found; i++) {
+                       BMEdge *e = (BMEdge *)weight_elems[i].ele;
+                       /* check twice because cumulative effect could disolve 
over angle limit */
+                       if (BM_edge_face_angle(bm, e) < angle_limit) {
+                               BMFace *nf = BM_faces_join_pair(bm, e->l->f,
+                                                               
e->l->radial_next->f,
+                                                               e); /* join 
faces */
+
+                               /* there may be some errors, we dont mind, just 
move on */
+                               if (nf == NULL) {
+                                       BMO_error_clear(bm);
+                               }
+                       }
+               }
+       }
+
+       /* --- second verts --- */
+       for (i = 0, tot_found = 0; i < vinput->len; i++) {
+               BMVert *v = ((BMVert **)vinput->data.p)[i];
+               const float angle = BM_vert_edge_angle(bm, v);
+
+               if (angle < angle_limit) {
+                       weight_elems[i].ele = (BMHeader *)v;
+                       weight_elems[i].weight = angle;
+                       tot_found++;
+               }
+               else {
+                       weight_elems[i].ele = NULL;
+                       weight_elems[i].weight = angle_max;
+               }
+       }
+
+       if (tot_found != 0) {
+               qsort(weight_elems, vinput->len, sizeof(DissolveElemWeight_t), 
dissolve_elem_cmp);
+
+               for (i = 0; i < tot_found; i++) {
+                       BMVert *v = (BMVert *)weight_elems[i].ele;
+                       /* check twice because cumulative effect could disolve 
over angle limit */
+                       if (BM_vert_edge_angle(bm, v) < angle_limit) {
+                               BM_vert_collapse_edges(bm, v->e, v); /* join 
edges */
+                       }
+               }
+       }
+
+       MEM_freeN(weight_elems);
+}

Modified: branches/bmesh/blender/source/blender/editors/mesh/bmesh_tools.c
===================================================================
--- branches/bmesh/blender/source/blender/editors/mesh/bmesh_tools.c    
2012-02-13 13:23:23 UTC (rev 44089)
+++ branches/bmesh/blender/source/blender/editors/mesh/bmesh_tools.c    
2012-02-13 14:37:07 UTC (rev 44090)
@@ -3522,9 +3522,48 @@
        RNA_def_boolean(ot->srna, "vcols", 0, "Compare VCols", "");
        RNA_def_boolean(ot->srna, "sharp", 0, "Compare Sharp", "");
        RNA_def_boolean(ot->srna, "materials", 0, "Compare Materials", "");
+}
 
+static int dissolve_limited_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit = CTX_data_edit_object(C);
+       BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
+       float angle_limit = RNA_float_get(op->ptr, "angle_limit");
+

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to