For the past two and a half weeks, I’ve been working on a procedural planet generator.  This weekend I finally polished it up enough to talk myself into putting it online.  You can check it out here.  (It’s heavy on the JavaScript, so I recommend Chrome.  Firefox and IE are slower, but manage.  I haven’t tried any other browser yet.  Also, I’ve never yet delved into supporting touch controls, so it’s pretty much keyboard only.  Sorry mobile users.) (The above link is for version 2, uploaded April 7th, 2015; version 1 is still accessible here.)

Update, October 2015: Worldbuilder Version 0.2.2 has been released, inspired by this prototype. Includes flat map projections and per pixel detail!

A lot of different steps go into generating the planet, utilizing a variety of algorithms and techniques.  They’re not perfect, and some of them are in fact quite finicky, requiring a lot of cautious tweaking of parameters and behaviors.  Some of them are bad enough to make me cringe.  But they work.  At least well enough to make some pretty pictures, and some planets with enough variety that they might be a half decent foundation for some strategy mechanics.  So in case anyone might be able to glean some useful ideas from my work, allow me to delve into some of the details (and include tons of colorful pictures along the way).

This is a long one, so here is a table of contents:

Cylinders and Spheres

A square grid wrapped around a cylinder.

Before I get into the technicals, first a bit about my original motivation.  One of the vague game ideas that I’ve been toying with for a few years is basically a non-competitive sandbox adaptation of a Civilization-style game.  So naturally it can take place on the scale of an entire planet.  It has always annoyed me, though, that standard planetary maps have almost always been cylindrical.  Whether it is a square, isometric, or hexagonal grid, when the map wraps around on the left and right but not the top and bottom, that is essentially a cylindrical world.

A hexagonal grid wrapped around a cylinder.

It’s an effective and simple technique that captures some of the essence of a planetary map.  But certain elements are simply left unavailable.  Missiles trajectories and shipping lanes across the poles, for example.  It also results in the mostly ignorable but still slightly odd feature that circumnavigating the globe while staying very far north or south takes just as long as circumnavigating the globe at the equator.  This is of course not at all true on an approximately spherical world.

So out of this nagging annoyance, and maybe just for the sake of taking up the challenge it posed, I spent time thinking about ways to address this, to get a more spherical map. But a tiled map, keep in mind. Just as with Civilization and so many other strategy games, I wanted to keep the tile system. Plenty of other games have been experimenting with spherical maps that aren’t tile based, and that’s excellent. But I personally know of none that have tried to do the spherical thing while maintaining a strong tile system for movement and other strategic elements. I really like the feel that tile-based games produce, and want to bring that feeling to a spheroidal world.

Tessellating a Sphere

I can easily imagine why I haven’t yet encountered a game that attempts this. Trying to stick tiles on a sphere is obnoxious. The maximum number of perfectly uniform tiles is twenty, in the form of triangles that compose an icosahedron. Anything above twenty, and stuff absolutely has to get non-uniform, in a few different ways. You might have tiles with different numbers of neighbors, such as the truncated icosahedron, a mix of hexagons and pentagons. Or you could have tiles that are all the same type of polygon, but are distorted to various degrees, such as by subdividing cube and then projecting all the points onto a sphere. You’ll have a lot of quadrilaterals, but very few of them will look square. Taking the subdivide and project approach also leads to a few isolated but predictable spots where fewer tiles than normal all touch the same point. With the subdivided cube, this happens at each of the original eight corners of the cube, where only three squares meet at a point instead of four. Or with a subdivided icosahedron, where only five triangles meet instead of six (the next picture further down includes an example of this in the top right polyhedron).

Now it’s true that a game could go ahead and utilize a subdivision technique, and just accept the intermittent irregularities as an acceptable oddity. Any effects they have on strategy, such as the rare but predictably located pentagons being stronger defensive tiles since they can only be attacked from five simultaneous directions rather than six, could just be acknowledged as an aspect of the game, corresponding to nothing in reality. But I was too stubborn to accept this. Luckily, I happened to think up a creative solution to this conundrum last year, and it’s been bouncing around in my brain ever since.

Irregularity Everywhere

The problem with the intermittent irregularities has to do with how predictable they are. If there are a lot of them, they follow a very clear and inorganic pattern. If there are very few, then their isolated nature makes them stand out like a sore thumb. But what if they weren’t predictable? What if they weren’t isolated? What if the irregularities were potentially all over the place, and with little rhyme or reason to their arrangement? Sometimes right next to each other, maybe even in clusters of three or four? Maybe they wouldn’t seem so out of place any longer. Maybe they’d fit into the game mechanics much more naturally, rather than being a crude deviation.

So how does one go about tiling a sphere in an organic way? Inspired by Amit Patel’s excellent page on polygonal map generation, my first attempt was to generate a collection of randomly generated points, uniformly distributed across the surface of a sphere, and then generate the Voronoi diagram based on these points. Unfortunately, I got a bit hung up because most resources on Voronoi diagrams focus on two dimensional diagrams. Adapting it to three dimensions seemed trickier, and it’s harder to find accessible descriptions on how to do this. Complicating things further is the fact that I’m still only wanting a two dimensional diagram, but instead of being in Euclidean space, it is in spherical space. But I did get inspired by a particular two dimensional method I ran across. The core idea is that you take a 2D collection of points and project them onto a 3D parabola (simply set z = x2 + y2). Then you find the convex hull of the 3D points, which, given the nature of the parabolic projection, is guaranteed to include all the points. This convex hull will conveniently be equivalent to the Delaunay triangulation of the points. And the Delaunay triangulation just so happens to be easily convertible to a corresponding Voronoi diagram.

Just as with the parabola, I knew that all my points would be included within the convex hull, so I figured that if I could compute the convex hull, I’d be able to quite simply get the Voronoi diagram. But figuring out how to efficiently compute the convex hull was more difficult than I expected. Again, reference material tended to focus on two dimensions. I did manage to come up with a recursive divide-and-conquer algorithm that seemed to work, but it was ugly. Every step threatened to create a concave pair of triangles, so the algorithm had to constantly guard against that, fixing up the triangle mesh every time it generated concavity.

