GLUT 事件處理函式 靜宜大學資管系 蔡奇偉 副教授 2003-2006
大綱 註冊處理事件的 callback 函式 註冊鍵盤輸入的 callback 註冊滑鼠操作的 callback glutKeyboardFunc glutSpecialFunc 註冊滑鼠操作的 callback glutMouseFunc glutMotionFunc & glutPassiveMotionFunc glutGetModifiers
glutKeyboardFunc void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)); 此函式註冊處理鍵盤輸入字元鍵的 callback 函式。當使用者在目前視窗中敲入能產生 ASCII 碼的按鍵時,GLUT 就會自動執行你所指定的 callback 函式,並傳入下列三項資料: key: 輸入鍵的 ASCII 碼。 x: 按鍵時滑鼠在視窗位置的 x 座標。 y: 按鍵時滑鼠在視窗位置的 y 座標。
範例 // draw_triangle(), draw_square(), and draw_circle() are // functions to darw a triangle, a square, and a circle, // respectively. void draw_figure (unsigned char key, int x, int y) { switch (key) { case ‘1’: draw_triangle(); break; case ‘2’: draw_square(); break; case ‘3’: draw_circle(); break; } glutPostRedisplay(); // update the window // in main() function // glutKeyboardFunc(draw_figure);
glutSpecialFunc void glutSpecialFunc(void (*func)(int key, int x, int y)); 此函式註冊處理鍵盤輸入功能鍵或方向鍵的 callback 函式。當使用者在目前視窗中敲入功能鍵或方向鍵時,GLUT 就會自動執行你所指定的 callback 函式,並傳入下列三項資料: key: 功能鍵或方向鍵的 GLUT 鍵名(見下一頁)。 x: 按鍵時滑鼠在視窗位置的 x 座標。 y: 按鍵時滑鼠在視窗位置的 y 座標。
GLUT 鍵名 按鍵 GLUT_KEY_F1 F1 功能鍵 GLUT_KEY_F2 F2 功能鍵 GLUT_KEY_F3 F3 功能鍵 GLUT_KEY_F4 F4 功能鍵 GLUT_KEY_F5 F5 功能鍵 GLUT_KEY_F6 F6 功能鍵 GLUT_KEY_F7 F7 功能鍵 GLUT_KEY_F8 F8 功能鍵 GLUT_KEY_F9 F9 功能鍵 GLUT_KEY_F10 F10 功能鍵 GLUT_KEY_F11 F11 功能鍵 GLUT_KEY_F12 F12 功能鍵 GLUT_KEY_LEFT 方向鍵 GLUT_KEY_UP 方向鍵 GLUT_KEY_RIGHT 方向鍵 GLUT_KEY_DOWN 方向鍵 GLUT_KEY_PAGE_UP Page up 方向鍵 GLUT_KEY_PAGE_DOWN Page down 方向鍵 GLUT_KEY_HOME Home 方向鍵 GLUT_KEY_END End 方向鍵 GLUT_KEY_INSERT Insert 鍵
範例 #include <GL/glut.h> int window_width = 250, window_height = 250; float center_x = 0.5, center_y = 0.5, half_width = 0.25; const float inc_amount = 0.01; void display(void) { glClear (GL_COLOR_BUFFER_BIT); /* clear all pixels */ glColor3f (1.0, 1.0, 1.0); glBegin(GL_POLYGON); glVertex3f (center_x - half_width, center_y - half_width, 0.0); glVertex3f (center_x + half_width, center_y - half_width, 0.0); glVertex3f (center_x + half_width, center_y + half_width, 0.0); glVertex3f (center_x - half_width, center_y + half_width, 0.0); glEnd(); glFlush (); }
void handle_special_key (int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: if (center_x >= half_width) center_x -= inc_amount; break; case GLUT_KEY_RIGHT: if (1.0 - center_x >= half_width) center_x += inc_amount; case GLUT_KEY_UP: if (1.0 - center_y >= half_width) center_y += inc_amount; case GLUT_KEY_DOWN: if (center_y >= half_width) center_y -= inc_amount; } glutPostRedisplay(); // update the window
void handle_key (unsigned char key, int x, int y) { switch (key) { case 's': if (half_width >= 0.1) half_width -= inc_amount; break; case 'l': if (half_width < 0.5) half_width += inc_amount; } glutPostRedisplay(); // update the window
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (window_width, window_height); glutInitWindowPosition (100, 100); glutCreateWindow ("hello"); init (); glutDisplayFunc(display); glutKeyboardFunc(handle_key); glutSpecialFunc(handle_special_key); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }
glutMouseFunc void glutMouseFunc(void (*func)(int button, int state, int x, int y)); 此函式註冊處理滑鼠按鈕的 callback。當滑鼠按鈕在目前視窗中按下或放開時, GLUT 就會自動執行你所指定的 callback 函式。 button: 下列三種按鈕值之一 GLUT_LEFT_BUTTON(左按鈕) GLUT_MIDDLE_BUTTON(中按鈕) GLUT_RIGHT_BUTTON(右按鈕) state: 按鈕的狀態 GLUT_UP(放開按鈕) GLUT_DOWN(壓下按鈕) x, y: 按鈕操作發生時滑鼠的視窗座標。
範例 void handle_mouse_buttons (int button, int state, int x, int y) { if (state == GLUT_DOWN) { // 只處理壓下滑鼠按鈕 switch (button) { case GLUT_LEFT_BUTTON: // 處理滑鼠的左按鈕 break; case GLUT_MIDDLE_BUTTON: // 處理滑鼠的中按鈕 case GLUT_RIGHT_BUTTON: // 處理滑鼠的右按鈕 } // in main() function glutMouseFunc(handle_mouse_buttons);
glutMotionFunc & glutPassiveMotionFunc void glutMotionFunc(void (*func)(int x, int y)); 此函式註冊處理滑鼠移動的 callback。按住任何一個滑鼠鈕在目前視窗中移動滑鼠時, GLUT 就會自動執行你所指定的 callback 函式。 void glutPassiveMotionFunc(void (*func)(int x, int y)); 此函式註冊處理滑鼠移動的 callback。當不按任何鈕地在目前視窗中移動滑鼠時, GLUT 就會自動執行你所指定的 callback 函式。 x, y: 移動時滑鼠在視窗位置的座標。
glutGetModifiers int glutGetModifiers(void); GLUT_ACTIVE_SHIFT 若按下 Shift 鍵或 Caps Lock 鍵 GLUT_ACTIVE_CTRL 若按下 Ctrl 鍵 GLUT_ACTIVE_ALT 若按下 Alt 鍵 此函式傳回鍵盤輸入或滑鼠操作時的修飾鍵狀態。在鍵盤 callback 或滑鼠 callback 中,你可以把函式的傳回值和上面的三個常數做 bit AND 運算來測試那一個修飾鍵被按下。譬如: int modifier_key = glutGetModifiers(); if (modifier_key & GLUT_ACTIVE_CTRL) { // 按下 Ctrl 鍵 }
範例 /* * mouseclick.c * This is a simple, introductory OpenGL program. */ #include <GL/glut.h> #include <stdio.h> int window_width = 250, window_height = 250; const int max_point = 100; GLint x_coord[max_point], y_coord[max_point]; int nPoints = 0; inline GLfloat x_convert (int x) { return x/(window_width-1.0); } inline GLfloat y_convert (int y) return 1.0 - y /(window_height-1.0);
void display(void) { glClear (GL_COLOR_BUFFER_BIT); /* clear all pixels */ glColor3f (1.0, 1.0, 1.0); glBegin(GL_POINTS); for (int i = 0; i < nPoints; i++) { glVertex3f (x_convert(x_coord[i]), y_convert(y_coord[i]), 0.0); } glEnd(); glFlush (); void handle_mouseclick (int button, int state, int x, int y) if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { if (nPoints == max_point) nPoints = 0; x_coord[nPoints] = x; y_coord[nPoints] = y; nPoints++; glutPostRedisplay();
int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (window_width, window_height); glutInitWindowPosition (100, 100); glutCreateWindow ("mouseclick"); init (); glutDisplayFunc(display); glutMouseFunc(handle_mouseclick); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }
範例 /* * hermite.c * This is a simple, introductory OpenGL program. */ #include <GL/glut.h> #include <stdio.h> int window_width = 250, window_height = 250; GLfloat x_coord[3], y_coord[3]; int nPoints = 0; inline GLfloat x_convert (int x) { return x/(float)(window_width-1); } inline GLfloat y_convert (int y) return 1.0 - y /(float)(window_height-1);
void HermiteCurve(int n) { float t, dt, t2, t3, f1, f2, f3, f4; dt = 1.0/n; // t runs from 0 to 1. GLfloat PT0_x = x_coord[1] - x_coord[0]; GLfloat PT0_y = y_coord[1] - y_coord[0]; GLfloat PT1_x = x_coord[2] - x_coord[1]; GLfloat PT1_y = y_coord[2] - y_coord[1]; glBegin(GL_LINE_STRIP); for (t = 0.0; t <= 1.0; t += dt) { t2 = t * t; t3 = t2 * t; // t3 = t * t * t f1 = 2.0*t3 - 3.0*t2 + 1.0; f2 = -2.0*t3 + 3.0*t2; f3 = t3 - 2.0*t2 + t; f4 = t3 - t2; glVertex2f( f1*x_coord[0] + f2*x_coord[2] + f3*PT0_x + f4*PT1_x, f1*y_coord[0] + f2*y_coord[2] + f3*PT0_y + f4*PT1_y ); } glEnd();
void display(void) { glClear (GL_COLOR_BUFFER_BIT); /* clear all pixels */ glColor3f (0.0, 1.0, 0.0); glBegin(GL_LINE_STRIP); for (int i = 0; i < nPoints; i++) { glVertex3f (x_coord[i], y_coord[i], 0.0); } glEnd(); if (nPoints == 3) { glColor3f (1.0, 1.0, 1.0); HermiteCurve(20); glFlush ();
void handle_mouseclick (int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { if (nPoints == 3) nPoints = 0; x_coord[nPoints] = x_convert(x); y_coord[nPoints] = y_convert(y); nPoints++; glutPostRedisplay(); }