Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/camera.c')
-rw-r--r--source/blender/blenkernel/intern/camera.c242
1 files changed, 177 insertions, 65 deletions
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 1402f62291f..451656a9bca 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -39,6 +39,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_rect.h"
#include "BKE_animsys.h"
#include "BKE_camera.h"
@@ -48,6 +49,8 @@
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "GPU_compositing.h"
+
/****************************** Camera Datablock *****************************/
void *BKE_camera_add(Main *bmain, const char *name)
@@ -65,7 +68,9 @@ void *BKE_camera_add(Main *bmain, const char *name)
cam->ortho_scale = 6.0;
cam->flag |= CAM_SHOWPASSEPARTOUT;
cam->passepartalpha = 0.5f;
-
+
+ GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
+
return cam;
}
@@ -77,6 +82,10 @@ Camera *BKE_camera_copy(Camera *cam)
id_lib_extern((ID *)camn->dof_ob);
+ if (cam->id.lib) {
+ BKE_id_lib_local_paths(G.main, cam->id.lib, &camn->id);
+ }
+
return camn;
}
@@ -257,7 +266,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView
/* camera view */
BKE_camera_params_from_object(params, v3d->camera);
- params->zoom = BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom);
+ params->zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
params->offsetx = 2.0f * rv3d->camdx * params->zoom;
params->offsety = 2.0f * rv3d->camdy * params->zoom;
@@ -454,17 +463,25 @@ void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3])
float dummy_drawsize;
const float dummy_scale[3] = {1.0f, 1.0f, 1.0f};
- BKE_camera_view_frame_ex(scene, camera, false, 1.0, dummy_scale,
+ BKE_camera_view_frame_ex(scene, camera, 0.0, true, dummy_scale,
dummy_asp, dummy_shift, &dummy_drawsize, r_vec);
}
+#define CAMERA_VIEWFRAME_NUM_PLANES 4
typedef struct CameraViewFrameData {
- float plane_tx[4][4]; /* 4 planes (not 4x4 matrix)*/
- float frame_tx[4][3];
- float normal_tx[4][3];
- float dist_vals_sq[4]; /* distance squared (signed) */
+ float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4]; /* 4 planes */
+ float normal_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
+ float dist_vals_sq[CAMERA_VIEWFRAME_NUM_PLANES]; /* distance squared (signed) */
unsigned int tot;
+
+ /* Ortho camera only. */
+ bool is_ortho;
+ float camera_no[3];
+ float dist_to_cam;
+
+ /* Not used by callbacks... */
+ float camera_rotmat[3][3];
} CameraViewFrameData;
static void camera_to_frame_view_cb(const float co[3], void *user_data)
@@ -472,67 +489,106 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data)
CameraViewFrameData *data = (CameraViewFrameData *)user_data;
unsigned int i;
- for (i = 0; i < 4; i++) {
- float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
- if (nd < data->dist_vals_sq[i]) {
- data->dist_vals_sq[i] = nd;
- }
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ const float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
+ CLAMP_MAX(data->dist_vals_sq[i], nd);
+ }
+
+ if (data->is_ortho) {
+ const float d = dot_v3v3(data->camera_no, co);
+ CLAMP_MAX(data->dist_to_cam, d);
}
data->tot++;
}
-/* don't move the camera, just yield the fit location */
-/* only valid for perspective cameras */
-bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
+static void camera_frame_fit_data_init(Scene *scene, Object *ob, CameraParams *params, CameraViewFrameData *data)
{
- float shift[2];
- float plane_tx[4][3];
- float rot_obmat[3][3];
- const float zero[3] = {0, 0, 0};
- CameraViewFrameData data_cb;
-
+ float camera_rotmat_transposed_inversed[4][4];
unsigned int i;
- BKE_camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);
+ /* setup parameters */
+ BKE_camera_params_init(params);
+ BKE_camera_params_from_object(params, ob);
- copy_m3_m4(rot_obmat, camera_ob->obmat);
- normalize_m3(rot_obmat);
-
- for (i = 0; i < 4; i++) {
- /* normalize so Z is always 1.0f*/
- mul_v3_fl(data_cb.frame_tx[i], 1.0f / data_cb.frame_tx[i][2]);
+ /* compute matrix, viewplane, .. */
+ if (scene) {
+ BKE_camera_params_compute_viewplane(params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
}
+ else {
+ BKE_camera_params_compute_viewplane(params, 1, 1, 1.0f, 1.0f);
+ }
+ BKE_camera_params_compute_matrix(params);
- /* get the shift back out of the frame */
- shift[0] = (data_cb.frame_tx[0][0] +
- data_cb.frame_tx[1][0] +
- data_cb.frame_tx[2][0] +
- data_cb.frame_tx[3][0]) / 4.0f;
- shift[1] = (data_cb.frame_tx[0][1] +
- data_cb.frame_tx[1][1] +
- data_cb.frame_tx[2][1] +
- data_cb.frame_tx[3][1]) / 4.0f;
-
- for (i = 0; i < 4; i++) {
- mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
+ /* initialize callback data */
+ copy_m3_m4(data->camera_rotmat, ob->obmat);
+ normalize_m3(data->camera_rotmat);
+ /* To transform a plane which is in its homogeneous representation (4d vector),
+ * we need the inverse of the transpose of the transform matrix... */
+ copy_m4_m3(camera_rotmat_transposed_inversed, data->camera_rotmat);
+ transpose_m4(camera_rotmat_transposed_inversed);
+ invert_m4(camera_rotmat_transposed_inversed);
+
+ /* Extract frustum planes from projection matrix. */
+ planes_from_projmat(params->winmat,
+ /* left right top bottom near far */
+ data->plane_tx[2], data->plane_tx[0], data->plane_tx[3], data->plane_tx[1], NULL, NULL);
+
+ /* Rotate planes and get normals from them */
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ mul_m4_v4(camera_rotmat_transposed_inversed, data->plane_tx[i]);
+ normalize_v3_v3(data->normal_tx[i], data->plane_tx[i]);
}
- for (i = 0; i < 4; i++) {
- normal_tri_v3(data_cb.normal_tx[i], zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
- plane_from_point_normal_v3(data_cb.plane_tx[i], data_cb.frame_tx[i], data_cb.normal_tx[i]);
+ copy_v4_fl(data->dist_vals_sq, FLT_MAX);
+ data->tot = 0;
+ data->is_ortho = params->is_ortho;
+ if (params->is_ortho) {
+ /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
+ negate_v3_v3(data->camera_no, data->camera_rotmat[2]);
+ data->dist_to_cam = FLT_MAX;
}
+}
- /* initialize callback data */
- copy_v4_fl(data_cb.dist_vals_sq, FLT_MAX);
- data_cb.tot = 0;
- /* run callback on all visible points */
- BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
- camera_to_frame_view_cb, &data_cb);
+static bool camera_frame_fit_calc_from_data(
+ CameraParams *params, CameraViewFrameData *data, float r_co[3], float *r_scale)
+{
+ float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
+ unsigned int i;
- if (data_cb.tot <= 1) {
+ if (data->tot <= 1) {
return false;
}
+
+ if (params->is_ortho) {
+ const float *cam_axis_x = data->camera_rotmat[0];
+ const float *cam_axis_y = data->camera_rotmat[1];
+ const float *cam_axis_z = data->camera_rotmat[2];
+ float dists[CAMERA_VIEWFRAME_NUM_PLANES];
+ float scale_diff;
+
+ /* apply the dist-from-plane's to the transformed plane points */
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ dists[i] = sqrtf_signed(data->dist_vals_sq[i]);
+ }
+
+ if ((dists[0] + dists[2]) > (dists[1] + dists[3])) {
+ scale_diff = (dists[1] + dists[3]) *
+ (BLI_rctf_size_x(&params->viewplane) / BLI_rctf_size_y(&params->viewplane));
+ }
+ else {
+ scale_diff = (dists[0] + dists[2]) *
+ (BLI_rctf_size_y(&params->viewplane) / BLI_rctf_size_x(&params->viewplane));
+ }
+ *r_scale = params->ortho_scale - scale_diff;
+
+ zero_v3(r_co);
+ madd_v3_v3fl(r_co, cam_axis_x, (dists[2] - dists[0]) * 0.5f + params->shiftx * scale_diff);
+ madd_v3_v3fl(r_co, cam_axis_y, (dists[1] - dists[3]) * 0.5f + params->shifty * scale_diff);
+ madd_v3_v3fl(r_co, cam_axis_z, -(data->dist_to_cam - 1.0f - params->clipsta));
+
+ return true;
+ }
else {
float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];
@@ -540,16 +596,16 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
float plane_isect_pt_1[3], plane_isect_pt_2[3];
/* apply the dist-from-plane's to the transformed plane points */
- for (i = 0; i < 4; i++) {
- mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], sqrtf_signed(data_cb.dist_vals_sq[i]));
+ for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
+ mul_v3_v3fl(plane_tx[i], data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
}
if ((!isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
- plane_tx[0], data_cb.normal_tx[0],
- plane_tx[2], data_cb.normal_tx[2])) ||
+ plane_tx[0], data->normal_tx[0],
+ plane_tx[2], data->normal_tx[2])) ||
(!isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
- plane_tx[1], data_cb.normal_tx[1],
- plane_tx[3], data_cb.normal_tx[3])))
+ plane_tx[1], data->normal_tx[1],
+ plane_tx[3], data->normal_tx[3])))
{
return false;
}
@@ -559,16 +615,17 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
plane_isect_2, plane_isect_2_other,
- plane_isect_pt_1, plane_isect_pt_2) == 0)
+ plane_isect_pt_1, plane_isect_pt_2) != 0)
{
- return false;
- }
- else {
- float cam_plane_no[3] = {0.0f, 0.0f, -1.0f};
+ float cam_plane_no[3];
float plane_isect_delta[3];
float plane_isect_delta_len;
- mul_m3_v3(rot_obmat, cam_plane_no);
+ float shift_fac = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y) /
+ params->lens;
+
+ /* we want (0, 0, -1) transformed by camera_rotmat, this is a quicker shortcut. */
+ negate_v3_v3(cam_plane_no, data->camera_rotmat[2]);
sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
plane_isect_delta_len = len_v3(plane_isect_delta);
@@ -578,18 +635,73 @@ bool BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object
/* offset shift */
normalize_v3(plane_isect_1_no);
- madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
+ madd_v3_v3fl(r_co, plane_isect_1_no, params->shifty * plane_isect_delta_len * shift_fac);
}
else {
copy_v3_v3(r_co, plane_isect_pt_2);
/* offset shift */
normalize_v3(plane_isect_2_no);
- madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
+ madd_v3_v3fl(r_co, plane_isect_2_no, params->shiftx * plane_isect_delta_len * shift_fac);
}
-
return true;
}
}
+
+ return false;
+}
+
+/* don't move the camera, just yield the fit location */
+/* r_scale only valid/useful for ortho cameras */
+bool BKE_camera_view_frame_fit_to_scene(
+ Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale)
+{
+ CameraParams params;
+ CameraViewFrameData data_cb;
+
+ /* just in case */
+ *r_scale = 1.0f;
+
+ camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
+
+ /* run callback on all visible points */
+ BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb);
+
+ return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
+}
+
+bool BKE_camera_view_frame_fit_to_coords(
+ Scene *scene, float (*cos)[3], int num_cos, Object *camera_ob, float r_co[3], float *r_scale)
+{
+ CameraParams params;
+ CameraViewFrameData data_cb;
+
+ /* just in case */
+ *r_scale = 1.0f;
+
+ camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
+
+ /* run callback on all given coordinates */
+ while (num_cos--) {
+ camera_to_frame_view_cb(cos[num_cos], &data_cb);
+ }
+
+ return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
+}
+
+void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings)
+{
+ if (camera->type == OB_CAMERA) {
+ Camera *cam = camera->data;
+ r_fx_settings->dof = &cam->gpu_dof;
+ r_fx_settings->dof->focal_length = cam->lens;
+ r_fx_settings->dof->sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
+ if (cam->dof_ob) {
+ r_fx_settings->dof->focus_distance = len_v3v3(cam->dof_ob->obmat[3], camera->obmat[3]);
+ }
+ else {
+ r_fx_settings->dof->focus_distance = cam->YF_dofdist;
+ }
+ }
}