gluunproject

gluUnProject

gluUnProject

Using gluUnProject (OpenGL, gluUnProject, glut)

I have been using OpenGL since a long time and a fundamental problem many would like is how to find out where the user clicked in the 3D-world given the mouse co-ordinates. OpenGL and GLU functions can be used to effectively solve this problem. Since i could not find any good tutorials regarding this i thought i'd put up one by myself.There is a simple function that glu provides. It's called gluUnProject, this function takes in 6 arguments.. which include the window x,y,z co-ordinates, modelview matrix, projection matrix, viewport and X,Y,Z for storing the world co-ordinates of that particular point. Dont' get worried about window z co-ordinate which is given to this function. This value is obtained by using glReadPixels( x, viewport[3]-y, GL_DEPTH_COMPONENT, GL_FLOAT, &z ); We need to use viewport[3]-y (this is equivalent to windowheight-y where x,y are the mouse location co-ordinates) instead of just y because the glut window has origin at top left corner where as OpenGL (glReadPixels) has the origin at bottom left corner.

Once you get the z value of the window (using glReadPixels), we can pass the window x,y,z values to the gluUnProject and get the world co-ordinates. In the example here a red cube is moved to the location where the user clicks on the green plane.

double objx, objy, objz;

//The drawing function glutDisplayFunc( )

void display( )

{

//Clearing the screen with black and clearing the depth buffer

glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

//The green polygon

glBegin( GL_POLYGON );

glColor3f( 0, 1, 0 );

glVertex3f( -100, 0, 100 );

glVertex3f( -100, 0, -100 );

glVertex3f( 100, 0, -100 );

glVertex3f( 100, 0, 100 );

glEnd( );

//store the current transformation matrix

//and translate the cube to the world location

glPushMatrix( );

glColor3f( 1, 0, 0 );

glTranslatef( objx, objy, objz );

glutSolidCube( 10 );

glPopMatrix( );

glFlush( );

glutSwapBuffers( );

}

//The function that handles the mouse clicks glutMouseFunc( )

void mouse( int button, int state, int x, int y )

{

double modelview[16], projection[16];

int viewport[4];

float z;

//get the projection matrix

glGetDoublev( GL_PROJECTION_MATRIX, projection );

//get the modelview matrix

glGetDoublev( GL_MODELVIEW_MATRIX, modelview );

//get the viewport

glGetIntegerv( GL_VIEWPORT, viewport );

//Read the window z co-ordinate

//(the z value on that point in unit cube)

glReadPixels( x, viewport[3]-y, 1, 1,

GL_DEPTH_COMPONENT, GL_FLOAT, &z );

//Unproject the window co-ordinates to

//find the world co-ordinates.

gluUnProject( x, viewport[3]-y, z, modelview,

projection, viewport, &objx, &objy, &objz );

}

Link to the source code

Note: I assume that you know and understand the opengl, glut code. The comments in the code above should answer most of the queries. If you have any doubts, do contact me. Let me know if this tutorial was useful to you.