I use glRenderMode (GL_SELECT) to determine which OpenGL object is hit when handling a mouse double click event. I want to extend its usage to mouse moving events. However, to make the rendering context available for glRenderMode (GL_SELECT), I have to redraw the screen in the mouse moving handler. It’s quite expensive. Even the mouse moves for a short distance, the screen can be easily redrawn hundreds of times. Am I doing in a right way? Is there a better way to achieve the same purpose? Any help is much appreciated.
Well, graphics programs typically redraw the screen constantly anyway, so it’s not a huge deal.
One thing you might try is just setting a boolean in your mouse handler, and then if the boolean is set the next time you call display(), deal with it then (and unset it).
The thing is that lots of stuffs are drawn in my case. Performance is a concern. I only need to hit-test a very small percentage of the total stuffs. I wonder whether I can set up a second rendering context and then use it for hit testing. Is it feasible?
Performance is a concern.
If performance were truly a concern, you would not use glRenderMode(GL_SELECT) to begin with. This is almost always implemented in software, so you shouldn’t expect it to be performant.
I totally agree with Korval, if you want to achieve the performance
i guess color ID apporach will be better where you render every object in the scene with unique color(RGB) in your back buffer and while mouse move get pixel color for (XY) and identify corresponding geometry.
I am not familiar rendering objects in the back buffer. Did you mean to render things after buffers gets swapped?
Then how to get pixel color for a screen location (XY)? Can you provide the OpenGL command and I will look into it? Thanks for any further help.
In a double-buffered context, you’re rendering into GL_BACK by default. SwapBuffers takes the rendered image and sends it to the front (screen) buffer.
The commands you want are glReadBuffer and glReadPixels.
You could do a ray intersect test.
Cast a ray from the eye (camera), through the mouse position (projected onto the near clip plane), into the world - look for the object with the closest intersection point.
All of this info is available on mouse move messages and doesn’t require a redraw.
To make it easier, you could also read the depth buffer value at the mouse position to get the depth, now you have a 3D world coord to check.
I recommend the hit-test rendering buffer. I use it in a 2D, non OpenGL, scenario.
It allows for high performance mouse interrogation.
For example: What should the current mouse cursor be? Often the mouse cursor is expected to reflect the intractability of the object it is currently over. If the mouse passes over an object that can be selected, the mouse cursor changes to reflect that. What if the mouse passes over an object that is already selected? Again the mouse cursor changes to reflect that. If the mouse is over empty space? Yep, mouse cursor changes to reflect that too.
What about tooltips? (the little text boxes that pop up when a mouse hovers over an object)
All that stuff requires that you interrogate the scene on events that can be as trival as mouse movements.
You don’t want to perform complex geometry equations on every mouse move. Not when the number of geometric objects that have to be tested is unlimited.
Looking up a pixel value in a saved “hit test” rendering image is fast, trivial and doesn’t slow down in situations that have large numbers of objects.
The challenging part of implementing a hit test image is: Knowing when to redraw it. The main view’s image may be redrawn constantly, but the hit test image doesn’t have to be.