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


_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to