[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