Blender V2.61 - r43446
|
00001 /* 00002 * BME_eulers.c jan 2007 00003 * 00004 * BMesh Euler construction API. 00005 * 00006 * 00007 * ***** BEGIN GPL LICENSE BLOCK ***** 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * about this. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with this program; if not, write to the Free Software Foundation, 00022 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00023 * 00024 * The Original Code is Copyright (C) 2004 Blender Foundation. 00025 * All rights reserved. 00026 * 00027 * The Original Code is: all of this file. 00028 * 00029 * Contributor(s): Geoffrey Bantle. 00030 * 00031 * ***** END GPL LICENSE BLOCK ***** 00032 */ 00033 00039 #include "MEM_guardedalloc.h" 00040 #include "BLI_listbase.h" 00041 #include "BLI_utildefines.h" 00042 00043 #include "bmesh_private.h" 00044 00045 /********************************************************* 00046 * "Euler API" * 00047 * * 00048 * * 00049 * Primitive construction operators for mesh tools. * 00050 * * 00051 **********************************************************/ 00052 00053 00054 /* 00055 The functions in this file represent the 'primitive' or 'atomic' operators that 00056 mesh tools use to manipulate the topology of the structure.* The purpose of these 00057 functions is to provide a trusted set of operators to manipulate the mesh topology 00058 and which can also be combined together like building blocks to create more 00059 sophisticated tools. It needs to be stressed that NO manipulation of an existing 00060 mesh structure should be done outside of these functions. 00061 00062 In the BMesh system, each euler is named by an ancronym which describes what it actually does. 00063 Furthermore each Euler has a logical inverse. An important design criteria of all Eulers is that 00064 through a Euler's logical inverse you can 'undo' an operation. (Special note should 00065 be taken of BME_loop_reverse, which is its own inverse). 00066 00067 BME_MF/KF: Make Face and Kill Face 00068 BME_ME/KE: Make Edge and Kill Edge 00069 BME_MV/KV: Make Vert and Kill Vert 00070 BME_SEMV/JEKV: Split Edge, Make Vert and Join Edge, Kill Vert 00071 BME_SFME/JFKE: Split Face, Make Edge and Join Face, Kill Edge 00072 BME_loop_reverse: Reverse a Polygon's loop cycle. (used for flip normals for one) 00073 00074 Using a combination of these eleven eulers any non-manifold modelling operation can be achieved. 00075 Each Euler operator has a detailed explanation of what is does in the comments preceding its 00076 code. 00077 00078 *The term "Euler Operator" is actually a misnomer when referring to a non-manifold 00079 data structure. Its use is in keeping with the convention established by others. 00080 00081 TODO: 00082 -Finish inserting 'strict' validation in all Eulers 00083 */ 00084 00085 void *BME_exit(char *s) { 00086 if (s) printf("%s\n",s); 00087 return NULL; 00088 } 00089 00090 #define RETCLEAR(bm) {bm->rval->v = bm->rval->e = bm->rval->f = bm->rva->l = NULL;} 00091 /*MAKE Eulers*/ 00092 00104 BME_Vert *BME_MV(BME_Mesh *bm, float *vec){ 00105 BME_Vert *v = BME_addvertlist(bm, NULL); 00106 VECCOPY(v->co,vec); 00107 return v; 00108 } 00109 00124 BME_Edge *BME_ME(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2){ 00125 BME_Edge *e=NULL; 00126 BME_CycleNode *d1=NULL, *d2=NULL; 00127 int valance1=0, valance2=0, edok; 00128 00129 /*edge must be between two distinct vertices...*/ 00130 if(v1 == v2) return NULL; 00131 00132 #ifndef BME_FASTEULER 00133 /*count valance of v1*/ 00134 if(v1->edge){ 00135 d1 = BME_disk_getpointer(v1->edge,v1); 00136 if(d1) valance1 = BME_cycle_length(d1); 00137 else BME_error(); 00138 } 00139 if(v2->edge){ 00140 d2 = BME_disk_getpointer(v2->edge,v2); 00141 if(d2) valance2 = BME_cycle_length(d2); 00142 else BME_error(); 00143 } 00144 #endif 00145 00146 /*go ahead and add*/ 00147 e = BME_addedgelist(bm, v1, v2, NULL); 00148 BME_disk_append_edge(e, e->v1); 00149 BME_disk_append_edge(e, e->v2); 00150 00151 #ifndef BME_FASTEULER 00152 /*verify disk cycle lengths*/ 00153 d1 = BME_disk_getpointer(e, e->v1); 00154 edok = BME_cycle_validate(valance1+1, d1); 00155 if(!edok) BME_error(); 00156 d2 = BME_disk_getpointer(e, e->v2); 00157 edok = BME_cycle_validate(valance2+1, d2); 00158 if(!edok) BME_error(); 00159 00160 /*verify that edge actually made it into the cycle*/ 00161 edok = BME_disk_hasedge(v1, e); 00162 if(!edok) BME_error(); 00163 edok = BME_disk_hasedge(v2, e); 00164 if(!edok) BME_error(); 00165 #endif 00166 return e; 00167 } 00168 00169 00170 00186 #define MF_CANDIDATE 1 00187 #define MF_VISITED 2 00188 #define MF_TAKEN 4 00189 00190 BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int len) 00191 { 00192 BME_Poly *f = NULL; 00193 BME_Edge *curedge; 00194 BME_Vert *curvert, *tv, **vlist; 00195 int i, j, done, cont, edok; 00196 00197 if(len < 2) return NULL; 00198 00199 /*make sure that v1 and v2 are in elist[0]*/ 00200 if(BME_verts_in_edge(v1,v2,elist[0]) == 0) return NULL; 00201 00202 /*clear euler flags*/ 00203 for(i=0;i<len;i++) elist[i]->eflag1=elist[i]->eflag2 = 0; 00204 for(i=0;i<len;i++){ 00205 elist[i]->eflag1 |= MF_CANDIDATE; 00206 00207 /*if elist[i] has a loop, count its radial length*/ 00208 if(elist[i]->loop) elist[i]->eflag2 = BME_cycle_length(&(elist[i]->loop->radial)); 00209 else elist[i]->eflag2 = 0; 00210 } 00211 00212 /* For each vertex in each edge, it must have exactly two MF_CANDIDATE edges attached to it 00213 Note that this does not gauruntee that face is a single closed loop. At best it gauruntees 00214 that elist contains a finite number of seperate closed loops. 00215 */ 00216 for(i=0; i<len; i++){ 00217 edok = BME_disk_count_edgeflag(elist[i]->v1, MF_CANDIDATE, 0); 00218 if(edok != 2) return NULL; 00219 edok = BME_disk_count_edgeflag(elist[i]->v2, MF_CANDIDATE, 0); 00220 if(edok != 2) return NULL; 00221 } 00222 00223 /*set start edge, start vert and target vert for our loop traversal*/ 00224 curedge = elist[0]; 00225 tv = v1; 00226 curvert = v2; 00227 00228 if(bm->vtarlen < len){ 00229 MEM_freeN(bm->vtar); 00230 bm->vtar = MEM_callocN(sizeof(BME_Vert *)* len, "BMesh Vert pointer array"); 00231 bm->vtarlen = len; 00232 } 00233 /*insert tv into vlist since its the first vertex in face*/ 00234 i=0; 00235 vlist=bm->vtar; 00236 vlist[i] = tv; 00237 00238 /* Basic procedure: Starting with curv we find the edge in it's disk cycle which hasn't 00239 been visited yet. When we do, we put curv in a linked list and find the next MF_CANDIDATE 00240 edge, loop until we find TV. We know TV is reachable because of test we did earlier. 00241 */ 00242 done=0; 00243 while(!done){ 00244 /*add curvert to vlist*/ 00245 /*insert some error cheking here for overflows*/ 00246 i++; 00247 vlist[i] = curvert; 00248 00249 /*mark curedge as visited*/ 00250 curedge->eflag1 |= MF_VISITED; 00251 00252 /*find next edge and vert*/ 00253 curedge = BME_disk_next_edgeflag(curedge, curvert, MF_CANDIDATE, 0); 00254 curvert = BME_edge_getothervert(curedge, curvert); 00255 if(curvert == tv){ 00256 curedge->eflag1 |= MF_VISITED; 00257 done=1; 00258 } 00259 } 00260 00261 /* Verify that all edges have been visited It's possible that we did reach tv 00262 from sv, but that several unconnected loops were passed in via elist. 00263 */ 00264 cont=1; 00265 for(i=0; i<len; i++){ 00266 if((elist[i]->eflag1 & MF_VISITED) == 0) cont = 0; 00267 } 00268 00269 /*if we get this far, its ok to allocate the face and add the loops*/ 00270 if(cont){ 00271 BME_Loop *l; 00272 BME_Edge *e; 00273 f = BME_addpolylist(bm, NULL); 00274 f->len = len; 00275 for(i=0;i<len;i++){ 00276 curvert = vlist[i]; 00277 l = BME_create_loop(bm,curvert,NULL,f,NULL); 00278 if(!(f->loopbase)) f->loopbase = l; 00279 BME_cycle_append(f->loopbase, l); 00280 } 00281 00282 /*take care of edge pointers and radial cycle*/ 00283 for(i=0, l = f->loopbase; i<len; i++, l=l->next){ 00284 e = NULL; 00285 if(l == f->loopbase) e = elist[0]; /*first edge*/ 00286 00287 else{/*search elist for others*/ 00288 for(j=1; j<len; j++){ 00289 edok = BME_verts_in_edge(l->v, l->next->v, elist[j]); 00290 if(edok){ 00291 e = elist[j]; 00292 break; 00293 } 00294 } 00295 } 00296 l->e = e; /*set pointer*/ 00297 BME_radial_append(e, l); /*append into radial*/ 00298 } 00299 00300 f->len = len; 00301 00302 /*Validation Loop cycle*/ 00303 edok = BME_cycle_validate(len, f->loopbase); 00304 if(!edok) BME_error(); 00305 for(i=0, l = f->loopbase; i<len; i++, l=l->next){ 00306 /*validate loop vert pointers*/ 00307 edok = BME_verts_in_edge(l->v, l->next->v, l->e); 00308 if(!edok) BME_error(); 00309 /*validate the radial cycle of each edge*/ 00310 edok = BME_cycle_length(&(l->radial)); 00311 if(edok != (l->e->eflag2 + 1)) BME_error(); 00312 } 00313 } 00314 return f; 00315 } 00316 00317 /* KILL Eulers */ 00318 00330 int BME_KV(BME_Mesh *bm, BME_Vert *v){ 00331 if(v->edge == NULL){ 00332 BLI_remlink(&(bm->verts), v); 00333 BME_free_vert(bm,v); 00334 return 1; 00335 } 00336 return 0; 00337 } 00338 00350 int BME_KE(BME_Mesh *bm, BME_Edge *e){ 00351 int edok; 00352 00353 /*Make sure that no faces!*/ 00354 if(e->loop == NULL){ 00355 BME_disk_remove_edge(e, e->v1); 00356 BME_disk_remove_edge(e, e->v2); 00357 00358 /*verify that edge out of disk*/ 00359 edok = BME_disk_hasedge(e->v1, e); 00360 if(edok) BME_error(); 00361 edok = BME_disk_hasedge(e->v2, e); 00362 if(edok) BME_error(); 00363 00364 /*remove and deallocate*/ 00365 BLI_remlink(&(bm->edges), e); 00366 BME_free_edge(bm, e); 00367 return 1; 00368 } 00369 return 0; 00370 } 00371 00384 int BME_KF(BME_Mesh *bm, BME_Poly *bply){ 00385 BME_Loop *newbase,*oldbase, *curloop; 00386 int i,len=0; 00387 00388 /*add validation to make sure that radial cycle is cleaned up ok*/ 00389 /*deal with radial cycle first*/ 00390 len = BME_cycle_length(bply->loopbase); 00391 for(i=0, curloop=bply->loopbase; i < len; i++, curloop = curloop->next) 00392 BME_radial_remove_loop(curloop, curloop->e); 00393 00394 /*now deallocate the editloops*/ 00395 for(i=0; i < len; i++){ 00396 newbase = bply->loopbase->next; 00397 oldbase = bply->loopbase; 00398 BME_cycle_remove(oldbase, oldbase); 00399 BME_free_loop(bm, oldbase); 00400 bply->loopbase = newbase; 00401 } 00402 00403 BLI_remlink(&(bm->polys), bply); 00404 BME_free_poly(bm, bply); 00405 return 1; 00406 } 00407 00408 /*SPLIT Eulers*/ 00409 00425 BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){ 00426 BME_Vert *nv, *ov; 00427 BME_CycleNode *diskbase; 00428 BME_Edge *ne; 00429 int i, edok, valance1=0, valance2=0; 00430 00431 if(BME_vert_in_edge(e,tv) == 0) return NULL; 00432 ov = BME_edge_getothervert(e,tv); 00433 //v2 = tv; 00434 00435 /*count valance of v1*/ 00436 diskbase = BME_disk_getpointer(e, ov); 00437 valance1 = BME_cycle_length(diskbase); 00438 /*count valance of v2*/ 00439 diskbase = BME_disk_getpointer(e, tv); 00440 valance2 = BME_cycle_length(diskbase); 00441 00442 nv = BME_addvertlist(bm, tv); 00443 ne = BME_addedgelist(bm, nv, tv, e); 00444 00445 //e->v2 = nv; 00446 /*remove e from v2's disk cycle*/ 00447 BME_disk_remove_edge(e, tv); 00448 /*swap out tv for nv in e*/ 00449 BME_edge_swapverts(e, tv, nv); 00450 /*add e to nv's disk cycle*/ 00451 BME_disk_append_edge(e, nv); 00452 /*add ne to nv's disk cycle*/ 00453 BME_disk_append_edge(ne, nv); 00454 /*add ne to tv's disk cycle*/ 00455 BME_disk_append_edge(ne, tv); 00456 /*verify disk cycles*/ 00457 diskbase = BME_disk_getpointer(ov->edge,ov); 00458 edok = BME_cycle_validate(valance1, diskbase); 00459 if(!edok) BME_error(); 00460 diskbase = BME_disk_getpointer(tv->edge,tv); 00461 edok = BME_cycle_validate(valance2, diskbase); 00462 if(!edok) BME_error(); 00463 diskbase = BME_disk_getpointer(nv->edge,nv); 00464 edok = BME_cycle_validate(2, diskbase); 00465 if(!edok) BME_error(); 00466 00467 /*Split the radial cycle if present*/ 00468 if(e->loop){ 00469 BME_Loop *nl,*l; 00470 BME_CycleNode *radEBase=NULL, *radNEBase=NULL; 00471 int radlen = BME_cycle_length(&(e->loop->radial)); 00472 /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/ 00473 while(e->loop){ 00474 l=e->loop; 00475 l->f->len++; 00476 BME_radial_remove_loop(l,e); 00477 00478 nl = BME_create_loop(bm,NULL,NULL,l->f,l); 00479 nl->prev = l; 00480 nl->next = l->next; 00481 nl->prev->next = nl; 00482 nl->next->prev = nl; 00483 nl->v = nv; 00484 00485 /*assign the correct edge to the correct loop*/ 00486 if(BME_verts_in_edge(nl->v, nl->next->v, e)){ 00487 nl->e = e; 00488 l->e = ne; 00489 00490 /*append l into ne's rad cycle*/ 00491 if(!radNEBase){ 00492 radNEBase = &(l->radial); 00493 radNEBase->next = NULL; 00494 radNEBase->prev = NULL; 00495 } 00496 00497 if(!radEBase){ 00498 radEBase = &(nl->radial); 00499 radEBase->next = NULL; 00500 radEBase->prev = NULL; 00501 } 00502 00503 BME_cycle_append(radEBase,&(nl->radial)); 00504 BME_cycle_append(radNEBase,&(l->radial)); 00505 00506 } 00507 else if(BME_verts_in_edge(nl->v,nl->next->v,ne)){ 00508 nl->e = ne; 00509 l->e = e; 00510 00511 if(!radNEBase){ 00512 radNEBase = &(nl->radial); 00513 radNEBase->next = NULL; 00514 radNEBase->prev = NULL; 00515 } 00516 if(!radEBase){ 00517 radEBase = &(l->radial); 00518 radEBase->next = NULL; 00519 radEBase->prev = NULL; 00520 } 00521 BME_cycle_append(radEBase,&(l->radial)); 00522 BME_cycle_append(radNEBase,&(nl->radial)); 00523 } 00524 00525 } 00526 00527 e->loop = radEBase->data; 00528 ne->loop = radNEBase->data; 00529 00530 /*verify length of radial cycle*/ 00531 edok = BME_cycle_validate(radlen,&(e->loop->radial)); 00532 if(!edok) BME_error(); 00533 edok = BME_cycle_validate(radlen,&(ne->loop->radial)); 00534 if(!edok) BME_error(); 00535 00536 /*verify loop->v and loop->next->v pointers for e*/ 00537 for(i=0,l=e->loop; i < radlen; i++, l = l->radial.next->data){ 00538 if(!(l->e == e)) BME_error(); 00539 if(!(l->radial.data == l)) BME_error(); 00540 if(l->prev->e != ne && l->next->e != ne) BME_error(); 00541 edok = BME_verts_in_edge(l->v, l->next->v, e); 00542 if(!edok) BME_error(); 00543 if(l->v == l->next->v) BME_error(); 00544 if(l->e == l->next->e) BME_error(); 00545 /*verify loop cycle for kloop->f*/ 00546 edok = BME_cycle_validate(l->f->len, l->f->loopbase); 00547 if(!edok) BME_error(); 00548 } 00549 /*verify loop->v and loop->next->v pointers for ne*/ 00550 for(i=0,l=ne->loop; i < radlen; i++, l = l->radial.next->data){ 00551 if(!(l->e == ne)) BME_error(); 00552 if(!(l->radial.data == l)) BME_error(); 00553 if(l->prev->e != e && l->next->e != e) BME_error(); 00554 edok = BME_verts_in_edge(l->v, l->next->v, ne); 00555 if(!edok) BME_error(); 00556 if(l->v == l->next->v) BME_error(); 00557 if(l->e == l->next->e) BME_error(); 00558 /*verify loop cycle for kloop->f. Redundant*/ 00559 edok = BME_cycle_validate(l->f->len, l->f->loopbase); 00560 if(!edok) BME_error(); 00561 } 00562 } 00563 00564 if(re) *re = ne; 00565 return nv; 00566 } 00567 00595 BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Loop **rl){ 00596 00597 BME_Poly *f2; 00598 BME_Loop *v1loop = NULL, *v2loop = NULL, *curloop, *f1loop=NULL, *f2loop=NULL; 00599 BME_Edge *e; 00600 int i, len, f1len, f2len; 00601 00602 00603 /*verify that v1 and v2 are in face.*/ 00604 len = BME_cycle_length(f->loopbase); 00605 for(i = 0, curloop = f->loopbase; i < len; i++, curloop = curloop->next){ 00606 if(curloop->v == v1) v1loop = curloop; 00607 else if(curloop->v == v2) v2loop = curloop; 00608 } 00609 00610 if(!v1loop || !v2loop) return NULL; 00611 00612 /*allocate new edge between v1 and v2*/ 00613 e = BME_addedgelist(bm, v1, v2,NULL); 00614 BME_disk_append_edge(e, v1); 00615 BME_disk_append_edge(e, v2); 00616 00617 f2 = BME_addpolylist(bm,f); 00618 f1loop = BME_create_loop(bm,v2,e,f,v2loop); 00619 f2loop = BME_create_loop(bm,v1,e,f2,v1loop); 00620 00621 f1loop->prev = v2loop->prev; 00622 f2loop->prev = v1loop->prev; 00623 v2loop->prev->next = f1loop; 00624 v1loop->prev->next = f2loop; 00625 00626 f1loop->next = v1loop; 00627 f2loop->next = v2loop; 00628 v1loop->prev = f1loop; 00629 v2loop->prev = f2loop; 00630 00631 f2->loopbase = f2loop; 00632 f->loopbase = f1loop; 00633 00634 /*validate both loops*/ 00635 /*I dont know how many loops are supposed to be in each face at this point! FIXME!*/ 00636 00637 /*go through all of f2's loops and make sure they point to it properly.*/ 00638 f2len = BME_cycle_length(f2->loopbase); 00639 for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next) curloop->f = f2; 00640 00641 /*link up the new loops into the new edges radial*/ 00642 BME_radial_append(e, f1loop); 00643 BME_radial_append(e, f2loop); 00644 00645 00646 f2->len = f2len; 00647 00648 f1len = BME_cycle_length(f->loopbase); 00649 f->len = f1len; 00650 00651 if(rl) *rl = f2loop; 00652 return f2; 00653 } 00654 00655 00687 int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) 00688 { 00689 BME_Edge *oe; 00690 BME_Vert *ov, *tv; 00691 BME_CycleNode *diskbase; 00692 BME_Loop *killoop,*nextl; 00693 int len,radlen=0, halt = 0, i, valance1, valance2,edok; 00694 00695 if(BME_vert_in_edge(ke,kv) == 0) return 0; 00696 diskbase = BME_disk_getpointer(kv->edge, kv); 00697 len = BME_cycle_length(diskbase); 00698 00699 if(len == 2){ 00700 oe = BME_disk_nextedge(ke, kv); 00701 tv = BME_edge_getothervert(ke, kv); 00702 ov = BME_edge_getothervert(oe, kv); 00703 halt = BME_verts_in_edge(kv, tv, oe); //check for double edges 00704 00705 if(halt) return 0; 00706 else{ 00707 00708 /*For verification later, count valance of ov and tv*/ 00709 diskbase = BME_disk_getpointer(ov->edge, ov); 00710 valance1 = BME_cycle_length(diskbase); 00711 diskbase = BME_disk_getpointer(tv->edge, tv); 00712 valance2 = BME_cycle_length(diskbase); 00713 00714 /*remove oe from kv's disk cycle*/ 00715 BME_disk_remove_edge(oe,kv); 00716 /*relink oe->kv to be oe->tv*/ 00717 BME_edge_swapverts(oe, kv, tv); 00718 /*append oe to tv's disk cycle*/ 00719 BME_disk_append_edge(oe, tv); 00720 /*remove ke from tv's disk cycle*/ 00721 BME_disk_remove_edge(ke, tv); 00722 00723 00724 00725 /*deal with radial cycle of ke*/ 00726 if(ke->loop){ 00727 /*first step, fix the neighboring loops of all loops in ke's radial cycle*/ 00728 radlen = BME_cycle_length(&(ke->loop->radial)); 00729 for(i=0,killoop = ke->loop; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){ 00730 /*relink loops and fix vertex pointer*/ 00731 killoop->next->prev = killoop->prev; 00732 killoop->prev->next = killoop->next; 00733 if(killoop->next->v == kv) killoop->next->v = tv; 00734 00735 /*fix len attribute of face*/ 00736 killoop->f->len--; 00737 if(killoop->f->loopbase == killoop) killoop->f->loopbase = killoop->next; 00738 } 00739 /*second step, remove all the hanging loops attached to ke*/ 00740 killoop = ke->loop; 00741 radlen = BME_cycle_length(&(ke->loop->radial)); 00742 /*make sure we have enough room in bm->lpar*/ 00743 if(bm->lparlen < radlen){ 00744 MEM_freeN(bm->lpar); 00745 bm->lpar = MEM_callocN(sizeof(BME_Loop *)* radlen, "BMesh Loop pointer array"); 00746 bm->lparlen = bm->lparlen * radlen; 00747 } 00748 /*this should be wrapped into a bme_free_radial function to be used by BME_KF as well...*/ 00749 i=0; 00750 while(i<radlen){ 00751 bm->lpar[i] = killoop; 00752 killoop = killoop->radial.next->data; 00753 i++; 00754 } 00755 i=0; 00756 while(i<radlen){ 00757 BME_free_loop(bm,bm->lpar[i]); 00758 i++; 00759 } 00760 /*Validate radial cycle of oe*/ 00761 edok = BME_cycle_validate(radlen,&(oe->loop->radial)); 00762 00763 } 00764 00765 00766 /*Validate disk cycles*/ 00767 diskbase = BME_disk_getpointer(ov->edge,ov); 00768 edok = BME_cycle_validate(valance1, diskbase); 00769 if(!edok) BME_error(); 00770 diskbase = BME_disk_getpointer(tv->edge,tv); 00771 edok = BME_cycle_validate(valance2, diskbase); 00772 if(!edok) BME_error(); 00773 00774 /*Validate loop cycle of all faces attached to oe*/ 00775 for(i=0,nextl = oe->loop; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){ 00776 edok = BME_cycle_validate(nextl->f->len,nextl->f->loopbase); 00777 if(!edok) BME_error(); 00778 } 00779 /*deallocate edge*/ 00780 BLI_remlink(&(bm->edges), ke); 00781 BME_free_edge(bm, ke); 00782 /*deallocate vertex*/ 00783 BLI_remlink(&(bm->verts), kv); 00784 BME_free_vert(bm, kv); 00785 return 1; 00786 } 00787 } 00788 return 0; 00789 } 00790 00791 00807 int BME_loop_reverse(BME_Mesh *bm, BME_Poly *f){ 00808 BME_Loop *l = f->loopbase, *curloop, *oldprev, *oldnext; 00809 int i, j, edok, len = 0; 00810 00811 len = BME_cycle_length(l); 00812 if(bm->edarlen < len){ 00813 MEM_freeN(bm->edar); 00814 bm->edar = MEM_callocN(sizeof(BME_Edge *)* len, "BMesh Edge pointer array"); 00815 bm->edarlen = len; 00816 } 00817 00818 for(i=0, curloop = l; i< len; i++, curloop=curloop->next){ 00819 curloop->e->eflag1 = 0; 00820 curloop->e->eflag2 = BME_cycle_length(&curloop->radial); 00821 BME_radial_remove_loop(curloop, curloop->e); 00822 /*in case of border edges we HAVE to zero out curloop->radial Next/Prev*/ 00823 curloop->radial.next = curloop->radial.prev = NULL; 00824 bm->edar[i] = curloop->e; 00825 } 00826 00827 /*actually reverse the loop. This belongs in BME_cycle_reverse!*/ 00828 for(i=0, curloop = l; i < len; i++){ 00829 oldnext = curloop->next; 00830 oldprev = curloop->prev; 00831 curloop->next = oldprev; 00832 curloop->prev = oldnext; 00833 curloop = oldnext; 00834 } 00835 00836 if(len == 2){ //two edged face 00837 //do some verification here! 00838 l->e = bm->edar[1]; 00839 l->next->e = bm->edar[0]; 00840 } 00841 else{ 00842 for(i=0, curloop = l; i < len; i++, curloop = curloop->next){ 00843 edok = 0; 00844 for(j=0; j < len; j++){ 00845 edok = BME_verts_in_edge(curloop->v, curloop->next->v, bm->edar[j]); 00846 if(edok){ 00847 curloop->e = bm->edar[j]; 00848 break; 00849 } 00850 } 00851 } 00852 } 00853 /*rebuild radial*/ 00854 for(i=0, curloop = l; i < len; i++, curloop = curloop->next) BME_radial_append(curloop->e, curloop); 00855 00856 /*validate radial*/ 00857 for(i=0, curloop = l; i < len; i++, curloop = curloop->next){ 00858 edok = BME_cycle_validate(curloop->e->eflag2, &(curloop->radial)); 00859 if(!edok){ 00860 BME_error(); 00861 } 00862 } 00863 return 1; 00864 } 00865 00898 BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) 00899 { 00900 00901 BME_Loop *curloop, *f1loop=NULL, *f2loop=NULL; 00902 int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok; 00903 00904 if(f1 == f2) return NULL; //can't join a face to itself 00905 /*verify that e is in both f1 and f2*/ 00906 f1len = BME_cycle_length(f1->loopbase); 00907 f2len = BME_cycle_length(f2->loopbase); 00908 for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = curloop->next){ 00909 if(curloop->e == e){ 00910 f1loop = curloop; 00911 break; 00912 } 00913 } 00914 for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next){ 00915 if(curloop->e==e){ 00916 f2loop = curloop; 00917 break; 00918 } 00919 } 00920 if(!(f1loop && f2loop)) return NULL; 00921 00922 /*validate that edge is 2-manifold edge*/ 00923 radlen = BME_cycle_length(&(f1loop->radial)); 00924 if(radlen != 2) return NULL; 00925 00926 /*validate direction of f2's loop cycle is compatible.*/ 00927 if(f1loop->v == f2loop->v) return NULL; 00928 00929 /* 00930 Finally validate that for each face, each vertex has another edge in its disk cycle that is 00931 not e, and not shared. 00932 */ 00933 if(BME_radial_find_face(f1loop->next->e,f2)) return NULL; 00934 if(BME_radial_find_face(f1loop->prev->e,f2)) return NULL; 00935 if(BME_radial_find_face(f2loop->next->e,f1)) return NULL; 00936 if(BME_radial_find_face(f2loop->prev->e,f1)) return NULL; 00937 00938 /*join the two loops*/ 00939 f1loop->prev->next = f2loop->next; 00940 f2loop->next->prev = f1loop->prev; 00941 00942 f1loop->next->prev = f2loop->prev; 00943 f2loop->prev->next = f1loop->next; 00944 00945 /*if f1loop was baseloop, give f1loop->next the base.*/ 00946 if(f1->loopbase == f1loop) f1->loopbase = f1loop->next; 00947 00948 /*validate the new loop*/ 00949 loopok = BME_cycle_validate((f1len+f2len)-2, f1->loopbase); 00950 if(!loopok) BME_error(); 00951 00952 /*make sure each loop points to the proper face*/ 00953 newlen = BME_cycle_length(f1->loopbase); 00954 for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = curloop->next) curloop->f = f1; 00955 00956 f1->len = newlen; 00957 00958 edok = BME_cycle_validate(f1->len, f1->loopbase); 00959 if(!edok) BME_error(); 00960 00961 /*remove edge from the disk cycle of its two vertices.*/ 00962 BME_disk_remove_edge(f1loop->e, f1loop->e->v1); 00963 BME_disk_remove_edge(f1loop->e, f1loop->e->v2); 00964 00965 /*deallocate edge and its two loops as well as f2*/ 00966 BLI_remlink(&(bm->edges), f1loop->e); 00967 BLI_remlink(&(bm->polys), f2); 00968 BME_free_edge(bm, f1loop->e); 00969 BME_free_loop(bm, f1loop); 00970 BME_free_loop(bm, f2loop); 00971 BME_free_poly(bm, f2); 00972 return f1; 00973 }