4장 기하학적 객체와 변환 – OpenGL 변환 학습목표 OpenGL 에서 어떻게 변환을 수행하는지 OpenGL 행렬모드 회전

Slides:



Advertisements
Similar presentations
LOGO OpenGL Project ( 해 결 사 ) 여태기 이수원 정화영 정유나 여태기 이수원 정화영 정유나.
Advertisements

School of Computer, Information and Communication Engineering
Chapter 3. 뷰잉(Viewing).
제 3 호 농촌 어메니티 관광개발 정보 -농어촌체험 ∙ 휴양마을 지정제도- 농 촌 진 흥 청 농촌자원과.
프로그래밍1 및 실습 (C언어) - 3장 기본자료형 (3.6부터 끝까지) -
Efl을 이용한 타이젠 네이티브 웨어러블 앱 만들기
Vision System Lab, Sang-Hun Han
제 11 장 구조체.
CG Programming (Modeling)
CG Programming (Modeling)
Implement of Input and Interaction
OpenGL 실습 12 로봇.
Mathematics for Computer Graphics
OpenGL Programming (III) 1. Drawing in 3D 2. Manipulating 3D Space
2016 ITA 1월 강의 C Programming -4일차- 포인터배열 및 이중포인터 정대진 ( )
C++ Espresso 제1장 기초 사항.
OpenGL 실습 1주차.
OpenGL 시작하기.
DirectX9를 이용한 3D GAME 프로그래밍 입문
블렌딩 안티앨리어싱, 안개효과 그리고 폴리곤 오프셋
Lecture #7 제 4 장. 기하학적 객체와 변환 (2).
기하학적 객체와 변환.
Chapter 5. 라이팅(Lighting)
7장 디스플레이 리스트.
쉽게 풀어쓴 C언어 Express 제13장 구조체 C Express Slide 1 (of 25)
Practice - texture mapping
제12장 유연한 카메라 클래스 만들기 학기 컴퓨터게임(DirectX).
제13장 기본적인 지형 렌더링 학기 컴퓨터게임(DirectX).
C로 쉽게 풀어쓴 자료구조 © Copyright 생능출판사 2011
시스템 생명 주기(System Life Cycle)(1/2)
구조체 활용 구조체 활용.
쉽게 풀어쓴 C언어 Express 제13장 구조체 C Express.
선 택 과 피 드 백.
1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍 3장 – 입력과 상호작용 4장 – 기하학적 객체와 변환 5장 관측
시스템 생명 주기(System Life Cycle)(1/2)
구조체 struct 구조체와 함수 구조체의 배열, sizeof 연산자 열거형 enum 형 정의 typedef
기초 이론.
모바일 햅틱 디스플레이를 위한 렌더링 시스템 Rendering System for Mobile Haptic Display
제  3 장  Lex 사용하기.
Sang Il Park Sejong University
자료구조 김현성.
12장 유연한 카메라 클래스 만들기 한성대학교 멀티미디어공학과 게임 프로그래밍-I 강의노트
계층적, 객체지향적 그래픽스 최 수 미
학습목표 5장. 오픈지엘 기본틀 논리적 입력장치를 설정하는 이유와 종류를 이해한다. 세 가지 입력모드의 차이점을 이해한다.
프로그래밍2 및 실습 C언어 기반의 C++ 2.
Geometric Transformations
1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍 3장 – 입력과 상호작용 4장 – 기하학적 객체와 변환
Hanyang University Jungsik Park
OpenGL PROJECT 우광식 성기영 서창수 이인주.
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
5장. 오픈지엘 기본틀 학습목표 논리적 입력장치를 설정하는 이유와 종류를 이해한다. 세 가지 입력모드의 차이점을 이해한다.
버퍼 (Buffer).
Computer Graphics OpenGL 설치 및 설정
광원 제어 하기.
C언어 프로그래밍의 이해 Ch13. 선행처리기와 주석문.
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
Draw the basic Geometry Objects
Web & Internet [06] CSS3 응용과 레이아웃
컴퓨터 프로그래밍 기초 - 4th : 수식과 연산자 -
Chapter 4 컬러( COLOR ).
4장 - PHP의 표현식과 흐름 제어-.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
OpenGL 프로젝트 김병욱 김상진 김성환.
3장. 제어 메시지 처리하기 1/211 1.
OpenGL project – Easy Flight Simulator
자바 5.0 프로그래밍.
컴퓨터 프로그래밍 기초 - 11th : 파일 입출력 및 구조체 -
argc, argv 의 사용방법 #include <stdio.h>
C.
PHP 기초문법 PHP를 공부하는데 있어 가장 기초가 되는 PHP기초문법에 대해서 배워 봅니다.
Presentation transcript:

