0

我正在尝试在 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鼠标函数)。我收到的错误是单击对象时似乎没有击中任何对象。

我正在使用带有 Opengl 3.0 的 Ubuntu 14.04 LTS

我不知道如何问或具体问什么,如果您发现有问题,我将不胜感激。

4

1 回答 1

0

您似乎错过了使用 glPopName()

选择缓冲区中使用的 GLNames 被压入堆栈。因此,除非您调用 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();
于 2015-07-02T06:18:34.217 回答