📄 chapter12.html
字号:
the number of values in the array to exceed the <B>size</B> argument specified
with <B>glSelectBuffer()</B>, OpenGL writes as much of the record as fits
in the array and sets an overflow flag. When you exit selection mode with
<B>glRenderMode()</B>, this command returns the number of hit records that
were written (including a partial record if there was one), clears the
name stack, resets the overflow flag, and resets the stack pointer. If
the overflow flag had been set, the return value is -1.
<P>
<HR>
<H3>
A Selection Example</H3>
In Example 12-2 , four triangles (green, red, and two yellow ones) are
drawn in selection mode, and the corresponding hit records are processed.
The first triangle generates a hit, the second one doesn't, and the third
and fourth ones together generate a single hit. Routines are defined to
draw a triangle (<B>drawTriangle()</B>) and to draw a wireframe box representing
the viewing volume (<B>drawViewVolume()</B>). The <B>processHits()</B>
routine prints out the selection array. Finally, <B>selectObjects()</B>
draws the triangles in selection mode to generate the hit records.
<P><B>Example 12-2 : </B>A Selection Example: select.c
<PRE>#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
void drawTriangle (GLfloat x1, GLfloat y1, GLfloat x2,
GLfloat y2, GLfloat x3, GLfloat y3, GLfloat z)
{
glBegin (GL_TRIANGLES);
glVertex3f (x1, y1, z);
glVertex3f (x2, y2, z);
glVertex3f (x3, y3, z);
glEnd ();
}
void drawViewVolume (GLfloat x1, GLfloat x2, GLfloat y1,
GLfloat y2, GLfloat z1, GLfloat z2)
{
glColor3f (1.0, 1.0, 1.0);
glBegin (GL_LINE_LOOP);
glVertex3f (x1, y1, -z1);
glVertex3f (x2, y1, -z1);
glVertex3f (x2, y2, -z1);
glVertex3f (x1, y2, -z1);
glEnd ();
glBegin (GL_LINE_LOOP);
glVertex3f (x1, y1, -z2);
glVertex3f (x2, y1, -z2);
glVertex3f (x2, y2, -z2);
glVertex3f (x1, y2, -z2);
glEnd ();
glBegin (GL_LINES); /* 4 lines */
glVertex3f (x1, y1, -z1);
glVertex3f (x1, y1, -z2);
glVertex3f (x1, y2, -z1);
glVertex3f (x1, y2, -z2);
glVertex3f (x2, y1, -z1);
glVertex3f (x2, y1, -z2);
glVertex3f (x2, y2, -z1);
glVertex3f (x2, y2, -z2);
glEnd ();
}
void drawScene (void)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (40.0, 4.0/3.0, 0.01, 100.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt (7.5, 7.5, 12.5, 2.5, 2.5, -5.0, 0.0, 1.0, 0.0);
glColor3f (0.0, 1.0, 0.0); /* green triangle */
drawTriangle (2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -5.0);
glColor3f (1.0, 0.0, 0.0); /* red triangle */
drawTriangle (2.0, 7.0, 3.0, 7.0, 2.5, 8.0, -5.0);
glColor3f (1.0, 1.0, 0.0); /* yellow triangles */
drawTriangle (2.0, 2.0, 3.0, 2.0, 2.5, 3.0, 0.0);
drawTriangle (2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -10.0);
drawViewVolume (0.0, 5.0, 0.0, 5.0, 0.0, 10.0);
}
void processHits (GLint hits, GLuint buffer[])
{
unsigned int i, j;
GLuint names, *ptr;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
for (i = 0; i < hits; i++) { /* for each hit */
names = *ptr;
printf(" number of names for hit = %d\n", names); ptr++;
printf (" z1 is %u;", *ptr); ptr++;
printf (" z2 is %u\n", *ptr); ptr++;
printf (" the name is ");
for (j = 0; j < names; j++) { /* for each name */
printf ("%d ", *ptr); ptr++;
}
printf ("\n");
}
}
#define BUFSIZE 512
void selectObjects(void)
{
GLuint selectBuf[BUFSIZE];
GLint hits, viewport[4];
glSelectBuffer (BUFSIZE, selectBuf);
(void) glRenderMode (GL_SELECT);
glInitNames();
glPushName(-1);
glPushMatrix ();
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0.0, 5.0, 0.0, 5.0, 0.0, 10.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glLoadName(1);
drawTriangle (2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -5.0);
glLoadName(2);
drawTriangle (2.0, 7.0, 3.0, 7.0, 2.5, 8.0, -5.0);
glLoadName(3);
drawTriangle (2.0, 2.0, 3.0, 2.0, 2.5, 3.0, 0.0);
drawTriangle (2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -10.0);
glPopMatrix ();
glFlush ();
hits = glRenderMode (GL_RENDER);
processHits (hits, selectBuf);
}
void myinit (void)
{
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawScene ();
selectObjects ();
glFlush();
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGBA | AUX_DEPTH);
auxInitPosition (0, 0, 200, 200);
auxInitWindow (argv[0]);
myinit ();
auxMainLoop(display);
}</PRE>
<HR>
<H3>
Picking</H3>
As an extension of the process described in the previous section, you can
use selection mode to determine if objects are picked. To do this, you
use a special picking matrix in conjunction with the projection matrix
to restrict drawing to a small region of the viewport, typically near the
cursor. Then you allow some form of input, such as clicking a mouse button,
to initiate selection mode. With selection mode established and with the
special picking matrix used, objects that are drawn near the cursor cause
selection hits. Thus, during picking you're typically determining which
objects are drawn near the cursor.
<P>Picking is set up almost exactly like regular selection mode is, with
the following major differences:
<UL>Picking is usually triggered by an input device. In the following code
examples, pressing the left mouse button invokes a function that performs
picking.
<BR>
<P>You use the utility routine <B>gluPickMatrix()</B> to multiply a special
projection matrix onto the current matrix. This routine should be called
prior to multiplying a projection matrix onto the stack.</UL>
Another, completely different way to perform picking is described in "Object
Selection Using the Back Buffer." This technique uses color values to identify
different components of an object. void <B>gluPickMatrix</B>(GLdouble <B>x</B>,
GLdouble <B>y</B>, GLdouble <B>width</B>, GLdouble <B>height</B>, GLint
<B>viewport[4]</B>);
<P>Creates a projection matrix that restricts drawing to a small region
of the viewport and multiplies that matrix onto the current matrix stack.
The center of the picking region is (<B>x, y</B>) in window coordinates,
typically the cursor location. <B>width</B> and <B>height</B> define the
size of the picking region in screen coordinates. (You can think of the
width and height as the sensitivity of the picking device.) <B>viewport[]</B>
indicates the current viewport boundaries, which can be obtained by calling
<PRE>glGetIntegerv(GL_VIEWPORT, GLint *viewport);</PRE>
<B>Advanced</B>
<P>The net result of the matrix created by <B>gluPickMatrix()</B> is to
transform the clipping region into the unit cube -1 &le; (<I>x</I>,
<I>y</I>, <I>z</I>) &le; 1 (or -<I>w</I> &le; (<I>wx</I>, <I>wy</I>,
<I>wz</I>) &le; <I>w</I>). The picking matrix effectively performs
an orthogonal transformation that maps a subregion of this unit cube to
the unit cube. Since the transformation is arbitrary, you can make picking
work for different sorts of regions - for example, for rotated rectangular
portions of the window. In certain situations, you might find it easier
to specify additional clipping planes to define the picking region.
<P>Example 12-3 illustrates simple picking. It also demonstrates how to
use multiple names to identify different components of a primitive, in
this case the row and column of a selected object. A 3
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -