Blender V2.61 - r43446
|
00001 /* 00002 * BME_structure.c jan 2007 00003 * 00004 * Low level routines for manipulating the BMesh structure. 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) 2007 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 <limits.h> 00040 00041 #include "MEM_guardedalloc.h" 00042 #include "BLI_listbase.h" 00043 #include "BLI_utildefines.h" 00044 #include "BKE_bmesh.h" 00050 int BME_vert_in_edge(BME_Edge *e, BME_Vert *v){ 00051 if(e->v1 == v || e->v2 == v) return 1; 00052 return 0; 00053 } 00054 int BME_verts_in_edge(BME_Vert *v1, BME_Vert *v2, BME_Edge *e){ 00055 if(e->v1 == v1 && e->v2 == v2) return 1; 00056 else if(e->v1 == v2 && e->v2 == v1) return 1; 00057 return 0; 00058 } 00059 00060 BME_Vert *BME_edge_getothervert(BME_Edge *e, BME_Vert *v){ 00061 if(e->v1 == v) return e->v2; 00062 else if(e->v2 == v) return e->v1; 00063 return NULL; 00064 } 00065 00066 int BME_edge_swapverts(BME_Edge *e, BME_Vert *orig, BME_Vert *new){ 00067 if(e->v1 == orig){ 00068 e->v1 = new; 00069 e->d1.next = NULL; 00070 e->d1.prev = NULL; 00071 return 1; 00072 } 00073 else if(e->v2 == orig){ 00074 e->v2 = new; 00075 e->d2.next = NULL; 00076 e->d2.prev = NULL; 00077 return 1; 00078 } 00079 return 0; 00080 } 00081 00086 BME_Vert *BME_addvertlist(BME_Mesh *bm, BME_Vert *example){ 00087 BME_Vert *v=NULL; 00088 v = BLI_mempool_alloc(bm->vpool); 00089 v->next = v->prev = NULL; 00090 v->EID = bm->nextv; 00091 v->co[0] = v->co[1] = v->co[2] = 0.0f; 00092 v->no[0] = v->no[1] = v->no[2] = 0.0f; 00093 v->edge = NULL; 00094 v->data = NULL; 00095 v->eflag1 = v->eflag2 = v->tflag1 = v->tflag2 = 0; 00096 v->flag = v->h = 0; 00097 v->bweight = 0.0f; 00098 BLI_addtail(&(bm->verts), v); 00099 bm->nextv++; 00100 bm->totvert++; 00101 00102 if(example){ 00103 VECCOPY(v->co,example->co); 00104 CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->data, &v->data); 00105 } 00106 else 00107 CustomData_bmesh_set_default(&bm->vdata, &v->data); 00108 00109 return v; 00110 } 00111 BME_Edge *BME_addedgelist(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge *example){ 00112 BME_Edge *e=NULL; 00113 e = BLI_mempool_alloc(bm->epool); 00114 e->next = e->prev = NULL; 00115 e->EID = bm->nexte; 00116 e->v1 = v1; 00117 e->v2 = v2; 00118 e->d1.next = e->d1.prev = e->d2.next = e->d2.prev = NULL; 00119 e->d1.data = e; 00120 e->d2.data = e; 00121 e->loop = NULL; 00122 e->data = NULL; 00123 e->eflag1 = e->eflag2 = e->tflag1 = e->tflag2 = 0; 00124 e->flag = e->h = 0; 00125 e->crease = e->bweight = 0.0f; 00126 bm->nexte++; 00127 bm->totedge++; 00128 BLI_addtail(&(bm->edges), e); 00129 00130 if(example) 00131 CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->data, &e->data); 00132 else 00133 CustomData_bmesh_set_default(&bm->edata, &e->data); 00134 00135 00136 return e; 00137 } 00138 BME_Loop *BME_create_loop(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Poly *f, BME_Loop *example){ 00139 BME_Loop *l=NULL; 00140 l = BLI_mempool_alloc(bm->lpool); 00141 l->next = l->prev = NULL; 00142 l->EID = bm->nextl; 00143 l->radial.next = l->radial.prev = NULL; 00144 l->radial.data = l; 00145 l->v = v; 00146 l->e = e; 00147 l->f = f; 00148 l->data = NULL; 00149 l->eflag1 = l->eflag2 = l->tflag1 = l->tflag2 = 0; 00150 l->flag = l->h = 0; //stupid waste! 00151 bm->nextl++; 00152 bm->totloop++; 00153 00154 if(example) 00155 CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->data, &l->data); 00156 else 00157 CustomData_bmesh_set_default(&bm->ldata, &l->data); 00158 00159 return l; 00160 } 00161 00162 BME_Poly *BME_addpolylist(BME_Mesh *bm, BME_Poly *example){ 00163 BME_Poly *f = NULL; 00164 f = BLI_mempool_alloc(bm->ppool); 00165 f->next = f->prev = NULL; 00166 f->EID = bm->nextp; 00167 f->loopbase = NULL; 00168 f->len = 0; 00169 f->data = NULL; 00170 f->eflag1 = f->eflag2 = f->tflag1 = f->tflag2 = 0; 00171 f->flag = f->h = f->mat_nr; 00172 BLI_addtail(&(bm->polys),f); 00173 bm->nextp++; 00174 bm->totpoly++; 00175 00176 if(example) 00177 CustomData_bmesh_copy_data(&bm->pdata, &bm->pdata, example->data, &f->data); 00178 else 00179 CustomData_bmesh_set_default(&bm->pdata, &f->data); 00180 00181 00182 return f; 00183 } 00184 00185 /* free functions dont do much *yet*. When per-vertex, per-edge and per-face/faceloop 00186 data is added though these will be needed. 00187 */ 00188 void BME_free_vert(BME_Mesh *bm, BME_Vert *v){ 00189 bm->totvert--; 00190 CustomData_bmesh_free_block(&bm->vdata, &v->data); 00191 BLI_mempool_free(bm->vpool, v); 00192 } 00193 void BME_free_edge(BME_Mesh *bm, BME_Edge *e){ 00194 bm->totedge--; 00195 CustomData_bmesh_free_block(&bm->edata, &e->data); 00196 BLI_mempool_free(bm->epool, e); 00197 } 00198 void BME_free_poly(BME_Mesh *bm, BME_Poly *f){ 00199 bm->totpoly--; 00200 CustomData_bmesh_free_block(&bm->pdata, &f->data); 00201 BLI_mempool_free(bm->ppool, f); 00202 } 00203 void BME_free_loop(BME_Mesh *bm, BME_Loop *l){ 00204 bm->totloop--; 00205 CustomData_bmesh_free_block(&bm->ldata, &l->data); 00206 BLI_mempool_free(bm->lpool, l); 00207 } 00281 void BME_cycle_append(void *h, void *nt) 00282 { 00283 BME_CycleNode *oldtail, *head, *newtail; 00284 00285 head = (BME_CycleNode*)h; 00286 newtail = (BME_CycleNode*)nt; 00287 00288 if(head->next == NULL){ 00289 head->next = newtail; 00290 head->prev = newtail; 00291 newtail->next = head; 00292 newtail->prev = head; 00293 } 00294 else{ 00295 oldtail = head->prev; 00296 oldtail->next = newtail; 00297 newtail->next = head; 00298 newtail->prev = oldtail; 00299 head->prev = newtail; 00300 00301 } 00302 } 00303 00313 int BME_cycle_length(void *h){ 00314 00315 int len = 0; 00316 BME_CycleNode *head, *curnode; 00317 head = (BME_CycleNode*)h; 00318 00319 if(head){ 00320 len = 1; 00321 for(curnode = head->next; curnode != head; curnode=curnode->next){ 00322 if(len == INT_MAX){ //check for infinite loop/corrupted cycle 00323 return -1; 00324 } 00325 len++; 00326 } 00327 } 00328 return len; 00329 } 00330 00331 00341 int BME_cycle_remove(void *h, void *remn) 00342 { 00343 int i, len; 00344 BME_CycleNode *head, *remnode, *curnode; 00345 00346 head = (BME_CycleNode*)h; 00347 remnode = (BME_CycleNode*)remn; 00348 len = BME_cycle_length(h); 00349 00350 if(len == 1 && head == remnode){ 00351 head->next = NULL; 00352 head->prev = NULL; 00353 return 1; 00354 } 00355 else{ 00356 for(i=0, curnode = head; i < len; curnode = curnode->next){ 00357 if(curnode == remnode){ 00358 remnode->prev->next = remnode->next; 00359 remnode->next->prev = remnode->prev; 00360 /*zero out remnode pointers, important!*/ 00361 //remnode->next = NULL; 00362 //remnode->prev = NULL; 00363 return 1; 00364 00365 } 00366 } 00367 } 00368 return 0; 00369 } 00370 00382 int BME_cycle_validate(int len, void *h){ 00383 int i; 00384 BME_CycleNode *curnode, *head; 00385 head = (BME_CycleNode*)h; 00386 00387 /*forward validation*/ 00388 for(i = 0, curnode = head; i < len; i++, curnode = curnode->next); 00389 if(curnode != head) return 0; 00390 00391 /*reverse validation*/ 00392 for(i = 0, curnode = head; i < len; i++, curnode = curnode->prev); 00393 if(curnode != head) return 0; 00394 00395 return 1; 00396 } 00397 00398 /*Begin Disk Cycle routines*/ 00399 00409 BME_Edge *BME_disk_nextedge(BME_Edge *e, BME_Vert *v) 00410 { 00411 if(BME_vert_in_edge(e, v)){ 00412 if(e->v1 == v) return e->d1.next->data; 00413 else if(e->v2 == v) return e->d2.next->data; 00414 } 00415 return NULL; 00416 } 00417 00426 BME_CycleNode *BME_disk_getpointer(BME_Edge *e, BME_Vert *v){ 00427 /*returns pointer to the cycle node for the appropriate vertex in this disk*/ 00428 if(e->v1 == v) return &(e->d1); 00429 else if (e->v2 == v) return &(e->d2); 00430 return NULL; 00431 } 00432 00442 int BME_disk_append_edge(BME_Edge *e, BME_Vert *v) 00443 { 00444 00445 BME_CycleNode *base, *tail; 00446 00447 if(BME_vert_in_edge(e, v) == 0) return 0; /*check to make sure v is in e*/ 00448 00449 /*check for loose vert first*/ 00450 if(v->edge == NULL){ 00451 v->edge = e; 00452 base = tail = BME_disk_getpointer(e, v); 00453 BME_cycle_append(base, tail); /*circular reference is ok!*/ 00454 return 1; 00455 } 00456 00457 /*insert e at the end of disk cycle and make it the new v->edge*/ 00458 base = BME_disk_getpointer(v->edge, v); 00459 tail = BME_disk_getpointer(e, v); 00460 BME_cycle_append(base, tail); 00461 return 1; 00462 } 00463 00475 void BME_disk_remove_edge(BME_Edge *e, BME_Vert *v) 00476 { 00477 BME_CycleNode *base, *remnode; 00478 BME_Edge *newbase; 00479 int len; 00480 00481 base = BME_disk_getpointer(v->edge, v); 00482 remnode = BME_disk_getpointer(e, v); 00483 00484 /*first deal with v->edge pointer...*/ 00485 len = BME_cycle_length(base); 00486 if(len == 1) newbase = NULL; 00487 else if(v->edge == e) newbase = base->next-> data; 00488 else newbase = v->edge; 00489 00490 /*remove and rebase*/ 00491 BME_cycle_remove(base, remnode); 00492 v->edge = newbase; 00493 } 00494 00504 BME_Edge *BME_disk_next_edgeflag(BME_Edge *e, BME_Vert *v, int eflag, int tflag){ 00505 00506 /* BME_CycleNode *diskbase; */ /* UNUSED */ 00507 BME_Edge *curedge; 00508 int /* len, */ /* UNUSED */ ok; 00509 00510 if(eflag && tflag) return NULL; 00511 00512 ok = BME_vert_in_edge(e,v); 00513 if(ok){ 00514 /* diskbase = BME_disk_getpointer(e, v); */ /* UNUSED */ 00515 /* len = BME_cycle_length(diskbase); */ /* UNUSED */ 00516 curedge = BME_disk_nextedge(e,v); 00517 while(curedge != e){ 00518 if(tflag){ 00519 if(curedge->tflag1 == tflag) return curedge; 00520 } 00521 else if(eflag){ 00522 if(curedge->eflag1 == eflag) return curedge; 00523 } 00524 curedge = BME_disk_nextedge(curedge, v); 00525 } 00526 } 00527 return NULL; 00528 } 00529 00540 int BME_disk_count_edgeflag(BME_Vert *v, int eflag, int tflag){ 00541 BME_CycleNode *diskbase; 00542 BME_Edge *curedge; 00543 int i, len=0, count=0; 00544 00545 if(v->edge){ 00546 if(eflag && tflag) return 0; /*tflag and eflag are reserved for different functions!*/ 00547 diskbase = BME_disk_getpointer(v->edge, v); 00548 len = BME_cycle_length(diskbase); 00549 00550 for(i = 0, curedge=v->edge; i<len; i++){ 00551 if(tflag){ 00552 if(curedge->tflag1 == tflag) count++; 00553 } 00554 else if(eflag){ 00555 if(curedge->eflag1 == eflag) count++; 00556 } 00557 curedge = BME_disk_nextedge(curedge, v); 00558 } 00559 } 00560 return count; 00561 } 00562 00563 int BME_disk_hasedge(BME_Vert *v, BME_Edge *e){ 00564 BME_CycleNode *diskbase; 00565 BME_Edge *curedge; 00566 int i, len=0; 00567 00568 if(v->edge){ 00569 diskbase = BME_disk_getpointer(v->edge,v); 00570 len = BME_cycle_length(diskbase); 00571 00572 for(i = 0, curedge=v->edge; i<len; i++){ 00573 if(curedge == e) return 1; 00574 else curedge=BME_disk_nextedge(curedge, v); 00575 } 00576 } 00577 return 0; 00578 } 00579 /*end disk cycle routines*/ 00580 00581 BME_Loop *BME_radial_nextloop(BME_Loop *l){ 00582 return (BME_Loop*)(l->radial.next->data); 00583 } 00584 00585 void BME_radial_append(BME_Edge *e, BME_Loop *l){ 00586 if(e->loop == NULL) e->loop = l; 00587 BME_cycle_append(&(e->loop->radial), &(l->radial)); 00588 } 00589 00590 void BME_radial_remove_loop(BME_Loop *l, BME_Edge *e) 00591 { 00592 BME_Loop *newbase; 00593 int len; 00594 00595 /*deal with edge->loop pointer*/ 00596 len = BME_cycle_length(&(e->loop->radial)); 00597 if(len == 1) newbase = NULL; 00598 else if(e->loop == l) newbase = e->loop->radial.next->data; 00599 else newbase = e->loop; 00600 00601 /*remove and rebase*/ 00602 BME_cycle_remove(&(e->loop->radial), &(l->radial)); 00603 e->loop = newbase; 00604 } 00605 00606 int BME_radial_find_face(BME_Edge *e,BME_Poly *f) 00607 { 00608 00609 BME_Loop *curloop; 00610 int i, len; 00611 00612 len = BME_cycle_length(&(e->loop->radial)); 00613 for(i = 0, curloop = e->loop; i < len; i++, curloop = curloop->radial.next->data){ 00614 if(curloop->f == f) return 1; 00615 } 00616 return 0; 00617 } 00618 00619 struct BME_Loop *BME_loop_find_loop(struct BME_Poly *f, struct BME_Vert *v) { 00620 BME_Loop *l; 00621 int i, len; 00622 00623 len = BME_cycle_length(f->loopbase); 00624 for (i = 0, l=f->loopbase; i < len; i++, l=l->next) { 00625 if (l->v == v) return l; 00626 } 00627 return NULL; 00628 }