Once that seemed to be working, I used Lloyd’s algorithm to relax the mesh, as recommended on Amit’s page above, so that my tiles would be more regularly shaped, with fewer really squashed or tiny tiles. But this is where I started to run into troubles. No matter what I did, I couldn’t seem to keep my convex hull algorithm in order; it kept creating strange overlapping or backward facing triangles here and there, sometimes everywhere. I also could not reliably avoid incredibly short edges between tiles, which made it often look like four tiles touched at a single point, even though technically only two tiles did, and the other two were just ever so slightly separated from each other by the two touching tiles. In retrospect, I think I have some ideas of how to avoid those problems while sticking with the same underlying technique, but at the time I ditched it.

Subdivided Icosahedrons

Instead, I decided I would start with a highly ordered mesh, and then disrupt it bit by bit until it was significantly irregular. A subdivided icosahedron was a natural fit, since it did a decent job of minimizing large scale distortions in the shape and size of tiles. (The distortions I wanted are smaller in scale; I still want large scale uniformity.) Initially, I just subdivided each triangle directly, with all of the subdivided points lying on the same plane, and afterward projected them onto a sphere, but I knew that this generated some of that unwanted large scale distortion. I later learned that using spherical linear interpolation, or the “slerp” function, avoids this, so huzzah!

I also didn’t want triangular tiles in the end. I rather like how tiles on a hexagonal map are guaranteed to never touch at just a single point; touching tiles always share an entire edge. Fortunately, it’s incredibly easy to take a triangle mesh and turn it into a map of tiles with precisely this property: Simply treat every point of the triangle mesh as a tile, and every triangle as a corner of a tile. This forms what is known as the dual polyhedron. (It’s also the basis for converting a Delaunay triangulation into a Voronoi diagram.) Here’s a diagram with a regular icosahedron, a second one that has had each edge subdivided into two segments, and a third with each edge subdivided into eight. It then shows how each one can be converted into it’s dual polyhedron.

Subdivided icosahedrons, and the corresponding dual polyhedra.

Note that the regular icosahedron’s dual is entirely pentagons (twelve of them to be exact; it’s a dodecahedron), but the higher subdivisions are mostly hexagons. In fact, no matter how detailed the subdivision gets, there will always be twelve pentagons embedded at fixed locations around the mesh, corresponding exactly to the vertices of the original icosahedron. Time to start adding that irregularity.

Conveniently, one of the functions I wrote while working on convex hulls was exactly what I needed to produce this irregularity. The idea is simple: Find two triangles that share an edge. Remove that edge, and replace it with an edge between the two points that are at opposite ends of the two triangles. In a sense, the edge has now been rotated, and the topology of the mesh has been perturbed. But this is likely to create some wildly obtuse triangles, which in turn make tiles look really ugly. So we relax the mesh somewhat, trying to pull those triangles back into a vaguely equilateral shape as much as we can, without severely disturbing nearby triangles. Here’s a diagram of the process in action, along with how it affects the tiles formed by the dual polyhedron:

Rotating an edge to perturb the topology of a mesh.

Notice how the tiles were originally all hexagons, but after the transformation, two of the hexagons turned into pentagons, and two others turned into heptagons. Using this technique, pentagons and heptagons will always retain this balance (though there will always be precisely twelve more pentagons than heptagons, thanks to the initial twelve). But if we do it on enough edges randomly, the one-to-one pairing will not be obvious at all, with pentagons and heptagons sort of migrating and popping up all over the place. This system also enables me to increase or decrease the regularity simply by modifying how many edges I randomly rotate. Below are three examples of a distorted mesh. The first has very few edge rotations, the second a moderate amount, though you can still pick out the regular hexagonal pattern, and the third has a lot of edge rotations.

Slightly, moderately, and heavily distorted meshes, all beginning with a subdivided icosahedron.

In my particular use of this transformation, I added some checks before approving a randomly selected edge for rotation. First, if the rotation would generate a tile with more than seven or fewer than five neighbors, I rejected the edge and randomly selected another. Second, if the original edge length and rotated edge length were too different, I rejected it on the grounds that I’d be making an already badly distorted segment of the mesh even worse. Third, I had to go so far as to ensure that neither of the original triangles had an obtuse angle along the shared edge. This added some hefty computations to the check, but helped avoid some distortions to the mesh that I found hard to recover from. The third mesh above is pretty much maximally distorted within the bounds of these constraints. Rotating even more edges would not increase the irregularity notably.

As for relaxing the mesh, I didn’t actually do that step after every single edge rotation. Instead, I did a bunch of edge rotations, and then did a single relaxation pass over the whole mesh. I proceeded with more rotations, followed by another relaxation pass. I did this six times (arbitrary number chosen empirically), after which I ran repeated relaxation passes until the mesh passed some threshold of being sufficiently relaxed. Or at least until it didn’t seem to be getting any more relaxed and was simply spinning in circles.

I also ended up using a different method than Lloyd’s algorithm. That algorithm requires the calculation of circumcenters for every triangle in a Delaunay triangulation in order to generate a Voronoi diagram, followed by calculating the centroids for each cell in the Voronoi diagram to create a new Delaunay triangulation. Not only is that a lot of computation, but because of my distortions to the mesh, circumcenters had a tendency to get pretty wild, especially since the circumcenter of an obtuse triangle isn’t even within the bounds of the triangle itself. The result was often the degenerate, overlapping, or backward facing triangles that I had been dealing with earlier, and I was starting to realize that it was the circumcenters that were causing most of this trouble.

