PDA

View Full Version : Depth to selected object



TheSpider
05-02-2010, 06:42 AM
Hello,

I am trying to obtain the depth to a selected object in my opengl rendering from my camera.

I have positioned a projection camera using gluLookAt , and then I am running a glRenderMode(GL_SELECT) to get the object under the mouse cursor. This all works fine.

Having done this, I need not only the object, but also the distance from the camera to that object, such that the user can move the object in the plane whose normal is the same as the camera, but is positioned at "depth" away.

I have tried to use gluUnproject to do this, by first calling glReadPixels, however glReadPixels seems to always return 1, even with an object completetly filling the screen.

GluUnproject's value changes as I move the camera, but not as a function of the object depth, so I guess I am doing something wrong.

Does GL_SELECT draws to the depth buffer? I assume it must in order to work out the hit record distances...






//Push on the matrix stack
glPushMatrix();

GLint oldViewport[4];
glGetIntegerv(GL_VIEWPORT, oldViewport);
//5x5px picking region. Picking is done by modifying the view
//to enlarge the selected region.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(p.x, oldViewport[3]-p.y,5, 5, oldViewport);
glMatrixMode(GL_MODELVIEW);

GLuint *selectionBuffer = new GLuint[512];
glSelectBuffer(512, selectionBuffer);
glRenderMode(GL_SELECT);
glInitNames();

glPushMatrix();
... Apply camera transform, this is done with a class, so I have omitted it here for brevity. ..
glFlush();
GLint hits = glRenderMode(GL_RENDER);

//Hit query records
GLuint *ptr = selectionBuffer;
GLuint *closestNames = 0;
GLuint minZ = 0xffffffff;
GLuint numClosestNames = 0;
for ( int i=0; i<hits; ++i )
{
if ( *(ptr+1) < minZ )
{
numClosestNames = *ptr;
minZ = *(ptr+1);
closestNames = ptr+3;
}
ptr+=*ptr+3;
}


//Use transformation matrix to work out scene depth
GLdouble model[16];
GLdouble proj[16];
GLint view[4];
glGetDoublev(GL_MODELVIEW_MATRIX, model);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
glGetIntegerv(GL_VIEWPORT, view);

//Map display coordinates [0-1] into depth coordinates.
double xR,yR,zR;
float pixelDepth;
glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &amp;pixelDepth);
std::cerr << " PixelDepth :" << pixelDepth << std::endl;
std::cerr << "UnProj:" << gluUnProject(0.5, 0.5, pixelDepth, model,
proj, view, &amp;xR, &amp;yR, &amp;zR) << std::endl;





Thanks.

strattonbrazil
05-02-2010, 08:42 AM
So the item in question is always being drawn at (0,0)? Where is it as far as depth? Should it be at .5 or something?

TheSpider
05-02-2010, 11:11 AM
This is part of what I have not been able to determine from the faq or the man pages. pickmatrix expands the view such that usually the object is pretty close to 0,0, (i.e. the it will be at most 2.5 px away from the user's mouse) or that the user's mouse is never far away. That is not so important, as there is some visual feedback, so a slight offset error shouldn't matter.

As for the depth value, I don't know that generically, as many of my objects calls are wrappers around glu calls, so the exact depth has to either (1) be computed by me for all possible primitive types or (2) read from the depth buffer.



Where is it as far as depth? Should it be at .5 or something?

I am a little confused as to your question. The object can be anywhere between nearplane and farplane, which are both known. nearplane is fixed at 0.1 world units. the farplane is set by my camera to always be slightly behind the furthest away object, and is hence dynamic. Is this what you mean?

strattonbrazil
05-02-2010, 02:52 PM
I was wondering if you were testing with a simple quad at a fixed depth, which is usually a good way to determine depth.

gluUnproject needs to use the exact same matrix from the render mode, not the selection mode. You can save those matrices off before you do your picking. Then at the end of the picking make the gluUnproject call to get the depth of that pixel back based on whereever the user clicked. This goes for glReadPixels, too.