A while ago now, Digimap gave data.gg a SHP file containing elevation data for Guernsey, Sark, Alderney and Herm. Using this data, I’m going to place a WebGL widget on data.gg allowing users to fly around the islands. There’s two ways to approach this:
Create a height-map using the SHP data and generate game engine terrain using it. This would be done using geographic software to rasterize the data into a normal image (like a PNG) with white pixels representing high points and black pixels low (e.g. sea level).
Triangulate the XYZ points in the SHP file to create 3D meshes. This is done using an algorithm to join all the points together to form edges and faces.
This post is going to be about the former method which is to create a height map, you can check out my post on the other method here. Both approaches have different pros and cons, the mesh approach may be more detailed while game engines (which is ultimately what the WebGL widget will be) will handle terrain better performance wise.
Thanks to Steve Streeting who helped figure out how to best process this data using GDAL.
Software
I’m going to be using GDAL (Geospatial Data Abstraction Library) commands which happen to come installed with QGIS desktop software for geographic data. You can install via either route – I went with QGIS because I can also use the software to view and edit the SHP file itself.
Generate a GeoTIFF
Taken from Wikipedia, a GeoTIFF is ‘a public domain metadata standard which allows georeferencing information to be embedded within a TIFF file’. Basically – we’re going to take our vector data and rasterize it, which is stored in a GeoTIFF. I’m going to use gdal_grid to convert the data, you could also use (and should try) gdal_rasterize. Both produced good results but as I have some gaps in the data, gdal_grid is more suitable because it can interpolate between the points (fill in holes).
I’m specifying that I want the grid system to use the linear algorithm which uses Delaunay, the same triangulation algorithm I used to make the meshes in the other post. Despite this, my end result had some artefacts which I couldn’t figure out a reason for. I found that setting the outsize to be ludicrously large (e.g. 20000) minimized the artefacts to roughly 4 pixels, instead of 40, which I was able to sort out in Photoshop after.
Converting to RAW
gdal_translate converts our GeoTIFF into other formats. Unity wants a .raw for height maps.
Attempting to open the .raw file in Photoshop, you’ll see a window like below (the defaults will be wrong!). The screenshot shows the correct settings to open the file. Notice we’re using 16 Bits as we did when interacting with GDAL above.
Height map
Tada, one height map!
It’s important to note that getting good results here took me a lot of trial and error. This will depend on the quality and quantity of your data. Try all the algorithms available in gdal_grid until you find the best results.
You can also do this using the QGIS desktop software instead of the command line, if that’s your preference.
A while ago now, Digimap gave data.gg a SHP file containing elevation data for Guernsey, Sark, Alderney and Herm. Using this data, I’m going to place a WebGL widget on data.gg allowing users to fly around the islands. There’s two ways to approach this:
Create a height-map using the SHP data and generate game engine terrain using it. This would be done using geographic software to rasterize the data into a normal image (like a PNG) with white pixels representing high points and black pixels low (e.g. sea level).
Triangulate the XYZ points in the SHP file to create 3D meshes. This is done using an algorithm to join all the points together to form edges and faces.
This post is going to be about the latter method which is to create a mesh, I’ll do a separate post about the other method in the future. Both approaches have different pros and cons, the mesh approach may be more detailed while game engines (which is ultimately what the WebGL widget will be) will handle terrain better performance wise.
To create the mesh I’m going to be using Blender, an awesome open source 3D graphics editor. You’ll also want to grab an add-on called BlenderGIS which is a “bridge between Blender and geographic data”.
Import
Using the menu, import your SHP file. Note that the ability to import SHP files comes from the BlenderGIS add-on.
These options will appear. The field holding the elevation in my case is caused ZVALUE.
Point Cloud
Depending on your data size, this could take a while but eventually the add-on will do its job and create vertices for all the XYZ coordinates.
What you have here is known as a point cloud. There are loads of tools and algorithms to triangulate point clouds into meshes but BlenderGIS comes with one called ‘Delaunay’ which worked perfectly for me. It’s in the tools area (press T) under the ‘GIS’ tab.
Mesh
Again – this could take a while depending on your data size but eventually you’ll be presented with a mesh containing edges and faces. Due to my data set containing rock formations around the islands, it has created some planes joining the rocks to the island and other rocks. Select one of the planes and press Ctrl-Shift-Alt-F to select all linked flat faces as in the screenshot below. Use X to delete these faces.
There we have it. One mesh.
I have a large data set, so my mesh has 433,775 faces which is too many to be usable. There’s a couple of ways to simplify a mesh but I found using ‘Decimate’ modifier with a collapse ratio of 0.03 produced good results. Below I’ve reduced the mesh to 5,987 faces.
On Wednesday I did a presentation in which I made a game using Unity in ten minutes for a new local software development meet-up called lunch && code. The presentation went surprisingly well, I had concerns about the game working (live programming is a nightmare) and keeping the presentation in the ten minute time window. The games objective is to avoid being knocked off of a platform by walls that spawn every three seconds and move towards the player. The walls are made up of six cubes, one of which is destroyed at random when the wall is created leaving a gap for the player to pass through. The source code for the game is on GitHub here.
lunch && code
The event was organised by Steve Streeting who has uploaded the README.TXT intro slides here. If you’re a software developer in Guernsey you can keep abreast of future events by visiting discuss.gg or by signing up to notifications here. Events will be at lunchtime every last Wednesday of the month.
Over on sacrificialinferno.com I’ve created an in-depth post about building GameMaker games for Linux using Hyper-V. It took me considerably longer than I expected due to the amount of screenshots involved in creating a Hyper-V guest and installing Ubuntu. I used Hyper-V because my Dell XPS 13 laptop is Windows Pro which comes with Hyper-V and I thought I’d give it a shot as I’d usually use VirtualBox. Sadly, I can’t say I was very impressed as the guest was able to cause a BSOD on the host by using dynamic memory.
Anyway, the post covers the following…
Downloading and setting up a base Linux Virtual Machine (VM)
There isn’t really a good reason not to support Linux when using GameMaker which has build support out the box. I’d like to see GameMaker streamlining the build process to make it easier for people unfamiliar with setting up a Linux system, though.