Instead, I focused entirely on the centroids of the triangles, which were guaranteed to always be within the bounds of the triangles. For each triangle, I calculated the distance from each corner to the centroid. I compared these distances to a precomputed ideal distance for an equilateral triangle of the appropriate size, given the surface area of the planet and the number of triangles I had. I then pushed or pulled the corners to bring them closer in line to this ideal distance. (I had to underestimate this size a little bit, though, or else it put too much pressure on the mesh, causing some triangles to flip completely around, because there wasn’t enough positive space for them.) There might be better mathematical explanations for why this works, or a different technique that would accomplish the same concept but more efficiently, but this worked well enough so I stuck with it.

Once I had the triangle mesh fully distorted and relaxed, I generated the dual polyhedron by interpreting triangles as tile corners, and vertices as tile faces. (Edges remain where they are essentially, though visually they become more or less orthogonal to their original arrangement, as you can observe in some of the images above.) As mentioned, the general approach for doing this with a Voronoi diagram is to use the circumcenters of triangles, but again I found that centroids worked more reliably. The did produce some visual stretchiness that circumcenters were better at avoiding, but I realized that these stretched tiles weren’t necessarily a bad thing; subjectively, the centroid-based tiles perhaps even look better. And since they also avoided the wild nastiness of circumcenters which caused the occasional tile or cluster of tiles to be egregiously broken, I was elated and decided to get on with the rest of the planet generation.


From a tweet on 2014/09/20

At this point, to create a pretty screenshot for Twitter’s #ScreenshotSaturday, I used a hasty probabilistic flood fill algorithm to create blobs of land and water, coloring one green and one blue, with some random variation to add character. It worked well enough for the ten minutes it took to code it up, but it was far from sufficient for creating interesting geographic formations. I needed real elevations at a minimum.

Perlin noise is a common algorithm used for this type of task, and I have dabbled with it in the past. But for some reason, I was hesitant to go down that road. Although the type of features it generates are definitely complex and interesting, they still tend to have a specific visual flavor that wasn’t quite what I was looking for. Perlin noise tends to be just a little bit too uniformly organic, but I want distinct geography with elements that really stand out. Mountain ranges and island chains, for example, that look like they really belong where they are, rather than just being the accidental byproduct of an oblivious height generating algorithm.

So tectonic plates naturally came to mind, and I was audacious enough to take them on. To be honest, at the time this felt like it might be one of the quicker routes to getting interesting geography, in contrast to a Perlin noise type of approach. That ultimately wasn’t entirely accurate, but the plates did happen to work out impressively well despite me not entirely knowing what I was doing.

First step was to actually define the plates. To do this, I randomly picked a fixed number of starting tiles, and then simply performed a random flood fill on all of them simultaneously. Once every tile on the planet belonged to a tectonic plate, I then calculated a few random parameters for each plate that would represent its movement and other attributes. The first was an axis passing through the center of the planet, around which the plate would rotate, along with a small angle to represent the rate of rotation. This generally represented a drifting movement, though it could produce a spinning type of movement if the axis passed through the plate itself. The second parameter was simply another small angle representing the rate of spin about the arbitrarily chosen center point of the plate. These two parameters together gave each tectonic plate a random amount of drift and spin, which would naturally cause boundaries between plates to have conflicting relative motion. In addition to movement, I randomly assigned the plate to be either oceanic or not, and then randomly picked a desired elevation for the plate. This elevation fell within a particular positive range for land plates, and within a negative range for oceanic plates. (Sure, floating oceans with mile high waterfalls would be awesome, but let’s keep the algorithms grounded for now.)

Tectonic plates, their movements, and the stresses along their boundaries. Click for a larger version.

The next step was to take the motion of plates and calculate the type and degree of stress at each point along the boundaries between the plates. For each point, I calculated the movement of each plate at that particular position. Subtracting the two gave me the relative movement. I then determined the component of that movement that exactly perpendicular to the plate boundary at that location. This corresponded to the amount of relative movement that was directly pushing the plates into each other or pulling them directly away. This I classified as pressure, and it could be either positive (collision) or negative (separation). I also determined the relative movement that was parallel to the boundary and stored this as shear. (Only the magnitude of this movement was relevant, so shear was strictly non-negative.)

With the type and degree of stress determined along the plate boundaries, I then used that information to assign elevations to each boundary point. For points where positive pressure was most prominent, I first checked to see if they were both ocean or land plates. If they were the same, then I treated them as directly colliding, took the maximum desired elevation of the two plates, and then added some additional elevation to create a mountain range. But if one was ocean and the other land, I presumed that the oceanic plate was subducting underneath the land plate, and adjusted my elevation calculations. For shearing and negative pressure interactions, I simply used the maximum desired elevation and created a weaker raised effect regardless of the type of plates involved. For boundaries where stress of all kinds were sufficiently low, I simply averaged the desired elevations of both plates and used that as the boundary elevation.

Elevation calculated from tectonic plate interactions. Click for a larger version.

With the tectonic interactions figured out and boundary elevations calculated, it was time to determine elevations for all the interior points of each plate. I basically used a priority queue to process points one by one, in order of how close to the boundary they were. At each point, I used the distance to the plate’s boundary, the distance to the plate’s center, and the elevation and tectonic activity at the nearest boundary to determine the elevation of that point. Most tectonic activity generated a pretty simple curve of elevation that was interpolated from the boundary to the center. Land plates with ocean plates subducting underneath them had a somewhat different curve, starting off with a lower elevation, quickly rising into a mountain range and then falling again to the plate’s desired elevation. This was inspired by Wikipedia’s pictures for convergent boundaries.

Ultimately, I think I made a enough assumptions and had enough misunderstandings to make geologists facepalm in profuse disappointment. But really, who cares? I have pretty looking continents! Well, the beginnings of them anyway.

From a tweet on 2014/09/22


Coloration of grass, mountains, and ocean based on elevation was enough to again give my a nice picture for Twitter. But was still lacking in terms of deserts, forests, jungles, and other such varied biomes. To conquer this challenge, I decided I would need some air currents to spread heat and moisture around, and to understand how moisture would affected by elevation along its travels as it turned to precipitation. Fortunately, I didn’t feel compelled to tackle a realistic simulation of air currents. Instead, I simply picked some points around the globe and treated those as the center points of around which air would travel, in a boringly circular fashion. Except not entirely boring, because where two circular patterns overlapped, I’d calculate a weighted average to determine the final direction and intensity of airflow at that point. With a careful selection of points on the sphere, along with some random perturbation of their location, strength, and size of influence, I ended up with air current patterns that felt like a nice mix between orderly and chaotic.

