Building terrain using heightmaps

A heightmap is basically a gray scale image. Each pixel’s coordinate will represent the x and y coordinates in your future terrain, while it’s color will encode the height. The lighter parts will be hills and mountains while the dark parts will end up being valleys.

This is a 16×16 pixels heightmap (enlarged here):


Nothing new so far. I knew what a hieghtmap was. However, I did not know how to use one in AvP2. First, a step-by-step procedure, then the explanations:

Prepare the heightmap

This means that you should prepare a .pcx image. To give you an idea of how big this image should be, take into account that each pixel in the image will be imported as 4 triangular prisms. That means that a heightmap of 8×8 will turn into 8x8x4 = 256 brushes. To import such a heightmap will not stress your CPU too much. However, a 16×16 heihtmap will give you 4 times the CPU consumption than the 8×8 one.

So, create your heightmap, convert it to grayscale, shrink it to a max. of 16×16 pixels and save it as a .pcx file. If you don’t have the tools needed, I would suggest The Gimp.

Prepare the .ed file 🙂

To actually import the heightmap, you will need to specify the editor how large your terrain will be; there is no absolute scaling, 1 pixel represents X DEdit units. Rather than that, the heightmap is scaled to the desired size. So, add a box. Resize it to whatever size you need your terrain.


The height of the bos is the height which will be reached by the white (as in white, not light gray. All gray tones will have intermediate heights) pixels.

Import the heightmap

Having the box selected, go Brush -> Import terrain:


At this point, you will be asked to select the heightmap. After you select  the .pcx file, well, depending on the size of the heightmap, you will have to wait. Give it time to finish. You will end up with a terrain according to the heightmap. At this stage, you can delete the box, we won’t be needing it.

You can then resize it, screw it up, whatever. After resizing it, I ended up with:



Now that you are so delighted you have obtained your terrain, you bind it to a terrain object and then fire up the game. And it lags. A lot. Simple arithmetics will show you why. What we’ll do next is to count the polygons generated:

8×8 (dims of the heightmap) x 4 (each pixel generates a prisms) x 5 (each prisms has 5 faces) = 1280 polies.

A little bit too close to the limits of the engine. What about the 16 x 16 map?

16×16 x 4 x 5 = 5120 polies

This is definately too much. At this point you should transform this terrain to nosnap, to keep the poly count low by a factor of 5! If you are not familiar with nosnap, please pay a visit to the menu of this page and click the nosnap button.

The explanations part is actualy taken in discussion at step 4. Basically, the import function of DEdit was written in this way, that for each pixel of the heightmap it will generate 10 vertices (points) in the final brush. The vertex in top center will have the height dictated by the formula:

h = H * level / 255


  • h – the height of the vetrex (in DEdit units)
  • H – the height of the box used to specify the size of the terrain (also in DEdit units)
  • level – the gray level of the pixel: black is 0, white is 255, all other gray levels fall in between

The vertices on the bottom will lay flat. The rest of 4 vertices will make the transition to the next pixel from the heightmap. So, at this point you will end up with 20 polies for each pixel in the heightmap.

At this point, two things happen:

  • for large heightmaps the engine will have a hard time importing them
  • the engine will have an even harder time running the level

While there is little we can do abou the first matter, the nosnap tehnique is a must to improve the second one. The biggest advantage in this heightmap tehnique is that it shaves a lot of time in building the main features of the terrain. Also, if the results are far from expectations, an new heightmap and some extra 30 minutes usualy will do the

I hope this info helped. One year ago I asked this question to one of the (at that
moment) most active forums (the site is closed now) but I didn’t get an answer.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s