Importing DEM Terrain Heightmaps for Unity using GDAL

I know that some folks reading my blog are from the spatial/mapping community, and may have been disappointed that my posts of late have been more influenced by game development and Unity than by spatial data and Bing Maps. Well, good news, spatial fans – this post is about mapping terrain from DEM data! (to create terrain for a Unity game… )

I’ve written a few posts in the past (such as here and here) that have made use of Digital Elevation Model data, such as collected by the SRTM or GTOPO30 datasets, via GDAL into Bing Maps, WPF etc. In this post I’ll be running through a similar workflow to that which I’ve used before, but this time with the target output being a Unity terrain object.

So, here goes:

1.) Get a GeoTIFF file of DEM data. For whole-world STRM coverage, use Google Earth browse of http://www.ambiotek.com/topoview, or download direct from e.g. http://srtm.geog.kcl.ac.uk/portal/srtm41/srtm_data_geotiff/srtm_36_02.zip (although I note that King’s have disabled directory browsing on their server so you’ll have to know the name of the SRTM file you want to access)

If you want to preview the data in the DEM file, you can open it up in MicroDEM (File –> Open –> Open DEM –> Select GeoTiff file). It should appear something like this:

image

Note that although you can load up GeoTIFF files in image applications such as Photoshop or GIMP, they won’t visualise the geographic data encoded in the file, and you’ll probably just see this:

image

 

2.) (Optional) Use gdalwarp to transform the data to an alternative projection and/or crop it to a particular area of interest. Like all forms of spatial data, DEM data can be provided in various different projections. The STRM data I’m using here is provided in WGS84 decimal degrees, but as it’s data for Great Britain, I’d like to reproject it to the National Grid of Great Britain (EPSG:27700) instead:

gdalwarp –multi –t_srs EPSG:27700 srtm_36_02.tif srtm_36_02_warped.tif

I’ll then crop a 100km2 area from the warped image so that it covers the Ordnance Survey Grid Square “SH”, which includes North Wales and Snowdonia National Park as shown in the red square here:

image

Here’s the gdalwarp command to crop the image:

gdalwarp srtm_36_02_warped.tif –te 200000 300000 300000 400000 srtm_36_02_warped_cropped.tif

If you were to view the warped, cropped image in MicroDEM again now, it would look like:

image

 

3.) Use gdal_translate to convert the GeoTIFF file to the raw heightmap format expected by Unity

gdal_translate –ot UInt16 –scale –of ENVI –outsize 1025 1025 srtm_36_02_warped_cropped.tif heightmap.raw

The settings used here are as follows:

  • -ot UInt16 Use 16 bit channel. Most graphics applications use 32 bit colour images, consisting of four channels (R,G,B,A), each one having 8 bits. That means that, in any given channel, you can only represent an integer value between 0-255. We’ll be encoding the heightmap data in a single channel, so having only 256 unique values would not give us very precise resolution. Instead. we’ll specify a 16bit channel that gives 65,536 unique values instead.
  • –scale To make the most of our 16 bit channel, we need to scale the height values from their original range to fill the full range of values available in the 16 bit channel (0 – 65535). Specifying –scale with no parameters automatically does this.
  • -of ENVI  This outputs the result in the raw binary output file format Unity expects.
  • -outsize 1025 1025 Unity terrain maps must have dimensions equal to a power of 2 + 1. i.e. 65x65, 129x129, 257x257, 513x513, 1025x1025, 2049x2049 etc.

 

4.) Import into Unity

Create a new terrain object and, from the settings tab of the Inspector, click the button to Import Raw heightmap. If you browse to select the heightmap.raw file created in the previous step, it should populate the correct settings automatically (note that, even when running under Windows, gdal appears to use Mac Byte Order). Note that Width and Height need to match the Heightmap Resolution field in the terrain inspector, not the Width and Height of the terrain itself:

image

If all goes well, your blank terrain should magically update to reflect the heightmap and you’ll see the following:

image

 

5.) Correct the orientation

The observant amongst you will notice one slight problem with the previous image – the heightmap has been rotated anti-clockwise by 90 degrees. It turns out that Unity treats heightmap coordinates with (0,0) at the bottom-left corner, whereas most other applications, including gdal, interpret (0,0) at the top-left corner. Fortunately the fix is quite simple. Just attach the following script to the terrain object and click play (changes will be saved to the terrain, so script can be disabled/deleted once used once)

using UnityEngine;
using System.Collections;

public class RotateTerrain : MonoBehaviour {
    
    void Start () {
        
        Terrain terrain = GetComponent<Terrain>();
        
        // Get a reference to the terrain
        TerrainData terrainData = terrain.terrainData;
        
        // Populate an array with current height data
        float[,] orgHeightData = terrainData.GetHeights(0,0,terrainData.heightmapWidth, terrainData.heightmapHeight);

        // Initialise a new array of same size to hold rotated data
          float[,] mirroredHeightData = new float[terrainData.heightmapWidth, terrainData.heightmapHeight];
        
        for (int y = 0; y < terrainData.heightmapHeight; y++)
        {
            for (int x = 0; x < terrainData.heightmapWidth; x++)
                {

                // Rotate each element clockwise
                mirroredHeightData[y,x] = orgHeightData[terrainData.heightmapHeight - y - 1, x];
            }
        }
        
        // Finally assign the new heightmap to the terrainData:
        terrainData.SetHeights(0, 0, mirroredHeightData);
    }
}

And there you have it – DEM data of Wales imported and ready to play in Unity. Now, if you want, you can texture it using procedural splat mapping (or just paint textures on manually).

image

image

About these ads
This entry was posted in Game Dev, Spatial and tagged , , , , . Bookmark the permalink.

7 Responses to Importing DEM Terrain Heightmaps for Unity using GDAL

  1. Excellent post – I’ve been wanting to see if this was possible for a while. Will bookmark and try this out later.

  2. Gordon says:

    Thank you for this awesome tutorial, very helpful!

  3. veddycent says:

    This is a daft question but where to use:
    gdal_translate –ot UInt32 –of ENVI –outsize 1025 1025 srtm_36_02_warped_cropped.tif heightmap.raw
    You don’t mention where you actually put/use this command.
    Is it used in cmd prompt, if so how?

    Thank you so much for this guide. I have had great difficulty converting a 32-bit TIFF in to 32-bit RAW.

  4. Pingback: Integration Experimentation – Unity 3D | SSHS Computer Club

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s