Presentation is loading. Please wait.

Presentation is loading. Please wait.

3장 입력과 상호작용 1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍

Similar presentations


Presentation on theme: "3장 입력과 상호작용 1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍"— Presentation transcript:

1 3장 입력과 상호작용 1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍
단순한 예제(Sierpinski Gasket)를 통해서 OpenGL프로그램을 시작 OpenGL 정점(Vertex)을 이해 장치독립 그래픽스를 이해 세계좌표와 윈도우좌표의 차이를 이해 OpenGL을 이루는 함수들의 종류들을 이해 예제를 통해 관측이 무엇인지를 이해 예제를 통해 2차원 프로그램이 3차원으로 간단히 확장됨을 알게됨.

2 3장 입력과 상호작용 학습목표 입력 장치를 이해한다 GLUT를 이용한 이벤트–구동(Event-driven)입력의 프로그래밍
물리적 장치 논리적 장치 입력 모드 GLUT를 이용한 이벤트–구동(Event-driven)입력의 프로그래밍 mouse keyboard 재구성(reshape) menu 기타 이중 버퍼링, 논리연산 등

3 물리적 입력장치 트랙볼 마우스 라이트펜 데이터 태블릿 조이스틱 스페이스 볼

4 절대위치와 상대위치 지정장치 데이터 태블릿같은 장치는 절대적 위치를 반환한다 마우스, 트랙볼, 조이스틱 같은 장치는 상대적인 값(속도)을 반환한다. 속도로부터 위치를 얻기 위해서는 적분이 필요하다

5 프로그래머 관점에서 보는 입력장치의 논리적 속성 예
논리적 장치들 프로그래머 관점에서 보는 입력장치의 논리적 속성 C++: cin >> x; C: scanf(“%d”, &x); 물리적 입력 장치가 무엇인지 알 수 있는가? 코드만 보아서는 말할 수 없다. 키보드, 파일 또는 다른 프로그램의 출력일 수도 있다. 물리적 장치가 무엇이든 숫자(int)가 프로그램에 반환된다.

6 그래픽 입력은 표준 프로그램에서의 입력(보통 숫자, 문자, 또는 비트)보더 더 다양하다
논리적 그래픽 장치들 그래픽 입력은 표준 프로그램에서의 입력(보통 숫자, 문자, 또는 비트)보더 더 다양하다 초기의 API에서 6 종류의 논리적 입력이 정의되었다(OpenGL은 이러한 접근방식을 택하지 않는다) 문자열 장치(String): 문자열을 반환 키보드 위치 장치(Locator): 위치(position)를 반환 마우스 지적 장치(Pick): 객체 ID를 반환 마우스 선택 장치(Choice): 선택사항들 중 하나를 반환 메뉴 밸류에이터(Valuator): 실수를 반환 슬라이드바 획 장치(Stroke): 위치의 배열을 반환 마우스

7 입력 모드 측정치와 트리거 Ex. 입력모드의 종류 측정치(Measure): 응용프로그램에게 전달되는 입력값
트리거(Trigger): 전달하라는 신호 Ex. dir <ENTER> 마우스 좌표와 클릭 선택된 메뉴 아이디와 클릭 입력모드의 종류 요구모드(Request mode) 샘플모드(Sample mode) 이벤트모드(Event mode)

8 사용자가 장치를 트리거할 때만 입력이 프로그램에 제공된다. 전형적인 키보드 입력
요구모드 사용자가 장치를 트리거할 때만 입력이 프로그램에 제공된다. 전형적인 키보드 입력 enter 키를 누를 때까지 삭제(backspace), 편집, 수정한다.

9 샘플모드 트리거 없이 즉각적인 입력을 제공

10 이벤트 레코드: 이벤트 타입, 장치 아이디, 측정치 응용 프로그램은 주기적으로 이벤트 큐를 검사
이벤트 모드 이벤트 모드 사용자가 입력 선택. cf. 요구/샘플 모드: 프로그램이 주도권 이벤트 레코드: 이벤트 타입, 장치 아이디, 측정치 응용 프로그램은 주기적으로 이벤트 큐를 검사 드라이버에게 이벤트 리퀘스트. 드라이버가 큐 프런트 레코드를 전달 큐가 비어있으면 응용 프로그램은 다른 일을 수행

