1장 3절 - Keyboard Event

|

Keyboard Event

 

 

 

OpenGL programming 에서의 Keyboard 로 Event 를 처리하기 위한 기능으로 2개의 callback 함수가 있다.  일반 Keyboard 를 처리하는 glKeyboardFunc() 와 특수 Keyboard 를 처리하는 glSpecialFunc() 이다.  함수의 syntax 를 보면...

 

void glutKeyboardFunc( void (*func)(unsigned char key, int x, int y) );
void glutSpecialFunc( void (*func)(int key, int x, int y) );

 

과 같다.

 

참고 Site:    glutKeyboardFunc()   http://www.opengl.org/resources/libraries/glut/spec3/node49.html

                   glutSpecialFunc()   http://www.opengl.org/resources/libraries/glut/spec3/node54.html

 

 

main() 함수에 위 2개의 callback 함수를 call 한 다음, 필요한 함수를 작성해 보자.

 

             .

             .
      // initialize rendering & register callbacks
      initRendering();
      glutDisplayFunc( display );
      glutReshapeFunc( reshape );

 

      glutKeyboardFunc( keyboard );

      glutSpecialFunc( special );

 

      glMainLoop();

      return 0;

}

 

keyboard() 함수:

 

void  keyboard( unsigned char key, int x, int y )
{
      int   mod;

 

      switch (key) {
         case 'r':
                  red = 1.0f; green = 0.0f; blue = 0.0f;
                  mod = glutGetModifiers();
                  if (mod && GLUT_ACTIVE_ALT) {
                        red = 0.5f;
                  }
                  break;

         case 'g':
                  red = 0.0f; green = 1.0f; blue = 0.0f;
                  mod = glutGetModifiers();
                  if (mod && GLUT_ACTIVE_ALT) {
                        green = 0.5f;
                  }
                  break;

         case 'b':
                  red = 0.0f; green = 0.0f; blue = 1.0f;
                  mod = glutGetModifiers();
                  if (mod && GLUT_ACTIVE_ALT) {
                        blue = 0.5f;
                  }
                  break;

         case 'y':
                  red = 1.0f; green = 1.0f; blue = 0.0f;
                  mod = glutGetModifiers();
                  if (mod && GLUT_ACTIVE_ALT) {
                        red = 0.5f; green = 0.5f;
                  }
                  break;

         case 'c':
                  red = 0.0f; green = 1.0f; blue = 1.0f;
                  mod = glutGetModifiers();
                  if (mod && GLUT_ACTIVE_ALT) {
                        green = 0.5f; blue = 0.5f;
                  }
                  break;

         case 'm':
                  red = 1.0f; green = 0.0f; blue = 1.0f;
                  mod = glutGetModifiers();
                  if (mod && GLUT_ACTIVE_ALT) {
                        red = 0.5f; blue = 0.5f;
                  }
                  break;

         case '+':
                  magfac += 0.02;
                  break;
         case '-':
                  magfac -= 0.02;
                  break;
         case 27:

                  exit(0);
                  break;

         default:
                  red = 1.0f; green = 1.0f; blue = 1.0f; alpha = 1.0f;
                  break;
      }

      glutPostRedisplay();
}

 

special() 함수:

 

void  special( int key, int x, int y )
{
      switch (key) {
         //  select image view mode when reshape the window
         case GLUT_KEY_F1: // both object shape & size is not changed
                  viewmode = 1; // Ortho view mode
                  break;

         case GLUT_KEY_F2: // both object shape & size is chaned
                  viewmode = 2; // Ortho view mode
                  break;

         case GLUT_KEY_F3: // object shape is not changed but object size is chaned
                  viewmode = 3; // Frustum view mode
                  break;
         case GLUT_KEY_F4: // object shape is not changed but object size is chaned
                  viewmode = 4; // Perspective view mode
                  break;


         //  spin key for image rotation
         case GLUT_KEY_UP:
                  xrot -= 2.0f;
                  if (xrot < -360.0f) xrot += 360.0f;
                  break;
         case GLUT_KEY_DOWN:
                  xrot += 2.0f;
                  if (xrot > +360.0f) xrot -= 360.0f;
                  break;
         case GLUT_KEY_LEFT:
                  yrot -= 2.0f;
                  if (yrot < -360.0f) yrot += 360.0f;
                  break;
         case GLUT_KEY_RIGHT:
                  yrot += 2.0f;
                  if (yrot > +360.0f) yrot -= 360.0f;
                  break;
         case GLUT_KEY_PAGE_DOWN:
                  zrot -= 2.0f;
                  if (zrot < -360.0f) zrot += 360.0f;
                  break;
         case GLUT_KEY_PAGE_UP:
                  zrot += 2.0f;
                  if (zrot > +360.0f) zrot -= 360.0f;
                  break;
         case GLUT_KEY_HOME:
                  xrot = yrot = zrot = 0.0f;
                  break;

         case '+':
                  magfac += 0.02;
                  break;
         case '-':
                  magfac -= 0.02;
                  break;

         case GLUT_KEY_F10:
                  glutFullScreen();
                  break;

         case GLUT_KEY_F9:
                  glutReshapeWindow( wwidth, wheight );
                  glutPositionWindow( 100, 100 );
                  break;

         default:
                  break;
      }

      glutPostRedisplay();
}

 

그리고 display() 함수를 다음과 같이 수정하고,  몇개의 전역변수를 더한다.

 

// global variables

GLfloat   xrot, yrot, zrot;
GLfloat   red=1.0, green=1.0, blue=1.0, alpha=1.0;

 

