[Bf-blender-cvs] [0626d27] master: Editmesh select nearest fixes

Campbell Barton noreply at git.blender.org
Mon Apr 20 17:51:53 CEST 2015


Commit: 0626d27bf62e41bf34191d011fe0e52a4c622ec6
Author: Campbell Barton
Date:   Tue Apr 21 01:33:09 2015 +1000
Branches: master
https://developer.blender.org/rB0626d27bf62e41bf34191d011fe0e52a4c622ec6

Editmesh select nearest fixes

- distance from edge check wasn't clamping 0-1
- vertex bias wasn't taking pixelsize into account.
- index & pass counter were floats

Also some improvements

- use BMesh lookup tables when available.
- use structs to avoid issues getting out of sync.

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

M	source/blender/bmesh/intern/bmesh_mesh.c
M	source/blender/bmesh/intern/bmesh_mesh.h
M	source/blender/editors/mesh/editmesh_select.c

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

diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 9a2869b..ba08f9e 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -1379,6 +1379,41 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index)
 	return BLI_mempool_findelem(bm->fpool, index);
 }
 
+/**
+ * Use lookup table when available, else use slower find functions.
+ *
+ * \note Try to use #BM_mesh_elem_table_ensure instead.
+ */
+BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index)
+{
+	if ((bm->elem_table_dirty & BM_VERT) == 0) {
+		return (index < bm->totvert) ? bm->vtable[index] : NULL;
+	}
+	else {
+		return BM_vert_at_index_find(bm, index);
+	}
+}
+
+BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index)
+{
+	if ((bm->elem_table_dirty & BM_EDGE) == 0) {
+		return (index < bm->totedge) ? bm->etable[index] : NULL;
+	}
+	else {
+		return BM_edge_at_index_find(bm, index);
+	}
+}
+
+BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index)
+{
+	if ((bm->elem_table_dirty & BM_FACE) == 0) {
+		return (index < bm->totface) ? bm->ftable[index] : NULL;
+	}
+	else {
+		return BM_face_at_index_find(bm, index);
+	}
+}
+
 
 /**
  * Return the amount of element of type 'type' in a given bmesh.
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index bac5da8..59feea2 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -68,6 +68,10 @@ BMVert *BM_vert_at_index_find(BMesh *bm, const int index);
 BMEdge *BM_edge_at_index_find(BMesh *bm, const int index);
 BMFace *BM_face_at_index_find(BMesh *bm, const int index);
 
+BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index);
+BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index);
+BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index);
+
 // XXX
 
 int  BM_mesh_elem_count(BMesh *bm, const char htype);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 403a80e..80b60c4 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -350,23 +350,42 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
 	
 }
 
+
+/* -------------------------------------------------------------------- */
+
+/** \name Find Nearest Vert/Edge/Face
+ * \{ */
+
+#define FIND_NEAR_THRESHOLD_MIN 3
+
+struct NearestVertUserData {
+	float mval_fl[2];
+	int pass;
+	char hflag_select;
+	bool is_strict;
+	float dist;
+	int index_last;
+	int index_nearest;
+	BMVert *vert_nearest;
+};
+
 static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index)
 {
-	struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } *data = userData;
+	struct NearestVertUserData *data = userData;
 
 	if (data->pass == 0) {
-		if (index <= data->lastIndex)
+		if (index <= data->index_last)
 			return;
 	}
 	else {
-		if (index > data->lastIndex)
+		if (index > data->index_last)
 			return;
 	}
 
