Cleanup: warnings
[blender-staging.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 #include <stddef.h>
34
35 #include "DNA_camera_types.h"
36 #include "DNA_lamp_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_view3d_types.h"
40 #include "DNA_ID.h"
41
42 #include "BLI_math.h"
43 #include "BLI_rect.h"
44 #include "BLI_string.h"
45 #include "BLI_utildefines.h"
46
47 #include "BKE_animsys.h"
48 #include "BKE_camera.h"
49 #include "BKE_object.h"
50 #include "BKE_global.h"
51 #include "BKE_library.h"
52 #include "BKE_library_query.h"
53 #include "BKE_library_remap.h"
54 #include "BKE_main.h"
55 #include "BKE_scene.h"
56 #include "BKE_screen.h"
57
58 #include "GPU_compositing.h"
59
60 /****************************** Camera Datablock *****************************/
61
62 void BKE_camera_init(Camera *cam)
63 {
64         BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(cam, id));
65
66         cam->lens = 35.0f;
67         cam->sensor_x = DEFAULT_SENSOR_WIDTH;
68         cam->sensor_y = DEFAULT_SENSOR_HEIGHT;
69         cam->clipsta = 0.1f;
70         cam->clipend = 100.0f;
71         cam->drawsize = 0.5f;
72         cam->ortho_scale = 6.0;
73         cam->flag |= CAM_SHOWPASSEPARTOUT;
74         cam->passepartalpha = 0.5f;
75
76         GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
77
78         /* stereoscopy 3d */
79         cam->stereo.interocular_distance = 0.065f;
80         cam->stereo.convergence_distance = 30.f * 0.065f;
81         cam->stereo.pole_merge_angle_from = DEG2RADF(60.0f);
82         cam->stereo.pole_merge_angle_to = DEG2RADF(75.0f);
83 }
84
85 void *BKE_camera_add(Main *bmain, const char *name)
86 {
87         Camera *cam;
88
89         cam =  BKE_libblock_alloc(bmain, ID_CA, name);
90
91         BKE_camera_init(cam);
92
93         return cam;
94 }
95
96 Camera *BKE_camera_copy(Main *bmain, Camera *cam)
97 {
98         Camera *camn;
99         
100         camn = BKE_libblock_copy(bmain, &cam->id);
101
102         if (ID_IS_LINKED_DATABLOCK(cam)) {
103                 BKE_id_expand_local(&camn->id);
104                 BKE_id_lib_local_paths(bmain, cam->id.lib, &camn->id);
105         }
106
107         return camn;
108 }
109
110 void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local)
111 {
112         BKE_id_make_local_generic(bmain, &cam->id, true, lib_local);
113 }
114
115 /** Free (or release) any data used by this camera (does not free the camera itself). */
116 void BKE_camera_free(Camera *ca)
117 {
118         BKE_animdata_free((ID *)ca, false);
119 }
120
121 /******************************** Camera Usage *******************************/
122
123 void BKE_camera_object_mode(RenderData *rd, Object *cam_ob)
124 {
125         rd->mode &= ~(R_ORTHO | R_PANORAMA);
126
127         if (cam_ob && cam_ob->type == OB_CAMERA) {
128                 Camera *cam = cam_ob->data;
129                 if (cam->type == CAM_ORTHO) rd->mode |= R_ORTHO;
130                 if (cam->type == CAM_PANO) rd->mode |= R_PANORAMA;
131         }
132 }
133
134 /* get the camera's dof value, takes the dof object into account */
135 float BKE_camera_object_dof_distance(Object *ob)
136 {
137         Camera *cam = (Camera *)ob->data; 
138         if (ob->type != OB_CAMERA)
139                 return 0.0f;
140         if (cam->dof_ob) {
141 #if 0
142                 /* too simple, better to return the distance on the view axis only */
143                 return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]);
144 #else
145                 float view_dir[3], dof_dir[3];
146                 normalize_v3_v3(view_dir, ob->obmat[2]);
147                 sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof_ob->obmat[3]);
148                 return fabsf(dot_v3v3(view_dir, dof_dir));
149 #endif
150         }
151         return cam->YF_dofdist;
152 }
153
154 float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y)
155 {
156         /* sensor size used to fit to. for auto, sensor_x is both x and y. */
157         if (sensor_fit == CAMERA_SENSOR_FIT_VERT)
158                 return sensor_y;
159
160         return sensor_x;
161 }
162
163 int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey)
164 {
165         if (sensor_fit == CAMERA_SENSOR_FIT_AUTO) {
166                 if (sizex >= sizey)
167                         return CAMERA_SENSOR_FIT_HOR;
168                 else
169                         return CAMERA_SENSOR_FIT_VERT;
170         }
171
172         return sensor_fit;
173 }
174
175 /******************************** Camera Params *******************************/
176
177 void BKE_camera_params_init(CameraParams *params)
178 {
179         memset(params, 0, sizeof(CameraParams));
180
181         /* defaults */
182         params->sensor_x = DEFAULT_SENSOR_WIDTH;
183         params->sensor_y = DEFAULT_SENSOR_HEIGHT;
184         params->sensor_fit = CAMERA_SENSOR_FIT_AUTO;
185
186         params->zoom = 1.0f;
187
188         /* fallback for non camera objects */
189         params->clipsta = 0.1f;
190         params->clipend = 100.0f;
191 }
192
193 void BKE_camera_params_from_object(CameraParams *params, const Object *ob)
194 {
195         if (!ob)
196                 return;
197
198         if (ob->type == OB_CAMERA) {
199                 /* camera object */
200                 Camera *cam = ob->data;
201
202                 if (cam->type == CAM_ORTHO)
203                         params->is_ortho = true;
204                 params->lens = cam->lens;
205                 params->ortho_scale = cam->ortho_scale;
206
207                 params->shiftx = cam->shiftx;
208                 params->shifty = cam->shifty;
209
210                 params->sensor_x = cam->sensor_x;
211                 params->sensor_y = cam->sensor_y;
212                 params->sensor_fit = cam->sensor_fit;
213
214                 params->clipsta = cam->clipsta;
215                 params->clipend = cam->clipend;
216         }
217         else if (ob->type == OB_LAMP) {
218                 /* lamp object */
219                 Lamp *la = ob->data;
220                 float fac = cosf(la->spotsize * 0.5f);
221                 float phi = acosf(fac);
222
223                 params->lens = 16.0f * fac / sinf(phi);
224                 if (params->lens == 0.0f)
225                         params->lens = 35.0f;
226
227                 params->clipsta = la->clipsta;
228                 params->clipend = la->clipend;
229         }
230         else {
231                 params->lens = 35.0f;
232         }
233 }
234
235 void BKE_camera_params_from_view3d(CameraParams *params, const View3D *v3d, const RegionView3D *rv3d)
236 {
237         /* common */
238         params->lens = v3d->lens;
239         params->clipsta = v3d->near;
240         params->clipend = v3d->far;
241
242         if (rv3d->persp == RV3D_CAMOB) {
243                 /* camera view */
244                 BKE_camera_params_from_object(params, v3d->camera);
245
246                 params->zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
247
248                 params->offsetx = 2.0f * rv3d->camdx * params->zoom;
249                 params->offsety = 2.0f * rv3d->camdy * params->zoom;
250
251                 params->shiftx *= params->zoom;
252                 params->shifty *= params->zoom;
253
254                 params->zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params->zoom;
255         }
256         else if (rv3d->persp == RV3D_ORTHO) {
257                 /* orthographic view */
258                 int sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y);
259                 params->clipend *= 0.5f;    // otherwise too extreme low zbuffer quality
260                 params->clipsta = -params->clipend;
261
262                 params->is_ortho = true;
263                 /* make sure any changes to this match ED_view3d_radius_to_dist_ortho() */
264                 params->ortho_scale = rv3d->dist * sensor_size / v3d->lens;
265                 params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
266         }
267         else {
268                 /* perspective view */
269                 params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
270         }
271 }
272
273 void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int winy, float xasp, float yasp)
274 {
275         rctf viewplane;
276         float pixsize, viewfac, sensor_size, dx, dy;
277         int sensor_fit;
278
279         /* fields rendering */
280         params->ycor = yasp / xasp;
281         if (params->use_fields)
282                 params->ycor *= 2.0f;
283
284         if (params->is_ortho) {
285                 /* orthographic camera */
286                 /* scale == 1.0 means exact 1 to 1 mapping */
287                 pixsize = params->ortho_scale;
288         }
289         else {
290                 /* perspective camera */
291                 sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y);
292                 pixsize = (sensor_size * params->clipsta) / params->lens;
293         }
294
295         /* determine sensor fit */
296         sensor_fit = BKE_camera_sensor_fit(params->sensor_fit, xasp * winx, yasp * winy);
297
298         if (sensor_fit == CAMERA_SENSOR_FIT_HOR)
299                 viewfac = winx;
300         else
301                 viewfac = params->ycor * winy;
302
303         pixsize /= viewfac;
304
305         /* extra zoom factor */
306         pixsize *= params->zoom;
307
308         /* compute view plane:
309          * fully centered, zbuffer fills in jittered between -.5 and +.5 */
310         viewplane.xmin = -0.5f * (float)winx;
311         viewplane.ymin = -0.5f * params->ycor * (float)winy;
312         viewplane.xmax =  0.5f * (float)winx;
313         viewplane.ymax =  0.5f * params->ycor * (float)winy;
314
315         /* lens shift and offset */
316         dx = params->shiftx * viewfac + winx * params->offsetx;
317         dy = params->shifty * viewfac + winy * params->offsety;
318
319         viewplane.xmin += dx;
320         viewplane.ymin += dy;
321         viewplane.xmax += dx;
322         viewplane.ymax += dy;
323
324         /* fields offset */
325         if (params->field_second) {
326                 if (params->field_odd) {
327                         viewplane.ymin -= 0.5f * params->ycor;
328                         viewplane.ymax -= 0.5f * params->ycor;
329                 }
330                 else {
331                         viewplane.ymin += 0.5f * params->ycor;
332                         viewplane.ymax += 0.5f * params->ycor;
333                 }
334         }
335
336         /* the window matrix is used for clipping, and not changed during OSA steps */
337         /* using an offset of +0.5 here would give clip errors on edges */
338         viewplane.xmin *= pixsize;
339         viewplane.xmax *= pixsize;
340         viewplane.ymin *= pixsize;
341         viewplane.ymax *= pixsize;
342
343         params->viewdx = pixsize;
344         params->viewdy = params->ycor * pixsize;
345         params->viewplane = viewplane;
346 }
347
348 /* viewplane is assumed to be already computed */
349 void BKE_camera_params_compute_matrix(CameraParams *params)
350 {
351         rctf viewplane = params->viewplane;
352
353         /* compute projection matrix */
354         if (params->is_ortho)
355                 orthographic_m4(params->winmat, viewplane.xmin, viewplane.xmax,
356                                 viewplane.ymin, viewplane.ymax, params->clipsta, params->clipend);
357         else
358                 perspective_m4(params->winmat, viewplane.xmin, viewplane.xmax,
359                                viewplane.ymin, viewplane.ymax, params->clipsta, params->clipend);
360 }
361
362 /***************************** Camera View Frame *****************************/
363
364 void BKE_camera_view_frame_ex(
365         const Scene *scene, const Camera *camera,
366         const float drawsize, const bool do_clip, const float scale[3],
367         float r_asp[2], float r_shift[2], float *r_drawsize, float r_vec[4][3])
368 {
369         float facx, facy;
370         float depth;
371
372         /* aspect correcton */
373         if (scene) {
374                 float aspx = (float) scene->r.xsch * scene->r.xasp;
375                 float aspy = (float) scene->r.ysch * scene->r.yasp;
376                 int sensor_fit = BKE_camera_sensor_fit(camera->sensor_fit, aspx, aspy);
377
378                 if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
379                         r_asp[0] = 1.0;
380                         r_asp[1] = aspy / aspx;
381                 }
382                 else {
383                         r_asp[0] = aspx / aspy;
384                         r_asp[1] = 1.0;
385                 }
386         }
387         else {
388                 r_asp[0] = 1.0f;
389                 r_asp[1] = 1.0f;
390         }
391
392         if (camera->type == CAM_ORTHO) {
393                 facx = 0.5f * camera->ortho_scale * r_asp[0] * scale[0];
394                 facy = 0.5f * camera->ortho_scale * r_asp[1] * scale[1];
395                 r_shift[0] = camera->shiftx * camera->ortho_scale * scale[0];
396                 r_shift[1] = camera->shifty * camera->ortho_scale * scale[1];
397                 depth = do_clip ? -((camera->clipsta * scale[2]) + 0.1f) : -drawsize * camera->ortho_scale * scale[2];
398
399                 *r_drawsize = 0.5f * camera->ortho_scale;
400         }
401         else {
402                 /* that way it's always visible - clipsta+0.1 */
403                 float fac, scale_x, scale_y;
404                 float half_sensor = 0.5f * ((camera->sensor_fit == CAMERA_SENSOR_FIT_VERT) ?
405                                             (camera->sensor_y) : (camera->sensor_x));
406
407
408                 if (do_clip) {
409                         /* fixed depth, variable size (avoids exceeding clipping range) */
410                         /* r_drawsize shouldn't be used in this case, set to dummy value */
411                         *r_drawsize = 1.0f;
412                         depth = -(camera->clipsta + 0.1f) * scale[2];
413                         fac = depth / (camera->lens / (-half_sensor));
414                         scale_x = scale[0] / scale[2];
415                         scale_y = scale[1] / scale[2];
416                 }
417                 else {
418                         /* fixed size, variable depth (stays a reasonable size in the 3D view) */
419                         *r_drawsize = drawsize / ((scale[0] + scale[1] + scale[2]) / 3.0f);
420                         depth = *r_drawsize * camera->lens / (-half_sensor) * scale[2];
421                         fac = *r_drawsize;
422                         scale_x = scale[0];
423                         scale_y = scale[1];
424                 }
425
426                 facx = fac * r_asp[0] * scale_x;
427                 facy = fac * r_asp[1] * scale_y;
428                 r_shift[0] = camera->shiftx * fac * 2.0f * scale_x;
429                 r_shift[1] = camera->shifty * fac * 2.0f * scale_y;
430         }
431
432         r_vec[0][0] = r_shift[0] + facx; r_vec[0][1] = r_shift[1] + facy; r_vec[0][2] = depth;
433         r_vec[1][0] = r_shift[0] + facx; r_vec[1][1] = r_shift[1] - facy; r_vec[1][2] = depth;
434         r_vec[2][0] = r_shift[0] - facx; r_vec[2][1] = r_shift[1] - facy; r_vec[2][2] = depth;
435         r_vec[3][0] = r_shift[0] - facx; r_vec[3][1] = r_shift[1] + facy; r_vec[3][2] = depth;
436 }
437
438 void BKE_camera_view_frame(const Scene *scene, const Camera *camera, float r_vec[4][3])
439 {
440         float dummy_asp[2];
441         float dummy_shift[2];
442         float dummy_drawsize;
443         const float dummy_scale[3] = {1.0f, 1.0f, 1.0f};
444
445         BKE_camera_view_frame_ex(scene, camera, 0.0, true, dummy_scale,
446                                  dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
447 }
448
449 #define CAMERA_VIEWFRAME_NUM_PLANES 4
450
451 typedef struct CameraViewFrameData {
452         float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4];  /* 4 planes */
453         float normal_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
454         float dist_vals_sq[CAMERA_VIEWFRAME_NUM_PLANES];  /* distance squared (signed) */
455         unsigned int tot;
456
457         /* Ortho camera only. */
458         bool is_ortho;
459         float camera_no[3];
460         float dist_to_cam;
461
462         /* Not used by callbacks... */
463         float camera_rotmat[3][3];
464 } CameraViewFrameData;
465
466 static void camera_to_frame_view_cb(const float co[3], void *user_data)
467 {
468         CameraViewFrameData *data = (CameraViewFrameData *)user_data;
469         unsigned int i;
470
471         for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
472                 const float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
473                 CLAMP_MAX(data->dist_vals_sq[i], nd);
474         }
475
476         if (data->is_ortho) {
477                 const float d = dot_v3v3(data->camera_no, co);
478                 CLAMP_MAX(data->dist_to_cam, d);
479         }
480
481         data->tot++;
482 }
483
484 static void camera_frame_fit_data_init(
485         const Scene *scene, const Object *ob,
486         CameraParams *params, CameraViewFrameData *data)
487 {
488         float camera_rotmat_transposed_inversed[4][4];
489         unsigned int i;
490
491         /* setup parameters */
492         BKE_camera_params_init(params);
493         BKE_camera_params_from_object(params, ob);
494
495         /* compute matrix, viewplane, .. */
496         if (scene) {
497                 BKE_camera_params_compute_viewplane(params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
498         }
499         else {
500                 BKE_camera_params_compute_viewplane(params, 1, 1, 1.0f, 1.0f);
501         }
502         BKE_camera_params_compute_matrix(params);
503
504         /* initialize callback data */
505         copy_m3_m4(data->camera_rotmat, (float (*)[4])ob->obmat);
506         normalize_m3(data->camera_rotmat);
507         /* To transform a plane which is in its homogeneous representation (4d vector),
508          * we need the inverse of the transpose of the transform matrix... */
509         copy_m4_m3(camera_rotmat_transposed_inversed, data->camera_rotmat);
510         transpose_m4(camera_rotmat_transposed_inversed);
511         invert_m4(camera_rotmat_transposed_inversed);
512
513         /* Extract frustum planes from projection matrix. */
514         planes_from_projmat(params->winmat,
515                             /*   left              right                 top              bottom        near  far */
516                             data->plane_tx[2], data->plane_tx[0], data->plane_tx[3], data->plane_tx[1], NULL, NULL);
517
518         /* Rotate planes and get normals from them */
519         for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
520                 mul_m4_v4(camera_rotmat_transposed_inversed, data->plane_tx[i]);
521                 normalize_v3_v3(data->normal_tx[i], data->plane_tx[i]);
522         }
523
524         copy_v4_fl(data->dist_vals_sq, FLT_MAX);
525         data->tot = 0;
526         data->is_ortho = params->is_ortho;
527         if (params->is_ortho) {
528                 /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
529                 negate_v3_v3(data->camera_no, data->camera_rotmat[2]);
530                 data->dist_to_cam = FLT_MAX;
531         }
532 }
533
534 static bool camera_frame_fit_calc_from_data(
535         CameraParams *params, CameraViewFrameData *data, float r_co[3], float *r_scale)
536 {
537         float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4];
538         unsigned int i;
539
540         if (data->tot <= 1) {
541                 return false;
542         }
543
544         if (params->is_ortho) {
545                 const float *cam_axis_x = data->camera_rotmat[0];
546                 const float *cam_axis_y = data->camera_rotmat[1];
547                 const float *cam_axis_z = data->camera_rotmat[2];
548                 float dists[CAMERA_VIEWFRAME_NUM_PLANES];
549                 float scale_diff;
550
551                 /* apply the dist-from-plane's to the transformed plane points */
552                 for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
553                         dists[i] = sqrtf_signed(data->dist_vals_sq[i]);
554                 }
555
556                 if ((dists[0] + dists[2]) > (dists[1] + dists[3])) {
557                         scale_diff = (dists[1] + dists[3]) *
558                                      (BLI_rctf_size_x(&params->viewplane) / BLI_rctf_size_y(&params->viewplane));
559                 }
560                 else {
561                         scale_diff = (dists[0] + dists[2]) *
562                                      (BLI_rctf_size_y(&params->viewplane) / BLI_rctf_size_x(&params->viewplane));
563                 }
564                 *r_scale = params->ortho_scale - scale_diff;
565
566                 zero_v3(r_co);
567                 madd_v3_v3fl(r_co, cam_axis_x, (dists[2] - dists[0]) * 0.5f + params->shiftx * scale_diff);
568                 madd_v3_v3fl(r_co, cam_axis_y, (dists[1] - dists[3]) * 0.5f + params->shifty * scale_diff);
569                 madd_v3_v3fl(r_co, cam_axis_z, -(data->dist_to_cam - 1.0f - params->clipsta));
570
571                 return true;
572         }
573         else {
574                 float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
575                 float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];
576
577                 float plane_isect_pt_1[3], plane_isect_pt_2[3];
578
579                 /* apply the dist-from-plane's to the transformed plane points */
580                 for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
581                         float co[3];
582                         mul_v3_v3fl(co, data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
583                         plane_from_point_normal_v3(plane_tx[i], co, data->normal_tx[i]);
584                 }
585
586                 if ((!isect_plane_plane_v3(plane_tx[0], plane_tx[2], plane_isect_1, plane_isect_1_no)) ||
587                     (!isect_plane_plane_v3(plane_tx[1], plane_tx[3], plane_isect_2, plane_isect_2_no)))
588                 {
589                         return false;
590                 }
591
592                 add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no);
593                 add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);
594
595                 if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
596                                        plane_isect_2, plane_isect_2_other,
597                                        plane_isect_pt_1, plane_isect_pt_2) != 0)
598                 {
599                         float cam_plane_no[3];
600                         float plane_isect_delta[3];
601                         float plane_isect_delta_len;
602
603                         float shift_fac = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y) /
604                                           params->lens;
605
606                         /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
607                         negate_v3_v3(cam_plane_no, data->camera_rotmat[2]);
608
609                         sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
610                         plane_isect_delta_len = len_v3(plane_isect_delta);
611
612                         if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
613                                 copy_v3_v3(r_co, plane_isect_pt_1);
614
615                                 /* offset shift */
616                                 normalize_v3(plane_isect_1_no);
617                                 madd_v3_v3fl(r_co, plane_isect_1_no, params->shifty * plane_isect_delta_len * shift_fac);
618                         }
619                         else {
620                                 copy_v3_v3(r_co, plane_isect_pt_2);
621
622                                 /* offset shift */
623                                 normalize_v3(plane_isect_2_no);
624                                 madd_v3_v3fl(r_co, plane_isect_2_no, params->shiftx * plane_isect_delta_len * shift_fac);
625                         }
626
627                         return true;
628                 }
629         }
630
631         return false;
632 }
633
634 /* don't move the camera, just yield the fit location */
635 /* r_scale only valid/useful for ortho cameras */
636 bool BKE_camera_view_frame_fit_to_scene(
637         Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale)
638 {
639         CameraParams params;
640         CameraViewFrameData data_cb;
641
642         /* just in case */
643         *r_scale = 1.0f;
644
645         camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
646
647         /* run callback on all visible points */
648         BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb);
649
650         return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
651 }
652
653 bool BKE_camera_view_frame_fit_to_coords(
654         const Scene *scene, const float (*cos)[3], int num_cos, const Object *camera_ob,
655         float r_co[3], float *r_scale)
656 {
657         CameraParams params;
658         CameraViewFrameData data_cb;
659
660         /* just in case */
661         *r_scale = 1.0f;
662
663         camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
664
665         /* run callback on all given coordinates */
666         while (num_cos--) {
667                 camera_to_frame_view_cb(cos[num_cos], &data_cb);
668         }
669
670         return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
671 }
672
673 /******************* multiview matrix functions ***********************/
674
675 static void camera_model_matrix(Object *camera, float r_modelmat[4][4])
676 {
677         copy_m4_m4(r_modelmat, camera->obmat);
678 }
679
680 static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4])
681 {
682         Camera *data = (Camera *)camera->data;
683         float interocular_distance, convergence_distance;
684         short convergence_mode, pivot;
685         float sizemat[4][4];
686
687         float fac = 1.0f;
688         float fac_signed;
689
690         interocular_distance = data->stereo.interocular_distance;
691         convergence_distance = data->stereo.convergence_distance;
692         convergence_mode = data->stereo.convergence_mode;
693         pivot = data->stereo.pivot;
694
695         if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
696             ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
697         {
698                 camera_model_matrix(camera, r_modelmat);
699                 return;
700         }
701         else {
702                 float size[3];
703                 mat4_to_size(size, camera->obmat);
704                 size_to_mat4(sizemat, size);
705         }
706
707         if (pivot == CAM_S3D_PIVOT_CENTER)
708                 fac = 0.5f;
709
710         fac_signed = is_left ? fac : -fac;
711
712         /* rotation */
713         if (convergence_mode == CAM_S3D_TOE) {
714                 float angle;
715                 float angle_sin, angle_cos;
716                 float toeinmat[4][4];
717                 float rotmat[4][4];
718
719                 unit_m4(rotmat);
720
721                 if (pivot == CAM_S3D_PIVOT_CENTER) {
722                         fac = -fac;
723                         fac_signed = -fac_signed;
724                 }
725
726                 angle = atanf((interocular_distance * 0.5f) / convergence_distance) / fac;
727
728                 angle_cos = cosf(angle * fac_signed);
729                 angle_sin = sinf(angle * fac_signed);
730
731                 rotmat[0][0] =  angle_cos;
732                 rotmat[2][0] = -angle_sin;
733                 rotmat[0][2] =  angle_sin;
734                 rotmat[2][2] =  angle_cos;
735
736                 if (pivot == CAM_S3D_PIVOT_CENTER) {
737                         /* set the rotation */
738                         copy_m4_m4(toeinmat, rotmat);
739                         /* set the translation */
740                         toeinmat[3][0] = interocular_distance * fac_signed;
741
742                         /* transform */
743                         normalize_m4_m4(r_modelmat, camera->obmat);
744                         mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
745
746                         /* scale back to the original size */
747                         mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
748                 }
749                 else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */
750                         /* rotate perpendicular to the interocular line */
751                         normalize_m4_m4(r_modelmat, camera->obmat);
752                         mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
753
754                         /* translate along the interocular line */
755                         unit_m4(toeinmat);
756                         toeinmat[3][0] = -interocular_distance * fac_signed;
757                         mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
758
759                         /* rotate to toe-in angle */
760                         mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
761
762                         /* scale back to the original size */
763                         mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
764                 }
765         }
766         else {
767                 normalize_m4_m4(r_modelmat, camera->obmat);
768
769                 /* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */
770                 translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f);
771
772                 /* scale back to the original size */
773                 mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
774         }
775 }
776
777 /* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */
778 void BKE_camera_multiview_view_matrix(RenderData *rd, Object *camera, const bool is_left, float r_viewmat[4][4])
779 {
780         BKE_camera_multiview_model_matrix(rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat);
781         invert_m4(r_viewmat);
782 }
783
784 /* left is the default */
785 static bool camera_is_left(const char *viewname)
786 {
787         if (viewname && viewname[0] != '\0') {
788                 return !STREQ(viewname, STEREO_RIGHT_NAME);
789         }
790         return true;
791 }
792
793 void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4])
794 {
795         const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
796
797         if (!is_multiview) {
798                 camera_model_matrix(camera, r_modelmat);
799         }
800         else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
801                 camera_model_matrix(camera, r_modelmat);
802         }
803         else { /* SCE_VIEWS_SETUP_BASIC */
804                 const bool is_left = camera_is_left(viewname);
805                 camera_stereo3d_model_matrix(camera, is_left, r_modelmat);
806         }
807         normalize_m4(r_modelmat);
808 }
809
810 bool BKE_camera_multiview_spherical_stereo(RenderData *rd, Object *camera)
811 {
812         Camera *cam;
813         const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
814
815         if (!is_multiview)
816                 return false;
817
818         if (camera->type != OB_CAMERA)
819                 return false;
820         else
821                 cam = camera->data;
822
823         if ((rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) &&
824             ELEM(cam->type, CAM_PANO, CAM_PERSP) &&
825             ((cam->stereo.flag & CAM_S3D_SPHERICAL) != 0))
826         {
827                 return true;
828         }
829
830         return false;
831 }
832
833 static Object *camera_multiview_advanced(Scene *scene, Object *camera, const char *suffix)
834 {
835         SceneRenderView *srv;
836         char name[MAX_NAME];
837         const char *camera_name = camera->id.name + 2;
838         const int len_name = strlen(camera_name);
839         int len_suffix_max = -1;
840
841         name[0] = '\0';
842
843         /* we need to take the better match, thus the len_suffix_max test */
844         for (srv = scene->r.views.first; srv; srv = srv->next) {
845                 const int len_suffix = strlen(srv->suffix);
846
847                 if ((len_suffix < len_suffix_max) || (len_name < len_suffix))
848                         continue;
849
850                 if (STREQ(camera_name + (len_name - len_suffix), srv->suffix)) {
851                         BLI_snprintf(name, sizeof(name), "%.*s%s", (len_name - len_suffix), camera_name, suffix);
852                         len_suffix_max = len_suffix;
853                 }
854         }
855
856         if (name[0] != '\0') {
857                 Base *base = BKE_scene_base_find_by_name(scene, name);
858                 if (base) {
859                         return base->object;
860                 }
861         }
862
863         return camera;
864 }
865
866 /* returns the camera to be used for render */
867 Object *BKE_camera_multiview_render(Scene *scene, Object *camera, const char *viewname)
868 {
869         const bool is_multiview = (camera != NULL) &&  (scene->r.scemode & R_MULTIVIEW) != 0;
870
871         if (!is_multiview) {
872                 return camera;
873         }
874         else if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
875                 return camera;
876         }
877         else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
878                 const char *suffix = BKE_scene_multiview_view_suffix_get(&scene->r, viewname);
879                 return camera_multiview_advanced(scene, camera, suffix);
880         }
881 }
882
883 static float camera_stereo3d_shift_x(Object *camera, const char *viewname)
884 {
885         Camera *data = camera->data;
886         float shift = data->shiftx;
887         float interocular_distance, convergence_distance;
888         short convergence_mode, pivot;
889         bool is_left = true;
890
891         float fac = 1.0f;
892         float fac_signed;
893
894         if (viewname && viewname[0]) {
895                 is_left = STREQ(viewname, STEREO_LEFT_NAME);
896         }
897
898         interocular_distance = data->stereo.interocular_distance;
899         convergence_distance = data->stereo.convergence_distance;
900         convergence_mode = data->stereo.convergence_mode;
901         pivot = data->stereo.pivot;
902
903         if (convergence_mode != CAM_S3D_OFFAXIS)
904                 return shift;
905
906         if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) ||
907             ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left))
908         {
909                 return shift;
910         }
911
912         if (pivot == CAM_S3D_PIVOT_CENTER)
913                 fac = 0.5f;
914
915         fac_signed = is_left ? fac : -fac;
916         shift += ((interocular_distance / data->sensor_x) * (data->lens / convergence_distance)) * fac_signed;
917
918         return shift;
919 }
920
921 float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *viewname)
922 {
923         const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
924         Camera *data = camera->data;
925
926         BLI_assert(camera->type == OB_CAMERA);
927
928         if (!is_multiview) {
929                 return data->shiftx;
930         }
931         else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
932                 return data->shiftx;
933         }
934         else { /* SCE_VIEWS_SETUP_BASIC */
935                 return camera_stereo3d_shift_x(camera, viewname);
936         }
937 }
938
939 void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, Object *camera, const char *viewname)
940 {
941         if (camera->type == OB_CAMERA) {
942                 params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname);
943         }
944 }
945
946 void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings)
947 {
948         if (camera->type == OB_CAMERA) {
949                 Camera *cam = camera->data;
950                 r_fx_settings->dof = &cam->gpu_dof;
951                 r_fx_settings->dof->focal_length = cam->lens;
952                 r_fx_settings->dof->sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
953                 r_fx_settings->dof->focus_distance = BKE_camera_object_dof_distance(camera);
954         }
955 }