PDA

View Full Version : Picking in opengl



infinitecmdz
11-02-2005, 01:03 AM
Hey guys,

I was trying out the picking methods in opengl and I am currently working on the method of coloring each objects uniquely in the back buffer and selecting the object based on these colors. Well actually, it aint working all well. When I use the glReadPixels() and see for the pixel that I selected I am not getting the correct color values in the pixels that the function returns. I cant find out whats wrong.

For example heres my processfunction for the picking:

void processPick ()
{
GLint viewport[4];
GLubyte pixel[3];

glGetIntegerv(GL_VIEWPORT,viewport);

glReadPixels(cursorX,viewport[3]-cursorY,1,1,GL_RGB,GL_UNSIGNED_BYTE,(void *)pixel);

printf("%d %d %d\n",pixel[0],pixel[1],pixel[2]);
if (pixel[0] == 255)
printf ("You picked the 1st octa");
else if (pixel[1] == 255)
printf ("You picked the 2nd octa");
else if (pixel[2] == 255)
printf ("You picked the 3rd octa");
else if (pixel[0] == 250)
printf ("You picked the 2nd snowman on the 2nd row");
else
printf("You didn't click a snowman!");
printf ("\n");

}

Now when I click on the black portion of the viewport i shoudl be getting 0,0,0 but no instead it shows me some other color values. And when I click on the object that is of unique color, I get a 0,0,0... I cant understand this situation.

Also I am wondering , whether it doesnt work because i am using an ortho projection. Does picking need to be perspective projection?

Plz reply if anyone knows.

Yours

Siddharth

RigidBody
11-02-2005, 03:28 AM
picking is independent of the projection type.
but of course, you have to set up the same
projection/modelview matrices that you use when
you draw the model. it could help if you post some
more code, especially the part in which you call
the picking routine.

11-02-2005, 03:36 AM
It may be because you're using an unsigned byte that's giving the wrong value?? I'm using exactly the same code in my program, and it works fine - but I'm just using a normal byte.

This is my code (in Java):

int viewport[] = new int[4];
byte pixel[] = new byte[3];
gl.glGetIntegerv(GL_VIEWPORT,viewport);
gl.glReadPixels(mouse_x,viewport[3]-mouse_y,1,1,GL_RGB,GL_BYTE,pixel);

And yes, I'm using perspective projection. See if that makes any difference. :)

Dan.

infinitecmdz
11-02-2005, 07:38 AM
Right, I'll try to explain my code as much as possible and avoid confusion. Here goes:

//For picking
void processPick ()
{
GLint viewport[4];
GLubyte pixel[3];

glGetIntegerv(GL_VIEWPORT,viewport);

glReadPixels(cursorX,viewport[3]-cursorY,1,1,GL_RGB,GL_UNSIGNED_BYTE,(void *)pixel);

printf("%d %d %d\n",pixel[0],pixel[1],pixel[2]);
if (pixel[0] == 255)
printf ("You picked the 1st octa");
else if (pixel[1] == 255)
printf ("You picked the 2nd octa");
else if (pixel[2] == 255)
printf ("You picked the 3rd octa");
else if (pixel[0] == 250)
printf ("You picked the 2nd snowman on the 2nd row");
else
printf("You didn't click a snowman!");
printf ("\n");

}

void display(void)
{
//glutSetWindow(mainWindow);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

/* view transform */
if (trackballMove)
{
glRotatef(angle, axis[0], axis[1], axis[2]);

}

{
//Draw the x , y , z Axis and the grid initially.
DrawAxis() ;
Draw3DGrid() ;

glPushMatrix() ;

glTranslatef(MoveX , 0.0f , MoveZ) ;



//To tilt the cube along with T1 octahedron and make one of the face
//of T1 on the XZ plane.

glRotatef(-36.0f , 0.0f , 0.0f , 1.0f) ;
glRotatef(45.0f , 1.0f , 0.0f , 0.0f) ;
glTranslatef(0.0f , 1.0f , 0.0f) ;

if(mode == RENDER)
DrawSetOne(RENDER) ;
else
{
if(mode == SELECT)
{
DrawSetOne(SELECT) ;
}
}

glPopMatrix() ;


//To draw the second Octahedron T2 along with the cube on the T1
//Octahedron along the edge
//opposite to the Z axis.

glPushMatrix();

glTranslatef(MoveX , 0.0f , MoveZ) ;
glTranslatef(0.81f , 1.15f , 0.0f) ;
glRotatef(ang,0,0,1);
glRotatef(-36.0f , 0.0f , 0.0f , 1.0f) ;
glRotatef(45.0f , 1.0f , 0.0f , 0.0f) ;
glTranslatef(0.0f , 1.0f , 0.0f) ;

if(mode == RENDER)
DrawSetTwo(RENDER) ;
else
if(mode == SELECT)
DrawSetTwo(SELECT) ;

glPopMatrix() ;

//To draw the third Octahedron T3 along with the cube on the T2
//Octahedron along the edge
//opposite to the Z axis.

glPushMatrix() ;

glTranslatef(MoveX , 0.0f , MoveZ) ;
glTranslatef(0.81f , 1.15f , 0.0f) ;
glRotatef(ang,0,0,1);
glTranslatef(0.81f , 1.15f , 0.0f) ;
glRotatef(ang1,0,0,1);
glRotatef(-36.0f , 0.0f , 0.0f , 1.0f) ;
glRotatef(45.0f , 1.0f , 0.0f , 0.0f) ;
glTranslatef(0.0f , 1.0f , 0.0f) ;

if(mode == RENDER)
DrawSetThree(RENDER) ;
else
if(mode == SELECT)
DrawSetThree(SELECT) ;

glPopMatrix() ;


glFlush() ;
}

if (mode == SELECT)
{
processPick();
mode = RENDER;
}
else
if(mode == RENDER)
glutSwapBuffers();

}

void mouseButton(int button, int state, int x, int y)
{
if(button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)
return ;

if(button==GLUT_LEFT_BUTTON) switch(state)
{
case GLUT_DOWN:
y=winHeight-y;
startMotion( x,y);

//For picking.
cursorX = x;
cursorY = y;
mode = SELECT;
break;

case GLUT_UP:
stopMotion( x,y);
break;
}
}

void main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow("colorcube");
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutMouseFunc(mouseButton);
glutMotionFunc(mouseMotion);
glutKeyboardFunc(Keyboard) ;
glutSpecialFunc(ArrowKeys) ;

glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-5.0, 5.0, -5.0, 5.0, -200.0, 200.0);
glMatrixMode(GL_MODELVIEW);

glutMainLoop();
}

So these are my essentials parts of code that i think are relavant to picking. I have no Init() in my code as i do all of them in my main() itself. Basically in the display() i have to draw a model that is arranged in a way that is on top of each each other so taht the next object touches the edge of the object below and hence i have done the transformations. But the point here is , i have kept a mode variable which is set when the mouse is clicked and depending on this, the object is drawn in the back buffer or its drawn with buffers swapping. I have used only glOrtho and that too at the main(). So guys could u tell wats wrong with this code???

thanx