
Selection/Picking
Posted Thursday, 17 January, 2008 - 13:40 by djk inBackground:
Over the last 20 years I have been using the Hoops3d graphics system from TechSoft to provide rendering and graphical selection of objects in a large engineering application. My last foray into OpenGl was 15 years ago on an SGI Onyx using the GLUT framework to render a simulation there was no picking required.
I have recently started with a new company that is chartered to create a similar engineering system as open source using the .Net framework. The requirements have lead us to OpenGL and the OpenTK GlControl has risen to the top of the list from the 3-4 open source C# OpenGl controls evaluated.
In the Hoops3d system one would apply a filter to the segment tree (scene graph) to specify what you were going to select, ie whole object, face of a shell, line/edge, or vertex. Every graphical item had a key which could be remapped to a reference to the object that generated it. Thus when you selected an item you accessed the key to get the underlying object to operate on.
Question:
I have tried to port several picking implementations from other C/C++ projects to the OpenTK GlControl without success, I am sure the issue is with my inability to get my head wrapped around the OpenGL picking model. Does anyone have an example app built on OpenTk's GlControl that implements picking that they would be willing to share?
thanks
djk
| Attachment | Size |
|---|---|
| SelectionExample.zip | 87.83 KB |


Comments
static int[]
You have to call GL.LoadName(id) before drawing each object.
You cannot call GL.LoadName inside a GL.Begin() and GL.End(), so you have to break the drawing up.
Thanks, that gets me a lot
Thanks, that gets me a lot closer.
However every selection seems to get the same id and distance reguardless of where on the screen that I select and one of the transforms is getting whacked.
I added a small MDI demo to the original post, that contains the view I am working on. The select method you posted is in the Graphic3dView.cs file. If you have a few minutes to point me in the right direction I would appreciate it. The Tools->CreateCube menu item creates 2 display lists one a cube and one a cylinder. Click on Tools->Select to activate selections on LeftMouseDown events.
Also, if anyone is interested, the ArcBall view transform tool that was posted to codeproject a couple weeks ago has been integrated into this view. I am planning on migrating the basic vector,matrix, quat contained in arcball.cs to use the OpenTk.Math versions.
djk
Change the line above
Change the line above
to
I have not verified that that will fix it, but it is a start.
public int
thanks for your help, your suggestion allowed the selection to pick the right object, however I had add the GL code to rebuild the viewport and perspective before returning so that the render would redraw correctly.
djk
Many thanks for sharing your
Many thanks for sharing your code, I'll add a new picking example for the next version. :)
Here is more robust code
Here is more robust code that preserves the projection matrix.
Thanks for the update it
Thanks for the update it makes more sense than my brute force attempt.
If anyone is looking at the sample there is a line in the overriden OnLoad in Graphics3dView.cs
That is causing all the events to be fired twice for mouse operations, just remove it. The constructor above that line is already adding the glControl to its collection.
again thanks for your help. I have now integrated it back into our framework for testing.
djk
Re: Selection/Picking
The example program is great and it's nice to have something to play with to get to understand how it works. I've been trying to learn how to implement OpenGL picking in my project through following this example program and referencing the 'net about some things I don't understand, but I'm afraid it's still a bit too involved for a noob like myself.
Can someone post a very simple implementation of picking with comments describing the process?
Re: Selection/Picking
Have you taken a look at http://www.glprogramming.com/red/chapter13.html ?
Re: Selection/Picking
No, but I'll read it thoroughly. It looks like it will fill me in on how it works.
Thanks!
Re: Selection/Picking
If that does not do it for you, let us know.
Re: Selection/Picking
There is also another, very easy and efficient way which should work not only with OpenGL. This method uses Unique Color IDs and is also described in the RedBook.
So how does it work?
From Lighhouse:
The color coding scheme does not require any perspective changes and therefore it is simpler in theory. Just define a rendering function where the relevant objects (pickable and occluders) are assigned each a different color. When the user clicks the mouse over the scene, render the scene on the back buffer, read back the selected pixel from the back buffer and check its color. The process is completely transparent to the user because the buffers are not swapped, so the color coding rendering is never seen.
You can find some nice tutorials here:
http://gpwiki.org/index.php/OpenGL_Selection_Using_Unique_Color_IDs
and here:
http://www.lighthouse3d.com/opengl/picking/index.php3?color1
The colour-coded method also has some drawbacks:
But is has a main advantage, it should be significant faster than the deprecated OpenGL Selection mode. The GL_SELECT method is done in software (!) and the colour-coded picking is just an extra render pass (in hardware) without light & stuff.
I implemented this method some time ago in a CAD/CAM system which could have a lot of pickable objects. For that I used the aux buffer.
Using the colour-coded picking was almost 4 times faster than the OGL Selection mode. And I also heared that GL_SELECT will be dropped in OGL 3.0.
There are also some discussions about that on the web. For example:
http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Numb...
And these are not the only methods for picking (Ray-Intersection test, ...).
If someone is interessed, I can do a little example for colour-coded picking?
Where can I find the OpenTK example for GL_SELECT, so I can use it as a starter?
Re: Selection/Picking
You folks are awesome!
JTalton, thanks.
teichgraf, CAD/CAM sounds right up my alley. I built a CNC mill by hand. It took forever to get the parts close enough. The machine works, but the controller board doesn't anymore... needs a new one. It would be awesome to contribute to open source CAD/CAM development... then when I get a new controller board the machine could come to life better than before!
Anyhow, I think I'm stuck to using the picking technique because the UI needs to allow the user to click and drag a box around a section of the view-port, which needs to return objects at a depth. I'm still looking into getting it implemented. Apparently, the picking method has an improvement over the selection method in that it only "draws" the objects that are within the tolerance of the point of reference.
Re: Selection/Picking
teichgraf: If someone is interessed, I can do a little example for colour-coded picking?
I would be interested. :)
Re: Selection/Picking
I would be very interested, and I was the one who started this thread.
Our application is essential a CAD Product Model system where I need to "pick/select" whole objects, faces of a solid, edges of a face and finally the vertex of the edges.
I never got past the selection of the whole object with the code contained in the example I provided at the top of the thread.
I am back working on the graphics aspects of the application for the next two weeks, so this is a very timely offer.
djk
Re: Selection/Picking
Ok, I have a bunch of noob questions, if someone is willing to help me harvest the spoils of OpenGL.
Why is it necessary to save the current transformation state to later recall it?
Why couldn't the existing matrix be applied to the selection/picking method?
With the transformations already applied to the existing matrix, it makes little sense to me to have to create a new one for drawing the selection to.
The SelectBuffer, the array that the GL.SelectBuffer method requires for writing hits to, how does this SelectBuffer work? The examples are confusing when they start out with the 1st value without a name. How does the name get there and why doesn't it have a name? Why add a hit to the buffer if it has no reference to it?
An one last one to help me figure out where I'm at: Is it appropriate to ask these questions? I mean, maybe I should have picked up this stuff through all the reading, gack!
Can't call this method until this... can't do this before this... need this before this...
Maybe I'm thinking about it too hard and the answers are really only obvious.
Re: Selection/Picking
You save off the current projection matrix.
Then you clear the projection matrix with LoadIdentity().
Then you initialize the matrix with your Glu.PickMatrix(x, y, 0.001f, 0.001f, viewport);
- The 0.001f here is actuall used to create a small area. You can put in bigger values to pick a region about the x, y point.
You then multiple that matrix times the original projection matrix
Which gives you a pick matrix for the area you want using the correct projection matrix.
Not sure about the examples added the 1st hit value without a name.
You have to call GL.LoadName(id) before drawing each object.
You cannot call GL.LoadName inside a GL.Begin() and GL.End(), so you have to break the drawing up.
4 values are put in the selction buffer for each object in the area specified by your projection matrix. (using the PickMatrix)
The distance is at an offset of 1. uint distance = (uint)selectBuffer[i * 4 + 1];
The object id is at the offset of 3. selectedId = (int)selectBuffer[i * 4 + 3];
Re: Selection/Picking
I have written a little OpenTK example based on a OpenTK WinForms example. You can download the source file "W05_Picking" here or as a SVN patch from here.
Usage:
Click on a sphere to select it. Press [C] to see the rendered color-index image, which is used for this technique.
The whole "magic" happens in the methods
DoPickingandDrawColorIds:Not that much. ;-)
There are a lot of improvements which could be done:
...
Re: Selection/Picking
I'm lost in the sauce with the matrix push/pop and transformations. I just don't understand what's going on there. Here's the chunk of code that I'm working on that pertains to rendering and picking. I'm trying to output the hits to the listbox object in this form; although, ultimately, I'll be doing something with the data that goes into the listbox... it would be nice to see the listbox provide some kind of info if I'm headed in the right direction.
Re: Selection/Picking
Technolithic in your render code it does not look like you are loading names with Gl.PushName(id) for each entity when you are drawing for select.
The only name in your code is the id zero and everything is drawn associated with that name.
djk
Re: Selection/Picking
Thanks, djk, good point. I changed the GL.LoadName(n) to GL.PushName(n), still nothing shows up in the ListBox.
I don't know if all that matrix transformation is correct, but when it renders in the window it displays the objects correctly.
Re: Selection/Picking
Sorry, I missed the fact that you had a LoadName on one DrawVertex call.
The only two things I can think of is that the SwapBuffers might need to be after the rendering code, and at some point I put a Flush command.
[Edit] I should probably point out that I have only recently come back to openGL after more than 20 years working with Hoops3d graphics, its been tough getting the hang of OpenGL's model and project matricies again. I still find myself going in circles because I mixed Hoops and OpenGL concepts.
Re: Selection/Picking
Thanks for the example.
Re: Selection/Picking
teichgraf, I had to make a couple changes to get the code to compile, not sure if its VS2005/VS2008 differences or not.
I think I finally get this method for selection. It just seemed so foreign a concept to me for 3d object selection. I can easily see how to extend it to select multiple object using shift/control key modifiers.
What's not obvious is how to implement selecting all the objects within an windowed selection? Do I need to iterate through all the pixels within the bounding box of the selection window and find all the unique colored pixels or is there a better aproach?
djk
Re: Selection/Picking
djk, I tried out your suggestion with calling swap buffers after the rendering method as well as calling flush before I start processing hits, but the result is the same.
It is a lot of concepts to apply before the code actually provides a clue about how the solution is progressing, good or bad. I'll keep looking for the solution. After I figure this beast out, I might just write my own "how to" technical document. I think just write about the simplest implementation describing every step and what's really going on underneath.
A good sub-title, "for the noob by the noob". Sounds like a good moto for something bigger, LOL
Re: Selection/Picking
Technolithic, I spent a fair bit of time playing with the example that teichgraf provided yesterday, and it makes alot of sense now that I see it in operation.
I mod'd his example to allow multiple selections with very liitle effort. I will be using it as model and changing out the selection mechanism in our project next week. I think I can hit all the remaining use cases that I deferred with much less effort than with the original mehod.
Fiddler, maybe there should be a 'OpenGL Techniques the OpenTk way' under under the Discussion topic, or would you prefer they be under the 'OpenTK -> Support or Tutorial' topics?
Re: Selection/Picking
OpenTK->Tutorials is meant for topics such as these. I think the fewer forums, the better - they might be too many of them even now.
Re: Selection/Picking
djk:teichgraf, I had to make a couple changes to get the code to compile, not sure if its VS2005/VS2008 differences or not.
That's right, I've written the example using Visual C# Express 2008 with some features from C# 3.0 (automatic properties).
djk:[...] Do I need to iterate through all the pixels within the bounding box of the selection window and find all the unique colored pixels [...]
That should work.
@djk:
By the way, I would be interessed to see your open source engineering system. Is there a URL?
Re: Selection/Picking
teichgraf, the Framework to our system is known as TurksHead. The framework is open source (LPGL), and we are hopefully nearing the end of all the corporate paperwork to expose the source repository. While the company has supported the OSS concept without issue, they have a very strict set of procedures for IT security and they are helping us get setup so we don't create vulnerabilities or risk. When we go live I will post a link under the projects topic.
TurksHead provides what we call a smart product model, which in essence is the organization and attribution of an engineering model of a concept or design. The "smart" in the framework is provided by a variety of simulation tools on which domain specific simulations can be built. Examples of domain specific simulations would be ship hydrostatics calculation or simulation of six degree of freedom ship motions.
We do build commercial applications and applications for hire on this framework, this first commercial product can be scene at http://orca3d.com/.
Re: Selection/Picking
I finally got it to work with quite a bit of discussion with my Professor in how the various matrices work.
After reading all the tutorials, I find that I must have been missing something.
It's challenging (and time-consuming) to write a good technical document that produces all the answers. In interest in helping to fill the gap between technology and humanity, I'm curious to find out if there's a decent career to be made in producing documents that bring more people into the realm of technology, specifically in the open-source community.
Now that selection/picking is incorporated into my application, a new obstacle remains. Something with creating custom events and using delegates to get the information obtained in one object, subclass, back to another object, base class, using event firing to tell the base class object that it's time to call a method to return the data contained in the subclass. Perhaps this is a new topic or maybe it isn't technically related to this forum at all.
I've looked at tons of tutorials on the net, but I can't seem to wrap my brain around the idea. It seems that it's so simple that ample explanation is beyond the scope of the concept.