Added a new slot type, that maps geometric elements to
authorJoseph Eagar <joeedh@gmail.com>
Mon, 9 Feb 2009 06:36:59 +0000 (06:36 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Mon, 9 Feb 2009 06:36:59 +0000 (06:36 +0000)
client-defined data.  Made edge subdivide use it.

Also removed the float and int slot buffer types, as per
discussion with Briggs, until such a time as we see
a use for them.

source/blender/bmesh/bmesh_operators.h
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/intern/bmesh_operators.c
source/blender/bmesh/operators/subdivideop.c
source/blender/bmesh/operators/subdivideop.h
source/blender/bmesh/operators/triangulateop.c
source/blender/editors/mesh/editmesh_loop.c

index 3debb0cbede29d78cc9a7c030e0c2961818a3fab..75f47f0d71e63f299964bea321c9a060919e08e2 100644 (file)
@@ -2,6 +2,7 @@
 #define BM_OPERATORS_H
 
 #include "BLI_memarena.h"
+#include "BLI_ghash.h"
 
 #define BMOP_OPSLOT_INT                        0
 #define BMOP_OPSLOT_FLT                        1
   dynamically allocated arrays.  we
   leave a space in the identifiers
   for future growth.*/
-#define BMOP_OPSLOT_INT_BUF            7
-#define BMOP_OPSLOT_FLT_BUF            8               
-#define BMOP_OPSLOT_PNT_BUF            9
-#define BMOP_OPSLOT_TYPES              10
+#define BMOP_OPSLOT_PNT_BUF            7
+
+#define BMOP_OPSLOT_MAPPING            8
+#define BMOP_OPSLOT_TYPES              9
 
 typedef struct BMOpSlot{
        int slottype;
        int len;
+       int flag;
        int index; /*index within slot array*/
        union {
                int i;
@@ -27,9 +29,14 @@ typedef struct BMOpSlot{
                void *p;                                        
                float vec[3];                           /*vector*/
                void *buf;                              /*buffer*/
+               GHash *ghash;
        } data;
 }BMOpSlot;
 
+/*BMOpSlot->flag*/
+/*is a dynamically-allocated array.  set at runtime.*/
+#define BMOS_DYNAMIC_ARRAY     1
+
 /*operators represent logical, executable mesh modules.*/
 #define BMOP_MAX_SLOTS                 16              /*way more than probably needed*/
 
@@ -54,6 +61,10 @@ typedef struct BMOpDefine {
 //doesn't do anything at the moment.
 
 /*API for operators*/
+
+/*data types that use pointers (arrays, etc) should never
+  have it set directly.  and never use BMO_Set_Pnt to
+  pass in a list of edges or any arrays, really.*/
 void BMO_Init_Op(struct BMOperator *op, int opcode);
 void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
 void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
@@ -61,8 +72,6 @@ BMOpSlot *BMO_GetSlot(struct BMOperator *op, int slotcode);
 void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op, int src, int dst);
 void BMO_Set_Float(struct BMOperator *op, int slotcode, float f);
 void BMO_Set_Int(struct BMOperator *op, int slotcode, int i);
-void BMO_Set_PntBuf(struct BMOperator *op, int slotcode, void *p, int len);
-void BMO_Set_FltBuf(BMOperator *op, int slotcode, float *p, int len);
 void BMO_Set_Pnt(struct BMOperator *op, int slotcode, void *p);
 void BMO_Set_Vec(struct BMOperator *op, int slotcode, float *vec);
 void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
@@ -72,6 +81,18 @@ int BMO_CountFlag(struct BMesh *bm, int flag, int type);
 void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag, int type);
 void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag);
 void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag, int type);
+int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, int slotcode);
+
+void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, int slotcode, 
+                       void *element, void *data, int len);
+void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, int slotcode, 
+                       void *element, float val);
+void *BMO_Get_MapData(BMesh *bm, BMOperator *op, int slotcode,
+                     void *element);
+float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, int slotcode,
+                      void *element);
+void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op, 
+                        int slotcode, int flag);
 
 /*if msg is null, then the default message for the errorcode is used*/
 void BMOP_RaiseError(BMesh *bm, int errcode, char *msg);
