Using gluUnproject

So I’m trying to write a simple picking program. Currently my program draws two squares on the screen and when you click on one, the terminal will output which one (if any) was clicked on. However, my current algorithm of executing this fails once the window is resized. I’ve read that you can use gluUnproject for Inverse mapping of the coordinates. This concept is a little fuzzy with me and I’m not sure how to implement it. I’ve read the OpenGL document on the function but I’m still not sure where it needs to go and what parameters it requires. Where could I use gluUnproject to accomplish my goal? See my code below. Thank you in advance!


#include <GL/glut.h>
#include <stdio.h>

static int x1 = 40, y1 = 260;          //lower left corner of red rectangle
static int x2 = 140, y2 = 360;         //upper right corner of red rectangle
static int a1 = 260, b1 = 40;          //lower left corner of blue rectangle
static int a2 = 360, b2 = 140;         //upper right corner of blue rectangle
static float ppw = 400.0, pph = 400.0; //projection plane dimensions

void init (void)
{
	glClearColor (1.0, 1.0, 1.0, 0.0);
	glShadeModel (GL_FLAT);
}

void reshape (int w, int h)
{
	if (w > h)
		glViewport(0, 0, (GLfloat)h, (GLfloat)h);
	else
		glViewport(0, 0, (GLfloat)w, (GLfloat)w);

	glMatrixMode (GL_PROJECTION);
	glLoadIdentity ();
	gluOrtho2D (0.0, ppw, 0.0, pph);
	glMatrixMode (GL_MODELVIEW);
	
}

void mouse (int button, int state, GLint x, GLint y)
{
	y = 400 - y;
	if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN)) {
		printf("x = %d, y = %d
", x, y);

	//***** picking code goes here *****
		if ((x >= 40 && x <= 140 && y >= 260 && y <= 360)) {
			printf("Red square selected
");
		}
		else if ((x >= 260 && x <= 360 && y >= 40 && y <= 140)) {
			printf("Blue square selected
");
		}
		else {
			printf("No square selected
");
		}
	}
}

void display (void)
{

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	glClear (GL_COLOR_BUFFER_BIT);
	glColor3f (1.0, 0.0, 0.0);
	glBegin (GL_POLYGON);
	glVertex2i (x1, y1);
	glVertex2i (x2, y1);
	glVertex2i (x2, y2);
	glVertex2i (x1, y2);
	glEnd ();

	glColor3f (0.0, 0.0, 1.0);
	glBegin (GL_POLYGON);
	glVertex2i (a1, b1);
	glVertex2i (a2, b1);
	glVertex2i (a2, b2);
	glVertex2i (a1, b2);
	glEnd ();

   	glFlush ();
}

int main (int argc, char** argv)
{
	glutInit (&argc, argv);
	glutInitDisplayMode (GLUT_SINGLE|GLUT_RGB);
	glutInitWindowSize (400, 400);
	glutInitWindowPosition (100, 100);
	glutCreateWindow (argv[0]);
	init ();
	glutReshapeFunc (reshape);
	glutMouseFunc (mouse);
	glutDisplayFunc (display);
	glutMainLoop ();
	return 0;
}

You’d use it in the mouse-click handler, to transform the mouse position into object space.

Typically, you’d use glGetIntegerv() to read the current viewport and glGetDoublev() to read the current projection matrix and model-view matrix, which are required as parameters to gluUnProject(). Note that glGet* calls are slow, so you’d try to avoid them if you were performing this operation frequently, but if it’s only done in response to a mouse click, that doesn’t matter.

Note that gluUnProject() expects window-space space coordinates, which have their origin at the lower-left, whereas GLUT (like most other toolkits) reports the mouse position relative to the upper-left, with Y increasing downwards.

If you were using a perspective (or oblique) projection, you’d need to determine window-space Z somehow. With an orthographic projection, window-space Z only affects object-space Z, so you can ignore it for 2D.

I greatly appreciate your response. I’m sorry, but what you just said has me even more confused now. I’m completely lost at what you are suggesting to do. I’m a beginning and my coding skills are not very strong.

This tutorial might be helpful for you.