CS 414 Assignment #3 Name: Frank Chu Project name: Fractal Terrain Generator 1. Introduction My project is a fractal terrain generator. The program generates random landscapes using fractal arithmetics, and displays it using OpenGL. A user interface is provided for the user to interact with the program. Some controls are provided by the GLUI library [1]. NOTE: I downloaded GLUI v2.2 from its official website, and compiled it in the labs. I have provided the necessary files, and the program should compile without trouble on a Linux compatible machine. -- This is permitted by Professor van de Penne. Through the user interface the user can: (1) move the result around and view it from different angles (2) change various options to generate different looking terrain (3) display the result in different modes The program should run with the following commands: > make > ./fractal 2. User Interface 2a. Display When the program starts, a randomly generated terrain appears on the left panel, and various controls appear on the right panel. The landscape is displayed as a rectangular mesh. Coloring is based on the height of the vertex, and is as follows: Height: Low ------> High Color: Blue --> Green --> Brown --> White 2b. Camera control User can change the camera view with the mouse on the LEFT panel. Control is as follows: 1) Left mouse button -- Rotate the landscape left/right and up/down. Rotation is always relative to center of screen. 2) Right mouse button -- Move the landscape. Translation is done as if the pointer is a hand 'grabbing' the land around. 2) Middle mouse button, or Two buttons together -- Zoom in/out. 2c. Sealevel (Right panel) This controls the height of the sea-level in the map. User can change the sealevel with either the spinner or the 5 radio buttons. When the sea-level change, the map is re-colored to match the new sea-level. Since changing the spinner will re-color the map in real-time, this may be very laggy. Thus radio-buttons provide 5 convenient sea-level to change to instantly. -- Range for sea-level is [-1.5, 1.5]. -- Changing the sea-level does NOT generate a new map. 2d. Roughness (Right panel) This controls the roughness of the landscape. User can change the roughness with either the spinner or the 3 radio buttons. When roughness change, a new map is generated with the new roughness. This variable is described in more detail in future sections. Again, the spinner will re-generate a new map in real-time, so it is better to either type in a new value or use the radio buttons instead. -- Range for roughness is [0, 1] 2e. Number of division steps (Right panel) This controls the number of division step used in the generation of the new terrain. The more division step, the more detail the terrain is. However, each extra division step will multiply the size of the map by 4!!! -- Range for num divs is [0, 12] (use high number with caution, it may blow up your computer ;) 2f. Regenerate This button will regenerate a new terrain with the options selected above. 2g. Display options 1) Solid -- this is the default style 2) Wireframe -- a green wireframe object 3) Colored wireframe -- a wireframe object with color 2h: Extra display options 1) Light -- toggle lighting on/off 2) Leveling (for Solid object only) -- toggle leveling on/off Leveling will flatten all land below sea-level so that the landscape looks realistic. Toggling it off allows the user to view the depth of the sea. 3. Mathematics The generation of the terrain is done via a method called the Diamon-Square Algorithm. In the following paragraphs, NumDivs refer to the number of division steps, sealevel refers to the sea level, and roughness refers to the roughness variable. These three variables are all controllable via the control panel on the right, as described in Section 2. DIAMOND STEP 1) We first start with a square with all four vertices at heigh 0. Then at each division step (up to NumDivs), we take all squares and insert the mid-point of the square into the mesh. The height of the mid-point is calculated as: average( height of the 4 points ) + random_perturbation random_perturbation is initially in the range [-1, 1]. SQUARE STEP 2) Step (1) created various new 'diamonds', and for each diamon, we again find insert the mid-point of the diamond into the mesh. The heigh of the mid-point is also calculated as: average( height of the 4 points ) + random_perturbation random_perturbation is in the same range as in Step (1). 3) Decrease the range of the random perturbation. If the range is previously [-r, r], then: r' = 2^(-roughness) new range is [-r', r'] Repeat step (1) and (2) if step is less than NumDivs As we can see, the above 3 steps result in a 2^(NumDivs)+1 by 2^(NumDivs)+1 height matrix. This describes our new landscape. The roughness variable, as seen in step (3), controls the perturbation range at each subsequent step. A small value means the map will perturbate a lot even at higher division level; a large value means the map will perturbate less. This means a low value -> rough surface; and a high value -> smooth surface. The sealevel variable only affects the coloring of the landscape and not the generation of the height map. The Diamond-square algorithm was first due to Fournier. I read about it in various online websites, and I have made reference to them ([2],[3],[4]). 4. Classes I have handed in 3 classes and a main file: 1) fractal.hh, fractal.cpp -- The main FractalTerrain class that is responsible for generating the height matrix, color matrix, and normal matrix. All options are set using the set() function, and are get using one get() function. Most functions are self-explanatory. 2) mvec.hh, mvec.cpp -- A Math vector class. This is a 3D math vector class that supports addition, subtraction, cross product, scalar multiplication and division. This is mainly used for storing Colors and Normal vectors, both are 3D. 3) colorsetter.hh, colorsetter.cpp -- A Color setter class used by FractalTerrain class to determine different color. I made it into a class on its own for two purposes: 1) So that color is independent on the mathematics of FractalTerrain. This makes sense because colors is just a display option and FractalTerrain class shouldn't really know how to generate color. 2) So that the main function can generate different color-setters and pass it into FractalTerrain (this feature not used in my program) 4) main.cpp -- The main OpenGL rendering code, which uses GL, GLU, GLUT and GLUI for various controls. Some codes for GLUI controls are inspired by the example code given in the GLUI distribution. 5. Disclaimer ALL codes are written by myself, Frank Chu, on or before April 08, 2004, with the exception of the file "glui.h" and the library file "libglui.a". I have read through many websites that describe the algorithm in detail, and some websites do provide sample source code. I did not look into, imitate, or copy any part of those source code. 6. TO-DO There's a few features that I like to implement but didn't have time to do so. Here they are, in order of importance: 1) Allow read/write of terrain. The loading should be able to read in "seeded" terrain so that certain effects can be easily generated (such as rivers, valleys, high mountains, etc.) 2) Displaying text and statistics on screen. 3) Better camera controls 4) Implements fog effects 5) Can piece together multiple terrains to populate entire screen 6) Better lighting effects 7) Allow easy save/load of screenshots. 7. References [1] "GLUI v2.2 official homepage", http://gd.tuwien.ac.at/hci/glui/ [2] "Generating Random Fractal Terrain", http://www.gameprogrammer.com/fractal.html [3] "Fractal Landscapes", http://astronomy.swin.edu.au/~pbourke/terrain/frachill/ [4] "Fractal Mountain Climbing", http://www.mactech.com/articles/mactech/Vol.07/07.05/FractalMountains/