5. 좌표변환과 OpenGL행렬 이론

Download Report

Transcript 5. 좌표변환과 OpenGL행렬 이론

Computer Graphics
5. 좌표변환과 OpenGL행렬 이론
Chapter 5 – 좌표 변환과 OpenGL 행렬
목차
좌표 변환의 이해
• 카메라와 시점 좌표
• 조망 변환
– gluLookAt()함수의 사용
– glRotate()와 glTranslate()함수의 사용
– 모델링 변환
투영 / 뷰포트 변환
OpenGL과 행렬
•
•
•
•
모델뷰 행렬
이동 / 회전
확대 / 축소
행렬 스택
Chapter 5 – 좌표 변환과 OpenGL 행렬
5-1 좌표 변환의 이해(1/6)
변환의 용도
• 3D 좌표를 2D 화면에 투영
• 이동, 회전, 확대 축소(실제로 이동하는 것은 좌표계)
변환
설명
조망변환
카메라의 위치를 지정한다.
모델링 변환
장면 안에서 객체를 움직인다.(이동, 회전, 확대/축소)
투영 변환
조망 입체와 절단면들을 정의한다.
뷰 포트
장면의 2D 투영을 랜더링 창에 매핑한다.
모델 뷰
조망 변환과 모델링 변환을 결합한 것
순서를 지켜야 함
• 조망변환은 반드시 모델링 변환 이전에 수행되어야 함
• 투영변환과 뷰 포트 변환은 랜더링 이전이기만 하면 됨
Chapter 5 – 좌표 변환과 OpenGL 행렬
5-1 좌표 변환의 이해(2/6)
카메라와 시점 좌표
• 기본 카메라는 항상 음의 Z축 쪽을 바라봄
• 시점 좌표는 카메라에 적용된 좌표계로부터 직접적
으로 도출
• 시점 좌표는 정점 변환으로부터 영향을 받지 않음
전역좌표계
객체좌표계
전역좌표계
(시점 좌표계)
객체좌표계
Chapter 5 – 좌표 변환과 OpenGL 행렬
5-1 좌표 변환의 이해(3/6)
조망 변환
•
회전과 이동을 통해 카메라의 기본 위치/방향을 변경
시킴
– 카메라의 기본 방향은 음의 Z축 방향, 기본 위치는 (0,0,0)
•
•
시점 좌표계에 대해 현재 좌표계를 이동
수행과정
– glLoadIdentity()함수 사용
: 현재 행렬을 초기화하여 단위행렬 생성
– 조망 변환에 적용될 행렬을 현재 행렬로 설정
1. 단위 행렬을 그대로 둔다.
2. gluLookAt()함수를 사용하여 카메라의 시선을 설정
3. 고정된 카메라에 대해 객체들을 움직이는 방법(glTranslate()함수와
glRotate()함수를 사용)
4. 독자적인 좌표계를 위한 이동과 회전루틴 직접 작성
Chapter 5 – 좌표 변환과 OpenGL 행렬
5-1 좌표 변환의 이해(4/6)
gluLookAt()함수의 사용(그림 5.4)
카메라 위치
void gluLookAt(Gldouble eyex, Gldouble eyey, Gldouble eyez,
카메라가 가리키는
Gldouble centerx, Gldouble centery, Gldouble centerz,
곳의 위치
Gldouble upx,Gldouble upy, Gldouble upz);
위쪽방향을
알려주는 상향 벡터
//gluLookAt()함수로 조망 변환을 설정
//카메라가 음의 x축인 (0.0, 0.0, -100.0)을 바라보게 함
gluLookAt(0.0f, 0.0f, 10.0f, 0.0f, 0.0f, -100.0f, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLE);
glVertexf(10.0f, 0.0f, 0.0f);
glVertexf(0.0f, 10.0f, 0.0f);
glVertexf(-10.0f, 0.0f, 0.0f);
glEnd();
원점에 삼각형을
하나 그린다.
Chapter 5 – 좌표 변환과 OpenGL 행렬
5-1 좌표 변환의 이해(5/6)
glRotate()와 glTranslate()함수의 사용
• gluLookAt()함수는 프로그램을 만들 때 반드시 GLU
라이브러리를 링크해야함
• GLU라이브러리를 사용하지 않고 고정적인 카메라
에 대한 전역 공간 안의 객체의 위치를 수정
– glRotate() : 카메라의 방향을 이동시킴
– glTranslate() : 카메라의 위치를 이동시킴
//glTranslatef()함수로 조망 변환을 설정
//모델링 변환을 (0.0, 0.0, -10.0)으로 설정
모델링 변환을 (0.0, 0.0, -10.0)
glTranslatef(0.0f, 0.0f, -10.0f);
으로 설정함으로써 카메라를
glBegin(GL_TRIANGLE);
(0.0, 0.0, 10.0)으로 옮기는 효과.
glVertextf(10.0, 0.0f, 0.0f);
glVertextf(0.0, 10.0f, 0.0f);
glVertextf(-10.0, 0.0f, 0.0f);
glEnd();
Chapter 5 – 좌표 변환과 OpenGL 행렬
5-1 좌표 변환의 이해(6/6)
커스텀 변환 루틴의 작성 후 사용
• 극좌표 방식의 변환 설정
– 하나의 고정된 점을 회전의 중심으로 사용
• 퀘이크 스타일의 변환 설정
– 마우스나 키보드를 이용해서 카메라를 조종
• P155 코드 : 비행 시뮬레이터의 조망변환 예
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.2 모델링 변환
모델을 이동, 회전, 확대.축소 함으로써 모델의
위치와 방향을 조작
모델링 변환들이 일어나는 순서는 최종적인 장
면에 영향을 미침
• 객체를 이동시킨 다음 회전시키는 것과 객체를 회전
시킨 다음 이동시키는 것은 결과가 틀림
회전후 이동
(5, 4.33)
이동후 회전
(5, 0)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.3 투영 변환 & 뷰포트 변환
 투영 변환
