Monday, February 11, 2019

Coasts!

How much time, toil, and failure the word "coasts" evokes for me! Writing this account of the work I've done to date on Undiscovered Worlds is an odd experience, because I'm missing out so many failed attempts and false starts, and complete impasses. The coasts are a case in point. I despaired of ever getting these to look right, and at one point decided trying to do it fractally was simply impossible, and started designing coastal tile sets.

Even stripping back UW as it currently is to try to show more primitive versions of its outputs misses out a lot. Take the point we reached in the last post:


In fact, the first version of the regional map with diamond-square was far worse than this - it was a mess that barely reflected the shape of the land, with enormous numbers of inland "seas" and fragmented islands covering the ocean. So what you see here already reflects a lot of tinkering with the settings of the diamond-square algorithm, but it's probably a good thing that we've skipped over all of those.

The main moves I took to make the coasts look better were:

(1) Adjusting the distortion value of the diamond-square algorithm, i.e. the amount that it displaces values by. Higher values lead to bumpier terrain, lower to smoother. I lowered it overall, but particularly on coastal tiles, to avoid having too-jagged coasts all the time. For this to work, I also adjusted the global map-making functions to make the sea at coasts somewhat shallower and the land somewhat lower too, to create something like the right amount of smoothness. If the sea is too deep and the land too high, the coasts are all straight edges as the diamond-square algorithm has no wherewithall to displace the values by. If the sea is too shallow and the land too low, it gets far too crinkly, with lots of islands (OK) and isolated bits of inland sea (not OK).

(2) Adapting my flood fill function to remove all remaining bits of inland sea. This represents something of a failure on my part. I wanted to ensure that every tile, as far as possible, is self-sufficient. That should mean that if any sea is present in the tile, the program is able to work out - without having to look at other tiles - whether that bit of sea connects up with the main ocean (in which case it's OK) or doesn't (in which case it must be filled in). I spent a lot of time trying to develop algorithms for UW to be able to work this out, but most didn't work and those that did made the coasts look very unnatural. So in the end I gave up and applied the flood fill routine to the whole regional map, after the tiles had all been done. Any area of sea that is fully contained within a single tile, or only two tiles, is considered an isolated pool and removed. Others are allowed to remain. This isn't an elegant solution to the problem, but it does work.

(3) Creating a new method of doing coastlines, which I call landfills. Basically, the methods described above resulted in quite jagged coastlines. The coast tended to form bays in each tile, with the arms of the bay at the tile edges. While fine in isolation, this looked a bit odd overall. So I added a function which fills these bays in. Imagine a tile that has land in the northern half (roughly) and sea in the southern half. The function locates the points on the eastern and western edges where the land and sea meet. It then draws a line between them, and uses midpoint displacement to make it wobbly. Any points to the north of that line that aren't already land are raised above sea level.

The idea of making coastlines by directly drawing them with fractals - rather than by allowing them to emerge from an overall fractal terrain - isn't new. But it has difficulties, such as how to stop the coastline from refracting back over itself. My method works quite well because the fractal coastline is drawn only at the level of the tile, that is, a 16 x 16 block of pixels. Within that, it can't really get out of hand. The overall shape of the coastline is still determined by the original global map. Moreover, my landfills don't create the coastline within each tile by themselves - they combine with the coastlines created by the diamond-square fractal within each tile. That also lends some control, since the shape of that fractal is determined to some extent not merely by the relative location of sea and land cells on the global map but by their height.

These work quite well at smoothing the coastlines without creating too many straight lines. (I turn them off wherever there is seasonal or permanent sea ice, since those areas ought to look more rugged.)

(4) Finally, UW goes over the map and cleans and tidies: it removes odd little stick-shaped islands that have a tendency to form, and it also checks for coastlines that have too-long straight lines. If it finds any, it pastes a random blobby template right over them (either creating new land or eating it away).

With all of these techniques added, we have:


And I think that's starting to look fairly reasonable. But those big, vague-looking, lumpy bits along the northern coast don't look very realistic given the scale this is supposed to be. (This image is about the size of France, remember.) They're meant to be mountains, but that's not what mountains look like at this scale. So that's the next problem to tackle.

2 comments:

  1. I had a number of problems with drawing coasts directly as fractals. The first was that I didn't much like the look of the resulting coasts, partly because they were sort of "equally fractally" everywhere. (Although I wasn't using midpoint displacement; maybe I should try that). The second problem was that fractals couldn't generate small islands along the coast. The third problem was that changing the coast line independent of the underlying terrain made it hard to match terrain features (like rivers) to the coastlines. I eventually addressed most of those problems, but I still didn't much like the result.

    ReplyDelete
    Replies
    1. Yes, these are all issues with making the coastlines directly fractal. I think my method mostly avoids them by combining the direct coastal fractal with the terrain fractal, which certainly does deliver islands, at least (though not many on the image on this post). I find also that the coasts generated with this method are fairly diverse - some look more "fractal" than others. Of course they will also get affected by other things such as river erosion, glacial fjords, and barrier islands, which also vary the look.

      Delete