[Bf-blender-cvs] [45b764e95b9] master: 3D View: new nethod of opengl selection

Campbell Barton noreply at git.blender.org
Wed Mar 8 20:23:33 CET 2017


Commit: 45b764e95b9e34cb17dece1cd37eb80dafa1924f
Author: Campbell Barton
Date:   Thu Mar 9 05:17:55 2017 +1100
Branches: master
https://developer.blender.org/rB45b764e95b9e34cb17dece1cd37eb80dafa1924f

3D View: new nethod of opengl selection

Intended to replace legacy GL_SELECT, without the limitations of
sample queries which can't access depth information.

This commit adds VIEW3D_SELECT_PICK_NEAREST and VIEW3D_SELECT_PICK_ALL
which access the depth buffers to detect whats under the pointer,
so initial selection is always the closest item.

The performance of this method depends a lot on the OpenGL
implementations glReadPixels.

Since reading depth can be slow, buffers are cached for object picking
so selecting re-uses depth data, performing 1 draw instead of 3
(for 24, 18, 10 px regions, picking with many items under the pointer).

Occlusion queries draw twice when picking nearest,
so worst case 6x draw calls per selection.

Even with these improvements occlusion queries is faster on AMD hardware.

Depth selection is disabled by default, toggle option under select method.
May enable by default if this works well on different hardware.

Reviewed as D2543

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

M	release/scripts/startup/bl_ui/space_userpref.py
M	source/blender/editors/armature/armature_select.c
M	source/blender/editors/armature/editarmature_sketch.c
M	source/blender/editors/include/ED_view3d.h
M	source/blender/editors/metaball/mball_edit.c
M	source/blender/editors/space_view3d/view3d_select.c
M	source/blender/editors/space_view3d/view3d_view.c
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/GPU_select.h
M	source/blender/gpu/intern/gpu_select.c
A	source/blender/gpu/intern/gpu_select_pick.c
A	source/blender/gpu/intern/gpu_select_private.h
A	source/blender/gpu/intern/gpu_select_sample_query.c
M	source/blender/makesdna/DNA_userdef_types.h
M	source/blender/makesrna/intern/rna_userdef.c

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

diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index d7f5723539d..cd12255c24c 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -453,6 +453,7 @@ class USERPREF_PT_system(Panel):
         col.separator()
         col.label(text="Selection")
         col.prop(system, "select_method", text="")
+        col.prop(system, "use_select_pick_depth")
 
         col.separator()
 
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index ec0f193e780..3a0d07c02ee 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -177,7 +177,7 @@ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel)
 	rect.xmin = rect.xmax = xy[0];
 	rect.ymin = rect.ymax = xy[1];
 	
-	hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
+	hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
 
 	if (hits > 0)
 		return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true);
@@ -279,7 +279,7 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
 /* note that BONE ROOT only gets drawn for root bones (or without IK) */
 static EditBone *get_nearest_editbonepoint(
         ViewContext *vc, const int mval[2],
-        ListBase *edbo, bool findunsel, int *r_selmask)
+        ListBase *edbo, bool findunsel, bool use_cycle, int *r_selmask)
 {
 	bArmature *arm = (bArmature *)vc->obedit->data;
 	EditBone *ebone_next_act = arm->act_edbone;
@@ -290,6 +290,7 @@ static EditBone *get_nearest_editbonepoint(
 	unsigned int hitresult, besthitresult = BONESEL_NOSEL;
 	int i, mindep = 5;
 	short hits;
+	static int last_mval[2] = {-100, -100};
 
 	/* find the bone after the current active bone, so as to bump up its chances in selection.
 	 * this way overlapping bones will cycle selection state as with objects. */
@@ -303,12 +304,33 @@ static EditBone *get_nearest_editbonepoint(
 		ebone_next_act = NULL;
 	}
 
+	bool do_nearest = false;
+
+	/* define if we use solid nearest select or not */
+	if (use_cycle) {
+		if (vc->v3d->drawtype > OB_WIRE) {
+			do_nearest = true;
+			if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
+				do_nearest = false;
+			}
+		}
+		copy_v2_v2_int(last_mval, mval);
+	}
+	else {
+		if (vc->v3d->drawtype > OB_WIRE) {
+			do_nearest = true;
+		}
+	}
+
+	const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+
+	/* TODO: select larger region first (so we can use GPU_select_cache) */
 	BLI_rcti_init_pt_radius(&rect, mval, 5);
+	hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
 
-	hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
 	if (hits == 0) {
 		BLI_rcti_init_pt_radius(&rect, mval, 12);
-		hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
+		hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
 	}
 	/* See if there are any selected bones in this group */
 	if (hits > 0) {
@@ -434,7 +456,7 @@ bool ED_armature_select_pick(bContext *C, const int mval[2], bool extend, bool d
 		return true;
 	}
 
-	nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, true, &selmask);
+	nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, true, true, &selmask);
 	if (nearBone) {
 
 		if (!extend && !deselect && !toggle) {
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 8690072ca85..bba486bc65c 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -1909,7 +1909,7 @@ static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], c
 
 	BLI_rcti_init_pt_radius(&rect, mval, 5);
 
-	hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
+	hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
 
 	if (hits > 0) {
 		int besthitresult = -1;
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 5514dc0d3df..af6f37d937c 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -302,7 +302,19 @@ bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], con
 /* select */
 #define MAXPICKELEMS    2500
 #define MAXPICKBUF      (4 * MAXPICKELEMS)
-short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, bool do_nearest);
+
+enum {
+	/* all elements in the region, ignore depth */
+	VIEW3D_SELECT_ALL = 0,
+	/* pick also depth sorts (only for small regions!) */
+	VIEW3D_SELECT_PICK_ALL = 1,
+	/* sorts and only returns visible objects (only for small regions!) */
+	VIEW3D_SELECT_PICK_NEAREST = 2,
+};
+
+int view3d_opengl_select(
+        struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input,
+        int select_mode);
 
 /* view3d_select.c */
 float ED_view3d_select_dist_px(void);
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index fff53d6885e..bc42717b69f 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -594,7 +594,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
 
 	BLI_rcti_init_pt_radius(&rect, mval, 12);
 
