OpenGL GL_SELECT or manual collision detection?

Ashika Umanga Umagiliya picture Ashika Umanga Umagiliya · Oct 28, 2010 · Viewed 9.5k times · Source

As seen in the image

http://oi56.tinypic.com/ifu33k.jpg

I draw set of contours (polygons) as GL_LINE_STRIP. Now I want to select curve(polygon) under the mouse to delete,move..etc in 3D .

I am wondering which method to use:

1.use OpenGL picking and selection. ( glRenderMode(GL_SELECT) )

2.use manual collision detection , by using a pick-ray and check whether the ray is inside each polygon.

Answer

Kos picture Kos · Oct 30, 2010

I strongly recommend against GL_SELECT. This method is very old and absent in new GL versions, and you're likely to get problems with modern graphics cards. Don't expect it to be supported by hardware - probably you'd encounter a software (driver) fallback for this mode on many GPUs, provided it would work at all. Use at your own risk :)

Let me provide you with an alternative.

For solid, big objects, there's an old, good approach of selection by:

  • enabling and setting the scissor test to a 1x1 window at the cursor position
  • drawing the screen with no lighting, texturing and multisampling, assigning an unique solid colour for every "important" entity - this colour will become the object ID for picking
  • calling glReadPixels and retrieving the colour, which would then serve to identify the picked object
  • clearing the buffers, resetting the scissor to the normal size and drawing the scene normally.

This gives you a very reliable "per-object" picking method. Also, drawing and clearing only 1 pixel with minimal per-pixel operation won't really hurt your performance, unless you are short on vertex processing power (unlikely, I think) or have really a lot of objects and are likely to get CPU-bound on the number of draw calls (but then again, I believe it's possible to optimize this away to a single draw call if you could pass the colour as per-pixel data).

The colour in RGB is 3 unsigned bytes, but it should be possible to additionally use the alpha channel of the framebuffer for the last byte, so you'd get 4 bytes in total - enough to store any 32-bit pointer to the object as the colour.

Alternatively, you can create a dedicated framebuffer object with a specific pixel format (like GL_R32UI, or even GL_RG32UI if you need 64 bits) for that.

The above is a nice and quick alternative (both in terms of reliability and in implementation time) for the strict geometric approach.