From a tweet on 2014/09/25

Adding heat and moisture to the mix was more challenging than I had anticipated. The idea was fairly simple: Do a single pass to generate an amount of heat and moisture at each point on the planet, and then do multiple passes to move the heat and moisture around according to the air currents, until all heat and moisture had been consumed. Turns out that’s a tricky process to get right, especially when one is playing fast and loose with units of energy, distance, area, velocity, and mass. It’s all just unitless floating point numbers to the computer. Being lazy, I did what I had to, squaring and dividing numbers as necessary to make thing more or less work out. But it probably just needs to be rewritten from scratch eventually. Nonetheless, as with much of the work above, it ended up performing its objective well enough for the moment.

Temperature determined by air currents, elevation, and latitude. Click for a larger version.

In my actual implementation, I computed the heat first. Every point generated the same amount of initial heat per area (which I now realize is silly; at the very least, polar regions would absorb less heat from the star). I then spread it around pretty simplistically, each point absorbing as much heat as it could when the available heat passed through, modulated by the air velocity (lower speed allowed more time for each point to absorb more heat). Finally, I used the absorbed heat, elevation, and latitude of each point to determine a final temperature, forced to fit within my own temperature scale from -2/3 to +1, with 0 as the freezing point.

Moisture, determined by air currents, bodies of water, temperature, and elevation. Click for a larger version.

Once that was determined, it was used to determine how much moisture would be available at each tile to spread elsewhere. Land tiles produced no moisture; they only consumed it. Ocean tiles produced moisture according to their area and temperature. Hotter areas evaporated more moisture into the air than cooler areas. (As with the geology, I’m sure I’ve annoyed some meteorologists just now also. They can commiserate together.) The moisture was then spread in a fashion similar to heat, but with some extra considerations for elevation and temperature (higher elevation and colder temperature would cause more precipitation). The result was that air coming inland from the ocean would carry lots of moisture with it. If the air blewws over a large stretch of plains, a lot of moisture was spread far inland, with each point getting a fair amount of precipitation before the air became too dry. But if the air passed over a mountain range, it tended to dump a lot of its rain quickly, and the land on the far side of the mountain range was drier as a result. This is known as a rain shadow.


Now that I had elevation, temperature, and precipitation, I felt I had enough variables to generate some interesting biomes. It’s a function that could be tweaked forever, but I put together a few rules that determined which of a handful of biomes a tile was assigned based on those three parameters. Low elevation hot regions with little precipitation became deserts, while those with lots of precipitation became rainforests. Low elevation temperate regions with moderate rainfall became grassland. Cold regions with little moisture became tundra. High elevations became rocky mountains or snowy mountains depending on temperature and precipitation. And so on. This gave me the diversity necessary to produce the following planets, and is more or less representative of the version that’s publicly accessible on this website.

High detail planet.

Medium detail planet.

Low detail planet, with no distortion of the original subdivided icosadron topology. Look in disgust at that rogue pentagon, just to the bottom right of center.

Code, Libraries, and Other Mundane Aspects

The code is 100% JavaScript, and can be obtained here. It utilizes three.js as a wrapper around WebGL. It’s fairly easy to use, and gave me simple access to the vertex and triangle buffers, which is great for procedurally generated geometry. It’s documentation is incomplete and at times outdated, but a quick peek at the source usually cleared things up. This is my first project delving into the realm of WebGL, and I have been pleased with the experience.

I continue to use jQuery for my HTML manipulations. This is the first time that I’ve used HTML as an overlay on top of a canvas, and it makes me happy how such a technique makes it easy to transfer my HTML skills over to the process of making a UI for a game-like environment. And jQuery extends that happiness even further.

I continue to wish Lua had become the language of the web instead of JavaScript. For one, the inability to use an object reference as a key in an object used as a dictionary is frustrating. But I’ve adapted my designs to compensate for this, so I didn’t feel severely affected by that on this project (though I did notice it). What really got me this time was JavaScript’s utterly single-threaded execution model. Initially, all the processes described above executed within the context of a single function generatePlanet(). Once things got complicated enough, this would cause the browser to kill the page because it presumed the page was permanently hung. It also meant that I had no hope of implementing a progress bar, let alone a way to cancel an in-progress generation of a planet.

Of course, Lua doesn’t support threads out of the box either, and would likely have similar single-thread limitations if it were implemented in browsers. But what it has had for a long time are coroutines, something that JavaScript may or may not get to some degree in the indefinitely distant future. (And who knows how much additional time it’d take for Internet Explorer to support them.) With coroutines, I could have kept my code clean, acting like it was single threaded, while throwing yields in at reasonable points to allow the browser to get on with its own activities before returning control back to my long running execution.

Instead, I ended up writing my own utility for handling this. At least JavaScript does support functions as objects, anonymous functions, and closures. This allowed me to set up a system where each function can either do work, or it can register additional functions that together do the work. Each one can run either once, or run repeatedly as in a loop until all of its work is complete. Each one can also indicate the relative proportion of its own work compared to its immediate sibling functions, as well as how far into its looping it has gotten (assuming it knows; sometimes it’s hard to estimate progress toward the end condition). This allows for reasonably effective progress calculations even for a very heterogeneous computation. This utility is named SteppedAction in my source, if you want to take a look at it.


I have finally worded myself out, so that’s pretty much it for this blog post. But not for the planet generator. My next focus will get back to games, as I attempt to use the generator to flesh out and prototype some of my game mechanic ideas. Although this was originally conceived for use in a civilization sandbox type game, I think I’ll first look into something more along the lines of combining Civilization’s city placement strategy with the simpler and faster paced strategic gameplay of the Warlords series by Steve Fawkner. I think I need to keep my grand visions under control, and target more tenable objectives before I head full steam toward to lofty goals. Even still, no promises on how long it’ll take me to create something I’m ready to show; this stuff can’t be predicted.

