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.
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.
- Start with the provided code. It already includes much of
the functionality for mouse handling.
- Having
trouble getting the normals right? Turn off lighting and use the
normals to colorize your landscape (using glColor3f for each vertex),
remembering, of course, to re-scale to get colors from 0-1.
- If you need to do these a lot, you can add new key handlers to
change what you render.
- If you must print or use a debugger, it's much easier if you only
print for one or a few selected triangles.
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.
- (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.).
- (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).
- (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.