Warming up Problem --------------------- Write a C program using GLUT and OpenGL calls to create a grid whose squares change color when clicked on. Specifically, you should divide the window into a grid of 50 squares horizontally by 50 squares vertically and draw lines on the screen to show the grid pattern. Each grid square should start out black, and change to a new color whenever the user clicks a mouse button within it. At a minimum, your program should create a window of at least 299x299 pixels, and use grid lines 1 pixel wide. The grid squares in this case will be 5x5 pixels. The odd window size arises because we do not want any grid lines on the edge of the window, so we have one less grid line in the horizontal and vertical direction than we have grid squares. you will need to keep track of the color of each square (possibly in a double dimension array) so the screen can be redrawn correctly by your GLUT display callback. The follow GLUT functions will be of use: glutPostRedisplay: used to force GLUT to call your display function. glutMouseFunc: used to create a mouse button press callback. Implement the following variations of the program A) watch mouse motion (see glutMotionFunc) If the user clicks a mouse button and moves the mouse while holding the mouse button down, any square the mouse passes over should change color. You must ensure that a square only changes color once as the mouse moves over it, until the mouse has left the square and returned to it (ie. moving the mouse back and forth between two squares will cause both of their colors to change each time the mouse enters either square, but moving the mouse within a single square does not cause the color to change). B) animate color changes using the GLUT idle function (see glutIdleFunc). When you click on a square, have the new color slowly fade to black over the course of 1-2 seconds. Note that mouse clicks (and mouse motion, if option B is implemented) should work while your squares are fading. Problem No 1: ------------- you will write a C program using GLUT and OpenGL. In this assignment, you will divide the window into a set of 50x50 virtual pixels (representing a small raster display) and create an internal array representing a 24 bit framebuffer (50x50x3 bytes). Into this small display, you will render an animated radar display consisting of a line that has one end anchored at the center of display and the second end tracing a circle of radius 24 units from the center. Your program should take one command line argument, a real number saying how long the line should take to do one loop around the screen. You will render the lines by implementing the midpoint algorithm for rasterizing lines, and using OpenGL to render polygons representing the pixels. A) anti-aliasing Use the simple form of anti-aliasing we discussed in class to anti-alias your lines. Include in your README file that you turn in a discussion of the visual differences you see (where are they most obvious, for example). B) fading Have the lines fade from the frame buffer gradually. Design an approach, based on a logarithmic model of the decay of the pixels, and implement it in conjunction with anti-aliasing of the lines so that the pixels fade out after the line sweeps by. Problem No 2: ------------- In this assignment, you will use the OpenGL polygon commands to draw polygons, but you will write a polygon clipping algorithm to clip them before drawing them. You will be given a description of a polygonal scene on standard input, as well as the starting position, size and velocity of a moving viewport in your window. Each frame you should clip the polygonal scene to the viewport and render only the portion of the polygonal scene visible through the viewport. The viewport will move each frame, based on its velocity. When it reaches the edge of the window, it should bounce off the edge and continue moving. Your program should create a window of 400x400 pixels. You should use an ortho2D projection to map the window to the range x=[-10..10] and y=[-10..10]. The scene description on standard input will consist of the following data. Any line that starts with a pound sign (#) should be treated as a comment and ignored. # the number of polygons (integer) NP # for each polygon we have # the color # number of vertices # vertex specifications .... # The polygon should draw line from each # vertex to the next, and end by drawing a line from the last # to the first specified (to close the polygon). This means # a square will have 4 vertices specified, for example, not # five (integer) # # the color is three floats specifying the R G and B components # of the color. Each value should be in the range 0..1 R G B NV # for each vertex we have 2 floating point numbers x y # the viewport lower left and upper right corners. These points # are specified in the OpenGL coordinates (ie. from -10 to 10 in # x and y directions, based on the above ortho2D xform) # all four are floating point Vx1 Vy1 Vx1 Vy1 # the viewport velocity, specified as floating point # delta x and delta y dx dy Your program should also take one command line argument "-debug". When specified, the program waits for a keystroke before advancing the viewport (ie. the viewport moves an increment as specified by its velocity each time the user presses a key on the keyboard). In addition, when it debug mode, after rendering the clipped polygons, you should render the entire scene (inside and outside the viewport) using white lines (not filled polygons) so that you (and the TA) can see if the polygons are being clipped correctly. Finally, in debug mode you should draw the viewport with medium gray lines before you render anything else (so that the viewport does not hide any graphics). When you are not in debug mode, do not render the viewport. Your polygon clipping routine should remove the extra edges discussed in class so that when a polygon is clipped into multiple separate components, they actually appear to be separate and not to be connected by a line along the viewport edge. Have your program take the initial viewport specification and create 3 viewports with it. They should all start out together, but have initial velocities of (dx, dy), (-dx, dy), and (dx, -dy). Each viewport should correspond to a primary color (red, green and blue). The scene should be clipped to each viewport and rendered separately, and each viewport should only render into the red, green or blue part of the framebuffer. Use the glColorMask function to accomplish this: set the color mask so only one of red, green or blue will be rendered, and then draw the objects with their normal color. This way, when the viewports overlap, the colors should combine. If you simply render the red, green or blue component without using glColorMask, the color of the viewport you draw last will be used (which is incorrect). Problem No 3: ------------- In this assignment, you will use the OpenGL polygon commands to draw polygons, GLUT glutStrokeCharacter to render text, as well as using OpenGL matrix stack manipulation and display list routines. You will implement your own matrix routines to support your lighting computations. Your program will render a cube with information on each of its six faces. Most of this information is to be obtained by running external programs by forking child processes and extracting the needed items from the program output. This information should be: - the user id of the person running the program, and the name of the mail host - the number of new (unread) email messages - a little mailbox with a flag showing if there is new mail or not - the text "CS 4390" - the text "Assignment #4" - the text "Winter '99" The user should be able to click a mouse button and drag in the window to spin the cube. Your program should create a window of 150x150 pixels. You should use a perspective projection (glPersp) that causes your cube to mostly fill the window. Use a relatively small field of view (in the 15 to 30 degree range) so that the perspective effect is not too exagerated. You must define your cube hierarchically, where each graphics item is defined in it's own local coordinate system and use transformations to position the items in the correct location. At a minimum, you must define each cube face in it's own coordinate system (ie. each cube face should be drawn using the same set of coordinates, which must be the unit coordinates in the x/y plane from 0..1 in X and 0..1 in Y. Each face will then have a transform applied to it to move it into the correct position). The contents of each cube face must also be positioned in their own coordinate system (any convenient one will do) and transformed to fit on the cube face. You should create your transformation matrices by hand, using the book . DO NOT use the OpenGL transformation routines (glTranslate, glScale, etc). Rather, you should create your matrix and then use glMultMatrix to multiply your new matrix onto the matrix stack. As you traverse the hierarchy you have defined for your cube, you should use the OpenGL matrix manipulation routines (glPushMatrix, glPopMatrix) to save state so you do not have to reload old matrices as you travel up the hierarchy. (ie. push the matrix stack before using glMultMatrix, and pop it when you are finished) You must also do the lighting calculations yourself. Use 3 lights: - a small amount of ambient light - a slightly redish light up and to the left of the viewpoint - a slightly bluish light down and to the right of the viewpoint To handle the lighting calculations, as you traverse the hierarchy, you must keep track of the inverse transformations so that they can be applied to the lights to bring them into the local coordinate system of the objects. (To illuminate the text, it is ok to calculate one color value for the text, based on the normal of the plane it is being drawn in.) Your program takes two command line arguments, the number of seconds to pause before checking for mail each time, and the hostname of the machine on which you read your mail. Your program should then prompt the user for their password using the "getpass" function (so that it will not be displayed for anyone to see). Each of the cube faces is defined as follows: - the user id of the person running the program, and the name of the mail host This could be obtained by forking off the program "who" with the arguments "am" and "i". The first field in the string is the user id. It could also be obtained from the USER environment variable, if set. Center this string on the face of the polygon. - the number of new (unread) email messages Displayed as a single character in the middle of the face. - a little mailbox with a flag showing if there is new mail or not This can be as simple as you want (a cube with a flag beside it). You could also use a cylinder and cube that intersect to form a more realistic looking object. The flag can be as simple as a rectangle and a triangle. The mailbox should be in one coordinate system, and the flag in another coordinate system relative to it. The origin of the flags coordinate system should be the point at which the flag would rotate (this will make it easy to raise and lower the flag). Write the program "chkmail" taking one argument, the IMAP mailbox to check for mail. The format of the mailbox definition is in the man page, but is of the form "{mailmachinename}INBOX" for your default mailbox on a machine named mailmachinename. For me, since I read my mail on "gvu1.cc.gatech.edu", the string is "{gvu1.cc.gatech.edu}INBOX". After being executed, "chkmail" will ask for the userid on the machine, and then the password. You will have to write this information to the stdin of the process when it requests it. - the text "Graphics Course" - the text "Problem # 3" Each of these should be drawn on two lines (first word above second) and centered on their face. The two separate strings can be treated as one or two objects, at your convenience. One tricky aspect of this assignment is dealing with the potential slownes of "chkmail". Because it can take one or more seconds to complete, you must create a simple "state machine" inside your idleProc to deal with this. Possible states include: - waiting for next mail checking period - forked off "chkmail", sent user/passwd, waiting for output For spinning the cube, you should base the rotation of the cube on how far the mouse has moved in the X and Y directions (and use these two values to determine two rotations to apply to the cube). When the mouse is released, the cube should remain where the user left it (do not revert to the orientation prior to the beginning of the user spinning the cube). You should watch for two keyboard presses: - "m" changes the cube orientation to show the three "mail status" faces - "i" changes the cube orientation to show the three "information" faces Further in this problem , All follwowing animations should be integrated into the state machine in the idleProc, so that screen refresh and mouse movement do not interfer with them. a) Animation 1 When the user presses "m" or "i", the cube should spin smoothly to the new orientation, not just change suddenly. The movements should reflect the cartoon animation characteristics we discussed briefly in class (if you would like to try this, I can provide a copy of the paper). In particular, the movement should use the animation features of "anticipation", "slow-in,slow-out" and "followthrough". b) Animation 2 When new mail arrives, the cube should animate using a sequence of scale, translation or rotation transformations (as you see fit) to give the impression of "jiggling". Furthermore, the flag on the mailbox should swing up smoothly (over the course of a second or two) after the scaling has completed. Problem No 4: -------------- Write a program to read a given input file (whose name is passed as a command line parameter). The data in the file will describe a scene to be rendered. After reading the file, your program should then ray trace the image specified by the data. All programs should be able to generate images with shadows and diffuse reflection. Your program should be able to handle spheres and (planar) polygons, and point light sources as well as ambient lighting. Optional additions for extra credit (and nicer images) are described below. Sample data will be provided. Your program should work on the sample data, as well on other similar data. You should ray trace at least one image of moderate complexity at a resolution of 300 by 300 and save the image to a publicly accessible file (use snapshot to capture it, and then xv to convert it to GIF so that it doesn't use up so much disk space). Your program at a minimum should handle spheres, polygons, and light sources. For the most basic version of this program you may assume that your eyepoint is on the positive z-axis, looking back toward the origin along the negative z-axis. You may assume the window is a square centered at the origin, extending from (-1,-1) to (1,1). In this simplified viewing system, just use the z value of the "from" coordinates to set the eye position. For this program write a shell (ray.c, ray.h and trace.c) that reads the scene data and builds linked lists of objects and light sources. Ray.c reads the input file and builds the data structures, while trace.c contains the display callback with the raytracing stub (as usual, ray.h contains some common structures, etc, used by both files). You should use the ray.c and ray.h files in an unmodified form, and implement your raytracing code in trace.c. In the simplest form, you just change shoot_ray to trace a single ray through the scene and return the resulting color. Add the following options 1. specular highlights 2. transparency/refraction 3. reflection 4. correct viewing transformations based on the input data 5. ray-object intersection calculations for the other objects supported by the input file format (cylinders and cones, polygonal patches) 6. speedup options such as bounding volumes, octrees, adaptive raytracing, etc. In all cases, be sure that your program header describes the enhancement(s), as well as instructions on how to invoke them or show them off. Note: you should NOT worry about any of these until you have implemented the basic functionality of the program--the required parts!