Reputation: 572
I would like to implement scene picking (for mouse clicks, moves, etc.). What is the best, fastest way? I used to use glSelectBuffer
and glRenderMode
with GL_SELECT
and then render whole scene again (of course with boost, without textures, heavy shaders, etc.).
It's too slow render recursively all nodes and geometries for one number (geometry ID) on every mouse click, move and drag. Does anybody know better way?
EDIT: Solution with reading depth buffer seems fain, but what if I don't want to pick some geometries and they are already drown to buffer? Finding box which contains point can be imprecisely, since point can be in multiple boxes.
Is it possible to write into two frame buffers, depth buffers in one draw? Then I can write geometry id to one buffer through shader. And what about speed?
Upvotes: 3
Views: 19392
Reputation: 96
Since I'm new here, I can't answer Joe directly so I'll do it here. I never tried his way of doing this, so I'm not sure if it will work for you. Hopefully it will, if not: I'll give you my version. There are a number of ways you can do it. Rendering the whole scene again seems like an overkill.
The way I do it is an OBB-Ray intersection test. You consider Object-Oriented Bounding Boxes around your geometry and detect if they collide with the ray coming from you mouse click. If you need less precision I'd say go for AABB or even Sphere. More precision: convex hull. Just be aware of the fact that the less precision you ask for, the faster the algorithm. It might be an overkill but consider using a physics library for accelerated calculation like Bullet or PhysX if you don't want to implement the algoritms yourself. And another way is an OpenGL hack which I haven't used before.
All these ways to do it are explained here: http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/
Upvotes: 6
Reputation: 1619
In the past I've used glReadPixels( xf, yf, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &zf);
to read the value of the depth buffer at a point (xf, yf) in screen space.
You can then unproject this point back into world coordinates (multiply by the inverse of the modelview and projection matrices.
This can be done with gluUnProject
provided you're happy including the GLU library in your application.
This gives you a coordinate, you then need to search through your objects to find one that has a bounding box that contains this coordinate. This object is the one selected.
I'd recommend searching for information on Unprojecting if you want more information about this, also https://www.opengl.org/archives/resources/faq/technical/selection.htm is helpful (and suggests other techniques you could use).
Upvotes: 5