조망 입체와 절단면들을 결정
모델뷰 변환 이후에 일어남
• 원근 투영
– 실세계에서 인간이 보는 것과 비슷한 방식으로 3D를 투영
– 카메라에 가까운 객체는 크게, 먼 객체는 작게 나타남
• 직교 투영
– 거리에 상관없이 객체를 실제 크기로 투영
– CAD 소프트웨어에서 흔히 쓰임
 뷰포트 변환
• 투영변환에 의해 만들어진 2차원 장면을 윈도우의
렌더링 표면에 대응
• 최종적인 2차원 화면을 랜더링 표면의 크기에 맞게
확대/축소 시키는 것
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.4 OpenGL과 행렬(1/7)
모든 변환은 행렬에 의해 연산
모델뷰 행렬 (cf. 투영 행렬, 텍스쳐 행렬)
• 객체의 위치와 방향을 잡는데 쓰이는 좌표계를 정의
• 모델뷰 행렬은 4 * 4 행렬이며 이 행렬의 정점들이
곱해짐으로써 모델링과 조망변환이 발생
• glMatirexMode()함수
– 행렬을
수정하고자
할 때 지금부터 수정할 행렬이 모델뷰
<모델뷰
행렬의
초기화 예>
행렬임을 알려주는 역할
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//모델뷰 행렬을 초기화
……..
//변환들을 수행
void glMatrixMode(GLenum
mode);
glBegin(GL_POINTS);
glVertex3f(0.0f, 0.0f, 0.0f);
• Mode인자에 GL_MODELVIEW를 지정하면
glEnd(); 모델뷰 행렬이 현재 행렬로 지정
•
이후의 변환 명령들은 모두 모델뷰 행렬에
영향을 미침
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.4 OpenGL과 행렬(2/7)
• 모델뷰 행렬을 현재 행렬로 설정한 후 초기화
– glLoadIdentity()함수를 호출하여 수행
▪ 이 함수를 호출하면 모델뷰 행렬이 단위 행렬이 되고, 현재 좌표계는
전역 좌표계의 원점에 위치
이동
• 객체를 한 곳에서 다른 곳으로 옮기는 것
void glTranslatef(GLfloat x, GLfoat y, GLfoat z);
void glTranslated(Gldoule x, Gldoule y, Gldoule z);
• 두 함수의 차이는 인자들의 데이터형 뿐
– 원하는 정밀도에 따라 달라짐(double이 정밀도가 더 높음)
glMatrixMod(GL_MODELVIEW);
모델뷰 행렬을 현재 행렬로 설정
glLoadIdentity(); 모델뷰 행렬을 단위 행렬로 초기화
glTranslatef(5.0f, 5.0f, 5.0f);
(5, 5, 5)로 이동
DrawCube();
입방체를 그린다.
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.4 OpenGL과 행렬(3/7)
회전
• glRotate()함수를 통해서 일어난다.
void glRotatef(GLfloat angle, GLfoat x , GLfoat y, GLfoat z);
void glTranslated(Gldoule angle, Gldoule x , Gldoule y, Gldoule z);
회전각으로 단위는 도 이며 반시계
방향이 양의 각도임
glRotatef(135.0f, 0.0f, 1.0f, 0.0f);
Y축에 대해 135도 회전
• 회전각을 음수로 주면 시계 방향으로 회전
• 임의의 축에 대한 회전도 가능
– x, y, z에 (1, 1, 0)을 지정하면 원점에서 (1, 1, 0)을 잊는 벡
터가 회전축이 된다.
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.4 OpenGL과 행렬(4/7)
• 여러 개의 회전들을 결합하는 것도 가능
모델뷰 행렬을 현재 행렬로 설정
glMatrixMod(GL_MODELVIEW);
glLoadIdentity();
단위 행렬을 최기화 한다.
glRotatef(60.0f, 1.0f, 0.0, 0.0f);
glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
DrawCube();
입방체를 그린다.
X축에 대해 60도 회전
Y축에 대해 45도 회전
(1,1,0)
glRotatef(105.0f, 1.0f, 1.0f, 0.0f);
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.4 OpenGL과 행렬(5/7)
확대 / 축소
• 객체의 크기를 키우거나 줄이는 것
• glScale()함수를 사용
void glScalef(GLfoat x , GLfoat y, GLfoat z);
void glScaled(Gldoule x , Gldoule y, Gldoule z);
– 비율이 1보다 크면 확대이고 1보다 작으면 축소
glScalef(2.0f, 2.0f, 2.0f);
glSaclef(0.5f, 0.5f, 0.5f);
비율을 현재의 2배만큼 확대
비율을 현재의 반으로 축소
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.4 OpenGL과 행렬(6/7)
행렬 스택
• 모델뷰 행렬 스택
– 좀 더 간단한 객체들로부터 복잡한 모델들을 구축하는 데
쓰임
– 모델뷰 행렬 스택의 최상위 행렬은 모델뷰 행렬
• 투영 행렬 스택
– 투영 행렬 스택의 최상위 행렬은 투영행렬
• 텍스쳐 행렬 스택
• 로봇을 만들 때, 각 부품마다 서로 다른 변환들이 일
어나야 하기 때문에 서로 다른 행렬들이 적용되어야
함
– 행렬 스택은 각기 다른 상황에 대해 서로 다른 행렬들을 적
용하려 할 때 행렬들을 일시적으로 저장해 두기 위한 수단
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.4 OpenGL과 행렬(7/7)
• glPushMatrix() 함수
– 현재 행렬을 복사해서 그것을 행렬 스택에 밀어넣는 작업
– 스택에 너무 많은 행렬이 쌓이면 OpenGL은
GL_STACK_OVERFLOW 오류를 발생
• glPopMatirx() 함수
– 현재 행렬을 폐기하고 스택에서 현재 행렬 바로 아래에 있
는 행렬을 현재 행렬로 만듬
– 스택에 행렬이 하나 밖에 없는 상태에서 이 함수를 호출하
면 OpenGL은 GL_STACK_UNDERFLOW 오류를 발생
glPushMatrix()
glPopMatrix()
행렬 스택
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.5 변환의 일반적인 순서
정점 데이터
(x, y, z, w)
모델뷰 행렬
시점좌표
투영행렬
클립좌표
윈도우 좌표
(x, y)
뷰포트 변환
정규회된 장치 좌표
원근조정
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (1/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (2/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (3/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (4/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (5/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (6/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (7/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.6 로봇 Source (8/8)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.7 응용 Source (1/4)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.7 응용 Source (2/4)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.7 응용 Source (3/4)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.7 응용 Source (4/4)
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.8 투영
직교(평행) 투영
• 원근을 고려하지 않는 투
영
원근 투영
• 사실적인 장면들을 담아내
는 원근을 고려한 투영(절
두체)
• 절단면 정의
투영변환
조망입체
• 객체 그려지
는 방식 결정
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.8 투영
직교(평행) 투영
glOrtho(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far);
glOrtho2D(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top);
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.8 투영
원근 투영
void glFrustum(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far);
void gluPerspective(GLdouble fov, GLdouble aspect,
GLdouble near, GLdouble far);
Chapter 5 – 좌표 변환과 OpenGL 행렬
5.9 커스텀 행렬 사용
부동 소수점 값들로 된 열 우선 4 x 4 행렬
m0 m4 m8 m12
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15
void glLoadMatrix(const Gldouble *matrix);
void glLoadMatrixf(const Glfloat *matrix);
void glMultMatrix(const Gldouble *matrix);
void glMultMatrixf(const Glfloat *matrix);