4장 기하학적 객체와 변환 – OpenGL 변환 학습목표 OpenGL 에서 어떻게 변환을 수행하는지 OpenGL 행렬모드 회전 이동 크기변환 OpenGL 행렬모드 모델-관측 행렬 투영행렬

OpenGL 행렬 OpenGL에서 행렬은 상태의 한 부분이다 세 가지 타입 조작을 위한 한 벌의 함수들 모델-관측 (GL_MODEL_VIEW) 투영 (GL_PROJECTION) 텍스처 (GL_TEXTURE) (지금은 다루지 않음) 조작을 위한 한 벌의 함수들 다음의 함수로 조작될 행렬을 선택 glMatrixMode(GL_MODEL_VIEW); glMatrixMode(GL_PROJECTION);

현재 변환행렬-Current Transformation Matrix (CTM) 정점들 p p’=Cp C

CTM 연산들 CTM은 새로운 CTM을 적재하든지, 뒤에 곱하기를 통해서 바뀐다 단위행렬을 적재: C  I 임의의 행렬을 적재: C  M 이동행렬을 적재: C  T 회전행렬을 적재: C  R 크기변환행렬을 적재: C  S 임의의 행렬을 뒤에 곱하기: C  CM 이동행렬을 뒤에 곱하기: C  CT 회전행렬을 뒤에 곱하기: C  C R 크기변환행렬을 뒤에 곱하기: C  C S

고정점을 중심으로한 회전 단위행렬로 시작: C  I 고정점을 원래대로 복귀: C  CT 회전: C  CR 고정점을 원점으로 이동: C  CT -1 결과: C = TRT-1 각 연산은 프로그램에서 하나의 함수호출에 대응된다 마지막으로 지정된 연산이 프로그램상에서 처음으로 실행되는 연산임을 주의하라

OpenGL에서의 CTM OpenGL은 모델-관측 행렬과 투영행렬을 파이프라인에 포함하고 있으며 이 두 행렬이 연결되어 CTM을 구성한다 행렬모드를 올바로 설정한 후에 각각을 조작할 수 있다

회전, 이동, 크기변환 단위행렬의 적재: 변환행렬을 CTM의 오른쪽에 곱하기: glLoadIdentity() glRotatef(theta, vx, vy, vz) theta 는 각도(degree), (vx, vy, vz) 는 회전축을 정의 glTranslatef(dx, dy, dz) glScalef(sx, sy, sz)

예제 (1.0, 2.0, 3.0)을 고정점으로 하고 z 축을 중심으로 30도 회전 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(1.0, 2.0, 3.0); glRotatef(30.0, 0.0, 0.0, 1.0); glTranslatef(-1.0, -2.0, -3.0); 프로그램에서 마지막으로 지정된 행렬이 처음으로 적용되는 행렬

예제 Ex. 크기조절 이후 회전? 회전 이후 크기조절? glMatrixMode(GL_MODELVIEW); glLoadIdentity( ); glScalef(sx, sy, sz);    glRotatef(theta, vx, vy, vz);   glBegin(GL_POINTS); glVertex3f(px, py, pz);                                          glEnd( ); 크기조절 이후 회전? 회전 이후 크기조절?

객체 변환에 의한 모델링 코드 세계좌표 기준의 객체변환 glMatrixMode(GL_MODELVIEW); glLoadIdentity();           glRotatef(45, 0.0, 0.0, 1.0);  객체 변환의 역순 glTranslatef(10.0, 0.0, 0.0); glVertex3f(Px, Py, Pz);  세계좌표 기준의 객체변환 P' = T•P P'' = R•P' = R•T•P

좌표계 변환에 의한 모델링 코드 모델 좌표계를 변환 glMatrixMode(GL_MODELVIEW); glLoadIdentity();           glRotatef(45, 0.0, 0.0, 1.0);   좌표계 변환과 동일 순서 glTranslatef(10.0, 0.0, 0.0); glVertex3f(Px, Py, Pz);   모델 좌표계를 변환 직전의 모델 좌표계를 기준으로 변환 CTM = I•R CTM = CTM•T = I•R•T P'' = CTM•P = I•R•T•P   

함수호출 순서 행렬연산 순서 함수호출 순서

많은 경우, 나중에 사용하기 위해서 변환행렬을 저장하기를 원한다 행렬 스택 많은 경우, 나중에 사용하기 위해서 변환행렬을 저장하기를 원한다 계층 자료구조의 순회 (9장) 디스플레이 리스트를 실행할 때 상태 변화를 피함 OpenGL은 각 타입의 행렬을 위해서 행렬 스택을 유지 다음 명령으로 현재 타입(glMatrixMode에 의해 설정된)에 접근 glPushMatrix() glPopMatrix()

