zoukankan      html  css  js  c++  java
  • [译]GLUT教程

    Lighthouse3d.com >> GLUT Tutorial >> Input >> Keyboard

    GLUT可以让应用程序自动监测键盘输入,包括普通按键和特殊按键,例如F1和向上键.本节我们来讨论怎样监测按键事件和如何响应.

    目前为止你应该已经发现,需要GLUT处理对应的事件,必须先告知GLUT把事件绑定到指定函数.之前已经介绍了重绘事件,系统空闲事件和窗体更改大小事件.

    同样的,下面来介绍键盘事件.我们要告知GLUT哪个函数是响应按键处理的.

    GLUT提供两个函数来为键盘事件注册回调函数.第一个是glutKeyboardFunc,用于告知窗体系统处理普通按键事件.例如字母,数字,和ASCII包含的内码.原型如下:

    void glutKeyboardFunc(void (*func) (unsigned char key, int x, int y));

    func - 处理普通按键事件的函数.如果传入NULL值则忽略普通按钮

    glutKeyboarFunc绑定的函数必须返回三个结果值.第一个是按键对应的ASCII内码,其余两个是按钮触发时鼠标所在的位置.鼠标位置是相对于窗体客户端的左上角.

    比较可行的实现方案是,当用户输入esc键的时候退出程序.留意到当看到glutMainLoop函数时,我们会注意到它是在一个死循环中,永远不会返回.跳出死循环的唯一办法是调用系统的exit函数.这就是函数里面需要实现的部分,当用户按esc键的时候,我们要调用系统exit函数来促使程序终止.代码如下:

    void processNormalKeys(unsigned char key, int x, int y) {
    
        if (key == 27)
            exit(0);
    }

    接着看特殊键处理.GLUT提供了glutSpecialFunc函数来处理,原型如下:

    void glutSpecialFunc(void (*func) (int key, int x, int y));

    func - 同glutKeyboardFunc函数.

    接下来实现一个功能,用户通过按特殊键来改变三角形的颜色.F1红色,F2绿色,F3蓝色.

    void processSpecialKeys(int key, int x, int y) {
    
        switch(key) {
            case GLUT_KEY_F1 :
                    red = 1.0;
                    green = 0.0;
                    blue = 0.0; break;
            case GLUT_KEY_F2 :
                    red = 0.0;
                    green = 1.0;
                    blue = 0.0; break;
            case GLUT_KEY_F3 :
                    red = 0.0;
                    green = 0.0;
                    blue = 1.0; break;
        }
    }

    常量GLUT_KEY_*是在glut.h头文件中预定义的.该常量的具体定义如下:

    GLUT_KEY_F1        F1 function key
    GLUT_KEY_F2        F2 function key
    GLUT_KEY_F3        F3 function key
    GLUT_KEY_F4        F4 function key
    GLUT_KEY_F5        F5 function key
    GLUT_KEY_F6        F6 function key
    GLUT_KEY_F7        F7 function key
    GLUT_KEY_F8        F8 function key
    GLUT_KEY_F9        F9 function key
    GLUT_KEY_F10        F10 function key
    GLUT_KEY_F11        F11 function key
    GLUT_KEY_F12        F12 function key
    GLUT_KEY_LEFT        Left function key
    GLUT_KEY_RIGHT        Right function key
    GLUT_KEY_UP        Up function key
    GLUT_KEY_DOWN        Down function key
    GLUT_KEY_PAGE_UP    Page Up function key
    GLUT_KEY_PAGE_DOWN    Page Down function key
    GLUT_KEY_HOME        Home function key
    GLUT_KEY_END        End function key
    GLUT_KEY_INSERT        Insert function key

    为配合自定义响应函数processSpecialKeys,我们添加红绿蓝变量到代码头部.除此之外,我们要更改renderScene函数来达到渲染效果.

    void renderScene(void) {
    
        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // Reset transformations
    
        glLoadIdentity();
        // Set the camera
        gluLookAt(    0.0f, 0.0f, 10.0f,
                0.0f, 0.0f,  0.0f,
                0.0f, 1.0f,  0.0f);
    
            glRotatef(angle, 0.0f, 1.0f, 0.0f);
    
            // the function responsible for setting the color
        glColor3f(red,green,blue);
        glBegin(GL_TRIANGLES);
            glVertex3f(-2.0f,-2.0f, 0.0f);
            glVertex3f( 2.0f, 0.0f, 0.0);
            glVertex3f( 0.0f, 2.0f, 0.0);
        glEnd();
        angle+=0.1f;
    
        glutSwapBuffers();
    }

    现在已经定义好glutKeyboardFunc和glutSpecialFunc函数的代码.

    要令任何地方都能调用该函数,就必须先更改处理函数中的键盘事件任何时候都能处理.因为这不是一个常用特征.所以我们会把它放在main函数中.下面是加了键盘处理的main函数:

    int main(int argc, char **argv) {
    
        // init GLUT and create window
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        glutInitWindowPosition(100,100);
        glutInitWindowSize(320,320);
        glutCreateWindow("Lighthouse3D- GLUT Tutorial");
    
            // register callbacks
        glutDisplayFunc(renderScene);
        glutReshapeFunc(changeSize);
        glutIdleFunc(renderScene);
    
        // here are the new entries
        glutKeyboardFunc(processNormalKeys);
        glutSpecialFunc(processSpecialKeys);
    
        // enter GLUT event processing cycle
        glutMainLoop();
    
        return 1;
    }

    Ctrl, Alt和Shift键

    有时我们需要处理编辑键,例如ctrl,alt和shift. GLUT提供一个函数来监测编辑键.但是该函数只能在键盘和鼠标输入事件的绑定函数里面调用.原型如下:

    int glutGetModifiers(void);

    该函数的返回值是三个可选的常量(包含在glut.h头文件中),用位或组合形式.

    GLUT_ACTIVE_SHIFT - 通知shift键被按下,或者大写锁在开启状态.如果两者都是开启状态,就反而是不大写.

    GLUT_ACTIVE_CTRL - 通知ctrl键被按下.

    GLUT_ACTIVE_ALT - 通知alt键被按下.

    接下来扩展我们的processNormalKeys函数以控制编辑键.假定你希望用r键把红色变量归零,用alt键加r键把红色调到最大.实现代码如下:

    void processNormalKeys(unsigned char key, int x, int y) {
    
        if (key == 27)
            exit(0);
        else if (key=='r') {
            int mod = glutGetModifiers();
            if (mod == GLUT_ACTIVE_ALT)
                red = 0.0;
            else
                red = 1.0;
        }
    }

    最后,我们如果要监测ctrl+alt+F1这样的组合键,如何实现? 我们要同时监测两个编辑键.我们以位或组合起两个需要的常量.例如下面代码是用ctrl+alt+F1组合键来更改为红色.

    void processSpecialKeys(int key, int x, int y) {
    
        int mod;
        switch(key) {
            case GLUT_KEY_F1 :
               mod = glutGetModifiers();
               if (mod == (GLUT_ACTIVE_CTRL|GLUT_ACTIVE_ALT)) {
                   red = 1.0; green = 0.0; blue = 0.0;
               }
               break;
            case GLUT_KEY_F2 :
               red = 0.0;
               green = 1.0;
               blue = 0.0; break;
            case GLUT_KEY_F3 :
               red = 0.0;
               green = 0.0;
               blue = 1.0; break;
        }
    }

    完整代码如下:

    #include <stdlib.h>
    
    #ifdef __APPLE__
    #include <GLUT/glut.h>
    #else
    #include <GL/glut.h>
    #endif
    
    // all variables initialized to 1.0, meaning
    // the triangle will initially be white
    float red=1.0f, blue=1.0f, green=1.0f;
    
    // angle for rotating triangle
    float angle = 0.0f;
    
    void changeSize(int w, int h) {
    
        // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if (h == 0)
            h = 1;
        float ratio =  w * 1.0 / h;
    
            // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION);
    
            // Reset Matrix
        glLoadIdentity();
    
        // Set the viewport to be the entire window
        glViewport(0, 0, w, h);
    
        // Set the correct perspective.
        gluPerspective(45.0f, ratio, 0.1f, 100.0f);
    
        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW);
    }
    
    void renderScene(void) {
    
        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // Reset transformations
        glLoadIdentity();
    
        // Set the camera
        gluLookAt(    0.0f, 0.0f, 10.0f,
                0.0f, 0.0f,  0.0f,
                0.0f, 1.0f,  0.0f);
    
        glRotatef(angle, 0.0f, 1.0f, 0.0f);
    
        glColor3f(red,green,blue);
        glBegin(GL_TRIANGLES);
            glVertex3f(-2.0f,-2.0f, 0.0f);
            glVertex3f( 2.0f, 0.0f, 0.0);
            glVertex3f( 0.0f, 2.0f, 0.0);
        glEnd();
    
        angle+=0.1f;
    
        glutSwapBuffers();
    }
    
    void processNormalKeys(unsigned char key, int x, int y) {
    
        if (key == 27)
            exit(0);
    }
    
    void processSpecialKeys(int key, int x, int y) {
    
        switch(key) {
            case GLUT_KEY_F1 :
                    red = 1.0;
                    green = 0.0;
                    blue = 0.0; break;
            case GLUT_KEY_F2 :
                    red = 0.0;
                    green = 1.0;
                    blue = 0.0; break;
            case GLUT_KEY_F3 :
                    red = 0.0;
                    green = 0.0;
                    blue = 1.0; break;
        }
    }
    
    int main(int argc, char **argv) {
    
        // init GLUT and create window
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        glutInitWindowPosition(100,100);
        glutInitWindowSize(320,320);
        glutCreateWindow("Lighthouse3D- GLUT Tutorial");
    
        // register callbacks
        glutDisplayFunc(renderScene);
        glutReshapeFunc(changeSize);
        glutIdleFunc(renderScene);
    
        // here are the new entries
        glutKeyboardFunc(processNormalKeys);
        glutSpecialFunc(processSpecialKeys);
    
        // enter GLUT event processing cycle
        glutMainLoop();
    
        return 1;
    }
  • 相关阅读:
    windows已经阻止此软件因为无法验证发行者解决方案
    vs用resharp如何调试到源码而不是对象浏览器
    Android环境变量的设置(详细图解版)
    js为xml添加节点和属性
    javascript操作xml文件综合实例
    js如何循环读取xml文件的节点
    游标的简单理解
    关于DATE函数datediff dateadd datename等
    分组数据where & having ,group by & order by
    SQL拼接字段,算数计算
  • 原文地址:https://www.cnblogs.com/live41/p/3385808.html
Copyright © 2011-2022 走看看