文章标题

OPENGL 鼠标拾取基础

拾取模式

基本的思路如下,这里的选择模式是OpenGL API 提供的特别绘制模式
* 得到鼠标点击位置的窗口坐标
* 进入选择模式
* 重新定义观察体
* 绘制场景
* 退出选择模式

名字堆栈

为了识别绘制的物体,必须对场景中的相关物体进行重命名。当进入到选择模式的时候,物体的名字被收集到一个数组里,对于未命名的物体,则只有深度信息被收集。

我们绘制一个雪人先,6*6 排布的36个雪人 头和身子分开绘制,如何制定名字堆栈?

    #define BODY
    #define HEAD
    ...
    void renderInSelectionMode()
    {
        glInitNames();
        glPushName(BODY);
        drawBody();
        glPushName();
        drawHead();
        drawEyes();
        glPopName();
        drawGround();
}

函数详解与补充:
1. void glInitNames(); 创建名字堆栈并初始化,必须在其他所有名字操作前被调用
2. void glPushname(GLuint name); 压入名字到堆栈 至少能容纳64个,溢出报错:GL_STACK_OVERFLOW
3. void glPopName(); 栈顶去掉名字 空栈中执行此操作:GL_STACK_UNDER_FLOW
4. void glLoadName(GLuint name); 等价于glPopName()和glPushName(name) 连用
-注意-
* 以上函数在非选择模式将被忽略
* 不能再glBegin 和 glEnd 间放置这些函数
* 支持多重命名和层次命名
如:

    for(int i=-3;i<3i++)
        glPushName(i);
            for(int j=-3;j<3;j++){
            glPushName(j);
            glTranslate(i*10.0,0.0,j*10.0);
            glCallList(snowmanDL);
            glPopName();
            glPopMatrix();
            }
        glPopName();
            }

这样当鼠标击中雪人时,就会得到两个名字,行数和列数

选择模式

现在我们介绍了Opengl的命名机制,下面进入为拾取设计的选择模式
下面代码给出了进入选择模式和开始拾取的所有操作,稍作修改你可以把上面代码用到自己的应用程序,但只在进入绘制模式时,在任何图形元素被绘制之前

#define BUFSIZE 512
GLuint selectBuf[BUFSIZE];
...
void startPicking(int cursorX,int cuesorY)
{   
    GL int viewport[4];
    glSelectBuffer(BUFSIZE,selectBuf);
    glRenderMode(GL_SELECT);
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glGetIntegerv(GL_VIEWPOINT,viewport);
    glPickMatrix(cursorX,viewport[3]-cursorY,5,5,viewport);
    gluPerspective(60,1,0.1,1000);
    glMatrixMode(GL_MODELVIEW);
    glInitName();
    }


  • 先告诉OpenGL 击中的保存地点:
    void glSelectBuffer(GLsizei size,GLuint*buffer);
  • 用下面函数进入选择模式 void glRenderMode(GLeum mode);
    参数: mode 使用GL-SELECT GL_RENDER来在选择模式和正常绘制模式之间做切换
  • 应用程序需要重新定义观察体,使得只有鼠标邻近的位置被绘制,为了实现这一点,需要将矩阵模式设置为CL-PROJECTION ,然后将投影矩阵变为单位矩阵,
  • 定义观察体。使得只有光标附件的小区域被绘制void gluPickMatrix(GL double x,GLdouble y,GLdouble width,GLdouble height,GLint viewport[4]);

    参数:x,y 定义光标位置,注意opengl的窗口原点坐标在左下角 而操作系统一般在左上角,所以减去y width height 当前视区的尺寸 viewport 当前视区
    所以在调取当前函数前,先用glGetIntegerv() 获取当前视区尺寸
  • 设置投影(和正常绘制一样流程)
  • 切换到GL_MODELVIEW,并初始化名字堆栈,开始绘制
glRenderMode(GL_RENDE);//返回正常模式,这个函数将返回在选择模式下创建击中的个数,在这之后应用程序才可以开始处理缓存,由于在进入选择模式之前已经push了矩阵,现在只需要pop一下,进行恢复
void stopPicking(){
    int hits;
    //重新载入原来的投影矩阵
    glMatrixMode(GL_PROJECTION);
    glPopMatrix;
    glMatrixMode(GL_MODEVIEW);
    glFlush();
    //返回法线绘制模型
    hits=glRenderMode(GL_RENDER);
    //如果有hit执行它们
    if(hits!=0)
        prosessHit(hits,sesectBuf);
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值