Picking in OpenGL: Picking allows you to push the mouse button in the graphics window and find out what is drawn at that location. In our application, the object at that location is going to be set as the active object, to which transformations are applied: To pick: 1) Enter selection mode; 2) "Draw" the scene as usual, but also give "names" to objects as they are being drawn. (In fact, in select mode, the frame buffer is not really changed.) A small area around the curser is designated as the pickable region. 3) Leave selection mode and return to render mode. At this time, information is returned indicating which objects were selected. 4) Process the returned information. More specifically: 1) In the Mouseclick() routine: check if the left button is the one used AND that the state is down (otherwise you will be selecting both when you press and when you release the button). If so, call a routine that you have to write to initiate picking. We will call it pick_object(). The parameters should be the location of the mouse (int xmouse,ymouse). In pick_object(), make an array of unsigned integers whose size is enough to contain information about all the objects that you might pick at once. (If multiple objects are near the cursor, more than one might be picked.) In fact, each object picked will cause at least four integers to appear in the buffer. Tell OpenGL about the buffer, because it will use it, with the command: glSelectBuffer(int buffersize, unsigned int *buffer); Put OpenGL into select mode: glRenderMode(GL_SELECT); Initialize the OpenGl internal "name stack" for picked identifiers: glInitNames(0); glPushName(0); Make the projection matrix active, so you can alter it: glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); Now indicate to OpenGL the center and size of the region in pixels (int pickwidth,pickheight) where objects drawn are considered picked. I.e., if you only set a picking area of 1 pixel in each direction, you have to be really accurate with the mouse; if you set it to 10 pixels in each direction, you may be picking things quite a distance from the mouse. This uses the present viewport setting, so you need to get it (int viewport[4]). Then reset the projection matrix, using either glOrtho() or gluPerspective(), depending on which you are using. glGetIntegerv(GL_VIEWPORT,viewport); gluPickMatrix((double) xmouse, (double) (viewport[3] - ymouse), pickwidth, pickheight, viewport); gluOrtho(...); Now call your display function, which would normally be called whenever you redraw the window. DisplayFunc(); /* or whatever you call it */ You aren't done in the routine pick_object(), you'll have more to do after you return from the display routine. 2) In the display function, check whether you are in select mode or render mode (int mode): glGetIntegerv(GL_RENDER_MODE,&mode); (This assumes that you are only going to change the picking name stack when in select mode. Alternatively, you could just not check and always change the name stack, because it has no effect if you aren't in select mode.) Now before you call the actual drawing calls for any object that you want picked, send an integer "name" to OpenGl that will be used as the identifier for all objects drawn in the future until you set a different name. for (i=0; i < numobjectsdrawn; i++) { if (mode == GL_SELECT) glLoadName(i); ...drawingstuff... } (If you only do glLoadName, there will never be more than one name on the name stack at once. Therefore, there will only be one name for every hit. Sometimes, it might be desirable to have a main name for an object, and other names for parts of the same object. In that case, you can call glPushName(j) which makes a new entry in the stack. In this case, there will be multiple "names" returned for each hit. This is NOT necessary (or desirable) for this assignment.) You don't want to swap buffers in this was a selection, because nothing really changed in the frame buffer. Before you leave the display routine: if (mode == GL_RENDER) glSwapBuffers(); 3) Now back to Mouseclick(), having just returned from the display routine call. You get the list of things picked by returning to GL_RENDER mode. This process returns the number (int hits) of hits. glMatrixMode(GL_PROJECTION); glPopMatrix(); glFlush(); hits = glRenderMode(GL_RENDER); Call a routine to process your hits, which are now in your buffer. processHits(int hits, unsigned it buffer[]); 4) In processHits(), find out which objects were near the cursor. A hit always includes: int numnames; /* in this hit */ int zmin; /* useful for determing the frontmost hit */ int zmax; /* the depth range of the hit */ int name1,name2,name3...namenumnames; Unless you have done something clever (stupid?), you will probably only get one name per hit. However, to be safe and general, you would walk through the list using pointer advances. For example: unsigned int *ptr,numnames,zmin,zmax,lastname; ptr = buffer; for (i=0; i < hits; i++) { numnames = *ptr; ptr++; zmin = *ptr; ptr++; zmax = *ptr; ptr++; for (j=0; j