Blender V2.61 - r43446
|
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 };