smooth view transformations, set the smoothview value to about 250 and the view animates when you switch between side, top etc.

This commit is contained in:
Campbell Barton 2007-04-09 11:15:23 +00:00
parent ad88bfae38
commit 525e7ac8d0
6 changed files with 216 additions and 56 deletions

@ -78,5 +78,8 @@ int play_anim(int mode);
void make_axis_color(char *col, char *col2, char axis); 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 */ #endif /* BSE_DRAWVIEW_H */

@ -179,6 +179,8 @@ typedef struct UserDef {
char versemaster[160]; char versemaster[160];
char verseuser[160]; char verseuser[160];
short recent_files; /* maximum number of recently used files to remember */ short recent_files; /* maximum number of recently used files to remember */
short smooth_viewtx; /* miliseconds to spend spinning the view */
char pad[6];
} UserDef; } UserDef;
extern UserDef U; /* from usiblender.c !!!! */ extern UserDef U; /* from usiblender.c !!!! */

@ -2058,6 +2058,10 @@ void view3d_border_zoom(void)
short val; short val;
float dvec[3], vb[2], xscale, yscale, scale; float dvec[3], vb[2], xscale, yscale, scale;
/* SMOOTHVIEW */
float new_dist;
float new_ofs[3];
/* doesn't work fine for perspective */ /* doesn't work fine for perspective */
if(G.vd->persp==1) if(G.vd->persp==1)
return; return;
@ -2069,12 +2073,18 @@ void view3d_border_zoom(void)
vb[0] = G.vd->area->winx; vb[0] = G.vd->area->winx;
vb[1] = G.vd->area->winy; 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 */ /* 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); 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 */ /* 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 */ /* work out the ratios, so that everything selected fits when we zoom */
xscale = ((rect.xmax-rect.xmin)/vb[0]); xscale = ((rect.xmax-rect.xmin)/vb[0]);
@ -2082,7 +2092,10 @@ void view3d_border_zoom(void)
scale = (xscale >= yscale)?xscale:yscale; scale = (xscale >= yscale)?xscale:yscale;
/* zoom in as required, or as far as we can go */ /* 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);
} }
} }

@ -1331,10 +1331,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
G.vd->camdx= G.vd->camdy= 0.0; G.vd->camdx= G.vd->camdy= 0.0;
else { else {
/*non camera center*/ /*non camera center*/
float new_ofs[3];
curs= give_cursor(); curs= give_cursor();
G.vd->ofs[0]= -curs[0]; new_ofs[0]= -curs[0];
G.vd->ofs[1]= -curs[1]; new_ofs[1]= -curs[1];
G.vd->ofs[2]= -curs[2]; new_ofs[2]= -curs[2];
smooth_view(G.vd, new_ofs, NULL, NULL);
} }
} }
doredraw= 1; doredraw= 1;
@ -1734,10 +1736,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
G.vd->camdx= G.vd->camdy= 0.0; G.vd->camdx= G.vd->camdy= 0.0;
else { else {
/*non camera center*/ /*non camera center*/
float new_ofs[3];
curs= give_cursor(); curs= give_cursor();
G.vd->ofs[0]= -curs[0]; new_ofs[0]= -curs[0];
G.vd->ofs[1]= -curs[1]; new_ofs[1]= -curs[1];
G.vd->ofs[2]= -curs[2]; new_ofs[2]= -curs[2];
smooth_view(G.vd, new_ofs, NULL, NULL);
} }
scrarea_queue_winredraw(curarea); scrarea_queue_winredraw(curarea);
} }
@ -3328,7 +3332,12 @@ void drawinfospace(ScrArea *sa, void *spacedata)
(xpos+edgsp+(3*mpref)+(4*midsp)),y1,(mpref),buth, (xpos+edgsp+(3*mpref)+(4*midsp)),y1,(mpref),buth,
&U.pad_rot_angle, 0, 90, 0, 0, &U.pad_rot_angle, 0, 90, 0, 0,
"The rotation step for numerical pad keys (2 4 6 8)"); "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:", uiDefBut(block, LABEL,0,"Select with:",
(xpos+(2*edgsp)+(3*mpref)+(3*midsp)),y6label,mpref,buth, (xpos+(2*edgsp)+(3*mpref)+(3*midsp)),y6label,mpref,buth,
0, 0, 0, 0, 0, ""); 0, 0, 0, 0, 0, "");

