Generating 3d Mountains
The goal of this project is to use OpenGL to render landscapes of some kind. We can render a mountain using a fractal algorithm. We are also able to navigate our landscape using mouse and keyboard input. In adition, we can generate an STL file version of the landscape and 3d print it.
Fractal Algorithm
The algorithm we used to generate our terrain is called the diamond-square algorithm. It consists of taking the average height of surrounding values and adding a random number to generate a new height. To understand in more detail what this algorithm does, this blog explains it. This website visualizes the result.
We used a 2d array of doubles initialized to 0, and ran the algorithm on it to generate a height map. To achieve a “mountain” like effect, we hardcoded the center value to be higher. This allowed all the other values to be calculated based off of it.
Below is the loop we run to generate the terrain.
//ds_steps determines how many levels deep the algorithm needs to go
for (int step = 0; step < ds_steps; step++){
// roughness factor is the bounds of the random number generator
// this roughness factor decreases every time step, so that details become
// sharper the deeper into the matrix we go
int loRough = roughness/(step +1.0);
//Executes the square step
square_step(matrix, grid_split, sideLength, loRough);
//make sure the heigh of the peak is maintained
matrix->rows[size/2][size/2] = 30;
//Executes the diamond step
diamond_step(matrix, grid_split, sideLength, loRough, max_index);
//change the increments for the next level
sideLength /= 2;
grid_split *= 2;
}
The diamond square algorithm isn’t a perfect terrain generating algorithm, but a recommended action is to run the algorithm twice, which we did, to achieve a more natural looking effect.
Visualizing in OpenGL
To visualize our mountain in OpenGL we used GLUT (OpenGL Utility Toolkit) as well as a wrapper library/tutorial for rendering heightmaps in GLUT provided by Lighthouse3D. The Lighthouse3D wrapper library helped us learn about calculating normals for a given heightmap – a necessary process to provide smooth lighting across a heightmap. Additionally the wrapper introduced us to OpenGL display lists which doubled the performance of our heightmap rendering by precompiling the rendering of our heightmap and its normals.
The final result of our OpenGL rendering looked as follows:
3D Printing
We were able to modify the code from https://github.com/anoved/libtrix to convert our height maps into an STL file format. The STL file format will allow us to 3D print our terrain maps. Some examples of visualizations of the STL files we generated are shown below.
STL files showing terrain generated by our make_mountain function:
Reflection
We achieved our MVP as well as a stretch goal. We were able to generate a mountain using a fractal algorithm, visualize it in OpenGL, and add key and mouse input. We were able to accomplish our stretch goal of generating a STL file and 3D printing some of these landscapes. We did not implement our other stretch goal of having a change in lighting to simulate the sun setting. Overall, we all go the opportunity to work on our learning goals (which were to learn C++, investigate fractal algorithms for the purpose of generating landscapes, and learn how to use OpenGL).