Lecture #7 제 4 장. 기하학적 객체와 변환 (2)
강의 내용 (1) 어떻게 기본적인 기하학적 형들을 표현 표현 사이의 변환 특정 표현 방식에 독립적인 방식으로 기본적인 기하학적 객체를 표현할 수 있는가? 표현 사이의 변환 컴퓨터 그래픽스 = 변환 모델 좌표계 세계 좌표계 카메라 좌표계 이미지 좌표계 장치 좌표계
강의 내용 (2) 1. 어파인 변환 2. 회전, 이동, 크기변환 3. 동차 좌표계에서의 변환 4. 변환의 연결 5. 변환의 구현 6. 예제 -회전 입방체 그리기
어파인 변환 (Affine Transformation) 선형변환 P = f (P) P = f (P1 + P2) = f( P1) + f(P2) 정점들의 선형조합 변환된 정점들의 선형조합 선형 변환의 중요성 : 정점만 변환해도 됨
어파인 변환의 행렬 표현 P = f (P) P = M P v = M v v = f (v) 어파인 변환 : 4째 행이 [0 0 0 1]의 값을 가짐 P’ = M P M is a 4x4 matrix, with 12 degrees of freedom v’ = M v M is a 4x4 matrix, with 9 degrees of freedom.
어파인 변환의 종류 직선을 보존 평행선을 보존 대표적인 어파인 변환 이동 Projective 회전 크기 변환 밀림(shear) Affine
기본적인 어파인 변환 이동(Translation) 회전(Rotation) 크기변환(Scaling) 밀림(Shearing)
이동(Translation) p’ = p + d 이차원 이동 변환의 행렬 표현 (b)
회전(Rotation) 이차원 회전 변환의 행렬 표현 회전의 중심 : 원점
회전하기 전에 먼저 고정점을 원점으로 이동해야 함 고정점(fixed point) 변환의 고정점 : 변환에 의해 변경되지 않는 점 회전 변환의 고정점은 원점 2차원 회전은 z축에 대한 3차원 회전과 동일 회전하기 전에 먼저 고정점을 원점으로 이동해야 함 The center of rotation is crucial. 고정점
3D 회전 고정점 Pf 각도 회전 중심축 v
크기변환(Scaling) (1) 크기변환 : 비강체(non-rigid-body) 변환
크기변환(Scaling) (1) 크기 변환의 고정점 : 원점 비균일 크기변환 이차원 크기변환의 행렬 표현 균일 크기변환
반사 변환(Reflection) 일종의 크기변환
밀림(Shearing) x 밀림 변환 x 밀림 변환의 행렬 표현 y 밀림 변환의 행렬 표현
동차 좌표계에서의 변환 이동 크기변환 회전 밀림
동차 좌표계에서의 이동 동차 좌표를 사용함으로써 행렬의 곱셈으로 표현
이동 변환의 역
동차 좌표계에서의 크기변환 p’=S p 역변환 :
동차 좌표계에서의 회전 (1) 원점을 고정점으로 하고 세가지 축을 중심으로 하는 회전을 정의할 수 있음 z-축 중심으로 회전
동차 좌표계에서의 회전 (2) x-축 중심으로 회전 y-축 중심으로 회전
동차 좌표계에서의 회전 (3) 회전의 역변환 R() : 직교 행렬(Orthogonal Matrix)
동차 좌표계에서의 밀림 x y (x,y) (x’,y’) q b a
변환의 연결 (Transformation Concatenation) q = C ( B ( A p ) ) = C B A p q = M p , where M = C B A 많은 정점에 효율적 파이프라인 구조에 적합
변환 연결 - 고정점에 대한 회전 (1) 원점에 고정점이 정의된 변환 원점이 아닌 점이 고정점인 경우는? 회전, 크기 변환, 밀림 원점이 아닌 점이 고정점인 경우는? z-축 중심으로 회전
변환 연결 - 고정점에 대한 회전 (2) 변환 연결로 해결
변환 연결 - 일반적인 회전 (1) 원점에 대한 임의의 회전은 세 축에 대한 세 번의 연속된 회전으로 구성할 수 있다 1) z축에 대한 회전
변환 연결 - 일반적인 회전 (2) 2) y축에 대한 회전 (a) (b)
변환 연결 - 일반적인 회전 (3) 3) x축에 대한 회전
변환 연결 - 임의의 축에 대한 회전 1. Po 를 원점으로 옮김 2. u 를 z-축과 일치시킴 4. 2번 역순 5. 1번 역순
변환 연결 - 사례(instance) 변환 많은 간단한 객체들로 구성된 장면 효율적인 구성 방법 정육면체를 한번만 정의 사례 변환을 통하여 각 사례를 생성 사면체의 한 사례
변환 연결 - 사례(instance) 변환
변환의 구현 현재 변환 행렬 (CTM) CTM 파이프라인의 일부 시스템 상태의 일부 정점들 C I 단위 행렬로 초기화 (C = CTM) C CT C CS 이동, 크기, 회전 변환을 곱함으로써 수정 C CR
OpenGL 변환 행렬 (1) CTM OpenGL의 CTM 모델-관측 투영 행렬 적재 glLoadIdentity(); 정점들 CTM 행렬 적재 glLoadIdentity(); glLoadMatrixf(pointer_to_matrix); vx, vy, vz : 회전 중심 벡터 회전, 이동, 크기 변환 glRotatef(angle, vx, vy, vz) glTranslatef(dx,dy,dz); glScalef(sx,sy,sz);
OpenGL 변환 행렬 (2) OpenGL에서 고정점에 대한 회전 변환순서 가장 최근에 지정된 변환이 가장 먼저 적용되는 변환 glMatrixMode(GL_MODEVIEW) glLoadIdentity(); glTranslatef(4.0,5.0,6.0); glRotatef(45.0,1.0,2.0,3.0); glTranslatef(-4.0,-5.0,-6.0); 변환순서 가장 최근에 지정된 변환이 가장 먼저 적용되는 변환 C I C T(4.0,5.0,6.0) C R(45.0,1.0,2.0,3.0) C T(-4.0,-5.0,-6.0) C = T(4.0,5.0,6.0)R(45.0,1.0,2.0,3.0)T(-4.0,-5.0,-6.0)
회전하는 입방체 그리기 3차원 객체 정의 모델링 카메라 프레임으로 변환 절단 투영 은면 제거 래스터화
입방체의 모델링 정점의 정의 한면의 정의 다른 다섯 면도 같은 방법으로 정의할 수 있다 typedef float point[3]; point node[8] ={{-1.0, -1.0, -1.0}, {1.0, -1.0, -1.0}, {1.0, 1.0, -1.0}, {-1.0, 1.0, -1.0}, {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0}}; 한면의 정의 glBegin(GL_POLYGON); glVertex3fv(node[0]); glVertex3fv(node[3]); glVertex3fv(node[2]); glVertex3fv(node[1]); glEnd(); 다른 다섯 면도 같은 방법으로 정의할 수 있다
내향면과 외향면 다각형의 정점들을 정의하는 순서에 의해서 면의 방향을 정의 오른손 법칙
입방체의 데이터 구조 위상을 표현할 수 있는 데이터 구조
각 정점마다 색을 지정하고 다각형 내부는 정점들의 색을 보간 색 입방체 (1) typedef GLfloat point[3]; point node[8] ={{-1.0,-1.0,-1.0}, {1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, {1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0}}; GLfloat colors[][3] ={{0.0,0.0,0.0}, {1.0,0.0,0.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0, 1.0, 1.0}}; void quad(int a, int b, int c, int d) { glBegin(GL_POLYGON); glColor3fv(colors[a]); glVertex3fv(node[a]); glColor3fv(colors[b]); glVertex3fv(node[b]); 각 정점마다 색을 지정하고 다각형 내부는 정점들의 색을 보간
색 입방체 (2) glVertex3fv(node[c]); glColor3fv(colors[d]); glColor3fv(colors[c]); glVertex3fv(node[c]); glColor3fv(colors[d]); glVertex3fv(node[d]); glEnd(); } void colorcube() { quad(0, 3, 2, 1); quad(2, 3, 7, 6); quad(0, 4, 7, 3); quad(1, 2, 6, 5); quad(4, 5, 6, 7); quad(0, 1, 5, 4);
쌍일차 보간 (bilinear interpolation) 참고 : 양선형 보간이라 번역하기도 함
주사선 보간 (scan-line interpolation) 주사선보간 이차원으로 투영된 후에 보간
색 입방체의 회전 (1) #include <stdio.h> #include <GL/glut.h> Glfloat vertices[][3]={{-1.0,-1.0,1.0}, {1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, {1.0,1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0}}; Glfloat normals[][3]={{-1.0,-1.0,-1.0}, {1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0},{-1.0,-1.0,1.0}, {1.0,1.0,1.0}, {1.0,1.0,1.0}, Glfloat colors[][3]={{0.0,0.0,0.0}, {1.0,0.0,0.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0,1.0,1.0}}; void polygon(int a, int b, int c, int d) { glBegin(GL_POLYGON); glColor3fv(colors[a]); glNormal3fv(normals[a]); glVertex3fv(vertices[a]); glColor3fv(colors[b]); glNormal3fv(normals[b]); glVertex3fv(vertices[b]); glColor3fv(colors[c]); glNormal3fv(normals[c]); glVertex3fv(vertices[c]); glColor3fv(colors[d]); glNormal3fv(normals[d]); glVertex3fv(vertices[d]); glEnd(); }
색 입방체의 회전 (2) glLoadIdentity(); glRotatef(theta[0],1.0,0.0,0.0); Void colorcube(void) { polygon(0,3,2,1); polygon(2,3,7,6); polygon(0,4,7,3); polygon(1,2,6,5); polygon(4,5,6,7); polygon(0,1,5,4); } static Glfloat theta[] = {0.0,0.0,0.0}; static Glint axis = 2; void display(void) { 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(); glFlush(); glutSwapBuffers(); } void spincube() { theta[axis] += 2.0; if(theta[axis] > 360.0) theta[axis] -= 360.0; display();
색 입방체의 회전 (3) 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 myReshape(int w, int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w<=h) glOrtho(-2.0, 2.0, -2.0*(GLfloat) h / (GLfloat) w, 2.0*(GLfloat) h / (GLfloat) w, -10.0, 10.0); else glOrtho(-2.0*(Glfloat) w / (Glfloat) h, 2.0*(Glfloat) w / (Glfloat) h, -2.0, 2.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); }
색 입방체의 회전 (4) 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); glutEnable(GL_DEPTH_TEST); glutMainLoop(); }