11 답신(Callback, 콜백)함수 이벤트모드 프로세싱 답신함수 – 이벤트 종류별로 프로그램이 처리해야 할 내용을 함수로 구현
Initialize Input Devices; do {    if (There Is an Event on the Event Queue)          switch (Event Type)          {    case Keyboard Event: Get  Event Record, Run Keyboard Callback               case Mouse Event: Get  Event Record, Run Mouse Callback           ...          }         else Do Background Process } while (User Does Not Request Escape); 답신함수 – 이벤트 종류별로 프로그램이 처리해야 할 내용을 함수로 구현 MS 윈도우 운영체제 자체도 일종의 이벤트 구동 시스템이다

12 주컴퓨터가 모든 처리를 담당--화소를 프레임버퍼로
디스플레이 리스트 주컴퓨터가 모든 처리를 담당--화소를 프레임버퍼로 디스플레이 프로세서 프레임 버퍼 주컴퓨터 화소 디스플레이 처리기 프레임 버퍼 주컴퓨터 화소 기본요소 디스플레이 리스트 클라이언트 서버

13 클라이언트와 서버 클라이언트: OpenGL 프로그램 그래픽스 서버: 지시장치 와 키보드를 갖춘 비트맵 디스플레이

14 즉시모드와 유지모드 – 디스플레이 리스트 즉시 모드 (Immediate mode) 유지 모드(Retained mode)
프로그램이 기본요소를 정의하는 문장을 실행하는 즉시 그 기본요소가 서버에 보내지고 시스템에는 메모리가 남지 않음 고도로 대화식인 프로그램에서 복잡한 객체의 경우, 클라이언트에서 서버로의 많은 데이터 량이 발생한다. 유지 모드(Retained mode) 객체를 한번 정의하고 그것을 디스플레이 리스트에 넣는다. 디스플레이 리스트는 서버에 저장되고 클라이언트로부터 서버에게 보내지는 간단한 함수호출로 다시 디스플레이 될 수 있다. 디스플레이 리스트 기본요소(Primitives), 상태변수(State Variable), 영상(Image) 이동, 회전, 조명 작업과 관련된 모든 명령 반복적으로 실행되어야 할 요소를 디스플레이 리스트 내부에 포함

15 즉시모드와 유지모드 – 디스플레이 리스트 유지모드의 장단점 장점 단점 클라이언트와 서버간의 통신량 절감
서버의 특수 하드웨어의 활용 단점 서버에 메모리 필요 디스플레이 리스트를 생성하는 부담

16 디스플레이 리스트의 실행을 요청 디스플레이리스트 - 예제 디스플레이 리스트의 정의 glCallList(BOX);
#define BOX 1 // 또는 다른 사용되지 않는 정수 glNewList(BOX, GL_COMPILE);// cf. GL_COMPILE_AND_EXECUTE glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex2f(-1.0, -1.0); glVertex2f( 1.0, -1.0); glVertex2f( 1.0, 1.0); glVertex2f(-1.0, 1.0); glEnd(); glEndList(); 디스플레이 리스트의 실행을 요청 glCallList(BOX);

17 이벤트와 답신함수(callback function)을 연결(attach)
이벤트-구동 입력의 프로그래밍 이벤트의 종류들 지시장치의 이벤트 이동 이벤트(move event) - 버튼이 눌린 상태에서 마우스 이동 비활성 이동 이벤트(passive move event) - 버튼이 눌리지 않은 상태에서 마우스 이동 마우스 이벤트 - 버튼이 눌리거나 떼임 윈도우 이벤트 resize, expose, iconify 키보드 이벤트 키를 누르거나 뗄 때 idle 이벤트 이벤트 큐가 비어있을 때 발생 이벤트와 답신함수(callback function)을 연결(attach)

18 이벤트-구동 입력의 프로그래밍 답신 연결 함수들 예 : 마우스 답신함수의 연결
glutDisplayFunc glutMouseFunc glutReshapeFunc glutKeyboardFunc glutIdleFunc glutMotionFunc glutPassiveMotionFunc 예 : 마우스 답신함수의 연결 glutMouseFunc(mouse) 예 : 마우스 답신함수의 정의 void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) exit(); }

