Voxel Engine: Heightmaps (Part 1)

Posted on 02/05/2017

My HTML5 voxel engine has so far been built up around the idea of handling terrains, specifically that from a heightmap. While this won't always be the case, it's a good place to start. There's no end to interesting heightmaps you can find for testing with a quick look on Google Images.

In my engine, a Heightmap is a class object. This object is designed to handle everything you might want to do with a heightmap, before doing anything with it such as passing it to the world to generate. There's not many options to use just yet, but I will touch more on it in the future.

To start, here is an example of how I currently create a heightmap and generate a world from it:

var heightmap = new BLOX.Heightmap( {
  src: [ "img/hm2.png" ]
} );

var world = new BLOX.World();
world.generateFromHeightmap( heightmap );

As you can see, the heightmap is created and passed the source name of an image to use. Creating a heightmap and giving it this image doesn't actually do anything, merely sets it up. In this case, when it's passed to the world with the World.generateFromHeightmap() method, that's when it loads in the images and gets the data. Because image loading is asynchronous in JavaScript, any function that takes a heightmap needs to be aware of that, and that is why the Heightmap object doesn't do anything until required. Internally, the world is actually generated via a callback when the Heightmap data is ready.

You'll also notice that the "src" property of the object we pass to the Heightmap is an array, this is so we can send it multiple images. These can be passed in multiple ways, such as:

// Source array
var heightmap = new BLOX.Heightmap( {
  src: [ "img/hm2.png", "img/hm2_1.png" ]
} );

// Multiple calls
var heightmap = new BLOX.Heightmap();
heightmap.addSource( "img/hm2.png" );
heightmap.addSource( "img/hm2_1.png" );

With multiple images, we can blend them together to make new, unique, heightmaps. This is particularly helpful in a game scenario, as you can take any heightmap and limit it/block it off some way using another heightmap. As an example, here's a heightmap combined with a random blob to produce an island:

OK, so I'm going to leave it at that. It's brief so I put Part 1 in the title. This part of the engine works independently, so my goal is to release this as a stand alone thing purely for generating heightmaps in various ways. Surprisingly, a quick look on Google didn't turn up anything that "just did it", so this could be useful as an online tool.