행렬 스택 오렌지 매달기 오렌지 매달기 프로그램 좌표계를 (d)로 되돌리려면 어떻게 하는가 -> 스택

행렬 스택 푸시, 팝 지엘의 푸시, 팝

행렬 스택 오렌지 매달기 프로그램의 스택 변화

행렬 스택 일반적 형태 glPushMatrix( ); glPopMatrix( ); glTranslatef( ); glRotatef( ); glScalef( ); ... Draw_TransformedObject( ); glPopMatrix( );                                                                                                            일반적인 스택함수 호출

계층구조 모델링 void drawArm( ){ glMatrixMode(GL_MODELVIEW);   glLoadIdentity( );                          전역 좌표계 = 모델 좌표계   Draw_Body( );                          몸체 그리기 glPushMatrix( );                          전역 좌표계 저장      GoToShoulderCoordinates( );           어깨 기준 모델 좌표계        Draw_UpperArm( );                  위 팔 그리기 glPushMatrix( );                      어깨 기준 모델 좌표계 저장 GoToElbowCoordinates( );        팔꿈치 기준 모델 좌표계 Draw_LowerArm( );               아래팔 그리기 glPushMatrix( );                   팔꿈치 기준 모델 좌표계 저장           GoToWristCoordinates( );  손목 기준 모델 좌표계 Draw_Hand( );               손 그리기 glPopMatrix( );                   팔꿈치 좌표계 복원      glPopMatrix( );                       어깨 좌표계 복원 glPopMatrix( );                            몸체 좌표계 복원 }

임의의 행렬 응용프로그램에서 정의된 행렬로 적재하거나 곱할 수 있다 행렬 m은 16 원소의 1차원 배열이고 원하는 4 x 4 행렬을 열(column) 순서로 저장한 것이다 glMultMatrixf에서, m은 기존의 행렬을 오른쪽에서 곱한다 glLoadMatrixf(m) glMultMatrixf(m)

행렬을 읽어들임 질의함수를 통해서 행렬들에(상태의 다른 부분도 마찬가지)접근할 수 있다 행렬에 대해서 다음과 같이 사용한다 glGetIntegerv glGetFloatv glGetBooleanv glGetDoublev glIsEnabled double m[16]; glGetFloatv(GL_MODELVIEW, m);

예제: idle 함수를 사용해서 입방체를 회전시키고 마우스 함수로 회전의 방향을 바꿈 변환의 사용 예제: idle 함수를 사용해서 입방체를 회전시키고 마우스 함수로 회전의 방향을 바꿈 입방체 그리기 프로그램으로 부터 시작 (colorcube.c) 중심이 원점에 있음 면들이 축에 평행

회전입방체 void main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow("colorcube"); glutReshapeFunc(myReshape); glutDisplayFunc(display); glutIdleFunc(spinCube); glutMouseFunc(mouse); glEnable(GL_DEPTH_TEST); glutMainLoop(); }

회전입방체 void spinCube() { theta[axis] += 2.0; if( theta[axis] > 360.0 ) theta[axis] -= 360.0; glutPostRedisplay(); } void mouse(int btn, int state, int x, int y) if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0; if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1; if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2;

회전입방체 void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glRotatef(theta[0], 1.0, 0.0, 0.0); glRotatef(theta[1], 0.0, 1.0, 0.0); glRotatef(theta[2], 0.0, 0.0, 1.0); colorcube(); glutSwapBuffers(); } 답신의 형태가 고정되어 있으므로, theta와 axis 같은 변수들은 전역변수로 정의되어야 함을 주의하라 카메라 정보는 표준적 재구성 답신에 들어간다

볼과 롤러 사이에 마찰이 작으면 볼을 밀어서 계속 돌게 함으로써 연속적인 변화를 일으킬 수 있다 두 가지 가능한 작동모드 물리적 트랙볼 트랙볼은 볼 마우스를 “뒤집어 놓은 것” 볼과 롤러 사이에 마찰이 작으면 볼을 밀어서 계속 돌게 함으로써 연속적인 변화를 일으킬 수 있다 두 가지 가능한 작동모드 연속적 밀기 혹은 손동작을 따름 회전

문제: 하나의 마우스에서 두 가지 동작모드를 원한다 또한 마우스가 마찰이 없는 이상적인 트랙볼을 흉내내기 원한다 마우스를 이용한 트랙볼 문제: 하나의 마우스에서 두 가지 동작모드를 원한다 또한 마우스가 마찰이 없는 이상적인 트랙볼을 흉내내기 원한다 두 단계로 해결 트랙볼 위치를 마우스 위치로 사상 GLUT 를 사용해서 적절한 모드를 얻음

트랙볼 프래임 원점이 볼의 중심

트랙볼 위치의 투영 트랙볼의 위치를 마우스 패드 위로 직교투영 함으로써 둘 사이의 관계를 얻음