19 이벤트-구동 입력의 프로그래밍 int main(int argc, char **argv) {
glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowSize(ww,wh); //전역 정의된 초기 윈도우 크기 glutCreateWindow("square"); myinit(); glutReshapeFunc(myReshape); glutMouseFunc(mouse); glutDisplayFunc(display); glutMainLoop(); }

20 이벤트-구동 입력의 프로그래밍 이벤트 루프 매 이벤트 루프를 돌며 GLUT는
main.c 의 마지막 라인에서 glutMainLoop();호출을 통해 무한루프로 들어간다. 매 이벤트 루프를 돌며 GLUT는 큐에서 이벤트들을 살펴본다 큐에 있는 이벤트에 대해, 답신함수가 정의되어 있으면 실행한다. 답신함수가 정의되지 않았으면 이벤트는 무시된다 .

21 이벤트-구동 입력의 프로그래밍 void mouse(int btn, int state, int x, int y) {
if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN) drawSquare(x,y); if(btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN) exit(0); } /* 전역 변수 */ GLsizei wh = 500, ww = 500; /* 초기 윈도우 크기 */ GLfloat size = 3.0; /* 사각형 변 길이의 절반 */ void myinit(void) glViewport(0, 0, ww, wh); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLdouble)ww, 0.0, (GLdouble)wh); glMatrixMode(GL_MODELVIEW); glClearColor(0.0, 0.0, 0.0, 1.0);

22 이벤트-구동 입력의 프로그래밍 void drawSquare(int x, int y) { y=wh-y;
glColor3ub( (char)rand()%256, (char)rand()%256,(char)rand()%256); glBegin(GL_POLYGON); glVertex2f(x+size, y+size); glVertex2f(x-size, y+size); glVertex2f(x-size, y-size); glVertex2f(x+size, y-size); glEnd(); glFlush(); }

23 GLUT 윈도우 제어 GLUT 윈도우 제어명령

24 GL의 뷰포트 설정 지엘의 뷰포트 설정

25 GL의 화면좌표, GLUT 화면좌표 GLUT, GL의 화면좌표

26 윈도우의 코너를 잡아 끌어서 OpenGL 윈도우의 모양과 크기를 바꿀 수 있다. 디스플레이에 일어나야 하는 것은?
윈도우 재구성(reshape) 윈도우의 코너를 잡아 끌어서 OpenGL 윈도우의 모양과 크기를 바꿀 수 있다. 디스플레이에 일어나야 하는 것은? 다시 그려줘야 한다. 두 가지 방법 세계의 일부분을 디스플레이한다. 전체 세계를 디스플레이 하지만 새로운 윈도우에 적합하게 한다. 종횡비(aspect ratio)가 바뀔 수 있다.

27 Reshape 방법 original reshaped

28 재구성 답신(Reshape callback)
glutReshapeFunc(myreshape) void myReshape(int w, int h) 새로운 윈도우의 너비와 높이를 픽셀단위로 전달 callback 실행의 끝에서 다시 그리기가 자동적으로 요청됨 GLUT는 디폴트 reshape callback을 가지며, 각자가 원하는 대로 정의할 수도 있다.

29 재구성 답신(Reshape callback)
void myReshape(GLsizei w, GLsizei h) { /* 클리핑 상자 조절 */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h); glMatrixMode(GL_MODELVIEW); /* 뷰포트의 조절과 지우기 */ glViewport(0,0,w,h); glClear(GL_COLOR_BUFFER_BIT); glFlush(); /* 전역변수로 저장된 새 윈도우 크기 */ ww=w; wh=h; }

30 motion callback을 사용하여 마우스 버튼이 눌려진 동안에 연속적으로 정사각형을 그릴 수 있다.
glutMotionFunc(drawSquare) 비활성(passive) motion callback을 사용하여 버튼을 누르지 않고 정사각형을 그릴 수 있다. glutPassiveMotionFunc(drawSquare)

31 키보드 사용하기 glutKeyboardFunc(mykey) void mykey(unsigned char key,
int x, int y) 눌려진 키의 ASCII코드와 마우스 위치를 반환 glutKeyboardUpFunc(mykey) void mykey(unsigned char key, int x, int y) { if(key == ‘Q’ || key == ‘q’) exit(0); }

