在前幾節(jié),我們看了怎么使用GLUT的keyboard函數(shù),來(lái)增加一個(gè)OpenGL程序的交互性?,F(xiàn)在,是時(shí)候研究下鼠標(biāo)了。GLUT的鼠標(biāo)接口提供一些列的選項(xiàng)來(lái)增加鼠標(biāo)的交互性。也就是檢測(cè)鼠標(biāo)單擊,和鼠標(biāo)移動(dòng)。
檢測(cè)鼠標(biāo)Clicks
和鍵盤處理一樣,GLUT為你的注冊(cè)函數(shù)(也就是處理鼠標(biāo)clicks事件的函數(shù))提供了一個(gè)方法。函數(shù)glutMouseFunc,這個(gè)函數(shù)一般在程序初始化階段被調(diào)用。函數(shù)原型如下:
void glutMouseFunc(void(*func)(int button,int state,int x,int y));
參數(shù):
func:處理鼠標(biāo)click事件的函數(shù)的函數(shù)名。
從上面可以看到到,處理鼠標(biāo)click事件的函數(shù),一定有4個(gè)參數(shù)。
第一個(gè)參數(shù)表明哪個(gè)鼠標(biāo)鍵被按下或松開(kāi),這個(gè)變量可以是下面的三個(gè)值中的一個(gè):
GLUT_LEFT_BUTTON
GLUT_MIDDLE_BUTTON
GLUT_RIGHT_BUTTON
第二個(gè)參數(shù)表明,函數(shù)被調(diào)用發(fā)生時(shí),鼠標(biāo)的狀態(tài),也就是是被按下,或松開(kāi),可能取值如下:
GLUT_DOWN
GLUT_UP
當(dāng)函數(shù)被調(diào)用時(shí),state的值是GLUT_DOWN,那么程序可能會(huì)假定將會(huì)有個(gè)GLUT_UP事件,甚至鼠標(biāo)移動(dòng)到窗口外面,也如此。然而,如果程序調(diào)用glutMouseFunc傳遞NULL作為參數(shù),那么GLUT將不會(huì)改變鼠標(biāo)的狀態(tài)。
剩下的兩個(gè)參數(shù)(x,y)提供了鼠標(biāo)當(dāng)前的窗口坐標(biāo)(以左上角為原點(diǎn))。
檢測(cè)動(dòng)作(motion)
GLUT提供鼠標(biāo)motion檢測(cè)能力。有兩種GLUT處理的motion:active motion和passive motion。
Active motion是指鼠標(biāo)移動(dòng)并且有一個(gè)鼠標(biāo)鍵被按下。(拖動(dòng)鼠標(biāo))
Passive motion是指當(dāng)鼠標(biāo)移動(dòng)時(shí),并有沒(méi)鼠標(biāo)鍵按下。(移動(dòng)鼠標(biāo))
如果一個(gè)程序正在追蹤鼠標(biāo),那么鼠標(biāo)移動(dòng)期間,沒(méi)一幀將產(chǎn)生一個(gè)結(jié)果。
和以前一樣,你必須注冊(cè)將處理鼠標(biāo)事件的函數(shù)(定義函數(shù))。GLUT讓我們可以指定兩個(gè)不同的函數(shù),一個(gè)追蹤passive motion,另一個(gè)追蹤active motion
它們的函數(shù)原型,如下:
void glutMotionFunc(void(*func)(int x,int y));
void glutPassiveMotionFunc(void (*func)(int x,int y));
參數(shù):
Func:處理各自類型motion的函數(shù)名。
處理motion的參數(shù)函數(shù)的參數(shù)(x,y)是鼠標(biāo)在窗口的坐標(biāo)。以左上角為原點(diǎn)。
檢測(cè)鼠標(biāo)進(jìn)入或離開(kāi)窗口
GLUT還能檢測(cè)鼠標(biāo)鼠標(biāo)離開(kāi),進(jìn)入窗口區(qū)域。一個(gè)回調(diào)函數(shù)可以被定義去處理這兩個(gè)事件。GLUT里,調(diào)用這個(gè)函數(shù)的是glutEntryFunc,函數(shù)原型如下:
void glutEntryFunc(void(*func)(int state));
參數(shù):
Func:處理這些事件的函數(shù)名。
上面函數(shù)的參數(shù)中,state有兩個(gè)值:
GLUT_LEFT 鼠標(biāo)離開(kāi)窗口
GLUT_ENTERED 鼠標(biāo)進(jìn)入窗口
表明,是離開(kāi),還是進(jìn)入窗口。
把它們放一起
首先我們要做的是在GLUT里定義哪些函數(shù)將負(fù)責(zé)處理鼠標(biāo)事件。因此我們將重寫我們的main函數(shù),讓它包含所有必須的回調(diào)注冊(cè)函數(shù)。我們將在程序里描述其他一些教程里沒(méi)說(shuō)清楚的地方。
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,現(xiàn)在做點(diǎn)有趣的。我們將定義那些將做一些不可思議事件的回調(diào)函數(shù)。當(dāng)一個(gè)鼠標(biāo)鍵和alt鍵都被按下,我們將改變?nèi)切蔚念伾?。鼠?biāo)左鍵使三角形變成紅色,中間的將三角形變成綠色,鼠標(biāo)右鍵將三角形變成藍(lán)色。函數(shù)如下:
void processMouse(int button, int state, int x, int y) { specialKey = glutGetModifiers(); // 當(dāng)鼠標(biāo)鍵和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; } }}接下來(lái)有一個(gè)精細(xì)的顏色拾取方法。當(dāng)一個(gè)鼠標(biāo)鍵被按下,但alt鍵被被按下。我們把blue設(shè)為0.0,并且讓red和green分量的值取決于鼠標(biāo)在窗口中的位置。。函數(shù)如下:
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添加一些動(dòng)作。當(dāng)shift鍵被按下,鼠標(biāo)將在x軸上有一個(gè)旋轉(zhuǎn)。我們不得不修改renderScene函數(shù)。函數(shù)如下:
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();}現(xiàn)在我們的有個(gè)函數(shù)處理passive motion事件。函數(shù)將改變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; }}最后鼠標(biāo)離開(kāi)窗口將使動(dòng)畫停止,為了做到這,我們也需要改變函數(shù)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是最后一個(gè)函數(shù)。注意,這個(gè)在微軟操作系統(tǒng)下可能工作的不是很好。void processMouseEntry(int state) { if (state == GLUT_LEFT) deltaAngle = 0.0; else deltaAngle = 1.0;}VC6.0工程可以在這里下載(glut8.zip)。 (到這里位置,鍵盤,鼠標(biāo)方面的控制講完了,下面就是菜單了。)(原文地址:http://www./opengl/glut/index.php?9)
本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/xie_zi/archive/2007/12/09/1925778.aspx