merge with/from trunk at r35190
[blender.git] / source / blender / modifiers / intern / MOD_edgesplit.c
index 05e195d9b8f4fc82c414ce0df39ca346a10e35c6..4549448f45ea22152acea73d29e3846a48497d55 100644 (file)
 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
 * All rights reserved.
 *
-* Contributor(s): Daniel Dunbar
-*                 Ton Roosendaal,
-*                 Ben Batt,
-*                 Brecht Van Lommel,
-*                 Campbell Barton
+* Contributor(s): Joseph Eagar
 *
 * ***** END GPL LICENSE BLOCK *****
 *
 */
 
-/** \file blender/modifiers/intern/MOD_edgesplit.c
- *  \ingroup modifiers
- */
-
-
 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
  * or edge angle (can be used to achieve autosmoothing) */
 
 #include "BLI_memarena.h"
 #include "BLI_edgehash.h"
 #include "BLI_math.h"
+#include "BLI_array.h"
 #include "BLI_utildefines.h"
 
-
 #include "BKE_cdderivedmesh.h"
 #include "BKE_modifier.h"
 #include "BKE_particle.h"
+#include "BKE_tessmesh.h"
+#include "BKE_mesh.h"
 
 #include "MEM_guardedalloc.h"
 
-#include "MOD_util.h"
-
-#if 0
-#define EDGESPLIT_DEBUG_3
-#define EDGESPLIT_DEBUG_2
-#define EDGESPLIT_DEBUG_1
-#define EDGESPLIT_DEBUG_0
-#endif
-
-static void initData(ModifierData *md)
-{
-       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
-
-       /* default to 30-degree split angle, sharpness from both angle & flag
-       */
-       emd->split_angle = 30;
-       emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
-}
-
-static void copyData(ModifierData *md, ModifierData *target)
-{
-       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
-       EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
-
-       temd->split_angle = emd->split_angle;
-       temd->flags = emd->flags;
-}
-
-/* Mesh data for edgesplit operation */
-typedef struct SmoothVert {
-       LinkNode *faces;     /* all faces which use this vert */
-       int oldIndex; /* the index of the original DerivedMesh vert */
-       int newIndex; /* the index of the new DerivedMesh vert */
-} SmoothVert;
-
-#define SMOOTHEDGE_NUM_VERTS 2
-
-typedef struct SmoothEdge {
-       SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
-       LinkNode *faces;     /* all faces which use this edge */
-       int oldIndex; /* the index of the original DerivedMesh edge */
-       int newIndex; /* the index of the new DerivedMesh edge */
-       short flag; /* the flags from the original DerivedMesh edge */
-} SmoothEdge;
-
-#define SMOOTHFACE_MAX_EDGES 4
-
-typedef struct SmoothFace {
-       SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
-       int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
-       float normal[3]; /* the normal of this face */
-       int oldIndex; /* the index of the original DerivedMesh face */
-       int newIndex; /* the index of the new DerivedMesh face */
-} SmoothFace;
-
-typedef struct SmoothMesh {
-       SmoothVert *verts;
-       SmoothEdge *edges;
-       SmoothFace *faces;
-       int num_verts, num_edges, num_faces;
-       int max_verts, max_edges, max_faces;
-       DerivedMesh *dm;
-       float threshold; /* the cosine of the smoothing angle */
-       int flags;
-       MemArena *arena;
-       ListBase propagatestack, reusestack;
-} SmoothMesh;
-
-static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
-{
-       SmoothVert *copy = &mesh->verts[mesh->num_verts];
+/* EdgeSplit */
+/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
+ * or edge angle (can be used to achieve autosmoothing)
+*/
 
-       if(mesh->num_verts >= mesh->max_verts) {
-               printf("Attempted to add a SmoothMesh vert beyond end of array\n");
+/*new cddm-based edge split code*/
+typedef struct VertUser {
+       int ov, v, done;
+       ListBase users;
+} VertUser;
+
+typedef struct EdgeNode {
+       struct EdgeNode *next, *prev;
+       struct EdgeData *edge;
+} EdgeNode;
+
+typedef struct EdgeData {
+       EdgeNode v1node, v2node;
+       VertUser *v1user, *v2user;
+       float fno[3]; /*used to calculate face angles*/
+       int has_fno;
+       int tag;
+       int v1, v2;
+       int used;
+} EdgeData;
+
+typedef struct MemBase {
+       BLI_mempool *vertuserpool;
+} MemBase;
+
+BM_INLINE EdgeData *edge_get_next(EdgeData *e, int ov) {
+       if (ov == e->v1)
+               return e->v1node.next ? e->v1node.next->edge : NULL;
+       else return e->v2node.next ? e->v2node.next->edge : NULL;
+}
+
+BM_INLINE EdgeNode *edge_get_node(EdgeData *e, int ov)
+{
+       if (ov == e->v1)
+               return &e->v1node;
+       else return &e->v2node;
                return NULL;
-       }
-
-       *copy = *vert;
-       copy->faces = NULL;
-       copy->newIndex = mesh->num_verts;
-       ++mesh->num_verts;
-
-#ifdef EDGESPLIT_DEBUG_2
-       printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
-#endif
-       return copy;
 }
 
-static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
+BM_INLINE VertUser *edge_get_vuser(MemBase *b, EdgeData *edge, int ov)
 {
-       SmoothEdge *copy = &mesh->edges[mesh->num_edges];
-
-       if(mesh->num_edges >= mesh->max_edges) {
-               printf("Attempted to add a SmoothMesh edge beyond end of array\n");
+       if (ov == edge->v1)
+               return edge->v1user;
+       else if (ov == edge->v2)
+               return edge->v2user;
+       else {
+               printf("yeek!!\n");
                return NULL;
        }
-
-       *copy = *edge;
-       copy->faces = NULL;
-       copy->newIndex = mesh->num_edges;
-       ++mesh->num_edges;
-
-#ifdef EDGESPLIT_DEBUG_2
-       printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
-#endif
-       return copy;
 }
 
-static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
-{
-       int i;
-       for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
-               if(edge->verts[i] == vert) return 1;
-
-       return 0;
-}
-
-static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
-                                 int max_verts, int max_edges, int max_faces)
-{
-       SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
-       mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
-                                 "SmoothMesh.verts");
-       mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
-                                 "SmoothMesh.edges");
-       mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
-                                 "SmoothMesh.faces");
-
-       mesh->num_verts = num_verts;
-       mesh->num_edges = num_edges;
-       mesh->num_faces = num_faces;
-
-       mesh->max_verts = max_verts;
-       mesh->max_edges = max_edges;
-       mesh->max_faces = max_faces;
-
-       return mesh;
-}
+BM_INLINE void edge_set_vuser(MemBase *b, EdgeData *e, int ov, VertUser *vu)
 
