正反馈与负反馈:选择和反馈



章节目标

读完此章的后,你将能够做到:
建立允许用户选择(select)屏幕区域或拾取(pick)绘制在屏幕上物体应用
利用OpenGL反馈(feedback)模式获取绚染计算结果

有些图形应用只绘制两维和 3维物体构成静态图形些允许用户识别屏幕上物体并移动、修改、删除或用其它思路方法操纵这些物体OpenGL正是设计用于支持这些交互式应用绘制在屏幕上物体通常经过多次旋转、移动和透视变换所以确定用户选中了 3维场景中哪个物体会很困难为了帮助你OpenGL提供了个选取机制可惟自动告诉你哪个物体被绘制在窗口提定区域里你可以用这个机制和个工具例程(a special utility routine)道决定哪个物体在用户介绍说明或用光标选取区域里

选择(selection)实际上是OpenGL个操作模式;反馈(feedback)是这类模式中在反馈模式中你用你图形硬件和OpenGL完成通常绚染计算但和用这个计算结果去在屏幕上绘制图形相反OpenGL返回(或反馈(feeds back))这些绘制信息给你如果你想在绘图仪而不是屏幕上绘制图形举个例子你就得在反馈模式绘制它们收集绘制指令然后将这些指令转换为绘图仪可以理解命令

在选择和反馈模式中绘制信息返回给应用而不是象在绚染模式中那样送往帧缓冲因此当OpenGL处于选择或反馈模式时屏幕将被冻结-没有图形出现章将会在各自节中解释这些模式:

“选择(Selection)” 讨论怎样使用选择模式和相关例程以使你用户能拾取画在屏幕上物体

“反馈(Feedback)” 描述了怎样获取有关什么将被画在屏幕上信息和这些信息是以什么格式组织

---------------------------------------------------
Section

通常当你打算使用OpenGL选择机制时你首先把你场景画进帧缓冲然后进入选择模式并重新绘制这个场景然而旦你进入了选择模式帧缓冲内容将保存不变直到你退出选择模式当你退出时OpenGL返回个图元(premitives)清单图元可能被视见体(viewing volume)分割(记住视见体是由当前模式视见和投影矩阵及你定义所有裁剪面定义裁剪面详见"Additional Clipping Planes.")每个被视见体图元引出资选择命中(hit)确切图元清单是作为个取整数值名字(eger-valued names)和相关数据-命中记录(hit record)-对应名字栈(name stack)当前内容当你在选择模式下发布图元绘制命令时向名字栈中加入名字就可建立起名字栈这样当名字清单被返回后你就可以用它来确定屏幕上哪个图元可能被用户选中了

除了这个选择机制的外OpenGL提供了个工具例程以便在某些情况下通过限定在视口(viewport)个小区域内绘制来简化选择通常你可以用这个例程决定哪个物体被画在光标附近了这样你就能识别用户拾取了哪个物体你也可以通过指定附加裁剪面来界定个选择区域;详见"Additional Clipping Planes"拾取是选择个特殊情况所以本章选讲选择然后讲拾取

基本步骤
建立名字矩阵
命中记录
个选择例子
拾取
有关编写使用选择提示

------------------------------------------------------------------------
基本步骤

为使用选择机制你得作以下几步:
1、用glSelectBuffer指定用于返回命中记录
2、以GL_SELECT为参数glRenderMode进入选择模式
3、用glInitName和glPushName化名字栈
4、定义用于选择视见体通常它和你原来用于绘制场景视见体区别因此你或许会想用glPushMatrix和glPopMatrix来保存和恢复当前变换矩阵
5、交替发布图元绘制命令和名字栈控制命令这样每个感兴趣图元都会被指定适当名字
6、退出选择模式并处理返回选择数据(命中记录)

后面段落将描述glSelectBuffer和glRenderMode节则讲解名字栈控制

void glSelectBuffer(GLsizei size, GLu *buffer);
指定用于返回选择数据参数buffer是指向无符号整数(unsigned eger)指针数据就存在这个size参数介绍说明中最多能够保存个数要在进入选择模式的前glSelectBuffer

GL glRenderMode(GLenum mode);
控制应用是否进入绚染(rendering)、选择或反馈模式mode参数可以是GL_RENDER(默认)、GL_SELECT或GL_FEEDBACK的应用将保持处于给定模式直到再次以区别参数glRenderMode在进入选择模式的前必须glSelectBuffer指定选择类似进入反馈模式的前要glFeedbackBuffer指定反馈如果当前模式是GL_SELECT或GL_FEEDBACK的那么glRenderMode返回值有意义返回值是当前退出当前模式时选择命中数或放在反馈个数(译者注:就会退出当前模式);负值意味着选择或反馈溢出(overflowed)你可以用GL_RENDER_MODEglGetIntegerv获取当前模式

