khdani's picture

Color Picking Help

Hello,
I'm trying to implement color picking, I just don't understand how I should draw the scene. I understand that I should disable all lightings and textures but where should I draw the picking-scene? I mean should it be in the Drawing method with all the drawings?

Thank You!


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
objarni's picture

I think you are better off doing you own picking algorithm, than using OpenGL's picking API, because it is so hard to use IMHO :)

If you are talking about brewing your own object picking method using the "one-color-per-object" method, please ignore the rest of this post!!

That said, here are some pointers which I'm reading from the Red Book:

- You should do the selection-buffer drawing when the user clicks the buffer. Doing it every frame is a big waste of time.

- Go into selection mode with GL.RenderMode and GL_SELECT, then redraw the scene, using the GL.LoadName method etc. Remeber to go back into ordinary GL_RENDER mode when after doing the pick thing.

- Note that "hits" are recorded to the array you specify using GL.SelectBuffer.

- When in selection mode, every primitive that intersects the viewing volume is recorded as a hit! So you have to setup a special viewing volume, and restore the ordinary viewing volumne (ModelView matrix) when done.

khdani's picture

Thanks Objarni,
Actually I indeed intended to use "one-color-per-object" method, I just don't understand when and how I need to draw to "back buffer?

objarni's picture

For the one-color-per-object method, you should re-render the scene in "identity-color-mode" that is stop texturing/lighting and "ask" all objects to paint with their unique color-id. (an int for example).

This will go into the back buffer, but since you won't SwapBuffers(), it will never be seen by the user visually (he sees the front buffer) and just cleared in the next frames' ordinary rendering.

You should do this when the picking is needed - for example when the user clicks the mouse.

A hint is that re-rendering the scene you can change the viewport to just the pixel clicked! That way the render will be quite a lot quicker than an ordinary render (because you are just rendering to a single pixel, all other pixels are viewport-rejected!).

Then you need to read the color back from the backbuffer to an integer; maybe someone with the knowledge of exactly how to do this (ReadPixels?) can fill in here..

oyvindra's picture

I just did a color picking function, and when you do you might find these functions valuable:

private Color ColorFromInt( int i ) {
byte R = (byte)( i & 0x000000FF );
byte G = (byte)( ( i & 0x0000FF00 ) >> 08 );
byte B = (byte)( ( i & 0x00FF0000 ) >> 16 );
return Color.FromArgb( R, G, B );
}

private int IntFromColor( Color color ) {
// We are limited to 255^3 = 16 million different objects.
int i = 0;
i += (int)color.R;
i += (int)color.G << 8;
i += (int)color.B << 16;

return i;
}

You can call these functions in your own function to get a unique color for each object;

for my Selection_draw function; I have simply done:

// Save old attributes
GL.PushAttrib( AttribMask.AllAttribBits );

// Disable some attributes to make the objects flat / solid color when they are drawn
GL.Disable( EnableCap.Fog );
GL.Disable( EnableCap.Texture2D );
GL.Disable( EnableCap.Dither );
GL.Disable( EnableCap.Lighting );
GL.Disable( EnableCap.LineStipple );
GL.Disable( EnableCap.PolygonStipple );
GL.Disable( EnableCap.CullFace );
GL.Disable( EnableCap.Blend );
GL.Disable( EnableCap.AlphaTest );

*Call select_draw functions of objects that are selectable*

GL.PopAttrib();

oyvindra's picture

The last function is just called whenever the user clicks somewhere in the GLControl in my case.