y = 역투영 패드와 볼의 상반구는 2차원 면이므로 투영의 역을 구할 수 있다 마우스 패드 상의 점 (x,z) 는 볼의 상반구 상의 점 (x,y,z) 와 대응된다. 여기서, y = if r  |x| 0, r  |z|  0

회전의 계산 마우스로부터 두 개의 점을 얻었다고 해 보자 두 점을 반구로 투영함으로써 반구 상의 두 점 p1과 p2 를 얻는다 이 점들은 구 상의 큰 원을 결정한다 적절한 회전축과 점들 사이의 회전각을 얻음으로써 점p1 으로부터 점 p2 로 회전 할 수 있다

외적의 사용 회전축은 원점과 점 p1 과 p2 로 이루어지는 평면의 법선에 의해서 주어진다 n = p1  p2

| sin q| = sin q  q 각도의 계산 p1 과 p2 사이의 각도는

idle, motion, mouse 답신을 사용하여 가상 트랙볼을 구현한다 다음의 세 개의 불리언을 사용해서 동작을 정의한다 GLUT를 이용한 구현 idle, motion, mouse 답신을 사용하여 가상 트랙볼을 구현한다 다음의 세 개의 불리언을 사용해서 동작을 정의한다 trackingMouse: true 이면, 트랙볼의 위치를 갱신 redrawContinue: true 이면, idle 함수가 다시 그리기를 포스트(glutPostRedisplay) trackballMove: true 이면, 회전 행렬을 갱신

가상트랙볼 이 예제에서는, 가상 트랙볼을 이용해서 앞에서 모델링한 컬러 입방체를 회전시킨다 colorcube 함수는 앞의 예제와 변함이 없으므로 생략한다

가상트랙볼 bool type */ #define false 0 #define true 1 #define bool int /* if system does not support bool type */ #define false 0 #define true 1 #define M_PI 3.14159 /* if not in math.h */ int winWidth, winHeight; float angle = 0.0, axis[3], trans[3]; bool trackingMouse = false; bool redrawContinue = false; bool trackballMove = false; float lastPos[3] = {0.0, 0.0, 0.0}; int curx, cury; int startX, startY;

가상트랙볼 void trackball_ptov(int x, int y, int width, int height, float v[3]) { float d, a; /* project x,y onto a hemisphere centered within width, height , note z is up here*/ v[0] = (2.0*x - width) / width; v[1] = (height - 2.0F*y) / height; d = sqrt(v[0]*v[0] + v[1]*v[1]); v[2] = cos((M_PI/2.0) * ((d < 1.0) ? d : 1.0)); a = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] *= a; v[1] *= a; v[2] *= a; }

가상트랙볼 void mouseMotion(int x, int y) { float curPos[3], dx, dy, dz; /* compute position on hemisphere */ trackball_ptov(x, y, winWidth, winHeight, curPos); if(trackingMouse) /* compute the change in position on the hemisphere */ dx = curPos[0] - lastPos[0]; dy = curPos[1] - lastPos[1]; dz = curPos[2] - lastPos[2];

가상트랙볼 if (dx || dy || dz) { /* compute theta and cross product */ angle = 90.0 * sqrt(dx*dx + dy*dy + dz*dz); axis[0] = lastPos[1]*curPos[2]–lastPos[2]*curPos[1]; axis[1] = lastPos[2]*curPos[0]–lastPos[0]*curPos[2]; axis[2] = lastPos[0]*curPos[1]–lastPos[1]*curPos[0]; /* update position */ lastPos[0] = curPos[0]; lastPos[1] = curPos[1]; lastPos[2] = curPos[2]; } glutPostRedisplay();

가상트랙볼 void spinCube() { if (redrawContinue) glutPostRedisplay(); } void display() glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); if (trackballMove) glRotatef(angle, axis[0], axis[1], axis[2]); colorcube(); glutSwapBuffers();

가상트랙볼 void mouseButton(int button, int state, int x, int y) { if(button==GLUT_RIGHT_BUTTON) exit(0); /* holding down left button allows user to rotate cube */ if(button==GLUT_LEFT_BUTTON) switch(state) case GLUT_DOWN: y=winHeight-y; startMotion( x,y); break; case GLUT_UP: stopMotion( x,y); }

가상트랙볼 void startMotion(int x, int y) { trackingMouse = true; redrawContinue = false; startX = x; startY = y; curx = x; cury = y; trackball_ptov(x, y, winWidth, winHeight, lastPos); trackballMove=true; }

가상트랙볼 void stopMotion(int x, int y) { trackingMouse = false; /* check if position has changed */ if (startX != x || startY != y) redrawContinue = true; else angle = 0.0; redrawContinue = false; trackballMove = false; }