@@ -159,12 +180,20 @@ enum {
        BMOP_ESUBDIVIDE_RADIUS,
        BMOP_ESUBDIVIDE_SELACTION,
 
-       BMOP_ESUBDIVIDE_CUSTOMFILL_FACES,
-       BMOP_ESUBDIVIDE_CUSTOMFILL_PATTERNS,
+       BMOP_ESUBDIVIDE_CUSTOMFILL_FACEMAP,
+       BMOP_ESUBDIVIDE_PERCENT_EDGEMAP,
 
-       BMOP_ESUBDIVIDE_PERCENT_EDGES,
-       BMOP_ESUBDIVIDE_PERCENT_VALUES,
+       /*inner verts/new faces of completely filled faces, e.g.
+         fully selected face.*/
+       BMOP_ESUBDIVIDE_INNER_MULTOUT,
 
+       /*new edges and vertices from splitting original edges,
+         doesn't include edges creating by connecting verts.*/
+       BMOP_ESUBDIVIDE_SPLIT_MULTOUT,
+       
+       /*edges created by connecting verts, except for those created
+         by fully-filled faces (e.g. fully selected faces).*/
+       BMOP_ESUBDIVIDE_CONNECT_MULTOUT,
        BMOP_ESUBDIVIDE_TOTSLOT,
 };
 /*
index b26b594037586d174b4e10d3d95fda2aa31e7510..dbf3656a3b868655e4ed642acabcded6c1ed11cb 100644 (file)
@@ -39,10 +39,12 @@ BMOpDefine def_subdop = {
         BMOP_OPSLOT_INT,
         BMOP_OPSLOT_FLT,
         BMOP_OPSLOT_INT,
+        BMOP_OPSLOT_MAPPING,
+        BMOP_OPSLOT_MAPPING,
         BMOP_OPSLOT_PNT_BUF,
         BMOP_OPSLOT_PNT_BUF,
         BMOP_OPSLOT_PNT_BUF,
-        BMOP_OPSLOT_FLT_BUF},
+        },
        esubdivide_exec,
        BMOP_ESUBDIVIDE_TOTSLOT,
        0
index f58c2d6c0cbc05b56370d2b4d332e1c27da21fee..da0c794ec584a0f744382d3eb953bf182023ab20 100644 (file)
@@ -17,18 +17,24 @@ static void clear_flag_layer(BMesh *bm);
 
 typedef void (*opexec)(struct BMesh *bm, struct BMOperator *op);
 
+/*mappings map elements to data, which
+  follows the mapping struct in memory.*/
+typedef struct element_mapping {
+       BMHeader *element;
+       int len;
+} element_mapping;
+
+
 /*operator slot type information - size of one element of the type given.*/
