| IntroductionNOTE: For the HTML version of this | | | | properly. As you can see below, the code for |
| article with graphics and downloads please visit the | | | | generating and rendering the terrain is very short. |
| following link: have always been interested in | | | | To give an overview, the first thing that happens |
| computer graphics and their applications. Data | | | | is for the windows to get created, and then we |
| representation and visualization is one of the main | | | | initialize OpenGL, and read in the BMP file and |
| areas of HCI (Human Computer Interaction), and | | | | assign it to the 2D array we discussed above. |
| the better you make the interaction between a | | | | Then, the texture is applied to the surface of the |
| machine and a human, the more productivity will | | | | mesh, and the scene rendered to the |
| be generated by both the human and the | | | | screen.Without further ado, the following listing is |
| machine. I had some experience with OpenGL | | | | the the portion of the code which initializes and |
| during my undergraduate studies while attending | | | | generates the terrain:. |
| the California Polytechnic University. Unfortunately, | | | | . |
| I never got a chance to pursue the more | | | | . |
| advanced features of the OpenGL library, given | | | | // InitializeTerrain() |
| my time and work responsibilities.You can find | | | | // desc: initializes the heightfield terrain data |
| more about OpenGL at There are also a bunch of | | | | void InitializeTerrain() |
| good literature available on the topic of Computer | | | | {// loop through all of the heightfield points, |
| Graphics and OpenGL that you can refer for | | | | calculating// the coordinates for each pointfor (int |
| further advancements. Please check the | | | | z = 0; z < MAP_Z; z++){for (int x = 0; x < |
| Background/Reference section for a list of some | | | | MAP_X; x++){terrain[x][z][0] = |
| reference material that I have used, in general, | | | | float(x)*MAP_SCALE;terrain[x][z][1] = |
| for computer graphics.The following project is a | | | | (float)imageData[(z*MAP_Z+x)*3];terrain[x][z][2] = |
| very simple example demonstrating how to | | | | -float(z)*MAP_SCALE;}} |
| generate a terrain based on a bitmap file. The | | | | } |
| objective of the project is to generate a three | | | | . |
| dimensional terrain based on some data file. Please | | | | . |
| note, that this could have been any data file, but | | | | . |
| for the purpose of our example, we are going to | | | | The code above is the implementation of what |
| be using a 32x32 dimensional bitmap file. We could | | | | we discussed about applying MAP_SCALE, which |
| have easily used a text file, and defined logic for | | | | allows us to scale the terrain to our likings. So, it |
| each word or letter to represent it graphically.The | | | | basically assigns the vertex coordinates for each |
| project also contains a good Windows framework | | | | grid location, the MAP_SCALE factor, which is |
| that can be used for your other OpenGL | | | | multiplying it with the grid location index based on |
| applications. The current project allows you to | | | | the coordinate element. It extends along the X |
| rotate the camera using your mouse.Once again, | | | | and Z-axis, with the Y-Axis representing the |
| this is a simple approach to terrain generation, | | | | terrain height.The function is called after the |
| which can be a very difficult task in complex | | | | bitmap has been loaded into the memory from |
| environments.Background/Reference | | | | the Initialize() function.. |
| Since Computer Graphics is kind of an advanced | | | | . |
| topic, it is necessary to have at least some king | | | | . |
| of understanding and exposure to the concepts | | | | // Render |
| and theories in the field. However, this does not | | | | // desc: handles drawing of scene |
| mean that you will not be able to use the | | | | void Render() |
| following code or understand it. I have made it as | | | | {radians = float(PI*(angle-90.0f)/180.0f);// |
| simple as possible, and hopefully, it will give you a | | | | calculate the camera's position// multiplying by |
| good start, or some additional source of | | | | mouseY makes the// camera get closer/farther |
| information that you can use for your projects. | | | | away with mouseYcameraX = lookX + |
| Also, please note that you will need to have a | | | | sin(radians)*mouseY;cameraZ = lookZ + |
| good understanding of C/C++ programming.Some | | | | cos(radians)*mouseY;cameraY = lookY + |
| books I have used for learning Computer Graphics | | | | mouseY / 2.0f;// calculate the camera look-at |
| and OpenGL programming:Books I used while | | | | coordinates// as the center of the terrain |
| attending the California Polytechnic University: | | | | maplookX = (MAP_X*MAP_SCALE)/2.0f;lookY = |
| OpenGL Programming Guide, or better know as | | | | 150.0f;lookZ = -(MAP_Z*MAP_SCALE)/2.0f;// |
| the Red Book. | | | | clear screen and depth |
| Computer Graphics Using OpenGL, 2nd Edition. | | | | bufferglClear(GL_COLOR_BUFFER_BIT | |
| Books I used while attending the California | | | | GL_DEPTH_BUFFER_BIT);glLoadIdentity();// set |
| Lutheran University: | | | | the camera positiongluLookAt(cameraX, cameraY, |
| OpenGL: A Premier, 2nd Edition. | | | | cameraZ,lookX, lookY, lookZ, 0.0, 1.0, 0.0);// set |
| Interactive Computer Graphics: A Top-Down | | | | the current texture to the land |
| Approach Using OpenGL, 4th Edition.What is a | | | | textureglBindTexture(GL_TEXTURE_2D, land);// |
| Terrain? | | | | we are going to loop through all// of our terrain's |
| Some background information on a terrain and | | | | data points,// but we only want to draw one |
| their uses in a game application: A terrain in an | | | | triangle// strip for each set along the x-axis.for |
| environment is one of the most critical | | | | (int z = 0; z < MAP_Z-1; |
| components in the scene that is being rendered. It | | | | z++){glBegin(GL_TRIANGLE_STRIP);for (int x = |
| could easily be the largest 3D object in the | | | | 0; x < MAP_X-1; x++){// for each vertex, we |
| project. Rendering the terrain can become a | | | | calculate// the grayscale shade color,// we set |
| daunting task, taking the most time to render in a | | | | the texture coordinate,// and we draw the |
| scene. To keep the terrain engine running in real | | | | vertex.// draw vertex 0glColor3f(terrain[x][z][1] |
| time can be a difficult task, and it requires some | | | | 255.0f,terrain[x][z][1]/255.0f,terrain[x][z][1] |
| thought out processes and modeling for it to be | | | | 255.0f);glTexCoord2f(0.0f, |
| sufficient.To be effective, the terrain needs to | | | | 0.0f);glVertex3f(terrain[x][z][0],terrain[x][z][1], |
| meet a number of requirements, many of which | | | | terrain[x][z][2]);// draw vertex |
| can be contradicting each other. A terrain should | | | | 1glTexCoord2f(1.0f, 0.0f);glColor3f(terrain[x+1][z][1] |
| appear to be continuous to the end user, yet the | | | | 255.0f,terrain[x+1][z][1]/255.0f,terrain[x+1][z][1] |
| mesh should be simplified or culled where possible, | | | | 255.0f);glVertex3f(terrain[x+1][z][0], |
| to reduce the load on the graphics card.In a | | | | terrain[x+1][z][1],terrain[x+1][z][2]);// draw vertex |
| gaming system, for example, some engines draw | | | | 2glTexCoord2f(0.0f, 1.0f);glColor3f(terrain[x][z+1][1] |
| the terrain just beyond the point a player can | | | | 255.0f,terrain[x][z+1][1]/255.0f,terrain[x][z+1][1] |
| reach, and then use a terrain drawn onto a | | | | 255.0f);glVertex3f(terrain[x][z+1][0], |
| skybox to simulate hills or mountains in the | | | | terrain[x][z+1][1],terrain[x][z+1][2]);// draw vertex |
| distance. The terrain should appear realistic to the | | | | 3glColor3f(terrain[x+1][z+1][1] |
| setting for the environment, yet this can be | | | | 255.0f,terrain[x+1][z+1][1] |
| taxing on the video card, and a balance needs to | | | | 255.0f,terrain[x+1][z+1][1] |
| be maintained. Detail textures are often used | | | | 255.0f);glTexCoord2f(1.0f, |
| close to the camera, allowing the areas further | | | | ][1],terrain[x+1][z+1][2]);}glEnd();}// enable |
| off to be rendered more quickly.What is a Height | | | | blendingglEnable(GL_BLEND);// enable read-only |
| Map? | | | | depth bufferglDepthMask(GL_FALSE);// set the |
| The first thing required for terrain rendering is a | | | | blend function// to what we use for |
| representation of the terrain's shape. While there | | | | transparencyglBlendFunc(GL_SRC_ALPHA, |
| are a number of structures that can be used to | | | | GL_ONE);// set back to normal depth buffer |
| perform the job, the most widely used is the | | | | mode (writable)glDepthMask(GL_TRUE);// disable |
| height map. Others include: NURBS, which can be | | | | blendingglDisable(GL_BLEND);glFlush();// bring |
| maintained through a number of control points, | | | | backbuffer to foregroundSwapBuffers(g_HDC); |
| and voxels, which allow for overhangs and | | | | } |
| caves.There is one drawback to a height map, | | | | . |
| and that is, for every point on the XZ-plane, | | | | . |
| there can only be one height value. You can see | | | | . |
| that this limits the representation of overhangs | | | | The first thing you see in the Render() function is |
| and caves by a height map. This can be | | | | the conversion of the angle into radians, by using |
| overcome by using two separate models.Another | | | | the formula: radians = float(PI*(angle-90.0f) |
| drawback is that height maps take a large | | | | 180.0f);. This makes it easier to compute the |
| amount of memory, as each height must be | | | | cameraX, cameraY, and cameraZ positions using |
| represented. On the other hand, height maps lend | | | | the sin() and cos() functions.The next block of |
| themselves to the creation of regular meshes | | | | code sets the look-at coordinates of the camera |
| easily. It is also easy to determine the height at | | | | at the center of the terrain. Then, we clear the |
| any given location, which is useful for collision | | | | screen and depth buffer using |
| against the terrain as well as laying dynamic | | | | glClear(GL_COLOR_BUFFER_BIT | |
| shadows onto the terrain.A height map is | | | | GL_DEPTH_BUFFER_BIT);. We set the camera |
| represented by a 2D array of values, where for | | | | position based on the camera (X, Y, Z) values and |
| any point (X, Y, Z), the X and Z are the indexes | | | | the look-at we computed.We then bind the |
| into the array, and the value of the array is the Y | | | | texture using the |
| value which is equivalent to the height value.The | | | | glBindTexture(GL_TEXTURE_2D, texture); |
| following is an example of such a | | | | function. This tells OpenGL that we are going to |
| representation:int height[5][5] ={ | | | | use that particular texture to apply to our |
| { 0, 0, 1, 1, 2 }, | | | | surfaces that will be drawn.So far, all the code |
| { 0, 1, 2, 2, 3 }, | | | | was just to setup the camera position and bind |
| { 0, 1, 3, 2, 3 }, | | | | the texture, the next block of code is what |
| { 0, 1, 2, 1, 2 }, | | | | actually draws the terrain and applies the texture |
| { 0, 0, 1, 1, 1 } };The Approach! | | | | to the surface. We have two for loops which go |
| There are many advanced algorithms to | | | | through the 2D array we have created that |
| generate terrains; I am using a very simple | | | | stores the terrain data, and as we discussed |
| solution for the purpose of this project.In a | | | | earlier, we process four vertices at a time. In the |
| nutshell, I used a 32 x 32 grayscale bitmap to | | | | process, we calculate the grayscale shade color, |
| represent a height-field that is used to generate | | | | we set the texture, and then we draw the |
| the terrain. The terrain itself is divided into a grid | | | | vertex.That is pretty much all you need to do to |
| of height values, the result of which is a mesh | | | | generate a terrain, given a 24-bit bitmap file.Points |
| representing the terrain in the scene.We create a | | | | of Interest |
| grid of vertices that are spaced evenly apart but | | | | If you are reading this, you most likely are |
| have varying heights, based on the height-field | | | | interested in computer graphics and want to learn |
| data. The color value of each bit is used to | | | | more about the techniques available to do really |
| determine the height value of each grid location; in | | | | cool stuff. Computer graphics can be very |
| this case, for a 24-bit grayscale bitmap, the | | | | complex in theory, but thanks to libraries such as |
| values for the color range from 0 to 255.Once | | | | OpenGL, the implementation of complex models |
| the bitmap has been read and the values loaded in | | | | scenes can be done easily. Upon writing this |
| memory, we have the data needed to represent | | | | article, I got the latest issue of Dr. Dobb's Journal |
| the terrain. We also use a variable called a | | | | (June 2006, Issue No. 385), and to my surprise, |
| MAP_SCALE to allow us to scale the map up or | | | | there is an article about OpenGL and Mobile |
| down. This is a scale factor; we use this to set | | | | Devices. It is under the name of OpenGL ES and |
| the distance between each height vertex. This | | | | it is a subset of OpenGL 1.3. That will make it |
| allows us to increase or decrease the size of the | | | | possible to do real time 3D graphics on hand-held |
| terrain.When we actually assign the vertex | | | | devices. Imagine the kind of nice looking |
| coordinates for each grid location, we need to | | | | applications/games that can be developed for |
| apply the MAP_SCALE factor, which is multiplying | | | | your PDA or cell phones! Not all the functionality is |
| it with the grid location index based on the | | | | available due to the limitations of the hand-held |
| coordinate element, i.e.:Terrain[X][Z][0] = | | | | hardware. But I assume, in the near term future, |
| Float(X)*MAP_SCALE; | | | | you will be able to create as fascinating graphics |
| Terrain[X][Z][1] = (float) | | | | on the handhelds as you can on your regular |
| imageData[(Z*MAP_SCALE+X)*3]; | | | | desktop machines.On another note, I am going to |
| Terrain[X][Z][2] = Float(Z)*MAP_SCALE; | | | | start working on a new article which will describe |
| The terrain map is represented in a grid of height | | | | the LoadBitmapFile(char *filename, |
| values, which is internally stored in a 2D array of | | | | BITMAPINFOHEADER *bitmapInfoHeader) function. |
| vertex coordinates. It extends along the X and | | | | I am looking forward to hearing your comments |
| Z-axis, with the Y-Axis representing the terrain | | | | and input, for future articles.About Vahe |
| height.To render the terrain map, we use | | | | KaramianI have been programming since the age |
| GL_TRIANGLE_STRIP for each row of grid | | | | of 15. Started with BASIC on Apple II computers |
| values along the Z-axis. To render the terrain | | | | then moved on to Pascal. I wrote the game of |
| correctly, we need to specify the point in a | | | | Tetris using both languages on Apple II. At the |
| specific order.This requires us to start at the end | | | | age of 16 I got my first computer, and I started |
| of the row and move along the positive X-axis by | | | | transferring the code over to Quick Basic. I then |
| drawing the vertices in a Z | | | | moved into C/C++ and have been developing in |
| pattern:(*)==========>(*)/////////// | | | | C/C++ until about 2 years ago when I switched |
| (*)=========>(*) ....Using the Code | | | | over to C#.My interests are in the field of |
| I will only list the code that deals with the terrain | | | | Computer Graphics and Computer Vision. I am |
| generation here. There is more code in the | | | | working on my graduate degree emphasizing on |
| project that you can look at. It is well | | | | Computer Vision. I will try to be writing more |
| documented, so you shouldn't have any problems. | | | | articles in this field for future submissions.Currently |
| The solution was compiled using MS Visual Studio | | | | I am employed at a BioTech company in |
| 2003, so you should be able to compile and run it | | | | California, and I work on interesting projects |
| easily. You will need to have the OpenGL libraries | | | | ranging in many areas, except Computer Vision |
| and DLL, which I will also provide as a download | | | | Hence my graduate emphasis on the |
| option just in case you do not have them. Make | | | | subject.You can find more C/C++ samples on my |
| life a little easier so you do not have to search | | | | site. There is a lot of good code for |
| for them online.So the majority of the code is for | | | | undergraduate Computer Science students. |
| preparing the windows to render the scene | | | | |