View Full Version : Need help with selection

Dylan K
06-11-2008, 09:21 AM

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] &amp;&amp; (*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