Planetfall

Planetfall
Daniel Huffman Uncategorized 24 MinutesGentle readers, I have just wrapped up a fun side project that will be of great interest to a very small number of you. The result of one of the most technically demanding efforts of my career, I am very pleased to share it with you.
Most of you will wonder what this place is, but I hope that, for a few of you, the names clicked into place in your memory. This is the planet Chiron, the setting (and one of the main characters) of Sid Meier’s Alpha Centauri—a computer game from 1999 that has a cult following; I count myself among the cult.
I could go on about the game—which is deep and thought-provoking and has a remarkably beautiful and carefully considered visual language—but I’m here to talk about the map. This project pushed my skills into some new places, so even if you don’t care about the game, I think it’s worth talking about the technical details behind it.
But first, before we get in to those details, I want to mention something that this project helped teach me about the difference between real and fictional maps. Recently, after I’d told someone I was a cartographer, they asked if I mapped real or fictional places. To an outsider, it’s reasonable to put those two things on equal footing. But, to me, they felt like entirely different things. Other than the map above, I stick almost exclusively to the real world, and I observe this to be true for the majority of my colleagues. As I was grappling with this person’s question, I realized that this split might be because fantasy maps require a different (but overlapping) skill set than real maps. If a fantasy or sci-fi author asked me to construct a map for them, I would need to sit down and draw something new from scratch. I’m not trained to work that way. All of my experience centers on manipulating and styling geographic data, not on creating that geographic data.
Some mappers can, and do, handle both fictional and real places, but a lot of us, myself included, are primarily skilled in cooking with ingredients someone hands us, rather than growing the ingredients ourselves. Thus, the only reason I was able to make a fictional map was because there were actual pre-existing datasets I could use to build it.
Before we jump in, I’ll mention that while this map is free to download, it was quite laborious. Your support helps me continue doing things like this, so consider clicking the buttons below, and/or sharing my work with others if you enjoyed it—it’s a big help! PATREON PAYPAL SUBSCRIBE
Getting the Data
The game of Alpha Centauri is played on a map. The program can make up a new, random map for you, but there’s also an official, built-in map of the planet, carefully crafted by one of the game designers, Chris Pine.
The official map is 128 × 64 diamond-shaped pixels. Importantly, each pixel has several attributes: elevation, rainfall level, rockiness, and more. These attributes were the basis for my mapping. I sampled various datasets from the in-game map, and then used them to construct my poster. Though, that was often easier said than done.
I began by tackling the elevation data. While it isn’t uncommon for games (then or now) to have 3D terrain, Alpha Centauri is somewhat unusual in my experience, in that it actually tells you the exact elevation value for each map tile. You can see that in the lower left of the above image. So, I went over the map and wrote down the elevation value of every tile. All 8,192 of them. And then I double-checked them to make sure I had transcribed them correctly. As you can imagine, this took a very long time—many hours. I began this process sometime in 2022 and poked at it occasionally until wrapping up in 2025.
If you look back to the snippet of the in-game map above, you’ll notice that some tiles have what appears to be vegetation on them. This is the game’s way of visually symbolizing a tile’s average rainfall. There are only three levels: rainy, moist, and arid. Fortunately, I did not have to manually sample every pixel to get this information. My version of Alpha Centauri has a mod, not found in the original game, which shows you a thematic map of rainfall level.
I took screenshots of the whole map, and did a little Photoshop work to separate the different colors into three maps, one per raininess level.
Then I brought each into QGIS, and dropped a grid of vector points on top, one per grid square. Each point sampled the underlying raster and absorbed its raininess level. The dataset still needed some double-checking and correcting, since there are other map items in the way that obscured the raininess data. But, I was able to get it done without too much hassle.
I did the same procedure with the rockiness, which likewise comes in three levels—though I ended up not using that dataset.
Finally, there’s the xenofungus, which is one of the native lifeforms on Chiron. That’s the pink ground cover on the map above (though according to a game manual, it’s “crimson”). This dataset is binary: xenofungus is there, or not. There wasn’t a thematic map available in-game for this, so I just brought in the normal game map and sampled it with my grid points and looked for pixels that matched the pink/red range of colors, then did some corrections.
With that, I had all the ingredients I would need to make my map. While the elevation data took me years to finish sampling, the rest was done in a matter of hours.
Projection
Like a lot of game maps, Alpha Centauri effectively takes place on a cylinder. You can travel infinitely toward the left or the right, but once you reach the top or the bottom, you stop; the map/world ends.
Though our map is cylindrical, the planet was certainly meant by the designers to be understood as spherical. Various in-game media, including the game’s title screen, show that Chiron is round. So I assumed that the in-game map was, like most maps, a 2D representation of a globe. But what was its projection?
Every time you build a base in the game, that base offers you control of a certain region, and the size of that region is always the same number of pixels, no matter where it is built. So, it seems reasonable to assume that each pixel represents the same amount of space on the planet—thus, the game map is on an equal-area projection. And given the rectilinear shape of the map (and the diagram above), we can reasonably assume a cylindrical projection. Thus, I assigned the game map a cylindrical equal area projection.
The aspect ratio of the cylindrical equal-area projection varies based on where you set the standard parallel. Here, on this excerpt from my Projection Connections poster, you can see a few named variations on this projection. Each just varies in where you set the standard parallel.
Setting it to 37.4° got me an aspect ratio that matched the in-game map, and that setting also means that we’re using the Trystan Edwards projection. To give you a better sense of all this, here’s how the game map and an earth map compare, under the same projection.
All this projection work actually took place before the data sampling. So, when I say that I brought game maps into QGIS and dropped vector points on them, I already had a projection set up to handle the new datasets I was generating.
Preparing the DEM
At this point I had a projection, and I had a bunch of data in a very low-resolution (128 × 64) grid. Part of my interest in tackling this project was in figuring out how to make a map that was more detailed than the original game map, while still conforming to the known, in-game facts about Chiron. So, I wanted to explore how to turn my 8,192 elevation values into a much more detailed grid.
I tried many, many things. I spent enough hours at it that, in truth, I don’t remember a lot of the details of my attempts. But, after many dead ends, here’s the technique that I finally landed on. I started with the elevation grid—one elevation value per tile, just like we have in the game.
Then I scattered a bunch of random points on it, while enforcing a minimum distance between them, so that they weren’t too bunched up. I ended up with about 1–3 points on each grid tile.
A small number of grid tiles ended up without a point. I added extra points to cover those (I just found the centroids of each of those tiles). I then gave each point the value of the elevation of the grid tile it sat on top. So, I effectively turned my original elevation grid tiles into a scattered bunch of dots, with some elevation values repeated multiple times.
And then I ran a TIN (triangulated irregular network) interpolation to generate an initial elevation model:
Now, if I hadn’t done any of the point scattering, and had simply used my original elevation grid, here’s what it would have looked like:
Notice how it’s much more grid-like and regular. By shifting all the points around, and sometimes duplicating them, I was able to break that grid up, and randomly give more weight to some areas vs. others. The first interpolation looks much more organic than the second, but it still uses the original elevation values.
That was only the first iteration of the process. I actually went back and refined it several times. While shifting all the elevation dots around, and duplicating them, was helpful, it wasn’t detailed enough. I wanted more elevation points, so I could have a finer scale of terrain. To do that, I first did a Delauney triangulation on my randomized points. This just draws triangles between all the points. Then I found the point at the center of each of those triangles.
And then I assigned an elevation value to each of those new points, simply by taking average of the three elevation values nearby. Finally, I added a bit of random noise: I nudged the elevation value of each point randomly up or down by a small amount, so that they would represent new bumps in the terrain, not a smooth continuation of the existing values. Here’s how that looks.
I repeated this process of triangulation and bumping a couple more times (reducing the amount of bumping each time), until I had a very large number of points.
And here’s what that looks like when interpolated into an elevation surface:
This is a big improvement over what we began with. It’s organic and detailed, and while it’s not perfect, it’s a large step in the right direction.
I made a few other adjustments to the field of elevation points before conducting the final interpolation. These were to help match my results with the canonical map of Chiron. Sometimes, due to the nature of the interpolation, or the random noise I introduced, things didn’t quite turn out as they should.
Above, you can see the canonical map, overlaid with a land/water mask from my interpolation. There’s an island in the top-center on the canonical map, but in my interpolated elevation model, it’s actually (barely) joined to the mainland. That occurs simply because I had some elevation points in the area that were above sea level, and some below, and the ones above sea level won out in the interpolation.
Here’s another situation requiring adjustment:
An island on the canonical map is only a couple of pixels wide in my interpolated elevation model. I would like it to be a bit bigger, so that it’s noticeable on the final map.
I manually reviewed the map to find places like these and added a few extra elevation data points, to correct things like closed straits, tiny islands, etc.
I also needed to manually adjust one major feature of the original map: Garland Crater. Here’s how it looks on the canonical map:
But remember, that map is based on an underlying diamond-shaped grid. When looking at the actual elevation values, the crater is much more of a square.
But, the crater is clearly meant to be a circle. The game designers even drew special map tiles to represent it as such. So, I un-squared this region of the map. I did a little rubbersheeting to shift my original elevation points around until I had something more circular.
With manual points added, and the crater circularized, I was ready to do the triangulation and interpolation steps once again. I’m explaining things a bit out of order here—there were many hours of trial and error and revision as part of this whole process. But this is effectively what I did.
Once I had the interpolation, I did a bit of smoothing on it. I do not remember the exact formula—it was a bit like mixing paints, in that I kept playing around until I got something that looked right. I did some focal statistics (mean and median), some line integral convolution via the Karika plugin, and I also added just a bit of Perlin noise. I mixed together smoothed layers with unsmoothed ones, and smoothed again. Again, a very seat-of-the-pants process.
In the end, here’s what I came up with:
Compare that to a simple TIN interpolation of just the original, unmodified elevation points (before any randomization, manual patches, triangulation, etc.):
I think the process of all those adjustments yielded something much more organic-looking.
I wasn’t quite done yet with the elevation model, however. This interpolation was fine for most areas, but the poles needed attention. Given how stretched-out they are on the above map, I knew I would need to re-do the elevation interpolation for the north/south poles using projections that were less distorted in those areas. As an example, here’s the north pole DEM that I came up with, along with the original elevation point locations.
Since a large chunk of the pole had no game data, I sprinkled some mostly-random noise in the middle. And then I proceeded to randomize my point locations and add extra triangulated points, as I did with the main elevation model.
I made separate DEMs for the north and south poles, for use in any future cartography that might focus on those areas. And I also blended them back into the main DEM. With that, my elevation model was done!
Except it wasn’t. As I went through the rest of the mapmaking process, I kept finding small errors: missing lakes, tiny islands, etc. Much like the ones I showed above, except this time I didn’t catch them until I was done with the DEM. I patched those up as best I could, either through tiny changes to the elevation model, or, more often, by manually drawing lakes and islands later on in the cartographic process. Speaking of which, let’s actually start making a map with all these data…
Fun with Projections
For the main map in the layout, decided I wanted to show Chiron using an orthoapsidal (Raisz Armadillo) projection, which also happens to be one of my favorite projections.
I love that it explicitly reminds the reader that they’re dealing with a curved surface. Given that game players are accustomed to seeing only a flat representation, I thought was especially important to try and show something rounder to bring it to life.
I’d never gotten to make a map in this projection before. It’s not available in QGIS, so I had to create my own little projection script. Fortunately, Wikipedia had the formulae for the transformation. That info, plus a little Python knowledge (aided by ChatGPT, as I’m still not super-comfortable with PyQGIS yet) let me start using the orthoapsidal projection.
I ended up modifying the projection. To better fit Chiron’s landmasses, I adjusted the amount and the direction of the vertical tilt (the default is 20°, but I changed it to -10°). I also reduced the curvature on the sides. The downside of the orthoapsidal is that, by showing the curvature that gives such a nice sense of roundness, we lose some areas (Australia is cut off on the above map, as is Antarctica). But, with a clever bit of tweaking, I was able to reduce the curvature. I did this by first horizontally shrinking anything I was projecting:
Then, when it was projected, it took up less horizontal space on the torus, and thus did not extend nearly as far to the sides:
Thus I avoided the severe perspective distortion that occurred on the left/right edges. Notice the right edge of the above image, how the landmasses start to really compress along the edge of the projection as it curves away from the viewer. But, the green version does not do this as badly. By shrinking the landmass, I kept more of it on the parts of the torus that most directly face the viewer. Another way to think about it: In effect, I sort of made the torus larger, in relation to the map.
When I was done with the projection, I stretched things out horizontally a bit to un-do the shrinking I’d done.
My script unfortunately only handled vectors, and I was too impatient to dig in and make the code work with rasters. So, for projecting something like the elevation model, I did a hacky GIS thing and just turned each pixel into a polygon, projected it, and then re-rasterized it. That was not ideal, and meant long processing times, but it worked fine.
At this point, we can probably start breaking down my map layer-by-layer, as I’ve often done in this blog.
Finally, Actual Cartography
So, let’s break down the main map, which was constructed mostly in Photoshop. First we start with the bathymetry.
This is a black and white raster showing the parts of my (reprojected) DEM that had an elevation below zero. To this, I applied a gradient map to recolor everything into shades of blue.
A gradient map in Photoshop takes each pixel in the underlying raster and recolors based on its greyscale value. So, it can (among other things) take a black-to-white raster and turn those pixels into a new color ramp.
Next up: the initial land. I took my reprojected elevation model, clipped off any underwater values, and fed it through Eduard, a program which simulates Swiss-style hand-shaded relief.
I spent a while tweaking the settings to try and find a good balance. Remember, I made some of this information up, because I wanted a realistically detailed relief model. But, I also didn’t want to show too much of the noise I’d added. Once done, I added a bit of a coastal inner glow to help separate the land from the water.
It also had the advantage of hiding the relief near the coastline, so that any nearby mountains gradually fade out as we hit the coast. That gives us a tiny bit of coastal plain. There are almost no flat areas in my map—this is a consequence of the very bumpy elevation values that are in the game. Mountains appear and disappear suddenly, often right next to the coast. I wanted to make the coasts just a little less rugged.
Next up, I used a hue/saturation layer to colorize the relief:
I then sprinkled a little color noise onto it, to help it feel a bit more organic.
I did this just by having a couple of adjustment layers: another hue/saturation, and one brightness/contrast, and having these each masked by a channel that contained some small specks of noise:
Next up was the greenery. Just like the canonical map, I intended to use the rainfall intensity data to show vegetation. First off, I made a copy of the relief and tinted it green, including some noisy variations on those colors.
I did this in exactly the same way I did the earlier tan/brown relief: a hue/saturation layer to colorize it, plus a couple of adjustment layers to add some noisy speckles of lighter/darker areas.
Due to the darker green color, some of the relief was getting lost, so I also added a few more adjustments to emphasize it. These were just more adjustment layers that lightened/darkened the underlying image.
I used the shadows/highlights of the relief in the mask for these adjustment layers, so that they only lightened/darkened the right areas. Here’s a look inside one mask:
Now I blend the green vegetation version of the relief with the original brown relief.
Some areas are still brown (those marked “arid” on the game map) and some are green (“rainy” or “moist” on the game map). But, how did I do this blending? Here’s a look at the mask that controls the opacity of the greenery layer:
On a macro scale, it comes from those rainfall data I gathered a long while back. Remember, each grid tile in the game has one of 3 raininess levels, and I had a point representation of that dataset. I conducted a thin plate spline interpolation on the points (after reprojecting).
That was the basis of my Photoshop mask. But, I also made it somewhat noisy, which you can see if you zoom into the Photoshop version:
This was done using a stack of Photoshop filters. First, I make use of the dissolve blending mode. This is one I’ve talked about before on this very blog. Below, I have a solid black layer, and it’s masked with the rainfall data.
In the dissolve mode, basically Photoshop uses the mask layer to decide the likelihood of a pixel appearing. There are no semi-transparent pixels: they are either wholly transparent, or wholly opaque. So this turns our rainfall data into a scatter of dots.
I took this scatter of dots, flattened it out (with a white background) into a single layer, and then made a bunch of copies. I blurred each copy a different amount, and stacked them all together. And then did some re-sharpening. In the end I was left with a speckly, but soft, noise texture.
And this is what I used to control where the green layer blended into the tan. If we zoom in closely you can see it at work.
I did all this work to ensure that the vegetation layer looked more like vegetation (i.e., individual plants). Though, honestly, a lot of this doesn’t show up on the printed version of the map unless you’ve got a magnifier. But, most people will look at it on screen and so they’ll hopefully still appreciate it.
Here’s what it would look like if I’d just used the original, unspeckled, smooth rainfall layer as a mask:
Now as we go from a rainy area to a dry one, the vegetation just sort of slowly fades out. It doesn’t look quite natural. At the boundary of a desert, individual trees don’t suddenly become transparent. Instead, you still have trees, but you just have fewer and fewer of them. That’s what the speckling accomplishes.
Next up: xenofungus. This is one of the native lifeforms of Chiron. It’s show on the game map, and in various in-game media, as pinkish or reddish. I add this to the map using pretty much exactly the same process as the greenery. I interpolated the point data, smooth it out a bit, make it noisy, and use it as a mask for a reddish version of the relief.
Next up : rivers. There are a handful of these which appear on the in-game map. They are very square, since they’re confined to the map grid. To make these a bit more real-looking, I redrew them manually in QGIS.
For the cartography side of things, I gave a slight taper to the source end of each river in Adobe Illustrator, and then brought them into Photoshop, colored them, and gave them a little bit of a downward bevel so that they seem incised into the land. It’s a tiny thing that no one will really notice on the final print, but you’d be able to tell if I didn’t do it.
I did look at generating a new set of rivers based on my DEM. I ran some hydrological analysis tools, but, due to the bumpy nature of the terrain (both because of my noise, and because of the original game map elevations) I mostly got a lot of endorheic basins and stubby rivers. Drawing my own was easier (and I looked at my relief model to make sure I didn’t cross over any ridges).
That wraps up all the stuff on land. I applied a clipping mask to all this stuff, so that the fungus/greenery/tan relief/etc. only show up where they are supposed to. I also put a little outer glow on the land, to lighten up the coastal waters. Here’s where we’re at right now in our Photoshop stack:
Just a few more layers to go! Next up is more xenofungus. The fungus occurs not only on land, but also in the water. I didn’t want to use exactly the same color, though, so I added the water fungus separately. Just a simple purple layer that uses the same speckled mask as the land fungus, but is also in a layer that keeps it clipped to the water only. It’s set to blend into the underlying water via a linear burn blending mode.
Next up, I apply a saturation boost to the whole map, and add a graticule to help visualize the curvature. The increase in saturation was something I originally did by accident, just moving layers around in Photoshop. But, I liked how it looked, so I kept it.
The result is a color scheme that’s a little outside of my comfort zone. I tend to lean toward less saturated colors, and am noted for my fondness of working in monochrome. But, this is a side project, so it’s a good time for me to experiment.
Next up, I gave things a semi-painted look. I copied the map, flattened it into a single layer, shrank it down, and ran a dry brush filter in Photoshop. This gives things a somewhat painted look that I really like.
Above, you can see both the before and after. In the center, we have the pre-filtered version. Around the outside, you can see the much softer version after the effect is applied. I’ve been meaning for some time to do a tutorial on this technique, and that might happen this year.
The softness was a little too blurry, so I actually mixed it 50-50 with the original map, which I think gives a nice balance of detail and painterly softness.
We’re nearly done with this file. Here’s how it looks at this stage:
Finally, I added a bit of darkening to emphasize the curved surface. I just did a couple of inner shadows to slightly darken the edges (by different amounts, depending on the edge), to give a sense of the light falling off in a way that perhaps suggests the reader that this is not a flat piece.
Labeling
I did the initial labeling work in Adobe Illustrator, as it has significantly better tools for handling type than Photoshop does. When I was done, the labels were ported back over to Photoshop to blend into the map.
I blurred the map under each label, which helps with legibility by keeping the text edges sharper than the background.
I also applied a glow to the land labels and the graticule, which you can see above. It’s just a darkened version of the original map, feathered out around the areas I chose to depict in semitransparent white text. I also added a light glow to the outside of the dark labels. Both of these help with contrast and let me get away with light text on a light background and dark text on a dark background.
I also applied a version of my smart halos technique to further strengthen the glow where needed.
I set all the labels in BellTopo Sans, designed by my friend and colleague Sarah Bell. Finding the right typeface for this map was a bit of a challenge. I didn’t want to go with a serif—I thought most of them looked too delicate for the map’s bold color scheme, and also seemed out of place on a sci-fi map. Plus they wouldn’t hold up very well when set semi-transparent.
The game itself uses Eurostile, but I thought it looked too hard for a map with a soft palette and style.
Most sans serifs seemed a little too solid for the feel of the map. But, BellTopo Sans worked nicely. It has the strength of a sans serif, but also has some strong humanistic elements. For example, look at that colorful lowercase g, the rounded tops of the W, or the squished curve forming the bowl of the a. The whole typeface has hints of a hand-drawn character (it’s derived from old topo maps).
The biggest challenge in labeling was not one that I usually face in my work: I didn’t always know where features were. In the game, features are not always labeled clearly. They are simply bits of white text placed atop single grid tiles.
In many cases, I had to apply my own interpretation to decide the boundaries of ambiguous features. Planetneck, seen above, was the most challenging of these. Does it refer to that finger of water? To the bit of land crossing it? To make matters worse, that bit of land is itself ambiguous. There are several spots in the game marked with these thin brown lines that indicate that they are traversable on both land and water.
So, there are plenty of areas that might reasonably be construed as land or as water. My randomization process used in creating the elevation model made it so I didn’t have to decide which was which, but it also still left me to decide what Planetneck is. I ended up deciding it was the narrow entrance to the long, finger-like bay.
This was mostly an arbitrary decision, but it is supported by the fact that the game has names for a few other straits, so there were other features of this type already called out in the canonical map.
The official map only has 32 names, which is far less than I would usually have for a map like this. But, I didn’t feel comfortable coining any new ones. The choices of what to label are sometimes strange. Only two landmasses are named, and they’re mid-sized islands. The big continents are anonymous. There’s only one body of water called an “ocean,” and it’s smaller than some that are called “seas.” But, it is what it is. Maybe one of the game developers will find this and comment with their thoughts on how this came to be.
Finally, it was time to put this map into a poster. I added a few more, smaller maps, made from the same datasets and with the same techniques. One to show the elevation data more clearly, and two to show the polar regions with less distortion.
I continued to use BellTopo Sans for the poster text. I also added some faint scanlines to the background and the maps themselves.
This is an homage to the game interface (as is the blue color on the title and the frames surrounding the map). I think the scanlines also really do a great job of tying all the items in the layout together.
Wrap-Up
So there you have it! This was one of the most technically laborious projects of my career. Tedious sampling from the game data; lots of GIS work to convert those data into something higherer resolution; the demands of fine-tuning a custom projection that isn’t supported in QGIS; and many Photoshop layers to try and bring everything together with lots of carefully constructed noise.
I wish I could say I did all of these things in the order I presented them above, or as efficiently as I described them. But, the real process was months of meandering and false starts and dead ends.
Now that I have the datasets, I may do more with them. I’ll probably play around in the future with larger scale mapping, zooming in on smaller chunks of the planet. This will give me a chance to explore ways to generate even more realistic terrain that still conforms with the handful of known elevation values. Your suggestions are welcome. One thing I didn’t try was using the rockiness data. I only thought of that after I finished the map designs. I went back and quickly had a look at using that layer as a mask to smooth my elevation model. Fortunately, it didn’t really make much of a difference at this scale, but it would if I zoomed in.
The original DEM also still needs some further cleanup (I had to manually patch a couple of missing lakes and islands onto the map, but I didn’t fix them in the elevation model). Though I’ll probably just replace it with a better one, once I know how to generate something with a bit more realism.
As I said, I could only make this map because I had data to work with. I don’t presently have the skills to sit down and make something like this just by drawing. I’m a manipulator, rather than a generator, of data. But it was fun to try and take those skills and apply them to a fictional location. It took basically all of my fifteen years of growth as a cartographer to get to the point where I could do justice to this game from my past (and present, though it’s been a few years since I played much). As is so often the case, the more I work on something, the more niche its appeal tends to be, but I’m glad to know that there is a specific type of nerd out there who will really appreciate it.
Speaking of, if you’re a nerd who appreciates this, I’ll once again remind you that your support helps me continue doing projects like this, so consider clicking the buttons below, and/or sharing my work with others if you enjoyed it—it’s a big help! PATREON PAYPAL SUBSCRIBE
What's Your Reaction?






