CS 312: Computer Graphics -- Assignment 2

Procedural Landscape Generation

Due October 8, 2010 by 11:59pm



For this assignment, you will be using OpenGL to create a simple interactive view of a procedurally modeled island. There is a demonstration of a procedurally generated island as the application ~eeaton/public/cs312/assn2/demoIsland and starting code for the assignment in ~eeaton/public/cs312/assn2/.  You should begin with the provided code (copy everything from the directory), modifying it as necessary to create your island.  The island landscape should be rendered as triangles in a height field; each vertex having a unique x,y, with z provided by the fractal function. Compute everything you need to render once, when you generate the island. During your rendering loop, you should only be responding to user interaction and rendering using pre-computed data.

As a reminder, to construct a fractal mountain, you start with a triangle or set of triangles. At each step, you split each existing triangle into four new triangles. This is shown in the figure below with the new vertices marked with green dots. A simple splitting places the new vertices at the midpoints of the edges (as shown on the left of each pair in the figure), you will then perturb these new vertex locations vertically by some random amount (as shown on the right in each pair in the figure).  At each step, reduce the scale of your random perturbation by 1/2.  This sequence gives the characteristic fractal self-similarity: at half the scale, you have half the noise amplitude. Sometimes when modeling natural processes (as we are here), this called 1/f noise because the noise amplitude is proportional to 1/f for noise frequency f (controlled in this case by the geometric splitting).

Intersect your generated landscape with a blue rectangle to simulate the ocean.  The base triangles of your island should be below sea level. The shape of the shoreline will be determined by the contour where the sea polygon intersects the island. To make sure that the edges of your island don't pop up above the level of the sea; you should clamp all edge vertices to make sure they don't protrude above sea level. In this diagram, the points marked with black dots can be allowed to move, but not above the level of the sea.  The figure on the right shows a screenshow from the demoIsland application.


      An example procedurally generated island

The landscape should be lit by one OpenGL distant light (simulating the sun or moon), and one ambient light (simulating bounce light and atmospheric scattering). For the lighting to work, you will need to compute surface normals at each vertex of your model. Compute these when you initially compute the landscape. The vertex normal should be the average of the normals for each face touching the vertex. Each face normal can be computed using the cross product of two of the edges on that face. Be careful to make sure your normals point up from the island (not into it).

Your program should take in the seed for a random number generator as an optional command line argument.  You should use this random number generator to randomize the island, once when the program is first called and once whenever the space bar is pressed as described below.

For user interaction, your program should support rotation exactly as shown in the sample program. To match rotations to mouse motion on the screen, it adds a rotation around an axis perpendicular to the mouse motion in screen space, before the current transform. You should also respond to several key presses. The demo program does not include support for the key presses.  When the space bar is pressed, you should generate a new random island. Initially, your island should begin with 8 triangles (2nd and 3rd columns in the diagram above), which is the minimum necessary to make something resembling an island.  When '+' or '-' are pressed, you should increase / decrease the number of triangles by a factor of two.  When any of '1' to '5' are pressed, you should select a set of pre-chosen values for the random seed, +/- scale, and view that you think look particularly nice.

As always, there will be points for creativity, effort and realism.


Strategy

There are several ways you could program the procedural island. Those details are up to you. I do suggest planning your development with lots of intermediate milestones with visual results. Also, rendering itself can be a great way to debug visually.

Using GLUT

Unfortunately, the only way to pass information between GLUT callback functions (the ones passed to GLUT through the glut*Func() calls) is by using global variables.

If you choose to code in C++, each of the GLUT callback functions must be a top-level function (not a class member function) declared extern "C". For example,

// declare
extern "C" void draw();

// define
extern "C" void draw() {
// C++ code
}


What to turn in

Submit your C or C++ program, all source code, the Makefile, and any other files necessary to run your project.  I must be able to type make on the CS systems and have it produce an executable for grading.  Name your executable "assn2".

In your comments, include information about the computer platform (hardware and OS) you used to develop your program, and be sure to include additional comments as needed to describe your code.  A good rule of thumb is that someone should be able to remove all code from the file and recreate a rough semblance of the result from your comments.

If you developed on somewhere other than the cs systems, be certain that your program runs correctly on the cs systems where it will be graded.  Leave time for this step!

Place all submitted files into a directory named LastnameFirstname-Assn2. For example, my directory would be EatonEric-Assn2. Then create a tar archive of that directory, such that the tar file expands to the directory (not a bunch of files). Copy that tar archive into ~eeaton/submit/cs312/username/ (where "username" is your cs system username) to complete the submission.


Extra Credit Opportunities

The following are some ideas for extra credit for this project, but you may also explore others of your own choosing.  The maximum amount of extra-credit is noted next to each item.  Completing the extra credit will not be accepted in lieu of completing the main assignment.

Be sure to include a README file in your submission describing your extra credit additions and how to use them.

  1. (up to +4%)  Color the island based on the elevation of each vertex.  For example, create snow-capped peaks and sandy beaches on top of a lush green island.  Randomize the colors a bit between adjacent polygons (e.g. different shades of green and brown) or add textures for more realism.  Make the terrain dependent on the direction of the normal (e.g., beaches in flat areas, make sharp rocky cliffs, etc.).
  2. (up to +4%)  Enable the creation of more complex islands by randomizing the starting center point of the subdivision (i.e., using non-even triangles) and/or creating multiple initial peaks.  You may also find it useful to modify the noise amplitude denominator (e.g., try 1/3 instead of 1/2, or use different amplitudes in different locations to vary the roughness of the terrain in different locations).
  3. (up to +8%)  Zoom in and out on the island based on the mouse forward/backward motion whenever the right mouse button is pressed.  Be careful not to allow zooming through the island!  Pressing 'n' should return to the normal view.  Automatically increase the triangulation as you zoom in for even more realism.


Based on an assignment by Marc Olano.