Sponsored By

An Algorithm for Generating Contour Maps or How I Discovered World Machine was Mangling my Terrain

I have always assumed the tools I buy actually work. I have learned that sometimes that isn't true. Also a handy algorithm to generate contour maps from heightmap data.

Robert Basler, Blogger

February 14, 2017

3 Min Read
Game Developer logo in a gray background | Game Developer

[Originally from onemanmmo.com.]

I use World Machine to generate the terrain for The Imperial Realm::Miranda, the seamless open-world RTS I'm building. I chose World Machine because it generates beautiful terrains, and because it supports tiled rendering for really huge maps. I had a lot of trouble finding tools that could manipulate a 300x300km dataset. It also generates this nice looking contour map of the terrain (scaled down from 2K resolution map.)

Playing the game, I always felt that the contour map didn't really line up with the terrain. If you clicked on the high point of the contour map, it was a 50/50 chance you'd end up on a hill. I always suspected I might have done something wrong importing the World Machine terrain so I decided I would generate my own contour map from the imported terrain heightmap to see what I had done.

I was surprised to find that nobody really has written up an algorithm for generating a contour map from a height map. I thought on it for a bit and came up with this: Treat each contour map pixel like it is in the centre of four heightmap samples. northeast/southeast/northwest/southwest are the floating point corner sample heights, contourHeight is the vertical distance between the contour lines. To fill in the bitmap, we just need to find if the edges of each pixel are on different sides of a contour line.


if ( floor( northeast / contourHeight ) != floor( southeast / contourHeight ) ||
     floor( northwest / contourHeight ) != floor( southwest / contourHeight ) ||
     floor( northeast / contourHeight ) != floor( northwest / contourHeight ) ||
     floor( southeast / contourHeight ) != floor( southwest / contourHeight ) )
{
     SetPixel( black );
}
else
{
     SetPixel( white );
}

Iterate over every pixel and you're done. Here's a tiny section from the top left of the full 8K resolution contour map.

I needed a contour map that was a lower resolution than my terrain, so originally I generated the contour map at the same resolution as the terrain and then scaled it using GIMP. That produced disappointing results. (Note that the bitmaps here are scaled-down with GIMP because they don't need to be pixel-perfect.) A better solution was to decrease the resolution of the contour map by testing heightmap samples that are farther apart.

When I generated the contour map from my imported World Machine heightmap, I was very surprised to see that it looks like this.

Wow, not even close to what it is supposed to look like. The reason was immediately obvious, I used the Tiled Rendering feature of World Machine to generate an 8x8 tiled heightmap. Apparently that doesn't actually work. I got on the World Machine forums for help, and received a suggestion to render with a higher blending percentage. I had originally used 25%, so I tried 100% (the maximum setting) and got this:

That's better, but still not really at all accurate. As an experiment I rendered the terrain in a single tile, and the results as expected are perfect.

Now when I click on the map, the terrain lines up perfectly in-game. Unfortunately, I still need tiled rendering to support my 300x300km terrain. With no help forthcoming from the World Machine developer, the takeaway here is that if you need to render a really large terrain with World Machine, you should render the largest possible resolution tiles to reduce the unavoidable tiling artifacts.

Read more about:

Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like