-------------------------------------------------------------------------------
建立名字矩阵

正如前面提到名字栈是返回给你选择信息基础要建立名字栈首先用glInitNames化它这将简单地清空栈然后当你发布相应绘制命令时向其中加入整数名字正如你可能想象栈控制命令允许你压入名字(glPushName)弹出名字(glPopName)替换栈顶名字(glLoadName)
/********************************************************************/
Example 12-1: Creating a Name Stack
glInitNames;
glPushName(-1);

glPushMatrix; /* save the current transformation state */

/*to do: create your desired viewing volume here */

glLoadName(1);
drawSomeObject;
glLoadName(2);
drawAnotherObject;
glLoadName(3);


drawYetAnotherObject;
drawJustOneMoreObject;

glPopMatrix ; /* restore the previous transformation state*/
/********************************************************************/

在这个例子中前两个被绘制物体有自己名字第 3和第 4个共用个名字这样如果第 3或第 4个物体中个或全部引起个选择命中只有个命中记录返回给你如果处理命中记录时不想区分各个物体可以让多个物体共享个名字

void glInitNames(void);
清空名字栈

void glPushName(GLu name);
将name压入名字栈压入名字超过栈容量时将生成个GL_STACK_OVERFLOW名字栈深度因OpenGL实现(implementations)区别而区别但最少要能容纳64个名字你可以用参数GL_NAME_STACK_DEPTHglGetIntegerv以获取名字栈深度

void glPopName(void);
弹出名字栈栈顶个名字从空栈中弹出名字引发GL_STACK_UNDERFLOW

void glLoadName(GLu name);
用name取代名字栈栈顶那个名字如果栈是空过glInitName后就是这样glLoadName生成个GL_INVALID_OPRATION错为避免这种情况如果栈时是空那么在glLoadName的前至少次glPushName以在名字栈中放上点东西

如果不是在选择模式下对glPushName、glPopName、glLoadName将被忽略这使得在选择模式和正常绚染模式下用相同绘制代码大为简化

-------------------------------------------------------------------------------
命中记录

在选择模式下被视见体裁剪每个图元引起个选择命中当前个名字栈控制命令被执行或glRenderModeOpenGL将个命中记录写进选择如果从上次名字栈操纵或glRenderMode以来有了个命中记录这个过程中共用同样名字物体-例如:由多个图元组成物体-不生成多个命中记录当然命中记录不保证会被写进中直到glRenderMode

除图元的外glRasterPos产生有效坐标也可以引起选择命中在多边形情况下如果它已经被消隐掉话不会有命中记录出现

每个命中记录由 4项组成依次是:
当命中出现时名字栈中名字数
至上次记录命中以来被视见体裁剪后图元所有顶点窗口Z坐标 最大和最小值
本次命中时名字栈内容最底元素最前

当前你进入选择模式时OpenGL个指针指向选择起点每写入个命中记录指针相应更新如果写入个命中记录会使中值个数超过glSelectBuffersize参数时OpenGL会写入尽可能多记录并设置个溢出标志当用glRenderMode退出选择模式时这条命令返回被写入记录个数(包括条部分记录如果有话)清除名字栈复位溢出标识重置栈指针如设定溢了出标识则返回值是-1

-------------------------------------------------------------------------------
个选择例子

在Example 12-2中4个 3角形(绿、红、两个黄)在选择模式下绘制相应命中记录被处理个 3角形生成个命中第 2个不第 3第 4个共同生成个命中定义了两个例程:绘制 3角形(drawTriangle)绘制个表示视见体线框盒子processHits例程打印出选择最后selectObjects在选择模式下绘制 3角形以生成命中记录

/*****************************************************************************/
Example 12-2 : A Selection Example: select.c

# <GL/gl.h>
# <GL/glu.h>
# "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 (GL hits, GLu buffer)
{
    unsigned  i, j;
    GLu names, *ptr;

    prf ("hits = %d\\n", hits);
    ptr = (GLu *) buffer;
    for (i = 0; i < hits; i) { /* for each hit */
        names = *ptr;
        prf(" number of names for hit = %d\\n", names); ptr;
        prf (" z1 is %u;", *ptr); ptr;
        prf (" z2 is %u\\n", *ptr); ptr;
        prf (" the name is ");
        for (j = 0; j < names; j) { /* for each name */
            prf ("%d ", *ptr); ptr;
        }
        prf ("\\n");
    }
}

