Index: source/blender/include/BSE_view.h =================================================================== --- source/blender/include/BSE_view.h (revision 11838) +++ source/blender/include/BSE_view.h (working copy) @@ -76,6 +76,7 @@ void calctrackballvecfirst(struct rcti *area, short *mval, float *vec); void calctrackballvec(struct rcti *area, short *mval, float *vec); void viewmove(int mode); +void view_zoom_mouseloc(float dfac, short *mouseloc); int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize); void setwinmatrixview3d(int winx, int winy, struct rctf *rect); Index: source/blender/src/toets.c =================================================================== --- source/blender/src/toets.c (revision 11838) +++ source/blender/src/toets.c (working copy) @@ -108,6 +108,9 @@ #include "BIF_poseobject.h" +#define VIEW_ZOOM_OUT_FACTOR (1.15f) +#define VIEW_ZOOM_IN_FACTOR (1.0f/VIEW_ZOOM_OUT_FACTOR) + /* ------------------------------------------------------------------------- */ static int is_an_active_object(void *ob) { @@ -155,6 +158,7 @@ float phi, si, q1[4], vec[3]; static int perspo=1; int preview3d_event= 1; + short mouseloc[2]; float new_dist, orig_ofs[3]; @@ -243,14 +247,20 @@ if(G.vd->persp==2) { G.vd->camzoom= MAX2(-30, G.vd->camzoom-5); } - else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f; + else if(G.vd->dist<10.0*G.vd->far) { + getmouseco_areawin(mouseloc); + view_zoom_mouseloc(VIEW_ZOOM_OUT_FACTOR, mouseloc); + } if(G.vd->persp!=1) preview3d_event= 0; } else if(event==PADPLUSKEY) { if(G.vd->persp==2) { G.vd->camzoom= MIN2(300, G.vd->camzoom+5); } - else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f; + else if(G.vd->dist> 0.001*G.vd->grid) { + getmouseco_areawin(mouseloc); + view_zoom_mouseloc(VIEW_ZOOM_IN_FACTOR, mouseloc); + } if(G.vd->persp!=1) preview3d_event= 0; } else if(event==PAD5) { Index: source/blender/src/view.c =================================================================== --- source/blender/src/view.c (revision 11838) +++ source/blender/src/view.c (working copy) @@ -538,7 +538,7 @@ float reverse, oldquat[4], q1[4], si, phi, dist0; float ofs[3], obofs[3]= {0.0f, 0.0f, 0.0f}; int firsttime=1; - short mvalball[2], mval[2], mvalo[2]; + short mvalball[2], mval[2], mvalo[2], mval_area[2]; short use_sel = 0; short preview3d_event= 1; @@ -556,6 +556,7 @@ QUATCOPY(oldquat, G.vd->viewquat); + getmouseco_areawin(mval_area); /* for zoom to mouse loc */ getmouseco_sc(mvalo); /* work with screen coordinates because of trackball function */ mvalball[0]= mvalo[0]; /* needed for turntable to work */ mvalball[1]= mvalo[1]; @@ -728,9 +729,10 @@ } } else if(mode==2) { + float zfac=1.0; if(U.viewzoom==USER_ZOOM_CONT) { // oldstyle zoom - G.vd->dist*= 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0; + zfac = 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0; } else if(U.viewzoom==USER_ZOOM_SCALE) { int ctr[2], len1, len2; @@ -742,14 +744,17 @@ len1 = (int)sqrt((ctr[0] - mval[0])*(ctr[0] - mval[0]) + (ctr[1] - mval[1])*(ctr[1] - mval[1])) + 5; len2 = (int)sqrt((ctr[0] - mvalo[0])*(ctr[0] - mvalo[0]) + (ctr[1] - mvalo[1])*(ctr[1] - mvalo[1])) + 5; - G.vd->dist= dist0 * ((float)len2/len1); + zfac = dist0 * ((float)len2/len1) / G.vd->dist; } else { /* USER_ZOOM_DOLLY */ float len1 = (curarea->winrct.ymax - mval[1]) + 5; float len2 = (curarea->winrct.ymax - mvalo[1]) + 5; - - G.vd->dist= dist0 * (2.0*((len2/len1)-1.0) + 1.0); + zfac = dist0 * (2.0*((len2/len1)-1.0) + 1.0) / G.vd->dist; } + + if(zfac != 1.0 && zfac*G.vd->dist > 0.001*G.vd->grid && + zfac*G.vd->dist < 10.0*G.vd->far) + view_zoom_mouseloc(zfac, mval_area); /* these limits are in toets.c too */ if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; @@ -799,7 +804,51 @@ BIF_view3d_previewrender_signal(curarea, PR_PROJECTED); } + +void view_zoom_mouseloc(float dfac, short *mouseloc) +{ + //if(U.uiflag & USER_MOUSEPOSDOLLY) { + if (1) { + short vb[2]; + float dvec[3]; + float tvec[3]; + float tpos[3]; + float new_dist; + /* find the current window width and height */ + vb[0] = G.vd->area->winx; + vb[1] = G.vd->area->winy; + + tpos[0] = -G.vd->ofs[0]; + tpos[1] = -G.vd->ofs[1]; + tpos[2] = -G.vd->ofs[2]; + + /* Project cursor position into 3D space */ + initgrabz(tpos[0], tpos[1], tpos[2]); + window_to_3d(dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2); + + /* Calculate view target position for dolly */ + tvec[0] = -(tpos[0] + dvec[0]); + tvec[1] = -(tpos[1] + dvec[1]); + tvec[2] = -(tpos[2] + dvec[2]); + + /* Offset to target position and dolly */ + new_dist = G.vd->dist * dfac; + + VECCOPY(G.vd->ofs, tvec); + G.vd->dist = new_dist; + + /* Calculate final offset */ + dvec[0] = tvec[0] + dvec[0] * dfac; + dvec[1] = tvec[1] + dvec[1] * dfac; + dvec[2] = tvec[2] + dvec[2] * dfac; + + VECCOPY(G.vd->ofs, dvec); + } else { + G.vd->dist *= dfac; + } +} + /* Gets the lens and clipping values from a camera of lamp type object */ void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipend) {