Commit: e0611ca832d793694cbda0fbae1a4388b81fc589
Author: Campbell Barton
Date:   Sat Mar 21 15:11:30 2015 +1100
Branches: master
https://developer.blender.org/rBe0611ca832d793694cbda0fbae1a4388b81fc589

View3D: fix view-selected zoom logic

- Correct logic converting radius to view distance.
- Wasn't taking view-zoom into account converting lens to angle.
- Support framing the selection in the camera bounds (for camera locked views).

Add ED_view3d_radius_to_dist to handles these details.

===================================================================

M       source/blender/blenkernel/intern/camera.c
M       source/blender/editors/include/ED_view3d.h
M       source/blender/editors/space_view3d/view3d_edit.c
M       source/blender/editors/space_view3d/view3d_view.c

===================================================================

diff --git a/source/blender/blenkernel/intern/camera.c 
b/source/blender/blenkernel/intern/camera.c
index 4588c00..ed400bc 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -283,7 +283,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, 
View3D *v3d, RegionView
                params->clipsta = -params->clipend;
 
                params->is_ortho = true;
-               /* make sure any changes to this match 
ED_view3d_radius_to_ortho_dist() */
+               /* make sure any changes to this match 
ED_view3d_radius_to_dist_ortho() */
                params->ortho_scale = rv3d->dist * sensor_size / v3d->lens;
                params->zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
        }
diff --git a/source/blender/editors/include/ED_view3d.h 
b/source/blender/editors/include/ED_view3d.h
index 11f9616..ec53bce 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -252,8 +252,12 @@ void ED_view3d_clipping_disable(void);
 
 float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]);
 
-float ED_view3d_radius_to_persp_dist(const float angle, const float radius);
-float ED_view3d_radius_to_ortho_dist(const float lens, const float radius);
+float ED_view3d_radius_to_dist_persp(const float angle, const float radius);
+float ED_view3d_radius_to_dist_ortho(const float lens, const float radius);
+float ED_view3d_radius_to_dist(
+        const struct View3D *v3d, const struct ARegion *ar,
+        const char persp, const bool use_aspect,
+        const float radius);
 
 void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4]);
 
diff --git a/source/blender/editors/space_view3d/view3d_edit.c 
b/source/blender/editors/space_view3d/view3d_edit.c
index 51915e0..0bced34 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -2748,29 +2748,15 @@ static void view3d_from_minmax(bContext *C, View3D 
*v3d, ARegion *ar,
        size = max_fff(afm[0], afm[1], afm[2]);
 
        if (ok_dist) {
-               /* fix up zoom distance if needed */
+               char persp;
 
                if (rv3d->is_persp) {
-                       float lens, sensor_size;
-                       /* offset the view based on the lens */
                        if (rv3d->persp == RV3D_CAMOB && 
ED_view3d_camera_lock_check(v3d, rv3d)) {
-                               CameraParams params;
-                               BKE_camera_params_init(&params);
-                               params.clipsta = v3d->near;
-                               params.clipend = v3d->far;
-                               BKE_camera_params_from_object(&params, 
v3d->camera);
-
-                               lens = params.lens;
-                               sensor_size = 
BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
+                               persp = RV3D_CAMOB;
                        }
                        else {
-                               lens = v3d->lens;
-                               sensor_size = DEFAULT_SENSOR_WIDTH;
+                               persp = RV3D_PERSP;
                        }
-                       size = 
ED_view3d_radius_to_persp_dist(focallength_to_fov(lens, sensor_size), size / 
2.0f) * VIEW3D_MARGIN;
-
-                       /* do not zoom closer than the near clipping plane */
-                       size = max_ff(size, v3d->near * 1.5f);
                }
                else { /* ortho */
                        if (size < 0.0001f) {
@@ -2779,7 +2765,15 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, 
ARegion *ar,
                        }
                        else {
                                /* adjust zoom so it looks nicer */
-                               size = 
ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN;
+                               persp = RV3D_ORTHO;
+                       }
+               }
+
+               if (ok_dist) {
+                       new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, 
true, (size / 2) * VIEW3D_MARGIN);
+                       if (rv3d->is_persp) {
+                               /* don't zoom closer than the near clipping 
plane */
+                               new_dist = max_ff(new_dist, v3d->near * 1.5f);
                        }
                }
        }