-const int BMOP_OPSLOT_TYPEINFO[BMOP_OPSLOT_TYPES] = {
+const int BMOP_OPSLOT_TYPEINFO[] = {
        sizeof(int),
        sizeof(float),
        sizeof(void*),
        0, /* unused */
        0, /* unused */
        0, /* unused */
-       sizeof(float)*3,
-       sizeof(int),    /* int buffer */
-       sizeof(float),  /* float buffer */
-       sizeof(void*)   /* pointer buffer */
+       sizeof(void*),  /* pointer buffer */
+       sizeof(element_mapping)
 };
 
 /*
@@ -132,6 +138,17 @@ void BMO_Exec_Op(BMesh *bm, BMOperator *op)
 
 void BMO_Finish_Op(BMesh *bm, BMOperator *op)
 {
+       BMOpSlot *slot;
+       int i;
+
+       for (i=0; i<opdefines[op->type]->totslot; i++) {
+               slot = &op->slots[i];
+               if (slot->slottype == BMOP_OPSLOT_MAPPING) {
+                       if (slot->data.ghash) 
+                               BLI_ghash_free(slot->data.ghash, NULL, NULL);
+               }
+       }
+
        BLI_memarena_free(op->arena);
 }
 
@@ -203,30 +220,13 @@ void BMO_Set_Int(BMOperator *op, int slotcode, int i)
 }
 
 
-void BMO_Set_PntBuf(BMOperator *op, int slotcode, void *p, int len)
-{
-       if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_PNT_BUF) )
-               return;
-
-       op->slots[slotcode].data.p = p;
-       op->slots[slotcode].len = len;
-}
-
-void BMO_Set_FltBuf(BMOperator *op, int slotcode, float *p, int len)
-{
-       if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_FLT_BUF) )
-               return;
-
-       op->slots[slotcode].data.p = p;
-       op->slots[slotcode].len = len;
-}
-
 void BMO_Set_Pnt(BMOperator *op, int slotcode, void *p)
 {
        if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_PNT) )
                return;
        op->slots[slotcode].data.p = p;
 }
+
 void BMO_Set_Vec(BMOperator *op, int slotcode, float *vec)
 {
        if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_VEC) )
@@ -312,6 +312,119 @@ int BMO_CountFlag(BMesh *bm, int flag, int type)
        return count;   
 }
 
+int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, int slotcode)
+{
+       BMOpSlot *slot = &op->slots[slotcode];
+       
+       /*check if its actually a buffer*/
+       if( !(slot->slottype > BMOP_OPSLOT_VEC) )
+               return 0;
+
+       return slot->len;
+}
+
+#if 0
+void *BMO_Grow_Array(BMesh *bm, BMOperator *op, int slotcode, int totadd) {
+       BMOpSlot *slot = &op->slots[slotcode];
+       void *tmp;
+       
+       /*check if its actually a buffer*/
+       if( !(slot->slottype > BMOP_OPSLOT_VEC) )
+               return NULL;
+
+       if (slot->flag & BMOS_DYNAMIC_ARRAY) {
+               if (slot->len >= slot->size) {
+                       slot->size = (slot->size+1+totadd)*2;
+
+                       tmp = slot->data.buf;
+                       slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->size, "opslot dynamic array");
+                       memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->size);
+                       MEM_freeN(tmp);
+               }
+
+               slot->len += totadd;
+       } else {
+               slot->flag |= BMOS_DYNAMIC_ARRAY;
+               slot->len += totadd;
+               slot->size = slot->len+2;
+               tmp = slot->data.buf;
+               slot->data.buf = MEM_callocN(BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->len, "opslot dynamic array");
+               memcpy(slot->data.buf, tmp, BMOP_OPSLOT_TYPEINFO[opdefines[op->type]->slottypes[slotcode]] * slot->len);
+       }
+
+       return slot->data.buf;
+}
+#endif
+
+void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, int slotcode, 
+                       void *element, void *data, int len) {
+       element_mapping *mapping;
+       BMOpSlot *slot = &op->slots[slotcode];
+
+       /*sanity check*/
+       if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
+       
+       mapping = BLI_memarena_alloc(op->arena, sizeof(*mapping) + len);
+
+       mapping->element = element;
+       mapping->len = len;
+       memcpy(mapping+1, data, len);
+
+       if (!slot->data.ghash) {
+               slot->data.ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, 
+                                                    BLI_ghashutil_ptrcmp);
+       }
+       
+       BLI_ghash_insert(slot->data.ghash, element, mapping);
+}
+
+void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op, 
+                        int slotcode, int flag)
+{
+       GHashIterator it;
+       BMOpSlot *slot = &op->slots[slotcode];
+       BMHeader *ele;
+
+       /*sanity check*/
+       if (slot->slottype != BMOP_OPSLOT_MAPPING) return;
+       if (!slot->data.ghash) return;
+
+       BLI_ghashIterator_init(&it, slot->data.ghash);
+       for (;ele=BLI_ghashIterator_getKey(&it);BLI_ghashIterator_step(&it)) {
+               BMO_SetFlag(bm, ele, flag);
+       }
+}
+
+void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, int slotcode, 
+                       void *element, float val)
+{
+       BMO_Insert_Mapping(bm, op, slotcode, element, &val, sizeof(float));
+}
+
+void *BMO_Get_MapData(BMesh *bm, BMOperator *op, int slotcode,
+                     void *element)
+{
+       element_mapping *mapping;
+       BMOpSlot *slot = &op->slots[slotcode];
+
+       /*sanity check*/
+       if (slot->slottype != BMOP_OPSLOT_MAPPING) return NULL;
+       if (!slot->data.ghash) return NULL;
+
+       mapping = BLI_ghash_lookup(slot->data.ghash, element);
+       
+       return mapping + 1;
+}
+
+float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, int slotcode,
+                      void *element)
+{
+       float *val = BMO_Get_MapData(bm, op, slotcode, element);
+       if (val) return *val;
+
+       return 0.0f;
+}
+
 static void *alloc_slot_buffer(BMOperator *op, int slotcode, int len){
 
        /*check if its actually a buffer*/
index 810ecd10319979f3efb1e5bf49b29e081ab23f2b..8dbe90aa34a977f626d4b0e154863d5ac096c138 100644 (file)
@@ -147,7 +147,8 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge,
        float percent;
         
        if (BMO_TestFlag(bm, edge, EDGE_PERCENT) && totpoint == 1)
-               percent= *((float*)BLI_ghash_lookup(params->percenthash,edge));
+               percent = BMO_Get_MapFloat(bm, params->op, 
+                                       BMOP_ESUBDIVIDE_PERCENT_EDGEMAP, edge);
        else {
                percent= 1.0f/(float)(totpoint+1-curpoint);
 
@@ -573,7 +574,7 @@ typedef struct subd_facedata {
 
 void esubdivide_exec(BMesh *bmesh, BMOperator *op)
 {
-       BMOpSlot *einput, *finput, *pinput;
+       BMOpSlot *einput;
        BMEdge *edge, **edges = NULL;
        V_DECLARE(edges);
        BMFace *face;
@@ -581,7 +582,6 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
        BMVert **verts = NULL;
        V_DECLARE(verts);
        BMIter fiter, liter;
-       GHash *customfill_hash, *percent_hash; 
        subdpattern *pat;
        subdparams params;
        subd_facedata *facedata = NULL;
@@ -605,35 +605,17 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                BMO_SetFlag(bmesh, edge, SUBD_SPLIT);
        }
        
-       customfill_hash = BLI_ghash_new(BLI_ghashutil_ptrhash,
-                                       BLI_ghashutil_ptrcmp);
-       percent_hash = BLI_ghash_new(BLI_ghashutil_ptrhash,
-                                       BLI_ghashutil_ptrcmp);
-
-       /*process custom fill patterns*/
-       finput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_CUSTOMFILL_FACES);
-       pinput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_CUSTOMFILL_PATTERNS);
-       for (i=0; i<finput->len; i++) {
-               face = ((BMFace**)finput->data.p)[i];
-               BMO_SetFlag(bmesh, face, FACE_CUSTOMFILL);
-               BLI_ghash_insert(customfill_hash, face,
-                               ((void**)pinput->data.p)[i]);
-       }
-       
-       einput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_PERCENT_EDGES);
-       pinput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_PERCENT_VALUES);
-       
-       for (i=0; i<einput->len; i++) {
-               edge = ((BMEdge**)einput->data.p)[i];
-               BMO_SetFlag(bmesh, edge, EDGE_PERCENT);
-               BLI_ghash_insert(percent_hash, edge, ((float*)pinput->data.p)+i);
-       }
-       
        params.flag = flag;
        params.numcuts = numcuts;
