|
Write a C program using GLUT and OpenGL calls to render lines in visually interesting ways. Your program will compute the pixels that make up a line and save them, and then render these pixels as rectangles in a "virtual frame buffer".
By "virtual frame buffer" we mean that you should divide the window into a set of 20x20 pixel squares, each of which represents a "virtual pixel", and use these large larger, virtual pixels when computing the pixels that make up a line. For example, if we had a 200x200 window, it would contain 100 20x20 pixels, as shown in the window to the right. NOTE: You will NOT render the lines shown in this picture as you did in assignment #1, as the division into 20x20 pixels squares is conceptual. When you adjust the size of the window, the number of virtual pixels should change, not the size of them.
You should have a module (in a separate file) that contains a function to compute the pixels that make up a line. The parameters to this function should include the endpoints of the line and a pointer to a data structure in which the function will return the set of pixel locations to the caller.
To determine the endpoints of the line, you will allow the user to click with the mouse twice to set the two end points, as described below. Once they have specified the two end points, you should use these endpoints to compute the virtual pixels that make up the line and then render them in one or more "interesting" ways, as described below.
Finally, as with most of the assignments you will do for the remainder of the course, you should implement a "debug mode" (described below), which is toggled on and off when the user presses the "d" key. We suggest implementing this early on, to help you debug your code. |
|
Your program should consist of a set of files which should be commented with your name and a description of the contents of that file, as well as the usual comments throughout the file. Your submission MUST include a makefile, and MUST be mailed to the class account as a single, uuencoded tar file (as described on the web page). (Using MIME attachments to turn in files will make the grader crabby and result in much tougher program grading!)
The time the mail is received will be used to determine whether or not the program is late, so be sure to allow a couple of minutes for the mail system to transmit your file if you are working right up to the deadline.
IMPORTANT: If the TA has to edit your files, including your Makefile, you will lose points. |
|
Computing the pixels on the line
You must implement the optimized, integer-only midpoint algorithm discussed in class and in the text.
Rendering
For the basic assignment, you should compute the set of pixels for the line once, when the line is specified by the user, and these should be saved for use in your display function. You should render each pixel as a 20x20 rectangle that is offset a small random amount from the center of the 20x20 square corresponding to the virtual pixel. Each rectangle should also be a slightly different color. For the purposes of this assignment, you should do this as follows:
- Compute a small random offset in the x and y directions for each pixel, and the use a 2D translation transformation to move the pixel from its default position to the new, slightly offset position. You must use 2D translations, and use the coordinates of the non-offset virtual pixel as parameters to the glRect() command.
- Select a shade of green as the color for the line and then adjust the color randomly by a small amount for each pixel.
To make the image slightly more interesting, the random position and color changes should be recomputed every time the line is redrawn, and the screen should be redrawn frequently (using a glutTimerFunc to trigger a redraw at least 10 times per second). The goal is to make the pixels jiggle and flicker.
The range of offset values for the position and the color is up to you. You should chose values that give a result you like: something that moves far enough to be interesting, but not so far that you can no longer tell that the pixels form a line. Similarly, the color differences should be enough that they are obviously different, but not so much that they no longer appear related.
Selecting Endpoints
When the user clicks the left mouse button, you should begin a new line.
- The old line should be cleared from the screen
- The first endpoint (where they just clicked) should be drawn as a rectangle
- As they move the mouse, the virtual pixel under the mouse should be rendered as a hollow rectangle (ie. using lines) to show them where they would select a pixel if they clicked
- When they click, the new line's pixels should be computed, and rendered, as described above.
Debug Mode
When debug mode is on, at least the following additional information should appear on the display when a line is being drawn (you could add information if you find it helpful). All of this additional information should be drawn after the rectangles, so it appears on top of the rectangles.
- A small white circle should be drawn at the center of the virtual pixel, and a small red circle should be drawn at the center of the intended location of the pixel (based on the random offset), with a white line connecting them. The position of the red circle should be computed from the offset and used directly (not drawn using the 2D translation transformation).
- A line should be drawn from the center of the start pixel to the center of the end pixel of the line.
When a line is being selected (between the first and second mouse clicks) and debug mode is on, nothing extra needs to appear, but when the pixels for the line are being computed, the value of the decision variable, the increments between each pixel, and the resulting pixel coordinates should be printed to stdout.
Finally, in debug mode, the position of the pixels and the color are not changed continuously, but only changed when the user hits the space bar.
Basic Submission
At a minimum, your program should create a window of at least 500x500 pixels, allow the user to select the two endpoints, store the pixels for the line, and draw them repeatedly using the random offsets.
HINTS:
You might want to consider first implementing the naive, inefficient line algorithm (using floating point values) and getting the basic assignment working (rendering a line using large rectangles) before beginning to implement the midpoint algorithm so that bugs in one part will be isolated from the other.
Make sure you test your algorithm with lines in all eight octants! Also, make sure you algorithm handles verticle and horizontal lines correctly. |
|
Extra credit will be give for doing additional interesting things with the line renderings. You may implement one or both of the following options, each of which may be worth an additional 10% (depending on how well they are implemented).
All extra credit programs should be contained in separate source files, and your makefile should create additional executable programs for each. (ie. your submission must still contain an implementation of the basic program that perfoms as described above.)
- Better feedback, smooth motion. This option has two components.
- First, after the user clicks to specify the first endpoint, the entire "possible line" should drawn using hollow rectangles as they move the mouse around (instead of just the second endpoint under the cursor, as described above). This rectangular pixels on this line should be draw with no random offsets, unlike the final line.
- Instead of choosing purely random color and position offsets each time the window is redrawn, you should choose colors and positions that are only slightly different than the ones used the frame before (in effect, you are chosing very small random changes to the changes of the color and position values, instead of chosing the changes themselves each time!) The changes you chose should also tend to keep the pixel location and color near the original values; as the position or color is farther away from the original, the random changes should be more likely to move them back toward the original. Be careful, though: you still want to have a reasonable amount of motion and color change, so you can't simply move toward the original each time.
- Physically-based jiggles. This option treats the pixels as if they were physcial objects connected to the center of the virtal pixel by a spring of some sort. Thus, each pixel has a position, a velocity and an acceleration. Prior to redrawing the scene, a new force should be computed for each pixel, the velocity should be adjusted using that force, and the position should be adjusted using that velocity.
- The forces that act on each pixel are
- Acceleration. Apply the obvious force based on the rectangle's acceleration. You can assume that all the rectangles have a mass of 1 if you want, or you could assign a different mass to each rectangle.
- Friction. Chose a small coefficient of friction and use it to dampen the motion of the object.
- Springs. The spring attaching the pixel to the center of the original virtual pixel location exerts an force on the object propotional to the distance from the center. When the object is within a certain range of the center of the virtual pixel (say, 1/4 the size of the virtual pixel), the spring should not exert any force.
- The accelerations that act on each pixel are
- Randomness. Each frame a small random acceleration should be applied to each pixel to keep it moving (the accleration should usually be small, and occasionally be somewhat larger)
- User nudging. When the user clicks on the right mouse button, a much larger acceleration is applied to each pixel in the direction of the vector from the mouse position to the current location of the virtual pixel, and is proportional to the distance between the two (ie. the mouse click is like a explosion pushing the pixels away). The size of the acceleration should also be proportional to the length of time they hold the button down.
- When the line is initially drawn, each pixel is given a random position as in the basic assignment.
- You should chose your random accelerations, coefficients of friction and spring constants so that the objects stay in motion, but do not behave too eratically.
For this option, you must also change the debug mode. In addition to the information presented in debug mode for the basic assignment, in this option you should render the acceleration and velocity vectors for each pixel. These vectors should be rendered as lines starting at the red dot (the offset position of the rectangle representing the virtual pixel), and the line should point in the direction of the velocity or acceleration, and have a length proportional to the velocity or acceleration. You should add text near the tip of the vector displaying the numeric value of the velocity or acceleration. Do not worry if your text disappears off the side of the window when pixels are near the window edge.
|