[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [40492] branches/bmesh/blender/source/ blender: Solidify bmesh op and edit mode tool

Andrew Wiggin ender79bl at gmail.com
Fri Sep 23 14:06:48 CEST 2011


Revision: 40492
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=40492
Author:   ender79
Date:     2011-09-23 12:06:47 +0000 (Fri, 23 Sep 2011)
Log Message:
-----------
Solidify bmesh op and edit mode tool

Modified Paths:
--------------
    branches/bmesh/blender/source/blender/blenlib/BLI_math_vector.h
    branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c
    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/operators/extrudeops.c
    branches/bmesh/blender/source/blender/editors/mesh/bmesh_tools.c

Modified: branches/bmesh/blender/source/blender/blenlib/BLI_math_vector.h
===================================================================
--- branches/bmesh/blender/source/blender/blenlib/BLI_math_vector.h	2011-09-23 11:47:53 UTC (rev 40491)
+++ branches/bmesh/blender/source/blender/blenlib/BLI_math_vector.h	2011-09-23 12:06:47 UTC (rev 40492)
@@ -165,6 +165,7 @@
 float angle_normalized_v3v3(const float v1[3], const float v2[3]);
 void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3]);
 void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
+void angle_poly_v3(float* angles, const float* verts[3], int len);
 
 /********************************* Geometry **********************************/
 

Modified: branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c
===================================================================
--- branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c	2011-09-23 11:47:53 UTC (rev 40491)
+++ branches/bmesh/blender/source/blender/blenlib/intern/math_vector.c	2011-09-23 12:06:47 UTC (rev 40492)
@@ -241,6 +241,20 @@
 	angles[3]= (float)M_PI - angle_normalized_v3v3(ed4, ed1);
 }
 
+void angle_poly_v3(float *angles, const float *verts[3], int len)
+{
+	int i;
+	float vec[3][3];
+
+	sub_v3_v3v3(vec[2], verts[len-1], verts[0]);
+	normalize_v3(vec[2]);
+	for (i = 0; i < len; i++) {
+		sub_v3_v3v3(vec[i%3], verts[i%len], verts[(i+1)%len]);
+		normalize_v3(vec[i%3]);
+		angles[i] = (float)M_PI - angle_normalized_v3v3(vec[(i+2)%3], vec[i%3]);
+	}
+}
+
 /********************************* Geometry **********************************/
 
 /* Project v1 on v2 */

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_opdefines.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2011-09-23 11:47:53 UTC (rev 40491)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2011-09-23 12:06:47 UTC (rev 40492)
@@ -593,6 +593,7 @@
 	"extrudefaceregion",
 	{{BMOP_OPSLOT_ELEMENT_BUF, "edgefacein"},
 	{BMOP_OPSLOT_MAPPING, "exclude"},
+	{BMOP_OPSLOT_INT, "alwayskeeporig"},
 	{BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
 	{0} /*null-terminating sentinel*/},
 	extrude_edge_context_exec,
@@ -1021,6 +1022,21 @@
 	BMOP_UNTAN_MULTIRES
 };
 
+/*
+  Solidify
+
+  Turns a mesh into a shell with thickness
+*/
+static BMOpDefine def_solidify = {
+	"solidify",
+	{{BMOP_OPSLOT_ELEMENT_BUF, "geom"},
+	{BMOP_OPSLOT_FLT, "thickness"},
+	{BMOP_OPSLOT_ELEMENT_BUF, "geomout"},
+	{0}},
+	bmesh_solidify_face_region_exec,
+	0
+};
+
 BMOpDefine *opdefines[] = {
 	&def_splitop,
 	&def_spinop,
@@ -1086,6 +1102,7 @@
 	&def_beautify_fill,
 	&def_triangle_fill,
 	&def_bridge_loops,
+	&def_solidify,
 };
 
 int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_operators_private.h
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_operators_private.h	2011-09-23 11:47:53 UTC (rev 40491)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_operators_private.h	2011-09-23 12:06:47 UTC (rev 40492)
@@ -74,5 +74,6 @@
 void bmesh_triangle_fill_exec(BMesh *bm, BMOperator *op);
 void bmesh_create_circle_exec(BMesh *bm, BMOperator *op);
 void bmesh_bridge_loops_exec(BMesh *bm, BMOperator *op);
+void bmesh_solidify_face_region_exec(BMesh *bm, BMOperator *op);
 
 #endif

