OpenGL 之 Processing the Hit Records
In order to process the hit records the application must first return to the normal rendering mode. This is done calling glRenderMode with GL_RENDER. This function returns the number of hit records that were created during rendering in the selection mode. After this step the application can process the selection buffer. Note that before calling glRender with GL_RENDER there is no guarantee that the hit records have been saved into the selection buffer.
Furthermore, it is necessary to restore the original projection matrix. Since this matrix was saved when entering the selection mode with glPushMatrix, all that is required is to pop the matrix. The following excerpt of code shows the required steps:
int hits;
// restoring the original projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glFlush();
// returning to normal rendering mode
hits = glRenderMode(GL_RENDER);
// if there are hits process them
if (hits != 0)
processHits(hits,selectBuf);
}
So the final issue is related to the selection buffer structure. The selection buffer stores the hit records sequentially by the order they occurred, i.e. by the order that the primitives we're drawn. Note that primitives that wouldn't be drawn due to Z buffer depth culling still produce hit records.
The hit records are potentially variable size records due to the number of names they contain.
An example of a selection buffer with 3 hit records is presented next:
Hit Record Contents | Description |
0 | No names have been stored for the first hit |
4.2822e+009 | Minimum depth for first hit |
4.28436e+009 | Maximum depth for first hit |
1 | Number of names for the second hit |
4.2732e+009 | Minimum depth for second hit |
4.27334e+009 | Maximum depth for second hit |
6 | A single name for the second hit |
2 | Number of names for the third hit |
4.27138e+009 | Minimum depth for third hit |
4.27155e+009 | Maximum depth for third hit |
2 | First name for third hit |
5 | Second name for third hit |
In order to detect which object was closest to the viewpoint you use the depth information. For instance you can select the object with the smalest minimum depth has the one which the user intended to click on. In the above example the relevant hit is the third one. The following function, adapted from the one in the Red Book, prints out the names for the closest object.
{
unsigned int i, j;
GLuint names, *ptr, minZ,*ptrNames, numberOfNames;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
minZ = 0xffffffff;
for (i = 0; i < hits; i++) {
names = *ptr;
ptr++;
if (*ptr < minZ) {
numberOfNames = names;
minZ = *ptr;
ptrNames = ptr+2;
}
ptr += names+2;
}
printf ("The closest hit names are ");
ptr = ptrNames;
for (j = 0; j < numberOfNames; j++,ptr++) {
printf ("%d ", *ptr);
}
printf ("\n");
}
【转】http://www.lighthouse3d.com/opengl/picking/index.php3?openglway3