3. Terrain Rendering

Jump To:

heightfield.h Source
heightfield.cpp Source
main.cpp Source

Download

Heightfield.H File:

In our heightfield.h file, we are going to declare some private variables inside our class, these are going to hold the height and the width of our heightfield, globally within the class:

// private:

// int hmHeight;
// int hmWidth;

1.
2.
3.
4.

5.
6.
7.
8.
9.
10.
11.
12.
13.

14.

    #include <windows.h>

class SwiftHeightField {
    
private:
    
int hmHeight;
    

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

    
void Render(void);
    

    
BYTE hHeightField[1024][1024];

};

Heightfield.CPP File:

To render our terrain, we are going to need to call OpenGL commands from within this source file, so we need include gl.h:

// #include <gl/gl.h>

To get the height and width of our heightfield, we then copy the height and width inside the Create function, to our global variables:

// hmHeight = hHeight;
// hmWidth = hWidth;

Now we move onto our Render function. Yay, we are about to start seeing some results 🙂

To start off, I am going to just render our terrain as a bunch of points in space. To do this, we need our glBegin(GL_POINTS) and glEnd() Inside of thse calls, I am placing a loop that will create a vertex at every point along the X and the Z axis at their respective Y positions. So our code goes from nothing, to this:

// void SwiftHeightField::Render(void){
// glBegin(GL_POINTS);
// glEnd();
// }

And then to this:

// void SwiftHeightField::Render(void){

// glBegin(GL_POINTS);
// for (int hMapX = 0; hMapX < hmWidth; hMapX++){
// for (int hMapZ = 0; hMapZ < hmHeight; hMapZ++){
// glVertex3f(hMapX, hHeightField[hMapX][hMapZ], hMapZ);
// }

// }
// glEnd();
// }

Upon running this program, you should find that a window is displayed with a black background, and a bunch of white spots in space. These spots are the vertices of our terrain and are the building blocks of everything to come 🙂

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.

    #include <stdio.h>
#include <gl\gl.h>

#include “heightfield.h”

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

hmHeight = hHeight;
    
hmWidth = hWidth;
    

    
FILE *fp;
    

    
fp = fopen(hFileName, “rb”);
    

    
fread(hHeightField, 1, hWidth * hHeight, fp);
    

    
fclose(fp);
    

    
return true;
}

void SwiftHeightField::Render(void){
    

glBegin(GL_POINTS);
    
for (int hMapX = 0; hMapX < hmWidth; hMapX++){
        

for (int hMapZ = 0; hMapZ < hmHeight; hMapZ++){
            
glVertex3f(hMapX, hHeightField[hMapX][hMapZ], hMapZ);
        

}
    
}
    
glEnd();
}

Main.CPP File:

Hehe, this is a simple change. All we need to do here is change our Create call to load in the file, heightfield.raw. So our Create line looks like:

// hField.Create("heightfield.raw", 1024, 1024);

Check out the next tutorial on rendering the heightfield with triangle strips instead of points 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(“heightfield.raw”, 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

Download heightfield.raw for this Tutorial

  • March 25, 2010
  • 3