I failed. But I got some cool images, and I learned some useful things.

Note: the /x/ series of posts on my site are mostly unpolished mini posts. The polished version of this will come later, maybe in a few months.

I need to figure out:

how to assign the elevations to blue points given the river drainage system how to ensure elevations on both sides of a mountain range are consistent how to assign elevations to red points given the blue points

Algorithm 1

This is the algorithm from the last blog post. Grow elevation upwards using some heuristic involving Strahler numbers.





Looks cool! But ... the ridges don’t match. Where two watersheds meet, the elevations were computed separately, and there’s nothing that makes them match up. This leads to lots of cliffs:





I tweaked this in different ways but fundamentally, there’s nothing that would make the ridges match up. Assigning elevation from the river mouths didn’t work so well. The cliffs were cool but they were accidental. If I make cliffs, I want them to be on purpose.

I spent some time reading papers (see list at the end of the page). There were some great ideas in there but my needs are simpler than what most of them covered. I’m looking for something simple (less than 50 lines of code) and runs in linear time. I know, that’s asking for a lot, but I don’t need realism, only consistency. So I decided to try to construct the simplest the simplest thing that could possibly work[2], inspired by what I learned from those papers.

Algorithm 2

I struggled with this, trying several different algorithms on paper, before I decided that maybe I should stop fighting the problem and embrace it instead. I had been trying to determine elevations purely from the river drainage basins, but I had built those drainage basins from something somewhat like elevation. Can I reuse that pseudo-elevation to guide the final elevation?

Output elevation cannot exceeed the input pseudo-elevation. Output elevation must be below the inflowing triangles’ elevations.

That still leaves some leeway in how I set the elevations. If I evenly distribute them across the length of the river I get this:

The problem with this is that it’s carving canyons into the valleys, and I want the carving to be in the mountains. I tried weighting the step sizes to see if I could fix this:





It was interesting to play with but it didn’t really help. I think the real problem is that if there are two tributaries that have different lengths, the assignment of elevation doesn’t match at the confluence, leading to a sudden drop:

Algorithm 1 made confluences match but ridges did not. Algorithm 2 made ridges match but confluences did not. I should combine these somehow.

Algorithm 3

The most straightforward approach is to mix the outputs:

This looks fine in the top-down view but it doesn’t actually solve any of the problems. It makes both ridges and confluences mismatch.

Algorithm 4

To make both ridges and confluences match, I started with algorithm 2, which makes ridges match. Then I looked for the sudden drops at confluences that made them not match:

I then spread the drop out over the length of the river upstream:

This makes confluences match up. It keeps ridges matched. Does it do what I want?

Kind of. It does make the mountains interesting. But it doesn’t flatten out the valleys.

Diagnosis

This was frustrating. I thought I had figured it out, but when I tried it, it didn’t work well. So I took a break for a few days and realized a few things:

The success of my 2010 polygon map generator project was in large part because I did not tweak the results an algorithm gave me, but instead I designed an algorithm that would construct the kinds of maps I wanted. But for this project I have ended up tweaking and tweaking. This “generate and test” approach is frustrating, and I should pause and figure out what my goals are. Even if I do need to tweak sometimes to find good parameters, the iteration is too slow. Although I took care to make the generation code fast, I have some fairly inefficient rendering code that’s keeping me from exploring more quickly. I’m also editing code and reloading the page, when I should be building a slider UI that lets me adjust parameters directly. I also should have debug information displayed as an overlay. Part of the poor results are because I grabbed the placeholder pseudo-elevation I implemented for rivers, and used it for elevation. The problem is the pseudo-elevation was only meant for river drainage basins, and doesn’t actually have good mountains and valleys.

As a quick experiment I tried putting in some better pseudo-elevation, and I got this much improved result:

I think I need to make the implementation fast enough to allow more experimentation, but I also need to think about what I actually want the algorithm to produce, and design an algorithm that produces that more directly.