diff options
-rw-r--r-- | source/blender/blenlib/BLI_linklist.h | 1 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_linklist.c | 17 | ||||
-rw-r--r-- | source/blender/include/BIF_editmesh.h | 9 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 4 | ||||
-rw-r--r-- | source/blender/src/editmesh_add.c | 22 | ||||
-rw-r--r-- | source/blender/src/editmesh_loop.c | 1547 | ||||
-rw-r--r-- | source/blender/src/editmesh_mods.c | 88 | ||||
-rw-r--r-- | source/blender/src/editmesh_tools.c | 3122 | ||||
-rw-r--r-- | source/blender/src/editobject.c | 48 | ||||
-rw-r--r-- | source/blender/src/header_view3d.c | 24 | ||||
-rw-r--r-- | source/blender/src/space.c | 13 | ||||
-rw-r--r-- | source/blender/src/toolbox.c | 5 |
12 files changed, 2693 insertions, 2207 deletions
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h index d0e6effae3d..2e75420a1ff 100644 --- a/source/blender/blenlib/BLI_linklist.h +++ b/source/blender/blenlib/BLI_linklist.h @@ -52,6 +52,7 @@ int BLI_linklist_length (struct LinkNode *list); void BLI_linklist_reverse (struct LinkNode **listp); void BLI_linklist_prepend (struct LinkNode **listp, void *ptr); +void BLI_linklist_append (struct LinkNode **listp, void *ptr); void BLI_linklist_prepend_arena (struct LinkNode **listp, void *ptr, struct MemArena *ma); void BLI_linklist_free (struct LinkNode *list, LinkNodeFreeFP freefunc); diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c index ad945b53d11..253d127db38 100644 --- a/source/blender/blenlib/intern/BLI_linklist.c +++ b/source/blender/blenlib/intern/BLI_linklist.c @@ -76,6 +76,23 @@ void BLI_linklist_prepend(LinkNode **listp, void *ptr) { *listp= nlink; } +void BLI_linklist_append(LinkNode **listp, void *ptr) { + LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink"); + LinkNode *node = *listp; + + nlink->link = ptr; + nlink->next = NULL; + + if(node == NULL){ + *listp = nlink; + } else { + while(node->next != NULL){ + node = node->next; + } + node->next = nlink; + } +} + void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) { LinkNode *nlink= BLI_memarena_alloc(ma, sizeof(*nlink)); nlink->link= ptr; diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h index 0f794e89ed6..c1dd2c43afa 100644 --- a/source/blender/include/BIF_editmesh.h +++ b/source/blender/include/BIF_editmesh.h @@ -101,6 +101,7 @@ extern void EM_free_backbuf_border(void); extern void EM_selectmode_menu(void); + extern void vertexnoise(void); extern void vertexsmooth(void); extern void righthandfaces(int select); @@ -135,20 +136,22 @@ extern void editmesh_deselect_by_material(int index); extern void Edge_Menu(void); extern void editmesh_mark_seam(int clear); + /* ******************* editmesh_loop.c */ #define KNIFE_PROMPT 0 #define KNIFE_EXACT 1 #define KNIFE_MIDPOINT 2 +#define KNIFE_MULTICUT 3 +extern void CutEdgeloop(int numcuts); extern void KnifeSubdivide(char mode); extern void LoopMenu(void); #define LOOP_SELECT 1 #define LOOP_CUT 2 -extern void loopoperations(char mode); -extern void vertex_loop_select(void); +extern short sharesFace(struct EditEdge* e1, struct EditEdge* e2); /* ******************* editmesh_tools.c */ extern void convert_to_triface(int all); @@ -156,6 +159,7 @@ extern int removedoublesflag(short flag, float limit); extern void xsortvert_flag(int flag); extern void hashvert_flag(int flag); extern void subdivideflag(int flag, float rad, int beauty); +extern void esubdivideflag(int flag, float rad, int beauty, int numcuts, int selecttype); extern void extrude_mesh(void); extern void split_mesh(void); extern void extrude_repeat_mesh(int steps, float offs); @@ -168,6 +172,7 @@ extern void edge_flip(void); extern void fill_mesh(void); extern void bevel_menu(); void edge_rotate_selected(int dir); +void EdgeSlide(short immediate, float imperc); #endif diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index e07b0d2118b..8a8423fe4bc 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -2048,7 +2048,7 @@ void do_meshbuts(unsigned short event) break; case B_SUBDIV: waitcursor(1); - subdivideflag(1, 0.0, editbutflag & B_BEAUTY); + esubdivideflag(1, 0.0, editbutflag & B_BEAUTY,1,0); countall(); waitcursor(0); allqueue(REDRAWVIEW3D, 0); @@ -2059,7 +2059,7 @@ void do_meshbuts(unsigned short event) if(button(&randfac, 1, 100, "Rand fac:")==0) return; waitcursor(1); fac= -( (float)randfac )/100; - subdivideflag(1, fac, editbutflag & B_BEAUTY); + esubdivideflag(1, fac, editbutflag & B_BEAUTY,1,0); countall(); waitcursor(0); allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c index f8518fc4a90..25249f890aa 100644 --- a/source/blender/src/editmesh_add.c +++ b/source/blender/src/editmesh_add.c @@ -776,7 +776,8 @@ void add_primitiveMesh(int type) } else if(type==12) { /* Icosphere */ EditVert *eva[12]; - + EditEdge *eed; + /* clear all flags */ eve= em->verts.first; while(eve) { @@ -792,14 +793,18 @@ void add_primitiveMesh(int type) eva[a]->f= 1+2; } for(a=0;a<20;a++) { - v1= eva[ icoface[a][0] ]; + EditFace *evtemp; + v1= eva[ icoface[a][0] ]; v2= eva[ icoface[a][1] ]; v3= eva[ icoface[a][2] ]; - addfacelist(v1, v2, v3, 0, NULL, NULL); + evtemp = addfacelist(v1, v2, v3, 0, NULL, NULL); + evtemp->e1->f = 1+2; + evtemp->e2->f = 1+2; + evtemp->e3->f = 1+2; } dia*=200; - for(a=1; a<subdiv; a++) subdivideflag(2, dia, 0); + for(a=1; a<subdiv; a++) esubdivideflag(2, dia, 0,1,0); /* and now do imat */ eve= em->verts.first; while(eve) { @@ -809,6 +814,15 @@ void add_primitiveMesh(int type) } eve= eve->next; } + + // Clear the flag 2 from the edges + for(eed=em->edges.first;eed;eed=eed->next){ + if(eed->f & 2){ + eed->f &= !2; + } + } + + } else if (type==13) { /* Monkey */ extern int monkeyo, monkeynv, monkeynf; extern signed char monkeyf[][4]; diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c index afc63ee50f7..ca1985ba5af 100644 --- a/source/blender/src/editmesh_loop.c +++ b/source/blender/src/editmesh_loop.c @@ -90,67 +90,123 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv #include "winlay.h" -/* *************** LOOP SELECT ************* */ - -static short edgeFaces(EditEdge *e){ +/* New LoopCut */ +static void edgering_sel(EditEdge *startedge, int select, int previewlines){ EditMesh *em = G.editMesh; - EditFace *search=NULL; - short count = 0; - - search = em->faces.first; - while(search){ - if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) - count++; - search = search->next; + EditEdge *eed; + EditFace *efa; + int looking= 1,i; + float co[2][3]; + EditVert *v[2][2]; + /* in eed->f1 we put the valence (amount of faces in edge) */ + /* in eed->f2 we put tagged flag as correct loop */ + /* in efa->f1 we put tagged flag as correct to select */ + + for(eed= em->edges.first; eed; eed= eed->next) { + eed->f1= 0; + eed->f2= 0; } - return count; -} - -/* this utility function checks to see if 2 edit edges share a face, - returns 1 if they do - returns 0 if they do not, or if the function is passed the same edge 2 times -*/ -static short sharesFace(EditEdge* e1, EditEdge* e2) -{ - EditMesh *em = G.editMesh; - EditFace *search=NULL; - search = em->faces.first; - if (e1 == e2){ - return 0 ; + for(efa= em->faces.first; efa; efa= efa->next) { + efa->f1= 0; + if(efa->h==0) { + efa->e1->f1++; + efa->e2->f1++; + efa->e3->f1++; + if(efa->e4) efa->e4->f1++; + } } - while(search){ - if( - ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) && - ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2)) - ) { - return 1; + + // tag startedge OK + startedge->f2= 1; + + while(looking) { + looking= 0; + + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->e4 && efa->f1==0) { // not done quad + if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok + + // if edge tagged, select opposing edge and mark face ok + if(efa->e1->f2) { + efa->e3->f2= 1; + efa->f1= 1; + looking= 1; + } + else if(efa->e2->f2) { + efa->e4->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e3->f2) { + efa->e1->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e4->f2) { + efa->e2->f2= 1; + efa->f1= 1; + looking= 1; + } + } + } } - search = search->next; } - return 0; + + if(previewlines > 0 && select == 0){ + persp(PERSP_VIEW); + glPushMatrix(); + mymultmatrix(G.obedit->obmat); + //glColor3ub(0, 255, 255); + //glBegin(GL_LINES); + //glVertex3f(nearest->v1->co[0],nearest->v1->co[1],nearest->v1->co[2]); + //glVertex3f(nearest->v2->co[0],nearest->v2->co[1],nearest->v2->co[2]); + //glEnd(); + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->v4 == NULL) { continue; } + if(efa->e1->f2 == 1){ + v[0][0] = efa->v1; + v[0][1] = efa->v2; + v[1][0] = efa->v4; + v[1][1] = efa->v3; + } else if(efa->e2->f2 == 1){ + v[0][0] = efa->v2; + v[0][1] = efa->v3; + v[1][0] = efa->v1; + v[1][1] = efa->v4; + } else { continue; } + + for(i=1;i<=previewlines;i++){ + co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0]; + co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1]; + co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2]; + + co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0]; + co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1]; + co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2]; + glColor3ub(255, 0, 255); + glBegin(GL_LINES); + glVertex3f(co[0][0],co[0][1],co[0][2]); + glVertex3f(co[1][0],co[1][1],co[1][2]); + glEnd(); + } + } + glPopMatrix(); + } else { + + /* (de)select the edges */ + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->f2) EM_select_edge(eed, select); + } + } } -/* This function selects a vertex loop based on a each succesive edge having a valance of 4 - and not sharing a face with the previous edge */ - -/* It uses ->f flags still, which isn't causing bugs now, but better be put in ->f1 (ton) */ - -void vertex_loop_select() -{ - EditMesh *em = G.editMesh; - EditVert *v1=NULL,*v2=NULL; - EditEdge *search=NULL,*startEdge=NULL,*valSearch = NULL,*nearest = NULL,*compEdge; - EditEdge *EdgeVal[5] = {NULL,NULL,NULL,NULL,NULL}; - short numEdges=0,curEdge = 0,looking = 1,edgeValCount = 0,i=0,looped = 0,choosing = 1,event,noloop=0,cancel=0, val; - short protect = 0, dist= 50; +void CutEdgeloop(int numcuts){ + EditMesh *em = G.editMesh; short mvalo[2] = {0,0}, mval[2]; - - SetBlenderCursor(BC_VLOOPCURSOR); - for(search=em->edges.first;search;search=search->next) - numEdges++; - - /* start with v1 and go in one direction. */ - while(choosing){ - getmouseco_areawin(mval); + EditEdge* nearest,*eed; + short event,val,choosing=1,cancel=0,dist,cuthalf = 0; + + while(choosing){ + getmouseco_areawin(mval); if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) { mvalo[0] = mval[0]; @@ -158,139 +214,12 @@ void vertex_loop_select() dist= 50; nearest = findnearestedge(&dist); // returns actual distance in dist - - scrarea_do_windraw(curarea); // after findnearestedge, backbuf! - - if (nearest && edgeFaces(nearest)==2) { - for(search = em->edges.first;search;search=search->next) - search->f &= ~32; - - compEdge = startEdge = nearest; - nearest->f |= 32; - curEdge = 0; - v1 = startEdge->v1; - v2 = startEdge->v2; - looking = 1; - while(looking){ - if(protect++ > numEdges) break; - if(edgeFaces(compEdge) != 2) break; - /*Find Edges that have v1*/ - edgeValCount = -1; - EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL; - - for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){ - if(valSearch->v1 == v1 || valSearch->v2 == v1){ - if(valSearch != compEdge){ - if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){ - if(edgeFaces(valSearch) == 2){ - edgeValCount++; - EdgeVal[edgeValCount] = valSearch; - } - } - } - } - if(edgeValCount == 3)break; - } - /* Check that there was a valance of 4*/ - if(edgeValCount != 2){ - noloop = 1; - looking = 0; - break; - } - else{ - /* There were 3 edges, so find the one that does not share the previous edge */ - for(i=0;i<3;i++){ - if(sharesFace(compEdge,EdgeVal[i]) == 0){ - /* We went all the way around the loop */ - if(EdgeVal[i] == nearest){ - looking = 0; - looped = 1; - break; - } - else{ - /* we are still in the loop, so add the next edge*/ - curEdge++; - EdgeVal[i]->f |= 32; - compEdge = EdgeVal[i]; - if(compEdge->v1 == v1) - v1 = compEdge->v2; - else - v1 = compEdge->v1; - } - } - } - } - } - compEdge = nearest; - looking = 1; - protect = 0; - while(looking/* && !looped*/){ - if(protect++ > numEdges) break; - if(edgeFaces(compEdge) != 2) break; - /*Find Edges that have v1*/ - edgeValCount = -1; - EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL; - - for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){ - if(valSearch->v1 == v2 || valSearch->v2 == v2){ - if(valSearch != compEdge){ - if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){ - if(edgeFaces(valSearch) == 2){ - edgeValCount++; - EdgeVal[edgeValCount] = valSearch; - } - } - } - } - if(edgeValCount == 3)break; - } - /* Check that there was a valance of 4*/ - if(edgeValCount != 2){ - noloop = 1; - looking = 0; - break; - } - else{ - /* There were 3 edges, so find the one that does not share the previous edge */ - for(i=0;i<3;i++){ - if(sharesFace(compEdge,EdgeVal[i]) == 0){ - /* We went all the way around the loop */ - if(EdgeVal[i] == nearest){ - looking = 0; - looped = 1; - break; - } - else{ - /* we are still in the loop, so add the next edge*/ - curEdge++; - EdgeVal[i]->f |= 32; - compEdge = EdgeVal[i]; - if(compEdge->v1 == v2) - v2 = compEdge->v2; - else - v2 = compEdge->v1; - } - } - } - } - } - /* set up for opengl drawing in the 3d window */ - persp(PERSP_VIEW); - glPushMatrix(); - mymultmatrix(G.obedit->obmat); - glColor3ub(0, 255, 255); - for(search = em->edges.first;search;search= search->next){ - if(search->f & 32){ - glBegin(GL_LINES); - glVertex3f(search->v1->co[0],search->v1->co[1],search->v1->co[2]); - glVertex3f(search->v2->co[0],search->v2->co[1],search->v2->co[2]); - glEnd(); - } - } - - glPopMatrix(); - } + scrarea_do_windraw(curarea); // after findnearestedge, backbuf! + /* Need to figure preview */ + if(nearest){ + edgering_sel(nearest, 0, numcuts); + } screen_swapbuffers(); /* backbuffer refresh for non-apples (no aux) */ @@ -300,14 +229,16 @@ void vertex_loop_select() } #endif } - else PIL_sleep_ms(10); // idle - + else PIL_sleep_ms(10); // idle while(qtest()) { val=0; event= extern_qread(&val); if(val && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE)) { + if(event == MIDDLEMOUSE){ + cuthalf = 1; + } if (nearest==NULL) cancel = 1; choosing=0; @@ -319,65 +250,90 @@ void vertex_loop_select() cancel = 1; break; } - if(val && (event==BKEY && G.qual==LR_ALTKEY )) - { - - SetBlenderCursor(SYSCURSOR); - loopoperations(LOOP_SELECT); - return; - } - } - } - if(!cancel){ - /* If this is a unmodified select, clear the selection */ - - /* XXX note that !1 is 0, so it not only clears bit 1 (ton) */ - if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){ - for(search = em->edges.first;search;search= search->next){ - search->v1->f &= !1; - search->v2->f &= !1; - } - EM_clear_flag_all(SELECT); /* XXX probably that's sufficient */ - } - /* Alt was not pressed, so add to the selection */ - if(!(G.qual & LR_ALTKEY)){ - for(search = em->edges.first;search;search= search->next){ - if(search->f & 32){ - search->v1->f |= 1; - search->v2->f |= 1; - } - search->f &= ~32; + if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE)) + { + numcuts++; + mvalo[0] = 0;mvalo[1] = 0; + break; } - /* XXX this will correctly flush */ - } - /* alt was pressed, so subtract from the selection */ - else - { - /* XXX this doesnt flush correct in face select mode */ - for(search = em->edges.first;search;search= search->next){ - if(search->f & 32){ - search->v1->f &= !1; - search->v2->f &= !1; - EM_select_edge(search, 0); // the call to deselect edge - } - search->f &= ~32; + if(val && (event==PADMINUS || event==WHEELDOWNMOUSE)) + { + if(numcuts > 1){ + numcuts--; + mvalo[0] = 0;mvalo[1] = 0; + break; + } } - } - - EM_select_flush(); // flushes vertex -> edge -> face selection - - countall(); - - BIF_undo_push("Select Vertex Loop"); - } - - addqueue(curarea->win, REDRAW, 1); - SetBlenderCursor(SYSCURSOR); - return; + } + } + if(cancel){ + return; + } + /* clean selection */ + for(eed=em->edges.first; eed; eed = eed->next){ + EM_select_edge(eed,0); + } + /* select edge ring */ + edgering_sel(nearest, 1, 0); + + /* now cut the loops */ + esubdivideflag(SELECT,0,0,numcuts,1); + + force_draw(0); + makeDispList(G.obedit); + scrarea_queue_winredraw(curarea); + + /* if this was a single cut, enter edgeslide mode */ + if(numcuts == 1){ + if(cuthalf) + EdgeSlide(1,0.0); + else + EdgeSlide(0,0.0); + } + + return; } -/* *********** END LOOP SELECT ********** */ +/* *************** LOOP SELECT ************* */ + +static short edgeFaces(EditEdge *e){ + EditMesh *em = G.editMesh; + EditFace *search=NULL; + short count = 0; + + search = em->faces.first; + while(search){ + if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) + count++; + search = search->next; + } + return count; +} + +/* this utility function checks to see if 2 edit edges share a face, + returns 1 if they do + returns 0 if they do not, or if the function is passed the same edge 2 times +*/ +short sharesFace(EditEdge* e1, EditEdge* e2) +{ + EditMesh *em = G.editMesh; + EditFace *search=NULL; + search = em->faces.first; + if (e1 == e2){ + return 0 ; + } + while(search){ + if( + ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) && + ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2)) + ) { + return 1; + } + search = search->next; + } + return 0; +} /* ***************** TRAIL ************************ @@ -549,6 +505,7 @@ void KnifeSubdivide(char mode) CutCurve *curve; EditEdge *eed; Window *win; + short numcuts=1; if (G.obedit==0) return; @@ -558,11 +515,15 @@ void KnifeSubdivide(char mode) } if (mode==KNIFE_PROMPT) { - short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2"); + short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2|Multicut%x3"); if(val<1) return; - mode= val; // warning, mode is char, pupmenu returns -1 with ESC + mode = val; // warning, mode is char, pupmenu returns -1 with ESC } + if(mode == KNIFE_MULTICUT) { + if(button(&numcuts, 2, 128, "Number of Cuts:")==0) return; + } + calc_meshverts_ext(); /*Update screen coords for current window */ /* Set a knife cursor here */ @@ -591,9 +552,10 @@ void KnifeSubdivide(char mode) eed= eed->next; } - if (mode==1) subdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD); - else if (mode==2) subdivideflag(1, 0, B_KNIFE); - + if (mode==KNIFE_EXACT) esubdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD,1,0); + else if (mode==KNIFE_MIDPOINT) esubdivideflag(1, 0, B_KNIFE,1,0); + else if (mode==KNIFE_MULTICUT) esubdivideflag(1, 0, B_KNIFE,numcuts,0); + eed=em->edges.first; while(eed){ eed->f2=0; @@ -718,1103 +680,26 @@ short seg_intersect(EditEdge *e, CutCurve *c, int len){ return(isect); } -/* ******************** LOOP ******************************************* */ - -/* XXX: this loop function is totally out of control! - can be half the code, and using structured functions (ton) */ - -/* -functionality: various loop functions -parameters: mode tells the function what it should do with the loop: - LOOP_SELECT = select - LOOP_CUT = cut in half -*/ - -void loopoperations(char mode) -{ - EditMesh *em = G.editMesh; - EditVert* look = NULL; - EditEdge *start, *eed, *opposite,*currente, *oldstart; - EditEdge **tagged = NULL,**taggedsrch = NULL,*close; - EditFace *efa,**percentfacesloop = NULL, *currentvl, *formervl; - short lastface=0, foundedge=0, c=0, tri=0, side=1, totface=0, searching=1, event=0, noface=1; - short skip,nextpos,percentfaces, dist=50; - - int i=0,ect=0,j=0,k=0,cut,smooth,timesthrough=0,inset = 0; - - float percentcut, outcut; - - char mesg[100]; - - if ((G.obedit==0) || (em->faces.first==0)) return; - - SetBlenderCursor(BC_VLOOPCURSOR); - - /* Clear flags */ - for(eed=em->edges.first; eed; eed=eed->next) eed->f2= 0; - for(efa= em->faces.first; efa; efa=efa->next) efa->f1= 0; - - start=NULL; - oldstart=NULL; - - while(searching){ - - /* reset variables */ - start=eed=opposite=currente=0; - efa=currentvl=formervl=0; - side=noface=1; - lastface=foundedge=c=tri=totface=0; - - //start=findnearestvisibleedge(); - dist= 50; - start= findnearestedge(&dist); - - /* used flags in the code: - vertex->f & 2: in findnearestvisibleedge - edge->f2 : subdiv codes - efa->f1 : subdiv codes - */ - - /* If the edge doesn't belong to a face, it's not a valid starting edge */ - /* and only accept starting edge if it is part of at least one visible face */ - if(start){ - start->f2 |= 16; - efa=em->faces.first; - while(efa){ - /* since this edge is on the face, check if the face is hidden */ - if( efa->h==0 ){ - if(efa->e1->f2 & 16){ - noface=0; - efa->e1->f2 &= ~16; - } - else if(efa->e2->f2 & 16){ - noface=0; - efa->e2->f2 &= ~16; - } - else if(efa->e3->f2 & 16){ - noface=0; - efa->e3->f2 &= ~16; - } - else if(efa->e4 && (efa->e4->f2 & 16)){ - noface=0; - efa->e4->f2 &= ~16; - } - } - efa=efa->next; - } - } - - /* Did we find anything that is selectable? */ - if(start && !noface && (oldstart==NULL || start!=oldstart)){ - - /* If we stay in the neighbourhood of this edge, we don't have to recalculate the loop everytime*/ - oldstart=start; - - /* Clear flags */ - for(eed=em->edges.first; eed; eed=eed->next){ - eed->f2 &= ~(2|4|8|32|64); - eed->v1->f &= ~(2|8|16); // xxxx - eed->v2->f &= ~(2|8|16); - } - - for(efa= em->faces.first; efa; efa=efa->next){ - efa->f1 &= ~(4|8); - totface++; - } - - /* Tag the starting edge */ - start->f2 |= (2|4|8|64); - start->v1->f |= 2; /* xxxx */ - start->v2->f |= 2; - - currente=start; - - /*-----Limit the Search----- */ - while(!lastface && c<totface+1){ - - /*----------Get Loop------------------------*/ - tri=foundedge=lastface=0; - efa= em->faces.first; - while(efa && !foundedge && !tri){ - - if(!(efa->v4)){ /* Exception for triangular faces */ - - if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2) & 2){ - if(!(efa->f1 & 4)){ - tri=1; - currentvl=efa; - if(side==1) efa->f1 |= 4; - } - } - } - else{ - - if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2 | efa->e4->f2) & 2){ - - if(c==0){ /* just pick a face, doesn't matter wich side of the edge we go to */ - if(!(efa->f1 & 4)){ - - if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){ // xxxxx - if(efa->e1->h==0){ - opposite=efa->e1; - foundedge=1; - } - } - else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){ // xxxx - if(efa->e2->h==0){ - opposite=efa->e2; - foundedge=1; - } - } - else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){ - if(efa->e3->h==0){ - opposite=efa->e3; - foundedge=1; - } - } - else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){ - if(efa->e4->h==0){ - opposite=efa->e4; - foundedge=1; - } - } - - if(foundedge){ - currentvl=efa; - formervl=efa; - - /* mark this side of the edge so we know in which direction we went */ - if(side==1) efa->f1 |= 4; - } - } - } - else { - if(efa!=formervl){ /* prevent going backwards in the loop */ - - if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){ - if(efa->e1->h==0){ - opposite=efa->e1; - foundedge=1; - } - } - else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){ - if(efa->e2->h==0){ - opposite=efa->e2; - foundedge=1; - } - } - else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){ - if(efa->e3->h==0){ - opposite=efa->e3; - foundedge=1; - } - } - else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){ - if(efa->e4->h==0){ - opposite=efa->e4; - foundedge=1; - } - } - - currentvl=efa; - } - } - } - } - efa=efa->next; - } - /*----------END Get Loop------------------------*/ - - - /*----------Decisions-----------------------------*/ - if(foundedge){ - /* mark the edge and face as done */ - currente->f2 |= 8; - currentvl->f1 |= 8; - - if(opposite->f2 & 4) lastface=1; /* found the starting edge! close loop */ - else{ - /* un-set the testflags */ - currente->f2 &= ~2; - currente->v1->f &= ~2; // xxxx - currente->v2->f &= ~2; - - /* set the opposite edge to be the current edge */ - currente=opposite; - - /* set the current face to be the FORMER face (to prevent going backwards in the loop) */ - formervl=currentvl; - - /* set the testflags */ - currente->f2 |= 2; - currente->v1->f |= 2; // xxxx - currente->v2->f |= 2; - } - c++; - } - else{ - /* un-set the testflags */ - currente->f2 &= ~2; - currente->v1->f &= ~2; // xxxx - currente->v2->f &= ~2; - - /* mark the edge and face as done */ - currente->f2 |= 8; - currentvl->f1 |= 8; - - - - /* is the the first time we've ran out of possible faces? - * try to start from the beginning but in the opposite direction go as far as possible - */ - if(side==1){ - if(tri)tri=0; - currente=start; - currente->f2 |= 2; - currente->v1->f |= 2; // xxxx - currente->v2->f |= 2; - side++; - c=0; - } - else lastface=1; - } - /*----------END Decisions-----------------------------*/ - - } - /*-----END Limit the Search----- */ - - - /*------------- Preview lines--------------- */ - - /* uses callback mechanism to draw it all in current area */ - scrarea_do_windraw(curarea); - - /* set window matrix to perspective, default an area returns with buttons transform */ - persp(PERSP_VIEW); - /* make a copy, for safety */ - glPushMatrix(); - /* multiply with the object transformation */ - mymultmatrix(G.obedit->obmat); - - glColor3ub(255, 255, 0); - - if(mode==LOOP_SELECT){ - efa= em->faces.first; - while(efa){ - if(efa->f1 & 8){ - - if(!(efa->e1->f2 & 8)){ - glBegin(GL_LINES); - glVertex3fv(efa->e1->v1->co); - glVertex3fv(efa->e1->v2->co); - glEnd(); - } - - if(!(efa->e2->f2 & 8)){ - glBegin(GL_LINES); - glVertex3fv(efa->e2->v1->co); - glVertex3fv(efa->e2->v2->co); - glEnd(); - } - - if(!(efa->e3->f2 & 8)){ - glBegin(GL_LINES); - glVertex3fv(efa->e3->v1->co); - glVertex3fv(efa->e3->v2->co); - glEnd(); - } - - if(efa->e4){ - if(!(efa->e4->f2 & 8)){ - glBegin(GL_LINES); - glVertex3fv(efa->e4->v1->co); - glVertex3fv(efa->e4->v2->co); - glEnd(); - } - } - } - efa=efa->next; - } - } - - if(mode==LOOP_CUT){ - efa= em->faces.first; - while(efa){ - if(efa->f1 & 8){ - float cen[2][3]; - int a=0; - - efa->v1->f &= ~8; // xxx - efa->v2->f &= ~8; - efa->v3->f &= ~8; - if(efa->v4)efa->v4->f &= ~8; - - if(efa->e1->f2 & 8){ - cen[a][0]= (efa->e1->v1->co[0] + efa->e1->v2->co[0])/2.0; - cen[a][1]= (efa->e1->v1->co[1] + efa->e1->v2->co[1])/2.0; - cen[a][2]= (efa->e1->v1->co[2] + efa->e1->v2->co[2])/2.0; - - efa->e1->v1->f |= 8; // xxx - efa->e1->v2->f |= 8; - - a++; - } - if((efa->e2->f2 & 8) && a!=2){ - cen[a][0]= (efa->e2->v1->co[0] + efa->e2->v2->co[0])/2.0; - cen[a][1]= (efa->e2->v1->co[1] + efa->e2->v2->co[1])/2.0; - cen[a][2]= (efa->e2->v1->co[2] + efa->e2->v2->co[2])/2.0; - - efa->e2->v1->f |= 8; // xxx - efa->e2->v2->f |= 8; - - a++; - } - if((efa->e3->f2 & 8) && a!=2){ - cen[a][0]= (efa->e3->v1->co[0] + efa->e3->v2->co[0])/2.0; - cen[a][1]= (efa->e3->v1->co[1] + efa->e3->v2->co[1])/2.0; - cen[a][2]= (efa->e3->v1->co[2] + efa->e3->v2->co[2])/2.0; - - efa->e3->v1->f |= 8; // xxx - efa->e3->v2->f |= 8; - - a++; - } - - if(efa->e4){ - if((efa->e4->f2 & 8) && a!=2){ - cen[a][0]= (efa->e4->v1->co[0] + efa->e4->v2->co[0])/2.0; - cen[a][1]= (efa->e4->v1->co[1] + efa->e4->v2->co[1])/2.0; - cen[a][2]= (efa->e4->v1->co[2] + efa->e4->v2->co[2])/2.0; - - efa->e4->v1->f |= 8; // xxx - efa->e4->v2->f |= 8; - - a++; - } - } - else{ /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */ - if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx - cen[a][0]= efa->v1->co[0]; - cen[a][1]= efa->v1->co[1]; - cen[a][2]= efa->v1->co[2]; - a++; - } - else if(!(efa->v2->f & 8) && efa->v2->h==0){ - cen[a][0]= efa->v2->co[0]; - cen[a][1]= efa->v2->co[1]; - cen[a][2]= efa->v2->co[2]; - a++; - } - else if(!(efa->v3->f & 8) && efa->v3->h==0){ - cen[a][0]= efa->v3->co[0]; - cen[a][1]= efa->v3->co[1]; - cen[a][2]= efa->v3->co[2]; - a++; - } - } - - if(a==2){ - glBegin(GL_LINES); - - glVertex3fv(cen[0]); - glVertex3fv(cen[1]); - - glEnd(); - } - } - efa=efa->next; - } - - eed=em->edges.first; - while(eed){ - if(eed->f2 & 64){ - glBegin(GL_LINES); - glColor3ub(200, 255, 200); - glVertex3fv(eed->v1->co); - glVertex3fv(eed->v2->co); - glEnd(); - eed=0; - }else{ - eed = eed->next; - } - } - } - - /* restore matrix transform */ - glPopMatrix(); - - headerprint("LMB to confirm, RMB to cancel"); - - /* this also verifies other area/windows for clean swap */ - screen_swapbuffers(); - - /* backbuffer refresh for non-apples (no aux) */ -#ifndef __APPLE__ - if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) { - backdrawview3d(0); - } -#endif - - /*--------- END Preview Lines------------*/ - - }/*if(start!=NULL){ */ - else PIL_sleep_ms(10); // idle - - while(qtest()) { - unsigned short val=0; - event= extern_qread(&val); /* extern_qread stores important events for the mainloop to handle */ - - /* val==0 on key-release event */ - if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY || event == MIDDLEMOUSE)){ - searching=0; - } - } - - }/*while(event!=ESCKEY && event!=RIGHTMOUSE && event!=LEFTMOUSE && event!=RETKEY){*/ - - /*----------Select Loop------------*/ - if(mode==LOOP_SELECT && start!=NULL && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE || event == BKEY)){ - - /* If this is a unmodified select, clear the selection */ - if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){ - for(efa= em->faces.first;efa;efa=efa->next){ - EM_select_face(efa, 0); // and this is correct deselect face - } - } - /* Alt was not pressed, so add to the selection */ - if(!(G.qual & LR_ALTKEY)){ - for(efa= em->faces.first;efa;efa=efa->next){ - if(efa->f1 & 8){ - EM_select_face(efa, 1); // and this is correct select face - } - } - } - /* alt was pressed, so subtract from the selection */ - else - { - for(efa= em->faces.first;efa;efa=efa->next){ - if(efa->f1 & 8){ - EM_select_face(efa, 0); // this is correct deselect face - } - } - } - - } - /*----------END Select Loop------------*/ - - /*----------Cut Loop---------------*/ - if(mode==LOOP_CUT && start!=NULL && (event==LEFTMOUSE || event==RETKEY)){ - - /* count the number of edges in the loop */ - for(eed=em->edges.first; eed; eed = eed->next){ - if(eed->f2 & 8) - ect++; - } - - tagged = MEM_mallocN(ect*sizeof(EditEdge*), "tagged"); - taggedsrch = MEM_mallocN(ect*sizeof(EditEdge*), "taggedsrch"); - for(i=0;i<ect;i++) - { - tagged[i] = NULL; - taggedsrch[i] = NULL; - } - ect = 0; - for(eed=em->edges.first; eed; eed = eed->next){ - if(eed->f2 & 8) - { - if(eed->h==0){ - eed->v1->f |= SELECT; - eed->v2->f |= SELECT; - eed->f |= SELECT; - tagged[ect] = eed; - eed->f2 &= ~(32); - ect++; - } - } - } - taggedsrch[0] = tagged[0]; - - while(timesthrough < 2) - { - i=0; - while(i < ect){/*Look at the members of the search array to line up cuts*/ - if(taggedsrch[i]==NULL)break; - for(j=0;j<ect;j++){ /*Look through the list of tagged verts for connected edges*/ - int addededge = 0; - if(taggedsrch[i]->f2 & 32) /*If this edgee is marked as flipped, use vert 2*/ - look = taggedsrch[i]->v2; - else /*else use vert 1*/ - look = taggedsrch[i]->v1; - - if(taggedsrch[i] == tagged[j]) - continue; /*If we are looking at the same edge, skip it*/ - - skip = 0; - for(k=0;k<ect;k++) { - if(taggedsrch[k] == NULL) /*go to empty part of search list without finding*/ - break; - if(tagged[j] == taggedsrch[k]){ /*We found a match already in the list*/ - skip = 1; - break; - } - } - if(skip) - continue; - nextpos = 0; - if(findedgelist(look,tagged[j]->v2)){ - while(nextpos < ect){ /*Find the first open spot in the search array*/ - if(taggedsrch[nextpos] == NULL){ - taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/ - taggedsrch[nextpos]->f2 |= 32; - addededge = 1; - break; - } - else - nextpos++; - } - } /* End else if connected to vert 2*/ - else if(findedgelist(look,tagged[j]->v1)){ /*If our vert is connected to vert 1 */ - while(nextpos < ect){ /*Find the first open spot in the search array */ - if(taggedsrch[nextpos] == NULL){ - taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/ - addededge = 1; - break; - } - else - nextpos++; - } - } - - if(addededge) - { - break; - } - }/* End Outer For (j)*/ - i++; - } /* End while(j<ect)*/ - timesthrough++; - } /*end while timesthrough */ - percentcut = 0.50; - searching = 1; - cut = 1; - smooth = 0; - close = NULL; - - - /* Count the Number of Faces in the selected loop*/ - percentfaces = 0; - for(efa= em->faces.first; efa ;efa=efa->next){ - if(efa->f1 & 8) - { - percentfaces++; - } - } - - /* create a dynamic array for those face pointers */ - percentfacesloop = MEM_mallocN(percentfaces*sizeof(EditFace*), "percentage"); - - /* put those faces in the array */ - i=0; - for(efa= em->faces.first; efa ;efa=efa->next){ - if(efa->f1 & 8) - { - percentfacesloop[i] = efa; - i++; - } - } - - while(searching){ - - /* For the % calculation */ - short mval[2]; - float labda, rc[2], len, slen=0.0; - float v1[2], v2[2], v3[2]; - - /*------------- Percent Cut Preview Lines--------------- */ - scrarea_do_windraw(curarea); - persp(PERSP_VIEW); - glPushMatrix(); - mymultmatrix(G.obedit->obmat); - glColor3ub(0, 255, 255); - - /*Put the preview lines where they should be for the percentage selected.*/ - - for(i=0;i<percentfaces;i++){ - efa = percentfacesloop[i]; - for(eed = em->edges.first; eed; eed=eed->next){ - if(eed->f2 & 64){ /* color the starting edge */ - glBegin(GL_LINES); - - glColor3ub(200, 255, 200); - glVertex3fv(eed->v1->co); - glVertex3fv(eed->v2->co); - - glEnd(); - - glPointSize(5); - glBegin(GL_POINTS); - glColor3ub(255,0,255); - - if(eed->f2 & 32) - glVertex3fv(eed->v2->co); - else - glVertex3fv(eed->v1->co); - glEnd(); - - - /*Get Starting Edge Length*/ - slen = sqrt((eed->v1->co[0]-eed->v2->co[0])*(eed->v1->co[0]-eed->v2->co[0])+ - (eed->v1->co[1]-eed->v2->co[1])*(eed->v1->co[1]-eed->v2->co[1])+ - (eed->v1->co[2]-eed->v2->co[2])*(eed->v1->co[2]-eed->v2->co[2])); - } - } - - if(!inset){ - glColor3ub(0,255,255); - if(efa->f1 & 8) - { - float cen[2][3]; - int a=0; - - efa->v1->f &= ~8; // xxx - efa->v2->f &= ~8; - efa->v3->f &= ~8; - if(efa->v4)efa->v4->f &= ~8; - - if(efa->e1->f2 & 8){ - float pct; - if(efa->e1->f2 & 32) - pct = 1-percentcut; - else - pct = percentcut; - cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (pct)); - cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (pct)); - cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (pct)); - efa->e1->v1->f |= 8; // xxx - efa->e1->v2->f |= 8; - a++; - } - if((efa->e2->f2 & 8) && a!=2) - { - float pct; - if(efa->e2->f2 & 32) - pct = 1-percentcut; - else - pct = percentcut; - cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (pct)); - cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (pct)); - cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (pct)); - - efa->e2->v1->f |= 8; // xxx - efa->e2->v2->f |= 8; - - a++; - } - if((efa->e3->f2 & 8) && a!=2){ - float pct; - if(efa->e3->f2 & 32) - pct = 1-percentcut; - else - pct = percentcut; - cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (pct)); - cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (pct)); - cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (pct)); - - efa->e3->v1->f |= 8; // xxx - efa->e3->v2->f |= 8; - - a++; - } - - if(efa->e4){ - if((efa->e4->f2 & 8) && a!=2){ - float pct; - if(efa->e4->f2 & 32) - pct = 1-percentcut; - else - pct = percentcut; - cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (pct)); - cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (pct)); - cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (pct)); - - efa->e4->v1->f |= 8; // xxx - efa->e4->v2->f |= 8; - - a++; - } - } - else { /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */ - if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx - cen[a][0]= efa->v1->co[0]; - cen[a][1]= efa->v1->co[1]; - cen[a][2]= efa->v1->co[2]; - a++; - } - else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx - cen[a][0]= efa->v2->co[0]; - cen[a][1]= efa->v2->co[1]; - cen[a][2]= efa->v2->co[2]; - a++; - } - else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx - cen[a][0]= efa->v3->co[0]; - cen[a][1]= efa->v3->co[1]; - cen[a][2]= efa->v3->co[2]; - a++; - } - } - - if(a==2){ - glBegin(GL_LINES); - - glVertex3fv(cen[0]); - glVertex3fv(cen[1]); - - glEnd(); - } - } - }/* end preview line drawing */ - else{ - glColor3ub(0,128,255); - if(efa->f1 & 8) - { - float cen[2][3]; - int a=0; - - efa->v1->f &= ~8; // xxx - efa->v2->f &= ~8; - efa->v3->f &= ~8; - if(efa->v4)efa->v4->f &= ~8; - - if(efa->e1->f2 & 8){ - float nlen,npct; - - nlen = sqrt((efa->e1->v1->co[0] - efa->e1->v2->co[0])*(efa->e1->v1->co[0] - efa->e1->v2->co[0])+ - (efa->e1->v1->co[1] - efa->e1->v2->co[1])*(efa->e1->v1->co[1] - efa->e1->v2->co[1])+ - (efa->e1->v1->co[2] - efa->e1->v2->co[2])*(efa->e1->v1->co[2] - efa->e1->v2->co[2])); - npct = (percentcut*slen)/nlen; - if(npct >= 1) npct = 1; - if(efa->e1->f2 & 32) npct = 1-npct; - - cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (npct)); - cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (npct)); - cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (npct)); - - efa->e1->f1 = 32768*(npct); - efa->e1->v1->f |= 8; // xxx - efa->e1->v2->f |= 8; - a++; - } - if((efa->e2->f2 & 8) && a!=2) - { - float nlen,npct; - - nlen = sqrt((efa->e2->v1->co[0] - efa->e2->v2->co[0])*(efa->e2->v1->co[0] - efa->e2->v2->co[0])+ - (efa->e2->v1->co[1] - efa->e2->v2->co[1])*(efa->e2->v1->co[1] - efa->e2->v2->co[1])+ - (efa->e2->v1->co[2] - efa->e2->v2->co[2])*(efa->e2->v1->co[2] - efa->e2->v2->co[2])); - npct = (percentcut*slen)/nlen; - if(npct >= 1) npct = 1; - if(efa->e2->f2 & 32) npct = 1-npct; - - cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (npct)); - cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (npct)); - cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (npct)); - - efa->e2->f1 = 32768*(npct); - efa->e2->v1->f |= 8; // xxx - efa->e2->v2->f |= 8; - a++; - } - if((efa->e3->f2 & 8) && a!=2){ - float nlen,npct; - - nlen = sqrt((efa->e3->v1->co[0] - efa->e3->v2->co[0])*(efa->e3->v1->co[0] - efa->e3->v2->co[0])+ - (efa->e3->v1->co[1] - efa->e3->v2->co[1])*(efa->e3->v1->co[1] - efa->e3->v2->co[1])+ - (efa->e3->v1->co[2] - efa->e3->v2->co[2])*(efa->e3->v1->co[2] - efa->e3->v2->co[2])); - npct = (percentcut*slen)/nlen; - if(npct >= 1) npct = 1; - if(efa->e3->f2 & 32) npct = 1-npct; - - cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (npct)); - cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (npct)); - cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (npct)); - - efa->e3->f1 = 32768*(npct); - efa->e3->v1->f |= 8; // xxx - efa->e3->v2->f |= 8; - a++; - } - - if(efa->e4){ - if((efa->e4->f2 & 8) && a!=2){ - float nlen,npct; - - nlen = sqrt((efa->e4->v1->co[0] - efa->e4->v2->co[0])*(efa->e4->v1->co[0] - efa->e4->v2->co[0])+ - (efa->e4->v1->co[1] - efa->e4->v2->co[1])*(efa->e4->v1->co[1] - efa->e4->v2->co[1])+ - (efa->e4->v1->co[2] - efa->e4->v2->co[2])*(efa->e4->v1->co[2] - efa->e4->v2->co[2])); - npct = (percentcut*slen)/nlen; - if(npct >= 1) npct = 1; - if(efa->e4->f2 & 32) npct = 1-npct; - - cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (npct)); - cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (npct)); - cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (npct)); - - efa->e4->f1 = 32768*(npct); - efa->e4->v1->f |= 8; // xxx - efa->e4->v2->f |= 8; - a++; - } - } - else { /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */ - if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx - cen[a][0]= efa->v1->co[0]; - cen[a][1]= efa->v1->co[1]; - cen[a][2]= efa->v1->co[2]; - a++; - } - else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx - cen[a][0]= efa->v2->co[0]; - cen[a][1]= efa->v2->co[1]; - cen[a][2]= efa->v2->co[2]; - a++; - } - else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx - cen[a][0]= efa->v3->co[0]; - cen[a][1]= efa->v3->co[1]; - cen[a][2]= efa->v3->co[2]; - a++; - } - } - - if(a==2){ - glBegin(GL_LINES); - - glVertex3fv(cen[0]); - glVertex3fv(cen[1]); - - glEnd(); - } - } - } - } - /* restore matrix transform */ - - glPopMatrix(); - - /*--------- END Preview Lines------------*/ - while(qtest()) - { - unsigned short val=0; - event= extern_qread(&val); /* extern_qread stores important events for the mainloop to handle */ - /* val==0 on key-release event */ - - if(val && (event==SKEY)) - { - if(smooth)smooth = 0; - else smooth = 1; - } - - if(val && (event==PKEY)) - { - if(inset)inset = 0; - else inset = 1; - } - - if(val && (event==FKEY)) - { - int ct; - for(ct = 0; ct < ect; ct++){ - if(tagged[ct]->f2 & 32) - tagged[ct]->f2 &= ~32; - else - tagged[ct]->f2 |= 32; - } - } - - if(val && (event == MIDDLEMOUSE)) - { - cut = 2; - searching=0; - } - else if(val && (event==LEFTMOUSE || event==RETKEY)) - { - searching=0; - } - - if(val && (event==ESCKEY || event==RIGHTMOUSE )) - { - searching=0; - cut = 0; - } - - } - - /* window coords, no clip with vertices f2 flags set (not used) */ - calc_meshverts_ext_f2(); - - - /* Determine the % on wich the loop should be cut */ - getmouseco_areawin(mval); - v1[0]=(float)mval[0]; - v1[1]=(float)mval[1]; - - v2[0]=(float)start->v1->xs; - v2[1]=(float)start->v1->ys; - - v3[0]=(float)start->v2->xs; - v3[1]=(float)start->v2->ys; - - rc[0]= v3[0]-v2[0]; - rc[1]= v3[1]-v2[1]; - len= rc[0]*rc[0]+ rc[1]*rc[1]; - - labda= ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len; - - - if(labda<=0.0) labda=0.0; - else if(labda>=1.0)labda=1.0; - - percentcut=labda; - - if(start->f2 & 32) - percentcut = 1.0-percentcut; - - if(cut == 2){ - percentcut = 0.5; - } - - if (G.qual & LR_SHIFTKEY){ - - percentcut = (int)(percentcut*100.0)/100.0; - } - else if (G.qual & LR_CTRLKEY) - percentcut = (int)(percentcut*10.0)/10.0; - - outcut = (percentcut*100.0); - - /* Build the Header Line */ - - if(inset) - sprintf(mesg,"Cut: %0.2f%% ",slen*percentcut); - else - sprintf(mesg,"Cut: %0.2f%% ",outcut); - - - if(smooth) - sprintf(mesg,"%s| (f)lip side | (s)mooth on |",mesg); - else - sprintf(mesg,"%s| (f)lip side | (s)mooth off |",mesg); - - if(inset) - sprintf(mesg,"%s (p)roportional on ",mesg); - else - sprintf(mesg,"%s (p)roportional off",mesg); - - headerprint(mesg); - - screen_swapbuffers(); - } - - if(cut){ - /* Now that we have selected a cut %, mark the edges for cutting. */ - if(!inset){ - - for(eed = em->edges.first; eed; eed=eed->next){ - if(percentcut == 1.0) - percentcut = 0.9999; - else if(percentcut == 0.0) - percentcut = 0.0001; - if(eed->f2 & 8){ - if(eed->f2 & 32)/* Need to offset by a const. (0.5/32768) for consistant roundoff */ - eed->f1 = 32768*(1.0-percentcut - 0.0000153); - else - eed->f1 = 32768*(percentcut + 0.0000153); - } - } - } - /*-------------------------------------*/ - - if(smooth) - subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD | B_SMOOTH); /* B_KNIFE tells subdivide that edgeflags are already set */ - else - subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD); /* B_KNIFE tells subdivide that edgeflags are already set */ - - for(eed = em->edges.first; eed; eed=eed->next){ - if(eed->v1->f & 16) eed->v1->f |= SELECT; // - else eed->v1->f &= ~SELECT; - - if(eed->v2->f & 16) eed->v2->f |= SELECT; - else eed->v2->f &= ~SELECT; - - /* proper edge select state, needed because subdivide still doesnt do it OK */ - if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT; - else eed->f &= ~SELECT; - } - } - } - /*----------END Cut Loop-----------------------------*/ - - - - /* Clear flags */ - for(eed = em->edges.first; eed; eed=eed->next){ - eed->f2 &= ~(2|4|8|32|64); - eed->v1->f &= ~(2|16); // xxx - eed->v2->f &= ~(2|16); - } - - for(efa= em->faces.first; efa; efa=efa->next){ - efa->f1 &= ~(4|8); - - /* proper face select state, needed because subdivide still doesnt do it OK */ - if( faceselectedAND(efa, SELECT) ) efa->f |= SELECT; - else efa->f &= ~SELECT; - } - - // flushes vertex -> edge -> face selection - EM_select_flush(); - - countall(); - - if(tagged) - MEM_freeN(tagged); - if(taggedsrch) - MEM_freeN(taggedsrch); - if(percentfacesloop) - MEM_freeN(percentfacesloop); - - /* send event to redraw this window, does header too */ - SetBlenderCursor(SYSCURSOR); - addqueue(curarea->win, REDRAW, 1); - - /* should have check for cancelled (ton) */ - if(mode==LOOP_CUT) BIF_undo_push("Face Loop Subdivide"); - else if(mode==LOOP_SELECT) BIF_undo_push("Select Face Loop"); - -} - -/* ****************************** END LOOPOPERATIONS ********************** */ - void LoopMenu(){ /* Called by KKey */ short ret; - ret=pupmenu("Loop/Cut Menu %t|Face Loop Select %x1|Face Loop Cut %x2|" - "Knife (Exact) %x3|Knife (Midpoints)%x4|"); + ret=pupmenu("Loop/Cut Menu %t|Loop Cut (CTRL-R)%x2|" + "Knife (Exact) %x3|Knife (Midpoints)%x4|Knife (Multicut)%x5"); switch (ret){ - case 1: - loopoperations(LOOP_SELECT); - break; case 2: - loopoperations(LOOP_CUT); + CutEdgeloop(1); break; case 3: KnifeSubdivide(KNIFE_EXACT); break; case 4: KnifeSubdivide(KNIFE_MIDPOINT); + break; + case 5: + KnifeSubdivide(KNIFE_MULTICUT); + break; } } diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 8229f55449f..e09748cf2cc 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -974,6 +974,74 @@ static void edgeloop_select(EditEdge *starteed, int select) } } +/* + Almostly exactly the same code as faceloop select +*/ +static void edgering_select(EditEdge *startedge, int select){ + EditMesh *em = G.editMesh; + EditEdge *eed; + EditFace *efa; + int looking= 1; + + /* in eed->f1 we put the valence (amount of faces in edge) */ + /* in eed->f2 we put tagged flag as correct loop */ + /* in efa->f1 we put tagged flag as correct to select */ + + for(eed= em->edges.first; eed; eed= eed->next) { + eed->f1= 0; + eed->f2= 0; + } + for(efa= em->faces.first; efa; efa= efa->next) { + efa->f1= 0; + if(efa->h==0) { + efa->e1->f1++; + efa->e2->f1++; + efa->e3->f1++; + if(efa->e4) efa->e4->f1++; + } + } + + // tag startedge OK + startedge->f2= 1; + + while(looking) { + looking= 0; + + for(efa= em->faces.first; efa; efa= efa->next) { + if(efa->e4 && efa->f1==0) { // not done quad + if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok + + // if edge tagged, select opposing edge and mark face ok + if(efa->e1->f2) { + efa->e3->f2= 1; + efa->f1= 1; + looking= 1; + } + else if(efa->e2->f2) { + efa->e4->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e3->f2) { + efa->e1->f2= 1; + efa->f1= 1; + looking= 1; + } + if(efa->e4->f2) { + efa->e2->f2= 1; + efa->f1= 1; + looking= 1; + } + } + } + } + } + + /* (de)select the edges */ + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->f2) EM_select_edge(eed, select); + } +} /* ***************** MAIN MOUSE SELECTION ************** */ // just to have the functions nice together @@ -993,8 +1061,14 @@ static void mouse_mesh_loop(void) if(G.scene->selectmode & SCE_SELECT_FACE) { faceloop_select(eed, eed->f & SELECT); } - else { - edgeloop_select(eed, eed->f & SELECT); + else if(G.scene->selectmode & SCE_SELECT_EDGE) { + if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY)) + edgering_select(eed, eed->f & SELECT); + else if(G.qual & LR_ALTKEY) + edgeloop_select(eed, eed->f & SELECT); + } + else if(G.scene->selectmode & SCE_SELECT_VERTEX) { + edgeloop_select(eed, eed->f & SELECT); } /* frontbuffer draw of last selected only */ @@ -1696,7 +1770,7 @@ void editmesh_mark_seam(int clear) void Edge_Menu() { short ret; - ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4"); + ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5"); switch(ret) { @@ -1712,6 +1786,14 @@ void Edge_Menu() { case 4: edge_rotate_selected(1); break; + case 5: + EdgeSlide(0,0.0); + BIF_undo_push("EdgeSlide"); + break; + case 6: + CutEdgeloop(1); + BIF_undo_push("Loopcut New"); + break; } } diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 0f836e5f92f..142678e1369 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -25,7 +25,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Johnny Matthews. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -46,7 +46,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "MEM_guardedalloc.h" - +#include "BMF_Api.h" #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_meshdata_types.h" @@ -59,6 +59,8 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "BLI_arithb.h" #include "BLI_editVert.h" #include "BLI_rand.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -90,11 +92,12 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "editmesh.h" +#include "MTC_vectorops.h" /* local prototypes ---------------*/ void bevel_menu(void); - - +static void free_tagged_edgelist(EditEdge *eed); +static void free_tagged_facelist(EditFace *efa); /********* qsort routines *********/ @@ -1098,868 +1101,1068 @@ void fill_mesh(void) BIF_undo_push("Fill"); } +/*--------------Edge Based Subdivide------------------*/ +#define EDGENEW 2 +#define EDGEINNER 4 +static void alter_co(float* co,EditEdge *edge,float rad,int beauty){ + float vec1[3],vec2[3],fac,vec3[3],vec4[4],len,ang; + + if(rad > 0.0) { /* subdivide sphere */ + Normalise(co); + co[0]*= rad; + co[1]*= rad; + co[2]*= rad; + } + else if(rad< 0.0) { /* fractal subdivide */ + fac= rad* VecLenf(edge->v1->co, edge->v2->co); + vec1[0]= fac*(float)(0.5-BLI_drand()); + vec1[1]= fac*(float)(0.5-BLI_drand()); + vec1[2]= fac*(float)(0.5-BLI_drand()); + VecAddf(co, co, vec1); + } -/* ******************** SUBDIVIDE ********************************** */ + if(beauty & B_SMOOTH) { + // We are using the 2 ends of the edge vertex normals to + // determine the arc for the smooth + + // This figures our smooth radius for this edge + ang = acos(MTC_dot3Float(edge->v1->no,edge->v2->no))/2; + len = VecLenf(edge->v1->co,edge->v2->co)/2; + rad = len/sin(ang); + + // Now find the centerpoint of the smooth radius + // Need to calculate and add the offset. + // + // L1 = v1->co + a v1->no + // L2 = v2->co + b v2->no + // + // Assume they intersect + // + // Set equal + // + // v1->co + a v1->no = v2->co + b v2->no + // + // a v1->no = (v2->co - v1->co) + b v2->no + // + // Cross v2->no with both sides + // + // a (v1->no X v2->no) = (v2->co - v1->co) X v2->no + // a (vec1) = vec2 X v2->no + // a vec1 = vec3 + // a = length(vec3) / length(vec1) + // + // Now plug a into L1 = v1->co + a v1->no, this is intersection + + Crossf(vec1,edge->v1->no,edge->v2->no); + VecSubf(vec2,edge->v2->co,edge->v1->co); + Crossf(vec3,vec2,edge->v2->no); + len = VecLength(vec3)/VecLength(vec1); + + VECCOPY(vec4,edge->v1->no); + VecMulf(vec4,len); + VecAddf(vec1,edge->v1->co,vec4); + // vec1 *should* be the smooth center offset. -static void merge_weights(EditVert * vt, EditVert *vs ) -{ - MDeformWeight *newdw; - int i,j,done; - for (j=0; j<vs->totweight; j++){ - done=0; - /* Is vertex memeber of group */ - /* If so: Change its weight */ - for (i=0; i<vt->totweight; i++){ - if (vt->dw[i].def_nr == vs->dw[j].def_nr) - { /* taking the maximum makes it independant from order of occurance */ - if (vt->dw[i].weight < vs->dw[j].weight) vt->dw[i].weight = vs->dw[j].weight; - done=1; - break; - } - } - /* If not: Add the group and set its weight */ - if (!done){ - newdw = MEM_callocN (sizeof(MDeformWeight)*(vt->totweight+1), "deformWeight"); - if (vt->dw){ - memcpy (newdw, vt->dw, sizeof(MDeformWeight)*vt->totweight); - MEM_freeN (vt->dw); - } - vt->dw=newdw; - vt->dw[vt->totweight].weight=vs->dw[j].weight; - vt->dw[vt->totweight].def_nr=vs->dw[j].def_nr; - vt->totweight++; - } - } + //VecSubf(co,co,vec1); + + Normalise(co); + + co[0]*= rad; + co[1]*= rad; + co[2]*= rad; + + //VecAddf(co,co,vec1); + } } - -static void set_weights(EditVert * vt, EditVert *vs1,EditVert *vs2,EditVert *vs3,EditVert *vs4 ) -{ -/* -vt is a new generated vertex with empty deform group information -vs1..v4 are egde neighbours holding group information -so let the information ooze into the new one -*/ - if (vs1) merge_weights(vt,vs1); - if (vs2) merge_weights(vt,vs2); - if (vs3) merge_weights(vt,vs3); - if (vs4) merge_weights(vt,vs4); +static void flipvertarray(EditVert** arr, short size){ + EditVert *hold; + int i; + + for(i=0;i<size/2;i++){ + hold = arr[i]; + arr[i] = arr[size-i-1]; + arr[size-i-1] = hold; + } } +static void set_uv_vcol(EditFace *efa, float *co, float *uv, char *col) +{ + EditVert *v1,*v2,*v3,*v4; + float xn, yn, zn; + float t00, t01, t10, t11; + float detsh, u, v, l; + int fac; + short i, j; + char *cp0, *cp1, *cp2; + + /* define best projection of face XY, XZ or YZ */ + xn= fabs(efa->n[0]); + yn= fabs(efa->n[1]); + zn= fabs(efa->n[2]); + if(zn>=xn && zn>=yn) {i= 0; j= 1;} + else if(yn>=xn && yn>=zn) {i= 0; j= 2;} + else {i= 1; j= 2;} + + /* calculate u and v */ + v1= efa->v1; + v2= efa->v2; + v3= efa->v3; + + t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j]; + t10= v3->co[i]-v2->co[i]; t11= v3->co[j]-v2->co[j]; + + detsh= 1.0/(t00*t11-t10*t01); /* potential danger */ + t00*= detsh; t01*=detsh; + t10*=detsh; t11*=detsh; + + u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10; + v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01; + + /* btw; u and v range from -1 to 0 */ + + /* interpolate */ + l= 1.0+u+v; + + /* outside triangle? */ + if(efa->v4 && l < 0.0) { + /* do it all over, but now with vertex 2 replaced with 4 */ + + /* calculate u and v */ + v1= efa->v1; + v4= efa->v4; + v3= efa->v3; + + t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j]; + t10= v3->co[i]-v4->co[i]; t11= v3->co[j]-v4->co[j]; + + detsh= 1.0/(t00*t11-t10*t01); /* potential danger */ + t00*= detsh; t01*=detsh; + t10*=detsh; t11*=detsh; + + u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10; + v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01; + + /* btw; u and v range from -1 to 0 */ + + /* interpolate */ + l= 1.0+u+v; + uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[3][0]); + uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[3][1]); + + cp0= &(efa->tf.col[0]); + cp1= &(efa->tf.col[3]); + cp2= &(efa->tf.col[2]); + + for(i=0; i<4; i++) { + fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]); + col[i]= CLAMPIS(fac, 0, 255); + } + } else { + //new = l*vertex3_val - u*vertex1_val - v*vertex2_val; + uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[1][0]); + uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[1][1]); + + cp0= &(efa->tf.col[0]); + cp1= &(efa->tf.col[1]); + cp2= &(efa->tf.col[2]); + + for(i=0; i<4; i++) { + fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]); + col[i]= CLAMPIS(fac, 0, 255); + } + } +} +static void facecopy(EditFace *source,EditFace *target){ + + set_uv_vcol(source,target->v1->co,target->tf.uv[0],(char*)target->tf.col); + set_uv_vcol(source,target->v2->co,target->tf.uv[1],(char*)target->tf.col+1); + set_uv_vcol(source,target->v3->co,target->tf.uv[2],(char*)target->tf.col+2); + if(target->v4){ + set_uv_vcol(source,target->v4->co,target->tf.uv[3],target->tf.col+3); + } - -static unsigned int cpack_fact(unsigned int col1, unsigned int col2, float fact) -{ - char *cp1, *cp2, *cp; - unsigned int col=0; - float facti; - - facti=1-fact; /*result is (1-fact) * col1 and fact * col2 */ - - cp1= (char *)&col1; - cp2= (char *)&col2; - cp= (char *)&col; - - cp[0]= (char)(facti*cp1[0]+fact*cp2[0]); - cp[1]= (char)(facti*cp1[1]+fact*cp2[1]); - cp[2]= (char)(facti*cp1[2]+fact*cp2[2]); - cp[3]= (char)(facti*cp1[3]+fact*cp2[3]); - - return col; + target->mat_nr = source->mat_nr; + target->tf.flag = source->tf.flag; + target->tf.transp = source->tf.transp; + target->tf.mode = source->tf.mode; + target->tf.tile = source->tf.tile; + target->tf.unwrap = source->tf.unwrap; + target->tf.tpage = source->tf.tpage; + target->flag = source->flag; + } - -static void uv_half(float *uv, float *uv1, float *uv2) -{ - uv[0]= (uv1[0]+uv2[0])/2.0f; - uv[1]= (uv1[1]+uv2[1])/2.0f; - +static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts){ + EditEdge *cedge; + EditVert *v[4], **verts; + EditFace *hold; + short start, end, left, right, vertsize,i; + + v[0] = efa->v1; + v[1] = efa->v2; + v[2] = efa->v3; + v[3] = efa->v4; + + if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;} + else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;} + else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;} + else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;} + + // Point verts to the array of new verts for cedge + verts = BLI_ghash_lookup(gh, cedge); + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0] != v[start]){flipvertarray(verts,numcuts+2);} + end = (start+1)%4; + left = (start+2)%4; + right = (start+3)%4; + + /* + We should have something like this now + + end start + 3 2 1 0 + |---*---*---| + | | + | | + | | + ------------- + left right + + where start,end,left, right are indexes of EditFace->v1, etc (stored in v) + and 0,1,2... are the indexes of the new verts stored in verts + + We will fill this case like this or this depending on even or odd cuts + + |---*---*---| |---*---| + | / \ | | / \ | + | / \ | | / \ | + |/ \| |/ \| + ------------- --------- + */ + + // Make center face + if(vertsize % 2 == 0){ + hold = addfacelist(verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL); + }else{ + hold = addfacelist(verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL); + } + facecopy(efa,hold); + + // Make side faces + for(i=0;i<(vertsize-1)/2;i++){ + hold = addfacelist(verts[i],verts[i+1],v[right],NULL,NULL,NULL); + facecopy(efa,hold); + hold = addfacelist(verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL); + facecopy(efa,hold); + } } -static void uv_fact(float *uv, float *uv1, float *uv2, float fact) -{ - float facti = 1.0f - fact; - uv[0] = facti * uv1[0] + fact * uv2[0]; - uv[1] = facti * uv1[1] + fact * uv2[1]; +static void fill_tri_single(EditFace *efa, struct GHash *gh, int numcuts){ + EditEdge *cedge; + EditVert *v[3], **verts; + EditFace *hold; + short start, end, op, vertsize,i; + + v[0] = efa->v1; + v[1] = efa->v2; + v[2] = efa->v3; + + if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;} + else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;} + else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;} + + // Point verts to the array of new verts for cedge + verts = BLI_ghash_lookup(gh, cedge); + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0] != v[start]){flipvertarray(verts,numcuts+2);} + end = (start+1)%3; + op = (start+2)%3; + + /* + We should have something like this now + + end start + 3 2 1 0 + |---*---*---| + \ | + \ | + \ | + \ | + \ | + \ | + |op + + where start,end,op are indexes of EditFace->v1, etc (stored in v) + and 0,1,2... are the indexes of the new verts stored in verts + + We will fill this case like this or this depending on even or odd cuts + + 3 2 1 0 + |---*---*---| + \ \ \ | + \ \ \ | + \ \ \ | + \ \ \| + \ \\| + \ | + |op + */ + + // Make side faces + for(i=0;i<(vertsize-1);i++){ + hold = addfacelist(verts[i],verts[i+1],v[op],NULL,NULL,NULL); + facecopy(efa,hold); + } } -static void uv_quart(float *uv, float *uv1) -{ - uv[0]= (uv1[0]+uv1[2]+uv1[4]+uv1[6])/4.0f; - uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0f; +static void fill_quad_double_op(EditFace *efa, struct GHash *gh, int numcuts){ + EditEdge *cedge[2]; + EditVert *v[4], **verts[2]; + EditFace *hold; + short start, end, left, right, vertsize,i; + + v[0] = efa->v1; + v[1] = efa->v2; + v[2] = efa->v3; + v[3] = efa->v4; + + if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;} + else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;} + + // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] + verts[0] = BLI_ghash_lookup(gh, cedge[0]); + verts[1] = BLI_ghash_lookup(gh, cedge[1]); + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);} + end = (start+1)%4; + left = (start+2)%4; + right = (start+3)%4; + if(verts[1][0] != v[left]){flipvertarray(verts[1],numcuts+2);} + /* + We should have something like this now + + end start + 3 2 1 0 + |---*---*---| + | | + | | + | | + |---*---*---| + 0 1 2 3 + left right + + We will fill this case like this or this depending on even or odd cuts + + |---*---*---| + | | | | + | | | | + | | | | + |---*---*---| + */ + + // Make side faces + for(i=0;i<vertsize-1;i++){ + hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL); + if(i < vertsize-2){ + hold->e2->f2 |= EDGEINNER; + } + facecopy(efa,hold); + } } -static void face_pin_vertex(EditFace *efa, EditVert *vertex) -{ - if(efa->v1 == vertex) efa->tf.unwrap |= TF_PIN1; - else if(efa->v2 == vertex) efa->tf.unwrap |= TF_PIN2; - else if(efa->v3 == vertex) efa->tf.unwrap |= TF_PIN3; - else if(efa->v4 && vertex && efa->v4 == vertex) efa->tf.unwrap |= TF_PIN4; -} -static int vert_offset(EditFace *efa, EditVert *eve) -{ - if (efa->v1 == eve) - return 0; - if (efa->v2 == eve) - return 1; - if (efa->v3 == eve) - return 2; - if (efa->v4) - if (efa->v4 == eve) - return 3; - return -1; +static void fill_quad_double_adj(EditFace *efa, struct GHash *gh, int numcuts){ + EditEdge *cedge[2]; + EditVert *v[4], **verts[2]; + EditFace *hold; + short start, start2, vertsize,i; + + v[0] = efa->v1; + v[1] = efa->v2; + v[2] = efa->v3; + v[3] = efa->v4; + + if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;} + if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;} + if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;} + if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;} + + // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] + verts[0] = BLI_ghash_lookup(gh, cedge[0]); + verts[1] = BLI_ghash_lookup(gh, cedge[1]); + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);} + if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);} + /* + We should have something like this now + + end start + 3 2 1 0 + start2 0|---*---*---| + | | + 1* | + | | + 2* | + | | + end2 3|-----------| + + We will fill this case like this or this depending on even or odd cuts + |---*---*---| + | / / / | + * / / | + | / / | + * / | + | / | + |-----------| + */ + + // Make outside tris + hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL); + facecopy(efa,hold); + hold = addfacelist(verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL); + facecopy(efa,hold); + // Make side faces + + for(i=0;i<numcuts;i++){ + hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL); + facecopy(efa,hold); + } } -static void set_wuv(int tot, EditFace *efa, int v1, int v2, int v3, int v4, EditFace *efapin) -{ - /* this weird function only to be used for subdivide, the 'w' in the name has no meaning! */ - float *uv, uvo[4][2]; - unsigned int *col, colo[4], col1, col2; - int a, v; - - /* recover pinning */ - if(efapin){ - efa->tf.unwrap= 0; - if(efapin->tf.unwrap & TF_PIN1) face_pin_vertex(efa, efapin->v1); - if(efapin->tf.unwrap & TF_PIN2) face_pin_vertex(efa, efapin->v2); - if(efapin->tf.unwrap & TF_PIN3) face_pin_vertex(efa, efapin->v3); - if(efapin->tf.unwrap & TF_PIN4) face_pin_vertex(efa, efapin->v4); - } - - memcpy(uvo, efa->tf.uv, sizeof(uvo)); - uv= efa->tf.uv[0]; - memcpy(colo, efa->tf.col, sizeof(colo)); - col= efa->tf.col; - - /* - Quads and Triangles reuse the same cases numbers, so we migh as well do both in the - same loop. Especially now that the offsets are calculated and not hardcoded, it's - much easier to reduce the code size (and make it less buggy). - */ - - /* ******************************************** */ - /* */ - /* Numbers corespond to verts (corner points), */ - /* edge->vn's (center edges), the Center */ - /* And the quincunx points of a face */ - /* */ - /* ******************************************** */ - - /* ******************************************** */ - /* as shown here for quads: */ - /* */ - /* 2 ------- 5 -------- 1 */ - /* | \ / | \ / | */ - /* | 10 | 13 | */ - /* | / \ | / \ | */ - /* 6 ------- 9 -------- 8 */ - /* | \ / | \ / | */ - /* | 11 | 12 | */ - /* | / \ | / \ | */ - /* 3 ------- 7 -------- 4 */ - /* */ - /* ******************************************** */ - - /* ******************************************** */ - /* and for triangles: */ - /* 1 */ - /* / \ */ - /* / \ */ - /* 5 7 */ - /* / \ */ - /* / \ */ - /* 2 --------- 6 -------- 3 */ - /* */ - /* ******************************************** */ - - /* ******************************************** */ - /* */ - /* My talents in ascii arts are minimal so the */ - /* drawings don't show all possible subdivision */ - /* just draw them on paper if you need to. */ - /* */ - /* ******************************************** */ - - for(a=0; a<tot; a++, uv+=2, col++) { - /* edges that are subdivided, if any */ - EditEdge *e1 = NULL, *e2 = NULL; - - if(a==0) v= v1; - else if(a==1) v= v2; - else if(a==2) v= v3; - else v= v4; - - if(a==3 && v4==0) break; - - switch (v) { - /* Face corners, direct copy of the UVs and VCol */ - case 1: - case 2: - case 3: - case 4: - uv[0]= uvo[v-1][0]; - uv[1]= uvo[v-1][1]; - *col= colo[v-1]; - break; - /* Face sides (cutting an edge) */ - /* - set the edge pointer accordingly, it's used latter to do the - actual calculations of the new UV and VCol - */ - case 5: - e1 = efapin->e1; - break; - case 6: - e1 = efapin->e2; - break; - case 7: - e1 = efapin->e3; - break; - case 8: - e1 = efapin->e4; - break; - - /* The following applies to Quads only */ - - /* Quad middle, just used when subdividing a quad as a whole */ - /* (not knife nor loop cut) */ - /* UVs and VCol is just the average of the four corners */ - case 9: - uv_quart(uv, uvo[0]); - col1= cpack_fact(colo[1], colo[0], 0.5f); - col2= cpack_fact(colo[2], colo[3], 0.5f); - *col= cpack_fact(col1, col2, 0.5f); - break; - /* Quad corner cuts */ - /* only when two adjacent edges are subdivided (and no others) */ - /* Set both edge pointers accordingly, used later for calculations */ - case 10: // case test==3 in subdivideflag() - e1 = efapin->e1; - e2 = efapin->e2; - break; - case 11: // case of test==6 - e1 = efapin->e2; - e2 = efapin->e3; - break; - case 12: // case of test==12 - e1 = efapin->e3; - e2 = efapin->e4; - break; - case 13: // case of test==9 - e1 = efapin->e4; - e2 = efapin->e1; - break; - } - /* if splitting at least an edge */ - if (e1) { - float percent; - int off1, off2; - /* if splitting two edges */ - if (e2) { - float uv1[2], uv2[2]; - /* - UV and VCol is obtained by using the middle ground of the weighted - average for both edges (weighted with Percent cut flag). - In a nutshell, the average of the cuts on both edges. - */ - /* first cut */ - off1 = vert_offset(efapin, e1->v1); - off2 = vert_offset(efapin, e1->v2); - percent = e1->f1 / 32768.0f; - uv_fact(uv1, uvo[off1], uvo[off2], percent); - col1= cpack_fact(colo[off1], colo[off2], percent); - - /* second cut */ - off1 = vert_offset(efapin, e2->v1); - off2 = vert_offset(efapin, e2->v2); - percent = e2->f1 / 32768.0f; - uv_fact(uv2, uvo[off1], uvo[off2], percent); - col2= cpack_fact(colo[off1], colo[off1], percent); - - /* average the two */ - uv_half(uv, uv1, uv2); - *col= cpack_fact(col1, col2, 0.5f); - } - /* or only one */ - else { - /* - UV and VCol is obtained by using the weighted average - of both vertice (weighted with Percent cut flag). - */ - off1 = vert_offset(efapin, e1->v1); - off2 = vert_offset(efapin, e1->v2); - percent = e1->f1 / 32768.0f; - uv_fact(uv, uvo[off1], uvo[off2], percent); - *col= cpack_fact(colo[off1], colo[off2], percent); - } - } - } +static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts){ + EditEdge *cedge[2]; + EditVert *v[3], **verts[2]; + EditFace *hold; + short start, start2, vertsize,i; + + v[0] = efa->v1; + v[1] = efa->v2; + v[2] = efa->v3; + + if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;} + if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;} + if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;} + + // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] + verts[0] = BLI_ghash_lookup(gh, cedge[0]); + verts[1] = BLI_ghash_lookup(gh, cedge[1]); + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);} + if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);} + /* + We should have something like this now + + end start + 3 2 1 0 + start2 0|---*---*---| + | / + 1* / + | / + 2* / + | / + end2 3| + + We will fill this case like this or this depending on even or odd cuts + |---*---*---| + | / / / + * / / + | / / + * / + | / + | + */ + + // Make outside tri + hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL); + facecopy(efa,hold); + // Make side faces + + for(i=0;i<numcuts;i++){ + hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL); + facecopy(efa,hold); + } } -static EditVert *vert_from_number(EditFace *efa, int nr) -{ - switch(nr) { - case 0: - return 0; - case 1: - return efa->v1; - case 2: - return efa->v2; - case 3: - return efa->v3; - case 4: - return efa->v4; - case 5: - return efa->e1->vn; - case 6: - return efa->e2->vn; - case 7: - return efa->e3->vn; - case 8: - return efa->e4->vn; - } - - return NULL; +static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts){ + EditEdge *cedge[3]; + EditVert *v[4], **verts[3]; + EditFace *hold; + short start, start2, start3, vertsize, i, repeats; + + v[0] = efa->v1; + v[1] = efa->v2; + v[2] = efa->v3; + v[3] = efa->v4; + + if(!(efa->e1->f & SELECT)) { + cedge[0] = efa->e2; + cedge[1] = efa->e3; + cedge[2] = efa->e4; + start = 1;start2 = 2;start3 = 3; + } + if(!(efa->e2->f & SELECT)) { + cedge[0] = efa->e3; + cedge[1] = efa->e4; + cedge[2] = efa->e1; + start = 2;start2 = 3;start3 = 0; + } + if(!(efa->e3->f & SELECT)) { + cedge[0] = efa->e4; + cedge[1] = efa->e1; + cedge[2] = efa->e2; + start = 3;start2 = 0;start3 = 1; + } + if(!(efa->e4->f & SELECT)) { + cedge[0] = efa->e1; + cedge[1] = efa->e2; + cedge[2] = efa->e3; + start = 0;start2 = 1;start3 = 2; + } + // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] + verts[0] = BLI_ghash_lookup(gh, cedge[0]); + verts[1] = BLI_ghash_lookup(gh, cedge[1]); + verts[2] = BLI_ghash_lookup(gh, cedge[2]); + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} + if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);} + if(verts[2][0] != v[start3]){flipvertarray(verts[2],numcuts+2);} + /* + We should have something like this now + + start2 + 3 2 1 0 + start3 0|---*---*---|3 + | | + 1* *2 + | | + 2* *1 + | | + 3|-----------|0 start + + We will fill this case like this or this depending on even or odd cuts + there are a couple of differences. For odd cuts, there is a tri in the + middle as well as 1 quad at the bottom (not including the extra quads + for odd cuts > 1 + + For even cuts, there is a quad in the middle and 2 quads on the bottom + + they are numbered here for clarity + + 1 outer tris and bottom quads + 2 inner tri or quad + 3 repeating quads + + |---*---*---*---| + |1/ / \ \ 1| + |/ 3 / \ 3 \| + * / 2 \ * + | / \ | + |/ \ | + *---------------* + | 3 | + | | + *---------------* + | | + | 1 | + | | + |---------------| + + |---*---*---*---*---| + | 1/ / \ \ 1| + | / / \ \ | + |/ 3 / \ 3 \| + * / \ * + | / \ | + | / 2 \ | + |/ \| + *-------------------* + | | + | 3 | + | | + *-------------------* + | | + | 1 | + | | + *-------------------* + | | + | 1 | + | | + |-------------------| + + */ + + // Make outside tris + hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL); + facecopy(efa,hold); + hold = addfacelist(verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL); + facecopy(efa,hold); + // Make bottom quad + hold = addfacelist(verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL); + facecopy(efa,hold); + //If it is even cuts, add the 2nd lower quad + if(numcuts % 2 == 0){ + hold = addfacelist(verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL); + facecopy(efa,hold); + // Also Make inner quad + hold = addfacelist(verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL); + facecopy(efa,hold); + repeats = (numcuts / 2) -1; + } else { + // Make inner tri + hold = addfacelist(verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL); + facecopy(efa,hold); + repeats = ((numcuts+1) / 2)-1; + } + + // cuts for 1 and 2 do not have the repeating quads + if(numcuts < 3){repeats = 0;} + for(i=0;i<repeats;i++){ + //Make side repeating Quads + hold = addfacelist(verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL); + facecopy(efa,hold); + hold = addfacelist(verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL); + facecopy(efa,hold); + } + // Do repeating bottom quads + for(i=0;i<repeats;i++){ + if(numcuts % 2 == 1){ + hold = addfacelist(verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL); + } else { + hold = addfacelist(verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL); + } + facecopy(efa,hold); + } } -static void addface_subdiv(EditFace *efa, int val1, int val2, int val3, int val4, EditVert *eve, EditFace *efapin) -{ - EditFace *w; - EditVert *v1, *v2, *v3, *v4; - - if(val1>=9) v1= eve; - else v1= vert_from_number(efa, val1); - - if(val2>=9) v2= eve; - else v2= vert_from_number(efa, val2); - - if(val3>=9) v3= eve; - else v3= vert_from_number(efa, val3); - - if(val4>=9) v4= eve; - else v4= vert_from_number(efa, val4); - - w= addfacelist(v1, v2, v3, v4, efa, NULL); - if(w) { - if(efa->v4) set_wuv(4, w, val1, val2, val3, val4, efapin); - else set_wuv(3, w, val1, val2, val3, val4, efapin); - } +static void fill_quad_quadruple(EditFace *efa, struct GHash *gh, int numcuts,float rad,int beauty){ + EditVert **verts[4], ***innerverts; + short vertsize, i, j; + float co[3]; + EditFace *hold; + EditEdge temp; + // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] + verts[0] = BLI_ghash_lookup(gh, efa->e1); + verts[1] = BLI_ghash_lookup(gh, efa->e2); + verts[2] = BLI_ghash_lookup(gh, efa->e3); + verts[3] = BLI_ghash_lookup(gh, efa->e4); + + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);} + if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);} + if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);} + if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);} + /* + We should have something like this now + 1 + + 3 2 1 0 + 0|---*---*---|0 + | | + 1* *1 + 2 | | 4 + 2* *2 + | | + 3|---*---*---|3 + 3 2 1 0 + + 3 + // we will fill a 2 dim array of editvert*s to make filling easier + // the innervert order is shown + + 0 0---1---2---3 + | | | | + 1 0---1---2---3 + | | | | + 2 0---1---2---3 + | | | | + 3 0---1---2---3 + + */ + innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array"); + for(i=0;i<numcuts+2;i++){ + innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array"); + } + // first row is e1 last row is e3 + for(i=0;i<numcuts+2;i++){ + innerverts[0][i] = verts[0][(numcuts+1)-i]; + innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i]; + } + for(i=1;i<=numcuts;i++){ + innerverts[i][0] = verts[1][i]; + innerverts[i][numcuts+1] = verts[3][i]; + for(j=1;j<=numcuts;j++){ + co[0] = ((verts[1][i]->co[0] - verts[3][i]->co[0]) * (j /(float)(numcuts+1))) + verts[3][i]->co[0]; + co[1] = ((verts[1][i]->co[1] - verts[3][i]->co[1]) * (j /(float)(numcuts+1))) + verts[3][i]->co[1]; + co[2] = ((verts[1][i]->co[2] - verts[3][i]->co[2]) * (j /(float)(numcuts+1))) + verts[3][i]->co[2]; + + temp.v1 = innerverts[i][0]; + temp.v2 = innerverts[i][numcuts+1]; + + // Call alter co for things like fractal and smooth + alter_co(co,&temp,rad,beauty); + + innerverts[i][(numcuts+1)-j] = addvertlist(co); + + //VECCOPY(innerverts[i][(numcuts+1)-j]->no,nor); + + } + } + // Fill with faces + for(i=0;i<numcuts+1;i++){ + for(j=0;j<numcuts+1;j++){ + hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL); + hold->e1->f2 = EDGENEW; + hold->e2->f2 = EDGENEW; + hold->e3->f2 = EDGENEW; + hold->e4->f2 = EDGENEW; + facecopy(efa,hold); + } + } + // Clean up our dynamic multi-dim array + for(i=0;i<numcuts+2;i++){ + MEM_freeN(innerverts[i]); + } + MEM_freeN(innerverts); } -static float smoothperc= 0.0; - -static void smooth_subdiv_vec(float *v1, float *v2, float *n1, float *n2, float *vec) -{ - float len, fac, nor[3], nor1[3], nor2[3]; - - VecSubf(nor, v1, v2); - len= 0.5f*Normalise(nor); - - VECCOPY(nor1, n1); - VECCOPY(nor2, n2); - - /* cosine angle */ - fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ; - - vec[0]= fac*nor1[0]; - vec[1]= fac*nor1[1]; - vec[2]= fac*nor1[2]; - - /* cosine angle */ - fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ; - - vec[0]+= fac*nor2[0]; - vec[1]+= fac*nor2[1]; - vec[2]+= fac*nor2[2]; - - vec[0]*= smoothperc*len; - vec[1]*= smoothperc*len; - vec[2]*= smoothperc*len; +static void fill_tri_triple(EditFace *efa, struct GHash *gh, int numcuts,float rad,int beauty){ + EditVert **verts[3], ***innerverts; + short vertsize, i, j; + float co[3]; + EditFace *hold; + EditEdge temp; + + // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] + verts[0] = BLI_ghash_lookup(gh, efa->e1); + verts[1] = BLI_ghash_lookup(gh, efa->e2); + verts[2] = BLI_ghash_lookup(gh, efa->e3); + + //This is the index size of the verts array + vertsize = numcuts+2; + + // Is the original v1 the same as the first vert on the selected edge? + // if not, the edge is running the opposite direction in this face so flip + // the array to the correct direction + + if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);} + if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);} + if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);} + /* + We should have something like this now + 3 + + 3 2 1 0 + 0|---*---*---|3 + | / + 1 1* *2 + | / + 2* *1 2 + | / + 3|/ + 0 + + we will fill a 2 dim array of editvert*s to make filling easier + + 3 + + 0 0---1---2---3---4 + | / | / |/ | / + 1 0---1----2---3 + 1 | / | / | / + 2 0----1---2 2 + | / | / + |/ |/ + 3 0---1 + | / + |/ + 4 0 + + */ + + innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array"); + for(i=0;i<numcuts+2;i++){ + innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array"); + } + //top row is e3 backwards + for(i=0;i<numcuts+2;i++){ + innerverts[0][i] = verts[2][(numcuts+1)-i]; + } + + for(i=1;i<=numcuts+1;i++){ + //first vert is from e1, last is from e2 + innerverts[i][0] = verts[0][i]; + innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i]; + for(j=1;j<(numcuts+1)-i;j++){ + co[0] = ((verts[0][i]->co[0] - verts[1][(numcuts+1)-i]->co[0]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[0]; + co[1] = ((verts[0][i]->co[1] - verts[1][(numcuts+1)-i]->co[1]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[1]; + co[2] = ((verts[0][i]->co[2] - verts[1][(numcuts+1)-i]->co[2]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[2]; + + temp.v1 = innerverts[i][0]; + temp.v2 = innerverts[i][(numcuts+1)-i]; + + alter_co(co,&temp,rad,beauty); + + innerverts[i][((numcuts+1)-i)-j] = addvertlist(co); + //VECCOPY(innerverts[i][((numcuts+1)-i)-j]->no,nor); + } + } + + + // Now fill the verts with happy little tris :) + for(i=0;i<=numcuts+1;i++){ + for(j=0;j<(numcuts+1)-i;j++){ + //We always do the first tri + hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL); + hold->e1->f2 = EDGENEW; + hold->e2->f2 = EDGENEW; + hold->e3->f2 = EDGENEW; + facecopy(efa,hold); + //if there are more to come, we do the 2nd + if(j+1 <= numcuts-i){ + hold = addfacelist(innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL); + facecopy(efa,hold); + hold->e1->f2 = EDGENEW; + hold->e2->f2 = EDGENEW; + hold->e3->f2 = EDGENEW; + } + } + } + + // Clean up our dynamic multi-dim array + for(i=0;i<numcuts+2;i++){ + MEM_freeN(innerverts[i]); + } + MEM_freeN(innerverts); } -static void smooth_subdiv_quad(EditFace *efa, float *vec) -{ - - float nor1[3], nor2[3]; - float vec1[3], vec2[3]; - float cent[3]; - - /* vlr->e1->vn is new vertex inbetween v1 / v2 */ - - VecMidf(nor1, efa->v1->no, efa->v2->no); - Normalise(nor1); - VecMidf(nor2, efa->v3->no, efa->v4->no); - Normalise(nor2); - - smooth_subdiv_vec( efa->e1->vn->co, efa->e3->vn->co, nor1, nor2, vec1); - - VecMidf(nor1, efa->v2->no, efa->v3->no); - Normalise(nor1); - VecMidf(nor2, efa->v4->no, efa->v1->no); - Normalise(nor2); - - smooth_subdiv_vec( efa->e2->vn->co, efa->e4->vn->co, nor1, nor2, vec2); - - VecAddf(vec1, vec1, vec2); - - CalcCent4f(cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - VecAddf(vec, cent, vec1); +// This function takes an example edge, the current point to create and +// the total # of points to create, then creates the point and return the +// editvert pointer to it. +static EditVert *subdivideedgenum(EditEdge *edge,int curpoint,int totpoint,float rad,int beauty){ + float co[3]; + float percent; + EditVert *ev; + + if (beauty & (B_PERCENTSUBD) && totpoint == 1){ + percent=(float)(edge->f1)/32768.0f; + co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent+edge->v1->co[0]; + co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent+edge->v1->co[1]; + co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent+edge->v1->co[2]; + } else { + co[0] = (edge->v2->co[0]-edge->v1->co[0])*(curpoint/(float)(totpoint+1))+edge->v1->co[0]; + co[1] = (edge->v2->co[1]-edge->v1->co[1])*(curpoint/(float)(totpoint+1))+edge->v1->co[1]; + co[2] = (edge->v2->co[2]-edge->v1->co[2])*(curpoint/(float)(totpoint+1))+edge->v1->co[2]; + } + + alter_co(co,edge,rad,beauty); + ev = addvertlist(co); + ev->f = edge->v1->f; + + return ev; } -void subdivideflag(int flag, float rad, int beauty) +void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype) { - EditMesh *em = G.editMesh; - /* subdivide all with (vertflag & flag) */ - /* if rad>0.0 it's a 'sphere' subdivide */ - /* if rad<0.0 it's a fractal subdivide */ - extern float doublimit; - EditVert *eve; - EditEdge *eed, *e1, *e2, *e3, *e4, *nexted; - EditFace *efa, efapin; - float fac, vec[3], vec1[3], len1, len2, len3, percent; - short test; - - if(beauty & B_SMOOTH) { - short perc= 100; - - if(button(&perc, 10, 500, "Percentage:")==0) return; - - smoothperc= 0.292f*perc/100.0f; - } - - /* edgeflags */ - if((beauty & B_KNIFE)==0) { // knife option sets own flags - eed= em->edges.first; - while(eed) { - if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f2= flag; - else eed->f2= 0; - eed= eed->next; - } - } - - /* if beauty: test for area and clear edge flags of 'ugly' edges */ - if(beauty & B_BEAUTY) { - efa= em->faces.first; - while(efa) { - if( faceselectedAND(efa, flag) ) { - if(efa->v4) { - - /* area */ - len1= AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - if(len1 <= doublimit) { - efa->e1->f2 = 0; - efa->e2->f2 = 0; - efa->e3->f2 = 0; - efa->e4->f2 = 0; - } - else { - len1= VecLenf(efa->v1->co, efa->v2->co) + VecLenf(efa->v3->co, efa->v4->co); - len2= VecLenf(efa->v2->co, efa->v3->co) + VecLenf(efa->v1->co, efa->v4->co); - - if(len1 < len2) { - efa->e1->f2 = 0; - efa->e3->f2 = 0; - } - else if(len1 > len2) { - efa->e2->f2 = 0; - efa->e4->f2 = 0; - } - } - } - else { - /* area */ - len1= AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co); - if(len1 <= doublimit) { - efa->e1->f2 = 0; - efa->e2->f2 = 0; - efa->e3->f2 = 0; - } - else { - len1= VecLenf(efa->v1->co, efa->v2->co) ; - len2= VecLenf(efa->v2->co, efa->v3->co) ; - len3= VecLenf(efa->v3->co, efa->v1->co) ; - - if(len1<len2 && len1<len3) { - efa->e1->f2 = 0; - } - else if(len2<len3 && len2<len1) { - efa->e2->f2 = 0; - } - else if(len3<len2 && len3<len1) { - efa->e3->f2 = 0; - } - } - } - } - efa= efa->next; - } - } - - if(beauty & B_SMOOTH) { - - vertexnormals(0); /* no1*/ - - } - - /* make new normal and put in edge, clear flag! needed for face creation part below */ - eed= em->edges.first; - while(eed) { - if(eed->f2 & flag) { - /* for now */ - eed->h &= ~EM_FGON; - - /* Subdivide percentage is stored in 1/32768ths in eed->f1 */ - if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0f; - else { - eed->f1 = 32768 / 2; - percent=0.5f; - } - - vec[0]= (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0]; - vec[1]= (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1]; - vec[2]= (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2]; - - if(rad > 0.0) { /* subdivide sphere */ - Normalise(vec); - vec[0]*= rad; - vec[1]*= rad; - vec[2]*= rad; - } - else if(rad< 0.0) { /* fractal subdivide */ - fac= rad* VecLenf(eed->v1->co, eed->v2->co); - vec1[0]= fac*(float)(0.5-BLI_drand()); - vec1[1]= fac*(float)(0.5-BLI_drand()); - vec1[2]= fac*(float)(0.5-BLI_drand()); - VecAddf(vec, vec, vec1); - } - - if(beauty & B_SMOOTH) { - smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1); - VecAddf(vec, vec, vec1); - } - - eed->vn= addvertlist(vec); - eed->vn->f= eed->v1->f; - - } - else eed->vn= 0; - - eed->f2= 0; /* needed! */ - - eed= eed->next; - } - - /* test all faces for subdivide edges, there are 8 or 16 cases (ugh)! */ - - efa= em->faces.last; - while(efa) { - - efapin= *efa; /* make a copy of efa to recover uv pinning later */ - - if( faceselectedOR(efa, flag) ) { - /* for now */ - efa->fgonf= 0; - - e1= efa->e1; - e2= efa->e2; - e3= efa->e3; - e4= efa->e4; - - test= 0; - if(e1 && e1->vn) { - test+= 1; - e1->f2= 1; - /* add edges here, to copy correct edge data */ - eed= addedgelist(e1->v1, e1->vn, e1); - eed= addedgelist(e1->vn, e1->v2, e1); - set_weights(e1->vn, e1->v1,e1->v2,NULL,NULL); - } - if(e2 && e2->vn) { - test+= 2; - e2->f2= 1; - /* add edges here, to copy correct edge data */ - eed= addedgelist(e2->v1, e2->vn, e2); - eed= addedgelist(e2->vn, e2->v2, e2); - set_weights(e2->vn, e2->v1,e2->v2,NULL,NULL); - } - if(e3 && e3->vn) { - test+= 4; - e3->f2= 1; - /* add edges here, to copy correct edge data */ - eed= addedgelist(e3->v1, e3->vn, e3); - eed= addedgelist(e3->vn, e3->v2, e3); - set_weights(e3->vn, e3->v1,e3->v2,NULL,NULL); - } - if(e4 && e4->vn) { - test+= 8; - e4->f2= 1; - /* add edges here, to copy correct edge data */ - eed= addedgelist(e4->v1, e4->vn, e4); - eed= addedgelist(e4->vn, e4->v2, e4); - set_weights(e4->vn, e4->v1,e4->v2,NULL,NULL); - } - if(test) { - if(efa->v4==0) { /* All the permutations of 3 edges*/ - if((test & 3)==3) addface_subdiv(efa, 2, 2+4, 1+4, 0, 0, &efapin); - if((test & 6)==6) addface_subdiv(efa, 3, 3+4, 2+4, 0, 0, &efapin); - if((test & 5)==5) addface_subdiv(efa, 1, 1+4, 3+4, 0, 0, &efapin); - - if(test==7) { /* four new faces, old face renews */ - efa->v1= e1->vn; - efa->v2= e2->vn; - efa->v3= e3->vn; - set_wuv(3, efa, 1+4, 2+4, 3+4, 0, &efapin); - } - else if(test==3) { - addface_subdiv(efa, 1+4, 2+4, 3, 0, 0, &efapin); - efa->v2= e1->vn; - set_wuv(3, efa, 1, 1+4, 3, 0, &efapin); - } - else if(test==6) { - addface_subdiv(efa, 2+4, 3+4, 1, 0, 0, &efapin); - efa->v3= e2->vn; - set_wuv(3, efa, 1, 2, 2+4, 0, &efapin); - } - else if(test==5) { - addface_subdiv(efa, 3+4, 1+4, 2, 0, 0, &efapin); - efa->v1= e3->vn; - set_wuv(3, efa, 3+4, 2, 3, 0, &efapin); - } - else if(test==1) { - addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin); - efa->v2= e1->vn; - set_wuv(3, efa, 1, 1+4, 3, 0, &efapin); - } - else if(test==2) { - addface_subdiv(efa, 2+4, 3, 1, 0, 0, &efapin); - efa->v3= e2->vn; - set_wuv(3, efa, 1, 2, 2+4, 0, &efapin); - } - else if(test==4) { - addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin); - efa->v1= e3->vn; - set_wuv(3, efa, 3+4, 2, 3, 0, &efapin); - } - efa->e1= addedgelist(efa->v1, efa->v2, NULL); - efa->e2= addedgelist(efa->v2, efa->v3, NULL); - efa->e3= addedgelist(efa->v3, efa->v1, NULL); - - } - else { /* All the permutations of 4 faces */ - if(test==15) { - /* add a new point in center */ - CalcCent4f(vec, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - - if(beauty & B_SMOOTH) { - smooth_subdiv_quad(efa, vec); /* adds */ - } - eve= addvertlist(vec); - set_weights(eve, efa->v1,efa->v2,efa->v3,efa->v4); - eve->f |= flag; - - addface_subdiv(efa, 2, 2+4, 9, 1+4, eve, &efapin); - addface_subdiv(efa, 3, 3+4, 9, 2+4, eve, &efapin); - addface_subdiv(efa, 4, 4+4, 9, 3+4, eve, &efapin); - - efa->v2= e1->vn; - efa->v3= eve; - efa->v4= e4->vn; - set_wuv(4, efa, 1, 1+4, 9, 4+4, &efapin); - } - else { - if(((test & 3)==3)&&(test!=3)) addface_subdiv(efa, 1+4, 2, 2+4, 0, 0, &efapin); - if(((test & 6)==6)&&(test!=6)) addface_subdiv(efa, 2+4, 3, 3+4, 0, 0, &efapin); - if(((test & 12)==12)&&(test!=12)) addface_subdiv(efa, 3+4, 4, 4+4, 0, 0, &efapin); - if(((test & 9)==9)&&(test!=9)) addface_subdiv(efa, 4+4, 1, 1+4, 0, 0, &efapin); - - if(test==1) { /* Edge 1 has new vert */ - addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin); - addface_subdiv(efa, 1+4, 3, 4, 0, 0, &efapin); - efa->v2= e1->vn; - efa->v3= efa->v4; - efa->v4= 0; - set_wuv(4, efa, 1, 1+4, 4, 0, &efapin); - } - else if(test==2) { /* Edge 2 has new vert */ - addface_subdiv(efa, 2+4, 3, 4, 0, 0, &efapin); - addface_subdiv(efa, 2+4, 4, 1, 0, 0, &efapin); - efa->v3= e2->vn; - efa->v4= 0; - set_wuv(4, efa, 1, 2, 2+4, 0, &efapin); - } - else if(test==4) { /* Edge 3 has new vert */ - addface_subdiv(efa, 3+4, 4, 1, 0, 0, &efapin); - addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin); - efa->v1= efa->v2; - efa->v2= efa->v3; - efa->v3= e3->vn; - efa->v4= 0; - set_wuv(4, efa, 2, 3, 3+4, 0, &efapin); - } - else if(test==8) { /* Edge 4 has new vert */ - addface_subdiv(efa, 4+4, 1, 2, 0, 0, &efapin); - addface_subdiv(efa, 4+4, 2, 3, 0, 0, &efapin); - efa->v1= efa->v3; - efa->v2= efa->v4; - efa->v3= e4->vn; - efa->v4= 0; - set_wuv(4, efa, 3, 4, 4+4, 0, &efapin); - } - else if(test==3) { /*edge 1&2 */ - /* make new vert in center of new edge */ - vec[0]=(e1->vn->co[0]+e2->vn->co[0])/2; - vec[1]=(e1->vn->co[1]+e2->vn->co[1])/2; - vec[2]=(e1->vn->co[2]+e2->vn->co[2])/2; - eve= addvertlist(vec); - set_weights(eve, e1->vn,e2->vn,NULL,NULL); - eve->f |= flag; - /* Add new faces */ - addface_subdiv(efa, 4, 10, 2+4, 3, eve, &efapin); - addface_subdiv(efa, 4, 1, 1+4, 10, eve, &efapin); - /* orig face becomes small corner */ - efa->v1=e1->vn; - //efa->v2=efa->v2; - efa->v3=e2->vn; - efa->v4=eve; - - set_wuv(4, efa, 1+4, 2, 2+4, 10, &efapin); - } - else if(test==6) { /* 2&3 */ - /* make new vert in center of new edge */ - vec[0]=(e2->vn->co[0]+e3->vn->co[0])/2; - vec[1]=(e2->vn->co[1]+e3->vn->co[1])/2; - vec[2]=(e2->vn->co[2]+e3->vn->co[2])/2; - eve= addvertlist(vec); - set_weights(eve, e2->vn,e3->vn,NULL,NULL); - eve->f |= flag; - /*New faces*/ - addface_subdiv(efa, 1, 11, 3+4, 4, eve, &efapin); - addface_subdiv(efa, 1, 2, 2+4, 11, eve, &efapin); - /* orig face becomes small corner */ - efa->v1=e2->vn; - efa->v2=efa->v3; - efa->v3=e3->vn; - efa->v4=eve; - - set_wuv(4, efa, 2+4, 3, 3+4, 11, &efapin); - } - else if(test==12) { /* 3&4 */ - /* make new vert in center of new edge */ - vec[0]=(e3->vn->co[0]+e4->vn->co[0])/2; - vec[1]=(e3->vn->co[1]+e4->vn->co[1])/2; - vec[2]=(e3->vn->co[2]+e4->vn->co[2])/2; - eve= addvertlist(vec); - set_weights(eve, e3->vn,e4->vn,NULL,NULL); - eve->f |= flag; - /*New Faces*/ - addface_subdiv(efa, 2, 12, 4+4, 1, eve, &efapin); - addface_subdiv(efa, 2, 3, 3+4, 12, eve, &efapin); - /* orig face becomes small corner */ - efa->v1=e3->vn; - efa->v2=efa->v4; - efa->v3=e4->vn; - efa->v4=eve; - - set_wuv(4, efa, 3+4, 4, 4+4, 12, &efapin); - } - else if(test==9) { /* 4&1 */ - /* make new vert in center of new edge */ - vec[0]=(e1->vn->co[0]+e4->vn->co[0])/2; - vec[1]=(e1->vn->co[1]+e4->vn->co[1])/2; - vec[2]=(e1->vn->co[2]+e4->vn->co[2])/2; - eve= addvertlist(vec); - set_weights(eve, e1->vn,e4->vn,NULL,NULL); - eve->f |= flag; - /*New Faces*/ - addface_subdiv(efa, 3, 13, 1+4, 2, eve, &efapin); - addface_subdiv(efa, 3, 4, 4+4,13, eve, &efapin); - /* orig face becomes small corner */ - efa->v2=efa->v1; - efa->v1=e4->vn; - efa->v3=e1->vn; - efa->v4=eve; - - set_wuv(4, efa, 4+4, 1, 1+4, 13, &efapin); - } - else if(test==5) { /* 1&3 */ - addface_subdiv(efa, 1+4, 2, 3, 3+4, 0, &efapin); - efa->v2= e1->vn; - efa->v3= e3->vn; - set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin); - } - else if(test==10) { /* 2&4 */ - addface_subdiv(efa, 2+4, 3, 4, 4+4, 0, &efapin); - efa->v3= e2->vn; - efa->v4= e4->vn; - set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin); - }/* Unfortunately, there is no way to avoid tris on 1 or 3 edges*/ - else if(test==7) { /*1,2&3 */ - addface_subdiv(efa, 1+4, 2+4, 3+4, 0, 0, &efapin); - efa->v2= e1->vn; - efa->v3= e3->vn; - set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin); - } - - else if(test==14) { /* 2,3&4 */ - addface_subdiv(efa, 2+4, 3+4, 4+4, 0, 0, &efapin); - efa->v3= e2->vn; - efa->v4= e4->vn; - set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin); - } - else if(test==13) {/* 1,3&4 */ - addface_subdiv(efa, 3+4, 4+4, 1+4, 0, 0, &efapin); - efa->v4= e3->vn; - efa->v1= e1->vn; - set_wuv(4, efa, 1+4, 2, 3, 3+4, &efapin); - } - else if(test==11) { /* 1,2,&4 */ - addface_subdiv(efa, 4+4, 1+4, 2+4, 0, 0, &efapin); - efa->v1= e4->vn; - efa->v2= e2->vn; - set_wuv(4, efa, 4+4, 2+4, 3, 4, &efapin); - } - } - efa->e1= addedgelist(efa->v1, efa->v2, NULL); - efa->e2= addedgelist(efa->v2, efa->v3, NULL); - if(efa->v4) efa->e3= addedgelist(efa->v3, efa->v4, NULL); - else efa->e3= addedgelist(efa->v3, efa->v1, NULL); - if(efa->v4) efa->e4= addedgelist(efa->v4, efa->v1, NULL); - else efa->e4= NULL; - } - } - } - efa= efa->prev; - } - - /* remove all old edges, if needed make new ones */ - eed= em->edges.first; - while(eed) { - nexted= eed->next; - if( eed->vn ) { - eed->vn->f |= 16; - if(eed->f2==0) { /* not used in face */ - addedgelist(eed->v1, eed->vn, eed); - addedgelist(eed->vn, eed->v2, eed); - } - remedge(eed); - free_editedge(eed); + EditMesh *em = G.editMesh; + EditFace *ef; + EditEdge *eed, *cedge; + EditVert **templist; + struct GHash *gh; + int i,edgecount,facetype; + short cuttype=0; + + //Set faces f1 to 0 cause we need it later + + for(ef=em->faces.first;ef;ef = ef->next){ + ef->f1 = 0; + } + for(eed = em->edges.first;eed;eed = eed->next){ + //Flush vertext flags upward to the edges + //if(eed->f & flag && eed->v1->f == eed->v2->f){ + // eed->f |= eed->v1->f; + // } + eed->f2 = 0; + } + // We store an array of verts for each edge that is subdivided, + // we put this array as a value in a ghash which is keyed by the EditEdge* + + gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut + if(beauty & B_KNIFE) { + for(eed= em->edges.first;eed;eed=eed->next){ + if( eed->f1 == 0 ){ + EM_select_edge(eed,0); + } } - eed= nexted; - } - - /* since this is all on vertex level, flush vertex selection */ - EM_select_flush(); + } + // So for each edge, if it is selected, we allocate an array of size cuts+2 + // so we can have a place for the v1, the new verts and v2 + for(eed=em->edges.first;eed;eed = eed->next){ + if(eed->f & flag){ + templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist"); + templist[0] = eed->v1; + for(i=0;i<numcuts;i++){ + // This function creates the new vert and returns it back + // to the array + templist[i+1] = subdivideedgenum(eed,i+1,numcuts,rad,beauty); + //while we are here, we can copy edge info from the original edge + cedge = addedgelist(templist[i],templist[i+1],eed); + // Also set the edge f2 to EDGENEW so that we can use this info later + cedge->f2 = EDGENEW; + } + templist[i+1] = eed->v2; + //Do the last edge too + cedge = addedgelist(templist[i],templist[i+1],eed); + cedge->f2 = EDGENEW; + // Now that the edge is subdivided, we can put its verts in the ghash + BLI_ghash_insert(gh, eed, templist); + } + } + vertexnormals(0); + // Now for each face in the mesh we need to figure out How many edges were cut + // and which filling method to use for that face + for(ef = em->faces.first;ef;ef = ef->next){ + edgecount = 0; + facetype = 3; + if(ef->e1->f & flag) {edgecount++;} + if(ef->e2->f & flag) {edgecount++;} + if(ef->e3->f & flag) {edgecount++;} + if(ef->v4){ + facetype = 4; + if(ef->e4->f & flag){edgecount++;} + } + if(facetype == 4){ + switch(edgecount){ + case 0: break; + case 1: ef->f1 = SELECT; + fill_quad_single(ef, gh, numcuts); + break; + case 2: ef->f1 = SELECT; + // if there are 2, we check if edge 1 and 3 are either both on or off that way + // we can tell if the selected pair is Adjacent or Opposite of each other + if((ef->e1->f & flag && ef->e3->f & flag) || + (ef->e2->f & flag && ef->e4->f & flag)){ + fill_quad_double_op(ef, gh, numcuts); + }else{ + //printf("adj\n"); + fill_quad_double_adj(ef, gh, numcuts); + } + break; + case 3: ef->f1 = SELECT; + fill_quad_triple(ef, gh, numcuts); + break; + case 4: ef->f1 = SELECT; + fill_quad_quadruple(ef, gh, numcuts,rad,beauty); + break; + } + } else { + switch(edgecount){ + case 0: break; + case 1: ef->f1 = SELECT; + fill_tri_single(ef, gh, numcuts); + break; + case 2: ef->f1 = SELECT; + fill_tri_double(ef, gh, numcuts); + break; + case 3: ef->f1 = SELECT; + fill_tri_triple(ef, gh, numcuts,rad,beauty); + break; + } + } + } + + // Delete Old Faces + free_tagged_facelist(em->faces.first); + //Delete Old Edges + for(eed = em->edges.first;eed;eed = eed->next){ + if(BLI_ghash_haskey(gh,eed)){ + eed->f1 = SELECT; + } else { + eed->f1 = 0; + } + } + free_tagged_edgelist(em->edges.first); + + if(seltype == 0){ + for(eed = em->edges.first;eed;eed = eed->next){ + if(eed->f2 & EDGENEW){ + eed->f |= flag; + EM_select_edge(eed,1); + }else{ + eed->f &= !flag; + EM_select_edge(eed,0); + } + } + } else if (seltype == 1){ + for(eed = em->edges.first;eed;eed = eed->next){ + if(eed->f2 & EDGEINNER){ + eed->f |= flag; + EM_select_edge(eed,1); + }else{ + eed->f &= !flag; + EM_select_edge(eed,0); + } + } + } + // Free the ghash and call MEM_freeN on all the value entries to return + // that memory + BLI_ghash_free(gh, NULL, MEM_freeN); + recalc_editnormals(); - countall(); allqueue(REDRAWVIEW3D, 0); DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); } + + static int count_selected_edges(EditEdge *ed) { int totedge = 0; @@ -2147,7 +2350,6 @@ if(efa1->v1== *v2) { else { *v3= *v4= NULL; - printf("error in givequadverts()\n"); return; } @@ -3858,4 +4060,1268 @@ void bevel_menu() /* *********** END BEVEL *********/ +typedef struct SlideVert { + EditEdge *up,*down; + EditVert origvert; +} SlideVert; + +// This passes a ghash to the ghash free function so we can use it pseudo-recursively later +void freeGHash(GHash *g){ + BLI_ghash_free(g,NULL,NULL); + return; +} + +void EdgeSlide(short immediate, float imperc){ + EditMesh *em = G.editMesh; + EditFace *efa; + EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; + EditVert *ev; + LinkNode *edgelist = NULL, *vertlist=NULL, *look; + int i = 0,j; + char str[128]; + int numsel,numadded=0,timesthrough = 0,vertsel=0,prop=1,side=1; + short event,draw=1; + GHash *vertgh; + SlideVert *tempsv; + float perc = 0, percp = 0; + short mval[2],mvalo[2]; + + mvalo[0] = -1;mvalo[1] = -1; + numsel =0; + + + + // Get number of selected edges and clear some flags + for(eed=em->edges.first;eed;eed=eed->next){ + eed->f1 = 0; + eed->f2 = 0; + if(eed->f & SELECT) numsel++; + } + + for(ev=em->verts.first;ev;ev=ev->next){ + ev->f1 = 0; + } + + //Make sure each edge only has 2 faces + // make sure loop doesn't cross face + for(efa=em->faces.first;efa;efa=efa->next){ + int ct = 0; + if(efa->e1->f & SELECT){ + ct++; + efa->e1->f1++; + if(efa->e1->f1 > 2){ + okee("3+ face edge - Stopping"); + return; + } + } + if(efa->e2->f & SELECT){ + ct++; + efa->e2->f1++; + if(efa->e2->f1 > 2){ + okee("3+ face edge - Stopping"); + return; + } + } + if(efa->e3->f & SELECT){ + ct++; + efa->e3->f1++; + if(efa->e3->f1 > 2){ + okee("3+ face edge - Stopping"); + return; + } + } + if(efa->e4 && efa->e4->f & SELECT){ + ct++; + efa->e4->f1++; + if(efa->e4->f1 > 2){ + okee("3+ face edge - Stopping"); + return; + } + } + // Make sure loop is not 2 edges of same face + if(ct > 1){ + okee("loop crosses itself - Stopping"); + return; + } + } + // Get # of selected verts + for(ev=em->verts.first;ev;ev=ev->next){ + if(ev->f & SELECT) vertsel++; + } + + // Test for multiple segments + if(vertsel > numsel+1){ + okee("Was not a single edge loop - Stopping"); + return; + } + + // Get the edgeloop in order - mark f1 with SELECT once added + for(eed=em->edges.first;eed;eed=eed->next){ + if((eed->f & SELECT) && !(eed->f1 & SELECT)){ + // If this is the first edge added, just put it in + if(!edgelist){ + BLI_linklist_prepend(&edgelist,eed); + numadded++; + first = eed; + last = eed; + eed->f1 = SELECT; + } else { + if((eed->v1 == last->v1 || eed->v1 == last->v2) || + (eed->v2 == last->v1 || eed->v2 == last->v2) ){ + BLI_linklist_append(&edgelist,eed); + eed->f1 = SELECT; + numadded++; + last = eed; + } else if((eed->v1 == first->v1 || eed->v1 == first->v2) || + ( eed->v2 == first->v1 || eed->v2 == first->v2) ){ + BLI_linklist_prepend(&edgelist,eed); + eed->f1 = SELECT; + numadded++; + first = eed; + } + } + } + if(eed->next == NULL && numadded != numsel){ + eed=em->edges.first; + timesthrough++; + } + + // It looks like there was an unexpected case - Hopefully should not happen + if(timesthrough >= numsel*2){ + BLI_linklist_free(edgelist,NULL); + okee("could not order loop - Stopping"); + return; + } + } + + // Put the verts in order in a linklist + look = edgelist; + while(look){ + eed = look->link; + if(!vertlist){ + if(look->next){ + temp = look->next->link; + + //This is the first entry takes care of extra vert + if(eed->v1 != temp->v1 && eed->v1 != temp->v2){ + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } else { + BLI_linklist_append(&vertlist,eed->v2); + eed->v2->f1 = 1; + } + } else { + //This is the case that we only have 1 edge + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } + } + // for all the entries + if(eed->v1->f1 != 1){ + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } else if(eed->v2->f1 != 1){ + BLI_linklist_append(&vertlist,eed->v2); + eed->v2->f1 = 1; + } + look = look->next; + } + + // populate the SlideVerts + + vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + look = vertlist; + while(look){ + i=0; + j=0; + ev = look->link; + tempsv = (struct SlideVert*)MEM_mallocN(sizeof(struct SlideVert),"SlideVert"); + tempsv->up = NULL; + tempsv->down = NULL; + tempsv->origvert.co[0] = ev->co[0]; + tempsv->origvert.co[1] = ev->co[1]; + tempsv->origvert.co[2] = ev->co[2]; + tempsv->origvert.no[0] = ev->no[0]; + tempsv->origvert.no[1] = ev->no[1]; + tempsv->origvert.no[2] = ev->no[2]; + // i is total edges that vert is on + // j is total selected edges that vert is on + + for(eed=em->edges.first;eed;eed=eed->next){ + if(eed->v1 == ev || eed->v2 == ev){ + i++; + if(eed->f & SELECT){ + j++; + } + } + } + // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges + if(i == 4 && j == 2){ + for(eed=em->edges.first;eed;eed=eed->next){ + if(eed->v1 == ev || eed->v2 == ev){ + if(!(eed->f & SELECT)){ + if(!tempsv->up){ + tempsv->up = eed; + } else if (!(tempsv->down)){ + tempsv->down = eed; + } + } + } + } + } + // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected + if(i >= 3 && j == 1){ + for(eed=em->edges.first;eed;eed=eed->next){ + if((eed->v1 == ev || eed->v2 == ev) && eed->f & SELECT){ + for(efa = em->faces.first;efa;efa=efa->next){ + if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || (efa->e4 && efa->e4 == eed))){ + if((efa->e1->v1 == ev || efa->e1->v2 == ev) && efa->e1 != eed){ + if(!tempsv->up){ + tempsv->up = efa->e1; + } else if (!(tempsv->down)){ + tempsv->down = efa->e1; + } + } + if((efa->e2->v1 == ev || efa->e2->v2 == ev) && efa->e2 != eed){ + if(!tempsv->up){ + tempsv->up = efa->e2; + } else if (!(tempsv->down)){ + tempsv->down = efa->e2; + } + } + if((efa->e3->v1 == ev || efa->e3->v2 == ev) && efa->e3 != eed){ + if(!tempsv->up){ + tempsv->up = efa->e3; + } else if (!(tempsv->down)){ + tempsv->down = efa->e3; + } + } + if(efa->e4){ + if((efa->e4->v1 == ev || efa->e4->v2 == ev) && efa->e4 != eed){ + if(!tempsv->up){ + tempsv->up = efa->e4; + } else if (!(tempsv->down)){ + tempsv->down = efa->e4; + } + } + } + + } + } + } + } + } + if(i > 4 && j == 2){ + BLI_ghash_free(vertgh,NULL,MEM_freeN); + BLI_linklist_free(vertlist,NULL); + BLI_linklist_free(edgelist,NULL); + return; + } + BLI_ghash_insert(vertgh,ev,tempsv); + + look = look->next; + } + + // make sure the UPs nad DOWNs are 'faceloops' + + look = vertlist; + while(look){ + SlideVert *sv; + if(look->next != NULL){ + tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); + sv = BLI_ghash_lookup(vertgh,(EditVert*)look->next->link); + if(!sharesFace(tempsv->up,sv->up)){ + EditEdge *swap; + swap = sv->up; + sv->up = sv->down; + sv->down = swap; + } + } + look = look->next; + } + + // we should have enough info now to slide + //persp(PERSP_WIN); + //glDrawBuffer(GL_FRONT); + while(draw){ + if(perc == percp){ + PIL_sleep_ms(10); + } else { + //Adjust Edgeloop + if(immediate){ + perc = imperc; + } + percp = perc; + if(perc >=0){ + if(prop){ + look = vertlist; + while(look){ + EditVert *tempev; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + + if(tempsv->up->v1 == ev){ + tempev = tempsv->up->v2; + } else { + tempev = tempsv->up->v1; + } + + ev->co[0] = ((tempsv->origvert.co[0]-tempev->co[0])*(1-fabs(perc))) + tempev->co[0]; + ev->co[1] = ((tempsv->origvert.co[1]-tempev->co[1])*(1-fabs(perc))) + tempev->co[1]; + ev->co[2] = ((tempsv->origvert.co[2]-tempev->co[2])*(1-fabs(perc))) + tempev->co[2]; + + look = look->next; + } + } + else { + //Non prop code + } + } else { + if(prop){ + look = vertlist; + while(look){ + EditVert *tempev; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + + if(tempsv->down->v1 == ev){ + tempev = tempsv->down->v2; + } else { + tempev = tempsv->down->v1; + } + + ev->co[0] = ((tempsv->origvert.co[0]-tempev->co[0])*(1-fabs(perc))) + tempev->co[0]; + ev->co[1] = ((tempsv->origvert.co[1]-tempev->co[1])*(1-fabs(perc))) + tempev->co[1]; + ev->co[2] = ((tempsv->origvert.co[2]-tempev->co[2])*(1-fabs(perc))) + tempev->co[2]; + + look = look->next; + } + } else { + //non-prop code + } + } + + sprintf(str, "Percentage %f", perc); + headerprint(str); + + force_draw(0); + DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); + scrarea_queue_winredraw(curarea); + } + + getmouseco_areawin(mval); + if(mvalo[0] == -1){ + mvalo[0] = mval[0]; + mvalo[1] = mval[1]; + } + + if(mval[0] > mvalo[0]){ + if(perc < 0.99) + perc += 0.01; + + } else if(mval[0] < mvalo[0]){ + if(perc > -0.99) + perc -= 0.01; + } + + mvalo[0] = mval[0]; + + if(!immediate){ + while(qtest()) { + unsigned short val=0; + event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle + + + /* val==0 on key-release event */ + if(val && (event==ESCKEY || ( event==LEFTMOUSE || event==RETKEY ))){ + draw = 0; + } + if(val && (event==RIGHTMOUSE || event==ESCKEY || (event==MIDDLEMOUSE) )){ + perc = 0; + immediate = 1; + } + if(val && (event==UPARROWKEY)){ + if(perc <= 1.0){ + perc += 0.01; + } + } + if(val && (event==DOWNARROWKEY)){ + if(perc >= -1.0){ + perc -= 0.01; + } + } + } + } else { + draw = 0; + } + } + + //BLI_ghash_free(edgesgh, freeGHash, NULL); + BLI_ghash_free(vertgh,NULL,MEM_freeN); + BLI_linklist_free(vertlist,NULL); + BLI_linklist_free(edgelist,NULL); +} + +//---------------------------------------------- OLD SUBDIVIDE ----------------------------------------------------- + +/* ******************** SUBDIVIDE ********************************** */ + + +static void merge_weights(EditVert * vt, EditVert *vs ) +{ + MDeformWeight *newdw; + int i,j,done; + for (j=0; j<vs->totweight; j++){ + done=0; + /* Is vertex memeber of group */ + /* If so: Change its weight */ + for (i=0; i<vt->totweight; i++){ + if (vt->dw[i].def_nr == vs->dw[j].def_nr) + { /* taking the maximum makes it independant from order of occurance */ + if (vt->dw[i].weight < vs->dw[j].weight) vt->dw[i].weight = vs->dw[j].weight; + done=1; + break; + } + } + /* If not: Add the group and set its weight */ + if (!done){ + newdw = MEM_callocN (sizeof(MDeformWeight)*(vt->totweight+1), "deformWeight"); + if (vt->dw){ + memcpy (newdw, vt->dw, sizeof(MDeformWeight)*vt->totweight); + MEM_freeN (vt->dw); + } + vt->dw=newdw; + vt->dw[vt->totweight].weight=vs->dw[j].weight; + vt->dw[vt->totweight].def_nr=vs->dw[j].def_nr; + vt->totweight++; + } + } +} + + +static void set_weights(EditVert * vt, EditVert *vs1,EditVert *vs2,EditVert *vs3,EditVert *vs4 ) +{ +/* +vt is a new generated vertex with empty deform group information +vs1..v4 are egde neighbours holding group information +so let the information ooze into the new one +*/ + if (vs1) merge_weights(vt,vs1); + if (vs2) merge_weights(vt,vs2); + if (vs3) merge_weights(vt,vs3); + if (vs4) merge_weights(vt,vs4); +} + + + + +static unsigned int cpack_fact(unsigned int col1, unsigned int col2, float fact) +{ + char *cp1, *cp2, *cp; + unsigned int col=0; + float facti; + + facti=1-fact; /*result is (1-fact) * col1 and fact * col2 */ + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + cp[0]= (char)(facti*cp1[0]+fact*cp2[0]); + cp[1]= (char)(facti*cp1[1]+fact*cp2[1]); + cp[2]= (char)(facti*cp1[2]+fact*cp2[2]); + cp[3]= (char)(facti*cp1[3]+fact*cp2[3]); + + return col; +} + + +static void uv_half(float *uv, float *uv1, float *uv2) +{ + uv[0]= (uv1[0]+uv2[0])/2.0f; + uv[1]= (uv1[1]+uv2[1])/2.0f; + +} + +static void uv_fact(float *uv, float *uv1, float *uv2, float fact) +{ + float facti = 1.0f - fact; + uv[0] = facti * uv1[0] + fact * uv2[0]; + uv[1] = facti * uv1[1] + fact * uv2[1]; +} + +static void uv_quart(float *uv, float *uv1) +{ + uv[0]= (uv1[0]+uv1[2]+uv1[4]+uv1[6])/4.0f; + uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0f; +} + +static void face_pin_vertex(EditFace *efa, EditVert *vertex) +{ + if(efa->v1 == vertex) efa->tf.unwrap |= TF_PIN1; + else if(efa->v2 == vertex) efa->tf.unwrap |= TF_PIN2; + else if(efa->v3 == vertex) efa->tf.unwrap |= TF_PIN3; + else if(efa->v4 && vertex && efa->v4 == vertex) efa->tf.unwrap |= TF_PIN4; +} + +static int vert_offset(EditFace *efa, EditVert *eve) +{ + if (efa->v1 == eve) + return 0; + if (efa->v2 == eve) + return 1; + if (efa->v3 == eve) + return 2; + if (efa->v4) + if (efa->v4 == eve) + return 3; + return -1; +} + +static void set_wuv(int tot, EditFace *efa, int v1, int v2, int v3, int v4, EditFace *efapin) +{ + /* this weird function only to be used for subdivide, the 'w' in the name has no meaning! */ + float *uv, uvo[4][2]; + unsigned int *col, colo[4], col1, col2; + int a, v; + + /* recover pinning */ + if(efapin){ + efa->tf.unwrap= 0; + if(efapin->tf.unwrap & TF_PIN1) face_pin_vertex(efa, efapin->v1); + if(efapin->tf.unwrap & TF_PIN2) face_pin_vertex(efa, efapin->v2); + if(efapin->tf.unwrap & TF_PIN3) face_pin_vertex(efa, efapin->v3); + if(efapin->tf.unwrap & TF_PIN4) face_pin_vertex(efa, efapin->v4); + } + + memcpy(uvo, efa->tf.uv, sizeof(uvo)); + uv= efa->tf.uv[0]; + memcpy(colo, efa->tf.col, sizeof(colo)); + col= efa->tf.col; + + /* + Quads and Triangles reuse the same cases numbers, so we migh as well do both in the + same loop. Especially now that the offsets are calculated and not hardcoded, it's + much easier to reduce the code size (and make it less buggy). + */ + + /* ******************************************** */ + /* */ + /* Numbers corespond to verts (corner points), */ + /* edge->vn's (center edges), the Center */ + /* And the quincunx points of a face */ + /* */ + /* ******************************************** */ + + /* ******************************************** */ + /* as shown here for quads: */ + /* */ + /* 2 ------- 5 -------- 1 */ + /* | \ / | \ / | */ + /* | 10 | 13 | */ + /* | / \ | / \ | */ + /* 6 ------- 9 -------- 8 */ + /* | \ / | \ / | */ + /* | 11 | 12 | */ + /* | / \ | / \ | */ + /* 3 ------- 7 -------- 4 */ + /* */ + /* ******************************************** */ + + /* ******************************************** */ + /* and for triangles: */ + /* 1 */ + /* / \ */ + /* / \ */ + /* 5 7 */ + /* / \ */ + /* / \ */ + /* 2 --------- 6 -------- 3 */ + /* */ + /* ******************************************** */ + + /* ******************************************** */ + /* */ + /* My talents in ascii arts are minimal so the */ + /* drawings don't show all possible subdivision */ + /* just draw them on paper if you need to. */ + /* */ + /* ******************************************** */ + + for(a=0; a<tot; a++, uv+=2, col++) { + /* edges that are subdivided, if any */ + EditEdge *e1 = NULL, *e2 = NULL; + if(a==0) v= v1; + else if(a==1) v= v2; + else if(a==2) v= v3; + else v= v4; + + if(a==3 && v4==0) break; + + switch (v) { + /* Face corners, direct copy of the UVs and VCol */ + case 1: + case 2: + case 3: + case 4: + uv[0]= uvo[v-1][0]; + uv[1]= uvo[v-1][1]; + *col= colo[v-1]; + break; + /* Face sides (cutting an edge) */ + /* + set the edge pointer accordingly, it's used latter to do the + actual calculations of the new UV and VCol + */ + case 5: + e1 = efapin->e1; + break; + case 6: + e1 = efapin->e2; + break; + case 7: + e1 = efapin->e3; + break; + case 8: + e1 = efapin->e4; + break; + + /* The following applies to Quads only */ + + /* Quad middle, just used when subdividing a quad as a whole */ + /* (not knife nor loop cut) */ + /* UVs and VCol is just the average of the four corners */ + case 9: + uv_quart(uv, uvo[0]); + col1= cpack_fact(colo[1], colo[0], 0.5f); + col2= cpack_fact(colo[2], colo[3], 0.5f); + *col= cpack_fact(col1, col2, 0.5f); + break; + /* Quad corner cuts */ + /* only when two adjacent edges are subdivided (and no others) */ + /* Set both edge pointers accordingly, used later for calculations */ + case 10: // case test==3 in subdivideflag() + e1 = efapin->e1; + e2 = efapin->e2; + break; + case 11: // case of test==6 + e1 = efapin->e2; + e2 = efapin->e3; + break; + case 12: // case of test==12 + e1 = efapin->e3; + e2 = efapin->e4; + break; + case 13: // case of test==9 + e1 = efapin->e4; + e2 = efapin->e1; + break; + } + /* if splitting at least an edge */ + if (e1) { + float percent; + int off1, off2; + /* if splitting two edges */ + if (e2) { + float uv1[2], uv2[2]; + /* + UV and VCol is obtained by using the middle ground of the weighted + average for both edges (weighted with Percent cut flag). + In a nutshell, the average of the cuts on both edges. + */ + /* first cut */ + off1 = vert_offset(efapin, e1->v1); + off2 = vert_offset(efapin, e1->v2); + percent = e1->f1 / 32768.0f; + uv_fact(uv1, uvo[off1], uvo[off2], percent); + col1= cpack_fact(colo[off1], colo[off2], percent); + + /* second cut */ + off1 = vert_offset(efapin, e2->v1); + off2 = vert_offset(efapin, e2->v2); + percent = e2->f1 / 32768.0f; + uv_fact(uv2, uvo[off1], uvo[off2], percent); + col2= cpack_fact(colo[off1], colo[off1], percent); + + /* average the two */ + uv_half(uv, uv1, uv2); + *col= cpack_fact(col1, col2, 0.5f); + } + /* or only one */ + else { + /* + UV and VCol is obtained by using the weighted average + of both vertice (weighted with Percent cut flag). + */ + off1 = vert_offset(efapin, e1->v1); + off2 = vert_offset(efapin, e1->v2); + percent = e1->f1 / 32768.0f; + uv_fact(uv, uvo[off1], uvo[off2], percent); + *col= cpack_fact(colo[off1], colo[off2], percent); + } + } + } +} + +static EditVert *vert_from_number(EditFace *efa, int nr) +{ + switch(nr) { + case 0: + return 0; + case 1: + return efa->v1; + case 2: + return efa->v2; + case 3: + return efa->v3; + case 4: + return efa->v4; + case 5: + return efa->e1->vn; + case 6: + return efa->e2->vn; + case 7: + return efa->e3->vn; + case 8: + return efa->e4->vn; + } + + return NULL; +} + +static void addface_subdiv(EditFace *efa, int val1, int val2, int val3, int val4, EditVert *eve, EditFace *efapin) +{ + EditFace *w; + EditVert *v1, *v2, *v3, *v4; + + if(val1>=9) v1= eve; + else v1= vert_from_number(efa, val1); + + if(val2>=9) v2= eve; + else v2= vert_from_number(efa, val2); + + if(val3>=9) v3= eve; + else v3= vert_from_number(efa, val3); + + if(val4>=9) v4= eve; + else v4= vert_from_number(efa, val4); + + w= addfacelist(v1, v2, v3, v4, efa, NULL); + if(w) { + if(efa->v4) set_wuv(4, w, val1, val2, val3, val4, efapin); + else set_wuv(3, w, val1, val2, val3, val4, efapin); + } +} + +static float smoothperc= 0.0; + +static void smooth_subdiv_vec(float *v1, float *v2, float *n1, float *n2, float *vec) +{ + float len, fac, nor[3], nor1[3], nor2[3]; + + VecSubf(nor, v1, v2); + len= 0.5f*Normalise(nor); + + VECCOPY(nor1, n1); + VECCOPY(nor2, n2); + + /* cosine angle */ + fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ; + + vec[0]= fac*nor1[0]; + vec[1]= fac*nor1[1]; + vec[2]= fac*nor1[2]; + + /* cosine angle */ + fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ; + + vec[0]+= fac*nor2[0]; + vec[1]+= fac*nor2[1]; + vec[2]+= fac*nor2[2]; + + vec[0]*= smoothperc*len; + vec[1]*= smoothperc*len; + vec[2]*= smoothperc*len; +} + +static void smooth_subdiv_quad(EditFace *efa, float *vec) +{ + + float nor1[3], nor2[3]; + float vec1[3], vec2[3]; + float cent[3]; + + /* vlr->e1->vn is new vertex inbetween v1 / v2 */ + + VecMidf(nor1, efa->v1->no, efa->v2->no); + Normalise(nor1); + VecMidf(nor2, efa->v3->no, efa->v4->no); + Normalise(nor2); + + smooth_subdiv_vec( efa->e1->vn->co, efa->e3->vn->co, nor1, nor2, vec1); + + VecMidf(nor1, efa->v2->no, efa->v3->no); + Normalise(nor1); + VecMidf(nor2, efa->v4->no, efa->v1->no); + Normalise(nor2); + + smooth_subdiv_vec( efa->e2->vn->co, efa->e4->vn->co, nor1, nor2, vec2); + + VecAddf(vec1, vec1, vec2); + + CalcCent4f(cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); + VecAddf(vec, cent, vec1); +} + +void subdivideflag(int flag, float rad, int beauty) +{ + EditMesh *em = G.editMesh; + /* subdivide all with (vertflag & flag) */ + /* if rad>0.0 it's a 'sphere' subdivide */ + /* if rad<0.0 it's a fractal subdivide */ + extern float doublimit; + EditVert *eve; + EditEdge *eed, *e1, *e2, *e3, *e4, *nexted; + EditFace *efa, efapin; + float fac, vec[3], vec1[3], len1, len2, len3, percent; + short test; + + printf("in old subdivideflag\n"); + + if(beauty & B_SMOOTH) { + short perc= 100; + + if(button(&perc, 10, 500, "Percentage:")==0) return; + + smoothperc= 0.292f*perc/100.0f; + } + + /* edgeflags */ + if((beauty & B_KNIFE)==0) { // knife option sets own flags + eed= em->edges.first; + while(eed) { + if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f2= flag; + else eed->f2= 0; + eed= eed->next; + } + } + + /* if beauty: test for area and clear edge flags of 'ugly' edges */ + if(beauty & B_BEAUTY) { + efa= em->faces.first; + while(efa) { + if( faceselectedAND(efa, flag) ) { + if(efa->v4) { + + /* area */ + len1= AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); + if(len1 <= doublimit) { + efa->e1->f2 = 0; + efa->e2->f2 = 0; + efa->e3->f2 = 0; + efa->e4->f2 = 0; + } + else { + len1= VecLenf(efa->v1->co, efa->v2->co) + VecLenf(efa->v3->co, efa->v4->co); + len2= VecLenf(efa->v2->co, efa->v3->co) + VecLenf(efa->v1->co, efa->v4->co); + + if(len1 < len2) { + efa->e1->f2 = 0; + efa->e3->f2 = 0; + } + else if(len1 > len2) { + efa->e2->f2 = 0; + efa->e4->f2 = 0; + } + } + } + else { + /* area */ + len1= AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co); + if(len1 <= doublimit) { + efa->e1->f2 = 0; + efa->e2->f2 = 0; + efa->e3->f2 = 0; + } + else { + len1= VecLenf(efa->v1->co, efa->v2->co) ; + len2= VecLenf(efa->v2->co, efa->v3->co) ; + len3= VecLenf(efa->v3->co, efa->v1->co) ; + + if(len1<len2 && len1<len3) { + efa->e1->f2 = 0; + } + else if(len2<len3 && len2<len1) { + efa->e2->f2 = 0; + } + else if(len3<len2 && len3<len1) { + efa->e3->f2 = 0; + } + } + } + } + efa= efa->next; + } + } + + if(beauty & B_SMOOTH) { + + vertexnormals(0); /* no1*/ + + } + + /* make new normal and put in edge, clear flag! needed for face creation part below */ + eed= em->edges.first; + while(eed) { + if(eed->f2 & flag) { + /* for now */ + eed->h &= ~EM_FGON; + + /* Subdivide percentage is stored in 1/32768ths in eed->f1 */ + if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0f; + else { + eed->f1 = 32768 / 2; + percent=0.5f; + } + + vec[0]= (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0]; + vec[1]= (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1]; + vec[2]= (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2]; + + if(rad > 0.0) { /* subdivide sphere */ + Normalise(vec); + vec[0]*= rad; + vec[1]*= rad; + vec[2]*= rad; + } + else if(rad< 0.0) { /* fractal subdivide */ + fac= rad* VecLenf(eed->v1->co, eed->v2->co); + vec1[0]= fac*(float)(0.5-BLI_drand()); + vec1[1]= fac*(float)(0.5-BLI_drand()); + vec1[2]= fac*(float)(0.5-BLI_drand()); + VecAddf(vec, vec, vec1); + } + + if(beauty & B_SMOOTH) { + smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1); + VecAddf(vec, vec, vec1); + } + + eed->vn= addvertlist(vec); + eed->vn->f= eed->v1->f; + + } + else eed->vn= 0; + + eed->f2= 0; /* needed! */ + + eed= eed->next; + } + + /* test all faces for subdivide edges, there are 8 or 16 cases (ugh)! */ + + efa= em->faces.last; + while(efa) { + + efapin= *efa; /* make a copy of efa to recover uv pinning later */ + + if( faceselectedOR(efa, flag) ) { + /* for now */ + efa->fgonf= 0; + + e1= efa->e1; + e2= efa->e2; + e3= efa->e3; + e4= efa->e4; + + test= 0; + if(e1 && e1->vn) { + test+= 1; + e1->f2= 1; + /* add edges here, to copy correct edge data */ + eed= addedgelist(e1->v1, e1->vn, e1); + eed= addedgelist(e1->vn, e1->v2, e1); + set_weights(e1->vn, e1->v1,e1->v2,NULL,NULL); + } + if(e2 && e2->vn) { + test+= 2; + e2->f2= 1; + /* add edges here, to copy correct edge data */ + eed= addedgelist(e2->v1, e2->vn, e2); + eed= addedgelist(e2->vn, e2->v2, e2); + set_weights(e2->vn, e2->v1,e2->v2,NULL,NULL); + } + if(e3 && e3->vn) { + test+= 4; + e3->f2= 1; + /* add edges here, to copy correct edge data */ + eed= addedgelist(e3->v1, e3->vn, e3); + eed= addedgelist(e3->vn, e3->v2, e3); + set_weights(e3->vn, e3->v1,e3->v2,NULL,NULL); + } + if(e4 && e4->vn) { + test+= 8; + e4->f2= 1; + /* add edges here, to copy correct edge data */ + eed= addedgelist(e4->v1, e4->vn, e4); + eed= addedgelist(e4->vn, e4->v2, e4); + set_weights(e4->vn, e4->v1,e4->v2,NULL,NULL); + } + if(test) { + if(efa->v4==0) { /* All the permutations of 3 edges*/ + if((test & 3)==3) addface_subdiv(efa, 2, 2+4, 1+4, 0, 0, &efapin); + if((test & 6)==6) addface_subdiv(efa, 3, 3+4, 2+4, 0, 0, &efapin); + if((test & 5)==5) addface_subdiv(efa, 1, 1+4, 3+4, 0, 0, &efapin); + + if(test==7) { /* four new faces, old face renews */ + efa->v1= e1->vn; + efa->v2= e2->vn; + efa->v3= e3->vn; + set_wuv(3, efa, 1+4, 2+4, 3+4, 0, &efapin); + } + else if(test==3) { + addface_subdiv(efa, 1+4, 2+4, 3, 0, 0, &efapin); + efa->v2= e1->vn; + set_wuv(3, efa, 1, 1+4, 3, 0, &efapin); + } + else if(test==6) { + addface_subdiv(efa, 2+4, 3+4, 1, 0, 0, &efapin); + efa->v3= e2->vn; + set_wuv(3, efa, 1, 2, 2+4, 0, &efapin); + } + else if(test==5) { + addface_subdiv(efa, 3+4, 1+4, 2, 0, 0, &efapin); + efa->v1= e3->vn; + set_wuv(3, efa, 3+4, 2, 3, 0, &efapin); + } + else if(test==1) { + addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin); + efa->v2= e1->vn; + set_wuv(3, efa, 1, 1+4, 3, 0, &efapin); + } + else if(test==2) { + addface_subdiv(efa, 2+4, 3, 1, 0, 0, &efapin); + efa->v3= e2->vn; + set_wuv(3, efa, 1, 2, 2+4, 0, &efapin); + } + else if(test==4) { + addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin); + efa->v1= e3->vn; + set_wuv(3, efa, 3+4, 2, 3, 0, &efapin); + } + efa->e1= addedgelist(efa->v1, efa->v2, NULL); + efa->e2= addedgelist(efa->v2, efa->v3, NULL); + efa->e3= addedgelist(efa->v3, efa->v1, NULL); + + } + else { /* All the permutations of 4 faces */ + if(test==15) { + /* add a new point in center */ + CalcCent4f(vec, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); + + if(beauty & B_SMOOTH) { + smooth_subdiv_quad(efa, vec); /* adds */ + } + eve= addvertlist(vec); + set_weights(eve, efa->v1,efa->v2,efa->v3,efa->v4); + eve->f |= flag; + + addface_subdiv(efa, 2, 2+4, 9, 1+4, eve, &efapin); + addface_subdiv(efa, 3, 3+4, 9, 2+4, eve, &efapin); + addface_subdiv(efa, 4, 4+4, 9, 3+4, eve, &efapin); + + efa->v2= e1->vn; + efa->v3= eve; + efa->v4= e4->vn; + set_wuv(4, efa, 1, 1+4, 9, 4+4, &efapin); + } + else { + if(((test & 3)==3)&&(test!=3)) addface_subdiv(efa, 1+4, 2, 2+4, 0, 0, &efapin); + if(((test & 6)==6)&&(test!=6)) addface_subdiv(efa, 2+4, 3, 3+4, 0, 0, &efapin); + if(((test & 12)==12)&&(test!=12)) addface_subdiv(efa, 3+4, 4, 4+4, 0, 0, &efapin); + if(((test & 9)==9)&&(test!=9)) addface_subdiv(efa, 4+4, 1, 1+4, 0, 0, &efapin); + + if(test==1) { /* Edge 1 has new vert */ + addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin); + addface_subdiv(efa, 1+4, 3, 4, 0, 0, &efapin); + efa->v2= e1->vn; + efa->v3= efa->v4; + efa->v4= 0; + set_wuv(4, efa, 1, 1+4, 4, 0, &efapin); + } + else if(test==2) { /* Edge 2 has new vert */ + addface_subdiv(efa, 2+4, 3, 4, 0, 0, &efapin); + addface_subdiv(efa, 2+4, 4, 1, 0, 0, &efapin); + efa->v3= e2->vn; + efa->v4= 0; + set_wuv(4, efa, 1, 2, 2+4, 0, &efapin); + } + else if(test==4) { /* Edge 3 has new vert */ + addface_subdiv(efa, 3+4, 4, 1, 0, 0, &efapin); + addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin); + efa->v1= efa->v2; + efa->v2= efa->v3; + efa->v3= e3->vn; + efa->v4= 0; + set_wuv(4, efa, 2, 3, 3+4, 0, &efapin); + } + else if(test==8) { /* Edge 4 has new vert */ + addface_subdiv(efa, 4+4, 1, 2, 0, 0, &efapin); + addface_subdiv(efa, 4+4, 2, 3, 0, 0, &efapin); + efa->v1= efa->v3; + efa->v2= efa->v4; + efa->v3= e4->vn; + efa->v4= 0; + set_wuv(4, efa, 3, 4, 4+4, 0, &efapin); + } + else if(test==3) { /*edge 1&2 */ + /* make new vert in center of new edge */ + vec[0]=(e1->vn->co[0]+e2->vn->co[0])/2; + vec[1]=(e1->vn->co[1]+e2->vn->co[1])/2; + vec[2]=(e1->vn->co[2]+e2->vn->co[2])/2; + eve= addvertlist(vec); + set_weights(eve, e1->vn,e2->vn,NULL,NULL); + eve->f |= flag; + /* Add new faces */ + addface_subdiv(efa, 4, 10, 2+4, 3, eve, &efapin); + addface_subdiv(efa, 4, 1, 1+4, 10, eve, &efapin); + /* orig face becomes small corner */ + efa->v1=e1->vn; + //efa->v2=efa->v2; + efa->v3=e2->vn; + efa->v4=eve; + + set_wuv(4, efa, 1+4, 2, 2+4, 10, &efapin); + } + else if(test==6) { /* 2&3 */ + /* make new vert in center of new edge */ + vec[0]=(e2->vn->co[0]+e3->vn->co[0])/2; + vec[1]=(e2->vn->co[1]+e3->vn->co[1])/2; + vec[2]=(e2->vn->co[2]+e3->vn->co[2])/2; + eve= addvertlist(vec); + set_weights(eve, e2->vn,e3->vn,NULL,NULL); + eve->f |= flag; + /*New faces*/ + addface_subdiv(efa, 1, 11, 3+4, 4, eve, &efapin); + addface_subdiv(efa, 1, 2, 2+4, 11, eve, &efapin); + /* orig face becomes small corner */ + efa->v1=e2->vn; + efa->v2=efa->v3; + efa->v3=e3->vn; + efa->v4=eve; + + set_wuv(4, efa, 2+4, 3, 3+4, 11, &efapin); + } + else if(test==12) { /* 3&4 */ + /* make new vert in center of new edge */ + vec[0]=(e3->vn->co[0]+e4->vn->co[0])/2; + vec[1]=(e3->vn->co[1]+e4->vn->co[1])/2; + vec[2]=(e3->vn->co[2]+e4->vn->co[2])/2; + eve= addvertlist(vec); + set_weights(eve, e3->vn,e4->vn,NULL,NULL); + eve->f |= flag; + /*New Faces*/ + addface_subdiv(efa, 2, 12, 4+4, 1, eve, &efapin); + addface_subdiv(efa, 2, 3, 3+4, 12, eve, &efapin); + /* orig face becomes small corner */ + efa->v1=e3->vn; + efa->v2=efa->v4; + efa->v3=e4->vn; + efa->v4=eve; + + set_wuv(4, efa, 3+4, 4, 4+4, 12, &efapin); + } + else if(test==9) { /* 4&1 */ + /* make new vert in center of new edge */ + vec[0]=(e1->vn->co[0]+e4->vn->co[0])/2; + vec[1]=(e1->vn->co[1]+e4->vn->co[1])/2; + vec[2]=(e1->vn->co[2]+e4->vn->co[2])/2; + eve= addvertlist(vec); + set_weights(eve, e1->vn,e4->vn,NULL,NULL); + eve->f |= flag; + /*New Faces*/ + addface_subdiv(efa, 3, 13, 1+4, 2, eve, &efapin); + addface_subdiv(efa, 3, 4, 4+4,13, eve, &efapin); + /* orig face becomes small corner */ + efa->v2=efa->v1; + efa->v1=e4->vn; + efa->v3=e1->vn; + efa->v4=eve; + + set_wuv(4, efa, 4+4, 1, 1+4, 13, &efapin); + } + else if(test==5) { /* 1&3 */ + addface_subdiv(efa, 1+4, 2, 3, 3+4, 0, &efapin); + efa->v2= e1->vn; + efa->v3= e3->vn; + set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin); + } + else if(test==10) { /* 2&4 */ + addface_subdiv(efa, 2+4, 3, 4, 4+4, 0, &efapin); + efa->v3= e2->vn; + efa->v4= e4->vn; + set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin); + }/* Unfortunately, there is no way to avoid tris on 1 or 3 edges*/ + else if(test==7) { /*1,2&3 */ + addface_subdiv(efa, 1+4, 2+4, 3+4, 0, 0, &efapin); + efa->v2= e1->vn; + efa->v3= e3->vn; + set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin); + } + + else if(test==14) { /* 2,3&4 */ + addface_subdiv(efa, 2+4, 3+4, 4+4, 0, 0, &efapin); + efa->v3= e2->vn; + efa->v4= e4->vn; + set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin); + } + else if(test==13) {/* 1,3&4 */ + addface_subdiv(efa, 3+4, 4+4, 1+4, 0, 0, &efapin); + efa->v4= e3->vn; + efa->v1= e1->vn; + set_wuv(4, efa, 1+4, 2, 3, 3+4, &efapin); + } + else if(test==11) { /* 1,2,&4 */ + addface_subdiv(efa, 4+4, 1+4, 2+4, 0, 0, &efapin); + efa->v1= e4->vn; + efa->v2= e2->vn; + set_wuv(4, efa, 4+4, 2+4, 3, 4, &efapin); + } + } + efa->e1= addedgelist(efa->v1, efa->v2, NULL); + efa->e2= addedgelist(efa->v2, efa->v3, NULL); + if(efa->v4) efa->e3= addedgelist(efa->v3, efa->v4, NULL); + else efa->e3= addedgelist(efa->v3, efa->v1, NULL); + if(efa->v4) efa->e4= addedgelist(efa->v4, efa->v1, NULL); + else efa->e4= NULL; + } + } + } + efa= efa->prev; + } + + /* remove all old edges, if needed make new ones */ + eed= em->edges.first; + while(eed) { + nexted= eed->next; + if( eed->vn ) { + eed->vn->f |= 16; + if(eed->f2==0) { /* not used in face */ + addedgelist(eed->v1, eed->vn, eed); + addedgelist(eed->vn, eed->v2, eed); + } + remedge(eed); + free_editedge(eed); + } + eed= nexted; + } + + /* since this is all on vertex level, flush vertex selection */ + EM_select_flush(); + recalc_editnormals(); + + countall(); + allqueue(REDRAWVIEW3D, 0); + DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); +} diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 8098f01970d..f01b88a2a78 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1897,7 +1897,7 @@ void special_editmenu(void) extern float doublimit; float fac; int nr,ret; - short randfac; + short randfac,numcuts; if(G.obpose) { pose_special_editmenu(); @@ -2024,26 +2024,38 @@ void special_editmenu(void) } } else if(G.obedit->type==OB_MESH) { - - nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11"); - if(nr>0) waitcursor(1); + + nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Multi Smooth - WIP%x12|Subdivide Smooth Old%x13|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11"); + //if(nr>0) waitcursor(1); switch(nr) { case 1: - subdivideflag(1, 0.0, editbutflag); - BIF_undo_push("Subdivide"); + numcuts = 1; + waitcursor(1); + esubdivideflag(1, 0.0, editbutflag,numcuts,0); + + BIF_undo_push("ESubdivide Single"); + //subdivideflag(1, 0.0, editbutflag); + //BIF_undo_push("Subdivide"); break; case 2: + numcuts = 2; + if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return; + waitcursor(1); + esubdivideflag(1, 0.0, editbutflag,numcuts,0); + BIF_undo_push("ESubdivide"); + break; + case 3: + numcuts = 2; + if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return; + waitcursor(1); randfac= 10; if(button(&randfac, 1, 100, "Rand fac:")==0) return; fac= -( (float)randfac )/100; - subdivideflag(1, fac, editbutflag); + esubdivideflag(1, fac, editbutflag,numcuts,0); BIF_undo_push("Subdivide Fractal"); break; - case 3: - subdivideflag(1, 0.0, editbutflag | B_SMOOTH); - BIF_undo_push("Subdivide Smooth"); - break; + case 4: mergemenu(); break; @@ -2070,7 +2082,19 @@ void special_editmenu(void) case 11: bevel_menu(); break; - } + case 12: + numcuts = 2; + if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return; + waitcursor(1); + esubdivideflag(1, 0.0, editbutflag | B_SMOOTH,numcuts,0); + BIF_undo_push("Subdivide Smooth"); + break; + case 13: + waitcursor(1); + subdivideflag(1, 0.0, editbutflag | B_SMOOTH); + BIF_undo_push("Subdivide Smooth"); + break; + } DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 340ee0b88b4..c35d1f71177 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -819,9 +819,6 @@ void do_view3d_select_meshmenu(void *arg, int event) case 5: /* select random */ selectrandom_mesh(); break; - case 6: /* select Faceloop */ - loopoperations(LOOP_SELECT); - break; case 7: /* select more */ select_more(); break; @@ -831,9 +828,6 @@ void do_view3d_select_meshmenu(void *arg, int event) case 9: /* select less */ select_non_manifold(); break; - case 10: /* select vertexloop */ - vertex_loop_select(); - break; } allqueue(REDRAWVIEW3D, 0); } @@ -873,8 +867,6 @@ static uiBlock *view3d_select_meshmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Face Loop...|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vertex Loop|Alt B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linked Vertices|Ctrl L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); if(curarea->headertype==HEADERTOP) { @@ -2088,25 +2080,25 @@ void do_view3d_edit_mesh_edgesmenu(void *arg, int event) switch(event) { case 0: /* subdivide smooth */ - subdivideflag(1, 0.0, editbutflag | B_SMOOTH); + esubdivideflag(1, 0.0, editbutflag | B_SMOOTH,1,0); BIF_undo_push("Subdivide Smooth"); break; case 1: /*subdivide fractal */ randfac= 10; if(button(&randfac, 1, 100, "Rand fac:")==0) return; fac= -( (float)randfac )/100; - subdivideflag(1, fac, editbutflag); + esubdivideflag(1, fac, editbutflag,1,0); BIF_undo_push("Subdivide Fractal"); break; case 2: /* subdivide */ - subdivideflag(1, 0.0, editbutflag); + esubdivideflag(1, 0.0, editbutflag,1,0); BIF_undo_push("Subdivide"); break; case 3: /* knife subdivide */ KnifeSubdivide(KNIFE_PROMPT); break; case 4: /* Loop subdivide */ - loopoperations(LOOP_CUT); + CutEdgeloop(1); break; case 5: /* Make Edge/Face */ addedgeface_mesh(); @@ -2130,6 +2122,9 @@ void do_view3d_edit_mesh_edgesmenu(void *arg, int event) case 11: /* Rotate Edge */ edge_rotate_selected(1); break; + case 12: /* Edgeslide */ + EdgeSlide(0,0.0); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -2170,7 +2165,10 @@ static uiBlock *view3d_edit_mesh_edgesmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CCW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CCW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Edgeslide |Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); + uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index dee2d7c0e92..7300135c86f 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1132,14 +1132,6 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case BKEY: if((G.qual==LR_SHIFTKEY)) set_render_border(); - else if((G.qual==LR_ALTKEY)){ - if(G.obedit && G.obedit->type==OB_MESH) { - /* Loop Select Operations */ - /* Vertexloop */ - /* Faceloop */ - vertex_loop_select(); - } - } else if((G.qual==0)) borderselect(); break; @@ -1535,12 +1527,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if((G.qual==LR_SHIFTKEY)) { if ELEM(G.obedit->type, OB_CURVE, OB_SURF) selectrow_nurb(); - else if (G.obedit->type==OB_MESH) - loopoperations(LOOP_SELECT); } else if(G.qual==LR_CTRLKEY) { if (G.obedit->type==OB_MESH) - loopoperations(LOOP_CUT); + CutEdgeloop(1); + BIF_undo_push("Cut Edgeloop"); } else if((G.qual==0)) { initTransform(TFM_ROTATION, CTX_NONE); diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 5f9c66386db..9c46f2f5e16 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -1735,7 +1735,10 @@ static TBitem tb_mesh_edit_edge[]= { { 0, "SEPR", 0, NULL}, { 0, "Crease SubSurf|Shift E", 9, NULL}, { 0, "SEPR", 0, NULL}, -{ 0, "Rotate Edge|Ctrl E", 10, NULL}, +{ 0, "Rotate Edge CW|Ctrl E", 10, NULL}, +{ 0, "Rotate Edge CCW|Ctrl E", 11, NULL}, +{ 0, "SEPR", 0, NULL}, +{ 0, "Edgeslide|Ctrl E", 12, NULL}, { -1, "", 0, do_view3d_edit_mesh_edgesmenu}}; static TBitem tb_mesh_edit_face[]= { |