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函数来促使程序终止.代码如下:

  1. void processNormalKeys(unsigned char key, int x, int y) {
  2.  
  3. if (key == )
  4. exit();
  5. }

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

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

func - 同glutKeyboardFunc函数.

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

  1. void processSpecialKeys(int key, int x, int y) {
  2.  
  3. switch(key) {
  4. case GLUT_KEY_F1 :
  5. red = 1.0;
  6. green = 0.0;
  7. blue = 0.0; break;
  8. case GLUT_KEY_F2 :
  9. red = 0.0;
  10. green = 1.0;
  11. blue = 0.0; break;
  12. case GLUT_KEY_F3 :
  13. red = 0.0;
  14. green = 0.0;
  15. blue = 1.0; break;
  16. }
  17. }

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

  1. GLUT_KEY_F1 F1 function key
  2. GLUT_KEY_F2 F2 function key
  3. GLUT_KEY_F3 F3 function key
  4. GLUT_KEY_F4 F4 function key
  5. GLUT_KEY_F5 F5 function key
  6. GLUT_KEY_F6 F6 function key
  7. GLUT_KEY_F7 F7 function key
  8. GLUT_KEY_F8 F8 function key
  9. GLUT_KEY_F9 F9 function key
  10. GLUT_KEY_F10 F10 function key
  11. GLUT_KEY_F11 F11 function key
  12. GLUT_KEY_F12 F12 function key
  13. GLUT_KEY_LEFT Left function key
  14. GLUT_KEY_RIGHT Right function key
  15. GLUT_KEY_UP Up function key
  16. GLUT_KEY_DOWN Down function key
  17. GLUT_KEY_PAGE_UP Page Up function key
  18. GLUT_KEY_PAGE_DOWN Page Down function key
  19. GLUT_KEY_HOME Home function key
  20. GLUT_KEY_END End function key
  21. GLUT_KEY_INSERT Insert function key

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

  1. void renderScene(void) {
  2.  
  3. // Clear Color and Depth Buffers
  4. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  5. // Reset transformations
  6.  
  7. glLoadIdentity();
  8. // Set the camera
  9. gluLookAt( 0.0f, 0.0f, 10.0f,
  10. 0.0f, 0.0f, 0.0f,
  11. 0.0f, 1.0f, 0.0f);
  12.  
  13. glRotatef(angle, 0.0f, 1.0f, 0.0f);
  14.  
  15. // the function responsible for setting the color
  16. glColor3f(red,green,blue);
  17. glBegin(GL_TRIANGLES);
  18. glVertex3f(-2.0f,-2.0f, 0.0f);
  19. glVertex3f( 2.0f, 0.0f, 0.0);
  20. glVertex3f( 0.0f, 2.0f, 0.0);
  21. glEnd();
  22. angle+=0.1f;
  23.  
  24. glutSwapBuffers();
  25. }

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

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

  1. int main(int argc, char **argv) {
  2.  
  3. // init GLUT and create window
  4. glutInit(&argc, argv);
  5. glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  6. glutInitWindowPosition(,);
  7. glutInitWindowSize(,);
  8. glutCreateWindow("Lighthouse3D- GLUT Tutorial");
  9.  
  10. // register callbacks
  11. glutDisplayFunc(renderScene);
  12. glutReshapeFunc(changeSize);
  13. glutIdleFunc(renderScene);
  14.  
  15. // here are the new entries
  16. glutKeyboardFunc(processNormalKeys);
  17. glutSpecialFunc(processSpecialKeys);
  18.  
  19. // enter GLUT event processing cycle
  20. glutMainLoop();
  21.  
  22. return ;
  23. }

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键把红色调到最大.实现代码如下:

  1. void processNormalKeys(unsigned char key, int x, int y) {
  2.  
  3. if (key == )
  4. exit();
  5. else if (key=='r') {
  6. int mod = glutGetModifiers();
  7. if (mod == GLUT_ACTIVE_ALT)
  8. red = 0.0;
  9. else
  10. red = 1.0;
  11. }
  12. }

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

  1. void processSpecialKeys(int key, int x, int y) {
  2.  
  3. int mod;
  4. switch(key) {
  5. case GLUT_KEY_F1 :
  6. mod = glutGetModifiers();
  7. if (mod == (GLUT_ACTIVE_CTRL|GLUT_ACTIVE_ALT)) {
  8. red = 1.0; green = 0.0; blue = 0.0;
  9. }
  10. break;
  11. case GLUT_KEY_F2 :
  12. red = 0.0;
  13. green = 1.0;
  14. blue = 0.0; break;
  15. case GLUT_KEY_F3 :
  16. red = 0.0;
  17. green = 0.0;
  18. blue = 1.0; break;
  19. }
  20. }

