问题
I know that OpenGL selection mode is deprecated and never was HW accelerated, except on a few SGI boxes and 3DLabs GPUs.But i can't get rid of it (not my code).Below its the C++ code:
void GLWidget::Selection(int x,int y) // This Is Where Selection Is Done
{
GLint viewport[4];
glSelectBuffer(BUFSIZE,selectBuf);
glRenderMode(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT,viewport);
gluPickMatrix(x,viewport[3]-y,5,5,viewport); //defining the picking matrix
gluPerspective(fov,ratio,0.1f,1000);
glMatrixMode(GL_MODELVIEW);
glInitNames();
glPushName(1); //Pushing names on the stack
glutSolidTorus(1, 2, 55, 55); //Some draw in GL_SELECT mode
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(2);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glPopName();
glPushName(3);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2); //public members
glTranslatef(5.0f,1,5.0f);
glPopName();
int hits;
// restoring the original projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
// returning to normal rendering mode
hits = glRenderMode(GL_RENDER);
// if there are hits process them
if (hits != 0){
qDebug() << "Found " << hits << " hit(s)";
processHits(hits,selectBuf);
}
}
This is the processHits method
void GLWidget::processHits (GLint hits, GLuint buffer[]) //Some prints
{
unsigned int i, j;
GLuint names, *ptr, minZ,*ptrNames, numberOfNames;
ptr = (GLuint *) buffer;
minZ = 0xffffffff;
for (i = 0; i < hits; i++) {
names = *ptr;
ptr++;
if (*ptr < minZ) {
numberOfNames = names;
minZ = *ptr;
ptrNames = ptr+2;
}
ptr += names+2;
}
qDebug() << "Nearest: ";
ptr = ptrNames;
for (j = 0; j < numberOfNames; j++,ptr++) {
qDebug() << *ptr ;
}
}
Selection() is invoked by using an *event (GLWidget derives from QGLWidget (QT 4.8)). So,only when i click the right mousebutton I ""draw"" objects in the buffer and push their names on the stack.
void GLWidget::mousePressEvent(QMouseEvent *event)
{
lastPos = event->pos();
if (event->buttons() & GLUT_RIGHT_BUTTON){
Selection(event->x(),event->y());
}
}
While the paintGL() method is
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glViewport (0, 0, w_screen, h_screen);
gluLookAt(objCamera->mPos.x, objCamera->mPos.y, objCamera->mPos.z,
0, objCamera->mView.y, 0,
objCamera->mUp.x, objCamera->mUp.y, objCamera->mUp.z);
glutSolidTorus(1, 2, 55, 55); //draw some objects
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(1, 2, 55, 55);
glTranslatef(5.0f,1,5.0f);
glutSolidTorus(RADIUS1, RADIUS2, complex1, complex2);
glTranslatef(5.0f,1,5.0f);
glTranslatef(-15.0f,-3,-15.0f);
}
At this time,with this code, I can select an object and retrieve its ID,and if there are more of them on the same xy coordinates i can retrieve the nearest one (by ID). So,now I've got 3 objects with 3 different IDs (1-2-3).
The one with ID=3 has non fixed size.My question is:how to use the buffer to retrieve the third torus and change its size modifying RADIUS1, RADIUS2, complex1, complex2?
Could someone of you write a small example?
Have I,when there is a hit,simply use the name of the hit on the stack (given with glPushName),that must refers in some way to an object (maybe with a string public member wich contains the name),so i can change its properties?
回答1:
You are going to have to store the properties of each object yourself. When you push a name onto the name stack, all you're doing is adding extra data to each fragment so you can effectively identify where it came from later.
You'll probably want to create a structure like { float rad1, rad2, complex1, complex2; } to store the values for each torus. Once you know the ID of the object selected, go into your array of said struct, and modify the values for the appropriate object. Each time you draw your scene, just run through this array of structs.
来源:https://stackoverflow.com/questions/16735736/opengl-picking-on-selection-mode