-static void smoothmesh_free(SmoothMesh *mesh)
 {
-       int i;
-
-       for(i = 0; i < mesh->num_verts; ++i)
-               BLI_linklist_free(mesh->verts[i].faces, NULL);
-
-       for(i = 0; i < mesh->num_edges; ++i)
-               BLI_linklist_free(mesh->edges[i].faces, NULL);
-       
-       if(mesh->arena)
-               BLI_memarena_free(mesh->arena);
-
-       MEM_freeN(mesh->verts);
-       MEM_freeN(mesh->edges);
-       MEM_freeN(mesh->faces);
-       MEM_freeN(mesh);
-}
-
-static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
-{
-       int i;
-       SmoothVert *tmp;
-
-       if(max_verts <= mesh->max_verts) return;
-
-       tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
+       VertUser *olduser = edge_get_vuser(b, e, ov);
 
-       memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
+       if (vu == olduser)
+               return;
 
-       /* remap vert pointers in edges */
-       for(i = 0; i < mesh->num_edges; ++i) {
-               int j;
-               SmoothEdge *edge = &mesh->edges[i];
+       if (olduser)
+               BLI_remlink(&olduser->users, ov==e->v1 ? &e->v1node : &e->v2node);
+       BLI_addtail(&vu->users, ov==e->v1 ? &e->v1node : &e->v2node);
 
-               for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
-                       /* pointer arithmetic to get vert array index */
-                       edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
-       }
-
-       MEM_freeN(mesh->verts);
-       mesh->verts = tmp;
-       mesh->max_verts = max_verts;
+       if (ov == e->v1)
+               e->v1user = vu;
+       else e->v2user = vu;
 }
 
-static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
+BM_INLINE VertUser *new_vuser(MemBase *base)
 {
-       int i;
-       SmoothEdge *tmp;
-
-       if(max_edges <= mesh->max_edges) return;
-
-       tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
-
-       memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
+       VertUser *vusr = BLI_mempool_calloc(base->vertuserpool);
 
-       /* remap edge pointers in faces */
-       for(i = 0; i < mesh->num_faces; ++i) {
-               int j;
-               SmoothFace *face = &mesh->faces[i];
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
-                       if(face->edges[j])
-                               /* pointer arithmetic to get edge array index */
-                               face->edges[j] = &tmp[face->edges[j] - mesh->edges];
-       }
-
-       MEM_freeN(mesh->edges);
-       mesh->edges = tmp;
-       mesh->max_edges = max_edges;
+       return vusr;
 }
 
-#ifdef EDGESPLIT_DEBUG_0
-static void smoothmesh_print(SmoothMesh *mesh)
+BM_INLINE MemBase *new_membase(void)
 {
-       int i, j;
-       DerivedMesh *dm = mesh->dm;
-
-       printf("--- SmoothMesh ---\n");
-       printf("--- Vertices ---\n");
-       for(i = 0; i < mesh->num_verts; i++) {
-               SmoothVert *vert = &mesh->verts[i];
-               LinkNode *node;
-               MVert mv;
-
-               dm->getVert(dm, vert->oldIndex, &mv);
-
-               printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
-                          i, vert->oldIndex, vert->newIndex,
-        mv.co[0], mv.co[1], mv.co[2]);
-               printf(", faces={");
-               for(node = vert->faces; node != NULL; node = node->next) {
-                       printf(" %d", ((SmoothFace *)node->link)->newIndex);
-               }
-               printf("}\n");
-       }
-
-       printf("\n--- Edges ---\n");
-       for(i = 0; i < mesh->num_edges; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-               LinkNode *node;
-
-               printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
-                          i,
-        edge->oldIndex, edge->newIndex,
-  edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-               if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
-               printf(", faces={");
-               for(node = edge->faces; node != NULL; node = node->next) {
-                       printf(" %d", ((SmoothFace *)node->link)->newIndex);
-               }
-               printf("}\n");
-       }
+       MemBase *b = MEM_callocN(sizeof(MemBase), "MemBase for edgesplit in modifier.c");
+       b->vertuserpool = BLI_mempool_create(sizeof(VertUser), 1, 2048, 1, 0);
 
-       printf("\n--- Faces ---\n");
-       for(i = 0; i < mesh->num_faces; i++) {
-               SmoothFace *face = &mesh->faces[i];
-
-               printf("%4d: indices={%4d, %4d}, edges={", i,
-                          face->oldIndex, face->newIndex);
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       if(face->flip[j])
-                               printf(" -%-2d", face->edges[j]->newIndex);
-                       else
-                               printf("  %-2d", face->edges[j]->newIndex);
-               }
-               printf("}, verts={");
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
-               }
-               printf("}\n");
-       }
+       return b;
 }
-#endif
 
