title: OpenGL 3D Selection
body: <p>I am trying to create a 3D robot that should perform certain actions when certain body parts are clicked. I have successfully (sort of) implemented picking in that if you click on any x-plane part, it registers a hit, but not anywhere else. That is, it is not registering depth, and if you clicked on it's square head, you could only register a hit by clicking on the front of the head (facing you). Obviously, I don't fully understand picking and selection and am sloppily trying to transcribe what I know about 2D selection to 3D (my teacher is as helpful as a rock) but I have left something out or not changed something pertaining to depth. Can anyone help me out? Here are the related functions.</p>
  
  <pre><code>void processHits (GLint hits, GLuint buffer[])
  {
      unsigned int i, j;
      GLint n, *ptr;
  
      printf ("hits = %d\n", hits);
      ptr = (GLint *) buffer;
  
      //For each hit.
      for (i = 0; i &lt; hits; i++)
      {
          n = *ptr;       //Number of names under current hit.
          ptr+=3;         //Bypass three integers: n, z1, z2.
          printf ("hit %d has %d name(s)\n", i, n);
  
          //For each name.
          for (j = 0; j &lt; n; j++)
          {
              if(*ptr==1) printf ("Body hit.\n");
              else if(*ptr==2) printf ("Right shoulder hit.\n");
              else if(*ptr==3) printf ("Left shoulder hit.\n");
              else if(*ptr==4) printf ("Left arm hit.\n");
              else if(*ptr==5) printf ("Right arm hit.\n");
              else if(*ptr==6) printf ("Left leg hit.\n");
              else if(*ptr==7) printf ("Right leg hit.\n");
              else if(*ptr==8) printf ("Right foot hit.\n");
              else if(*ptr==9) printf ("Left foot hit.\n");
              else if(*ptr==10) printf ("Neck hit.\n");
              else if(*ptr==11) printf ("Head hit.\n");
              else printf ("Nothing hit.\n");
  
              ptr++;
          }
          printf ("\n");
      }
  }
  
  void selection(int mouse_x, int mouse_y)
  {
      GLuint buffer[512];                     //Set up a selection buffer.
      GLint hits;                             //The number of objects we selected.
      GLint viewport[4];                      //Viewport size. [0] Is &lt;x&gt;, [1] Is &lt;y&gt;, [2] Is &lt;length&gt;, [3] Is &lt;width&gt;.
  
      glGetIntegerv(GL_VIEWPORT, viewport);   //Sets the array &lt;viewport&gt; to size and location of screen relative to window.
      glSelectBuffer(512, buffer);            //Tell OpenGL to use our array for selection.
  
      glRenderMode(GL_SELECT);                //Puts OpenGL in selection mode. Nothing will be drawn. Object IDs and extents stored in buffer.
  
      glInitNames();                          //Initializes name stack.
      glPushName(0);                          //Push an entry onto the stack.
  
      glMatrixMode(GL_PROJECTION);            //Selects the projection matrix.
      glPushMatrix();                         //Push the projection matrix.
      glLoadIdentity();                       //Resets matrix.
  
      //This creates a matrix that will zoom up to a small portion of the screen, where the mouse is.
      gluPickMatrix((GLdouble) mouse_x, (GLdouble) (viewport[3]-mouse_y), 0.01, 0.01, viewport);
  
      gluPerspective(45.0f, (GLfloat) (viewport[2]-viewport[0])/(GLfloat) (viewport[3]-viewport[1]), 0.1f, 100.0f);
      glMatrixMode(GL_MODELVIEW);                                 //Select the modelview matrix.
      drawObjects(GL_SELECT);                                     //Render the targets to the selection buffer.
      glMatrixMode(GL_PROJECTION);                                //Select the projection matrix.
      glPopMatrix();                                              //Pop the projection matrix.
      glMatrixMode(GL_MODELVIEW);                                 //Select the modelview matrix.
      hits = glRenderMode(GL_RENDER);
      processHits (hits, buffer);
  
      //printf("%d ", hits);
  
      //Post redisplay message.
      glutPostRedisplay();
  }
  
  void mouse(int button, int state, int x, int y)
  {    
      if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_DOWN)
      {
          selection(x, y);
      }
  } 
  </code></pre>