opengl中鼠标拾取操作分析

来源:互联网 发布:游戏王网络对战 编辑:程序博客网 时间:2024/05/22 15:53

     

   在进行Opengl编程时,通常会进行一些交互式操作,其中的鼠标拾取技术可以实现对目标物体的选取和判断,为开发者和用户带来便利。下面笔者就对这当中的一些核心代码进行总结和分析。

     Opengl中的拾取是对opengl管线的一个应用,所以这个过程并不是想象中利用射线求交来判断是否选中目标物体,而是利用投影变换阶段的拾取矩阵进行的。

 

     由于我的工程是在mfc环境下进行的,所以我只列出核心代码并进行分析,不过只要读者真正理解了这部分代码,相信这个功能也就很好的实现了。

 

     int  mouse_x ,mouse_Y;   //鼠标位置

     GLuint   buffer[512];        //设定一个选择缓冲区

      GLint    hits;                 //被选中的物体的数量

 

     voidSelection(void//拾取

{

 

        GLint viewport[4];      //视口的大小,四个值分别为,x,y,width,height;

        glGetIntegerv(GL_VIEWPORT,viewport);     

        glSelectBuffer(512, buffer);  

   

        (void) glRenderMode(GL_SELECT);  //拾取前,要进入进入选择模式

 

         glInitNames();      //初始化名字栈,主要用来存放目标物体的名字

         glPushName(0);      //在名字栈里放入一个初始化名字

   

         glMatrixMode(GL_PROJECTION); //选择投影矩阵,我前面说过,判断是以投影的形式进行的

         glPushMatrix();           //压入投影矩阵

         glLoadIdentity();     // Resets The Matrix 重置矩阵,为了使构建拾取矩阵

  gluPickMatrix((GLdouble)mouse_x,    //建立拾取矩阵

(GLdouble) (viewport[3]-mouse_y),//窗口坐标转化为opengl坐标

                    1.0f, 1.0f,                 //选择框的大小

viewport);      //视口的位置和大小

 

   

    gluPerspective(45.0f, (GLfloat) (viewport[2]-viewport[0])/(GLfloat) (viewport[3]-viewport[1]), 0.01f, 1200.0f); //乘以投影矩阵

   

    glMatrixMode(GL_MODELVIEW);    //进入视图变换状态

    Draw(GL_SELECT);//该函数是用来渲染物体,也就是你自己要绘制的物体,包括名字                

    glMatrixMode(GL_PROJECTION);//投影变换状态

    glPopMatrix();        // 进入之前的投影状态,因为以上都是绘制时的状态

    glMatrixMode(GL_MODELVIEW);    

    hits=glRenderMode(GL_RENDER);  // 获得选中物体的个数

                                                 

 

    ProcessHits(hits,buffer);    //对选中的物体进行处理

}

 

void  ProcessHits(GLinthits, GLuintbuffer[])

{

    if (hits > 0)              // 如果选中物体数目大于0

    {

       int choose = buffer[3];      //buffer第一个值为选中物体的的个数,第二个、第三个表示物体的最小深度和最大深度,第四个为选中的名字  

       int depth = buffer[1];                

 

       for (intloop = 1; loop <hits; loop++)             

       {

           if (buffer[loop*4+1] <GLuint(depth)) //判断当前的物体是否离我们最近

           {

              choose = buffer[loop*4+3];               

              depth = buffer[loop*4+1];         

           }      

       }

       //

       添加自己的处理代码

    }

}

 

void  Draw(GLenummodel)

{

    if (model ==GL_SELECT)

    {

       glLoadName(1);

    }

//添加物体1代码

    if (model ==GL_SELECT)

    {

       glLoadName(2);

    }

//添加物体2代码

   

}

 

希望通过上面的代码大家可以有所收获,不对之处还望更正。