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. 實驗作業:
試比較所給兩個示范代碼的窗口坐標系有何不同。實現一通過鼠標右鍵菜單切換來繪圖的簡單程序,可以嘗試繪制直線、三角形、正方形等常見圖形。