以下内容主要整理《OpenGL编程指南》第13章的内容。主要解决以下问题:
(1)如何允许用户选择屏幕上的一块区域或者挑选屏幕上所绘制的一个物体?
一. 选择
1. OpenGL的选择机制如何实现
当我们打算使用OpenGL的选择机制时:
(1)首先把整个场景绘制到帧缓冲区中;
(2)然后进入选择模式,并且对场景进行重绘,此时,帧缓冲区的内容将不会被修改;
(3)退出选择模式时,OpenGL就会返回与视景体相交的图元列表,与视景体相交的每一个图元都产生一个所谓的“选择点击”。
2. 基本步骤
//在绘制了场景之后,进入以下步骤
(1)
#define BUFSIZE 512
GLuint selectBuf[BUFSIZE];
glSelectBuffer( BUFSIZE, selectBuf );
(2)
glRenderMode( GL_SELECT );
(3)
glInitNames();
glPushName();
(4)
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,5.0,0.0,5.0,0.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
(5)
glLoadName(1);
drawTri();
glLoadName(2);
drawTri();
glLoadName(3);
drawTri();
drawTri();
(6)
glPopMatrix();
glFlush();
(7)
//返回绘制模式,hits记录的是产生的点击的个数,即在视景体内的图元的个数
Gluint hits = glRenderMode(GL_RENDER);
(8)
//处理点击记录
printf("hits = %d\n", hits); //输出一共产生的点击的个数
//注意:
//图元列表(点击记录)selectBuf中记录了所有的点击记录
//某一个点击记录来说,由四个项目组成:
//(1)当点击发生时,名字堆栈中的名称数量
//(2)自上一个点击记录之后,与视景体相交的所有顶点的最小和最大窗口坐标z值
//(3)当点击发生时,名称堆栈的内容,从最底部的元素开始
GLuint *ptr = selectBuf;
GLuint names;
for( i=0; i<hits; i++ )
{
}
二. 拾取
1. 如何拾取
前一节介绍了OpenGL的选择机制如何实现和使用,这一节将深入的介绍如何利用选择模式来确定一个物体是否被挑选。
为了实现这个目的,可以在选择模式中使用一个特殊的挑选矩阵,结合投影矩阵,把绘图限制在视口的一个小区域内,一般是在靠近光标的位置。这样,只有靠近光标位置的物体才会引起点击。
gluPickMatrix( GLdouble x, GLdouble y, GLdouble width, GLdouble height, GLint viewport[4] );
(x,y)就是挑选区域的中心的窗口坐标,width和height定义了屏幕坐标下这个挑选区域的大小,viewport是指视口边界,通过glGeIntegerv(GL_VIEWPORT, GLint *viewport)获得
(2) 具体实例
下面,用OpenGL编程指南上的实例来介绍如何实现拾取。
//该程序完成的功能是:绘制9个方块,鼠标左键点击,改变方块的颜色
#include <gl/glut.h>
int board[3][3];
#define BUFSIZE 512
//处理点击记录:
//hits为产生的点击的数量,buffer中存储点击记录,每个点击记录由四个项目组成
void processHits(GLint hits, GLuint buffer[])
{
//(1)当点击发生时,名字堆栈中的名称数量
//(2)自上一个点击记录之后,与视景体相交的所有顶点的最小和最大窗口坐标z值
//(3)当点击发生时,名称堆栈的内容,从最底部的元素开始
}
//绘制所有方块,参数有GL_RENDER和GL_SELECT两种模式
void drawSquares(GLenum mode)
{
}
//当鼠标左键点击窗口时,进入选择模式开始绘制;绘制之后,处理点击记录
void pickSquares(int button, int state, int x, int y)
{
//处理点击记录
}
void init()
{
}
void display()
{
}
void reshape( int w, int h )
{
}
int main(int argc, char ** argv)
{
}