I might be tempted to work on a version 2 of the planet generator, though. Optimize some of the algorithms, fix some of my mistakes, add rivers to the mix. Again, no promises, but you might as well keep an eye out (my RSS feed is ready to assist). Follow me on Twitter (@AndyGainey) and you’ll likely see preview shots well before I put something up on my website.


Comment by Josh — 2014/10/01 @ 11:51

I must say, I played around with it and thought it was really fantastic. I love the level of detail, with wind patterns and tectonic plates, and the day-night cycle is a very nice touch – frosting on the cake, if you will.

“With coroutines, I could have kept my code clean, acting like it was single threaded, while throwing yields in at reasonable points to allow the browser to get on with its own activities before returning control back to my long running execution.”

Have you looked into promises? It really has helped clean up some Javascript code I had been working on, making it a lot more readable.

Comment by Yahiko — 2014/10/04 @ 00:53

Pretty impressive results.
Your planet generator is a bunch of knowledge and work.

Comment by Andy Gainey2014/10/04 @ 08:37

@Benoit: I remember reading a bit about them a while back, and was probably discouraged by poor browser support at the time. I see that the support is much better now, but I had forgotten all about them. Thanks for the reminder! Time for some more learning. Always more learning. :-)

Comment by Oz — 2014/10/11 @ 21:37

This is awesome! It was a very interesting read, and the results are great. I can’t tell if you’re going to make a game or start your PhD in procedurally generated content.

You’ve inspired me to take some time and try my hand at my own planet generator. Keep up the good work.

Comment by Andy Gainey2014/10/13 @ 10:08

@Brandon: Yup, remember reading about generators. They absolutely would do. I just don’t know about their current level of support across browsers, the ever present annoyance regarding new HTML/CSS/JavaScript features.

Glad you found the links and ideas useful.

Game mechanics are in the works right now. Had to spend some time massively refactoring code, though, because I was getting swamped by the excessive entanglement of interface logic, rendering logic, and game logic. Spaghetti itself doesn’t get knotty, but spaghetti code most certainly does.

@Oz: Haha, I wonder what I’d end up with in 5 years if this was the beginning of a PhD focus. :-)

I’ll be interested to hear about where the inspiration leads you!

Comment by John — 2014/10/15 @ 22:42

Neat stuff! For shiggles I’m porting it to C# to play around with (mostly because I can’t stand working with Javascript). I did find one possible bug so far: about halfway down the source code (sorry, don’t have a line number) you have:
corner.precipitationRate *= 1 + (1 – Math.max(0, Math.max(corner.temperature, 1))) * 0.1;
I think that should be a max/min construct.

Anyways, once I get the port working I plan on toying around with the weather generation: start it out with heat and prevailing winds based on latitude, and then iteratively modify based on terrain (elevation, albedo, etc.).

Comment by Andy Gainey2014/10/19 @ 15:04

@John: Awesome, and best of luck with the port! That most definitely is a bug. The effect would be colder regions don’t increase precipitation, and particularly hot regions could reduce precipitation more than I intended. Since it was only multiplied by 0.1, the effect is probably minor. But I bet I tried fiddling with that 0.1 at some point and experienced frustration when I couldn’t seem to make temperature matter.

If you need any assistance with any bit of the code, let me know. It’s obviously not well commented and has some crazy undocumented math in places. And some is just downright silly; like I realized later that I could calculate a triangle centroid simply by averaging the three corners, rather than messing with bisected edges and stuff.

Comment by Bad_Syntax — 2014/11/30 @ 20:11

This is amazing, seriously. I’ve been looking for a good planet generation system for well over 10 years, and so far, this one is the best.

Any chance of an EXE that could output the data into a flat icosohedron so I could use this as a random planet generator? I suck at javascript so converting this to C# or VB.NET is a bit beyond me, but I would love to attempt it.

I have had a pet project for many years I’ve started multiple times and never finished. That project is basically mapping out entire sci-fi worlds, kinda realistically, with altitude, biomes, temperatures, winds, and hopefully weather patterns. I wasn’t looking for anything super cool 3D, just something where I could say “you are fighting on planet A, at coordinates XXXXX.YYYYY, which is at its aphelion orbit, and there is currently a rainstorm on planet”. I’ve gotten some progress where I took an already made planet, broke it into 10km squares, and then could navigate it down to 25m hexes or so, but I was never real happy with the results… you can see a pic here: http://3.bp.blogspot.com/-NEtqzsBR2Is/T3a9JLDziWI/AAAAAAAAAFU/m5ggHwUE5Qg/s1600/World.png

Anyway, great job, I look forward to seeing what else you make along these lines!

Comment by Victor Tramp — 2014/12/01 @ 16:28

you should check out the code in http://pioneerspacesim.net

a great planetary generation adventure if there ever was one.

also, get hired by Cloud Imperium. They will have planets to generate no doubt. =)


Comment by sectorone — 2014/12/01 @ 20:45

