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=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个\n",nPicks);
    ptr=pickBuffer;
    for(i=0;i<nPicks;i++)
    {
        name=*ptr;//选中图元在堆栈中的位置
        ptr+=3;//跳过名字和深度信息
        ptr+=name-1;//根据位置信息获得选中的图元名字
        if(*ptr==1)printf("你选择了红色图元\n");
        if(*ptr==2)printf("你选择了绿色图元\n");
        if(*ptr==3)printf("你选择了蓝色图元\n");
        ptr++;
    }
    printf("\n\n");
}

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;
}

时间: 2024-07-29 14:30:35

opengl中拾取操作的实现的相关文章

OpenGL中的拾取模式( Picking)

1. Opengl中的渲染模式有三种:(1)渲染模式,默认的模式:(2)选择模式, (3)反馈模式.如下 GLint glRenderMode(GLenum mode) mode可以选取以下三种模式之一:绘制模式(GL_RENDER),选择模式(GL_SELECT),反馈模式(GL_FEEDBACK). 函数的返回值可以确定选择模式下的命中次数或反馈模式下的图元数量. 2. OpenGL进行图形编程的时候,通常要用鼠标进行交互操作,比如用鼠标点选择画面中的物体,我们称之为拾取(Picking).

【转】D3D中详细拾取操作

Direct3D中实现图元的鼠标拾取 BY 重剑,2004.5.28 重剑空间 原文链接:http://dev.gameres.com/Program/Visual/3D/pick_2004_529.htm 索引: 1.什么是拾取,拾取能做什么? 2.拾取操作的步骤和实现 2.1.  变换并获得通过视点和屏幕上点击点的射线矢量(Dir) 2.1.1 确定鼠标选取点的屏幕坐标 2.1.2 得到Dir在观察坐标空间内的表示 2.1.3 转换Dir到世界坐标空间,并得到观察点在世界坐标系中的坐标 2.

OpenGL中平移、旋转、缩放矩阵堆栈操作

在OpenGL中,图元的几何变换均为线性变换,通过矩阵变换实现.OpenGL中的坐标用齐次坐标表示,即(x,y,z)表示成(x',y',z',h),其中x=x'/h; y=y'/h; z=z'/h. 通常h取1. 比如空间中的点(2,3,4),在OpenGL中将表示成(2,3,4,1). 齐次坐标表示方式适合于矩阵运算,也很方便地表示了无穷远的点,比如(1,0,0,0)就表示x轴上无穷远的点,因为1/0是无穷大,这里约定0/0=0. 例:点(1,1,1)将该向量平移变换(2,3,4)个单位,得到

OpenGL 中的三维纹理操作

#define _CRT_SECURE_NO_WARNINGS #include <gl/glut.h> #include <stdio.h> #include <stdlib.h> #define WindowWidth 400 #define WindowHeight 400 #define WindowTitle "OpenGL纹理测试" /* 函数grab * 抓取窗口中的像素 * 假设窗口宽度为WindowWidth,高度为WindowHe

折腾了两天的拾取操作。。。

啊哈,折腾了两天opengl上的拾取操作,总算是找到问题了. 一开始是能拾取的但是selectbuffer中的记录总是不对,开始还以为只是拾取函数出问题了,然后仔细看了遍红宝书,按照红宝书中的步骤走了一遍,还是出错...然后就开始考虑是不是之前用了glulookat视图变换的问题,索性不用这个函数了,也就是视图变换采用默认,还是出错...然后不断的改代码,不断地debug...终于找到问题了,丫的,在 gluPickMatrix(point.x,viewport[3]-point.y,5.0,5

OpenGL中实现双缓冲技术

在OpenGL中实现双缓冲技术的一种简单方法: 1.在调用glutInitDisplayMode函数时, 开启GLUT_DOUBLE,即glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);.这里将我们惯用的GLUT_SINGLE替换为GLUT_DOUBLE,意为要使用双缓冲而非单缓冲. 2. 调用glutDisplayFunc(display)注册回调函数时, 在回调函数中所有绘制操作完成后调用glutSwapBuffers()交换两个缓冲区指针. 3. 调用

OpenGL中的颜色混合功能(一)

我们知道,材料属性和光照参数可以极大地增加图形的逼真度,但除此之外,我们在对现实世界进行建模时,有许多效果是通过混合颜色的方式实现的.透明的物体,像是玻璃水杯,在它后面发射过来的光会与透明物体的颜色混合在一起.这种透明在OpenGL中的实现方式,是通过首先绘制背景物体,然后把前景物体(比如水杯)与颜色缓冲区中已经存在的颜色进行混合而实现的.在这一过程中,颜色的alpha值成分发挥了重要作用. 颜色的混合功能 在一般情况下,OpenGL在渲染时把颜色值存放在颜色缓冲区中,把每个片段(像素)的深度值

OpenGL中的多重采样

抗锯齿处理的最大优点之一就是它能够使多边形的边缘更为平滑,使渲染效果显得更为逼真和自然.点和直线的抗锯齿处理是得到广泛支持的,但遗憾的是,对多边形的平滑处理并没有在所有平台上都得到实现.并且,即使在可以使用GL_POLYGON_SMOOTH的时候,对整个场景进行抗锯齿处理也没有想象中的那么方便.这是因为,抗锯齿处理是基于混合操作的,这就需要从前到后对所有的图元进行排序,这是十分麻烦的. 在OpenGL中还有一个功能,称为多重采样(multisampling),可以用来解决抗锯齿处理中的这个问题.

opengl中场景变换|2D与3D互转换(转)

opengl中场景变换|2D与3D互转换 我们生活在一个三维的世界——如果要观察一个物体,我们可以: 1.从不同的位置去观察它.(视图变换) 2.移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它.(模型变换) 3.如果把物体画下来,我们可以选择:是否需要一种“近大远小”的透视效果.另外,我们可能只希望看到物体的一部分,而不是全部(剪裁).(投影变换) 4.我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部.(视口变换) 这些,都可以在OpenGL中实