Blender V2.61 - r43446

MOD_edgesplit.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software  Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Daniel Dunbar
00022  *                 Ton Roosendaal,
00023  *                 Ben Batt,
00024  *                 Brecht Van Lommel,
00025  *                 Campbell Barton
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  *
00029  */
00030 
00036 /* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
00037  * or edge angle (can be used to achieve autosmoothing) */
00038 
00039 #include <assert.h>
00040 
00041 #include "DNA_meshdata_types.h"
00042 
00043 #include "BLI_listbase.h"
00044 #include "BLI_memarena.h"
00045 #include "BLI_edgehash.h"
00046 #include "BLI_math.h"
00047 #include "BLI_utildefines.h"
00048 #include "BLI_linklist.h"
00049 
00050 #include "MEM_guardedalloc.h"
00051 
00052 #include "BKE_cdderivedmesh.h"
00053 #include "BKE_modifier.h"
00054 #include "BKE_particle.h"
00055 
00056 
00057 #include "MOD_util.h"
00058 
00059 #if 0
00060 #define EDGESPLIT_DEBUG_3
00061 #define EDGESPLIT_DEBUG_2
00062 #define EDGESPLIT_DEBUG_1
00063 #define EDGESPLIT_DEBUG_0
00064 #endif
00065 
00066 static void initData(ModifierData *md)
00067 {
00068     EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
00069 
00070     /* default to 30-degree split angle, sharpness from both angle & flag
00071     */
00072     emd->split_angle = 30;
00073     emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
00074 }
00075 
00076 static void copyData(ModifierData *md, ModifierData *target)
00077 {
00078     EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
00079     EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
00080 
00081     temd->split_angle = emd->split_angle;
00082     temd->flags = emd->flags;
00083 }
00084 
00085 /* Mesh data for edgesplit operation */
00086 typedef struct SmoothVert {
00087     LinkNode *faces;     /* all faces which use this vert */
00088     int oldIndex; /* the index of the original DerivedMesh vert */
00089     int newIndex; /* the index of the new DerivedMesh vert */
00090 } SmoothVert;
00091 
00092 #define SMOOTHEDGE_NUM_VERTS 2
00093 
00094 typedef struct SmoothEdge {
00095     SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
00096     LinkNode *faces;     /* all faces which use this edge */
00097     int oldIndex; /* the index of the original DerivedMesh edge */
00098     int newIndex; /* the index of the new DerivedMesh edge */
00099     short flag; /* the flags from the original DerivedMesh edge */
00100 } SmoothEdge;
00101 
00102 #define SMOOTHFACE_MAX_EDGES 4
00103 
00104 typedef struct SmoothFace {
00105     SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
00106     int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
00107     float normal[3]; /* the normal of this face */
00108     int oldIndex; /* the index of the original DerivedMesh face */
00109     int newIndex; /* the index of the new DerivedMesh face */
00110 } SmoothFace;
00111 
00112 typedef struct SmoothMesh {
00113     SmoothVert *verts;
00114     SmoothEdge *edges;
00115     SmoothFace *faces;
00116     int num_verts, num_edges, num_faces;
00117     int max_verts, max_edges, max_faces;
00118     DerivedMesh *dm;
00119     float threshold; /* the cosine of the smoothing angle */
00120     int flags;
00121     MemArena *arena;
00122     ListBase propagatestack, reusestack;
00123 } SmoothMesh;
00124 
00125 static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
00126 {
00127     SmoothVert *copy = &mesh->verts[mesh->num_verts];
00128 
00129     assert(vert != NULL);
00130 
00131     if(mesh->num_verts >= mesh->max_verts) {
00132         printf("Attempted to add a SmoothMesh vert beyond end of array\n");
00133         return NULL;
00134     }
00135 
00136     *copy = *vert;
00137     copy->faces = NULL;
00138     copy->newIndex = mesh->num_verts;
00139     ++mesh->num_verts;
00140 
00141 #ifdef EDGESPLIT_DEBUG_2
00142     printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
00143 #endif
00144     return copy;
00145 }
00146 
00147 static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
00148 {
00149     SmoothEdge *copy = &mesh->edges[mesh->num_edges];
00150 
00151     if(mesh->num_edges >= mesh->max_edges) {
00152         printf("Attempted to add a SmoothMesh edge beyond end of array\n");
00153         return NULL;
00154     }
00155 
00156     *copy = *edge;
00157     copy->faces = NULL;
00158     copy->newIndex = mesh->num_edges;
00159     ++mesh->num_edges;
00160 
00161 #ifdef EDGESPLIT_DEBUG_2
00162     printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
00163 #endif
00164     return copy;
00165 }
00166 
00167 static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
00168 {
00169     int i;
00170     for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
00171         if(edge->verts[i] == vert) return 1;
00172 
00173     return 0;
00174 }
00175 
00176 static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
00177                   int max_verts, int max_edges, int max_faces)
00178 {
00179     SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
00180     mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
00181             "SmoothMesh.verts");
00182     mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
00183             "SmoothMesh.edges");
00184     mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
00185             "SmoothMesh.faces");
00186 
00187     mesh->num_verts = num_verts;
00188     mesh->num_edges = num_edges;
00189     mesh->num_faces = num_faces;
00190 
00191     mesh->max_verts = max_verts;
00192     mesh->max_edges = max_edges;
00193     mesh->max_faces = max_faces;
00194 
00195     return mesh;
00196 }
00197 
00198 static void smoothmesh_free(SmoothMesh *mesh)
00199 {
00200     int i;
00201 
00202     for(i = 0; i < mesh->num_verts; ++i)
00203         BLI_linklist_free(mesh->verts[i].faces, NULL);
00204 
00205     for(i = 0; i < mesh->num_edges; ++i)
00206         BLI_linklist_free(mesh->edges[i].faces, NULL);
00207     
00208     if(mesh->arena)
00209         BLI_memarena_free(mesh->arena);
00210 
00211     MEM_freeN(mesh->verts);
00212     MEM_freeN(mesh->edges);
00213     MEM_freeN(mesh->faces);
00214     MEM_freeN(mesh);
00215 }
00216 
00217 static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
00218 {
00219     int i;
00220     SmoothVert *tmp;
00221 
00222     if(max_verts <= mesh->max_verts) return;
00223 
00224     tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
00225 
00226     memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
00227 
00228     /* remap vert pointers in edges */
00229     for(i = 0; i < mesh->num_edges; ++i) {
00230         int j;
00231         SmoothEdge *edge = &mesh->edges[i];
00232 
00233         for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
00234             /* pointer arithmetic to get vert array index */
00235             edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
00236     }
00237 
00238     MEM_freeN(mesh->verts);
00239     mesh->verts = tmp;
00240     mesh->max_verts = max_verts;
00241 }
00242 
00243 static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
00244 {
00245     int i;
00246     SmoothEdge *tmp;
00247 
00248     if(max_edges <= mesh->max_edges) return;
00249 
00250     tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
00251 
00252     memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
00253 
00254     /* remap edge pointers in faces */
00255     for(i = 0; i < mesh->num_faces; ++i) {
00256         int j;
00257         SmoothFace *face = &mesh->faces[i];
00258 
00259         for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
00260             if(face->edges[j])
00261                 /* pointer arithmetic to get edge array index */
00262                 face->edges[j] = &tmp[face->edges[j] - mesh->edges];
00263     }
00264 
00265     MEM_freeN(mesh->edges);
00266     mesh->edges = tmp;
00267     mesh->max_edges = max_edges;
00268 }
00269 
00270 #ifdef EDGESPLIT_DEBUG_0
00271 static void smoothmesh_print(SmoothMesh *mesh)
00272 {
00273     int i, j;
00274     DerivedMesh *dm = mesh->dm;
00275 
00276     printf("--- SmoothMesh ---\n");
00277     printf("--- Vertices ---\n");
00278     for(i = 0; i < mesh->num_verts; i++) {
00279         SmoothVert *vert = &mesh->verts[i];
00280         LinkNode *node;
00281         MVert mv;
00282 
00283         dm->getVert(dm, vert->oldIndex, &mv);
00284 
00285         printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
00286             i, vert->oldIndex, vert->newIndex,
00287             mv.co[0], mv.co[1], mv.co[2]);
00288         printf(", faces={");
00289         for(node = vert->faces; node != NULL; node = node->next) {
00290             printf(" %d", ((SmoothFace *)node->link)->newIndex);
00291         }
00292         printf("}\n");
00293     }
00294 
00295     printf("\n--- Edges ---\n");
00296     for(i = 0; i < mesh->num_edges; i++) {
00297         SmoothEdge *edge = &mesh->edges[i];
00298         LinkNode *node;
00299 
00300         printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
00301             i,
00302             edge->oldIndex, edge->newIndex,
00303             edge->verts[0]->newIndex, edge->verts[1]->newIndex);
00304         if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
00305         printf(", faces={");
00306         for(node = edge->faces; node != NULL; node = node->next) {
00307             printf(" %d", ((SmoothFace *)node->link)->newIndex);
00308         }
00309         printf("}\n");
00310     }
00311 
00312     printf("\n--- Faces ---\n");
00313     for(i = 0; i < mesh->num_faces; i++) {
00314         SmoothFace *face = &mesh->faces[i];
00315 
00316         printf("%4d: indices={%4d, %4d}, edges={", i,
00317             face->oldIndex, face->newIndex);
00318         for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
00319             if(face->flip[j])
00320                 printf(" -%-2d", face->edges[j]->newIndex);
00321             else
00322                 printf("  %-2d", face->edges[j]->newIndex);
00323         }
00324         printf("}, verts={");
00325         for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
00326             printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
00327         }
00328         printf("}\n");
00329     }
00330 }
00331 #endif
00332 
00333 static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
00334 {
00335     SmoothMesh *mesh;
00336     EdgeHash *edges = BLI_edgehash_new();
00337     int i;
00338     int totvert, totedge, totface;
00339 
00340     totvert = dm->getNumVerts(dm);
00341     totedge = dm->getNumEdges(dm);
00342     totface = dm->getNumFaces(dm);
00343 
00344     mesh = smoothmesh_new(totvert, totedge, totface,
00345             totvert, totedge, totface);
00346 
00347     mesh->dm = dm;
00348 
00349     for(i = 0; i < totvert; i++) {
00350         SmoothVert *vert = &mesh->verts[i];
00351 
00352         vert->oldIndex = vert->newIndex = i;
00353     }
00354 
00355     for(i = 0; i < totedge; i++) {
00356         SmoothEdge *edge = &mesh->edges[i];
00357         MEdge med;
00358 
00359         dm->getEdge(dm, i, &med);
00360         edge->verts[0] = &mesh->verts[med.v1];
00361         edge->verts[1] = &mesh->verts[med.v2];
00362         edge->oldIndex = edge->newIndex = i;
00363         edge->flag = med.flag;
00364 
00365         BLI_edgehash_insert(edges, med.v1, med.v2, edge);
00366     }
00367 
00368     for(i = 0; i < totface; i++) {
00369         SmoothFace *face = &mesh->faces[i];
00370         MFace mf;
00371         MVert v1, v2, v3;
00372         int j;
00373 
00374         dm->getFace(dm, i, &mf);
00375 
00376         dm->getVert(dm, mf.v1, &v1);
00377         dm->getVert(dm, mf.v2, &v2);
00378         dm->getVert(dm, mf.v3, &v3);
00379         face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
00380         if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
00381         face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
00382         if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
00383         if(mf.v4) {
00384             MVert v4;
00385             dm->getVert(dm, mf.v4, &v4);
00386             face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
00387             if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
00388             face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
00389             if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
00390             normal_quad_v3( face->normal,v1.co, v2.co, v3.co, v4.co);
00391         } else {
00392             face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
00393             if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
00394             face->edges[3] = NULL;
00395             normal_tri_v3( face->normal,v1.co, v2.co, v3.co);
00396         }
00397 
00398         for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
00399             SmoothEdge *edge = face->edges[j];
00400             BLI_linklist_prepend(&edge->faces, face);
00401             BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
00402         }
00403 
00404         face->oldIndex = face->newIndex = i;
00405     }
00406 
00407     BLI_edgehash_free(edges, NULL);
00408 
00409     return mesh;
00410 }
00411 
00412 static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
00413 {
00414     DerivedMesh *result = CDDM_from_template(mesh->dm,
00415             mesh->num_verts,
00416             mesh->num_edges,
00417             mesh->num_faces);
00418     MVert *new_verts = CDDM_get_verts(result);
00419     MEdge *new_edges = CDDM_get_edges(result);
00420     MFace *new_faces = CDDM_get_faces(result);
00421     int i;
00422 
00423     for(i = 0; i < mesh->num_verts; ++i) {
00424         SmoothVert *vert = &mesh->verts[i];
00425         MVert *newMV = &new_verts[vert->newIndex];
00426 
00427         DM_copy_vert_data(mesh->dm, result,
00428                 vert->oldIndex, vert->newIndex, 1);
00429         mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
00430     }
00431 
00432     for(i = 0; i < mesh->num_edges; ++i) {
00433         SmoothEdge *edge = &mesh->edges[i];
00434         MEdge *newME = &new_edges[edge->newIndex];
00435 
00436         DM_copy_edge_data(mesh->dm, result,
00437                 edge->oldIndex, edge->newIndex, 1);
00438         mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
00439         newME->v1 = edge->verts[0]->newIndex;
00440         newME->v2 = edge->verts[1]->newIndex;
00441     }
00442 
00443     for(i = 0; i < mesh->num_faces; ++i) {
00444         SmoothFace *face = &mesh->faces[i];
00445         MFace *newMF = &new_faces[face->newIndex];
00446 
00447         DM_copy_face_data(mesh->dm, result,
00448                 face->oldIndex, face->newIndex, 1);
00449         mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
00450 
00451         newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
00452         newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
00453         newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
00454 
00455         if(face->edges[3]) {
00456             newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
00457         } else {
00458             newMF->v4 = 0;
00459         }
00460     }
00461 
00462     return result;
00463 }
00464 
00465 /* returns the other vert in the given edge
00466  */
00467 static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
00468 {
00469     if(edge->verts[0] == vert) return edge->verts[1];
00470     else return edge->verts[0];
00471 }
00472 
00473 /* returns the other edge in the given face that uses the given vert
00474  * returns NULL if no other edge in the given face uses the given vert
00475  * (this should never happen)
00476  */
00477 static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
00478                   SmoothEdge *edge)
00479 {
00480     int i,j;
00481     for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
00482         SmoothEdge *tmp_edge = face->edges[i];
00483         if(tmp_edge == edge) continue;
00484 
00485         for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
00486             if(tmp_edge->verts[j] == vert) return tmp_edge;
00487     }
00488 
00489     /* if we get to here, something's wrong (there should always be 2 edges
00490     * which use the same vert in a face)
00491     */
00492     return NULL;
00493 }
00494 
00495 /* returns a face attached to the given edge which is not the given face.
00496  * returns NULL if no other faces use this edge.
00497  */
00498 static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
00499 {
00500     LinkNode *node;
00501 
00502     for(node = edge->faces; node != NULL; node = node->next)
00503         if(node->link != face) return node->link;
00504 
00505     return NULL;
00506 }
00507 
00508 #if 0
00509 /* copies source list to target, overwriting target (target is not freed)
00510  * nodes in the copy will be in the same order as in source
00511  */
00512 static void linklist_copy(LinkNode **target, LinkNode *source)
00513 {
00514     LinkNode *node = NULL;
00515     *target = NULL;
00516 
00517     for(; source; source = source->next) {
00518         if(node) {
00519             node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
00520             node = node->next;
00521         } else {
00522             node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
00523         }
00524         node->link = source->link;
00525         node->next = NULL;
00526     }
00527 }
00528 #endif
00529 
00530 /* appends source to target if it's not already in target */
00531 static void linklist_append_unique(LinkNode **target, void *source)
00532 {
00533     LinkNode *node;
00534     LinkNode *prev = NULL;
00535 
00536     /* check if source value is already in the list */
00537     for(node = *target; node; prev = node, node = node->next)
00538         if(node->link == source) return;
00539 
00540     node = MEM_mallocN(sizeof(*node), "nlink");
00541     node->next = NULL;
00542     node->link = source;
00543 
00544     if(prev) prev->next = node;
00545     else *target = node;
00546 }
00547 
00548 /* appends elements of source which aren't already in target to target */
00549 static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
00550 {
00551     for(; source; source = source->next)
00552         linklist_append_unique(target, source->link);
00553 }
00554 
00555 #if 0 /* this is no longer used, it should possibly be removed */
00556 /* prepends prepend to list - doesn't copy nodes, just joins the lists */
00557 static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
00558 {
00559     if(prepend) {
00560         LinkNode *node = prepend;
00561         while(node->next) node = node->next;
00562 
00563         node->next = *list;
00564         *list = prepend;
00565     }
00566 }
00567 #endif
00568 
00569 /* returns 1 if the linked list contains the given pointer, 0 otherwise
00570  */
00571 static int linklist_contains(LinkNode *list, void *ptr)
00572 {
00573     LinkNode *node;
00574 
00575     for(node = list; node; node = node->next)
00576         if(node->link == ptr) return 1;
00577 
00578     return 0;
00579 }
00580 
00581 /* returns 1 if the first linked list is a subset of the second (comparing
00582  * pointer values), 0 if not
00583  */
00584 static int linklist_subset(LinkNode *list1, LinkNode *list2)
00585 {
00586     for(; list1; list1 = list1->next)
00587         if(!linklist_contains(list2, list1->link))
00588             return 0;
00589 
00590     return 1;
00591 }
00592 
00593 #if 0
00594 /* empties the linked list
00595  * frees pointers with freefunc if freefunc is not NULL
00596  */
00597 static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
00598 {
00599     BLI_linklist_free(*list, freefunc);
00600     *list = NULL;
00601 }
00602 #endif
00603 
00604 /* removes the first instance of value from the linked list
00605  * frees the pointer with freefunc if freefunc is not NULL
00606  */
00607 static void linklist_remove_first(LinkNode **list, void *value,
00608                   LinkNodeFreeFP freefunc)
00609 {
00610     LinkNode *node = *list;
00611     LinkNode *prev = NULL;
00612 
00613     while(node && node->link != value) {
00614         prev = node;
00615         node = node->next;
00616     }
00617 
00618     if(node) {
00619         if(prev)
00620             prev->next = node->next;
00621         else
00622             *list = node->next;
00623 
00624         if(freefunc)
00625             freefunc(node->link);
00626 
00627         MEM_freeN(node);
00628     }
00629 }
00630 
00631 /* removes all elements in source from target */
00632 static void linklist_remove_list(LinkNode **target, LinkNode *source,
00633                  LinkNodeFreeFP freefunc)
00634 {
00635     for(; source; source = source->next)
00636         linklist_remove_first(target, source->link, freefunc);
00637 }
00638 
00639 #ifdef EDGESPLIT_DEBUG_0
00640 static void print_ptr(void *ptr)
00641 {
00642     printf("%p\n", ptr);
00643 }
00644 
00645 static void print_edge(void *ptr)
00646 {
00647     SmoothEdge *edge = ptr;
00648     printf(" %4d", edge->newIndex);
00649 }
00650 
00651 static void print_face(void *ptr)
00652 {
00653     SmoothFace *face = ptr;
00654     printf(" %4d", face->newIndex);
00655 }
00656 #endif
00657 
00658 typedef struct ReplaceData {
00659     void *find;
00660     void *replace;
00661 } ReplaceData;
00662 
00663 static void edge_replace_vert(void *ptr, void *userdata)
00664 {
00665     SmoothEdge *edge = ptr;
00666     SmoothVert *find = ((ReplaceData *)userdata)->find;
00667     SmoothVert *replace = ((ReplaceData *)userdata)->replace;
00668     int i;
00669 
00670 #ifdef EDGESPLIT_DEBUG_3
00671     printf("replacing vert %4d with %4d in edge %4d",
00672         find->newIndex, replace->newIndex, edge->newIndex);
00673     printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
00674 #endif
00675 
00676     for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
00677         if(edge->verts[i] == find) {
00678             linklist_append_list_unique(&replace->faces, edge->faces);
00679             linklist_remove_list(&find->faces, edge->faces, NULL);
00680 
00681             edge->verts[i] = replace;
00682         }
00683     }
00684 
00685 #ifdef EDGESPLIT_DEBUG_3
00686     printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
00687 #endif
00688 }
00689 
00690 static void face_replace_vert(void *ptr, void *userdata)
00691 {
00692     SmoothFace *face = ptr;
00693     int i;
00694 
00695     for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
00696         edge_replace_vert(face->edges[i], userdata);
00697 }
00698 
00699 static void face_replace_edge(void *ptr, void *userdata)
00700 {
00701     SmoothFace *face = ptr;
00702     SmoothEdge *find = ((ReplaceData *)userdata)->find;
00703     SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
00704     int i;
00705 
00706 #ifdef EDGESPLIT_DEBUG_3
00707     printf("replacing edge %4d with %4d in face %4d",
00708         find->newIndex, replace->newIndex, face->newIndex);
00709     if(face->edges[3])
00710         printf(": {%2d %2d %2d %2d}",
00711             face->edges[0]->newIndex, face->edges[1]->newIndex,
00712             face->edges[2]->newIndex, face->edges[3]->newIndex);
00713     else
00714         printf(": {%2d %2d %2d}",
00715             face->edges[0]->newIndex, face->edges[1]->newIndex,
00716             face->edges[2]->newIndex);
00717 #endif
00718 
00719     for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
00720         if(face->edges[i] == find) {
00721             linklist_remove_first(&face->edges[i]->faces, face, NULL);
00722             BLI_linklist_prepend(&replace->faces, face);
00723             face->edges[i] = replace;
00724         }
00725     }
00726 
00727 #ifdef EDGESPLIT_DEBUG_3
00728     if(face->edges[3])
00729         printf(" -> {%2d %2d %2d %2d}\n",
00730             face->edges[0]->newIndex, face->edges[1]->newIndex,
00731             face->edges[2]->newIndex, face->edges[3]->newIndex);
00732     else
00733         printf(" -> {%2d %2d %2d}\n",
00734             face->edges[0]->newIndex, face->edges[1]->newIndex,
00735             face->edges[2]->newIndex);
00736 #endif
00737 }
00738 
00739 static int edge_is_loose(SmoothEdge *edge)
00740 {
00741     return !(edge->faces && edge->faces->next);
00742 }
00743 
00744 static int edge_is_sharp(SmoothEdge *edge)
00745 {
00746 #ifdef EDGESPLIT_DEBUG_1
00747     printf("edge %d: ", edge->newIndex);
00748 #endif
00749     if(edge->flag & ME_SHARP) {
00750         /* edge can only be sharp if it has at least 2 faces */
00751         if(!edge_is_loose(edge)) {
00752 #ifdef EDGESPLIT_DEBUG_1
00753             printf("sharp\n");
00754 #endif
00755             return 1;
00756         } else {
00757             /* edge is loose, so it can't be sharp */
00758             edge->flag &= ~ME_SHARP;
00759         }
00760     }
00761 
00762 #ifdef EDGESPLIT_DEBUG_1
00763     printf("not sharp\n");
00764 #endif
00765     return 0;
00766 }
00767 
00768 /* finds another sharp edge which uses vert, by traversing faces around the
00769  * vert until it does one of the following:
00770  * - hits a loose edge (the edge is returned)
00771  * - hits a sharp edge (the edge is returned)
00772  * - returns to the start edge (NULL is returned)
00773  */
00774 static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, LinkNode **visited_faces)
00775 {
00776     SmoothFace *face = NULL;
00777     SmoothEdge *edge2 = NULL;
00778     /* holds the edges we've seen so we can avoid looping indefinitely */
00779     LinkNode *visited_edges = NULL;
00780 #ifdef EDGESPLIT_DEBUG_1
00781     printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
00782         edge->newIndex, vert->newIndex);
00783 #endif
00784 
00785     /* get a face on which to start */
00786     if(edge->faces) face = edge->faces->link;
00787     else return NULL;
00788 
00789     /* record this edge as visited */
00790     BLI_linklist_prepend(&visited_edges, edge);
00791 
00792     /* get the next edge */
00793     edge2 = other_edge(face, vert, edge);
00794 
00795     /* record this face as visited */
00796     if(visited_faces)
00797         BLI_linklist_prepend(visited_faces, face);
00798 
00799     /* search until we hit a loose edge or a sharp edge or an edge we've
00800     * seen before
00801     */
00802     while(face && !edge_is_sharp(edge2)
00803              && !linklist_contains(visited_edges, edge2)) {
00804 #ifdef EDGESPLIT_DEBUG_3
00805         printf("current face %4d; current edge %4d\n", face->newIndex,
00806             edge2->newIndex);
00807 #endif
00808         /* get the next face */
00809         face = other_face(edge2, face);
00810 
00811         /* if face == NULL, edge2 is a loose edge */
00812         if(face) {
00813             /* record this face as visited */
00814             if(visited_faces)
00815                 BLI_linklist_prepend(visited_faces, face);
00816 
00817             /* record this edge as visited */
00818             BLI_linklist_prepend(&visited_edges, edge2);
00819 
00820             /* get the next edge */
00821             edge2 = other_edge(face, vert, edge2);
00822 #ifdef EDGESPLIT_DEBUG_3
00823             printf("next face %4d; next edge %4d\n",
00824                 face->newIndex, edge2->newIndex);
00825         } else {
00826             printf("loose edge: %4d\n", edge2->newIndex);
00827 #endif
00828         }
00829     }
00830 
00831     /* either we came back to the start edge or we found a sharp/loose edge */
00832     if(linklist_contains(visited_edges, edge2))
00833         /* we came back to the start edge */
00834         edge2 = NULL;
00835 
00836     BLI_linklist_free(visited_edges, NULL);
00837 
00838 #ifdef EDGESPLIT_DEBUG_1
00839     printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
00840         "returning edge %d\n",
00841         edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
00842 #endif
00843     return edge2;
00844 }
00845 
00846 static void split_single_vert(SmoothVert *vert, SmoothFace *face,
00847                   SmoothMesh *mesh)
00848 {
00849     SmoothVert *copy_vert;
00850     ReplaceData repdata;
00851 
00852     copy_vert = smoothvert_copy(vert, mesh);
00853 
00854     if(copy_vert == NULL) {
00855         /* bug [#26316], this prevents a segfault
00856          * but this still needs fixing */
00857         return;
00858     }
00859 
00860     repdata.find = vert;
00861     repdata.replace = copy_vert;
00862     face_replace_vert(face, &repdata);
00863 }
00864 
00865 typedef struct PropagateEdge {
00866     struct PropagateEdge *next, *prev;
00867     SmoothEdge *edge;
00868     SmoothVert *vert;
00869 } PropagateEdge;
00870 
00871 static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
00872 {
00873     PropagateEdge *pedge = mesh->reusestack.first;
00874 
00875     if(pedge) {
00876         BLI_remlink(&mesh->reusestack, pedge);
00877     }
00878     else {
00879         if(!mesh->arena) {
00880             mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "edgesplit arena");
00881             BLI_memarena_use_calloc(mesh->arena);
00882         }
00883 
00884         pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
00885     }
00886 
00887     pedge->edge = edge;
00888     pedge->vert = vert;
00889     BLI_addhead(&mesh->propagatestack, pedge);
00890 }
00891 
00892 static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
00893 {
00894     PropagateEdge *pedge = mesh->propagatestack.first;
00895 
00896     if(pedge) {
00897         *edge = pedge->edge;
00898         *vert = pedge->vert;
00899         BLI_remlink(&mesh->propagatestack, pedge);
00900         BLI_addhead(&mesh->reusestack, pedge);
00901     }
00902     else {
00903         *edge = NULL;
00904         *vert = NULL;
00905     }
00906 }
00907 
00908 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
00909 
00910 static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
00911                 SmoothMesh *mesh)
00912 {
00913     SmoothEdge *edge2;
00914     LinkNode *visited_faces = NULL;
00915 #ifdef EDGESPLIT_DEBUG_1
00916     printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
00917         edge->newIndex, vert->newIndex);
00918 #endif
00919 
00920     edge2 = find_other_sharp_edge(vert, edge, &visited_faces);
00921 
00922     if(!edge2) {
00923         /* didn't find a sharp or loose edge, so we've hit a dead end */
00924     } else if(!edge_is_loose(edge2)) {
00925         /* edge2 is not loose, so it must be sharp */
00926         if(edge_is_loose(edge)) {
00927             /* edge is loose, so we can split edge2 at this vert */
00928             split_edge(edge2, vert, mesh);
00929         } else if(edge_is_sharp(edge)) {
00930             /* both edges are sharp, so we can split the pair at vert */
00931             split_edge(edge, vert, mesh);
00932         } else {
00933             /* edge is not sharp, so try to split edge2 at its other vert */
00934             split_edge(edge2, other_vert(edge2, vert), mesh);
00935         }
00936     } else { /* edge2 is loose */
00937         if(edge_is_loose(edge)) {
00938             SmoothVert *vert2;
00939             ReplaceData repdata;
00940 
00941             /* can't split edge, what should we do with vert? */
00942             if(linklist_subset(vert->faces, visited_faces)) {
00943                 /* vert has only one fan of faces attached; don't split it */
00944             } else {
00945                 /* vert has more than one fan of faces attached; split it */
00946                 vert2 = smoothvert_copy(vert, mesh);
00947 
00948                 /* fails in rare cases, see [#26993] */
00949                 if(vert2) {
00950                     /* replace vert with its copy in visited_faces */
00951                     repdata.find = vert;
00952                     repdata.replace = vert2;
00953                     BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
00954                 }
00955             }
00956         } else {
00957             /* edge is not loose, so it must be sharp; split it */
00958             split_edge(edge, vert, mesh);
00959         }
00960     }
00961 
00962     BLI_linklist_free(visited_faces, NULL);
00963 #ifdef EDGESPLIT_DEBUG_1
00964     printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
00965         edge->newIndex, vert->newIndex);
00966 #endif
00967 }
00968 
00969 static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
00970 {
00971     SmoothEdge *edge2;
00972     SmoothVert *vert2;
00973     ReplaceData repdata;
00974     /* the list of faces traversed while looking for a sharp edge */
00975     LinkNode *visited_faces = NULL;
00976 #ifdef EDGESPLIT_DEBUG_1
00977     printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
00978         edge->newIndex, vert->newIndex);
00979 #endif
00980 
00981     edge2 = find_other_sharp_edge(vert, edge, &visited_faces);
00982 
00983     if(!edge2) {
00984         /* didn't find a sharp or loose edge, so try the other vert */
00985         vert2 = other_vert(edge, vert);
00986         push_propagate_stack(edge, vert2, mesh);
00987     } else if(!edge_is_loose(edge2)) {
00988         /* edge2 is not loose, so it must be sharp */
00989         SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
00990         SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
00991         SmoothVert *vert2;
00992 
00993         /* replace edge with its copy in visited_faces */
00994         repdata.find = edge;
00995         repdata.replace = copy_edge;
00996         BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
00997 
00998         /* replace edge2 with its copy in visited_faces */
00999         repdata.find = edge2;
01000         repdata.replace = copy_edge2;
01001         BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
01002 
01003         vert2 = smoothvert_copy(vert, mesh);
01004 
01005         /* replace vert with its copy in visited_faces (must be done after
01006         * edge replacement so edges have correct vertices)
01007         */
01008         repdata.find = vert;
01009         repdata.replace = vert2;
01010         BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
01011 
01012         /* all copying and replacing is done; the mesh should be consistent.
01013         * now propagate the split to the vertices at either end
01014         */
01015         push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
01016         push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh);
01017 
01018         if(smoothedge_has_vert(edge, vert))
01019             push_propagate_stack(edge, vert, mesh);
01020     } else {
01021         /* edge2 is loose */
01022         SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
01023         SmoothVert *vert2;
01024 
01025         /* replace edge with its copy in visited_faces */
01026         repdata.find = edge;
01027         repdata.replace = copy_edge;
01028         BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
01029 
01030         vert2 = smoothvert_copy(vert, mesh);
01031 
01032         /* bug [#29205] which is caused by exactly the same reason as [#26316]
01033            this check will only prevent crash without fixing actual issue and
01034            some vertices can stay unsplitted when they should (sergey) */
01035         if(vert2) {
01036             /* replace vert with its copy in visited_faces (must be done after
01037              * edge replacement so edges have correct vertices)
01038              */
01039             repdata.find = vert;
01040             repdata.replace = vert2;
01041             BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
01042         }
01043 
01044         /* copying and replacing is done; the mesh should be consistent.
01045         * now propagate the split to the vertex at the other end
01046         */
01047         push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
01048 
01049         if(smoothedge_has_vert(edge, vert))
01050             push_propagate_stack(edge, vert, mesh);
01051     }
01052 
01053     BLI_linklist_free(visited_faces, NULL);
01054 #ifdef EDGESPLIT_DEBUG_1
01055     printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
01056         edge->newIndex, vert->newIndex);
01057 #endif
01058 }
01059 
01060 static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
01061                       int flags, int *extra_edges)
01062 {
01063     /* if normal1 dot normal2 < threshold, angle is greater, so split */
01064     /* FIXME not sure if this always works */
01065     /* 0.00001 added for floating-point rounding */
01066     float threshold = cos((split_angle + 0.00001f) * (float)M_PI / 180.0f);
01067     int i;
01068 
01069     *extra_edges = 0;
01070 
01071     /* loop through edges, counting potential new ones */
01072     for(i = 0; i < mesh->num_edges; i++) {
01073         SmoothEdge *edge = &mesh->edges[i];
01074         int sharp = 0;
01075 
01076         /* treat all non-manifold edges (3 or more faces) as sharp */
01077         if(edge->faces && edge->faces->next && edge->faces->next->next) {
01078             LinkNode *node;
01079 
01080             /* this edge is sharp */
01081             sharp = 1;
01082 
01083             /* add an extra edge for every face beyond the first */
01084             *extra_edges += 2;
01085             for(node = edge->faces->next->next->next; node; node = node->next)
01086                 (*extra_edges)++;
01087         } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
01088                      && !edge_is_loose(edge)) {
01089             /* (the edge can only be sharp if we're checking angle or flag,
01090             * and it has at least 2 faces) */
01091 
01092             /* if we're checking the sharp flag and it's set, good */
01093             if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
01094                 /* this edge is sharp */
01095                 sharp = 1;
01096 
01097                 (*extra_edges)++;
01098             } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
01099                 /* we know the edge has 2 faces, so check the angle */
01100                 SmoothFace *face1 = edge->faces->link;
01101                 SmoothFace *face2 = edge->faces->next->link;
01102                 float edge_angle_cos = dot_v3v3(face1->normal,
01103                 face2->normal);
01104 
01105                 if(edge_angle_cos < threshold) {
01106                     /* this edge is sharp */
01107                     sharp = 1;
01108 
01109                     (*extra_edges)++;
01110                 }
01111             }
01112         }
01113 
01114         /* set/clear sharp flag appropriately */
01115         if(sharp) edge->flag |= ME_SHARP;
01116         else edge->flag &= ~ME_SHARP;
01117     }
01118 }
01119 
01120 static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
01121 {
01122     SmoothVert *vert;
01123     int i;
01124     /* if normal1 dot normal2 < threshold, angle is greater, so split */
01125     /* FIXME not sure if this always works */
01126     /* 0.00001 added for floating-point rounding */
01127     mesh->threshold = cosf((split_angle + 0.00001f) * (float)M_PI / 180.0f);
01128     mesh->flags = flags;
01129 
01130     /* loop through edges, splitting sharp ones */
01131     /* can't use an iterator here, because we'll be adding edges */
01132     for(i = 0; i < mesh->num_edges; i++) {
01133         SmoothEdge *edge = &mesh->edges[i];
01134 
01135         if(edge_is_sharp(edge)) {
01136             split_edge(edge, edge->verts[0], mesh);
01137 
01138             do {
01139                 pop_propagate_stack(&edge, &vert, mesh);
01140                 if(edge && smoothedge_has_vert(edge, vert))
01141                     propagate_split(edge, vert, mesh);
01142             } while(edge);
01143         }
01144     }
01145 }
01146 
01147 static int count_bridge_verts(SmoothMesh *mesh)
01148 {
01149     int i, j, count = 0;
01150 
01151     for(i = 0; i < mesh->num_faces; i++) {
01152         SmoothFace *face = &mesh->faces[i];
01153 
01154         for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
01155             SmoothEdge *edge = face->edges[j];
01156             SmoothEdge *next_edge;
01157             SmoothVert *vert = edge->verts[1 - face->flip[j]];
01158             int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
01159 
01160             /* wrap next around if at last edge */
01161             if(!face->edges[next]) next = 0;
01162 
01163             next_edge = face->edges[next];
01164 
01165             /* if there are other faces sharing this vertex but not
01166             * these edges, the vertex will be split, so count it
01167             */
01168             /* vert has to have at least one face (this one), so faces != 0 */
01169             if(!edge->faces->next && !next_edge->faces->next
01170                          && vert->faces->next) {
01171                 count++;
01172                          }
01173         }
01174     }
01175 
01176     /* each bridge vert will be counted once per face that uses it,
01177     * so count is too high, but it's ok for now
01178     */
01179     return count;
01180 }
01181 
01182 static void split_bridge_verts(SmoothMesh *mesh)
01183 {
01184     int i,j;
01185 
01186     for(i = 0; i < mesh->num_faces; i++) {
01187         SmoothFace *face = &mesh->faces[i];
01188 
01189         for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
01190             SmoothEdge *edge = face->edges[j];
01191             SmoothEdge *next_edge;
01192             SmoothVert *vert = edge->verts[1 - face->flip[j]];
01193             int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
01194 
01195             /* wrap next around if at last edge */
01196             if(!face->edges[next]) next = 0;
01197 
01198             next_edge = face->edges[next];
01199 
01200             /* if there are other faces sharing this vertex but not
01201             * these edges, split the vertex
01202             */
01203             /* vert has to have at least one face (this one), so faces != 0 */
01204             if(!edge->faces->next && !next_edge->faces->next
01205                          && vert->faces->next)
01206                 /* FIXME this needs to find all faces that share edges with
01207                 * this one and split off together
01208                 */
01209                 split_single_vert(vert, face, mesh);
01210         }
01211     }
01212 }
01213 
01214 static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd, DerivedMesh *dm)
01215 {
01216     SmoothMesh *mesh;
01217     DerivedMesh *result;
01218     int max_verts, max_edges;
01219 
01220     if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
01221         return dm;
01222 
01223     /* 1. make smoothmesh with initial number of elements */
01224     mesh = smoothmesh_from_derivedmesh(dm);
01225 
01226     /* 2. count max number of elements to add */
01227     tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
01228     max_verts = max_edges * 2 + mesh->max_verts;
01229     max_verts += count_bridge_verts(mesh);
01230     max_edges += mesh->max_edges;
01231 
01232     /* 3. reallocate smoothmesh arrays & copy elements across */
01233     /* 4. remap copied elements' pointers to point into the new arrays */
01234     smoothmesh_resize_verts(mesh, max_verts);
01235     smoothmesh_resize_edges(mesh, max_edges);
01236 
01237 #ifdef EDGESPLIT_DEBUG_1
01238     printf("********** Pre-split **********\n");
01239     smoothmesh_print(mesh);
01240 #endif
01241 
01242     split_sharp_edges(mesh, emd->split_angle, emd->flags);
01243 #ifdef EDGESPLIT_DEBUG_1
01244     printf("********** Post-edge-split **********\n");
01245     smoothmesh_print(mesh);
01246 #endif
01247 
01248     split_bridge_verts(mesh);
01249 
01250 #ifdef EDGESPLIT_DEBUG_1
01251     printf("********** Post-vert-split **********\n");
01252     smoothmesh_print(mesh);
01253 #endif
01254 
01255 #ifdef EDGESPLIT_DEBUG_0
01256     printf("Edgesplit: Estimated %d verts & %d edges, "
01257         "found %d verts & %d edges\n", max_verts, max_edges,
01258         mesh->num_verts, mesh->num_edges);
01259 #endif
01260 
01261     result = CDDM_from_smoothmesh(mesh);
01262     smoothmesh_free(mesh);
01263 
01264     return result;
01265 }
01266 
01267 static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
01268                         DerivedMesh *derivedData,
01269                         int UNUSED(useRenderParams),
01270                         int UNUSED(isFinalCalc))
01271 {
01272     DerivedMesh *result;
01273     EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
01274 
01275     result = edgesplitModifier_do(emd, derivedData);
01276 
01277     if(result != derivedData)
01278         CDDM_calc_normals(result);
01279 
01280     return result;
01281 }
01282 
01283 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
01284                         struct EditMesh *UNUSED(editData),
01285                         DerivedMesh *derivedData)
01286 {
01287     return applyModifier(md, ob, derivedData, 0, 1);
01288 }
01289 
01290 
01291 ModifierTypeInfo modifierType_EdgeSplit = {
01292     /* name */              "EdgeSplit",
01293     /* structName */        "EdgeSplitModifierData",
01294     /* structSize */        sizeof(EdgeSplitModifierData),
01295     /* type */              eModifierTypeType_Constructive,
01296     /* flags */             eModifierTypeFlag_AcceptsMesh
01297                             | eModifierTypeFlag_AcceptsCVs
01298                             | eModifierTypeFlag_SupportsMapping
01299                             | eModifierTypeFlag_SupportsEditmode
01300                             | eModifierTypeFlag_EnableInEditmode,
01301 
01302     /* copyData */          copyData,
01303     /* deformVerts */       NULL,
01304     /* deformMatrices */    NULL,
01305     /* deformVertsEM */     NULL,
01306     /* deformMatricesEM */  NULL,
01307     /* applyModifier */     applyModifier,
01308     /* applyModifierEM */   applyModifierEM,
01309     /* initData */          initData,
01310     /* requiredDataMask */  NULL,
01311     /* freeData */          NULL,
01312     /* isDisabled */        NULL,
01313     /* updateDepgraph */    NULL,
01314     /* dependsOnTime */     NULL,
01315     /* dependsOnNormals */  NULL,
01316     /* foreachObjectLink */ NULL,
01317     /* foreachIDLink */     NULL,
01318     /* foreachTexLink */    NULL,
01319 };