-static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
+BM_INLINE void free_membase(MemBase *b)
 {
-       SmoothMesh *mesh;
-       EdgeHash *edges = BLI_edgehash_new();
-       int i;
-       int totvert, totedge, totface;
-
-       totvert = dm->getNumVerts(dm);
-       totedge = dm->getNumEdges(dm);
-       totface = dm->getNumFaces(dm);
-
-       mesh = smoothmesh_new(totvert, totedge, totface,
-                                 totvert, totedge, totface);
-
-       mesh->dm = dm;
-
-       for(i = 0; i < totvert; i++) {
-               SmoothVert *vert = &mesh->verts[i];
-
-               vert->oldIndex = vert->newIndex = i;
-       }
-
-       for(i = 0; i < totedge; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-               MEdge med;
-
-               dm->getEdge(dm, i, &med);
-               edge->verts[0] = &mesh->verts[med.v1];
-               edge->verts[1] = &mesh->verts[med.v2];
-               edge->oldIndex = edge->newIndex = i;
-               edge->flag = med.flag;
-
-               BLI_edgehash_insert(edges, med.v1, med.v2, edge);
-       }
-
-       for(i = 0; i < totface; i++) {
-               SmoothFace *face = &mesh->faces[i];
-               MFace mf;
-               MVert v1, v2, v3;
-               int j;
-
-               dm->getFace(dm, i, &mf);
-
-               dm->getVert(dm, mf.v1, &v1);
-               dm->getVert(dm, mf.v2, &v2);
-               dm->getVert(dm, mf.v3, &v3);
-               face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
-               if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
-               face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
-               if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
-               if(mf.v4) {
-                       MVert v4;
-                       dm->getVert(dm, mf.v4, &v4);
-                       face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
-                       if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
-                       face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
-                       if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
-                       normal_quad_v3( face->normal,v1.co, v2.co, v3.co, v4.co);
-               } else {
-                       face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
-                       if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
-                       face->edges[3] = NULL;
-                       normal_tri_v3( face->normal,v1.co, v2.co, v3.co);
-               }
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       SmoothEdge *edge = face->edges[j];
-                       BLI_linklist_prepend(&edge->faces, face);
-                       BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
-               }
-
-               face->oldIndex = face->newIndex = i;
-       }
-
-       BLI_edgehash_free(edges, NULL);
-
-       return mesh;
-}
-
-static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
-{
-       DerivedMesh *result = CDDM_from_template(mesh->dm,
-                       mesh->num_verts,
-   mesh->num_edges,
-   mesh->num_faces);
-       MVert *new_verts = CDDM_get_verts(result);
-       MEdge *new_edges = CDDM_get_edges(result);
-       MFace *new_faces = CDDM_get_faces(result);
-       int i;
-
-       for(i = 0; i < mesh->num_verts; ++i) {
-               SmoothVert *vert = &mesh->verts[i];
-               MVert *newMV = &new_verts[vert->newIndex];
-
-               DM_copy_vert_data(mesh->dm, result,
-                                 vert->oldIndex, vert->newIndex, 1);
-               mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
-       }
-
-       for(i = 0; i < mesh->num_edges; ++i) {
-               SmoothEdge *edge = &mesh->edges[i];
-               MEdge *newME = &new_edges[edge->newIndex];
-
-               DM_copy_edge_data(mesh->dm, result,
-                                 edge->oldIndex, edge->newIndex, 1);
-               mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
-               newME->v1 = edge->verts[0]->newIndex;
-               newME->v2 = edge->verts[1]->newIndex;
-       }
-
-       for(i = 0; i < mesh->num_faces; ++i) {
-               SmoothFace *face = &mesh->faces[i];
-               MFace *newMF = &new_faces[face->newIndex];
-
-               DM_copy_face_data(mesh->dm, result,
-                                 face->oldIndex, face->newIndex, 1);
-               mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
-
-               newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
-               newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
-               newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
-
-               if(face->edges[3]) {
-                       newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
-               } else {
-                       newMF->v4 = 0;
-               }
-       }
-
-       return result;
-}
-
-/* returns the other vert in the given edge
- */
-static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
-{
-       if(edge->verts[0] == vert) return edge->verts[1];
-       else return edge->verts[0];
-}
-
-/* returns the other edge in the given face that uses the given vert
- * returns NULL if no other edge in the given face uses the given vert
- * (this should never happen)
- */
-static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
-                                 SmoothEdge *edge)
-{
-       int i,j;
-       for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
-               SmoothEdge *tmp_edge = face->edges[i];
-               if(tmp_edge == edge) continue;
-
-               for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
-                       if(tmp_edge->verts[j] == vert) return tmp_edge;
-       }
-
-       /* if we get to here, something's wrong (there should always be 2 edges
-       * which use the same vert in a face)
-       */
-       return NULL;
-}
-
-/* returns a face attached to the given edge which is not the given face.
- * returns NULL if no other faces use this edge.
- */
-static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
-{
-       LinkNode *node;
-
-       for(node = edge->faces; node != NULL; node = node->next)
-               if(node->link != face) return node->link;
-
-       return NULL;
-}
-
-#if 0
-/* copies source list to target, overwriting target (target is not freed)
- * nodes in the copy will be in the same order as in source
- */
-static void linklist_copy(LinkNode **target, LinkNode *source)
-{
-       LinkNode *node = NULL;
-       *target = NULL;
-
-       for(; source; source = source->next) {
-               if(node) {
-                       node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
-                                                                               node = node->next;
-} else {
-                                                                               node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
-}
-                                                                               node->link = source->link;
-                                                                               node->next = NULL;
-}
-}
-#endif
-
-                                                                               /* appends source to target if it's not already in target */
-                                                                               static void linklist_append_unique(LinkNode **target, void *source) 
-{
-       LinkNode *node;
-       LinkNode *prev = NULL;
-
-       /* check if source value is already in the list */
-       for(node = *target; node; prev = node, node = node->next)
-               if(node->link == source) return;
-
-       node = MEM_mallocN(sizeof(*node), "nlink");
-       node->next = NULL;
-       node->link = source;
-
-       if(prev) prev->next = node;
-       else *target = node;
-}
-
-/* appends elements of source which aren't already in target to target */
-static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
-{
-       for(; source; source = source->next)
-               linklist_append_unique(target, source->link);
-}
-
-#if 0 /* this is no longer used, it should possibly be removed */
-/* prepends prepend to list - doesn't copy nodes, just joins the lists */
-static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
-{
-       if(prepend) {
-               LinkNode *node = prepend;
-               while(node->next) node = node->next;
-
-               node->next = *list;
-               *list = prepend;
+       BLI_mempool_destroy(b->vertuserpool);
+       MEM_freeN(b);
 }
-}
-#endif
 
-/* returns 1 if the linked list contains the given pointer, 0 otherwise
- */
-static int linklist_contains(LinkNode *list, void *ptr)
+BM_INLINE EdgeData *edge_get_first(VertUser *vu)
 {
-       LinkNode *node;
-
-       for(node = list; node; node = node->next)
-               if(node->link == ptr) return 1;
-
-       return 0;
+       return vu->users.first ? ((EdgeNode*)vu->users.first)->edge : NULL;
 }
 