# BUFSIZE 512

void selectObjects(void)
{
    GLu selectBuf[BUFSIZE];
    GL 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;
}


 ( argc, char** argv)
{
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA | AUX_DEPTH);
    auxInitPosition (0, 0, 200, 200);
    auxInitWindow (argv[0]);
    myinit ;
    auxMainLoop(display);
}


/************************************************************************************/

-------------------------------------------------------------------------------
拾取

作为前节所描述处理过程个扩展你可以用选择模式确定物体是否被拾取了要做到这个和投影矩阵相关联拾取矩阵将绘制限制在视口个很小区域里通常是在光标附近然后允许某种形式输入如点击鼠标个键引发选择模式建立起选择模式并使用特定拾取矩阵绘制在光标附近物体引发选择命中通常在拾取时候确定哪个物体被画在光标附近了

拾取建立几乎和正规选择模式完全只有以下主要区别:

拾取通常由某个输入设备触发在下面例子中按鼠标左键运行实现拾取
用例程gluPickMatrix个特殊投影矩阵乘到当前矩阵上它要在把投影矩阵乘到栈上的前

另外实现拾取完全区别思路方法在"Object Selection Using the Back Buffer"里有所描述技术使用颜色值标识物体区别部件

void gluPickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height, GL viewport[4]);
建立个投影矩阵用于将绘制限制在视口个小区域里并将这个矩阵乘到当前矩阵栈上拾取区域中心是窗口坐标(x,y)处通常是光标位置width和height定义选取区域大小用屏幕坐标(你可以认为宽和高是设备第 3)viewport表明当前视口边界这可以用glGetIntegerv(GL_VIEWPORTGL *viewport);获得

深入

gluPickMatrix建立矩阵净结果(net result)是将裁剪区域变换到单位立方体-1&1e;(x,y,z)&1e;1(或-w&1e;(wx,wy,wz)&1e;w)拾取矩阵实际上提供了个正交变换将这个单位立方体个子区域映射到单位立方体变换是任意你可以让拾取为区别类型领域工作-如用于旋转窗口矩形区域在某些情况下你会发觉用附加裁剪平面定义拾取区域要容易些

Example 12-3演示了个简单选取它也演示了怎样用多个名字标识同图元区别部件在这里行和列是个被选物体个3X3矩阵被画出来每个广场有区别颜色board[3][3]维护每个块当前点击总数当前鼠标左键被按下pickSquares例子被来识别哪个方块被鼠标拾取了在网格中两个名字标识个方块-个表示行、个表示列当鼠标左键被按下光标位置下所有方块颜色也会改变

/*******************************************************************/
Example 12-3 : A Picking Example: picksquare.c

# <GL/gl.h>
# <GL/glu.h>
# "aux.h"

 board[3][3]; /* amount of color for each square */

/* Clear color value for every square on the board */
void myinit(void)
{
     i, j;
    for (i = 0; i < 3; i)
        for (j = 0; j < 3; j )
            board[j] = 0;
    glClearColor (0.0, 0.0, 0.0, 0.0);
}

void drawSquares(GLenum mode)
{
    GLu i, j;
    for (i = 0; i < 3; i) {
         (mode  GL_SELECT)
            glLoadName (i);
        for (j = 0; j < 3; j ) {
             (mode  GL_SELECT)
                glPushName (j);
            glColor3f ((GLfloat) i/3.0, (GLfloat) j/3.0,
            (GLfloat) board[j]/3.0);
            glRecti (i, j, i+1, j+1);
             (mode  GL_SELECT)
                glPopName ;
        }
    }
}

void processHits (GL hits, GLu buffer)
{
    unsigned  i, j;
    GLu ii, jj, names, *ptr;

    prf ("hits = %d\\n", hits);
    ptr = (GLu *) buffer;
    for (i = 0; i < hits; i) { /* for each hit */
        names = *ptr;
        prf (" number of names for this hit = %d\\n", names);
        ptr;
        prf (

" z1 is %u;", *ptr); ptr;
        prf (" z2 is %u\\n", *ptr); ptr;
        prf (" names are ");
        for (j = 0; j < names; j) { /* for each name */
            prf ("%d ", *ptr);
             (j  0) /*  row and column */
                ii = *ptr;
              (j  1)
                jj = *ptr;
            ptr;
        }
        prf ("\\n");
        board[ii][jj] = (board[ii][jj] + 1) % 3;
    }
}

# BUFSIZE 512

