Begin port of edge subdivide (with multicut) to
authorJoseph Eagar <joeedh@gmail.com>
Mon, 2 Feb 2009 03:25:23 +0000 (03:25 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Mon, 2 Feb 2009 03:25:23 +0000 (03:25 +0000)
bmesh.  Basic infrastructure is in place, and
subdivision patterns for quads are implemented.
Properly handling of the (many) flags and options
related to edge subdivide isn't complete, but I've
made a good start.

Goal is eventual 100% api compatibility with old
esubdivide function, with some of the uglier design
aspects refactored after some of the tools that rely
on them are redone.

Some notes: Customdata interpolation wasn't working
right.  I thought maybe the weights were off, so I
swapped them, which surprising made it work.  It's
still not completely identical to old edge
subdivide though.

source/blender/blenkernel/BKE_utildefines.h
source/blender/bmesh/bmesh_operators.h
source/blender/bmesh/intern/bmesh_interp.c
source/blender/bmesh/intern/bmesh_mods.c
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/intern/bmesh_operators.c
source/blender/bmesh/operators/subdivideop.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/mesh_intern.h

index 6584af085cd5c962e9cc36ef66f32900b17a99d2..2f092d3a5a34b6ae99fd58194b0e979f4aaa6104 100644 (file)
 #define SET_INT_IN_POINTER(i) ((void*)(intptr_t)(i))
 #define GET_INT_FROM_POINTER(i) ((int)(intptr_t)(i))
 
+/*little pointer array macro library.  example of usage:
+
+int *arr = NULL;
+V_DECLARE(arr);
+int i;
+
+for (i=0; i<10; i++) {
+       V_GROW(arr);
+       arr[i] = something;
+}
+V_FREE(arr);
+*/
+
+#define V_DECLARE(vec) int _##vec##_count=0; void *_##vec##_tmp
+#define V_SIZE(vec) ((vec)==NULL ? 0 : MEM_allocN_len(vec) / sizeof(*vec))
+#define V_COUNT(vec) _##vec##_count
+#define MSTR(s) #s
+#define V_GROW(vec) \
+       V_SIZE(vec) > _##vec##_count ? _##vec##_count++ : \
+       ((_##vec##_tmp = MEM_callocN(sizeof(*vec)*(_##vec##_count*2+2), #vec " " __FILE__ " ")),\
+       (vec && memcpy(_##vec##_tmp, vec, sizeof(*vec) * _##vec##_count)),\
+       (vec && (MEM_freeN(vec),1)),\
+       (vec = _##vec##_tmp),\
+       _##vec##_count++)
+
+//(vec) ? WMEM_freeN(vec), 1 : 0
+#define V_FREE(vec) if (vec) MEM_freeN(vec);
+#define V_RESET(vec) _##vec##_count=0
+
 #endif
 
index b7fd6cc5275d2e19d1a70b9a0f3f7a3dfecaa0bb..390283393c7b4032bc0dcedcf2eea094f6281e52 100644 (file)
@@ -22,7 +22,7 @@ typedef struct BMOpSlot{
        int len;
        int index; /*index within slot array*/
        union {
-               int     i;
+               int i;
                float f;                                        
                void *p;                                        
                float vec[3];                           /*vector*/
@@ -52,7 +52,6 @@ typedef struct BMOpDefine {
 
 /*BMOpDefine->flag*/
 //doesn't do anything at the moment.
-#define BMO_NOFLAGS            1
 
 /*API for operators*/
 void BMO_Init_Op(struct BMOperator *op, int opcode);
@@ -152,16 +151,31 @@ enum {
 
 /*edge subdivide op*/
 #define BMOP_ESUBDIVIDE                        5
-#define BMOP_ESUBDIVIDE_EDGES  0
-#define BMOP_ESUBDIVIDE_TOTSLOT        1
+enum {
+       BMOP_ESUBDIVIDE_EDGES,
+       BMOP_ESUBDIVIDE_NUMCUTS,
+       BMOP_ESUBDIVIDE_FLAG, //beauty flag in esubdivide
+       BMOP_ESUBDIVIDE_RADIUS,
+       BMOP_ESUBDIVIDE_SELACTION,
+       BMOP_ESUBDIVIDE_TOTSLOT,
+};
+/*
+SUBDIV_SELECT_INNER
+SUBDIV_SELECT_ORIG
+SUBDIV_SELECT_INNER_SEL
+SUBDIV_SELECT_LOOPCUT
+DOUBLEOPFILL
+*/
 
 /*triangulate*/
 #define BMOP_TRIANGULATE               6
 
-#define BMOP_TRIANG_FACEIN             0
-#define BMOP_TRIANG_NEW_EDGES  1
-#define BMOP_TRIANG_NEW_FACES  2
-#define BMOP_TRIANG_TOTSLOT            3
+enum {
+       BMOP_TRIANG_FACEIN,
+       BMOP_TRIANG_NEW_EDGES,
+       BMOP_TRIANG_NEW_FACES,
+       BMOP_TRIANG_TOTSLOT,
+};
 
 /*dissolve faces*/
 #define BMOP_DISSOLVE_FACES            7
index 9e9d6e0c355ba4650753fa8b303763d474abef1e..47d1c5104039143ae807d4e692204427c0e0cef0 100644 (file)
@@ -79,8 +79,8 @@ void BM_Data_Facevert_Edgeinterp(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, B
        float w[2];
        BMLoop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
        
-       w[0] = 1.0f - fac;
-       w[1] = fac;
+       w[1] = 1.0f - fac;
+       w[0] = fac;
 
        if(!e1->loop) return;
        l = e1->loop;
index 525c26e5d9aded557de0d00805c0e6870966d359..15ef76eb5bb42c844a580945ef5eeba65584fc92 100644 (file)
@@ -39,7 +39,7 @@
  *  Returns -
  *     1 for success, 0 for failure.
  */
-
+#if 1
 void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
        BMFace *f, *f2;
        BMEdge *e, *keepedge=NULL, *baseedge=NULL;
@@ -111,6 +111,38 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
                BM_Join_Faces(bm, f, f2, NULL, 0, 0);
        }
 }
+#else
+void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
+       BMFace *f;
+       BMEdge *e;
+       BMIter iter;
+       int done, len;
+       
+       if(v->edge){
+               done = 0;
+               while(!done){
+                       done = 1;
+                       
+                       /*loop the edges looking for an edge to dissolve*/
+                       for (e=BMIter_New(&iter, bm, BM_EDGES_OF_VERT, v); e;
+                            e = BMIter_Step(&iter)) {
+                               f = NULL;
+                               len = bmesh_cycle_length(&(e->loop->radial));
+                               if(len == 2){
+                                       f = BM_Join_Faces(bm,e->loop->f,((BMLoop*)
+                                             (e->loop->radial.next->data))->f, 
+                                              e, 1, 0);
+                               }
+                               if(f){ 
+                                       done = 0;
+                                       break;
+                               }
+                       };
+               }
+               BM_Collapse_Vert(bm, v->edge, v, 1.0, 1);
+       }
+}
+#endif
 
 /**
  *                     bmesh_join_faces
index b25cdd453372339d5239f606f471418de6eb1aa7..49e51e11e31b6d1a1f5b391f6b5dbdfa07651bab 100644 (file)
@@ -34,7 +34,11 @@ BMOpDefine def_triangop = {
 };
 
 BMOpDefine def_subdop = {
-       {BMOP_OPSLOT_PNT_BUF},
+       {BMOP_OPSLOT_PNT_BUF,
+        BMOP_OPSLOT_INT,
+        BMOP_OPSLOT_INT,
+        BMOP_OPSLOT_FLT,
+        BMOP_OPSLOT_INT},
        esubdivide_exec,
        BMOP_ESUBDIVIDE_TOTSLOT,
        0
index 231c0b999b40ef6daf0ad0f33e8bbd3972f3011e..f843ae173f553e277c4d3f94dc53c319a2613876 100644 (file)
@@ -80,9 +80,6 @@ void BMO_Init_Op(BMOperator *op, int opcode)
        memset(op, 0, sizeof(BMOperator));
        op->type = opcode;
        
-       //currently not used, flags are always allocated
-       op->needflag = !(opdefines[opcode]->flag & BMO_NOFLAGS);
-
        /*initialize the operator slot types*/
        for(i = 0; i < opdefines[opcode]->totslot; i++) {
                op->slots[i].slottype = opdefines[opcode]->slottypes[i];
index cd9d37cfae8204266a729a1215269cecf14ce429..e47dfa7de815b5756a46e9de0564431ac480a271 100644 (file)
@@ -2,45 +2,37 @@
 
 #include "BKE_utildefines.h"
 
-#include "bmesh.h"
 #include "BLI_arithb.h"
+#include "BLI_rand.h"
 
-#include <stdio.h>
+#include "DNA_object_types.h"
 
-/*
-note: this is a pattern-based edge subdivider.
-it tries to match a pattern to edge selections on faces.
-it was a fairly easy exercise to test the bmesh api; it
-doesn't support multicuts, so it won't actually be used.
+#include "ED_mesh.h"
 
-the patterns are defined as followed:
+#include "bmesh.h"
+#include "mesh_intern.h"
 
-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.
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
 
-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
-};
+#define SUBD_SPLIT     1
+#define FACE_NEW       1
+#define MAX_FACE       800
 
+/*
+note: this is a pattern-based edge subdivider.
+it tries to match a pattern to edge selections on faces,
+then executes functions to cut them.
 */
 typedef struct subdpattern {
        int seledges[20]; //selected edges mask, for splitting
-       int connectverts[20]; //verts to connect;
-
-       int secondstage_splitedges[20];
-       //verts to connect afterwards.  size must be len + number 
-       //of edges split in secondstage_splitedges
-       int secondstage_connect[20];
 
+       /*verts starts at the first new vert cut, not the first vert in the
+         face*/
+       void (*connectexec)(BMesh *bm, BMFace *face, BMVert **verts, 
+                           int numcuts, int beauty, float rad);
        int len; /*total number of verts*/
 } subdpattern;
 
@@ -53,269 +45,485 @@ typedef struct subdpattern {
     split the edge only?
 */
 
-/*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
+/* calculates offset for co, based on fractal, sphere or smooth settings  */
+static void alter_co(float *co, BMEdge *edge, float rad, int beauty, float perc)
+{
+       float vec1[3], fac;
+       
+       if(beauty & B_SMOOTH) {
+               /* we calculate an offset vector vec1[], to be added to *co */
+               float len, fac, nor[3], nor1[3], nor2[3];
+               
+               VecSubf(nor, edge->v1->co, edge->v2->co);
+               len= 0.5f*Normalize(nor);
+       
+               VECCOPY(nor1, edge->v1->no);
+               VECCOPY(nor2, edge->v2->no);
+       
+               /* cosine angle */
+               fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+               
+               vec1[0]= fac*nor1[0];
+               vec1[1]= fac*nor1[1];
+               vec1[2]= fac*nor1[2];
+       
+               /* cosine angle */
+               fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
+               
+               vec1[0]+= fac*nor2[0];
+               vec1[1]+= fac*nor2[1];
+               vec1[2]+= fac*nor2[2];
+               
+               vec1[0]*= rad*len;
+               vec1[1]*= rad*len;
+               vec1[2]*= rad*len;
+               
+               co[0] += vec1[0];
+               co[1] += vec1[1];
+               co[2] += vec1[2];
+       }
+       else {
+               if(rad > 0.0) {   /* subdivide sphere */
+                       Normalize(co);
+                       co[0]*= rad;
+                       co[1]*= rad;
+                       co[2]*= rad;
+               }
+               else if(rad< 0.0) {  /* fractal subdivide */
+                       fac= rad* VecLenf(edge->v1->co, edge->v2->co);
+                       vec1[0]= fac*(float)(0.5-BLI_drand());
+                       vec1[1]= fac*(float)(0.5-BLI_drand());
+                       vec1[2]= fac*(float)(0.5-BLI_drand());
+                       VecAddf(co, co, vec1);
+               }
 
-handle case of one edge selected.
-*/
+       }
+}
 
-subdpattern t_1edge = {
-       {1, 1, 0, 0},
-       {-1, 3, -1, -1},
-       {0},
-       {-1, -1, -1, -1, -1, -1, -1, -1, -1},
-       4
-};
+/* assumes in the edge is the correct interpolated vertices already */
+/* percent defines the interpolation, rad and beauty are for special options */
+/* results in new vertex with correct coordinate, vertex normal and weight group info */
+static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, float rad, 
+                                        int beauty, float percent, BMEdge **out)
+{
+       BMVert *ev;
+//     float co[3];
+       
+       ev = BM_Split_Edge(bm, edge->v1, edge, out, percent, 1);
 
+       /* offset for smooth or sphere or fractal */
+       alter_co(ev->co, edge, rad, beauty, percent);
 
-/*
-     v2
-    /  \e2
-v1 e1   e3 v3
-  /e0     \
-v0---e4----v4
+#if 0 //TODO
+       /* clip if needed by mirror modifier */
+       if (edge->v1->f2) {
+               if ( edge->v1->f2 & edge->v2->f2 & 1) {
+                       co[0]= 0.0f;
+               }
+               if ( edge->v1->f2 & edge->v2->f2 & 2) {
+                       co[1]= 0.0f;
+               }
+               if ( edge->v1->f2 & edge->v2->f2 & 4) {
+                       co[2]= 0.0f;
+               }
+       }
+#endif 
+       
+       return ev;
+}
 
-handle case of two edges selected.
-*/
-subdpattern t_2edge = {
-       {1, 1, 1, 1, 0},
-       {-1, 3, -1, -1, -1},
-       {0},
-       {-1, -1, -1, -1, -1, -1, -1, -1, -1},
-       5
-};
+static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, 
+                               int curpoint, int totpoint, float rad, 
+                               int beauty, BMEdge **newe)
+{
+       BMVert *ev;
+       float percent;
+        
+       if (beauty & (B_PERCENTSUBD) && totpoint == 1)
+               /*I guess the idea is vertices store what
+                 percent to use?*/
+               //percent=(float)(edge->tmp.l)/32768.0f;
+               percent= 1.0; //edge->tmp.fp;
+       else {
+               percent= 1.0f/(float)(totpoint+1-curpoint);
 
-/*
-     v2
-    /  \e2
-v1 e1   e3 v3
-  /e0     \
-v0--e5--e4-v4
-     v5
-
-handle case of one edge selected.
-make an edge between v1 and v5,
-v5 and v3, and v3 and v1
+       }
+       
+       /*{
+               float co[3], co2[3];
+               VecSubf(co, edge->v2->co, edge->v1->co);
+               VecMulf(co, 1.0f/(float)(totpoint+1-curpoint));
+               VecAddf(co2, edge->v1->co, co);
 */
-subdpattern t_3edge = {
-       {1, 1, 1, 1, 1, 1},
-       {-1, 5, -1, 1, -1, 3}, //creates e6
-       {0},
-       {-1, -1, -1, -1, -1, -1, -1},
-       6
-};
+               ev= bm_subdivide_edge_addvert(bm, edge, rad, beauty, percent, newe);
+/*             VECCOPY(ev->co, co2);
+       }
+*/     
+       return ev;
+}
+
+static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, float rad,
+                                 int beauty, int numcuts) {
+       BMEdge *eed = edge, *newe;
+       BMVert *v;
+       int i;
+
+       for(i=0;i<numcuts;i++) {
+               v = subdivideedgenum(bm, eed, i, numcuts, rad, beauty, &newe);
+               BMO_SetFlag(bm, v, SUBD_SPLIT);
+               BMO_SetFlag(bm, eed, SUBD_SPLIT);
+       }
+}
+
+/*note: the patterns are rotated as necassary to
+  match the input geometry.  they're based on the
+  pre-split state of the  face*/
 
 /*
-      e3
-v4---------v3
+     
+v3---------v2
 |          |
-|e4        | e2
 |          |
-|e0   e1   |
-v0---v1----v2
-
-connect v1 to v4 and v3
+|          |
+|          |
+v4---v0---v1
 
 */
+static void q_1edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
+                         int beauty, float rad) {
+       BMFace *nf;
+       int i, add;
+
+       /*if it's odd, the middle face is a quad, otherwise it's a triangle*/
+       if (numcuts % 2==0) {
+               add = 2;
+               for (i=0; i<numcuts; i++) {
+                       if (i == numcuts/2) add -= 1;
+                       BM_Connect_Verts(bm, vlist[i], vlist[numcuts+add], &nf);
+               }
+       } else {
+               add = 2;
+               for (i=0; i<numcuts; i++) {
+                       BM_Connect_Verts(bm, vlist[i], vlist[numcuts+add], &nf);
+                       if (i == numcuts/2) {
+                               add -= 1;
+                               BM_Connect_Verts(bm, vlist[i], vlist[numcuts+add], &nf);
+                       }
+               }
+
+       }
+}
+
 subdpattern q_1edge = {
-       {1, 1, 0, 0, 0},
-       {-1, 3, -1, -1, 1},
-       {0},
-       {-1, -1, -1, -1, -1, -1, -1, -1, -1},
-       5
+       {1, 0, 0, 0},
+       q_1edge_split,
+       4,
 };
 
+
 /*
-      e4
-v5---------v4
+v4---v3---v2
+|     s    |
 |          |
-|e5        | e3
-|          |v3
-|e0   e1   | e2
-v0---v1----v2
-
-connect v1 to v3
+|          |
+|     s    |
+v5---v0---v1
 
 */
-subdpattern q_2adjedge = {
-       {1, 1, 1, 1, 0, 0},
-       {-1, 3, -1, -1, -1, -1},
-       {0, 0, 0, 0, 0, 0, 1},
-       {-1, -1, -1, -1, -1, 6, -1, -1, -1},
-       6
-};
+static void q_2edge_op_split(BMesh *bm, BMFace *face, BMVert **vlist, 
+                            int numcuts, int beauty, float rad) {
+       BMFace *nf;
+       int i;
+       
+       for (i=0; i<numcuts; i++) {
+               BM_Connect_Verts(bm, vlist[i], vlist[(numcuts-i-1)+numcuts+2], &nf);
+       }
+}
 
+subdpattern q_2edge_op = {
+       {1, 0, 1, 0},
+       q_2edge_op_split,
+       4,
+};
 
 /*
-   e4 v4 e3
-v5---------v3
+v6--------v5
 |          |
-|e5        |
-|          | e2
-|  e0   e1 |
-v0---v1----v2
-
-connect v1 to v4
+|          |v4s
+|          |v3s
+|   s  s   |
+v7-v0--v1-v2
 
 */
-subdpattern q_2opedge = {
-       {1, 1, 0, 1, 1, 0},
-       {-1, 4, -1, -1, -1, -1},
-       {0},
-       {-1, -1, -1, -1, -1, -1, -1, -1, -1},
-       6
-};
+static void q_2edge_split(BMesh *bm, BMFace *face, BMVert **vlist, 
+                            int numcuts, int beauty, float rad) {
+       BMFace *nf;
+       int i;
+       
+       for (i=0; i<numcuts; i++) {
+               BM_Connect_Verts(bm, vlist[i], vlist[numcuts+(numcuts-i)], &nf);
+       }
+       BM_Connect_Verts(bm, vlist[numcuts*2+3], vlist[numcuts*2+1], &nf);
+}
 
-/*
-   e5 v5 e4
-v6---------v4
-|          | 
-|e6        | e3
-|          | v3
-|  e0   e1 | e2
-v0---v1----v2
+subdpattern q_2edge = {
+       {1, 1, 0, 0},
+       q_2edge_split,
+       4,
+};
 
-connect v1 to v5, v1 to v3, and v3 to v5
+/*  s   s
+v8--v7--v6-v5
+|          |
+|          v4 s
+|          |
+|          v3 s
+|   s  s   |
+v9-v0--v1-v2
 
 */
+static void q_3edge_split(BMesh *bm, BMFace *face, BMVert **vlist, 
+                            int numcuts, int beauty, float rad) {
+       BMFace *nf;
+       int i, add=0;
+       
+       for (i=0; i<numcuts; i++) {
+               if (i == numcuts/2) {
+                       if (numcuts % 2 != 0) {
+                               BM_Connect_Verts(bm, vlist[numcuts-i-1+add], vlist[i+numcuts+1], &nf);
+                       }
+                       add = numcuts*2+2;
+               }
+               BM_Connect_Verts(bm, vlist[numcuts-i-1+add], vlist[i+numcuts+1], &nf);
+       }
+
+       for (i=0; i<numcuts/2+1; i++) {
+               BM_Connect_Verts(bm, vlist[i], vlist[(numcuts-i)+numcuts*2+1], &nf);
+       }
+}
+
 subdpattern q_3edge = {
-       {1, 1, 1, 1, 1, 1, 0},
-       {-1, 3, -1, 5, -1, 1, -1},
-       {0},
-       {-1, -1, -1, -1, -1, -1, -1, -1, -1},
-       7
+       {1, 1, 1, 0},
+       q_3edge_split,
+       4,
 };
 
 /*
-   e5 v5 e4
-v6---------v4
-|          | 
-|e6        | e3
-|v7        | v3
-|e7 e0  e1 | e2
-v0---v1----v2
+           v8--v7-v6--v5
+           |     s    |
+           |v9 s     s|v4
+first line |          |   last line
+           |v10s s   s|v3
+           v11-v0--v1-v2
+
+          it goes from bottom up
+*/
+static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
+                         int beauty, float rad) {
+       BMFace *nf;
+       BMVert *v;
+       BMEdge *e, *ne;
+       BMVert **lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
+                                    "q_4edge_split");
+       int i, j, a, b, s=numcuts+2, totv=numcuts*4+4;
+
+       /*build a 2-dimensional array of verts,
+         containing every vert (and all new ones)
+         in the face.*/
+
+       /*first line*/
+       for (i=0; i<numcuts+2; i++) {
+               lines[i] = vlist[numcuts*3+2+(numcuts-i+1)];
+       }
 
-connect v1 to v5, split edge, than connect
-v3 and v7 to v8 (new vert from split)
+       /*last line*/
+       for (i=0; i<numcuts+2; i++) {
+               lines[(s-1)*s+i] = vlist[numcuts+i];
+       }
+       
+       /*first and last members of middle lines*/
+       for (i=0; i<numcuts; i++) {
+               a = i;
+               b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
+               
+               e = BM_Connect_Verts(bm, vlist[a], vlist[b], &nf);
+               
+               lines[(i+1)*s] = vlist[a];
+               lines[(i+1)*s + s-1] = vlist[b];
+
+               for (a=0; a<numcuts; a++) {
+                       v = subdivideedgenum(bm, e, a, numcuts, rad, beauty, &ne);
+                       lines[(i+1)*s+a+1] = v;
+               }
+       }
+
+       for (i=1; i<numcuts+2; i++) {
+               for (j=1; j<numcuts+1; j++) {
+                       a = i*s + j;
+                       b = (i-1)*s + j;
+                       BM_Connect_Verts(bm, lines[a], lines[b], &nf);
+               }
+       }
+
+       /*
+       for (i=0; i<numcuts; i++) {
+               a = i;
+               b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
+               BM_Connect_Verts(bm, vlist[a], vlist[b], &nf);
+       }*/
+
+       MEM_freeN(lines);
+}
 
-*/
 subdpattern q_4edge = {
-       {1, 1, 1, 1, 1, 1, 1, 1},
-       {-1, 5, -1, -1, -1, -1, -1, -1},
-       {0, 0, 0, 0, 0, 0, 0, 0, 1},
-       {-1, -1, -1, 8, -1, -1, -1, 8, -1},
-       8
+       {1, 1, 1, 1},
+       q_4edge_split,
+       4,
 };
 
 subdpattern *patterns[] = {
-       &t_1edge,
-       &t_2edge,
-       &t_3edge,
        &q_1edge,
-       &q_2adjedge,
-       &q_2opedge,
-       &q_3edge,
+       &q_2edge_op,
        &q_4edge,
+       &q_3edge,
+       &q_2edge,
 };
 
 #define PLEN   (sizeof(patterns) / sizeof(void*))
 
-#define SUBD_SPLIT     1
-#define FACE_NEW       1
-#define MAX_FACE       10
+typedef struct subd_facedata {
+       BMVert *start; subdpattern *pat;
+} subd_facedata;
 
 void esubdivide_exec(BMesh *bmesh, BMOperator *op)
 {
        BMOpSlot *einput;
-       BMEdge *edge, *nedge, *edges[MAX_FACE];
-       BMFace *face, *nf;
-       BMLoop *nl, *loop;
-       BMVert *v1, *verts[MAX_FACE], *lastv;
-       BMIter fiter, eiter;
+       BMEdge *edge, *edges[MAX_FACE];
+       BMFace *face;
+       BMLoop *nl;
+       BMVert *verts[MAX_FACE];
+       BMIter fiter, liter;
        subdpattern *pat;
-       int i, j, matched, a, b, newlen, newvlen;
+       float rad;
+       int i, j, matched, a, b, numcuts, flag, selaction;
+       subd_facedata *facedata = NULL;
+       V_DECLARE(facedata);
        
        BMO_Flag_Buffer(bmesh, op, BMOP_ESUBDIVIDE_EDGES, SUBD_SPLIT);
+       
+       numcuts = BMO_GetSlot(op, BMOP_ESUBDIVIDE_NUMCUTS)->data.i;
+       flag = BMO_GetSlot(op, BMOP_ESUBDIVIDE_FLAG)->data.i;
+       rad = BMO_GetSlot(op, BMOP_ESUBDIVIDE_RADIUS)->data.f;
+       selaction = BMO_GetSlot(op, BMOP_ESUBDIVIDE_SELACTION)->data.i;
 
        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, v1, SUBD_SPLIT);
-               BMO_SetFlag(bmesh, nedge, SUBD_SPLIT);
+               BMO_SetFlag(bmesh, edge, SUBD_SPLIT);
        }
+       
+       for (face=BMIter_New(&fiter, bmesh, BM_FACES, NULL);
+            face; face=BMIter_Step(&fiter)) {
+               /*figure out which pattern to use*/
+               if (face->len > MAX_FACE) continue;
+
+               i = 0;
+               for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+                    nl; nl=BMIter_Step(&liter)) {
+                       edges[i] = nl->e;
+                       verts[i] = nl->v;
+                       i++;
+               }
 
-       /*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 (BMO_TestFlag(bmesh, face, FACE_NEW)) continue;
-
-               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, loop=BMIter_New(&eiter, bmesh, BM_LOOPS_OF_FACE,face); loop; a++, loop=BMIter_Step(&eiter)) {
-                                               b = (j + a) % patterns[i]->len;
-
-                                               edge = loop->e;
-                                               verts[b] = loop->v;
-                                               edges[b] = edge;
-                                               if (!(patterns[i]->seledges[b] == BMO_TestFlag(bmesh, edge, SUBD_SPLIT))) break;
-
-                                               lastv = verts[b];
-                                       }
-
-                                       if (a == face->len) {
-                                               matched = 1;
-                                               pat = patterns[i];
-                                               break;
+               for (i=0; i<PLEN; i++) {
+                       pat = patterns[i];
+                       if (pat->len == face->len) {
+                               for (a=0; a<pat->len; a++) {
+                               matched = 1;
+                               for (b=0; b<pat->len; b++) {
+                                       j = (b + a) % pat->len;
+                                       if ((!!BMO_TestFlag(bmesh, edges[j], SUBD_SPLIT))
+                                               != (!!pat->seledges[b])) {
+                                                       matched = 0;
+                                                       break;
                                        }
                                }
                                if (matched) break;
+                               }
+                               if (matched) {
+                                       V_GROW(facedata);
+                                       BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+                                       j = V_COUNT(facedata) - 1;
+                                       facedata[j].pat = pat;
+                                       facedata[j].start = verts[a];
+                                       break;
+                               }
                        }
                }
+       }
 
-               if (matched) {
-                       /*first stage*/
-                       newlen = pat->len;
-                       for (i=0; i<pat->len; i++) {
-                               if (pat->connectverts[i] != -1) {
-                                       edges[newlen++] = BM_Connect_Verts(bmesh, verts[i], verts[pat->connectverts[i]], &nf);
-                                       BMO_SetFlag(bmesh, nf, FACE_NEW);
-                               }
-                       }
+       /*go through and split edges*/
+       for (i=0; i<einput->len; i++) {
+               edge = ((BMEdge**)einput->data.p)[i];
+               bm_subdivide_multicut(bmesh, edge, rad, flag, numcuts);
+               //BM_Split_Edge_Multi(bmesh, edge, numcuts);
+       }
 
-                       newvlen = pat->len;             
-                       /*second stage*/
-                       for (i; i<newlen; i++) {
-                               if (pat->secondstage_splitedges[i]) {
-                                       v1 = BM_Split_Edge(bmesh, edges[i]->v1, edges[i], &nedge, 0.5, 1);
-                                       verts[newvlen++] = v1;
-                               }
+       //if (facedata) V_FREE(facedata);
+       //return;
+
+       i = 0;
+       for (face=BMIter_New(&fiter, bmesh, BM_FACES, NULL);
+            face; face=BMIter_Step(&fiter)) {
+               /*figure out which pattern to use*/
+               if (face->len > MAX_FACE) continue;
+               if (BMO_TestFlag(bmesh, face, SUBD_SPLIT) == 0) continue;
+               
+               pat = facedata[i].pat;
+               if (!pat) continue;
+
+               j = a = 0;
+               for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+                    nl; nl=BMIter_Step(&liter)) {
+                       if (nl->v == facedata[i].start) {
+                               a = j+1;
+                               break;
                        }
+                       j++;
+               }
 
-                       for (i=0; i<newvlen; i++) {
-                               if (pat->secondstage_connect[i] != -1) {
-                                       edges[newlen++] = BM_Connect_Verts(bmesh, verts[i], verts[pat->secondstage_connect[i]], &nf);
-                                       BMO_SetFlag(bmesh, nf, FACE_NEW);
-                               }
-                       }
-               } else { /*no match in the pattern*/
-                       /*this should do some sort of generic subdivision*/
+               j = 0;
+               for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
+                    nl; nl=BMIter_Step(&liter)) {
+                       b = (j-a+face->len) % face->len;
+                       verts[b] = nl->v;
+                       j += 1;
                }
+               
+               pat->connectexec(bmesh, face, verts, numcuts, flag, rad);
+               i++;
        }
-}
\ No newline at end of file
+
+       if (facedata) V_FREE(facedata);
+}
+
+/*editmesh-emulating function*/
+void BM_esubdivideflag(Object *obedit, BMesh *bm, int flag, float rad, 
+                      int beauty, int numcuts, int seltype) {
+       BMOperator op;
+
+       BMO_Init_Op(&op, BMOP_ESUBDIVIDE);
+       BMO_Set_Int(&op, BMOP_ESUBDIVIDE_NUMCUTS, numcuts);
+       BMO_Set_Int(&op, BMOP_ESUBDIVIDE_FLAG, beauty);
+       BMO_Set_Float(&op, BMOP_ESUBDIVIDE_RADIUS, rad);
+       BMO_Set_Int(&op, BMOP_ESUBDIVIDE_SELACTION, seltype);
+       BMO_HeaderFlag_To_Slot(bm, &op, BMOP_ESUBDIVIDE_EDGES, flag, BM_EDGE);
+       
+       BMO_Exec_Op(bm, &op);
+       BMO_Finish_Op(bm, &op);
+}
index d79d8003ff0a2c1fc45bb4145816ac65be2be0ed..65c2930b7585867c79d0dd6cab5d13b44a55acab 100644 (file)
@@ -3301,7 +3301,11 @@ static int bmesh_test_exec(bContext *C, wmOperator *op)
 
        bm = editmesh_to_bmesh(em);
 
-#if 1
+#if 1 /*edge subdivide test*/
+       BM_esubdivideflag(obedit, bm, SELECT, 0, 0, G.rt==0?1:G.rt, 0);
+#endif
+
+#if 0
        /*dissolve vert test*/
        {
                        BMOperator op;
index cf4adc4a59cc9c4393dfa8af6a4d41eea4b21c9e..37d18be18200172b6979996b1aeef02a129b6478 100644 (file)
 #ifndef MESH_INTERN_H
 #define MESH_INTERN_H
 
+#include "BLI_editVert.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
 struct bContext;
 struct wmOperatorType;
 struct ViewContext;