Saturday, April 1, 2023

Cubular balls

After the last release version of Undiscovered Worlds I'm more or less at the point I was nearly four years ago, when I got as far as I could with the original version of this project in AGK. Back then I wondered which of these three things to do next:

(1) Create a new level of detail, so one could zoom in on the regional maps and expand them.
(2) Start populating worlds with procedurally generated life forms.
(3) Rewrite the entire thing in a more suitable language.

I went for option (3), and the current state of UW is the result. It's much better than what I had then - faster, fewer errors, more options and variety, and much more detail and realism (within reason). So what next?

Options (1) and (2) remain on the to-do list, and I was initially going to get cracking with (1). This would add "local" maps, which would have the same relation to the regional map that the regional map does to the world map. But before doing that I thought I'd try a bit of more fundamental experimenting with the program.

One obvious limitation of UW as it stands is that it deals only with flat maps. I wrote right back at the start that creating spherical worlds is theoretically possible, but I wasn't going to try it as it's too difficult. But I've always wished I could have done it, and this limitation is more apparent now that worlds with different climates are possible. That means that there's no guarantee that any given world will have ice caps at the northern and southern edges of the map, which in turn makes it harder to hand-wave away the terrible warping that happens if you try to wrap one of these rectangular world maps onto a sphere.

So I thought, having come this far, I might as well at least try to see whether I could rewrite the program to work with spherical worlds. If it doesn't work then I can just give it up and continue with the flat maps as before, but it might be interesting to see what can be done.

So after a fair bit of tinkering, and wrestling with the horrors of OpenGL textures, I have this:


This is my existing diamond-square algorithm, which forms the basis for a lot of the global generation, but rewritten to map onto a sphere. This wasn't easy, but it works!

The basic idea is to represent the world as a cube. Each of the six faces of the cube has its own terrain map. When the cube is displayed, we warp each face to form a sphere shape:


This works because each face of the cube is not a single plane object but a grid of 16*16 of them. We warp the cube by taking each vertex of each plane object and transforming them using the extremely useful formulae found here. Here's what it looks like if we show all the sub-faces:


So our sphere is actually a polyhedron made up of 1,536 squares, which are distorted to varying degrees. As you can see, this projection keeps all of the subfaces roughly the same size as each other, but distorts the shapes towards the edges of the faces and especially at the corners. An additional irregularity is that where most of the squares have eight neighbours (including the diagonals), the ones at the corners have only seven.

The visualisation is useful because each of those squares also corresponds to a single regional map. Exactly how the regional map will work with this remains somewhat unclear, particularly when it comes to navigating round the corners, but I'll cross that bridge if I come to it.

In any case, the distortion involving in warping the cube into a sphere is much less than you get if you try to wrap a rectangle onto a sphere. In the latter case there are two points of distortion - the north and south poles - whereas with the cube there are eight - the corners. That shares out the distortion more evenly so that it is much harder to see.

The next job is to see if I can adapt the rest of my global terrain (and climate!) generation algorithms to the spherical maps. I'm fairly sure it should be theoretically possible, but that doesn't mean it's practical to do, so we shall see... If not, back to the flat maps!