轉載:http://blog.csdn.net/xie_zi/archive/2007/12/09/1925778.aspx
GLUT教程 鼠標
在前幾節,我們看了怎么使用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)。 (到這里位置,鍵盤,鼠標方面的控制講完了,下面就是菜單了。)(原文地址:http://www.lighthouse3d.com/opengl/glut/index.php?9)
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/xie_zi/archive/2007/12/09/1925778.aspx