-/* returns 1 if the first linked list is a subset of the second (comparing
- * pointer values), 0 if not
- */
-static int linklist_subset(LinkNode *list1, LinkNode *list2)
+DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd)
 {
-       for(; list1; list1 = list1->next)
-               if(!linklist_contains(list2, list1->link))
-                       return 0;
+       DerivedMesh *cddm = CDDM_copy(dm, 0);
+       MEdge *medge;
+       BLI_array_declare(medge);
+       MLoop *mloop, *ml, *prevl;
+       MPoly *mpoly, *mp;
+       MVert *mvert;
+       BLI_array_declare(mvert);
+       EdgeData *etags, *e, *enext;
+       BLI_array_declare(etags);
+       VertUser *vu, *vu2;
+       MemBase *membase;
+       CustomData edata, vdata;
+       int i, j, curv, cure;
+       float threshold = cos((emd->split_angle + 0.00001) * M_PI / 180.0);
+       float no[3], edge_angle_cos;
 
-       return 1;
-}
+       if (!cddm->numVertData || !cddm->numEdgeData)
+               return cddm;
 
-#if 0
-/* empties the linked list
- * frees pointers with freefunc if freefunc is not NULL
- */
-static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
-{
-       BLI_linklist_free(*list, freefunc);
-       *list = NULL;
-}
-#endif
+       membase = new_membase();
 