32 GLUT는 특수키를 glut.h에 정의해 놓음
특수키와 수정키 GLUT는 특수키를 glut.h에 정의해 놓음 function key 1: GLUT_KEY_F1 위 화살표 키: GLUT_KEY_UP if(key == ‘GLUT_KEY_F1’ …… glutGetModifiers()을 이용하여 눌려진 수정키를 체크 GLUT_ACTIVE_SHIFT GLUT_ACTIVE_CTRL GLUT_ACTIVE_ALT

33 display callback은 윈도우가 갱신되어야 한다고 결정될 마다 실행된다. 예를 들면,
디스플레이 답신과 아이들 답신 display callback은 윈도우가 갱신되어야 한다고 결정될 마다 실행된다. 예를 들면, 윈도우가 처음 열릴 때 윈도우가 변경될 때 윈도우가 보여질 때 프로그램이 디스플레이에 변화를 줄 때 main.c에서 glutDisplayFunc(display): 실행될 함수를 지정 모든 GLUT 프로그램은 display callback을 가져야 한다. 예: void display() { glClear(GL_COLOR_BUFFER_BIT); }

34 많은 이벤트들은 display callback함수를 호출한다.
디스플레이 답신과 아이들 답신 많은 이벤트들은 display callback함수를 호출한다. 한 번의 이벤트 루프 검사에서 여러 번의 display callback이 실행될 수 있다. 이 문제를 glutPostRedisplay()를 사용하여 해결한다. 이것은 플래그를 설정한다. GLUT는 이벤트 루프의 마지막에서 이 플래그가 설정되어 있는지를 검사한다. 설정되어 있으면 display callback함수를 실행한다. 아이들 답신(Idle callback)은 큐에 이벤트가 없을 때 호출됨 - GLUT checks to see if the flag is set at the end of the event loop - If set then the display callback function is executed

35 대부분의 윈도우 시스템들은 위제트라고 하는 사용자 인터페이스를 만들기 위한 툴킷 또는 라이브러리 함수를 제공한다
툴킷과 위제트 대부분의 윈도우 시스템들은 위제트라고 하는 사용자 인터페이스를 만들기 위한 툴킷 또는 라이브러리 함수를 제공한다 위제트 메뉴 (Menus) 슬라이드바(Slidebars) 다이얼(Dials) 입력 상자(Input boxes) 그러나 툴킷은 플랫폼에 의존적인 경향이 있다. GLUT는 메뉴를 포함하는 약간의 위제트를 제공함

36 메뉴 GLUT는 팝업메뉴를 제공 3단계 메뉴는 서브메뉴를 가진다. 메뉴의 항목들을 정의 각 메뉴 항목을 위한 동작을 정의
항목이 선택될 때 동작이 실행됨 메뉴를 마우스 버튼에 연결

37 간단한 메뉴의 정의 main.c에서 glutCreateMenu(demo_menu);
glutAddMenuEntry(“quit”, 1); gluAddMenuEntry(“increase squre size”, 2); gluAddMenuEntry(“decrease squre size”, 3); glutAttachMenu(GLUT_RIGHT_BUTTON); void demo_menu(int id) { switch(id) case 1 : exit(0); break; case 2 : size = 2*size; case 3 : if (size>1) size = size/2; } glutPostRedisplay();

38 간단한 메뉴의 정의 sub_menu = glutCreateMenu(size_menu);
glutAddMenuEntry("increase square size", 2); glutAddMenuEntry("decrease square size", 3); glutCreateMenu(top_menu); glutAddMenuEntry("quit", 1); glutAddSubMenu("Resize", sub_menu); glutAttachMenu(GLUT_RIGHT_BUTTON);

39 대화식 프로그램의 애니메이션 회전 정방형 void display() { glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON) thetar = theta/(180.0/ ); glVertex2f(cos(thetar), sin(thetar)); glVertex2f(-sin(thetar), cos(thetar)); glVertex2f(-cos(thetar), -sin(thetar)); glVertex2f(sin(thetar), -cos(thetar)); glEnd(); }

40 대화식 프로그램의 애니메이션 glutIdlefunc(idle); ====================== void idle()
{ theta +=2; if(theta >= 360.0) theta -=360.0; glutPostRedisplay(); } glutMousefunc(mouse); void mouse(int button, int state, int x, int y) if(button ==GLUT_LEFT_BUTTON && state==GLUT_DOWN) glutIdleFunc(idle); if(button ==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN) glutIdleFunc(NULL);

