1장 – 그래픽스 시스템과 모델 2장 – 그래픽스 프로그래밍 3장 – 입력과 상호작용 4장 – 기하학적 객체와 변환 5장 관측 벡터공간, 아핀공간 좌표계와 프레임 아핀변환 이동, 회전, 크기변환 동차좌표에서의 변환 변환의 연결 OpenGL에서의 변환행렬
5장 관측 학습목표 고전적 관측을 살펴본다 투영의 수학적 이론을 이해한다 OpenGL 관측함수를 살펴본다 투영 정규화를 이해한다
고전적 관측은 이 요소들 사이의 관계에 기반을 둠 관측의 3가지 요소 객체 관측자(관측면 포함) 투영선 고전적 관측은 이 요소들 사이의 관계에 기반을 둠 관측자는 자신이 원하는 대로 객체의 방향을 정한다 각 객체는 평평한 주면(principal faces)으로부터 구성된다고 가정 건축물, 다면체, 생산품
투영면이 비평면인 경우는 지도제작과 같은 응용을 위해 필요하다 평면 기하 투영 투영면은 평면, 투영선은 직선 투영선들은 종류 투영의 중심에서 수렴하는 경우 평행한 경우 직선이 보존됨 각도는 일반적으로 보존되지 않는다 투영면이 비평면인 경우는 지도제작과 같은 응용을 위해 필요하다
고전적 투영
컴퓨터 그래픽스에서 모든 투영은 동일하게 처리되고 하나의 파이프라인으로 수행한다 투시투영 vs 평행투영 컴퓨터 그래픽스에서 모든 투영은 동일하게 처리되고 하나의 파이프라인으로 수행한다 고전적 관측에서는 각 투영종류에 따라 각기 다른 제도 기술이 개발되었다 근본적 차이는 평행관측과 투시관측 사이에 있다 수학적으로는 평행관측이 투시관측의 극한에서의 특수한 경우이다(투영중심이 무한대로 떨어져있는 경우)
평면 기하 투영의 분류 평행투영 투시투영 축측투영 다중직교투영 경사투영 등축투영 이축투영 삼축투영 2 점투시 1 점투시 3 점투시 평면 기하 투영
투시투영
평행투영
직교투영
다중 직교투영 투영면이 주면에 평행 일반적으로 정면,평면, 측면 관측을 표시 등축 (다중 직교 관측이 아님) 정면 CAD와 건축설계에서, 종종 등축 외에 3개의 다중관측을 같이 나타낸다. 측면 평면
많은 면들이 관측자에게 안 보이므로 실제로 어떻게 보일지 알 수 없다 장단점 거리와 각 둘 다 보존 모양(shape) 보존 측정을 위해 사용될 수 있다 건물 설계도 매뉴얼 많은 면들이 관측자에게 안 보이므로 실제로 어떻게 보일지 알 수 없다 흔히 등축투영을 추가
축측 투영(axonometric projection) 투영면의 이동을 허용 투영된 입방체 코너에서 몇 개의 각이 같은지에 따라 분류 모두 다름 : 삼축 투영 2개가 같음 : 이축 투영 3개가 같음 : 등축 투영 q 1 q 3 q 2
축측 투영의 종류
선분의 길이가 달라지지만(축소된다) 축소비율을 구할 수 있다 장단점 선분의 길이가 달라지지만(축소된다) 축소비율을 구할 수 있다 선은 보존되지만 각은 보존되지 않는다 원을 투영면과 평행하지 않은 면에 투영하면 타원이 된다 상자와 같은 객체의 세 주면을 볼 수 있다 착시가능성이 있다 평행선이 발산하는 것으로 보인다 먼 객체와 가까운 객체가 같은 비율로 축소되므로 실제처럼 보이지 않는다 CAD 응용에서 사용
경사 투영(oblique projection) 투영선과 투영면사이의 임의의 관계
투영면에 평행한 면내의 각은 보존된다. “주변”의 면들을 볼 수 있다 장단점 특정한 면을 강조하기 위한 각을 선택할 수 있다. 건축: 평면경사, 입면경사 투영면에 평행한 면내의 각은 보존된다. “주변”의 면들을 볼 수 있다 실세계에서, 간단한 카메라로 생성할 수는 없다 주름상자 카메라 또는 특별한 렌즈로 가능
투시 투영(perspective projection) 투영선이 투영 중심에 수렴
소실점 객체상의(투영면에 평행하지 않은) 평행선들은 투영 내의 하나의 점(소실점)에 수렴한다. 소실점을 사용하여 수작업으로 간단한 투시를 그릴 수 있다 소실점
삼점투시 모든 주면이 투영면과 평행하지 않다. 입방체 : 세 개의 소실점
이점투시 하나의 주방향이 투영면에 평행한다. 입방체 : 두 개의 소실점
일점투시 하나의 주면이 투영면에 평행 입방체 : 하나의 소실점
관측자로부터 멀리 있는 객체는 가까이 있는 같은 크기의 객체보다 더 작게 투영된다 장단점 관측자로부터 멀리 있는 객체는 가까이 있는 같은 크기의 객체보다 더 작게 투영된다 실감나게 보인다 일직선 상의 같은 거리가 다른 거리로 투영된다 각은 투영면에 평행인 면에서만 보존된다 평행 투영보다 손으로 그리기에는 더 어렵다 (그러나 컴퓨터로 하면 더 어렵지 않음)
세 가지 관측 처리 - 파이프라인에 구현되어 있다 컴퓨터 관측 세 가지 관측 처리 - 파이프라인에 구현되어 있다 카메라 배치 모델-관측 행렬 설정 렌즈 선택 투영행렬 설정 절단 관측 공간 설정
OpenGL에서, 세계프레임과 카메라 프레임이 같도록 초기화 디폴트 모델-관측 행렬은 단위행렬 카메라는 원점에 위치하고 음의 z 방향으로 향하게 한다 OpenGL의 디폴트 관측 공간은 중심이 원점이고 길이가 2인 변을 가진 입방체이다 디폴트 투영 행렬은 단위행렬
디폴트 투영 디폴트는 직교투영이다. clipped out 2 z=0
두 관점이 등가적이며 모델-관측 행렬에 의해 결정된다 카메라 프레임의 이동 음과 양의 Z 값을 모두 갖는 객체를 보여주려면 양의 z방향으로 카메라를 이동 카메라 프레임을 이동 음의 z방향에서 객체를 이동 세계프레임을 이동 두 관점이 등가적이며 모델-관측 행렬에 의해 결정된다 glTranslatef(0.0,0.0,-d); d > 0
원점에서 카메라를 뒤로 이동 디폴트 프레임 -d 만큼 이동후의 프레임 d > 0
일련의 회전과 이동에 의해 임의의 위치로 카메라를 옮길 수 있다 카메라 이동 일련의 회전과 이동에 의해 임의의 위치로 카메라를 옮길 수 있다 예제: 측면 관측 카메라를 회전 원점에서 떨어져서 이동 모델-관측 행렬 C = TR
지정된 마지막 변환이 첫 번째로 적용됨을 유념하라 OpenGL 코드 지정된 마지막 변환이 첫 번째로 적용됨을 유념하라 glMatrixMode(GL_MODELVIEW) glLoadIdentity(); glTranslatef(0.0, 0.0, -d); glRotatef(-90.0, 0.0, 1.0, 0.0);
GLU 라이브러리는 간단한 인터페이스를 통해 요구된 모델-관측 행렬을 형성하기 위한 gluLookAt 함수를 제공한다 상향 설정이 필요 초기화 필요 모델링 변환들과 연결하여 사용할 수 있다 예: 축과 정렬된 입방체의 등축관측 glMatrixMode(GL_MODELVIEW): glLoadIdentity(); gluLookAt(1.0, 1.0, 1.0, // eye 0.0, 0.0, 0.0, // at 0.0, 1.0. 0.0); // up
gluLookAt gluLookAt(eyex, eyey, eyez, atx, aty, atz, upx, upy, upz)
장면 안에서의 움직임 void keys(unsigned char key, int x, int y) { if(key == 'x') viewer[0]-= 1.0; if(key == 'X') viewer[0]+= 1.0; if(key == 'y') viewer[1]-= 1.0; if(key == 'Y') viewer[1]+= 1.0; if(key == 'z') viewer[2]-= 1.0; if(key == 'Z') viewer[2]+= 1.0; glutPostRedisplay(); }
장면 안에서의 움직임 void display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(viewer[0],viewer[1],viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 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(); }
장면 안에서의 움직임 void myReshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w<=h) glFrustum(-2.0, 2.0, -2.0*(GLfloat)h/(GLfloat)w, 2.0*(GLfloat)h/(GLfloat)w, 2.0, 20.0); else glFrustum(-2.0*(GLfloat)w/(GLfloat)h, 2.0*(GLfloat)w/(GLfloat)h, -2.0, 2.0, 2.0, 20.0); glMatrixMode(GL_MODELVIEW); }
LookAt함수는 카메라를 배치하기 위한 하나의 방법이다. 기타 방법들 기타 관측 API들 LookAt함수는 카메라를 배치하기 위한 하나의 방법이다. 기타 방법들 관측 참조점, 관측면 법선, 관측 상향 (PHIGS, GKS-3D) 횡전(Yaw), 종전(pitch), 편요(roll) 앙각(Elevation), 방위각(azimuth), 꼬임각(twist) 방향각
대부분의 그래픽스 시스템은 관측 정규화를 사용 투영과 정규화 카메라 프레임에서 디폴트는 직교 투영 디폴트 관측 공간 내에 있는 점에 대해서, 대부분의 그래픽스 시스템은 관측 정규화를 사용 모든 다른 관측들은 투영 행렬을 결정하는 변환에 의해 디폴트 관측으로 전환된다 모든 관측을 위해 같은 파이프라인의 사용을 허용한다
동차 좌표 표현 디폴트 직교 투영 실제로는, M = I 라고 가정하고 나중에 z는 0으로 설정할 수 있다
단순한 투시 투영 중심은 원점 투영면 z = d, d < 0
투시 방정식 평면관측과 측면 관측을 고려해보자
동차 좌표 형식
투시 제산 w 1 : 동차좌표에서 반환되는 w로 나눠야 한다. 투시 제산은 다음과 같이 원하는 투시 방정식을 산출한다. OpenGL함수로 정해지는 절단공간을 살펴본다
OpenGL 직교 관측 glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) near 와 far 는 카메라로부터 측정됨
OpenGL 투시 glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far
시야(field of view)의 사용 front plane glFrustum으로 원하는 관측을 얻기 어려운 경우가 있다 gluPerpective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far) : 때로는 더 좋은 인터페이스를 제공 front plane aspect = w/h fovy : angle in deg.
정규화 여러 가지 투영들을 위한 각각의 투영행렬을 유도하지 않고, 모든 투영을 디폴트 관측공간을 갖는 직교투영으로 변환한다 이 방법은 파이프라인에서 표준 변환을 사용할 수 있게 하며 절단을 효율적으로 한다
파이프라인 모델 관측 변환 투영 변환 투시 제산 절단 투영 비특이(nonsingular) 4D 3D 디폴트 입방체에 대해서 3D 2D
모델 관측과 투영변환 모두를 통해 4차원 동차 좌표를 유지 유의사항 모델 관측과 투영변환 모두를 통해 4차원 동차 좌표를 유지 이 두 변환은 비특이 변환이다. 디폴트는 단위행렬 (직교 관측) 정규화를 함으로써 어떤 투영방법이 사용되든지 간단한 입방체에 대해서 절단할 수 있도록 한다 최종적인 투영은 마지막까지 지연된다 은면 제거를 위해 가능한 한 오랫동안 깊이 정보를 남기는 것이 중요하다
정규화 지정된 절단 공간을 디폴트 절단공간으로 전환하기 위한 변환을 찾는다. 직교 정규화 glOrtho(left,right,bottom,top,near,far) 정규화 지정된 절단 공간을 디폴트 절단공간으로 전환하기 위한 변환을 찾는다.
직교 행렬 두 단계 P = ST = 중심을 원점으로 이동 T(-(left+right)/2, -(bottom+top)/2,(near+far)/2)) 변의 길이가 2가 되도록 크기변환을 함 S(2/(left-right),2/(top-bottom),2/(near-far)) P = ST =
최종적인 투영 z =0으로 설정 동차 좌표 변환과 같음 따라서, 4D에서 일반적인 직교 투영은 다음과 같다
경사투영 OpenGL 투영 함수는 다음과 같은 일반적인 평행 투영을 만들 수 없다. 그러나 입방체의 예에서 본다면 입방체가 밀린 것처럼 나타난다. 경사 투영 = 밀림 + 직교 투영
일반적인 밀림 side view top view
밀림 행렬 xy 밀림 (z 값은 변하지 않음) 투영 행렬 일반적인 경우:
등가성
절단에 대한 효과 투영 행렬 P = STH 은 원래의 절단 공간을 디폴트 절단 공간으로 변환시킨다 객체 top view z = 1 DOP DOP x = -1 x = 1 far 면 z = -1 절단 공간 Near 면 왜곡된 객체 (올바르게 투영)
투시투영행렬 COP가 원점이고, near 절단면이 z= -1인 면이고, 다음의 평면들에 의해 결정되는 시야가 90도인 간단한 투시를 고려해 보자 x = z, y = z
투시투영행렬 동차 좌표에서의 간단한 투시행렬 이 행렬은 far 절단면에 독립적임을 유의하라
투시투영행렬 투시제산 후에 , 점 (x, y, z, 1)은 다음과 같이 된다.
투시투영행렬 z 축을 따라서 N에 직교투영을 적용하면 이 행렬은 단순 투시투영행렬이고 임의의 점 p의 투영은 다음과 같다
투시투영행렬 절두체의 경계면이 N에 의해 어떻게 변환되는가?
투시투영행렬 original 절단공간 original 객체 새로운 절단 공간 올바르게 투영된 왜곡된 객체
투시투영행렬 투시행렬 형식의 선택이 임의적인 것으로 보이지만, 원래의 절단 공간에서 z1 > z2 이면 변환된 점도 z1’ > z2’이 되도록 선택된 것이다 따라서 정규화 변환을 먼저 적용해도 은면제거가 올바로 동작한다 그러나, 식 z’’ = -(a+b/z) 는 거리를 왜곡시키는데 특히 near 거리가 작은 경우 수치적인 문제를 일으킬 수 있다
투시투영행렬 glFrustum : 비대칭 관측 절두체를 허용 (gluPerspective에서는 허용하지 않음)
투시투영행렬 glFrustum에 의해서 정해지는 일반적인 절두체에 대해서는 밀림과 크기변환을 통해서 정규화된 절두체로 먼저 바꾸어 준다.
투시투영행렬 밀림은 다음과 같다
투시투영행렬
투시투영행렬
투시투영행렬 glFrustum에서 정규화는 올바른 관측 피라미드를 형성하기 위해 초기에 밀림이 필요하며, 다음으로 크기변환을 통해 정규화된 투시 공간을 얻는다. 최종적으로 투시 행렬은 적용함으로써 마지막 직교변환만을 남겨놓게 된다 앞서 정의한 투시행렬 밀림과 크기변환
투시투영행렬 정규화를 함으로써 투시관측과 직교관측 모두를 하나의 파이프라인으로 할 수 있다 은면제거와 음영을 위해 필요한 3차원 정보를 유지하기 위해 4차원 동차 좌표를 가능한 한 오랫동안 유지해 왔다 절단을 단순화한다
모델좌표 세계좌표 카메라좌표 절단좌표 정규화장치좌표 화면좌표 모델행렬 관측행렬 투영행렬 투시제산 뷰포트변환 래스터변환