중간고사 담당교수 : 단국대학교멀티미디어공학전공박경신 답은반드시답안지에기술할것. 공간이부족할경우반드시답안지몇쪽의뒤에있다고명기한후기술할것. 그외의경우의답안지뒤쪽이나연습지에기술한내용은답안으로인정안함. 답에는반드시네모를쳐서확실히표시할것. 답안지에학과, 학번, 이름외에본인의암호를기입하면성적공고시학번대신암호를사용할것임. 1. 맞으면 true, 틀리면 flse를적으시오. (20점) 1) OpenGL에서다각형의 winding order는반시계방향이다. T 2) 프레임버퍼는벡터그래픽시스템에서사용한다. F 3) 볼록한 (conve) 객체는객체내에임의의두점을연결하는선분위에놓인임의의점 이객체내에있다. T 4) 아핀변환 (Affine Trnsformtion) 은선형성 (Colinerit) 과거리의비례 (Rtio of distnce) 를유지한다. T 5) 벡터는공간내에고정된위치를갖지않는다. T 6) 정방행렬 (Squre Mtri) 는반드시역행렬 (Inverse Mtri) 를갖는다. F 7) glutpostredispl() 함수는윈도우가새로그려져야할필요가있는경우를표시할때 사용된다. T 8) 샘플모드 (Request mode) 입력장치에서는장치가트리거될때까지측정치 (Mesure) 가프로그램으로반환되지않는다. F 9) glutbitmpchrcter() 함수를사용한문자는 GL의변환 ( 즉, 위치, 크기, 방향 ) 에의해 영향을받는다. F 10) 사원수 (Quternion) 의곱은교환법칙이성립된다. F 2. 다음문제에답하시오. (30점) 1) 아래의자동차그림위에 OPENGL의좌표계 (,, 축 ) 과회전 (rottion) 방향을표시하시오. 1/12
2/12 2) 아래의빈칸을채우시오. 점 p 가평면 (n, d) 에서만약 n p d < 0 이라면 p 는평면 안쪽 에있다. 점 p 가평면 (n, d) 에서만약 n p d 0 이라면 p 는평면 위 에있다. 점 p 가평면 (n, d) 에서만약 n p d > 0 이라면 p 는평면 바깥쪽 에있다. 3) glutdisplfunc(void (func*)(void)) 함수를설명하시오. glutdisplfunc(displ) 의 void displ() 답신함수는 GLUT 에서윈도우가새로그리기 (window refresh) 를요할때불려진다. 모든 GLUT 프로그램에서반드시불리는함수이다. - 윈도우가처음으로열렸을때 - 윈도우가재구성이필요할때 - 윈도우가 epose 됐을때 - 사용자프로그램에서디스플레이가바뀌길원할때 4) OpenGL 에서기본카메라 (Defult Cmer) 의위치와관측공간을간단히설명하고그림으로표시하라. OpenGL 에서는카메라가물체의공간 (drwing coordintes) 의원점 (origin) 에위치하며 - 방향으로향하고있다. 관측공간을지정하지않는다면, 디폴트로 222 입방체의 viewing volume 을사용한다. 5) 다음 3 차원회전행렬공식에서 Smmetric Mtri 를유도하라. θ θ θ sin ) cos (1 cos Skew Smmetric R I ( ) [ ] 2 2 2 2 2 2 ' ' ' ) ( Smmetric Smmetric
6) 아래의그림을참고하여 OPENGL Geometr Primitives 예제에서기하학적객체의모드로 GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP를그렸을때차이점을설명하라. glbegin(gl_lines); for (int i0; i<5; i) glverte2fv(v[i]); glbegin(gl_line_strip); for (int i0; i<5; i) glverte2fv(v[i]); glbegin(gl_line_loop); for (int i0; i<5; i) glverte2fv(v[i]); 3. 다음은실습숙제1에서 OPENGL Geometr를사용하여우주선 (Spceship) 을그리는함수를보여주고있다. 우주선의색을표시하여출력결과를그려라. (10점) // drw the ship where (c, c) is the center position of the spceship void Ship::drw() glbegin(gl_polygon); // bse glcolor3f(0.0, 0.0, 1.0); glverte2f(c, c 20); glverte2f(c - 4, c 15); glverte2f(c - 4, c 5); glverte2f(c 4, c 5); glverte2f(c 4, c 15); 3/12
glbegin(gl_polygon); // bse left wing glcolor3f(0.0, 1.0, 0.0); glverte2f(c - 4, c 5); glverte2f(c - 4, c 15); glverte2f(c - 13, c 5); glbegin(gl_polygon); // bse right wing glcolor3f(0.0, 1.0, 0.0); glverte2f(c 4, c 5); glverte2f(c 13, c 5); glverte2f(c 4, c 15); glbegin(gl_polygon); // left wing glcolor3f(1.0, 1.0, 1.0); glverte2f(c - 4, c 5); glverte2f(c - 4, c 15); glverte2f(c - 10, c 2); glbegin(gl_polygon); // right wing glcolor3f(1.0, 1.0, 1.0); glverte2f(c 4, c 5); glverte2f(c 10, c 2); glverte2f(c 4, c 15); glbegin(gl_polygon); // big fire glcolor3f(1.0, 1.0, 0.0); glverte2f(c, c); glverte2f(c 4, c 5); glverte2f(c - 4, c 5); glbegin(gl_polygon); // smll fire glcolor3f(1.0, 0.0, 0.0); glverte2f(c, c 2); glverte2f(c 2, c 5); glverte2f(c - 2, c 5); 4/12
4. 다음은그래픽스기하파이프라인 (Geometric Pipeline) 구조를보여주고있다. 각각의단계를간단히설명하라. (10점) Verte Processor ( 정점처리 ): 각정점 (Verte) 의좌표계변환을수행하고 ( 예 : model trnsformtion, viewing trnsformtion 등 ) 각정점의색을계산처리 ( 예 : 광원의특성과객체표면의물리적인특성을고려하여색을계산 ) 한다. Clipper nd Primitive Assembler ( 클리핑과기본요소로조립 ): 카메라가찍을수있는시야각영역, 즉클리핑볼륨 (Clipping Volume) 을두어, 이것의밖에투영되는객체는영상으로나타나지않고클리핑되도록하고, 클리핑볼륨에걸친객체들은영상에부분적으로보이도록한다. 클리핑을위하여정점의집합을선분과다각형과같은기본요소로조립한다. 이단계의출력은투영변환 (Projection) 되어영상으로표시되는기본요소의집합이다. Rsterier ( 래스터화 ): 클리핑기로부터나온기본요소의집합은정점으로표현되어있는데이를프레임버퍼의픽셀로변환되는과정이다. 이단계의출력은각기본요소단편 (frgment) 의집합이다. 단편은색과위치정보를전달하는잠정적인픽셀값이다. Frgment Processor ( 단편처리 ): 단편처리기에서는단편을받아들여프레임버퍼안에있는픽셀을갱신한다. 단편처리기에서깊이버퍼를사용한은면제거와택스쳐맵핑 ( 혹은범프매핑 ), 반투명효과를주는알파블렌딩등이수행된다. 5/12
5. 다음은디스플레이리스트 (Displ List) 로구성한 3차원객체와지적 (Picking) 이사용된 OPENGL 프로그램일부를보여주고있다. 디스플레이리스트를사용하여구성한 3차원객체의출력결과 ( 즉, drwobject) 와전체적인장면의출력결과를그림으로나타내라 (10점). 그리고, 각함수에작동원리를주석으로달아라 (10점). // 디스플레이리스트를사용하여눈사람객체를구성 void initdl() GLflot white[] 1, 1, 1, 1; GLflot blck[] 0, 0, 0, 1; GLflot ornge[] 1.0f, 0.5f, 0.5f; glnewlist(1, GL_COMPILE); glmterilfv(gl_front, GL_AMBIENT_AND_DIFFUSE, white); // bse bod glpushmtri(); gltrnsltef(0.0f, 1.0f, 0.0f); glusphere(qudric, 1.5f, 20, 20); // upper bod glpushmtri(); gltrnsltef(0.0f, 2.0f, 0.0f); glusphere(qudric, 1.0f, 20, 20); glpopmtri(); glpopmtri(); glpopmtri(); // hed glpushmtri(); gltrnsltef(0.0f, 1.3f, 0.0f); glusphere(qudric, 0.6f, 20, 20); // ees glpushmtri(); glmterilfv(gl_front, GL_AMBIENT_AND_DIFFUSE, blck); gltrnsltef(0.2f, 0.1f, 0.6f); glusphere(qudric, 0.1f, 10, 10); glpopmtri(); glpushmtri(); gltrnsltef(-0.2f, 0.1f, 0.6f); glusphere(qudric, 0.1f, 10, 10); glpopmtri(); // nose glpushmtri(); glmterilfv(gl_front, GL_AMBIENT_AND_DIFFUSE, ornge); gltrnsltef(0.0f, -0.1f, 0.6f); glrottef(0.0f,1.0f, 0.0f, 0.0f); gluclinder(qudric, 0.1f, 0.0, 0.35, 10, 2); glpopmtri(); 6/12
glendlist(); // _ 디스플레이리스트를사용하여객체를그림 void drwobject(flot, flot, flot ) glpushmtri(); gltrnsltef(,, ); glclllist(1); glpopmtri(); // 5 개의객체를일반렌더링모드로그리거나, SELECT 모드에선네임스택에 ID 를지정 void drwobjects(glenum mode) if (mode GL_SELECT) gllodnme(1); drwobject(0, -3, -3); if (mode GL_SELECT) gllodnme(2); drwobject(-3, -3, 3); if (mode GL_SELECT) gllodnme(3); drwobject(3, -3, 0); if (mode GL_SELECT) gllodnme(4); drwobject(-6, -3, 3); if (mode GL_SELECT) gllodnme(5); drwobject(6, -3, -3); // 지면을그림 void drwground() glmterilfv(gl_front, GL_AMBIENT_AND_DIFFUSE, drkbrown); glbegin(gl_quads); for(int i -10;i < 10; i) glnorml3f(0, 1, 0); glverte3f(i*5, -3, -50); glverte3f(i*5, -3, 50); glverte3f(50, -3, i*5); glverte3f(-50, -3, i*5); // _OPENGL 초기화함수에서 displ list를초기화 void init(void) glclercolor(0.0f, 0.0f, 0.0f, 0.0f); // Cler The Bckground Color To Blue glclerdepth(1.0); // Enbles Clering Of The Depth Buffer gldepthfunc(gl_less); // The Tpe Of Depth Test To Do glenble(gl_depth_test); // Enbles Depth Testing glshdemodel(gl_smooth); // Enbles Smooth Color Shding // lighting GLflot lightpos[4] -1, 1, 1, 0; 7/12
gllightfv(gl_light0, GL_POSITION, lightpos); gllightfv(gl_light0, GL_DIFFUSE, white); glenble(gl_lighting); glenble(gl_light0); // qudric qudric glunewqudric(); gluqudricnormls(qudric, GLU_SMOOTH); gluqudricdrwstle(qudric, GLU_FILL); for (int i 0; i < 5; i) initdl(); // _ 지면과일반렌더링모드에서객체를그림 void displ() glcler(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glmtrimode(gl_projection); gllodidentit(); gluperspective(60, 1, 0.1, 1000); glmtrimode(gl_modelview); // 중간생략.. drwground(); drwobjects(gl_render); glutswpbuffers(); // _ 다수의 hits 가존재할시가까운것으로선택 int processhits (GLint hits, GLuint buffer[]) int i, j, choose, depth; // if there is more thn 0 hits if (hits > 0) printf ("hits %d\n", hits); choose buffer[3]; depth buffer[1]; // mke the selection the first object // store how fr w it is for (i 1; i < hits; i) // for ll detected hits // if this object is closer to us thn the one we selected if (buffer[i*41] < GLuint(depth)) choose buffer[i*43]; // select the closer object depth buffer[i*41]; // store how fr w it is return choose; return -1; 8/12
// GL_SELECT 모드로전환하고, 마우스위치의영역과객체를렌더링한후 _ 다시 GL_RENDER 모드로전환하면다수의 hits가넘겨져오고, _ processhits 함수를호출하여어느것이선택되었는지알아냄 void pick(int, int ) GLuint selectbuf[512]; GLint viewport[4]; GLint hits; int id; glselectbuffer(512, selectbuf); glrendermode(gl_select); glinitnmes(); glpushnme(0); // selectbuf is where to store the hits // GL_SELCT mode // cler nme stck // fill the stck with one element // modif the viewing volume, restricting selection re round the cursor glmtrimode(gl_projection); // select the projection mtri glpushmtri(); // push the projection mtri gllodidentit(); glgetintegerv(gl_viewport, viewport); glupickmtri((gldouble), (GLdouble)(viewport[3]-), 1, 1, viewport); gluperspective(60, (flot)viewport[2]/(flot)viewport[3], 0.1, 1000); glmtrimode(gl_modelview); drwobjects(gl_select); // drw object onto the screen // i.e., drw onl the nmes in the stck glmtrimode(gl_projection); // select the projection mtri glpopmtri(); // pop the projection mtri glmtrimode(gl_modelview); // select the modelview mtri glflush(); // swith to render mode, get hit info hits glrendermode(gl_render); id processhits(hits, selectbuf); printf ("You picked object %d\n", id); // 왼쪽마우스버튼이눌리면, pick 연산이호출 void mouse(int button,int stte,int,int ) prevx ; prevy ; switch(button) cse GLUT_LEFT_BUTTON: mbuttons[0] ((GLUT_DOWNstte)?1:0); if (mbuttons[0]) pick(, ); brek; cse GLUT_MIDDLE_BUTTON: mbuttons[1] ((GLUT_DOWNstte)?1:0); brek; cse GLUT_RIGHT_BUTTON: mbuttons[2] ((GLUT_DOWNstte)?1:0); brek; defult: 9/12
brek; glutpostredispl(); int min(int rgc, chr** rgv) glutinit(&rgc, rgv); glutinitdisplmode(glut_double GLUT_RGB GLUT_DEPTH); glutinitwindowsie(600, 600); glutinitwindowposition(0,0); glutcretewindow(rgv[0]); glutreshpefunc(reshpe); glutdisplfunc(displ); glutkebordfunc(kebord); glutspecilfunc(specilke); glutmousefunc(mouse); glutmotionfunc(motion); init(); glutminloop(); return 0; 10/12
6. 다음은광선 (R) 이평면 (Plne) 과교차하는공식을표현한간단한코드이다. 빈칸에계산한값을적으시오. (10점) clss plne public: flot, b, c, d; // constructor.. plne(flot _, flot b_, flot c_, flot d_); // sttic utilit methods (plne p:, b, c, d & vector3 v:,, ) sttic flot dotnorml(const plne & p, const vector3 & v); // * b* c* d*0 sttic flot dotcoord(const plne & p, const vector3 & v); // * b* c* d*1 ; // 중간생략... tpedef struct _RAY vector3 p0; vector3 u; RAY; // 시작점 // 방향 bool RPlneIntersection(plne p, RAY line, vector3& out) flot denom plne::dotnorml(p, line.u); if (denom 0) return flse; flot t -plne::dotcoord(p, line.p0)/denom; 11/12
if (t < 0) return flse; out line.p0 t*(line.u); // return vector return true; int min(int rgc, chr *rgv[]) plne plne0(1, 0, 0, 1); RAY r1, r2, r3; r1.p vector3(1, 0, 0); r1.u vector3(-1, -1, 0); r2.p vector3(0, 0, -2); r2.u vector3(1, 1, 1); r3.p vector3(1, 1, 0); r3.u vector3(1, 1, 1); vector3 out1, out2, out3; if (RPlneIntersection(plne0, r1, out1)) cout << "out1 " << out1 << endl; // out1 (-1, -2, 0) if (RPlneIntersection(plne0, r2, out2)) cout << "out2 " << out2 << endl; // nothing if (RPlneIntersection(plne0, r3, out3)) cout << "out3 " << out3 << endl; // nothing return 0; 12/12