-/* removes the first instance of value from the linked list
- * frees the pointer with freefunc if freefunc is not NULL
- */
-static void linklist_remove_first(LinkNode **list, void *value,
-                                 LinkNodeFreeFP freefunc)
-{
-       LinkNode *node = *list;
-       LinkNode *prev = NULL;
+       etags = MEM_callocN(sizeof(EdgeData)*cddm->numEdgeData, "edgedata tag thingies");
+       BLI_array_set_length(etags, cddm->numEdgeData);
 
-       while(node && node->link != value) {
-               prev = node;
-               node = node->next;
-       }
+       mvert = cddm->getVertArray(cddm);
+       BLI_array_set_length(mvert, cddm->numVertData);
+       medge = cddm->getEdgeArray(cddm);
+       BLI_array_set_length(medge, cddm->numEdgeData);
+       mloop = CustomData_get_layer(&cddm->loopData, CD_MLOOP);
+       mpoly = CustomData_get_layer(&cddm->polyData, CD_MPOLY);
 
-       if(node) {
-               if(prev)
-                       prev->next = node->next;
-               else
-                       *list = node->next;
+       for (i=0; i<cddm->numEdgeData; i++) {
+               etags[i].v1 = medge[i].v1;
+               etags[i].v2 = medge[i].v2;
 
-               if(freefunc)
-                       freefunc(node->link);
+               etags[i].tag = (medge[i].flag & ME_SHARP) != 0;
 
-               MEM_freeN(node);
+               etags[i].v1node.edge = etags+i;
+               etags[i].v2node.edge = etags+i;
        }
-}
-
-/* removes all elements in source from target */
-static void linklist_remove_list(LinkNode **target, LinkNode *source,
-                                LinkNodeFreeFP freefunc)
-{
-       for(; source; source = source->next)
-               linklist_remove_first(target, source->link, freefunc);
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void print_ptr(void *ptr)
-{
-       printf("%p\n", ptr);
-}
 
-static void print_edge(void *ptr)
-{
-       SmoothEdge *edge = ptr;
-       printf(" %4d", edge->newIndex);
-}
-
-static void print_face(void *ptr)
-{
-       SmoothFace *face = ptr;
-       printf(" %4d", face->newIndex);
-}
-#endif
-
-typedef struct ReplaceData {
-       void *find;
-       void *replace;
-} ReplaceData;
-
-static void edge_replace_vert(void *ptr, void *userdata)
-{
-       SmoothEdge *edge = ptr;
-       SmoothVert *find = ((ReplaceData *)userdata)->find;
-       SmoothVert *replace = ((ReplaceData *)userdata)->replace;
-       int i;
-
-#ifdef EDGESPLIT_DEBUG_3
-       printf("replacing vert %4d with %4d in edge %4d",
-                  find->newIndex, replace->newIndex, edge->newIndex);
-       printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-
-       for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
-               if(edge->verts[i] == find) {
-                       linklist_append_list_unique(&replace->faces, edge->faces);
-                       linklist_remove_list(&find->faces, edge->faces, NULL);
-
-                       edge->verts[i] = replace;
+       if (emd->flags & MOD_EDGESPLIT_FROMANGLE) {
+               mp = mpoly;
+               for (i=0; i<cddm->numPolyData; i++, mp++) {
+                       mesh_calc_poly_normal(mp, mloop+mp->loopstart, mvert, no);
+
+                       ml = mloop + mp->loopstart;
+                       for (j=0; j<mp->totloop; j++, ml++) {
+                               if (!etags[ml->e].has_fno) {
+                                       VECCOPY(etags[ml->e].fno, no);
+                                       etags[ml->e].has_fno = 1;
+                               } else if (!etags[ml->e].tag) {
+                                       edge_angle_cos = INPR(etags[ml->e].fno, no);
+                                       if (edge_angle_cos < threshold) {
+                                               etags[ml->e].tag = 1;
+                                       }
+                               }
+                       }
                }
        }
 
-#ifdef EDGESPLIT_DEBUG_3
-       printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-}
+       mp = mpoly;
+       for (i=0; i<cddm->numPolyData; i++, mp++) {
+               ml = mloop + mp->loopstart;
+               for (j=0; j<mp->totloop; j++, ml++) {
+                       if (etags[ml->e].tag)
+                               continue;
 
-static void face_replace_vert(void *ptr, void *userdata)
-{
-       SmoothFace *face = ptr;
-       int i;
+                       prevl = mloop + mp->loopstart + ((j-1)+mp->totloop) % mp->totloop;
 
-       for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
-               edge_replace_vert(face->edges[i], userdata);
-}
+                       if (!edge_get_vuser(membase, etags+prevl->e, ml->v)) {
+                               vu = new_vuser(membase);
+                               vu->ov = vu->v = ml->v;
+                               edge_set_vuser(membase, etags+prevl->e, ml->v, vu);
+                       }
 
-static void face_replace_edge(void *ptr, void *userdata)
-{
-       SmoothFace *face = ptr;
-       SmoothEdge *find = ((ReplaceData *)userdata)->find;
-       SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
-       int i;
-
-#ifdef EDGESPLIT_DEBUG_3
-       printf("replacing edge %4d with %4d in face %4d",
-                  find->newIndex, replace->newIndex, face->newIndex);
-       if(face->edges[3])
-               printf(": {%2d %2d %2d %2d}",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex, face->edges[3]->newIndex);
-       else
-               printf(": {%2d %2d %2d}",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex);
-#endif
+                       if (!edge_get_vuser(membase, etags+ml->e, ml->v)) {
+                               vu = new_vuser(membase);
+                               vu->ov = vu->v = ml->v;
+                               edge_set_vuser(membase, etags+ml->e, ml->v, vu);
+                       }
 
-       for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
-               if(face->edges[i] == find) {
-                       linklist_remove_first(&face->edges[i]->faces, face, NULL);
-                       BLI_linklist_prepend(&replace->faces, face);
-                       face->edges[i] = replace;
+                       /*continue if previous edge is tagged*/
+                       if (etags[prevl->e].tag)
+                               continue;
+
+                       /*merge together adjacent split vert users*/
+                       if (edge_get_vuser(membase, etags+prevl->e, ml->v)
+                               != edge_get_vuser(membase, etags+ml->e, ml->v))
+                       {
+                               vu = edge_get_vuser(membase, etags+prevl->e, ml->v);
+                               vu2 = edge_get_vuser(membase, etags+ml->e, ml->v);
+
+                               /*remove from vu2's users list and add to vu's*/
+                               for (e=edge_get_first(vu2); e; e=enext) {
+                                       enext = edge_get_next(e, ml->v);
+                                       edge_set_vuser(membase, e, ml->v, vu);
+                               }
+                       }
                }
        }
 
-#ifdef EDGESPLIT_DEBUG_3
-       if(face->edges[3])
-               printf(" -> {%2d %2d %2d %2d}\n",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex, face->edges[3]->newIndex);
-       else
-               printf(" -> {%2d %2d %2d}\n",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex);
-#endif
-}
+       mp = mpoly;
+       for (i=0; i<cddm->numPolyData; i++, mp++) {
+               ml = mloop + mp->loopstart;
+               for (j=0; j<mp->totloop; j++, ml++) {
+                       if (!etags[ml->e].tag)
+                               continue;
 
-static int edge_is_loose(SmoothEdge *edge)
-{
-       return !(edge->faces && edge->faces->next);
-}
+                       prevl = mloop + mp->loopstart + ((j-1)+mp->totloop) % mp->totloop;
 
-static int edge_is_sharp(SmoothEdge *edge)
-{
-#ifdef EDGESPLIT_DEBUG_1
-       printf("edge %d: ", edge->newIndex);
-#endif
-       if(edge->flag & ME_SHARP) {
-               /* edge can only be sharp if it has at least 2 faces */
-               if(!edge_is_loose(edge)) {
-#ifdef EDGESPLIT_DEBUG_1
-                       printf("sharp\n");
-#endif
-                       return 1;
-               } else {
-                       /* edge is loose, so it can't be sharp */
-                       edge->flag &= ~ME_SHARP;
+                       if (!etags[prevl->e].tag) {
+                               vu = edge_get_vuser(membase, etags+prevl->e, ml->v);
+                               if (!vu) {
+                                       vu = new_vuser(membase);
+                                       vu->ov = vu->v = ml->v;
+                                       edge_set_vuser(membase, etags+prevl->e, ml->v, vu);
+                               }
+
+                               edge_set_vuser(membase, etags+ml->e, ml->v, vu);
+                       } else {
+                               vu = new_vuser(membase);
+                               vu->ov = vu->v = ml->v;
+                               edge_set_vuser(membase, etags+ml->e, ml->v, vu);
+                       }
                }
        }
 
-#ifdef EDGESPLIT_DEBUG_1
-       printf("not sharp\n");
-#endif
-       return 0;
-}
-
-/* finds another sharp edge which uses vert, by traversing faces around the
- * vert until it does one of the following:
- * - hits a loose edge (the edge is returned)
- * - hits a sharp edge (the edge is returned)
- * - returns to the start edge (NULL is returned)
- */
-static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, LinkNode **visited_faces)
-{
-       SmoothFace *face = NULL;
-       SmoothEdge *edge2 = NULL;
-       /* holds the edges we've seen so we can avoid looping indefinitely */
-       LinkNode *visited_edges = NULL;
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
+       curv = cddm->numVertData;
+       cure = cddm->numEdgeData;
+       mp = mpoly;
+       for (i=0; i<cddm->numPolyData; i++, mp++) {
+               ml = mloop + mp->loopstart;
+               for (j=0; j<mp->totloop; j++, ml++) {
+                       e = etags + ml->e;
+                       if (e->v1user && !e->v1user->done) {
+                               e->v1user->done = 1;
+                               BLI_array_growone(mvert);
+
+                               mvert[curv] = mvert[e->v1user->ov];
+                               e->v1user->v = curv;
+
+                               curv++;
+                       }
 
-       /* get a face on which to start */
-       if(edge->faces) face = edge->faces->link;
-       else return NULL;
+                       if (e->v2user && !e->v2user->done) {
+                               e->v2user->done = 1;
+                               BLI_array_growone(mvert);
 
-       /* record this edge as visited */
-       BLI_linklist_prepend(&visited_edges, edge);
+                               mvert[curv] = mvert[e->v2user->ov];
+                               e->v2user->v = curv;
 
-       /* get the next edge */
-       edge2 = other_edge(face, vert, edge);
+                               curv++;
+                       }
 
-       /* record this face as visited */
-       if(visited_faces)
-               BLI_linklist_prepend(visited_faces, face);
+                       vu = edge_get_vuser(membase, e, ml->v);
+                       if (!vu)
+                               continue;
+                       ml->v = vu->v;
+
+#if 0 //BMESH_TODO should really handle edges here, but for now use cddm_calc_edges
+                       /*ok, now we have to deal with edges. . .*/
+                       if (etags[ml->e].tag) {
+                               if (etags[ml->e].used) {
+                                       BLI_array_growone(medge);
+                                       BLI_array_growone(etags);
+                                       medge[cure] = medge[ml->e];
+
+                                       ml->e = cure;
+                                       etags[cure].used = 1;
+                                       cure++;
+                               }
+
+                               vu = etags[ml->e].v1user;
+                               vu2 = etags[ml->e].v2user;
+
+                               if (vu)
+                                       medge[ml->e].v1 = vu->v;
+                               if (vu2)
+                                       medge[ml->e].v2 = vu2->v;
+                       } else {
+                               etags[ml->e].used = 1;
 
-       /* search until we hit a loose edge or a sharp edge or an edge we've
-       * seen before
-       */
-       while(face && !edge_is_sharp(edge2)
-                        && !linklist_contains(visited_edges, edge2)) {
-#ifdef EDGESPLIT_DEBUG_3
-               printf("current face %4d; current edge %4d\n", face->newIndex,
-                          edge2->newIndex);
-#endif
-               /* get the next face */
-               face = other_face(edge2, face);
-
-               /* if face == NULL, edge2 is a loose edge */
-               if(face) {
-                       /* record this face as visited */
-                       if(visited_faces)
-                               BLI_linklist_prepend(visited_faces, face);
-
-                       /* record this edge as visited */
-                       BLI_linklist_prepend(&visited_edges, edge2);
-
-                       /* get the next edge */
-                       edge2 = other_edge(face, vert, edge2);
-#ifdef EDGESPLIT_DEBUG_3
-                       printf("next face %4d; next edge %4d\n",
-                                  face->newIndex, edge2->newIndex);
-               } else {
-                       printf("loose edge: %4d\n", edge2->newIndex);
+                               if (vu->ov == etags[ml->e].v1)
+                                       medge[ml->e].v1 = vu->v;
+                               else if (vu->ov == etags[ml->e].v2)
+                                       medge[ml->e].v2 = vu->v;
+                       }
 #endif
                }
-                        }
-
-                        /* either we came back to the start edge or we found a sharp/loose edge */
-                        if(linklist_contains(visited_edges, edge2))
-                                /* we came back to the start edge */
-                                edge2 = NULL;
-
-                        BLI_linklist_free(visited_edges, NULL);
-
-#ifdef EDGESPLIT_DEBUG_1
-                        printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
-                                        "returning edge %d\n",
-        edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
-#endif
-                        return edge2;
-}
-
-static void split_single_vert(SmoothVert *vert, SmoothFace *face,
-                                 SmoothMesh *mesh)
-{
-       SmoothVert *copy_vert;
-       ReplaceData repdata;
-
-       copy_vert = smoothvert_copy(vert, mesh);
-
-       repdata.find = vert;
-       repdata.replace = copy_vert;
-       face_replace_vert(face, &repdata);
-}
-
-typedef struct PropagateEdge {
-       struct PropagateEdge *next, *prev;
-       SmoothEdge *edge;
-       SmoothVert *vert;
-} PropagateEdge;
-
-static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
-       PropagateEdge *pedge = mesh->reusestack.first;
-
-       if(pedge) {
-               BLI_remlink(&mesh->reusestack, pedge);
        }
-       else {
-               if(!mesh->arena) {
-                       mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "edgesplit arena");
-                       BLI_memarena_use_calloc(mesh->arena);
-               }
 
-               pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
-       }
 
-       pedge->edge = edge;
-       pedge->vert = vert;
-       BLI_addhead(&mesh->propagatestack, pedge);
-}
+       /*resize customdata arrays and add new medge/mvert arrays*/
+       vdata = cddm->vertData;
+       edata = cddm->edgeData;
 
-static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
-{
-       PropagateEdge *pedge = mesh->propagatestack.first;
+       /*make sure we don't copy over mvert/medge layers*/
+       CustomData_set_layer(&vdata, CD_MVERT, NULL);
+       CustomData_set_layer(&edata, CD_MEDGE, NULL);
+       CustomData_free_layer_active(&vdata, CD_MVERT, cddm->numVertData);
+       CustomData_free_layer_active(&edata, CD_MEDGE, cddm->numEdgeData);
 
-       if(pedge) {
-               *edge = pedge->edge;
-               *vert = pedge->vert;
-               BLI_remlink(&mesh->propagatestack, pedge);
-               BLI_addhead(&mesh->reusestack, pedge);
-       }
-       else {
-               *edge = NULL;
-               *vert = NULL;
-       }
-}
+       memset(&cddm->vertData, 0, sizeof(CustomData));
+       memset(&cddm->edgeData, 0, sizeof(CustomData));
 
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
+       CustomData_copy(&vdata, &cddm->vertData, CD_MASK_DERIVEDMESH, CD_CALLOC, curv);
+       CustomData_copy_data(&vdata, &cddm->vertData, 0, 0, cddm->numVertData);
+       CustomData_free(&vdata, cddm->numVertData);
+       cddm->numVertData = curv;
 
-static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
-                               SmoothMesh *mesh)
-{
-       SmoothEdge *edge2;
-       LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
+       CustomData_copy(&edata, &cddm->edgeData, CD_MASK_DERIVEDMESH, CD_CALLOC, cure);
+       CustomData_copy_data(&edata, &cddm->edgeData, 0, 0, cddm->numEdgeData);
+       CustomData_free(&edata, cddm->numEdgeData);
+       cddm->numEdgeData = cure;
 
-       edge2 = find_other_sharp_edge(vert, edge, &visited_faces);
-
-       if(!edge2) {
-               /* didn't find a sharp or loose edge, so we've hit a dead end */
-       } else if(!edge_is_loose(edge2)) {
-               /* edge2 is not loose, so it must be sharp */
-               if(edge_is_loose(edge)) {
-                       /* edge is loose, so we can split edge2 at this vert */
-                       split_edge(edge2, vert, mesh);
-               } else if(edge_is_sharp(edge)) {
-                       /* both edges are sharp, so we can split the pair at vert */
-                       split_edge(edge, vert, mesh);
-               } else {
-                       /* edge is not sharp, so try to split edge2 at its other vert */
-                       split_edge(edge2, other_vert(edge2, vert), mesh);
-               }
-       } else { /* edge2 is loose */
-               if(edge_is_loose(edge)) {
-                       SmoothVert *vert2;
-                       ReplaceData repdata;
-
-                       /* can't split edge, what should we do with vert? */
-                       if(linklist_subset(vert->faces, visited_faces)) {
-                               /* vert has only one fan of faces attached; don't split it */
-                       } else {
-                               /* vert has more than one fan of faces attached; split it */
-                               vert2 = smoothvert_copy(vert, mesh);
+       CDDM_set_mvert(cddm, mvert);
+       CDDM_set_medge(cddm, medge);
 
-                               /* replace vert with its copy in visited_faces */
-                               repdata.find = vert;
-                               repdata.replace = vert2;
-                               BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-                       }
-               } else {
-                       /* edge is not loose, so it must be sharp; split it */
-                       split_edge(edge, vert, mesh);
-               }
-       }
+       free_membase(membase);
+       MEM_freeN(etags);
 
-       BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
-}
+       /*edge calculation isn't working correctly, so just brute force it*/
+       cddm->numEdgeData = 0;
+       CDDM_calc_edges_poly(cddm);
 
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
-       SmoothEdge *edge2;
-       SmoothVert *vert2;
-       ReplaceData repdata;
-       /* the list of faces traversed while looking for a sharp edge */
-       LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
+       cddm->numFaceData = mesh_recalcTesselation(&cddm->faceData,
+               &cddm->loopData, &cddm->polyData,
+               mvert, cddm->numFaceData,
+               cddm->numLoopData, cddm->numPolyData, 1, 0);
 
-       edge2 = find_other_sharp_edge(vert, edge, &visited_faces);
-
-       if(!edge2) {
-               /* didn't find a sharp or loose edge, so try the other vert */
-               vert2 = other_vert(edge, vert);
-               push_propagate_stack(edge, vert2, mesh);
-       } else if(!edge_is_loose(edge2)) {
-               /* edge2 is not loose, so it must be sharp */
-               SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
-               SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
-               SmoothVert *vert2;
-
-               /* replace edge with its copy in visited_faces */
-               repdata.find = edge;
-               repdata.replace = copy_edge;
-               BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
-               /* replace edge2 with its copy in visited_faces */
-               repdata.find = edge2;
-               repdata.replace = copy_edge2;
-               BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
-               vert2 = smoothvert_copy(vert, mesh);
-
-               /* replace vert with its copy in visited_faces (must be done after
-               * edge replacement so edges have correct vertices)
-               */
-               repdata.find = vert;
-               repdata.replace = vert2;
-               BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
-               /* all copying and replacing is done; the mesh should be consistent.
-               * now propagate the split to the vertices at either end
-               */
-               push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
-               push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh);
-
-               if(smoothedge_has_vert(edge, vert))
-                       push_propagate_stack(edge, vert, mesh);
-       } else {
-               /* edge2 is loose */
-               SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
-               SmoothVert *vert2;
-
-               /* replace edge with its copy in visited_faces */
-               repdata.find = edge;
-               repdata.replace = copy_edge;
-               BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
-               vert2 = smoothvert_copy(vert, mesh);
-
-               /* replace vert with its copy in visited_faces (must be done after
-               * edge replacement so edges have correct vertices)
-               */
-               repdata.find = vert;
-               repdata.replace = vert2;
-               BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
-               /* copying and replacing is done; the mesh should be consistent.
-               * now propagate the split to the vertex at the other end
-               */
-               push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
-
-               if(smoothedge_has_vert(edge, vert))
-                       push_propagate_stack(edge, vert, mesh);
-       }
+       CDDM_set_mface(cddm, DM_get_tessface_data_layer(cddm, CD_MFACE));
+       CDDM_calc_normals(cddm);
 
-       BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
+       return cddm;
 }
 
-static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
-                                         int flags, int *extra_edges)
-{
-       /* if normal1 dot normal2 < threshold, angle is greater, so split */
-       /* FIXME not sure if this always works */
-       /* 0.00001 added for floating-point rounding */
-       float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
-       int i;
-
-       *extra_edges = 0;
-
-       /* loop through edges, counting potential new ones */
-       for(i = 0; i < mesh->num_edges; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-               int sharp = 0;
-
-               /* treat all non-manifold edges (3 or more faces) as sharp */
-               if(edge->faces && edge->faces->next && edge->faces->next->next) {
-                       LinkNode *node;
-
-                       /* this edge is sharp */
-                       sharp = 1;
-
-                       /* add an extra edge for every face beyond the first */
-                       *extra_edges += 2;
-                       for(node = edge->faces->next->next->next; node; node = node->next)
-                               (*extra_edges)++;
-               } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
-                                        && !edge_is_loose(edge)) {
-                       /* (the edge can only be sharp if we're checking angle or flag,
-                       * and it has at least 2 faces) */
-
-                                                /* if we're checking the sharp flag and it's set, good */
-                                                if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
-                                                        /* this edge is sharp */
-                                                        sharp = 1;
-
-                                                        (*extra_edges)++;
-                                                } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
-                                                        /* we know the edge has 2 faces, so check the angle */
-                                                        SmoothFace *face1 = edge->faces->link;
-                                                        SmoothFace *face2 = edge->faces->next->link;
-                                                        float edge_angle_cos = dot_v3v3(face1->normal,
-                                                                        face2->normal);
-
-                                                        if(edge_angle_cos < threshold) {
-                                                                /* this edge is sharp */
-                                                                sharp = 1;
-
-                                                                (*extra_edges)++;
-                                                        }
-                                                }
-                                        }
-
-                                        /* set/clear sharp flag appropriately */
-                                        if(sharp) edge->flag |= ME_SHARP;
-                                        else edge->flag &= ~ME_SHARP;
-       }
-}
 
