|
Blender
V2.59
|
00001 /* 00002 * $Id: scanfill.c 36672 2011-05-13 16:04:20Z 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) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * (uit traces) maart 95 00029 */ 00030 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "BLI_callbacks.h" 00039 #include "BLI_editVert.h" 00040 #include "BLI_listbase.h" 00041 #include "BLI_math.h" 00042 #include "BLI_scanfill.h" 00043 00044 /* callbacks for errors and interrupts and some goo */ 00045 static void (*BLI_localErrorCallBack)(const char*) = NULL; 00046 static int (*BLI_localInterruptCallBack)(void) = NULL; 00047 00048 void BLI_setErrorCallBack(void (*f)(const char *)) 00049 { 00050 BLI_localErrorCallBack = f; 00051 } 00052 00053 void BLI_setInterruptCallBack(int (*f)(void)) 00054 { 00055 BLI_localInterruptCallBack = f; 00056 } 00057 00058 /* just flush the error to /dev/null if the error handler is missing */ 00059 void callLocalErrorCallBack(const char* msg) 00060 { 00061 if (BLI_localErrorCallBack) { 00062 BLI_localErrorCallBack(msg); 00063 } 00064 } 00065 00066 #if 0 00067 /* ignore if the interrupt wasn't set */ 00068 static int callLocalInterruptCallBack(void) 00069 { 00070 if (BLI_localInterruptCallBack) { 00071 return BLI_localInterruptCallBack(); 00072 } else { 00073 return 0; 00074 } 00075 } 00076 #endif 00077 00078 /* local types */ 00079 typedef struct PolyFill { 00080 int edges,verts; 00081 float min[3],max[3]; 00082 short f,nr; 00083 } PolyFill; 00084 00085 typedef struct ScFillVert { 00086 EditVert *v1; 00087 EditEdge *first,*last; 00088 } ScFillVert; 00089 00090 00091 /* local funcs */ 00092 00093 #define COMPLIMIT 0.00003 00094 00095 static ScFillVert *scdata; 00096 00097 ListBase fillvertbase = {NULL, NULL}; 00098 ListBase filledgebase = {NULL, NULL}; 00099 ListBase fillfacebase = {NULL, NULL}; 00100 00101 static short cox, coy; 00102 00103 /* **** FUBCTIONS FOR QSORT *************************** */ 00104 00105 00106 static int vergscdata(const void *a1, const void *a2) 00107 { 00108 const ScFillVert *x1=a1,*x2=a2; 00109 00110 if( x1->v1->co[coy] < x2->v1->co[coy] ) return 1; 00111 else if( x1->v1->co[coy] > x2->v1->co[coy]) return -1; 00112 else if( x1->v1->co[cox] > x2->v1->co[cox] ) return 1; 00113 else if( x1->v1->co[cox] < x2->v1->co[cox]) return -1; 00114 00115 return 0; 00116 } 00117 00118 static int vergpoly(const void *a1, const void *a2) 00119 { 00120 const PolyFill *x1=a1, *x2=a2; 00121 00122 if( x1->min[cox] > x2->min[cox] ) return 1; 00123 else if( x1->min[cox] < x2->min[cox] ) return -1; 00124 else if( x1->min[coy] > x2->min[coy] ) return 1; 00125 else if( x1->min[coy] < x2->min[coy] ) return -1; 00126 00127 return 0; 00128 } 00129 00130 /* ************* MEMORY MANAGEMENT ************* */ 00131 00132 struct mem_elements { 00133 struct mem_elements *next, *prev; 00134 char *data; 00135 }; 00136 00137 00138 /* simple optimization for allocating thousands of small memory blocks 00139 only to be used within loops, and not by one function at a time 00140 free in the end, with argument '-1' 00141 */ 00142 00143 static void *new_mem_element(int size) 00144 { 00145 int blocksize= 16384; 00146 static int offs= 0; /* the current free address */ 00147 static struct mem_elements *cur= 0; 00148 static ListBase lb= {0, 0}; 00149 void *adr; 00150 00151 if(size>10000 || size==0) { 00152 printf("incorrect use of new_mem_element\n"); 00153 } 00154 else if(size== -1) { 00155 cur= lb.first; 00156 while(cur) { 00157 MEM_freeN(cur->data); 00158 cur= cur->next; 00159 } 00160 BLI_freelistN(&lb); 00161 00162 return NULL; 00163 } 00164 00165 size= 4*( (size+3)/4 ); 00166 00167 if(cur) { 00168 if(size+offs < blocksize) { 00169 adr= (void *) (cur->data+offs); 00170 offs+= size; 00171 return adr; 00172 } 00173 } 00174 00175 cur= MEM_callocN( sizeof(struct mem_elements), "newmem"); 00176 cur->data= MEM_callocN(blocksize, "newmem"); 00177 BLI_addtail(&lb, cur); 00178 00179 offs= size; 00180 return cur->data; 00181 } 00182 00183 void BLI_end_edgefill(void) 00184 { 00185 new_mem_element(-1); 00186 00187 fillvertbase.first= fillvertbase.last= 0; 00188 filledgebase.first= filledgebase.last= 0; 00189 fillfacebase.first= fillfacebase.last= 0; 00190 } 00191 00192 /* **** FILL ROUTINES *************************** */ 00193 00194 EditVert *BLI_addfillvert(float *vec) 00195 { 00196 EditVert *eve; 00197 00198 eve= new_mem_element(sizeof(EditVert)); 00199 BLI_addtail(&fillvertbase, eve); 00200 00201 eve->co[0] = vec[0]; 00202 eve->co[1] = vec[1]; 00203 eve->co[2] = vec[2]; 00204 00205 return eve; 00206 } 00207 00208 EditEdge *BLI_addfilledge(EditVert *v1, EditVert *v2) 00209 { 00210 EditEdge *newed; 00211 00212 newed= new_mem_element(sizeof(EditEdge)); 00213 BLI_addtail(&filledgebase, newed); 00214 00215 newed->v1= v1; 00216 newed->v2= v2; 00217 00218 return newed; 00219 } 00220 00221 static void addfillface(EditVert *v1, EditVert *v2, EditVert *v3, short mat_nr) 00222 { 00223 /* does not make edges */ 00224 EditFace *evl; 00225 00226 evl= new_mem_element(sizeof(EditFace)); 00227 BLI_addtail(&fillfacebase, evl); 00228 00229 evl->v1= v1; 00230 evl->v2= v2; 00231 evl->v3= v3; 00232 evl->f= 2; 00233 evl->mat_nr= mat_nr; 00234 } 00235 00236 static int boundisect(PolyFill *pf2, PolyFill *pf1) 00237 { 00238 /* has pf2 been touched (intersected) by pf1 ? with bounding box */ 00239 /* test first if polys exist */ 00240 00241 if(pf1->edges==0 || pf2->edges==0) return 0; 00242 00243 if(pf2->max[cox] < pf1->min[cox] ) return 0; 00244 if(pf2->max[coy] < pf1->min[coy] ) return 0; 00245 00246 if(pf2->min[cox] > pf1->max[cox] ) return 0; 00247 if(pf2->min[coy] > pf1->max[coy] ) return 0; 00248 00249 /* join */ 00250 if(pf2->max[cox]<pf1->max[cox]) pf2->max[cox]= pf1->max[cox]; 00251 if(pf2->max[coy]<pf1->max[coy]) pf2->max[coy]= pf1->max[coy]; 00252 00253 if(pf2->min[cox]>pf1->min[cox]) pf2->min[cox]= pf1->min[cox]; 00254 if(pf2->min[coy]>pf1->min[coy]) pf2->min[coy]= pf1->min[coy]; 00255 00256 return 1; 00257 } 00258 00259 00260 static void mergepolysSimp(PolyFill *pf1, PolyFill *pf2) /* add pf2 to pf1 */ 00261 { 00262 EditVert *eve; 00263 EditEdge *eed; 00264 00265 /* replace old poly numbers */ 00266 eve= fillvertbase.first; 00267 while(eve) { 00268 if(eve->xs== pf2->nr) eve->xs= pf1->nr; 00269 eve= eve->next; 00270 } 00271 eed= filledgebase.first; 00272 while(eed) { 00273 if(eed->f1== pf2->nr) eed->f1= pf1->nr; 00274 eed= eed->next; 00275 } 00276 00277 pf1->verts+= pf2->verts; 00278 pf1->edges+= pf2->edges; 00279 pf2->verts= pf2->edges= 0; 00280 pf1->f= (pf1->f | pf2->f); 00281 } 00282 00283 static short testedgeside(float *v1, float *v2, float *v3) 00284 /* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */ 00285 { 00286 float inp; 00287 00288 inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) 00289 +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]); 00290 00291 if(inp<0.0) return 0; 00292 else if(inp==0) { 00293 if(v1[cox]==v3[cox] && v1[coy]==v3[coy]) return 0; 00294 if(v2[cox]==v3[cox] && v2[coy]==v3[coy]) return 0; 00295 } 00296 return 1; 00297 } 00298 00299 static short addedgetoscanvert(ScFillVert *sc, EditEdge *eed) 00300 { 00301 /* find first edge to the right of eed, and insert eed before that */ 00302 EditEdge *ed; 00303 float fac,fac1,x,y; 00304 00305 if(sc->first==0) { 00306 sc->first= sc->last= eed; 00307 eed->prev= eed->next=0; 00308 return 1; 00309 } 00310 00311 x= eed->v1->co[cox]; 00312 y= eed->v1->co[coy]; 00313 00314 fac1= eed->v2->co[coy]-y; 00315 if(fac1==0.0) { 00316 fac1= 1.0e10*(eed->v2->co[cox]-x); 00317 00318 } 00319 else fac1= (x-eed->v2->co[cox])/fac1; 00320 00321 ed= sc->first; 00322 while(ed) { 00323 00324 if(ed->v2==eed->v2) return 0; 00325 00326 fac= ed->v2->co[coy]-y; 00327 if(fac==0.0) { 00328 fac= 1.0e10*(ed->v2->co[cox]-x); 00329 00330 } 00331 else fac= (x-ed->v2->co[cox])/fac; 00332 if(fac>fac1) break; 00333 00334 ed= ed->next; 00335 } 00336 if(ed) BLI_insertlinkbefore((ListBase *)&(sc->first), ed, eed); 00337 else BLI_addtail((ListBase *)&(sc->first),eed); 00338 00339 return 1; 00340 } 00341 00342 00343 static ScFillVert *addedgetoscanlist(EditEdge *eed, int len) 00344 { 00345 /* inserts edge at correct location in ScFillVert list */ 00346 /* returns sc when edge already exists */ 00347 ScFillVert *sc,scsearch; 00348 EditVert *eve; 00349 00350 /* which vert is left-top? */ 00351 if(eed->v1->co[coy] == eed->v2->co[coy]) { 00352 if(eed->v1->co[cox] > eed->v2->co[cox]) { 00353 eve= eed->v1; 00354 eed->v1= eed->v2; 00355 eed->v2= eve; 00356 } 00357 } 00358 else if(eed->v1->co[coy] < eed->v2->co[coy]) { 00359 eve= eed->v1; 00360 eed->v1= eed->v2; 00361 eed->v2= eve; 00362 } 00363 /* find location in list */ 00364 scsearch.v1= eed->v1; 00365 sc= (ScFillVert *)bsearch(&scsearch,scdata,len, 00366 sizeof(ScFillVert), vergscdata); 00367 00368 if(sc==0) printf("Error in search edge: %p\n", (void *)eed); 00369 else if(addedgetoscanvert(sc,eed)==0) return sc; 00370 00371 return 0; 00372 } 00373 00374 static short boundinsideEV(EditEdge *eed, EditVert *eve) 00375 /* is eve inside boundbox eed */ 00376 { 00377 float minx,maxx,miny,maxy; 00378 00379 if(eed->v1->co[cox]<eed->v2->co[cox]) { 00380 minx= eed->v1->co[cox]; 00381 maxx= eed->v2->co[cox]; 00382 } else { 00383 minx= eed->v2->co[cox]; 00384 maxx= eed->v1->co[cox]; 00385 } 00386 if(eve->co[cox]>=minx && eve->co[cox]<=maxx) { 00387 if(eed->v1->co[coy]<eed->v2->co[coy]) { 00388 miny= eed->v1->co[coy]; 00389 maxy= eed->v2->co[coy]; 00390 } else { 00391 miny= eed->v2->co[coy]; 00392 maxy= eed->v1->co[coy]; 00393 } 00394 if(eve->co[coy]>=miny && eve->co[coy]<=maxy) return 1; 00395 } 00396 return 0; 00397 } 00398 00399 00400 static void testvertexnearedge(void) 00401 { 00402 /* only vertices with ->h==1 are being tested for 00403 being close to an edge, if true insert */ 00404 00405 EditVert *eve; 00406 EditEdge *eed,*ed1; 00407 float dist,vec1[2],vec2[2],vec3[2]; 00408 00409 eve= fillvertbase.first; 00410 while(eve) { 00411 if(eve->h==1) { 00412 vec3[0]= eve->co[cox]; 00413 vec3[1]= eve->co[coy]; 00414 /* find the edge which has vertex eve */ 00415 ed1= filledgebase.first; 00416 while(ed1) { 00417 if(ed1->v1==eve || ed1->v2==eve) break; 00418 ed1= ed1->next; 00419 } 00420 if(ed1->v1==eve) { 00421 ed1->v1= ed1->v2; 00422 ed1->v2= eve; 00423 } 00424 eed= filledgebase.first; 00425 while(eed) { 00426 if(eve!=eed->v1 && eve!=eed->v2 && eve->xs==eed->f1) { 00427 if(compare_v3v3(eve->co,eed->v1->co, COMPLIMIT)) { 00428 ed1->v2= eed->v1; 00429 eed->v1->h++; 00430 eve->h= 0; 00431 break; 00432 } 00433 else if(compare_v3v3(eve->co,eed->v2->co, COMPLIMIT)) { 00434 ed1->v2= eed->v2; 00435 eed->v2->h++; 00436 eve->h= 0; 00437 break; 00438 } 00439 else { 00440 vec1[0]= eed->v1->co[cox]; 00441 vec1[1]= eed->v1->co[coy]; 00442 vec2[0]= eed->v2->co[cox]; 00443 vec2[1]= eed->v2->co[coy]; 00444 if(boundinsideEV(eed,eve)) { 00445 dist= dist_to_line_v2(vec1,vec2,vec3); 00446 if(dist<COMPLIMIT) { 00447 /* new edge */ 00448 ed1= BLI_addfilledge(eed->v1, eve); 00449 00450 /* printf("fill: vertex near edge %x\n",eve); */ 00451 ed1->f= ed1->h= 0; 00452 ed1->f1= eed->f1; 00453 eed->v1= eve; 00454 eve->h= 3; 00455 break; 00456 } 00457 } 00458 } 00459 } 00460 eed= eed->next; 00461 } 00462 } 00463 eve= eve->next; 00464 } 00465 } 00466 00467 static void splitlist(ListBase *tempve, ListBase *temped, short nr) 00468 { 00469 /* everything is in templist, write only poly nr to fillist */ 00470 EditVert *eve,*nextve; 00471 EditEdge *eed,*nexted; 00472 00473 BLI_movelisttolist(tempve,&fillvertbase); 00474 BLI_movelisttolist(temped,&filledgebase); 00475 00476 eve= tempve->first; 00477 while(eve) { 00478 nextve= eve->next; 00479 if(eve->xs==nr) { 00480 BLI_remlink(tempve,eve); 00481 BLI_addtail(&fillvertbase,eve); 00482 } 00483 eve= nextve; 00484 } 00485 eed= temped->first; 00486 while(eed) { 00487 nexted= eed->next; 00488 if(eed->f1==nr) { 00489 BLI_remlink(temped,eed); 00490 BLI_addtail(&filledgebase,eed); 00491 } 00492 eed= nexted; 00493 } 00494 } 00495 00496 00497 static int scanfill(PolyFill *pf, short mat_nr) 00498 { 00499 ScFillVert *sc = NULL, *sc1; 00500 EditVert *eve,*v1,*v2,*v3; 00501 EditEdge *eed,*nexted,*ed1,*ed2,*ed3; 00502 float miny = 0.0; 00503 int a,b,verts, maxface, totface; 00504 short nr, test, twoconnected=0; 00505 00506 nr= pf->nr; 00507 00508 /* PRINTS 00509 verts= pf->verts; 00510 eve= fillvertbase.first; 00511 while(eve) { 00512 printf("vert: %x co: %f %f\n",eve,eve->co[cox],eve->co[coy]); 00513 eve= eve->next; 00514 } 00515 eed= filledgebase.first; 00516 while(eed) { 00517 printf("edge: %x verts: %x %x\n",eed,eed->v1,eed->v2); 00518 eed= eed->next; 00519 } */ 00520 00521 /* STEP 0: remove zero sized edges */ 00522 eed= filledgebase.first; 00523 while(eed) { 00524 if(eed->v1->co[cox]==eed->v2->co[cox]) { 00525 if(eed->v1->co[coy]==eed->v2->co[coy]) { 00526 if(eed->v1->f==255 && eed->v2->f!=255) { 00527 eed->v2->f= 255; 00528 eed->v2->tmp.v= eed->v1->tmp.v; 00529 } 00530 else if(eed->v2->f==255 && eed->v1->f!=255) { 00531 eed->v1->f= 255; 00532 eed->v1->tmp.v= eed->v2->tmp.v; 00533 } 00534 else if(eed->v2->f==255 && eed->v1->f==255) { 00535 eed->v1->tmp.v= eed->v2->tmp.v; 00536 } 00537 else { 00538 eed->v2->f= 255; 00539 eed->v2->tmp.v = eed->v1->tmp.v; 00540 } 00541 } 00542 } 00543 eed= eed->next; 00544 } 00545 00546 /* STEP 1: make using FillVert and FillEdge lists a sorted 00547 ScFillVert list 00548 */ 00549 sc= scdata= (ScFillVert *)MEM_callocN(pf->verts*sizeof(ScFillVert),"Scanfill1"); 00550 eve= fillvertbase.first; 00551 verts= 0; 00552 while(eve) { 00553 if(eve->xs==nr) { 00554 if(eve->f!= 255) { 00555 verts++; 00556 eve->f= 0; /* flag for connectedges later on */ 00557 sc->v1= eve; 00558 sc++; 00559 } 00560 } 00561 eve= eve->next; 00562 } 00563 00564 qsort(scdata, verts, sizeof(ScFillVert), vergscdata); 00565 00566 eed= filledgebase.first; 00567 while(eed) { 00568 nexted= eed->next; 00569 eed->f= 0; 00570 BLI_remlink(&filledgebase,eed); 00571 /* commented all of this out, this I have no idea for what it is for, probably from ancient past */ 00572 /* it does crash blender, since it uses mixed original and new vertices (ton) */ 00573 // if(eed->v1->f==255) { 00574 // v1= eed->v1; 00575 // while((eed->v1->f == 255) && (eed->v1->tmp.v != v1)) 00576 // eed->v1 = eed->v1->tmp.v; 00577 // } 00578 // if(eed->v2->f==255) { 00579 // v2= eed->v2; 00580 // while((eed->v2->f == 255) && (eed->v2->tmp.v != v2)) 00581 // eed->v2 = eed->v2->tmp.v; 00582 // } 00583 if(eed->v1!=eed->v2) addedgetoscanlist(eed,verts); 00584 00585 eed= nexted; 00586 } 00587 /* 00588 sc= scdata; 00589 for(a=0;a<verts;a++) { 00590 printf("\nscvert: %x\n",sc->v1); 00591 eed= sc->first; 00592 while(eed) { 00593 printf(" ed %x %x %x\n",eed,eed->v1,eed->v2); 00594 eed= eed->next; 00595 } 00596 sc++; 00597 }*/ 00598 00599 00600 /* STEP 2: FILL LOOP */ 00601 00602 if(pf->f==0) twoconnected= 1; 00603 00604 /* (temporal) security: never much more faces than vertices */ 00605 totface= 0; 00606 maxface= 2*verts; /* 2*verts: based at a filled circle within a triangle */ 00607 00608 sc= scdata; 00609 for(a=0;a<verts;a++) { 00610 /* printf("VERTEX %d %x\n",a,sc->v1); */ 00611 ed1= sc->first; 00612 while(ed1) { /* set connectflags */ 00613 nexted= ed1->next; 00614 if(ed1->v1->h==1 || ed1->v2->h==1) { 00615 BLI_remlink((ListBase *)&(sc->first),ed1); 00616 BLI_addtail(&filledgebase,ed1); 00617 if(ed1->v1->h>1) ed1->v1->h--; 00618 if(ed1->v2->h>1) ed1->v2->h--; 00619 } 00620 else ed1->v2->f= 1; 00621 00622 ed1= nexted; 00623 } 00624 while(sc->first) { /* for as long there are edges */ 00625 ed1= sc->first; 00626 ed2= ed1->next; 00627 00628 /* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */ 00629 /* if(callLocalInterruptCallBack()) break; */ 00630 if(totface>maxface) { 00631 /* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */ 00632 a= verts; 00633 break; 00634 } 00635 if(ed2==0) { 00636 sc->first=sc->last= 0; 00637 /* printf("just 1 edge to vert\n"); */ 00638 BLI_addtail(&filledgebase,ed1); 00639 ed1->v2->f= 0; 00640 ed1->v1->h--; 00641 ed1->v2->h--; 00642 } else { 00643 /* test rest of vertices */ 00644 v1= ed1->v2; 00645 v2= ed1->v1; 00646 v3= ed2->v2; 00647 /* this happens with a serial of overlapping edges */ 00648 if(v1==v2 || v2==v3) break; 00649 /* printf("test verts %x %x %x\n",v1,v2,v3); */ 00650 miny = ( (v1->co[coy])<(v3->co[coy]) ? (v1->co[coy]) : (v3->co[coy]) ); 00651 /* miny= MIN2(v1->co[coy],v3->co[coy]); */ 00652 sc1= sc+1; 00653 test= 0; 00654 00655 for(b=a+1;b<verts;b++) { 00656 if(sc1->v1->f==0) { 00657 if(sc1->v1->co[coy] <= miny) break; 00658 00659 if(testedgeside(v1->co,v2->co,sc1->v1->co)) 00660 if(testedgeside(v2->co,v3->co,sc1->v1->co)) 00661 if(testedgeside(v3->co,v1->co,sc1->v1->co)) { 00662 /* point in triangle */ 00663 00664 test= 1; 00665 break; 00666 } 00667 } 00668 sc1++; 00669 } 00670 if(test) { 00671 /* make new edge, and start over */ 00672 /* printf("add new edge %x %x and start again\n",v2,sc1->v1); */ 00673 00674 ed3= BLI_addfilledge(v2, sc1->v1); 00675 BLI_remlink(&filledgebase, ed3); 00676 BLI_insertlinkbefore((ListBase *)&(sc->first), ed2, ed3); 00677 ed3->v2->f= 1; 00678 ed3->f= 2; 00679 ed3->v1->h++; 00680 ed3->v2->h++; 00681 } 00682 else { 00683 /* new triangle */ 00684 /* printf("add face %x %x %x\n",v1,v2,v3); */ 00685 addfillface(v1, v2, v3, mat_nr); 00686 totface++; 00687 BLI_remlink((ListBase *)&(sc->first),ed1); 00688 BLI_addtail(&filledgebase,ed1); 00689 ed1->v2->f= 0; 00690 ed1->v1->h--; 00691 ed1->v2->h--; 00692 /* ed2 can be removed when it's an old one */ 00693 if(ed2->f==0 && twoconnected) { 00694 BLI_remlink((ListBase *)&(sc->first),ed2); 00695 BLI_addtail(&filledgebase,ed2); 00696 ed2->v2->f= 0; 00697 ed2->v1->h--; 00698 ed2->v2->h--; 00699 } 00700 00701 /* new edge */ 00702 ed3= BLI_addfilledge(v1, v3); 00703 BLI_remlink(&filledgebase, ed3); 00704 ed3->f= 2; 00705 ed3->v1->h++; 00706 ed3->v2->h++; 00707 00708 /* printf("add new edge %x %x\n",v1,v3); */ 00709 sc1= addedgetoscanlist(ed3, verts); 00710 00711 if(sc1) { /* ed3 already exists: remove */ 00712 /* printf("Edge exists\n"); */ 00713 ed3->v1->h--; 00714 ed3->v2->h--; 00715 00716 if(twoconnected) ed3= sc1->first; 00717 else ed3= 0; 00718 while(ed3) { 00719 if( (ed3->v1==v1 && ed3->v2==v3) || (ed3->v1==v3 && ed3->v2==v1) ) { 00720 BLI_remlink((ListBase *)&(sc1->first),ed3); 00721 BLI_addtail(&filledgebase,ed3); 00722 ed3->v1->h--; 00723 ed3->v2->h--; 00724 break; 00725 } 00726 ed3= ed3->next; 00727 } 00728 } 00729 00730 } 00731 } 00732 /* test for loose edges */ 00733 ed1= sc->first; 00734 while(ed1) { 00735 nexted= ed1->next; 00736 if(ed1->v1->h<2 || ed1->v2->h<2) { 00737 BLI_remlink((ListBase *)&(sc->first),ed1); 00738 BLI_addtail(&filledgebase,ed1); 00739 if(ed1->v1->h>1) ed1->v1->h--; 00740 if(ed1->v2->h>1) ed1->v2->h--; 00741 } 00742 00743 ed1= nexted; 00744 } 00745 } 00746 sc++; 00747 } 00748 00749 MEM_freeN(scdata); 00750 00751 return totface; 00752 } 00753 00754 00755 00756 int BLI_edgefill(short mat_nr) 00757 { 00758 /* 00759 - fill works with its own lists, so create that first (no faces!) 00760 - for vertices, put in ->tmp.v the old pointer 00761 - struct elements xs en ys are not used here: don't hide stuff in it 00762 - edge flag ->f becomes 2 when it's a new edge 00763 - mode: & 1 is check for crossings, then create edges (TO DO ) 00764 - returns number of triangle faces added. 00765 */ 00766 ListBase tempve, temped; 00767 EditVert *eve; 00768 EditEdge *eed,*nexted; 00769 PolyFill *pflist,*pf; 00770 float *minp, *maxp, *v1, *v2, norm[3], len; 00771 short a,c,poly=0,ok=0,toggle=0; 00772 int totfaces= 0; /* total faces added */ 00773 00774 /* reset variables */ 00775 eve= fillvertbase.first; 00776 while(eve) { 00777 eve->f= 0; 00778 eve->xs= 0; 00779 eve->h= 0; 00780 eve= eve->next; 00781 } 00782 00783 /* first test vertices if they are in edges */ 00784 /* including resetting of flags */ 00785 eed= filledgebase.first; 00786 while(eed) { 00787 eed->f= eed->f1= eed->h= 0; 00788 eed->v1->f= 1; 00789 eed->v2->f= 1; 00790 00791 eed= eed->next; 00792 } 00793 00794 eve= fillvertbase.first; 00795 while(eve) { 00796 if(eve->f & 1) { 00797 ok=1; 00798 break; 00799 } 00800 eve= eve->next; 00801 } 00802 00803 if(ok==0) return 0; 00804 00805 /* NEW NEW! define projection: with 'best' normal */ 00806 /* just use the first three different vertices */ 00807 00808 /* THIS PART STILL IS PRETTY WEAK! (ton) */ 00809 00810 eve= fillvertbase.last; 00811 len= 0.0; 00812 v1= eve->co; 00813 v2= 0; 00814 eve= fillvertbase.first; 00815 while(eve) { 00816 if(v2) { 00817 if( compare_v3v3(v2, eve->co, COMPLIMIT)==0) { 00818 len= normal_tri_v3( norm,v1, v2, eve->co); 00819 if(len != 0.0) break; 00820 } 00821 } 00822 else if(compare_v3v3(v1, eve->co, COMPLIMIT)==0) { 00823 v2= eve->co; 00824 } 00825 eve= eve->next; 00826 } 00827 00828 if(len==0.0) return 0; /* no fill possible */ 00829 00830 norm[0]= fabs(norm[0]); 00831 norm[1]= fabs(norm[1]); 00832 norm[2]= fabs(norm[2]); 00833 00834 if(norm[2]>=norm[0] && norm[2]>=norm[1]) { 00835 cox= 0; coy= 1; 00836 } 00837 else if(norm[1]>=norm[0] && norm[1]>=norm[2]) { 00838 cox= 0; coy= 2; 00839 } 00840 else { 00841 cox= 1; coy= 2; 00842 } 00843 00844 /* STEP 1: COUNT POLYS */ 00845 eve= fillvertbase.first; 00846 while(eve) { 00847 /* get first vertex with no poly number */ 00848 if(eve->xs==0) { 00849 poly++; 00850 /* now a sortof select connected */ 00851 ok= 1; 00852 eve->xs= poly; 00853 00854 while(ok) { 00855 00856 ok= 0; 00857 toggle++; 00858 if(toggle & 1) eed= filledgebase.first; 00859 else eed= filledgebase.last; 00860 00861 while(eed) { 00862 if(eed->v1->xs==0 && eed->v2->xs==poly) { 00863 eed->v1->xs= poly; 00864 eed->f1= poly; 00865 ok= 1; 00866 } 00867 else if(eed->v2->xs==0 && eed->v1->xs==poly) { 00868 eed->v2->xs= poly; 00869 eed->f1= poly; 00870 ok= 1; 00871 } 00872 else if(eed->f1==0) { 00873 if(eed->v1->xs==poly && eed->v2->xs==poly) { 00874 eed->f1= poly; 00875 ok= 1; 00876 } 00877 } 00878 if(toggle & 1) eed= eed->next; 00879 else eed= eed->prev; 00880 } 00881 } 00882 } 00883 eve= eve->next; 00884 } 00885 /* printf("amount of poly's: %d\n",poly); */ 00886 00887 /* STEP 2: remove loose edges and strings of edges */ 00888 eed= filledgebase.first; 00889 while(eed) { 00890 if(eed->v1->h++ >250) break; 00891 if(eed->v2->h++ >250) break; 00892 eed= eed->next; 00893 } 00894 if(eed) { 00895 /* otherwise it's impossible to be sure you can clear vertices */ 00896 callLocalErrorCallBack("No vertices with 250 edges allowed!"); 00897 return 0; 00898 } 00899 00900 /* does it only for vertices with ->h==1 */ 00901 testvertexnearedge(); 00902 00903 ok= 1; 00904 while(ok) { 00905 ok= 0; 00906 toggle++; 00907 if(toggle & 1) eed= filledgebase.first; 00908 else eed= filledgebase.last; 00909 while(eed) { 00910 if(toggle & 1) nexted= eed->next; 00911 else nexted= eed->prev; 00912 if(eed->v1->h==1) { 00913 eed->v2->h--; 00914 BLI_remlink(&fillvertbase,eed->v1); 00915 BLI_remlink(&filledgebase,eed); 00916 ok= 1; 00917 } 00918 else if(eed->v2->h==1) { 00919 eed->v1->h--; 00920 BLI_remlink(&fillvertbase,eed->v2); 00921 BLI_remlink(&filledgebase,eed); 00922 ok= 1; 00923 } 00924 eed= nexted; 00925 } 00926 } 00927 if(filledgebase.first==0) { 00928 /* printf("All edges removed\n"); */ 00929 return 0; 00930 } 00931 00932 00933 /* CURRENT STATUS: 00934 - eve->f :1= availalble in edges 00935 - eve->xs :polynumber 00936 - eve->h :amount of edges connected to vertex 00937 - eve->tmp.v :store! original vertex number 00938 00939 - eed->f : 00940 - eed->f1 :poly number 00941 */ 00942 00943 00944 /* STEP 3: MAKE POLYFILL STRUCT */ 00945 pflist= (PolyFill *)MEM_callocN(poly*sizeof(PolyFill),"edgefill"); 00946 pf= pflist; 00947 for(a=1;a<=poly;a++) { 00948 pf->nr= a; 00949 pf->min[0]=pf->min[1]=pf->min[2]= 1.0e20; 00950 pf->max[0]=pf->max[1]=pf->max[2]= -1.0e20; 00951 pf++; 00952 } 00953 eed= filledgebase.first; 00954 while(eed) { 00955 pflist[eed->f1-1].edges++; 00956 eed= eed->next; 00957 } 00958 00959 eve= fillvertbase.first; 00960 while(eve) { 00961 pflist[eve->xs-1].verts++; 00962 minp= pflist[eve->xs-1].min; 00963 maxp= pflist[eve->xs-1].max; 00964 00965 minp[cox]= (minp[cox])<(eve->co[cox]) ? (minp[cox]) : (eve->co[cox]); 00966 minp[coy]= (minp[coy])<(eve->co[coy]) ? (minp[coy]) : (eve->co[coy]); 00967 maxp[cox]= (maxp[cox])>(eve->co[cox]) ? (maxp[cox]) : (eve->co[cox]); 00968 maxp[coy]= (maxp[coy])>(eve->co[coy]) ? (maxp[coy]) : (eve->co[coy]); 00969 if(eve->h>2) pflist[eve->xs-1].f= 1; 00970 00971 eve= eve->next; 00972 } 00973 00974 /* STEP 4: FIND HOLES OR BOUNDS, JOIN THEM 00975 * ( bounds just to divide it in pieces for optimization, 00976 * the edgefill itself has good auto-hole detection) 00977 * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */ 00978 00979 if(poly>1) { 00980 short *polycache, *pc; 00981 00982 /* so, sort first */ 00983 qsort(pflist, poly, sizeof(PolyFill), vergpoly); 00984 00985 /*pf= pflist; 00986 for(a=1;a<=poly;a++) { 00987 printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f); 00988 PRINT2(f, f, pf->min[0], pf->min[1]); 00989 pf++; 00990 }*/ 00991 00992 polycache= pc= MEM_callocN(sizeof(short)*poly, "polycache"); 00993 pf= pflist; 00994 for(a=0; a<poly; a++, pf++) { 00995 for(c=a+1;c<poly;c++) { 00996 00997 /* if 'a' inside 'c': join (bbox too) 00998 * Careful: 'a' can also be inside another poly. 00999 */ 01000 if(boundisect(pf, pflist+c)) { 01001 *pc= c; 01002 pc++; 01003 } 01004 /* only for optimize! */ 01005 /* else if(pf->max[cox] < (pflist+c)->min[cox]) break; */ 01006 01007 } 01008 while(pc!=polycache) { 01009 pc--; 01010 mergepolysSimp(pf, pflist+ *pc); 01011 } 01012 } 01013 MEM_freeN(polycache); 01014 } 01015 01016 /* printf("after merge\n"); 01017 pf= pflist; 01018 for(a=1;a<=poly;a++) { 01019 printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f); 01020 pf++; 01021 } */ 01022 01023 /* STEP 5: MAKE TRIANGLES */ 01024 01025 tempve.first= fillvertbase.first; 01026 tempve.last= fillvertbase.last; 01027 temped.first= filledgebase.first; 01028 temped.last= filledgebase.last; 01029 fillvertbase.first=fillvertbase.last= 0; 01030 filledgebase.first=filledgebase.last= 0; 01031 01032 pf= pflist; 01033 for(a=0;a<poly;a++) { 01034 if(pf->edges>1) { 01035 splitlist(&tempve,&temped,pf->nr); 01036 totfaces += scanfill(pf, mat_nr); 01037 } 01038 pf++; 01039 } 01040 BLI_movelisttolist(&fillvertbase,&tempve); 01041 BLI_movelisttolist(&filledgebase,&temped); 01042 01043 /* FREE */ 01044 01045 MEM_freeN(pflist); 01046 01047 return totfaces; 01048 }