Crafting a Hexagonal Map Generator

Lucas DZIURA prepared a breakdown of another procedural generator – this time for hexagonal maps that can be 3D printed and used for board games.

Lucas DZIURA prepared a breakdown of another procedural generator – this time for hexagonal maps that can be 3D printed and used for board games. The project is made with Substance Designer and Houdini.

Introduction

Hello, my name is Lucas DZIURA, I’m 19 and I’m currently a third-year student studying Game Art at ArtFX, Montpellier, France.

Read the full introduction and learn the process of creating a Procedural Shield Generator in our previous article featuring Lucas:

Hexagonal Map Generator

Goals

I came across this artwork by Simon Tartar and was amazed by what he succeeded to do in Substance Designer.

The first goal of this project was only to wrap my mind around the way Simon created his project and try to do my own Hexagonal Generator.

Later during the development, I thought it would be very cool to actually get all the elevation data and do something game-ready with it since at the moment it was only an SD project. For that, my go-to-option was Houdini as both software solutions synergize well because of the procedural aspect. I aimed at making a 40x40cm Boardgame Map out of the map done in SD.

Substance Designer Workflow

Here’s the graph view which I tried to organize the best I could:

The generator takes a grayscale as an input which was created by using a noise and some levels.

The generator also takes an RGB map as an input: Red is for the Desert biome, Green for the Temperate area and Blue for the Snow one. By default, you can choose one biome for the whole map, but if you want to have multiple biomes at the same time you can try a “demo map” to preview the result. Of course, you can also input a custom map.

First, the grayscale input is transformed into the hexagonal map and separated into masks:

Throughout the project, I used a lot of Tile Sampler, particularly two of its options: Color Parametrization Multiplier and Mask Map Threshold.

Basically, this generator extracts masks from the Hexagonalizer.

Here is an example of how I extracted the ground and sand layers:

In order to colorize every mask, I used the same setup for every layer.

Here is the colorization of every layer:

And this is how I colorized the sand and ground:

I took the masks that were extracted from the hexagonal map and applied them to each biome mask extracted from the RGB input. Then, I combined all the biomes together to form the final color image.

For every color, the process was the same.

The Villages

The module for the villages is composed of two parts: the village global shape and the village roads.

The first part of the module is just subtracting all the mask from unwanted layers which allowed me to keep the layers only in the range I wanted.

Then, I used Flood Fill Bounding Box which is a node that colors each shape depending on its size. I clamped the result and used two levels to create a mask with only those areas that were big enough.

Then, I subtracted it with Edge Detect node to keep only round shapes.

With another Edge Detect, I created the outline of each village.

The Tile Sampler is used to splatter houses with a mask map input corresponding to the village area without the walls.

To avoid intersecting houses I used Flood Fill Bounding Box with the Flood Fill node set to “no failure mode” and the Override Safety/Speed trade-off set to 13. This allowed me to focus only on the shapes bigger than a single house. Then, I subtract them from the mask to only keep separated houses.

In the bottom Tile Sampler, I created a grid for my poles with random rotation and again used the mask map input.

Then, everything was blended together to get the village shapes.

The roads are very straightforward: I deformed Cell 2 with different Perlin noises to create some random curves and kept them only in the village areas.

The rocks and trees are also a simplified version of this setup (since they are just simple shapes).

This is the finished result in SD:

  • 2D (4 variations of the same map ):
  • And 3D:

Houdini Workflow

To convert 2D images into 3D models (and since I basically created a terrain), the natural thing to do was to use Heightfields.

I converted the heightmap from SD into a Heightfield in Houdini, then converted it into polygons and scaled it down. After that, I reduced some polys to only keep the hexagons. I simply projected the UV on the ZX Plan and that’s it!

I could have used the heightmap to displace the grid of hexagons but since I had some objects in it such as rocks, trees, and villages, I would have lost that data. In that case, I would have had to recreate it in Houdini by re-scattering those elements and the result would be different from my SD map. I think that method would have been more precise but my goal was to create an exact copy of my 2D map.

There was nothing really interesting in Unreal Engine: I just imported the mesh and applied the material containing the maps from SD to it.

Here is a map render with different variations:

3D Print Workflow

The 3D printer I used is quite small, it could only print 13x18x13 cm. I used white 1,75mm PLA that needs to be heated to 190°C. To convert my meshes into data recognizable to the printer, I used Ultimaker Cura with custom settings because my printer was not in the preset list.

I first tried to print the entire map in 10x5x10 cm (plus 3 cm on each side which helped me to remove the piece from the printer bed).

I was quite satisfied with the result (and it was my first 3D print ever!), however, I wanted to scale it up in order to make the map actually playable.

In order to do that, I came back to Houdini to create a network that would allow me cutting the map into a certain number of parts and easily saving them.

This is the final network. Below, I will focus on a few parts that seem important to me.

This is the main function of the network (to cut the map in equal parts):

The left part serves for adding (or not) a cap at the bottom of the map.

In the right part, in order to control the number of pieces, I created a line which corresponded to the length of the map and controlled the number of points in this line with a parameter. I copied a grid on each point and unified them with a Boolean, then cut the map by subtracting the grids from the map with another Boolean.

The rest of the network is just for cleaning and adding caps on the side of each piece.

Finally, I put each piece in a different frame to save them all at once by saving the geometry to a frame range. To know what frame range I need, I started from 0 and ended at 2 of my parameter responsible for the number of pieces.

And here it is, the map cut in several pieces where each piece has caps on the sides and the bottom, ready to be printed.

My printer took almost 2 weeks to print 16 pieces (almost 16 hours per piece since my printer is very slow ). I tried to optimize the PLA consumption but got almost +3 hours per piece.

Here is a picture of the final map (the parts are not glued together for the storage purpose):

Afterword

I hope this article turned out to be helpful to someone! You can check my Artstation where I post new projects mainly focused on proceduralism and where you can send me any questions you have.

Lucas DZIURA, 3D Artist

Sponsored

Meet the Razer Huntsman Elite: the product of years of research and innovation — now taken to new heights. By redefining the boundaries of precision and speed, you are about to experience performance that can only be described as ahead of its time. The next stage of keyboard evolution is here.

Join discussion

Comments 0

    You might also like

    We need your consent

    We use cookies on this website to make your browsing experience better. By using the site you agree to our use of cookies.Learn more