41 이중 버퍼링 display callback을 통해 다시 그릴때, 보통 윈도우를 클리어하고 변경된 디스플레이를 그린다.
glClear() 문제 : 프레임 버퍼에서 정보를 그리는 것이 디스플레이로부터 분리된다 그래픽스 시스템은 듀얼 포트 메모리를 사용한다. 그러므로 부분적으로 그려진 화면을 볼 수 있다. 예제 : 회전 정방형 single_double.c

42 이중 버퍼링 하나의 컬러 버퍼를 사용하는 대신 다음과 같은 두 개의 버퍼를 사용한다.
전면 버퍼(Front Buffer) : 디스플레이되는 곳 후면 버퍼(Back Buffer) : 그리는 곳 main.c에서 이중 버퍼링을 사용하기 위한 변경 glutInitDisplayMode(GL_RGB | GL_DOUBLE) display callback 의 끝에서 교체함수사용. void mydisplay() { glClear() . /* draw graphics here */ glutSwapBuffers() } cf. glDrawBuffer(GL_BACK); //디폴트 glDrawBuffer(GL_FRONT_AND_BACK);

43 이중 버퍼링

44 타이머의 사용 idle 콜백합수의 문제점은? int n = 60; // 설정하려는 프레임률
glutTimerFunc(100, myTimer, n); void myTimer(int v) { glutPostRedisplay; glutTimerFunc(1000/n, myTimer, v); }

45 대화식 프로그램의 설계 인터페이스의 설계 1) 깜박임이나 재생 과정의 부자연함이 없는 부드러운 표시
2) 화면상의 다양한 대화식 장치 3) 정보의 입력과 표시의 다양한 방법 4) 배우는데 많은 노력이 필요 없는 쉬운 인터페이스 5) 사용자로의 피드백 6) 사용자 오류에 대한 허용성 7) 인간의 시각과 운동 근육 특성이 고려된 설계

46 기하학적 렌더링 모형이 아닌 프레임버퍼상의 직접적인 작업이 필요한 사례
툴킷, 위제트, 프레임버퍼 메뉴, 슬라이드, 다이얼 등의 위제트(그래픽 심볼과 그에 연결된 프로그램)는 사용자가 직접 만들 수도 있지만 여러가지 툴킷을 통해 제공된다. 기하학적 렌더링 모형이 아닌 프레임버퍼상의 직접적인 작업이 필요한 사례 메뉴 고무줄 기법(Rubber-banding)

47 논리연산

48 XOR 쓰기 통상적인(디폴트)모드: source가 destination을 치환 (d’ = s) 임시로 선분을 그릴 때 선분 아래 있었던 내용을 복구할 빠르고 간편한 방법이 없으므로 임시 선분을 그릴 수 없다. Exclusive OR 모드 (XOR) (d’ = d  s) (x  y)  y =x

49 고무줄 기법(Rubber-banding)
XOR write mode로 전환 객체 그리기 첫 번째 마우스로 클릭한 위치에 선분의 한 끝이 고정되고 두 번째 끝은 motion callback을 이용해서 연속적으로 갱신된다. 마우스가 움직일 때마다, 선분을 다시 그리면 그것이 지워지고 고정된 첫 번째 점과 새로운 두 번째 위치까지 선을 그린다. 끝에서, 표준 그리기 모드로 전환하고 선분을 그린다. 다른 객체에도 적용됨 : 사각형, 원

50 고무줄 기법(Rubber-banding)
두번째 점 첫번째 점 XOR 모드로 마우스를 이용해 선분을 그린다. 초기화면 원래 선분을 XOR로 다시 그린다. XOR로 새로운 선분을 그린다. 마우스를 새로운 위치로 이동

51 OpenGL에서의 XOR 2bit사이에 16개의 가능한 논리연산이 있다. 모두 OpenGL에서 제공
우선 논리연산을 enable한다. glEnable(GL_COLOR_LOGIC_OP) 논리연산을 선택 glLogicOp(GL_XOR) glLogicOp(GL_COPY) (default)


Download ppt "3장 입력과 상호작용 1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍"

Similar presentations


Ads by Google