[Bf-blender-cvs] [a452fcb9a54] master: View3D: take clipping into account for Frame All

Campbell Barton noreply at git.blender.org
Sat Nov 7 11:27:35 CET 2020


Commit: a452fcb9a5495ecbbbaedb7e5c631814c7f4372a
Author: Campbell Barton
Date:   Sat Nov 7 20:16:32 2020 +1100
Branches: master
https://developer.blender.org/rBa452fcb9a5495ecbbbaedb7e5c631814c7f4372a

View3D: take clipping into account for Frame All

Clamp the min/max used for Frame All/Selected
by the clipping region if it's set.

Resolve T81050

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

M	source/blender/editors/include/ED_view3d.h
M	source/blender/editors/space_view3d/view3d_edit.c
M	source/blender/editors/space_view3d/view3d_utils.c

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

diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index f64c6a42f18..a0246174970 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -459,6 +459,8 @@ void ED_view3d_clipping_calc(struct BoundBox *bb,
                              const struct ARegion *region,
                              const struct Object *ob,
                              const struct rcti *rect);
+bool ED_view3d_clipping_clamp_minmax(const struct RegionView3D *rv3d, float min[3], float max[3]);
+
 void ED_view3d_clipping_local(struct RegionView3D *rv3d, const float mat[4][4]);
 bool ED_view3d_clipping_test(const struct RegionView3D *rv3d,
                              const float co[3],
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 897777c9159..c16cd94d90d 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -2978,6 +2978,11 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
     return OPERATOR_FINISHED;
   }
 
+  if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
+    /* This is an approximation, see function documentation for details. */
+    ED_view3d_clipping_clamp_minmax(rv3d, min, max);
+  }
+
   if (use_all_regions) {
     view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
   }
@@ -3125,6 +3130,11 @@ static int viewselected_exec(bContext *C, wmOperator *op)
     return OPERATOR_FINISHED;
   }
 
+  if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
+    /* This is an approximation, see function documentation for details. */
+    ED_view3d_clipping_clamp_minmax(rv3d, min, max);
+  }
+
   if (use_all_regions) {
     view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx);
   }
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 22cdbb090a5..c334b2ce541 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -330,6 +330,76 @@ void ED_view3d_clipping_calc(
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name View Clipping Clamp Min/Max
+ * \{ */
+
+struct PointsInPlanesMinMax_UserData {
+  float min[3];
+  float max[3];
+};
+
+static void points_in_planes_minmax_fn(
+    const float co[3], int UNUSED(i), int UNUSED(j), int UNUSED(k), void *user_data_p)
+{
+  struct PointsInPlanesMinMax_UserData *user_data = user_data_p;
+  minmax_v3v3_v3(user_data->min, user_data->max, co);
+}
+
+/**
+ * Clamp min/max by the viewport clipping.
+ *
+ * \note This is an approximation, with the limitation that the bounding box from the (mix, max)
+ * calculation might not have any geometry inside the clipped region.
+ * Performing a clipping test on each vertex would work well enough for most cases,
+ * although it's not perfect either as edges/faces may intersect the clipping without having any
+ * of their vertices inside it.
+ * A more accurate result would be quite involved.
+ *
+ * \return True when the arguments were clamped.
+ */
+bool ED_view3d_clipping_clamp_minmax(const RegionView3D *rv3d, float min[3], float max[3])
+{
+  /* 6 planes for the cube, 4..6 for the current view clipping planes. */
+  float planes[6 + 6][4];
+
+  /* Convert the min/max to 6 planes. */
+  for (int i = 0; i < 3; i++) {
+    float *plane_min = planes[(i * 2) + 0];
+    float *plane_max = planes[(i * 2) + 1];
+    zero_v3(plane_min);
+    zero_v3(plane_max);
+    plane_min[i] = -1.0f;
+    plane_min[3] = +min[i];
+    plane_max[i] = +1.0f;
+    plane_max[3] = -max[i];
+  }
+
+  /* Copy planes from the viewport & flip. */
+  int planes_len = 6;
+  int clip_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6;
+  for (int i = 0; i < clip_len; i++) {
+    negate_v4_v4(planes[planes_len], rv3d->clip[i]);
+    planes_len += 1;
+  }
+
+  /* Calculate points intersecting all planes (effectively intersecting two bounding boxes). */
+  struct PointsInPlanesMinMax_UserData user_data;
+  INIT_MINMAX(user_data.min, user_data.max);
+
+  const float eps_coplanar = 1e-4f;
+  const float eps_isect = 1e-6f;
+  if (isect_planes_v3_fn(
+          planes, planes_len, eps_coplanar, eps_isect, points_in_planes_minmax_fn, &user_data)) {
+    copy_v3_v3(min, user_data.min);
+    copy_v3_v3(max, user_data.max);
+    return true;
+  }
+  return false;
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name View Bound-Box Utilities
  *



More information about the Bf-blender-cvs mailing list