Hello,
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;
if(!ShowBestFit)
return;
// 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++)
if((*i)->BestFitPlanes[x][y])
{
(*i)->BestFitPlanes[x][y]->Hit = false;
(*i)->BestFitPlanes[x][y]->Name = 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
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// 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
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
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;
ColorScene(SLOPE);
}
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);
glBegin(GL_QUADS);
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);
glEnd();
}
}
}
}
Any help would be much appreciated!
– Dylan