diff options
Diffstat (limited to 'source/blender/src/view.c')
-rw-r--r-- | source/blender/src/view.c | 2558 |
1 files changed, 0 insertions, 2558 deletions
diff --git a/source/blender/src/view.c b/source/blender/src/view.c deleted file mode 100644 index 258e4fd99e0..00000000000 --- a/source/blender/src/view.c +++ /dev/null @@ -1,2558 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Trackball math (in calctrackballvec()) Copyright (C) Silicon Graphics, Inc. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include <math.h> -#include <string.h> - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef WIN32 -#include <io.h> -#else -#include <unistd.h> -#endif - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "DNA_action_types.h" -#include "DNA_armature_types.h" -#include "DNA_camera_types.h" -#include "DNA_lamp_types.h" -#include "DNA_object_types.h" -#include "DNA_screen_types.h" -#include "DNA_scene_types.h" -#include "DNA_space_types.h" -#include "DNA_userdef_types.h" -#include "DNA_view3d_types.h" - -#include "BKE_action.h" -#include "BKE_anim.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_object.h" -#include "BKE_sculpt.h" -#include "BKE_utildefines.h" - -#include "BIF_transform.h" -#include "BIF_editparticle.h" -#include "BIF_gl.h" -#include "BIF_previewrender.h" -#include "BIF_mywindow.h" -#include "BIF_retopo.h" -#include "BIF_space.h" -#include "BIF_screen.h" -#include "BIF_toolbox.h" - -#include "BSE_view.h" -#include "BSE_edit.h" /* For countall */ -#include "BSE_drawview.h" /* For inner_play_anim_loop */ - -#include "BDR_drawobject.h" /* For draw_object */ -#include "BDR_editface.h" /* For minmax_tface */ -#include "BDR_sculptmode.h" - -#include "mydevice.h" -#include "blendef.h" -#include "transform.h" - -#include "PIL_time.h" /* smoothview */ -#include <float.h> - -#define TRACKBALLSIZE (1.1) -#define BL_NEAR_CLIP 0.001 - -#define COS45 0.70710678118654746 -#define SIN45 COS45 - - -/* local prototypes ----------*/ -void setcameratoview3d(void); /* windows.c & toets.c */ - -void persp_general(int a) -{ - /* for all window types, not 3D */ - - if(a== 0) { - glPushMatrix(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - - myortho2(-0.375f, ((float)(curarea->winx))-0.375f, -0.375f, ((float)(curarea->winy))-0.375f); - glLoadIdentity(); - } - else if(a== 1) { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } -} - -void persp(int a) -{ - /* only 3D windows */ - - if(curarea->spacetype!=SPACE_VIEW3D) persp_general(a); - else if(a == PERSP_STORE) { // only store - glMatrixMode(GL_PROJECTION); - mygetmatrix(G.vd->winmat1); - glMatrixMode(GL_MODELVIEW); - mygetmatrix(G.vd->viewmat1); - } - else if(a== PERSP_WIN) { // only set - myortho2(-0.375f, (float)(curarea->winx)-0.375f, -0.375f, (float)(curarea->winy)-0.375f); - glLoadIdentity(); - } - else if(a== PERSP_VIEW) { - glMatrixMode(GL_PROJECTION); - myloadmatrix(G.vd->winmat1); // put back - Mat4CpyMat4(curarea->winmat, G.vd->winmat1); // to be sure? - glMatrixMode(GL_MODELVIEW); - myloadmatrix(G.vd->viewmat); // put back - - } -} - -/* create intersection ray in view Z direction at mouse coordinates */ -void viewray(short mval[2], float ray_start[3], float ray_normal[3]) -{ - float ray_end[3]; - viewline(mval, ray_start, ray_end); - VecSubf(ray_normal, ray_end, ray_start); - Normalize(ray_normal); -} - -/* create intersection coordinates in view Z direction at mouse coordinates */ -void viewline(short mval[2], float ray_start[3], float ray_end[3]) -{ - float vec[4]; - - if(G.vd->persp != V3D_ORTHO){ - vec[0]= 2.0f * mval[0] / curarea->winx - 1; - vec[1]= 2.0f * mval[1] / curarea->winy - 1; - vec[2]= -1.0f; - vec[3]= 1.0f; - - Mat4MulVec4fl(G.vd->persinv, vec); - VecMulf(vec, 1.0f / vec[3]); - - VECCOPY(ray_start, G.vd->viewinv[3]); - VECSUB(vec, vec, ray_start); - Normalize(vec); - - VECADDFAC(ray_start, G.vd->viewinv[3], vec, G.vd->near); - VECADDFAC(ray_end, G.vd->viewinv[3], vec, G.vd->far); - } - else { - vec[0] = 2.0f * mval[0] / curarea->winx - 1; - vec[1] = 2.0f * mval[1] / curarea->winy - 1; - vec[2] = 0.0f; - vec[3] = 1.0f; - - Mat4MulVec4fl(G.vd->persinv, vec); - - VECADDFAC(ray_start, vec, G.vd->viewinv[2], 1000.0f); - VECADDFAC(ray_end, vec, G.vd->viewinv[2], -1000.0f); - } -} - -void initgrabz(float x, float y, float z) -{ - if(G.vd==NULL) return; - G.vd->zfac= G.vd->persmat[0][3]*x+ G.vd->persmat[1][3]*y+ G.vd->persmat[2][3]*z+ G.vd->persmat[3][3]; - - /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that - * (accounting for near zero values) - * */ - if (G.vd->zfac < 1.e-6f && G.vd->zfac > -1.e-6f) G.vd->zfac = 1.0f; - - /* Negative zfac means x, y, z was behind the camera (in perspective). - * This gives flipped directions, so revert back to ok default case. - */ - if (G.vd->zfac < 0.0f) G.vd->zfac = 1.0f; -} - -void window_to_3d(float *vec, short mx, short my) -{ - /* always call initgrabz */ - float dx, dy; - - dx= 2.0f*mx*G.vd->zfac/curarea->winx; - dy= 2.0f*my*G.vd->zfac/curarea->winy; - - vec[0]= (G.vd->persinv[0][0]*dx + G.vd->persinv[1][0]*dy); - vec[1]= (G.vd->persinv[0][1]*dx + G.vd->persinv[1][1]*dy); - vec[2]= (G.vd->persinv[0][2]*dx + G.vd->persinv[1][2]*dy); -} - -void project_short(float *vec, short *adr) /* clips */ -{ - float fx, fy, vec4[4]; - - adr[0]= IS_CLIPPED; - - if(G.vd->flag & V3D_CLIPPING) { - if(view3d_test_clipping(G.vd, vec)) - return; - } - - VECCOPY(vec4, vec); - vec4[3]= 1.0; - Mat4MulVec4fl(G.vd->persmat, vec4); - - if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx= (curarea->winx/2)*(1 + vec4[0]/vec4[3]); - - if( fx>0 && fx<curarea->winx) { - - fy= (curarea->winy/2)*(1 + vec4[1]/vec4[3]); - - if(fy>0.0 && fy< (float)curarea->winy) { - adr[0]= (short)floor(fx); - adr[1]= (short)floor(fy); - } - } - } -} - -void project_int(float *vec, int *adr) -{ - float fx, fy, vec4[4]; - - adr[0]= (int)2140000000.0f; - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(G.vd->persmat, vec4); - - if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx= (curarea->winx/2)*(1 + vec4[0]/vec4[3]); - - if( fx>-2140000000.0f && fx<2140000000.0f) { - fy= (curarea->winy/2)*(1 + vec4[1]/vec4[3]); - - if(fy>-2140000000.0f && fy<2140000000.0f) { - adr[0]= (int)floor(fx); - adr[1]= (int)floor(fy); - } - } - } -} - -void project_int_noclip(float *vec, int *adr) -{ - float fx, fy, vec4[4]; - - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(G.vd->persmat, vec4); - - if( fabs(vec4[3]) > BL_NEAR_CLIP ) { - fx = (curarea->winx/2)*(1 + vec4[0]/vec4[3]); - fy = (curarea->winy/2)*(1 + vec4[1]/vec4[3]); - - adr[0] = (int)floor(fx); - adr[1] = (int)floor(fy); - } - else - { - adr[0] = curarea->winx / 2; - adr[1] = curarea->winy / 2; - } -} - -void project_short_noclip(float *vec, short *adr) -{ - float fx, fy, vec4[4]; - - adr[0]= IS_CLIPPED; - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(G.vd->persmat, vec4); - - if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx= (curarea->winx/2)*(1 + vec4[0]/vec4[3]); - - if( fx>-32700 && fx<32700) { - - fy= (curarea->winy/2)*(1 + vec4[1]/vec4[3]); - - if(fy>-32700.0 && fy<32700.0) { - adr[0]= (short)floor(fx); - adr[1]= (short)floor(fy); - } - } - } -} - -void project_float(float *vec, float *adr) -{ - float vec4[4]; - - adr[0]= IS_CLIPPED; - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(G.vd->persmat, vec4); - - if( vec4[3]>BL_NEAR_CLIP ) { - adr[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*vec4[0]/vec4[3]; - adr[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*vec4[1]/vec4[3]; - } -} - -void project_float_noclip(float *vec, float *adr) -{ - float vec4[4]; - - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(G.vd->persmat, vec4); - - if( fabs(vec4[3]) > BL_NEAR_CLIP ) { - adr[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*vec4[0]/vec4[3]; - adr[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*vec4[1]/vec4[3]; - } - else - { - adr[0] = curarea->winx / 2.0f; - adr[1] = curarea->winy / 2.0f; - } -} - -void view3d_get_object_project_mat(ScrArea *area, Object *ob, float pmat[4][4], float vmat[4][4]) -{ - if (area->spacetype!=SPACE_VIEW3D || !area->spacedata.first) { - Mat4One(pmat); - Mat4One(vmat); - } else { - View3D *vd = area->spacedata.first; - - Mat4MulMat4(vmat, ob->obmat, vd->viewmat); - Mat4MulMat4(pmat, vmat, vd->winmat1); - Mat4CpyMat4(vmat, ob->obmat); - } -} - -/* projectmat brings it to window coords, wmat to rotated world space */ -void view3d_project_short_clip(ScrArea *area, float *vec, short *adr, float projmat[4][4], float wmat[4][4]) -{ - View3D *v3d= area->spacedata.first; - float fx, fy, vec4[4]; - - adr[0]= IS_CLIPPED; - - /* clipplanes in eye space */ - if(v3d->flag & V3D_CLIPPING) { - VECCOPY(vec4, vec); - Mat4MulVecfl(wmat, vec4); - if(view3d_test_clipping(v3d, vec4)) - return; - } - - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(projmat, vec4); - - /* clipplanes in window space */ - if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx= (area->winx/2)*(1 + vec4[0]/vec4[3]); - - if( fx>0 && fx<area->winx) { - - fy= (area->winy/2)*(1 + vec4[1]/vec4[3]); - - if(fy>0.0 && fy< (float)area->winy) { - adr[0]= (short)floor(fx); - adr[1]= (short)floor(fy); - } - } - } -} - -void view3d_project_short_noclip(ScrArea *area, float *vec, short *adr, float mat[4][4]) -{ - float fx, fy, vec4[4]; - - adr[0]= IS_CLIPPED; - - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(mat, vec4); - - if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx= (area->winx/2)*(1 + vec4[0]/vec4[3]); - - if( fx>-32700 && fx<32700) { - - fy= (area->winy/2)*(1 + vec4[1]/vec4[3]); - - if(fy>-32700.0 && fy<32700.0) { - adr[0]= (short)floor(fx); - adr[1]= (short)floor(fy); - } - } - } -} - -void view3d_project_float(ScrArea *area, float *vec, float *adr, float mat[4][4]) -{ - float vec4[4]; - - adr[0]= IS_CLIPPED; - VECCOPY(vec4, vec); - vec4[3]= 1.0; - - Mat4MulVec4fl(mat, vec4); - - if( vec4[3]>FLT_EPSILON ) { - adr[0] = (float)(area->winx/2.0f)+(area->winx/2.0f)*vec4[0]/vec4[3]; - adr[1] = (float)(area->winy/2.0f)+(area->winy/2.0f)*vec4[1]/vec4[3]; - } else { - adr[0] = adr[1] = 0.0f; - } -} - -int boundbox_clip(float obmat[][4], BoundBox *bb) -{ - /* return 1: draw */ - - float mat[4][4]; - float vec[4], min, max; - int a, flag= -1, fl; - - if(bb==NULL) return 1; - if(bb->flag & OB_BB_DISABLED) return 1; - - Mat4MulMat4(mat, obmat, G.vd->persmat); - - for(a=0; a<8; a++) { - VECCOPY(vec, bb->vec[a]); - vec[3]= 1.0; - Mat4MulVec4fl(mat, vec); - max= vec[3]; - min= -vec[3]; - - fl= 0; - if(vec[0] < min) fl+= 1; - if(vec[0] > max) fl+= 2; - if(vec[1] < min) fl+= 4; - if(vec[1] > max) fl+= 8; - if(vec[2] < min) fl+= 16; - if(vec[2] > max) fl+= 32; - - flag &= fl; - if(flag==0) return 1; - } - - return 0; - -} - -void fdrawline(float x1, float y1, float x2, float y2) -{ - float v[2]; - - glBegin(GL_LINE_STRIP); - v[0] = x1; v[1] = y1; - glVertex2fv(v); - v[0] = x2; v[1] = y2; - glVertex2fv(v); - glEnd(); -} - -void fdrawbox(float x1, float y1, float x2, float y2) -{ - float v[2]; - - glBegin(GL_LINE_STRIP); - - v[0] = x1; v[1] = y1; - glVertex2fv(v); - v[0] = x1; v[1] = y2; - glVertex2fv(v); - v[0] = x2; v[1] = y2; - glVertex2fv(v); - v[0] = x2; v[1] = y1; - glVertex2fv(v); - v[0] = x1; v[1] = y1; - glVertex2fv(v); - - glEnd(); -} - -void sdrawline(short x1, short y1, short x2, short y2) -{ - short v[2]; - - glBegin(GL_LINE_STRIP); - v[0] = x1; v[1] = y1; - glVertex2sv(v); - v[0] = x2; v[1] = y2; - glVertex2sv(v); - glEnd(); -} - -void sdrawbox(short x1, short y1, short x2, short y2) -{ - short v[2]; - - glBegin(GL_LINE_STRIP); - - v[0] = x1; v[1] = y1; - glVertex2sv(v); - v[0] = x1; v[1] = y2; - glVertex2sv(v); - v[0] = x2; v[1] = y2; - glVertex2sv(v); - v[0] = x2; v[1] = y1; - glVertex2sv(v); - v[0] = x1; v[1] = y1; - glVertex2sv(v); - - glEnd(); -} - -/* the central math in this function was copied from trackball.cpp, sample code from the - Developers Toolbox series by SGI. */ - -/* trackball: better one than a full spherical solution */ - -void calctrackballvecfirst(rcti *area, short *mval, float *vec) -{ - float x, y, radius, d, z, t; - - radius= TRACKBALLSIZE; - - /* normalize x and y */ - x= (area->xmax + area->xmin)/2 -mval[0]; - x/= (float)((area->xmax - area->xmin)/2); - y= (area->ymax + area->ymin)/2 -mval[1]; - y/= (float)((area->ymax - area->ymin)/2); - - d = sqrt(x*x + y*y); - if (d < radius*M_SQRT1_2) /* Inside sphere */ - z = sqrt(radius*radius - d*d); - else - { /* On hyperbola */ - t = radius / M_SQRT2; - z = t*t / d; - } - - vec[0]= x; - vec[1]= y; - vec[2]= -z; /* yah yah! */ - - if( fabs(vec[2])>fabs(vec[1]) && fabs(vec[2])>fabs(vec[0]) ) { - vec[0]= 0.0; - vec[1]= 0.0; - if(vec[2]>0.0) vec[2]= 1.0; else vec[2]= -1.0; - } - else if( fabs(vec[1])>fabs(vec[0]) && fabs(vec[1])>fabs(vec[2]) ) { - vec[0]= 0.0; - vec[2]= 0.0; - if(vec[1]>0.0) vec[1]= 1.0; else vec[1]= -1.0; - } - else { - vec[1]= 0.0; - vec[2]= 0.0; - if(vec[0]>0.0) vec[0]= 1.0; else vec[0]= -1.0; - } -} - -void calctrackballvec(rcti *area, short *mval, float *vec) -{ - float x, y, radius, d, z, t; - - radius= TRACKBALLSIZE; - - /* x en y normalizeren */ - x= (area->xmax + area->xmin)/2 -mval[0]; - x/= (float)((area->xmax - area->xmin)/4); - y= (area->ymax + area->ymin)/2 -mval[1]; - y/= (float)((area->ymax - area->ymin)/2); - - d = sqrt(x*x + y*y); - if (d < radius*M_SQRT1_2) /* Inside sphere */ - z = sqrt(radius*radius - d*d); - else - { /* On hyperbola */ - t = radius / M_SQRT2; - z = t*t / d; - } - - vec[0]= x; - vec[1]= y; - vec[2]= -z; /* yah yah! */ - -} - - -// ndof scaling will be moved to user setting. -// In the mean time this is just a place holder. - -// Note: scaling in the plugin and ghostwinlay.c -// should be removed. With driver default setting, -// each axis returns approx. +-200 max deflection. - -// The values I selected are based on the older -// polling i/f. With event i/f, the sensistivity -// can be increased for improved response from -// small deflections of the device input. - - -// lukep notes : i disagree on the range. -// the normal 3Dconnection driver give +/-400 -// on defaut range in other applications -// and up to +/- 1000 if set to maximum -// because i remove the scaling by delta, -// which was a bad idea as it depend of the system -// speed and os, i changed the scaling values, but -// those are still not ok - - -float ndof_axis_scale[6] = { - +0.01, // Tx - +0.01, // Tz - +0.01, // Ty - +0.0015, // Rx - +0.0015, // Rz - +0.0015 // Ry -}; - -// statics for controlling G.vd->dist corrections. -// viewmoveNDOF zeros and adjusts G.vd->ofs. -// viewmove restores based on dz_flag state. - -int dz_flag = 0; -float m_dist; - -void viewmoveNDOFfly(int mode) -{ - int i; - float phi; - float dval[7]; - // static fval[6] for low pass filter; device input vector is dval[6] - static float fval[6]; - float tvec[3],rvec[3]; - float q1[4]; - float mat[3][3]; - float upvec[3]; - - - /*---------------------------------------------------- - * sometimes this routine is called from headerbuttons - * viewmove needs to refresh the screen - */ - areawinset(curarea->win); - - - // fetch the current state of the ndof device - getndof(dval); - - if (G.vd->ndoffilter) - filterNDOFvalues(fval); - - // Scale input values - -// if(dval[6] == 0) return; // guard against divide by zero - - for(i=0;i<6;i++) { - - // user scaling - dval[i] = dval[i] * ndof_axis_scale[i]; - } - - - // low pass filter with zero crossing reset - - for(i=0;i<6;i++) { - if((dval[i] * fval[i]) >= 0) - dval[i] = (fval[i] * 15 + dval[i]) / 16; - else - fval[i] = 0; - } - - - // force perspective mode. This is a hack and is - // incomplete. It doesn't actually effect the view - // until the first draw and doesn't update the menu - // to reflect persp mode. - - G.vd->persp = V3D_PERSP; - - - // Correct the distance jump if G.vd->dist != 0 - - // This is due to a side effect of the original - // mouse view rotation code. The rotation point is - // set a distance in front of the viewport to - // make rotating with the mouse look better. - // The distance effect is written at a low level - // in the view management instead of the mouse - // view function. This means that all other view - // movement devices must subtract this from their - // view transformations. - - if(G.vd->dist != 0.0) { - dz_flag = 1; - m_dist = G.vd->dist; - upvec[0] = upvec[1] = 0; - upvec[2] = G.vd->dist; - Mat3CpyMat4(mat, G.vd->viewinv); - Mat3MulVecfl(mat, upvec); - VecSubf(G.vd->ofs, G.vd->ofs, upvec); - G.vd->dist = 0.0; - } - - - // Apply rotation - // Rotations feel relatively faster than translations only in fly mode, so - // we have no choice but to fix that here (not in the plugins) - rvec[0] = -0.5 * dval[3]; - rvec[1] = -0.5 * dval[4]; - rvec[2] = -0.5 * dval[5]; - - // rotate device x and y by view z - - Mat3CpyMat4(mat, G.vd->viewinv); - mat[2][2] = 0.0f; - Mat3MulVecfl(mat, rvec); - - // rotate the view - - phi = Normalize(rvec); - if(phi != 0) { - VecRotToQuat(rvec,phi,q1); - QuatMul(G.vd->viewquat, G.vd->viewquat, q1); - } - - - // Apply translation - - tvec[0] = dval[0]; - tvec[1] = dval[1]; - tvec[2] = -dval[2]; - - // the next three lines rotate the x and y translation coordinates - // by the current z axis angle - - Mat3CpyMat4(mat, G.vd->viewinv); - mat[2][2] = 0.0f; - Mat3MulVecfl(mat, tvec); - - // translate the view - - VecSubf(G.vd->ofs, G.vd->ofs, tvec); - - - /*---------------------------------------------------- - * refresh the screen - */ - scrarea_do_windraw(curarea); - screen_swapbuffers(); - - // update render preview window - - BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); -} - -int view_autodist( float mouse_worldloc[3] ) //, float *autodist ) -{ - View3D *v3d = G.vd; - - /* Zooms in on a border drawn by the user */ - short mval[2]; - rcti rect; - - /* ZBuffer depth vars */ - bglMats mats; - float depth, depth_close= MAXFLOAT; - int had_depth = 0; - double cent[2], p[3]; - int xs, ys; - - getmouseco_areawin(mval); - - persp(PERSP_VIEW); - - rect.xmax = mval[0] + 4; - rect.ymax = mval[1] + 4; - - rect.xmin = mval[0] - 4; - rect.ymin = mval[1] - 4; - - /* Get Z Depths, needed for perspective, nice for ortho */ - bgl_get_mats(&mats); - draw_depth(curarea, (void *)v3d, NULL); - - /* force updating */ - if (v3d->depths) { - had_depth = 1; - v3d->depths->damaged = 1; - } - - view3d_update_depths(v3d); - - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= v3d->depths->w) rect.xmax = v3d->depths->w-1; - if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->depths->h-1; - - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= v3d->depths->depths[ys*v3d->depths->w+xs]; - if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } - - if (depth_close==MAXFLOAT) - return 0; - - if (had_depth==0) { - MEM_freeN(v3d->depths->depths); - v3d->depths->depths = NULL; - } - v3d->depths->damaged = 1; - - cent[0] = (double)mval[0]; - cent[1] = (double)mval[1]; - - if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, mats.viewport, &p[0], &p[1], &p[2])) - return 0; - - mouse_worldloc[0] = (float)p[0]; - mouse_worldloc[1] = (float)p[1]; - mouse_worldloc[2] = (float)p[2]; - return 1; -} - -void viewmove(int mode) -{ - static float lastofs[3] = {0,0,0}; - Object *ob = OBACT; - float firstvec[3], newvec[3], dvec[3]; - 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], mval_area[2], mvali[2]; - short use_sel = 0; - short preview3d_event= 1; - - // locals for dist correction - float mat[3][3]; - float upvec[3]; - - /* 3D window may not be defined */ - if( !G.vd ) { - fprintf( stderr, "G.vd == NULL in viewmove()\n" ); - return; - } - - // dist correction from other movement devices - if((dz_flag)||G.vd->dist==0) { - dz_flag = 0; - G.vd->dist = m_dist; - upvec[0] = upvec[1] = 0; - upvec[2] = G.vd->dist; - Mat3CpyMat4(mat, G.vd->viewinv); - Mat3MulVecfl(mat, upvec); - VecAddf(G.vd->ofs, G.vd->ofs, upvec); - } - - /* sometimes this routine is called from headerbuttons */ - - areawinset(curarea->win); - - QUATCOPY(oldquat, G.vd->viewquat); - - getmouseco_areawin(mval_area); /* for zoom to mouse loc */ - getmouseco_sc(mvali); /* work with screen coordinates because of trackball function */ - mvalball[0]= mvalo[0] = mvali[0]; /* needed for turntable to work */ - mvalball[1]= mvalo[1] = mvali[1]; - dist0= G.vd->dist; - - calctrackballvec(&curarea->winrct, mvalo, firstvec); - - /* cumultime(0); */ - - if(!G.obedit && (G.f & G_SCULPTMODE) && ob && G.vd->pivot_last) { - use_sel= 1; - VecCopyf(ofs, G.vd->ofs); - - VecCopyf(obofs, sculpt_data()->pivot); - Mat4MulVecfl(ob->obmat, obofs); - obofs[0]= -obofs[0]; - obofs[1]= -obofs[1]; - obofs[2]= -obofs[2]; - } - else if (U.uiflag & USER_ORBIT_SELECTION) { - use_sel = 1; - - VECCOPY(ofs, G.vd->ofs); - - /* If there's no selection, lastofs is unmodified and last value since static */ - calculateTransformCenter(V3D_CENTROID, lastofs); - - VECCOPY(obofs, lastofs); - VecMulf(obofs, -1.0f); - } - else if (U.uiflag & USER_ORBIT_ZBUF) { - if ((use_sel=view_autodist(obofs))) { - if (G.vd->persp==V3D_PERSP) { - float my_origin[3]; /* original G.vd->ofs */ - float my_pivot[3]; /* view */ - - VECCOPY(my_origin, G.vd->ofs); - VecMulf(my_origin, -1.0f); /* ofs is flipped */ - - /* Set the dist value to be the distance from this 3d point */ - /* this means youll always be able to zoom into it and panning wont go bad when dist was zero */ - - /* remove dist value */ - upvec[0] = upvec[1] = 0; - upvec[2] = G.vd->dist; - Mat3CpyMat4(mat, G.vd->viewinv); - Mat3MulVecfl(mat, upvec); - VecSubf(my_pivot, G.vd->ofs, upvec); - VecMulf(my_pivot, -1.0f); /* ofs is flipped */ - - /* find a new ofs value that is allong the view axis (rather then the mouse location) */ - lambda_cp_line_ex(obofs, my_pivot, my_origin, dvec); - dist0 = G.vd->dist = VecLenf(my_pivot, dvec); - - VecMulf(dvec, -1.0f); - VECCOPY(G.vd->ofs, dvec); - } - VecMulf(obofs, -1.0f); - VECCOPY(ofs, G.vd->ofs); - } else { - ofs[0] = ofs[1] = ofs[2] = 0.0f; - } - } - else - ofs[0] = ofs[1] = ofs[2] = 0.0f; - - initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); - - reverse= 1.0f; - if (G.vd->persmat[2][1] < 0.0f) - reverse= -1.0f; - - while(TRUE) { - getmouseco_sc(mval); - - // if playanim = alt+A, screenhandlers are for animated UI, python, etc - if( (mode==2 && U.viewzoom==USER_ZOOM_CONT) || /* continues zoom always update */ - mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || /* mouse moved, so update */ - (G.f & G_PLAYANIM) || do_screenhandlers(G.curscreen) - ) { - - if(firsttime) { - - firsttime= 0; - /* are we translating, rotating or zooming? */ - if(mode==0) { - if(G.vd->view!=0) scrarea_queue_headredraw(curarea); /*for button */ - } - if(G.vd->persp==V3D_CAMOB && mode!=1 && G.vd->camera) { - G.vd->persp= V3D_PERSP; - scrarea_do_windraw(curarea); - scrarea_queue_headredraw(curarea); - } - } - - if(mode==0) { /* view rotate */ - G.vd->view= 0; /* need to reset everytime because of view snapping */ - - if (U.uiflag & USER_AUTOPERSP) G.vd->persp= V3D_PERSP; - - if (U.flag & USER_TRACKBALL) mvalball[0]= mval[0]; - mvalball[1]= mval[1]; - - calctrackballvec(&curarea->winrct, mvalball, newvec); - - VecSubf(dvec, newvec, firstvec); - - si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]); - si/= (2.0*TRACKBALLSIZE); - - if (U.flag & USER_TRACKBALL) { - Crossf(q1+1, firstvec, newvec); - - Normalize(q1+1); - - /* Allow for rotation beyond the interval - * [-pi, pi] */ - while (si > 1.0) - si -= 2.0; - - /* This relation is used instead of - * phi = asin(si) so that the angle - * of rotation is linearly proportional - * to the distance that the mouse is - * dragged. */ - phi = si * M_PI / 2.0; - - si= sin(phi); - q1[0]= cos(phi); - q1[1]*= si; - q1[2]*= si; - q1[3]*= si; - QuatMul(G.vd->viewquat, q1, oldquat); - - if (use_sel) { - /* compute the post multiplication quat, to rotate the offset correctly */ - QUATCOPY(q1, oldquat); - QuatConj(q1); - QuatMul(q1, q1, G.vd->viewquat); - - QuatConj(q1); /* conj == inv for unit quat */ - VECCOPY(G.vd->ofs, ofs); - VecSubf(G.vd->ofs, G.vd->ofs, obofs); - QuatMulVecf(q1, G.vd->ofs); - VecAddf(G.vd->ofs, G.vd->ofs, obofs); - } - } else { - /* New turntable view code by John Aughey */ - - float m[3][3]; - float m_inv[3][3]; - float xvec[3] = {1,0,0}; - /* Sensitivity will control how fast the viewport rotates. 0.0035 was - obtained experimentally by looking at viewport rotation sensitivities - on other modeling programs. */ - /* Perhaps this should be a configurable user parameter. */ - const float sensitivity = 0.0035; - - /* Get the 3x3 matrix and its inverse from the quaternion */ - QuatToMat3(G.vd->viewquat, m); - Mat3Inv(m_inv,m); - - /* Determine the direction of the x vector (for rotating up and down) */ - /* This can likely be compuated directly from the quaternion. */ - Mat3MulVecfl(m_inv,xvec); - - /* Perform the up/down rotation */ - phi = sensitivity * -(mval[1] - mvalo[1]); - si = sin(phi); - q1[0] = cos(phi); - q1[1] = si * xvec[0]; - q1[2] = si * xvec[1]; - q1[3] = si * xvec[2]; - QuatMul(G.vd->viewquat, G.vd->viewquat, q1); - - if (use_sel) { - QuatConj(q1); /* conj == inv for unit quat */ - VecSubf(G.vd->ofs, G.vd->ofs, obofs); - QuatMulVecf(q1, G.vd->ofs); - VecAddf(G.vd->ofs, G.vd->ofs, obofs); - } - - /* Perform the orbital rotation */ - phi = sensitivity * reverse * (mval[0] - mvalo[0]); - q1[0] = cos(phi); - q1[1] = q1[2] = 0.0; - q1[3] = sin(phi); - QuatMul(G.vd->viewquat, G.vd->viewquat, q1); - - if (use_sel) { - QuatConj(q1); - VecSubf(G.vd->ofs, G.vd->ofs, obofs); - QuatMulVecf(q1, G.vd->ofs); - VecAddf(G.vd->ofs, G.vd->ofs, obofs); - } - } - - /* check for view snap */ - if (G.qual==LR_CTRLKEY){ - int i; - float viewmat[3][3]; - - static const float thres = 0.93f; //cos(20 deg); - - static float snapquats[39][6] = { - /*{q0, q1, q3, q4, view, oposite_direction}*/ - {COS45, -SIN45, 0.0, 0.0, 1, 0}, //front - {0.0, 0.0, -SIN45, -SIN45, 1, 1}, //back - {1.0, 0.0, 0.0, 0.0, 7, 0}, //top - {0.0, -1.0, 0.0, 0.0, 7, 1}, //bottom - {0.5, -0.5, -0.5, -0.5, 3, 0}, //left - {0.5, -0.5, 0.5, 0.5, 3, 1}, //right - - /* some more 45 deg snaps */ - {0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0}, - {0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0}, - {0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0}, - {0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0}, - {0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0}, - {0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0}, - {0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0}, - {0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0}, - {0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0}, - {0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0}, - {0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0}, - {0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0}, - {0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0}, - {0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0}, - {-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0}, - {-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0}, - {-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0}, - {0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0}, - {-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0}, - {-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0}, - {-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0}, - {-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0}, - {-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0}, - {-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0}, - {-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0}, - {0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0}, - {-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0}, - {-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0}, - {-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0}, - {-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0}, - {-COS45, 0.0, 0.0, SIN45, 0, 0}, - {COS45, 0.0, 0.0, SIN45, 0, 0}, - {0.0, 0.0, 0.0, 1.0, 0, 0} - }; - - QuatToMat3(G.vd->viewquat, viewmat); - - for (i = 0 ; i < 39; i++){ - float snapmat[3][3]; - float view = (int)snapquats[i][4]; - float oposite_dir = (int)snapquats[i][5]; - - QuatToMat3(snapquats[i], snapmat); - - if ((Inpf(snapmat[0], viewmat[0]) > thres) && - (Inpf(snapmat[1], viewmat[1]) > thres) && - (Inpf(snapmat[2], viewmat[2]) > thres)){ - - QUATCOPY(G.vd->viewquat, snapquats[i]); - - G.vd->view = view; - if (view){ - if (oposite_dir){ - G.vd->flag2 |= V3D_OPP_DIRECTION_NAME; - }else{ - G.vd->flag2 &= ~V3D_OPP_DIRECTION_NAME; - } - } - - break; - } - } - } - } - else if(mode==1) { /* translate */ - if(G.vd->persp==V3D_CAMOB) { - float max= (float)MAX2(curarea->winx, curarea->winy); - - G.vd->camdx += (mvalo[0]-mval[0])/(max); - G.vd->camdy += (mvalo[1]-mval[1])/(max); - CLAMP(G.vd->camdx, -1.0f, 1.0f); - CLAMP(G.vd->camdy, -1.0f, 1.0f); - preview3d_event= 0; - } - else { - window_to_3d(dvec, mval[0]-mvalo[0], mval[1]-mvalo[1]); - VecAddf(G.vd->ofs, G.vd->ofs, dvec); - } - } - else if(mode==2) { - float zfac=1.0; - - /* use initial value (do not use mvalo (that is used to detect mouse moviments)) */ - mvalo[0] = mvali[0]; - mvalo[1] = mvali[1]; - - if(U.viewzoom==USER_ZOOM_CONT) { - // oldstyle zoom - 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; - // method which zooms based on how far you move the mouse - - ctr[0] = (curarea->winrct.xmax + curarea->winrct.xmin)/2; - ctr[1] = (curarea->winrct.ymax + curarea->winrct.ymin)/2; - - 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; - - 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; - 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); - - - if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (G.vd->persp==V3D_PERSP)) { - /* Secret apricot feature, translate the view when in continues mode */ - upvec[0] = upvec[1] = 0; - upvec[2] = (dist0 - G.vd->dist) * G.vd->grid; - G.vd->dist = dist0; - Mat3CpyMat4(mat, G.vd->viewinv); - Mat3MulVecfl(mat, upvec); - VecAddf(G.vd->ofs, G.vd->ofs, upvec); - } else { - /* these limits are in toets.c too */ - if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; - if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far; - } - - if(G.vd->persp==V3D_ORTHO || G.vd->persp==V3D_CAMOB) preview3d_event= 0; - } - - - - mvalo[0]= mval[0]; - mvalo[1]= mval[1]; - - if(G.f & G_PLAYANIM) inner_play_anim_loop(0, 0); - - /* If in retopo paint mode, update lines */ - if(retopo_mesh_paint_check() && G.vd->retopo_view_data) { - G.vd->retopo_view_data->queue_matrix_update= 1; - retopo_paint_view_update(G.vd); - } - - scrarea_do_windraw(curarea); - screen_swapbuffers(); - } - else { - short val; - unsigned short event; - /* we need to empty the queue... when you do this very long it overflows */ - while(qtest()) event= extern_qread(&val); - - BIF_wait_for_statechange(); - } - - /* this in the end, otherwise get_mbut does not work on a PC... */ - if( !(get_mbut() & (L_MOUSE|M_MOUSE))) break; - } - - if(G.vd->depths) G.vd->depths->damaged= 1; - retopo_queue_updates(G.vd); - allqueue(REDRAWVIEW3D, 0); - - if(preview3d_event) - BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); - else - BIF_view3d_previewrender_signal(curarea, PR_PROJECTED); - -} - -void view_zoom_mouseloc(float dfac, short *mouseloc) -{ - if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - 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; - } -} - -void viewmoveNDOF(int mode) -{ - float fval[7]; - float dvec[3]; - float sbadjust = 1.0f; - float len; - short use_sel = 0; - Object *ob = OBACT; - float m[3][3]; - float m_inv[3][3]; - float xvec[3] = {1,0,0}; - float yvec[3] = {0,-1,0}; - float zvec[3] = {0,0,1}; - float phi, si; - float q1[4]; - float obofs[3]; - float reverse; - //float diff[4]; - float d, curareaX, curareaY; - float mat[3][3]; - float upvec[3]; - - /* Sensitivity will control how fast the view rotates. The value was - * obtained experimentally by tweaking until the author didn't get dizzy watching. - * Perhaps this should be a configurable user parameter. - */ - float psens = 0.005f * (float) U.ndof_pan; /* pan sensitivity */ - float rsens = 0.005f * (float) U.ndof_rotate; /* rotate sensitivity */ - float zsens = 0.3f; /* zoom sensitivity */ - - const float minZoom = -30.0f; - const float maxZoom = 300.0f; - - //reset view type - G.vd->view = 0; -//printf("passing here \n"); -// - if (G.obedit==NULL && ob && !(ob->flag & OB_POSEMODE)) { - use_sel = 1; - } - - if((dz_flag)||G.vd->dist==0) { - dz_flag = 0; - G.vd->dist = m_dist; - upvec[0] = upvec[1] = 0; - upvec[2] = G.vd->dist; - Mat3CpyMat4(mat, G.vd->viewinv); - Mat3MulVecfl(mat, upvec); - VecAddf(G.vd->ofs, G.vd->ofs, upvec); - } - - /*---------------------------------------------------- - * sometimes this routine is called from headerbuttons - * viewmove needs to refresh the screen - */ - areawinset(curarea->win); - - /*---------------------------------------------------- - * record how much time has passed. clamp at 10 Hz - * pretend the previous frame occured at the clamped time - */ -// now = PIL_check_seconds_timer(); - // frametime = (now - prevTime); - // if (frametime > 0.1f){ /* if more than 1/10s */ - // frametime = 1.0f/60.0; /* clamp at 1/60s so no jumps when starting to move */ -// } -// prevTime = now; - // sbadjust *= 60 * frametime; /* normalize ndof device adjustments to 100Hz for framerate independence */ - - /* fetch the current state of the ndof device & enforce dominant mode if selected */ - getndof(fval); - if (G.vd->ndoffilter) - filterNDOFvalues(fval); - - - // put scaling back here, was previously in ghostwinlay - fval[0] = fval[0] * (1.0f/600.0f); - fval[1] = fval[1] * (1.0f/600.0f); - fval[2] = fval[2] * (1.0f/1100.0f); - fval[3] = fval[3] * 0.00005f; - fval[4] =-fval[4] * 0.00005f; - fval[5] = fval[5] * 0.00005f; - fval[6] = fval[6] / 1000000.0f; - - // scale more if not in perspective mode - if (G.vd->persp == V3D_ORTHO) { - fval[0] = fval[0] * 0.05f; - fval[1] = fval[1] * 0.05f; - fval[2] = fval[2] * 0.05f; - fval[3] = fval[3] * 0.9f; - fval[4] = fval[4] * 0.9f; - fval[5] = fval[5] * 0.9f; - zsens *= 8; - } - - - /* set object offset */ - if (ob) { - obofs[0] = -ob->obmat[3][0]; - obofs[1] = -ob->obmat[3][1]; - obofs[2] = -ob->obmat[3][2]; - } - else { - VECCOPY(obofs, G.vd->ofs); - } - - /* calc an adjustment based on distance from camera - disabled per patch 14402 */ - d = 1.0f; - -/* if (ob) { - VecSubf(diff, obofs, G.vd->ofs); - d = VecLength(diff); - } -*/ - - reverse = (G.vd->persmat[2][1] < 0.0f) ? -1.0f : 1.0f; - - /*---------------------------------------------------- - * ndof device pan - */ - psens *= 1.0f + d; - curareaX = sbadjust * psens * fval[0]; - curareaY = sbadjust * psens * fval[1]; - dvec[0] = curareaX * G.vd->persinv[0][0] + curareaY * G.vd->persinv[1][0]; - dvec[1] = curareaX * G.vd->persinv[0][1] + curareaY * G.vd->persinv[1][1]; - dvec[2] = curareaX * G.vd->persinv[0][2] + curareaY * G.vd->persinv[1][2]; - VecAddf(G.vd->ofs, G.vd->ofs, dvec); - - /*---------------------------------------------------- - * ndof device dolly - */ - len = zsens * sbadjust * fval[2]; - - if (G.vd->persp==V3D_CAMOB) { - if(G.vd->persp==V3D_CAMOB) { /* This is stupid, please fix - TODO */ - G.vd->camzoom+= 10.0f * -len; - } - if (G.vd->camzoom < minZoom) G.vd->camzoom = minZoom; - else if (G.vd->camzoom > maxZoom) G.vd->camzoom = maxZoom; - } - else if ((G.vd->dist> 0.001*G.vd->grid) && (G.vd->dist<10.0*G.vd->far)) { - G.vd->dist*=(1.0 + len); - } - - - /*---------------------------------------------------- - * ndof device turntable - * derived from the turntable code in viewmove - */ - - /* Get the 3x3 matrix and its inverse from the quaternion */ - QuatToMat3(G.vd->viewquat, m); - Mat3Inv(m_inv,m); - - /* Determine the direction of the x vector (for rotating up and down) */ - /* This can likely be compuated directly from the quaternion. */ - Mat3MulVecfl(m_inv,xvec); - Mat3MulVecfl(m_inv,yvec); - Mat3MulVecfl(m_inv,zvec); - - /* Perform the up/down rotation */ - phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */ - si = sin(phi); - q1[0] = cos(phi); - q1[1] = si * xvec[0]; - q1[2] = si * xvec[1]; - q1[3] = si * xvec[2]; - QuatMul(G.vd->viewquat, G.vd->viewquat, q1); - - if (use_sel) { - QuatConj(q1); /* conj == inv for unit quat */ - VecSubf(G.vd->ofs, G.vd->ofs, obofs); - QuatMulVecf(q1, G.vd->ofs); - VecAddf(G.vd->ofs, G.vd->ofs, obofs); - } - - /* Perform the orbital rotation */ - /* Perform the orbital rotation - If the seen Up axis is parallel to the zoom axis, rotation should be - achieved with a pure Roll motion (no Spin) on the device. When you start - to tilt, moving from Top to Side view, Spinning will increasingly become - more relevant while the Roll component will decrease. When a full - Side view is reached, rotations around the world's Up axis are achieved - with a pure Spin-only motion. In other words the control of the spinning - around the world's Up axis should move from the device's Spin axis to the - device's Roll axis depending on the orientation of the world's Up axis - relative to the screen. */ - //phi = sbadjust * rsens * reverse * fval[4]; /* spin the knob, y axis */ - phi = sbadjust * rsens * (yvec[2] * fval[4] + zvec[2] * fval[5]); - q1[0] = cos(phi); - q1[1] = q1[2] = 0.0; - q1[3] = sin(phi); - QuatMul(G.vd->viewquat, G.vd->viewquat, q1); - - if (use_sel) { - QuatConj(q1); - VecSubf(G.vd->ofs, G.vd->ofs, obofs); - QuatMulVecf(q1, G.vd->ofs); - VecAddf(G.vd->ofs, G.vd->ofs, obofs); - } - - /*---------------------------------------------------- - * refresh the screen - */ - scrarea_do_windraw(curarea); - screen_swapbuffers(); -} - - -/* 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) -{ - if (!ob) return; - - if(ob->type==OB_LAMP ) { - Lamp *la = ob->data; - if (lens) { - float x1, fac; - fac= cos( M_PI*la->spotsize/360.0); - x1= saacos(fac); - *lens= 16.0*fac/sin(x1); - } - if (clipsta) *clipsta= la->clipsta; - if (clipend) *clipend= la->clipend; - } - else if(ob->type==OB_CAMERA) { - Camera *cam= ob->data; - if (lens) *lens= cam->lens; - if (clipsta) *clipsta= cam->clipsta; - if (clipend) *clipend= cam->clipend; - } -} - - -int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize) -{ - Camera *cam=NULL; - float lens, fac, x1, y1, x2, y2; - float winx= (float)winxi, winy= (float)winyi; - int orth= 0; - - lens= G.vd->lens; - - *clipsta= G.vd->near; - *clipend= G.vd->far; - -/* - * Cant use this since we need the fac and x1 values set - * if(G.vd->persp==V3D_CAMOB) - object_view_settings(G.vd->camera, &lens, &(*clipsta), &(*clipend));*/ - - if(G.vd->persp==V3D_CAMOB) { - if(G.vd->camera) { - if(G.vd->camera->type==OB_LAMP ) { - Lamp *la; - - la= G.vd->camera->data; - fac= cos( M_PI*la->spotsize/360.0); - - x1= saacos(fac); - lens= 16.0*fac/sin(x1); - - *clipsta= la->clipsta; - *clipend= la->clipend; - } - else if(G.vd->camera->type==OB_CAMERA) { - cam= G.vd->camera->data; - lens= cam->lens; - *clipsta= cam->clipsta; - *clipend= cam->clipend; - } - } - } - - if(G.vd->persp==V3D_ORTHO) { - if(winx>winy) x1= -G.vd->dist; - else x1= -winx*G.vd->dist/winy; - x2= -x1; - - if(winx>winy) y1= -winy*G.vd->dist/winx; - else y1= -G.vd->dist; - y2= -y1; - - *clipend *= 0.5; // otherwise too extreme low zbuffer quality - *clipsta= - *clipend; - orth= 1; - } - else { - /* fac for zoom, also used for camdx */ - if(G.vd->persp==V3D_CAMOB) { - fac= (1.41421+( (float)G.vd->camzoom )/50.0); - fac*= fac; - } - else fac= 2.0; - - /* viewplane size depends... */ - if(cam && cam->type==CAM_ORTHO) { - /* ortho_scale == 1 means exact 1 to 1 mapping */ - float dfac= 2.0*cam->ortho_scale/fac; - - if(winx>winy) x1= -dfac; - else x1= -winx*dfac/winy; - x2= -x1; - - if(winx>winy) y1= -winy*dfac/winx; - else y1= -dfac; - y2= -y1; - orth= 1; - } - else { - float dfac; - - if(winx>winy) dfac= 64.0/(fac*winx*lens); - else dfac= 64.0/(fac*winy*lens); - - x1= - *clipsta * winx*dfac; - x2= -x1; - y1= - *clipsta * winy*dfac; - y2= -y1; - orth= 0; - } - /* cam view offset */ - if(cam) { - float dx= 0.5*fac*G.vd->camdx*(x2-x1); - float dy= 0.5*fac*G.vd->camdy*(y2-y1); - x1+= dx; - x2+= dx; - y1+= dy; - y2+= dy; - } - } - - if(pixsize) { - float viewfac; - - if(orth) { - viewfac= (winx >= winy)? winx: winy; - *pixsize= 1.0f/viewfac; - } - else { - viewfac= (((winx >= winy)? winx: winy)*lens)/32.0; - *pixsize= *clipsta/viewfac; - } - } - - viewplane->xmin= x1; - viewplane->ymin= y1; - viewplane->xmax= x2; - viewplane->ymax= y2; - - return orth; -} - -/* important to not set windows active in here, can be renderwin for example */ -void setwinmatrixview3d(int winx, int winy, rctf *rect) /* rect: for picking */ -{ - rctf viewplane; - float clipsta, clipend, x1, y1, x2, y2; - int orth; - - orth= get_view3d_viewplane(winx, winy, &viewplane, &clipsta, &clipend, NULL); -// printf("%d %d %f %f %f %f %f %f\n", winx, winy, viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax, clipsta, clipend); - x1= viewplane.xmin; - y1= viewplane.ymin; - x2= viewplane.xmax; - y2= viewplane.ymax; - - if(rect) { /* picking */ - rect->xmin/= (float)curarea->winx; - rect->xmin= x1+rect->xmin*(x2-x1); - rect->ymin/= (float)curarea->winy; - rect->ymin= y1+rect->ymin*(y2-y1); - rect->xmax/= (float)curarea->winx; - rect->xmax= x1+rect->xmax*(x2-x1); - rect->ymax/= (float)curarea->winy; - rect->ymax= y1+rect->ymax*(y2-y1); - - if(orth) myortho(rect->xmin, rect->xmax, rect->ymin, rect->ymax, -clipend, clipend); - else mywindow(rect->xmin, rect->xmax, rect->ymin, rect->ymax, clipsta, clipend); - - } - else { - if(orth) myortho(x1, x2, y1, y2, clipsta, clipend); - else mywindow(x1, x2, y1, y2, clipsta, clipend); - } - - /* not sure what this was for? (ton) */ - glMatrixMode(GL_PROJECTION); - mygetmatrix(curarea->winmat); - glMatrixMode(GL_MODELVIEW); -} - -void obmat_to_viewmat(Object *ob, short smooth) -{ - float bmat[4][4]; - float tmat[3][3]; - - G.vd->view= 0; /* dont show the grid */ - - Mat4CpyMat4(bmat, ob->obmat); - Mat4Ortho(bmat); - Mat4Invert(G.vd->viewmat, bmat); - - /* view quat calculation, needed for add object */ - Mat3CpyMat4(tmat, G.vd->viewmat); - if (smooth) { - float new_quat[4]; - if (G.vd->persp==V3D_CAMOB && G.vd->camera) { - /* were from a camera view */ - - float orig_ofs[3]; - float orig_dist= G.vd->dist; - float orig_lens= G.vd->lens; - VECCOPY(orig_ofs, G.vd->ofs); - - /* Switch from camera view */ - Mat3ToQuat(tmat, new_quat); - - G.vd->persp=V3D_PERSP; - G.vd->dist= 0.0; - - view_settings_from_ob(G.vd->camera, G.vd->ofs, NULL, NULL, &G.vd->lens); - smooth_view(G.vd, orig_ofs, new_quat, &orig_dist, &orig_lens); - - G.vd->persp=V3D_CAMOB; /* just to be polite, not needed */ - - } else { - Mat3ToQuat(tmat, new_quat); - smooth_view(G.vd, NULL, new_quat, NULL, NULL); - } - } else { - Mat3ToQuat(tmat, G.vd->viewquat); - } -} - -/* dont set windows active in in here, is used by renderwin too */ -void setviewmatrixview3d() -{ - if(G.vd->persp==V3D_CAMOB) { /* obs/camera */ - if(G.vd->camera) { - where_is_object(G.vd->camera); - obmat_to_viewmat(G.vd->camera, 0); - } - else { - QuatToMat4(G.vd->viewquat, G.vd->viewmat); - G.vd->viewmat[3][2]-= G.vd->dist; - } - } - else { - - QuatToMat4(G.vd->viewquat, G.vd->viewmat); - if(G.vd->persp==V3D_PERSP) G.vd->viewmat[3][2]-= G.vd->dist; - if(G.vd->ob_centre) { - Object *ob= G.vd->ob_centre; - float vec[3]; - - VECCOPY(vec, ob->obmat[3]); - if(ob->type==OB_ARMATURE && G.vd->ob_centre_bone[0]) { - bPoseChannel *pchan= get_pose_channel(ob->pose, G.vd->ob_centre_bone); - if(pchan) { - VECCOPY(vec, pchan->pose_mat[3]); - Mat4MulVecfl(ob->obmat, vec); - } - } - i_translate(-vec[0], -vec[1], -vec[2], G.vd->viewmat); - } - else i_translate(G.vd->ofs[0], G.vd->ofs[1], G.vd->ofs[2], G.vd->viewmat); - } -} - -void setcameratoview3d(void) -{ - Object *ob; - float dvec[3]; - - ob= G.vd->camera; - dvec[0]= G.vd->dist*G.vd->viewinv[2][0]; - dvec[1]= G.vd->dist*G.vd->viewinv[2][1]; - dvec[2]= G.vd->dist*G.vd->viewinv[2][2]; - VECCOPY(ob->loc, dvec); - VecSubf(ob->loc, ob->loc, G.vd->ofs); - G.vd->viewquat[0]= -G.vd->viewquat[0]; - /* */ - /*if (ob->transflag & OB_QUAT) { - QUATCOPY(ob->quat, G.vd->viewquat); - } else {*/ - QuatToEul(G.vd->viewquat, ob->rot); - /*}*/ - G.vd->viewquat[0]= -G.vd->viewquat[0]; -} - -/* IGLuint-> GLuint*/ -/* Warning: be sure to account for a negative return value - * This is an error, "Too many objects in select buffer" - * and no action should be taken (can crash blender) if this happens - */ -short view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1, short y1, short x2, short y2) -{ - rctf rect; - short mval[2], code, hits; - - G.f |= G_PICKSEL; - - if(x1==0 && x2==0 && y1==0 && y2==0) { - getmouseco_areawin(mval); - rect.xmin= mval[0]-12; // seems to be default value for bones only now - rect.xmax= mval[0]+12; - rect.ymin= mval[1]-12; - rect.ymax= mval[1]+12; - } - else { - rect.xmin= x1; - rect.xmax= x2; - rect.ymin= y1; - rect.ymax= y2; - } - /* get rid of overlay button matrix */ - persp(PERSP_VIEW); - setwinmatrixview3d(curarea->winx, curarea->winy, &rect); - Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat); - - if(G.vd->drawtype > OB_WIRE) { - G.vd->zbuf= TRUE; - glEnable(GL_DEPTH_TEST); - } - - if(G.vd->flag & V3D_CLIPPING) - view3d_set_clipping(G.vd); - - glSelectBuffer( bufsize, (GLuint *)buffer); - glRenderMode(GL_SELECT); - glInitNames(); /* these two calls whatfor? It doesnt work otherwise */ - glPushName(-1); - code= 1; - - if(G.obedit && G.obedit->type==OB_MBALL) { - draw_object(BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); - } - else if ((G.obedit && G.obedit->type==OB_ARMATURE)) { - draw_object(BASACT, DRAW_PICKING|DRAW_CONSTCOLOR); - } - else { - Base *base; - - G.vd->xray= TRUE; // otherwise it postpones drawing - for(base= G.scene->base.first; base; base= base->next) { - if(base->lay & G.vd->lay) { - - if (base->object->restrictflag & OB_RESTRICT_SELECT) - base->selcol= 0; - else { - base->selcol= code; - glLoadName(code); - draw_object(base, DRAW_PICKING|DRAW_CONSTCOLOR); - - /* we draw group-duplicators for selection too */ - if((base->object->transflag & OB_DUPLI) && base->object->dup_group) { - ListBase *lb; - DupliObject *dob; - Base tbase; - - tbase.flag= OB_FROMDUPLI; - lb= object_duplilist(G.scene, base->object); - - for(dob= lb->first; dob; dob= dob->next) { - tbase.object= dob->ob; - Mat4CpyMat4(dob->ob->obmat, dob->mat); - - draw_object(&tbase, DRAW_PICKING|DRAW_CONSTCOLOR); - - Mat4CpyMat4(dob->ob->obmat, dob->omat); - } - free_object_duplilist(lb); - } - code++; - } - } - } - G.vd->xray= FALSE; // restore - } - - glPopName(); /* see above (pushname) */ - hits= glRenderMode(GL_RENDER); - - G.f &= ~G_PICKSEL; - setwinmatrixview3d(curarea->winx, curarea->winy, NULL); - Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat); - - if(G.vd->drawtype > OB_WIRE) { - G.vd->zbuf= 0; - glDisable(GL_DEPTH_TEST); - } - persp(PERSP_WIN); - - if(G.vd->flag & V3D_CLIPPING) - view3d_clr_clipping(); - - if(hits<0) error("Too many objects in select buffer"); - - return hits; -} - -float *give_cursor() -{ - if(G.vd && G.vd->localview) return G.vd->cursor; - else return G.scene->cursor; -} - -unsigned int free_localbit() -{ - unsigned int lay; - ScrArea *sa; - bScreen *sc; - - lay= 0; - - /* sometimes we loose a localview: when an area is closed */ - /* check all areas: which localviews are in use? */ - sc= G.main->screen.first; - while(sc) { - sa= sc->areabase.first; - while(sa) { - SpaceLink *sl= sa->spacedata.first; - while(sl) { - if(sl->spacetype==SPACE_VIEW3D) { - View3D *v3d= (View3D*) sl; - lay |= v3d->lay; - } - sl= sl->next; - } - sa= sa->next; - } - sc= sc->id.next; - } - - if( (lay & 0x01000000)==0) return 0x01000000; - if( (lay & 0x02000000)==0) return 0x02000000; - if( (lay & 0x04000000)==0) return 0x04000000; - if( (lay & 0x08000000)==0) return 0x08000000; - if( (lay & 0x10000000)==0) return 0x10000000; - if( (lay & 0x20000000)==0) return 0x20000000; - if( (lay & 0x40000000)==0) return 0x40000000; - if( (lay & 0x80000000)==0) return 0x80000000; - - return 0; -} - - -void initlocalview() -{ - Base *base; - float size = 0.0, min[3], max[3], afm[3]; - unsigned int locallay; - int ok=0; - - if(G.vd->localvd) return; - - INIT_MINMAX(min, max); - - locallay= free_localbit(); - - if(locallay==0) { - error("Sorry, no more than 8 localviews"); - ok= 0; - } - else { - if(G.obedit) { - minmax_object(G.obedit, min, max); - - ok= 1; - - BASACT->lay |= locallay; - G.obedit->lay= BASACT->lay; - } - else { - base= FIRSTBASE; - while(base) { - if TESTBASE(base) { - minmax_object(base->object, min, max); - base->lay |= locallay; - base->object->lay= base->lay; - ok= 1; - } - base= base->next; - } - } - - afm[0]= (max[0]-min[0]); - afm[1]= (max[1]-min[1]); - afm[2]= (max[2]-min[2]); - size= 0.7*MAX3(afm[0], afm[1], afm[2]); - if(size<=0.01) size= 0.01; - } - - if(ok) { - G.vd->localvd= MEM_mallocN(sizeof(View3D), "localview"); - memcpy(G.vd->localvd, G.vd, sizeof(View3D)); - - 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; - - // 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; - } - - if (G.vd->persp==V3D_CAMOB) G.vd->persp= V3D_PERSP; - if (G.vd->near> 0.1) G.vd->near= 0.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->lay= locallay; - - countall(); - scrarea_queue_winredraw(curarea); - } - else { - /* clear flags */ - base= FIRSTBASE; - while(base) { - if( base->lay & locallay ) { - base->lay-= locallay; - if(base->lay==0) base->lay= G.vd->layact; - if(base->object != G.obedit) base->flag |= SELECT; - base->object->lay= base->lay; - } - base= base->next; - } - scrarea_queue_headredraw(curarea); - - G.vd->localview= 0; - } - BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); -} - -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; - - INIT_MINMAX(min, max); - - if (G.f & G_WEIGHTPAINT) { - /* hardcoded exception, we look for the one selected armature */ - /* this is weak code this way, we should make a generic active/selection callback interface once... */ - Base *base; - for(base=FIRSTBASE; base; base= base->next) { - if(TESTBASELIB(base)) { - if(base->object->type==OB_ARMATURE) - if(base->object->flag & OB_POSEMODE) - break; - } - } - if(base) - ob= base->object; - } - - - if(G.obedit) { - ok = minmax_verts(min, max); /* only selected */ - } - else if(ob && (ob->flag & OB_POSEMODE)) { - if(ob->pose) { - bArmature *arm= ob->data; - bPoseChannel *pchan; - float vec[3]; - - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(pchan->bone->flag & BONE_SELECTED) { - if(pchan->bone->layer & arm->layer) { - ok= 1; - VECCOPY(vec, pchan->pose_head); - Mat4MulVecfl(ob->obmat, vec); - DO_MINMAX(vec, min, max); - VECCOPY(vec, pchan->pose_tail); - Mat4MulVecfl(ob->obmat, vec); - DO_MINMAX(vec, min, max); - } - } - } - } - } - else if (FACESEL_PAINT_TEST) { - ok= minmax_tface(min, max); - } - else if (G.f & G_PARTICLEEDIT) { - ok= PE_minmax(min, max); - } - else { - Base *base= FIRSTBASE; - while(base) { - if TESTBASE(base) { - minmax_object(base->object, min, max); - /* account for duplis */ - minmax_object_duplis(base->object, min, max); - - ok= 1; - } - base= base->next; - } - } - - if(ok==0) return; - - afm[0]= (max[0]-min[0]); - afm[1]= (max[1]-min[1]); - afm[2]= (max[2]-min[2]); - size= 0.7f*MAX3(afm[0], afm[1], afm[2]); - - if(size <= G.vd->near*1.5f) size= G.vd->near*1.5f; - - new_ofs[0]= -(min[0]+max[0])/2.0f; - new_ofs[1]= -(min[1]+max[1])/2.0f; - new_ofs[2]= -(min[2]+max[2])/2.0f; - - 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.0f) size= 1.0f/size; - new_dist*= size; - } - - G.vd->cursor[0]= -new_ofs[0]; - G.vd->cursor[1]= -new_ofs[1]; - G.vd->cursor[2]= -new_ofs[2]; - - if (G.vd->persp==V3D_CAMOB && G.vd->camera) { - float orig_lens= G.vd->lens; - - G.vd->persp=V3D_PERSP; - G.vd->dist= 0.0f; - view_settings_from_ob(G.vd->camera, G.vd->ofs, NULL, NULL, &G.vd->lens); - smooth_view(G.vd, new_ofs, NULL, &new_dist, &orig_lens); - } else { - if(G.vd->persp==V3D_CAMOB) - G.vd->persp= V3D_PERSP; - - smooth_view(G.vd, new_ofs, NULL, &new_dist, NULL); - } - scrarea_queue_winredraw(curarea); - BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); - -} - - -void restore_localviewdata(View3D *vd) -{ - if(vd->localvd==0) return; - - VECCOPY(vd->ofs, vd->localvd->ofs); - vd->dist= vd->localvd->dist; - vd->persp= vd->localvd->persp; - vd->view= vd->localvd->view; - vd->near= vd->localvd->near; - vd->far= vd->localvd->far; - vd->lay= vd->localvd->lay; - vd->layact= vd->localvd->layact; - vd->drawtype= vd->localvd->drawtype; - vd->camera= vd->localvd->camera; - QUATCOPY(vd->viewquat, vd->localvd->viewquat); - -} - -void endlocalview(ScrArea *sa) -{ - View3D *v3d; - struct Base *base; - unsigned int locallay; - - if(sa->spacetype!=SPACE_VIEW3D) return; - v3d= sa->spacedata.first; - - if(v3d->localvd) { - - locallay= v3d->lay & 0xFF000000; - - restore_localviewdata(v3d); - - MEM_freeN(v3d->localvd); - v3d->localvd= 0; - v3d->localview= 0; - - /* for when in other window the layers have changed */ - if(v3d->scenelock) v3d->lay= G.scene->lay; - - base= FIRSTBASE; - while(base) { - if( base->lay & locallay ) { - base->lay-= locallay; - if(base->lay==0) base->lay= v3d->layact; - if(base->object != G.obedit) { - base->flag |= SELECT; - base->object->flag |= SELECT; - } - base->object->lay= base->lay; - } - base= base->next; - } - - countall(); - 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) -{ - Base *base; - float size, min[3], max[3], afm[3]; - int ok= 1, onedone=0; - - if(center) { - min[0]= min[1]= min[2]= 0.0f; - max[0]= max[1]= max[2]= 0.0f; - } - else { - INIT_MINMAX(min, max); - } - - for(base= FIRSTBASE; base; base= base->next) { - if(base->lay & G.vd->lay) { - onedone= 1; - minmax_object(base->object, min, max); - } - } - if(!onedone) return; - - afm[0]= (max[0]-min[0]); - afm[1]= (max[1]-min[1]); - afm[2]= (max[2]-min[2]); - size= 0.7f*MAX3(afm[0], afm[1], afm[2]); - if(size==0.0) ok= 0; - - if(ok) { - float new_dist; - float new_ofs[3]; - - new_dist = size; - new_ofs[0]= -(min[0]+max[0])/2.0f; - new_ofs[1]= -(min[1]+max[1])/2.0f; - new_ofs[2]= -(min[2]+max[2])/2.0f; - - // 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.0f/size; - new_dist*= size; - } - - if (G.vd->persp==V3D_CAMOB && G.vd->camera) { - /* switch out of camera view */ - float orig_lens= G.vd->lens; - - G.vd->persp= V3D_PERSP; - G.vd->dist= 0.0; - view_settings_from_ob(G.vd->camera, G.vd->ofs, NULL, NULL, &G.vd->lens); - smooth_view(G.vd, new_ofs, NULL, &new_dist, &orig_lens); - - } else { - if(G.vd->persp==V3D_CAMOB) G.vd->persp= V3D_PERSP; - smooth_view(G.vd, new_ofs, NULL, &new_dist, NULL); - } - scrarea_queue_winredraw(curarea); - } - BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); - -} - - -void view3d_align_axis_to_vector(View3D *v3d, int axisidx, float vec[3]) -{ - float alignaxis[3] = {0.0, 0.0, 0.0}; - float norm[3], axis[3], angle, new_quat[4]; - - if(axisidx > 0) alignaxis[axisidx-1]= 1.0; - else alignaxis[-axisidx-1]= -1.0; - - VECCOPY(norm, vec); - Normalize(norm); - - angle= (float)acos(Inpf(alignaxis, norm)); - Crossf(axis, alignaxis, norm); - VecRotToQuat(axis, -angle, new_quat); - - v3d->view= 0; - - if (v3d->persp==V3D_CAMOB && v3d->camera) { - /* switch out of camera view */ - float orig_ofs[3]; - float orig_dist= v3d->dist; - float orig_lens= v3d->lens; - - VECCOPY(orig_ofs, v3d->ofs); - G.vd->persp= V3D_PERSP; - G.vd->dist= 0.0; - view_settings_from_ob(v3d->camera, v3d->ofs, NULL, NULL, &v3d->lens); - smooth_view(G.vd, orig_ofs, new_quat, &orig_dist, &orig_lens); - } else { - if (v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP; /* switch out of camera mode */ - smooth_view(v3d, NULL, new_quat, NULL, NULL); - } -} - - - -/* SMOOTHVIEW */ -void smooth_view(View3D *v3d, float *ofs, float *quat, float *dist, float *lens) -{ - /* View Animation enabled */ - if (U.smooth_viewtx) { - int i; - char changed = 0; - float step = 0.0, step_inv; - float orig_dist; - float orig_lens; - 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 (lens) { - if ((*lens) != v3d->lens) - 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 the 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; - orig_lens = v3d->lens; - - 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 = (float)pow(step*2, 2)/2; - else step = (float)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); - - if (lens) - v3d->lens = ((*lens)*step) + (orig_lens*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; - if (lens) - v3d->lens = *lens; - -} - - - -/* Gets the view trasnformation from a camera - * currently dosnt take camzoom into account - * - * The dist is not modified for this function, if NULL its assimed zero - * */ -void view_settings_from_ob(Object *ob, float *ofs, float *quat, float *dist, float *lens) -{ - float bmat[4][4]; - float imat[4][4]; - float tmat[3][3]; - - if (!ob) return; - - /* Offset */ - if (ofs) { - where_is_object(ob); - VECCOPY(ofs, ob->obmat[3]); - VecMulf(ofs, -1.0f); /*flip the vector*/ - } - - /* Quat */ - if (quat) { - Mat4CpyMat4(bmat, ob->obmat); - Mat4Ortho(bmat); - Mat4Invert(imat, bmat); - Mat3CpyMat4(tmat, imat); - Mat3ToQuat(tmat, quat); - } - - if (dist) { - float vec[3]; - Mat3CpyMat4(tmat, ob->obmat); - - vec[0]= vec[1] = 0.0; - vec[2]= -(*dist); - Mat3MulVecfl(tmat, vec); - VecSubf(ofs, ofs, vec); - } - - /* Lens */ - if (lens) - object_view_settings(ob, lens, NULL, NULL); -} - -/* For use with smooth view - * - * the current view is unchanged, blend between the current view and the - * camera view - * */ -void smooth_view_to_camera(View3D *v3d) -{ - if (!U.smooth_viewtx || !v3d->camera || G.vd->persp != V3D_CAMOB) { - return; - } else { - Object *ob = v3d->camera; - - float orig_ofs[3]; - float orig_dist=v3d->dist; - float orig_lens=v3d->lens; - float new_dist=0.0; - float new_lens=35.0; - float new_quat[4]; - float new_ofs[3]; - - VECCOPY(orig_ofs, v3d->ofs); - - view_settings_from_ob(ob, new_ofs, new_quat, NULL, &new_lens); - - G.vd->persp= V3D_PERSP; - smooth_view(v3d, new_ofs, new_quat, &new_dist, &new_lens); - VECCOPY(v3d->ofs, orig_ofs); - v3d->lens= orig_lens; - v3d->dist = orig_dist; /* restore the dist */ - - v3d->camera = ob; - v3d->persp= V3D_CAMOB; - } -} - |