Modified: branches/bmesh/blender/source/blender/bmesh/operators/extrudeops.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/operators/extrudeops.c	2011-09-23 11:47:53 UTC (rev 40491)
+++ branches/bmesh/blender/source/blender/bmesh/operators/extrudeops.c	2011-09-23 12:06:47 UTC (rev 40492)
@@ -17,10 +17,14 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define EXT_INPUT	1
-#define EXT_KEEP	2
-#define EXT_DEL		4
+#define EXT_INPUT 1
+#define EXT_KEEP  2
+#define EXT_DEL   4
 
+#define VERT_NONMAN 1
+#define EDGE_NONMAN 1
+#define FACE_MARK 1
+
 void bmesh_extrude_face_indiv_exec(BMesh *bm, BMOperator *op)
 {
 	BMOIter siter;
@@ -179,21 +183,23 @@
 	BMO_Flag_Buffer(bm, op, "edgefacein", EXT_INPUT, BM_EDGE|BM_FACE);
 	
 	/*if one flagged face is bordered by an unflagged face, then we delete
-	  original geometry.*/
-	BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
-		if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue;
+	  original geometry unless caller explicitly asked to keep it. */
+	if (!BMO_Get_Int(op, "alwayskeeporig")) {
+		BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+			if (!BMO_TestFlag(bm, e, EXT_INPUT)) continue;
 
-		found = 0;
-		f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e);
-		for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) {
-			if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
-				found = 1;
-				delorig = 1;
-				break;
+			found = 0;
+			f = BMIter_New(&fiter, bm, BM_FACES_OF_EDGE, e);
+			for (rlen=0; f; f=BMIter_Step(&fiter), rlen++) {
+				if (!BMO_TestFlag(bm, f, EXT_INPUT)) {
+					found = 1;
+					delorig = 1;
+					break;
+				}
 			}
+		
+			if (!found && (rlen > 1)) BMO_SetFlag(bm, e, EXT_DEL);
 		}
-		
-		if (!found && (rlen > 1)) BMO_SetFlag(bm, e, EXT_DEL);
 	}
 
 	/*calculate verts to delete*/
@@ -223,9 +229,12 @@
 		if (BMO_TestFlag(bm, f, EXT_INPUT))
 			BMO_SetFlag(bm, f, EXT_DEL);
 	}
-	if (delorig) BMO_InitOpf(bm, &delop, "del geom=%fvef context=%d", 
-	                         EXT_DEL, DEL_ONLYTAGGED);
 
+	if (delorig) {
+		BMO_InitOpf(bm, &delop, "del geom=%fvef context=%d", 
+		            EXT_DEL, DEL_ONLYTAGGED);
+	}
+
 	BMO_CopySlot(op, &dupeop, "edgefacein", "geom");
 	BMO_Exec_Op(bm, &dupeop);
 
@@ -321,3 +330,181 @@
 	if (delorig) BMO_Finish_Op(bm, &delop);
 	BMO_Finish_Op(bm, &dupeop);
 }
