중간고사 담당교수 : 단국대학교멀티미디어공학전공박경신 답은반드시답안지에기술할것. 공간이부족할경우반드시답안지몇쪽의뒤에있다고명기한후기술할것. 그외의경우의답안지뒤쪽이나연습지에기술한내용은답안으로인정안함. 답에는반드시네모를쳐서확실히표시할것. 답안지에학과, 학번, 이름외에본인의암호를기입하면성적공고시학번대신암호를사용할것임. 1. 맞으면 true, 틀리면 false를적으시오. (20점) 1) OpenGL에서다각형의 winding order는반시계방향이다. 2) 프레임버퍼는벡터그래픽시스템에서사용한다. 3) 볼록한 (convex) 객체는객체내에임의의두점을연결하는선분위에놓인임의의점 이객체내에있다. 4) 아핀변환 (Affine Transformation) 은선형성 (Colinearity) 과거리의비례 (Ratio of distance) 를유지한다. 5) 벡터는공간내에고정된위치를갖지않는다. 6) 정방행렬 (Square Matrix) 는반드시역행렬 (Inverse Matrix) 를갖는다. 7) glutpostredisplay() 함수는윈도우가새로그려져야할필요가있는경우를표시할때 사용된다. 8) 샘플모드 (Request mode) 입력장치에서는장치가트리거될때까지측정치 (Measure) 가프로그램으로반환되지않는다. 9) glutbitmapcharacter() 함수를사용한문자는 GL의변환 ( 즉, 위치, 크기, 방향 ) 에의해 영향을받는다. 10) 사원수 (Quaternion) 의곱은교환법칙이성립된다. 2. 다음문제에답하시오. (30점) 1) 아래의자동차그림위에 OPENGL의좌표계 (x, y, z축 ) 과회전 (rotation) 방향을표시하시오. 1/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) glutdisplayfunc(void (func*)(void)) 함수를설명하시오. 4) OpenGL에서기본카메라 (Default Camera) 의위치와관측공간을간단히설명하고그림으로표시하라. 5) 다음 3 차원회전행렬공식에서 Symmetric Matrix 를유도하라. R = Icosθ + Symmetric (1 cosθ ) + Skew sinθ 2/12
6) 아래의그림을참고하여 OPENGL Geometry Primitives 예제에서기하학적객체의모드로 GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP를그렸을때차이점을설명하라. glbegin(gl_lines); for (int i=0; i<5; i++) glvertex2fv(v[i]); glbegin(gl_line_strip); for (int i=0; i<5; i++) glvertex2fv(v[i]); glbegin(gl_line_loop); for (int i=0; i<5; i++) glvertex2fv(v[i]); 3. 다음은실습숙제1에서 OPENGL Geometry를사용하여우주선 (Spaceship) 을그리는함수를보여주고있다. 우주선의색을표시하여출력결과를그려라. (10점) // draw the ship where (cx, cy) is the center position of the spaceship void Ship::draw() glbegin(gl_polygon); // base glcolor3f(0.0, 0.0, 1.0); glvertex2f(cx, cy + 20); glvertex2f(cx - 4, cy + 15); glvertex2f(cx - 4, cy + 5); glvertex2f(cx + 4, cy + 5); glvertex2f(cx + 4, cy + 15); glbegin(gl_polygon); glcolor3f(0.0, 1.0, 0.0); // base left wing 3/12
glvertex2f(cx - 4, cy + 5); glvertex2f(cx - 4, cy + 15); glvertex2f(cx - 13, cy + 5); glbegin(gl_polygon); // base right wing glcolor3f(0.0, 1.0, 0.0); glvertex2f(cx + 4, cy + 5); glvertex2f(cx + 13, cy + 5); glvertex2f(cx + 4, cy + 15); glbegin(gl_polygon); // left wing glcolor3f(1.0, 1.0, 1.0); glvertex2f(cx - 4, cy + 5); glvertex2f(cx - 4, cy + 15); glvertex2f(cx - 10, cy + 2); glbegin(gl_polygon); // right wing glcolor3f(1.0, 1.0, 1.0); glvertex2f(cx + 4, cy + 5); glvertex2f(cx + 10, cy + 2); glvertex2f(cx + 4, cy + 15); glbegin(gl_polygon); // big fire glcolor3f(1.0, 1.0, 0.0); glvertex2f(cx, cy); glvertex2f(cx + 4, cy + 5); glvertex2f(cx - 4, cy + 5); glbegin(gl_polygon); // small fire glcolor3f(1.0, 0.0, 0.0); glvertex2f(cx, cy + 2); glvertex2f(cx + 2, cy + 5); glvertex2f(cx - 2, cy + 5); 4/12
4. 다음은그래픽스기하파이프라인 (Geometric Pipeline) 구조를보여주고있다. 각각의단계를간단히설명하라. (10점) Vertex Processor ( 정점처리 ): Clipper and Primitive Assembler ( 클리핑과기본요소로조립 ): Rasterizer ( 래스터화 ): Fragment Processor ( 단편처리 ): 5/12
5. 다음은디스플레이리스트 (Display List) 로구성한 3차원객체와지적 (Picking) 이사용된 OPENGL 프로그램일부를보여주고있다. 디스플레이리스트를사용하여구성한 3차원객체의출력결과 ( 즉, drawobject) 와전체적인장면의출력결과를그림으로나타내라 (10점). 그리고, 각함수에작동원리를주석으로달아라 (10점). void initdl() GLfloat white[] = 1, 1, 1, 1; GLfloat black[] = 0, 0, 0, 1; GLfloat orange[] = 1.0f, 0.5f, 0.5f; glnewlist(1, GL_COMPILE); glmaterialfv(gl_front, GL_AMBIENT_AND_DIFFUSE, white); // base body gltranslatef(0.0f, 1.0f, 0.0f); glusphere(quadric, 1.5f, 20, 20); // upper body gltranslatef(0.0f, 2.0f, 0.0f); glusphere(quadric, 1.0f, 20, 20); // head gltranslatef(0.0f, 1.3f, 0.0f); glusphere(quadric, 0.6f, 20, 20); // eyes glmaterialfv(gl_front, GL_AMBIENT_AND_DIFFUSE, black); gltranslatef(0.2f, 0.1f, 0.6f); glusphere(quadric, 0.1f, 10, 10); gltranslatef(-0.2f, 0.1f, 0.6f); glusphere(quadric, 0.1f, 10, 10); // nose glmaterialfv(gl_front, GL_AMBIENT_AND_DIFFUSE, orange); gltranslatef(0.0f, -0.1f, 0.6f); glrotatef(0.0f,1.0f, 0.0f, 0.0f); glucylinder(quadric, 0.1f, 0.0, 0.35, 10, 2); 6/12
glendlist(); void drawobject(float x, float y, float z) gltranslatef(x, y, z); glcalllist(1); void drawobjects(glenum mode) if (mode == GL_SELECT) glloadname(1); drawobject(0, -3, -3); if (mode == GL_SELECT) glloadname(2); drawobject(-3, -3, 3); if (mode == GL_SELECT) glloadname(3); drawobject(3, -3, 0); if (mode == GL_SELECT) glloadname(4); drawobject(-6, -3, 3); if (mode == GL_SELECT) glloadname(5); drawobject(6, -3, -3); // 바닥을그리는함수 void drawground() glmaterialfv(gl_front, GL_AMBIENT_AND_DIFFUSE, darkbrown); glbegin(gl_quads); for(int i = -10;i <= 10; ++i) glnormal3f(0, 1, 0); glvertex3f(i*5, -3, -50); glvertex3f(i*5, -3, 50); glvertex3f(50, -3, i*5); glvertex3f(-50, -3, i*5); void init(void) glclearcolor(0.0f, 0.0f, 0.0f, 0.0f); // Clear The Background Color To Blue glcleardepth(1.0); // Enables Clearing Of The Depth Buffer gldepthfunc(gl_less); // The Type Of Depth Test To Do glenable(gl_depth_test); // Enables Depth Testing glshademodel(gl_smooth); // Enables Smooth Color Shading // lighting GLfloat lightpos[4] = -1, 1, 1, 0; 7/12
gllightfv(gl_light0, GL_POSITION, lightpos); gllightfv(gl_light0, GL_DIFFUSE, white); glenable(gl_lighting); glenable(gl_light0); // quadric quadric = glunewquadric(); gluquadricnormals(quadric, GLU_SMOOTH); gluquadricdrawstyle(quadric, GLU_FILL); for (int i = 0; i < 5; i++) initdl(); void display() glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glmatrixmode(gl_projection); glloadidentity(); gluperspective(60, 1, 0.1, 1000); glmatrixmode(gl_modelview); // 중간생략.. drawground(); drawobjects(gl_render); glutswapbuffers(); int processhits (GLint hits, GLuint buffer[]) int i, j, choose, depth; // if there is more than 0 hits if (hits > 0) printf ("hits = %d\n", hits); choose = buffer[3]; depth = buffer[1]; // make the selection the first object // store how far away it is for (i = 1; i < hits; i++) // for all detected hits // if this object is closer to us than the one we selected if (buffer[i*4+1] < GLuint(depth)) choose = buffer[i*4+3]; // select the closer object depth = buffer[i*4+1]; // store how far away it is return choose; return -1; 8/12
void pick(int x, int y) GLuint selectbuf[512]; GLint viewport[4]; GLint hits; int id; glselectbuffer(512, selectbuf); glrendermode(gl_select); glinitnames(); glpushname(0); // selectbuf is where to store the hits // GL_SELCT mode // clear name stack // fill the stack with one element // modify the viewing volume, restricting selection area around the cursor glmatrixmode(gl_projection); // select the projection matrix // push the projection matrix glloadidentity(); glgetintegerv(gl_viewport, viewport); glupickmatrix((gldouble)x, (GLdouble)(viewport[3]-y), 1, 1, viewport); gluperspective(60, (float)viewport[2]/(float)viewport[3], 0.1, 1000); glmatrixmode(gl_modelview); // draw object onto the screen drawobjects(gl_select); // i.e., draw only the names in the stack glmatrixmode(gl_projection); // select the projection matrix // pop the projection matrix glmatrixmode(gl_modelview); // select the modelview matrix glflush(); // swith to render mode, get hit info hits = glrendermode(gl_render); id = processhits(hits, selectbuf); printf ("You picked object %d\n", id); void mouse(int button,int state,int x,int y) prevx = x; prevy = y; switch(button) case GLUT_LEFT_BUTTON: mbuttons[0] = ((GLUT_DOWN==state)?1:0); if (mbuttons[0]) pick(x, y); break; case GLUT_MIDDLE_BUTTON: mbuttons[1] = ((GLUT_DOWN==state)?1:0); break; case GLUT_RIGHT_BUTTON: mbuttons[2] = ((GLUT_DOWN==state)?1:0); break; default: break; 9/12
glutpostredisplay(); int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode(glut_double GLUT_RGB GLUT_DEPTH); glutinitwindowsize(600, 600); glutinitwindowposition(0,0); glutcreatewindow(argv[0]); glutreshapefunc(reshape); glutdisplayfunc(display); glutkeyboardfunc(keyboard); glutspecialfunc(specialkey); glutmousefunc(mouse); glutmotionfunc(motion); init(); glutmainloop(); return 0; 10/12
6. 다음은광선 (Ray) 이평면 (Plane) 과교차하는공식을표현한간단한코드이다. 빈칸에계산한값을적으시오. (10점) class plane public: float a, b, c, d; // constructor.. plane(float a_, float b_, float c_, float d_); // static utility methods (plane p: a, b, c, d & vector3 v: x, y, z) static float dotnormal(const plane & p, const vector3 & v); // a*x + b*y + c*z + d*0 static float dotcoord(const plane & p, const vector3 & v); // a*x + b*y + c*z + d*1 ; // 중간생략... typedef struct _RAY vector3 p0; vector3 u; RAY; // 시작점 // 방향 bool RayPlaneIntersection(plane p, RAY line, vector3& out) float denom = plane::dotnormal(p, line.u); if (denom == 0) return false; float t = -plane::dotcoord(p, line.p0)/denom; 11/12
if (t < 0) return false; out = line.p0 + t*(line.u); // return vector return true; int main(int argc, char *argv[]) plane plane0(1, 0, 0, 1); RAY ray1, ray2, ray3; ray1.p = vector3(1, 0, 0); ray1.u = vector3(-1, -1, 0); ray2.p = vector3(0, 0, -2); ray2.u = vector3(1, 1, 1); ray3.p = vector3(1, 1, 0); ray3.u = vector3(1, 1, 1); vector3 out1, out2, out3; if (RayPlaneIntersection(plane0, ray1, out1)) cout << "out1 = " << out1 << endl; // if (RayPlaneIntersection(plane0, ray2, out2)) cout << "out2 = " << out2 << endl; // if (RayPlaneIntersection(plane0, ray3, out3)) cout << "out3 = " << out3 << endl; // return 0; 12/12