-static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
-{
-       SmoothVert *vert;
-       int i;
-       /* if normal1 dot normal2 < threshold, angle is greater, so split */
-       /* FIXME not sure if this always works */
-       /* 0.00001 added for floating-point rounding */
-       mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
-       mesh->flags = flags;
-
-       /* loop through edges, splitting sharp ones */
-       /* can't use an iterator here, because we'll be adding edges */
-       for(i = 0; i < mesh->num_edges; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-
-               if(edge_is_sharp(edge)) {
-                       split_edge(edge, edge->verts[0], mesh);
-
-                       do {
-                               pop_propagate_stack(&edge, &vert, mesh);
-                               if(edge && smoothedge_has_vert(edge, vert))
-                                       propagate_split(edge, vert, mesh);
-                       } while(edge);
-               }
-       }
-}
-
-static int count_bridge_verts(SmoothMesh *mesh)
+static void initData(ModifierData *md)
 {
-       int i, j, count = 0;
-
-       for(i = 0; i < mesh->num_faces; i++) {
-               SmoothFace *face = &mesh->faces[i];
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       SmoothEdge *edge = face->edges[j];
-                       SmoothEdge *next_edge;
-                       SmoothVert *vert = edge->verts[1 - face->flip[j]];
-                       int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
-                       /* wrap next around if at last edge */
-                       if(!face->edges[next]) next = 0;
-
-                       next_edge = face->edges[next];
-
-                       /* if there are other faces sharing this vertex but not
-                       * these edges, the vertex will be split, so count it
-                       */
-                       /* vert has to have at least one face (this one), so faces != 0 */
-                       if(!edge->faces->next && !next_edge->faces->next
-                                                && vert->faces->next) {
-                               count++;
-                                                }
-               }
-       }
+       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
 
