opengl中拾取操作的实现
opengl采用一种比较复杂的方式来实现拾取操作,即选择模式。选择模式是一种绘制模式,它的基本思想是在一次拾取操作时,系统会根据拾取操作的参数(如鼠标位置)生成一个特定视景体,然后又系统重新绘制场景中的所有图元,但这些图元并不会绘制到颜色缓存中,系统跟踪有哪些图元绘制到了这个特定的视景体中,并将这些对象的标识符保存到拾取缓冲区数组中。
步骤:
1、设置拾取缓冲区:void glSelectBuffer(GLsizei n,GLunint *buff);
2、进入选择模式:指定选择模式采用函数:GLint glRenderMode(GLenum mode);
3、名字堆栈操作:
初始化名字堆栈:void glInitNames();
压栈:void glPushNmae(GLuint name);
弹栈:void glLoadName(GLuint name);
出栈:void glPopNmae();
4、设置合适的变换过程:矩形拾取窗口来实现拾取:gluPickMatrix(xPick,yPick,widthPick,heightPick,*vp);
5、位每个图元分配名字并绘制
6、切换回渲染模式
7、分析选择缓冲区中的数据
程序如下:
#include"gl/glut.h"
#include"stdio.h"
#include"iostream"
using namespace std;
const GLint pickSize=;//拾取缓冲区的大小
int winWidth=,winHeight=;
void Initial(void)
{
glClearColor(1.0f,1.0f,1.0f,1.0f);
}
//按照指定的模式绘制矩形对象
void DrawRect(GLenum mode)
{
if(mode==GL_SELECT)glPushName();//将名字1压入堆栈
glColor3f(1.0f,0.0f,0.0f);
glRectf(60.0f,50.0f,150.0f,150.0f);//绘制红色矩形
if(mode==GL_SELECT)glPushName();//将名字2压入堆栈
glColor3f(0.0f,1.0f,0.0f);
glRectf(230.0f,50.0f,330.0f,150.0f);//绘制绿色矩形
if(mode==GL_SELECT)glPushName();//将名字3压入堆栈
glColor3f(0.0f,0.0f,1.0f);
glRectf(140.0f,140.0f,240.0f,240.0f);//绘制蓝色矩形
}
void ProcessPicks(GLint nPicks,GLuint pickBuffer[])
{
GLint i;
GLuint name,*ptr;
printf("选中的数目为%d个\n",nPicks);
ptr=pickBuffer;
for(i=;i<nPicks;i++)
{
name=*ptr;//选中图元在堆栈中的位置
ptr+=;//跳过名字和深度信息
ptr+=name-;//根据位置信息获得选中的图元名字
if(*ptr==)printf("你选择了红色图元\n");
if(*ptr==)printf("你选择了绿色图元\n");
if(*ptr==)printf("你选择了蓝色图元\n");
ptr++;
}
printf("\n\n");
} void ChangeSize(int w,int h)
{
winWidth=w;
winHeight=h;
glViewport(,,w,h);//指定视区,即指定窗口中用于图形显示的区域
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,winWidth,0.0,winHeight);
}
void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
DrawRect(GL_RENDER);//用渲染模式绘制图形
glFlush();
}
void MousePlot(GLint button,GLint action,GLint xMouse,GLint yMouse)
{
GLuint pickBuffer[pickSize];
GLint nPicks,vp[];
if(button==GLUT_LEFT_BUTTON&&action==GLUT_DOWN)
{
glSelectBuffer(pickSize,pickBuffer);//设置选择缓冲区
glRenderMode(GL_SELECT);//激活选择模式
glInitNames();//初始化名字堆栈
glMatrixMode(GL_PROJECTION);
glPushMatrix();//将当前的投影矩阵复制一个并压入堆栈
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT,vp);//获得当前窗口显示区域的参数
//定义一个10*10的选择区域
gluPickMatrix(GLdouble(xMouse),GLdouble(vp[]-yMouse),10.0,10.0,vp);
gluOrtho2D(0.0,winWidth,0.0,winHeight);
DrawRect(GL_SELECT);//用选择模式绘制图形
//恢复投影变换
glMatrixMode(GL_PROJECTION);
glPopMatrix();//将投影矩阵堆栈中的栈顶元素删除
glFlush();
//获得选择集并输出
nPicks=glRenderMode(GL_RENDER);
ProcessPicks(nPicks,pickBuffer);//输出选择结果
glutPostRedisplay(); }
}
int main(int argc,char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(,);
glutInitWindowPosition(,);
glutCreateWindow("拾取操作");
glutDisplayFunc(Display);
glutReshapeFunc(ChangeSize);
glutMouseFunc(MousePlot);
Initial();
glutMainLoop();
return ;
}
opengl中拾取操作的实现的更多相关文章
- Qt OpenGL 鼠标拾取实现
在之前的文章中讲到了OpenGL鼠标拾取操作的例子,工作中需要在Qt中实现,下面的程序演示了QT中opengl的拾取例子. 本例子在Qt5.12和Qt Creator4.8.0上测试,使用的是QOpe ...
- OpenGL中的拾取模式( Picking)
1. Opengl中的渲染模式有三种:(1)渲染模式,默认的模式:(2)选择模式, (3)反馈模式.如下 GLint glRenderMode(GLenum mode) mode可以选取以下三种模式之 ...
- OpenGL中位图的操作(glReadPixels,glDrawPixels等)
OpenGL中位图的操作 OpenGL中位图的操作(glReadPixels,glDrawPixels和glCopyPixels应用举例). 1. BMP文件格式简单介绍 BMP文件是一种像素文件,它 ...
- OpenGL中平移、旋转、缩放矩阵堆栈操作
在OpenGL中,图元的几何变换均为线性变换,通过矩阵变换实现.OpenGL中的坐标用齐次坐标表示,即(x,y,z)表示成(x',y',z',h),其中x=x'/h; y=y'/h; z=z'/h. ...
- OpenGL 中的三维纹理操作
#define _CRT_SECURE_NO_WARNINGS #include <gl/glut.h> #include <stdio.h> #include <std ...
- openGL中的gl,glu,glut
OpenGL函数库相关的API有核心库(gl).实用库(glu).辅助库(aux).实用工具库(glut).窗口库(glx.agl.wgl)和扩展函数库等.gl是核心,glu是对gl的部分封装.glx ...
- CSharpGL(26)在opengl中实现控件布局/渲染文字
CSharpGL(26)在opengl中实现控件布局/渲染文字 效果图 如图所示,可以将文字.坐标轴固定在窗口的一角. 下载 CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入( ...
- OpenGL中实现双缓冲技术
在OpenGL中实现双缓冲技术的一种简单方法: 1.在调用glutInitDisplayMode函数时, 开启GLUT_DOUBLE,即glutInitDisplayMode(GLUT_RGB | G ...
- OpenGL中各种坐标系的理解[转]
OPENGL坐标系可分为:世界坐标系和当前绘图坐标系. 世界坐标系:在OpenGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的.你面对 屏幕,你的右边是x正轴,上面是y正轴,屏幕 ...
随机推荐
- codeforces A. K-Periodic Array 解题报告
题目链接:http://codeforces.com/problemset/problem/371/A 题目意思:给出n和k和一个只有1或者2组成的序列,需要求出最少的改变次数,使得 n/k 组里面的 ...
- Spring MVC前台使用html页面作为视图,配置静态资源后Controller控制器不起作用的解决办法
1.Spring MVC搭建项目的时候,想使用html页面作为前端的视图,你会发现html页面不能访问,原因是由于Spring拦截器将其拦截寻找控制器的缘故,解决办法就是配置静态资源: <mvc ...
- 使用apktool工具遇到could not decode arsc file的解决办法
问题详情: 当前环境为 win7 64位 jdk1.7 apktool.jar(版本1.5.2) apktool(版本windows-r05-ibot) 使用的反编译工具和apk文件为 反编译 ...
- iOS设备通知中心精品推荐消息删除
如要彻底解决这个问题可以通过手机连接PC端91助手—功能大全—文件管理,进入/Library/MobileSubstrate/DynamicLibraries 文件夹,把AppSafety开头的文件都 ...
- 【读书笔记】读《JavaScript高级程序设计-第2版》 - 非函数部分
章节列表: 第08章:BOM 第09章:客户端检测 第10章:DOM 第11章:DOM2和DOM3 第12章:事件 第13章:表单脚本 第14章:错误处理与调试 第17章:Ajax和JSON第20章: ...
- 二、JavaScript语言--JS基础--JavaScript进阶篇--JS基础语法
1.变量 定义:从字面上看,变量是可变的量:从编程角度讲,变量是用于存储某种/某些数值的存储器.我们可以把变量看做一个盒子,盒子用来存放物品,物品可以是衣服.玩具.水果...等. 命名:变量名字可以任 ...
- php 工厂模式
<body> <?php //设计模式:工厂模式 /* class YunSuan { public $a; public $b; function Jia() { return ( ...
- angularjs教程
http://www.runoob.com/angularjs/angularjs-routing.htmlA
- PHP使用七牛云存储之图片的上传、下载、303重定向教程,CI框架实例
网上关于七牛云存储的教程除了官网上的API文档,其他的资料太少了.研究了下API之后,现在已经能实现图片的上传和下载及上传之后的重定向. http://blog.csdn.net/cqcre/arti ...
- Codeforces Round #313 (Div. 2) C. Gerald's Hexagon 数学
C. Gerald's Hexagon Time Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/559/pr ...