+
+/*
+ *  Compute higher-quality vertex normals used by solidify.
+ *  Note that this will not work for non-manifold regions.
+ *
+ */
+static void calc_solidify_normals(BMesh *bm)
+{
+	BMIter viter, eiter, fiter;
+	BMVert *v;
+	BMEdge *e;
+	BMLoop *l;
+	BMFace *f, *f1, *f2;
+	float edge_normal[3];
+
+	BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, NULL) {
+		/* Mark the non-manifold edges and the vertices they connect */
+		if (BM_Nonmanifold_Edge(bm, e)) {
+			BMO_SetFlag(bm, e, EDGE_NONMAN);
+			BMO_SetFlag(bm, e->v1, VERT_NONMAN);
+			BMO_SetFlag(bm, e->v2, VERT_NONMAN);
+		}
+	}
+
+	BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
+		BM_SetIndex(v, 0);
+		zero_v3(v->no);
+	}
+
+	BM_ITER(e, &eiter, bm, BM_EDGES_OF_MESH, NULL) {
+		float angle;
+
+		if (BMO_TestFlag(bm, e, EDGE_NONMAN)) {
+			continue;
+		}
+
+		l = e->l;
+		f1 = l->f;
+		f2 = bmesh_radial_nextloop(l)->f;
+
+		angle = angle_normalized_v3v3(f1->no, f2->no);
+
+		if (f1 != f2) {
+			if (angle > 0.0f) {
+				/* two faces using this edge, calculate the edges normal
+				 * using the angle between the faces as a weighting */
+				add_v3_v3v3(edge_normal, f1->no, f2->no);
+				normalize_v3(edge_normal);
+				mul_v3_fl(edge_normal, angle);
+			}
+			else {
+				/* can't do anything useful here!
+				   Set the face index for a vert incase it gets a zero normal */
+				BM_SetIndex(e->v1, -1);
+				BM_SetIndex(e->v2, -1);
+				continue;
+			}
+		}
+		else {
+			/* only one face attached to that edge */
+			/* an edge without another attached- the weight on this is
+			 * undefined, M_PI/2 is 90d in radians and that seems good enough */
+			copy_v3_v3(edge_normal, f1->no);
+			mul_v3_fl(edge_normal, M_PI/2);
+		}
+
+		add_v3_v3(e->v1->no, edge_normal);
+		add_v3_v3(e->v2->no, edge_normal);
+	}
+
+	/* normalize accumulated vertex normals*/
+	BM_ITER(v, &viter, bm, BM_VERTS_OF_MESH, NULL) {
+		if (BMO_TestFlag(bm, v, VERT_NONMAN)) {
+			/* use standard normals for vertices connected to non-manifold
+			   edges */
+			BM_Vert_UpdateNormal(bm, v);
+		}
+		else if (normalize_v3(v->no) == 0.0f && BM_GetIndex(v) < 0) {
+			/* exceptional case, totally flat. use the normal
+			   of any face around the vertex */
+			f = BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
+			if (f) {
+				copy_v3_v3(v->no, f->no);
+			}
+		}	
+	}
+}
+
+static void solidify_add_thickness(BMesh *bm, float dist)
+{
+	BMFace *f;
+	BMVert *v;
+	BMLoop *l;
+	BMIter iter, loopIter;
+	float *vert_angles = MEM_callocN(sizeof(float) * bm->totvert * 2, "solidify"); /* 2 in 1 */
+	float *vert_accum = vert_angles + bm->totvert;
+	float angle;
+	int i, index;
+	float maxdist = dist * sqrtf(3.0f);
+
+	/* array for passing verts to angle_poly_v3 */
+	float **verts = NULL;
+	BLI_array_staticdeclare(verts, 16);
+	/* array for receiving angles from angle_poly_v3 */
+	float *angles = NULL;
+	BLI_array_staticdeclare(angles, 16);
+
+	i = 0;
+	BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+		BM_SetIndex(v, i++);
+	}
+
+	BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+		if(!BMO_TestFlag(bm, f, FACE_MARK)) {
+			continue;
+		}
+
+		BM_ITER(l, &loopIter, bm, BM_LOOPS_OF_FACE, f) {
+			BLI_array_append(verts, l->v->co);
+			BLI_array_growone(angles);
+		}
+
+		angle_poly_v3(angles, verts, f->len);
+
+		i = 0;
+		BM_ITER(l, &loopIter, bm, BM_LOOPS_OF_FACE, f) {
+			v = l->v;
+			index = BM_GetIndex(v);
+			angle = angles[i];
+			vert_accum[index] += angle;
+			vert_angles[index] += shell_angle_to_dist(angle_normalized_v3v3(v->no, f->no)) * angle;
+			i++;
+		}
+
+		BLI_array_empty(verts);
+		BLI_array_empty(angles);
+	}
+
+	BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+		index = BM_GetIndex(v);
+		if(vert_accum[index]) { /* zero if unselected */
+			float vdist = MIN2(maxdist, dist * vert_angles[index] / vert_accum[index]);
+			madd_v3_v3fl(v->co, v->no, vdist);
+		}
+	}
+
+	MEM_freeN(vert_angles);
+}
+
+void bmesh_solidify_face_region_exec(BMesh *bm, BMOperator *op)
+{
+	BMOperator extrudeop;
+	BMOperator reverseop;
+	float thickness;
+  
+	thickness = BMO_Get_Float(op, "thickness");
+
+	/* Flip original faces (so the shell is extruded inward) */
+	BMO_Init_Op(&reverseop, "reversefaces");
+	BMO_CopySlot(op, &reverseop, "geom", "faces");
+	BMO_Exec_Op(bm, &reverseop);
+	BMO_Finish_Op(bm, &reverseop);
+
+	calc_solidify_normals(bm);
+
+	/* Extrude the region */
+	BMO_InitOpf(bm, &extrudeop, "extrudefaceregion alwayskeeporig=%i", 1);
+	BMO_CopySlot(op, &extrudeop, "geom", "edgefacein");
+	BMO_Exec_Op(bm, &extrudeop);
+
+	/* Push the verts of the extruded faces inward to create thickness */
+	BMO_Flag_Buffer(bm, &extrudeop, "geomout", FACE_MARK, BM_FACE);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list