[Bf-blender-cvs] [e3a6440] master: BMesh: mesh-data picking, general improvements

Campbell Barton noreply at git.blender.org
Tue Apr 21 13:26:01 CEST 2015


Commit: e3a6440e7af7f90432319aec9f6ad43b557def31
Author: Campbell Barton
Date:   Tue Apr 21 21:16:19 2015 +1000
Branches: master
https://developer.blender.org/rBe3a6440e7af7f90432319aec9f6ad43b557def31

BMesh: mesh-data picking, general improvements

Generalize logic for vert/edge/face selection:
- index cycling.
- selection bias with mixed modes.

Details:
- Edges now support index cycling (as verts/faces did already)
- Cycling over near elements is now only enabled when the mouse position remains the same.
- No longer do 2 selection passes to perform index cycling.

Fixes:
- Edges behind the view could be selected (surprising nobody reported!)
- Selection bias now only changes the element that gets picked without interning the return distance
  (was buggy with mixed modes).

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

M	source/blender/editors/include/ED_mesh.h
M	source/blender/editors/include/ED_view3d.h
M	source/blender/editors/mesh/editmesh_select.c
M	source/blender/editors/space_view3d/view3d_draw.c

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

diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 3c67236..b982ff2 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -137,20 +137,18 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2]
                                    short xmin, short ymin, short xmax, short ymax);
 bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
 
-struct BMVert *EDBM_vert_find_nearest_ex(
-        struct ViewContext *vc, float *r_dist,
-        const bool use_select_bias);
+struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist,
+        const bool use_select_bias, bool use_cycle);
 struct BMVert *EDBM_vert_find_nearest(
         struct ViewContext *vc, float *r_dist);
 
-struct BMEdge *EDBM_edge_find_nearest_ex(
-        struct ViewContext *vc, float *r_dist,
-        const bool use_select_bias);
+struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, float *r_dist,
+        const bool use_select_bias, const bool use_cycle);
 struct BMEdge *EDBM_edge_find_nearest(
         struct ViewContext *vc, float *r_dist);
 
-struct BMFace *EDBM_face_find_nearest_ex(
-        struct ViewContext *vc, float *r_dist,
+struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, float *r_dist,
+        const bool use_select_bias, const bool use_cycle,
         struct BMFace **r_efa_zbuf);
 struct BMFace *EDBM_face_find_nearest(
         struct ViewContext *vc, float *r_dist);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 6be7f70..ab270f6 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -271,7 +271,7 @@ void          ED_view3d_backbuf_validate(struct ViewContext *vc);
 struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
 unsigned int  ED_view3d_backbuf_sample_rect(
         struct ViewContext *vc, const int mval[2], int size,
-        unsigned int min, unsigned int max, float *dist);
+        unsigned int min, unsigned int max, float *r_dist);
 int          ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
 unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y);
 
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 84ca945..92c7dde 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -354,45 +354,62 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
 /* -------------------------------------------------------------------- */
 
 /** \name Find Nearest Vert/Edge/Face
+ *
+ * \note Screen-space manhatten distances are used here,
+ * since its faster and good enough for the purpose of selection.
+ *
+ * \note \a dist_bias is used so we can bias against selected items.
+ * when choosing between elements of a single type, but return the real distance
+ * to avoid the bias interfering with distance comparisons when mixing types.
  * \{ */
 
-#define FIND_NEAR_THRESHOLD_MIN 3
-#define FIND_NEAR_BIAS 5
+#define FIND_NEAR_SELECT_BIAS 5
+#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3
+
+struct NearestVertUserData_Hit {
+	float   dist;
+	float   dist_bias;
+	int     index;
+	BMVert *vert;
+};
 
 struct NearestVertUserData {
 	float mval_fl[2];
-	int pass;
 	bool use_select_bias;
-	float dist;
-	int index_last;
-	int index_nearest;
-	BMVert *vert_nearest;
+	bool use_cycle;
+	int cycle_index_prev;
+
+	struct NearestVertUserData_Hit hit;
+	struct NearestVertUserData_Hit hit_cycle;
 };
 
 static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
 {
 	struct NearestVertUserData *data = userData;
+	float dist_test, dist_test_bias;
 
-	if (data->pass == 0) {
-		if (index <= data->index_last)
-			return;
-	}
-	else {
-		if (index > data->index_last)
-			return;
-	}
+	dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
 
-	if (data->dist > FIND_NEAR_THRESHOLD_MIN) {
-		float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
+	if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+		dist_test_bias += FIND_NEAR_SELECT_BIAS;
+	}
 
-		if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
-			dist_test += FIND_NEAR_BIAS;
-		}
+	if (dist_test_bias < data->hit.dist_bias) {
+		data->hit.dist_bias = dist_test_bias;
+		data->hit.dist = dist_test;
+		data->hit.index = index;
+		data->hit.vert = eve;
+	}
 