-	if (data->dist > 3) {
+	if (data->dist > FIND_NEAR_THRESHOLD_MIN) {
 		float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
-		if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->select) {
-			if (data->strict == 1) {
+		if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->hflag_select) {
+			if (data->is_strict == true) {
 				return;
 			}
 			else {
@@ -376,8 +395,8 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, const float
 
 		if (dist_test < data->dist) {
 			data->dist = dist_test;
-			data->closest = eve;
-			data->closestIndex = index;
+			data->vert_nearest = eve;
+			data->index_nearest = index;
 		}
 	}
 }
@@ -402,6 +421,8 @@ BMVert *EDBM_vert_find_nearest(
         ViewContext *vc, float *r_dist,
         const bool use_select_bias, const bool is_strict)
 {
+	BMesh *bm = vc->em->bm;
+
 	if (V3D_IS_ZBUF(vc->v3d)) {
 		float distance;
 		unsigned int index;
@@ -418,7 +439,7 @@ BMVert *EDBM_vert_find_nearest(
 			        0, NULL, NULL);
 		}
 		
-		eve = index ? BM_vert_at_index_find(vc->em->bm, index - 1) : NULL;
+		eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
 		
 		if (eve && distance < *r_dist) {
 			*r_dist = distance;
@@ -427,26 +448,26 @@ BMVert *EDBM_vert_find_nearest(
 		else {
 			return NULL;
 		}
-			
 	}
 	else {
-		struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } data;
-		static int lastSelectedIndex = 0;
-		static BMVert *lastSelected = NULL;
-		
-		if (lastSelected && BM_vert_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) {
-			lastSelectedIndex = 0;
-			lastSelected = NULL;
+		struct NearestVertUserData data;
+
+		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))) {
+			prev_select_index = 0;
+			prev_select_elem = NULL;
 		}
 
-		data.lastIndex = lastSelectedIndex;
+		data.index_last = prev_select_index;
 		data.mval_fl[0] = vc->mval[0];
 		data.mval_fl[1] = vc->mval[1];
-		data.select = use_select_bias ? BM_ELEM_SELECT : 0;
+		data.hflag_select = use_select_bias ? BM_ELEM_SELECT : 0;
 		data.dist = *r_dist;
-		data.strict = is_strict;
-		data.closest = NULL;
-		data.closestIndex = 0;
+		data.is_strict = is_strict;
+		data.vert_nearest = NULL;
+		data.index_nearest = 0;
 
 		data.pass = 0;
 
@@ -454,23 +475,30 @@ BMVert *EDBM_vert_find_nearest(
 
 		mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
 
-		if (data.dist > 3) {
+		if (data.dist > FIND_NEAR_THRESHOLD_MIN) {
 			data.pass = 1;
 			mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
 		}
 
 		*r_dist = data.dist;
-		lastSelected = data.closest;
-		lastSelectedIndex = data.closestIndex;
+		prev_select_elem = data.vert_nearest;
+		prev_select_index = data.index_nearest;
 
-		return data.closest;
+		return data.vert_nearest;
 	}
 }
 
+struct NearestEdgeUserData {
+	ViewContext vc;
+	float mval_fl[2];
+	float dist;
+	BMEdge *edge_nearest;
+};
+
 /* 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))
 {
-	struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } *data = userData;
+	struct NearestEdgeUserData *data = userData;
 	int distance;
 
 	distance = dist_to_line_segment_v2(data->mval_fl, screen_co_a, screen_co_b);
@@ -481,26 +509,26 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float
 
 	if (distance < data->dist) {
 		if (data->vc.rv3d->rflag & RV3D_CLIPPING) {
-			float lambda = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
+			float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b);
 			float vec[3];
 
-			vec[0] = eed->v1->co[0] + lambda * (eed->v2->co[0] - eed->v1->co[0]);
-			vec[1] = eed->v1->co[1] + lambda * (eed->v2->co[1] - eed->v1->co[1]);
-			vec[2] = eed->v1->co[2] + lambda * (eed->v2->co[2] - eed->v1->co[2]);
-
+			CLAMP(fac, 0, 1);
+			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->closest = eed;
+				data->edge_nearest = eed;
 			}
 		}
 		else {
 			data->dist = distance;
-			data->closest = eed;
+			data->edge_nearest = eed;
 		}
 	}
 }
+
 BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
 {
+	BMesh *bm = vc->em->bm;
 
 	if (V3D_IS_ZBUF(vc->v3d)) {
 		float distance;
@@ -510,7 +538,7 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
 		view3d_validate_backbuf(vc);
 		
 		index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL);
-		eed = index ? BM_edge_at_index_find(vc->em->bm, index - 1) : NULL;
+		eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
 		
 		if (eed && distance < *r_dist) {
 			*r_dist = distance;
@@ -521,27 +549,42 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
 		}
 	}
 	else {
-		struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } data;
+		struct NearestEdgeUserData data;
 
 		data.vc = *vc;
 		data.mval_fl[0] = vc->mval[0];
 		data.mval_fl[1] = vc->mval[1];
 		data.dist = *r_dist;
-		data.closest = NULL;
+		data.edge_nearest = NULL;
 		ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
 
 		mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN);
 
 		*r_dist = data.dist;
-		return data.closest;
+		return data.edge_nearest;
 	}
 }
 
-static void findnearestface__getDistance(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
+struct NearestFaceUserData_ZBuf {
+	float mval_fl[2];
+	float dist;
+	const BMFace *face_test;
+};
+
+struct NearestFaceUserData_Closest {
+	float mval_fl[2];
+	int pass;
+	float dist;
+	int index_last;
+	int index_nearest;
+	BMFace *face_nearest;
+};
+
+static void findnearestface__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
 {
-	struct { float mval_fl[2]; float dist; BMFace *toFace; } *data = userData;
+	struct NearestFaceUserData_ZBuf *data = userData;
 
-	if (efa == data->toFace) {
+	if (efa == data->face_test) {
 		const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
 
 		if (dist_test < data->dist) {
@@ -549,32 +592,35 @@ static void findnearestface__getDistance(void *userData, BMFace *efa, const floa
 		}
 	}
 }
+
+
 static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index)
 {
-	struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } *data = userData;
+	struct NearestFaceUserData_Closest *data = userData;
 
 	if (data->pass == 0) {
-		if (index <= data->lastIndex)
+		if (index <= data->index_last)
 			return;
 	}
 	else {
-		if (index > data->lastIndex)
+		if (index > data->index_last)
 			retur

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list