Robert (DetectiveThorn) Wenzlaff's Knife subdivide tool. See previous

message on Bf-committers for description.
This commit is contained in:
Alexander Ewering 2003-10-12 23:43:26 +00:00
parent 1bc0f43da0
commit 5c2005cf06
10 changed files with 509 additions and 112 deletions

View File

@ -155,7 +155,8 @@ typedef enum {
GHOST_kStandardCursorBottomRightCorner,
GHOST_kStandardCursorBottomLeftCorner,
GHOST_kStandardCursorCustom,
GHOST_kStandardCursorNumCursors
GHOST_kStandardCursorNumCursors,
GHOST_kStandardCursorPencil
} GHOST_TStandardCursor;

View File

@ -506,27 +506,28 @@ void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor cursor) c
bool success = true;
LPCSTR id;
switch (cursor) {
case GHOST_kStandardCursorDefault: id = IDC_ARROW;
case GHOST_kStandardCursorRightArrow: id = IDC_ARROW; break;
case GHOST_kStandardCursorLeftArrow: id = IDC_ARROW; break;
case GHOST_kStandardCursorInfo: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
case GHOST_kStandardCursorDestroy: id = IDC_NO; break; // Slashed circle
case GHOST_kStandardCursorHelp: id = IDC_HELP; break; // Arrow and question mark
case GHOST_kStandardCursorCycle: id = IDC_NO; break; // Slashed circle
case GHOST_kStandardCursorSpray: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
case GHOST_kStandardCursorWait: id = IDC_WAIT; break; // Hourglass
case GHOST_kStandardCursorText: id = IDC_IBEAM; break; // I-beam
case GHOST_kStandardCursorCrosshair: id = IDC_CROSS; break; // Crosshair
case GHOST_kStandardCursorUpDown: id = IDC_SIZENS; break; // Double-pointed arrow pointing north and south
case GHOST_kStandardCursorLeftRight: id = IDC_SIZEWE; break; // Double-pointed arrow pointing west and east
case GHOST_kStandardCursorTopSide: id = IDC_UPARROW; break; // Vertical arrow
case GHOST_kStandardCursorBottomSide: id = IDC_SIZENS; break;
case GHOST_kStandardCursorLeftSide: id = IDC_SIZEWE; break;
case GHOST_kStandardCursorTopLeftCorner: id = IDC_SIZENWSE; break;
case GHOST_kStandardCursorTopRightCorner: id = IDC_SIZENESW; break;
case GHOST_kStandardCursorDefault: id = IDC_ARROW; break;
case GHOST_kStandardCursorRightArrow: id = IDC_ARROW; break;
case GHOST_kStandardCursorLeftArrow: id = IDC_ARROW; break;
case GHOST_kStandardCursorInfo: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
case GHOST_kStandardCursorDestroy: id = IDC_NO; break; // Slashed circle
case GHOST_kStandardCursorHelp: id = IDC_HELP; break; // Arrow and question mark
case GHOST_kStandardCursorCycle: id = IDC_NO; break; // Slashed circle
case GHOST_kStandardCursorSpray: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
case GHOST_kStandardCursorWait: id = IDC_WAIT; break; // Hourglass
case GHOST_kStandardCursorText: id = IDC_IBEAM; break; // I-beam
case GHOST_kStandardCursorCrosshair: id = IDC_CROSS; break; // Crosshair
case GHOST_kStandardCursorUpDown: id = IDC_SIZENS; break; // Double-pointed arrow pointing north and south
case GHOST_kStandardCursorLeftRight: id = IDC_SIZEWE; break; // Double-pointed arrow pointing west and east
case GHOST_kStandardCursorTopSide: id = IDC_UPARROW; break; // Vertical arrow
case GHOST_kStandardCursorBottomSide: id = IDC_SIZENS; break;
case GHOST_kStandardCursorLeftSide: id = IDC_SIZEWE; break;
case GHOST_kStandardCursorTopLeftCorner: id = IDC_SIZENWSE; break;
case GHOST_kStandardCursorTopRightCorner: id = IDC_SIZENESW; break;
case GHOST_kStandardCursorBottomRightCorner: id = IDC_SIZENWSE; break;
case GHOST_kStandardCursorBottomLeftCorner: id = IDC_SIZENESW; break;
default:
case GHOST_kStandardCursorBottomLeftCorner: id = IDC_SIZENESW; break;
case GHOST_kStandardCursorPencil: id = IDC_CROSS; break;
default:
success = false;
}

View File

@ -600,6 +600,7 @@ getStandardCursor(
GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
default:
xcursor_id = 0;
}

View File

@ -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.
*/

View File

@ -47,7 +47,8 @@ enum {
CURSOR_Y_MOVE,
CURSOR_HELP,
CURSOR_STD,
CURSOR_NONE
CURSOR_NONE,
CURSOR_PENCIL
};
void set_cursor(int curs);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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 */