merge with 2.5 at r18865
authorJoseph Eagar <joeedh@gmail.com>
Sun, 8 Feb 2009 14:25:04 +0000 (14:25 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Sun, 8 Feb 2009 14:25:04 +0000 (14:25 +0000)
1  2 
source/blender/blenkernel/BKE_utildefines.h
source/blender/bmesh/bmesh_operators.h
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/operators/subdivideop.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/mesh_intern.h

index 0eccf0cf56b2723836e3c6080476bd9a33aa846f,6584af085cd5c962e9cc36ef66f32900b17a99d2..605858bef58c20755336266d8d217fc95e73e87f
  #define SET_INT_IN_POINTER(i) ((void*)(intptr_t)(i))
  #define GET_INT_FROM_POINTER(i) ((int)(intptr_t)(i))
  
- #define V_SIZE(vec) ((vec)==NULL ? 0 : MEM_allocN_len(vec) / sizeof(*vec))
 +/*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);
 +
 +arrays are buffered, using double-buffering (so on each reallocation,
 +the array size is doubled).  supposedly this should give good Big Oh
 +behaviour, though it may not be the best in practice.
 +*/
 +
 +#define V_DECLARE(vec) int _##vec##_count=0; void *_##vec##_tmp
 +
 +/*this returns the entire size of the array, including any buffering.*/
++#define V_SIZE(vec) ((signed int)((vec)==NULL ? 0 : MEM_allocN_len(vec) / sizeof(*vec)))
 +
 +/*this returns the logical size of the array, not including buffering.*/
 +#define V_COUNT(vec) _##vec##_count
 +
 +/*grow the array by one.  zeroes the new elements.*/
 +#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++)
 +
 +#define V_FREE(vec) if (vec) MEM_freeN(vec);
 +/*resets the logical size of an array to zero, but doesn't
 +  free the memory.*/
 +#define V_RESET(vec) _##vec##_count=0
 +
  #endif
  
index ed12cf3b81152c15e55365a690ee75d5d47f8b6b,0000000000000000000000000000000000000000..9f0d6cb1c8c1b5ef5b24d0ef529becae8376a09a
mode 100644,000000..100644
--- /dev/null
@@@ -1,213 -1,0 +1,220 @@@
 +#ifndef BM_OPERATORS_H
 +#define BM_OPERATORS_H
 +
 +#include "BLI_memarena.h"
 +
 +#define BMOP_OPSLOT_INT                       0
 +#define BMOP_OPSLOT_FLT                       1
 +#define BMOP_OPSLOT_PNT                       2
 +#define BMOP_OPSLOT_VEC                       6
 +
 +/*after BMOP_OPSLOT_VEC, everything is 
 +  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
 +
 +typedef struct BMOpSlot{
 +      int slottype;
 +      int len;
 +      int index; /*index within slot array*/
 +      union {
 +              int i;
 +              float f;                                        
 +              void *p;                                        
 +              float vec[3];                           /*vector*/
 +              void *buf;                              /*buffer*/
 +      } data;
 +}BMOpSlot;
 +
 +/*operators represent logical, executable mesh modules.*/
 +#define BMOP_MAX_SLOTS                        16              /*way more than probably needed*/
 +
 +typedef struct BMOperator{
 +      int type;
 +      int slottype;
 +      int needflag;
 +      struct BMOpSlot slots[BMOP_MAX_SLOTS];
 +      void (*exec)(struct BMesh *bm, struct BMOperator *op);
 +      MemArena *arena;
 +}BMOperator;
 +
 +/*need to refactor code to use this*/
 +typedef struct BMOpDefine {
 +      int slottypes[BMOP_MAX_SLOTS];
 +      void (*exec)(BMesh *bm, BMOperator *op);
 +      int totslot;
 +      int flag;
 +} BMOpDefine;
 +
 +/*BMOpDefine->flag*/
 +//doesn't do anything at the moment.
 +
 +/*API for operators*/
 +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);
 +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_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);
 +void BMO_ClearFlag(struct BMesh *bm, void *element, int flag);
 +int BMO_TestFlag(struct BMesh *bm, void *element, int flag);
 +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);
 +
 +/*if msg is null, then the default message for the errorcode is used*/
 +void BMOP_RaiseError(BMesh *bm, int errcode, char *msg);
 +/*returns error code or 0 if no error*/
 +int BMOP_GetError(BMesh *bm, char **msg);
 +/*returns 1 if there was an error*/
 +int BMOP_CheckError(BMesh *bm);
 +int BMOP_PopError(BMesh *bm, char **msg);
 +
 +/*------ error code defines -------*/
 +
 +/*error messages*/
 +#define BMERR_SELF_INTERSECTING        1
 +
 +static char *bmop_error_messages[] = {
 +       0,
 +       "Self intersection error",
 +};
 +
 +/*------------begin operator defines (see bmesh_opdefines.c too)------------*/
 +/*split op*/
 +#define BMOP_SPLIT                            0
 +
 +enum {
 +      BMOP_SPLIT_MULTIN,
 +      BMOP_SPLIT_MULTOUT,
 +      BMOP_SPLIT_TOTSLOT,
 +};
 +
 +/*dupe op*/
 +#define BMOP_DUPE     1
 +
 +enum {
 +      BMOP_DUPE_MULTIN,
 +      BMOP_DUPE_ORIG,
 +      BMOP_DUPE_NEW,
 +      BMOP_DUPE_TOTSLOT
 +};
 +
 +/*delete op*/
 +#define BMOP_DEL      2
 +
 +enum {
 +      BMOP_DEL_MULTIN,
 +      BMOP_DEL_CONTEXT,
 +      BMOP_DEL_TOTSLOT,
 +};
 +
 +#define DEL_VERTS             1
 +#define DEL_EDGES             2
 +#define DEL_ONLYFACES 3
 +#define DEL_EDGESFACES        4
 +#define DEL_FACES             5
 +#define DEL_ALL                       6
 +
 +/*BMOP_DEL_CONTEXT*/
 +enum {
 +      BMOP_DEL_VERTS = 1,
 +      BMOP_DEL_EDGESFACES,
 +      BMOP_DEL_ONLYFACES,
 +      BMOP_DEL_FACES,
 +      BMOP_DEL_ALL,
 +};
 +
 +/*editmesh->bmesh op*/
 +#define BMOP_FROM_EDITMESH            3
 +enum {
 +      BMOP_FROM_EDITMESH_EM,
 +      BMOP_FROM_EDITMESH_TOTSLOT,
 +};
 +
 +#define BMOP_TO_EDITMESH              4
 +/*bmesh->editmesh op*/
 +enum {
 +      BMOP_TO_EDITMESH_EMOUT,
 +      BMOP_TO_EDITMESH_TOTSLOT,
 +};
 +
 +/*edge subdivide op*/
 +#define BMOP_ESUBDIVIDE                       5
 +enum {
 +      BMOP_ESUBDIVIDE_EDGES,
 +      BMOP_ESUBDIVIDE_NUMCUTS,
 +      BMOP_ESUBDIVIDE_FLAG, //beauty flag in esubdivide
 +      BMOP_ESUBDIVIDE_RADIUS,
 +      BMOP_ESUBDIVIDE_SELACTION,
++
++      BMOP_ESUBDIVIDE_CUSTOMFILL_FACES,
++      BMOP_ESUBDIVIDE_CUSTOMFILL_PATTERNS,
++
++      BMOP_ESUBDIVIDE_PERCENT_VERTS,
++      BMOP_ESUBDIVIDE_PERCENT_VALUES,
++
 +      BMOP_ESUBDIVIDE_TOTSLOT,
 +};
 +/*
 +SUBDIV_SELECT_INNER
 +SUBDIV_SELECT_ORIG
 +SUBDIV_SELECT_INNER_SEL
 +SUBDIV_SELECT_LOOPCUT
 +DOUBLEOPFILL
 +*/
 +
 +/*triangulate*/
 +#define BMOP_TRIANGULATE              6
 +
 +enum {
 +      BMOP_TRIANG_FACEIN,
 +      BMOP_TRIANG_NEW_EDGES,
 +      BMOP_TRIANG_NEW_FACES,
 +      BMOP_TRIANG_TOTSLOT,
 +};
 +
 +/*dissolve faces*/
 +#define BMOP_DISSOLVE_FACES           7
 +
 +#define BMOP_DISFACES_FACEIN  0
 +#define BMOP_DISFACES_TOTSLOT 1
 +
 +/*dissolve verts*/
 +#define BMOP_DISSOLVE_VERTS           8
 +
 +#define BMOP_DISVERTS_VERTIN  0
 +#define BMOP_DISVERTS_TOTSLOT 1
 +
 +#define BMOP_MAKE_FGONS                       9
 +#define BMOP_MAKE_FGONS_TOTSLOT       0
 +
 +/*keep this updated!*/
 +#define BMOP_TOTAL_OPS                        10
 +/*-------------------------------end operator defines-------------------------------*/
 +
 +extern BMOpDefine *opdefines[];
 +extern int bmesh_total_ops;
 +
 +/*------specific operator helper functions-------*/
 +
 +/*executes the duplicate operation, feeding elements of 
 +  type flag etypeflag and header flag flag to it.  note,
 +  to get more useful information (such as the mapping from
 +  original to new elements) you should run the dupe op manually.*/
 +struct Object;
 +
 +void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
 +void BM_esubdivideflag(struct Object *obedit, struct BMesh *bm, int selflag, float rad, 
 +                     int flag, int numcuts, int seltype);
 +#endif
