diff options
Diffstat (limited to 'source/blender/src/view.c')
-rw-r--r-- | source/blender/src/view.c | 1095 |
1 files changed, 1095 insertions, 0 deletions
diff --git a/source/blender/src/view.c b/source/blender/src/view.c new file mode 100644 index 00000000000..05a9de22620 --- /dev/null +++ b/source/blender/src/view.c @@ -0,0 +1,1095 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> + +#ifdef WIN32 +#include <io.h> +#include "BLI_winstuff.h" +#else +#include <unistd.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" + +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_camera_types.h" +#include "DNA_lamp_types.h" +#include "DNA_userdef_types.h" + +#include "BKE_utildefines.h" +#include "BKE_object.h" +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BIF_gl.h" +#include "BIF_space.h" +#include "BIF_mywindow.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 "mydevice.h" +#include "blendef.h" + +/* Modules used */ +#include "render.h" + +#define TRACKBALLSIZE (1.1) + +void persp3d(View3D *v3d, int a) +{ + ScrArea *area= v3d->area; + + /* oppasen met optimaliseren: dan laatste mode in area bewaren */ + /* only 3D windows */ + if(a== 0) { + bwin_get_winmatrix(area->win, area->winmat); + glMatrixMode(GL_MODELVIEW); + bwin_ortho2(area->win, -0.5, (float)(area->winx)-.05, -0.5, (float)(area->winy)-0.5); + glLoadIdentity(); + } + else if(a== 1) { + glMatrixMode(GL_PROJECTION); + bwin_load_winmatrix(area->win, area->winmat); + glMatrixMode(GL_MODELVIEW); + bwin_load_viewmatrix(area->win, v3d->viewmat); + } +} + +void persp_general(int a) +{ + /* for all window types, not 3D */ + + if(a== 0) { + glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + + myortho2(-0.5, ((float)(curarea->winx))-0.5, -0.5, ((float)(curarea->winy))-0.5); + glLoadIdentity(); + } + else if(a== 1) { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } +} + +void persp(int a) +{ + /* oppasen met optimaliseren: dan laatste mode in area bewaren */ + /* only 3D windows */ + + if(curarea->spacetype!=SPACE_VIEW3D) persp_general(a); + else if(a== 0) { + glMatrixMode(GL_PROJECTION); + mygetmatrix(curarea->winmat); + glMatrixMode(GL_MODELVIEW); + myortho2(-0.5, (float)(curarea->winx)-.05, -0.5, (float)(curarea->winy)-0.5); + glLoadIdentity(); + } + else if(a== 1) { + glMatrixMode(GL_PROJECTION); + myloadmatrix(curarea->winmat); + glMatrixMode(GL_MODELVIEW); + myloadmatrix(G.vd->viewmat); + } +} + + +float zfac=1.0; + +void initgrabz(float x, float y, float z) +{ + if(G.vd==0) return; + zfac= G.vd->persmat[0][3]*x+ G.vd->persmat[1][3]*y+ G.vd->persmat[2][3]*z+ G.vd->persmat[3][3]; +} + +void window_to_3d(float *vec, short mx, short my) +{ + /* altijd initzgrab aanroepen */ + float dx, dy; + float fmx, fmy, winx, winy; + + /* stupid! */ + winx= curarea->winx; + winy= curarea->winy; + fmx= mx; + fmy= my; + + dx= (2.0*fmx)/winx; + dx*= zfac; + dy= (2.0*fmy)/winy; + dy*= zfac; + + 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) /* clipt */ +{ + float fx, fy, vec4[4]; + + adr[0]= 3200; + VECCOPY(vec4, vec); + vec4[3]= 1.0; + + Mat4MulVec4fl(G.vd->persmat, vec4); + + if( vec4[3]>0.1 ) { + fx= (curarea->winx/2)+(curarea->winx/2)*vec4[0]/vec4[3]; + + if( fx>0 && fx<curarea->winx) { + + fy= (curarea->winy/2)+(curarea->winy/2)*vec4[1]/vec4[3]; + + if(fy>0.0 && fy< (float)curarea->winy) { + adr[0]= floor(fx+0.5); + adr[1]= floor(fy+0.5); + } + } + } +} + +void project_short_noclip(float *vec, short *adr) +{ + float fx, fy, vec4[4]; + + adr[0]= 3200; + VECCOPY(vec4, vec); + vec4[3]= 1.0; + + Mat4MulVec4fl(G.vd->persmat, vec4); + + if( vec4[3]>0.1 ) { + fx= (curarea->winx/2)+(curarea->winx/2)*vec4[0]/vec4[3]; + + if( fx>-32700 && fx<32700) { + + fy= (curarea->winy/2)+(curarea->winy/2)*vec4[1]/vec4[3]; + + if(fy>-32700.0 && fy<32700.0) { + adr[0]= floor(fx+0.5); + adr[1]= floor(fy+0.5); + } + } + } +} + +int boundbox_clip(float obmat[][4], BoundBox *bb) +{ + /* return 1: afbeelden */ + + float mat[4][4]; + float vec[4], min, max; + int a, flag= -1, fl; + + if(bb==0) 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(); +} + +/* trackball: deze is t.o.v. een 100% bol formule wel zo mooi */ + +void calctrackballvecfirst(rcti *area, short *mval, float *vec) +{ + float x, y, radius, d, z, t; + + radius= TRACKBALLSIZE; + + /* x en y normaliseren */ + 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; /* jawel! */ + + 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 normaliseren */ + 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; /* jawel! */ + +} + +void viewmove(int mode) +{ + float firstvec[3], newvec[3], dvec[3]; + float oldquat[4], q1[4], q2[4], si, phi; + int firsttime=1; + short mval[2], mvalo[2]; + + /* sometimes this routine is called from headerbuttons */ + areawinset(curarea->win); + curarea->head_swap= 0; + + initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); + + QUATCOPY(oldquat, G.vd->viewquat); + getmouseco_sc(mvalo); /* werk met screencoordinaten ivm trackball functie */ + calctrackballvec(&curarea->winrct, mvalo, firstvec); + + /* cumultime(0); */ + + while(TRUE) { + getmouseco_sc(mval); + + if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || (G.f & G_PLAYANIM)) { + + if(firsttime) { + firsttime= 0; + /* wordt hier geroteerd, gezoomd of transleerd */ + if(mode==0) { + if(G.vd->view!=0) scrarea_queue_headredraw(curarea); /* voor button */ + G.vd->view= 0; + } + + if(G.vd->persp==2 || (G.vd->persp==3 && mode!=1)) { + G.vd->persp= 1; + scrarea_do_windraw(curarea); + scrarea_queue_headredraw(curarea); + } + } + + + if(mode==0) { /* viewroteer */ + + if(U.flag & TRACKBALL) { + calctrackballvec(&curarea->winrct, mval, newvec); + + VecSubf(dvec, newvec, firstvec); + + si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]); + si/= (2.0*TRACKBALLSIZE); + + if(si<1.0) { + Crossf(q1+1, firstvec, newvec); + + Normalise(q1+1); + + phi= asin(si); + + si= sin(phi); + q1[0]= cos(phi); + q1[1]*= si; + q1[2]*= si; + q1[3]*= si; + + QuatMul(G.vd->viewquat, q1, oldquat); + } + } + else { + /* roteren om z-as (x beweging) en liggende as (y) */ + + phi= 2*(mval[0]-mvalo[0]); + phi/= (float)curarea->winx; + si= sin(phi); + q1[0]= cos(phi); + q1[1]= q1[2]= 0.0; + q1[3]= si; + + /* liggende as */ + VECCOPY(q2+1, G.vd->viewinv[0]); + Normalise(q2+1); + phi= (mvalo[1]-mval[1]); + phi/= (float)curarea->winy; + si= sin(phi); + q2[0]= cos(phi); + q2[1]*= si; + q2[2]*= si; + q2[3]*= si; + + QuatMul(q1, q1, q2); + QuatMul(G.vd->viewquat, G.vd->viewquat, q1); + } + } + else if(mode==1) { /* translate */ + if(G.vd->persp==3) { + /* zoom= 0.5+0.5*(float)(2<<G.vd->rt1); */ + /* dx-= (mval[0]-mvalo[0])/zoom; */ + /* dy-= (mval[1]-mvalo[1])/zoom; */ + /* G.vd->rt2= dx; */ + /* G.vd->rt3= dy; */ + /* if(G.vd->rt2<-320) G.vd->rt2= -320; */ + /* if(G.vd->rt2> 320) G.vd->rt2= 320; */ + /* if(G.vd->rt3<-250) G.vd->rt3= -250; */ + /* if(G.vd->rt3> 250) G.vd->rt3= 250; */ + } + 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) { + G.vd->dist*= 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0; + + /* deze limits ook in toets.c */ + 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; + + mval[1]= mvalo[1]; /* blijft ie zoomen */ + mval[0]= mvalo[0]; + } + + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + + if(G.f & G_PLAYANIM) inner_play_anim_loop(0, 0); + if(G.f & G_SIMULATION) break; + + scrarea_do_windraw(curarea); + screen_swapbuffers(); + } + else BIF_wait_for_statechange(); + + /* dit moet onderaan, anders pakt de get_mbut het niet op de PC... */ + if( !(get_mbut() & (L_MOUSE|M_MOUSE))) break; + } + + curarea->head_swap= WIN_FRONT_OK; +} + +short v3d_windowmode=0; + +void setwinmatrixview3d(rctf *rect) /* rect: voor picking */ +{ + Camera *cam=0; + float d, near, far, winx = 0.0, winy = 0.0; + float lens, dfac, tfac, fac, x1, y1, x2, y2; + short orth; + + lens= G.vd->lens; + near= G.vd->near; + far= G.vd->far; + + if(G.vd->persp==2) { + 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); + + near= la->clipsta; + far= la->clipend; + } + else if(G.vd->camera->type==OB_CAMERA) { + cam= G.vd->camera->data; + lens= cam->lens; + near= cam->clipsta; + far= cam->clipend; + + if(cam->type==CAM_ORTHO) { + lens*= 100.0; + near= (near+1.0)*100.0; /* otherwise zbuffer troubles. a Patch! */ + far*= 100.0; + } + } + } + } + + if(v3d_windowmode) { + winx= R.rectx; + winy= R.recty; + } + else { + winx= curarea->winx; + winy= curarea->winy; + } + + if(winx>winy) d= 0.015625*winx*lens; + else d= 0.015625*winy*lens; + + dfac= near/d; + + /* if(G.vd->persp==1 && G.vd->dproj>1.0) far= G.vd->dproj*far; */ + + if(G.vd->persp==0) { + /* x1= -winx*G.vd->dist/1000.0; */ + x1= -G.vd->dist; + x2= -x1; + y1= -winy*G.vd->dist/winx; + y2= -y1; + orth= 1; + } + else { + if(G.vd->persp==2) { + fac= (1.41421+( (float)G.vd->camzoom )/50.0); + fac*= fac; + } + else fac= 2.0; + + x1= -dfac*(winx/fac); + x2= -x1; + y1= -dfac*(winy/fac); + y2= -y1; + + if(G.vd->persp==2 && (G.special1 & G_HOLO)) { + if(cam && (cam->flag & CAM_HOLO2)) { + tfac= fac/4.0; /* de fac is 1280/640 gecorr voor obszoom */ + + if(cam->netend==0.0) cam->netend= EFRA; + fac= (G.scene->r.cfra-1.0)/(cam->netend)-0.5; + + fac*= tfac*(x2-x1); + fac*= ( cam->hololen1 ); + x1-= fac; + x2-= fac; + } + } + + orth= 0; + } + + if(rect) { /* picking */ + rect->xmin/= winx; + rect->xmin= x1+rect->xmin*(x2-x1); + rect->ymin/= winy; + rect->ymin= y1+rect->ymin*(y2-y1); + rect->xmax/= winx; + rect->xmax= x1+rect->xmax*(x2-x1); + rect->ymax/= winy; + rect->ymax= y1+rect->ymax*(y2-y1); + + if(orth) myortho(rect->xmin, rect->xmax, rect->ymin, rect->ymax, -far, far); + else mywindow(rect->xmin, rect->xmax, rect->ymin, rect->ymax, near, far); + + } + else { + if(v3d_windowmode) { + if(orth) i_ortho(x1, x2, y1, y2, -far, far, R.winmat); + else { + if(cam && cam->type==CAM_ORTHO) i_window(x1, x2, y1, y2, near, far, R.winmat); + else i_window(x1, x2, y1, y2, near, far, R.winmat); + } + } + else { + if(orth) myortho(x1, x2, y1, y2, -far, far); + else { + if(cam && cam->type==CAM_ORTHO) mywindow(x1, x2, y1, y2, near, far); + else mywindow(x1, x2, y1, y2, near, far); + } + } + } + + if(v3d_windowmode==0) { + glMatrixMode(GL_PROJECTION); + mygetmatrix(curarea->winmat); + glMatrixMode(GL_MODELVIEW); + } +} + + +void obmat_to_viewmat(Object *ob) +{ + float bmat[4][4]; + float tmat[3][3]; + + Mat4CpyMat4(bmat, ob->obmat); + Mat4Ortho(bmat); + Mat4Invert(G.vd->viewmat, bmat); + + /* viewquat berekenen, o.a. voor add object */ + Mat3CpyMat4(tmat, G.vd->viewmat); + Mat3ToQuat(tmat, G.vd->viewquat); +} + + +void setviewmatrixview3d() +{ + Camera *cam; +/* float bepaalphitheta(); */ + + if(G.special1 & G_HOLO) RE_holoview(); + + if(G.vd->persp>=2) { /* obs/camera */ + if(G.vd->camera) { + + where_is_object(G.vd->camera); + obmat_to_viewmat(G.vd->camera); + + if(G.vd->camera->type==OB_CAMERA) { + cam= G.vd->camera->data; + if(cam->type==CAM_ORTHO) G.vd->viewmat[3][2]*= 100.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==1) G.vd->viewmat[3][2]-= G.vd->dist; + i_translate(G.vd->ofs[0], G.vd->ofs[1], G.vd->ofs[2], G.vd->viewmat); + } +} + +/* IGLuint-> GLuint*/ +short selectprojektie(unsigned int *buffer, short x1, short y1, short x2, short y2) +{ + rctf rect; + Base *base; + 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]-7; + rect.xmax= mval[0]+7; + rect.ymin= mval[1]-7; + rect.ymax= mval[1]+7; + } + else { + rect.xmin= x1; + rect.xmax= x2; + rect.ymin= y1; + rect.ymax= y2; + } + setwinmatrixview3d(&rect); + Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat); + + if(G.vd->drawtype > OB_WIRE) { + G.zbuf= TRUE; + glEnable(GL_DEPTH_TEST); + } + + glSelectBuffer( MAXPICKBUF, buffer); + glRenderMode(GL_SELECT); + glInitNames(); /* deze twee fies zijn waarvoor? Anders werkt het niet */ + glPushName(-1); + code= 1; + + if(G.obedit && G.obedit->type==OB_MBALL) { + draw_object(BASACT); + } + else if ((G.obedit && G.obedit->type==OB_ARMATURE)||(G.obpose && G.obpose->type==OB_ARMATURE)) { + draw_object(BASACT); + } + else { + base= G.scene->base.first; + while(base) { + if(base->lay & G.vd->lay) { + base->selcol= code; + glLoadName(code); + draw_object(base); + code++; + } + base= base->next; + } + } + glPopName(); /* zie boven (pushname) */ + hits= glRenderMode(GL_RENDER); + if(hits<0) error("Too many objects in selectbuf"); + + G.f &= ~G_PICKSEL; + setwinmatrixview3d(0); + Mat4MulMat4(G.vd->persmat, G.vd->viewmat, curarea->winmat); + + if(G.vd->drawtype > OB_WIRE) { + G.zbuf= 0; + glDisable(GL_DEPTH_TEST); + } + + 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; + + /* soms kunnen we een localview kwijtrijaken: als een area gesloten wordt */ + /* alle area's aflopen: welke localviews zijn in gebruik */ + 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; + + min[0]= min[1]= min[2]= 1.0e10; + max[0]= max[1]= max[2]= -1.0e10; + + 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= 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; + + if(G.vd->persp>1) { + G.vd->persp= 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 { + /* flags wissen */ + 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; + } +} + +void centreview() /* localview zonder local! */ +{ + Base *base; + float size, min[3], max[3], afm[3]; + int ok=0; + + min[0]= min[1]= min[2]= 1.0e10; + max[0]= max[1]= max[2]= -1.0e10; + + if(G.obedit) { + minmax_object(G.obedit, min, max); + + ok= 1; + } + else { + base= FIRSTBASE; + while(base) { + if TESTBASE(base) { + minmax_object(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= MAX3(afm[0], afm[1], afm[2]); + + 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; + + if(G.vd->persp>1) { + G.vd->persp= 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]; + + scrarea_queue_winredraw(curarea); + +} + + +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; + + /* als in ander window de layers zijn veranderd */ + 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->lay= base->lay; + } + base= base->next; + } + + countall(); + allqueue(REDRAWVIEW3D, 0); /* ivm select */ + + } +} + +void view3d_home(int centre) +{ + Base *base; + float size, min[3], max[3], afm[3]; + int ok= 1, onedone=0; + + if(centre) { + min[0]= min[1]= min[2]= 0.0; + max[0]= max[1]= max[2]= 0.0; + } + else { + min[0]= min[1]= min[2]= 1.0e10; + max[0]= max[1]= max[2]= -1.0e10; + } + + base= FIRSTBASE; + if(base==0) return; + while(base) { + if(base->lay & G.vd->lay) { + onedone= 1; + minmax_object(base->object, min, max); + } + base= base->next; + } + if(!onedone) return; + + afm[0]= (max[0]-min[0]); + afm[1]= (max[1]-min[1]); + afm[2]= (max[2]-min[2]); + size= MAX3(afm[0], afm[1], afm[2]); + 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; + + if(G.vd->persp==2) G.vd->persp= 1; + + scrarea_queue_winredraw(curarea); + } +} + + +void view3d_align_axis_to_vector(View3D *v3d, int axisidx, float vec[3]) +{ + float alignaxis[3]; + float norm[3], axis[3], angle; + + alignaxis[0]= alignaxis[1]= alignaxis[2]= 0.0; + alignaxis[axisidx]= 1.0; + + norm[0]= vec[0], norm[1]= vec[1], norm[2]= vec[2]; + Normalise(norm); + + angle= acos(Inpf(alignaxis, norm)); + Crossf(axis, alignaxis, norm); + VecRotToQuat(axis, -angle, v3d->viewquat); + + v3d->view= 0; + if (v3d->persp>=2) v3d->persp= 0; /* switch out of camera mode */ +} + |