void pickSquares(AUX_EVENTREC *event)
{
    GLu selectBuf[BUFSIZE];
    GL hits;
    GL viewport[4];
     x, y;

    x = event->data[AUX_MOUSEX];
    y = event->data[AUX_MOUSEY];
    glGetIntegerv (GL_VIEWPORT, viewport);

    glSelectBuffer (BUFSIZE, selectBuf);
    (void) glRenderMode (GL_SELECT);

    glInitNames;
    glPushName(-1);

    glMatrixMode (GL_PROJECTION);
    glPushMatrix ;
    glLoadIdentity ;
    /* create 5x5 pixel picking region near cursor location */
    gluPickMatrix((GLdouble) x,
    (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport);
    gluOrtho2D (0.0, 3.0, 0.0, 3.0);
    drawSquares (GL_SELECT);
    glPopMatrix ;
    glFlush ;

    hits = glRenderMode (GL_RENDER);
    processHits (hits, selectBuf);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    drawSquares (GL_RENDER);
    glFlush;
}

void myReshape(GLsizei w, GLsizei h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    gluOrtho2D (0.0, 3.0, 0.0, 3.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity;
}


 ( argc, char** argv)
{
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
    auxInitPosition (0, 0, 100, 100);
    auxInitWindow (argv[0]);
    myinit ;
    auxMouseFunc (AUX_LEFTBUTTON, AUX_MOUSEDOWN, pickSquares);
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
}

Picking with Multiple Names and a Hierarchical Model

Multiple names can also be used to choose parts of a hierarchical object in a scene. For example,  you were rendering an
assembly line of automobiles, you might want the user to move the mouse to pick the third bolt on the left front tire of the third
car in line. A dferent name can be used to identy each level of hierarchy: which car, which tire, and finally which bolt. As
another example, one name can be used to describe a single molecule among other molecules, and additional names can
dferentiate individual atoms within that molecule.

Example 12-4 is a modication of Example 3-4 that draws an automobile with four identical wheels, each of which has five
identical bolts. Code has been added to manipulate the name stack with the object hierarchy.



Example 12-4 : Creating Multiple Names

draw_wheel_and_bolts
{
    long i;

    draw_wheel_body;
    for (i = 0; i < 5; i) {
        glPushMatrix;
        glRotate(72.0*i, 0.0, 0.0, 1.0);
        glTranslatef(3.0, 0.0, 0.0);
        glPushName(i);
        draw_bolt_body;
        glPopName;
        glPopMatrix;
    }
}

draw_body_and_wheel_and_bolts
{
    draw_car_body;
    glPushMatrix;
    glTranslate(40, 0, 20); /* first wheel position*/
    glPushName(1); /* name of wheel number 1 */
    draw_wheel_and_bolts;
    glPopName;
    glPopMatrix;
    glPushMatrix;
    glTranslate(40, 0, -20); /* second wheel position */
    glPushName(2); /* name of wheel number 2 */
    draw_wheel_and_bolts;
    glPopName;
    glPopMatrix;

    /* draw last two wheels similarly */
}

Example 12-5 uses the routines in Example 12-4 to draw three dferent cars, numbered 1, 2, and 3.

Example 12-5 : Using Multiple Names

draw_three_cars
{
    glInitNames;
    glPushMatrix;
    translate_to_first_car_position;
    glPushName(1);
    draw_body_and_wheel_and_bolts;
    glPopName;
    glPopMatrix;

    glPushMatrix;
    translate_to_second_car_position;
    glPushName(2);
    draw_body_and_wheel_and_bolts;
    glPopName;
    glPopMatrix;

    glPushMatrix;
    translate_to_third_car_position;
    glPushName(3);
    draw_body_and_wheel_and_bolts;
    glPopName;
    glPopMatrix;
}

Assuming that picking is performed, the following are some possible name-stack  values and their erpretations. In
these examples, at most one hit record is ed; also, d1 and d2 are depth values.

empty The pick was outside all cars

2 d1d2 2 1 Car 2, wheel 1

1 d1d2 3 Car 3 body

3 d1d2 1 1 0 Bolt 0 on wheel 1 on car 1

The last erpretation assumes that the bolt and wheel don't occupy the same picking region. A user might well pick both the
wheel and the bolt, yielding two hits. If you receive multiple hits, you have to decide which hit to process, perhaps by using the
depth values to determine which picked object is closest to the viewpo. The use of depth values is explored further in the
next section.

Picking and Depth values

Example 12-6 demonstrates how to use depth values when picking to determine which object is picked. This program draws
three overlapping rectangles in normal rendering mode. When the left mouse button is pressed, the pickRects routine is
called. This routine s the cursor position, enters selection mode, initializes the name stack, and multiplies the picking
matrix onto the stack before the orthographic projection matrix. A selection hit occurs for each rectangle the cursor is over
when the left mouse button is clicked. Finally, the contents of the selection buffer is examined to identy which named objects


were within the picking region near the cursor.

The rectangles in this program are drawn at dferent depth, or z, values. Since only one name is used to identy all three
rectangles, only one hit can be recorded. However,  more than one rectangle is picked, that single hit has dferent minimum
and maximum z values.

Example 12-6 : Picking with Depth values: pickdepth.c

# <GL/gl.h>
# <GL/glu.h>
# "aux.h"

void myinit(void)
{
    glClearColor (0.0, 0.0, 0.0, 0.0);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_FLAT);
    glDepthRange (0.0, 1.0); /* The default z mapping */
}

void drawRects(GLenum mode)
{
     (mode  GL_SELECT)
        glLoadName (1);
    glBegin (GL_QUADS);
    glColor3f (1.0, 1.0, 0.0);
    glVertex3i (2, 0, 0);
    glVertex3i (2, 6, 0);
    glVertex3i (6, 6, 0);
    glVertex3i (6, 0, 0);
    glColor3f (0.0, 1.0, 1.0);
    glVertex3i (3, 2, -1);
    glVertex3i (3, 8, -1);
    glVertex3i (8, 8, -1);
    glVertex3i (8, 2, -1);
    glColor3f (1.0, 0.0, 1.0);
    glVertex3i (0, 2, -2);
    glVertex3i (0, 7, -2);
    glVertex3i (5, 7, -2);
    glVertex3i (5, 2, -2);
    glEnd ;
}

void processHits (GL hits, GLu buffer)
{
    unsigned  i, j;
    GLu names, *ptr;

    prf ("hits = %d\\n", hits);
    ptr = (GLu *) buffer;
    for (i = 0; i < hits; i) { /* for each hit */
        names = *ptr;
        prf (" number of names for hit = %d\\n", names);
        ptr;
        prf (" z1 is %u;", *ptr); ptr;
        prf (" z2 is %u\\n", *ptr); ptr;
        prf (" the name is ");
        for (j = 0; j < names; j) { /* for each name */
            prf ("%d ", *ptr); ptr;
        }
        prf ("\\n");
    }
}

# BUFSIZE 512

void pickRects(AUX_EVENTREC *event)
{
    GLu selectBuf[BUFSIZE];
    GL hits;
    GL viewport[4];
     x, y;

    x = event->data[AUX_MOUSEX];
    y = event->data[AUX_MOUSEY];
    glGetIntegerv (GL_VIEWPORT, viewport);

    glSelectBuffer (BUFSIZE, selectBuf);
    (void) glRenderMode (GL_SELECT);

    glInitNames;
    glPushName(-1);

    glMatrixMode (GL_PROJECTION);
    glPushMatrix ;
    glLoadIdentity ;
    /* create 5x5 pixel picking region near cursor location */
    gluPickMatrix ((GLdouble) x,
    (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport);
    glOrtho (0.0, 8.0, 0.0, 8.0, 0.0, 2.0);
    drawRects (GL_SELECT);
    glPopMatrix ;
    glFlush ;



    hits = glRenderMode (GL_RENDER);
    processHits (hits, selectBuf);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    drawRects (GL_RENDER);
    glFlush;
}

void myReshape(GLsizei w, GLsizei h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    glOrtho (0.0, 8.0, 0.0, 8.0, 0.0, 2.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity;
}


 ( argc, char** argv)
{
    auxInitDisplayMode (AUX_SINGLE | AUX_RGBA | AUX_DEPTH);
    auxInitPosition (0, 0, 100, 100);
    auxInitWindow (argv[0]);
    myinit ;
    auxMouseFunc (AUX_LEFTBUTTON, AUX_MOUSEDOWN, pickRects);
    auxReshapeFunc (myReshape);
    auxMainLoop(display);
}

Try This

Try This

Mody Example 12-6 to add additional calls to glPushName so that multiple names are on the stack when the
selection hit occurs. What will the contents of the selection buffer be?

By default, glDepthRange s the mapping of the z values to [0.0,1.0]. Try modying the glDepthRange values
and see how it affects the z values that are ed in the selection .gif' />.
-------------------------------------------------------------------------------
有关编写使用选择提示
Tags:  反馈表 负反馈 反馈抑制器 正反馈与负反馈

延伸阅读

最新评论

发表评论