index 49e51e11e31b6d1a1f5b391f6b5dbdfa07651bab,0000000000000000000000000000000000000000..ac13f8319a6453e7fcdc2614ae85949dad30061c
mode 100644,000000..100644
--- /dev/null
@@@ -1,95 -1,0 +1,99 @@@
-        BMOP_OPSLOT_INT},
 +#include "bmesh.h"
 +#include "bmesh_private.h"
 +
 +#include <stdio.h>
 +
 +BMOpDefine def_makefgonsop = {
 +      {0},
 +      bmesh_make_fgons_exec,
 +      BMOP_MAKE_FGONS_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_dissolvevertsop = {
 +      {BMOP_OPSLOT_PNT_BUF},
 +      dissolveverts_exec,
 +      BMOP_DISVERTS_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_dissolvefacesop = {
 +      {BMOP_OPSLOT_PNT_BUF},
 +      dissolvefaces_exec,
 +      BMOP_DISFACES_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_triangop = {
 +      {BMOP_OPSLOT_PNT_BUF, 
 +       BMOP_OPSLOT_PNT_BUF,
 +       BMOP_OPSLOT_PNT_BUF},
 +      triangulate_exec,
 +      BMOP_TRIANG_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_subdop = {
 +      {BMOP_OPSLOT_PNT_BUF,
 +       BMOP_OPSLOT_INT,
 +       BMOP_OPSLOT_INT,
 +       BMOP_OPSLOT_FLT,
++       BMOP_OPSLOT_INT,
++       BMOP_OPSLOT_PNT_BUF,
++       BMOP_OPSLOT_PNT_BUF,
++       BMOP_OPSLOT_PNT_BUF,
++       BMOP_OPSLOT_FLT},
 +      esubdivide_exec,
 +      BMOP_ESUBDIVIDE_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_edit2bmesh = {
 +      {BMOP_OPSLOT_PNT},
 +      edit2bmesh_exec,
 +      BMOP_TO_EDITMESH_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_bmesh2edit = {
 +      {BMOP_OPSLOT_PNT},
 +      bmesh2edit_exec,
 +      BMOP_FROM_EDITMESH_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_delop = {
 +      {BMOP_OPSLOT_PNT_BUF, BMOP_OPSLOT_INT},
 +      delop_exec,
 +      BMOP_DEL_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_dupeop = {
 +      {BMOP_OPSLOT_PNT_BUF, BMOP_OPSLOT_PNT_BUF, BMOP_OPSLOT_PNT_BUF},
 +      dupeop_exec,
 +      BMOP_DUPE_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine def_splitop = {
 +      {BMOP_OPSLOT_PNT_BUF, BMOP_OPSLOT_PNT_BUF},
 +      splitop_exec,
 +      BMOP_SPLIT_TOTSLOT,
 +      0
 +};
 +
 +BMOpDefine *opdefines[] = {
 +      &def_splitop,
 +      &def_dupeop,
 +      &def_delop,
 +      &def_edit2bmesh,
 +      &def_bmesh2edit,
 +      &def_subdop,
 +      &def_triangop,
 +      &def_dissolvefacesop,
 +      &def_dissolvevertsop,
 +      &def_makefgonsop,
 +};
 +
 +int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
index c94381a3f2054d0a85f6f1883af25321da662014,0000000000000000000000000000000000000000..076f47786ba6ae4c505de176351808cb04e42333
mode 100644,000000..100644
--- /dev/null
@@@ -1,744 -1,0 +1,778 @@@
- #define FACE_NEW      1
- #define MAX_FACE      800
 +#include "MEM_guardedalloc.h"
 +
 +#include "BKE_utildefines.h"
 +
 +#include "BLI_arithb.h"
 +#include "BLI_rand.h"
++#include "BLI_ghash.h"
 +
 +#include "DNA_object_types.h"
 +
 +#include "ED_mesh.h"
 +
 +#include "bmesh.h"
 +#include "mesh_intern.h"
++#include "subdivideop.h"
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <math.h>
 +
 +#define SUBD_SPLIT    1
++
++/*I don't think new faces are flagged, currently, but
++  better safe than sorry.*/
++#define FACE_NEW      2
++#define FACE_CUSTOMFILL       4
 +
 +/*stuff for the flag paramter.  note that
 +  what used to live in "beauty" and
 +  in "seltype" live here.  still have to
 +  convert the beauty flags over, which
 +  is why it starts at 128 (to avoid
 +  collision).*/
 +#define SELTYPE_INNER 128
 +
- /*
- 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
-       /*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 flag, float rad);
-       int len; /*total number of verts*/
- } subdpattern;
 +/*
 +NOTE: beauty has been renamed to flag!
 +*/
 +
-       BMOpSlot *einput;
-       BMEdge *edge, **edges = NULL;
 +/*generic subdivision rules:
 +  
 +  * two selected edges in a face should make a link
 +    between them.
 +
 +  * one edge should do, what? make pretty topology, or just
 +    split the edge only?
 +*/
 +
 +/* calculates offset for co, based on fractal, sphere or smooth settings  */
 +static void alter_co(float *co, BMEdge *edge, float rad, int flag, float perc,
 +                   BMVert *vsta, BMVert *vend)
 +{
 +      float vec1[3], fac;
 +      
 +      if(flag & B_SMOOTH) {
 +              /* we calculate an offset vector vec1[], to be added to *co */
 +              float len, fac, nor[3], nor1[3], nor2[3];
 +              
 +              VecSubf(nor, vsta->co, vend->co);
 +              len= 0.5f*Normalize(nor);
 +      
 +              VECCOPY(nor1, vsta->no);
 +              VECCOPY(nor2, vend->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(vsta->co, vend->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);
 +              }
 +
 +      }
 +}
 +
 +/* assumes in the edge is the correct interpolated vertices already */
 +/* percent defines the interpolation, rad and flag 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 flag, float percent, BMEdge **out,
 +                                       BMVert *vsta, BMVert *vend)
 +{
 +      BMVert *ev;
 +//    float co[3];
 +      
 +      ev = BM_Split_Edge(bm, edge->v1, edge, out, percent, 1);
 +      if (flag & SELTYPE_INNER) BM_Select_Vert(bm, ev, 1);
 +
 +      /* offset for smooth or sphere or fractal */
 +      alter_co(ev->co, edge, rad, flag, percent, vsta, vend);
 +
 +#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;
 +}
 +
 +static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, 
 +                              int curpoint, int totpoint, float rad, 
 +                              int flag, BMEdge **newe,
 +                              BMVert *vsta, BMVert *vend)
 +{
 +      BMVert *ev;
 +      float percent;
 +       
 +      if (flag & (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);
 +
 +      }
 +      
 +      /*{
 +              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);
 +*/
 +              ev= bm_subdivide_edge_addvert(bm, edge, rad, flag, percent, 
 +                                     newe, vsta, vend);
 +              
 +/*            VECCOPY(ev->co, co2);
 +      }
 +*/    
 +      return ev;
 +}
 +
 +static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, float rad,
 +                                int flag, int numcuts, 
 +                                BMVert *vsta, BMVert *vend) {
 +      BMEdge *eed = edge, *newe;
 +      BMVert *v;
 +      int i;
 +
 +      for(i=0;i<numcuts;i++) {
 +              v = subdivideedgenum(bm, eed, i, numcuts, rad, 
 +                      flag, &newe, vsta, vend);
 +              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*/
 +
 +/*
 +     
 +v3---------v2
 +|          |
 +|          |
 +|          |
 +|          |
 +v4---v0---v1
 +
 +*/
 +static void q_1edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
 +                        int flag, 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, 0, 0, 0},
 +      q_1edge_split,
 +      4,
 +};
 +
 +
 +/*
 + 
 +v4---v3---v2
 +|     s    |
 +|          |
 +|          |
 +|     s    |
 +v5---v0---v1
 +
 +*/
++
 +static void q_2edge_op_split(BMesh *bm, BMFace *face, BMVert **vlist, 
 +                           int numcuts, int flag, 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,
 +};
 +
 +/*
 +v6--------v5
 +|          |
 +|          |v4s
 +|          |v3s
 +|   s  s   |
 +v7-v0--v1-v2
 +
 +*/
 +static void q_2edge_split(BMesh *bm, BMFace *face, BMVert **vlist, 
 +                           int numcuts, int flag, 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);
 +}
 +
 +subdpattern q_2edge = {
 +      {1, 1, 0, 0},
 +      q_2edge_split,
 +      4,
 +};
 +
 +/*  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 flag, 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, 0},
 +      q_3edge_split,
 +      4,
 +};
 +
 +/*
 + 
 +           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 flag, float rad) {
 +      BMFace *nf;
 +      BMVert *v, *v1, *v2;
 +      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)];
 +      }
 +
 +      /*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);
 +              if (flag & SELTYPE_INNER) {
 +                      BM_Select_Edge(bm, e, 1);
 +                      BM_Select_Face(bm, nf, 1);
 +              }
 +              
 +              v1 = lines[(i+1)*s] = vlist[a];
 +              v2 = lines[(i+1)*s + s-1] = vlist[b];
 +
 +              for (a=0; a<numcuts; a++) {
 +                      v = subdivideedgenum(bm, e, a, numcuts, rad, flag, &ne,
 +                                           v1, v2);
 +                      if (flag & SELTYPE_INNER) {
 +                              BM_Select_Edge(bm, ne, 1);
 +                      }
 +                      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;
 +                      e = BM_Connect_Verts(bm, lines[a], lines[b], &nf);
 +                      if (flag & SELTYPE_INNER) {
 +                              BM_Select_Edge(bm, e, 1);
 +                              BM_Select_Face(bm, nf, 1);
 +                      }
 +              }
 +      }
 +
 +      MEM_freeN(lines);
 +}
 +
 +/*    v3
 +     / \
 +    /   \
 +   /     \
 +  /       \
 + /         \
 +v4--v0--v1--v2
 +    s    s
 +*/
 +static void t_1edge_split(BMesh *bm, BMFace *face, BMVert **vlist, 
 +                           int numcuts, int flag, float rad) {
 +      BMFace *nf;
 +      int i;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              BM_Connect_Verts(bm, vlist[i], vlist[numcuts+1], &nf);
 +      }
 +}
 +
 +subdpattern t_1edge = {
 +      {1, 0, 0},
 +      t_1edge_split,
 +      3,
 +};
 +
 +/*    v5
 +     / \
 +    /   \ v4 s
 +   /     \
 +  /       \ v3 s
 + /         \
 +v6--v0--v1--v2
 +    s   s
 +*/
 +static void t_2edge_split(BMesh *bm, BMFace *face, BMVert **vlist, 
 +                           int numcuts, int flag, float rad) {
 +      BMFace *nf;
 +      int i;
 +      
 +      for (i=0; i<numcuts; i++) {
 +              BM_Connect_Verts(bm, vlist[i], vlist[numcuts+numcuts-i], &nf);
 +      }
 +}
 +
 +subdpattern t_2edge = {
 +      {1, 1, 0},
 +      t_2edge_split,
 +      3,
 +};
 +
 +
 +/*     v5
 +      / \
 + s v6/---\ v4 s
 +    / \ / \
 +sv7/---v---\ v3 s
 +  /  \/  \/ \
 + v8--v0--v1--v2
 +    s    s
 +*/
 +static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **vlist, 
 +                           int numcuts, int flag, float rad) {
 +      BMFace *nf;
 +      BMEdge *e, *ne;
 +      BMVert ***lines, *v;
 +      void *stackarr[1];
 +      int i, j, a, b;
 +      
 +      /*number of verts in each line*/
 +      lines = MEM_callocN(sizeof(void*)*(numcuts+2), "triangle vert table");
 +      
 +      lines[0] = (BMVert**) stackarr;
 +      lines[0][0] = vlist[numcuts*2+1];
 +      
 +      lines[1+numcuts] = MEM_callocN(sizeof(void*)*(numcuts+2), 
 +                                     "triangle vert table 2");
 +      for (i=0; i<numcuts; i++) {
 +              lines[1+numcuts][1+i] = vlist[i];
 +      }
 +      lines[1+numcuts][0] = vlist[numcuts*3+2];
 +      lines[1+numcuts][1+numcuts] = vlist[numcuts];
 +
 +      for (i=0; i<numcuts; i++) {
 +              lines[i+1] = MEM_callocN(sizeof(void*)*(2+i), 
 +                                     "triangle vert table row");
 +              a = numcuts*2 + 2 + i;
 +              b = numcuts + numcuts - i;
 +              e = BM_Connect_Verts(bm, vlist[a], vlist[b], &nf);
 +              
 +              if (flag & SELTYPE_INNER) {
 +                      BM_Select_Edge(bm, e, 1);
 +                      BM_Select_Face(bm, nf, 1);
 +              }
 +
 +              lines[i+1][0] = vlist[a];
 +              lines[i+1][1+i] = vlist[b];
 +
 +              for (j=0; j<i; j++) {
 +                      v = subdivideedgenum(bm, e, j, i, rad, flag, &ne,
 +                                           vlist[a], vlist[b]);
 +                      lines[i+1][j+1] = v;
 +
 +                      if (flag & SELTYPE_INNER) {
 +                              BM_Select_Edge(bm, ne, 1);
 +                      }
 +              }
 +      }
 +      
 +
 +/*     v5
 +      / \
 + s v6/---\ v4 s
 +    / \ / \
 +sv7/---v---\ v3 s
 +  /  \/  \/ \
 + v8--v0--v1--v2
 +    s    s
 +*/
 +      for (i=1; i<numcuts+1; i++) {
 +              for (j=0; j<i; j++) {
 +                      e= BM_Connect_Verts(bm, lines[i][j], lines[i+1][j+1],
 +                                         &nf);
 +                      if (flag & SELTYPE_INNER) {
 +                              BM_Select_Edge(bm, e, 1);
 +                              BM_Select_Face(bm, nf, 1);
 +                      }
 +
 +                      e= BM_Connect_Verts(bm,lines[i][j+1],lines[i+1][j+1],
 +                                         &nf);
 +                      if (flag & SELTYPE_INNER) {
 +                              BM_Select_Edge(bm, e, 1);
 +                              BM_Select_Face(bm, nf, 1);
 +                      }
 +              }
 +      }
 +
 +      for (i=1; i<numcuts+2; i++) {
 +              MEM_freeN(lines[i]);
 +      }
 +
 +      MEM_freeN(lines);
 +}
 +
 +subdpattern t_3edge = {
 +      {1, 1, 1},
 +      t_3edge_split,
 +      3,
 +};
 +
 +
 +subdpattern q_4edge = {
 +      {1, 1, 1, 1},
 +      q_4edge_split,
 +      4,
 +};
 +
 +subdpattern *patterns[] = {
 +      &q_1edge,
 +      &q_2edge_op,
 +      &q_4edge,
 +      &q_3edge,
 +      &q_2edge,
 +      &t_1edge,
 +      &t_2edge,
 +      &t_3edge,
 +};
 +
 +#define PLEN  (sizeof(patterns) / sizeof(void*))
 +
 +typedef struct subd_facedata {
 +      BMVert *start; subdpattern *pat;
 +} subd_facedata;
 +
 +void esubdivide_exec(BMesh *bmesh, BMOperator *op)
 +{
-       V_DECLARE(verts);
++      V_DECLARE(facedata);
++      V_DECLARE(verts);
 +      V_DECLARE(edges);
++      BMOpSlot *einput, *finput, *pinput;
++      BMEdge *edge, **edges = NULL;
 +      BMFace *face;
 +      BMLoop *nl;
 +      BMVert **verts = NULL;
-       float rad;
-       int i, j, matched, a, b, numcuts, flag, selaction;
 +      BMIter fiter, liter;
++      GHash *customfill_hash; 
 +      subdpattern *pat;
-       V_DECLARE(facedata);
 +      subd_facedata *facedata = NULL;
-               i = 0;
++      float rad;
++      int i, j, matched, a, b, numcuts, flag, selaction, fillindex;
 +      
 +      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;
 +      if (selaction == SUBDIV_SELECT_INNER) flag |= SELTYPE_INNER;
 +
 +      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];
 +              BMO_SetFlag(bmesh, edge, SUBD_SPLIT);
 +      }
 +      
++      customfill_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]);
++      }
++      
 +      for (face=BMIter_New(&fiter, bmesh, BM_FACES, NULL);
 +           face; face=BMIter_Step(&fiter)) {
 +              /*figure out which pattern to use*/
-               
++
 +              V_RESET(edges);
 +              V_RESET(verts);
++              i = 0;
 +              for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
 +                   nl; nl=BMIter_Step(&liter)) {
 +                      V_GROW(edges);
 +                      V_GROW(verts);
 +                      edges[i] = nl->e;
 +                      verts[i] = nl->v;
 +                      i++;
 +              }
 +
