opengl中拾取操作的实现

摘要:
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、分析选择缓冲区中的数据

程序如下:

opengl中拾取操作的实现第1张opengl中拾取操作的实现第2张
#include"gl/glut.h"
#include"stdio.h"
#include"iostream"
using namespace std;
const GLint pickSize=32;//拾取缓冲区的大小
int winWidth=400,winHeight=300;
void Initial(void)
{
    glClearColor(1.0f,1.0f,1.0f,1.0f);
}
//按照指定的模式绘制矩形对象
void DrawRect(GLenum mode)
{
    if(mode==GL_SELECT)glPushName(1);//将名字1压入堆栈
    glColor3f(1.0f,0.0f,0.0f);
    glRectf(60.0f,50.0f,150.0f,150.0f);//绘制红色矩形
    if(mode==GL_SELECT)glPushName(2);//将名字2压入堆栈
    glColor3f(0.0f,1.0f,0.0f);
    glRectf(230.0f,50.0f,330.0f,150.0f);//绘制绿色矩形
    if(mode==GL_SELECT)glPushName(3);//将名字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个
",nPicks);
    ptr=pickBuffer;
    for(i=0;i<nPicks;i++)
    {
        name=*ptr;//选中图元在堆栈中的位置
        ptr+=3;//跳过名字和深度信息
        ptr+=name-1;//根据位置信息获得选中的图元名字
        if(*ptr==1)printf("你选择了红色图元
");
        if(*ptr==2)printf("你选择了绿色图元
");
        if(*ptr==3)printf("你选择了蓝色图元
");
        ptr++;
    }
    printf("

");
}

void ChangeSize(int w,int h)
{
    winWidth=w;
    winHeight=h;
    glViewport(0,0,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[4];
    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[3]-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(400,300);
    glutInitWindowPosition(100,100);
    glutCreateWindow("拾取操作");
    glutDisplayFunc(Display);
    glutReshapeFunc(ChangeSize);
    glutMouseFunc(MousePlot);
    Initial();
    glutMainLoop();
    return 0;
}
View Code

免责声明:文章转载自《opengl中拾取操作的实现》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Maven学习总结(四):更改maven的编码格式方式Centos7搭建日志服务器rsyslog+loganalyzer下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

GDB堆栈跟踪与汇编调试

GDB堆栈跟踪与汇编调试 堆栈跟踪 源代码: 对预先编写的 stack.c 文件进行编译,并且使用 CGDB 进行调试,对堆栈进行跟踪,了解该代码堆栈是如何变化的。 在 CGDB 中,先设置 main 断点,接着运行(run),使用 frameinfo frame 分别查看当前栈帧的简要信息,以及该栈帧的详细信息。其中: frame 打印出的信息:...

OpenGL的glViewport视口变换函数详解[转]

调用glViewPort函数来决定视见区域,告诉OpenGL应把渲染之后的图形绘制在窗体的哪个部位。当视见区域是整个窗体时,OpenGL将把渲染结果绘制到整个窗口。 voidglViewPort(GLInt x; GLInty; GLSizeiWidth; GLSizeiHeight);     其中,参数X,Y指定了视见区域的左下角在窗口中的位置,一般情...

【OpenGL】学习笔记#1

没事干总要学点东西,这个系列的文章既是我的笔记,又是一篇教程(给我自己的教程),主干内容参考一篇国外教程,教程很粗略,但是代码不错,所以我借着它的脉络,补充网上的资料来扩充内容,每一句话都要理解是什么意思,还有实现的原理。不定期更新,国外教程网址在文末,有兴趣的同学可以去看看。 一、OpenGL简介 OpenGL是一套开放图形库API(的标准),因此可以跨...

WebGL的第二个小程序

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <...

脱壳实践之寻找OEP——堆栈平衡法

 0x00 前言   上一篇介绍了壳程序的加载过程以及通过两次内存断点法寻找OEP,这篇我们将利用新的的方法——堆栈平衡法来寻找OEP。 0x01 堆栈平衡法原理   堆栈平衡原理就是利用壳程序在运行前后需要保存和恢复原程序的堆栈环境来实现的。我们可以把壳程序当作一个子程序,调用这个子程序前,肯定需要保存原程序的堆栈环境,子程序调用完毕之后,就需要pop处...

实现对第三方应用任意SO注入

实现对第三方应用任意SO注入 0x01 应用在Android中运行,从外部对该进程可以进行任意SO文件动态注入,就是应用动态运行我们的SO文件 0x02 基本的逻辑是: 1.    获取目标进程的pid,关联目标进程:通过遍历查找/proc/pid/cmdline文件中是否含有目标进程名process_name,若有则进程名对应的进程号即为pid。接着,直...