Blender V4.3
blender/camera.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "scene/camera.h"
6#include "scene/bake.h"
7#include "scene/scene.h"
8
9#include "blender/sync.h"
10#include "blender/util.h"
11
12#include "util/log.h"
13
15
16/* Blender Camera Intermediate: we first convert both the offline and 3d view
17 * render camera to this, and from there convert to our native camera format. */
18
20 float nearclip;
21 float farclip;
22
25
26 float lens;
30
33
38
41 float zoom;
42
44
46
60
66
72
76
79
82
87
89
91
93
95};
96
97static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_render)
98{
99 memset((void *)bcam, 0, sizeof(BlenderCamera));
100
101 bcam->nearclip = 1e-5f;
102 bcam->farclip = 1e5f;
103
104 bcam->type = CAMERA_PERSPECTIVE;
105 bcam->ortho_scale = 1.0f;
106
107 bcam->lens = 50.0f;
108 bcam->shuttertime = 1.0f;
109
111 bcam->rolling_shutter_duration = 0.1f;
112
113 bcam->aperturesize = 0.0f;
114 bcam->apertureblades = 0;
115 bcam->aperturerotation = 0.0f;
116 bcam->focaldistance = 10.0f;
117
118 bcam->zoom = 1.0f;
119 bcam->pixelaspect = one_float2();
120 bcam->aperture_ratio = 1.0f;
121
122 bcam->sensor_width = 36.0f;
123 bcam->sensor_height = 24.0f;
126 bcam->border.right = 1.0f;
127 bcam->border.top = 1.0f;
128 bcam->viewport_camera_border.right = 1.0f;
129 bcam->viewport_camera_border.top = 1.0f;
130 bcam->pano_viewplane.right = 1.0f;
131 bcam->pano_viewplane.top = 1.0f;
132 bcam->pano_aspectratio = 0.0f;
133 bcam->passepartout_alpha = 0.5f;
134 bcam->offscreen_dicing_scale = 1.0f;
135 bcam->matrix = transform_identity();
136
137 bcam->central_cylindrical_radius = 1.0f;
138
139 /* render resolution */
140 bcam->render_width = render_resolution_x(b_render);
141 bcam->render_height = render_resolution_y(b_render);
142 bcam->full_width = bcam->render_width;
143 bcam->full_height = bcam->render_height;
144}
145
146static float blender_camera_focal_distance(BL::RenderEngine &b_engine,
147 BL::Object &b_ob,
148 BL::Camera &b_camera,
149 BlenderCamera *bcam)
150{
151 BL::Object b_dof_object = b_camera.dof().focus_object();
152
153 if (!b_dof_object) {
154 return b_camera.dof().focus_distance();
155 }
156
157 Transform dofmat = get_transform(b_dof_object.matrix_world());
158
159 string focus_subtarget = b_camera.dof().focus_subtarget();
160 if (b_dof_object.pose() && !focus_subtarget.empty()) {
161 BL::PoseBone b_bone = b_dof_object.pose().bones[focus_subtarget];
162 if (b_bone) {
163 dofmat = dofmat * get_transform(b_bone.matrix());
164 }
165 }
166
167 /* for dof object, return distance along camera Z direction */
168 BL::Array<float, 16> b_ob_matrix;
169 b_engine.camera_model_matrix(b_ob, bcam->use_spherical_stereo, b_ob_matrix);
170 Transform obmat = transform_clear_scale(get_transform(b_ob_matrix));
171 float3 view_dir = normalize(transform_get_column(&obmat, 2));
172 float3 dof_dir = transform_get_column(&obmat, 3) - transform_get_column(&dofmat, 3);
173 return fabsf(dot(view_dir, dof_dir));
174}
175
176static PanoramaType blender_panorama_type_to_cycles(const BL::Camera::panorama_type_enum type)
177{
178 switch (type) {
179 case BL::Camera::panorama_type_EQUIRECTANGULAR:
181 case BL::Camera::panorama_type_EQUIANGULAR_CUBEMAP_FACE:
183 case BL::Camera::panorama_type_MIRRORBALL:
184 return PANORAMA_MIRRORBALL;
185 case BL::Camera::panorama_type_FISHEYE_EQUIDISTANT:
187 case BL::Camera::panorama_type_FISHEYE_EQUISOLID:
189 case BL::Camera::panorama_type_FISHEYE_LENS_POLYNOMIAL:
191 case BL::Camera::panorama_type_CENTRAL_CYLINDRICAL:
193 }
194 /* Could happen if loading a newer file that has an unsupported type. */
196}
197
199 BL::RenderEngine &b_engine,
200 BL::Object &b_ob,
201 bool skip_panorama = false)
202{
203 BL::ID b_ob_data = b_ob.data();
204
205 if (b_ob_data.is_a(&RNA_Camera)) {
206 BL::Camera b_camera(b_ob_data);
207
208 bcam->nearclip = b_camera.clip_start();
209 bcam->farclip = b_camera.clip_end();
210
211 switch (b_camera.type()) {
212 case BL::Camera::type_ORTHO:
214 break;
215 case BL::Camera::type_PANO:
216 if (!skip_panorama) {
217 bcam->type = CAMERA_PANORAMA;
218 }
219 else {
220 bcam->type = CAMERA_PERSPECTIVE;
221 }
222 break;
223 case BL::Camera::type_PERSP:
224 default:
225 bcam->type = CAMERA_PERSPECTIVE;
226 break;
227 }
228
229 bcam->panorama_type = blender_panorama_type_to_cycles(b_camera.panorama_type());
230 bcam->fisheye_fov = b_camera.fisheye_fov();
231 bcam->fisheye_lens = b_camera.fisheye_lens();
232 bcam->latitude_min = b_camera.latitude_min();
233 bcam->latitude_max = b_camera.latitude_max();
234 bcam->longitude_min = b_camera.longitude_min();
235 bcam->longitude_max = b_camera.longitude_max();
236
237 bcam->fisheye_polynomial_k0 = b_camera.fisheye_polynomial_k0();
238 bcam->fisheye_polynomial_k1 = b_camera.fisheye_polynomial_k1();
239 bcam->fisheye_polynomial_k2 = b_camera.fisheye_polynomial_k2();
240 bcam->fisheye_polynomial_k3 = b_camera.fisheye_polynomial_k3();
241 bcam->fisheye_polynomial_k4 = b_camera.fisheye_polynomial_k4();
242
243 bcam->central_cylindrical_range_u_min = b_camera.central_cylindrical_range_u_min();
244 bcam->central_cylindrical_range_u_max = b_camera.central_cylindrical_range_u_max();
245 bcam->central_cylindrical_range_v_min = b_camera.central_cylindrical_range_v_min();
246 bcam->central_cylindrical_range_v_max = b_camera.central_cylindrical_range_v_max();
247 bcam->central_cylindrical_radius = b_camera.central_cylindrical_radius();
248
249 bcam->interocular_distance = b_camera.stereo().interocular_distance();
250 if (b_camera.stereo().convergence_mode() == BL::CameraStereoData::convergence_mode_PARALLEL) {
252 }
253 else {
254 bcam->convergence_distance = b_camera.stereo().convergence_distance();
255 }
256 bcam->use_spherical_stereo = b_engine.use_spherical_stereo(b_ob);
257
258 bcam->use_pole_merge = b_camera.stereo().use_pole_merge();
259 bcam->pole_merge_angle_from = b_camera.stereo().pole_merge_angle_from();
260 bcam->pole_merge_angle_to = b_camera.stereo().pole_merge_angle_to();
261
262 bcam->ortho_scale = b_camera.ortho_scale();
263
264 bcam->lens = b_camera.lens();
265
266 bcam->passepartout_alpha = b_camera.show_passepartout() ? b_camera.passepartout_alpha() : 0.0f;
267
268 if (b_camera.dof().use_dof()) {
269 /* allow f/stop number to change aperture_size but still
270 * give manual control over aperture radius */
271 float fstop = b_camera.dof().aperture_fstop();
272 fstop = max(fstop, 1e-5f);
273
274 if (bcam->type == CAMERA_ORTHOGRAPHIC) {
275 bcam->aperturesize = 1.0f / (2.0f * fstop);
276 }
277 else {
278 bcam->aperturesize = (bcam->lens * 1e-3f) / (2.0f * fstop);
279 }
280
281 bcam->apertureblades = b_camera.dof().aperture_blades();
282 bcam->aperturerotation = b_camera.dof().aperture_rotation();
283 bcam->focaldistance = blender_camera_focal_distance(b_engine, b_ob, b_camera, bcam);
284 bcam->aperture_ratio = b_camera.dof().aperture_ratio();
285 }
286 else {
287 /* DOF is turned of for the camera. */
288 bcam->aperturesize = 0.0f;
289 bcam->apertureblades = 0;
290 bcam->aperturerotation = 0.0f;
291 bcam->focaldistance = 0.0f;
292 bcam->aperture_ratio = 1.0f;
293 }
294
295 bcam->shift.x = b_engine.camera_shift_x(b_ob, bcam->use_spherical_stereo);
296 bcam->shift.y = b_camera.shift_y();
297
298 bcam->sensor_width = b_camera.sensor_width();
299 bcam->sensor_height = b_camera.sensor_height();
300
301 if (b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO) {
303 }
304 else if (b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL) {
306 }
307 else {
309 }
310 }
311 else if (b_ob_data.is_a(&RNA_Light)) {
312 /* Can also look through spot light. */
313 BL::SpotLight b_light(b_ob_data);
314 float lens = 16.0f / tanf(b_light.spot_size() * 0.5f);
315 if (lens > 0.0f) {
316 bcam->lens = lens;
317 }
318 }
319
320 bcam->motion_steps = object_motion_steps(b_ob, b_ob);
321}
322
324 const CameraType type,
325 const PanoramaType panorama_type)
326{
328
329 if (type == CAMERA_PANORAMA) {
330 if (panorama_type == PANORAMA_MIRRORBALL) {
331 /* Mirror ball camera is looking into the negative Y direction
332 * which matches texture mirror ball mapping.
333 */
334 result = tfm * make_transform(
335 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
336 }
337 else {
338 /* Make it so environment camera needs to be pointed in the direction
339 * of the positive x-axis to match an environment texture, this way
340 * it is looking at the center of the texture
341 */
342 result = tfm * make_transform(
343 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f);
344 }
345 }
346 else {
347 /* note the blender camera points along the negative z-axis */
348 result = tfm * transform_scale(1.0f, 1.0f, -1.0f);
349 }
350
351 return transform_clear_scale(result);
352}
353
355 int width,
356 int height,
357 BoundBox2D *viewplane,
358 float *aspectratio,
359 float *sensor_size)
360{
361 /* dimensions */
362 float xratio = (float)width * bcam->pixelaspect.x;
363 float yratio = (float)height * bcam->pixelaspect.y;
364
365 /* compute x/y aspect and ratio */
366 float xaspect, yaspect;
367 bool horizontal_fit;
368
369 /* sensor fitting */
370 if (bcam->sensor_fit == BlenderCamera::AUTO) {
371 horizontal_fit = (xratio > yratio);
372 if (sensor_size != NULL) {
373 *sensor_size = bcam->sensor_width;
374 }
375 }
376 else if (bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
377 horizontal_fit = true;
378 if (sensor_size != NULL) {
379 *sensor_size = bcam->sensor_width;
380 }
381 }
382 else {
383 horizontal_fit = false;
384 if (sensor_size != NULL) {
385 *sensor_size = bcam->sensor_height;
386 }
387 }
388
389 if (horizontal_fit) {
390 if (aspectratio != NULL) {
391 *aspectratio = xratio / yratio;
392 }
393 xaspect = *aspectratio;
394 yaspect = 1.0f;
395 }
396 else {
397 if (aspectratio != NULL) {
398 *aspectratio = yratio / xratio;
399 }
400 xaspect = 1.0f;
401 yaspect = *aspectratio;
402 }
403
404 /* modify aspect for orthographic scale */
405 if (bcam->type == CAMERA_ORTHOGRAPHIC) {
406 xaspect = xaspect * bcam->ortho_scale / (*aspectratio * 2.0f);
407 yaspect = yaspect * bcam->ortho_scale / (*aspectratio * 2.0f);
408 if (aspectratio != NULL) {
409 *aspectratio = bcam->ortho_scale / 2.0f;
410 }
411 }
412
413 if (bcam->type == CAMERA_PANORAMA) {
414 /* Set viewplane for panoramic camera. */
415 if (viewplane != NULL) {
416 *viewplane = bcam->pano_viewplane;
417
418 /* Modify viewplane for camera shift. */
419 const float shift_factor = (bcam->pano_aspectratio == 0.0f) ?
420 1.0f :
421 *aspectratio / bcam->pano_aspectratio;
422 const float dx = bcam->shift.x * shift_factor;
423 const float dy = bcam->shift.y * shift_factor;
424
425 viewplane->left += dx;
426 viewplane->right += dx;
427 viewplane->bottom += dy;
428 viewplane->top += dy;
429 }
430 }
431 else {
432 /* set viewplane */
433 if (viewplane != NULL) {
434 viewplane->left = -xaspect;
435 viewplane->right = xaspect;
436 viewplane->bottom = -yaspect;
437 viewplane->top = yaspect;
438
439 /* zoom for 3d camera view */
440 *viewplane = (*viewplane) * bcam->zoom;
441
442 /* modify viewplane with camera shift and 3d camera view offset */
443 const float dx = 2.0f * (*aspectratio * bcam->shift.x + bcam->offset.x * xaspect * 2.0f);
444 const float dy = 2.0f * (*aspectratio * bcam->shift.y + bcam->offset.y * yaspect * 2.0f);
445
446 viewplane->left += dx;
447 viewplane->right += dx;
448 viewplane->bottom += dy;
449 viewplane->top += dy;
450 }
451 }
452}
453
455 BlenderCamera *bcam,
456 int width,
457 int height,
458 const char *viewname,
459 PointerRNA *cscene)
460{
461 float aspectratio, sensor_size;
462
463 /* viewplane */
464 BoundBox2D viewplane;
465 blender_camera_viewplane(bcam, width, height, &viewplane, &aspectratio, &sensor_size);
466
467 cam->set_viewplane_left(viewplane.left);
468 cam->set_viewplane_right(viewplane.right);
469 cam->set_viewplane_top(viewplane.top);
470 cam->set_viewplane_bottom(viewplane.bottom);
471
472 cam->set_full_width(width);
473 cam->set_full_height(height);
474
475 /* panorama sensor */
478 {
479 float fit_xratio = (float)bcam->render_width * bcam->pixelaspect.x;
480 float fit_yratio = (float)bcam->render_height * bcam->pixelaspect.y;
481 bool horizontal_fit;
482 float sensor_size;
483
484 if (bcam->sensor_fit == BlenderCamera::AUTO) {
485 horizontal_fit = (fit_xratio > fit_yratio);
486 sensor_size = bcam->sensor_width;
487 }
488 else if (bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
489 horizontal_fit = true;
490 sensor_size = bcam->sensor_width;
491 }
492 else { /* vertical */
493 horizontal_fit = false;
494 sensor_size = bcam->sensor_height;
495 }
496
497 if (horizontal_fit) {
498 cam->set_sensorwidth(sensor_size);
499 cam->set_sensorheight(sensor_size * fit_yratio / fit_xratio);
500 }
501 else {
502 cam->set_sensorwidth(sensor_size * fit_xratio / fit_yratio);
503 cam->set_sensorheight(sensor_size);
504 }
505 }
506
507 /* clipping distances */
508 cam->set_nearclip(bcam->nearclip);
509 cam->set_farclip(bcam->farclip);
510
511 /* type */
512 cam->set_camera_type(bcam->type);
513
514 /* panorama */
515 cam->set_panorama_type(bcam->panorama_type);
516 cam->set_fisheye_fov(bcam->fisheye_fov);
517 cam->set_fisheye_lens(bcam->fisheye_lens);
518 cam->set_latitude_min(bcam->latitude_min);
519 cam->set_latitude_max(bcam->latitude_max);
520
521 cam->set_fisheye_polynomial_k0(bcam->fisheye_polynomial_k0);
522 cam->set_fisheye_polynomial_k1(bcam->fisheye_polynomial_k1);
523 cam->set_fisheye_polynomial_k2(bcam->fisheye_polynomial_k2);
524 cam->set_fisheye_polynomial_k3(bcam->fisheye_polynomial_k3);
525 cam->set_fisheye_polynomial_k4(bcam->fisheye_polynomial_k4);
526
527 cam->set_longitude_min(bcam->longitude_min);
528 cam->set_longitude_max(bcam->longitude_max);
529
530 cam->set_central_cylindrical_range_u_min(bcam->central_cylindrical_range_u_min);
531 cam->set_central_cylindrical_range_u_max(bcam->central_cylindrical_range_u_max);
532 cam->set_central_cylindrical_range_v_min(bcam->central_cylindrical_range_v_min /
534 cam->set_central_cylindrical_range_v_max(bcam->central_cylindrical_range_v_max /
536
537 /* panorama stereo */
538 cam->set_interocular_distance(bcam->interocular_distance);
539 cam->set_convergence_distance(bcam->convergence_distance);
540 cam->set_use_spherical_stereo(bcam->use_spherical_stereo);
541
542 if (cam->get_use_spherical_stereo()) {
543 if (strcmp(viewname, "left") == 0) {
544 cam->set_stereo_eye(Camera::STEREO_LEFT);
545 }
546 else if (strcmp(viewname, "right") == 0) {
547 cam->set_stereo_eye(Camera::STEREO_RIGHT);
548 }
549 else {
550 cam->set_stereo_eye(Camera::STEREO_NONE);
551 }
552 }
553
554 cam->set_use_pole_merge(bcam->use_pole_merge);
555 cam->set_pole_merge_angle_from(bcam->pole_merge_angle_from);
556 cam->set_pole_merge_angle_to(bcam->pole_merge_angle_to);
557
558 /* anamorphic lens bokeh */
559 cam->set_aperture_ratio(bcam->aperture_ratio);
560
561 /* perspective */
562 cam->set_fov(2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio));
563 cam->set_focaldistance(bcam->focaldistance);
564 cam->set_aperturesize(bcam->aperturesize);
565 cam->set_blades(bcam->apertureblades);
566 cam->set_bladesrotation(bcam->aperturerotation);
567
568 /* transform */
569 cam->set_matrix(blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type));
570
571 array<Transform> motion;
572 motion.resize(bcam->motion_steps, cam->get_matrix());
573 cam->set_motion(motion);
574 cam->set_use_perspective_motion(false);
575
576 cam->set_shuttertime(bcam->shuttertime);
577 cam->set_fov_pre(cam->get_fov());
578 cam->set_fov_post(cam->get_fov());
579 cam->set_motion_position(bcam->motion_position);
580
581 cam->set_rolling_shutter_type(bcam->rolling_shutter_type);
582 cam->set_rolling_shutter_duration(bcam->rolling_shutter_duration);
583
584 cam->set_shutter_curve(bcam->shutter_curve);
585
586 /* border */
587 cam->set_border_left(bcam->border.left);
588 cam->set_border_right(bcam->border.right);
589 cam->set_border_top(bcam->border.top);
590 cam->set_border_bottom(bcam->border.bottom);
591
592 cam->set_viewport_camera_border_left(bcam->viewport_camera_border.left);
593 cam->set_viewport_camera_border_right(bcam->viewport_camera_border.right);
594 cam->set_viewport_camera_border_top(bcam->viewport_camera_border.top);
595 cam->set_viewport_camera_border_bottom(bcam->viewport_camera_border.bottom);
596
597 bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale");
598 cam->set_offscreen_dicing_scale(bcam->offscreen_dicing_scale);
599}
600
601/* Sync Render Camera */
602
604 const BL::RenderSettings::motion_blur_position_enum type)
605{
606 switch (type) {
607 case BL::RenderSettings::motion_blur_position_START:
609 case BL::RenderSettings::motion_blur_position_CENTER:
611 case BL::RenderSettings::motion_blur_position_END:
612 return MOTION_POSITION_END;
613 }
614 /* Could happen if loading a newer file that has an unsupported type. */
616}
617
618void BlenderSync::sync_camera(BL::RenderSettings &b_render,
619 BL::Object &b_override,
620 int width,
621 int height,
622 const char *viewname)
623{
624 BlenderCamera bcam;
625 blender_camera_init(&bcam, b_render);
626
627 /* pixel aspect */
628 bcam.pixelaspect.x = b_render.pixel_aspect_x();
629 bcam.pixelaspect.y = b_render.pixel_aspect_y();
630 bcam.shuttertime = b_render.motion_blur_shutter();
632 b_render.motion_blur_position());
633
634 BL::CurveMapping b_shutter_curve(b_render.motion_blur_shutter_curve());
636
637 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
639 cscene,
640 "rolling_shutter_type",
643 bcam.rolling_shutter_duration = RNA_float_get(&cscene, "rolling_shutter_duration");
644
645 /* border */
646 if (b_render.use_border()) {
647 bcam.border.left = b_render.border_min_x();
648 bcam.border.right = b_render.border_max_x();
649 bcam.border.bottom = b_render.border_min_y();
650 bcam.border.top = b_render.border_max_y();
651 }
652
653 /* camera object */
654 BL::Object b_ob = b_scene.camera();
655
656 if (b_override) {
657 b_ob = b_override;
658 }
659
660 if (b_ob) {
661 BL::Array<float, 16> b_ob_matrix;
662 blender_camera_from_object(&bcam, b_engine, b_ob);
663 b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
664 bcam.matrix = get_transform(b_ob_matrix);
665 scene->bake_manager->set_use_camera(b_render.bake().view_from() ==
666 BL::BakeSettings::view_from_ACTIVE_CAMERA);
667 }
668 else {
669 scene->bake_manager->set_use_camera(false);
670 }
671
672 /* sync */
673 Camera *cam = scene->camera;
674 blender_camera_sync(cam, &bcam, width, height, viewname, &cscene);
675
676 /* dicing camera */
677 b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera"));
678 if (b_ob) {
679 BL::Array<float, 16> b_ob_matrix;
680 blender_camera_from_object(&bcam, b_engine, b_ob);
681 b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
682 bcam.matrix = get_transform(b_ob_matrix);
683
684 blender_camera_sync(scene->dicing_camera, &bcam, width, height, viewname, &cscene);
685 }
686 else {
687 *scene->dicing_camera = *cam;
688 }
689}
690
691void BlenderSync::sync_camera_motion(
692 BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time)
693{
694 if (!b_ob) {
695 return;
696 }
697
698 Camera *cam = scene->camera;
699 BL::Array<float, 16> b_ob_matrix;
700 b_engine.camera_model_matrix(b_ob, cam->get_use_spherical_stereo(), b_ob_matrix);
701 Transform tfm = get_transform(b_ob_matrix);
702 tfm = blender_camera_matrix(tfm, cam->get_camera_type(), cam->get_panorama_type());
703
704 if (motion_time == 0.0f) {
705 /* When motion blur is not centered in frame, cam->matrix gets reset. */
706 cam->set_matrix(tfm);
707 }
708
709 /* Set transform in motion array. */
710 int motion_step = cam->motion_step(motion_time);
711 if (motion_step >= 0) {
712 array<Transform> motion = cam->get_motion();
713 motion[motion_step] = tfm;
714 cam->set_motion(motion);
715 }
716
717 if (cam->get_camera_type() == CAMERA_PERSPECTIVE) {
718 BlenderCamera bcam;
719 float aspectratio, sensor_size;
720 blender_camera_init(&bcam, b_render);
721
722 /* TODO(sergey): Consider making it a part of blender_camera_init(). */
723 bcam.pixelaspect.x = b_render.pixel_aspect_x();
724 bcam.pixelaspect.y = b_render.pixel_aspect_y();
725
726 blender_camera_from_object(&bcam, b_engine, b_ob);
727 blender_camera_viewplane(&bcam, width, height, NULL, &aspectratio, &sensor_size);
728 /* TODO(sergey): De-duplicate calculation with camera sync. */
729 float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
730 if (fov != cam->get_fov()) {
731 VLOG_WORK << "Camera " << b_ob.name() << " FOV change detected.";
732 if (motion_time == 0.0f) {
733 cam->set_fov(fov);
734 }
735 else if (motion_time == -1.0f) {
736 cam->set_fov_pre(fov);
737 cam->set_use_perspective_motion(true);
738 }
739 else if (motion_time == 1.0f) {
740 cam->set_fov_post(fov);
741 cam->set_use_perspective_motion(true);
742 }
743 }
744 }
745}
746
747/* Sync 3D View Camera */
748
749static void blender_camera_view_subset(BL::RenderEngine &b_engine,
750 BL::RenderSettings &b_render,
751 BL::Scene &b_scene,
752 BL::Object &b_ob,
753 BL::SpaceView3D &b_v3d,
754 BL::RegionView3D &b_rv3d,
755 int width,
756 int height,
757 BoundBox2D *view_box,
758 BoundBox2D *cam_box,
759 float *view_aspect);
760
762 BL::RenderEngine &b_engine,
763 BL::Scene &b_scene,
764 BL::SpaceView3D &b_v3d,
765 BL::RegionView3D &b_rv3d,
766 int width,
767 int height,
768 bool skip_panorama = false)
769{
770 /* 3d view parameters */
771 bcam->nearclip = b_v3d.clip_start();
772 bcam->farclip = b_v3d.clip_end();
773 bcam->lens = b_v3d.lens();
774 bcam->shuttertime = b_scene.render().motion_blur_shutter();
775
776 BL::CurveMapping b_shutter_curve(b_scene.render().motion_blur_shutter_curve());
777 curvemapping_to_array(b_shutter_curve, bcam->shutter_curve, RAMP_TABLE_SIZE);
778
779 if (b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
780 /* camera view */
781 BL::Object b_ob = (b_v3d.use_local_camera()) ? b_v3d.camera() : b_scene.camera();
782
783 if (b_ob) {
784 blender_camera_from_object(bcam, b_engine, b_ob, skip_panorama);
785
786 if (!skip_panorama && bcam->type == CAMERA_PANORAMA) {
787 /* in panorama camera view, we map viewplane to camera border */
788 BoundBox2D view_box, cam_box;
789 float view_aspect;
790
791 BL::RenderSettings b_render_settings(b_scene.render());
793 b_render_settings,
794 b_scene,
795 b_ob,
796 b_v3d,
797 b_rv3d,
798 width,
799 height,
800 &view_box,
801 &cam_box,
802 &view_aspect);
803
804 bcam->pano_viewplane = view_box.make_relative_to(cam_box);
805 bcam->pano_aspectratio = view_aspect;
806 }
807 else {
808 /* magic zoom formula */
809 bcam->zoom = (float)b_rv3d.view_camera_zoom();
810 bcam->zoom = (1.41421f + bcam->zoom / 50.0f);
811 bcam->zoom *= bcam->zoom;
812 bcam->zoom = 2.0f / bcam->zoom;
813
814 /* offset */
815 bcam->offset = get_float2(b_rv3d.view_camera_offset());
816 }
817 }
818 }
819 else if (b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) {
820 /* orthographic view */
821 bcam->farclip *= 0.5f;
822 bcam->nearclip = -bcam->farclip;
823
824 float sensor_size;
825 if (bcam->sensor_fit == BlenderCamera::VERTICAL) {
826 sensor_size = bcam->sensor_height;
827 }
828 else {
829 sensor_size = bcam->sensor_width;
830 }
831
833 bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens();
834 }
835
836 bcam->zoom *= 2.0f;
837
838 /* 3d view transform */
839 bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
840
841 /* dimensions */
842 bcam->full_width = width;
843 bcam->full_height = height;
844}
845
846static void blender_camera_view_subset(BL::RenderEngine &b_engine,
847 BL::RenderSettings &b_render,
848 BL::Scene &b_scene,
849 BL::Object &b_ob,
850 BL::SpaceView3D &b_v3d,
851 BL::RegionView3D &b_rv3d,
852 int width,
853 int height,
854 BoundBox2D *view_box,
855 BoundBox2D *cam_box,
856 float *view_aspect)
857{
858 BoundBox2D cam, view;
859 float cam_aspect, sensor_size;
860
861 /* Get viewport viewplane. */
862 BlenderCamera view_bcam;
863 blender_camera_init(&view_bcam, b_render);
864 blender_camera_from_view(&view_bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height, true);
865
866 blender_camera_viewplane(&view_bcam, width, height, &view, view_aspect, &sensor_size);
867
868 /* Get camera viewplane. */
869 BlenderCamera cam_bcam;
870 blender_camera_init(&cam_bcam, b_render);
871 blender_camera_from_object(&cam_bcam, b_engine, b_ob, true);
872
873 /* Camera border is affect by aspect, viewport is not. */
874 cam_bcam.pixelaspect.x = b_render.pixel_aspect_x();
875 cam_bcam.pixelaspect.y = b_render.pixel_aspect_y();
876
878 &cam_bcam, cam_bcam.full_width, cam_bcam.full_height, &cam, &cam_aspect, &sensor_size);
879
880 /* Return */
881 *view_box = view * (1.0f / *view_aspect);
882 *cam_box = cam * (1.0f / cam_aspect);
883}
884
885static void blender_camera_border_subset(BL::RenderEngine &b_engine,
886 BL::RenderSettings &b_render,
887 BL::Scene &b_scene,
888 BL::SpaceView3D &b_v3d,
889 BL::RegionView3D &b_rv3d,
890 BL::Object &b_ob,
891 int width,
892 int height,
893 const BoundBox2D &border,
894 BoundBox2D *result)
895{
896 /* Determine camera viewport subset. */
897 BoundBox2D view_box, cam_box;
898 float view_aspect;
900 b_render,
901 b_scene,
902 b_ob,
903 b_v3d,
904 b_rv3d,
905 width,
906 height,
907 &view_box,
908 &cam_box,
909 &view_aspect);
910
911 /* Determine viewport subset matching given border. */
912 cam_box = cam_box.make_relative_to(view_box);
913 *result = cam_box.subset(border);
914}
915
917 BL::RenderEngine &b_engine,
918 BL::RenderSettings &b_render,
919 BL::Scene &b_scene,
920 BL::SpaceView3D &b_v3d,
921 BL::RegionView3D &b_rv3d,
922 int width,
923 int height)
924{
925 bool is_camera_view;
926
927 /* camera view? */
928 is_camera_view = b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA;
929
930 if (!is_camera_view) {
931 /* for non-camera view check whether render border is enabled for viewport
932 * and if so use border from 3d viewport
933 * assume viewport has got correctly clamped border already
934 */
935 if (b_v3d.use_render_border()) {
936 bcam->border.left = b_v3d.render_border_min_x();
937 bcam->border.right = b_v3d.render_border_max_x();
938 bcam->border.bottom = b_v3d.render_border_min_y();
939 bcam->border.top = b_v3d.render_border_max_y();
940 }
941 return;
942 }
943
944 BL::Object b_ob = (b_v3d.use_local_camera()) ? b_v3d.camera() : b_scene.camera();
945
946 if (!b_ob) {
947 return;
948 }
949
950 /* Determine camera border inside the viewport. */
951 BoundBox2D full_border;
953 b_render,
954 b_scene,
955 b_v3d,
956 b_rv3d,
957 b_ob,
958 width,
959 height,
960 full_border,
962
963 if (b_render.use_border()) {
964 bcam->border.left = b_render.border_min_x();
965 bcam->border.right = b_render.border_max_x();
966 bcam->border.bottom = b_render.border_min_y();
967 bcam->border.top = b_render.border_max_y();
968 }
969 else if (bcam->passepartout_alpha == 1.0f) {
970 bcam->border = full_border;
971 }
972 else {
973 return;
974 }
975
976 /* Determine viewport subset matching camera border. */
978 b_render,
979 b_scene,
980 b_v3d,
981 b_rv3d,
982 b_ob,
983 width,
984 height,
985 bcam->border,
986 &bcam->border);
987 bcam->border = bcam->border.clamp();
988}
989
990void BlenderSync::sync_view(BL::SpaceView3D &b_v3d,
991 BL::RegionView3D &b_rv3d,
992 int width,
993 int height)
994{
995 BlenderCamera bcam;
996 BL::RenderSettings b_render_settings(b_scene.render());
997 blender_camera_init(&bcam, b_render_settings);
998 blender_camera_from_view(&bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height);
999 blender_camera_border(&bcam, b_engine, b_render_settings, b_scene, b_v3d, b_rv3d, width, height);
1000 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
1001 blender_camera_sync(scene->camera, &bcam, width, height, "", &cscene);
1002
1003 /* dicing camera */
1004 BL::Object b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera"));
1005 if (b_ob) {
1006 BL::Array<float, 16> b_ob_matrix;
1007 blender_camera_from_object(&bcam, b_engine, b_ob);
1008 b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
1009 bcam.matrix = get_transform(b_ob_matrix);
1010
1011 blender_camera_sync(scene->dicing_camera, &bcam, width, height, "", &cscene);
1012 }
1013 else {
1014 *scene->dicing_camera = *scene->camera;
1015 }
1016}
1017
1019 BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height)
1020{
1022 bool use_border = false;
1023
1024 params.full_width = width;
1025 params.full_height = height;
1026
1027 if (b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA) {
1028 use_border = b_v3d.use_render_border();
1029 }
1030 else {
1031 /* the camera can always have a passepartout */
1032 use_border = true;
1033 }
1034
1035 if (use_border) {
1036 /* border render */
1037 /* the viewport may offset the border outside the view */
1038 BoundBox2D border = cam->border.clamp();
1039 params.full_x = (int)(border.left * (float)width);
1040 params.full_y = (int)(border.bottom * (float)height);
1041 params.width = (int)(border.right * (float)width) - params.full_x;
1042 params.height = (int)(border.top * (float)height) - params.full_y;
1043
1044 /* survive in case border goes out of view or becomes too small */
1045 params.width = max(params.width, 1);
1046 params.height = max(params.height, 1);
1047 }
1048 else {
1049 params.width = width;
1050 params.height = height;
1051 }
1052
1053 params.window_width = params.width;
1054 params.window_height = params.height;
1055
1056 return params;
1057}
1058
unsigned int uint
static AppView * view
static void blender_camera_border(BlenderCamera *bcam, BL::RenderEngine &b_engine, BL::RenderSettings &b_render, BL::Scene &b_scene, BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, int width, int height)
static float blender_camera_focal_distance(BL::RenderEngine &b_engine, BL::Object &b_ob, BL::Camera &b_camera, BlenderCamera *bcam)
static MotionPosition blender_motion_blur_position_type_to_cycles(const BL::RenderSettings::motion_blur_position_enum type)
static void blender_camera_border_subset(BL::RenderEngine &b_engine, BL::RenderSettings &b_render, BL::Scene &b_scene, BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, BL::Object &b_ob, int width, int height, const BoundBox2D &border, BoundBox2D *result)
static void blender_camera_from_view(BlenderCamera *bcam, BL::RenderEngine &b_engine, BL::Scene &b_scene, BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, int width, int height, bool skip_panorama=false)
static void blender_camera_view_subset(BL::RenderEngine &b_engine, BL::RenderSettings &b_render, BL::Scene &b_scene, BL::Object &b_ob, BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box, float *view_aspect)
static PanoramaType blender_panorama_type_to_cycles(const BL::Camera::panorama_type_enum type)
static void blender_camera_from_object(BlenderCamera *bcam, BL::RenderEngine &b_engine, BL::Object &b_ob, bool skip_panorama=false)
static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, BoundBox2D *viewplane, float *aspectratio, float *sensor_size)
static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height, const char *viewname, PointerRNA *cscene)
static Transform blender_camera_matrix(const Transform &tfm, const CameraType type, const PanoramaType panorama_type)
static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_render)
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
void sync_camera(BL::RenderSettings &b_render, BL::Object &b_override, int width, int height, const char *viewname)
static BufferParams get_buffer_params(BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height)
void sync_view(BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, int width, int height)
BoundBox2D clamp(float mn=0.0f, float mx=1.0f)
Definition boundbox.h:251
BoundBox2D make_relative_to(const BoundBox2D &other) const
Definition boundbox.h:239
float bottom
Definition boundbox.h:194
float top
Definition boundbox.h:195
float right
Definition boundbox.h:193
BoundBox2D subset(const BoundBox2D &other) const
Definition boundbox.h:227
float left
Definition boundbox.h:192
T * resize(size_t newsize)
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
static uint object_motion_steps(BL::Object &b_parent, BL::Object &b_ob, const int max_steps=INT_MAX)
static int render_resolution_x(BL::RenderSettings &b_render)
static void curvemapping_to_array(BL::CurveMapping &cumap, array< float > &data, int size)
static int render_resolution_y(BL::RenderSettings &b_render)
static int get_enum(PointerRNA &ptr, const char *name, int num_values=-1, int default_value=-1)
static float2 get_float2(const BL::Array< float, 2 > &array)
static Transform get_transform(const BL::Array< float, 16 > &array)
#define tanf(x)
#define CCL_NAMESPACE_END
#define NULL
#define atanf(x)
#define fabsf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
MotionPosition
@ MOTION_POSITION_END
@ MOTION_POSITION_START
@ MOTION_POSITION_CENTER
#define RAMP_TABLE_SIZE
PanoramaType
@ PANORAMA_MIRRORBALL
@ PANORAMA_FISHEYE_EQUISOLID
@ PANORAMA_CENTRAL_CYLINDRICAL
@ PANORAMA_EQUIANGULAR_CUBEMAP_FACE
@ PANORAMA_FISHEYE_EQUIDISTANT
@ PANORAMA_FISHEYE_LENS_POLYNOMIAL
@ PANORAMA_EQUIRECTANGULAR
CameraType
@ CAMERA_PERSPECTIVE
@ CAMERA_PANORAMA
@ CAMERA_ORTHOGRAPHIC
#define VLOG_WORK
Definition log.h:75
ccl_device_inline float2 one_float2()
Definition math_float2.h:19
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
#define FLT_MAX
Definition stdcycles.h:14
float central_cylindrical_radius
float rolling_shutter_duration
float central_cylindrical_range_u_min
MotionPosition motion_position
float fisheye_polynomial_k2
float fisheye_polynomial_k1
array< float > shutter_curve
float fisheye_polynomial_k0
float offscreen_dicing_scale
float central_cylindrical_range_v_min
enum BlenderCamera::@1412 sensor_fit
float fisheye_polynomial_k4
BoundBox2D pano_viewplane
Camera::RollingShutterType rolling_shutter_type
BoundBox2D border
float central_cylindrical_range_v_max
float pole_merge_angle_from
float fisheye_polynomial_k3
PanoramaType panorama_type
float central_cylindrical_range_u_max
BoundBox2D viewport_camera_border
RollingShutterType
@ ROLLING_SHUTTER_NUM_TYPES
@ ROLLING_SHUTTER_NONE
BoundBox2D border
int motion_step(float time) const
@ STEREO_LEFT
@ STEREO_NONE
@ STEREO_RIGHT
float x
float y
ccl_device_inline Transform transform_identity()
Definition transform.h:296
ccl_device_inline float3 transform_get_column(const Transform *t, int column)
Definition transform.h:326
ccl_device_inline Transform make_transform(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l)
Definition transform.h:133
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:423
ccl_device_inline Transform transform_scale(float3 s)
Definition transform.h:254
ccl_device_inline Transform transform_clear_scale(const Transform &tfm)
Definition transform.h:372
float max