Seamless and Collaborative Generation of Infinite Worlds

I am worried about what some of the tech giants truly envision when it comes to the concepts of metaverse and of web 3.0, but if there is one thing that I like in these conversations, it’s the idea of having some sort of open worlds available to connect us with other people.

In 1999, we had this virtual world in France named Le Deuxième Monde (The Second World), and I remember finding it to be a wonderful and captivating experience. I met some lovely people there with whom I’m still connected to this day, and others who even helped me getting started in 3D, which eventually kickstarted my career in the animation and VFX film industry.

Wouldn’t it be cool if we had some interactive experiences like that today, in worlds that would be authored by their users, and where we could somehow satisfy our innate desires to explore an unknown land and to form communities?[1][2]

Design Objectives

One thing that I learned during my time as a technical artist, it’s that you usually don’t want to take away control from the users by fully automatizing some systems. Every tool, every feature, should always allow users to override their behaviour and to drive the result in whichever direction they like.

That’s also true for such open worlds. Yes, we might want to be able to generate them to some extent, but how cool would it be if users could also author their little piece of land however they’d like?

So that’s what I decided to tackle during the 4 days of the Easter break!

The goal was to build a quick proof of concept in Houdini where an infinite world can be created based on a set of tiles that are provided, and where users can focus on getting their own tile to look good in a standalone fashion, while having the confidence that they would seamlessly blend with the rest of the world.

Terrainterrain

To keep the scope of this experiment small, the result shall not be expected to represent the final look of the terrain. Instead, the intention is to use it as an intermediate step, on top of which more procedural work can be applied, such as adding hard edges depending on the curvature, running an erosion pass, adding roads and rivers, and whatnot.

SDF All the Things!

The Signed Distance Function (SDF) is one of these techniques that is just too good to ignore.

Knowing the distance to a surface for cheap makes it well suited for algorithms involving collision detection, such as ray marching, and many fluid and rigid body solvers used in the film industry when making VFXs.

Not only that but it’s also a prime choice for procedural modeling where it makes organically combining multiple arbitrary shapes a walk in the park.

In other words, I’m a big fan of SDFs. And so are the masterminds behind Shadertoy, Dreams, and Clayxels.

The more I thought about it, the more the smooth blending property that comes with SDFs seemed like a must-have to address the needs of seamlessly connecting adjacent tiles.

smooth blending using SDFs

The smooth blending formula can be found on Inigo Quilez’s excellent website where it is described as a function named smin().

Porting that to Houdini was fairly straighforward.

Smooth Blending SetupSDF smooth blending setup in Houdini

Tiling

To divide the world up into equal areas, I decided to use hexagonal tiles—it seemed like a good opportunity for me to experiment with these, but they also look much more organic while remaining simple enough to build grids with.

Generating the grid was done in two steps. First, I created a bunch of points that would represent the center of each tile, and then I instantiated one hexagon on each of these points.

There’s probably a formal definition for that approach somewhere but I found out through some lucky experimentations that, to generate these instance points, I could use... more hexagons!

For the first layer, I’d create an hexagon with a single division per edge. Then another hexagon for the second layer, this time with 2 divisions per edge, and so on.

Hexagonal Gridhexagonal grid with instance points

The only trick being to know by how much to scale the hexagons for each layer but, after some empirical measurements, I figured it out to be equal to the expression scale = \sqrt{(1 + i)^2 * 3} where i is a 0-based index representing the current layer.

Hexagonal Gridhexagonal grid generation

Safe Area

One immediate drawback of smooth blending in the context of connecting adjacent tiles is that it actually modifies the tile’s geometry up to a specific number of voxels deep, with the actual amount of voxels directly depending on the value k used in the smooth blending formula.

So we need a sort of “safe area” to inform users that within it anything they do will be preserved as-is. However, outside of that safe zone, in a thin band near the boundaries of the tile, the terrain might change a little bit to accomodate for the smooth blending operation, and hence some edits like placing buildings and other structures might not be permitted in there—but others like roads and rivers might be alright.

Not only that but if we were to blend 2 adjacent tiles that are in direct contact, then the transition might be a bit... crude? So we need to allow for a bit of padding between the tiles in order for the blending to generate a smoother transition.

And there we have it, tiles being seamlessly connected to each other in an organic fashion while preserving their features within the safe areas.

Tile Blendingblending of 3 adjacent tiles

Ad Infinitum

If we only had a fixed numbers of tiles as input that would never change, then we could go ahead and generate the whole terrain in one go through this approach.

However, remember that we’re after an infinite world here, so we need to be able to keep connecting new tiles to the already existing world as soon as they are being authored by the users.

For that, we need to be able to generate the seams on the go.

The approach that I went for was to subdivide the hexagonal grid to obtain another grid made of triangles, where each triangle is centered at the intersection of 3 tiles.

Cell Gridcell grid

What this means is that, to generate the geometry for a single triangle cell, this solution requires the 3 surrounding tiles to be readily available. And to generate the geometry for a single hexagonal tile, with its seams, all the surrounding cells are required to be known.

Full Tile Blendingblending of all the cells overlapping a single tile

The advantage of dividing each tile with these triangular cells is that their edge boundaries should pretty much line up, regardless of how much terrain sculpting was done in these areas by the users, which should make it straighforward to stitch them back together. To be honest, I’m not too sure how to explain this assumption with words but I can see pretty pictures in my mind telling me that it should be viable. Or not?

The geometry for these cells can be generated on a server as soon as new tiles are being added to the world, or they could also be generated on demand, just before a user is about to explore a new tile for the very first time.

Cell Streamingstreaming of new cells

Either way, the result is the same... a world whose boundaries can stretch to infinity and beyond!

Infinite Worldinfinite world (kindof)

What’s Next

As mentioned before, this technique only aims at generating an intermediate representation of the terrain, so additional work would need to be done to give it a more interesting and polished look.

And by no mean is this proof of concept devoid of issues. For example, connecting adjacent tiles with the smooth function tends to create a bulge in the middle. That being said, I don’t foresee any of these issues to be a showstopper—they should all be addressable, and it should be possible to turn this approach into a reliable product.

Alas, I ran out of time to take this experiment further and need to refocus on my others, already too numerous, personal projects.

But maybe you’ll be the one to do something cool with it? If so, please share the result!