From 525e7ac8d0b40b5f11fe9247f8be74a259f5e889 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 9 Apr 2007 11:15:23 +0000 Subject: [PATCH] smooth view transformations, set the smoothview value to about 250 and the view animates when you switch between side, top etc. --- source/blender/include/BSE_drawview.h | 3 + source/blender/makesdna/DNA_userdef_types.h | 2 + source/blender/src/editview.c | 19 ++- source/blender/src/space.c | 23 ++- source/blender/src/toets.c | 66 +++++--- source/blender/src/view.c | 159 +++++++++++++++++--- 6 files changed, 216 insertions(+), 56 deletions(-) diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index 6e612859173..1283ba4fdca 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -78,5 +78,8 @@ int play_anim(int mode); void make_axis_color(char *col, char *col2, char axis); +/* SMOOTHVIEW */ +void smooth_view(struct View3D *v3d, float *ofs, float *quat, float *dist); + #endif /* BSE_DRAWVIEW_H */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index d486f8eae5f..6d2f9411ebf 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -179,6 +179,8 @@ typedef struct UserDef { char versemaster[160]; char verseuser[160]; short recent_files; /* maximum number of recently used files to remember */ + short smooth_viewtx; /* miliseconds to spend spinning the view */ + char pad[6]; } UserDef; extern UserDef U; /* from usiblender.c !!!! */ diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index 6dfdd3cf1c0..225854b1fff 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -2058,6 +2058,10 @@ void view3d_border_zoom(void) short val; float dvec[3], vb[2], xscale, yscale, scale; + /* SMOOTHVIEW */ + float new_dist; + float new_ofs[3]; + /* doesn't work fine for perspective */ if(G.vd->persp==1) return; @@ -2069,12 +2073,18 @@ void view3d_border_zoom(void) vb[0] = G.vd->area->winx; vb[1] = G.vd->area->winy; + new_dist = G.vd->dist; + new_ofs[0] = G.vd->ofs[0]; + new_ofs[1] = G.vd->ofs[1]; + new_ofs[2] = G.vd->ofs[2]; + /* convert the drawn rectangle into 3d space */ - initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); + initgrabz(-new_ofs[0], -new_ofs[1], -new_ofs[2]); + window_to_3d(dvec, (rect.xmin+rect.xmax-vb[0])/2, (rect.ymin+rect.ymax-vb[1])/2); /* center the view to the center of the rectangle */ - VecSubf(G.vd->ofs, G.vd->ofs, dvec); + VecSubf(new_ofs, new_ofs, dvec); /* work out the ratios, so that everything selected fits when we zoom */ xscale = ((rect.xmax-rect.xmin)/vb[0]); @@ -2082,7 +2092,10 @@ void view3d_border_zoom(void) scale = (xscale >= yscale)?xscale:yscale; /* zoom in as required, or as far as we can go */ - G.vd->dist = ((G.vd->dist*scale) >= 0.001*G.vd->grid)? G.vd->dist*scale:0.001*G.vd->grid; + new_dist = ((new_dist*scale) >= 0.001*G.vd->grid)? new_dist*scale:0.001*G.vd->grid; + + smooth_view(G.vd, new_ofs, NULL, &new_dist); + } } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 73fc627ebe6..bd403f878c1 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1331,10 +1331,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) G.vd->camdx= G.vd->camdy= 0.0; else { /*non camera center*/ + float new_ofs[3]; curs= give_cursor(); - G.vd->ofs[0]= -curs[0]; - G.vd->ofs[1]= -curs[1]; - G.vd->ofs[2]= -curs[2]; + new_ofs[0]= -curs[0]; + new_ofs[1]= -curs[1]; + new_ofs[2]= -curs[2]; + smooth_view(G.vd, new_ofs, NULL, NULL); } } doredraw= 1; @@ -1734,10 +1736,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) G.vd->camdx= G.vd->camdy= 0.0; else { /*non camera center*/ + float new_ofs[3]; curs= give_cursor(); - G.vd->ofs[0]= -curs[0]; - G.vd->ofs[1]= -curs[1]; - G.vd->ofs[2]= -curs[2]; + new_ofs[0]= -curs[0]; + new_ofs[1]= -curs[1]; + new_ofs[2]= -curs[2]; + smooth_view(G.vd, new_ofs, NULL, NULL); } scrarea_queue_winredraw(curarea); } @@ -3328,7 +3332,12 @@ void drawinfospace(ScrArea *sa, void *spacedata) (xpos+edgsp+(3*mpref)+(4*midsp)),y1,(mpref),buth, &U.pad_rot_angle, 0, 90, 0, 0, "The rotation step for numerical pad keys (2 4 6 8)"); - + + uiDefButS(block, NUM, B_DRAWINFO, "Smooth View:", + (xpos+edgsp+(4*mpref)+(5*midsp)),y1,(mpref),buth, + &U.smooth_viewtx, 0, 1000, 0, 0, + "The time to animate the view in miliseconds, zero to disable"); + uiDefBut(block, LABEL,0,"Select with:", (xpos+(2*edgsp)+(3*mpref)+(3*midsp)),y6label,mpref,buth, 0, 0, 0, 0, 0, ""); diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 87b76a084fe..63c4d764d74 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -127,6 +127,8 @@ void persptoetsen(unsigned short event) static int perspo=1; int preview3d_event= 1; + float new_quat[4], new_dist; + if(event==PADENTER) { if (G.qual == LR_SHIFTKEY) { view3d_set_1_to_1_viewborder(G.vd); @@ -134,7 +136,8 @@ void persptoetsen(unsigned short event) if (G.vd->persp==2) { G.vd->camzoom= 0; } else { - G.vd->dist= 10.0; + new_dist = 10.0; + smooth_view(G.vd, NULL, NULL, &new_dist); } } } @@ -149,28 +152,35 @@ void persptoetsen(unsigned short event) /* G.vd->persp= 3; */ } else if(event==PAD7) { - G.vd->viewquat[0]= 0.0; - G.vd->viewquat[1]= -1.0; - G.vd->viewquat[2]= 0.0; - G.vd->viewquat[3]= 0.0; + new_quat[0]=0.0; + new_quat[1]=-1.0; + new_quat[2]=0.0; + new_quat[3]=0.0; + G.vd->view= 0; + smooth_view(G.vd, NULL, new_quat, NULL); G.vd->view= 7; + if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; else if(G.vd->persp>=2) G.vd->persp= perspo; } else if(event==PAD1) { - G.vd->viewquat[0]= 0.0; - G.vd->viewquat[1]= 0.0; - G.vd->viewquat[2]= (float)-cos(M_PI/4.0); - G.vd->viewquat[3]= (float)-cos(M_PI/4.0); + new_quat[0]=0.0; + new_quat[1]=0.0; + new_quat[2]=(float)-cos(M_PI/4.0); + new_quat[3]=(float)-cos(M_PI/4.0); + G.vd->view=0; + smooth_view(G.vd, NULL, new_quat, NULL); G.vd->view=1; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; else if(G.vd->persp>=2) G.vd->persp= perspo; } else if(event==PAD3) { - G.vd->viewquat[0]= 0.5; - G.vd->viewquat[1]= -0.5; - G.vd->viewquat[2]= 0.5; - G.vd->viewquat[3]= 0.5; + new_quat[0]= 0.5; + new_quat[1]=-0.5; + new_quat[2]= 0.5; + new_quat[3]= 0.5; + G.vd->view=0; + smooth_view(G.vd, NULL, new_quat, NULL); G.vd->view=3; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; else if(G.vd->persp>=2) G.vd->persp= perspo; @@ -211,28 +221,34 @@ void persptoetsen(unsigned short event) if(event==PAD7) { - G.vd->viewquat[0]= 1.0; - G.vd->viewquat[1]= 0.0; - G.vd->viewquat[2]= 0.0; - G.vd->viewquat[3]= 0.0; + new_quat[0]=1.0; + new_quat[1]=0.0; + new_quat[2]=0.0; + new_quat[3]=0.0; + G.vd->view=0; + smooth_view(G.vd, NULL, new_quat, NULL); G.vd->view=7; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; else if(G.vd->persp>=2) G.vd->persp= perspo; } else if(event==PAD1) { - G.vd->viewquat[0]= (float)cos(M_PI/4.0); - G.vd->viewquat[1]= (float)-sin(M_PI/4.0); - G.vd->viewquat[2]= 0.0; - G.vd->viewquat[3]= 0.0; + new_quat[0]= (float)cos(M_PI/4.0); + new_quat[1]= (float)-sin(M_PI/4.0); + new_quat[2]= 0.0; + new_quat[3]= 0.0; + G.vd->view=0; + smooth_view(G.vd, NULL, new_quat, NULL); G.vd->view=1; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; else if(G.vd->persp>=2) G.vd->persp= perspo; } else if(event==PAD3) { - G.vd->viewquat[0]= 0.5; - G.vd->viewquat[1]= -0.5; - G.vd->viewquat[2]= -0.5; - G.vd->viewquat[3]= -0.5; + new_quat[0]= 0.5; + new_quat[1]= -0.5; + new_quat[2]= -0.5; + new_quat[3]= -0.5; + G.vd->view=0; + smooth_view(G.vd, NULL, new_quat, NULL); G.vd->view=3; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; else if(G.vd->persp>=2) G.vd->persp= perspo; diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 0c8f5ae66e5..5c36d85203a 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -87,6 +87,8 @@ #include "mydevice.h" #include "blendef.h" +#include "PIL_time.h" /* smoothview */ + #define TRACKBALLSIZE (1.1) #define BL_NEAR_CLIP 0.001 @@ -1248,7 +1250,7 @@ void initlocalview() scrarea_queue_winredraw(curarea); } else { - /* clear flags */ + /* clear flags */ base= FIRSTBASE; while(base) { if( base->lay & locallay ) { @@ -1271,7 +1273,12 @@ void centerview() /* like a localview without local! */ Object *ob= OBACT; float size, min[3], max[3], afm[3]; int ok=0; - + + /* SMOOTHVIEW */ + float new_ofs[3]; + float new_dist; + + min[0]= min[1]= min[2]= 1.0e10; max[0]= max[1]= max[2]= -1.0e10; @@ -1340,27 +1347,29 @@ void centerview() /* like a localview without local! */ if(size<=0.01) size= 0.01; - G.vd->ofs[0]= -(min[0]+max[0])/2.0; - G.vd->ofs[1]= -(min[1]+max[1])/2.0; - G.vd->ofs[2]= -(min[2]+max[2])/2.0; - - G.vd->dist= size; + new_ofs[0]= -(min[0]+max[0])/2.0; + new_ofs[1]= -(min[1]+max[1])/2.0; + new_ofs[2]= -(min[2]+max[2])/2.0; + + new_dist = size; // correction for window aspect ratio if(curarea->winy>2 && curarea->winx>2) { size= (float)curarea->winx/(float)curarea->winy; if(size<1.0) size= 1.0/size; - G.vd->dist*= size; + new_dist*= size; } if(G.vd->persp>1) { G.vd->persp= 1; } - - G.vd->cursor[0]= -G.vd->ofs[0]; - G.vd->cursor[1]= -G.vd->ofs[1]; - G.vd->cursor[2]= -G.vd->ofs[2]; - + + G.vd->cursor[0]= -new_ofs[0]; + G.vd->cursor[1]= -new_ofs[1]; + G.vd->cursor[2]= -new_ofs[2]; + + smooth_view(G.vd, new_ofs, NULL, &new_dist); + scrarea_queue_winredraw(curarea); BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); @@ -1425,7 +1434,7 @@ void endlocalview(ScrArea *sa) allqueue(REDRAWVIEW3D, 0); /* because of select */ allqueue(REDRAWOOPS, 0); /* because of select */ BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); - } + } } void view3d_home(int center) @@ -1458,21 +1467,24 @@ void view3d_home(int center) if(size==0.0) ok= 0; if(ok) { - - G.vd->ofs[0]= -(min[0]+max[0])/2.0; - G.vd->ofs[1]= -(min[1]+max[1])/2.0; - G.vd->ofs[2]= -(min[2]+max[2])/2.0; - - G.vd->dist= size; + float new_dist; + float new_ofs[3]; + + new_dist = size; + new_ofs[0]= -(min[0]+max[0])/2.0; + new_ofs[1]= -(min[1]+max[1])/2.0; + new_ofs[2]= -(min[2]+max[2])/2.0; // correction for window aspect ratio if(curarea->winy>2 && curarea->winx>2) { size= (float)curarea->winx/(float)curarea->winy; if(size<1.0) size= 1.0/size; - G.vd->dist*= size; + new_dist*= size; } if(G.vd->persp==2) G.vd->persp= 1; + + smooth_view(G.vd, new_ofs, NULL, &new_dist); scrarea_queue_winredraw(curarea); } @@ -1500,3 +1512,108 @@ void view3d_align_axis_to_vector(View3D *v3d, int axisidx, float vec[3]) if (v3d->persp>=2) v3d->persp= 0; /* switch out of camera mode */ } + + +/* SMOOTHVIEW */ +void smooth_view(View3D *v3d, float *ofs, float *quat, float *dist) +{ + /* View Animation enabled */ + if (U.smooth_viewtx) { + int i; + char changed = 0; + float step = 0.0, step_inv; + float orig_dist; + float orig_quat[4]; + float orig_ofs[3]; + + double time_allowed, time_current, time_start; + + /* if there is no difference, return */ + changed = 0; /* zero means no difference */ + if (dist) { + if ((*dist) != v3d->dist) + changed = 1; + } + + if (!changed && ofs) { + if ((ofs[0]!=v3d->ofs[0]) || + (ofs[1]!=v3d->ofs[1]) || + (ofs[2]!=v3d->ofs[2]) ) + changed = 1; + } + + if (!changed && quat ) { + if ((quat[0]!=v3d->viewquat[0]) || + (quat[1]!=v3d->viewquat[1]) || + (quat[2]!=v3d->viewquat[2]) || + (quat[3]!=v3d->viewquat[3]) ) + changed = 1; + } + + /* The new view is different from teh old one + * so animate the view */ + if (changed) { + + /* store original values */ + VECCOPY(orig_ofs, v3d->ofs); + QUATCOPY(orig_quat, v3d->viewquat); + orig_dist = v3d->dist; + + time_allowed= (float)U.smooth_viewtx / 1000.0; + time_current = time_start = PIL_check_seconds_timer(); + + /* if this is view rotation only + * we can decrease the time allowed by + * the angle between quats + * this means small rotations wont lag */ + if (quat && !ofs && !dist) { + float vec1[3], vec2[3]; + VECCOPY(vec1, quat); + VECCOPY(vec2, v3d->viewquat); + Normalize(vec1); + Normalize(vec2); + /* scale the time allowed by the rotation */ + time_allowed *= NormalizedVecAngle2(vec1, vec2)/(M_PI/2); + } + + while (time_start + time_allowed > time_current) { + + step = (float)((time_current-time_start) / time_allowed); + + /* ease in/out */ + if (step < 0.5) step = pow(step*2, 2)/2; + else step = 1-(pow(2*(1-step) ,2)/2); + + step_inv = 1-step; + + if (ofs) + for (i=0; i<3; i++) + v3d->ofs[i] = ofs[i]*step + orig_ofs[i]*step_inv; + + if (quat) + QuatInterpol(v3d->viewquat, orig_quat, quat, step); + + if (dist) { + v3d->dist = ((*dist)*step) + (orig_dist*step_inv); + } + + /*redraw the view*/ + scrarea_do_windraw(curarea); + screen_swapbuffers(); + + time_current= PIL_check_seconds_timer(); + } + } + } + + /* set these values even if animation is enabled because flaot + * error will make then not quite accurate */ + if (ofs) + VECCOPY(v3d->ofs, ofs); + if (quat) + QUATCOPY(v3d->viewquat, quat); + if (dist) + v3d->dist = *dist; + +} +