void  display( void )
{
      char  info[128];

 

      // clear all color & depth buffers
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

 

      /*  Translate & rotate the image  */
      glPushMatrix();
      glTranslatef( 1.0, 1.0, 0.0 );       // move rotation axis to triangle center
      glRotatef( xrot, 1.0f, 0.0f, 0.0f ); // rotate the image
      glRotatef( yrot, 0.0f, 1.0f, 0.0f );
      glRotatef( zrot, 0.0f, 0.0f, 1.0f );
      glTranslatef(-1.0, -1.0, 0.0 );      // restore axis origin


      /*  Draw triangle  */
      glColor4f( red, green, blue, alpha ); // color set as RGBA 
      glBegin( GL_TRIANGLES );
            glVertex3f( 0.0f, 0.0f, 0.0f );
            glVertex3f( 2.0f, 1.0f, 0.0f );
            glVertex3f( 1.0f, 2.0f, 0.0f );
      glEnd();
      glPopMatrix();     // restore the coord. matrix


      sprintf( info, "x=%.1f, y=%.1f, z=%.1f,  mag=%.2f", xrot, yrot, zrot, magfac );
      glutSetWindowTitle( info );

 

      glFlush();
}

 

함수 glPushMatrix() 는 이전 변환행렬을 저장하고  glPopMatrix() 는 Push 로 저장된 행렬값을 가져오는 역할을 한다.  따라서 glRotate*(), glTranslate*(), glScale*() 등의 함수의 기능을 활성화하기 위하여 앞뒤로 위의 두 함수를 지정해 놓는다.

 

컴파일 후 프로그램을 실행하고,  'g' key 를 누르고, PgUp key 로 삼각형을 회전시키면 다음과 같은 결과를 얻는다.  Window Title 창에 x, y, z 축에 대한 회전각이 나타난다.  이는 glutSetWindowTitle() 함수를 통해 실현된다.   위,아래, 좌,우 화살표로 여러 방향으로 회전을 시켜 이미지를 관찰할 수 있다.   또한 '+' 와 '-' key 를 사용하여 이미지의 크기를 확대하고 줄일 수 있다.   'Esc' key 를 누르면 프로그램이 종료된다.   위 프로그램에서 glRotate*(angle, x, y, z );  함수는 좌표계의 축에 따라 주어진 각만큼 이미지를 회전시키는 역할을 한다.

 

 

 

 

일반키와 특수키에 대한 내용은 쉽게 이해할 수 있다.  키 callback 함수에서 SHIFT, CTRL 또는 ALT 키를 동시에 눌러 Event 를 Handle 할 경우에는 glutGetModifiers() 함수와 함께 GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, GLUT_ACTIVE_ALT  mode 를 연계시켜 사용한다.

위의 프로그램에서 Alt + r, 또는 Alt + b 등을 Test 해 보면 삼각형의 색상변화를 볼 수 있다.  Special key 에서의 Ctrl+Alt+F7 과 같이 동시에 3개의 키를 사용할 때는 다음과 같이 표현한다.

 

          .

          .

      mod = glutGetModifiers();
      if (mod && (GLUT_ACTIVE_CTRL | GLUT_ACTIVE_ALT)) {

          .

          .

 

참고 Site: glutGetModifiers() http://www.opengl.org/resources/libraries/glut/spec3/node73.html

 

 

 

 

Advanced Keyboard 기능

 

화살표 같은 key 를 계속눌러 자동반복을 실행하면, 약간의 delay 현상이 일어난다.  이러한 자동반복의 문제점을 해결해주는 함수들을 살펴보자.

 

 int  glutSetRepeat( int repeatMode );

 

Parameters:

  • GLUT_KEY_REPEAT_OFF      -  자동반복 Mode 기능 비활성
  • GLUT_KEY_REPEAT_ON       -  자동반복 Mode 기능 활성
  • GLUT_KEY_REPEAT_DEFAUT   -  default 상태로 자동반복 Mode 를 Reset

 

위 함수는 전역기반으로 작용한다. 즉 Application 으로부터 하나가 아닌 모든 Window 의 반복기능에 영향을 준다.  따라서 이 함수를 자동 mode 의 비활성화로 사용할 때는 Application 을 끝내기 전 default 상태로 복원하는 것이 편리하다.

 

Key 반복이 일어날 때의 callback 받는것을 비활성화 시켜, 다른 Application 에 영향을 주지않고 안전하게 key 누름을 무시해야 할 때가 있다.  이러한 경우의 함수는

 

int  glutIgnoreKeyRepeat( int repeatMode );

 

Parameters:

  • repeatMode – 0 이면 자동반복 mode 활성, 0 이 아니면 자동반복 mode 비활성 

 

어느 경우,  key 반복이 일어날 때 callback 받는것을 멈출것이다.  만약 key 를 누르고 있는 동안에만 어떤 Action 이 실행되기를  원한다면,  그 key 가 누르기를 해지하는 때를 또한 알아야 한다.  GLUT 는 key 가 해지 되었을 때를 위한 두개의 register callback 기능을 제공한다.

 

void  glutKeyboardUpFunc( void (*func)(unsigned char key,int x,int y) );
void  glutSpecialUpFunc( void (*func)(int key,int x, int y) );

 

Parameters:

  • func – callback 함수 이름 

 

 

 

 

Source Code:         01_3 - keyboard.zip             01_3 - advanced_keyboard.zip

 

 

 

 

 

'OpenGL 활용 > 1장 - Basic' 카테고리의 다른 글

1장 6절 - Mouse Motion Event  (0) 2013.01.22
1장 5절 - Mouse Event  (0) 2013.01.22
1장 4절 - Animation by Idling  (0) 2013.01.21
1장 2절 - Resize OpenGL Window  (0) 2013.01.20
1장 1절 - Create a Simple OpenGL Window  (0) 2013.01.19
And