1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup bke
22  */
23 
24 #include <stddef.h>
25 #include <stdlib.h>
26 
27 /* Allow using deprecated functionality for .blend file I/O. */
28 #define DNA_DEPRECATED_ALLOW
29 
30 #include "DNA_ID.h"
31 #include "DNA_camera_types.h"
32 #include "DNA_defaults.h"
33 #include "DNA_light_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_view3d_types.h"
37 
38 #include "BLI_listbase.h"
39 #include "BLI_math.h"
40 #include "BLI_rect.h"
41 #include "BLI_string.h"
42 #include "BLI_utildefines.h"
43 
44 #include "BKE_anim_data.h"
45 #include "BKE_camera.h"
46 #include "BKE_idtype.h"
47 #include "BKE_layer.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_lib_query.h"
50 #include "BKE_main.h"
51 #include "BKE_object.h"
52 #include "BKE_scene.h"
53 #include "BKE_screen.h"
54 
55 #include "BLT_translation.h"
56 
57 #include "DEG_depsgraph_query.h"
58 
59 #include "MEM_guardedalloc.h"
60 
61 #include "BLO_read_write.h"
62 
63 /* -------------------------------------------------------------------- */
64 /** \name Camera Data-Block
65  * \{ */
66 
camera_init_data(ID * id)67 static void camera_init_data(ID *id)
68 {
69   Camera *cam = (Camera *)id;
70   BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(cam, id));
71 
72   MEMCPY_STRUCT_AFTER(cam, DNA_struct_default_get(Camera), id);
73 }
74 
75 /**
76  * Only copy internal data of Camera ID from source
77  * to already allocated/initialized destination.
78  * You probably never want to use that directly,
79  * use #BKE_id_copy or #BKE_id_copy_ex for typical needs.
80  *
81  * WARNING! This function will not handle ID user count!
82  *
83  * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
84  */
camera_copy_data(Main * UNUSED (bmain),ID * id_dst,const ID * id_src,const int UNUSED (flag))85 static void camera_copy_data(Main *UNUSED(bmain),
86                              ID *id_dst,
87                              const ID *id_src,
88                              const int UNUSED(flag))
89 {
90   Camera *cam_dst = (Camera *)id_dst;
91   const Camera *cam_src = (const Camera *)id_src;
92   BLI_duplicatelist(&cam_dst->bg_images, &cam_src->bg_images);
93 }
94 
camera_make_local(Main * bmain,ID * id,const int flags)95 static void camera_make_local(Main *bmain, ID *id, const int flags)
96 {
97   BKE_lib_id_make_local_generic(bmain, id, flags);
98 }
99 
100 /** Free (or release) any data used by this camera (does not free the camera itself). */
camera_free_data(ID * id)101 static void camera_free_data(ID *id)
102 {
103   Camera *cam = (Camera *)id;
104   BLI_freelistN(&cam->bg_images);
105 }
106 
camera_foreach_id(ID * id,LibraryForeachIDData * data)107 static void camera_foreach_id(ID *id, LibraryForeachIDData *data)
108 {
109   Camera *camera = (Camera *)id;
110 
111   BKE_LIB_FOREACHID_PROCESS(data, camera->dof.focus_object, IDWALK_CB_NOP);
112   LISTBASE_FOREACH (CameraBGImage *, bgpic, &camera->bg_images) {
113     if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
114       BKE_LIB_FOREACHID_PROCESS(data, bgpic->ima, IDWALK_CB_USER);
115     }
116     else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
117       BKE_LIB_FOREACHID_PROCESS(data, bgpic->clip, IDWALK_CB_USER);
118     }
119   }
120 }
121 
camera_blend_write(BlendWriter * writer,ID * id,const void * id_address)122 static void camera_blend_write(BlendWriter *writer, ID *id, const void *id_address)
123 {
124   Camera *cam = (Camera *)id;
125   if (cam->id.us > 0 || BLO_write_is_undo(writer)) {
126     /* write LibData */
127     BLO_write_id_struct(writer, Camera, id_address, &cam->id);
128     BKE_id_blend_write(writer, &cam->id);
129 
130     if (cam->adt) {
131       BKE_animdata_blend_write(writer, cam->adt);
132     }
133 
134     LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) {
135       BLO_write_struct(writer, CameraBGImage, bgpic);
136     }
137   }
138 }
139 
camera_blend_read_data(BlendDataReader * reader,ID * id)140 static void camera_blend_read_data(BlendDataReader *reader, ID *id)
141 {
142   Camera *ca = (Camera *)id;
143   BLO_read_data_address(reader, &ca->adt);
144   BKE_animdata_blend_read_data(reader, ca->adt);
145 
146   BLO_read_list(reader, &ca->bg_images);
147 
148   LISTBASE_FOREACH (CameraBGImage *, bgpic, &ca->bg_images) {
149     bgpic->iuser.ok = 1;
150     bgpic->iuser.scene = NULL;
151   }
152 }
153 
camera_blend_read_lib(BlendLibReader * reader,ID * id)154 static void camera_blend_read_lib(BlendLibReader *reader, ID *id)
155 {
156   Camera *ca = (Camera *)id;
157   BLO_read_id_address(reader, ca->id.lib, &ca->ipo); /* deprecated, for versioning */
158 
159   BLO_read_id_address(reader, ca->id.lib, &ca->dof_ob); /* deprecated, for versioning */
160   BLO_read_id_address(reader, ca->id.lib, &ca->dof.focus_object);
161 
162   LISTBASE_FOREACH (CameraBGImage *, bgpic, &ca->bg_images) {
163     BLO_read_id_address(reader, ca->id.lib, &bgpic->ima);
164     BLO_read_id_address(reader, ca->id.lib, &bgpic->clip);
165   }
166 }
167 
camera_blend_read_expand(BlendExpander * expander,ID * id)168 static void camera_blend_read_expand(BlendExpander *expander, ID *id)
169 {
170   Camera *ca = (Camera *)id;
171   BLO_expand(expander, ca->ipo);  // XXX deprecated - old animation system
172 
173   LISTBASE_FOREACH (CameraBGImage *, bgpic, &ca->bg_images) {
174     if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
175       BLO_expand(expander, bgpic->ima);
176     }
177     else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
178       BLO_expand(expander, bgpic->ima);
179     }
180   }
181 }
182 
183 IDTypeInfo IDType_ID_CA = {
184     .id_code = ID_CA,
185     .id_filter = FILTER_ID_CA,
186     .main_listbase_index = INDEX_ID_CA,
187     .struct_size = sizeof(Camera),
188     .name = "Camera",
189     .name_plural = "cameras",
190     .translation_context = BLT_I18NCONTEXT_ID_CAMERA,
191     .flags = 0,
192 
193     .init_data = camera_init_data,
194     .copy_data = camera_copy_data,
195     .free_data = camera_free_data,
196     .make_local = camera_make_local,
197     .foreach_id = camera_foreach_id,
198     .foreach_cache = NULL,
199 
200     .blend_write = camera_blend_write,
201     .blend_read_data = camera_blend_read_data,
202     .blend_read_lib = camera_blend_read_lib,
203     .blend_read_expand = camera_blend_read_expand,
204 };
205 
206 /** \} */
207 
208 /* -------------------------------------------------------------------- */
209 /** \name Camera Usage
210  * \{ */
211 
BKE_camera_add(Main * bmain,const char * name)212 void *BKE_camera_add(Main *bmain, const char *name)
213 {
214   Camera *cam;
215 
216   cam = BKE_id_new(bmain, ID_CA, name);
217 
218   return cam;
219 }
220 
221 /* get the camera's dof value, takes the dof object into account */
BKE_camera_object_dof_distance(Object * ob)222 float BKE_camera_object_dof_distance(Object *ob)
223 {
224   Camera *cam = (Camera *)ob->data;
225   if (ob->type != OB_CAMERA) {
226     return 0.0f;
227   }
228   if (cam->dof.focus_object) {
229     float view_dir[3], dof_dir[3];
230     normalize_v3_v3(view_dir, ob->obmat[2]);
231     sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof.focus_object->obmat[3]);
232     return fabsf(dot_v3v3(view_dir, dof_dir));
233   }
234   return cam->dof.focus_distance;
235 }
236 
BKE_camera_sensor_size(int sensor_fit,float sensor_x,float sensor_y)237 float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y)
238 {
239   /* sensor size used to fit to. for auto, sensor_x is both x and y. */
240   if (sensor_fit == CAMERA_SENSOR_FIT_VERT) {
241     return sensor_y;
242   }
243 
244   return sensor_x;
245 }
246 
BKE_camera_sensor_fit(int sensor_fit,float sizex,float sizey)247 int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey)
248 {
249   if (sensor_fit == CAMERA_SENSOR_FIT_AUTO) {
250     if (sizex >= sizey) {
251       return CAMERA_SENSOR_FIT_HOR;
252     }
253 
254     return CAMERA_SENSOR_FIT_VERT;
255   }
256 
257   return sensor_fit;
258 }
259 
260 /** \} */
261 
262 /* -------------------------------------------------------------------- */
263 /** \name Camera Parameter Access
264  * \{ */
265 
BKE_camera_params_init(CameraParams * params)266 void BKE_camera_params_init(CameraParams *params)
267 {
268   memset(params, 0, sizeof(CameraParams));
269 
270   /* defaults */
271   params->sensor_x = DEFAULT_SENSOR_WIDTH;
272   params->sensor_y = DEFAULT_SENSOR_HEIGHT;
273   params->sensor_fit = CAMERA_SENSOR_FIT_AUTO;
274 
275   params->zoom = 1.0f;
276 
277   /* fallback for non camera objects */
278   params->clip_start = 0.1f;
279   params->clip_end = 100.0f;
280 }
281 
BKE_camera_params_from_object(CameraParams * params,const Object * cam_ob)282 void BKE_camera_params_from_object(CameraParams *params, const Object *cam_ob)
283 {
284   if (!cam_ob) {
285     return;
286   }
287 
288   if (cam_ob->type == OB_CAMERA) {
289     /* camera object */
290     Camera *cam = cam_ob->data;
291 
292     if (cam->type == CAM_ORTHO) {
293       params->is_ortho = true;
294     }
295     params->lens = cam->lens;
296     params->ortho_scale = cam->ortho_scale;
297 
298     params->shiftx = cam->shiftx;
299     params->shifty = cam->shifty;
300 
301     params->sensor_x = cam->sensor_x;
302     params->sensor_y = cam->sensor_y;
303     params->sensor_fit = cam->sensor_fit;
304 
305     params->clip_start = cam->clip_start;
306     params->clip_end = cam->clip_end;
307   }
308   else if (cam_ob->type == OB_LAMP) {
309     /* light object */
310     Light *la = cam_ob->data;
311     params->lens = 16.0f / tanf(la->spotsize * 0.5f);
312     if (params->lens == 0.0f) {
313       params->lens = 35.0f;
314     }
315   }
316   else {
317     params->lens = 35.0f;
318   }
319 }
320 
BKE_camera_params_from_view3d(CameraParams * params,Depsgraph * depsgraph,const View3D * v3d,const RegionView3D * rv3d)321 void BKE_camera_params_from_view3d(CameraParams *params,
322                                    Depsgraph *depsgraph,
323                                    const View3D *v3d,
324                                    const RegionView3D *rv3d)
325 {
326   /* common */
327   params->lens = v3d->lens;
328   params->clip_start = v3d->clip_start;
329   params->clip_end = v3d->clip_end;
330 
331   if (rv3d->persp == RV3D_CAMOB) {
332     /* camera view */
333     const Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera);
334     BKE_camera_params_from_object(params, ob_camera_eval);
335 
336     params->zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
337 
338     params->offsetx = 2.0f * rv3d->camdx * params->zoom;
339     params->offsety = 2.0f * rv3d->camdy * params->zoom;
340 
341     params->shiftx *= params->zoom;
342     params->shifty *= params->zoom;
343 
344     params->zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params->zoom;
345   }
346   else if (rv3d->persp == RV3D_ORTHO) {
347     /* orthographic view */
348     float sensor_size = BKE_camera_sensor_size(
349         params->sensor_fit, params->sensor_x, params->sensor_y);
350     /* Halve, otherwise too extreme low zbuffer quality. */
351     params->clip_end *= 0.5f;
352     params->clip_start = -params->clip_end;
353 
354     params->is_ortho = true;
355     /* make sure any changes to this match ED_view3d_radius_to_dist_ortho() */
356     params->ortho_scale = rv3d->dist * sensor_size / v3d->lens;
357     params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
358   }
359   else {
360     /* perspective view */
361     params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
362   }
363 }
364 
BKE_camera_params_compute_viewplane(CameraParams * params,int winx,int winy,float aspx,float aspy)365 void BKE_camera_params_compute_viewplane(
366     CameraParams *params, int winx, int winy, float aspx, float aspy)
367 {
368   rctf viewplane;
369   float pixsize, viewfac, sensor_size, dx, dy;
370   int sensor_fit;
371 
372   params->ycor = aspy / aspx;
373 
374   if (params->is_ortho) {
375     /* orthographic camera */
376     /* scale == 1.0 means exact 1 to 1 mapping */
377     pixsize = params->ortho_scale;
378   }
379   else {
380     /* perspective camera */
381     sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y);
382     pixsize = (sensor_size * params->clip_start) / params->lens;
383   }
384 
385   /* determine sensor fit */
386   sensor_fit = BKE_camera_sensor_fit(params->sensor_fit, aspx * winx, aspy * winy);
387 
388   if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
389     viewfac = winx;
390   }
391   else {
392     viewfac = params->ycor * winy;
393   }
394 
395   pixsize /= viewfac;
396 
397   /* extra zoom factor */
398   pixsize *= params->zoom;
399 
400   /* compute view plane:
401    * fully centered, zbuffer fills in jittered between -.5 and +.5 */
402   viewplane.xmin = -0.5f * (float)winx;
403   viewplane.ymin = -0.5f * params->ycor * (float)winy;
404   viewplane.xmax = 0.5f * (float)winx;
405   viewplane.ymax = 0.5f * params->ycor * (float)winy;
406 
407   /* lens shift and offset */
408   dx = params->shiftx * viewfac + winx * params->offsetx;
409   dy = params->shifty * viewfac + winy * params->offsety;
410 
411   viewplane.xmin += dx;
412   viewplane.ymin += dy;
413   viewplane.xmax += dx;
414   viewplane.ymax += dy;
415 
416   /* the window matrix is used for clipping, and not changed during OSA steps */
417   /* using an offset of +0.5 here would give clip errors on edges */
418   viewplane.xmin *= pixsize;
419   viewplane.xmax *= pixsize;
420   viewplane.ymin *= pixsize;
421   viewplane.ymax *= pixsize;
422 
423   /* Used for rendering (offset by near-clip with perspective views), passed to RE_SetPixelSize.
424    * For viewport drawing 'RegionView3D.pixsize'. */
425   params->viewdx = pixsize;
426   params->viewdy = params->ycor * pixsize;
427   params->viewplane = viewplane;
428 }
429 
430 /* viewplane is assumed to be already computed */
BKE_camera_params_compute_matrix(CameraParams * params)431 void BKE_camera_params_compute_matrix(CameraParams *params)
432 {
433   rctf viewplane = params->viewplane;
434 
435   /* compute projection matrix */
436   if (params->is_ortho) {
437     orthographic_m4(params->winmat,
438                     viewplane.xmin,
439                     viewplane.xmax,
440                     viewplane.ymin,
441                     viewplane.ymax,
442                     params->clip_start,
443                     params->clip_end);
444   }
445   else {
446     perspective_m4(params->winmat,
447                    viewplane.xmin,
448                    viewplane.xmax,
449                    viewplane.ymin,
450                    viewplane.ymax,
451                    params->clip_start,
452                    params->clip_end);
453   }
454 }
455 
456 /** \} */
457 
458 /* -------------------------------------------------------------------- */
459 /** \name Camera View Frame
460  * \{ */
461 
BKE_camera_view_frame_ex(const Scene * scene,const Camera * camera,const float drawsize,const bool do_clip,const float scale[3],float r_asp[2],float r_shift[2],float * r_drawsize,float r_vec[4][3])462 void BKE_camera_view_frame_ex(const Scene *scene,
463                               const Camera *camera,
464                               const float drawsize,
465                               const bool do_clip,
466                               const float scale[3],
467                               float r_asp[2],
468                               float r_shift[2],
469                               float *r_drawsize,
470                               float r_vec[4][3])
471 {
472   float facx, facy;
473   float depth;
474 
475   /* aspect correction */
476   if (scene) {
477     float aspx = (float)scene->r.xsch * scene->r.xasp;
478     float aspy = (float)scene->r.ysch * scene->r.yasp;
479     int sensor_fit = BKE_camera_sensor_fit(camera->sensor_fit, aspx, aspy);
480 
481     if (sensor_fit == CAMERA_SENSOR_FIT_HOR) {
482       r_asp[0] = 1.0;
483       r_asp[1] = aspy / aspx;
484     }
485     else {
486       r_asp[0] = aspx / aspy;
487       r_asp[1] = 1.0;
488     }
489   }
490   else {
491     r_asp[0] = 1.0f;
492     r_asp[1] = 1.0f;
493   }
494 
495   if (camera->type == CAM_ORTHO) {
496     facx = 0.5f * camera->ortho_scale * r_asp[0] * scale[0];
497     facy = 0.5f * camera->ortho_scale * r_asp[1] * scale[1];
498     r_shift[0] = camera->shiftx * camera->ortho_scale * scale[0];
499     r_shift[1] = camera->shifty * camera->ortho_scale * scale[1];
500     depth = -drawsize * scale[2];
501 
502     *r_drawsize = 0.5f * camera->ortho_scale;
503   }
504   else {
505     /* that way it's always visible - clip_start+0.1 */
506     float fac, scale_x, scale_y;
507     float half_sensor = 0.5f * ((camera->sensor_fit == CAMERA_SENSOR_FIT_VERT) ?
508                                     (camera->sensor_y) :
509                                     (camera->sensor_x));
510 
511     /* fixed size, variable depth (stays a reasonable size in the 3D view) */
512     *r_drawsize = (drawsize / 2.0f) / ((scale[0] + scale[1] + scale[2]) / 3.0f);
513     depth = *r_drawsize * camera->lens / (-half_sensor) * scale[2];
514     fac = *r_drawsize;
515     scale_x = scale[0];
516     scale_y = scale[1];
517 
518     facx = fac * r_asp[0] * scale_x;
519     facy = fac * r_asp[1] * scale_y;
520     r_shift[0] = camera->shiftx * fac * 2.0f * scale_x;
521     r_shift[1] = camera->shifty * fac * 2.0f * scale_y;
522   }
523 
524   r_vec[0][0] = r_shift[0] + facx;
525   r_vec[0][1] = r_shift[1] + facy;
526   r_vec[0][2] = depth;
527   r_vec[1][0] = r_shift[0] + facx;
528   r_vec[1][1] = r_shift[1] - facy;
529   r_vec[1][2] = depth;
530   r_vec[2][0] = r_shift[0] - facx;
531   r_vec[2][1] = r_shift[1] - facy;
532   r_vec[2][2] = depth;
533   r_vec[3][0] = r_shift[0] - facx;
534   r_vec[3][1] = r_shift[1] + facy;
535   r_vec[3][2] = depth;
536 
537   if (do_clip) {
538     /* Ensure the frame isn't behind the near clipping plane, T62814. */
539     float fac = (camera->clip_start + 0.1f) / -r_vec[0][2];
540     for (uint i = 0; i < 4; i++) {
541       if (camera->type == CAM_ORTHO) {
542         r_vec[i][2] *= fac;
543       }
544       else {
545         mul_v3_fl(r_vec[i], fac);
546       }
547     }
548   }
549 }
550 
BKE_camera_view_frame(const Scene * scene,const Camera * camera,float r_vec[4][3])551 void BKE_camera_view_frame(const Scene *scene, const Camera *camera, float r_vec[4][3])
552 {
553   float dummy_asp[2];
554   float dummy_shift[2];
555   float dummy_drawsize;
556   const float dummy_scale[3] = {1.0f, 1.0f, 1.0f};
557 
558   BKE_camera_view_frame_ex(
559       scene, camera, 1.0, false, dummy_scale, dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
560 }
561 
562 /** \} */
563 
564 /* -------------------------------------------------------------------- */
565 /** \name Camera View Frame Fit to Points
566  * \{ */
567 
568 #define CAMERA_VIEWFRAME_NUM_PLANES 4
569 
570 typedef struct CameraViewFrameData {
571   float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4]; /* 4 planes */
572   float normal_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
573   float dist_vals_sq[CAMERA_VIEWFRAME_NUM_PLANES]; /* distance squared (signed) */
574   unsigned int tot;
575 
576   /* Ortho camera only. */
577   bool is_ortho;
578   float camera_no[3];
579   float dist_to_cam;
580 
581   /* Not used by callbacks... */
582   float camera_rotmat[3][3];
583 } CameraViewFrameData;
584 
camera_to_frame_view_cb(const float co[3],void * user_data)585 static void camera_to_frame_view_cb(const float co[3], void *user_data)
586 {
587   CameraViewFrameData *data = (CameraViewFrameData *)user_data;
588 
589   for (uint i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
590     const float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
591     CLAMP_MAX(data->dist_vals_sq[i], nd);
592   }
593 
594   if (data->is_ortho) {
595     const float d = dot_v3v3(data->camera_no, co);
596     CLAMP_MAX(data->dist_to_cam, d);
597   }
598 
599   data->tot++;
600 }
601 
camera_frame_fit_data_init(const Scene * scene,const Object * ob,CameraParams * params,CameraViewFrameData * data)602 static void camera_frame_fit_data_init(const Scene *scene,
603                                        const Object *ob,
604                                        CameraParams *params,
605                                        CameraViewFrameData *data)
606 {
607   float camera_rotmat_transposed_inversed[4][4];
608 
609   /* setup parameters */
610   BKE_camera_params_init(params);
611   BKE_camera_params_from_object(params, ob);
612 
613   /* compute matrix, viewplane, .. */
614   if (scene) {
615     BKE_camera_params_compute_viewplane(
616         params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
617   }
618   else {
619     BKE_camera_params_compute_viewplane(params, 1, 1, 1.0f, 1.0f);
620   }
621   BKE_camera_params_compute_matrix(params);
622 
623   /* initialize callback data */
624   copy_m3_m4(data->camera_rotmat, (float(*)[4])ob->obmat);
625   normalize_m3(data->camera_rotmat);
626   /* To transform a plane which is in its homogeneous representation (4d vector),
627    * we need the inverse of the transpose of the transform matrix... */
628   copy_m4_m3(camera_rotmat_transposed_inversed, data->camera_rotmat);
629   transpose_m4(camera_rotmat_transposed_inversed);
630   invert_m4(camera_rotmat_transposed_inversed);
631 
632   /* Extract frustum planes from projection matrix. */
633   planes_from_projmat(
634       params->winmat,
635       /*   left              right                 top              bottom        near  far */
636       data->plane_tx[2],
637       data->plane_tx[0],
638       data->plane_tx[3],
639       data->plane_tx[1],
640       NULL,
641       NULL);
642 
643   /* Rotate planes and get normals from them */
644   for (uint i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
645     mul_m4_v4(camera_rotmat_transposed_inversed, data->plane_tx[i]);
646     normalize_v3_v3(data->normal_tx[i], data->plane_tx[i]);
647   }
648 
649   copy_v4_fl(data->dist_vals_sq, FLT_MAX);
650   data->tot = 0;
651   data->is_ortho = params->is_ortho;
652   if (params->is_ortho) {
653     /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
654     negate_v3_v3(data->camera_no, data->camera_rotmat[2]);
655     data->dist_to_cam = FLT_MAX;
656   }
657 }
658 
camera_frame_fit_calc_from_data(CameraParams * params,CameraViewFrameData * data,float r_co[3],float * r_scale)659 static bool camera_frame_fit_calc_from_data(CameraParams *params,
660                                             CameraViewFrameData *data,
661                                             float r_co[3],
662                                             float *r_scale)
663 {
664   float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4];
665 
666   if (data->tot <= 1) {
667     return false;
668   }
669 
670   if (params->is_ortho) {
671     const float *cam_axis_x = data->camera_rotmat[0];
672     const float *cam_axis_y = data->camera_rotmat[1];
673     const float *cam_axis_z = data->camera_rotmat[2];
674     float dists[CAMERA_VIEWFRAME_NUM_PLANES];
675     float scale_diff;
676 
677     /* apply the dist-from-plane's to the transformed plane points */
678     for (int i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
679       dists[i] = sqrtf_signed(data->dist_vals_sq[i]);
680     }
681 
682     if ((dists[0] + dists[2]) > (dists[1] + dists[3])) {
683       scale_diff = (dists[1] + dists[3]) *
684                    (BLI_rctf_size_x(&params->viewplane) / BLI_rctf_size_y(&params->viewplane));
685     }
686     else {
687       scale_diff = (dists[0] + dists[2]) *
688                    (BLI_rctf_size_y(&params->viewplane) / BLI_rctf_size_x(&params->viewplane));
689     }
690     *r_scale = params->ortho_scale - scale_diff;
691 
692     zero_v3(r_co);
693     madd_v3_v3fl(r_co, cam_axis_x, (dists[2] - dists[0]) * 0.5f + params->shiftx * scale_diff);
694     madd_v3_v3fl(r_co, cam_axis_y, (dists[1] - dists[3]) * 0.5f + params->shifty * scale_diff);
695     madd_v3_v3fl(r_co, cam_axis_z, -(data->dist_to_cam - 1.0f - params->clip_start));
696 
697     return true;
698   }
699 
700   float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
701   float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];
702 
703   float plane_isect_pt_1[3], plane_isect_pt_2[3];
704 
705   /* apply the dist-from-plane's to the transformed plane points */
706   for (int i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
707     float co[3];
708     mul_v3_v3fl(co, data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
709     plane_from_point_normal_v3(plane_tx[i], co, data->normal_tx[i]);
710   }
711 
712   if ((!isect_plane_plane_v3(plane_tx[0], plane_tx[2], plane_isect_1, plane_isect_1_no)) ||
713       (!isect_plane_plane_v3(plane_tx[1], plane_tx[3], plane_isect_2, plane_isect_2_no))) {
714     return false;
715   }
716 
717   add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no);
718   add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);
719 
720   if (isect_line_line_v3(plane_isect_1,
721                          plane_isect_1_other,
722                          plane_isect_2,
723                          plane_isect_2_other,
724                          plane_isect_pt_1,
725                          plane_isect_pt_2) != 0) {
726     float cam_plane_no[3];
727     float plane_isect_delta[3];
728     float plane_isect_delta_len;
729 
730     float shift_fac = BKE_camera_sensor_size(
731                           params->sensor_fit, params->sensor_x, params->sensor_y) /
732                       params->lens;
733 
734     /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
735     negate_v3_v3(cam_plane_no, data->camera_rotmat[2]);
736 
737     sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
738     plane_isect_delta_len = len_v3(plane_isect_delta);
739 
740     if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
741       copy_v3_v3(r_co, plane_isect_pt_1);
742 
743       /* offset shift */
744       normalize_v3(plane_isect_1_no);
745       madd_v3_v3fl(r_co, plane_isect_1_no, params->shifty * plane_isect_delta_len * shift_fac);
746     }
747     else {
748       copy_v3_v3(r_co, plane_isect_pt_2);
749 
750       /* offset shift */
751       normalize_v3(plane_isect_2_no);
752       madd_v3_v3fl(r_co, plane_isect_2_no, params->shiftx * plane_isect_delta_len * shift_fac);
753     }
754 
755     return true;
756   }
757 
758   return false;
759 }
760 
761 /* don't move the camera, just yield the fit location */
762 /* r_scale only valid/useful for ortho cameras */
BKE_camera_view_frame_fit_to_scene(Depsgraph * depsgraph,const Scene * scene,Object * camera_ob,float r_co[3],float * r_scale)763 bool BKE_camera_view_frame_fit_to_scene(
764     Depsgraph *depsgraph, const Scene *scene, Object *camera_ob, float r_co[3], float *r_scale)
765 {
766   CameraParams params;
767   CameraViewFrameData data_cb;
768 
769   /* just in case */
770   *r_scale = 1.0f;
771 
772   camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
773 
774   /* run callback on all visible points */
775   BKE_scene_foreach_display_point(depsgraph, camera_to_frame_view_cb, &data_cb);
776 
777   return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
778 }
779 
BKE_camera_view_frame_fit_to_coords(const Depsgraph * depsgraph,const float (* cos)[3],int num_cos,Object * camera_ob,float r_co[3],float * r_scale)780 bool BKE_camera_view_frame_fit_to_coords(const Depsgraph *depsgraph,
781                                          const float (*cos)[3],
782                                          int num_cos,
783                                          Object *camera_ob,
784                                          float r_co[3],
785                                          float *r_scale)
786 {
787   Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
788   Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob);
789   CameraParams params;
790   CameraViewFrameData data_cb;
791 
792   /* just in case */
793   *r_scale = 1.0f;
794 
795   camera_frame_fit_data_init(scene_eval, camera_ob_eval, &params, &data_cb);
796 
797   /* run callback on all given coordinates */
798   while (num_cos--) {
799     camera_to_frame_view_cb(cos[num_cos], &data_cb);
800   }
801 
802   return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
803 }
804 
805 /** \} */
806 
807 /* -------------------------------------------------------------------- */
808 /** \name Camera Multi-View Matrix
809  * \{ */
810 
camera_model_matrix(const Object * camera,float r_modelmat[4][4])811 static void camera_model_matrix(const Object *camera, float r_modelmat[4][4])
812 {
813   copy_m4_m4(r_modelmat, camera->obmat);
814 }
815 
camera_stereo3d_model_matrix(const Object * camera,const bool is_left,float r_modelmat[4][4])816 static void camera_stereo3d_model_matrix(const Object *camera,
817                                          const bool is_left,
818                                          float r_modelmat[4][4])
819 {
820   Camera *data = (Camera *)camera->data;
821   float interocular_distance, convergence_distance;
822   short convergence_mode, pivot;
823   float sizemat[4][4];
824 
825   float fac = 1.0f;
826   float fac_signed;
827 
828   interocular_distance = data->stereo.interocular_distance;
829   convergence_distance = data->stereo.convergence_distance;
830   convergence_mode = data->stereo.convergence_mode;
831   pivot = data->stereo.pivot;
832 
833   if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) || ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left)) {
834     camera_model_matrix(camera, r_modelmat);
835     return;
836   }
837 
838   float size[3];
839   mat4_to_size(size, camera->obmat);
840   size_to_mat4(sizemat, size);
841 
842   if (pivot == CAM_S3D_PIVOT_CENTER) {
843     fac = 0.5f;
844   }
845 
846   fac_signed = is_left ? fac : -fac;
847 
848   /* rotation */
849   if (convergence_mode == CAM_S3D_TOE) {
850     float angle;
851     float angle_sin, angle_cos;
852     float toeinmat[4][4];
853     float rotmat[4][4];
854 
855     unit_m4(rotmat);
856 
857     if (pivot == CAM_S3D_PIVOT_CENTER) {
858       fac = -fac;
859       fac_signed = -fac_signed;
860     }
861 
862     angle = atanf((interocular_distance * 0.5f) / convergence_distance) / fac;
863 
864     angle_cos = cosf(angle * fac_signed);
865     angle_sin = sinf(angle * fac_signed);
866 
867     rotmat[0][0] = angle_cos;
868     rotmat[2][0] = -angle_sin;
869     rotmat[0][2] = angle_sin;
870     rotmat[2][2] = angle_cos;
871 
872     if (pivot == CAM_S3D_PIVOT_CENTER) {
873       /* set the rotation */
874       copy_m4_m4(toeinmat, rotmat);
875       /* set the translation */
876       toeinmat[3][0] = interocular_distance * fac_signed;
877 
878       /* transform */
879       normalize_m4_m4(r_modelmat, camera->obmat);
880       mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
881 
882       /* scale back to the original size */
883       mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
884     }
885     else { /* CAM_S3D_PIVOT_LEFT, CAM_S3D_PIVOT_RIGHT */
886       /* rotate perpendicular to the interocular line */
887       normalize_m4_m4(r_modelmat, camera->obmat);
888       mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
889 
890       /* translate along the interocular line */
891       unit_m4(toeinmat);
892       toeinmat[3][0] = -interocular_distance * fac_signed;
893       mul_m4_m4m4(r_modelmat, r_modelmat, toeinmat);
894 
895       /* rotate to toe-in angle */
896       mul_m4_m4m4(r_modelmat, r_modelmat, rotmat);
897 
898       /* scale back to the original size */
899       mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
900     }
901   }
902   else {
903     normalize_m4_m4(r_modelmat, camera->obmat);
904 
905     /* translate - no rotation in CAM_S3D_OFFAXIS, CAM_S3D_PARALLEL */
906     translate_m4(r_modelmat, -interocular_distance * fac_signed, 0.0f, 0.0f);
907 
908     /* scale back to the original size */
909     mul_m4_m4m4(r_modelmat, r_modelmat, sizemat);
910   }
911 }
912 
913 /* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */
BKE_camera_multiview_view_matrix(const RenderData * rd,const Object * camera,const bool is_left,float r_viewmat[4][4])914 void BKE_camera_multiview_view_matrix(const RenderData *rd,
915                                       const Object *camera,
916                                       const bool is_left,
917                                       float r_viewmat[4][4])
918 {
919   BKE_camera_multiview_model_matrix(
920       rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat);
921   invert_m4(r_viewmat);
922 }
923 
924 /* left is the default */
camera_is_left(const char * viewname)925 static bool camera_is_left(const char *viewname)
926 {
927   if (viewname && viewname[0] != '\0') {
928     return !STREQ(viewname, STEREO_RIGHT_NAME);
929   }
930   return true;
931 }
932 
BKE_camera_multiview_model_matrix(const RenderData * rd,const Object * camera,const char * viewname,float r_modelmat[4][4])933 void BKE_camera_multiview_model_matrix(const RenderData *rd,
934                                        const Object *camera,
935                                        const char *viewname,
936                                        float r_modelmat[4][4])
937 {
938   BKE_camera_multiview_model_matrix_scaled(rd, camera, viewname, r_modelmat);
939   normalize_m4(r_modelmat);
940 }
941 
BKE_camera_multiview_model_matrix_scaled(const RenderData * rd,const Object * camera,const char * viewname,float r_modelmat[4][4])942 void BKE_camera_multiview_model_matrix_scaled(const RenderData *rd,
943                                               const Object *camera,
944                                               const char *viewname,
945                                               float r_modelmat[4][4])
946 {
947   const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
948 
949   if (!is_multiview) {
950     camera_model_matrix(camera, r_modelmat);
951   }
952   else if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
953     camera_model_matrix(camera, r_modelmat);
954   }
955   else { /* SCE_VIEWS_SETUP_BASIC */
956     const bool is_left = camera_is_left(viewname);
957     camera_stereo3d_model_matrix(camera, is_left, r_modelmat);
958   }
959 }
960 
BKE_camera_multiview_window_matrix(const RenderData * rd,const Object * camera,const char * viewname,float r_winmat[4][4])961 void BKE_camera_multiview_window_matrix(const RenderData *rd,
962                                         const Object *camera,
963                                         const char *viewname,
964                                         float r_winmat[4][4])
965 {
966   CameraParams params;
967 
968   /* Setup parameters */
969   BKE_camera_params_init(&params);
970   BKE_camera_params_from_object(&params, camera);
971   BKE_camera_multiview_params(rd, &params, camera, viewname);
972 
973   /* Compute matrix, viewplane, .. */
974   BKE_camera_params_compute_viewplane(&params, rd->xsch, rd->ysch, rd->xasp, rd->yasp);
975   BKE_camera_params_compute_matrix(&params);
976 
977   copy_m4_m4(r_winmat, params.winmat);
978 }
979 
BKE_camera_multiview_spherical_stereo(const RenderData * rd,const Object * camera)980 bool BKE_camera_multiview_spherical_stereo(const RenderData *rd, const Object *camera)
981 {
982   Camera *cam;
983   const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
984 
985   if (!is_multiview) {
986     return false;
987   }
988 
989   if (camera->type != OB_CAMERA) {
990     return false;
991   }
992 
993   cam = camera->data;
994 
995   if ((rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) && ELEM(cam->type, CAM_PANO, CAM_PERSP) &&
996       ((cam->stereo.flag & CAM_S3D_SPHERICAL) != 0)) {
997     return true;
998   }
999 
1000   return false;
1001 }
1002 
camera_multiview_advanced(const Scene * scene,Object * camera,const char * suffix)1003 static Object *camera_multiview_advanced(const Scene *scene, Object *camera, const char *suffix)
1004 {
1005   char name[MAX_NAME];
1006   const char *camera_name = camera->id.name + 2;
1007   const int len_name = strlen(camera_name);
1008   int len_suffix_max = -1;
1009 
1010   name[0] = '\0';
1011 
1012   /* we need to take the better match, thus the len_suffix_max test */
1013   LISTBASE_FOREACH (const SceneRenderView *, srv, &scene->r.views) {
1014     const int len_suffix = strlen(srv->suffix);
1015 
1016     if ((len_suffix < len_suffix_max) || (len_name < len_suffix)) {
1017       continue;
1018     }
1019 
1020     if (STREQ(camera_name + (len_name - len_suffix), srv->suffix)) {
1021       BLI_snprintf(name, sizeof(name), "%.*s%s", (len_name - len_suffix), camera_name, suffix);
1022       len_suffix_max = len_suffix;
1023     }
1024   }
1025 
1026   if (name[0] != '\0') {
1027     Object *ob = BKE_scene_object_find_by_name(scene, name);
1028     if (ob != NULL) {
1029       return ob;
1030     }
1031   }
1032 
1033   return camera;
1034 }
1035 
1036 /* returns the camera to be used for render */
BKE_camera_multiview_render(const Scene * scene,Object * camera,const char * viewname)1037 Object *BKE_camera_multiview_render(const Scene *scene, Object *camera, const char *viewname)
1038 {
1039   const bool is_multiview = (camera != NULL) && (scene->r.scemode & R_MULTIVIEW) != 0;
1040 
1041   if (!is_multiview) {
1042     return camera;
1043   }
1044   if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
1045     return camera;
1046   }
1047   /* SCE_VIEWS_FORMAT_MULTIVIEW */
1048   const char *suffix = BKE_scene_multiview_view_suffix_get(&scene->r, viewname);
1049   return camera_multiview_advanced(scene, camera, suffix);
1050 }
1051 
camera_stereo3d_shift_x(const Object * camera,const char * viewname)1052 static float camera_stereo3d_shift_x(const Object *camera, const char *viewname)
1053 {
1054   Camera *data = camera->data;
1055   float shift = data->shiftx;
1056   float interocular_distance, convergence_distance;
1057   short convergence_mode, pivot;
1058   bool is_left = true;
1059 
1060   float fac = 1.0f;
1061   float fac_signed;
1062 
1063   if (viewname && viewname[0]) {
1064     is_left = STREQ(viewname, STEREO_LEFT_NAME);
1065   }
1066 
1067   interocular_distance = data->stereo.interocular_distance;
1068   convergence_distance = data->stereo.convergence_distance;
1069   convergence_mode = data->stereo.convergence_mode;
1070   pivot = data->stereo.pivot;
1071 
1072   if (convergence_mode != CAM_S3D_OFFAXIS) {
1073     return shift;
1074   }
1075 
1076   if (((pivot == CAM_S3D_PIVOT_LEFT) && is_left) || ((pivot == CAM_S3D_PIVOT_RIGHT) && !is_left)) {
1077     return shift;
1078   }
1079 
1080   if (pivot == CAM_S3D_PIVOT_CENTER) {
1081     fac = 0.5f;
1082   }
1083 
1084   fac_signed = is_left ? fac : -fac;
1085   shift += ((interocular_distance / data->sensor_x) * (data->lens / convergence_distance)) *
1086            fac_signed;
1087 
1088   return shift;
1089 }
1090 
BKE_camera_multiview_shift_x(const RenderData * rd,const Object * camera,const char * viewname)1091 float BKE_camera_multiview_shift_x(const RenderData *rd,
1092                                    const Object *camera,
1093                                    const char *viewname)
1094 {
1095   const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0;
1096   Camera *data = camera->data;
1097 
1098   BLI_assert(camera->type == OB_CAMERA);
1099 
1100   if (!is_multiview) {
1101     return data->shiftx;
1102   }
1103   if (rd->views_format == SCE_VIEWS_FORMAT_MULTIVIEW) {
1104     return data->shiftx;
1105   }
1106   /* SCE_VIEWS_SETUP_BASIC */
1107   return camera_stereo3d_shift_x(camera, viewname);
1108 }
1109 
BKE_camera_multiview_params(const RenderData * rd,CameraParams * params,const Object * camera,const char * viewname)1110 void BKE_camera_multiview_params(const RenderData *rd,
1111                                  CameraParams *params,
1112                                  const Object *camera,
1113                                  const char *viewname)
1114 {
1115   if (camera->type == OB_CAMERA) {
1116     params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname);
1117   }
1118 }
1119 
1120 /** \} */
1121 
1122 /* -------------------------------------------------------------------- */
1123 /** \name Camera Background Image
1124  * \{ */
1125 
BKE_camera_background_image_new(Camera * cam)1126 CameraBGImage *BKE_camera_background_image_new(Camera *cam)
1127 {
1128   CameraBGImage *bgpic = MEM_callocN(sizeof(CameraBGImage), "Background Image");
1129 
1130   bgpic->scale = 1.0f;
1131   bgpic->alpha = 0.5f;
1132   bgpic->iuser.ok = 1;
1133   bgpic->iuser.flag |= IMA_ANIM_ALWAYS;
1134   bgpic->flag |= CAM_BGIMG_FLAG_EXPANDED;
1135 
1136   BLI_addtail(&cam->bg_images, bgpic);
1137 
1138   return bgpic;
1139 }
1140 
BKE_camera_background_image_remove(Camera * cam,CameraBGImage * bgpic)1141 void BKE_camera_background_image_remove(Camera *cam, CameraBGImage *bgpic)
1142 {
1143   BLI_remlink(&cam->bg_images, bgpic);
1144 
1145   MEM_freeN(bgpic);
1146 }
1147 
BKE_camera_background_image_clear(Camera * cam)1148 void BKE_camera_background_image_clear(Camera *cam)
1149 {
1150   CameraBGImage *bgpic = cam->bg_images.first;
1151 
1152   while (bgpic) {
1153     CameraBGImage *next_bgpic = bgpic->next;
1154 
1155     BKE_camera_background_image_remove(cam, bgpic);
1156 
1157     bgpic = next_bgpic;
1158   }
1159 }
1160 
1161 /** \} */
1162