-       params.percenthash = percent_hash;
+       params.op = op;
        params.rad = rad;
 
+       BMO_Mapping_To_Flag(bmesh, op, BMOP_ESUBDIVIDE_CUSTOMFILL_FACEMAP,
+                           FACE_CUSTOMFILL);
+
+       BMO_Mapping_To_Flag(bmesh, op, BMOP_ESUBDIVIDE_PERCENT_EDGEMAP,
+                           EDGE_PERCENT);
+
        for (face=BMIter_New(&fiter, bmesh, BM_FACES, NULL);
             face; face=BMIter_Step(&fiter)) {
                /*figure out which pattern to use*/
@@ -651,7 +633,8 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
                }
 
                if (BMO_TestFlag(bmesh, face, FACE_CUSTOMFILL)) {
-                       pat = BLI_ghash_lookup(customfill_hash, face);
+                       pat = BMO_Get_MapData(bmesh, op, 
+                                   BMOP_ESUBDIVIDE_CUSTOMFILL_FACEMAP, face);
                        for (i=0; i<pat->len; i++) {
                                matched = 1;
                                for (j=0; j<pat->len; j++) {
index 2c669f60e2c21a66a11852b46d4735e402ed9bde..7404f189e456cb00d1b87d820f5fde40e413fe11 100644 (file)
@@ -5,7 +5,7 @@ typedef struct subdparams {
        int numcuts;
        int flag;
        float rad;
-       GHash *percenthash;
+       BMOperator *op;
 } subdparams;
 
 typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, 
index f8ef5f2f64e41bc9e0db792283434f8592331a12..d79b94e0fb8dc804c4fbb19e340edebfab17e239 100644 (file)
@@ -19,7 +19,6 @@ void triangulate_exec(BMesh *bmesh, BMOperator *op)
        BMFace *face;
        float (*projectverts)[3] = NULL;
        V_DECLARE(projectverts);
-       void *projverts;
        int i, lastlen=0, count = 0;
        
        finput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_EDGES);
@@ -37,8 +36,6 @@ void triangulate_exec(BMesh *bmesh, BMOperator *op)
                }
                
                BM_Triangulate_Face(bmesh, face, projectverts, EDGE_NEW, FACE_NEW);
-               
-               if (projverts != projectverts) MEM_freeN(projverts);
        }
        
        BMO_Flag_To_Slot(bmesh, op, BMOP_TRIANG_NEW_EDGES, EDGE_NEW, BM_EDGE);