完整代码如下:

  1. #include <stdlib.h>
  2.  
  3. #ifdef __APPLE__
  4. #include <GLUT/glut.h>
  5. #else
  6. #include <GL/glut.h>
  7. #endif
  8.  
  9. // all variables initialized to 1.0, meaning
  10. // the triangle will initially be white
  11. float red=1.0f, blue=1.0f, green=1.0f;
  12.  
  13. // angle for rotating triangle
  14. float angle = 0.0f;
  15.  
  16. void changeSize(int w, int h) {
  17.  
  18. // Prevent a divide by zero, when window is too short
  19. // (you cant make a window of zero width).
  20. if (h == )
  21. h = ;
  22. float ratio = w * 1.0 / h;
  23.  
  24. // Use the Projection Matrix
  25. glMatrixMode(GL_PROJECTION);
  26.  
  27. // Reset Matrix
  28. glLoadIdentity();
  29.  
  30. // Set the viewport to be the entire window
  31. glViewport(, , w, h);
  32.  
  33. // Set the correct perspective.
  34. gluPerspective(45.0f, ratio, 0.1f, 100.0f);
  35.  
  36. // Get Back to the Modelview
  37. glMatrixMode(GL_MODELVIEW);
  38. }
  39.  
  40. void renderScene(void) {
  41.  
  42. // Clear Color and Depth Buffers
  43. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  44.  
  45. // Reset transformations
  46. glLoadIdentity();
  47.  
  48. // Set the camera
  49. gluLookAt( 0.0f, 0.0f, 10.0f,
  50. 0.0f, 0.0f, 0.0f,
  51. 0.0f, 1.0f, 0.0f);
  52.  
  53. glRotatef(angle, 0.0f, 1.0f, 0.0f);
  54.  
  55. glColor3f(red,green,blue);
  56. glBegin(GL_TRIANGLES);
  57. glVertex3f(-2.0f,-2.0f, 0.0f);
  58. glVertex3f( 2.0f, 0.0f, 0.0);
  59. glVertex3f( 0.0f, 2.0f, 0.0);
  60. glEnd();
  61.  
  62. angle+=0.1f;
  63.  
  64. glutSwapBuffers();
  65. }
  66.  
  67. void processNormalKeys(unsigned char key, int x, int y) {
  68.  
  69. if (key == )
  70. exit();
  71. }
  72.  
  73. void processSpecialKeys(int key, int x, int y) {
  74.  
  75. switch(key) {
  76. case GLUT_KEY_F1 :
  77. red = 1.0;
  78. green = 0.0;
  79. blue = 0.0; break;
  80. case GLUT_KEY_F2 :
  81. red = 0.0;
  82. green = 1.0;
  83. blue = 0.0; break;
  84. case GLUT_KEY_F3 :
  85. red = 0.0;
  86. green = 0.0;
  87. blue = 1.0; break;
  88. }
  89. }
  90.  
  91. int main(int argc, char **argv) {
  92.  
  93. // init GLUT and create window
  94. glutInit(&argc, argv);
  95. glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  96. glutInitWindowPosition(,);
  97. glutInitWindowSize(,);
  98. glutCreateWindow("Lighthouse3D- GLUT Tutorial");
  99.  
  100. // register callbacks
  101. glutDisplayFunc(renderScene);
  102. glutReshapeFunc(changeSize);
  103. glutIdleFunc(renderScene);
  104.  
  105. // here are the new entries
  106. glutKeyboardFunc(processNormalKeys);
  107. glutSpecialFunc(processSpecialKeys);
  108.  
  109. // enter GLUT event processing cycle
  110. glutMainLoop();
  111.  
  112. return ;
  113. }

