Input and Interaction
3.1 Interaction
Input 기능의처리 input : 사용자와의대화 O/S 와밀접한관계 문제점 : portability 에심각한장애 MS Windows 용으로작성하면, 거기서만작동 OpenGL approach OpenGL 은 portability 를중시 input 은 OpenGL 기능에서되도록제거 GLUT : 기본적인 input 기능을제공 portability 보장 X window, MS window, Macintosh 에서공통적인기능만제공 2
3.2 Input Devices
Physical device & Logical device input device를보는 2가지관점 physical device : hardware 관점에서 logical device : user / programmer가보는관점 C program 에서의예제 user logical device printf( ) program hardware physical device printer terminal disk file 4
Physical Input Devices primary types of physical devices pointing device : 2D / 3D 좌표를 return relative-positioning : mouse, track ball absolute-positioning : tablet 3D : space ball variable-sensitivity : joystick keyboard device : string 처리 5
Logical Devices 표준분류 :six classes of logical devices string 문자열 (character string) locator 하나의좌표 pick 여러개중에서고르기 choice 선택사항들중에서고르기 (menu) dial 숫자하나 (= valuator) stroke 연속된좌표들 widget : a graphical interactive device window system 에서제공하는 menu, button, logical device 들을 software 로구현한예제들 6
Measure and Trigger input device 의처리단계 measure : program 에 return 할값을측정 trigger : 현재의값을 program 에 return mouse click mouse 좌표 (x, y) input modes : input device 작동방법 measure / trigger 의작동방법에따라 request mode sample mode event mode 7
Input Modes request mode program 에서요청 (request) 하면, measure & trigger mouse click mouse 좌표 (x, y) sample mode program에서직접 measure trigger 는필요없음 mouse 좌표 (x, y) 8
Input Modes event mode 사용자가 program flow 를 control 하는경우에는 request / sample 로는어려움 사용자가 action을할때마다 event queue 에등록 program 은 event queue 에서하나씩처리 새로운 event? mouse click mouse 좌표 (x, y) 첫번째좌표부터처리 callback function : 특정 event 를처리하도록등록 9
3.3 Clients and Servers
Client-Server Model network, multi-user 환경의산물 client : 어떤일을요청하기만한다 server : 실제로그일을수행한다 print server (networked printer) print client (PC, workstation) 11
Client-Server Model in Graphics X window system 에서시초 graphics server : graphics output / input service 제공 raster display + keyboard + mouse graphics client (display 요청 ) graphics server (display 실행 ) 12
Client-Server Model in Graphics 현재의 graphics 환경 (OpenGL 포함 ) application program : client 로작동 OpenGL server : server 역할 1대의 computer 가 server, client 모두수행가능 graphics client (OpenGL application #1) network graphics client (OpenGL application #2) internal communication (IPC) graphics server (OpenGL server) 13
3.4 Display Lists
Display List 의유래 DPU model display processor display list 에저장된내용을반복해서 display host 에서는한번만저장하면된다 한번저장 반복 display 15
Display List 현재의환경 : DPU model 은사라짐 server : frame buffer + GPU model client : application program immediate mode 단순출력만제공 화면을반복해서그려야한다 retained mode object 정의를 display list 에저장 GPU 가반복해서 display display list object 정의를저장하는, GPU 용의 memory video card 내의 RAM 에위치 16
Display List frame buffer + GPU model application program GPU memory 일부에 display list 저장 17
Display List in OpenGL display list 의설정 #define BOX 1 glnewlist(box, GL_COMPLLE); glbegin(gl_polygon); glvertex2f( 1.0, 1.0); glvertex2f( 1.0, 1.0); glvertex2f( 1.0, 1.0); glvertex2f( 1.0, 1.0); glend( ); glendlist( ); 18
Display List in OpenGL display list 의사용 glmatrixmode(gl_projection); for (i = 1; i < 5; i++) { glloadidentity( ); gluortho2d( 2.0 * i, 2.0 * i, 2.0 * i, 2.0 * i); glcolor3f(i / 5.0, i / 5.0, i / 5.0); glcalllist(box); } 19
Attribute 의저장, 복원 display list 내에서 attribute, matrix 가바뀔수있다. glcalllist( ) 전에 save, 나중에 restore 필요 해결책 glpushattribute(gl_all_attrib_bits); glpushmatrix( ); // matrix, attribute 변경가능 glcalllist(box); glpopmatrix( ); glpopattribute( ); 20
Example: Stroke Fonts stoke font 를작성한다. void OurFont(char ch) { switch (ch) { case a : gltranslate(0.5, 0.5, 0.0); // move to center glbegin(gl_quad_strip); break; for (i = 0; i <= 12; i++) { case A : angle = (2 * M_PI / 12) * i; glvertex2f(0.4 * cos(angle), 0.4 * sin(angle)); case O : glvertex2f(0.5 * cos(angle), 0.5 * sin(angle)); } glend( ); } gltranslate(0.5, -0.5, 0.0); // move to next } break; 21
Example: Stroke Fonts display list 256 개를동시에만든다. GLuint base = glgenlists(256); for (int i = 0; i < 256; i++) { glnewlist(base + i, GL_COMPILE); OurFont(i); glendlist( ); } glgenlists(glsizei range) : display list 를 range 개만큼미리확보 [base.. base + range 1] 22
Example: Stroke Fonts display list 를한꺼번에사용한다. char* text_string = Hello, World! ; gllistbase(base); glcalllists(strlen(text_string), GL_BYTE, text_string); text_string 의길이만큼, 반복해서 glcalllist( ) 수행 아래와같은의미 for (int i = 0; i < strlen(text_string); i++) { glcalllist(base + text_string[i]); } 23
Fonts in GLUT void glutstrokecharacter(void* font, int character); 글자하나를출력 int glutstrokewidth(void* font, int character); 해당글자의폭을 return font == GLUT_STROKE_ROMAN proportionally spaced Roman (times-roman) font == GLUT_STROKE_MONO_ROMAN mono-spaced Roman ( 모두같은폭 ) 24
Fonts in GLUT void glutbitmapcharacter(void* font, int character); int glutbitmapwidth(void* font, int character); font : GLUT_BITMAP_8_BY_13, GLUT_BITMAP_9_BY_15, example glrasterpos2i(rx, ry); glutbitmapcharacter(glut_bitmap_8_by_13, k); rx += glutbitmapwidth(glut_bitmap_8_by_13, k); 25
glrasterpos*( ) world coordinate 를주고, 해당되는 raster position 으로이동 glrasterpos3f(x, y, z); (x, y, z) raster position A OpenGL window camera position 26
3.5 Programming Event-Driven Input
Event-driven Program Model event : program 에서발생할수있는모든상황 main loop : 필요한 event 를처리하는무한 loop callback : 해당 event 발생시, 처리할함수 event 발생 callback 함수정의 callback 함수등록 (2) main loop if (event? ) { call CallBack } (3) (5) (1) callback list mycallback (4) callback 함수가처리 28
GLUT event model 기본철학 모든 window system 에서공통인 event 만처리 pointing device events (mouse events) motion event (button downed) passive motion evnet (button released) mouse event (button press / release) passive motion event mouse event (button pressed) motion event mouse event (button released) passive motion event 29
Pointing Device Events callback 형태 void mousecallback(int button, int state, int x, int y) { } if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) exit(0); void motioncallback(int x, int y) { } 등록하기 void glutmousefunc(mousecallback); void glutmotionfunc(motioncallback); void glutpassivemotionfunc(motioncallback); 30
Keyboard Event keyboard 의키를누르는순간 event 발생 callback 형태 void keyboardcallback(unsigned char key, int x, int y) { // mouse 가 (x, y) 에있는상황에서 key 누름 } int glutgetmodifiers(void); keyboard event 시의 modifier 상황 Shift, Ctrl, Alt 키가눌려졌나? 등록하기 void glutkeyboardfunc(keyboardcallback); 31
Reshape Event window 의크기가변했을때 callback 형태 보통, 화면을새로그려야함 void reshapecallback(int width, int height) { // window size is changed to width height } 등록하기 void glutreshapefunc(reshapecallback); 32
Display Event window 를새로그려야할필요가있을때 event 발생 예 : window 가처음화면에뜨는순간, 가려졌던 window 가위로올라오는순간, void glutpostredisplay(void); 강제로 display event 발생 callback 형태 void displaycallback(void) { } 등록하기 void glutdisplayfunc(displaycallback); 33
Main Loop, Idle Callback void glutmainloop(void); 무한 loop 상황에서 event 처리 callback 중의하나가 exit( ) 를해야함! idle callback : 처리할 event 가없는경우에 call void idlecallback(void); 등록하기 void glutidlefunc(idlecallback); 주의 : 빠른시간내로처리가끝나야한다. 34
Main 함수의예 int main(int argc, char* argv) { glutinit(&argc, argv); glutinitdisplaymode(glut_single GLUT_RGB); glutcreatewindow( Sqaure ); myinit( ); glutreshapefunc(myreshape); glutmousefunc(mouse); glutdisplayfunc(display); glutmainloop( ); } 35
Multi-window 환경 int glutcreatewindow(char* name); 새로운 window 1 개를생성 void glutsetwindow(int id); 지금부터출력에사용될 window 를지정 int glutgetwindow(void); 지금출력중인 window 를 return callback 에서는? glutgetwindow( ) 로각 window 마다다른일가능! 36
3.6 Menus
GUI 개발 GUI : graphical user interface toolkit : UI 용도구모음 widget : visually appealing and effective graphical devices 실제로는 GUI 용의조그만 unit GLUT : GUI 에취약함 : slide why? window system 과분리 해결책 : 1. mouse event 로직접구현 2. pop-up menus 38
GLUT Pop-up Menus void menucallback(int id) { if (id == 1) exit(0); else if (id == 2) size *= 2; else if (id == 3) size /= 2; glutpostredisplay( ); } int glutcreatemenu(menucallback); pop-up menu 를생성 39
GLUT Pop-up Menus void glutaddmenuentry(char* label, int value); 현재 pop-up menu에 entry 첨가 화면표시는 label callback 에들어가는값은 value void glutaddsubmenu(char* label, int submenu); menu 에 submenu 첨가 void glutattachmenu(int button); button = GLUT_{LEFT,MIDDLE,RIGHT}_BUTTON 현재 pop-up menu를마우스버튼에연결 40
Example Menu sub_menu = glutcreatemenu(menucallback); glutaddmenuentry( increase, 2); glutaddmenuentry( decrease, 3); glutcreatemenu(menucallback); glutaddmenuentry( quit, 1); glutaddsubmenu( resize, sub_menu); glutattachmenu(glut_right_button); quit resize sub_menu increase decrease 41
3.7 Picking
Picking an input operation that allows the user to identify an object on the display mouse click 시에, 어느 object 인지찾는방법 상당히까다롭다 3D world coordinates (x, y, z) 3D world coordinates (x, y, z) 1. 2D 3D mapping 방법? 2. 여러개중의어느 object? mouse click : 2D device coordinate (x, y) 43
Picking 해결책 2D 3D mapping 방법 camera setting 에서계산한다! chap 4 에서 mapping 계산식이나온다 여러개중의어느 object bounding rectangle 사용 제일앞에오는것을고른다 bounding rectangle 이안에들어와야 click 될가능성이있다. 44
3.8 A Simple Paint Program
A Simple Paint Program 간단한 CAD 프로그램 2D-based : picking 문제를피한다 위쪽 : 그림그리기위한 icon 들 46
A Simple Paint Program menu 구조 왼쪽 button : 그림을그린다 가운데, 오른쪽 button : menu 할당 47
A Simple Paint Program 자세한프로그램은교재참고 OpenGL function, GLUT function 은 manual 참고 RTFM : Read The Fine Manual 48
3.9 Animating Interactive Programs
Rotating Square 2차원평면상에서, 각도θ 에따라, 정사각형돌리기 정해진θ 에대응되는정사각형그리기? display callback θ를어떻게증가시킬것인가? idle callback (ww, wh) ( sin θ, cos θ) (cos θ, sin θ) center point : (ww/2, wh/2) ( cos θ, sin θ) (sin θ, cos θ) (0,0) 50
Rotating Square init function int ww = 400; /* window width */ int wh = 400; /* window height */ void myinit(void) { glviewport(0, 0, ww, wh); glmatrixmode(gl_projection); glloadidentity(); glortho(0.0, (GLdouble)ww, 0.0, (GLdouble)wh, -1.0, 1.0); glclearcolor(0.0, 0.0, 0.0, 1.0); glclear(gl_color_buffer_bit); glflush(); } 51
Rotating Square display function : 교재의수식은일부틀렸음! int radius = 150; double theta = 0.0; /* in degree */ void display(void) { double radian = theta * 2 * 3.141592 / 360.0; /* in radian */ glclear(gl_color_buffer_bit); glbegin(gl_polygon); glvertex2f(ww / 2 + radius * cos(radian), wh / 2 + radius * sin(radian)); glvertex2f(ww / 2 + radius * -sin(radian), wh / 2 + radius * cos(radian)); glvertex2f(ww / 2 + radius * -cos(radian), wh / 2 + radius * -sin(radian)); glvertex2f(ww / 2 + radius * sin(radian), wh / 2 + radius * -cos(radian)); glend(); glflush(); } 52
Rotating Square idle function #include <time.h> void usleep(clock_t wait) { /* UNIX system 에서는불필요 */ clock_t goal; goal = wait + clock(); while (goal > clock()) ; } void idle(void) { usleep(10); theta += 2.0; if (theta >= 360.0) theta = 360.0; glutpostredisplay(); } 53
Rotating Square mouse callback left button : animation 작동 right button : animation 중지 void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) glutidlefunc(idle); if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) glutidlefunc(null); } 54
Rotating Square main function #include <stdlib.h> #include <GL/glut.h> int main(int argc, char** argv) { glutinit(&argc,argv); glutinitdisplaymode (GLUT_SINGLE GLUT_RGB); glutinitwindowsize(ww, wh); glutcreatewindow("rotate"); myinit( ); glutdisplayfunc(display); glutmousefunc (mouse); glutmainloop( ); } 55
Double Buffering animation program 의문제점 화면이깜빡일수있다. 왜? 각 frame 을완전히그리기전에화면에그려야되는상황이생겼다. 해결책 : double buffering 2 개의 buffer 에서교대로그림 front buffer : 화면에현재나오는그림 back buffer : 화면에나오지않는버퍼새로운그림은여기에그린다. 56
Double Buffering 설정하기 glutinitdisplaymode(glut_rgb GLUT_DOUBLE); 실제사용 front buffer front buffer glutswapbuffers( ); back buffer back buffer 그리기 그리기 57
3.10 Design of Interactive Programs
HCI good interactive programs smooth display : no flicker variety of interactive devices variety of methods for entering/displaying information easy-to-use interface feedback to the user tolerance for user errors consideration of the human factor 해결책 : HCI (human-computer interaction) 새로운학문분야 59
GUI 를위한지원책 현재는 H/W 로주로해결 overlay 기능 : pop-up menu 가지우는부분을자동복구 rubber-banding : 마우스이동에따라자동추적 60
Assignment #1 오목을둘수있는 graphics 환경을 implement 하라. 9 9 크기의바둑판이화면에떠야한다. 왼쪽마우스버튼을누를때마다바둑돌이검정 / 흰색으로교대로놓인다. 바둑돌은바둑판의정확한위치에놓여야한다. 이미바둑돌이놓인곳에놓으려고하면, 무시하고다른위치에놓을때까지기다린다. 누가이겼는지 check 할필요는없다. 오른쪽마우스버튼을누르면, quit ( 종료 ), reset ( 처음부터다시시작 ) 기능을위한 pop-up menu 가떠야한다. 61