zoukankan      html  css  js  c++  java
  • 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个
    ",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
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 奇偶判断
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Qt: 访问容器(三种方法,加上for循环就四种了)good
  • 原文地址:https://www.cnblogs.com/acm-jing/p/4374331.html
Copyright © 2011-2022 走看看