Выбор в OpenGL с использованием glRenderMode(GL_SELECT) и glReadPixels

Я пытаюсь сделать выбор в opengl, но это не работает. Я рисую объекты, которые получаю из файла .obj (v, vn, f, o и подобные индексы). Каждый объект состоит из «групп», и каждая группа представляет собой группу из GL_POLYGON. Вот функция рисования:

void draw(GLenum mode) {
    glBegin(GL_LINES);
    glColor3f(1, 0, 0);
    glVertex3f(0.0, 0.0, 0.0);
    glVertex3f(100.0, 0.0, 0.0);

    glColor3f(0, 0, 1);
    glVertex3f(0.0, 0.0, 0.0);
    glVertex3f(0.0, 100.0, 0.0);

    glColor3f(0, 1, 0);
    glVertex3f(0.0, 0.0, 0.0);
    glVertex3f(0.0, 0.0, 100.0);
    glEnd();

    glColor4f(1.0, 1.0, 1.0, 1.0);

    if (changeFOV) {
        fovAngle += fovScale;
        changeFOV = false;
        setTransformations();
    }
    for (unsigned int i = 0; i < objects.size(); i++) {
        objectItem currObject = objects[i];
        for (unsigned int j = 0; j < currObject.getGroups().size(); j++) {
            group currGroup = currObject.getGroups().at(j);
            for (unsigned int k = 0; k < currGroup.getFs().size(); k++) {
                if (mode == GL_SELECT)
                    glPushName(currGroup.getName());
                glPushMatrix();
                vector<pair<int, int> > currF = currGroup.getFs()[k];
                glBegin(GL_POLYGON);
                for (unsigned int kk = 0; kk < currF.size(); kk++) {
                    Vector3f currVertex = vertexes.at(
                            (currF.at(kk).first - 1 >= 0) ?
                                    currF.at(kk).first - 1 : 0);

                    Vector3f currNormal = vertexesNormal.at(
                            (currF.at(kk).second - 1 >= 0) ?
                                    currF.at(kk).second - 1 : 0);

                    glNormal3f(currNormal.x, currNormal.y, currNormal.z);
                    glVertex3f(currVertex.x / 1, currVertex.y / 1,
                            currVertex.z / 1);
                }
                glEnd();
                glPopMatrix();
            }
        }
    }
}

Рисунок работает нормально, и я вижу объект на экране.

Вот и вся процедура подбора

/*      PICKING     */
void processHits(GLint hits, GLuint *buffer) {
    float z1, z2;
    for (int i = 0; buffer[i] > 0; i += 5) {
        z1 = buffer[i + 1] / 4294967295.0;
        z2 = buffer[i + 2] / 4294967295.0;
        printf("z1 = %f ,z2 = %f zValue = %f\n", z1, z2, zValue[0]);
        if ((zValue[0] <= z1 + 0.0001 && zValue[0] >= z2 - 0.0001)
                || (zValue[0] >= z1 - 0.0001 && zValue[0] <= z2 + 0.0001)) { //try to locate which name is correlated with the pressed pixel according to z value
            ii = buffer[i + 3];
            jj = buffer[i + 4];
        }

    }
}

void startPicking(GLuint *selectionBuf) {
    glSelectBuffer(bufSize, selectionBuf); //declare buffer for input in selection mode
    glRenderMode(GL_SELECT); //change to selecting mode
    glInitNames();          //initialize names stack
    glPushName(-1);         //push name
}

void pick(int button, int x, int y) {
    //use selection mode to pick
    glReadPixels(x, viewport[3] - y, 1, 1, GL_RGBA, GL_FLOAT, pix);
    //printf("depth = %f, x = %d, y = %d\n",pixels[(viewport[3]-y)*512+x],x,viewport[3]-y);
    glMatrixMode(GL_PROJECTION);
    glReadPixels((GLdouble) x, (GLdouble) viewport[3] - y, 2, 2,
            GL_DEPTH_COMPONENT, GL_FLOAT, zValue);
    glPushMatrix(); //saves current projection matrix
    startPicking(selectionBuf); //preper selection mode
    glLoadIdentity();
    gluPickMatrix((GLdouble) x, (GLdouble) viewport[3] - y, 1, 1, viewport); //change matrices so only the area of the picking pixel can be seen.
    gluPerspective(fovAngle, 1, near, far); //return to perspective state
    glMatrixMode(GL_MODELVIEW);
    draw(GL_SELECT); //draws board on background
    hits = glRenderMode(GL_RENDER); //gets hits number
    glMatrixMode(GL_PROJECTION);
    glPopMatrix(); //restores projection matrix
    glMatrixMode(GL_MODELVIEW);
    processHits(hits, selectionBuf); //check hits
    if(hits > 0)
        printf("touched: %d\n",selectionBuf[3]);
    //printf("depth %f hits: %d\n\n",pixels[(viewport[3]-y)*512+x], hits);
    if (zValue[0] < 1.0) {
        isPick = true;
        xx = x;
        yy = y;
        if (button == GLUT_RIGHT_BUTTON)
            zMove = true;
        else
            zMove = false;
    }
}

функция pick вызывается при щелчке мышью (используя функцию мыши opengl). Ошибка, которую я получаю, заключается в том, что при нажатии на объект не появляются объекты.

Я использую Ubuntu 14.04 LTS с Opengl 3.0.

Я не знаю, как спросить или что конкретно спросить, я был бы признателен за некоторые входные данные по коду, если вы видите что-то не так..


person Javi    schedule 23.06.2015    source источник
comment
Можете ли вы рассказать о вашем методе сбора? Как это должно работать и какая часть выходит из строя?   -  person jozxyqk    schedule 23.06.2015
comment
Я добавил, скажите, если вы хотите, чтобы я добавил что-то еще @jozxyqk   -  person Javi    schedule 23.06.2015


Ответы (1)


Вы, кажется, пропустили использование glPopName()

GLName, используемые в буфере выбора, помещаются в стек. Поэтому, если вы не вызовете glPopName(), стек никогда не раскрутится. Работа этого аналогична вызовам glPushMatrix() и glPopMatrix().

Обычно так выглядит поток кода.

//Push the name of the primitives on top of selection stack
glPushName(...)
  //Set Transformations / Draw the primitives
  ..
  ..
//Pop the name (Clear the stack for pushing another name)
glPopName();
person SamCoder    schedule 02.07.2015