Open GL Super Bible

Previous Table of Contents Next


Step 2: Get Feedback on the Object

Now that we have determined which object was clicked on, we set up the feedback buffer, and render again in feedback mode. Listing 19-8 is the code that sets up feedback mode for this example and calls RenderScene to redraw the scene. This time, however, the glPassThrough functions put markers for the objects in the feedback buffer.

Listing 19-8 Load and parse the feedback buffer

// Go into feedback mode and draw a rectangle around the object
#define FEED_BUFF_SIZE 4096
void MakeSelection(int nChoice)
        {
        // Space for the feedback buffer
        GLfloat feedBackBuff[FEED_BUFF_SIZE];

        // Storage for counters, etc.
        int size,i,j,count;

        // Min and max x and y values for 2D vertex positions
        float nMaxX,nMaxY,nMinX,nMinY;

        // Initial minimum and maximum values
        nMaxX = nMaxY = -999999.0f;
        nMinX = nMinY =  999999.0f;

        // Set the feedback buffer
        glFeedbackBuffer(FEED_BUFF_SIZE,GL_2D, feedBackBuff);

        // Enter feedback mode
        glRenderMode(GL_FEEDBACK);

        // Redraw the scene
        RenderScene();

        // Leave feedback mode
        size = glRenderMode(GL_RENDER);

        // Parse the feedback buffer and get the
        // min and max X and Y window coordinates
        i = 0;
        while(i < FEED_BUFF_SIZE)
                {
                // Search for appropriate token
                if(feedBackBuff[i] == GL_PASS_THROUGH_TOKEN)
                        if(feedBackBuff[i+1] == (GLfloat)nChoice)
                        {
                        i+= 2;
                        // Loop until next token is reached
                        while(feedBackBuff[i] != GL_PASS_THROUGH_TOKEN)
                                {
                                // Just get the polygons
                                if(feedBackBuff[i] == GL_POLYGON_TOKEN)
                                        {
                                        // Get all the values for this
                                        polygon
                                        // How many vertices
                                        count = (int)feedBackBuff[++i];
                                        i++;

                                        // Loop for each vertex
                                        for(j = 0; j < count; j++)
                                           {
                                           // Min and Max X
                                           if(feedBackBuff[i] > nMaxX)
                                                nMaxX = feedBackBuff[i];

                                           if(feedBackBuff[i] < nMinX)
                                                nMinX = feedBackBuff[i];

                                           i++;

                                           // Min and Max Y
                                           if(feedBackBuff[i] > nMaxY)
                                                nMaxY = feedBackBuff[i];

                                           if(feedBackBuff[i] < nMinY)
                                                nMinY = feedBackBuff[i];

                                           i++;
                                           }
                                        }
                                else
                                        i++;    // Get next index and keep
                                        looking
                                }
                        break;
                        }
                i++;
                }
        // Draw focus rectangle
        HighLight((int)floor(nMinX+0.5), (int)floor(nMinY+0.5),
                (int)floor(nMaxX+0.5), (int)floor(nMaxY+0.5));
        }

Once the feedback buffer is filled, we search it for GL_PASS_THROUGH_TOKEN. When we find one, we get the next value and determine if it is the one we are looking for. If so, the only thing that remains is to loop through all the polygons for this object and get the minimum and maximum window x and y values. The HighLight function uses the Win32 function DrawFocusRect to draw a rectangle around the outside of the object that was clicked on. This function uses XOR drawing mode, so calling it twice causes the rectangle to disappear. This allows you to select by clicking on an object, and deselect by clicking again.

Summary

Selection and feedback are two very powerful features of OpenGL that give you the ability to facilitate the userís active interaction with the scene. Selection and picking are used to identify an object or region of a scene in OpenGL coordinates rather than just window coordinates. Feedback returns valuable information about how an object or primitive is actually drawn in the window. You can use this information to supplement OpenGLís graphics with Windows-specific graphics and operations that appear to interact with your OpenGL graphics.

Reference Section

glFeedbackBuffer

Purpose
Sets the feedback mode.
Include File
<gl.h>
Syntax
void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer);
Description
This function establishes the feedback buffer and the type of vertex information desired. Feedback is a rendering mode; rather than rendering to the framebuffer, OpenGL sends vertex data to the buffer specified here. These blocks of data can include x, y, z, and w coordinate positions (in window coordinates); color data for color index mode or RGBA color mode; and finally texture coordinates. The amount and type of information desired is specified by the type argument.

Parameters

size
GLsizei: The maximum number of entries allocated for *buffer. If a block of data written to the feedback would overflow the amount of space allocated, only the part of the block that will fit in the buffer is written.
type
GLenum: Specifies the kind of vertex data to be returned in the feedback buffer. Each vertex generates a block of data in the feedback buffer. For each of the following types, the block of data contains a primitive token identifier followed by the vertex data. The vertex data specifically will include the following:
GL_2D: x and y coordinate pairs.
GL_3D: x, y, and z coordinate triplets.
GL_3D_COLOR: x, y, z coordinates, and color data (one value for Color Index, four for RGBA).
GL_3D_COLOR_TEXTURE: x, y, z coordinates, color data (one or four values), and four texture coordinates.
GL_4D_COLOR_TEXTURE: x, y, z, and w coordinates, color data (one or four values), and four texture coordinates.
buffer
GLfloat*: Buffer where feedback data will be stored.
Returns
None.

Example

The following code from the SELECT sample program initializes the feedback buffer with glFeedbackBuffer, then switches to feedback mode, renders the scene, and fills the feedback buffer by switching back to rendering mode.

     #define FEED_BUFF_SIZE 4096
     ...
     ...

     // Space for the feedback buffer
     GLfloat feedBackBuff[FEED_BUFF_SIZE];

     ...
     ...

     // Set the feedback buffer
     glFeedbackBuffer(FEED_BUFF_SIZE,GL_2D, feedBackBuff);

     // Enter feedback mode
     glRenderMode(GL_FEEDBACK);

     // Redraw the scene
     RenderScene();

     // Leave feedback mode
     size = glRenderMode(GL_RENDER);
See Also
glPassThrough, glRenderMode, glSelectBuffer


Previous Table of Contents Next