openGl提供了对键盘和鼠标事件的响应。GLUT提供了2个键盘注册回调函数。第一个, glutKeyboardFunc, 用来告诉windows系统我们调用哪个函数处理"普通"按键. "普通"按键就是指, 单词,数字,任何有ASCII码的东西。
这个函数的语法如下:
extern void APIENTRY glutKeyboardFunc(void (*func)(unsigned char key, int x, int y));
第一个参数key指的是键盘按下哪个键的ASCII码。x,y表示按键时鼠标的坐标,该坐标是相对于窗口左上角。
还有一类键,比如F1,F2.....方向箭头,并不是在上述函数中注册,GLUT提供了一个另外的函数。
具体如下:
extern void APIENTRY glutSpecialFunc(void (*func)(int key, int x, int y));
三个参数和上述一样,但是F1,F2.....方向箭头这些键的ASCII码可以在glut.h中找到。
具体如下:
/* function keys */
#define GLUT_KEY_F1 1
#define GLUT_KEY_F2 2
#define GLUT_KEY_F3 3
#define GLUT_KEY_F4 4
#define GLUT_KEY_F5 5
#define GLUT_KEY_F6 6
#define GLUT_KEY_F7 7
#define GLUT_KEY_F8 8
#define GLUT_KEY_F9 9
#define GLUT_KEY_F10 10
#define GLUT_KEY_F11 11
#define GLUT_KEY_F12 12
/* directional keys */
#define GLUT_KEY_LEFT 100
#define GLUT_KEY_UP 101
#define GLUT_KEY_RIGHT 102
#define GLUT_KEY_DOWN 103
#define GLUT_KEY_PAGE_UP 104
#define GLUT_KEY_PAGE_DOWN 105
#define GLUT_KEY_HOME 106
#define GLUT_KEY_END 107
#define GLUT_KEY_INSERT 108
#endif
GLUT也提供了鼠标注册回调函数
具体如下:
extern void APIENTRY glutMouseFunc(void (*func)(int button, int state, int x, int y));
button 分别对应鼠标左键,中键,右键。
/* Mouse buttons. */
#define GLUT_LEFT_BUTTON 0
#define GLUT_MIDDLE_BUTTON 1
#define GLUT_RIGHT_BUTTON 2
state 对应鼠标状态:按下与弹起
/* Mouse button state. */
#define GLUT_DOWN 0
#define GLUT_UP 1
x ,y 对应鼠标的坐标
这篇博文还对其他一些组合键做了介绍http://www.cnblogs.com/jiaohuang/archive/2011/07/25/2116263.html
我的应用:
在窗口中,第一次点击鼠标左键,绘制直线的起点
按 f 键,从起点水平延生,绘制一条直线
按 t 键,旋转直线,我设定每次旋转30°
按 i 键,直线的长度扩大一倍
按 s 键,直线的长度缩小一倍
按 r , g , b 键,分别使直线的颜色变成红色,绿色,蓝色
按方向键,移动直线
第二次点击鼠标左键,重新绘制直线的起点
功能很简单,但是作为键盘,鼠标事件的应用还是一个不错的练习。
具体代码如下所示:
#include <gl/glut.h>
#include<stdio.h>
#include <stdlib.h>
#include <math.h>
GLint flag = 1;
GLfloat ori[2]; //起点坐标
GLfloat next[2];//终点坐标
GLfloat dir[2]={1,0};//方向向量
GLint D = 100;//直线长度
GLfloat angle= 30*3.1415926/180.0;//旋转角度
GLint n = 1;//直线旋转角度次数
void init()
{
flag = 1;
dir[0]=1;
dir[1]=0;
D=100;
n = 1;
}
void myDisplay(void)
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
if(flag == 1)
{
glBegin(GL_POINTS);//画点
glVertex2f(ori[0],400-ori[1]);
glEnd();
}
if(flag == 2)
{
glBegin(GL_LINES);//画线
glVertex2f(ori[0],400-ori[1]);
glVertex2f(next[0],400-next[1]);
glEnd();
}
glFlush();
}
void myMouse(int button,int state,int x,int y)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
if(state == GLUT_DOWN)
{
ori[0] = x;
ori[1] = y;
init();
glutPostRedisplay();
break;
}
}
}
void updata()
{
if(flag==1)
{
next[0] = ori[0] + D * dir[0];
next[1] = ori[1] + D * dir[1];
flag=2;
}
else
{
next[0] = ori[0] + D * dir[0];
next[1] = ori[1] - D * dir[1];
}
glutPostRedisplay();
}
void myKeyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 'f':
{
if(flag==1)
updata();
break;
}
case 't':
{
if(flag==2)
{
dir[0] = cos(angle * n );
dir[1] = sin(angle * n );
n++;
updata();
}
break;
}
case 'i':
{
D = D * 2;
updata();
break;
}
case 's':
{
D = D * 0.5;
updata();
break;
}
case 'r':
{
glColor3f(1,0,0);
glutPostRedisplay();
break;
}
case 'g':
{
glColor3f(0,1,0);
glutPostRedisplay();
break;
}
case 'b':
{
glColor3f(0,0,1);
glutPostRedisplay();
break;
}
case 27:
exit(0);
}
}
void myKeyboard1(int key,int x,int y)
{
switch(key)
{
case GLUT_KEY_LEFT:
{
ori[0]-=5;
next[0]-=5;
glutPostRedisplay();
break;
}
case GLUT_KEY_UP:
{
ori[1]-=5;
next[1]-=5;
glutPostRedisplay();
break;
}
case GLUT_KEY_RIGHT:
{
ori[0]+=5;
next[0]+=5;
glutPostRedisplay();
break;
}
case GLUT_KEY_DOWN:
{
ori[1]+=5;
next[1]+=5;
glutPostRedisplay();
break;
}
}
}
void reshape(int w ,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,(GLdouble)w,0,(GLdouble)h);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("第一个OpenGL程序");
glutDisplayFunc(myDisplay);
glutKeyboardFunc(myKeyboard);
glutSpecialFunc(myKeyboard1);
glutMouseFunc(myMouse);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
程序部分效果:
11