CS3500 Computer Graphics Programming Assignment 3 Your own Modelling, Viewing, Projection, Viewport & Triangles Due: Midnight on March 26, 2009 ** Note: Start on the first part immediately. Some aspects of the scan conversion will only be covered in the next week in class. The objective of this project is to design your very own OpenGL-like Graphics API. The first part will develop the complete graphics pipeline starting from ORC to Screen coordinates through the steps of WC, VRC, and NC. This is the an easy part. The second part will involve clipping and scan conversion. Your system should have 4 different matrices to hold the current modelling, viewing, projection, and viewport transformations. To make matters easy, we will have different commands for each. Modelling commands: Modelling commands affect the objects that are described thereafter. 1. iglModRotate(angle, axisx, axisy, axisz) 2. iglModTranslate(tx, ty, tz) 3. iglModScale(sx, sy, sz) 4. iglModMatrix(float mat[16]) 5. iglModLoadIdentity() 6. iglModPushMatrix() 7. iglModPopMatrix() Each of the above right multiplies the current Modelling Matrix with a matrix corresponding to the transform. (Except, obviously, the last three!) The Modelling Matrix transforms ORC to WC. Viewing Commands: Viewing commands affect the camera position/parameters. 1. iglViewRotate(angle, axisx, axisy, axisz) 2. iglViewTranslate(tx, ty, tz) 3. iglLookAt(cx, cy, cz, lx, ly, lz, upx, upy, upz) 4. iglViewMatrix(float mat[16]) 5. iglViewLoadIdentity() The first 3 commands right multiply the current Viewing Matrix by a matrix corresponding to the command. The last one loads identity matrix. This corresponds to the VRC and WC being aligned. As with OpenGL, the camera is at the origin of VRC and looks into -Z direction. The Viewing Matrix transforms from WC to VRC. Projection Commands: Projection commands define the camera: its projection model and parameters. 1. iglProjOrtho(left, right, bottom, top, near, far) 2. iglProjFrustum(left, right, bottiom, top, near, far) 3. iglProjPerspective(horizontal_fov, aspect, near, far) These commands assign the Projection Matrix to that corresponding to the command. (i.e., no right multiplication!). The Ortho and Frustum commands can define asymmetric view volumes; the Perspective defines symmetric view volumes. The Projection Matrix transforms from VRC to NC. At the end, the normalized screen coordinates in the range [-1 .. 1] are obtained by dividing the first two components by the fourth one. Viewport Commands: Viewport commands map the normalized view window to the actual one in use. 1. iglViewport(llx, lly, width, height) The Viewport Matrix is defined by this command. (i.e, no right multiplication.) Suported Primitives The following primitives are supported by the system with the usual meanings. 1. iglBegin(IGL_POINTS) 2. iglBegin(IGL_LINE) 3. iglBegin(IGL_TRIANGLE) 4. iglEnd() 5. iglColour(r, g, b) 6. iglClear(r, g, b) 7. iglVertex(x, y, z) 8. iglPolygonMode(type) // could be IGL_FILL or IGL_LINES 9. iglShow() // Makes the scene so far appear iglClear clears the framebuffer to the given colour. iglColour defines the current colour. The first 3 commands starts defining the primitives. We only support triangles for this assignment. The Task: Modelling/Viewing/etc. The real task is to write the above functions. When the system starts up, initialize all matrices to identity matrices. The above commands thereafter modify the matrices. The real drawing takes place when iglVertex() commands are given for all supported primitives. When the required number of vertices for a primitive is available, they are transformed from ORC to the screen coordinates. You will setup the final image in an array within your program space. This array will use 32 bits per pixel with R-G-B in that order with one byte empty. Keep it compatible with the formats used by glDrawPixels(). For the last step, define an glOrtho(scrL, scrR, scrB, scrT, -1, 1) where scrL, scrR, scrB, scrT are the left, right, bottom, top planes in screen coords. For lines, transform the end vertices using the matrices to the screen points spt1 and spt2. Scan conversion and drawing: The second part of your Graphics API involves scan converting the primitives. This is a highly simplified API. You should fill an RGB array within your program memory that corresponds to the frame buffer during conversion. In the code for this assignment, you can only use one OpenGL call: The final glDrawPixels() to send your memory array to the window. For this assignment, we use only unfilled triangles, set using the iglPolygonMode() function. The other calls that affect the contents of the frame buffer are: iglColour() that sets the current colour and iglClear() that clears the frame buffer. The normalized screen coordinates of a point are obtained using Modelling, Viewing, and Projection matrices. Divide the first 2 components of the 4-vector by the 4th component to get the normalized (u, v) coordinates. Transform these by the Viewport matrix and round to the nearest integer to get the screen coordinates. Use these coordinates prior to clipping to the viewport. a) For points, directly fill the array location corresponding to the mapped screen coordinates with the current colour. b) For lines, use the Mid-Point Line algorithm to determine the points on it and colour the corresponding pixels. You will need 4 versions of the algorithm for the slope ranges of 0 to 45 degrees, 45 to 90, 90 to 135, and 135 to 180 from the X-axis. Given a line, order the end points to suit one of these cases (swapping the end points if necessary) and call the appropriate function for scan conversion. c) For unfilled triangles, draw each side using the Mid-Point Line algorithm. You need to clip the primitives to the viewport (the view-rectangle in screen coordinates) before doing the scan conversion. You need to implement the Cohen-Sutherland line clipping algorithm for the IGL_LINES and the Sutherland-Hodgeman polygon clipping algorithm for the polygons. (The triangle may get clipped to a general polygon, which then gets drawn as a number of lines representing the sides.) The scene is built up in the memory array corresponding to the frame buffer. When a iglShow() call is received, send the array to the graphics window using "glDrawPixels()". You can use SDL/GLUT commands to open and setup the window etc. The TAs will give you sample input files. They will use their own for the final evaluation. Compilation and Evaluation: Place all your igl-API functions in one file. Put your main and other associated functions in another file. They can use SDL/GLUT to open the window and to handle keyboard etc. They can only use iglXXX() commands for drawing. Demonstrate the program working using your own main file that does something "interesting". The TAs will also use their own main programs and will link your igl.o file to their main program. They will have a fairly complex drawing to be performed and your program should hold up!!