[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [18187] branches/bmesh/bmesh/operators/ subdivideop.c: coded a simple pattern-based edge subdivider, to get used to the operator API.

Joseph Eagar joeedh at gmail.com
Wed Dec 31 03:47:39 CET 2008


Revision: 18187
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=18187
Author:   joeedh
Date:     2008-12-31 03:47:30 +0100 (Wed, 31 Dec 2008)

Log Message:
-----------
coded a simple pattern-based edge subdivider, to get used to the operator API.  I coded this for hemesh a long time ago, so it was pretty easy.  most likely does not compile.

Added Paths:
-----------
    branches/bmesh/bmesh/operators/subdivideop.c

Added: branches/bmesh/bmesh/operators/subdivideop.c
===================================================================
--- branches/bmesh/bmesh/operators/subdivideop.c	                        (rev 0)
+++ branches/bmesh/bmesh/operators/subdivideop.c	2008-12-31 02:47:30 UTC (rev 18187)
@@ -0,0 +1,195 @@
+#include "bmesh.h"
+
+/*
+note: this is a pattern-based edge subdivider.
+it tries to match a pattern to edge selections on faces.
+
+the patterns are defined as followed:
+
+the patterns are defined for the state of the face after
+initial splitting.  each edge that was split is flagged, as is
+the new resulting edge.
+
+subdpattern pattern = {
+	//boolean flags for if an edge should have been split or not
+	{1, 0, 0, 0},
+	//connection values for verts,
+	{2, -1, -1, -1},
+	//second stage split flags, splits newly created edges
+	{0, 0, 0, 0, 1},
+	//second stage connection values for verts, connects stuff again.
+	{-1, -1, -1, -1, 3},
+	4 //len of face before second stage splits, but after initial edge splits
+};
+
+*/
+typedef struct subdpattern {
+	int *seledges; //selected edges mask, for splitting
+	int *connectverts //verts to connect;
+
+	int *secondstage_splitedges;
+	//verts to connect afterwards.  size must be len + number 
+	//of edges split in secondstage_splitedges
+	int *secondstage_connect;
+
+	int len; /*total number of verts*/
+} subdpattern;
+
+
+/*note: the patterns are rotated as necassary to
+  match the input geometry.  they're also based on the
+  post-splitted state of the faces.  note that
+  second stage splitted stuff doesn't count
+  for pattern->len!*/
+
+/*
+     v2
+    /  \
+v1 s_e1 e2
+  /e0     \
+v0---e3----v3
+
+handle case of one edge selected.
+*/
+
+subdpattern t_1edge = {
+	{1, 1, 0, 0},
+	{-1, 3, -1, -1},
+	NULL,
+	NULL,
+	4
+};
+
+
+/*
+     v2
+    /  \e2
+v1 e1   e3 v3
+  /e0     \
+v0---e2----v4
+
+handle case of two edges selected.
+*/
+subdpattern t_2edge = {
+	{1, 1, 1, 1, 0},
+	{0, 3, -1, -1, -1},
+	NULL,
+	NULL,
+	5
+};
+
+/*
+     v2
+    /  \e2
+v1 e1   e3 v3
+  /e0     \
+v0--e5--e4-v4
+     v5
+
+handle case of one edge selected.
+make an edge between v1 and v3,
+than split that and make an edge between
+the new vert and v4
+*/
+subdpattern t_3edge = {
+	{1, 1, 1, 1, 1, 1},
+	{-1, 3, -1, -1, -1}, //creates e5
+	{0, 0, 0, 0, 0, 1},
+	{-1, -1, -1, -1, -1, 6, -1},
+	6
+};
+
+subdpattern *patterns[] = {
+	t_1edge,
+	t_2edge,
+	t_3edge,
+};
+
+#define PLEN	(sizeof(patterns) / sizeof(void*))
+
+#define SUBD_SPLIT	1
+#define MAX_FACE	10
+
+void esubdivide_exec(BMesh *bmesh, BMOperator *op)
+{
+	BMOpSlot *einput;
+	BMEdge *edge, *nedge, edges[MAX_FACE];
+	BMFace *face;
+	BMLoop *nl;
+	BMVert *v1, verts[MAX_FACE], *lastv, *newv;
+	BMIter fiter, eiter;
+	subdpattern *pat;
+	int i, j, matched, a, b, newlen, newvlen;
+	
+	BMO_Flag_Buffer(bm, dupeop, BMOP_ESUBDIVIDE_EDGES, SUBD_SPLIT);
+
+	einput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_EDGES);
+
+	/*first go through and split edges*/
+	for (i=0; i<einput->len; i++) {
+		edge = ((BMEdge**)einput->data.p)[i];
+		v1 = BM_Split_Edge(bmesh, edge->v1, edge, &nedge, 0.5, 1);
+		BMO_SetFlag(bmesh, vert, SUBD_SPLIT);
+		BMO_SetFlag(bmesh, nedge, SUBD_SPLIT);
+	}
+
+	/*now go through all the faces and connect the new geometry*/
+	for (face = BMIter_New(&fiter, bmesh, BM_FACES, NULL); face; face=BMIter_Step(&fiter)) {
+		matched = 0;
+
+		if (face->len < MAX_FACE) {
+			/*try all possible pattern rotations*/
+			for (i=0, i<PLEN; i++) {
+				if (patterns[i]->len != face->len) continue;
+				lastv = NULL;
+				for (j=0; j<patterns[i]->len; j++) {
+					for (a=0, edge=BMIter_New(&eiter, bmesh, BM_EDGES_OF_FACE, face); edge; a++, edge=BMIter_Step(&eiter)) {
+						verts[a] = edge->v1 == lastv? edge->v2 : edge->v1;
+						edges[a] = edge;
+
+						b = (j + a) % patterns[i]->len;
+						if (!(patterns[i]->seledges[b] == BMOP_TestFlag(bmesh, edge, SUBD_SPLIT))) break;
+
+						lastv = verts[a];
+					}
+					if (a == face->len) {
+						matched = 1;
+						pat = patterns[i];
+						break;
+					}
+				}
+			}
+		}
+		struct BMFace *BM_Split_Face(struct BMesh *bm, struct BMFace *f, struct BMVert *v1, struct BMVert *v2, struct BMLoop **nl, struct BMEdge *example, int calcnorm);
+
+		if (matched) {
+			/*first stage*/
+			newlen = pat->len;
+			for (i=0; i<pat->len; i++) {
+				if (pat->connectverts[i] != -1) {
+					BM_Split_Face(bmesh, face, verts[i], verts[pat->connectverts[i]], &nl, edges[i], 1);
+					edges[newlen] = nl->edge;
+					newlen++;
+				}
+			}
+
+			newvlen = pat->len;			
+			/*second stage*/
+			for (i=0; i<pat->len; i++) {
+				if (pat->secondstage_splitedges[i]) {
+					v1 = BM_Split_Edge(bmesh, edges[i]->v1, edges[i], &nedge, 0.5, 1);
+					verts[newvlen++] = v1;
+				}
+			}
+
+			for (i=0; i<newvlen; i++) {
+				if (pat->secondstage_connectverts[i] != -1) {
+					BM_Split_Face(bmesh, face, verts[i], verts[pat->secondstage_connectverts[i]], &nl, edges[i], 1);
+					edges[newlen] = nl->edge;
+					newlen++;
+				}
+			}
+		} else { /*no match in the pattern*/
+		}
+	}
+}
\ No newline at end of file





More information about the Bf-blender-cvs mailing list