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