Color picking with Qt in OpenGL

1.4k Views Asked by At

I've been reading tutorials about picking and that color picking is far the most popular and simplest form.

Tried some tutorials with snowmans as example but it doesn't work for me. When I run the program , it gives me just a black sceen without anything draw on it. When I click a couple of times nothing happens except when I close the window then it sais "you haven't clicked on a snowman".

Don't know what is wrong with it can someone help me?

void GLWidget::paintGL() {
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

    gluLookAt(camPosx ,camPosy ,camPosz,
              camPosx + camViewx,camViewy,camPosz + camViewz,
              camUpx, camUpy, camUpz );

    draw(); //draw the normal scene

    if (mode == SELECT)
        drawPickingMode();
    else
        drawPickingMode();

    if (mode == SELECT) {
        processPick();
        mode = RENDER;
    }
    else
        QGLWidget::swapBuffers();

    // restore current matrix
    glMatrixMode( GL_MODELVIEW );
    glPopMatrix( );

}

void GLWidget::mousePressEvent(QMouseEvent * e)
{
    if(e->button() == Qt::LeftButton)
    {
        qDebug("mouse");
        qDebug("%d %d",QCursor::pos().x(),QCursor::pos().y());
        this->cursorX = QCursor::pos().x(); // set x and y cord from mouse
        this->cursorY = QCursor::pos().y();
        mode = SELECT; // set the mode to select
    }
}

void GLWidget::draw() {

// Draw ground
    glColor3f(0.9f, 0.9f, 0.9f);
    glBegin(GL_QUADS);
        glVertex3f(-100.0f, 0.0f, -100.0f);
        glVertex3f(-100.0f, 0.0f,  100.0f);
        glVertex3f( 100.0f, 0.0f,  100.0f);
        glVertex3f( 100.0f, 0.0f, -100.0f);
    glEnd();

// Draw 4 Snowmen

    glColor3f(1.0f, 1.0f, 1.0f);

    for(int i = 0; i < 2; i++)
        for(int j = 0; j < 2; j++) {
            glPushMatrix();
            glTranslatef(i*3.0,0,-j * 3.0);
            glColor3f(1.0f, 1.0f, 1.0f);
            glCallList(snowman_display_list);
            glPopMatrix();
        }

}

void GLWidget::processPick ()
{
    GLint viewport[4];
    GLubyte pixel[3];

    glGetIntegerv(GL_VIEWPORT,viewport);

    glReadPixels(cursorX,viewport[3]-cursorY,1,1,
        GL_RGB,GL_UNSIGNED_BYTE,(void *)pixel);

    printf("%d %d %d\n",pixel[0],pixel[1],pixel[2]);
    if (pixel[0] == 255)
      printf ("You picked the 1st snowman on the 1st row");
    else if (pixel[1] == 255)
      printf ("You picked the 1st snowman on the 2nd row");
    else if (pixel[2] == 255)
      printf ("You picked the 2nd snowman on the 1st row");
    else if (pixel[0] == 250)
      printf ("You picked the 2nd snowman on the 2nd row");
    else
       printf("You didn't click a snowman!");
  printf ("\n");

}

void GLWidget::drawPickingMode() {

// Draw 4 SnowMen


    glDisable(GL_DITHER);
    for(int i = 0; i < 2; i++)
           for(int j = 0; j < 2; j++) {
        glPushMatrix();

// A different color for each snowman

        switch (i*2+j) {
            case 0: glColor3ub(255,0,0);break;
            case 1: glColor3ub(0,255,0);break;
            case 2: glColor3ub(0,0,255);break;
            case 3: glColor3ub(250,0,250);break;
        }

        glTranslatef(i*3.0,0,-j * 3.0);
        glCallList(snowman_display_list);
        glPopMatrix();
       }
    glEnable(GL_DITHER);
}

void GLWidget::initializeGL() {

    loadGLTextures();
    //LoadXml();
    glEnable(GL_TEXTURE_2D);       // Enable Texture Mapping
    glShadeModel(GL_SMOOTH);       // Enable Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background
    glClearDepth(1.0f);         // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);       // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);        // The Type Of Depth Testing To Do
    glEnable(GL_LIGHT0);        // Quick And Dirty Lighting (Assumes Light0 Is Set Up)
    glEnable(GL_LIGHTING);        // Enable Lighting
    glEnable(GL_COLOR_MATERIAL);      // Enable Material Coloring
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Perspective Calculations
   // buildLists(2);                                      // Creating displaylist #
    glLoadIdentity();

    timer->start(50);
    qDebug("Init");
}

Projection matrix is set as follows:

void GLWidget::resizeGL(int width, int height) {

    //set viewport
    glViewport(0,0,width,height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //set persepective
    //change the next line order to have a different perspective
    aspect_ratio=(GLdouble)width/(GLdouble)height;
    gluPerspective(45.0f, aspect_ratio, 0.1 , 100.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
2

There are 2 best solutions below

0
On

Although you're not specifying it explicitly, you're probably rendering to the back buffer double buffered window. Hence you should prepend calls to glReadPixels with a call to glReadBuffer to set which buffer to read the color from. Also remember that on-screen windows are subject to pixel ownership tests and other things that may interfere with your method of choice.

1
On

I don't see a flush. That can cause a blank screen since it is loading previous data (generally non-sense and therefor blank)