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