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