GLUT鼠標

轉自:http://blog.csdn.net/xie_zi/article/details/1925778


在前幾節,我們看了怎麼使用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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章