Nice work. I recently built a noise-based planet generator myself (you can check it out at http://exoplanet.photos/) but that approach has its drawbacks. I really like the tectonic plate approach.

Comment by Ed Allen — 2014/12/02 @ 00:02

Fascinating stuff, especially since I’ve been working on a graph based dungeon generator for paper and pencil dungeon crawling in JavaScript lately myself. As I work up into the outdoors it might be really fun to hook into a copy of your code to place stuff on a world map.

The Warlords series are old favorites in my family too.

Comment by David — 2014/12/02 @ 07:20

Extremely impressive. What would you say is your math background?

Comment by Aaron K. Clark — 2014/12/02 @ 10:05

Came here from reddit.com/r/programming

This is probably the coolest thing I have read about in years. Have you thought about submitting this to ACM?

Comment by Niall — 2014/12/02 @ 11:53

This is magnificent, and I have a fair idea of how complex it is, having done it in Java in a very similar procedural way. I’m an ex-geologist turned coder, and your plates are fine by me – in one sense, knowing more is a handicap, because you can’t rest until you’ve done a variety of pointless things!

My planet producer eventually outputs to mySQL or text files the following for a 91×91 grid:


It generates civilisations on top through a rather similar approach to your tectonic plates. The tectonic plates I did were slightly different as a result of knowing too much geology – so I generated a set of small Archaean plates, whacked them together, then produced some more plates, chopped them up etc…gives me old mountain ranges like the Caledonides (Ireland, Scotland, Norway, Appalachians) as well as new ones like the Himalayas, and allows me to generate subsurface geology and soil types.

I love this – particularly the display, which mine was weak on – it might inspire me to pull out the old code and give it a going over.

Comment by Bob Aman — 2014/12/02 @ 17:16

This is really fantastic stuff!

John, I’d be interested in helping out w/ a C# port BTW, with an eye towards getting it going in Unity. Ping me on GitHub if you’re interested (sporkmonger).

Andy, any chance of licensing this under something OSI-compatible, since it’s obviously something a lot of us are really interested in taking a crack at working with? Apache 2.0 perhaps (which is pretty close in spirit to what you’ve already got)?

Comment by Simon Heath — 2014/12/02 @ 17:47

From a geologist, your geological simulation isn’t terrible. The only thing that stood out was that diverging plates should create rift valleys between them rather than raised topography. There are some special cases to handle things like island arcs and volcanic mountain ranges that might be nice to include for verisimilitude, and you might want to add a bit of an erosion effect so that places with heavy rainfall and high elevation end up with lots of rivers and lower elevation than they might otherwise have, possibly carrying material out to the end of the rivers to form deltas. (You know, if you ever feel like implementing rivers.) Still, if you don’t want to generate an entire geological history for a planet, that’s about as good as you can get. Certainly better than anything I’ve done.

Comment by bo_knows — 2014/12/02 @ 17:53

Wow, I missed the demo link in the first paragraph. Sigh. Please delete my shameful comment above :)

Comment by Ronald Stepp — 2014/12/02 @ 20:22

Good Lord, this is amazing. The only thing I would beg and grovel for is some way to create a flat map projection so I can carry the generated planet into my games and add further detail via photoshop.


Comment by Serdain — 2014/12/02 @ 22:59

This is excellent! I would love to have a way to add in landmarks/etc by Hex for use in my Pen and Paper tabletop games.. as well as perhaps a save/print to 2d option for use at the actual table.

Have you considered a few minor changes to make it an excellent RPG World Generator tool?

Comment by Travis — 2014/12/03 @ 03:35

Interesting and fun initial concept, and the solution is fantastic. By anchoring each aspect of the planet generation on physical processes, you achieved a result that is somewhat believable and looks great! I thought that was very cool. It seems like you could almost squeeze some kind of journal paper out of this idea with a little more work.

Also, your writing was clear and concise, which helped to make this post an enjoyable read. Good stuff.

Comment by Surlebecque — 2014/12/03 @ 03:51

I’ve dreamt about this for Unreal Tournament 2004… The future of gaming sure looks fine.

Oh, and for other purposes of this technology, of course.

Comment by Andy Gainey2014/12/03 @ 09:10

Thanks for all the great feedback everyone!

@Bad_Syntax, @Ronald, the request for a flat projection and/or some way to output the data is a common one. I’ll definitely be prioritizing such features if I ever get around to doing a second iteration of this.

@sectorone, those planets do look really cool. I like the increased variety, really great for a 4X space strategy style game.

@Zellyn, Poisson-disc sampling does look promising. I’d seen it before, but was not familiar enough with it for it to occur to me naturally while looking for solutions, so thanks for the reminder!

@David, I have an undergrad minor in math from 2003, though most of the math that I utilize in programming was either learned before college, or self-taught. Or both: I recall learning trigonometry so that I could program a wireframe 3D renderer in QBASIC. (I only kind of sort of succeeded.) This was obviously before I learned about linear algebra; oops. :-)

@Anonymous, yeah, I’m looking forward to widespread adoption of the Map and WeakMap objects.

@Aaron, @Travis, publishing something like this in a journal never even crossed my mind, but it’s an intriguing thought. I’m not too involved in the academic space so the notion is admittedly a bit intimidating. But if I do get around to working on a second version of this, I’ll keep the academic aspect in mind for sure.

@Niall, @Simon, thanks for the geologist encouragement! :-) I would very much like to do rivers. I tried briefly, but I ran into issues with elevation distributions and a lack of any hydrology effects, so I chose to limit my scope creep and call it sufficient for now. If I come back to this, I’ll definitely want to refine my tectonic plates and the generation of elevation some, and actually get a basic hydrology system in place, so thank you for the pointers.

