Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5520561
  • 博文数量: 763
  • 博客积分: 12108
  • 博客等级: 上将
  • 技术积分: 15717
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-28 21:21
个人简介

业精于勤,荒于嬉

文章分类

全部博文(763)

文章存档

2018年(6)

2017年(15)

2016年(2)

2015年(31)

2014年(14)

2013年(87)

2012年(75)

2011年(94)

2010年(190)

2009年(38)

2008年(183)

2007年(28)

分类: C/C++

2010-05-25 19:06:34

在前几节,我们看了怎么使用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函数,让它包含所有必须的回调注册函数。我们将在程序里描述其他一些教程里没说清楚的地方。
void main(int argc, char **argv) {         glutInit(&argc, argv);         glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);         glutInitWindowPosition(100,100);         glutInitWindowSize(320,320);         glutCreateWindow("SnowMen");         glutDisplayFunc(renderScene);         glutIdleFunc(renderScene);         glutReshapeFunc(changeSize);          //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;}VC6.0工程可以在这里下载(glut8.zip)。 (到这里位置,键盘,鼠标方面的控制讲完了,下面就是菜单了。)(原文地址:

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xie_zi/archive/2007/12/09/1925778.aspx

阅读(1907) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~