2015-06-23 46 views
0

我想在opengl中做選擇,但它不工作。 我畫了從.obj文件(v,vn,f,o和這樣的索引)收到的對象。每個對象由「組」組成,每個組都是一組GL_POLYGON。 這裏是繪製函數:使用glRenderMode(GL_SELECT)和glReadPixels在OpenGL中採摘

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

的繪製工作正常,我在屏幕上看到的對象。

這是所有的拾取過程(使用的OpenGL鼠標功能)單擊鼠標時

/*  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函數被調用。 我收到的錯誤是當點擊一個對象時沒有任何物體被擊中。

我使用Ubuntu 14.04 LTS與OpenGL 3.0的

我不知道如何提出或什麼特別要求,我將不勝感激代碼中的一些投入,如果你看到的東西錯了..

+0

你可以介紹一下你的採摘方法嗎?這是如何工作,哪部分失敗? – jozxyqk

+0

我補充說,如果你想讓我添加更多@jozxyqk – Javi

回答

0

您似乎錯過了使用glPopName()

在選擇緩衝區中使用的GL名稱被壓入堆棧。所以除非你調用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();