Help with selection/picking (mouse based)???

hi…
I am currently working on a drawing application using openGL and C#…this might sound silly but having a nightmare trying to grasp concept of selection/picking…
please explain the concept pushing data to name stack and manipulating the data all examples that I have seen just print the contents of the name stack…how this data is actually used

please suggest links/tutorials (better if in C#)
thanks :frowning:

Ali, you are better of by implementing a simple picking system based on bounding boxes or oclusion queries. Teh GL picking is a deprecated, not-accelerated system with many shortcomings.

Search Google, first 10 lines are pretty close to what you need.

http://www.google.com/search?hl=en&q=opengl+picking&btnG=Search

Don’t worry about name stack, you don’t have to use it. It can only help you identify complicated hierarchical objects.
For simple scenes, call to glLoadName() is enough.

@Zengar Where did you read that GL picking is deprecated?

I meant “deprecated” :slight_smile: Just like the feedback mode, evaluators, convolution and some other things. AFAIK no consumer hardware driver accelerates it. It is clumsy, it is slow and apparently noone cares about it. This is enough reason to consider a feature deprecated.

thanks for the replies…and yes i know google exists :slight_smile:
my application will be drawing 2D(later 3D) objects…the user will be able to select any edge of a polygon and move it around/modify it…
I am still confused with the idea of drawing/redrawing in selection mode because in most cases my scene will be rendered before the user will select any part of it …for example i draw a polygon using GL_LINE_LOOP I select an edge how will it be redrawn…

You have to store all the information about your scene (DataModel) in your last render-to-screen invocation.
When user picks (mouse click event) somewhere.
You have to enable selection mode and run your scene update function again. In this case no real rendering is done. It is pretty fast.
You can reuse the same rendering function in 2 places.
for real render and for picking.
But beware (I’m not sure about C#) but the picking functions that is called from Event dispatcher must be done in the same thread that rendered the scene. Another threads don’t have the OpenGL context current.
Another way for you is to use stencil buffer. If the number of your objects is less then 255 then you can store something like ObjectID in stencil, then during picking you can read very small region from this buffer (like 4x4 pixels) and check the object id.

Another way:
If you have only lines, then you can do it in your own code like Zengar suggested. Just implement algo that intersects line with small box under mouse cursor. Call it for all lines and you get all picked candidates.

@Zengar I don’t thing it is deprecated. There must some accelerated way to get back the transformed vertices. See
brand new extension GL_NV_transform_feedback. The selection inside driver can use this ext to be fully accelerated. If you use vertex programs you cannot compute bounding box (yes you can but you have to emulate the vertex program that is not so easy.

@mfort: A nvidia employee confirmed that this feature is fully software. Mainly because it has nothing to do in general 3D API. It could be accelerated using occlusion queries, but as I said noone cares about it :slight_smile:

For selectin objects in 3D you can use gluUnproject() function (check it’s documentation for details).

hey
i am drawing a polygon using GL_LINE_LOOP…
but face a strange problem…when i click around the drawing no hits are recorded however hits are recorded in an another area of the screen
…i have checked the code 3-4 times…values that are being passed to gluPickMatrix() are valid and hits should be recorded…
I have seen various examples for guidance and cannot figure out what could be the problem?

thanks

when i click around the drawing no hits are recorded however hits are recorded in an another area of the screen
I guess can two reasons

1)your screen point input requires some offset adjustment and may not be relatively correct.
Thats why you may be getting hits in different areas.

2)During selection are you setting back both modelview and projection back correctly similar to normal rendering mode…?

glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluPickMatrix ((GLdouble) pt->x,(GLdouble)(viewport[3] - pt->y),2.0, 2.0, viewport);
// set the camera settings properly now.

Good Luck,
kumar.k

@Kumar…thanks for the reply
please take a look at my code

glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluPickMatrix ((GLdouble) pt->x,(GLdouble)(viewport[3] - pt->y),2.0, 2.0, viewport);
//after this I use the foolowing lines to code
GL.gluOrtho2D(0.0, 3.0, 0.0, 3.0);
drawPolygon(GL.GL_SELECT);////drwaing func. is called

   GL.glMatrixMode(GL.GL_PROJECTION);
   GL.glPopMatrix();
   GL.glFlush();

hits = GL.glRenderMode(GL.GL_RENDER);
proces****s(hits, buffer) //the hits are processed

I use the following intial settings of viewport etc.

GL.glViewport(0, 0, s.Width, s.Height);
GL.glMatrixMode(GL.GL_PROJECTION);
GL.glLoadIdentity();
GL.gluOrtho2D(0, (double)Width, 0, (double)Height);
GL.glMatrixMode(GL.GL_MODELVIEW);
GL.glLoadIdentity();

thanks

@kumar
Please take a lookat my code

glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluPickMatrix ((GLdouble) x,(GLdouble)(viewport[3] - y),5.0, 5.0, viewport);

GL.gluPickMatrix((double)x,(double) y, 5.0, 5.0, viewport);
GL.gluOrtho2D(0.0, 3.0, 0.0, 3.0);
drawPolygon(GL.GL_SELECT);
GL.glMatrixMode(GL.GL_PROJECTION);
GL.glPopMatrix();
GL.glFlush();

hits = GL.glRenderMode(GL.GL_RENDER);
process(hits, buffer)/////hits are processed

I am using follwoing intial settings of viewport etc.
GL.glViewport(0, 0, Width, Height);
GL.glMatrixMode(GL.GL_PROJECTION);
GL.glLoadIdentity();
GL.gluOrtho2D(0, (double)Width, 0, (double) Height);
GL.glMatrixMode(GL.GL_MODELVIEW);
GL.glLoadIdentity();

come on guys hep is needed urgent

This is a hack, but one I found to be very useful for a quick selection. Use the stencil buffer.

Give each object a unique integer id. When you click on a position in the screen, get the pixel coordinates.

Then, do a glReadPixels from the stencil buffer on that on pixel into a single-element array. That integer will be the unique id. I think it worked rather well. It will however require several passes if you plan to use the stencil buffer for something else later, but it works rather well for a quick and reliable fix.

thanks for the response will stencil buffer as i wish to include 3d drawings in application later?

AND

i have seen an example that uses same parameters for glOrtho2D() in both modes i.e. Render and selection…
will that solve my problem?
thanks

The stencil buffer solution works on 3D drawing. Basically, if it renders to the screen, it gets rendered to the stencil buffer 2D or 3D. So if you render a 3D object behind something, it won’t get drawn to the stencil, but it will work fine for most situation. I used in a 3D application to control a 3D animated person. What I meant with future problems is if you use the stencil buffer for other things like shadows later you need to do a whole other pass. If you aren’t using it, you can ignore that detail for now.

hey…
The hits problem is solved…but I have one more question…
How will selection/picking work when I draw with the help my mouse e.g. clicking at two places two draw a line, since the drawing has to be done in selection mode as well …does the program has to remember all the points
??
thanks

good to knw that you solved your selection problem…

Regarding your latest query on drawing lines with mouse, do you expect to render 2D lines…?, anyways i dont understand the exact line drawing you may be doing for your App with mouse. However to solve your problem you can have two different modes (or) flags which you can enable/disable, one for selection and second for your line rendering or navigation with mouse.

hey
thanks for the reply…
I had the same soloution in mind…well I want to give user option to draw lines, quads etc. by using mouse or a input pad. I am not yet clear about how to keep record of all the points, because the drawing has to be re-drawn in select mode…???

another question if I draw a figure e.g. triangle using a single command (GL_POLYGON or GL_TRIANGLE) can one of it’s edges be selected/picked…if yes how??
thanks for the help