[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