-       /* each bridge vert will be counted once per face that uses it,
-       * so count is too high, but it's ok for now
+       /* default to 30-degree split angle, sharpness from both angle & flag
        */
-       return count;
+       emd->split_angle = 30;
+       emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
 }
 
-static void split_bridge_verts(SmoothMesh *mesh)
+static void copyData(ModifierData *md, ModifierData *target)
 {
-       int i,j;
-
-       for(i = 0; i < mesh->num_faces; i++) {
-               SmoothFace *face = &mesh->faces[i];
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       SmoothEdge *edge = face->edges[j];
-                       SmoothEdge *next_edge;
-                       SmoothVert *vert = edge->verts[1 - face->flip[j]];
-                       int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
-                       /* wrap next around if at last edge */
-                       if(!face->edges[next]) next = 0;
-
-                       next_edge = face->edges[next];
-
-                       /* if there are other faces sharing this vertex but not
-                       * these edges, split the vertex
-                       */
-                       /* vert has to have at least one face (this one), so faces != 0 */
-                       if(!edge->faces->next && !next_edge->faces->next
-                                                && vert->faces->next)
-                               /* FIXME this needs to find all faces that share edges with
-                               * this one and split off together
-                               */
-                               split_single_vert(vert, face, mesh);
-               }
-       }
+       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+       EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
+
+       temd->split_angle = emd->split_angle;
+       temd->flags = emd->flags;
 }
 