index e5682726844bef953ab1a8c5f4a03acf3c804638..db423304ad3d5d5dad63d5cc67f7e2564d9f9d3b 100644 (file)
@@ -787,14 +787,12 @@ static int knife_cut_exec(bContext *C, wmOperator *op)
        BMVert *bv;
        BMIter iter;
        BMEdge **edges = NULL, *be;
-       V_DECLARE(edges);
        BMOperator bmop;
        CutCurve curve[MAX_CUTS];
        struct GHash *gh;
        float isect=0.0;
        float  *scr, co[4], *percents = NULL;
-       V_DECLARE(percents);
-       int len=0, isected, flag;
+       int len=0, isected, flag, i;
        short numcuts=1, mode= RNA_int_get(op->ptr, "type");
        
        if (EM_nvertices_selected(em) < 2) {
@@ -826,34 +824,34 @@ static int knife_cut_exec(bContext *C, wmOperator *op)
                BLI_ghash_insert(gh, bv, scr);
        }
        
+       BMO_Init_Op(&bmop, BMOP_ESUBDIVIDE);
+       
+       i = 0;
        /*store percentage of edge cut for KNIFE_EXACT here.*/
        for (be=BMIter_New(&iter, bm, BM_EDGES, NULL); be; be=BMIter_Step(&iter)) {
                if( BM_Is_Selected(bm, be) ) {
                        isect= bm_seg_intersect(be, curve, len, mode, gh, &isected);
                        
                        if (isect != 0.0f) {
-                               V_GROW(edges);
-                               V_GROW(percents);
-                               edges[V_COUNT(edges)-1] = be;
-                               percents[V_COUNT(percents)-1] = isect;
+                               if (mode != KNIFE_MULTICUT) {
+                                       BMO_Insert_MapFloat(bm, &bmop, 
+                                              BMOP_ESUBDIVIDE_PERCENT_EDGEMAP,
+                                              be, isect);
+
+                               }
+                               BMO_SetFlag(bm, be, 1);
                        }
                }
        }
-               
-       BMO_Init_Op(&bmop, BMOP_ESUBDIVIDE);
        
+       BMO_Flag_To_Slot(bm, &bmop, BMOP_ESUBDIVIDE_EDGES, 1, BM_EDGE);
+
        BMO_Set_Int(&bmop, BMOP_ESUBDIVIDE_NUMCUTS, numcuts);
        flag = B_KNIFE;
        if (mode == KNIFE_MIDPOINT) numcuts = 1;
-       else if (mode != KNIFE_MULTICUT) {
-               BMO_Set_PntBuf(&bmop, BMOP_ESUBDIVIDE_PERCENT_EDGES, edges, V_COUNT(edges));
-               BMO_Set_FltBuf(&bmop, BMOP_ESUBDIVIDE_PERCENT_VALUES, percents, V_COUNT(percents));
-       }
-
        BMO_Set_Int(&bmop, BMOP_ESUBDIVIDE_FLAG, flag);
        BMO_Set_Float(&bmop, BMOP_ESUBDIVIDE_RADIUS, 0);
        BMO_Set_Int(&bmop, BMOP_ESUBDIVIDE_SELACTION, SUBDIV_SELECT_ORIG);
-       BMO_Set_PntBuf(&bmop, BMOP_ESUBDIVIDE_EDGES, edges, V_COUNT(edges));
        
        BMO_Exec_Op(bm, &bmop);
        BMO_Finish_Op(bm, &bmop);