Open GL Super Bible

Previous Table of Contents Next


An Example

An excellent use of feedback is to obtain window coordinate information regarding any objects that you render. You can then use this information to place controls near the objects in the window, or other windows around them.

To demonstrate feedback, we will use selection to determine which of two objects on the screen have been clicked on by the user. Then we will enter feedback mode and render the scene again to obtain the vertex information in window coordinates. Using this data, we will determine the minimum and maximum x and y values for the object, and use those values to draw a focus rectangle around the object. The end result is graphical selection and deselection of one or both objects.

Label the Objects for Feedback

Listing 19-6 shows the rendering code for our example program, SELECT. Don’t confuse this with a demonstration of selection mode! Even though selection mode is employed in our example to select an object on the screen, we are demonstrating the process of getting enough information about that object—using feedback—to draw a rectangle around it using normal Windows GDI commands. Notice the use of glPassThrough to label the objects in the feedback buffer, right after the calls to glLoadName to label the objects in the selection buffer.

Listing 19-6 Rendering code for the SELECT example program

#define CUBE1
#define SPHERE2

// Called to draw scene
void RenderScene(void)
        {
        // Clear the window with current clearing color
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Save the matrix state and do the rotations
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();

        // Translate the whole scene out and into view
        glTranslatef(-80.0f, 0.0f, -300.0f);

        // Initialize the names stack
        glInitNames();
        glPushName(0);

        // Set material color, Yellow
        // Cube
        glRGB(255, 255, 0);
        glLoadName(CUBE);
        glPassThrough((GLfloat)CUBE);
        auxSolidCube(75.0f);

        // Draw Sphere
        glRGB(128,0,0);
        glTranslatef(130.0f, 0.0f, 0.0f);
        glLoadName(SPHERE);
        glPassThrough((GLfloat)SPHERE);
        auxSolidSphere(50.0f);

        // Restore the matrix state
        glPopMatrix(); // Modelview matrix

        // Flush drawing commands
        glFlush();
        }

Step 1: Select the Object

Figure 19-6 shows the output from this rendering code, displaying a cube and a sphere. When the user clicks on one of the objects, the function ProcessSelection is called (Listing 19-7). This is very similar to the selection code in the previous two examples.


Figure 19-6  Output from the SELECT program after the sphere has been clicked

Listing 19-7 Selection processing for the SELECT example program

// Process the selection, which is triggered by a right mouse
// click at (xPos, yPos).
#define BUFFER_LENGTH 64
void ProcessSelection(int xPos, int yPos)
        {
        // Space for selection buffer
        GLuint selectBuff[BUFFER_LENGTH];

        // Hit counter and viewport storage
        GLint hits, viewport[4];

        // Set up selection buffer
        glSelectBuffer(BUFFER_LENGTH, selectBuff);

        // Get the viewport
        glGetIntegerv(GL_VIEWPORT, viewport);

        // Switch to projection and save the matrix
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();

        // Change render mode
        glRenderMode(GL_SELECT);

        // Establish new clipping volume to be unit cube around
        // mouse cursor point (xPos, yPos) and extending two pixels
        // in the vertical and horizontal direction
        glLoadIdentity();
        gluPickMatrix(xPos, yPos, 2,2, viewport);

        // Apply perspective matrix
        gluPerspective(60.0f, fAspect, 1.0, 425.0);

        // Draw the scene
        RenderScene();

        // Collect the hits
        hits = glRenderMode(GL_RENDER);

        // Restore the projection matrix
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();

        // Go back to modelview for normal rendering
        glMatrixMode(GL_MODELVIEW);

        // If a single hit occurred, display the info.
        if(hits == 1)
                MakeSelection(selectBuff[3]);
        }


Previous Table of Contents Next