-static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, DerivedMesh *dm)
+static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
+                                        Object *ob, DerivedMesh *dm)
 {
-       SmoothMesh *mesh;
-       DerivedMesh *result;
-       int max_verts, max_edges;
-
        if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
                return dm;
 
-       /* 1. make smoothmesh with initial number of elements */
-       mesh = smoothmesh_from_derivedmesh(dm);
-
-       /* 2. count max number of elements to add */
-       tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
-       max_verts = max_edges * 2 + mesh->max_verts;
-       max_verts += count_bridge_verts(mesh);
-       max_edges += mesh->max_edges;
-
-       /* 3. reallocate smoothmesh arrays & copy elements across */
-       /* 4. remap copied elements' pointers to point into the new arrays */
-       smoothmesh_resize_verts(mesh, max_verts);
-       smoothmesh_resize_edges(mesh, max_edges);
-
-#ifdef EDGESPLIT_DEBUG_1
-       printf("********** Pre-split **********\n");
-       smoothmesh_print(mesh);
-#endif
-
-       split_sharp_edges(mesh, emd->split_angle, emd->flags);
-#ifdef EDGESPLIT_DEBUG_1
-       printf("********** Post-edge-split **********\n");
-       smoothmesh_print(mesh);
-#endif
-
-       split_bridge_verts(mesh);
-
-#ifdef EDGESPLIT_DEBUG_1
-       printf("********** Post-vert-split **********\n");
-       smoothmesh_print(mesh);
-#endif
-
-#ifdef EDGESPLIT_DEBUG_0
-       printf("Edgesplit: Estimated %d verts & %d edges, "
-                       "found %d verts & %d edges\n", max_verts, max_edges,
-   mesh->num_verts, mesh->num_edges);
-#endif
-
-       result = CDDM_from_smoothmesh(mesh);
-       smoothmesh_free(mesh);
-
-       return result;
+       return doEdgeSplit(dm, emd);
 }
 
-static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
-                                               DerivedMesh *derivedData,
-                                               int UNUSED(useRenderParams),
-                                               int UNUSED(isFinalCalc))
+static DerivedMesh *applyModifier(
+               ModifierData *md, Object *ob, DerivedMesh *derivedData,
+  int useRenderParams, int isFinalCalc)
 {
        DerivedMesh *result;
        EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
 
-       result = edgesplitModifier_do(emd, derivedData);
+       result = edgesplitModifier_do(emd, ob, derivedData);
 
        if(result != derivedData)
                CDDM_calc_normals(result);
@@ -1264,8 +429,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
 }
 
 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
-                                               struct EditMesh *UNUSED(editData),
-                                               DerivedMesh *derivedData)
+                                                                       BMEditMesh *editData, DerivedMesh *derivedData)
 {
        return applyModifier(md, ob, derivedData, 0, 1);
 }
@@ -1284,7 +448,7 @@ ModifierTypeInfo modifierType_EdgeSplit = {
 
        /* copyData */          copyData,
        /* deformVerts */       0,
-       /* deformMatrices */    0,
+       /* deformMatrices */  0,
        /* deformVertsEM */     0,
        /* deformMatricesEM */  0,
        /* applyModifier */     applyModifier,
@@ -1295,7 +459,6 @@ ModifierTypeInfo modifierType_EdgeSplit = {
        /* isDisabled */        0,
        /* updateDepgraph */    0,
        /* dependsOnTime */     0,
-       /* dependsOnNormals */  0,
        /* foreachObjectLink */ 0,
        /* foreachIDLink */     0,
 };