[Bf-blender-cvs] [9baf39c8dad] master: Fix T86666: Lasso and Circle select tools selecting objects behind clip_min

Germano Cavalcante noreply at git.blender.org
Mon Mar 22 16:46:44 CET 2021


Commit: 9baf39c8daded5b000d4eacc6c677dbfd3359478
Author: Germano Cavalcante
Date:   Fri Mar 19 15:10:51 2021 -0300
Branches: master
https://developer.blender.org/rB9baf39c8daded5b000d4eacc6c677dbfd3359478

Fix T86666: Lasso and Circle select tools selecting objects behind clip_min

Although it works well in most cases, the algorithm to detect if a point
is within the limits of the camera does not work well in othographic mode.

This commit also adds the option `V3D_PROJ_TEST_CLIP_FAR` (currently unused).

Differential Revision: https://developer.blender.org/D10771

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

M	source/blender/editors/include/ED_view3d.h
M	source/blender/editors/space_view3d/view3d_project.c
M	source/blender/editors/space_view3d/view3d_select.c

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

diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index a63b133cc22..3b8e062ffec 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -163,14 +163,16 @@ typedef enum {
   V3D_PROJ_RET_OK = 0,
   /** can't avoid this when in perspective mode, (can't avoid) */
   V3D_PROJ_RET_CLIP_NEAR = 1,
+  /** After clip_end. */
+  V3D_PROJ_RET_CLIP_FAR = 2,
   /** so close to zero we can't apply a perspective matrix usefully */
-  V3D_PROJ_RET_CLIP_ZERO = 2,
+  V3D_PROJ_RET_CLIP_ZERO = 3,
   /** bounding box clip - RV3D_CLIPPING */
-  V3D_PROJ_RET_CLIP_BB = 3,
+  V3D_PROJ_RET_CLIP_BB = 4,
   /** outside window bounds */
-  V3D_PROJ_RET_CLIP_WIN = 4,
+  V3D_PROJ_RET_CLIP_WIN = 5,
   /** outside range (mainly for short), (can't avoid) */
-  V3D_PROJ_RET_OVERFLOW = 5,
+  V3D_PROJ_RET_OVERFLOW = 6,
 } eV3DProjStatus;
 
 /* some clipping tests are optional */
@@ -179,14 +181,14 @@ typedef enum {
   V3D_PROJ_TEST_CLIP_BB = (1 << 0),
   V3D_PROJ_TEST_CLIP_WIN = (1 << 1),
   V3D_PROJ_TEST_CLIP_NEAR = (1 << 2),
-  V3D_PROJ_TEST_CLIP_ZERO = (1 << 3),
+  V3D_PROJ_TEST_CLIP_FAR = (1 << 3),
+  V3D_PROJ_TEST_CLIP_ZERO = (1 << 4),
 } eV3DProjTest;
 
 #define V3D_PROJ_TEST_CLIP_DEFAULT \
   (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR)
 #define V3D_PROJ_TEST_ALL \
-  (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR | \
-   V3D_PROJ_TEST_CLIP_ZERO)
+  (V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_FAR | V3D_PROJ_TEST_CLIP_ZERO)
 
 /* view3d_iterators.c */
 
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 58538fc3ecb..24d34e514c5 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -38,7 +38,6 @@
 
 #include "ED_view3d.h" /* own include */
 
-#define BL_NEAR_CLIP 0.001
 #define BL_ZERO_CLIP 0.001
 
 /* Non Clipping Projection Functions
@@ -139,38 +138,32 @@ static eV3DProjStatus ed_view3d_project__internal(const ARegion *region,
   copy_v3_v3(vec4, co);
   vec4[3] = 1.0;
   mul_m4_v4(perspmat, vec4);
+  const float w = fabsf(vec4[3]);
 
-  if (((flag & V3D_PROJ_TEST_CLIP_ZERO) == 0) || (fabsf(vec4[3]) > (float)BL_ZERO_CLIP)) {
-    if (((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) || (vec4[3] > (float)BL_NEAR_CLIP)) {
-      const float scalar = (vec4[3] != 0.0f) ? (1.0f / vec4[3]) : 0.0f;
-      const float fx = ((float)region->winx / 2.0f) * (1.0f + (vec4[0] * scalar));
-      if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)region->winx)) {
-        const float fy = ((float)region->winy / 2.0f) * (1.0f + (vec4[1] * scalar));
-        if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)region->winy)) {
-          r_co[0] = fx;
-          r_co[1] = fy;
-
-          /* check if the point is behind the view, we need to flip in this case */
-          if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) {
-            negate_v2(r_co);
-          }
-        }
-        else {
-          return V3D_PROJ_RET_CLIP_WIN;
-        }
-      }
-      else {
-        return V3D_PROJ_RET_CLIP_WIN;
-      }
-    }
-    else {
-      return V3D_PROJ_RET_CLIP_NEAR;
-    }
-  }
-  else {
+  if ((flag & V3D_PROJ_TEST_CLIP_ZERO) && (w <= (float)BL_ZERO_CLIP)) {
     return V3D_PROJ_RET_CLIP_ZERO;
   }
 
+  if ((flag & V3D_PROJ_TEST_CLIP_NEAR) && (vec4[2] <= -w)) {
+    return V3D_PROJ_RET_CLIP_NEAR;
+  }
+
+  if ((flag & V3D_PROJ_TEST_CLIP_FAR) && (vec4[2] >= w)) {
+    return V3D_PROJ_RET_CLIP_FAR;
+  }
+
+  const float scalar = (w != 0.0f) ? (1.0f / w) : 0.0f;
+  const float fx = ((float)region->winx / 2.0f) * (1.0f + (vec4[0] * scalar));
+  const float fy = ((float)region->winy / 2.0f) * (1.0f + (vec4[1] * scalar));
+
+  if ((flag & V3D_PROJ_TEST_CLIP_WIN) &&
+      (fx <= 0.0f || fy <= 0.0f || fx >= (float)region->winx || fy >= (float)region->winy)) {
+    return V3D_PROJ_RET_CLIP_WIN;
+  }
+
+  r_co[0] = fx;
+  r_co[1] = fy;
+
   return V3D_PROJ_RET_OK;
 }
 
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 7dc4a72e510..3166b818d3c 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -2054,11 +2054,9 @@ static bool ed_object_select_pick(bContext *C,
       while (base) {
         if (BASE_SELECTABLE(v3d, base)) {
           float screen_co[2];
-          if (ED_view3d_project_float_global(region,
-                                             base->object->obmat[3],
-                                             screen_co,
-                                             V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN |
-                                                 V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
+          if (ED_view3d_project_float_global(
+                  region, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) ==
+              V3D_PROJ_RET_OK) {
             float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
             if (base == oldbasact) {
               dist_temp += 10.0f;
@@ -4054,11 +4052,9 @@ static bool object_circle_select(ViewContext *vc,
   for (base = FIRSTBASE(view_layer); base; base = base->next) {
     if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) {
       float screen_co[2];
-      if (ED_view3d_project_float_global(vc->region,
-                                         base->object->obmat[3],
-                                         screen_co,
-                                         V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN |
-                                             V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
+      if (ED_view3d_project_float_global(
+              vc->region, base->object->obmat[3], screen_co, V3D_PROJ_TEST_CLIP_DEFAULT) ==
+          V3D_PROJ_RET_OK) {
         if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
           ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
           changed = true;



More information about the Bf-blender-cvs mailing list