[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [52010] trunk/blender/source/blender: Merge gsoc Bevel (with rounding) into trunk.

Howard Trickey howard.trickey at gmail.com
Thu Nov 8 16:12:24 CET 2012


Revision: 52010
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=52010
Author:   howardt
Date:     2012-11-08 15:12:21 +0000 (Thu, 08 Nov 2012)
Log Message:
-----------
Merge gsoc Bevel (with rounding) into trunk.

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
    trunk/blender/source/blender/bmesh/operators/bmo_bevel.c
    trunk/blender/source/blender/editors/mesh/editmesh_tools.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2012-11-08 14:34:42 UTC (rev 52009)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2012-11-08 15:12:21 UTC (rev 52010)
@@ -1064,6 +1064,7 @@
 	0,
 };
 
+#define NEW_BEVEL 1
 /*
  * Bevel
  *
@@ -1071,7 +1072,13 @@
  */
 static BMOpDefine bmo_bevel_def = {
 	"bevel",
+#ifdef NEW_BEVEL
 	{{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */
+	 {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */
+	 {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */
+	 {0} /* null-terminating sentinel */},
+#else
+	{{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */
 	 {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */
 	 {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */
 	 {BMO_OP_SLOT_BOOL, "use_lengths"}, /* grab edge lengths from a PROP_FLT customdata layer */
@@ -1081,6 +1088,7 @@
 	 {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */
 	 {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */
 	 {0} /* null-terminating sentinel */},
+#endif
 	bmo_bevel_exec,
 	BMO_OP_FLAG_UNTAN_MULTIRES
 };

Modified: trunk/blender/source/blender/bmesh/operators/bmo_bevel.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_bevel.c	2012-11-08 14:34:42 UTC (rev 52009)
+++ trunk/blender/source/blender/bmesh/operators/bmo_bevel.c	2012-11-08 15:12:21 UTC (rev 52010)
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
- * Contributor(s): Joseph Eagar.
+ * Contributor(s): Joseph Eagar, Aleksandr Mokhov, Howard Trickey
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -26,6 +26,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_listbase.h"
 #include "BLI_array.h"
 #include "BLI_math.h"
 #include "BLI_smallhash.h"
@@ -36,7 +37,1438 @@
 
 #include "intern/bmesh_operators_private.h" /* own include */
 
+#define NEW_BEVEL 1
+
+#ifdef NEW_BEVEL
 #define BEVEL_FLAG	1
+#define EDGE_SELECTED	2
+
+#define BEVEL_EPSILON  1e-6
+
+/* Constructed vertex, sometimes later instantiated as BMVert */
+typedef struct NewVert {
+	float co[3];
+	BMVert *v;
+} NewVert;
+
+struct BoundVert;
+
+/* Data for one end of an edge involved in a bevel */
+typedef struct EdgeHalf {
+	struct EdgeHalf *next, *prev;	/* in CCW order */
+	BMEdge *e;			/* original mesh edge */
+	int isbev;			/* is this edge beveled? */
+	int isrev;			/* is e->v2 the vertex at this end? */
+	int seg;			/* how many segments for the bevel */
+	float offset;			/* offset for this edge */
+	BMFace *fprev;			/* face between this edge and previous, if any */
+	BMFace *fnext;			/* face between this edge and next, if any */
+	struct BoundVert *leftv;	/* left boundary vert (looking along edge to end) */
+	struct BoundVert *rightv;	/* right boundary vert, if beveled */
+} EdgeHalf;
+
+/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */
+typedef struct BoundVert {
+	struct BoundVert *next, *prev;	/* in CCW order */
+	int index;			/* used for vmesh indexing */
+	NewVert nv;
+	EdgeHalf *efirst;		/* first of edges attached here: in CCW order */
+	EdgeHalf *elast;
+	EdgeHalf *ebev;			/* beveled edge whose left side is attached here, if any */
+} BoundVert;
+
+/* Mesh structure replacing a vertex */
+typedef struct VMesh {
+	enum {
+		M_NONE,			/* no polygon mesh needed */
+		M_POLY,			/* a simple polygon */
+		M_ADJ,			/* "adjacent edges" mesh pattern */
+		M_CROSS,		/* "cross edges" mesh pattern */
+	} mesh_kind;
+	int count;			/* number of vertices in the boundary */
+	int seg;			/* common # of segments for segmented edges */
+	BoundVert *boundstart;		/* start of boundary double-linked list */
+	NewVert *mesh;			/* allocated array - size and structure depends on kind */
+} VMesh;
+
+/* Data for a vertex involved in a bevel */
+typedef struct BevVert {
+	struct BevVert *next, *prev;
+	BMVert *v;			/* original mesh vertex */
+	int edgecount;			/* total number of edges around the vertex */
+	int selcount;			/* number of selected edges around the vertex */
+	EdgeHalf *edges;		/* array of size edgecount; CCW order from vertex normal side */
+	VMesh *vmesh;			/* mesh structure for replacing vertex */
+} BevVert;
+
+/*
+ * Bevel parameters and state
+ */
+typedef struct BevelParams {
+	ListBase vertList;		/* list of BevVert for each vertex involved in bevel */
+	float offset;			/* blender units to offset each side of a beveled edge */
+	int seg;				/* number of segments in beveled edge profile */
+
+	BMOperator *op;
+} BevelParams;
+
+/* Make a new BoundVert of the given kind, insert it at the end of the circular linked
+ * list with entry point bv->boundstart, and return it. */
+static BoundVert * add_new_bound_vert(VMesh *vm, float co[3])
+{
+	BoundVert *ans = (BoundVert*) MEM_callocN(sizeof(BoundVert), "BoundVert");
+	copy_v3_v3(ans->nv.co, co);
+	if (!vm->boundstart) {
+		ans->index = 0;
+		vm->boundstart = ans;
+		ans->next = ans->prev = ans;
+	}
+	else {
+		BoundVert *tail = vm->boundstart->prev;
+		ans->index = tail->index + 1;
+		ans->prev = tail;
+		ans->next = vm->boundstart;
+		tail->next = ans;
+		vm->boundstart->prev = ans;
+	}
+	vm->count++;
+	return ans;
+}
+
+/* Mesh verts are indexed (i, j, k) where
+ * i = boundvert index (0 <= i < nv)
+ * j = ring index (0 <= j <= ns2)
+ * k = segment index (0 <= k <= ns)
+ * Not all of these are used, and some will share BMVerts */
+static NewVert* mesh_vert(VMesh* vm, int i, int j, int k)
+{
+	int nj = (vm -> seg / 2) + 1;
+	int nk = vm->seg + 1;
+
+	return &vm->mesh[i * nk * nj  + j * nk + k];
+}
+
+static void create_mesh_bmvert(BMesh* bm, VMesh *vm, int i, int j, int k, BMVert *eg)
+{
+	NewVert *nv = mesh_vert(vm, i, j, k);
+	nv->v = BM_vert_create(bm, nv->co, eg);
+}
+
+static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto,
+		int ifrom, int jfrom, int kfrom)
+{
+	NewVert *nvto, *nvfrom;
+
+	nvto = mesh_vert(vm, ito, jto, kto);
+	nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom);
+	nvto->v = nvfrom->v;
+	copy_v3_v3(nvto->co, nvfrom->co);
+}
+
+/* find the EdgeHalf in bv's array that has edge bme */
+static EdgeHalf* find_edge_half(BevVert *bv, BMEdge *bme)
+{
+	int i;
+
+	for (i = 0; i < bv->edgecount; i++) {
+		if (bv->edges[i].e == bme)
+			return &bv->edges[i];
+	}
+	return NULL;
+}
+
+/* Return the next EdgeHalf after from_e that is beveled.
+ * If from_e is NULL, find the first beveled edge. */
+static EdgeHalf* next_bev(BevVert *bv, EdgeHalf *from_e)
+{
+	EdgeHalf *e;
+
+	if (from_e == NULL)
+		from_e = &bv->edges[bv->edgecount -1];
+	e = from_e;
+	do {
+		if (e->isbev)
+			return e;
+		e = e->next;
+	} while (e != from_e);
+	return NULL;
+}
+
+/* find the BevVert corresponding to BMVert bmv */
+static BevVert* find_bevvert(BevelParams *bp, BMVert *bmv)
+{
+	BevVert *bv;
+
+	for (bv = bp->vertList.first; bv; bv = bv->next) {
+		if (bv->v == bmv)
+			return bv;
+	}
+	return NULL;
+}
+
+/* Return a good respresentative face (for materials, etc.) for faces
+ * created around/near BoundVert v */
+static BMFace* boundvert_rep_face(BoundVert *v)
+{
+	BMFace *fans = NULL;
+	BMFace *firstf = NULL;
+	BMEdge *e1, *e2;
+	BMFace *f1, *f2;
+	BMIter iter1, iter2;
+
+	BLI_assert(v->efirst != NULL && v->elast != NULL);
+	e1 = v->efirst->e;
+	e2 = v->elast->e;
+	BM_ITER_ELEM(f1, &iter1, e1, BM_FACES_OF_EDGE) {
+		if (!firstf)
+			firstf = f1;
+		BM_ITER_ELEM(f2, &iter2, e2, BM_FACES_OF_EDGE) {
+			if (f1 == f2) {
+				fans = f1;
+				break;
+			}
+		}
+	}
+	if (!fans)
+		fans = firstf;
+
+	return fans;
+}
+
+/* Make ngon from verts alone.
+ * Make sure to properly copy face attributes and do custom data interpolation from
+ * example face, facerep. */
+static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *facerep)
+{
+	BMIter iter;
+	BMLoop *l;
+	BMFace *f;
+
+	if (totv == 3) {
+		f = BM_face_create_quad_tri(bm,
+			vert_arr[0], vert_arr[1], vert_arr[2], NULL, facerep, 0);
+	}
+	else if (totv == 4) {
+		f = BM_face_create_quad_tri(bm,
+			vert_arr[0], vert_arr[1], vert_arr[2], vert_arr[3], facerep, 0);
+	}
+	else {
+		int i;
+		BMEdge *e;
+		BMEdge **ee = NULL;
+		BLI_array_staticdeclare(ee, 30);
+
+		for (i = 0; i < totv; i++) {
+			e = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, TRUE);
+			BLI_array_append(ee, e);
+		}
+		f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, FALSE);
+		BLI_array_free(ee);
+	}
+	if (facerep && f) {
+		int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
+		BM_elem_attrs_copy(bm, bm, facerep, f);
+		BM_ITER_ELEM(l, &iter, f, BM_LOOPS_OF_FACE) {
+			BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE);
+			if (has_mdisps)
+				BM_loop_interp_multires(bm, l, facerep);
+		}
+	}
+	return f;
+}
+
+static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+		BMFace *facerep)
+{
+	BMVert *varr[4];
+
+	varr[0] = v1;
+	varr[1] = v2;
+	varr[2] = v3;
+	varr[3] = v4;
+	return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep);
+}
+
+/*
+ * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco.
+ * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of
+ * the bevel vertex,  e1 precedes e2 in CCW order.
+ * If on_right is true, offset edge is on right of both edges, where e1 enters v and
+ * e2 leave it. If on_right is false, then the offset edge is on the left.
+ * When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2),
+ * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may
+ * lead to different offsets) then meeting point can be found be intersecting offset lines.
+ */
+static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
+                        int on_right, float meetco[3])
+{
+	float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3],
+		off1a[3], off1b[3], off2a[3], off2b[3], isect2[3];
+
+	/* get direction vectors for two offset lines */
+	sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
+	sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
+
+	/* get normal to plane where meet point should be */
+	cross_v3_v3v3(norm_v, dir2, dir1);
+	normalize_v3(norm_v);
+	if (!on_right)
+		negate_v3(norm_v);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list