/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 1997 by Ton Roosendaal, Frank van Beek and Joeri Kassenaar. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* verdit.c */ /* struct EditVert *addvertlist(vec) addedgelist(v1,v2) struct EditVlak *addvlaklist(v1,v2,v3) struct EditEdge *findedgelist(v1,v2) short exist_vlak(v1,v2,v3) make_ebasedata() load_ebasedata() muis_ebase() selectconnected() short extrudeflag(flag,type) rotateflag(flag) extrudeVV() addvert_ebase() addedgevlak_ebase() delvert() adduplicateVV() addprimitive() vertgrabber() vertroteer() vertsizing() */ #include #include #include #include #include #include #include #include #include "/usr/people/include/Trace.h" extern ListBase editNurb; extern ListBase bpbase; extern short rodedit; /* trabuts.c */ extern short editbutflag; long totedgesb,oblen; char *obdup=0; float icovert[12][3] = {0,0,-200, 144.72,-105.144,-89.443, -55.277,-170.128,-89.443, -178.885,0,-89.443, -55.277,170.128,-89.443, 144.72,105.144,-89.443, 55.277,-170.128,89.443, -144.72,-105.144,89.443, -144.72,105.144,89.443, 55.277,170.128,89.443, 178.885,0,89.443, 0,0,200}; short icovlak[20][3] = { 1,0,2, 1,0,5, 2,0,3, 3,0,4, 4,0,5, 1,5,10, 2,1,6, 3,2,7, 4,3,8, 5,4,9, 10,1,6, 6,2,7, 7,3,8, 8,4,9, 9,5,10, 6,10,11, 7,6,11, 8,7,11, 9,8,11, 10,9,11}; /* ************ FAST MALLOC ******************** */ struct ListBase fastmallocbase; struct fastmalloc { struct fastmalloc *next, *prev; int size, nr; struct ListBase subbase; void *data; int *dataflags; int flag; /* 1: full */ }; void initfastmalloc(int size, int nr) { } /* ***************** HASH ********************* */ /* HASH struct voor snel opzoeken edges */ struct HashEdge { struct EditEdge *eed; struct HashEdge *next; }; struct HashEdge *hashedgetab=0; /********* qsort routines *********/ struct xvertsort { float x; struct EditVert *v1; }; long vergxco(x1,x2) struct xvertsort *x1,*x2; { if( x1->x > x2->x ) return 1; else if( x1->x < x2->x) return -1; return 0; } struct vlaksort { int x; struct EditVlak *evl; }; long vergvlak(x1, x2) struct vlaksort *x1, *x2; { if( x1->x > x2->x ) return 1; else if( x1->x < x2->x) return -1; return 0; } /* ************ ADD / REMOVE / FIND ****************** */ #define EDHASH(a, b) ( (a)*256 + (b) ) #define EDHASHSIZE 65536 struct EditVert *addvertlist(vec) float *vec; { extern unsigned char hash[512]; struct EditVert *eve; static unsigned char hashnr= 0; eve= (struct EditVert *)calloc(sizeof(struct EditVert),1); addtail(&G.edve, eve); if(vec) VECCOPY(eve->co, vec); eve->hash= hashnr++; return eve; } struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2) { struct EditVert *v3; struct HashEdge *he; if(hashedgetab==0) { hashedgetab= callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab"); } /* swap ? */ if(v1>v2) { v3= v2; v2= v1; v1= v3; } /* eerst even op de flip-plek kijken */ he= hashedgetab + EDHASH(v2->hash, v1->hash); if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed; he= hashedgetab + EDHASH(v1->hash, v2->hash); while(he) { if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed; he= he->next; } return 0; } void insert_hashedge(struct EditEdge *eed) { /* er van uitgaande dat eed nog niet in lijst zit, en eerst een find is gedaan */ struct HashEdge *first, *he; /* eerst even op de flip-plek kijken */ he= hashedgetab + EDHASH(eed->v2->hash, eed->v1->hash); if(he->eed==0) { he->eed= eed; return; } first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); if( first->eed==0 ) { first->eed= eed; } else { he= (struct HashEdge *)malloc(sizeof(struct HashEdge)); he->eed= eed; he->next= first->next; first->next= he; } } void remove_hashedge(struct EditEdge *eed) { /* er van uitgaande dat eed in lijst zit */ struct HashEdge *first, *he, *prev; /* eerst even op de flip-plek kijken */ first= hashedgetab + EDHASH(eed->v2->hash, eed->v1->hash); if(first->eed==eed) { /* uit lijst verwijderen */ if(first->next) { he= first->next; first->eed= he->eed; first->next= he->next; free(he); } else first->eed= 0; return; } he=first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); while(he) { if(he->eed == eed) { /* uit lijst verwijderen */ if(he==first) { if(first->next) { he= first->next; first->eed= he->eed; first->next= he->next; free(he); } else he->eed= 0; } else { prev->next= he->next; free(he); } return; } prev= he; he= he->next; } } void free_hashedgetab() { struct HashEdge *he, *first, *hen; int a, test[30], nr, toted=0; /* for(a=0; a<30; a++) test[a]=0; */ if(hashedgetab) { first= hashedgetab; for(a=0; anext; /* nr= 0; */ /* if(first->eed) toted++; */ /* if(first->eed) nr++; */ while(he) { hen= he->next; free(he); he= hen; /* nr++; */ } /* if(nr>29) nr= 29; */ /* test[nr]++; */ } freeN(hashedgetab); hashedgetab= 0; /* printf("toted %d\n", toted); */ /* toted= 0; */ /* for(a=0; a<30; a++) { */ /* printf("tab %d %d\n", a, test[a]); */ /* } */ } } struct EditEdge *addedgelist(struct EditVert *v1, struct EditVert *v2) { struct EditVert *v3; struct EditEdge *eed; /* swap ? */ if(v1>v2) { v3= v2; v2= v1; v1= v3; } if(v1==v2) return 0; /* opzoeken in hashlijst */ eed= findedgelist(v1, v2); if(eed==0) { eed= (struct EditEdge *)calloc(sizeof(struct EditEdge), 1); eed->v1= v1; eed->v2= v2; addtail(&G.eded, eed); insert_hashedge(eed); } return eed; } void remedge(eed) struct EditEdge *eed; { remlink(&G.eded, eed); remove_hashedge(eed); } struct EditVlak *addvlaklist(v1,v2,v3,col) struct EditVert *v1,*v2,*v3; short col; { struct EditVlak *evl; /* voeg vlak toe aan lijst en doe meteen de edges */ addedgelist(v1,v2); addedgelist(v2,v3); addedgelist(v3,v1); if(v1==v2 || v2==v3 || v1==v3) return 0; evl= (struct EditVlak *)malloc(sizeof(struct EditVlak)); evl->v1= v1; evl->v2= v2; evl->v3= v3; evl->f1= col; evl->f= 0; addtail(&G.edvl,evl); CalcNormFloat(v1->co, v2->co, v3->co, evl->n); return evl; } short exist_vlak(v1,v2,v3) struct EditVert *v1,*v2,*v3; { struct EditVlak *evl; if(findedgelist(v1,v2)==0) return 0; if(findedgelist(v2,v3)==0) return 0; if(findedgelist(v3,v1)==0) return 0; evl= (struct EditVlak *)G.edvl.first; while(evl) { if(evl->v1==v1 || evl->v2==v1 || evl->v3==v1) { if(evl->v1==v2 || evl->v2==v2 || evl->v3==v2) { if(evl->v1==v3 || evl->v2==v3 || evl->v3==v3) { return 1; } } } evl= evl->next; } return 0; } short comparevlak(vl1, vl2) struct EditVlak *vl1,*vl2; /* return: aantal punten gelijk */ { short tot=0; if(vl1->v1==vl2->v1 || vl1->v2==vl2->v1 || vl1->v3==vl2->v1) tot++; if(vl1->v1==vl2->v2 || vl1->v2==vl2->v2 || vl1->v3==vl2->v2) tot++; if(vl1->v1==vl2->v3 || vl1->v2==vl2->v3 || vl1->v3==vl2->v3) tot++; return tot; } short dubbelvlak(struct EditVlak *evltest) { struct EditVert *v1, *v2, *v3; struct EditVlak *evl; v1= evltest->v1; v2= evltest->v2; v3= evltest->v3; evl= (struct EditVlak *)G.edvl.first; while(evl) { if(evl!=evltest) { if(evl->v1==v1 || evl->v2==v1 || evl->v3==v1) { if(evl->v1==v2 || evl->v2==v2 || evl->v3==v2) { if(evl->v1==v3 || evl->v2==v3 || evl->v3==v3) { return 1; } } } } evl= evl->next; } return 0; } void recalc_editnormals() { struct EditVlak *evl; evl= G.edvl.first; while(evl) { CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n); evl= evl->next; } } /* ************************ IN & OUT ***************************** */ void make_obdups() { struct Base *base; struct ObData *ob,*obd; struct VV *vv; char *obdup1; if(obdup) freeN(obdup); obdup= 0; ob= (struct ObData *)G.ebase->d; if(G.ebase->soort==1) { vv= ob->vv; oblen= sizeof(struct ObData) +ob->c*sizeof(struct ColBlck); obdup1=obdup= mallocN(vv->us*oblen,"obdup"); base= G.firstbase; while(base) { if(base->soort==1) { obd= (struct ObData *)base->d; if(obd->vv== vv) { memcpy(obdup1,obd,oblen); obdup1+=oblen; } } base= base->next; } } else if ELEM(G.ebase->soort, 5, 11) { oblen= sizeof(struct ObData) +ob->c*sizeof(struct ColBlck); obdup= mallocN(oblen,"obdup"); memcpy(obdup,ob,oblen); } } void make_ebasedata() { struct Base *base; struct VertOb *adrve; struct VlakOb *adrvl; struct Key *key; struct EditVert *eve,**eld,**evlist,**edlist,*eve1,*eve2,*eve3; struct EditEdge *eed; struct EditVlak *evl; struct ObData *ob; struct VV *vv; float *fp; long tot=0,a,toted, tijd; char *cp; if(G.ebase==0) return; setcursorN(2); /* ivm reload */ if(G.edve.first) freelist(&G.edve); if(G.eded.first) freelist(&G.eded); if(G.edvl.first) freelist(&G.edvl); free_hashedgetab(); if(obdup) freeN(obdup); obdup=0; if(G.ebase->soort==1) { ob= (struct ObData *)G.ebase->d; vv= ob->vv; G.totvert= tot= vv->vert; if(G.colact==0) G.colact=1; if(ob->c disp)); /* kopie van ObData en ColBlck blokken maken bij duplicates */ make_obdups(); if(tot==0) { setcursorN(1); return; } adrve= (struct VertOb *)(vv+1); adrvl= (struct VlakOb *)(adrve+tot); if(G.ipomode==22 && vv->key && G.actkey) { key= vv->key; a= 1; while(key) { if(a== G.actkey) break; a++; key= key->next; } if(key) { fp= (float *)(key+1); vv->ws= *fp; /* anders wordt het verkeerd getekend. Bij verlaten wordt het weer goed gezet */ adrve= (struct VertOb *)(fp+1); } } /* editverts aanmaken */ evlist= (struct EditVert **)mallocN(tot*4,"evlist"); for(a=0; aco, adrve->c); /* keepnorm */ if(ob->rt3) { cp= (char *)&(eve->vnorm); cp[0]= *( (char *)adrve->n); cp[1]= *( (char *)(adrve->n+1)); cp[2]= *( (char *)(adrve->n+2)); } adrve++; } /* tijd= clock(); */ if(vv->vlak) { /* edges en vlakken maken */ for(a=0;avlak;a++) { eve1= evlist[adrvl->v1]; eve2= evlist[adrvl->v2]; eve3= evlist[adrvl->v3]; evl= addvlaklist(eve1,eve2,eve3,(adrvl->ec & 31)); adrvl++; } } /* printf("time %d\n", clock()-tijd); */ freeN(evlist); } setcursorN(1); } void load_ebasedata() { struct ListBase tempbase; struct VertOb *adrve, *adrve1, *adrve2, *adrve3; struct VlakOb *adrvl; struct EditVert *eve; struct EditEdge *eed; struct EditVlak *evl; struct Base *base; struct ObData *ob, *obtemp; struct VV *vv,*vvn; struct Key *key=0, *prevk, *newk; struct Bezier *bez; float fac,min[3],max[3],cent[3],f1, *fp; long tot=0,a,len; short c, diffvert=0; char *obdup1, *cp; if(G.ebase==0) return; setcursorN(2); countall(); /* alles eerst tellen ivm lengte datablok */ if(G.totvlak>65000) { error("Too many faces"); setcursorN(1); return; } if(G.totvert>65000) { error("Too many vertices"); setcursorN(1); return; } if(G.ebase->soort==1) { /* zijn er vertex keys? * zo ja: doe dan alles als gewoonlijk, maak een nieuwe * keypos en interpoleer weer de vertices. * Is wat omslachtig, maar wel de helderste methode. * Als verschillend aantal vertices: twee gevallen: wel of geen actkey. */ ob= (struct ObData *)G.ebase->d; vv= ob->vv; if(vv->key) { if(G.totvert!= vv->vert) { diffvert= 1; } if(G.ipomode==22 && G.actkey) { key= vv->key; a= 1; while(key) { if(a== G.actkey) break; a++; key= key->next; } } } /* tellen of edges niet in vlakken zitten, en array maken */ eed= (struct EditEdge *)G.eded.first; while(eed) { eed->f= 0; eed= eed->next; } evl= (struct EditVlak *)G.edvl.first; while(evl) { eed= findedgelist(evl->v1,evl->v2); eed->f= 1; eed= findedgelist(evl->v2,evl->v3); eed->f= 1; eed= findedgelist(evl->v3,evl->v1); eed->f= 1; evl= evl->next; } eed= (struct EditEdge *)G.eded.first; while(eed) { if(eed->f==0) G.totvlak++; eed= eed->next; } /* nieuw vv datablok */ ob= (struct ObData *)G.ebase->d; if(ob->floatverts) freeN(ob->floatverts); ob->floatverts= 0; vv= ob->vv; len= sizeof(struct VV)+G.totvert*sizeof(struct VertOb) +G.totvlak*sizeof(struct VlakOb); vvn= (struct VV *)callocN(len,"loadebasedataVV"); memcpy(vvn,vv,sizeof(struct VV)); /* testen op users */ if(vv->us>1) { if(okee("Copy data to duplicates")) { base= G.firstbase; while(base) { if(base->soort==1) { ob= (struct ObData *)base->d; if(ob->vv== vv) ob->vv= vvn; if(ob->floatverts) freeN(ob->floatverts); ob->floatverts= 0; } base= base->next; } freeN(vv); } else { vv->us--; vvn->us= 1; obdup1= obdup; base= G.firstbase; while(base) { if(base!=G.ebase && base->soort==1) { ob= (struct ObData *)base->d; if(ob->vv== vv) { tempbase= ob->disp; freeN(ob); ob= (struct ObData *)mallocN(oblen,"newObblock"); memcpy(ob, obdup1, oblen); ob->disp= tempbase; base->d= (long *)ob; obdup1+=oblen; } } else if(base==G.ebase) obdup1+=oblen; base= base->next; } if(vv->key) { /* dupliceer keys */ key= vv->key; prevk= 0; len= sizeof(struct Key)+ 6*2*vv->vert+4; while(key) { newk= (struct Key *)mallocN(len,"loadebasenewKey1"); memcpy(newk, key, len); if(prevk==0) { /* eerste */ vvn->key= newk; prevk= key; } else { prevk->next= newk; newk->next= 0; prevk= newk; } key= key->next; } } } } else freeN(vv); ob= (struct ObData *)G.ebase->d; vv= ob->vv= vvn; vv->vert= G.totvert; vv->vlak= G.totvlak; /* opnieuw kopie van ObData en ColBlck blokken */ make_obdups(); /* wordruimte */ adrve= (struct VertOb *)(vv+1); min[0]=min[1]=min[2]= 1.0e20; max[0]=max[1]=max[2]= -1.0e20; eve= (struct EditVert *)G.edve.first; while(eve) { for(c=0;c<3;c++) { if(eve->co[c]>max[c]) max[c]= eve->co[c]; if(eve->co[c]co[c]; } eve= eve->next; } max[0]= MAX2(fabs(min[0]),fabs(max[0])); max[1]= MAX2(fabs(min[1]),fabs(max[1])); max[2]= MAX2(fabs(min[2]),fabs(max[2])); fac= MAX3(max[0],max[1],max[2]); cent[0]=cent[1]=cent[2]= 0.0; vv->afm[0]= vv->ws*max[0]; vv->afm[1]= vv->ws*max[1]; vv->afm[2]= vv->ws*max[2]; if(fac>1.0e+9 || fac<1.0e-3) fac= 1.0; else { if(key) { fac/=32767.0; /* waarom stond hier ooit 16384? Vanwege Bspline! */ fp= (float *)(key+1); (*fp)*= fac; } else { fac/=32767; vv->ws*=fac; } } /* de vertices */ /* gebruik ->vn als teller */ eve= (struct EditVert *)G.edve.first; a=0; while(eve) { for(c=0;c<3;c++) { eve->co[c]= (eve->co[c]-cent[c])/fac; /* hierboven moet eerst als ebasedata blijft bestaan (b.v. tijdens render) */ adrve->c[c]= (short)( eve->co[c] ); } eve->vn= (struct EditVert *)a++; /* teller */ eve= eve->next; adrve++; } /* de vlakken */ adrve= (struct VertOb *)(vv+1); adrvl= (struct VlakOb *)(adrve+vv->vert); evl= (struct EditVlak *)G.edvl.first; while(evl) { adrvl->v1= (int) evl->v1->vn; adrvl->v2= (int) evl->v2->vn; adrvl->v3= (int) evl->v3->vn; adrvl->f= 0; adrvl->ec= evl->f1; adrvl++; evl= evl->next; } /* losse edges als vlak toevoegen */ eed= (struct EditEdge *)G.eded.first; while(eed) { if( eed->f==0 ) { adrvl->v1= (int) eed->v1->vn; /* v1==v2 wordt door initrender afgevangen */ adrvl->v2= (int) eed->v1->vn; adrvl->v3= (int) eed->v2->vn; adrvl->ec= 0; adrvl++; } eed= eed->next; } /* voor zekerheid: ->vn pointers wissen */ eve= G.edve.first; while(eve) { eve->vn= 0; eve= eve->next; } adrve= (struct VertOb *)(vv+1); adrvl= (struct VlakOb *)(adrve+vv->vert); normalen(adrve, adrvl, vv->vert, vv->vlak); /* keepnorm */ if(ob->rt3) { eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->vnorm) { cp= (char *)&(eve->vnorm); adrve->n[0]= adrve->n[1]= adrve->n[2]= 0; *( (char *)adrve->n)= cp[0]; *( (char *)(adrve->n+1))= cp[1]; *( (char *)(adrve->n+2))= cp[2]; } eve= eve->next; adrve++; } /* OPNIEUW: puntnormaal omklap-vlaggen voor bij shade*/ adrve= (struct VertOb *)(vv+1); for(a=0; avlak; a++) { adrve1= adrve+adrvl->v1; adrve2= adrve+adrvl->v2; adrve3= adrve+adrvl->v3; adrvl->f=0; len= adrvl->n[0]*adrve1->n[0]+adrvl->n[1]*adrve1->n[1]+adrvl->n[2]*adrve1->n[2]; if(len<0) adrvl->f= 1; len= adrvl->n[0]*adrve2->n[0]+adrvl->n[1]*adrve2->n[1]+adrvl->n[2]*adrve2->n[2]; if(len<0) adrvl->f+= 2; len= adrvl->n[0]*adrve3->n[0]+adrvl->n[1]*adrve3->n[1]+adrvl->n[2]*adrve3->n[2]; if(len<0) adrvl->f+= 4; adrvl++; } } adrvl= (struct VlakOb *)(adrve+vv->vert); if(editbutflag & 8) edgesnew(adrvl, vv->vert, vv->vlak); else edges(adrvl, vv->vert, vv->vlak); if(key && diffvert==0) { fp= (float *)(key+1); memcpy(fp+1, vv+1, 2*6*vv->vert); /* loadkeypos(G.ebase, G.ebase); */ } else if(diffvert) { if( key) { /* wspace uit key halen */ fp= (float *)(key+1); vv->ws= *fp; } key= vv->key; prevk= 0; len= sizeof(struct Key)+2*6*vv->vert+4; while(key) { newk= (struct Key *)mallocN(len, "loadebase4"); memcpy(newk, key, sizeof(struct Key)); fp= (float *)(newk+1); *fp= vv->ws; memcpy(fp+1, vv+1, 2*6*vv->vert); freeN(key); if(prevk==0) vv->key= newk; else prevk->next= newk; prevk= newk; key= newk->next; } } /* displisten van alle users, ook deze base */ ob= (struct ObData *)G.ebase->d; vv= ob->vv; base= G.firstbase; while(base) { if(base->soort==1 && base->lay & view0.lay) { ob= (struct ObData *)base->d; if(ob->vv == vv) { makeDispList(base); if(base->skelnr) calc_deform(base); } } base= base->next; } /* tijdelijk: controleer aantal users ob= (struct ObData *)G.ebase->d; vv= ob->vv; if(vv->us>1) { tot= 0; base= G.firstbase; while(base) { if(base->soort==1) { obtemp= (struct ObData *)base->d; if(obtemp->vv == vv) tot++; } base= base->next; } if(tot!= vv->us) { error("Iets mis met users, lees console"); printf("ERROR in aantal users: object %s %d\n", G.ebase->str, G.ebase->nnr); printf("Getelde users %d, in vv: %d\n", tot, vv->us); printf("Wat heb je gedaan en kun je het herhalen?\n"); printf("(Fout is wel gerepareerd)\n"); vv->us= tot; } } */ } setcursorN(1); } void remake_ebasedata() { struct ObData *ob; struct VV *vv; struct Base *base; char *obduptemp=0; if(G.ebase==0) return; if(okee("Reload Original data")==0) return; if (G.ebase->soort==1) { /* de de obdups terugkopieeren */ obduptemp= obdup; ob= (struct ObData *)G.ebase->d; vv= ob->vv; base= G.firstbase; while(base) { if(base->soort==1) { ob= (struct ObData *)base->d; if(ob->vv==vv) { ob= mallocN(oblen, "remake_ebase"); memcpy(ob, obduptemp, oblen); freeN(base->d); base->d= (long *)ob; obduptemp+= oblen; } } base= base->next; } make_ebasedata(); } else if ELEM(G.ebase->soort, 5, 11) { ob= mallocN(oblen, "remake_ebase"); memcpy(ob, obdup, oblen); freeN(G.ebase->d); G.ebase->d= (long *)ob; make_ebaseNurb(); makeDispList(G.ebase); } else if(G.ebase->soort== -2) { make_ebaseNurb(); makeDispList(G.ebase); } else if(G.ebase->soort== -4) { make_ebaseIka(); } projektie(); if(G.mainb==9) tekeneditbuts(1); if(G.mainb==5) tekenobjbuts(1); } void clearDisplistObdups() { struct ObData *ob; char *obduptemp=0; int a, tot; if(G.ebase==0) return; ob= (struct ObData *)G.ebase->d; tot= ob->vv->us; obduptemp= obdup; for(a=0; adisp.first= ob->disp.last= 0; obduptemp+= oblen; } } /* ********************* TOOLS ********************* */ void righthandfaces() /* maakt vlakken rechtsdraaiend */ { struct EditVert *eve; struct EditEdge *eed, *ed1, *ed2, *ed3, **edpoin; struct EditVlak *evl, *startvl; float minx, miny, minz, cent[3]; long totsel, found, foundone, direct, turn; /* in deze routine wordt tijdelijk in vlaknormaal de edgepointers opgeslagen; /* op basis selectconnected om losse objecten te onderscheiden */ /* tel per edge hoeveel vlakken het heeft */ /* vind het meest linkse, voorste, bovenste vlak */ /* zet normaal naar buiten en de eerste richtings vlaggen in de edges */ /* loop object af en zet richtingen / richtingsvlaggen: alleen bij edges van 1 of 2 vlakken */ /* dit is in feit de select connected */ /* indien nog (selected) vlakken niet gedaan: opnieuw vind de meest linkse ... */ eed= (struct EditEdge *)G.eded.first; while(eed) { if(eed->f==0) G.totvlak++; eed= eed->next; } /* vlakken en edges tellen */ totsel= 0; evl= G.edvl.first; while(evl) { if( (evl->v1->f & 1) && (evl->v2->f & 1) && (evl->v3->f & 1) ) { evl->f= 1; totsel++; edpoin= (struct EditEdge **)evl->n; eed= findedgelist(evl->v1, evl->v2); eed->f1++; edpoin[0]= eed; eed= findedgelist(evl->v2, evl->v3); eed->f1++; edpoin[1]= eed; eed= findedgelist(evl->v3, evl->v1); eed->f1++; edpoin[2]= eed; } else evl->f= 0; evl= evl->next; } while(totsel>0) { /* de meest linkse, bovenste... */ evl= G.edvl.first; startvl= 0; minx= miny= minz= 1.0e10; while(evl) { if(evl->f) { CalcCent3f(cent, evl->v1->co, evl->v2->co, evl->v3->co); if(cent[0]==minx) { if(cent[1]==miny) { if(cent[2]next; } /* eerste vlak goedzetten: normaal berekenen vanwege edgepointers */ CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, cent); if(cent[0]+ cent[1]+ cent[2] > 0.0) { eve= startvl->v2; startvl->v2= startvl->v3; startvl->v3= eve; } eed= findedgelist(startvl->v1, startvl->v2); if(eed->v1==startvl->v1) eed->f= 1; else eed->f= 2; eed= findedgelist(startvl->v2, startvl->v3); if(eed->v1==startvl->v2) eed->f= 1; else eed->f= 2; eed= findedgelist(startvl->v3, startvl->v1); if(eed->v1==startvl->v3) eed->f= 1; else eed->f= 2; startvl->f= 0; totsel--; /* de normalen testen */ found= 1; direct= 1; while(found) { found= 0; if(direct) evl= G.edvl.first; else evl= G.edvl.last; while(evl) { if(evl->f) { turn= 0; foundone= 0; edpoin= (struct EditEdge **)evl->n; ed1= edpoin[0]; ed2= edpoin[1]; ed3= edpoin[2]; if(ed1->f) { if(ed1->v1==evl->v1 && ed1->f==1) turn= 1; if(ed1->v2==evl->v1 && ed1->f==2) turn= 1; foundone= 1; } else if(ed2->f) { if(ed2->v1==evl->v2 && ed2->f==1) turn= 1; if(ed2->v2==evl->v2 && ed2->f==2) turn= 1; foundone= 1; } else if(ed3->f) { if(ed3->v1==evl->v3 && ed3->f==1) turn= 1; if(ed3->v2==evl->v3 && ed3->f==2) turn= 1; foundone= 1; } if(foundone) { found= 1; totsel--; evl->f= 0; if(turn) { if(ed1->v1==evl->v1) ed1->f= 2; else ed1->f= 1; if(ed2->v1==evl->v2) ed2->f= 2; else ed2->f= 1; if(ed3->v1==evl->v3) ed3->f= 2; else ed3->f= 1; eve= evl->v2; evl->v2= evl->v3; evl->v3= eve; } else { if(ed1->v1==evl->v1) ed1->f= 1; else ed1->f= 2; if(ed2->v1==evl->v2) ed2->f= 1; else ed2->f= 2; if(ed3->v1==evl->v3) ed3->f= 1; else ed3->f= 2; } } } if(direct) evl= evl->next; else evl= evl->prev; } direct= 1-direct; } } recalc_editnormals(); } struct EditVert *findnearestvert(sel) short sel; { /* als sel==1 krijgen vertices met flag==1 een nadeel */ struct EditVert *eve,*act=0; static struct EditVert *acto=0; short dist=100,temp,mval[2]; if(G.edve.first==0) return 0; winset(G.winar[0]); /* er wordt geteld van acto->next tot last en van first tot acto */ /* bestaat acto ? */ eve= (struct EditVert *)G.edve.first; while(eve) { if(eve==acto) break; eve= eve->next; } if(eve==0) acto=(struct EditVert *)G.edve.first; if(acto==0) return 0; /* is er een aangegeven vertex? deel 1 */ getmouseco(mval); eve= acto->next; while(eve) { if(eve->h==0) { temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys); if( (eve->f & 1)==sel ) temp+=5; if(tempnext; } /* is er een aangegeven vertex? deel 2 */ if(dist>3) { eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->h==0) { temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys); if( (eve->f & 1)==sel ) temp+=5; if(tempnext; } } acto= act; return act; } void muis_ebase() { void vertgrabber(); extern ulong rectyellow[5][5],rectpurple[5][5]; struct EditVert *eve,*act=0; float omat[3][3], mat[4][4]; struct ObData *ob; long a; short xs,ys,mval[2], dist=100,temp; if(G.zbuf) zbuffer(0); act= findnearestvert(1); if(act) { frontbuffer(1); backbuffer(0); if(editbutflag & 32) { parentbase(G.ebase, mat, omat); ob= (struct ObData *)G.ebase->d; Mat4MulFloat3(mat, ob->vv->ws); multmatrix(mat); } if((G.qual & 3)==0) { eve= (struct EditVert *)G.edve.first; while(eve) { if(eve!=act) { eve->f&= -2; if(eve->h==0) { if(editbutflag & 32) { cpack(0xFF70FF); bgnpoint(); v3f(eve->co); endpoint(); } else { if(eve->xs!=3200) { xs= eve->xs; ys= eve->ys; lrectwrite(xs-1,ys-1,xs+1,ys,rectpurple); } } } } eve= eve->next; } } if( (act->f & 1)==0) act->f+= 1; else if(G.qual & 3) act->f-= 1; if(act->xs!=3200) { xs= act->xs; ys= act->ys; if(editbutflag & 32) { if(act->f & 1) cpack(0x77FFFF); else cpack(0xFF70FF); bgnpoint(); v3f(act->co); endpoint(); } else { if(act->f & 1) lrectwrite(xs-1,ys-1,xs+1,ys,rectyellow); else lrectwrite(xs-1,ys-1,xs+1,ys,rectpurple); } } if(editbutflag & 32) loadmatrix(G.viewmat); frontbuffer(0); backbuffer(1); countall(); tekenoverdraw(0); } if(G.zbuf) zbuffer(1); getmouseco(mval); xs= mval[0]; ys= mval[1]; while(getbutton(RIGHTMOUSE)) { gsync(); getmouseco(mval); if(abs(mval[0]-xs)+abs(mval[1]-ys) > 10) { vertgrabber(); while(getbutton(RIGHTMOUSE)) gsync(); } } } void selectconnectedAll() { struct EditVert *eve,*v1,*v2,*act= 0; struct EditEdge *eed; short flag=1,sel,toggle=0; if(G.eded.first==0) return; while(flag==1) { flag= 0; toggle++; if(toggle & 1) eed= (struct EditEdge *)G.eded.first; else eed= (struct EditEdge *)G.eded.last; while(eed) { v1= eed->v1; v2= eed->v2; if(eed->h==0) { if(v1->f & 1) { if( (v2->f & 1)==0 ) { v2->f |= 1; flag= 1; } } else if(v2->f & 1) { if( (v1->f & 1)==0 ) { v1->f |= 1; flag= 1; } } } if(toggle & 1) eed= eed->next; else eed= eed->prev; } } winset(G.winar[0]); countall(); tekenoverdraw(0); tekenvertices_ext(); } void selectconnected() { struct EditVert *eve,*v1,*v2,*act= 0; struct EditEdge *eed; short flag=1,sel,toggle=0; if(G.eded.first==0) return; if(G.qual > 3) { selectconnectedAll(); return; } sel= 3; if(G.qual & 3) sel=2; act= findnearestvert(sel-2); if(act==0) { error(" Nothing indicated "); return; } /* testflaggen wissen */ eve= (struct EditVert *)G.edve.first; while(eve) { eve->f&= ~2; eve= eve->next; } act->f= (act->f & ~3) | sel; while(flag==1) { flag= 0; toggle++; if(toggle & 1) eed= (struct EditEdge *)G.eded.first; else eed= (struct EditEdge *)G.eded.last; while(eed) { v1= eed->v1; v2= eed->v2; if(eed->h==0) { if(v1->f & 2) { if( (v2->f & 2)==0 ) { v2->f= (v2->f & ~3) | sel; flag= 1; } } else if(v2->f & 2) { if( (v1->f & 2)==0 ) { v1->f= (v1->f & ~3) | sel; flag= 1; } } } if(toggle & 1) eed= eed->next; else eed= eed->prev; } } winset(G.winar[0]); countall(); tekenoverdraw(0); tekenvertices_ext(); } short extrudeflag(flag,type) short flag,type; { /* als type=1 worden oude extrudevlakken verwijderd (ivm spin etc) */ /* alle verts met (flag & 'flag') extrude */ /* van oude wordt flag 'flag' gewist, van nieuwe gezet */ struct EditVert *eve,*v1,*v2,*v3,*nextve; struct EditEdge *eed,*e1,*e2,*e3,*nexted; struct EditVlak *evl,*nextvl,*evln; static long toggle=0; short sel=0,a0=0,a1=0,a2=0,a3=0,deloud= 0; if(G.ebase==0 || G.ebase->soort!=1) return 0; /* de vert flag f1 wissen, hiermee test op losse geselecteerde vert */ eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & flag) eve->f1= 1; else eve->f1= 0; eve= eve->next; } /* de edges tellerflag wissen, als selected op 1 zetten */ eed= (struct EditEdge *)G.eded.first; while(eed) { if( (eed->v1->f & flag) && (eed->v2->f & flag) ) { eed->f= 1; eed->v1->f1= 0; eed->v2->f1= 0; } else eed->f= 0; eed->f1= 1; /* aangeven is 'oude' edge (er worden in deze routine nieuwe gemaakt */ eed= eed->next; } /* in alle vlak sel een dupl.flag zetten en bijhorende edgeflags ophogen */ evl= (struct EditVlak *)G.edvl.first; while(evl) { evl->f= 0; sel= 0; if(evl->v1->f & flag) sel++; if(evl->v2->f & flag) sel+=2; if(evl->v3->f & flag) sel+=4; if(sel==3) { e1= findedgelist(evl->v1,evl->v2); e1->f1= 2; } else if(sel==6) { e2= findedgelist(evl->v2,evl->v3); e2->f1= 2; } else if(sel==5) { e3= findedgelist(evl->v3,evl->v1); e3->f1= 2; } else if(sel==7) { e1= findedgelist(evl->v1,evl->v2); e2= findedgelist(evl->v2,evl->v3); e3= findedgelist(evl->v3,evl->v1); if(e1->f < 3) e1->f++; if(e2->f < 3) e2->f++; if(e3->f < 3) e3->f++; evl->f= 1; } evl= evl->next; } /* de stand van zaken nu: eve->f1==1: losse selected vertex eed->f==0 : edge niet selected, geen extrude eed->f==1 : edge selected, komt niet in vlak voor, extrude eed->f==2 : edge selected, komt 1 keer in vlak voor, extrude eed->f==3 : edge selected, komt in meer vlakken voor, geen extrude eed->f1==0: nieuwe edge eed->f1==1: edge selected, komt in selected vlak voor, als f==3: remove eed->f1==2: edge selected, komt in NIET selected vlak voor evl->f==1 : vlak dupliceren */ /* alle geselecteerde vertices kopieeren, */ /* de pointer naar nieuwe vert in oude struct schrijven op eve->vn */ eve= (struct EditVert *)G.edve.last; while(eve) { eve->f&= ~128; /* wissen voor test later op losse verts */ if(eve->f & flag) { sel= 1; v1= addvertlist(0); VECCOPY(v1->co, eve->co); v1->f= eve->f; eve->f-= flag; eve->vn= v1; } else eve->vn= 0; eve= eve->prev; } if(sel==0) return 0; /* alle edges met eed->f==1 of eed->f==2 worden vlakken */ /* als deloud==1 worden edges eed->f>2 verwijderd */ toggle++; eed= (struct EditEdge *)G.eded.last; while(eed) { nexted= eed->prev; if( eed->f<3) { eed->v1->f|=128; /* =geen losse vert! */ eed->v2->f|=128; } if( (eed->f==1 || eed->f==2) ) { if(eed->f1==2) deloud=1; v1= eed->v1->vn; v2= eed->v2->vn; if(toggle & 1) { addvlaklist(eed->v1,v1,v2,G.colact-1); addvlaklist(eed->v1,v2,eed->v2,G.colact-1); } else { addvlaklist(eed->v2,eed->v1,v1,G.colact-1); addvlaklist(eed->v2,v1,v2,G.colact-1); } } eed= nexted; } if(deloud) { eed= (struct EditEdge *)G.eded.first; while(eed) { nexted= eed->next; if(eed->f==3 && eed->f1==1) { remedge(eed); free(eed); } eed= nexted; } } /* de vlakken dupliceren, eventueel oude verwijderen */ evl= (struct EditVlak *)G.edvl.first; while(evl) { nextvl= evl->next; if(evl->f & 1) { v1= evl->v1->vn; v2= evl->v2->vn; v3= evl->v3->vn; evln= addvlaklist(v1,v2,v3,evl->f1); if(deloud) { remlink(&G.edvl,evl); free(evl); } } evl= nextvl; } /* alle verts met eve->vn!=0 als eve->f1==1: edge maken als flag!=128 :als deloud==1: verwijderen */ eve= (struct EditVert *)G.edve.last; while(eve) { nextve= eve->prev; if(eve->vn) { if(eve->f1==1) addedgelist(eve,eve->vn); else if( (eve->f & 128)==0) { if(deloud) { remlink(&G.edve,eve); free(eve); } } } eve->f&= ~128; eve= nextve; } /* debug temp: testen op consistente: evl= G.edvl.first; while(evl) { e1= findedgelist(evl->v1, evl->v2); e2= findedgelist(evl->v2, evl->v3); e3= findedgelist(evl->v3, evl->v1); if(e1==0 || e2==0 || e3==0) { error("edge not in edgelist"); break; } evl= evl->next; } */ return 1; } void rotateflag(flag,cent,rotmat) short flag; float *cent,*rotmat; { /* alle verts met (flag & 'flag') rotate */ struct EditVert *eve; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & flag) { eve->co[0]-=cent[0]; eve->co[1]-=cent[1]; eve->co[2]-=cent[2]; Mat3MulVecfl(rotmat,eve->co); eve->co[0]+=cent[0]; eve->co[1]+=cent[1]; eve->co[2]+=cent[2]; } eve= eve->next; } } void translateflag(flag,vec) short flag; float *vec; { /* alle verts met (flag & 'flag') translate */ struct EditVert *eve; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & flag) { eve->co[0]+=vec[0]; eve->co[1]+=vec[1]; eve->co[2]+=vec[2]; } eve= eve->next; } } short removedoublesflag(flag, limit) /* return aantal */ short flag; float limit; { /* alle verts met (flag & 'flag') worden getest */ struct EditVert *eve, *v1, *v2, *v3, *nextve, *vn; struct EditEdge *eed,*e1,*nexted; struct EditVlak *evl,*nextvl; struct xvertsort *sortblock, *sb, *sb1; struct vlaksort *vlsortblock, *vsb, *vsb1; float dist,cx,cy,cz; int a,b,test,aantal; /* flag 128 wordt gewist, aantal tellen */ eve= (struct EditVert *)G.edve.first; aantal= 0; while(eve) { eve->f&= ~128; if(eve->f & flag) aantal++; eve= eve->next; } if(aantal==0) return 0; /* geheugen reserveren en qsorten */ sb= sortblock= (struct xvertsort *)mallocN(8*aantal,"sortremovedoub"); eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & flag) { sb->x= eve->co[0]+eve->co[1]+eve->co[2]; sb->v1= eve; sb++; } eve= eve->next; } qsort(sortblock, aantal, 8, vergxco); /* testen op doubles */ sb= sortblock; for(a=0; av1; if( (eve->f & 128)==0 ) { sb1= sb+1; for(b=a+1; bx - sb->x; if(dist > limit) break; /* tweede test: is vertex toegestaan */ v1= sb1->v1; if( (v1->f & 128)==0 ) { dist= fabs(v1->co[0]-eve->co[0]); if(dist<=limit) { dist= fabs(v1->co[1]-eve->co[1]); if(dist<=limit) { dist= fabs(v1->co[2]-eve->co[2]); if(dist<=limit) { v1->f|= 128; v1->vn= eve; } } } } sb1++; } } sb++; } freeN(sortblock); /* edges testen en opnieuw invoegen */ eed= (struct EditEdge *)G.eded.first; while(eed) { eed->f= 0; eed= eed->next; } eed= (struct EditEdge *)G.eded.first; while(eed) { nexted= eed->next; if(eed->f==0) { if( (eed->v1->f & 128) || (eed->v2->f & 128) ) { if(eed->v1->f & 128) eed->v1= eed->v1->vn; if(eed->v2->f & 128) eed->v2= eed->v2->vn; remedge(eed); e1= addedgelist(eed->v1,eed->v2); if(e1) e1->f= 1; free(eed); } } eed= nexted; } /* eerst aantal testvlakken tellen */ evl= (struct EditVlak *)G.edvl.first; aantal= 0; while(evl) { evl->f= 0; if(evl->v1->f & 128) evl->f= 1; else if(evl->v2->f & 128) evl->f= 1; else if(evl->v3->f & 128) evl->f= 1; if(evl->f==1) aantal++; evl= evl->next; } /* vlakken testen op dubbele punten en eventueel verwijderen */ evl= (struct EditVlak *)G.edvl.first; while(evl) { nextvl= evl->next; if(evl->f==1) { if(evl->v1->f & 128) evl->v1= evl->v1->vn; if(evl->v2->f & 128) evl->v2= evl->v2->vn; if(evl->v3->f & 128) evl->v3= evl->v3->vn; test= 0; if(evl->v1==evl->v2) test++; else if(evl->v2==evl->v3) test++; else if(evl->v3==evl->v1) test++; if(test) { remlink(&G.edvl, evl); free(evl); aantal--; } } evl= nextvl; } if(aantal) { /* dubbele vlakken: sortblock */ vsb= vlsortblock= mallocN(8*aantal, "sortremovedoub"); evl= G.edvl.first; while(evl) { if(evl->f & 1) { vsb->x= (int) MIN3( (int)evl->v1, (int)evl->v2, (int)evl->v3); vsb->evl= evl; vsb++; } evl= evl->next; } qsort(vlsortblock, aantal, 8, vergvlak); vsb= vlsortblock; for(a=0; aevl; if( (evl->f & 128)==0 ) { vsb1= vsb+1; v1= evl->v1; v2= evl->v2; v3= evl->v3; for(b=a+1; bx != vsb1->x) break; /* tweede test: is test toegestaan */ evl= vsb1->evl; if( (evl->f & 128)==0 ) { if(evl->v1==v1 || evl->v2==v1 || evl->v3==v1) { if(evl->v1==v2 || evl->v2==v2 || evl->v3==v2) { if(evl->v1==v3 || evl->v2==v3 || evl->v3==v3) { evl->f |= 128; } } } } vsb1++; } } vsb++; } freeN(vlsortblock); /* dubbele vlakken eruit */ evl= (struct EditVlak *)G.edvl.first; while(evl) { nextvl= evl->next; if(evl->f & 128) { remlink(&G.edvl, evl); free(evl); } evl= nextvl; } } /* dubbele vertices eruit */ a= 0; eve= (struct EditVert *)G.edve.first; while(eve) { nextve= eve->next; if(eve->f & flag) { if(eve->f & 128) { a++; remlink(&G.edve, eve); free(eve); } } eve= nextve; } return a; /* aantal */ } void xsortvert_flag(flag) short flag; { /* alle verts met (flag & 'flag') worden gesorteerd */ struct EditVert *eve, *nextve; struct xvertsort *sortblock, *sb; ListBase tbase; float mat[4][4], omat, pmat[4][4]; int aantal; /* aantal tellen */ eve= G.edve.first; aantal= 0; while(eve) { if(eve->f & flag) aantal++; eve= eve->next; } if(aantal==0) return; parentbase(G.ebase, mat, omat); Mat4MulMat4(pmat, pmat, G.viewmat); /* geheugen reserveren en qsorten */ sb= sortblock= (struct xvertsort *)mallocN(8*aantal,"sortremovedoub"); eve= G.edve.first; while(eve) { if(eve->f & flag) { sb->x= pmat[0][0]*eve->co[0]+pmat[0][1]*eve->co[1]+pmat[0][2]*eve->co[2]+pmat[0][3]; sb->v1= eve; sb++; } eve= eve->next; } qsort(sortblock, aantal, 8, vergxco); /* tijdelijke listbase maken */ tbase.first= tbase.last= 0; sb= sortblock; while(aantal--) { eve= sb->v1; remlink(&G.edve, eve); addtail(&tbase, eve); sb++; } addlisttolist(&G.edve, &tbase); freeN(sortblock); } void hashvert_flag(flag) short flag; { struct EditVert *eve; struct xvertsort *sortblock, *sb, onth, *new; ListBase tbase; float mult; int aantal, a, b; /* aantal tellen */ eve= G.edve.first; aantal= 0; while(eve) { if(eve->f & flag) aantal++; eve= eve->next; } if(aantal==0) return; /* geheugen reserveren */ sb= sortblock= (struct xvertsort *)mallocN(8*aantal,"sortremovedoub"); eve= G.edve.first; while(eve) { if(eve->f & flag) { sb->v1= eve; sb++; } eve= eve->next; } srandom(1); mult= ((float)aantal)/32768.0; sb= sortblock; for(a=0; a=0 && bv1; remlink(&G.edve, eve); addtail(&tbase, eve); sb++; } addlisttolist(&G.edve, &tbase); freeN(sortblock); } void subdivideflag(flag,rad) short flag; float rad; { /* divide alle vlakken met (vertflag & flag) */ /* als rad>0.0 zet dan nieuw vert op afstand rad van 0,0,0 */ struct EditVert *eve; struct EditEdge *eed,*e1,*e2,*e3,*nexted; struct EditVlak *evl; float fac,vec[3],vec1[3],VecLenf(); short test; /* edges testen, nieuw punt maken en in edge wegschrijven, flag wissen */ eed= (struct EditEdge *)G.eded.first; while(eed) { eed->f= 0; if( (eed->v1->f & flag) && (eed->v2->f & flag) ) { vec[0]= (eed->v1->co[0]+eed->v2->co[0])/2; vec[1]= (eed->v1->co[1]+eed->v2->co[1])/2; vec[2]= (eed->v1->co[2]+eed->v2->co[2])/2; if(rad>0.0) { /* perf sph */ Normalise(vec); vec[0]*= rad; vec[1]*= rad; vec[2]*= rad; } else if(rad< 0.0) { /* fract */ fac= rad* VecLenf(eed->v1->co,eed->v2->co)/32767.0; vec1[0]= fac*( (float)(random() & 32767) -16384); vec1[1]= fac*( (float)(random() & 32767) -16384); vec1[2]= fac*( (float)(random() & 32767) -16384); VecAddf(vec,vec,vec1); } eed->vn= addvertlist(vec); eed->vn->f= eed->v1->f; } else eed->vn= 0; eed= eed->next; } /* alle vlakken testen op subdiv edges, drie gevallen! */ evl= (struct EditVlak *)G.edvl.last; while(evl) { if( (evl->v1->f & flag) || (evl->v2->f & flag) || (evl->v2->f & flag) ) { e1= findedgelist(evl->v1,evl->v2); e2= findedgelist(evl->v2,evl->v3); e3= findedgelist(evl->v3,evl->v1); test= 0; if(e1 && e1->vn) { test+=1; e1->f=1; } if(e2 && e2->vn) { test+=2; e2->f=1; } if(e3 && e3->vn) { test+=4; e3->f=1; } if(test) { if((test & 3)==3) addvlaklist(evl->v2,e2->vn,e1->vn,evl->f1); if((test & 6)==6) addvlaklist(evl->v3,e3->vn,e2->vn,evl->f1); if((test & 5)==5) addvlaklist(evl->v1,e1->vn,e3->vn,evl->f1); if(test==7) { /* vier nieuwe vlakken, oude vernieuwt */ evl->v1= e1->vn; evl->v2= e2->vn; evl->v3= e3->vn; } else if(test==3) { addvlaklist(e1->vn,e2->vn,evl->v3,evl->f1); evl->v2= e1->vn; } else if(test==6) { addvlaklist(e2->vn,e3->vn,evl->v1,evl->f1); evl->v3= e2->vn; } else if(test==5) { addvlaklist(e3->vn,e1->vn,evl->v2,evl->f1); evl->v1= e3->vn; } else if(test==1) { addvlaklist(e1->vn,evl->v2,evl->v3,evl->f1); evl->v2= e1->vn; addedgelist(evl->v1,evl->v2); } else if(test==2) { addvlaklist(e2->vn,evl->v3,evl->v1,evl->f1); evl->v3= e2->vn; addedgelist(evl->v2,evl->v3); } else if(test==4) { addvlaklist(e3->vn,evl->v1,evl->v2,evl->f1); evl->v1= e3->vn; addedgelist(evl->v3,evl->v1); } } } evl= evl->prev; } /* alle oude edges verwijderen, eventueel nog nieuwe maken */ eed= (struct EditEdge *)G.eded.first; while(eed) { nexted= eed->next; if( eed->vn ) { if(eed->f==0) { /* niet gebruikt in vlak */ addedgelist(eed->v1,eed->vn); addedgelist(eed->vn,eed->v2); } remedge(eed); free(eed); } eed= nexted; } } void adduplicateflag(flag) short flag; { /* oude verts hebben flag 128 gezet en flag 'flag' gewist nieuwe verts hebben flag 'flag' gezet */ struct EditVert *eve,*v1,*v2,*v3; struct EditEdge *eed,*e1,*e2,*e3; struct EditVlak *evl; /* eerst vertices */ eve= (struct EditVert *)G.edve.last; while(eve) { eve->f&= ~128; if(eve->f & flag) { v1= addvertlist(eve->co); v1->f= eve->f; v1->vnorm= eve->vnorm; eve->f-= flag; eve->f|= 128; eve->vn= v1; } eve= eve->prev; } eed= (struct EditEdge *)G.eded.first; while(eed) { if( (eed->v1->f & 128) && (eed->v2->f & 128) ) { v1= eed->v1->vn; v2= eed->v2->vn; addedgelist(v1,v2); } eed= eed->next; } /* tenslotte de vlakken dupliceren */ evl= (struct EditVlak *)G.edvl.first; while(evl) { if( (evl->v1->f & 128) && (evl->v2->f & 128) && (evl->v3->f & 128) ) { v1= evl->v1->vn; v2= evl->v2->vn; v3= evl->v3->vn; addvlaklist(v1,v2,v3,evl->f1); } evl= evl->next; } } void delvlakflag(flag) short flag; { /* alle vlak 3 verts flag + edges + losse vertices deleten */ /* van alle verts wordt 'flag' gewist */ struct EditVert *eve,*nextve; struct EditEdge *eed; struct EditVlak *evl,*nextvl; short test; evl= (struct EditVlak *)G.edvl.first; while(evl) { nextvl= evl->next; if( evl->v1->f & flag) { if( evl->v2->f & flag) { if( evl->v3->f & flag) { eed= findedgelist(evl->v1,evl->v2); if(eed) { remedge(eed); free(eed); } eed= findedgelist(evl->v2,evl->v3); if(eed) { remedge(eed); free(eed); } eed= findedgelist(evl->v3,evl->v1); if(eed) { remedge(eed); free(eed); } remlink(&G.edvl,evl); free(evl); } } } evl= nextvl; } /* alle vlakken 1,2 verts select weer edges maken */ evl= (struct EditVlak *)G.edvl.first; while(evl) { test= 0; if(evl->v1->f & flag) test++; if(evl->v2->f & flag) test+=2; if(evl->v3->f & flag) test+=4; if(test & 3) addedgelist(evl->v1,evl->v2); if(test & 6) addedgelist(evl->v2,evl->v3); if(test & 5) addedgelist(evl->v3,evl->v1); evl= evl->next; } /* alle edges testen op vertices met flag en wissen */ eed= (struct EditEdge *)G.eded.first; while(eed) { if( (eed->v1->f & flag) || (eed->v2->f & flag) ) { eed->v1->f&= ~flag; eed->v2->f&= ~flag; } eed= eed->next; } /* vertices met flag nog gezet zijn losse en worden gewist */ eve= (struct EditVert *)G.edve.first; while(eve) { nextve= eve->next; if(eve->f & flag) { remlink(&G.edve,eve); free(eve); } eve= nextve; } } void extrudeVV() { void vertgrabber(); struct EditVert *eve,*nextve; short a; if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; if(okee("Extrude")==0) return; setcursorN(2); a= extrudeflag(1,1); setcursorN(1); if(a==0) { error("Can't extrude"); } else { countall(); /* voor G.totvert in calc_ebaseverts() */ winset(G.winar[0]); frontbuffer(0); backbuffer(1); calc_ebaseverts(); vertgrabber(); } } void adduplicateVV() { void vertgrabber(); if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; winset(G.winar[0]); setcursorN(2); adduplicateflag(1); setcursorN(1); countall(); /* voor G.totvert in calc_ebaseverts() */ calc_ebaseverts(); vertgrabber(); } void splitVV() { if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; if(okee(" Split ")==0) return; winset(G.winar[0]); setcursorN(2); /* eerste duplicate maken */ adduplicateflag(1); /* oude vlakken hebben 3x flag 128 gezet, deze deleten */ delvlakflag(128); setcursorN(1); countall(); projektie(); } void separateVV() { struct EditVert *eve, *v1; struct EditEdge *eed, *e1; struct EditVlak *evl, *vl1; struct Base *oldbase, *base; struct ObData *ob; struct VV *vv; struct ListBase edve, eded, edvl; int ok, flag; if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; if(okee("Separate")==0) return; winset(G.winar[0]); setcursorN(2); ob= (struct ObData *)G.ebase->d; vv= ob->vv; if(vv->key) { error("Can't separate with vertex keys"); return; } /* we gaan de zaak als volgt neppen: * 1. duplicate base: dit wordt de nieuwe, oude pointer onthouden * 2: split doen als modig. * 3. alle NIET geselecteerde verts, edges, vlakken apart zetten * 4. loadebasedata(): dit is de nieuwe base * 5. freelist en oude verts, eds, vlakken weer terughalen */ /* alleen ebase geselecteerd */ base= G.firstbase; while(base) { if(base->lay & view0.lay) { if(base==G.ebase) base->f |= 1; else base->f &= ~1; } base= base->next; } G.f |= 1; /* grabber uitgeschakeld */ adduplicate(); G.f -= 1; oldbase= G.ebase; G.ebase= G.basact; /* basact wordt in adduplicate() gezet */ /* testen of split */ ok= 0; eed= G.eded.first; while(eed) { flag= (eed->v1->f & 1)+(eed->v2->f & 1); if(flag==1) { ok= 1; break; } eed= eed->next; } if(ok) { /* SPLIT: eerst duplicate maken */ adduplicateflag(1); /* SPLIT: oude vlakken hebben 3x flag 128 gezet, deze deleten */ delvlakflag(128); } /* apart zetten: alles wat maar enigszins NIET select is */ edve.first= edve.last= eded.first= eded.last= edvl.first= edvl.last= 0; eve= G.edve.first; while(eve) { v1= eve->next; if((eve->f & 1)==0) { remlink(&G.edve, eve); addtail(&edve, eve); } eve= v1; } eed= G.eded.first; while(eed) { e1= eed->next; if( (eed->v1->f & 1)==0 || (eed->v2->f & 1)==0 ) { remlink(&G.eded, eed); addtail(&eded, eed); } eed= e1; } evl= G.edvl.first; while(evl) { vl1= evl->next; if( (evl->v1->f & 1)==0 || (evl->v2->f & 1)==0 || (evl->v3->f & 1)==0 ) { remlink(&G.edvl, evl); addtail(&edvl, evl); } evl= vl1; } /* alvorens loadebasedata, eerst aantal users op 1 */ vv= mallocN(sizeof(struct VV), "Separate"); memcpy(vv, ob->vv, sizeof(struct VV)); ob->vv->us--; /* oldbase */ ob= (struct ObData *)G.ebase->d; ob->vv= vv; vv->us= 1; load_ebasedata(); if(G.edve.first) freelist(&G.edve); if(G.eded.first) freelist(&G.eded); if(G.edvl.first) freelist(&G.edvl); G.edve= edve; G.eded= eded; G.edvl= edvl; base= G.ebase; G.ebase= 0; makeDispList(base); /* nieuwe base */ G.ebase= G.basact= oldbase; make_obdups(); setcursorN(1); countall(); projektie(); } void extrude_repeatVV(steps, offs) short steps, offs; { struct EditVert *eve, *nextve; float dvec[3], tmat[4][4], bmat[3][3], phi; short a,ok; if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; winset(G.winar[0]); setcursorN(2); /* dvec */ dvec[0]= G.persinv[2][0]; dvec[1]= G.persinv[2][1]; dvec[2]= G.persinv[2][2]; Normalise(dvec); dvec[0]*= offs; dvec[1]*= offs; dvec[2]*= offs; /* base correctie */ parentbase(G.ebase, tmat, bmat); Mat3CpyMat4(bmat,tmat); phi= ((struct ObData *)G.ebase->d)->vv->ws; Mat3MulFloat(bmat, phi); Mat3Inv(tmat, bmat); Mat3MulVecfl(tmat, dvec); for(a=0;asoort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; winset(G.winar[0]); setcursorN(2); /* imat en centrum en afmeting */ parentbase(G.ebase,tmat,bmat); Mat3CpyMat4(bmat,tmat); if(G.ebase->soort==1) { phi= ((struct ObData *)G.ebase->d)->vv->ws; Mat3MulFloat(bmat,phi); } Mat3Inv(imat,bmat); VECCOPY(cent,view0.muis); cent[0]-= tmat[3][0]; cent[1]-= tmat[3][1]; cent[2]-= tmat[3][2]; Mat3MulVecfl(imat,cent); phi= degr*PI/360.0; phi/= steps; if(editbutflag & 1) phi= -phi; if(dvec) { n[0]=n[1]= 0.0; n[2]= 1.0; } else { n[0]= -G.persinv[2][0]; n[1]= -G.persinv[2][1]; n[2]= -G.persinv[2][2]; Normalise(n); } q[0]= fcos(phi); si= fsin(phi); q[1]= n[0]*si; q[2]= n[1]*si; q[3]= n[2]*si; QuatToMat3(q,cmat); Mat3MulMat3(tmat,cmat,bmat); Mat3MulMat3(bmat,imat,tmat); if(mode==0) if(editbutflag & 2) adduplicateflag(1); ok= 1; for(a=0;anext; if(eve->f & 1) { remlink(&G.edve,eve); free(eve); } eve= nextve; } } countall(); projektie(); } void screwVV(steps,turns) short steps,turns; { struct EditVert *eve,*v1=0,*v2=0; struct EditEdge *eed; float dvec[3]; if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; /* eerste voorwaarde: frontview! */ if(view0.view!=1) { error("Only in frontview!"); return; } /* flags wissen */ eve= (struct EditVert *)G.edve.first; while(eve) { eve->f1= 0; eve= eve->next; } /* edges zetten flags in verts */ eed= (struct EditEdge *)G.eded.first; while(eed) { if(eed->v1->f & 1) { if(eed->v2->f & 1) { /* oppassen f1 is een byte */ if(eed->v1->f1<2) eed->v1->f1++; if(eed->v2->f1<2) eed->v2->f1++; } } eed= eed->next; } /* vind twee vertices met eve->f1==1, meer of minder is fout */ eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f1==1) { if(v1==0) v1= eve; else if(v2==0) v2= eve; else { v1=0; break; } } eve= eve->next; } if(v1==0 || v2==0) { error("No curve selected"); return; } /* bereken dvec */ dvec[0]= ( fabs(v1->co[0]- v2->co[0]) )/(steps); dvec[1]= ( fabs(v1->co[1]- v2->co[1]) )/(steps); dvec[2]= ( fabs(v1->co[2]- v2->co[2]) )/(steps); spinVV(turns*steps,turns*360,dvec,0); } void selectswapVV() { struct EditVert *eve; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->h==0) { if(eve->f & 1) eve->f&= ~1; else eve->f|= 1; } eve= eve->next; } countall(); projektie(); } /* ******************************* ADD ********************* */ void addvert_ebase() { struct EditVert *eve,*v1=0; float fac,mat[3][3],imat[3][3],tmat[4][4]; short val; if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; parentbase(G.ebase,tmat,mat); Mat3CpyMat4(mat,tmat); if(G.ebase->soort==1) { fac= ((struct ObData *)G.ebase->d)->vv->ws; Mat3MulFloat(mat,fac); } Mat3Inv(imat,mat); if(editbutflag & 4) { v1= (struct EditVert *)G.edve.first; while(v1) { if(v1->f & 1) break; v1= v1->next; } eve= v1; /* voorkomen dat er nog meer select zijn */ while(eve) { eve->f&= ~1; eve= eve->next; } } eve= addvertlist(0); VECCOPY(eve->co, view0.muis); eve->xs= view0.mx; eve->ys= view0.my; VecSubf(eve->co,eve->co,tmat[3]); Mat3MulVecfl(imat,eve->co); eve->f= 1; if( (editbutflag & 4) && (v1!=0) ) { addedgelist(v1,eve); v1->f=0; countall(); projektie(); } else { countall(); winset(G.winar[0]); tekenoverdraw(0); tekenvertices_ext(); } while(getbutton(RIGHTMOUSE)); while(qtest()) { if( traces_qread(&val)==INPUTCHANGE) { if(val) G.winakt=val; } } } void addedgevlak_ebase() { struct EditVert *eve,*new[4]; struct EditVlak *evl; short aantal=0; if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; /* hoeveel geselecteerd ? */ eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { new[aantal++]= eve; if(aantal>3) break; } eve= eve->next; } if(aantal<2 || aantal>3) { error("Can't make edge/face"); return; } addedgelist(new[0],new[1]); if(aantal==3) { if(exist_vlak(new[0],new[1],new[2])==0) { addvlaklist(new[0],new[1],new[2],G.colact-1); } else error("Already a face"); } countall(); projektie(); } void delVV() { struct EditVert *eve,*nextve; struct EditVlak *evl,*nextvl; struct EditEdge *eed,*nexted; short event; if(G.ebase==0 || G.ebase->soort!=1) return; if( (view0.lay & G.ebase->lay)==0 ) return; event= pupmenu("ERASE %t|Vertices%x0|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4"); if(event== -1) return; if(event==0 || event==4) { eed= (struct EditEdge *)G.eded.first; while(eed) { nexted= eed->next; if( (eed->v1->f & 1) || (eed->v2->f & 1) ) { remedge(eed); free(eed); } eed= nexted; } evl= (struct EditVlak *)G.edvl.first; while(evl) { nextvl= evl->next; if( (evl->v1->f & 1) || (evl->v2->f & 1) || (evl->v3->f & 1) ) { remlink(&G.edvl, evl); free(evl); } evl= nextvl; } if(event==0) { eve= (struct EditVert *)G.edve.first; while(eve) { nextve= eve->next; if(eve->f & 1) { remlink(&G.edve, eve); free(eve); } eve= nextve; } } } else if(event==1) { eed= (struct EditEdge *)G.eded.first; while(eed) { nexted= eed->next; if( (eed->v1->f & 1) && (eed->v2->f & 1) ) { remedge(eed); free(eed); } eed= nexted; } evl= (struct EditVlak *)G.edvl.first; while(evl) { nextvl= evl->next; event=0; if( evl->v1->f & 1) event++; if( evl->v2->f & 1) event++; if( evl->v3->f & 1) event++; if(event>1) { remlink(&G.edvl,evl); free(evl); } evl= nextvl; } /* om losse vertices te wissen: */ eed= (struct EditEdge *)G.eded.first; while(eed) { if( eed->v1->f & 1) eed->v1->f-=1; if( eed->v2->f & 1) eed->v2->f-=1; eed= eed->next; } eve= (struct EditVert *)G.edve.first; while(eve) { nextve= eve->next; if(eve->f & 1) { remlink(&G.edve,eve); free(eve); } eve= nextve; } } else if(event==2) delvlakflag(1); else if(event==3) { if(G.edve.first) freelist(&G.edve); if(G.eded.first) freelist(&G.eded); if(G.edvl.first) freelist(&G.edvl); } countall(); projektie(); } void addprimitiveVV(soort) short soort; { struct EditVert *eve, *v1, *v2, *v3, *v4, *vtop, *vdown; float d, dia, phi, phid, cent[3], vec[3], imat[3][3], mat[3][3], tmat[4][4]; float si, co, q[4], cmat[3][3], pmat[4][4]; static short tot=32, seg=32, subdiv=2; static short resx = 4, resy = 4, resz = 4; short a, b, sym=0, ext=0, fill, type, totoud, button(); if(soort!= -1) { /* deselectall */ eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) eve->f&= ~1; eve= eve->next; } totoud= tot; /* onthouden en terugzetten als cube/plane */ /* imat en centrum en afmeting */ parentbase(G.ebase,tmat,mat); Mat3CpyMat4(mat,tmat); if(G.ebase->soort==1) { phi= ((struct ObData *)G.ebase->d)->vv->ws; Mat3MulFloat(mat,phi); } VECCOPY(cent,view0.muis); cent[0]-= tmat[3][0]; cent[1]-= tmat[3][1]; cent[2]-= tmat[3][2]; if(soort!= 11) { winset(G.winar[0]); getmatrix(pmat); Mat3CpyMat4(imat,pmat); Mat3MulVecfl(imat, cent); Mat3MulMat3(cmat, imat, mat); Mat3Inv(imat,cmat); } else { Mat3Inv(imat,mat); } /* ext=extrudeflag tot=aantal verts in basis */ switch(soort) { case 0: /* plane */ tot= 4; ext= 0; fill= 1; break; case 1: /* cube */ tot= 4; ext= 1; fill= 1; break; case 4: /* circle */ if(button(&tot,4,100,"Vertices:")==0) return; ext= 0; fill= 0; break; case 5: /* cylinder */ if(button(&tot,4,100,"Vertices:")==0) return; ext= 1; fill= 1; break; case 6: /* tube */ if(button(&tot,4,100,"Vertices:")==0) return; ext= 1; fill= 0; break; case 7: /* cone */ if(button(&tot,4,100,"Vertices:")==0) return; ext= 0; fill= 1; break; case 10: /* grid */ if(button(&tot,3,100,"X res:")==0) return; if(button(&seg,3,100,"Y res:")==0) return; break; case 11: /* UVsphere */ if(button(&seg,3,100,"Segments:")==0) return; if(button(&tot,3,100,"Rings:")==0) return; break; case 12: /* Icosphere */ if(button(&subdiv,1,5,"Subdivision:")==0) return; break; case 13: /* lattice */ if(button(&resx,1,10,"X res:")==0) return; if(button(&resy,1,10,"Y res:")==0) return; if(button(&resz,1,10,"Z res:")==0) return; break; } dia= fsqrt(2.0)*view0.grid; d= -view0.grid; phid= 2*PI/tot; phi= .25*PI; setcursorN(2); if(soort<10) { /* alles behalve grid of sphere */ if(ext==0 && soort!=7) d=0; /* de vertices */ vtop= vdown= v1= v2= 0; for(b=0;b<=ext;b++) { for(a=0;af= 1; if(a==0) { if(b==0) v1= eve; else v2= eve; } phi+=phid; } d= -d; } /* centrum vertices */ if(fill & soort>1) { VECCOPY(vec,cent); vec[2]-= -d; Mat3MulVecfl(imat,vec); vdown= addvertlist(vec); if(ext || soort==7) { VECCOPY(vec,cent); vec[2]-= d; Mat3MulVecfl(imat,vec); vtop= addvertlist(vec); } } else { vdown= v1; vtop= v2; } if(vtop) vtop->f= 1; if(vdown) vdown->f= 1; /* boven en ondervlak */ if(fill) { v3= v1; v4= v2; for(a=1;anext,G.colact-1); v3= v3->next; if(ext) { addvlaklist(vtop,v4,v4->next,G.colact-1); v4= v4->next; } } if(soort>1) { addvlaklist(vdown,v3,v1,G.colact-1); if(ext) addvlaklist(vtop,v4,v2,G.colact-1); } } else if(soort==4) { /* wel edges bij circle */ v3= v1; for(a=1;anext); v3= v3->next; } addedgelist(v3,v1); } /* zijvlakken */ if(ext) { v3= v1; v4= v2; for(a=1;anext,v4,G.colact-1); addvlaklist(v4,v3->next,v4->next,G.colact-1); v3= v3->next; v4= v4->next; } addvlaklist(v3,v1,v4,G.colact-1); addvlaklist(v4,v1,v2,G.colact-1); } else if(soort==7) { /* cone */ v3= v1; for(a=1;anext,v3,G.colact-1); v3= v3->next; } addvlaklist(vtop,v1,v3,G.colact-1); } } else if(soort==10) { /* grid */ /* alle flags wissen */ eve= (struct EditVert *)G.edve.first; while(eve) { eve->f= 0; eve= eve->next; } dia= view0.grid; /* eerst een segment: de X as */ phi= -1.0; phid= 2.0/((float)tot-1); for(a=0;af= 1+2+4; if (a) addedgelist(eve->prev,eve); phi+=phid; } /* extruden en transleren */ vec[0]= vec[2]= 0.0; vec[1]= dia*phid; Mat3MulVecfl(imat, vec); for(a=0;af= 0; eve= eve->next; } /* eerst een segment */ phi= 0; phid/=2; for(a=0;a<=tot;a++) { vec[0]= cent[0]+dia*fsin(phi); vec[1]= cent[1]; vec[2]= cent[2]+dia*fcos(phi); Mat3MulVecfl(imat,vec); eve= addvertlist(vec); eve->f= 1+2+4; if(a==0) v1= eve; else addedgelist(eve->prev,eve); phi+=phid; } /* extruden en roteren */ phi= PI/seg; q[0]= fcos(phi); q[3]= fsin(phi); q[1]=q[2]= 0; QuatToMat3(q,cmat); Mat3MulMat3(tmat,cmat,mat); Mat3MulMat3(cmat,imat,tmat); for(a=0;aco,cmat); } removedoublesflag(4,3.0); } else if(soort==12) { /* Icosphere */ struct EditVert *eva[12]; /* alle flags wissen */ eve= (struct EditVert *)G.edve.first; while(eve) { eve->f= 0; eve= eve->next; } dia/=200; for(a=0;a<12;a++) { vec[0]= dia*icovert[a][0]; vec[1]= dia*icovert[a][1]; vec[2]= dia*icovert[a][2]; eva[a]= addvertlist(vec); eva[a]->f= 1+2; } for(a=0;a<20;a++) { v1= eva[ icovlak[a][0] ]; v2= eva[ icovlak[a][1] ]; v3= eva[ icovlak[a][2] ]; addvlaklist(v1,v2,v3,G.colact-1); } dia*=200; for(a=1;af & 2) { VecAddf(eve->co,eve->co,cent); Mat3MulVecfl(imat,eve->co); } eve= eve->next; } } setcursorN(1); if(soort<2) tot= totoud; } countall(); recalc_editnormals(); projektie(); } void vertexsmooth() { struct EditVert *eve; struct EditEdge *eed; float *adror,*adr, fac; int teller=0, count; float fvec[3]; if(G.ebase==0) return; if( (view0.lay & G.ebase->lay)==0 ) return; winset(G.winar[0]); /* aantal tellen */ eve= G.edve.first; while(eve) { if(eve->f & 1) teller++; eve= eve->next; } if(teller==0) return; adr=adror= (float *)callocN(3*4*teller, "vertsmooth"); eve= G.edve.first; while(eve) { if(eve->f & 1) { eve->vn= (struct EditVert *)adr; eve->f1= 0; adr+= 3; } eve= eve->next; } eed= G.eded.first; while(eed) { if( (eed->v1->f & 1) && (eed->v2->f & 1) ) { fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0; fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0; fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0; if(eed->v1->f1<255) { eed->v1->f1++; VecAddf(eed->v1->vn, eed->v1->vn, fvec); } if(eed->v2->f1<255) { eed->v2->f1++; VecAddf(eed->v2->vn, eed->v2->vn, fvec); } } eed= eed->next; } eve= G.edve.first; while(eve) { if(eve->f & 1) { if(eve->f1) { adr= (float *)eve->vn; fac= 0.5/(float)eve->f1; eve->co[0]= 0.5*eve->co[0]+fac*adr[0]; eve->co[1]= 0.5*eve->co[1]+fac*adr[1]; eve->co[2]= 0.5*eve->co[2]+fac*adr[2]; } eve->vn= 0; } eve= eve->next; } freeN(adror); clearprintoverdraw(); projektie(); } void vertexnoise() { struct Tex *rtex; struct EditVert *eve; float b2,t[3],vec[3],hnoise(),ofs; short tex=1, button(); if(G.totex==0) return; if(button(&tex,1,G.totex,"Textblock")==0) return; rtex= G.adrtex[tex]; initrendertexture(); eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { ofs=rtex->var[1]; VECCOPY(t,eve->co); if(rtex->soort!=8) { externtex(tex, t, &b2); vec[0]= 0.0; vec[1]= 0.0; vec[2]= b2; } else { b2= hnoise(rtex->var[0],t[0],t[1],t[2]); if(rtex->type > 1) ofs*=(b2*b2); vec[0]= b2-hnoise(rtex->var[0],t[0]+ofs,t[1],t[2]); vec[1]= b2-hnoise(rtex->var[0],t[0],t[1]+ofs,t[2]); vec[2]= b2-hnoise(rtex->var[0],t[0],t[1],t[2]+ofs); } eve->co[0]+= 4000*vec[0]; eve->co[1]+= 4000*vec[1]; eve->co[2]+= 4000*vec[2]; } eve= eve->next; } projektie(); } void hideVV() { struct EditVert *eve; struct EditEdge *eed; if(G.ebase==0) return; if( (view0.lay & G.ebase->lay)==0 ) return; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { eve->f-=1; eve->xs= 3200; eve->h= 1; } eve= eve->next; } eed= (struct EditEdge *)G.eded.first; while(eed) { if(eed->v1->h || eed->v2->h) eed->h= 1; else eed->h= 0; eed= eed->next; } projektie(); } void revealVV() { struct EditVert *eve; struct EditEdge *eed; if(G.ebase==0) return; if( (view0.lay & G.ebase->lay)==0 ) return; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->h) { eve->h= 0; eve->f|=1; } eve= eve->next; } eed= (struct EditEdge *)G.eded.first; while(eed) { eed->h= 0; eed= eed->next; } projektie(); } void beautyfill() { /* - alle geselecteerde edges met 2 vlakken * - vind die vlakken: opslaan in edges (extra datablok) * - per edge: - test convex * - test edge: flip? - zoja: remedge, addedge, alle randedges nieuwe vlakpointers */ } /* ************************** MOVE ************************ */ void copyVedit() { /* dit is een 'patch', als ebase->soort==NURB worden de EditVertco's * naar de nurbvertco's gekopieerd. * Vervolgens handles testen. */ struct Base *base; struct EditVert *eve; struct Nurb *nu; if ELEM4(G.ebase->soort, 5, 11, -2, -4) { eve= G.edve.first; while(eve) { memcpy(eve->vn, eve->co, 12); eve= eve->next; } if(G.ebase->soort== -4) { calc_ika(); /* bases die deze ika als deformparent hebben: herberekenen */ base= G.firstbase; while(base) { if(view0.lay & base->lay) { if(base->p==G.ebase && base->skelnr) calc_deform(base); } base= base->next; } } else { nu= editNurb.first; while(nu) { test2DNurb(nu); testhandlesNurb(nu); /* test ook op bezier */ nu= nu->next; } } } makeDispList(G.ebase); } void projektieV() { copyVedit(); if(G.f & 32) recalc_editnormals(); projektie(); } void bgnVedit() { /* indien ebase->soort==NURB worden EditVerts gemaakt */ struct EditVert *eve; struct Nurb *nu; struct BPoint *bp; struct BezTriple *bezt; struct BodyPoint *bop; long a; winset(G.winar[0]); if ELEM3(G.ebase->soort, 5, 11, -2) { nu= editNurb.first; while(nu) { if((nu->type & 7)==1) { a= nu->pntsu; bezt= nu->bezt; while(a--) { if(bezt->f1 & 1) { eve= addvertlist(bezt->vec[0]); eve->vn= (struct EditVert *)(bezt->vec[0]); eve->f= 1; } if(bezt->f2 & 1) { eve= addvertlist(bezt->vec[1]); eve->vn= (struct EditVert *)(bezt->vec[1]); eve->f= 1; } if(bezt->f3 & 1) { eve= addvertlist(bezt->vec[2]); eve->vn= (struct EditVert *)(bezt->vec[2]); eve->f= 1; } bezt++; } } else { a= nu->pntsu*nu->pntsv; bp= nu->bp; while(a--) { if(bp->f1 & 1) { eve= addvertlist(bp->vec); eve->vn= (struct EditVert *)(bp->vec); eve->f= 1; } bp++; } } nu= nu->next; } } else if(G.ebase->soort== -4) { bop= bpbase.first; while(bop) { if(bop->f & 1) { if(rodedit) { eve= addvertlist(bop->r); eve->vn= (struct EditVert *)(bop->r); } else { VECCOPY(bop->hold, bop->r); eve= addvertlist(bop->hold); eve->vn= (struct EditVert *)(bop->hold); } eve->f= 1; } bop= bop->next; } } } void endVedit() { /* indien ebase->soort==NURB worden EditVerts vrijgegeven */ if ELEM4(G.ebase->soort, 5, 11, -2, -4) { freelist(&G.edve); } } void vertgrabber() { struct EditVert *eve; float *adror,*adr,dx,dy,z=0,mat[3][3],cmat[3][3],tmat[4][4]; long teller=0,a,dvec[3],vec[3]; short val,mval[2],xn,yn,xm,ym,toets,midtog=0,proj; Device mdev[2]; char s[40]; if(G.ebase==0) return; if( (view0.lay & G.ebase->lay)==0 ) return; bgnVedit(); /* indien NurbEdit: worden editverts gemaakt */ /* aantal tellen en centrum */ vec[0]=vec[1]=vec[2]=0; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { teller++; vec[0]+= eve->co[0]; vec[1]+= eve->co[1]; vec[2]+= eve->co[2]; } eve= eve->next; } if(teller==0) return; /* opslaan */ adr=adror= (float *)mallocN(3*4*teller,"vertgrab"); eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(adr,eve->co); adr+=3; } eve= eve->next; } mdev[0] = MOUSEX; mdev[1] = MOUSEY; getdev(2, mdev, mval); mval[1]-= S.vys; xn=xm=mval[0]; yn=ym=mval[1]; initprintoverdraw(); sprintf(s,"Dx: 0"); cmov2i(10,204); charstr(s); sprintf(s,"Dy: 0"); cmov2i(160,204); charstr(s); sprintf(s,"Dz: 0"); cmov2i(310,204); charstr(s); endprintoverdraw(); /* mat, imat en initgrabz */ parentbase(G.ebase,tmat,mat); Mat3CpyMat4(mat,tmat); if(G.ebase->soort==1) { dx= ((struct ObData *)G.ebase->d)->vv->ws; Mat3MulFloat(mat,dx); } else if ELEM(G.ebase->soort, 5, 11) { dx= ((struct ObData *)G.ebase->d)->cu->ws; Mat3MulFloat(mat,dx); } Mat3Inv(cmat,mat); vec[0]/=teller; vec[1]/=teller; vec[2]/=teller; Mat3MulVec(mat,vec); vec[0]+= tmat[3][0]; vec[1]+= tmat[3][1]; vec[2]+= tmat[3][2]; z=initgrabz(vec[0],vec[1],vec[2]); while(TRUE) { getdev(2, mdev, mval); mval[1]-= S.vys; if(mval[0]!=xm || mval[1]!=ym) { xm=mval[0]; ym=mval[1]; dx= 2.0*(xn-xm)*z/S.vxw; dy= 2.0*(yn-ym)*z/S.vyw; dvec[0] = (G.persinv[0][0]*dx + G.persinv[1][0]*dy); dvec[1] = (G.persinv[0][1]*dx + G.persinv[1][1]*dy); dvec[2] = (G.persinv[0][2]*dx + G.persinv[1][2]*dy); if(G.move2==1) dvec[1]=dvec[2]=0; if(G.move2==2) dvec[0]=dvec[2]=0; if(G.move2==3) dvec[0]=dvec[1]=0; if(midtog) { if(proj==0) dvec[1]=dvec[2]=0; if(proj==1) dvec[0]=dvec[2]=0; if(proj==2) dvec[0]=dvec[1]=0; } if(G.qual & (48+3) ) { dy= view0.grid; if(G.qual & 3) dy/= 10.0; dx= dvec[0]/dy; dx= ffloor(dx+.5); dvec[0]= dx*dy; dx= dvec[1]/dy; dx= ffloor(dx+.5); dvec[1]= dx*dy; dx= dvec[2]/dy; dx= ffloor(dx+.5); dvec[2]= dx*dy; } VECCOPY(vec,dvec); Mat3MulVec(cmat,vec); adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { eve->co[0]= adr[0]-vec[0]; eve->co[1]= adr[1]-vec[1]; eve->co[2]= adr[2]-vec[2]; adr+=3; } eve= eve->next; } projektieV(); initprintoverdraw(); sprintf(s,"Dx: %d",-dvec[0]); cmov2i(10,204); charstr(s); sprintf(s,"Dy: %d",-dvec[1]); cmov2i(160,204); charstr(s); sprintf(s,"Dz: %d",-dvec[2]); cmov2i(310,204); charstr(s); endprintoverdraw(); } else { if(G.ebase && G.ebase->soort== -4) { calc_ika(); projektieV(); } sginap(2); } if(qtest()) { toets= traces_qread(&val); if(val) { if(toets==ESCKEY || toets==LEFTMOUSE || toets==SPACEKEY) break; if(toets==MIDDLEMOUSE) { midtog= ~midtog; if(midtog) proj= testproj(xn,yn,mval); } arrowsmovecursor(toets); } if(toets==INPUTCHANGE) G.winakt= val; toets=0; xm--; } } if(toets==ESCKEY) { adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(eve->co,adr); adr+=3; } eve= eve->next; } } freeN(adror); clearprintoverdraw(); projektieV(); endVedit(); } void vertroteer() { struct EditVert *eve; struct Base *b; struct MoData *mo; float dx,dy,bmat[3][3],mat[4][4],cmat[3][3],imat[3][3],pmat[3][3],n[3]; float *adror,*adr,hoek=0,hoeko=0,deler,choek,dhoek,si,co; float rotn[3],vec[3],vec1[3],q1[4],q2[4],q3[4],hoek1=0,hoek2=0; long a, teller=0; short xc=0,yc=0,val,mval[2],toets; short dx1,dy1,dx2,dy2,midtog=0,proj,xn,yn; Device mdev[2]; char s[40]; vec[0]=vec[1]=vec[2]=0; if(G.ebase==0) return; if( (view0.lay & G.ebase->lay)==0 ) return; bgnVedit(); /* indien NurbEdit: worden editverts gemaakt */ /* aantal tellen en centrum */ eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { teller++; VecAddf(vec,vec,eve->co); } eve= eve->next; } if(teller==0) return; if(G.move2) { n[0]=n[1]=n[2]=0; if(G.move2==1) n[0]=1.0; if(G.move2==2) n[1]=1.0; if(G.move2==3) n[2]=1.0; } else { n[0]= -G.persinv[2][0]; n[1]= -G.persinv[2][1]; n[2]= -G.persinv[2][2]; Normalise(n); } /* opslaan */ adr=adror= (float *)mallocN(3*4*teller,"vertrot"); eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(adr,eve->co); adr+=3; } eve= eve->next; } parentbase(G.ebase,mat,bmat); Mat3CpyMat4(bmat,mat); if(G.ebase->soort==1) { dx= ((struct ObData *)G.ebase->d)->vv->ws; Mat3MulFloat(bmat,dx); } else if ELEM(G.ebase->soort, 5, 11) { dx= ((struct ObData *)G.ebase->d)->cu->ws; Mat3MulFloat(bmat,dx); } Mat3Inv(imat,bmat); if(G.move1==1) { /* around cursor */ berekenschermco_noclip(view0.muis,mval); xc= mval[0]; yc= mval[1]; VECCOPY(vec,view0.muis); VecSubf(vec,vec,mat[3]); Mat3MulVecfl(imat,vec); } else { vec[0]/=teller; vec[1]/=teller; vec[2]/=teller; VECCOPY(vec1,vec); Mat3MulVecfl(bmat,vec1); VecAddf(vec1,vec1,mat[3]); berekenschermcofl(vec1,mval); xc= mval[0]; yc= mval[1]; if (G.move1 == 2) vec[0] = vec[1] = vec[2] = 0.0; } mdev[0] = MOUSEX; mdev[1] = MOUSEY; getdev(2, mdev, mval); mval[1]-= S.vys; dx1=xc-mval[0]; dy1=yc-mval[1]; xn= mval[0]; yn=mval[1]; initprintoverdraw(); sprintf(s,"Rotate: %3.3f\n",hoek); cmov2i(10,204); charstr(s); endprintoverdraw(); while(TRUE) { getdev(2, mdev, mval); mval[1]-= S.vys; if(midtog) { dx2= -xn+mval[0]; dy2= yn-mval[1]; hoek1+= .2*(float)(dy2-dy1); if(G.qual & 32) hoek1= 5*ffloor(hoek1/5.0 +.5); choek= PI*hoek1/360.0; VECCOPY(rotn,(G.persinv[0])); Normalise(rotn); si= fsin(choek); co= fcos(choek); q2[0]= co; q2[1]= si*rotn[0]; q2[2]= si*rotn[1]; q2[3]= si*rotn[2]; hoek2+= .2*(float)(dx2-dx1); if(G.qual & 32) hoek2= 5*ffloor(hoek2/5.0 +.5); choek= PI*hoek2/360.0; VECCOPY(rotn,(G.persinv[1])); Normalise(rotn); si= fsin(choek); co= fcos(choek); q3[0]= co; q3[1]= si*rotn[0]; q3[2]= si*rotn[1]; q3[3]= si*rotn[2]; QuatMul(q1,q2,q3); if( q1[0]!=hoeko ) { dx1=dx2; dy1=dy2; } } else { dx2=xc-mval[0]; dy2=yc-mval[1]; deler=fsqrt( (float)(dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2)); if(deler>1) { choek=(dx1*dx2+dy1*dy2)/deler; dhoek= 180.0*facos(choek)/PI; if( (dx1*dy2-dx2*dy1)<0 ) dhoek= -dhoek; if(G.qual & 3) hoek+= dhoek/30.0; else hoek+=dhoek; if(hoek>=360) hoek-=360; else if(hoek<-360) hoek+=360; if(G.qual & 32) if(G.qual & 3) hoek=ffloor(hoek+.5); else hoek= 5*ffloor(hoek/5.0 +.5); if(hoek>=360) hoek-=360; else if(hoek<-360) hoek+=360; choek=PI*hoek/360.0; si= fsin(choek); co= fcos(choek); q1[0]= co; q1[1]= si*n[0]; q1[2]= si*n[1]; q1[3]= si*n[2]; if( q1[0]!=hoeko ) { dx1=dx2; dy1=dy2; } } } if( q1[0]!=hoeko ) { hoeko= q1[0]; QuatToMat3(q1,cmat); Mat3MulMat3(pmat,cmat,bmat); Mat3MulMat3(cmat,imat,pmat); adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { vec1[0]= adr[0]-vec[0]; vec1[1]= adr[1]-vec[1]; vec1[2]= adr[2]-vec[2]; Mat3MulVecfl(cmat,vec1); eve->co[0]= vec1[0]+vec[0]; eve->co[1]= vec1[1]+vec[1]; eve->co[2]= vec1[2]+vec[2]; adr+=3; } eve= eve->next; } projektieV(); initprintoverdraw(); if(midtog) { sprintf(s,"Rotate: %3.3f %3.3f\n",hoek1,hoek2); cmov2i(10,204); charstr(s); } else { sprintf(s,"Rotate: %3.3f\n",hoek); cmov2i(10,204); charstr(s); } endprintoverdraw(); } else { if(G.ebase && G.ebase->soort== -4) { calc_ika(); projektieV(); } sginap(2); } if(qtest()) { toets= traces_qread(&val); if(val) { if(toets==ESCKEY || toets==LEFTMOUSE || toets==SPACEKEY) break; if(toets==MIDDLEMOUSE) { midtog= ~midtog; if(midtog) { dx1=xn-mval[0]; dy1=yn-mval[1]; } else { dx1=xc-mval[0]; dy1=yc-mval[1]; } } arrowsmovecursor(toets); } if(toets==INPUTCHANGE) G.winakt= val; toets=0; hoeko-=1.0; } } if(toets==ESCKEY) { adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(eve->co,adr); adr+=3; } eve= eve->next; } } freeN(adror); clearprintoverdraw(); projektieV(); endVedit(); } void vertbend() { struct EditVert *eve; struct Base *b; float fz, fw, dx, dy, bmat[4][4],mat[4][4], cmat[3][3],imat[4][4],n[3]; float *adror, *adr, dist, si, co, viewinv[4][4]; float min[3], max[3]; float vec[3], cent[3], axis[3], q1[4], rad, startomtrekfac, hoek, omtrekfac; long a, *rt=0, teller=0; short ys, yc, yco=0, val, mval[2], toets; char s[40]; if(G.ebase==0) return; if( (view0.lay & G.ebase->lay)==0 ) return; bgnVedit(); /* indien NurbEdit: worden editverts gemaakt */ parentbase(G.ebase, bmat, cmat); dx= 1.0; if(G.ebase->soort==1) { dx= ((struct ObData *)G.ebase->d)->vv->ws; Mat4MulFloat3(bmat,dx); } else if ELEM(G.ebase->soort, 5, 11) { dx= ((struct ObData *)G.ebase->d)->cu->ws; Mat4MulFloat3(bmat,dx); } Mat4Invert(imat, bmat); /* aantal tellen en centrum */ min[0]= min[1]= min[2]= 1.0e20; max[0]= max[1]= max[2]= -1.0e20; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { teller++; MinMax3(min, max, eve->co); } eve= eve->next; } if(teller<2) return; Mat4Invert(viewinv, G.viewmat); Mat4MulVecfl(bmat, min); Mat4MulVecfl(G.viewmat, min); Mat4MulVecfl(bmat, max); Mat4MulVecfl(G.viewmat, max); cent[0]= (min[0]+max[0])/2.0; cent[1]= (min[1]+max[1])/2.0; cent[2]= (min[2]+max[2])/2.0; /* opslaan */ adr=adror= (float *)mallocN(3*4*teller,"vertrot"); eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(adr,eve->co); adr+=3; } eve= eve->next; } getmouseco(mval); ys= mval[1]; /* middelpunt is cursor */ VECCOPY(axis, view0.muis); Mat4MulVecfl(G.viewmat, axis); rad= fsqrt( (axis[0]-cent[0])*(axis[0]-cent[0])+(axis[1]-cent[1])*(axis[1]-cent[1]) ); startomtrekfac= (90*rad*PI)/(360.0*(max[0]-cent[0])); while(TRUE) { getmouseco(mval); yc= mval[1]; if(yc!=yco) { yco= yc; omtrekfac= startomtrekfac+0.008*(yc-ys); /* berekenen hoek voor print */ dist= max[0]-cent[0]; hoek= 360*omtrekfac*dist/(rad*PI); if(G.qual & 48) { hoek= 5.0*ffloor(hoek/5.0); omtrekfac= (hoek*rad*PI)/(360.0*dist); } initprintoverdraw(); sprintf(s,"Warp %3.3f", hoek); cmov2i(10,204); charstr(s); endprintoverdraw(); /* elke vertex moet apart geroteerd */ adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { /* punt transleren naar cent, zodanig roteren dat omtrekafstand==afstand */ VECCOPY(vec, adr); Mat4MulVecfl(bmat, vec); Mat4MulVecfl(G.viewmat, vec); dist= vec[0]-cent[0]; hoek= omtrekfac*dist/rad-0.5*PI; co= fcos(hoek); si= fsin(hoek); vec[0]= (cent[0]-axis[0]); vec[1]= (vec[1]-axis[1]); eve->co[0]= si*vec[0]+co*vec[1]+axis[0]; eve->co[1]= co*vec[0]-si*vec[1]+axis[1]; eve->co[2]= vec[2]; Mat4MulVecfl(viewinv, eve->co); Mat4MulVecfl(imat, eve->co); adr+= 3; } eve= eve->next; } projektieV(); } else { if(G.ebase && G.ebase->soort== -4) { calc_ika(); projektieV(); } sginap(2); } if(qtest()) { toets= traces_qread(&val); if(val) { if(toets==ESCKEY || toets==LEFTMOUSE || toets==SPACEKEY) break; arrowsmovecursor(toets); } yco= 3000; /* gegarandeerd redraw */ if(toets==INPUTCHANGE) G.winakt= val; toets=0; } } if(toets==ESCKEY) { adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(eve->co,adr); adr+=3; } eve= eve->next; } } freeN(adror); clearprintoverdraw(); projektieV(); endVedit(); } void vertsizing() { struct EditVert *eve; float *adror,*adr,mat[4][4],bmat[3][3],pmat[3][3],imat[3][3],cmat[3][3]; float xref, yref, dx,sizex,sizey,sizez,sizexo,sizeyo,sizezo,fac; float vec[3],vec1[3],persmat[3][3],persinv[3][3]; long a, teller=0,teller2,a1; short val,mval[2],xm,ym,xn,yn,xc=0,yc=0,toets; short midtog=0,proj; Device mdev[2]; char s[20]; if(G.ebase==0) return; if( (view0.lay & G.ebase->lay)==0 ) return; winset(G.winar[0]); xref= yref= 1.0; bgnVedit(); /* indien NurbEdit: worden editverts gemaakt */ /* aantal tellen en centrum */ vec[0]= vec[1]= vec[2]= 0; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { teller++; vec[0]+= eve->co[0]; vec[1]+= eve->co[1]; vec[2]+= eve->co[2]; } eve= eve->next; } if(teller==0) return; /* opslaan */ adr=adror= (float *)mallocN(3*4*teller,"vertrot"); eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(adr,eve->co); adr+=3; } eve= eve->next; } parentbase(G.ebase,mat,cmat); Mat3CpyMat4(bmat,mat); if(G.ebase->soort==1) { dx= ((struct ObData *)G.ebase->d)->vv->ws; Mat3MulFloat(bmat,dx); } else if ELEM(G.ebase->soort, 5, 11) { dx= ((struct ObData *)G.ebase->d)->cu->ws; Mat3MulFloat(bmat,dx); } Mat3Inv(imat,bmat); Mat3CpyMat4(persmat,G.persmat); Mat3CpyMat4(persinv,G.persinv); if(G.move1==1) { /* around cursor */ berekenschermco_noclip(view0.muis,mval); xc= mval[0]; yc= mval[1]; VECCOPY(vec1, view0.muis); VecSubf(vec,vec1,mat[3]); Mat3MulVecfl(imat,vec); } else { vec[0]/=teller; vec[1]/=teller; vec[2]/=teller; VECCOPY(vec1,vec); Mat3MulVecfl(bmat,vec1); VecAddf(vec1,vec1,mat[3]); berekenschermcofl(vec1,mval); xc= mval[0]; yc= mval[1]; if (G.move1 == 2) vec[0] = vec[1] = vec[2] = 0.0; } mdev[0] = MOUSEX; mdev[1] = MOUSEY; getdev(2, mdev, mval); mval[1]-= S.vys; xm=mval[0]; ym=mval[1]; sizexo=sizeyo=sizezo=1.0; fac= fsqrt( (float)((yc-ym)*(yc-ym)+(xm-xc)*(xm-xc)) ); if(fac<1.0) fac= 1.0; initprintoverdraw(); sprintf(s,"Size X: %3.3f",sizexo); cmov2i(10,204); charstr(s); sprintf(s,"Size Y: %3.3f",sizeyo); cmov2i(160,204); charstr(s); sprintf(s,"Size Z: %3.3f",sizezo); cmov2i(310,204); charstr(s); if(G.move2==4) { sprintf(s,"SizeView"); cmov2i(460,204); charstr(s); } else if(G.move2==5) { sprintf(s,"Shear"); cmov2i(460,204); charstr(s); } endprintoverdraw(); while(TRUE) { getdev(2, mdev, mval); mval[1]-= S.vys; xn=mval[0]; yn=mval[1]; if(G.move2>=4) { sizex=1-(float)(xm-xn)*0.005; if(G.move2==4) sizey=1+(float)(ym-yn)*0.005; sizez=1; } else { sizex=sizey=sizez= (fsqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) ))/fac; if(G.move2==1) sizey=sizez=1; if(G.move2==2) sizex=sizez=1; if(G.move2==3) sizey=sizex=1; } if(midtog) { if(proj==0) sizey=sizez=1; if(proj==1) sizex=sizez=1; if(proj==2) sizey=sizex=1; } if(G.qual & 32) { if (G.qual & 3) { sizex= (ffloor(100.0*sizex))/100.0; sizey= (ffloor(100.0*sizey))/100.0; sizez= (ffloor(100.0*sizez))/100.0; if(sizex==0.0) sizex== 0.01; if(sizey==0.0) sizey== 0.01; if(sizez==0.0) sizez== 0.01; } else { sizex= (ffloor(10.0*sizex))/10.0; sizey= (ffloor(10.0*sizey))/10.0; sizez= (ffloor(10.0*sizez))/10.0; if(sizex==0.0) sizex== 0.1; if(sizey==0.0) sizey== 0.1; if(sizez==0.0) sizez== 0.1; } } else if (G.qual & 3) { sizex = ((sizex - 1.0) / 10.0) + 1.0; sizey = ((sizey - 1.0) / 10.0) + 1.0; sizez = ((sizez - 1.0) / 10.0) + 1.0; } /* x flip */ val= testproj(mval[0]+10, mval[1], mval); if(val==0) sizex*= xref; else if(val==1) sizey*= xref; else sizez*=xref; /* y flip */ val= testproj(mval[0], mval[1]+10, mval); if(val==0) sizex*= yref; else if(val==1) sizey*= yref; else sizez*=yref; if(sizex!=sizexo || sizey!=sizeyo || sizez!=sizezo) { Mat3One(cmat); cmat[0][0]= sizex; cmat[1][1]= sizey; cmat[2][2]= sizez; if(G.move2>=4) { if(G.move2==5) { cmat[0][0]= cmat[2][2]= cmat[1][1]= 1.0; cmat[1][0]=sizex-1.0; } Mat3MulMat3(pmat,persmat,bmat); Mat3MulMat3(mat,cmat,pmat); Mat3MulMat3(pmat,persinv,mat); Mat3MulMat3(cmat,imat,pmat); } else { Mat3MulMat3(pmat,cmat,bmat); Mat3MulMat3(cmat,imat,pmat); } adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { vec1[0]= adr[0]-vec[0]; vec1[1]= adr[1]-vec[1]; vec1[2]= adr[2]-vec[2]; Mat3MulVecfl(cmat,vec1); eve->co[0]= vec1[0]+vec[0]; eve->co[1]= vec1[1]+vec[1]; eve->co[2]= vec1[2]+vec[2]; adr+=3; } eve= eve->next; } projektieV(); initprintoverdraw(); sprintf(s,"Size X: %3.3f",sizex); cmov2i(10,204); charstr(s); sprintf(s,"Size Y: %3.3f",sizey); cmov2i(160,204); charstr(s); sprintf(s,"Size Z: %3.3f",sizez); cmov2i(310,204); charstr(s); if(G.move2==4) { sprintf(s,"SizeView"); cmov2i(460,204); charstr(s); } else if(G.move2==5) { sprintf(s,"Shear"); cmov2i(460,204); charstr(s); } endprintoverdraw(); } else { if(G.ebase && G.ebase->soort== -4) { calc_ika(); projektieV(); } sginap(2); } sizexo=sizex; sizeyo=sizey; sizezo=sizez; if(qtest()) { toets= traces_qread(&val); if(val) { if(toets==ESCKEY || toets==LEFTMOUSE || toets==SPACEKEY) break; else if(toets==MIDDLEMOUSE) { midtog= ~midtog; if(midtog) proj= testproj(xm,ym,mval); } else if(toets==XKEY) xref= -xref; else if(toets==YKEY) yref= -yref; arrowsmovecursor(toets); } if(toets==INPUTCHANGE) G.winakt= val; toets=0; sizexo-= 1.0; } } if(toets==ESCKEY) { adr= adror; eve= (struct EditVert *)G.edve.first; while(eve) { if(eve->f & 1) { VECCOPY(eve->co,adr); adr+=3; } eve= eve->next; } } freeN(adror); clearprintoverdraw(); projektieV(); endVedit(); } void vertices_to_sphere() { struct EditVert *eve; struct ObData *ob; float len, vec[3], cent[3], imat[3][3], tmat[4][4], bmat[3][3]; float VecLenf(); int tot; if(G.ebase==0 || G.ebase->soort!=1) return; parentbase(G.ebase,tmat, bmat); Mat3CpyMat4(bmat, tmat); ob= (struct ObData *)G.ebase->d; Mat3MulFloat(bmat, ob->vv->ws); Mat3Inv(imat, bmat); /* centrum */ cent[0]= view0.muis[0]-tmat[3][0]; cent[1]= view0.muis[1]-tmat[3][1]; cent[2]= view0.muis[2]-tmat[3][2]; Mat3MulVecfl(imat, cent); len= 0.0; tot= 0; eve= G.edve.first; while(eve) { if(eve->f & 1) { tot++; len+= VecLenf(cent, eve->co); } eve= eve->next; } len/=tot; if(len==0.0) len= 10.000; eve= G.edve.first; while(eve) { if(eve->f & 1) { vec[0]= eve->co[0]-cent[0]; vec[1]= eve->co[1]-cent[1]; vec[2]= eve->co[2]-cent[2]; Normalise(vec); eve->co[0]= cent[0]+vec[0]*len; eve->co[1]= cent[1]+vec[1]*len; eve->co[2]= cent[2]+vec[2]*len; } eve= eve->next; } projektie(); } void leesCurryEdit(char *name) { struct Base *base; struct ObData *ob; struct VV *vv; struct EditVert *v1, *v2, *v3; struct EditVert *v1o=0, *v2o=0, *v3o=0; struct ColBlck *col; struct VlakOb *adrvl; struct VertOb *adrve; float vec[3]; short svec[3]; int a, file, filelen; char *filedata, *fd, *end; file= open(name, O_RDONLY); if(file<=0) { error("Can't open file"); return; } filelen= lseek(file, 0, 2); /* seek end */ lseek(file, 0, 0); /* en weer terug */ if(filelen<20) { close(file); return; } filedata= mallocN(filelen, "curry"); read(file, filedata, filelen); close(file); end= filedata+filelen; fd= filedata+20; while(fd