Terrain Engine
Authors
Overview
The Terrain Engine application was created by Travis Miller and Devin Snider of
Seraphim Studios as a project for the
fall semester 2002 CS 470 (Computer Graphics) class at WVU.
It is a terrain rendering engine that uses the ROAM (Real-time Optimally Adapting Meshes)
algorithm.
Download
TerrainEngine.zip
Dependencies
This project was written using Microsoft Visual Studio.NET. It uses
OpenGL for graphical rendering and DirectInput for mouse and keyboard
control. It has the following dependencies:
OpenGL
-
opengl32.lib
-
glu32.lib
-
glaux.lib
DirectInput
Windows
The project does not use GLUT to handle windows API calls. All Windows API calls are used natively for controlling window drawing and message handling. It does use DirectX for gathering input and requires version 8.1 to compile and run. If you are using the music or sound subsystems, you will need to include other DirectX libs as well. All other dependencies are included for the default Win32 application workspace.
Organization
This project was written such that it could be incorporated into a game system. Thus, the main class object is a game system. It encapsulates all the subsystems that would be needed in a game system inlcuding a graphics and input subsystem. Other subsystems exist but have not been included in this distribution. It only contains those systems and classes necessary for the rendering of terrain using ROAM.
There are four subdirectories below the default project directory:
-
include - all *.h files contained in the project
-
src - all *.cpp files contained in the project
-
resources - all data files needed to run the application
-
doc - all documentation for the project
Both of the src and include subdirectories have the following subdirectories:
-
game - all files pertaining to the game system
-
graphics - all files pertaining to the graphics subsystem
-
input - all files pertaining to the input subsystem
-
math - all files pertaining to mathmatical needs
-
util - all files pertaining to utility needs
The game system contains an application window, graphics system, and input system. Each is initialized before rendering begins. For each frame, windows messages are gathered and dispatched, keyboard and mouse input is polled and corresponding messages and actions are dispatched, and the graphics system renders the scene.
The graphics system uses the ROAM algorithm to draw terrain. It does so by loading point data from either a formatted text file containing x, y, and z values or by loading height values from a 8-bit grayscale heightmap in RAW format. For more information on loading terrain data, see the Commands section.
ROAM
The ROAM algorithm begins by creating two bintrees that will contain all of the triangles created and manipulated by ROAM. The two root triangles of the bintrees combine to encapsulate the entire terrain dataset. The vertices of the root triangles are determined by retrieving the boundaries of the dataset from the quadtree data structure. Each triangle contains pointers to a left neighbor, right neighbor, bottom neighbor, left child triangle, and right child triangle. After these pointers are initialized, the root triangles are pushed onto a first-in-first-out queue to ensure a breadth first traversal through the bintrees.
A test is then performed on each triangle to determine which triangles need to be split. The triangle must also be within the viewing area of the camera to be considered for a split. If the current triangle's midpoint is within a specified distance of the camera, then it is split. If the distance between the actual height data and the midpoint of the hypotenuse of the current triangle is beyond the specified variance, then the triangle is split. If the length of the triangle's hypotenuse is longer than the specified maximum size, then the triangle is split.
When the triangle is split, the ROAM algorithm attempts to create two child triangles. If the new triangles exceed the specified maximum number of allowable triangles, then the parent triangle is not split and the program exits the ROAM algorithm. If the length of the new triangle's hypotenuse is smaller than the specified minimum size, then the triangle isn't split. This is usually because there are no more real world coordinates to allow a split to happen. If the tests are passed, then two children triangles are created and added to the FIFO queue. The vertices, neighbors, and children of the new triangles are also initialized.
After the ROAM algorithm finishes all of its splits, it then traverses the two bintrees to place all of the triangle into an array to prepare for the rendering process. The rendering array contains the vertices of the triangle as Vertex objects in counter-clockwise order. The face normal of the triangle is then calculated and added to all of its vertex normals. If a normal already exists for one of the vertices, then this addition will create an average normal. The normals are then stored in a vertex object that is added to the rendering array. The rendering array is then processed and all vertices are rendered and normals are assigned to each vertex.
Execution
The application relies on some data files, namely textures, to reside in a subdirectory labelled 'resources'. The application itself uses a command processing system. When the application loads, a blank scene including the grid origin is rendered. Terrain points must be loaded using a 'load' command. There are other commands besides load, all of which are listed in the Commands section. Commands are entered by pressing the " ` " (tick or tilde) key. Commands are entered and then committed by pressing the enter key when finished. A list of key controls and commands can be seen by pressing the 'H' key.
Commands
-
distance <size> - Set the maximum distance from the camera to split triangles.
-
exit - Exits the application
-
load <filename><.txt | .raw> <size> - Loads the terrain points from the specified file. If a text file is used, then the data must be formatted as follows: <longitude><tab><lattitude><tab><height><CRLF>. A raw file is a height map. The size parameter is only used when loading a height map. NOTE: The height map must be a square with a size that is a power of 4, such as 16, 64, 256, and 1024.
-
maxcount <size> - Set the maximum allowable triangles.
-
maxtrisize <size> - Set the maximum size of all triangles.
-
mintrisize <size> - Set the minimum size of all triangles.
-
reverse - Reverses the up and down direction of the mouse.
-
speed <units/sec> - Sets the speed of the camera.
-
variance <size> - Set the maximum distance between the actual height data and the midpoint of the hypotenuse of the current triangle.
Controls
-
W - Move camera forward.
-
S - Move camera backward.
-
A - Move camera left.
-
D - Move camera right.
-
Z - Move camera up.
-
C - Move camera down.
-
+ - (On Keypad) Increase mouse sensitivity.
-
- - (On Keypad) Decrease mouse sensitivity.
-
SPACE - Centers the camera on the origin.
-
R - Switches rendering modes (Point, Wire, Filled).
-
M - Switches model shading modes (Flat, Smooth).
-
F - Toggles view frustrum culling.
-
H - Toggles display of the Help window.
-
L - Toggles lighting.
-
O - Toggles the display of the origin grid.
-
K - Toggles the display of the skybox.
-
T - Toggles texturing.
-
TAB - Toggles statistics display.
-
TICK - Toggles Command processing mode
-
ENTER - Commits a command.
-
ESC - Exits the application.
|