Friday, June 12, 2020

Surprise!!!

...it's a post about lakes!

In my last post, I talked about a new way of doing rift lakes that works by drawing the outline for the whole lake in one go and then filling it, rather than by trying to make each tile by itself, as I originally did. I wanted to make better rift lakes, of course, but I was also curious to see whether this method would work at all as a possible new approach to the other kinds of lakes.

Just as a reminder: Undiscovered Worlds has four kinds of lakes. At the global level, it has (1) what I refer to feebly as "normal" large lakes, and it has (2) rift lakes. Then, at the regional level, it also has (3) what I refer to equally feebly as "normal" small lakes, and it has (4) glacial lakes.

(3) and (4) are created from scratch at the regional level, because they are relatively small and wouldn't show at the global level. (1) and (2) are much larger and are created at the global level, and must be translated into something that looks reasonable at the regional level.

(I'm ignoring salt lakes here, not to mention wetlands and ergs, because these are all treated as varieties of normal large and small lakes.)

What I'm interested in here is lakes of type (1): very large, wide lakes along the lines of the American Great Lakes. To date, my attempts to make these look reasonable at the regional level haven't been very successful. They've got even worse in the new, rewritten version of UW, with so many overlapping functions trying to correct each other's problems that I don't really understand how they work any more, and they don't look very good. The basic approach, though, remains the same: go through the lake tile by tile, create terrain using the diamond-square algorithm to expand on the terrain elevations given in the global map, and flood any areas that fall below the surface level of the lake. I want to try to replace this with a new method entirely, where we instead calculate the outline of the entire lake in one go.

The first step is straightforward: we mark out all cells that lie on the border of a tile that corresponds to lake on the global map with a tile that does not correspond to lake. That gives us this sort of thing:


(Note that some bits of rivers are still present within the lakes, but they are weird - that is fine as obviously they aren't normally calculated when the lakes are actually there. The lakes are done before the rivers, remember.)

Then, for each lake, using one border tile chosen at random in world generation as our starting point, we go around this outline and select every nth highlighted cell to be a node. To start with I'm trying n=6. If we do this and join up the nodes with straight splines, we get:


Not so different in appearance, though the corners are a little blunted because the nodes aren't in them. But because this outline is now based on the nodes, rather than simply drawn directly onto the borders between the tiles, we can shift those nodes around and hopefully make it all look a bit more natural.

I could just give a random offset to each node, but I don't think that would distort the squareness enough. Rather, I use a running offset. We go round the outline, taking each node in turn, and apply the same offset to each, altering it a little each time. That gets us this:



Already some bits are looking almost reasonable there. Now we add a bit of random variation to each node in addition to the running offset:



The nodes are being connected by straight lines here. With a bit of random curve to them, and some additional jiggling of the other parameters, we get this:


I think that's starting to look reasonable.

After this, it's basically a matter of filling it in, and also adding a few islands. These are done with templates, and I'm careful to ensure that every island is placed such that it has clear water all around it - islands can't overlap with each other or with the lake coast.

With that done, and further tweaking of the various parameters, we get lakes like these:




I think these are OK. The great virtue of this approach is that the lakes are guaranteed to be single bodies of water - there is no chance of them somehow getting split into more than one, as could happen with the old approach. That means that you can't get weird situations where the outlet river leaves a different lake from the one the inlet rivers flow into.

A disadvantage of this method is that it can't handle islands that form in the lakes at the global level - that is, where entire tiles of land exist within the boundaries of the lake. So I need to tweak the global lake creation functions to ensure that those never form. Otherwise, it's not looking too bad.

So with that, the entire functionality of the original version of Undiscovered Worlds is now in place, and refined in many ways. The next stage is sorting out all kinds of appalling bugs that are also in place. After that, some tweaks to various things, and I hope to have an initial releasable version.