-	hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
+	hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
 
 	/* does startelem exist? */
 	ml = mb->editelems->first;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 49f24ef634f..0b3468f2c23 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -96,8 +96,12 @@
 
 #include "GPU_draw.h"
 
+#include "GPU_select.h"
+
 #include "view3d_intern.h"  /* own include */
 
+// #include "PIL_time_utildefines.h"
+
 float ED_view3d_select_dist_px(void)
 {
 	return 75.0f * U.pixelsize;
@@ -1091,7 +1095,7 @@ static Base *object_mouse_select_menu(
         bContext *C, ViewContext *vc, unsigned int *buffer, int hits,
         const int mval[2], bool toggle)
 {
-	int baseCount = 0;
+	short baseCount = 0;
 	bool ok;
 	LinkNode *linklist = NULL;
 	
@@ -1236,44 +1240,56 @@ static int mixed_bones_object_selectbuffer(
 
 	do_nearest = do_nearest && !enumerate;
 
+	const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+	int hits = 0;
+
+	/* we _must_ end cache before return, use 'goto finally' */
+	GPU_select_cache_begin();
+
 	BLI_rcti_init_pt_radius(&rect, mval, 14);
-	hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, do_nearest);
+	hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
 	if (hits15 == 1) {
-		return selectbuffer_ret_hits_15(buffer, hits15);
+		hits = selectbuffer_ret_hits_15(buffer, hits15);
+		goto finally;
 	}
 	else if (hits15 > 0) {
 		has_bones15 = selectbuffer_has_bones(buffer, hits15);
 
 		offs = 4 * hits15;
 		BLI_rcti_init_pt_radius(&rect, mval, 9);
-		hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
+		hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
 		if (hits9 == 1) {
-			return selectbuffer_ret_hits_9(buffer, hits15, hits9);
+			hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
+			goto finally;
 		}
 		else if (hits9 > 0) {
 			has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
 
 			offs += 4 * hits9;
 			BLI_rcti_init_pt_radius(&rect, mval, 5);
-			hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
+			hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
 			if (hits5 == 1) {
-				return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
+				hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
+				goto finally;
 			}
 			else if (hits5 > 0) {
 				has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
 			}
 		}
 
-		if      (has_bones5)  return selectbuffer_ret_hits_5(buffer,  hits15, hits9, hits5);
-		else if (has_bones9)  return selectbuffer_ret_hits_9(buffer,  hits15, hits9);
-		else if (has_bones15) return selectbuffer_ret_hits_15(buffer, hits15);
-		
-		if      (hits5 > 0) return selectbuffer_ret_hits_5(buffer,  hits15, hits9, hits5);
-		else if (hits9 > 0) return selectbuffer_ret_hits_9(buffer,  hits15, hits9);
-		else                return selectbuffer_ret_hits_15(buffer, hits15);
+		if      (has_bones5)  { hits = selectbuffer_ret_hits_5(buffer,  hits15, hits9, hits5); goto finally; }
+		else if (has_bones9)  { hits = selectbuffer_ret_hits_9(buffer,  hits15, hits9); goto finally; }
+		else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
+
+		if      (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer,  hits15, hits9, hits5); goto finally; }
+		else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer,  hits15, hits9); goto finally; }
+		else                { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
 	}
-	
-	return 0;
+
+finally:
+	GPU_select_cache_end();
+
+	return hits;
 }
 
 /* returns basact */
@@ -1466,10 +1482,13 @@ static bool ed_object_select_pick(
 		unsigned int buffer[MAXPICKBUF];
 		bool do_nearest;
 
+		// TIMEIT_START(select_time);
+
 		/* if objects have posemode set, the bones are in the same selection buffer */
-		
 		hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
-		
+
+		// TIMEIT_END(select_time);
+
 		if (hits > 0) {
 			/* note: bundles are handling in the same way as bones */
 			const bool has_bones = selectbuffer_has_bones(buffer, hits);
@@ -1908,7 +1927,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
 	unsigned int buffer[MAXPICKBUF];
 	int hits;
 
-	hits = view3d_opengl_

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list