@ -127,6 +127,8 @@ void persptoetsen(unsigned short event)
static int perspo=1; static int perspo=1;
int preview3d_event= 1; int preview3d_event= 1;
float new_quat[4], new_dist;
if(event==PADENTER) { if(event==PADENTER) {
if (G.qual == LR_SHIFTKEY) { if (G.qual == LR_SHIFTKEY) {
view3d_set_1_to_1_viewborder(G.vd); view3d_set_1_to_1_viewborder(G.vd);
@ -134,7 +136,8 @@ void persptoetsen(unsigned short event)
if (G.vd->persp==2) { if (G.vd->persp==2) {
G.vd->camzoom= 0; G.vd->camzoom= 0;
} else { } 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; */ /* G.vd->persp= 3; */
} }
else if(event==PAD7) { else if(event==PAD7) {
G.vd->viewquat[0]= 0.0; new_quat[0]=0.0;
G.vd->viewquat[1]= -1.0; new_quat[1]=-1.0;
G.vd->viewquat[2]= 0.0; new_quat[2]=0.0;
G.vd->viewquat[3]= 0.0; new_quat[3]=0.0;
G.vd->view= 0;
smooth_view(G.vd, NULL, new_quat, NULL);
G.vd->view= 7; G.vd->view= 7;
if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
else if(G.vd->persp>=2) G.vd->persp= perspo; else if(G.vd->persp>=2) G.vd->persp= perspo;
} }
else if(event==PAD1) { else if(event==PAD1) {
G.vd->viewquat[0]= 0.0; new_quat[0]=0.0;
G.vd->viewquat[1]= 0.0; new_quat[1]=0.0;
G.vd->viewquat[2]= (float)-cos(M_PI/4.0); new_quat[2]=(float)-cos(M_PI/4.0);
G.vd->viewquat[3]= (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; G.vd->view=1;
if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
else if(G.vd->persp>=2) G.vd->persp= perspo; else if(G.vd->persp>=2) G.vd->persp= perspo;
} }
else if(event==PAD3) { else if(event==PAD3) {
G.vd->viewquat[0]= 0.5; new_quat[0]= 0.5;
G.vd->viewquat[1]= -0.5; new_quat[1]=-0.5;
G.vd->viewquat[2]= 0.5; new_quat[2]= 0.5;
G.vd->viewquat[3]= 0.5; new_quat[3]= 0.5;
G.vd->view=0;
smooth_view(G.vd, NULL, new_quat, NULL);
G.vd->view=3; G.vd->view=3;
if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
else if(G.vd->persp>=2) G.vd->persp= perspo; else if(G.vd->persp>=2) G.vd->persp= perspo;
@ -211,28 +221,34 @@ void persptoetsen(unsigned short event)
if(event==PAD7) { if(event==PAD7) {
G.vd->viewquat[0]= 1.0; new_quat[0]=1.0;
G.vd->viewquat[1]= 0.0; new_quat[1]=0.0;
G.vd->viewquat[2]= 0.0; new_quat[2]=0.0;
G.vd->viewquat[3]= 0.0; new_quat[3]=0.0;
G.vd->view=0;
smooth_view(G.vd, NULL, new_quat, NULL);
G.vd->view=7; G.vd->view=7;
if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
else if(G.vd->persp>=2) G.vd->persp= perspo; else if(G.vd->persp>=2) G.vd->persp= perspo;
} }
else if(event==PAD1) { else if(event==PAD1) {
G.vd->viewquat[0]= (float)cos(M_PI/4.0); new_quat[0]= (float)cos(M_PI/4.0);
G.vd->viewquat[1]= (float)-sin(M_PI/4.0); new_quat[1]= (float)-sin(M_PI/4.0);
G.vd->viewquat[2]= 0.0; new_quat[2]= 0.0;
G.vd->viewquat[3]= 0.0; new_quat[3]= 0.0;
G.vd->view=0;
smooth_view(G.vd, NULL, new_quat, NULL);
G.vd->view=1; G.vd->view=1;
if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
else if(G.vd->persp>=2) G.vd->persp= perspo; else if(G.vd->persp>=2) G.vd->persp= perspo;
} }
else if(event==PAD3) { else if(event==PAD3) {
G.vd->viewquat[0]= 0.5; new_quat[0]= 0.5;
G.vd->viewquat[1]= -0.5; new_quat[1]= -0.5;
G.vd->viewquat[2]= -0.5; new_quat[2]= -0.5;
G.vd->viewquat[3]= -0.5; new_quat[3]= -0.5;
G.vd->view=0;
smooth_view(G.vd, NULL, new_quat, NULL);
G.vd->view=3; G.vd->view=3;
if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0; if (U.uiflag & USER_AUTOPERSP) G.vd->persp= 0;
else if(G.vd->persp>=2) G.vd->persp= perspo; else if(G.vd->persp>=2) G.vd->persp= perspo;

@ -87,6 +87,8 @@
#include "mydevice.h" #include "mydevice.h"
#include "blendef.h" #include "blendef.h"
#include "PIL_time.h" /* smoothview */
#define TRACKBALLSIZE (1.1) #define TRACKBALLSIZE (1.1)
#define BL_NEAR_CLIP 0.001 #define BL_NEAR_CLIP 0.001
@ -1248,7 +1250,7 @@ void initlocalview()
scrarea_queue_winredraw(curarea); scrarea_queue_winredraw(curarea);
} }
else { else {
/* clear flags */ /* clear flags */
base= FIRSTBASE; base= FIRSTBASE;
while(base) { while(base) {
if( base->lay & locallay ) { if( base->lay & locallay ) {
@ -1271,7 +1273,12 @@ void centerview() /* like a localview without local! */
Object *ob= OBACT; Object *ob= OBACT;
float size, min[3], max[3], afm[3]; float size, min[3], max[3], afm[3];
int ok=0; int ok=0;
/* SMOOTHVIEW */
float new_ofs[3];
float new_dist;
min[0]= min[1]= min[2]= 1.0e10; min[0]= min[1]= min[2]= 1.0e10;
max[0]= max[1]= max[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; if(size<=0.01) size= 0.01;
G.vd->ofs[0]= -(min[0]+max[0])/2.0; new_ofs[0]= -(min[0]+max[0])/2.0;
G.vd->ofs[1]= -(min[1]+max[1])/2.0; new_ofs[1]= -(min[1]+max[1])/2.0;
G.vd->ofs[2]= -(min[2]+max[2])/2.0; new_ofs[2]= -(min[2]+max[2])/2.0;
G.vd->dist= size; new_dist = size;
// correction for window aspect ratio // correction for window aspect ratio
if(curarea->winy>2 && curarea->winx>2) { if(curarea->winy>2 && curarea->winx>2) {
size= (float)curarea->winx/(float)curarea->winy; size= (float)curarea->winx/(float)curarea->winy;
if(size<1.0) size= 1.0/size; if(size<1.0) size= 1.0/size;
G.vd->dist*= size; new_dist*= size;
} }
if(G.vd->persp>1) { if(G.vd->persp>1) {
G.vd->persp= 1; G.vd->persp= 1;
} }
G.vd->cursor[0]= -G.vd->ofs[0]; G.vd->cursor[0]= -new_ofs[0];
G.vd->cursor[1]= -G.vd->ofs[1]; G.vd->cursor[1]= -new_ofs[1];
G.vd->cursor[2]= -G.vd->ofs[2]; G.vd->cursor[2]= -new_ofs[2];
smooth_view(G.vd, new_ofs, NULL, &new_dist);
scrarea_queue_winredraw(curarea); scrarea_queue_winredraw(curarea);
BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
@ -1425,7 +1434,7 @@ void endlocalview(ScrArea *sa)
allqueue(REDRAWVIEW3D, 0); /* because of select */ allqueue(REDRAWVIEW3D, 0); /* because of select */
allqueue(REDRAWOOPS, 0); /* because of select */ allqueue(REDRAWOOPS, 0); /* because of select */
BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
} }
} }
void view3d_home(int center) void view3d_home(int center)
@ -1458,21 +1467,24 @@ void view3d_home(int center)
if(size==0.0) ok= 0; if(size==0.0) ok= 0;
if(ok) { if(ok) {
float new_dist;
G.vd->ofs[0]= -(min[0]+max[0])/2.0; float new_ofs[3];
G.vd->ofs[1]= -(min[1]+max[1])/2.0;
G.vd->ofs[2]= -(min[2]+max[2])/2.0; new_dist = size;
new_ofs[0]= -(min[0]+max[0])/2.0;
G.vd->dist= size; new_ofs[1]= -(min[1]+max[1])/2.0;
new_ofs[2]= -(min[2]+max[2])/2.0;
// correction for window aspect ratio // correction for window aspect ratio
if(curarea->winy>2 && curarea->winx>2) { if(curarea->winy>2 && curarea->winx>2) {
size= (float)curarea->winx/(float)curarea->winy; size= (float)curarea->winx/(float)curarea->winy;
if(size<1.0) size= 1.0/size; if(size<1.0) size= 1.0/size;
G.vd->dist*= size; new_dist*= size;
} }
if(G.vd->persp==2) G.vd->persp= 1; if(G.vd->persp==2) G.vd->persp= 1;
smooth_view(G.vd, new_ofs, NULL, &new_dist);
scrarea_queue_winredraw(curarea); 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 */ 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;
}