1.实验目的:
理解掌握一个OpenGL程序的常见交互方法。
2.实验内容:
(1) 运行示范实验代码1,掌握程序鼠标交互方法,尝试为其添加键盘与菜单控制,实现同样功能;
(2)运行示范实验代码2,掌握程序鼠标坐标获取与绘图方法,尝试为其添加绘制直线功能;
(3)结合上述两步,能否实现通过鼠标右键菜单切换实现一个简单的绘图程序,可以绘制直线、三角形、正方形等常见图形?
3.实验原理:
要想在OpenGL中处理鼠标事件非常的方便,GLUT已经为我们的注册好了函数,只要我们提供一个方法。使用函数glutMouseFunc,就可以帮我们注册我们的函数,这样当发生鼠标事件时就会自动调用我们的方法。
函数的原型是:
void glutMouseFunc(void(*func)(int button,int state,int x,int y));
参数:func:处理鼠标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)提供了鼠标当前的窗口坐标(以左上角为原点)。
键盘相关知识可参考:http://blog.csdn.net/xie_zi/article/details/1911891
菜单相关知识可参考:http://blog.csdn.net/xie_zi/article/details/1963383
4.示范代码:
(1)鼠标控制旋转的正方形
1 #include <GL/glut.h> 2 3 #include <math.h> 4 5 #include <stdlib.h> 6 7 #define DEGREES_TO_RADIANS 3.14159/180.0 8 9 static GLfloat spin = 0.0; 10 11 GLfloat x = 0.0; 12 13 GLfloat y = 0.0; 14 15 GLfloat size = 50.0; 16 17 GLfloat angle = 2.0; 18 19 GLsizei wh = 500, ww = 500; 20 21 void square() 22 23 { 24 25 glBegin(GL_QUADS); 26 27 glVertex2f(x,y); 28 29 glVertex2f(-y,x); 30 31 glVertex2f(-x,-y); 32 33 glVertex2f(y,-x); 34 35 glEnd(); 36 37 } 38 39 void spinDisplay(void) 40 41 { 42 43 spin = spin + 2.0; 44 45 if (spin > 360.0) spin = spin - 360.0; 46 47 x=125.0 * cos(DEGREES_TO_RADIANS*spin); 48 49 y=125.0 * sin(DEGREES_TO_RADIANS*spin); 50 51 glutPostRedisplay(); 52 53 } 54 55 void mydisplay() 56 57 { 58 59 glClear(GL_COLOR_BUFFER_BIT); 60 61 glColor3f(1.0, 1.0, 1.0); 62 63 square(); 64 65 glutSwapBuffers(); 66 67 } 68 69 void init() 70 71 { 72 73 glClearColor (0.0, 0.0, 0.0, 1.0); 74 75 } 76 77 void myreshape(GLint w, GLint h) { 78 79 glViewport(0, 0, w, h); 80 81 glMatrixMode(GL_PROJECTION); 82 83 glLoadIdentity(); 84 85 glOrtho(-w/2, w/2, -h/2, h/2, -1.0, 1.0); 86 87 glMatrixMode(GL_MODELVIEW); 88 89 ww = w; 90 91 wh = h; 92 93 } 94 95 void mymouse(GLint button, GLint state, GLint wx, GLint wy) 96 97 { 98 99 if(button ==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 100 101 exit(0); 102 103 if(button ==GLUT_LEFT_BUTTON && state == GLUT_DOWN) 104 105 glutIdleFunc(spinDisplay); 106 107 if(button== GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) 108 109 glutIdleFunc(NULL); 110 111 } 112 113 void main(int argc, char** argv) 114 115 { 116 117 glutInit(&argc,argv); 118 119 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 120 121 glutInitWindowSize(500,500); 122 123 glutInitWindowPosition(0,0); 124 125 glutCreateWindow("double"); 126 127 init(); 128 129 glutDisplayFunc(mydisplay); 130 131 glutReshapeFunc(myreshape); 132 133 glutMouseFunc(mymouse); 134 135 glutIdleFunc(spinDisplay); 136 137 glutMainLoop(); 138 139 }
VC++工程代码(VC++2008)
(2)鼠标当前位置绘制方框
1 #include <GL/glut.h> 2 3 #include <math.h> 4 5 #include <stdlib.h> 6 7 GLfloat x = 0.0; 8 9 GLfloat y = 0.0; 10 11 GLfloat size = 50.0; 12 13 GLsizei wh = 500, ww = 500; 14 15 void drawSquare(GLint x, GLint y) { 16 17 y = wh-y; 18 19 glBegin(GL_POLYGON); 20 21 glVertex3f(x + size, y + size, 0); 22 23 glVertex3f(x - size, y + size, 0); 24 25 glVertex3f(x - size, y - size, 0); 26 27 glVertex3f(x + size, y - size, 0); 28 29 glEnd(); 30 31 } 32 33 void mydisplay() 34 35 { 36 37 glClear(GL_COLOR_BUFFER_BIT); 38 39 glColor3f(1.0, 1.0, 1.0); 40 41 drawSquare(x, y); 42 43 glutSwapBuffers(); 44 45 glutPostRedisplay(); 46 47 } 48 49 void init() 50 51 { 52 53 glClearColor (0.0, 0.0, 0.0, 1.0); 54 55 } 56 57 void myreshape(GLint w, GLint h) { 58 59 glViewport(0, 0, w, h); 60 61 glMatrixMode(GL_PROJECTION); 62 63 glLoadIdentity(); 64 65 glOrtho(0, w, 0, h, -1.0, 1.0); 66 67 glMatrixMode(GL_MODELVIEW); 68 69 ww = w; 70 71 wh = h; 72 73 } 74 75 void mymouse(GLint button, GLint state, GLint wx, GLint wy) 76 77 { 78 79 if(button ==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 80 81 exit(0); 82 83 if(button ==GLUT_LEFT_BUTTON && state == GLUT_DOWN) 84 85 { 86 87 x = wx; 88 89 y = wy; 90 91 } 92 93 } 94 95 void main(int argc, char** argv) 96 97 { 98 99 glutInit(&argc,argv); 100 101 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 102 103 glutInitWindowSize(500,500); 104 105 glutInitWindowPosition(0,0); 106 107 glutCreateWindow("double"); 108 109 init(); 110 111 glutDisplayFunc(mydisplay); 112 113 glutReshapeFunc(myreshape); 114 115 glutMouseFunc(mymouse); 116 117 glutMainLoop(); 118 119 }
VC++工程代码(VC++2008)
5. 实验作业:
试比较所给两个示范代码的窗口坐标系有何不同。实现一通过鼠标右键菜单切换来绘图的简单程序,可以尝试绘制直线、三角形、正方形等常见图形。