[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [44090] branches/bmesh/blender: new bmesh tool - limited dissolve.

Campbell Barton ideasman42 at gmail.com
Mon Feb 13 15:37:11 CET 2012


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. @@



More information about the Bf-blender-cvs mailing list