4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2008 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation
26 * ***** END GPL LICENSE BLOCK *****
34 #include "DNA_action_types.h"
35 #include "DNA_armature_types.h"
36 #include "DNA_camera_types.h"
37 #include "DNA_lamp_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_space_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_userdef_types.h"
43 #include "DNA_view3d_types.h"
44 #include "DNA_world_types.h"
46 #include "MEM_guardedalloc.h"
48 #include "BLI_blenlib.h"
49 #include "BLI_arithb.h"
53 #include "BKE_action.h"
54 #include "BKE_context.h"
55 #include "BKE_object.h"
56 #include "BKE_global.h"
58 #include "BKE_scene.h"
59 #include "BKE_screen.h"
60 #include "BKE_utildefines.h"
62 #include "RE_pipeline.h" // make_stars
68 #include "ED_screen.h"
70 #include "UI_interface.h"
71 #include "UI_resources.h"
72 #include "UI_view2d.h"
74 #include "PIL_time.h" /* smoothview */
76 #include "view3d_intern.h" // own include
78 #define BL_NEAR_CLIP 0.001
80 /* use this call when executing an operator,
81 event system doesn't set for each event the
82 opengl drawing context */
83 void view3d_operator_needs_opengl(const bContext *C)
85 ARegion *ar= CTX_wm_region(C);
87 /* for debugging purpose, context should always be OK */
88 if(ar->regiontype!=RGN_TYPE_WINDOW)
89 printf("view3d_operator_needs_opengl error, wrong region\n");
91 ScrArea *sa= CTX_wm_area(C);
92 View3D *v3d= sa->spacedata.first;
94 wmSubWindowSet(CTX_wm_window(C), ar->swinid);
95 glMatrixMode(GL_PROJECTION);
96 wmLoadMatrix(v3d->winmat);
97 glMatrixMode(GL_MODELVIEW);
98 wmLoadMatrix(v3d->viewmat);
102 float *give_cursor(Scene *scene, View3D *v3d)
104 if(v3d && v3d->localview) return v3d->cursor;
105 else return scene->cursor;
108 /* create intersection coordinates in view Z direction at mouse coordinates */
109 void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_end[3])
113 if(v3d->persp != V3D_ORTHO){
114 vec[0]= 2.0f * mval[0] / ar->winx - 1;
115 vec[1]= 2.0f * mval[1] / ar->winy - 1;
119 Mat4MulVec4fl(v3d->persinv, vec);
120 VecMulf(vec, 1.0f / vec[3]);
122 VECCOPY(ray_start, v3d->viewinv[3]);
123 VECSUB(vec, vec, ray_start);
126 VECADDFAC(ray_start, v3d->viewinv[3], vec, v3d->near);
127 VECADDFAC(ray_end, v3d->viewinv[3], vec, v3d->far);
130 vec[0] = 2.0f * mval[0] / ar->winx - 1;
131 vec[1] = 2.0f * mval[1] / ar->winy - 1;
135 Mat4MulVec4fl(v3d->persinv, vec);
137 VECADDFAC(ray_start, vec, v3d->viewinv[2], 1000.0f);
138 VECADDFAC(ray_end, vec, v3d->viewinv[2], -1000.0f);
142 /* create intersection ray in view Z direction at mouse coordinates */
143 void viewray(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3])
147 viewline(ar, v3d, mval, ray_start, ray_end);
148 VecSubf(ray_normal, ray_end, ray_start);
149 Normalize(ray_normal);
153 void initgrabz(View3D *v3d, float x, float y, float z)
155 if(v3d==NULL) return;
156 v3d->zfac= v3d->persmat[0][3]*x+ v3d->persmat[1][3]*y+ v3d->persmat[2][3]*z+ v3d->persmat[3][3];
158 /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
159 * (accounting for near zero values)
161 if (v3d->zfac < 1.e-6f && v3d->zfac > -1.e-6f) v3d->zfac = 1.0f;
163 /* Negative zfac means x, y, z was behind the camera (in perspective).
164 * This gives flipped directions, so revert back to ok default case.
166 if (v3d->zfac < 0.0f) v3d->zfac = 1.0f;
169 void window_to_3d(ARegion *ar, View3D *v3d, float *vec, short mx, short my)
171 /* always call initgrabz */
174 dx= 2.0f*mx*v3d->zfac/ar->winx;
175 dy= 2.0f*my*v3d->zfac/ar->winy;
177 vec[0]= (v3d->persinv[0][0]*dx + v3d->persinv[1][0]*dy);
178 vec[1]= (v3d->persinv[0][1]*dx + v3d->persinv[1][1]*dy);
179 vec[2]= (v3d->persinv[0][2]*dx + v3d->persinv[1][2]*dy);
182 void view3d_get_object_project_mat(View3D *v3d, Object *ob, float pmat[4][4], float vmat[4][4])
184 Mat4MulMat4(vmat, ob->obmat, v3d->viewmat);
185 Mat4MulMat4(pmat, vmat, v3d->winmat);
186 Mat4CpyMat4(vmat, ob->obmat);
189 /* projectmat brings it to window coords, wmat to rotated world space */
190 void view3d_project_short_clip(ARegion *ar, View3D *v3d, float *vec, short *adr, float projmat[4][4], float wmat[4][4])
192 float fx, fy, vec4[4];
196 /* clipplanes in eye space */
197 if(v3d->flag & V3D_CLIPPING) {
199 Mat4MulVecfl(wmat, vec4);
200 if(view3d_test_clipping(v3d, vec4))
207 Mat4MulVec4fl(projmat, vec4);
209 /* clipplanes in window space */
210 if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
211 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
213 if( fx>0 && fx<ar->winx) {
215 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
217 if(fy>0.0 && fy< (float)ar->winy) {
218 adr[0]= (short)floor(fx);
219 adr[1]= (short)floor(fy);
225 void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr, float mat[4][4])
227 float fx, fy, vec4[4];
234 Mat4MulVec4fl(mat, vec4);
236 if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
237 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
239 if( fx>-32700 && fx<32700) {
241 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
243 if(fy>-32700.0 && fy<32700.0) {
244 adr[0]= (short)floor(fx);
245 adr[1]= (short)floor(fy);
251 void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])
259 Mat4MulVec4fl(mat, vec4);
261 if( vec4[3]>FLT_EPSILON ) {
262 adr[0] = (float)(ar->winx/2.0f)+(ar->winx/2.0f)*vec4[0]/vec4[3];
263 adr[1] = (float)(ar->winy/2.0f)+(ar->winy/2.0f)*vec4[1]/vec4[3];
265 adr[0] = adr[1] = 0.0f;
269 int boundbox_clip(View3D *v3d, float obmat[][4], BoundBox *bb)
274 float vec[4], min, max;
277 if(bb==NULL) return 1;
278 if(bb->flag & OB_BB_DISABLED) return 1;
280 Mat4MulMat4(mat, obmat, v3d->persmat);
283 VECCOPY(vec, bb->vec[a]);
285 Mat4MulVec4fl(mat, vec);
290 if(vec[0] < min) fl+= 1;
291 if(vec[0] > max) fl+= 2;
292 if(vec[1] < min) fl+= 4;
293 if(vec[1] > max) fl+= 8;
294 if(vec[2] < min) fl+= 16;
295 if(vec[2] > max) fl+= 32;
298 if(flag==0) return 1;
304 void project_short(ARegion *ar, View3D *v3d, float *vec, short *adr) /* clips */
306 float fx, fy, vec4[4];
310 if(v3d->flag & V3D_CLIPPING) {
311 if(view3d_test_clipping(v3d, vec))
317 Mat4MulVec4fl(v3d->persmat, vec4);
319 if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
320 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
322 if( fx>0 && fx<ar->winx) {
324 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
326 if(fy>0.0 && fy< (float)ar->winy) {
327 adr[0]= (short)floor(fx);
328 adr[1]= (short)floor(fy);
334 void project_int(ARegion *ar, View3D *v3d, float *vec, int *adr)
336 float fx, fy, vec4[4];
338 adr[0]= (int)2140000000.0f;
342 Mat4MulVec4fl(v3d->persmat, vec4);
344 if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
345 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
347 if( fx>-2140000000.0f && fx<2140000000.0f) {
348 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
350 if(fy>-2140000000.0f && fy<2140000000.0f) {
351 adr[0]= (int)floor(fx);
352 adr[1]= (int)floor(fy);
358 void project_int_noclip(ARegion *ar, View3D *v3d, float *vec, int *adr)
360 float fx, fy, vec4[4];
365 Mat4MulVec4fl(v3d->persmat, vec4);
367 if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
368 fx = (ar->winx/2)*(1 + vec4[0]/vec4[3]);
369 fy = (ar->winy/2)*(1 + vec4[1]/vec4[3]);
371 adr[0] = (int)floor(fx);
372 adr[1] = (int)floor(fy);
376 adr[0] = ar->winx / 2;
377 adr[1] = ar->winy / 2;
381 void project_short_noclip(ARegion *ar, View3D *v3d, float *vec, short *adr)
383 float fx, fy, vec4[4];
389 Mat4MulVec4fl(v3d->persmat, vec4);
391 if( vec4[3]>BL_NEAR_CLIP ) { /* 0.001 is the NEAR clipping cutoff for picking */
392 fx= (ar->winx/2)*(1 + vec4[0]/vec4[3]);
394 if( fx>-32700 && fx<32700) {
396 fy= (ar->winy/2)*(1 + vec4[1]/vec4[3]);
398 if(fy>-32700.0 && fy<32700.0) {
399 adr[0]= (short)floor(fx);
400 adr[1]= (short)floor(fy);
406 void project_float(ARegion *ar, View3D *v3d, float *vec, float *adr)
414 Mat4MulVec4fl(v3d->persmat, vec4);
416 if( vec4[3]>BL_NEAR_CLIP ) {
417 adr[0] = (float)(ar->winx/2.0)+(ar->winx/2.0)*vec4[0]/vec4[3];
418 adr[1] = (float)(ar->winy/2.0)+(ar->winy/2.0)*vec4[1]/vec4[3];
422 void project_float_noclip(ARegion *ar, View3D *v3d, float *vec, float *adr)
429 Mat4MulVec4fl(v3d->persmat, vec4);
431 if( fabs(vec4[3]) > BL_NEAR_CLIP ) {
432 adr[0] = (float)(ar->winx/2.0)+(ar->winx/2.0)*vec4[0]/vec4[3];
433 adr[1] = (float)(ar->winy/2.0)+(ar->winy/2.0)*vec4[1]/vec4[3];
437 adr[0] = ar->winx / 2.0f;
438 adr[1] = ar->winy / 2.0f;
444 /* also exposed in previewrender.c */
445 int get_view3d_viewplane(View3D *v3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize)
448 float lens, fac, x1, y1, x2, y2;
449 float winx= (float)winxi, winy= (float)winyi;
457 if(v3d->persp==V3D_CAMOB) {
459 if(v3d->camera->type==OB_LAMP ) {
462 la= v3d->camera->data;
463 fac= cos( M_PI*la->spotsize/360.0);
466 lens= 16.0*fac/sin(x1);
468 *clipsta= la->clipsta;
469 *clipend= la->clipend;
471 else if(v3d->camera->type==OB_CAMERA) {
472 cam= v3d->camera->data;
474 *clipsta= cam->clipsta;
475 *clipend= cam->clipend;
480 if(v3d->persp==V3D_ORTHO) {
481 if(winx>winy) x1= -v3d->dist;
482 else x1= -winx*v3d->dist/winy;
485 if(winx>winy) y1= -winy*v3d->dist/winx;
489 *clipend *= 0.5; // otherwise too extreme low zbuffer quality
490 *clipsta= - *clipend;
494 /* fac for zoom, also used for camdx */
495 if(v3d->persp==V3D_CAMOB) {
496 fac= (1.41421+( (float)v3d->camzoom )/50.0);
501 /* viewplane size depends... */
502 if(cam && cam->type==CAM_ORTHO) {
503 /* ortho_scale == 1 means exact 1 to 1 mapping */
504 float dfac= 2.0*cam->ortho_scale/fac;
506 if(winx>winy) x1= -dfac;
507 else x1= -winx*dfac/winy;
510 if(winx>winy) y1= -winy*dfac/winx;
518 if(winx>winy) dfac= 64.0/(fac*winx*lens);
519 else dfac= 64.0/(fac*winy*lens);
521 x1= - *clipsta * winx*dfac;
523 y1= - *clipsta * winy*dfac;
527 /* cam view offset */
529 float dx= 0.5*fac*v3d->camdx*(x2-x1);
530 float dy= 0.5*fac*v3d->camdy*(y2-y1);
542 viewfac= (winx >= winy)? winx: winy;
543 *pixsize= 1.0f/viewfac;
546 viewfac= (((winx >= winy)? winx: winy)*lens)/32.0;
547 *pixsize= *clipsta/viewfac;
560 /* important to not set windows active in here, can be renderwin for example */
561 void setwinmatrixview3d(View3D *v3d, int winx, int winy, rctf *rect) /* rect: for picking */
564 float clipsta, clipend, x1, y1, x2, y2;
567 orth= get_view3d_viewplane(v3d, winx, winy, &viewplane, &clipsta, &clipend, NULL);
568 // printf("%d %d %f %f %f %f %f %f\n", winx, winy, viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax, clipsta, clipend);
574 if(rect) { /* picking */
575 rect->xmin/= (float)winx;
576 rect->xmin= x1+rect->xmin*(x2-x1);
577 rect->ymin/= (float)winy;
578 rect->ymin= y1+rect->ymin*(y2-y1);
579 rect->xmax/= (float)winx;
580 rect->xmax= x1+rect->xmax*(x2-x1);
581 rect->ymax/= (float)winy;
582 rect->ymax= y1+rect->ymax*(y2-y1);
584 if(orth) wmOrtho(rect->xmin, rect->xmax, rect->ymin, rect->ymax, -clipend, clipend);
585 else wmFrustum(rect->xmin, rect->xmax, rect->ymin, rect->ymax, clipsta, clipend);
589 if(orth) wmOrtho(x1, x2, y1, y2, clipsta, clipend);
590 else wmFrustum(x1, x2, y1, y2, clipsta, clipend);
593 /* not sure what this was for? (ton) */
594 glMatrixMode(GL_PROJECTION);
595 wmGetMatrix(v3d->winmat);
596 glMatrixMode(GL_MODELVIEW);
601 /* Gets the lens and clipping values from a camera of lamp type object */
602 static void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipend)
606 if(ob->type==OB_LAMP ) {
610 fac= cos( M_PI*la->spotsize/360.0);
612 *lens= 16.0*fac/sin(x1);
614 if (clipsta) *clipsta= la->clipsta;
615 if (clipend) *clipend= la->clipend;
617 else if(ob->type==OB_CAMERA) {
618 Camera *cam= ob->data;
619 if (lens) *lens= cam->lens;
620 if (clipsta) *clipsta= cam->clipsta;
621 if (clipend) *clipend= cam->clipend;
626 /* Gets the view trasnformation from a camera
627 * currently dosnt take camzoom into account
629 * The dist is not modified for this function, if NULL its assimed zero
631 void view_settings_from_ob(Object *ob, float *ofs, float *quat, float *dist, float *lens)
642 VECCOPY(ofs, ob->obmat[3]);
643 VecMulf(ofs, -1.0f); /*flip the vector*/
648 Mat4CpyMat4(bmat, ob->obmat);
650 Mat4Invert(imat, bmat);
651 Mat3CpyMat4(tmat, imat);
652 Mat3ToQuat(tmat, quat);
657 Mat3CpyMat4(tmat, ob->obmat);
659 vec[0]= vec[1] = 0.0;
661 Mat3MulVecfl(tmat, vec);
662 VecSubf(ofs, ofs, vec);
667 object_view_settings(ob, lens, NULL, NULL);
671 void obmat_to_viewmat(View3D *v3d, Object *ob, short smooth)
676 v3d->view= 0; /* dont show the grid */
678 Mat4CpyMat4(bmat, ob->obmat);
680 Mat4Invert(v3d->viewmat, bmat);
682 /* view quat calculation, needed for add object */
683 Mat3CpyMat4(tmat, v3d->viewmat);
686 if (v3d->persp==V3D_CAMOB && v3d->camera) {
687 /* were from a camera view */
690 float orig_dist= v3d->dist;
691 float orig_lens= v3d->lens;
692 VECCOPY(orig_ofs, v3d->ofs);
694 /* Switch from camera view */
695 Mat3ToQuat(tmat, new_quat);
697 v3d->persp=V3D_PERSP;
700 view_settings_from_ob(v3d->camera, v3d->ofs, NULL, NULL, &v3d->lens);
701 smooth_view(v3d, orig_ofs, new_quat, &orig_dist, &orig_lens);
703 v3d->persp=V3D_CAMOB; /* just to be polite, not needed */
706 Mat3ToQuat(tmat, new_quat);
707 smooth_view(v3d, NULL, new_quat, NULL, NULL);
710 Mat3ToQuat(tmat, v3d->viewquat);
714 /* dont set windows active in in here, is used by renderwin too */
715 void setviewmatrixview3d(View3D *v3d)
717 if(v3d->persp==V3D_CAMOB) { /* obs/camera */
719 where_is_object(v3d->camera);
720 obmat_to_viewmat(v3d, v3d->camera, 0);
723 QuatToMat4(v3d->viewquat, v3d->viewmat);
724 v3d->viewmat[3][2]-= v3d->dist;
729 QuatToMat4(v3d->viewquat, v3d->viewmat);
730 if(v3d->persp==V3D_PERSP) v3d->viewmat[3][2]-= v3d->dist;
732 Object *ob= v3d->ob_centre;
735 VECCOPY(vec, ob->obmat[3]);
736 if(ob->type==OB_ARMATURE && v3d->ob_centre_bone[0]) {
737 bPoseChannel *pchan= get_pose_channel(ob->pose, v3d->ob_centre_bone);
739 VECCOPY(vec, pchan->pose_mat[3]);
740 Mat4MulVecfl(ob->obmat, vec);
743 i_translate(-vec[0], -vec[1], -vec[2], v3d->viewmat);
745 else i_translate(v3d->ofs[0], v3d->ofs[1], v3d->ofs[2], v3d->viewmat);
749 void setcameratoview3d(View3D *v3d)
755 dvec[0]= v3d->dist*v3d->viewinv[2][0];
756 dvec[1]= v3d->dist*v3d->viewinv[2][1];
757 dvec[2]= v3d->dist*v3d->viewinv[2][2];
758 VECCOPY(ob->loc, dvec);
759 VecSubf(ob->loc, ob->loc, v3d->ofs);
760 v3d->viewquat[0]= -v3d->viewquat[0];
762 /*if (ob->transflag & OB_QUAT) {
763 QUATCOPY(ob->quat, v3d->viewquat);
765 QuatToEul(v3d->viewquat, ob->rot);
767 v3d->viewquat[0]= -v3d->viewquat[0];
771 /* IGLuint-> GLuint*/
772 /* Warning: be sure to account for a negative return value
773 * This is an error, "Too many objects in select buffer"
774 * and no action should be taken (can crash blender) if this happens
776 short view3d_opengl_select(Scene *scene, ARegion *ar, View3D *v3d, unsigned int *buffer, unsigned int bufsize, rcti *input)
783 /* case not a border select */
784 if(input->xmin==input->xmax) {
785 rect.xmin= input->xmin-12; // seems to be default value for bones only now
786 rect.xmax= input->xmin+12;
787 rect.ymin= input->ymin-12;
788 rect.ymax= input->xmin+12;
791 rect.xmin= input->xmin;
792 rect.xmax= input->xmax;
793 rect.ymin= input->ymin;
794 rect.ymax= input->ymax;
797 setwinmatrixview3d(v3d, ar->winx, ar->winy, &rect);
798 Mat4MulMat4(v3d->persmat, v3d->viewmat, v3d->winmat);
800 if(v3d->drawtype > OB_WIRE) {
802 glEnable(GL_DEPTH_TEST);
805 if(v3d->flag & V3D_CLIPPING)
806 view3d_set_clipping(v3d);
808 glSelectBuffer( bufsize, (GLuint *)buffer);
809 glRenderMode(GL_SELECT);
810 glInitNames(); /* these two calls whatfor? It doesnt work otherwise */
814 if(G.obedit && G.obedit->type==OB_MBALL) {
815 draw_object(scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR);
817 else if ((G.obedit && G.obedit->type==OB_ARMATURE)) {
818 draw_object(scene, ar, v3d, BASACT, DRAW_PICKING|DRAW_CONSTCOLOR);
823 v3d->xray= TRUE; // otherwise it postpones drawing
824 for(base= scene->base.first; base; base= base->next) {
825 if(base->lay & v3d->lay) {
827 if (base->object->restrictflag & OB_RESTRICT_SELECT)
832 draw_object(scene, ar, v3d, base, DRAW_PICKING|DRAW_CONSTCOLOR);
834 /* we draw group-duplicators for selection too */
835 if((base->object->transflag & OB_DUPLI) && base->object->dup_group) {
840 tbase.flag= OB_FROMDUPLI;
841 lb= object_duplilist(scene, base->object);
843 for(dob= lb->first; dob; dob= dob->next) {
844 tbase.object= dob->ob;
845 Mat4CpyMat4(dob->ob->obmat, dob->mat);
847 draw_object(scene, ar, v3d, &tbase, DRAW_PICKING|DRAW_CONSTCOLOR);
849 Mat4CpyMat4(dob->ob->obmat, dob->omat);
851 free_object_duplilist(lb);
857 v3d->xray= FALSE; // restore
860 glPopName(); /* see above (pushname) */
861 hits= glRenderMode(GL_RENDER);
864 setwinmatrixview3d(v3d, ar->winx, ar->winy, NULL);
865 Mat4MulMat4(v3d->persmat, v3d->viewmat, v3d->winmat);
867 if(v3d->drawtype > OB_WIRE) {
869 glDisable(GL_DEPTH_TEST);
871 // XXX persp(PERSP_WIN);
873 if(v3d->flag & V3D_CLIPPING)
874 view3d_clr_clipping();
876 if(hits<0) printf("Too many objects in select buffer\n"); // XXX make error message
881 // XXX solve: localview on region level? no.... layers are area, so all regions in area have to be set
882 static unsigned int free_localbit(void)
890 /* sometimes we loose a localview: when an area is closed */
891 /* check all areas: which localviews are in use? */
892 for(sc= G.main->screen.first; sc; sc= sc->id.next) {
893 for(sa= sc->areabase.first; sa; sa= sa->next) {
894 SpaceLink *sl= sa->spacedata.first;
895 for(; sl; sl= sl->next) {
896 if(sl->spacetype==SPACE_VIEW3D) {
897 View3D *v3d= (View3D*) sl;
904 if( (lay & 0x01000000)==0) return 0x01000000;
905 if( (lay & 0x02000000)==0) return 0x02000000;
906 if( (lay & 0x04000000)==0) return 0x04000000;
907 if( (lay & 0x08000000)==0) return 0x08000000;
908 if( (lay & 0x10000000)==0) return 0x10000000;
909 if( (lay & 0x20000000)==0) return 0x20000000;
910 if( (lay & 0x40000000)==0) return 0x40000000;
911 if( (lay & 0x80000000)==0) return 0x80000000;
917 void initlocalview(Scene *scene, ARegion *ar, View3D *v3d)
920 float size = 0.0, min[3], max[3], afm[3];
921 unsigned int locallay;
924 if(v3d->localvd) return;
926 INIT_MINMAX(min, max);
928 locallay= free_localbit();
931 printf("Sorry, no more than 8 localviews\n"); // XXX error
936 minmax_object(G.obedit, min, max);
940 BASACT->lay |= locallay;
941 G.obedit->lay= BASACT->lay;
946 if(TESTBASE(v3d, base)) {
947 minmax_object(base->object, min, max);
948 base->lay |= locallay;
949 base->object->lay= base->lay;
956 afm[0]= (max[0]-min[0]);
957 afm[1]= (max[1]-min[1]);
958 afm[2]= (max[2]-min[2]);
959 size= 0.7*MAX3(afm[0], afm[1], afm[2]);
960 if(size<=0.01) size= 0.01;
964 v3d->localvd= MEM_mallocN(sizeof(View3D), "localview");
965 memcpy(v3d->localvd, v3d, sizeof(View3D));
967 v3d->ofs[0]= -(min[0]+max[0])/2.0;
968 v3d->ofs[1]= -(min[1]+max[1])/2.0;
969 v3d->ofs[2]= -(min[2]+max[2])/2.0;
973 // correction for window aspect ratio
974 if(ar->winy>2 && ar->winx>2) {
975 size= (float)ar->winx/(float)ar->winy;
976 if(size<1.0) size= 1.0/size;
980 if (v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP;
981 if (v3d->near> 0.1) v3d->near= 0.1;
983 v3d->cursor[0]= -v3d->ofs[0];
984 v3d->cursor[1]= -v3d->ofs[1];
985 v3d->cursor[2]= -v3d->ofs[2];
990 // XXX scrarea_queue_winredraw(curarea);
996 if( base->lay & locallay ) {
997 base->lay-= locallay;
998 if(base->lay==0) base->lay= v3d->layact;
999 if(base->object != G.obedit) base->flag |= SELECT;
1000 base->object->lay= base->lay;
1004 // XXX scrarea_queue_headredraw(curarea);
1008 // XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
1011 void restore_localviewdata(View3D *vd)
1013 if(vd->localvd==0) return;
1015 VECCOPY(vd->ofs, vd->localvd->ofs);
1016 vd->dist= vd->localvd->dist;
1017 vd->persp= vd->localvd->persp;
1018 vd->view= vd->localvd->view;
1019 vd->near= vd->localvd->near;
1020 vd->far= vd->localvd->far;
1021 vd->lay= vd->localvd->lay;
1022 vd->layact= vd->localvd->layact;
1023 vd->drawtype= vd->localvd->drawtype;
1024 vd->camera= vd->localvd->camera;
1025 QUATCOPY(vd->viewquat, vd->localvd->viewquat);
1029 void endlocalview(Scene *scene, ScrArea *sa)
1033 unsigned int locallay;
1035 if(sa->spacetype!=SPACE_VIEW3D) return;
1036 v3d= sa->spacedata.first;
1040 locallay= v3d->lay & 0xFF000000;
1042 restore_localviewdata(v3d);
1044 MEM_freeN(v3d->localvd);
1048 /* for when in other window the layers have changed */
1049 if(v3d->scenelock) v3d->lay= scene->lay;
1053 if( base->lay & locallay ) {
1054 base->lay-= locallay;
1055 if(base->lay==0) base->lay= v3d->layact;
1056 if(base->object != G.obedit) {
1057 base->flag |= SELECT;
1058 base->object->flag |= SELECT;
1060 base->object->lay= base->lay;
1066 // XXX allqueue(REDRAWVIEW3D, 0); /* because of select */
1067 // XXX allqueue(REDRAWOOPS, 0); /* because of select */
1068 // XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
1072 void view3d_align_axis_to_vector(View3D *v3d, int axisidx, float vec[3])
1074 float alignaxis[3] = {0.0, 0.0, 0.0};
1075 float norm[3], axis[3], angle, new_quat[4];
1077 if(axisidx > 0) alignaxis[axisidx-1]= 1.0;
1078 else alignaxis[-axisidx-1]= -1.0;
1083 angle= (float)acos(Inpf(alignaxis, norm));
1084 Crossf(axis, alignaxis, norm);
1085 VecRotToQuat(axis, -angle, new_quat);
1089 if (v3d->persp==V3D_CAMOB && v3d->camera) {
1090 /* switch out of camera view */
1092 float orig_dist= v3d->dist;
1093 float orig_lens= v3d->lens;
1095 VECCOPY(orig_ofs, v3d->ofs);
1096 v3d->persp= V3D_PERSP;
1098 view_settings_from_ob(v3d->camera, v3d->ofs, NULL, NULL, &v3d->lens);
1099 smooth_view(v3d, orig_ofs, new_quat, &orig_dist, &orig_lens);
1101 if (v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP; /* switch out of camera mode */
1102 smooth_view(v3d, NULL, new_quat, NULL, NULL);
1109 void smooth_view(View3D *v3d, float *ofs, float *quat, float *dist, float *lens)
1111 /* View Animation enabled */
1112 if (U.smooth_viewtx) {
1115 float step = 0.0, step_inv;
1121 double time_allowed, time_current, time_start;
1123 /* if there is no difference, return */
1124 changed = 0; /* zero means no difference */
1126 if ((*dist) != v3d->dist)
1131 if ((*lens) != v3d->lens)
1135 if (!changed && ofs) {
1136 if ((ofs[0]!=v3d->ofs[0]) ||
1137 (ofs[1]!=v3d->ofs[1]) ||
1138 (ofs[2]!=v3d->ofs[2]) )
1142 if (!changed && quat ) {
1143 if ((quat[0]!=v3d->viewquat[0]) ||
1144 (quat[1]!=v3d->viewquat[1]) ||
1145 (quat[2]!=v3d->viewquat[2]) ||
1146 (quat[3]!=v3d->viewquat[3]) )
1150 /* The new view is different from the old one
1151 * so animate the view */
1154 /* store original values */
1155 VECCOPY(orig_ofs, v3d->ofs);
1156 QUATCOPY(orig_quat, v3d->viewquat);
1157 orig_dist = v3d->dist;
1158 orig_lens = v3d->lens;
1160 time_allowed= (float)U.smooth_viewtx / 1000.0;
1161 time_current = time_start = PIL_check_seconds_timer();
1163 /* if this is view rotation only
1164 * we can decrease the time allowed by
1165 * the angle between quats
1166 * this means small rotations wont lag */
1167 if (quat && !ofs && !dist) {
1168 float vec1[3], vec2[3];
1169 VECCOPY(vec1, quat);
1170 VECCOPY(vec2, v3d->viewquat);
1173 /* scale the time allowed by the rotation */
1174 time_allowed *= NormalizedVecAngle2(vec1, vec2)/(M_PI/2);
1177 while (time_start + time_allowed > time_current) {
1179 step = (float)((time_current-time_start) / time_allowed);
1182 if (step < 0.5) step = (float)pow(step*2, 2)/2;
1183 else step = (float)1-(pow(2*(1-step),2)/2);
1189 v3d->ofs[i] = ofs[i]*step + orig_ofs[i]*step_inv;
1193 QuatInterpol(v3d->viewquat, orig_quat, quat, step);
1196 v3d->dist = ((*dist)*step) + (orig_dist*step_inv);
1199 v3d->lens = ((*lens)*step) + (orig_lens*step_inv);
1202 // scrarea_do_windraw(ar);
1203 // screen_swapbuffers();
1205 time_current= PIL_check_seconds_timer();
1210 /* set these values even if animation is enabled because flaot
1211 * error will make then not quite accurate */
1213 VECCOPY(v3d->ofs, ofs);
1215 QUATCOPY(v3d->viewquat, quat);
1223 /* For use with smooth view
1225 * the current view is unchanged, blend between the current view and the
1228 void smooth_view_to_camera(View3D *v3d)
1230 if (!U.smooth_viewtx || !v3d->camera || v3d->persp != V3D_CAMOB) {
1233 Object *ob = v3d->camera;
1236 float orig_dist=v3d->dist;
1237 float orig_lens=v3d->lens;
1239 float new_lens=35.0;
1243 VECCOPY(orig_ofs, v3d->ofs);
1245 view_settings_from_ob(ob, new_ofs, new_quat, NULL, &new_lens);
1247 v3d->persp= V3D_PERSP;
1248 smooth_view(v3d, new_ofs, new_quat, &new_dist, &new_lens);
1249 VECCOPY(v3d->ofs, orig_ofs);
1250 v3d->lens= orig_lens;
1251 v3d->dist = orig_dist; /* restore the dist */
1254 v3d->persp= V3D_CAMOB;