@@ -2787,15 +2781,6 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, 
ARegion *ar,
        mid_v3_v3v3(new_ofs, min, max);
        negate_v3(new_ofs);
 
-       new_dist = size;
-
-       /* correction for window aspect ratio */
-       if (ar->winy > 2 && ar->winx > 2) {
-               size = (float)ar->winx / (float)ar->winy;
-               if (size < 1.0f) size = 1.0f / size;
-               new_dist *= size;
-       }
-
        if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, 
rv3d)) {
                rv3d->persp = RV3D_PERSP;
                ED_view3d_smooth_view(C, v3d, ar, v3d->camera, NULL,
diff --git a/source/blender/editors/space_view3d/view3d_view.c 
b/source/blender/editors/space_view3d/view3d_view.c
index 4888c68..1c10a85 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -1214,7 +1214,7 @@ static bool view3d_localview_init(
        View3D *v3d = sa->spacedata.first;
        Base *base;
        float min[3], max[3], box[3], mid[3];
-       float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f;
+       float size = 0.0f;
        unsigned int locallay;
        bool ok = false;
 
@@ -1252,13 +1252,6 @@ static bool view3d_localview_init(
 
                sub_v3_v3v3(box, max, min);
                size = max_fff(box[0], box[1], box[2]);
-
-               /* do not zoom closer than the near clipping plane */
-               size = max_ff(size, v3d->near * 1.5f);
-
-               /* perspective size (we always switch out of camera view so no 
need to use its lens size) */
-               size_persp = 
ED_view3d_radius_to_persp_dist(focallength_to_fov(v3d->lens, 
DEFAULT_SENSOR_WIDTH), size / 2.0f) * VIEW3D_MARGIN;
-               size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 
2.0f) * VIEW3D_MARGIN;
        }
        
        if (ok == true) {
@@ -1275,6 +1268,7 @@ static bool view3d_localview_init(
                for (ar = sa->regionbase.first; ar; ar = ar->next) {
                        if (ar->regiontype == RGN_TYPE_WINDOW) {
                                RegionView3D *rv3d = ar->regiondata;
+                               bool ok_dist = true;
 
                                /* new view values */
                                Object *camera_old = NULL;
@@ -1290,25 +1284,24 @@ static bool view3d_localview_init(
                                        camera_old = v3d->camera;
                                }
 
-                               /* perspective should be a bit farther away to 
look nice */
-                               if (rv3d->persp != RV3D_ORTHO) {
-                                       dist_new = size_persp;
-                               }
-                               else {
-                                       dist_new = size_ortho;
+                               if (rv3d->persp == RV3D_ORTHO) {
+                                       if (size < 0.0001) {
+                                               ok_dist = false;
+                                       }
                                }
 
-                               /* correction for window aspect ratio */
-                               if (ar->winy > 2 && ar->winx > 2) {
-                                       float asp = (float)ar->winx / 
(float)ar->winy;
-                                       if (asp < 1.0f) asp = 1.0f / asp;
-                                       dist_new *= asp;
+                               if (ok_dist) {
+                                       dist_new = 
ED_view3d_radius_to_dist(v3d, ar, rv3d->persp, true, (size / 2) * 
VIEW3D_MARGIN);
+                                       if (rv3d->persp == RV3D_PERSP) {
+                                               /* don't zoom closer than the 
near clipping plane */
+                                               dist_new = max_ff(dist_new, 
v3d->near * 1.5f);
+                                       }
                                }
 
                                ED_view3d_smooth_view_ex(
                                        wm, win, sa,
                                        v3d, ar, camera_old, NULL,
-                                       ofs_new, NULL, &dist_new, NULL,
+                                       ofs_new, NULL, ok_dist ? &dist_new : 
NULL, NULL,
                                        smooth_viewtx);
                        }
                }
@@ -1720,16 +1713,111 @@ float ED_view3d_pixel_size(RegionView3D *rv3d, const 
float co[3])
        return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * 
U.pixelsize;
 }
 
-float ED_view3d_radius_to_persp_dist(const float angle, const float radius)
+float ED_view3d_radius_to_dist_persp(const float angle, const float radius)
 {
-       return (radius / 2.0f) * fabsf(1.0f / cosf((((float)M_PI) - angle) / 
2.0f));
+       return radius * (1.0f / tanf(angle / 2.0f));
 }
 
-float ED_view3d_radius_to_ortho_dist(const float lens, const float radius)
+float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
 {
        return radius / (DEFAULT_SENSOR_WIDTH / lens);
 }
 
+/**
+ * Return a new RegionView3D.dist value to fit the \a radius.
+ *
+ * \note Depth isn't taken into account, this will fit a flat plane exactly,
+ * but points towards the view (with a perspective projection),
+ * may be within the radius but outside the view. eg:
+ *
+ * <pre>
+ *           +
+ * pt --> + /^ radius
+ *         / |
+ *        /  |
+ * view  +   +
+ *        \  |
+ *         \ |
+ *          \|
+ *           +
+ * </pre>
+ *
+ * \param ar  Can be NULL if \a use_aspect is false.
+ * \param persp  Allow the caller to tell what kind of perspective to use 
(ortho/view/camera)
+ * \param use_aspect  Increase the distance to account for non 1:1 view aspect.
+ * \param radius  The radius will be fitted exactly, typically pre-scaled by a 
margin (#VIEW3D_MARGIN).
+ */
+float ED_view3d_radius_to_dist(
+        const View3D *v3d, const ARegion *ar,
+        const char persp, const bool use_aspect,
+        const float radius)
+{
+       float dist;
+
+       BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
+       BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
+
+       if (persp == RV3D_ORTHO) {
+               dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
+       }
+       else {
+               float lens, sensor_size, zoom;
+               float angle;
+
+               if (persp == RV3D_CAMOB) {
+                       CameraParams params;
+                       BKE_camera_params_init(&params);
+                       params.clipsta = v3d->near;
+                       params.clipend = v3d->far;
+                       BKE_camera_params_from_object(&params, v3d->camera);
+
+                       lens = params.lens;
+                       sensor_size = BKE_camera_sensor_size(params.sensor_fit, 
params.sensor_x, params.sensor_y);
+
+                       /* ignore 'rv3d->camzoom' because we wan't to fit to 
the cameras frame */
+                       zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
+               }
+               else {
+                       lens = v3d->lens;
+                       sensor_size = DEFAULT_SENSOR_WIDTH;
+                       zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
+               }
+
+               angle = focallength_to_fov(lens, sensor_size);
+
+               /* zoom influences lens, correct this by scaling the angle as a 
distance (by the zoom-level) */
+               angle = ((atanf(tanf(angle / 2.0f) * zoom) * 2.0f));
+
+               dist = ED_view3d_radius_to_dist_persp(angle, radius);
+       }
+
+       if (use_aspect) {
+               const RegionView3D *rv3d = ar->regiondata;
+
+               float winx, winy;
+
+               if (persp == RV3D_CAMOB) {
+                       /* camera frame x/y in pixels */
+                       winx = ar->winx / rv3d->viewcamtexcofac[0];
+                       winy = ar->winy / rv3d->viewcamtexcofac[1];
+               }
+               else {
+                       winx = ar->winx;
+                       winy = ar->winy;
+               }
+
+               if (winx && winy) {
+                       float aspect = winx / winy;
+                       if (aspect < 1.0f) {
+                               aspect = 1.0f / aspect;
+                       }
+                       dist *= aspect;
+               }
+       }
+
+       return dist;
+}
+
 /* view matrix properties utilities */
 
 /* unused */

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to