++              if (BMO_TestFlag(bmesh, face, FACE_CUSTOMFILL)) {
++                      pat = BLI_ghash_lookup(customfill_hash, face);
++                      for (i=0; i<pat->len; i++) {
++                              matched = 1;
++                              for (j=0; j<pat->len; j++) {
++                                      a = (j + i) % pat->len;
++                                      if ((!!BMO_TestFlag(bmesh, edges[a], SUBD_SPLIT))
++                                              != (!!pat->seledges[j])) {
++                                                      matched = 0;
++                                                      break;
++                                      }
++                              }
++                              if (matched) {
++                                      V_GROW(facedata);
++                                      b = V_COUNT(facedata)-1;
++                                      facedata[b].pat = pat;
++                                      facedata[b].start = verts[i];
++                                      break;
++                              }
++                      }
++                      if (!matched) {
++                              /*if no match, append null element to array.*/
++                              V_GROW(facedata);
++                      }
++
++                      /*obvously don't test for other patterns matching*/
++                      continue;
++              }
++
 +              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;
 +                              }
 +                      }
 +              }
 +      }
 +
 +      /*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,
 +                                    edge->v1, edge->v2);
 +              //BM_Split_Edge_Multi(bmesh, edge, numcuts);
 +      }
 +
 +      //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*/
 +              V_RESET(verts);
 +              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 (j=0; j<face->len; j++) {
 +                      V_GROW(verts);
 +              }
 +              
 +              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++;
 +      }
 +
 +      if (facedata) V_FREE(facedata);
 +      if (edges) V_FREE(edges);
 +      if (verts) V_FREE(verts);
 +}
 +
 +/*editmesh-emulating function*/
 +void BM_esubdivideflag(Object *obedit, BMesh *bm, int selflag, float rad, 
 +                     int flag, 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, flag);
 +      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, selflag, BM_EDGE);
 +      
 +      BMO_Exec_Op(bm, &op);
 +      BMO_Finish_Op(bm, &op);
 +}
 +
 +void BM_esubdivideflag_conv(Object *obedit,EditMesh *em,int selflag, float rad, 
 +                     int flag, int numcuts, int seltype) {
 +      BMesh *bm = editmesh_to_bmesh(em);
 +      EditMesh *em2;
 +
 +      BM_esubdivideflag(obedit, bm, selflag, rad, flag, numcuts, seltype);
 +      em2 = bmesh_to_editmesh(bm);
 +      
 +      free_editMesh(em);
 +      *em = *em2;
 +      MEM_freeN(em2);
 +      BM_Free_Mesh(bm);
 +}
index 58401d79bf12c3bbc0cab64708f4ab62e6b766c9,89dc8942a2aa12d6fa9b4f0307cfeadf761f5265..debf7f3b1da0c2d732d912a26b908ce9b3c2c194
@@@ -200,8 -189,12 +196,12 @@@ void MESH_OT_select_random(struct wmOpe
  void MESH_OT_vertices_to_sphere(struct wmOperatorType *ot);
  void MESH_OT_selection_type(struct wmOperatorType *ot);
  void MESH_OT_select_multi_loop(struct wmOperatorType *ot);
+ void MESH_OT_mark_seam(struct wmOperatorType *ot);
+ void MESH_OT_mark_sharp(struct wmOperatorType *ot);
+ void MESH_OT_smooth_vertex(struct wmOperatorType *ot);
+ void MESH_OT_flip_editnormals(struct wmOperatorType *ot);
  
 -extern EditEdge *findnearestedge(ViewContext *vc, int *dist);
 +extern EditEdge *findnearestedge(struct ViewContext *vc, int *dist);
  extern void EM_automerge(int update);
  void editmesh_select_by_material(EditMesh *em, int index);
  void righthandfaces(EditMesh *em, int select);        /* makes faces righthand turning */