PDA

View Full Version : Double buffering and picking



PollyPocket4eva
02-24-2010, 09:13 AM
Hi,
I am trying to do something like the process described here:
http://www.lighthouse3d.com/opengl/picking/index.php?color1
In brief, I want to use double buffering in my opengl view so that the user sees every triangle shaded white (the front buffer) and in the back buffer each triangle is shaded with its own unique color. When the mouse is pressed, we read from the back buffer. But otherwise we always display the front, which is the white triangles.
I think I have the right method for reading from the back buffer, I'm uncertain of how to generate that buffer in the first place. Meaning I'm not sure how to go about drawing the scene twice, once for each buffer.
Here is what I have. I know it does not work. But not sure where and when to call drawCodedScene.
Any help would be greatly appreciated.
Thanks!

- (void) drawRect:(NSRect)rect {
[self resizeGL];
[self updateModelView];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[self drawScene];
[[self openGLContext] flushBuffer];
}
-(void) drawScene {
for(int i = 0; i < 5; i++) {
glColor3f(255.0,255.0,255.0); // NOT color coded!
glBegin(GL_TRIANGLES);
glVertex3f(vertA[i].x,vertA[i].y,vertA[i].z);
glVertex3f(vertB[i].x,vertB[i].y,vertB[i].z);
glVertex3f(vertC[i].x,vertC[i].y,vertC[i].z);
glEnd();
}
[self setNeedsDisplay: YES];
}
-(void) drawCodedScene {
for(int i = 0; i < 5; i++) {
glColor3f(i/255.0,i/255.0,i/255.0); // Color coded!
glBegin(GL_TRIANGLES);
glVertex3f(vertA[i].x,vertA[i].y,vertA[i].z);
glVertex3f(vertB[i].x,vertB[i].y,vertB[i].z);
glVertex3f(vertC[i].x,vertC[i].y,vertC[i].z);
glEnd();
}
[self setNeedsDisplay: YES];
}
- (void)mouseDown:(NSEvent *)theEvent
{
NSPoint location = [self convertPoint:[theEvent locationInWindow] fromView:nil];
location.y = camera.viewHeight - location.y;
[self pixelValueForX:location.x Y:location.y];
}
- (void)pixelValueForX:(float)myX Y:(float)myY {
[self drawCodedScene];
GLint viewport[4];
GLubyte pixelVal[3];
glGetIntegerv(GL_VIEWPORT, viewport);
glReadPixels(myX, (float)viewport[3]-myY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &amp;pixelVal);
NSLog(@"%i %i %i",pixelVal[0],pixelVal[1],pixelVal[2]);
}

scratt
02-24-2010, 09:45 AM
I am not sure how complex your geometry is, but to be frank you are much better doing ray - intersection picking on the CPU side, and allowing your GPU to get on with the job of drawing a scene. Rather than drawing it all twice, and reading data back via glReadPixels - which is slowish and a bit out dated these days... Just my 2c. :)

You can use a library like ColDet on SourceForge to base your collision code on.

And the method for casting a ray into your scene is discussed here..
http://www.opengl.org/resources/faq/technical/selection.htm

PollyPocket4eva
02-24-2010, 10:14 AM
Hey,
In an earlier version of my software, I implemented the intersection picking method. However, I now need to use the color based method for several reasons.
For my purposes, I do not really need to render the color-coded back buffer every frame. I only need the color coded version every once in a while (when the mouse is clicked) so that I can glReadPixels on the color coded info. Is it possible to set it up that way?
If so, how?
Thanks!

scratt
02-24-2010, 08:54 PM
My approach to doing this would be to simply draw it to the existing backbuffer, do my picking, and then overwrite that with the scene I actually want to view and then swap buffers...

There's a fairly straight forward example here : http://gpwiki.org/index.php/OpenGL_Selection_Using_Unique_Color_IDs

Of course, I presume you could setup a dedicated FrameBuffer just for picking views and leave that sitting around with the last "picking view" in it when you are just drawing. But at the end of the day Framebuffers are just chunks of memory that you choose to write to or display, so you could do this many ways.

For what you are describing, if I understand correctly, then you may need to fiddle with (glReadBuffer) http://www.opengl.org/sdk/docs/man/xhtml/glReadBuffer.xml , so you can play around with which buffer you are actually reading from.

PollyPocket4eva
02-25-2010, 08:51 AM
Thanks for your help. I'm not sure I totally how you do the actual swapping, but I'll try to work through it.

scratt
02-25-2010, 10:26 AM
In it's simplest form (this is a bit of a hack), call the drawCodedScene, do your reading back, then call the drawScene after clearing the COLOR_BITS.

What you want to do is not call the setNeedsDisplay in your drawCodedScene, and then you'll be drawing twice to the same buffer, and only swapping that buffer into view at the end of drawScene.

Does that clarify it?

Once you get it going that way then you can refine it later as you progress with your projects design.

Note : I have not used setNeedsDisplay on OS X, but am presuming this is what does the buffer swap for you.