Fix for using non camera objects as a camera having zero area view-frame
[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 #include "DNA_view3d_types.h"
39
40 #include "BLI_math.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_animsys.h"
44 #include "BKE_camera.h"
45 #include "BKE_object.h"
46 #include "BKE_global.h"
47 #include "BKE_library.h"
48 #include "BKE_main.h"
49 #include "BKE_screen.h"
50
51 /****************************** Camera Datablock *****************************/
52
53 void *BKE_camera_add(Main *bmain, const char *name)
54 {
55         Camera *cam;
56         
57         cam =  BKE_libblock_alloc(bmain, ID_CA, name);
58
59         cam->lens = 35.0f;
60         cam->sensor_x = DEFAULT_SENSOR_WIDTH;
61         cam->sensor_y = DEFAULT_SENSOR_HEIGHT;
62         cam->clipsta = 0.1f;
63         cam->clipend = 100.0f;
64         cam->drawsize = 0.5f;
65         cam->ortho_scale = 6.0;
66         cam->flag |= CAM_SHOWPASSEPARTOUT;
67         cam->passepartalpha = 0.5f;
68         
69         return cam;
70 }
71
72 Camera *BKE_camera_copy(Camera *cam)
73 {
74         Camera *camn;
75         
76         camn = BKE_libblock_copy(&cam->id);
77
78         id_lib_extern((ID *)camn->dof_ob);
79
80         return camn;
81 }
82
83 void BKE_camera_make_local(Camera *cam)
84 {
85         Main *bmain = G.main;
86         Object *ob;
87         int is_local = FALSE, is_lib = FALSE;
88
89         /* - only lib users: do nothing
90          * - only local users: set flag
91          * - mixed: make copy
92          */
93         
94         if (cam->id.lib == NULL) return;
95         if (cam->id.us == 1) {
96                 id_clear_lib_data(bmain, &cam->id);
97                 return;
98         }
99         
100         for (ob = bmain->object.first; ob && ELEM(0, is_lib, is_local); ob = ob->id.next) {
101                 if (ob->data == cam) {
102                         if (ob->id.lib) is_lib = TRUE;
103                         else is_local = TRUE;
104                 }
105         }
106         
107         if (is_local && is_lib == FALSE) {
108                 id_clear_lib_data(bmain, &cam->id);
109         }
110         else if (is_local && is_lib) {
111                 Camera *cam_new = BKE_camera_copy(cam);
112
113                 cam_new->id.us = 0;
114
115                 /* Remap paths of new ID using old library as base. */
116                 BKE_id_lib_local_paths(bmain, cam->id.lib, &cam_new->id);
117
118                 for (ob = bmain->object.first; ob; ob = ob->id.next) {
119                         if (ob->data == cam) {
120                                 if (ob->id.lib == NULL) {
121                                         ob->data = cam_new;
122                                         cam_new->id.us++;
123                                         cam->id.us--;
124                                 }
125                         }
126                 }
127         }
128 }
129
130 void BKE_camera_free(Camera *ca)
131 {
132         BKE_free_animdata((ID *)ca);
133 }
134
135 /******************************** Camera Usage *******************************/
136
137 void BKE_camera_object_mode(RenderData *rd, Object *cam_ob)
138 {
139         rd->mode &= ~(R_ORTHO | R_PANORAMA);
140
141         if (cam_ob && cam_ob->type == OB_CAMERA) {
142                 Camera *cam = cam_ob->data;
143                 if (cam->type == CAM_ORTHO) rd->mode |= R_ORTHO;
144                 if (cam->type == CAM_PANO) rd->mode |= R_PANORAMA;
145         }
146 }
147
148 /* get the camera's dof value, takes the dof object into account */
149 float BKE_camera_object_dof_distance(Object *ob)
150 {
151         Camera *cam = (Camera *)ob->data; 
152         if (ob->type != OB_CAMERA)
153                 return 0.0f;
154         if (cam->dof_ob) {
155                 /* too simple, better to return the distance on the view axis only
156                  * return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */
157                 float mat[4][4], imat[4][4], obmat[4][4];
158                 
159                 copy_m4_m4(obmat, ob->obmat);
160                 normalize_m4(obmat);
161                 invert_m4_m4(imat, obmat);
162                 mul_m4_m4m4(mat, imat, cam->dof_ob->obmat);
163                 return fabsf(mat[3][2]);
164         }
165         return cam->YF_dofdist;
166 }
167
168 float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y)
169 {
170         /* sensor size used to fit to. for auto, sensor_x is both x and y. */
171         if (sensor_fit == CAMERA_SENSOR_FIT_VERT)
172                 return sensor_y;
173
174         return sensor_x;
175 }
176
177 int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey)
178 {
179         if (sensor_fit == CAMERA_SENSOR_FIT_AUTO) {
180                 if (sizex >= sizey)
181                         return CAMERA_SENSOR_FIT_HOR;
182                 else
183                         return CAMERA_SENSOR_FIT_VERT;
184         }
185
186         return sensor_fit;
187 }
188
189 /******************************** Camera Params *******************************/
190
191 void BKE_camera_params_init(CameraParams *params)
192 {
193         memset(params, 0, sizeof(CameraParams));
194
195         /* defaults */
196         params->sensor_x = DEFAULT_SENSOR_WIDTH;
197         params->sensor_y = DEFAULT_SENSOR_HEIGHT;
198         params->sensor_fit = CAMERA_SENSOR_FIT_AUTO;
199
200         params->zoom = 1.0f;
201
202         /* fallback for non camera objects */
203         params->clipsta = 0.1f;
204         params->clipsta = 100.0f;
205 }
206
207 void BKE_camera_params_from_object(CameraParams *params, Object *ob)
208 {
209         if (!ob)
210                 return;
211
212         if (ob->type == OB_CAMERA) {
213                 /* camera object */
214                 Camera *cam = ob->data;
215
216                 if (cam->type == CAM_ORTHO)
217                         params->is_ortho = TRUE;
218                 params->lens = cam->lens;
219                 params->ortho_scale = cam->ortho_scale;
220
221                 params->shiftx = cam->shiftx;
222                 params->shifty = cam->shifty;
223
224                 params->sensor_x = cam->sensor_x;
225                 params->sensor_y = cam->sensor_y;
226                 params->sensor_fit = cam->sensor_fit;
227
228                 params->clipsta = cam->clipsta;
229                 params->clipend = cam->clipend;
230         }
231         else if (ob->type == OB_LAMP) {
232                 /* lamp object */
233                 Lamp *la = ob->data;
234                 float fac = cosf(la->spotsize * 0.5f);
235                 float phi = acos(fac);
236
237                 params->lens = 16.0f * fac / sinf(phi);
238                 if (params->lens == 0.0f)
239                         params->lens = 35.0f;
240
241                 params->clipsta = la->clipsta;
242                 params->clipend = la->clipend;
243         }
244         else {
245                 params->lens = 35.0f;
246         }
247 }
248
249 void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView3D *rv3d)
250 {
251         /* common */
252         params->lens = v3d->lens;
253         params->clipsta = v3d->near;
254         params->clipend = v3d->far;
255
256         if (rv3d->persp == RV3D_CAMOB) {
257                 /* camera view */
258                 BKE_camera_params_from_object(params, v3d->camera);
259
260                 params->zoom = BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom);
261
262                 params->offsetx = 2.0f * rv3d->camdx * params->zoom;
263                 params->offsety = 2.0f * rv3d->camdy * params->zoom;
264
265                 params->shiftx *= params->zoom;
266                 params->shifty *= params->zoom;
267
268                 params->zoom = 1.0f / params->zoom;
269         }
270         else if (rv3d->persp == RV3D_ORTHO) {
271                 /* orthographic view */
272                 int sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y);
273                 params->clipend *= 0.5f;    // otherwise too extreme low zbuffer quality
274                 params->clipsta = -params->clipend;
275
276                 params->is_ortho = TRUE;
277                 /* make sure any changes to this match ED_view3d_radius_to_ortho_dist() */
278                 params->ortho_scale = rv3d->dist * sensor_size / v3d->lens;
279                 params->zoom = 2.0f;
280         }
281         else {
282                 /* perspective view */
283                 params->zoom = 2.0f;
284         }
285 }
286
287 void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int winy, float xasp, float yasp)
288 {
289         rctf viewplane;
290         float pixsize, viewfac, sensor_size, dx, dy;
291         int sensor_fit;
292
293         /* fields rendering */
294         params->ycor = yasp / xasp;
295         if (params->use_fields)
296                 params->ycor *= 2.0f;
297
298         if (params->is_ortho) {
299                 /* orthographic camera */
300                 /* scale == 1.0 means exact 1 to 1 mapping */
301                 pixsize = params->ortho_scale;
302         }
303         else {
304                 /* perspective camera */
305                 sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y);
306                 pixsize = (sensor_size * params->clipsta) / params->lens;
307         }
308
309         /* determine sensor fit */
310         sensor_fit = BKE_camera_sensor_fit(params->sensor_fit, xasp * winx, yasp * winy);
311
312         if (sensor_fit == CAMERA_SENSOR_FIT_HOR)
313                 viewfac = winx;
314         else
315                 viewfac = params->ycor * winy;
316
317         pixsize /= viewfac;
318
319         /* extra zoom factor */
320         pixsize *= params->zoom;
321
322         /* compute view plane:
323          * fully centered, zbuffer fills in jittered between -.5 and +.5 */
324         viewplane.xmin = -0.5f * (float)winx;
325         viewplane.ymin = -0.5f * params->ycor * (float)winy;
326         viewplane.xmax =  0.5f * (float)winx;
327         viewplane.ymax =  0.5f * params->ycor * (float)winy;
328
329         /* lens shift and offset */
330         dx = params->shiftx * viewfac + winx * params->offsetx;
331         dy = params->shifty * viewfac + winy * params->offsety;
332
333         viewplane.xmin += dx;
334         viewplane.ymin += dy;
335         viewplane.xmax += dx;
336         viewplane.ymax += dy;
337
338         /* fields offset */
339         if (params->field_second) {
340                 if (params->field_odd) {
341                         viewplane.ymin -= 0.5f * params->ycor;
342                         viewplane.ymax -= 0.5f * params->ycor;
343                 }
344                 else {
345                         viewplane.ymin += 0.5f * params->ycor;
346                         viewplane.ymax += 0.5f * params->ycor;
347                 }
348         }
349
350         /* the window matrix is used for clipping, and not changed during OSA steps */
351         /* using an offset of +0.5 here would give clip errors on edges */
352         viewplane.xmin *= pixsize;
353         viewplane.xmax *= pixsize;
354         viewplane.ymin *= pixsize;
355         viewplane.ymax *= pixsize;
356
357         params->viewdx = pixsize;
358         params->viewdy = params->ycor * pixsize;
359         params->viewplane = viewplane;
360 }
361
362 /* viewplane is assumed to be already computed */
363 void BKE_camera_params_compute_matrix(CameraParams *params)
364 {
365         rctf viewplane = params->viewplane;
366
367         /* compute projection matrix */
368         if (params->is_ortho)
369                 orthographic_m4(params->winmat, viewplane.xmin, viewplane.xmax,
370                                 viewplane.ymin, viewplane.ymax, params->clipsta, params->clipend);
371         else
372                 perspective_m4(params->winmat, viewplane.xmin, viewplane.xmax,
373                                viewplane.ymin, viewplane.ymax, params->clipsta, params->clipend);
374 }
375
376 /***************************** Camera View Frame *****************************/
377
378 void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, const bool do_clip, const float scale[3],
379                               float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3])
380 {
381         float facx, facy;
382         float depth;
383
384         /* aspect correcton */
385         if (scene) {
386                 float aspx = (float) scene->r.xsch * scene->r.xasp;
387                 float aspy = (float) scene->r.ysch * scene->r.yasp;
388                 int sensor_fit = BKE_camera_sensor_fit(camera->sensor_fit, aspx, aspy);
389
390                 if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
391                         r_asp[0] = 1.0;
392                         r_asp[1] = aspy / aspx;
393                 }
394                 else {
395                         r_asp[0] = aspx / aspy;
396                         r_asp[1] = 1.0;
397                 }
398         }
399         else {
400                 r_asp[0] = 1.0f;
401                 r_asp[1] = 1.0f;
402         }
403
404         if (camera->type == CAM_ORTHO) {
405                 facx = 0.5f * camera->ortho_scale * r_asp[0] * scale[0];
406                 facy = 0.5f * camera->ortho_scale * r_asp[1] * scale[1];
407                 r_shift[0] = camera->shiftx * camera->ortho_scale * scale[0];
408                 r_shift[1] = camera->shifty * camera->ortho_scale * scale[1];
409                 depth = do_clip ? -((camera->clipsta * scale[2]) + 0.1f) : -drawsize * camera->ortho_scale * scale[2];
410
411                 *r_drawsize = 0.5f * camera->ortho_scale;
412         }
413         else {
414                 /* that way it's always visible - clipsta+0.1 */
415                 float fac, scale_x, scale_y;
416                 float half_sensor = 0.5f * ((camera->sensor_fit == CAMERA_SENSOR_FIT_VERT) ?
417                                             (camera->sensor_y) : (camera->sensor_x));
418
419
420                 if (do_clip) {
421                         /* fixed depth, variable size (avoids exceeding clipping range) */
422                         /* r_drawsize shouldn't be used in this case, set to dummy value */
423                         *r_drawsize = 1.0f;
424                         depth = -(camera->clipsta + 0.1f) * scale[2];
425                         fac = depth / (camera->lens / (-half_sensor));
426                         scale_x = 1.0f;
427                         scale_y = 1.0f;
428                 }
429                 else {
430                         /* fixed size, variable depth (stays a reasonable size in the 3D view) */
431                         *r_drawsize = drawsize / ((scale[0] + scale[1] + scale[2]) / 3.0f);
432                         depth = *r_drawsize * camera->lens / (-half_sensor) * scale[2];
433                         fac = *r_drawsize;
434                         scale_x = scale[0];
435                         scale_y = scale[1];
436                 }
437
438                 facx = fac * r_asp[0] * scale_x;
439                 facy = fac * r_asp[1] * scale_y;
440                 r_shift[0] = camera->shiftx * fac * 2.0f * scale_x;
441                 r_shift[1] = camera->shifty * fac * 2.0f * scale_y;
442         }
443
444         r_vec[0][0] = r_shift[0] + facx; r_vec[0][1] = r_shift[1] + facy; r_vec[0][2] = depth;
445         r_vec[1][0] = r_shift[0] + facx; r_vec[1][1] = r_shift[1] - facy; r_vec[1][2] = depth;
446         r_vec[2][0] = r_shift[0] - facx; r_vec[2][1] = r_shift[1] - facy; r_vec[2][2] = depth;
447         r_vec[3][0] = r_shift[0] - facx; r_vec[3][1] = r_shift[1] + facy; r_vec[3][2] = depth;
448 }
449
450 void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
451 {
452         float dummy_asp[2];
453         float dummy_shift[2];
454         float dummy_drawsize;
455         const float dummy_scale[3] = {1.0f, 1.0f, 1.0f};
456
457         BKE_camera_view_frame_ex(scene, camera, FALSE, 1.0, dummy_scale,
458                                  dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
459 }
460
461
462 typedef struct CameraViewFrameData {
463         float plane_tx[4][4];  /* 4 planes (not 4x4 matrix)*/
464         float frame_tx[4][3];
465         float normal_tx[4][3];
466         float dist_vals_sq[4];  /* distance squared (signed) */
467         unsigned int tot;
468 } CameraViewFrameData;
469
470 static void camera_to_frame_view_cb(const float co[3], void *user_data)
471 {
472         CameraViewFrameData *data = (CameraViewFrameData *)user_data;
473         unsigned int i;
474
475         for (i = 0; i < 4; i++) {
476                 float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]);
477                 if (nd < data->dist_vals_sq[i]) {
478                         data->dist_vals_sq[i] = nd;
479                 }
480         }
481
482         data->tot++;
483 }
484
485 /* don't move the camera, just yield the fit location */
486 /* only valid for perspective cameras */
487 bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
488 {
489         float shift[2];
490         float plane_tx[4][3];
491         float rot_obmat[3][3];
492         const float zero[3] = {0, 0, 0};
493         CameraViewFrameData data_cb;
494
495         unsigned int i;
496
497         BKE_camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);
498
499         copy_m3_m4(rot_obmat, camera_ob->obmat);
500         normalize_m3(rot_obmat);
501
502         for (i = 0; i < 4; i++) {
503                 /* normalize so Z is always 1.0f*/
504                 mul_v3_fl(data_cb.frame_tx[i], 1.0f / data_cb.frame_tx[i][2]);
505         }
506
507         /* get the shift back out of the frame */
508         shift[0] = (data_cb.frame_tx[0][0] +
509                     data_cb.frame_tx[1][0] +
510                     data_cb.frame_tx[2][0] +
511                     data_cb.frame_tx[3][0]) / 4.0f;
512         shift[1] = (data_cb.frame_tx[0][1] +
513                     data_cb.frame_tx[1][1] +
514                     data_cb.frame_tx[2][1] +
515                     data_cb.frame_tx[3][1]) / 4.0f;
516
517         for (i = 0; i < 4; i++) {
518                 mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
519         }
520
521         for (i = 0; i < 4; i++) {
522                 normal_tri_v3(data_cb.normal_tx[i], zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
523                 plane_from_point_normal_v3(data_cb.plane_tx[i], data_cb.frame_tx[i], data_cb.normal_tx[i]);
524         }
525
526         /* initialize callback data */
527         copy_v4_fl(data_cb.dist_vals_sq, FLT_MAX);
528         data_cb.tot = 0;
529         /* run callback on all visible points */
530         BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
531                                         camera_to_frame_view_cb, &data_cb);
532
533         if (data_cb.tot <= 1) {
534                 return false;
535         }
536         else {
537                 float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
538                 float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];
539
540                 float plane_isect_pt_1[3], plane_isect_pt_2[3];
541
542                 /* apply the dist-from-plane's to the transformed plane points */
543                 for (i = 0; i < 4; i++) {
544                         mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], sqrtf_signed(data_cb.dist_vals_sq[i]));
545                 }
546
547                 if ((!isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
548                                            plane_tx[0], data_cb.normal_tx[0],
549                                            plane_tx[2], data_cb.normal_tx[2])) ||
550                     (!isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
551                                            plane_tx[1], data_cb.normal_tx[1],
552                                            plane_tx[3], data_cb.normal_tx[3])))
553                 {
554                         return false;
555                 }
556
557                 add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no);
558                 add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);
559
560                 if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
561                                        plane_isect_2, plane_isect_2_other,
562                                        plane_isect_pt_1, plane_isect_pt_2) == 0)
563                 {
564                         return false;
565                 }
566                 else {
567                         float cam_plane_no[3] = {0.0f, 0.0f, -1.0f};
568                         float plane_isect_delta[3];
569                         float plane_isect_delta_len;
570
571                         mul_m3_v3(rot_obmat, cam_plane_no);
572
573                         sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
574                         plane_isect_delta_len = len_v3(plane_isect_delta);
575
576                         if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
577                                 copy_v3_v3(r_co, plane_isect_pt_1);
578
579                                 /* offset shift */
580                                 normalize_v3(plane_isect_1_no);
581                                 madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
582                         }
583                         else {
584                                 copy_v3_v3(r_co, plane_isect_pt_2);
585
586                                 /* offset shift */
587                                 normalize_v3(plane_isect_2_no);
588                                 madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
589                         }
590
591
592                         return true;
593                 }
594         }
595 }