6ba7a76dd5c46c6ad2ceb5f5aa31112112bca1f0
[blender.git] / source / blender / blenkernel / intern / camera.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/camera.c
29  *  \ingroup bke
30  */
31
32 #include <stdlib.h>
33
34 #include "DNA_camera_types.h"
35 #include "DNA_lamp_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_scene_types.h"
38
39 #include "BLI_math.h"
40 #include "BLI_utildefines.h"
41
42 #include "BKE_animsys.h"
43 #include "BKE_camera.h"
44 #include "BKE_object.h"
45 #include "BKE_global.h"
46 #include "BKE_library.h"
47 #include "BKE_main.h"
48
49 void *add_camera(const char *name)
50 {
51         Camera *cam;
52         
53         cam=  alloc_libblock(&G.main->camera, ID_CA, name);
54
55         cam->lens= 35.0f;
56         cam->sensor_x= 32.0f;
57         cam->sensor_y= 18.0f;
58         cam->clipsta= 0.1f;
59         cam->clipend= 100.0f;
60         cam->drawsize= 0.5f;
61         cam->ortho_scale= 6.0;
62         cam->flag |= CAM_SHOWPASSEPARTOUT;
63         cam->passepartalpha = 0.5f;
64         
65         return cam;
66 }
67
68 Camera *copy_camera(Camera *cam)
69 {
70         Camera *camn;
71         
72         camn= copy_libblock(&cam->id);
73         
74         return camn;
75 }
76
77 void make_local_camera(Camera *cam)
78 {
79         Main *bmain= G.main;
80         Object *ob;
81         int is_local= FALSE, is_lib= FALSE;
82
83         /* - only lib users: do nothing
84          * - only local users: set flag
85          * - mixed: make copy
86          */
87         
88         if(cam->id.lib==NULL) return;
89         if(cam->id.us==1) {
90                 id_clear_lib_data(bmain, &cam->id);
91                 return;
92         }
93         
94         for(ob= bmain->object.first; ob && ELEM(0, is_lib, is_local); ob= ob->id.next) {
95                 if(ob->data==cam) {
96                         if(ob->id.lib) is_lib= TRUE;
97                         else is_local= TRUE;
98                 }
99         }
100         
101         if(is_local && is_lib == FALSE) {
102                 id_clear_lib_data(bmain, &cam->id);
103         }
104         else if(is_local && is_lib) {
105                 Camera *camn= copy_camera(cam);
106
107                 camn->id.us= 0;
108
109                 /* Remap paths of new ID using old library as base. */
110                 BKE_id_lib_local_paths(bmain, &camn->id);
111
112                 for(ob= bmain->object.first; ob; ob= ob->id.next) {
113                         if(ob->data == cam) {
114                                 if(ob->id.lib==NULL) {
115                                         ob->data= camn;
116                                         camn->id.us++;
117                                         cam->id.us--;
118                                 }
119                         }
120                 }
121         }
122 }
123
124 /* get the camera's dof value, takes the dof object into account */
125 float dof_camera(Object *ob)
126 {
127         Camera *cam = (Camera *)ob->data; 
128         if (ob->type != OB_CAMERA)
129                 return 0.0f;
130         if (cam->dof_ob) {      
131                 /* too simple, better to return the distance on the view axis only
132                  * return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */
133                 float mat[4][4], imat[4][4], obmat[4][4];
134                 
135                 copy_m4_m4(obmat, ob->obmat);
136                 normalize_m4(obmat);
137                 invert_m4_m4(imat, obmat);
138                 mul_m4_m4m4(mat, cam->dof_ob->obmat, imat);
139                 return (float)fabs(mat[3][2]);
140         }
141         return cam->YF_dofdist;
142 }
143
144 void free_camera(Camera *ca)
145 {
146         BKE_free_animdata((ID *)ca);
147 }
148
149 void object_camera_mode(RenderData *rd, Object *camera)
150 {
151         rd->mode &= ~(R_ORTHO|R_PANORAMA);
152         if(camera && camera->type==OB_CAMERA) {
153                 Camera *cam= camera->data;
154                 if(cam->type == CAM_ORTHO) rd->mode |= R_ORTHO;
155                 if(cam->flag & CAM_PANORAMA) rd->mode |= R_PANORAMA;
156         }
157 }
158
159 void object_camera_intrinsics(Object *camera, Camera **cam_r, short *is_ortho, float *shiftx, float *shifty,
160                         float *clipsta, float *clipend, float *lens, float *sensor_x, float *sensor_y, short *sensor_fit)
161 {
162         Camera *cam= NULL;
163
164         (*shiftx)= 0.0f;
165         (*shifty)= 0.0f;
166
167         (*sensor_x)= DEFAULT_SENSOR_WIDTH;
168         (*sensor_y)= DEFAULT_SENSOR_HEIGHT;
169         (*sensor_fit)= CAMERA_SENSOR_FIT_AUTO;
170
171         if(camera->type==OB_CAMERA) {
172                 cam= camera->data;
173
174                 if(cam->type == CAM_ORTHO) {
175                         *is_ortho= TRUE;
176                 }
177
178                 /* solve this too... all time depending stuff is in convertblender.c?
179                  * Need to update the camera early because it's used for projection matrices
180                  * and other stuff BEFORE the animation update loop is done
181                  * */
182 #if 0 // XXX old animation system
183                 if(cam->ipo) {
184                         calc_ipo(cam->ipo, frame_to_float(re->scene, re->r.cfra));
185                         execute_ipo(&cam->id, cam->ipo);
186                 }
187 #endif // XXX old animation system
188                 (*shiftx)=cam->shiftx;
189                 (*shifty)=cam->shifty;
190                 (*lens)= cam->lens;
191                 (*sensor_x)= cam->sensor_x;
192                 (*sensor_y)= cam->sensor_y;
193                 (*clipsta)= cam->clipsta;
194                 (*clipend)= cam->clipend;
195                 (*sensor_fit)= cam->sensor_fit;
196         }
197         else if(camera->type==OB_LAMP) {
198                 Lamp *la= camera->data;
199                 float fac= cosf((float)M_PI*la->spotsize/360.0f);
200                 float phi= acos(fac);
201
202                 (*lens)= 16.0f*fac/sinf(phi);
203                 if((*lens)==0.0f)
204                         (*lens)= 35.0f;
205                 (*clipsta)= la->clipsta;
206                 (*clipend)= la->clipend;
207         }
208         else {  /* envmap exception... */;
209                 if((*lens)==0.0f) /* is this needed anymore? */
210                         (*lens)= 16.0f;
211
212                 if((*clipsta)==0.0f || (*clipend)==0.0f) {
213                         (*clipsta)= 0.1f;
214                         (*clipend)= 1000.0f;
215                 }
216         }
217
218         (*cam_r)= cam;
219 }
220
221 /* 'lens' may be set for envmap only */
222 void object_camera_matrix(
223                 RenderData *rd, Object *camera, int winx, int winy, short field_second,
224                 float winmat[][4], rctf *viewplane, float *clipsta, float *clipend, float *lens,
225                 float *sensor_x, float *sensor_y, short *sensor_fit, float *ycor,
226                 float *viewdx, float *viewdy)
227 {
228         Camera *cam=NULL;
229         float pixsize;
230         float shiftx=0.0, shifty=0.0, winside, viewfac;
231         short is_ortho= FALSE;
232
233         /* question mark */
234         (*ycor)= rd->yasp / rd->xasp;
235         if(rd->mode & R_FIELDS)
236                 (*ycor) *= 2.0f;
237
238         object_camera_intrinsics(camera, &cam, &is_ortho, &shiftx, &shifty, clipsta, clipend, lens, sensor_x, sensor_y, sensor_fit);
239
240         /* ortho only with camera available */
241         if(cam && is_ortho) {
242                 if((*sensor_fit)==CAMERA_SENSOR_FIT_AUTO) {
243                         if(rd->xasp*winx >= rd->yasp*winy) viewfac= winx;
244                         else viewfac= (*ycor) * winy;
245                 }
246                 else if((*sensor_fit)==CAMERA_SENSOR_FIT_HOR) {
247                         viewfac= winx;
248                 }
249                 else { /* if((*sensor_fit)==CAMERA_SENSOR_FIT_VERT) { */
250                         viewfac= (*ycor) * winy;
251                 }
252
253                 /* ortho_scale == 1.0 means exact 1 to 1 mapping */
254                 pixsize= cam->ortho_scale/viewfac;
255         }
256         else {
257                 if((*sensor_fit)==CAMERA_SENSOR_FIT_AUTO) {
258                         if(rd->xasp*winx >= rd->yasp*winy)      viewfac= ((*lens) * winx) / (*sensor_x);
259                         else                                    viewfac= (*ycor) * ((*lens) * winy) / (*sensor_x);
260                 }
261                 else if((*sensor_fit)==CAMERA_SENSOR_FIT_HOR) {
262                         viewfac= ((*lens) * winx) / (*sensor_x);
263                 }
264                 else { /* if((*sensor_fit)==CAMERA_SENSOR_FIT_VERT) { */
265                         viewfac= ((*lens) * winy) / (*sensor_y);
266                 }
267
268                 pixsize= (*clipsta) / viewfac;
269         }
270
271         /* viewplane fully centered, zbuffer fills in jittered between -.5 and +.5 */
272         winside= MAX2(winx, winy);
273
274         if(cam) {
275                 if(cam->sensor_fit==CAMERA_SENSOR_FIT_HOR)
276                         winside= winx;
277                 else if(cam->sensor_fit==CAMERA_SENSOR_FIT_VERT)
278                         winside= winy;
279         }
280
281         viewplane->xmin= -0.5f*(float)winx + shiftx*winside;
282         viewplane->ymin= -0.5f*(*ycor)*(float)winy + shifty*winside;
283         viewplane->xmax=  0.5f*(float)winx + shiftx*winside;
284         viewplane->ymax=  0.5f*(*ycor)*(float)winy + shifty*winside;
285
286         if(field_second) {
287                 if(rd->mode & R_ODDFIELD) {
288                         viewplane->ymin-= 0.5f * (*ycor);
289                         viewplane->ymax-= 0.5f * (*ycor);
290                 }
291                 else {
292                         viewplane->ymin+= 0.5f * (*ycor);
293                         viewplane->ymax+= 0.5f * (*ycor);
294                 }
295         }
296         /* the window matrix is used for clipping, and not changed during OSA steps */
297         /* using an offset of +0.5 here would give clip errors on edges */
298         viewplane->xmin *= pixsize;
299         viewplane->xmax *= pixsize;
300         viewplane->ymin *= pixsize;
301         viewplane->ymax *= pixsize;
302
303         (*viewdx)= pixsize;
304         (*viewdy)= (*ycor) * pixsize;
305
306         if(is_ortho)
307                 orthographic_m4(winmat, viewplane->xmin, viewplane->xmax, viewplane->ymin, viewplane->ymax, *clipsta, *clipend);
308         else
309                 perspective_m4(winmat, viewplane->xmin, viewplane->xmax, viewplane->ymin, viewplane->ymax, *clipsta, *clipend);
310
311 }
312
313 void camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, const short do_clip, const float scale[3],
314                           float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3])
315 {
316         float facx, facy;
317         float depth;
318
319         /* aspect correcton */
320         if (scene) {
321                 float aspx= (float) scene->r.xsch*scene->r.xasp;
322                 float aspy= (float) scene->r.ysch*scene->r.yasp;
323
324                 if(camera->sensor_fit==CAMERA_SENSOR_FIT_AUTO) {
325                         if(aspx < aspy) {
326                                 r_asp[0]= aspx / aspy;
327                                 r_asp[1]= 1.0;
328                         }
329                         else {
330                                 r_asp[0]= 1.0;
331                                 r_asp[1]= aspy / aspx;
332                         }
333                 }
334                 else if(camera->sensor_fit==CAMERA_SENSOR_FIT_AUTO) {
335                         r_asp[0]= aspx / aspy;
336                         r_asp[1]= 1.0;
337                 }
338                 else {
339                         r_asp[0]= 1.0;
340                         r_asp[1]= aspy / aspx;
341                 }
342         }
343         else {
344                 r_asp[0]= 1.0f;
345                 r_asp[1]= 1.0f;
346         }
347
348         if(camera->type==CAM_ORTHO) {
349                 facx= 0.5f * camera->ortho_scale * r_asp[0] * scale[0];
350                 facy= 0.5f * camera->ortho_scale * r_asp[1] * scale[1];
351                 r_shift[0]= camera->shiftx * camera->ortho_scale * scale[0];
352                 r_shift[1]= camera->shifty * camera->ortho_scale * scale[1];
353                 depth= do_clip ? -((camera->clipsta * scale[2]) + 0.1f) : - drawsize * camera->ortho_scale * scale[2];
354
355                 *r_drawsize= 0.5f * camera->ortho_scale;
356         }
357         else {
358                 /* that way it's always visible - clipsta+0.1 */
359                 float fac;
360                 float half_sensor= 0.5f*((camera->sensor_fit==CAMERA_SENSOR_FIT_VERT) ? (camera->sensor_y) : (camera->sensor_x));
361
362                 *r_drawsize= drawsize / ((scale[0] + scale[1] + scale[2]) / 3.0f);
363
364                 if(do_clip) {
365                         /* fixed depth, variable size (avoids exceeding clipping range) */
366                         depth = -(camera->clipsta + 0.1f);
367                         fac = depth / (camera->lens/(-half_sensor) * scale[2]);
368                 }
369                 else {
370                         /* fixed size, variable depth (stays a reasonable size in the 3D view) */
371                         depth= *r_drawsize * camera->lens/(-half_sensor) * scale[2];
372                         fac= *r_drawsize;
373                 }
374
375                 facx= fac * r_asp[0] * scale[0];
376                 facy= fac * r_asp[1] * scale[1];
377                 r_shift[0]= camera->shiftx*fac*2 * scale[0];
378                 r_shift[1]= camera->shifty*fac*2 * scale[1];
379         }
380
381         r_vec[0][0]= r_shift[0] + facx; r_vec[0][1]= r_shift[1] + facy; r_vec[0][2]= depth;
382         r_vec[1][0]= r_shift[0] + facx; r_vec[1][1]= r_shift[1] - facy; r_vec[1][2]= depth;
383         r_vec[2][0]= r_shift[0] - facx; r_vec[2][1]= r_shift[1] - facy; r_vec[2][2]= depth;
384         r_vec[3][0]= r_shift[0] - facx; r_vec[3][1]= r_shift[1] + facy; r_vec[3][2]= depth;
385 }
386
387 void camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
388 {
389         float dummy_asp[2];
390         float dummy_shift[2];
391         float dummy_drawsize;
392         const float dummy_scale[3]= {1.0f, 1.0f, 1.0f};
393
394         camera_view_frame_ex(scene, camera, FALSE, 1.0, dummy_scale,
395                              dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
396 }
397
398
399 typedef struct CameraViewFrameData {
400         float frame_tx[4][3];
401         float normal_tx[4][3];
402         float dist_vals[4];
403         unsigned int tot;
404 } CameraViewFrameData;
405
406 static void camera_to_frame_view_cb(const float co[3], void *user_data)
407 {
408         CameraViewFrameData *data= (CameraViewFrameData *)user_data;
409         unsigned int i;
410
411         for (i= 0; i < 4; i++) {
412                 float nd= -dist_to_plane_v3(co, data->frame_tx[i], data->normal_tx[i]);
413                 if (nd < data->dist_vals[i]) {
414                         data->dist_vals[i]= nd;
415                 }
416         }
417
418         data->tot++;
419 }
420
421 /* dont move the camera, just yield the fit location */
422 int camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
423 {
424         float shift[2];
425         float plane_tx[4][3];
426         float rot_obmat[3][3];
427         const float zero[3]= {0,0,0};
428         CameraViewFrameData data_cb;
429
430         unsigned int i;
431
432         camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);
433
434         copy_m3_m4(rot_obmat, camera_ob->obmat);
435         normalize_m3(rot_obmat);
436
437         for (i= 0; i < 4; i++) {
438                 /* normalize so Z is always 1.0f*/
439                 mul_v3_fl(data_cb.frame_tx[i], 1.0f/data_cb.frame_tx[i][2]);
440         }
441
442         /* get the shift back out of the frame */
443         shift[0]= (data_cb.frame_tx[0][0] +
444                    data_cb.frame_tx[1][0] +
445                    data_cb.frame_tx[2][0] +
446                    data_cb.frame_tx[3][0]) / 4.0f;
447         shift[1]= (data_cb.frame_tx[0][1] +
448                    data_cb.frame_tx[1][1] +
449                    data_cb.frame_tx[2][1] +
450                    data_cb.frame_tx[3][1]) / 4.0f;
451
452         for (i= 0; i < 4; i++) {
453                 mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
454         }
455
456         for (i= 0; i < 4; i++) {
457                 normal_tri_v3(data_cb.normal_tx[i],
458                               zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
459         }
460
461         /* initialize callback data */
462         data_cb.dist_vals[0]=
463         data_cb.dist_vals[1]=
464         data_cb.dist_vals[2]=
465         data_cb.dist_vals[3]= FLT_MAX;
466         data_cb.tot= 0;
467         /* run callback on all visible points */
468         BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
469                                         camera_to_frame_view_cb, &data_cb);
470
471         if (data_cb.tot <= 1) {
472                 return FALSE;
473         }
474         else {
475                 float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
476                 float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];
477
478                 float plane_isect_pt_1[3], plane_isect_pt_2[3];
479
480                 /* apply the dist-from-plane's to the transformed plane points */
481                 for (i= 0; i < 4; i++) {
482                         mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]);
483                 }
484
485                 if ( (isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
486                                            plane_tx[0], data_cb.normal_tx[0],
487                                            plane_tx[2], data_cb.normal_tx[2]) == 0) ||
488                      (isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
489                                            plane_tx[1], data_cb.normal_tx[1],
490                                            plane_tx[3], data_cb.normal_tx[3]) == 0))
491                 {
492                         /* this is very unlikely */
493                         return FALSE;
494                 }
495                 else {
496
497                         add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no);
498                         add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);
499
500                         if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
501                                                plane_isect_2, plane_isect_2_other,
502                                                plane_isect_pt_1, plane_isect_pt_2) == 0)
503                         {
504                                 return FALSE;
505                         }
506                         else {
507                                 float cam_plane_no[3]= {0.0f, 0.0f, -1.0f};
508                                 float plane_isect_delta[3];
509                                 float plane_isect_delta_len;
510
511                                 mul_m3_v3(rot_obmat, cam_plane_no);
512
513                                 sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
514                                 plane_isect_delta_len= len_v3(plane_isect_delta);
515
516                                 if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
517                                         copy_v3_v3(r_co, plane_isect_pt_1);
518
519                                         /* offset shift */
520                                         normalize_v3(plane_isect_1_no);
521                                         madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
522                                 }
523                                 else {
524                                         copy_v3_v3(r_co, plane_isect_pt_2);
525
526                                         /* offset shift */
527                                         normalize_v3(plane_isect_2_no);
528                                         madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
529                                 }
530
531
532                                 return TRUE;
533                         }
534                 }
535         }
536 }