static void testvertexnearedge(ScanFillContext *sf_ctx) { /* only vertices with ->h==1 are being tested for * being close to an edge, if true insert */ ScanFillVert *eve; ScanFillEdge *eed, *ed1; for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { if (eve->h == 1) { /* find the edge which has vertex eve */ ed1 = sf_ctx->filledgebase.first; while (ed1) { if (ed1->v1 == eve || ed1->v2 == eve) break; ed1 = ed1->next; } if (ed1->v1 == eve) { ed1->v1 = ed1->v2; ed1->v2 = eve; } for (eed = sf_ctx->filledgebase.first; eed; eed = eed->next) { if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) { if (compare_v3v3(eve->co, eed->v1->co, SF_EPSILON)) { ed1->v2 = eed->v1; eed->v1->h++; eve->h = 0; break; } else if (compare_v3v3(eve->co, eed->v2->co, SF_EPSILON)) { ed1->v2 = eed->v2; eed->v2->h++; eve->h = 0; break; } else { if (boundinsideEV(eed, eve)) { const float dist = dist_to_line_v2(eed->v1->xy, eed->v2->xy, eve->xy); if (dist < SF_EPSILON) { /* new edge */ ed1 = BLI_addfilledge(sf_ctx, eed->v1, eve); /* printf("fill: vertex near edge %x\n",eve); */ ed1->f = 0; ed1->poly_nr = eed->poly_nr; eed->v1 = eve; eve->h = 3; break; } } } } } } } }
static void draw_filled_lasso(wmGesture *gt) { EditVert *v=NULL, *lastv=NULL, *firstv=NULL; EditEdge *e; EditFace *efa; short *lasso= (short *)gt->customdata; int i; for (i=0; i<gt->points; i++, lasso+=2) { float co[3]; co[0]= (float)lasso[0]; co[1]= (float)lasso[1]; co[2]= 0.0f; v = BLI_addfillvert(co); if (lastv) e = BLI_addfilledge(lastv, v); lastv = v; if (firstv==NULL) firstv = v; } /* highly unlikely this will fail, but could crash if (gt->points == 0) */ if(firstv) { BLI_addfilledge(firstv, v); BLI_edgefill(0); glEnable(GL_BLEND); glColor4f(1.0, 1.0, 1.0, 0.05); glBegin(GL_TRIANGLES); for (efa = fillfacebase.first; efa; efa=efa->next) { glVertex2f(efa->v1->co[0], efa->v1->co[1]); glVertex2f(efa->v2->co[0], efa->v2->co[1]); glVertex2f(efa->v3->co[0], efa->v3->co[1]); } glEnd(); glDisable(GL_BLEND); BLI_end_edgefill(); } }
static void scanfill(PolyFill *pf, int mat_nr) { ScFillVert *sc = NULL, *sc1; EditVert *eve,*v1,*v2,*v3; EditEdge *eed,*nexted,*ed1,*ed2,*ed3; float miny = 0.0; int a,b,verts, maxface, totface; short nr, test, twoconnected=0; nr= pf->nr; /* PRINTS verts= pf->verts; eve= fillvertbase.first; while(eve) { printf("vert: %x co: %f %f\n",eve,eve->co[cox],eve->co[coy]); eve= eve->next; } eed= filledgebase.first; while(eed) { printf("edge: %x verts: %x %x\n",eed,eed->v1,eed->v2); eed= eed->next; } */ /* STEP 0: remove zero sized edges */ eed= filledgebase.first; while(eed) { if(eed->v1->co[cox]==eed->v2->co[cox]) { if(eed->v1->co[coy]==eed->v2->co[coy]) { if(eed->v1->f==255 && eed->v2->f!=255) { eed->v2->f= 255; eed->v2->tmp.v= eed->v1->tmp.v; } else if(eed->v2->f==255 && eed->v1->f!=255) { eed->v1->f= 255; eed->v1->tmp.v= eed->v2->tmp.v; } else if(eed->v2->f==255 && eed->v1->f==255) { eed->v1->tmp.v= eed->v2->tmp.v; } else { eed->v2->f= 255; eed->v2->tmp.v = eed->v1->tmp.v; } } } eed= eed->next; } /* STEP 1: make using FillVert and FillEdge lists a sorted ScFillVert list */ sc= scdata= (ScFillVert *)MEM_callocN(pf->verts*sizeof(ScFillVert),"Scanfill1"); eve= fillvertbase.first; verts= 0; while(eve) { if(eve->xs==nr) { if(eve->f!= 255) { verts++; eve->f= 0; /* flag for connectedges later on */ sc->v1= eve; sc++; } } eve= eve->next; } qsort(scdata, verts, sizeof(ScFillVert), vergscdata); eed= filledgebase.first; while(eed) { nexted= eed->next; eed->f= 0; BLI_remlink(&filledgebase,eed); /* commented all of this out, this I have no idea for what it is for, probably from ancient past */ /* it does crash blender, since it uses mixed original and new vertices (ton) */ // if(eed->v1->f==255) { // v1= eed->v1; // while((eed->v1->f == 255) && (eed->v1->tmp.v != v1)) // eed->v1 = eed->v1->tmp.v; // } // if(eed->v2->f==255) { // v2= eed->v2; // while((eed->v2->f == 255) && (eed->v2->tmp.v != v2)) // eed->v2 = eed->v2->tmp.v; // } if(eed->v1!=eed->v2) addedgetoscanlist(eed,verts); eed= nexted; } /* sc= scdata; for(a=0;a<verts;a++) { printf("\nscvert: %x\n",sc->v1); eed= sc->first; while(eed) { printf(" ed %x %x %x\n",eed,eed->v1,eed->v2); eed= eed->next; } sc++; }*/ /* STEP 2: FILL LOOP */ if(pf->f==0) twoconnected= 1; /* (temporal) security: never much more faces than vertices */ totface= 0; maxface= 2*verts; /* 2*verts: based at a filled circle within a triangle */ sc= scdata; for(a=0;a<verts;a++) { /* printf("VERTEX %d %x\n",a,sc->v1); */ ed1= sc->first; while(ed1) { /* set connectflags */ nexted= ed1->next; if(ed1->v1->h==1 || ed1->v2->h==1) { BLI_remlink((ListBase *)&(sc->first),ed1); BLI_addtail(&filledgebase,ed1); if(ed1->v1->h>1) ed1->v1->h--; if(ed1->v2->h>1) ed1->v2->h--; } else ed1->v2->f= 1; ed1= nexted; } while(sc->first) { /* for as long there are edges */ ed1= sc->first; ed2= ed1->next; /* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */ /* if(callLocalInterruptCallBack()) break; */ if(totface>maxface) { /* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */ a= verts; break; } if(ed2==0) { sc->first=sc->last= 0; /* printf("just 1 edge to vert\n"); */ BLI_addtail(&filledgebase,ed1); ed1->v2->f= 0; ed1->v1->h--; ed1->v2->h--; } else { /* test rest of vertices */ v1= ed1->v2; v2= ed1->v1; v3= ed2->v2; /* this happens with a serial of overlapping edges */ if(v1==v2 || v2==v3) break; /* printf("test verts %x %x %x\n",v1,v2,v3); */ miny = ( (v1->co[coy])<(v3->co[coy]) ? (v1->co[coy]) : (v3->co[coy]) ); /* miny= MIN2(v1->co[coy],v3->co[coy]); */ sc1= sc+1; test= 0; for(b=a+1;b<verts;b++) { if(sc1->v1->f==0) { if(sc1->v1->co[coy] <= miny) break; if(testedgeside(v1->co,v2->co,sc1->v1->co)) if(testedgeside(v2->co,v3->co,sc1->v1->co)) if(testedgeside(v3->co,v1->co,sc1->v1->co)) { /* point in triangle */ test= 1; break; } } sc1++; } if(test) { /* make new edge, and start over */ /* printf("add new edge %x %x and start again\n",v2,sc1->v1); */ ed3= BLI_addfilledge(v2, sc1->v1); BLI_remlink(&filledgebase, ed3); BLI_insertlinkbefore((ListBase *)&(sc->first), ed2, ed3); ed3->v2->f= 1; ed3->f= 2; ed3->v1->h++; ed3->v2->h++; } else { /* new triangle */ /* printf("add face %x %x %x\n",v1,v2,v3); */ addfillface(v1, v2, v3, mat_nr); totface++; BLI_remlink((ListBase *)&(sc->first),ed1); BLI_addtail(&filledgebase,ed1); ed1->v2->f= 0; ed1->v1->h--; ed1->v2->h--; /* ed2 can be removed when it's an old one */ if(ed2->f==0 && twoconnected) { BLI_remlink((ListBase *)&(sc->first),ed2); BLI_addtail(&filledgebase,ed2); ed2->v2->f= 0; ed2->v1->h--; ed2->v2->h--; } /* new edge */ ed3= BLI_addfilledge(v1, v3); BLI_remlink(&filledgebase, ed3); ed3->f= 2; ed3->v1->h++; ed3->v2->h++; /* printf("add new edge %x %x\n",v1,v3); */ sc1= addedgetoscanlist(ed3, verts); if(sc1) { /* ed3 already exists: remove */ /* printf("Edge exists\n"); */ ed3->v1->h--; ed3->v2->h--; if(twoconnected) ed3= sc1->first; else ed3= 0; while(ed3) { if( (ed3->v1==v1 && ed3->v2==v3) || (ed3->v1==v3 && ed3->v2==v1) ) { BLI_remlink((ListBase *)&(sc1->first),ed3); BLI_addtail(&filledgebase,ed3); ed3->v1->h--; ed3->v2->h--; break; } ed3= ed3->next; } } } } /* test for loose edges */ ed1= sc->first; while(ed1) { nexted= ed1->next; if(ed1->v1->h<2 || ed1->v2->h<2) { BLI_remlink((ListBase *)&(sc->first),ed1); BLI_addtail(&filledgebase,ed1); if(ed1->v1->h>1) ed1->v1->h--; if(ed1->v2->h>1) ed1->v2->h--; } ed1= nexted; } } sc++; } MEM_freeN(scdata); }
static void testvertexnearedge(void) { /* only vertices with ->h==1 are being tested for being close to an edge, if true insert */ EditVert *eve; EditEdge *eed,*ed1; float dist,vec1[2],vec2[2],vec3[2]; eve= fillvertbase.first; while(eve) { if(eve->h==1) { vec3[0]= eve->co[cox]; vec3[1]= eve->co[coy]; /* find the edge which has vertex eve */ ed1= filledgebase.first; while(ed1) { if(ed1->v1==eve || ed1->v2==eve) break; ed1= ed1->next; } if(ed1->v1==eve) { ed1->v1= ed1->v2; ed1->v2= eve; } eed= filledgebase.first; while(eed) { if(eve!=eed->v1 && eve!=eed->v2 && eve->xs==eed->f1) { if(compare_v3v3(eve->co,eed->v1->co, COMPLIMIT)) { ed1->v2= eed->v1; eed->v1->h++; eve->h= 0; break; } else if(compare_v3v3(eve->co,eed->v2->co, COMPLIMIT)) { ed1->v2= eed->v2; eed->v2->h++; eve->h= 0; break; } else { vec1[0]= eed->v1->co[cox]; vec1[1]= eed->v1->co[coy]; vec2[0]= eed->v2->co[cox]; vec2[1]= eed->v2->co[coy]; if(boundinsideEV(eed,eve)) { dist= dist_to_line_v2(vec1,vec2,vec3); if(dist<COMPLIMIT) { /* new edge */ ed1= BLI_addfilledge(eed->v1, eve); /* printf("fill: vertex near edge %x\n",eve); */ ed1->f= ed1->h= 0; ed1->f1= eed->f1; eed->v1= eve; eve->h= 3; break; } } } } eed= eed->next; } } eve= eve->next; } }
void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal) { EditVert *eve, *v1, *vlast; EditFace *efa; DispList *dlnew=NULL, *dl; float *f1; int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0; intptr_t totvert; if(dispbase==NULL) return; if(dispbase->first==NULL) return; while(cont) { cont= 0; totvert= 0; nextcol= 0; dl= dispbase->first; while(dl) { if(dl->type==DL_POLY) { if(charidx<dl->charidx) cont= 1; else if(charidx==dl->charidx) { /* character with needed index */ if(colnr==dl->col) { /* make editverts and edges */ f1= dl->verts; a= dl->nr; eve= v1= NULL; while(a--) { vlast= eve; eve= BLI_addfillvert(f1); totvert++; if(vlast==NULL) v1= eve; else { BLI_addfilledge(vlast, eve); } f1+=3; } if(eve!=NULL && v1!=NULL) { BLI_addfilledge(eve, v1); } } else if (colnr<dl->col) { /* got poly with next material at current char */ cont= 1; nextcol= 1; } } } dl= dl->next; } if(totvert && (tot= BLI_edgefill(0))) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { if(tot) { dlnew= MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type= DL_INDEX3; dlnew->col= colnr; dlnew->nr= totvert; dlnew->parts= tot; dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex"); dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts"); /* vert data */ f1= dlnew->verts; totvert= 0; eve= fillvertbase.first; while(eve) { VECCOPY(f1, eve->co); f1+= 3; /* index number */ eve->tmp.l = totvert; totvert++; eve= eve->next; } /* index data */ efa= fillfacebase.first; index= dlnew->index; while(efa) { index[0]= (intptr_t)efa->v1->tmp.l; index[1]= (intptr_t)efa->v2->tmp.l; index[2]= (intptr_t)efa->v3->tmp.l; if(flipnormal) SWAP(int, index[0], index[2]); index+= 3; efa= efa->next; } } BLI_addhead(to, dlnew); } BLI_end_edgefill(); if(nextcol) { /* stay at current char but fill polys with next material */ colnr++; } else { /* switch to next char and start filling from first material */ charidx++; colnr= 0; } } /* do not free polys, needed for wireframe display */ }
static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) { ScanFillVertLink *sc = NULL, *sc1; ScanFillVert *eve, *v1, *v2, *v3; ScanFillEdge *eed, *nexted, *ed1, *ed2, *ed3; int a, b, verts, maxface, totface; short nr, test, twoconnected = 0; nr = pf->nr; /* PRINTS */ #if 0 verts = pf->verts; eve = sf_ctx->fillvertbase.first; while (eve) { printf("vert: %x co: %f %f\n", eve, eve->xy[0], eve->xy[1]); eve = eve->next; } eed = sf_ctx->filledgebase.first; while (eed) { printf("edge: %x verts: %x %x\n", eed, eed->v1, eed->v2); eed = eed->next; } #endif /* STEP 0: remove zero sized edges */ eed = sf_ctx->filledgebase.first; while (eed) { if (equals_v2v2(eed->v1->xy, eed->v2->xy)) { if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) { eed->v2->f = SF_VERT_ZERO_LEN; eed->v2->tmp.v = eed->v1->tmp.v; } else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) { eed->v1->f = SF_VERT_ZERO_LEN; eed->v1->tmp.v = eed->v2->tmp.v; } else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) { eed->v1->tmp.v = eed->v2->tmp.v; } else { eed->v2->f = SF_VERT_ZERO_LEN; eed->v2->tmp.v = eed->v1; } } eed = eed->next; } /* STEP 1: make using FillVert and FillEdge lists a sorted * ScanFillVertLink list */ sc = sf_ctx->_scdata = (ScanFillVertLink *)MEM_callocN(pf->verts * sizeof(ScanFillVertLink), "Scanfill1"); eve = sf_ctx->fillvertbase.first; verts = 0; while (eve) { if (eve->poly_nr == nr) { if (eve->f != SF_VERT_ZERO_LEN) { verts++; eve->f = 0; /* flag for connectedges later on */ sc->v1 = eve; sc++; } } eve = eve->next; } qsort(sf_ctx->_scdata, verts, sizeof(ScanFillVertLink), vergscdata); eed = sf_ctx->filledgebase.first; while (eed) { nexted = eed->next; BLI_remlink(&sf_ctx->filledgebase, eed); /* This code is for handling zero-length edges that get * collapsed in step 0. It was removed for some time to * fix trunk bug #4544, so if that comes back, this code * may need some work, or there will have to be a better * fix to #4544. */ if (eed->v1->f == SF_VERT_ZERO_LEN) { v1 = eed->v1; while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v)) eed->v1 = eed->v1->tmp.v; } if (eed->v2->f == SF_VERT_ZERO_LEN) { v2 = eed->v2; while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v)) eed->v2 = eed->v2->tmp.v; } if (eed->v1 != eed->v2) addedgetoscanlist(sf_ctx, eed, verts); eed = nexted; } #if 0 sc = scdata; for (a = 0; a < verts; a++) { printf("\nscvert: %x\n", sc->v1); eed = sc->first; while (eed) { printf(" ed %x %x %x\n", eed, eed->v1, eed->v2); eed = eed->next; } sc++; } #endif /* STEP 2: FILL LOOP */ if (pf->f == 0) twoconnected = 1; /* (temporal) security: never much more faces than vertices */ totface = 0; maxface = 2 * verts; /* 2*verts: based at a filled circle within a triangle */ sc = sf_ctx->_scdata; for (a = 0; a < verts; a++) { /* printf("VERTEX %d %x\n",a,sc->v1); */ ed1 = sc->first; while (ed1) { /* set connectflags */ nexted = ed1->next; if (ed1->v1->h == 1 || ed1->v2->h == 1) { BLI_remlink((ListBase *)&(sc->first), ed1); BLI_addtail(&sf_ctx->filledgebase, ed1); if (ed1->v1->h > 1) ed1->v1->h--; if (ed1->v2->h > 1) ed1->v2->h--; } else ed1->v2->f = SF_VERT_UNKNOWN; ed1 = nexted; } while (sc->first) { /* for as long there are edges */ ed1 = sc->first; ed2 = ed1->next; /* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */ /* if (callLocalInterruptCallBack()) break; */ if (totface > maxface) { /* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */ a = verts; break; } if (ed2 == 0) { sc->first = sc->last = NULL; /* printf("just 1 edge to vert\n"); */ BLI_addtail(&sf_ctx->filledgebase, ed1); ed1->v2->f = 0; ed1->v1->h--; ed1->v2->h--; } else { /* test rest of vertices */ float miny; v1 = ed1->v2; v2 = ed1->v1; v3 = ed2->v2; /* this happens with a serial of overlapping edges */ if (v1 == v2 || v2 == v3) break; /* printf("test verts %x %x %x\n",v1,v2,v3); */ miny = minf(v1->xy[1], v3->xy[1]); /* miny= MIN2(v1->xy[1],v3->xy[1]); */ sc1 = sc + 1; test = 0; for (b = a + 1; b < verts; b++) { if (sc1->v1->f == 0) { if (sc1->v1->xy[1] <= miny) break; if (testedgeside(v1->xy, v2->xy, sc1->v1->xy)) if (testedgeside(v2->xy, v3->xy, sc1->v1->xy)) if (testedgeside(v3->xy, v1->xy, sc1->v1->xy)) { /* point in triangle */ test = 1; break; } } sc1++; } if (test) { /* make new edge, and start over */ /* printf("add new edge %x %x and start again\n",v2,sc1->v1); */ ed3 = BLI_addfilledge(sf_ctx, v2, sc1->v1); BLI_remlink(&sf_ctx->filledgebase, ed3); BLI_insertlinkbefore((ListBase *)&(sc->first), ed2, ed3); ed3->v2->f = SF_VERT_UNKNOWN; ed3->f = SF_EDGE_UNKNOWN; ed3->v1->h++; ed3->v2->h++; } else { /* new triangle */ /* printf("add face %x %x %x\n",v1,v2,v3); */ addfillface(sf_ctx, v1, v2, v3); totface++; BLI_remlink((ListBase *)&(sc->first), ed1); BLI_addtail(&sf_ctx->filledgebase, ed1); ed1->v2->f = 0; ed1->v1->h--; ed1->v2->h--; /* ed2 can be removed when it's a boundary edge */ if ((ed2->f == 0 && twoconnected) || (ed2->f == SF_EDGE_BOUNDARY)) { BLI_remlink((ListBase *)&(sc->first), ed2); BLI_addtail(&sf_ctx->filledgebase, ed2); ed2->v2->f = 0; ed2->v1->h--; ed2->v2->h--; } /* new edge */ ed3 = BLI_addfilledge(sf_ctx, v1, v3); BLI_remlink(&sf_ctx->filledgebase, ed3); ed3->f = SF_EDGE_UNKNOWN; ed3->v1->h++; ed3->v2->h++; /* printf("add new edge %x %x\n",v1,v3); */ sc1 = addedgetoscanlist(sf_ctx, ed3, verts); if (sc1) { /* ed3 already exists: remove if a boundary */ /* printf("Edge exists\n"); */ ed3->v1->h--; ed3->v2->h--; ed3 = sc1->first; while (ed3) { if ( (ed3->v1 == v1 && ed3->v2 == v3) || (ed3->v1 == v3 && ed3->v2 == v1) ) { if (twoconnected || ed3->f == SF_EDGE_BOUNDARY) { BLI_remlink((ListBase *)&(sc1->first), ed3); BLI_addtail(&sf_ctx->filledgebase, ed3); ed3->v1->h--; ed3->v2->h--; } break; } ed3 = ed3->next; } } } } /* test for loose edges */ ed1 = sc->first; while (ed1) { nexted = ed1->next; if (ed1->v1->h < 2 || ed1->v2->h < 2) { BLI_remlink((ListBase *)&(sc->first), ed1); BLI_addtail(&sf_ctx->filledgebase, ed1); if (ed1->v1->h > 1) ed1->v1->h--; if (ed1->v2->h > 1) ed1->v2->h--; } ed1 = nexted; } } sc++; } MEM_freeN(sf_ctx->_scdata); sf_ctx->_scdata = NULL; return totface; }