@Bob, the license I chose was the Fair License (http://opensource.org/licenses/Fair). But I’m honestly not an active participant in the open source world, so the use of and interaction among licenses still feels a bit foreign to me. If there’s anything else I need to do to clear up the license situation, let me know. Heh, I was initially just gonna use the more crude WTFPL (http://www.wtfpl.net/), but decided to use something more professional and listed on OSI’s website.

Comment by BJ Altman — 2014/12/03 @ 15:02

I’ve only played with it a bit so far. I enjoy the quality and attention to details like tectonic plates, but one thing jumped out at me as a quirk: The map seems to be twice as big as the sphere. I made maps at all three default detail settings, and I found that scrolling/rotating from the south pole to the north pole took a 360 turn instead of a 180.

Comment by Andy Gainey2014/12/03 @ 15:33

@BJ, I think that’s just an artifact of the aspect ratio and position of the camera. Even when zoomed out, you can’t see a full 180° of the planet surface. A rough estimate is that you can only see 120° at a time. My camera parameters could probably stand to be tweaked. Might even be better off using an orthographic camera rather than a perspective camera.

Comment by Thomas — 2014/12/03 @ 15:34

Hey, I love this program, but is there any way to export the final image?

Comment by Andy Gainey2014/12/03 @ 16:31

@Thomas, for the globe as presented, I’ve just been using ‘0’ or forward slash to hide the use interface, and then the Print Screen key to copy the image to edit in an image editor. But if you’re looking for a flat projection like a map, then that’s regrettably an oft requested but unimplemented feature presently.

Comment by Kelvin Green — 2014/12/03 @ 17:03

I was thinking about the irregularity of the tiles and how the effect might be improved by matching it with the environmental characteristics of a region.

If you were to determine biomes, plate tectonics, and terrain information prior to creating the irregularities, you could pinpoint the production of irregularities so that they occur more or less frequently in a region of the map depending on the environmental characteristics of that region. So an area with lots of hills and mountains might have more irregularity in the tiles than an area of flat grassland, seas would be almost entirely uniform.

Comment by Ryan — 2014/12/03 @ 17:29

Hi Andy!

I was just wondering if you had any plans to emulate cloud generation as well? I am working on a mod for Kerbal Space Program (check the game out!), and I was hoping to add procedurally generated clouds to the mix. The problem is that perlin noise doesn’t generate a good world-texture for clouds.

I was thinking of doing something similar to your process, albedo map + sunlight = heat map; heat map + ocean map = humidity map, heat map + humidity map = cloud map.

Comment by James Livingston — 2014/12/03 @ 20:54

Very cool, it makes me want to go and play with the idea too, which I last did a few years ago.

Kelvin: I wonder if you could get the idea of irregularity based on environment working by doing tile refinement. First generate a lower-density mesh and environemt values, and for each tile generate and store a RNG seed value. To increase the resolution of a tile, seed the PRNG with the parent tile’s seed, and then use a similar process to generate irregular sub-tiles, based on the environment values of the parent tile and it’s adjacent ones.

Storing the seed when you generate a tile means you could repeatably generate sub-tiles for the parent tiles in any order, handy when you want to zoom in. When doing refinement, you usually end up with artifacts based on the borders of the parent tiles, but I wonder the the irregular tiling would make that less of an issue.

Comment by Robert de Forest — 2014/12/04 @ 11:58

Do you have a project for this on github or anything yet?

Also I’m pleased that you chose my favorite license. :)

Comment by Ryan G — 2014/12/06 @ 12:35

I saw this a while back on Reddit and wanted to use it for a while since I fought with hex based planets unsuccesfully in the past and this looks really awesome, even a bit overkill with all the weather simulation (but I love overkill). I’m using it now for my Ludum Dare game, I separated the code into generator/planet/mathy utility functions to make it easier to handle as part of the game loop, I’ll be happy to share any modifications once I’m finished. http://ludumdare.com/compo/2014/12/06/lets-put-this-on-ice/

Comment by Pierrick — 2015/01/24 @ 16:52

@brnkhy Wo, neat

Andy, this is just awesome !

Comment by Mr. Cowles — 2015/02/26 @ 10:28

I think this is a wonderful concept! I am a high school biology teacher I was looking for a fantastic world map generator that takes into account plate tectonics. I have only been able to access your program once; otherwise it stalls on the options screen. I’m using Chrome. Any help would be appreciated.

Comment by Andy Gainey2015/02/26 @ 12:53

@Mr. Cowles, if you open up the JavaScript console (Ctrl+Shift+J in Windows, Cmd+Opt+J for Mac I believe), there might be a message indicating what’s wrong, or at least some additional information that I could investigate. If you don’t see anything useful, try refreshing the generator page while the console pane is open.

Comment by Bree — 2015/09/21 @ 10:51

Just a wonder. I wish I could move this into a stand alone system generator , so it would be useful for SciFi rp . no real system but would like to see it go that way too..

Comment by MacK — 2015/11/18 @ 06:57

I was doing some research and google pointed me here.
One word: AMAZING.

I usually write WebGL experiments on codepen and I am up to write a procedural galaxy generator just for fun, I would like to ask you for the permission to reuse your script (instead of writing up shaders, which I am not fully comfortable it would be the right thing for planet generation), not for commercial use and full credit to you of course.


Comment by Robert Babiak — 2015/12/02 @ 10:00

I was wondering if anyone has converted this to c++ or python? I am looking for a terrain base to do some simulated civilization on, and this looks good.

Comment by Robert Babiak — 2015/12/02 @ 10:19

Also have you put any thought into higher resolution terrain generation within each hex?

Comment by Andy Gainey2015/12/04 @ 09:56

In Worldbuilder 0.2.x, I interpolate continuously between the elevation values at each vertex, and add some turbulence (based on Perlin noise) to make it more interesting even when zoomed it. It’s an okay interim solution, but there’s definitely more I hope to do with elevation in the future.

Comment by Robert Babiak — 2015/12/04 @ 10:53

Ran across this, and am wondering Why?

1049: borders[i] = new Border(i, 2, 4, 2); //edge.f.length, mesh.faces[edge.f[0]].e.length + mesh.faces[edge.f[1]].e.length – 2, edge.n.length

Why the hard coded magic numbers?

Comment by Andy Gainey2015/12/04 @ 11:09

Those were just some hard constraints that other parts of the code depended on. Since I knew ahead of time that every edge would have exactly two faces, four neighboring edges, and two nodes, I avoided all the lookups of those values. I guess I left everything as dynamically sized arrays anyway because it made the code more consistent among borders, corners, and tiles. Also, given that it was a two week prototype, my design thoughts were constantly shifting, and stuff that just worked tended to be left as it was.

In retrospect, I was essentially approaching the winged-edge data structure without realizing it. That, or the half-edge variant, is probably what I’d prefer to use if I were rewriting this. (Which I’m essentially doing in the course of making a collection of utilities for the Unity Asset Store, and the winged half-edge structure is indeed what I’m using.)

Comment by Anonymous — 2016/01/14 @ 09:59

Thanks for this article, this is really really nice, I’m working on a similar project and your article will save me many nights :) . Thought it’s a shame that the code is uncommented, but with your article I hope I could understand most of it.

