'OpenGL 활용/1장 - Basic'에 해당되는 글 6건
- 2013.01.22 1장 6절 - Mouse Motion Event
- 2013.01.22 1장 5절 - Mouse Event
- 2013.01.21 1장 4절 - Animation by Idling
- 2013.01.20 1장 3절 - Keyboard Event
- 2013.01.20 1장 2절 - Resize OpenGL Window
- 2013.01.19 1장 1절 - Create a Simple OpenGL Window
Mouse Motion Event
GLUT 는 Mouse 를 Window 위에서 움직여 Window 상에 있는 물체에 움직임을 줄 수 있는 다음 2개의 callback 함수를 제공하고 있다.
void glutMotionFunc( void (*func)(int x, int y) ); |
위 두 개의 함수중 위의 것은 Mouse 를 눌렀을때의 Window 상의 위치 (x, y), 아래의 함수는 Mouse를 누르지 않았을 때의 위치를 기억한다. 위의 함수는 Mouse callback 함수 glutMouseFunc() 과 함께 사용하여, 필요한 실행에 대해 명령을 하게된다.
앞절의 프로그램에서 다음을 수정하여 보자.
전역지역에 다음의 변수와 함수의 prototype 을 새로 더한다.
. . enum actions { MOVE_OBJECT, ROTATE_OBJECT, ZOOM_OBJECT, DO_NONE };
// function prototypes . void motion( int, int ); . . |
main() 함수:
. .
// idle function registration for animation . . |
display() 함수:
. . // draw a point on the center of window
/* Translate & rotate the image */ . . |
mouse() 함수: 왼쪽 Mouse 를 물체의 회전을 실행하는 것 대신에 물체의 이동에 대한 실행을 하고, 대신 중간 Mouse button 을 눌렀을 때 물체의 회전이 서로 toggling 하도록 다음과 같이 새로 작성한다.
void mouse( int button, int state, int x, int y ) /* Update the saved mouse position */ |
motion() 함수:
void motion( int x, int y ) /* Update the stored mouse position for later use */
glutPostRedisplay(); |
위의 두 함수를 분석해 보면, mouse() 함수에서는 Mouse button 을 눌렀는지, 해지했는지에 대한 정보와 Mouse 를 눌렀을 때의 초기위치를 기억한다. motion() 함수에서는 현재의 Mouse 위치를 찾아 Mouse 가 움직인 거리를 계산하고, 항상 Mouse 위치를 초기화 시킨다. glutPostRedisplay() 함수를 통해 화면을 다시 정리하고 있다. 주의 깊게 보아야 할 점은 두 함수 모두 초기값을 기억하도록 하고 있는데, 이는 두 함수 모두에게 초기치를 기억시켜 mouse 에 대한 정확한 위치계산을 하기 위한 것이다. 두 함수 중에 하나에 대한 초기화를 하지 않았을 경우 움직임을 살펴보면, 사용자가 의도한 정확한 거리계산에 에러가 생기게 된다. motion() 함수에 대한 변수들은 항상 전역변수화 되어 전체 Program 에 영향을 주도록 하는것이 일반적이다.
Mouse 를 누르지 않은 상태에서 어떤 움직임에 대한 실행을 하고자 한다면, 위 두 함수의 Up, Down 의 조건을 서로 바꾸어 주고, glMotionFunc() 대신 glPassiveMotionFunc() callback 함수 를 사용하면 된다. 이 경우는 Mouse button 을 눌렀을 시 요구하는 명령을 실행하지 않게 된다.
Program 을 컴파일 한 후 화면내의 Image 를 Mouse 로 이리저리 Drag 해보면 Image 가 순조롭게 이동하는 것을 볼 수 있다. 화면의 중앙의 위치를 보여주기 위하여, 흰색 점을 하나 추가 하였다. 화살표나 Page Up, Down key, 또는 Space bar 를 사용하여 삼각형을 회전 시켰을 경우 Mouse 의 이동에 대한 물체의 이동 방향이 서로 바꾸어 지는것은 물체의 회전에 따라 좌표축이 회전하고, 그에 따라 Window 의 (x, y) 위치가 서로 뒤집어져 나타나는 현상이다. Program 을 분석하여 보면 그 이유를 이해를 할 수 있을 것이다. 따라서 Home key 를 눌러 회전위치를 원위치로 돌려놓은 후에 Mouse 을 이동 시키면 물체가 Mouse 의 이동방향에 따라 움직이게 된다.
응용 Program:
1장 3 절에 있는 advanced_keyboard 프로그램을 수정하면서 Mouse Motion 에 대한 부분을 좀 더 살펴보자. 이 프로그램은 화살표 Key 를 좌우로 움직여 360 도로 보는 방향을 회전시키고, 상하 화살표 Key 로 물체를 화면의 전후로 이동 (Zoom In & Out) 시키도록 구성되어 있었다. Special key 에 의한 작동을 Mouse 의 왼쪽 과 오른쪽 Button 으로 대체 하여 보는 시각을 이동시키도록 수정하여 보자. Mouse 의 왼쪽 Button 은 시각의 회전, 오른쪽 Button 은 Zoon In/Out 의 역할을 맡는다.
전역 지역에 다음의 변수와 함수의 Prototype 을 첨가한다.
. . GLsizei xini = 0, yini = 0; . // void pressKey( int, int, int ); // 2개의 함수 주석처리 void motion( int, int ); // 새로운 함수 추가 . |
main() 함수:
. .
// enter GLUT event processing cycle . . |
display() 함수: 아래 2개의 함수는 keyboard 를 통해서 들어오는 값은 처리하는 함수이므로 주석처리한다.
. // if (dmov) computePos( dmov ); // 주석처리 . |
pressKey() 와 releaseKey() 함수를 지운 후에, 다음의 motion() 과 mouse() 함수를 만든다.
mouse() 함수:
void mouse( int button, int state, int x, int y ) |
motion() 함수:
void motion( int x, int y ) // update camera's direction dmov = (GLfloat)(yini - y) * 0.05f; |
여기서 보면, Mouse 위치에 대한 초기값과, 최종적인 계산값 angle 에 대한 함수의 위치가, 위에서 설명한 것과 조금 다름을 엿볼 수 있다. 이는 변수 angle 이 motion() 함수에서보다 mouse() 함수에 있을 때 움직임이 좀더 부드럽기 때문이다 (motion() 함수에서 사용하려면 drot 값을 아주 낮게 잡아주어야 함). 이와 같이 Mouse motion 에 대한 것은 mouse() 함수 와 motion() 함수가 전역변수를 통하여 서로 밀접하게 연계되므로, 프로그램하기에 따라 여러 형태로 구성을 할 수 있다.
이제는 좌우 화살표 Key 대신에 Mouse 의 좌우 Button을 누른다음 커서를 이동시켜가며 화면의 물체를 시각을 달리하여 볼 수 있게 되었다.
Source Code: 01_6 - motion.zip
01_6 - advanced_motion.zip
'OpenGL 활용 > 1장 - Basic' 카테고리의 다른 글
1장 5절 - Mouse Event (0) | 2013.01.22 |
---|---|
1장 4절 - Animation by Idling (0) | 2013.01.21 |
1장 3절 - Keyboard Event (0) | 2013.01.20 |
1장 2절 - Resize OpenGL Window (0) | 2013.01.20 |
1장 1절 - Create a Simple OpenGL Window (0) | 2013.01.19 |
Mouse Event
GLUT 에서는 Mouse 의 Button 을 눌러 Event 를 Handling 하는 것을 제공하고 있다. Mouse event 에 대한 callback 함수는
void glutMouseFunc( void (*func)(int button, int state, int x, int y) ); |
로 표현하는데, 변수 button 은 mouse 의 왼쪽, 중간, 오른쪽 button 을 선택하고, state 는 누름과 해지, x, y 는 Window 위의 pixel 위치를 확인한다. 위 함수는 단독으로 사용하는것은 별로 많지 않지만, 다음에 배울 mouse motion 과 Popup Menu 의 기능을 함께 할 때 연계되어 많이 사용된다.
이전 animation 프로그램에서 몇 가지를 새로 수정해보자.
전역변수:
GLboolean rot_status = FALSE; |
main() 함수:
. . // handling input events
// idle function registration for animation . |
main() 함수에서 새로 glutMouseFunc() callback 함수를 첨가하고, glutIdleFunc() callback 함수를 주석 처리 하였다.
다음의 glutMouseFunc() callback 함수에 필요한 mouse() 함수를 다음과 같이 작성해 program 에 첨가해 보자.
void mouse( int button, int state, int x, int y ) |
왼쪽 mouse button 을 누르면, idle callback 함수를 활성화 시키고, 가운데, 또는 오른쪽 mouse button 을 눌렀을 시 비활성화 시키도록 하였다. 따라서 왼쪽과 오른쪽 mouse button 을 눌러 삼각형의 회전을 멈추고, 다시 시작하고 할 수 있다. '<' , '>' key 를 사용하여 회전 속도를 변화시킬수 있다.
Source Code: 01_5 - mouse.zip
'OpenGL 활용 > 1장 - Basic' 카테고리의 다른 글
1장 6절 - Mouse Motion Event (0) | 2013.01.22 |
---|---|
1장 4절 - Animation by Idling (0) | 2013.01.21 |
1장 3절 - Keyboard Event (0) | 2013.01.20 |
1장 2절 - Resize OpenGL Window (0) | 2013.01.20 |
1장 1절 - Create a Simple OpenGL Window (0) | 2013.01.19 |
Animation by Idling
OpenGL 에서 이미지의 움직임과 동작을 주기 위한 방법으로 glutIdleFunc() 과 glutTimerFunc() callback 함수가 있다. 함수의 syntax 는 다음과 같다.
void glutIdleFunc( void (*func)(void) ); void glutTimerFunc( unsigned int millisec, void (*func)(int value), int value ); |
참고 Site: glutIdleFunc() http://www.opengl.org/resources/libraries/glut/spec3/node63.html
glutTimerFunc() http://www.opengl.org/resources/libraries/glut/spec3/node64.html
간단한 Animation 을 해보기 위해 다음의 함수를 main() 함수에 등록하고, idle() 함수 와 Timer() 함수를 만들어 보자.
추가 전역변수:
GLfloat speed = 1.0; GLboolean rot_status = TRUE; |
main() 함수:
. . // init GLUT and create Window .
// enter GLUT event processing cycle . . |
diaplay() 함수: 마지막의 glFlush(); 를 주석처리 해주고 대신
. . // glFlush(); // 주석처리 |
keyboard() 함수: 삼각형의 회전 속도의 변화를 주기위하여 다음을 더한다.
. . case ' ': // space bar . . |
idle() 함수:
void idle( void ) { zrot += speed * 0.025f; if (zrot > 360.0f) zrot -= 360.0f; glutPostRedisplay(); // tell GLUT that the display has changed } |
Timer() 함수:
void Timer( int value ) |
main() 에 있는 glutInitDisplayMode() 의 Mode 가 GLUT_SINGLE 에서 GLUT_DOUBLE 로 변화되었음을 볼 수 있다. 그리고 display() 함수의 마지막을 glFlush() 대신 glutSwapBuffers() 를 사용하였다. 이는 GLUT_DOUBLE 로 이중 Buffer 를 사용할여 앞, 뒤의 Buffer 를 서로 Swapping 하면서 교환하라는 명령을 주기 위함이다.
한 Buffer 에서 지웠다 그리기를 계속 반복하면 깜박거림이 발생하여 눈에 거슬리므로 두 개의 Buffer 를 교대로 사용한다. 초기화시에 GLUT_DOUBLE flag 를 전달하면 OpenGL 은 화면에 출력하는 Front Buffer 와 뒤에서 그리는 작업을 하는 Back Buffer, 두 개의 Buffer 를 준비한다. glutSwapBuffers() 에 의해 Front Buffer 와 Back Buffer 가 일시에 교체됨으로써 Back Bufff 에 미리 준비해 놓은 그림이 바로 나타난다. 순간적으로 교체되므로 깜박거림은 전혀 느낄 수 없다. 이 과정을 계속 반복하면 animation 이 되는 것이다. Buffer 를 교체하는 것 자체가 출력이므로 glFlush() 는 호출하지 않아도 상관없다. 위 에서 speed 는 전역변수로 rotation 속도를 조절하기 위한 변수이다. '<' 와 '>' key 로 크기를 조절하게 하였다.
idle() 함수는 단지 idling 시간만을 지정해 주고, glutPostRedisplay() 함수를 불러 display 할 내용을 변화시키도록 한다.
위 두개의 함수의 차이를 보면 Timer() 함수는 함수내에서 다시 재귀 (recursive) 형태로 자신을 다시 호출한다는 것이다. 이유는 glutTimerFunc() 은 지정된 시간후에 지정된 함수를 딱 한번 호출한다. 주기적으로 계속 호출하려면 callback 함수에서 자신을 다시 호출해야 한다. 지속적으로 호출되는 방식에 비해 약간 불편하지만 매 호출시마다 다음 주기를 가변적으로 결정할 수 있다는 면에서 활용성은 오히려 더 높다. 더 이상 Timer() 호출이 필요없으면 callback 을 재등록하지 않으면 된다. 함수의 동작형태는
millisec 후에 Timer() 함수를 호출하며 인수로 value를 전달한다. value는 Timer callback 으로 전달되어 작업 시간의 거리를 지시하는데, Timer 의 용도가 하나뿐이라면 아무 값이나 주어도 상관없다. callback 을 등록해 놓으면 millisec 후에 callback 함수가 호출된다. main() 에서는 다만 시동만 걸어줄 뿐이고 다음 타이머 호출 시점은 callback 함수가 자체적으로 결정할 수 있다.
System 이 초당 60 frame 을 refresh 한다고 가정하면, 가장 빠른 frame 율은 60 fps 이다. 따라서 1/60 초 이내에 frame 이 정리되고 다시 그려져야 부드럽게 움직이는 animation 이 된다. 그림이 복잡하여 한 frame 을 그리는데 1/45 초가 걸린다면, frame 율은 30 fps 가 될 것이다. 이 경우 graphic 은 1/30 - 1/45 = 1/90 초의 frame 당 시간 (sec per frame) 의 idle 이 요구된다. 만일 Back Buffer 에서 각각의 그림들이 그려지는 시간이 일정하지 않다면, 어떤 frame 은 시간을 좀더 많이 쓰고, 어떤 frame 은 시간을 적게 쓰게 되는 현상들이 발생할 것이다. 이러한 현상들에 의해 부드러운 Animation 진행과정이 방해 받게된다.
프로그램을 컴파일한 후 실행하면서, 앞 절, keyboard 프로그램 실행시 Test 해 보았던 것들을 해보면, 어떤 변화가 일어나는지를 볼 수 있을 것이다.
응용 Program:
무한정 움직이는 1개의 당구공을 생각해 보자. 당구공은 당구대의 벽면에 대한 입사각에 대하여 같은 반사각으로 튕겨진다. 이 원리를 적용하여 공의 위치를 속도에 따른 움직이는 거리를 계산하여 glTranslate() 함수를 사용, 공이 Table 내에서 계속 움직이도록 프로그램 한것이다.
우선 몇개의 전역변수를 정의 하였다.
#define angle -30.0 // launching angle
// set window size & image size coordinates & image view mode |
다음 display() 함수를 다음과 같이 수정한다.
. . // clear all color & depth buffers
/* Translate & rotate the image */
/* Draw circular ball */
sprintf( info, "x=%.1f, y=%.1f, launching angle=%.3f", xtr, ytr, angle );
glutSwapBuffers(); |
위에서 drawTable(); 함수의 내용을 지금 설명에는 조금 이른감이 있어 아래 Source Code 에 포함 되어있는것을 사용하기로 한다.
다음 idle() 함수 또는 Timer() 함수를 다음과 같이 작성한다.
void idle( void )
xtr += speed * cos( xdeg * PI/180.0 );
if (ytr >= ymax) ydeg = -ydeg;
glutPostRedisplay(); // tell GLUT that the display has changed |
ball 의 table 을 향한 입사각과 반사각에 대한 계산이므로 조금만 깊이 살펴보면 원리를 이해할 수 있을것이다.
그외 reshape(), keyboard() 및 special() 함수를 약간 수정하여 컴파일 후 실행배보면 재미있는 결과를 볼것이다.
실행할 때 선택사항은 다음과 같다.
'>' 와 '<' key - 공의 속도를 변화.
'arrow' keys - 공의 입사각의 변화
'r', 'g', 'b', 'w' key - 공의 색상 변화
'F11' & 'F11' - Toggle fullsize window
Source Code: 01_4 - animation.zip
01_4 - moving_ball.zip
'OpenGL 활용 > 1장 - Basic' 카테고리의 다른 글
1장 6절 - Mouse Motion Event (0) | 2013.01.22 |
---|---|
1장 5절 - Mouse Event (0) | 2013.01.22 |
1장 3절 - Keyboard Event (0) | 2013.01.20 |
1장 2절 - Resize OpenGL Window (0) | 2013.01.20 |
1장 1절 - Create a Simple OpenGL Window (0) | 2013.01.19 |
Keyboard Event
OpenGL programming 에서의 Keyboard 로 Event 를 처리하기 위한 기능으로 2개의 callback 함수가 있다. 일반 Keyboard 를 처리하는 glKeyboardFunc() 와 특수 Keyboard 를 처리하는 glSpecialFunc() 이다. 함수의 syntax 를 보면...
void glutKeyboardFunc( void (*func)(unsigned char 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 한 다음, 필요한 함수를 작성해 보자.
. .
glutKeyboardFunc( keyboard ); glutSpecialFunc( special );
glMainLoop(); return 0; } |
keyboard() 함수:
void keyboard( unsigned char key, int x, int y )
switch (key) { case 'g': case 'b': case 'y': case 'c': case 'm': case '+': default: glutPostRedisplay(); |
special() 함수:
void special( int key, int x, int y ) case GLUT_KEY_F2: // both object shape & size is chaned case GLUT_KEY_F3: // object shape is not changed but object size is chaned
case '+': case GLUT_KEY_F9: default: glutPostRedisplay(); |
그리고 display() 함수를 다음과 같이 수정하고, 몇개의 전역변수를 더한다.
// global variables GLfloat xrot, yrot, zrot;
void display( void )
// clear all color & depth buffers
/* Translate & rotate the image */
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(); . |
참고 Site: glutGetModifiers() http://www.opengl.org/resources/libraries/glut/spec3/node73.html
Advanced Keyboard 기능
화살표 같은 key 를 계속눌러 자동반복을 실행하면, 약간의 delay 현상이 일어난다. 이러한 자동반복의 문제점을 해결해주는 함수들을 살펴보자.
int glutSetRepeat( int repeatMode );
Parameters:
|
위 함수는 전역기반으로 작용한다. 즉 Application 으로부터 하나가 아닌 모든 Window 의 반복기능에 영향을 준다. 따라서 이 함수를 자동 mode 의 비활성화로 사용할 때는 Application 을 끝내기 전 default 상태로 복원하는 것이 편리하다.
Key 반복이 일어날 때의 callback 받는것을 비활성화 시켜, 다른 Application 에 영향을 주지않고 안전하게 key 누름을 무시해야 할 때가 있다. 이러한 경우의 함수는
int glutIgnoreKeyRepeat( int repeatMode );
Parameters:
|
어느 경우, 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:
|
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 |
Resize OpenGL Window
OpenGL Window 에 그려진 이미지를 확대, 또는 축소를 해서 보기 위해, Mouse 로 Window 의 크기를 조정할 때, 원래의 모형에 따라 보여지는 형태가 어떻게 변하는지를 살펴보기로 하자.
지난 절에서 만든 삼각형이 그려진 Window 의 크기를 Mouse 로 조정해 보면, OpenGL Window 안에 있는 이미지의 형태가 뒤바뀜을 볼 수 있다. 새로운 모양의 삼각형을 좌표를 지난 절에서 그린것과는 다르게 잡아 그려보기로 하자. display() 함수를 다음과 같이 수정하였다.
void display()
glColor4f( 1.0f, 1.0f, 0.0f, 1.0f ); // triangle color as RGBA
glFlush(); |
삼각형의 각 꼭지점의 (x, y) 좌표에 대응하는 위치가 (0, 0), (2, 1), (1, 2) 로 원점에서 옮겨져 x-y 좌표의 제 1 4분면에 위치하였다. 실행결과 이미지가 다음과 같이 나타내진다. OpenGL 은 default 로 이미지를 보는 영역을 이미지 크기의 창에서 원점을 중심으로 보기 때문이다. 즉 삼각형의 이미지 크기 영역은 가로 2, 세로 2의 크기로 꼭지점이 직교좌표계의 (0, 0), (2, 1), (1, 2) 에 위치하여 있지만, 이 이미지를 투시하여 보는 영역이 x 축에서 (-1,1), y축에서 (-1,1) 의 범위이기 때문이다.
이 좌표계를 조금 옮기기 위해 display() 함수를 조금더 수정해 보자.
void display( void )
glPushMatrix();
glColor4f( 1.0f, 1.0f, 0.0f, 1.0f ); // triangle color as RGBA
glFlush(); |
함수 glPushMatrix() 와 glPopMatrix() 사이에 glTranslatef( -1.0, -1.0, 0.0 ) 를 집어 넣어 x-축과 y-축 방향으로 -1.0 만큼의 크기로 좌표를 옮겼다. 결과를 보면 삼각형의 이미지가 Window 중앙으로 옮겨짐을 볼 수 있다. glTranslate*() 함수는 Image 의 좌표를 옮기는데 사용되는 함수이다. * 에 들어가는 문자가 f 이면 함수내의 변수값을 float 로 사용한다는 의미이다 (i 일 경우는 int( 정수형)). glPushMatrix() 와 glPopMatrix() 함수는 좌표계의 위치와 방향 행렬을 저장, 복원하기 위한 함수이다. 앞, 뒤의 두 함수를 지우고 실행을 해보면 어떤 결과가 나오는지 알 수 있을것이다.
그러나 여기에서도 Window 크기를 조절해보면 이미지의 형태가 변형되는 것을 볼 수 있다. 이 것을 해결하기 위해 새로운 glut callback 함수 glReshapeFunc() 가 필요하다. 다음의 program 을 살펴보자.
main() 함수에 다음의 새로운 Line 을 넣는다.
. .
glMainLoop(); return 0; } |
다음의 reshape() 함수를 작성하고 위의 첫번째 display() 함수와 함께 program 을 컴파일한 후 실행한다.
void reshape( int w, int h ) if (h == 0) h = 1;
// Tell OpenGL how to convert from coordinates to pixel values
if (w >= h) {
glMatrixMode( GL_MODELVIEW ); // Select the Modelview Matrix |
Window 크기를 조절해보면 이미지의 형태가 변형되지 않고 크기도 Window 는 크기와 함께 항상 Window 중앙에 위치 하면서 변해 가는 것을 볼수 있다. 또한 위 함수에서 glViewport( 0, 0, w, h ); 부분의 함수 인자를 glViewport( 50, 50, 0.7*w, 0.7*h ); 로 수정하여 실행을 해보았을 때 어떤 결과가 나오는지 살펴보았으면 한다. Window 내의 이미지 크기가 작아짐을 볼 수 있다.
다음은 2차원과 3차원의 이미지를 투시하여 보는 방법과 원근적인 시각으로 보는 방법을 정리한 reshape() 함수이다. 3개의 global variable (전역변수) 를 사용하여 이미지의 크기, Viewing Method 등을 선택하도록 구성되어 있다. viewmode 와 magfac 값을 요구조건에 맞게 바꾸어 필요한 Viewing Mode 와 Window 내에서의 이미지 크기를 결정할 수 있다.
// global variables
void reshape( int w, int h ) // set window size & image size coordinates & image view mode
double x1, x2, y1, y2, z1, z2;
// Calculate coordinates & object size
x1 = (ix1 - (1.0-magfac)*ixc) / magfac;
ww = (GLdouble)w / (GLdouble)wwidth;
// Tell OpenGL how to convert from coordinates to pixel values
glMatrixMode( GL_MODELVIEW ); |
각각의 viewmode 에 대한 함수들의 사용방법은 OpenGL Reference 를 통하여 찾을 수 있다. 다음은 행렬 및 투영 등, Image Object 를 표현하는데 필요한 함수들에 대한 간단한 설명이다.
- 행렬 (Matrix)
- glMatrixMode(); - 현재 행렬을 설정
- glLoadIdentity(); - 현재 행렬을 단위행렬 (Identity Matrix) 로 설정
- glLoadMatrix[f,d](); - 지정된 행렬을 최상위 행렬 Stack 에 Loading
- glMultiMatrix[f,d](); - 현재 행렬과 지정된 행렬을 곱하기
- 투영 (Projection)
- glOrtho(); - 범위가 정해진 직교투영
- gluOrtho2D(); - Z 방향의 범위가 -1.0~1.0 인 직교투영
- glLoadMatrix[f,d](); - 비대칭 절두체 원근투영
- gluPerspective(); - 원근투영
- 조망 (View)
- glViewport(); - Viewport 설정
-
gluLookAt(); - 카메라의 위치와 방향 설정
- 모델링 변환 (Modeling Transform)
- glRotate[f,d](); - Image Object 의 회전 방향 설정
-
glTranslate[f,d](); - Imgae Object 의 좌표 위치 이동
-
glScale[f,d](); - Imgae Object 의 확대 및 축소
참고 Site:
glMatrixMode(); glLoadIdentity(); glTranslate*();
glOrtho(); gluOrtho2D(); glFrustum(); gluPerpective();
gluLookAt(); |
http://www.opengl.org/sdk/docs/man2/xhtml/glMatrixMode.xml http://www.khronos.org/opengles/sdk/1.1/docs/man/glLoadIdentity.xml http://www.talisman.org/opengl-1.1/Reference/glTranslate.html http://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml http://www.opengl.org/sdk/docs/man2/xhtml/gluOrtho2D.xml http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml http://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml |
Viewing Theory:
참고 Site: http://fly.cc.fer.hr/~unreal/theredbook/chapter03.html
Source Code:

'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장 3절 - Keyboard Event (0) | 2013.01.20 |
1장 1절 - Create a Simple OpenGL Window (0) | 2013.01.19 |
Create a Simple OpenGL Window
OpenGL Programming 을 하는 방법의 여러가지 중에서 GLUT (Graphic Library Utility Tools)을 이용하여 하는 기초적인 사항들을 알아보기로 하자. GLUT 은 graphic 처리에 대한 event handling 의 기본적인 callback 함수들을 제공하고 있는데, 대표적인것이
- 도형을 화면에 표현하는 Display Event Handler
- OpenGL 화면의 크기를 조정하는 Reshape Event Handler
- Keyboard 의 일반 key 에 대한 Keyboard Event Handler
- Keyboard 의 특수 key 에 대한 Special Event Handler
- Mouse Button 에 대한 Mouse Event Handler
- Mouse 움직임에 따른 Motion Event Handler
- 화면에서 Object 의 움직임과 동작을 주는 Idle Event Handler
- Menu 에 대한 Menu Event Handler
등이 있다. 이번 장에서는 이러한 사항에 대한 기초적인 부분을 알아보기로 한다.
MS Windows 환경에서 OpenGL Programming 을 하는 방법에는 Console 모드를 사용하는 방법과 Win32 API 를 사용하는 두가지 방식이 있다. 여기에서는 간단히 두가지의 Programming 하는 방법을 비교해 보고 GLUT 의 기본적인 사용법을 알아 보기로 한다.
OpenGL 의 처음 시작으로 간단한 OpenGL 창을 만들어 보기로 하자.
OpenGL Programming 을 위한 Header File 은 다음을 준비해 두는게 일반적이다. 때에 따라 필요하지 않은 Header 도 있지만 컴파일된 파일 Size가 큰 문제가 되지 않는다면, 다음의 Header File 들은 일반적으로 붙여서 사용하는 것이 programming 하는데 편리하다.
#include <stdio.h> #include <gl/glew.h> |
위의 Header File 중 #include <gl/wglew.h> 부분은 생략해도 일반적으로 별 문제가 없다.
다음은 GLUT 를 사용한 main 함수를 살펴보자.
void showOpenGLInfo( void );
int main( int argc, char *argv[] )
// initialize rendering & register callbacks
// enter GLUT event processing cycle
return 0; |
위에서 glutInitDisplayMode() 부분은 매우 중요한 부분으로 몇가지의 옵션이 있는데, 여기에 보여주는것은 Buffer 는 SINGLE Buffer, 색상은 RGB, 그리고 깊이 Buffer 를 사용하겠다는 의미이다. 초기 단순한 Window 를 만드는데는 GLUT_DEPTH 는 필요치 않으나 일반적으로 포함시켰다.
다른 glut*() 함수들은 그 의미를 쉽게 이해할 수 있을것이다. showOpenGL(); 함수는 기본적인 OpenGL 정보를 보여주기 위한것이다. 꼭 필요한 부분이 아니므로 일반적으로 사용하지는 않는다. 이 함수는 아래에 첨부되었다.
여기까지가 GLUT 을 사용하여 OpenGL Programming 을 하기위한 거의 필수 함수들이다.
void showOpenGLInfo( void )
return; |
다음의 initRendering(); 함수는 OpenGL programming 의 초기화에 필요한 부분들에 대한 함수들을 묶어놓은 함수이다.
void initRendering( void ) { glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); // black background color glEnable( GL_DEPTH_TEST ); // Enable hidden--surface--removal } |
위에서 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 는 검은색 배경색을 나타낸다. 함수내의 숫자는 RGBA 의 크기를 나타내는데, 0에서 1 사이의 값을 가진다. 변수형태는 float 로 표현된다. glEnable( GL_DEPTH_TEST ); 는 현재는 별 의미가 없다. 다음에 3차원 도형을 다룰 때 설명이 따르게 될것이다.
glutDisplayFunc( display ); 함수는 display() 함수에서 요구한 사항들을 OpenGL Window 에 나타내는 것이다. 다음의 display() 함수를 살펴보면
void display( void ) glFlush(); |
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 는 색상 Buffer 와 깊이 Buffer 를 비우고, 마지막에 glFlush();
함수를 통해 display() 명령들을 화면으로 내보낸다. 이러한 display() 함수의 모든 명령들을 받아 처리하는 glut callback 함수가 glutDisplayFunc(); 이다. 여기에서는 아무런 그림이나 도형도 그리지 않고 단지 OpenGL Window 만 열게 하였다.
main() 함수의 마지막 glutMainLoop(); 함수는 위 모든 함수들을 최종적으로 정리, Looping 하여 나타낸다. 다음은 위에서 사용된 함수들에 대한 간단한 설명이다.
- glClearColor(); - 화면 배경 색상 설정
- glClear(); - 화면과 Buffer 를 지움
- glFlush(); - Buffer 의 내용을 화면에 뿌려줌
- glGetString(); - OpenGL 의 version, 확장목록등의 정보를 알려줌
위 프로그램을 실행시키면, Command 창과 함께 OpenGL Window 창이 뜨게 된다. Win32API mode 로 프로그래밍을 하게 되면, Command 창은 뜨지 않게 된다. Win32API mode 에 대한 Programming 은 다음의 Site 에가면 매우 잘 설명이 되어있다. 영어해석에 별 무리가 없다면 다양한 좋은 정보들을 얻을 수 있을것이다.
NeHe Production: http://nehe.gamedev.net/
Win32API 로 구현된 Program 들은 매우 복잡하게 보이나, 단지 keyboard, mouse, 등의 Event Handler 에 대한 부분만이 glut 을 사용할 때와 조금 다르고 다른 부분에 별 차이가 없음을 알게 될것이다.
간단히 Win32API Mode 로 위의 program을 변경하면 다음과 같이 몇 부분만 바꾸면 된다. main() 함수의 처음 부분을
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, . . . |
그리고 showOpenGL(); 함수는 다음과 같이 변형시키면 된다. 이 부분에 대하여는 아주 쉽게 처리됨을 알 수 있을것이다.
void showOpenGLInfo( void )
if (glewInit() != GLEW_OK) { "OpenGL Version: %s\n" "GLU Version: %s\n" "GLEW Version: %s\n", glGetString(GL_VENDOR ),glGetString(GL_VERSION), gluGetString(GLU_VERSION), glewGetString(GLEW_VERSION) ); MessageBox( GetFocus(), buffer, "OpenGL Info", MB_OK );
return; |
이상으로 이제 OpenGL 프로그래밍의 기본은 준비되었다. 기본적이 도형을 그리는 부분은 다음에 알아보겠지만 우선 간단한 노란색 2차원 삼각형 그림을 그리기 위해, 위의 display() 함수 내에 다음의 몇 줄을 더해보자.
void display( void )
glColor4f( 1.0, 1.0, 0.0, 1.0 ); // yellow color
glFlush(); |
이 Program 을 컴파일 한 후 실행시키면 다음과 같은 검은 바탕에 노란 삼각형의 그림이 그려지는 것을 볼 수 있을것이다.
GLUT 상태 정보 검색 함수
다음의 함수
int glutGet( GLenum state ) |
는 OpenGL 사용시 필요한 정보를 얻는데 자주 사용된다. state 는 어떤 정보를 검색할 것인지에 대한 symbolic 상수 이다. 다음의 예는;
width = glutGet( GLUT_SCREEN_WIDTH ); now = glutGet( GLUT_ELAPSED_TIME ); |
pixel 크기로 screen 의 가로와 세로에 대한 정보를 알려준다. 마지막의 예는 현재의 시간에 대한 정보를 알려주는 예이다. OpenGL Window를 screen 의 한 가운데에 screen 크기의 절반의 크기로 위치하게 하기위하여는 main() 함수를 다음과 같이 수정하면 된다.
int main( int argc, char *argv[] ) glutInitWindowSize( width, height ); // 초기 Window 크기 glutCreateWindow( "OpenGL: Open a Simple Window" ); // OpenGL Window Title . . return 0; |
Source Code: 01_1 - create_window.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장 3절 - Keyboard Event (0) | 2013.01.20 |
1장 2절 - Resize OpenGL Window (0) | 2013.01.20 |