diff options
author | Alexander Ewering <blender@instinctive.de> | 2003-10-13 03:43:26 +0400 |
---|---|---|
committer | Alexander Ewering <blender@instinctive.de> | 2003-10-13 03:43:26 +0400 |
commit | 5c2005cf06d786985ebf2213aa25070bdbda2a4f (patch) | |
tree | 7e14efbe3813412840c70452a2b88d5264027176 /source | |
parent | 1bc0f43da04e856586cb674cec5bacc98ca26f8a (diff) |
Robert (DetectiveThorn) Wenzlaff's Knife subdivide tool. See previous
message on Bf-committers for description.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/include/BIF_editmesh.h | 11 | ||||
-rw-r--r-- | source/blender/include/BIF_graphics.h | 3 | ||||
-rw-r--r-- | source/blender/include/BSE_view.h | 1 | ||||
-rw-r--r-- | source/blender/src/editmesh.c | 537 | ||||
-rw-r--r-- | source/blender/src/ghostwinlay.c | 3 | ||||
-rw-r--r-- | source/blender/src/space.c | 5 | ||||
-rw-r--r-- | source/blender/src/view.c | 16 |
7 files changed, 485 insertions, 91 deletions
diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h index 3e545ac4507..2820bbee242 100644 --- a/source/blender/include/BIF_editmesh.h +++ b/source/blender/include/BIF_editmesh.h @@ -48,6 +48,17 @@ void vertexsmooth(void); void make_sticky(void); void deselectall_mesh(void); +/* For Knife subdivide */ +typedef struct CutCurve { + short x; + short y; +} CutCurve; + +void KnifeSubdivide(void); +CutCurve *get_mouse_trail(int * length); +short seg_intersect(struct EditEdge * e, CutCurve *c, int len); +/* End Knife Subdiv */ + /** Aligns the selected TFace's of @a me to the @a v3d, * using the given axis (0-2). Can give a user error. */ diff --git a/source/blender/include/BIF_graphics.h b/source/blender/include/BIF_graphics.h index 90e77e1fb7e..05e0883e81d 100644 --- a/source/blender/include/BIF_graphics.h +++ b/source/blender/include/BIF_graphics.h @@ -47,7 +47,8 @@ enum { CURSOR_Y_MOVE, CURSOR_HELP, CURSOR_STD, - CURSOR_NONE + CURSOR_NONE, + CURSOR_PENCIL }; void set_cursor(int curs); diff --git a/source/blender/include/BSE_view.h b/source/blender/include/BSE_view.h index e6477012c8a..f46de2ba3ff 100644 --- a/source/blender/include/BSE_view.h +++ b/source/blender/include/BSE_view.h @@ -46,6 +46,7 @@ void initgrabz(float x, float y, float z); void window_to_3d(float *vec, short mx, short my); void project_short(float *vec, short *adr); void project_short_noclip(float *vec, short *adr); +void project_float(float *vec, float *adr); int boundbox_clip(float obmat[][4], struct BoundBox *bb); void fdrawline(float x1, float y1, float x2, float y2); void fdrawbox(float x1, float y1, float x2, float y2); diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 81024270d63..4da75e11183 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -2833,19 +2833,22 @@ void hashvert_flag(int flag) MEM_freeN(sortblock); } -static unsigned int cpack_half(unsigned int col1, unsigned int col2) +static unsigned int cpack_fact(unsigned int col1, unsigned int col2, float fact) { char *cp1, *cp2, *cp; unsigned int col=0; + float fact1; + fact1=1-fact; /*result is fact% col1 and (1-fact) % col2 */ + cp1= (char *)&col1; cp2= (char *)&col2; cp= (char *)&col; - cp[0]= (cp1[0]+cp2[0])>>1; - cp[1]= (cp1[1]+cp2[1])>>1; - cp[2]= (cp1[2]+cp2[2])>>1; - cp[3]= (cp1[3]+cp2[3])>>1; + cp[0]= fact*cp1[0]+fact1*cp2[0]; + cp[1]= fact*cp1[1]+fact1*cp2[1]; + cp[2]= fact*cp1[2]+fact1*cp2[2]; + cp[3]= fact*cp1[3]+fact1*cp2[3]; return col; } @@ -2870,14 +2873,15 @@ static void set_wuv(int tot, EditVlak *evl, int v1, int v2, int v3, int v4) float *uv, uvo[4][2]; unsigned int *col, colo[4], col1, col2; int a, v; - - memcpy(uvo, evl->uv, sizeof(uvo)); - uv= evl->uv[0]; - - memcpy(colo, evl->col, sizeof(colo)); - col= evl->col; - - if(tot==4) { + /* Numbers corespond to verts (corner points), */ + /* edge->vn's (center edges), the Center */ + memcpy(uvo, evl->uv, sizeof(uvo)); /* And the quincunx points of a face */ + uv= evl->uv[0]; /* as shown here: */ + /* 2 5 1 */ + memcpy(colo, evl->col, sizeof(colo)); /* 10 13 */ + col= evl->col; /* 6 9 8 */ + /* 11 12 */ + if(tot==4) { /* 3 7 4 */ for(a=0; a<4; a++, uv+=2, col++) { if(a==0) v= v1; else if(a==1) v= v2; @@ -2893,17 +2897,48 @@ static void set_wuv(int tot, EditVlak *evl, int v1, int v2, int v3, int v4) } else if(v==8) { uv_half(uv, uvo[3], uvo[0]); - *col= cpack_half(colo[3], colo[0]); + *col= cpack_fact(colo[3], colo[0], 0.5); } else if(v==9) { uv_quart(uv, uvo[0]); - col1= cpack_half(colo[1], colo[0]); - col2= cpack_half(colo[2], colo[3]); - *col= cpack_half(col1, col2); + col1= cpack_fact(colo[1], colo[0], 0.5); + col2= cpack_fact(colo[2], colo[3], 0.5); + *col= cpack_fact(col1, col2, 0.5); } - else { + /* Cases for adjacent edge square subdivide Real voodoo */ + /* 1/2 closest corner + 1/4 adjacent corners */ + else if (v==10){ /* case test==3 in subdivideflag() */ + uv[0]=(2*uvo[1][0]+uvo[0][0]+uvo[2][0])/4; + uv[1]=(2*uvo[1][1]+uvo[0][1]+uvo[2][1])/4; + col1= cpack_fact(colo[1], colo[0], 0.75); + col2= cpack_fact(colo[2], colo[3], 0.75); + *col= cpack_fact(col1, col2, 0.75); + } + else if (v==11) { /* case of test==6 */ + uv[0]=(2*uvo[2][0]+uvo[1][0]+uvo[3][0])/4; + uv[1]=(2*uvo[2][1]+uvo[1][1]+uvo[3][1])/4; + col1= cpack_fact(colo[1], colo[0], 0.75); + col2= cpack_fact(colo[2], colo[3], 0.75); + *col= cpack_fact(col1, col2, 0.25); + } + else if (v==12) { /* case of test==12 */ + uv[0]=(2*uvo[3][0]+uvo[2][0]+uvo[0][0])/4; + uv[1]=(2*uvo[3][1]+uvo[2][1]+uvo[0][1])/4; + col1= cpack_fact(colo[1], colo[0], 0.25); + col2= cpack_fact(colo[2], colo[3], 0.25); + *col= cpack_fact(col1, col2, 0.25); + } + else if (v==13) { /* case of test==9 */ + uv[0]=(2*uvo[0][0]+uvo[1][0]+uvo[3][0])/4; + uv[1]=(2*uvo[0][1]+uvo[1][1]+uvo[3][1])/4; + col1= cpack_fact(colo[1], colo[0], 0.25); + col2= cpack_fact(colo[2], colo[3], 0.25); + *col= cpack_fact(col1, col2, 0.75); + } + /* default for consecutive verts*/ + else { uv_half(uv, uvo[v-5], uvo[v-4]); - *col= cpack_half(colo[v-5], colo[v-4]); + *col= cpack_fact(colo[v-5], colo[v-4], 0.5); } } } @@ -2920,11 +2955,11 @@ static void set_wuv(int tot, EditVlak *evl, int v1, int v2, int v3, int v4) } else if(v==7) { uv_half(uv, uvo[2], uvo[0]); - *col= cpack_half(colo[2], colo[0]); + *col= cpack_fact(colo[2], colo[0], 0.5); } else { uv_half(uv, uvo[v-5], uvo[v-4]); - *col= cpack_half(colo[v-5], colo[v-4]); + *col= cpack_fact(colo[v-5], colo[v-4], 0.5); } } } @@ -2961,20 +2996,19 @@ static void addvlak_subdiv(EditVlak *evl, int val1, int val2, int val3, int val4 EditVlak *w; EditVert *v1, *v2, *v3, *v4; - if(val1==9) v1= eve; + if(val1>=9) v1= eve; else v1= vert_from_number(evl, val1); - if(val2==9) v2= eve; + if(val2>=9) v2= eve; else v2= vert_from_number(evl, val2); - if(val3==9) v3= eve; + if(val3>=9) v3= eve; else v3= vert_from_number(evl, val3); - if(val4==9) v4= eve; + if(val4>=9) v4= eve; else v4= vert_from_number(evl, val4); w= addvlaklist(v1, v2, v3, v4, evl); - if(w) { if(evl->v4) set_wuv(4, w, val1, val2, val3, val4); else set_wuv(3, w, val1, val2, val3, val4); @@ -3050,7 +3084,7 @@ void subdivideflag(int flag, float rad, int beauty) EditVert *eve; EditEdge *eed, *e1, *e2, *e3, *e4, *nexted; EditVlak *evl; - float fac, vec[3], vec1[3], len1, len2, len3; + float fac, vec[3], vec1[3], len1, len2, len3, percent; short test; if(beauty & B_SMOOTH) { @@ -3063,11 +3097,9 @@ void subdivideflag(int flag, float rad, int beauty) /* edgeflags */ eed= G.eded.first; - while(eed) { - + while((eed) && !(beauty & B_KNIFE)) { if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f= flag; - else eed->f= 0; - + else eed->f= 0; eed= eed->next; } @@ -3101,7 +3133,6 @@ void subdivideflag(int flag, float rad, int beauty) } } else { - /* area */ len1= AreaT3Dfl(evl->v1->co, evl->v2->co, evl->v3->co); if(len1 <= doublimit) { @@ -3110,7 +3141,6 @@ void subdivideflag(int flag, float rad, int beauty) evl->e3->f = 0; } else { - len1= VecLenf(evl->v1->co, evl->v2->co) ; len2= VecLenf(evl->v2->co, evl->v3->co) ; len3= VecLenf(evl->v3->co, evl->v1->co) ; @@ -3141,10 +3171,13 @@ void subdivideflag(int flag, float rad, int beauty) eed= G.eded.first; while(eed) { if(eed->f & flag) { + + if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0; + else percent=0.5; - vec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0; - vec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0; - vec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0; + 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); @@ -3203,9 +3236,8 @@ void subdivideflag(int flag, float rad, int beauty) test+= 8; e4->f= 1; } - if(test) { - if(evl->v4==0) { + if(evl->v4==0) { /* All the permutations of 3 edges*/ if((test & 3)==3) addvlak_subdiv(evl, 2, 2+4, 1+4, 0, 0); if((test & 6)==6) addvlak_subdiv(evl, 3, 3+4, 2+4, 0, 0); if((test & 5)==5) addvlak_subdiv(evl, 1, 1+4, 3+4, 0, 0); @@ -3251,9 +3283,9 @@ void subdivideflag(int flag, float rad, int beauty) evl->e3= addedgelist(evl->v3, evl->v1); } - else { + else { /* All the permutations of 4 faces */ if(test==15) { - /* add a new point */ + /* add a new point in center */ CalcCent4f(vec, evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co); if(beauty & B_SMOOTH) { @@ -3262,7 +3294,7 @@ void subdivideflag(int flag, float rad, int beauty) eve= addvertlist(vec); eve->f |= flag; - + addvlak_subdiv(evl, 2, 2+4, 9, 1+4, eve); addvlak_subdiv(evl, 3, 3+4, 9, 2+4, eve); addvlak_subdiv(evl, 4, 4+4, 9, 3+4, eve); @@ -3272,13 +3304,13 @@ void subdivideflag(int flag, float rad, int beauty) evl->v4= e4->vn; set_wuv(4, evl, 1, 1+4, 9, 4+4); } - else { - if((test & 3)==3) addvlak_subdiv(evl, 1+4, 2, 2+4, 0, 0); - if((test & 6)==6) addvlak_subdiv(evl, 2+4, 3, 3+4, 0, 0); - if((test & 12)==12) addvlak_subdiv(evl, 3+4, 4, 4+4, 0, 0); - if((test & 9)==9) addvlak_subdiv(evl, 4+4, 1, 1+4, 0, 0); + else { + if(((test & 3)==3)&&(test!=3)) addvlak_subdiv(evl, 1+4, 2, 2+4, 0, 0); + if(((test & 6)==6)&&(test!=6)) addvlak_subdiv(evl, 2+4, 3, 3+4, 0, 0); + if(((test & 12)==12)&&(test!=12)) addvlak_subdiv(evl, 3+4, 4, 4+4, 0, 0); + if(((test & 9)==9)&&(test!=9)) addvlak_subdiv(evl, 4+4, 1, 1+4, 0, 0); - if(test==1) { + if(test==1) { /* Edge 1 has new vert */ addvlak_subdiv(evl, 1+4, 2, 3, 0, 0); addvlak_subdiv(evl, 1+4, 3, 4, 0, 0); evl->v2= e1->vn; @@ -3286,14 +3318,14 @@ void subdivideflag(int flag, float rad, int beauty) evl->v4= 0; set_wuv(4, evl, 1, 1+4, 4, 0); } - else if(test==2) { + else if(test==2) { /* Edge 2 has new vert */ addvlak_subdiv(evl, 2+4, 3, 4, 0, 0); addvlak_subdiv(evl, 2+4, 4, 1, 0, 0); evl->v3= e2->vn; evl->v4= 0; set_wuv(4, evl, 1, 2, 2+4, 0); } - else if(test==4) { + else if(test==4) { /* Edge 3 has new vert */ addvlak_subdiv(evl, 3+4, 4, 1, 0, 0); addvlak_subdiv(evl, 3+4, 1, 2, 0, 0); evl->v1= evl->v2; @@ -3302,7 +3334,7 @@ void subdivideflag(int flag, float rad, int beauty) evl->v4= 0; set_wuv(4, evl, 2, 3, 3+4, 0); } - else if(test==8) { + else if(test==8) { /* Edge 4 has new vert */ addvlak_subdiv(evl, 4+4, 1, 2, 0, 0); addvlak_subdiv(evl, 4+4, 2, 3, 0, 0); evl->v1= evl->v3; @@ -3311,71 +3343,110 @@ void subdivideflag(int flag, float rad, int beauty) evl->v4= 0; set_wuv(4, evl, 3, 4, 4+4, 0); } - else if(test==3) { - addvlak_subdiv(evl, 1+4, 2+4, 4, 0, 0); - addvlak_subdiv(evl, 2+4, 3, 4, 0, 0); - evl->v2= e1->vn; - evl->v3= evl->v4; - evl->v4= 0; - set_wuv(4, evl, 1, 1+4, 4, 0); + 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); + eve->f |= flag; + /* Add new faces */ + addvlak_subdiv(evl, 4, 10, 2+4, 3, eve); + addvlak_subdiv(evl, 4, 1, 1+4, 10, eve); + /* orig face becomes small corner */ + evl->v1=e1->vn; + //evl->v2=evl->v2; + evl->v3=e2->vn; + evl->v4=eve; + + set_wuv(4, evl, 1+4, 2, 2+4, 10); } - else if(test==6) { - addvlak_subdiv(evl, 2+4, 3+4, 1, 0, 0); - addvlak_subdiv(evl, 3+4, 4, 1, 0, 0); - evl->v3= e2->vn; - evl->v4= 0; - set_wuv(4, evl, 1, 2, 2+4, 0); + 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); + eve->f |= flag; + /*New faces*/ + addvlak_subdiv(evl, 1, 11, 3+4, 4, eve); + addvlak_subdiv(evl, 1, 2, 2+4, 11, eve); + /* orig face becomes small corner */ + evl->v1=e2->vn; + evl->v2=evl->v3; + evl->v3=e3->vn; + evl->v4=eve; + + set_wuv(4, evl, 2+4, 3, 3+4, 11); } - else if(test==12) { - addvlak_subdiv(evl, 3+4, 4+4, 2, 0, 0); - addvlak_subdiv(evl, 4+4, 1, 2, 0, 0); - evl->v1= evl->v2; - evl->v2= evl->v3; - evl->v3= e3->vn; - evl->v4= 0; - set_wuv(4, evl, 2, 3, 3+4, 0); + 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); + eve->f |= flag; + /*New Faces*/ + addvlak_subdiv(evl, 2, 12, 4+4, 1, eve); + addvlak_subdiv(evl, 2, 3, 3+4, 12, eve); + /* orig face becomes small corner */ + evl->v1=e3->vn; + evl->v2=evl->v4; + evl->v3=e4->vn; + evl->v4=eve; + + set_wuv(4, evl, 3+4, 4, 4+4, 12); } - else if(test==9) { - addvlak_subdiv(evl, 4+4, 1+4, 3, 0, 0); - addvlak_subdiv(evl, 1+4, 2, 3, 0, 0); - evl->v1= evl->v3; - evl->v2= evl->v4; - evl->v3= e4->vn; - evl->v4= 0; - set_wuv(4, evl, 3, 4, 4+4, 0); + 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); + eve->f |= flag; + /*New Faces*/ + addvlak_subdiv(evl, 3, 13, 1+4, 2, eve); + addvlak_subdiv(evl, 3, 4, 4+4, 13, eve); + /* orig face becomes small corner */ + evl->v2=evl->v1; + evl->v1=e4->vn; + evl->v3=e1->vn; + evl->v4=eve; + + set_wuv(4, evl, 4+4, 1, 1+4, 13); } - else if(test==5) { + else if(test==5) { /* 1&3 */ addvlak_subdiv(evl, 1+4, 2, 3, 3+4, 0); evl->v2= e1->vn; evl->v3= e3->vn; set_wuv(4, evl, 1, 1+4, 3+4, 4); } - else if(test==10) { + else if(test==10) { /* 2&4 */ addvlak_subdiv(evl, 2+4, 3, 4, 4+4, 0); evl->v3= e2->vn; evl->v4= e4->vn; set_wuv(4, evl, 1, 2, 2+4, 4+4); - } - - else if(test==7) { + }/* Unfortunately, there is no way to avoid tris on 1 or 3 edges*/ + else if(test==7) { /*1,2&3 */ addvlak_subdiv(evl, 1+4, 2+4, 3+4, 0, 0); evl->v2= e1->vn; evl->v3= e3->vn; set_wuv(4, evl, 1, 1+4, 3+4, 4); } - else if(test==14) { + + else if(test==14) { /* 2,3&4 */ addvlak_subdiv(evl, 2+4, 3+4, 4+4, 0, 0); evl->v3= e2->vn; evl->v4= e4->vn; set_wuv(4, evl, 1, 2, 2+4, 4+4); } - else if(test==13) { + else if(test==13) {/* 1,3&4 */ addvlak_subdiv(evl, 3+4, 4+4, 1+4, 0, 0); evl->v4= e3->vn; evl->v1= e1->vn; set_wuv(4, evl, 1+4, 3, 3, 3+4); } - else if(test==11) { + else if(test==11) { /* 1,2,&4 */ addvlak_subdiv(evl, 4+4, 1+4, 2+4, 0, 0); evl->v1= e4->vn; evl->v2= e2->vn; @@ -3383,7 +3454,7 @@ void subdivideflag(int flag, float rad, int beauty) } } evl->e1= addedgelist(evl->v1, evl->v2); - evl->e2= addedgelist(evl->v2, evl->v3); + evl->e2= addedgelist(evl->v2, evl->v3); if(evl->v4) evl->e3= addedgelist(evl->v3, evl->v4); else evl->e3= addedgelist(evl->v3, evl->v1); if(evl->v4) evl->e4= addedgelist(evl->v4, evl->v1); @@ -6527,3 +6598,293 @@ void editmesh_align_view_to_selected(View3D *v3d, int axis) view3d_align_axis_to_vector(v3d, axis, norm); } } + +/* + +Read a trail of mouse coords and return them as an array of CutCurve structs +len returns number of mouse coords read before commiting with RETKEY +It is up to the caller to free the block when done with it, + +this doesn't belong here..... + */ + +CutCurve *get_mouse_trail(int *len){ + + CutCurve *curve,*temp; + short event, val, ldown=0, restart=0, rubberband=0; + short mval[2], lockaxis=0, lockx=0, locky=0, lastx=0, lasty=0; + int i=0, j, blocks=1, lasti=0; + + *len=0; + curve=(CutCurve *)MEM_callocN(1024*sizeof(CutCurve), "MouseTrail"); + + if (!curve) { + printf("failed to allocate memory in get_mouse_trail()\n"); + return(NULL); + } + mywinset(curarea->win); + glDrawBuffer(GL_FRONT); + persp(0); + event=extern_qread(&val); + while((event != RETKEY ) && (event != RIGHTMOUSE) ){ + event=extern_qread(&val); /* Enter or RMB indicates finish */ + + if (event==ESCKEY){ + for(j=1;j<i;j++) sdrawXORline(curve[j-1].x, curve[j-1].y, curve[j].x, curve[j].y ); + if (curve) MEM_freeN(curve); + *len=0; + return(NULL); + break; + } + + if (rubberband) { /* rubberband mode, undraw last rubberband */ + sdrawXORline(curve[i-1].x, curve[i-1].y,mval[0], mval[1]); + glFlush(); + rubberband=0; + } + + getmouseco_areawin(mval); + + if (lockaxis==1) mval[1]=locky; + if (lockaxis==2) mval[0]=lockx; + + if ( ((i==0) || (mval[0]!=curve[i-1].x) || (mval[1]!=curve[i-1].y)) + && (get_mbut() & L_MOUSE) ){ /* record changes only, if LMB down */ + + lastx=curve[i].x=mval[0]; + lasty=curve[i].y=mval[1]; + + lockaxis=0; + + i++; + + ldown=1; + if (restart) { + for(j=1;j<i;j++) sdrawXORline(curve[j-1].x, curve[j-1].y, curve[j].x, curve[j].y); + if (rubberband) sdrawXORline(curve[j].x, curve[j].y, mval[0], mval[1]); + glFlush(); + rubberband=0; + lasti=i=0; + restart=0; + ldown=0; + } + } + + if ((event==MIDDLEMOUSE)&&(get_mbut()&M_MOUSE)&&(i)){/*MMB Down*/ + /*determine which axis to lock to, or clear if locked */ + if (lockaxis) lockaxis=0; + else if (abs(curve[i-1].x-mval[0]) > abs(curve[i-1].y-mval[1])) lockaxis=1; + else lockaxis=2; + + if (lockaxis) { + lockx=lastx; + locky=lasty; + } + } + + if ((i>1)&&(i!=lasti)) { /*Draw recorded part of curve */ + sdrawXORline(curve[i-2].x, curve[i-2].y, curve[i-1].x, curve[i-1].y); + glFlush(); + } + + if ((i==lasti)&&(i>0)) { /*Draw rubberband */ + sdrawXORline(curve[i-1].x, curve[i-1].y,mval[0], mval[1]); + glFlush(); + rubberband=1; + } + lasti=i; + + if (i>=blocks*1024) { /* reallocate data if out of room */ + temp=curve; + curve=(CutCurve *)MEM_callocN((blocks+1)*1024*sizeof(CutCurve), "MouseTrail"); + if (!curve) { + printf("failed to re-allocate memory in get_mouse_trail()\n"); + return(NULL); + } + memcpy(curve, temp, blocks*1024*sizeof(CutCurve)); + blocks++; + MEM_freeN(temp); + } + } + for(j=1;j<i;j++) { + sdrawXORline(curve[j-1].x, curve[j-1].y, curve[j].x, curve[j].y ); + } + glFlush(); + *len=i; + return(curve); +} + +/* ******************************************************************** */ +/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail + drawn by user. + + Currently mapped to KKey when in MeshEdit mode. + Usage: + Hit K, + Hold LMB down to draw path, hit RETKEY. + ESC cancels as expected. + + Contributed by Robert Wenzlaff (Det. Thorn). +*/ + +void KnifeSubdivide(){ + + int oldcursor, len=0; + short isect=0, mode=0; + CutCurve *curve; + EditEdge *eed; + + if (G.obedit==0) return; + + /* Set a knife cursor here ??? */ + oldcursor=get_cursor(); + set_cursor(CURSOR_PENCIL); + + calc_meshverts_ext(); /*Update screen coords for current window */ + + curve=get_mouse_trail(&len); + + if (curve) mode=pupmenu("Cut Type %t|Intersect%x1|50%%x2|"); + + if (curve && len && mode){ + eed= G.eded.first; + while(eed) { + if((eed->v1->f)&&(eed->v2->f)){ + isect=seg_intersect(eed, curve, len); + if (isect) eed->f=1; + else eed->f=0; + eed->f1=isect; + //printf("isect=%i\n", isect); + } + else { + eed->f=0; + eed->f1=0; + } + eed= eed->next; + } + + if (mode==1) subdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD); + else if (mode==2) subdivideflag(1, 0, B_KNIFE); + + addqueue(curarea->win, REDRAW, 1); + + eed=G.eded.first; + while(eed){ + eed->f=0; + eed->f1=0; + eed=eed->next; + } + } + /* Return ot old cursor and flags...*/ + set_cursor(oldcursor); + if (curve) MEM_freeN(curve); +} + +/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */ + +short seg_intersect(EditEdge *e, CutCurve *c, int len){ +#define MAXSLOPE 100000 + short isect=0; + float x11, y11, x12=0, y12=0, x2max, x2min, y2max; + float y2min, dist, lastdist=0, xdiff2, xdiff1; + float m1, b1, m2, b2, x21, x22, y21, y22, xi; + float yi, x1min, x1max, y1max, y1min, perc=0; + float scr[2], co[4]; + int i; + + /* Get screen coords of verts (v->xs and v->ys clip if off screen */ + VECCOPY(co, e->v1->co); + co[3]= 1.0; + Mat4MulVec4fl(G.obedit->obmat, co); + project_float(co, scr); + x21=scr[0]; + y21=scr[1]; + + VECCOPY(co, e->v2->co); + co[3]= 1.0; + Mat4MulVec4fl(G.obedit->obmat, co); + project_float(co, scr); + x22=scr[0]; + y22=scr[1]; + + xdiff2=(x22-x21); + if (xdiff2) { + m2=(y22-y21)/xdiff2; + b2= ((x22*y21)-(x21*y22))/xdiff2; + } + else { + m2=MAXSLOPE; /* Verticle slope */ + b2=x22; + } + for (i=0; i<len; i++){ + if (i>0){ + x11=x12; + y11=y12; + } + else { + x11=c[i].x; + y11=c[i].y; + } + x12=c[i].x; + y12=c[i].y; + + /* Perp. Distance from point to line */ + if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */ + /* change in sign. Skip extra math */ + else dist=x22-x12; + + if (i==0) lastdist=dist; + + /* if dist changes sign, and intersect point in edge's Bound Box*/ + if ((lastdist*dist)<=0){ + xdiff1=(x12-x11); /* Equation of line between last 2 points */ + if (xdiff1){ + m1=(y12-y11)/xdiff1; + b1= ((x12*y11)-(x11*y12))/xdiff1; + } + else{ + m1=MAXSLOPE; + b1=x12; + } + x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */ + x2min=MIN2(x21,x22)-0.001; /* due to round off error */ + y2max=MAX2(y21,y22)+0.001; + y2min=MIN2(y21,y22)-0.001; + + /* Found an intersect, calc intersect point */ + if (m1==m2){ /* co-incident lines */ + /* cut at 50% of overlap area*/ + x1max=MAX2(x11, x12); + x1min=MIN2(x11, x12); + xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0; + + y1max=MAX2(y11, y12); + y1min=MIN2(y11, y12); + yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0; + } + else if (m2==MAXSLOPE){ + xi=x22; + yi=m1*x22+b1; + } + else if (m1==MAXSLOPE){ + xi=x12; + yi=m2*x12+b2; + } + else { + xi=(b1-b2)/(m2-m1); + yi=(b1*m2-m1*b2)/(m2-m1); + } + + /* Intersect inside bounding box of edge?*/ + if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){ + if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21); + else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/ + isect=32768.0*(perc+0.0000153); + break; + } + } + lastdist=dist; + } + return(isect); +} + diff --git a/source/blender/src/ghostwinlay.c b/source/blender/src/ghostwinlay.c index e4fa0429d28..ffe10f0a19b 100644 --- a/source/blender/src/ghostwinlay.c +++ b/source/blender/src/ghostwinlay.c @@ -71,12 +71,13 @@ static GHOST_TStandardCursor convert_cursor(int curs) { default: case CURSOR_STD: return GHOST_kStandardCursorDefault; case CURSOR_VPAINT: return GHOST_kStandardCursorRightArrow; - case CURSOR_FACESEL: return GHOST_kStandardCursorRightArrow; + case CURSOR_FACESEL: return GHOST_kStandardCursorRightArrow; case CURSOR_WAIT: return GHOST_kStandardCursorWait; case CURSOR_EDIT: return GHOST_kStandardCursorCrosshair; case CURSOR_HELP: return GHOST_kStandardCursorHelp; case CURSOR_X_MOVE: return GHOST_kStandardCursorLeftRight; case CURSOR_Y_MOVE: return GHOST_kStandardCursorUpDown; + case CURSOR_PENCIL: return GHOST_kStandardCursorPencil; } } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 3050fcbe57d..d24c8ce0e02 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -974,7 +974,10 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case KKEY: if(G.obedit) { - if(G.obedit->type==OB_SURF) printknots(); + if (G.qual & LR_SHIFTKEY ){ + if (G.obedit->type==OB_MESH) KnifeSubdivide(); + } + else if(G.obedit->type==OB_SURF) printknots(); } else { if(G.qual & LR_SHIFTKEY) { diff --git a/source/blender/src/view.c b/source/blender/src/view.c index b1d0c367cec..8025d7663e3 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -225,6 +225,22 @@ void project_short_noclip(float *vec, short *adr) } } +void project_float(float *vec, float *adr) +{ + float fx, fy, vec4[4]; + + adr[0]= 3200.0; + VECCOPY(vec4, vec); + vec4[3]= 1.0; + + Mat4MulVec4fl(G.vd->persmat, vec4); + + if( vec4[3]>0.1 ) { + adr[0]= (curarea->winx/2.0)+(curarea->winx/2.0)*vec4[0]/vec4[3]; + adr[1]= (curarea->winy/2.0)+(curarea->winy/2.0)*vec4[1]/vec4[3]; + } +} + int boundbox_clip(float obmat[][4], BoundBox *bb) { /* return 1: draw */ |