Comment by b — 2016/01/25 @ 13:48

Is the temperature measured in Celsius or Fahrenheit?

Comment by Andy Gainey2016/01/25 @ 13:55

Temperature is a made-up scale, really, but it’s probably roughly equivalent to Celsius divided by 100. 0.0 is definitely treated as the freezing point of water. The blue/yellow/red coloration scale bottoms out at -0.67 and tops out at +1.00, with 0.00 being the transition point between pale blue and bright yellow.

Comment by Pranav Sathy — 2016/03/16 @ 21:07

Hey Andy,

I have been working on a “port” or version of your code for Babylon.JS. I managed to get the hex’sphere to render , however for higher subdivisions it takes the order of minutes to get working. I am not entirely sure why it takes so long, I was wondering if you could help me figure it out. I took your Icosahedron generation functions, but my “reciprocal” function is quite different (however benchmarking showed mine to be faster than yours without asynchronous execution). My code is located at :


Please tell me what you think, thank you!

Comment by Harry Legg — 2016/03/30 @ 14:02

Brilliant, this is something very similar to what I wrote for my dissertation back in 2007/8. Only yours is a lot more thought through and complete. I am always considering revisiting the subject, my main issue is finding the time. Lately I have picked up Three.js and started using it, but I have so much on I haven’t had much success lately. Anyway, its nice to see the concept working.

Comment by Kirby Urner — 2016/05/08 @ 14:48

Most exciting. I scour the Web for “hexapent global data displays” i.e. the hexagons + 12 pentagons look. I tend to think of a canonical tiling wherein the irregularities come from further subdividing hexagons / pentagons into a much smaller mesh (“pixels”) i.e. if the grid resolution is high enough, then staying with a pure hexapent is consistent with showing even highly irregular data e.g. geographic landmasses. A good primer on all this is http://www.dividedspheres.com.

Comment by JK — 2016/06/11 @ 16:57

I’d really love to see some way of increasing the density of the map. My computer could handle the generation. It seems as though there isn’t enough detail to look like an entire planet. Imagine the map of a small moon compared to a rocky planet the size of Jupiter with not 7, but hundreds of full continents. That’s the kind of scaling feature I’m looking for. I have a need for quite a massive map.

Comment by Durakken — 2016/06/19 @ 09:43

So I’ve messed with the demo and here’s my feedback…

No idea what the following 4 things mean: Grid Disruption Iteration, regularity, Major & Minor Turbulance Scale

Plate Count… The way you have it doesn’t work good imo, because the world isn’t divided up like that. The world has several Major plates and then a bunch of minor plates. What you have is equal area plates that all have the same effect. It’d be nice if you changed this to have a number of plates that are Major and a number that are Minor.

Ocean Percentage… I like being able to turn this up and down freely without regenerating the map so that I can refine what I’m looking for and also so that I can get a look at how things look without the water being there. Sometimes this happens and sometimes it doesn’t. I imagine it’s some sort of bug that causes it to regen?

Moisture Modifier… I’d change this to be “rainfall” and give a number that is more in line with global average rainfall so that it’s not just some weird perecent of “wetness”

Heat Modifier… This is obviously off from what it should be realistically, but that’s ok. The main problem I have is that you can’t create a world without icecaps and the icecaps that are generated all have this weird dip. Also at the setting of 1 it is far too large for what I’d expect, which is Earth standard (though it’s changing ^.^) to get anything remotely to where I like it I have to put it at 1.75, but that still has issues with that dip.

Both Heat and Moisture Modifiers would be nice to have the ability for text input.

With regards to the Map output and projections…
I’d like to be able to move the flat maps so that I can center on any point.
Also a hemispheral map which has both hemispheres on it would be nice so I could get both hemisphere of a spherical map at once.

Rivers… Considering you know rain where there is rain and the height of each area is, it’d be nice if it would map rivers/lakes out.

In the Help menu or perhaps a setting you could include how biomes look and might be alterable. Some people might prefer a black ground or a red foliage. It’d be a nice option to be able to pick the colors, or at the very least be informed what some of what I am looking at is without guessing. Most of it is easy to figure out, but there is a brownish swirly biome that I have no clue what that is.

And lastly.. It would be great if I could put in a seed and get the same result, rather than if I don’t export something, which I don’t know what, and hope to maybe get something similar. This would also allow for people to adjust parts, and get a more stable result rather than something completely different from what they wanted to just tweak a bit.

Comment by Smithk623 — 2016/11/08 @ 18:47

I really like your writing style, good information, thankyou for posting D. kebgkacdbgekgkad

Trackback by molodezhka4sezon212223seriya2016/11/19 @ 09:08

Молодежка 4 сезон 21 серия 22 серия 23 серия 24 сери…

Молодежка 4 сезон 21 серия 22 серия 23 серия 24 сери…

Comment by Smithe684 — 2016/11/29 @ 00:52

I do trust all of the ideas you’ve presented in your post. They’re very convincing and can certainly work. Nonetheless, the posts are very short for beginners. May just you please lengthen them a bit from next time? Thanks for the post. adffgcdkeceakaef

Trackback by pic2016/12/02 @ 18:00

…Kar��yaka Eskort

[…]you made running a blog glance[…]

Comment by for — 2016/12/09 @ 05:12

What is the website that means it is easy to understand podcasts and blog sites? I don’t get an iPod, does that make any difference? .

Comment by Smithg64 — 2016/12/21 @ 00:44

Awesome article post.Thanks Again. Much obliged. ddkcddeebfddkbdd

Comment by Smithd125 — 2017/01/13 @ 04:13

Definitely, what a fantastic website and informative posts, I definitely will bookmark your blog.All the Best! fbddefkcckddebdk

Comment by without — 2017/01/19 @ 19:42

I am just seeming both for blog sites which give independent, nutritious commentary on all difficulties or blogging sites which have a liberal or droppedwing slant. Thank you..

Leave a comment