使用glRenderMode(GL_SELECT)和glReadPixels在OpenGL中拾取

使用glRenderMode(GL_SELECT)和glReadPixels在OpenGL中拾取,opengl,glu,picking,mouse-picking,Opengl,Glu,Picking,Mouse Picking,我试图在opengl中进行选择,但它不起作用。 我从.obj文件(v、vn、f、o等索引)中提取对象。每个对象由“组”组成,每个组是一组GL\u多边形。 以下是draw函数: 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);

我试图在opengl中进行选择,但它不起作用。 我从
.obj
文件(v、vn、f、o等索引)中提取对象。每个对象由“组”组成,每个组是一组
GL\u多边形
。 以下是draw函数:

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();
            }
        }
    }
}
void draw(格伦模式){
glBegin(GL_行);
gl3f(1,0,0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(100.0,0.0,0.0);
gl3f(0,0,1);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0100.0,0.0);
gl3f(0,1,0);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.0,100.0);
格伦德();
glColor4f(1.0,1.0,1.0,1.0);
if(changeFOV){
fovAngle+=fovScale;
changeFOV=false;
setTransformations();
}
for(无符号整数i=0;i=0)?
电流(kk.first-1:0);
向量3f currNormal=顶点snormal.at(
(kk.秒时的电流-1>=0)?
电流(kk.second-1:0);
glNormal3f(currennormal.x,currennormal.y,currennormal.z);
glVertex3f(currVertex.x/1,currVertex.y/1,
(1.z/1);
}
格伦德();
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;
    }
}
/*拣选*/
void processHits(闪烁命中、GLuint*缓冲区){
浮球z1、z2;
对于(int i=0;缓冲区[i]>0;i+=5){
z1=缓冲区[i+1]/4294967295.0;
z2=缓冲区[i+2]/4294967295.0;
printf(“z1=%f,z2=%f zValue=%f\n”,z1,z2,zValue[0]);
如果((zValue[0]=z2-0.0001)
||(zValue[0]>=z1-0.0001&&zValue[0]0)
printf(“触摸:%d\n”,选择buf[3]);
//printf(“深度%f命中率:%d\n\n”,像素[(视口[3]-y)*512+x],命中率);
if(zValue[0]<1.0){
isPick=true;
xx=x;
yy=y;
如果(按钮==GLUT\u右按钮)
zMove=true;
其他的
zMove=false;
}
}
单击鼠标(使用opengl鼠标功能)时,将调用
拾取
函数。 我收到的错误是,当单击某个对象时,似乎没有对象被击中

我在OpenGL3.0中使用Ubuntu14.04LTS


我不知道该怎么问,也不知道具体问什么,如果您发现有问题,我将非常感谢您对代码的一些输入。

您似乎没有使用glPopName()

选择缓冲区中使用的GLName被推送到堆栈上。因此,除非调用glPopName(),否则堆栈将永远不会展开。其工作原理与调用glPushMatrix()和GLPOPMARRIX()类似

通常这就是代码流的样子

//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();

你能介绍一下你的拣选方法吗?它是如何工作的?哪个部分失败了?我补充道,如果你想让我在@jozxyqk添加更多内容,请告诉我