Need help with selection


I’ve been trying to get selection to work for an OpenGL app I’m writing. I’m coding under Windows Vista with Visual Studio 2008. The problem is, when I click on a polygon, it does not properly detect which polygon was hit - or it will think another polygon (in a very different location) has been selected.

I’ve looked at several tutorials online, and cross-referenced the code. Most of them look the same, but I must be doing something wrong.

The program displays lots of different planes at assorted locations. The coordinates for these planes are stored in BestFitPlanes[x][y] (where BestFitPlanes is a 2 dimensional array of Plane*).

The pseudo-code version of my program is:
Clear the “hit” boolean for all planes, and name each one
Get the viewport
Initialize the selection buffer
Set render mode to select
Initialize names array

Create a pick matrix

Draw the planes

Exit selection mode
Find the foremost plane that was hit and mark its boolean as hit

Here’s the code for my selection function.

void Selection()
	const int BUFFER_SIZE = 512;


	// Mark all the planes as not hit and name them.
	int Name = 0;
	for(vector<Cloud*>::iterator i = Clouds.begin(); i != Clouds.end(); i++)
		for(int x = 0; x < (*i)->Columns; x++)
			for(int y = 0; y < (*i)->Rows; y++)
					(*i)->BestFitPlanes[x][y]->Hit = false;
					(*i)->BestFitPlanes[x][y]->Name = Name;

	GLuint buffer[BUFFER_SIZE]; // Create the selection buffer
	GLint viewport[4]; // Create a viewport
	glGetIntegerv(GL_VIEWPORT, viewport); // Set the viewport
	glSelectBuffer(BUFFER_SIZE, buffer);// Set the select buffer
	glRenderMode(GL_SELECT); // Put OpenGL in select mode
	glInitNames(); // Initialize the name stack
	glPushName(0); // Push a fake ID on the stack to prevent load error


	// Setup a pick matrix
	gluPickMatrix((GLdouble)MouseX, (GLdouble)(viewport[3] - MouseY), 5.0, 5.0, viewport);
	gluPerspective(45.0f, (GLfloat)1280/(GLfloat)974, 0.1f, 100.0f);

	glLoadIdentity(); // Reset the current matrix
	DrawPlanes(true); // Draw to the pick matrix instead of our normal one
	GLint hits = glRenderMode(GL_RENDER); // Count the hits

	// Find the object that was hit (if any)
	if(hits > 0)
		for(vector<Cloud*>::iterator i = Clouds.begin(); i != Clouds.end(); i++)
			for(int x = 0; x < (*i)->Columns; x++)
				for(int y = 0; y < (*i)->Rows; y++)
					if((*i)->BestFitPlanes[x][y] && (*i)->BestFitPlanes[x][y]->Name == buffer[3])
						(*i)->BestFitPlanes[x][y]->Hit = true;

and the code for the DrawPlanes function…

void DrawPlanes(bool Selection = false)
	for(vector<Cloud*>::iterator i = Clouds.begin(); i != Clouds.end(); i++)
		Cloud* const c = *i;
		if(c->BestFitPlanes == 0) continue;
		for(int row = 0; row < c->Rows; row++)
			for(int col = 0; col < c->Columns; col++)
				Plane* p = c->BestFitPlanes[row][col];
				if(p == 0) continue;
				if(Selection) glLoadName(p->Name);
				glColor3f(p->P1.r, p->P1.g, p->P1.b);
				glVertex3f(p->P1.x, p->P1.y, p->P1.z);
				glColor3f(p->P2.r, p->P2.g, p->P2.b);
				glVertex3f(p->P2.x, p->P2.y, p->P2.z);
				glColor3f(p->P3.r, p->P3.g, p->P3.b);
				glVertex3f(p->P3.x, p->P3.y, p->P3.z);
				glColor3f(p->P4.r, p->P4.g, p->P4.b);
				glVertex3f(p->P4.x, p->P4.y, p->P4.z);

Any help would be much appreciated!

– Dylan