zoukankan      html  css  js  c++  java
  • GLUT Tutorials 9: GLUT鼠标

    博客转自:https://www.cnblogs.com/yangxi/archive/2011/09/16/2178499.html

    在前几节,我们看了怎么使用GLUT的keyboard函数,来增加一个OpenGL程序的交互性。现在,是时候研究下鼠标了。GLUT的鼠标接口提供一些列的选项来增加鼠标的交互性。也就是检测鼠标单击,和鼠标移动。

    检测鼠标Clicks

    和键盘处理一样,GLUT为你的注册函数(也就是处理鼠标clicks事件的函数)提供了一个方法。函数glutMouseFunc,这个函数一般在程序初始化阶段被调用。函数原型如下:

    void glutMouseFunc(void(*func)(int button,int state,int x,int y));
    参数:
    func:处理鼠标click事件的函数的函数名。
    从上面可以看到到,处理鼠标click事件的函数,一定有4个参数。第一个参数表明哪个鼠标键被按下或松开,这个变量可以是下面的三个值中的一个:
    GLUT_LEFT_BUTTON
    GLUT_MIDDLE_BUTTON
    GLUT_RIGHT_BUTTON

    第二个参数表明,函数被调用发生时,鼠标的状态,也就是是被按下,或松开,可能取值如下:

    GLUT_DOWN
    GLUT_UP

    当函数被调用时,state的值是GLUT_DOWN,那么程序可能会假定将会有个GLUT_UP事件,甚至鼠标移动到窗口外面,也如此。然而,如果程序调用glutMouseFunc传递NULL作为参数,那么GLUT将不会改变鼠标的状态。

    剩下的两个参数(x,y)提供了鼠标当前的窗口坐标(以左上角为原点)。
    检测动作(motion
    GLUT提供鼠标motion检测能力。有两种GLUT处理的motion:active motion和passive motion。Active motion是指鼠标移动并且有一个鼠标键被按下。Passive motion是指当鼠标移动时,并有没鼠标键按下。如果一个程序正在追踪鼠标,那么鼠标移动期间,每一帧将产生一个结果。
    和以前一样,你必须注册将处理鼠标事件的函数(定义函数)。GLUT让我们可以指定两个不同的函数,一个追踪passive motion,另一个追踪active motion。
    它们的函数原型,如下:
    void glutMotionFunc(void(*func)(int x,int y));
    void glutPassiveMotionFunc(void (*func)(int x,int y));
    参数:
    Func:处理各自类型motion的函数名。
    处理motion的参数函数的参数(x,y)是鼠标在窗口的坐标。以左上角为原点。
    检测鼠标进入或离开窗口

    GLUT还能检测鼠标鼠标离开,进入窗口区域。一个回调函数可以被定义去处理这两个事件。GLUT里,调用这个函数的是glutEntryFunc,函数原型如下:

    void glutEntryFunc(void(*func)(int state));
    参数:
    Func:处理这些事件的函数名。
    上面函数的参数中,state有两个值:
    GLUT_LEFT
    GLUT_ENTERED

    表明,是离开,还是进入窗口。

    整合全部功能到程序内

    首先我们要做的是在GLUT里定义哪些函数将负责处理鼠标事件。因此我们将重写我们的main函数,让它包含所有必须的回调注册函数。我们将在程序里描述其他一些教程里没说清楚的地方。

    #include <gl/glut.h>
    
    void main(int argc, char **argv) 
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        glutInitWindowPosition(100, 100);
        glutInitWindowSize(320, 320);
        glutCreateWindow("GLUT Tutorial Cursor");
    
        glutDisplayFunc(renderScene);
        glutIdleFunc(renderScene);
        glutReshapeFunc(reShape);
    
        //adding here the mouse processing callbacks
        glutMouseFunc(processMouse);
        glutMotionFunc(processMouseActiveMotion);
        glutPassiveMotionFunc(processMousePassiveMotion);
        glutEntryFunc(processMouseEntry);
    
        glutMainLoop();
    }

    OK,现在做点有趣的。我们将定义那些将做一些不可思议事件的回调函数。当一个鼠标键和alt键都被按下,我们将改变三角形的颜色。鼠标左键使三角形变成红色,中间的将三角形变成绿色,鼠标右键将三角形变成蓝色。函数如下:

    void processMouse(int button, int state, int x, int y) {
     
     
             specialKey = glutGetModifiers();
             // 当鼠标键和alt键都被按下
             if ((state == GLUT_DOWN) && 
                              (specialKey == GLUT_ACTIVE_ALT)) {
     
                     // set the color to pure red for the left button
                     if (button == GLUT_LEFT_BUTTON) {
                              red = 1.0; green = 0.0; blue = 0.0;
                     }
                     // set the color to pure green for the middle button
                     else if (button == GLUT_MIDDLE_BUTTON) {
                              red = 0.0; green = 1.0; blue = 0.0;
                     }
                     // set the color to pure blue for the right button
                     else {
                              red = 0.0; green = 0.0; blue = 1.0;
                     }
             }
    }

    接下来有一个精细的颜色拾取方法。当一个鼠标键被按下,但alt键被被按下。我们把blue设为0.0,并且让red和green分量的值取决于鼠标在窗口中的位置。。函数如下:

    void processMouseActiveMotion(int x, int y) {
     
             // the ALT key was used in the previous function
             if (specialKey != GLUT_ACTIVE_ALT) {
                     // setting red to be relative to the mouse 
                     // position inside the window
                     if (x < 0)
                              red = 0.0;
                     else if (x > width)
                              red = 1.0;
                     else
                              red = ((float) x)/height;
                     // setting green to be relative to the mouse 
                     // position inside the window
                     if (y < 0)
                              green = 0.0;
                     else if (y > width)
                              green = 1.0;
                     else
                              green = ((float) y)/height;
                     // removing the blue component.
                     blue = 0.0;
             }
    }

    下面给passive motion添加一些动作。当shift键被按下,鼠标将在x轴上有一个旋转。我们不得不修改renderScene函数。函数如下:

    float angleX = 0.0;
    
    void renderScene(void) {
             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             glPushMatrix();
             glRotatef(angle,0.0,1.0,0.0);
             
             // This is the line we added for the
             // rotation on the X axis;
             glRotatef(angleX,1.0,0.0,0.0);
             
             glColor3f(red,green,blue);
     
             glBegin(GL_TRIANGLES);
                     glVertex3f(-0.5,-0.5,0.0);
                     glVertex3f(0.5,0.0,0.0);
                     glVertex3f(0.0,0.5,0.0);
             glEnd();
             glPopMatrix();
             angle++;
             glutSwapBuffers();
    }

    现在我们的有个函数处理passive motion事件。函数将改变angleX的值。

    void processMousePassiveMotion(int x, int y) {
     
             // User must press the SHIFT key to change the 
             // rotation in the X axis
             if (specialKey != GLUT_ACTIVE_SHIFT) {
     
                     // setting the angle to be relative to the mouse 
                     // position inside the window
                     if (x < 0)
                              angleX = 0.0;
                     else if (x > width)
                              angleX = 180.0;
                     else
                              angleX = 180.0 * ((float) x)/height;
             }
    }

    最后鼠标离开窗口将使动画停止,为了做到这,我们也需要改变函数renderScene。

    // initially define the increase of the angle by 1.0;
    float deltaAngle = 1.0;
    
    void renderScene(void) {
             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             glPushMatrix();
             glRotatef(angle,0.0,1.0,0.0);
             glRotatef(angleX,1.0,0.0,0.0);
             glColor3f(red,green,blue);
     
             glBegin(GL_TRIANGLES);
                     glVertex3f(-0.5,-0.5,0.0);
                     glVertex3f(0.5,0.0,0.0);
                     glVertex3f(0.0,0.5,0.0);
             glEnd();
             glPopMatrix();
             // this is the new line
             // previously it was: angle++;
             angle+=deltaAngle;
             glutSwapBuffers();
    }

    processMouseEntry是最后一个函数。注意,这个在微软操作系统下可能工作的不是很好。

    void processMouseEntry(int state) {
             if (state == GLUT_LEFT)
                     deltaAngle = 0.0;
             else
                     deltaAngle = 1.0;
    }

    显示效果如下

    完整代码如下
    #include <stdio.h>
    #include <gl/glut.h>
    
    int specialKey = 0;
    static float angle = 0.0, angleX = 0.0, ratio;
    
    // initially define the increase of the angle by 1.0;
    float deltaAngle = 0.05;
    
    //windows size 
    int width = 320, height = 320;
    
    //所有的变量被初始化为1,表明三角形最开始是白色的。
    float red = 1.0, blue = 1.0, green = 1.0;
    
    void processMouse(int button, int state, int x, int y)
    {
        specialKey = glutGetModifiers();
    
        // 当鼠标键和alt键都被按下
        if ((state == GLUT_DOWN) && (specialKey == GLUT_ACTIVE_ALT))
        {
            // set the color to pure red for the left button
            if (button == GLUT_LEFT_BUTTON) 
            {
                red = 1.0; green = 0.0; blue = 0.0;
            }
            // set the color to pure green for the middle button
            else if (button == GLUT_MIDDLE_BUTTON) 
            {
                red = 0.0; green = 1.0; blue = 0.0;
            }
            // set the color to pure blue for the right button
            else 
            {
                red = 0.0; green = 0.0; blue = 1.0;
            }
        }
    }
    
    void processMousePassiveMotion(int x, int y) 
    {
        // User must press the SHIFT key to change the 
        // rotation in the X axis
        if (specialKey != GLUT_ACTIVE_SHIFT)
        {
            // setting the angle to be relative to the mouse 
            // position inside the window
            if (x < 0)
                angleX = 0.0;
            else if (x > width)
                angleX = 180.0;
            else
                angleX = 180.0 * ((float)x) / height;
        }
    }
    
    void processMouseActiveMotion(int x, int y)
    {
        // the ctrl key was used in the previous function
        if (specialKey != GLUT_ACTIVE_ALT)
        {
            // setting red to be relative to the mouse 
            // position inside the window
            if (x < 0)
                red = 0.0;
            else if (x > width)
                red = 1.0;
            else
                red = ((float)x) / height;
            // setting green to be relative to the mouse 
            // position inside the window
            if (y < 0)
                green = 0.0;
            else if (y > width)
                green = 1.0;
            else
                green = ((float)y) / height;
    
            // removing the blue component.
            blue = 0.0;
        }
    }
    
    
    void renderScene(void)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glPushMatrix();
        glRotatef(angle, 0.0, 1.0, 0.0);
        glRotatef(angleX, 1.0, 0.0, 0.0);
        glColor3f(red, green, blue);
    
        glBegin(GL_TRIANGLES);
        glVertex3f(-0.5, -0.5, 0.0);
        glVertex3f(0.5, 0.0, 0.0);
        glVertex3f(0.0, 0.5, 0.0);
        glEnd();
        glPopMatrix();
        // this is the new line
        // previously it was: angle++;
        angle += deltaAngle;
        glutSwapBuffers();
    }
    
    void processMouseEntry(int state)
    {
        if (state == GLUT_LEFT)
            deltaAngle = 0.0;
        else
            deltaAngle = 0.05;
    }
    
    void reShape(int w, int h)
    {
        // 防止被0除.
        if (h == 0)
            h = 1;
    
        width = w;
        height = h;
    
        ratio = 1.0f * w / h;
        //Reset the coordinate system before modifying
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        //设置视口为整个窗口大小
        glViewport(0, 0, width, height);
    
        //设置可视空间
        gluPerspective(45, ratio, 1, 1000);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f);
    }
    
    void main(int argc, char **argv) 
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        glutInitWindowPosition(100, 100);
        glutInitWindowSize(320, 320);
        glutCreateWindow("GLUT Tutorial Cursor");
    
        glutDisplayFunc(renderScene);
        glutIdleFunc(renderScene);
        glutReshapeFunc(reShape);
    
        //adding here the mouse processing callbacks
        glutMouseFunc(processMouse);
        glutMotionFunc(processMouseActiveMotion);
        glutPassiveMotionFunc(processMousePassiveMotion);
        glutEntryFunc(processMouseEntry);
    
        glutMainLoop();
    }
  • 相关阅读:
    vue——图片懒加载v-lazy
    vue——利用intersectionOberver实现全局appear/disappear事件
    WXS-----学会使用WXS
    使用内联样式
    样式引入
    小程序开发框架----WXSS
    引入内部外部模板
    Selenium元素定位的几种方式
    Response Assertion(响应断言)
    参数化CSV Data Set config元件
  • 原文地址:https://www.cnblogs.com/flyinggod/p/12926934.html
Copyright © 2011-2022 走看看