[译]GLUT教程 - 键盘的更多相关文章

  1. [译]GLUT教程 - 键盘高级特性

    Lighthouse3d.com >> GLUT Tutorial >> Input >> Advanced Keyboard 本节我们会介绍另外4个处理键盘事件的 ...

  2. [译]GLUT教程 - 鼠标

    Lighthouse3d.com >> GLUT Tutorial >> Input >> The Mouse 上一节我们讨论了怎么用GLUT的键盘函数跟OpenG ...

  3. [译]GLUT教程(目录)

    http://www.lighthouse3d.com/tutorials/glut-tutorial/ GLUT是OpenGL Utility Toolkit的意思.作者Mark J. Kilgar ...

  4. [译]GLUT教程 - glutPostRedisplay函数

    Lighthouse3d.com >> GLUT Tutorial >> Avoiding the Idle Func >> glutPostRedisplay 直 ...

  5. [译]GLUT教程 - 渲染到子窗体

    Lighthouse3d.com >> GLUT Tutorial >> Subwindows >> Rendering to Subwindows 先回顾一下之前 ...

  6. [译]GLUT教程 - 游戏模式

    Lighthouse3d.com >> GLUT Tutorial >> Extras >> Game Mode 根据GLUT官网的说明,GLUT的游戏模式是为开启 ...

  7. [译]GLUT教程 - 修改菜单

    Lighthouse3d.com >> GLUT Tutorial >> Pop-up Menus >> Modifying Menus 肯定会有菜单需要被修改的状 ...

  8. [译]GLUT教程 - 弹出菜单基础

    Lighthouse3d.com >> GLUT Tutorial >> Pop-up Menus >> Popup Menus 弹出菜单也是GLUT的一部分.虽然 ...

  9. [译]GLUT教程 - 移动镜头3

    Lighthouse3d.com >> GLUT Tutorial >> Input >> Moving the Camera III 上一节的示例中我们用键盘更改 ...

随机推荐

  1. Java Socket编程详细解说

    Java Socket编程 JavaSocketServerSocket乱码超时 Java Socket编程 对于Java Socket编程而言,有两个概念,一个是ServerSocket,一个是So ...

  2. SQL表操作习题2 1~10题

  3. 一次PHP面试经历

    9月9号,去了一家朋友的公司参加面试,然后就被直接吊打了,问的许多问题居然是我压根没有关心过的,看起来只在高层搞框架不行啊,还是得自己造个轮子试试,下面回顾一下问到的问题和我自己找到的一些答案. fi ...

  4. extjs grid合并单元格

    http://blog.csdn.net/kunoy/article/details/7829395 /** * Kunoy * 合并单元格 * @param {} grid 要合并单元格的grid对 ...

  5. System对象

    System:类中的方法和属性都是静态的 out:标准输出,默认是控制台 in:标准输入.默认是键盘 System:描述系统的一些信息. 获取系统属性信息:Properties getProperti ...

  6. Overview of iOS Crash Reporting Tools: Part 2/2

    Thanks for joining me for the second part of this two-part series on crash reporting services! The f ...

  7. JAVA常见算法题(三)

    package com.xiaowu.demo; //打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身. //例如:153 ...

  8. [置顶] kubernetes资源类型--pod和job

    pod Pod是K8S的最小操作单元,一个Pod可以由一个或多个容器组成:整个K8S系统都是围绕着Pod展开的,比如如何部署运行Pod.如何保证Pod的数量.如何访问Pod等. 特点 Pod是能够被创 ...

  9. 关于VS下的应用程序出现0xc000007b的问题以及OpenCV相关的0xc000007b问题

    本文参考过其他一些文章: http://www.cnblogs.com/csuftzzk/p/windows_launch_error_0xc000007b.html 这个问题在网上一查一大堆,主要的 ...

  10. mysql行转列,单列转多行

    行转列 使用CASE语句: SELECT SUM(CASE USER_NAME='A' THEN KILLS END) AS 'A', SUM(CASE USERNAME='B' THEN KILL ...