1. Terrain Class

Terrain is one of those things that so far, hasn’t been perfectly recreated in computer graphics. But it is almost there! Looking over a beautiful landscape can be one of the most amazing feelings in the world. And is probably my inspiration for these tutorials.

Jump To:

heightfield.h Source
heightfield.cpp Source

main.cpp Source
Download

Heightfield.H File:

This tutorial is going on the basis that you have read at least some of the previous OpenGL tutorials. It pretty much starts off where the second camera tutorial ends. This tutorial unlike my previous OpenGL tutorials, is going to expand into multiple custom files include header and source code files while my previous tutorials just kept everything in the one file, and became quite messy. Anyway, time to begin.

First off we are going to look into our heightfield.h file. This is going to be our global header file for the creation of our terrain. I am going to create a custom class in here called SwiftHeightField with the following code:

// class SwiftHeightField {
// };

In here, I am going to start off with two public functions. The first is a boolean function that will handle that loading and creation of our heightfield, while the second will render our terrain.

We will start off by creating our Create function. The code will look like:

// class SwiftHeightField {

// public:
// bool Create(char *hFileName, int hWidth, int hHeight);
// };

The first variable hFileName will be the filename for the .RAW file we store our terrain height data in. The next two are the width and the height of the file in pixels so that we can load it in correctly.

The next function I am going to add is the Render function. This is just a basic void function that doesn’t return any value. Our heightfield.h file will look like this:

// class SwiftHeightField {

// public:
// bool Create(char *hFileName, int hWidth, int hHeight);
// void Render(void);
// };

This is all we are going to do in our heightfield.h file for now. Seems quite basic, but I want to keep it as basic as possible 🙂

1.
2.
3.
4.
5.
6.
    class SwiftHeightField {

public:
bool Create(char *hFileName, int hWidth, int hHeight);

void Render(void);
};

Heightfield.CPP File:

Here is the start of our heightfield.cpp source code file. The first thing we need to do now is load in our heightfield.h file with the following line:

// #include "heightfield.h"

Our creation and rendering functions are going to be pretty much empty, because in this tutorial we are just starting off and getting everything ready for later when we really get into coding.

So we have our Create function:

// bool SwiftHeightField::Create(char *hFileName, int hWidth, int hHeight){
// return true;
// }

And our Render function:

// void SwiftHeightField::Render(void){

// }

1.
2.
3.
4.
5.
6.

7.
8.
9.
10.

    #include “heightfield.h”

bool SwiftHeightField::Create(char *hFileName, int hWidth, int hHeight){

return true;
}

void SwiftHeightField::Render(void){

}

Main.CPP File:

Here we have our main source code file. This is not going to change much until later on in the tutorials. It is pretty much as I said, the seconds camera tutorial. The first thing we need to do here is include our header file. So we add the line:

// #include "heightfield.h"

Then we need to add a variable that ties into our heightfield class. This is going to be added with:

// SwiftHeightField hField;

Now we have a class to hold our heightfield information for our terrain. So we need to Create our heightfield. So we call our Create function inside an initialization function, before we start drawing. So our Init function becomes:

// void Init (void) {

// glEnable(GL_DEPTH_TEST);

// hField.Create("", 1024, 1024);
// }

Note here that I am not actually loading anything. The blank "" will not throw back an error looking for a file named nothing, because our Create function does not try to load anything yet. (Remember, it’s blank inside, hehe). I just decided to place the integer 1024 for the width and height of the file, because that is the size I am going to be using later on.

We then need to move onto calling our Render function. This goes inside our display function after we perform our camera rotations. Our display function will look as such:

// void display (void) {
// glClearColor (0.0,0.0,0.0,1.0);
// glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glLoadIdentity();
// camera();

// hField.Render();

// glutSwapBuffers();
// }

This is all we need for now. Check out the next tutorial on loading the heightfield data in here 🙂

If you have any questions, just email me at swiftless@gmail.com