-		if (dist_test < data->dist) {
-			data->dist = dist_test;
-			data->vert_nearest = eve;
-			data->index_nearest = index;
+	if (data->use_cycle) {
+		if ((data->hit_cycle.vert == NULL) &&
+		    (index > data->cycle_index_prev) &&
+		    (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN))
+		{
+			data->hit_cycle.dist_bias = dist_test_bias;
+			data->hit_cycle.dist = dist_test;
+			data->hit_cycle.index = index;
+			data->hit_cycle.vert = eve;
 		}
 	}
 }
@@ -408,89 +425,94 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float
  */
 BMVert *EDBM_vert_find_nearest_ex(
         ViewContext *vc, float *r_dist,
-        const bool use_select_bias)
+        const bool use_select_bias, bool use_cycle)
 {
 	BMesh *bm = vc->em->bm;
 
 	if (V3D_IS_ZBUF(vc->v3d)) {
 		const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
-		float distance;
+		float dist_test;
 		unsigned int index;
 		BMVert *eve;
 		
 		index = ED_view3d_backbuf_sample_rect(
-		        vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &distance);
-
+		        vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test);
 		eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
 		
-		if (eve && distance < *r_dist) {
-			*r_dist = distance;
-			return eve;
-		}
-		else {
-			return NULL;
+		if (eve) {
+			if (dist_test < *r_dist) {
+				*r_dist = dist_test;
+				return eve;
+			}
 		}
+		return NULL;
 	}
 	else {
-		struct NearestVertUserData data;
+		struct NearestVertUserData data = {{0}};
+		const struct NearestVertUserData_Hit *hit;
+		const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
 
 		static int prev_select_index = 0;
 		static const BMVert *prev_select_elem = NULL;
 
-		if (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))) {
+		if ((use_cycle == false) ||
+		    (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index))))
+		{
 			prev_select_index = 0;
 			prev_select_elem = NULL;
 		}
 
-		data.index_last = prev_select_index;
 		data.mval_fl[0] = vc->mval[0];
 		data.mval_fl[1] = vc->mval[1];
 		data.use_select_bias = use_select_bias;
-		data.dist = *r_dist;
-
-		data.vert_nearest = NULL;
-		data.index_nearest = 0;
-
-		data.pass = 0;
+		data.use_cycle = use_cycle;
+		data.hit.dist      = data.hit_cycle.dist = \
+		data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
+		data.cycle_index_prev = prev_select_index;
 
 		ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+		mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
 
-		mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-
-		if (data.dist > FIND_NEAR_THRESHOLD_MIN) {
-			data.pass = 1;
-			mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
-		}
+		hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+		*r_dist = hit->dist;
 
-		*r_dist = data.dist;
-		prev_select_elem = data.vert_nearest;
-		prev_select_index = data.index_nearest;
+		prev_select_elem = hit->vert;
+		prev_select_index = hit->index;
 
-		return data.vert_nearest;
+		return hit->vert;
 	}
 }
 
 BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
 {
-	return EDBM_vert_find_nearest_ex(vc, r_dist, false);
+	return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
 }
 
+struct NearestEdgeUserData_Hit {
+	float   dist;
+	float   dist_bias;
+	int     index;
+	BMEdge *edge;
+};
 
 struct NearestEdgeUserData {
 	ViewContext vc;
 	float mval_fl[2];
 	bool use_select_bias;
-	char hflag_select;
-	float dist;
-	BMEdge *edge_nearest;
+	bool use_cycle;
+	int cycle_index_prev;
+
+	struct NearestEdgeUserData_Hit hit;
+	struct NearestEdgeUserData_Hit hit_cycle;
 };
 
 /* note; uses v3d, so needs active 3d window */
-static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
+static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
 {
 	struct NearestEdgeUserData *data = userData;
+	float dist_test, dist_test_bias;
+
 	float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
-	float distance;
 	float screen_co[2];
 
 	if (fac <= 0.0f) {
@@ -505,93 +527,117 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float
 		interp_v3_v3v3(screen_co, screen_co_a, screen_co_b, fac);
 	}
 
-	distance = len_manhattan_v2v2(data->mval_fl, screen_co);
+	dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
 
 	if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
-		distance += FIND_NEAR_BIAS;
+		dist_test += FIND_NEAR_SELECT_BIAS;
 	}
 
-	if (distance < data->dist) {
-		if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
-			float vec[3];
+	if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
+		float vec[3];
 
-			interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
-			if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) {
-				data->dist = distance;
-				data->edge_nearest = eed;
-			}
+		interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac);
+		if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) {
+			return;
 		}
-		else {
-			data->dist = distance;
-			data->edge_nearest = eed;
+	}
+
+	if (dist_test_bias < data->hit.dist_bias) {
+		data->hit.dist_bias = dist_test_bias;
+		data->hit.dist = dist_test;
+		data->hit.index = index;
+		data->hit.edge = eed;
+	}
+
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list