OpenGL从1.0开始--拾取操作
来源:互联网 发布:收购淘宝店铺的网站 编辑:程序博客网 时间:2024/06/10 04:18
基本上,拾取操作是通过一个修正观察体来实现的,而这个观察体根据一个指定的拾取窗口形成。我们队一个场景内的对象用整数进行标识。所有与观察体相交的对象的标识符都保存在一个拾取缓冲区数组中。因此,为了使用OpenGL的拾取功能,我们必须在程序中包含以下过程:
1.创建并显示一个场景
2.拾取一个屏幕位置,并且在鼠标回调函数内部进行如下操作:
设置一个拾取缓冲区
激活拾取操作(选择模式)
为对象标识符初始化一个ID名称栈
保存当前的观察和几何变换矩阵
指定鼠标输入的拾取窗口
给对象分配标识符然后用观察体在处理一次场景,从而将拾取信息存储到拾取缓冲区中
恢复原来的观察和几何变换矩阵
确定被拾取的对象的数目,然后返回正常的绘制模式
处理拾取信息
以下命令用来设置一个拾取缓冲区:
glSelectBuffer(pickBuffSize,pickBuffer);
参数pickBuffer指定一个具有pickBufferSize个元素的整形数组。对于每次拾取选中的每一个对象,向拾取缓冲区数组中添加一个整数信息记录。拾取缓冲区中的每一条记录包含如下信息:
1.对象在名称栈中的位置,即名称栈中位于该对象之下的标识符数目。
2.拾取对象的最小深度。
3.拾取对象的最大深度。
4.从名称栈中第一个标识符(底部)到拾取对象的标识符之间的所有标识符的列表。
OpenGL的拾取操作由以下命令激活:
glRenderMode(GL_SELECT);
这个命令将当前模式设置为选择模式,即一个场景虽然通过观察流水线的处理,但是并不存储在帧缓存中。将参数改为GL_RENDER就可以将当前模式设置为正常的绘制模式,将参数改为GL_FEEDBACK则将对象的坐标及其他信息存储到一个反馈缓冲区中。
以下命令用于激活拾取操作的整型ID名称栈:
glInitname();
向栈顶放入一个无符号整数值:
glPushNames(ID);
替换栈顶:
glLoadName(ID);
定义拾取窗口:
gluPickMatrix(xPick,yPick,widthPick,heightPick,vpArray);
前两个参数给出了拾取窗口中心的坐标值,后两个窗口指定拾取窗口的宽和高。最后一个参数指定一个包含当前拾取的坐标位置和尺寸等参数的整型数组。
我们来看下一个示例:
#include <Gl/glut.h>#include <stdio.h>const GLint pickBuffsize = 32;GLsizei winWidth = 400, winHeight = 400;void init(){ glClearColor(1.0, 0.0, 1.0, 1.0);}void rects(GLenum mode){ if (mode == GL_SELECT) glPushName(30);//向栈中放入一个无符号整型 glColor3f(1.0, 0.0, 0.0); glRecti(40, 130, 150, 260); if (mode == GL_SELECT) glPushName(10); glColor3f(0.0, 0.0, 1.0); glRecti(150, 130, 260, 260); if (mode == GL_SELECT) glPushName(20); glColor3f(0.0, 1.0, 0.0); glRecti(40, 40, 260, 130);}void processPicks(GLint nPicks, GLuint pickBuffer[]){ GLint j, k; GLuint objID, *ptr; printf("Number of objects picked=%d\n", nPicks); printf("\n"); ptr = pickBuffer; for (j = 0; j < nPicks;j++) { objID = *ptr; printf("Stack position=%d\n", objID); ptr++; printf("Min depth=%g,", float(*ptr / 0x7fffffff)); ptr++; printf("Max depth=%g\n", float(*ptr / 0x7fffffff)); ptr++; printf("Stack IDs are:\n"); for (k = 0; k < objID; k++) { printf("%d", *ptr); ptr++; } printf("\n\n"); }}void pickRects(GLint button, GLint action, GLint xMouse, GLint yMouse)//鼠标消息回调函数{ GLuint pickBuffer[pickBuffsize]; GLint nPicks, vpArray[4]; if (button != GLUT_LEFT_BUTTON || action != GLUT_DOWN) return; glSelectBuffer(pickBuffsize, pickBuffer);//设置缓冲区数组 glRenderMode(GL_SELECT);//激活选择模式 glInitNames();//初始化名称栈 glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glGetIntegerv(GL_VIEWPORT, vpArray);//获得视口属性 gluPickMatrix(GLdouble(xMouse), GLdouble(vpArray[3] - yMouse), 5.0, 5.0, vpArray);//设置拾取窗口 gluOrtho2D(0.0, 300.0, 0.0, 300.0); rects(GL_SELECT); glMatrixMode(GL_PROJECTION); glPopMatrix(); glFlush(); nPicks = glRenderMode(GL_RENDER);//获取选中的对象数量 processPicks(nPicks, pickBuffer);//打印缓冲区数据 glutPostRedisplay();}void displayFcn(void){ glClear(GL_COLOR_BUFFER_BIT); rects(GL_RENDER); glFlush();}void winReshapeFcn(GLint newWidth, GLint newHeight){ glViewport(0, 0, newWidth, newHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, GLdouble(newWidth), 0.0, GLdouble(newHeight)); winWidth = newWidth; winHeight = newHeight;}void main(int argc, char**argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(100, 100); glutInitWindowSize(winWidth, winHeight); glutCreateWindow("An Example OpenGL Program"); init(); glutDisplayFunc(displayFcn); glutReshapeFunc(winReshapeFcn); glutMouseFunc(pickRects);//响应鼠标消息 glutMainLoop();//启动主循环,等待消息}
这个程序显示了红、蓝、绿三个矩形,我们定义了一个5*5的选择窗口并通过拾取操作选中了三个矩形并打输出了缓冲区信息。
- OpenGL从1.0开始--拾取操作
- OpenGL拾取操作流程
- 拾取操作的实现[OpenGL]
- opengl中鼠标拾取操作分析
- OpenGL拾取
- OpenGL从1.0开始--输出图元
- OpenGL从1.0开始--绘制常用统计图
- OpenGL从1.0开始--曲线图形
- OpenGL从1.0开始--颜色调和
- OpenGL从1.0开始--填充区属性
- OpenGL从1.0开始--二维几何变换
- OpenGL从1.0开始--二维观察
- OpenGL从1.0开始--三维观察
- OpenGL从1.0开始--计算机动画
- OpenGL从1.0开始--绘制规则多面体
- OpenGL从1.0开始--绘制二次曲面
- OpenGL从1.0开始--GLUT菜单
- OpenGL从1.0开始--第一个OpenGL程序
- Laravel 创建指定表 migrate
- caffe拷贝权重之Check failed: param_size <= num_param_blobs (2 vs. 1)
- java设计模式之适配器模式
- 注册表限制软件使用次数
- CAS操作
- OpenGL从1.0开始--拾取操作
- 数论练习--日常更新
- 阿里云HotFix热修复应用
- TortoiseSVN入门
- mui的下拉刷新的用法及其解决双滚动的办法
- jQuery的函数,有些直接就用$this(表示当前操作的标签),而也不见this在哪里定义过,这个this究竟谁什么?答:把this当成在内从中存在的JavaScript的一个变量即可,一个关键字
- .word说明
- Jenkins+github+maven自动构建发布SpringBoot项目
- android-studio 复制项目到新的路径 Installation fail问题解决