1.
2.
3.
4.
5.
6.
7.

8.
9.
10.
11.
12.
13.
14.
15.
16.

17.
18.
19.
20.
21.
22.
23.
24.
25.

26.
27.
28.
29.
30.
31.
32.
33.
34.

35.
36.
37.
38.
39.
40.
41.
42.
43.

44.
45.
46.
47.
48.
49.
50.
51.
52.

53.
54.
55.
56.
57.
58.
59.
60.
61.

62.
63.
64.
65.
66.
67.
68.
69.
70.

71.
72.
73.
74.
75.
76.
77.
78.
79.

80.
81.
82.
83.
84.
85.
86.
87.
88.

89.
90.
91.
92.
93.
94.
95.
96.
97.

98.
99.
100.
101.
102.
103.
104.
105.
106.

107.
108.
109.
110.
111.
112.
113.
114.
115.

116.
117.
118.
119.
120.
121.
122.
123.
124.

125.
126.
127.
128.

    #include <GL/glew.h>
#include <GL/gl.h>

#include <GL/glext.h>
#include <GL/GLUT.h>

#include <math.h>

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <fstream>

#include <assert.h>

#include “heightfield.h”

#pragma comment(lib,“glew32.lib”)

float xpos = 851.078, ypos = 351.594, zpos = 281.033, xrot = 
758, yrot = 238, angle=0.0;

float lastx, lasty;

float bounce;
float cScale = 1.0;

SwiftHeightField hField;

void camera (void) {
int posX = (int)xpos;

int posZ = (int)zpos;

glRotatef(xrot,1.0,0.0,0.0);
glRotatef(yrot,0.0,1.0,0.0);

glTranslated(xpos,ypos,zpos);
}

void display (void) {

glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
camera();

hField.Render();

glutSwapBuffers();
}

void Init (void) {
glEnable(GL_DEPTH_TEST);

hField.Create(“”, 1024, 1024);
}

void mouseMovement(int x, int y) {

int diffx=xlastx;
int diffy=ylasty;
lastx=x;

lasty=y;
xrot += (float) diffy;
yrot += (float) diffx;

}

void keyboard (unsigned char key, int x, int y) {

if (key == ‘w’)
{
float xrotrad, yrotrad;

yrotrad = (yrot / 180 * 3.141592654f);
xrotrad = (xrot / 180 * 3.141592654f);

xpos += float(sin(yrotrad)) * cScale;
zpos = float(cos(yrotrad)) * cScale;

ypos = float(sin(xrotrad)) ;
bounce += 0.04;

}

if (key == ‘s’)
{
float xrotrad, yrotrad;

yrotrad = (yrot / 180 * 3.141592654f);
xrotrad = (xrot / 180 * 3.141592654f);

xpos = float(sin(yrotrad)) * cScale;
zpos += float(cos(yrotrad)) * cScale;

ypos += float(sin(xrotrad));
bounce += 0.04;

}

if (key == ‘d’)
{
float yrotrad;

yrotrad = (yrot / 180 * 3.141592654f);
xpos += float(cos(yrotrad)) * cScale;

zpos += float(sin(yrotrad)) * cScale;
}

if (key == ‘a’)
{
float yrotrad;

yrotrad = (yrot / 180 * 3.141592654f);
xpos = float(cos(yrotrad)) * cScale;

zpos = float(sin(yrotrad)) * cScale;
}

}

void reshape (int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h);

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 1000.0);

glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char **argv) {

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);

glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(“A basic OpenGL Window);

Init();
glutDisplayFunc(display);
glutIdleFunc(display);

glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutPassiveMotionFunc(mouseMovement);

glutMainLoop ();
return 0;
} 

Download:

Download heightfield.h Source Code for this Tutorial

Download heightfield.cpp Source Code for this Tutorial

Download main.cpp Source Code for this Tutorial

  • March 25, 2010
  • 4