Monday, January 20, 2020

New Mountain Style (Part 8)

I've found a few problems during the previous development stages that I didn't address, so I'll try to take care of them now.

The first problem is that sometimes the range of drawn mountain sizes is too large; the largest mountains are so big they look odd on the map.  An example:
The largest mountain in the left chain is much bigger than the others and looks odd as a result.  (Although admittedly this is something of a matter of taste.  Maybe you like the look of a huge mountain anchoring the mountain chain.)  The real problem here might be that the very big mountain is mostly surrounded by much smaller mountains, but detecting and correct that situation would be difficult.  The easier way to address this is to tune the parameter that controls the maximum mountain size.  This compresses the range of mountain sizes that will be drawn.  After playing around a bit with the parameters:
This seems better to my eye.

A second problem can be seen in this screen shot:
The red lines are drawn to connect the ridgeline of one mountain to the topline of the next mountain.  But they've obviously gone wrong in the upper-left mountain chain.

The reason is that I wrote the mountain chain code to draw mountain chains top down.  In the upper-left mountain chain you can see that the green line the mountain chain is following turns to go upward where the problematic red lines begin.  You can see another problem with the last mountain in the chain -- it doesn't actually connect to the previous mountain.  In contrast the other mountain chain -- which goes downward -- is fine.

I won't run through the whole logic of drawing a mountain chain upwards, but the general idea is that instead of intersecting the topline of the new mountain with the ridgeline of the old mountain, you have to do the opposite -- intersect the topline of the old mountain with the ridgeline of the new mountain.  This turns out to be a surprisingly small code change (at least once I quit confusing the X and Y axes in the code):
Now you can see the right side of the mountain chain makes more sense, and only short red lines are needed to connect adjacent mountains.

Another problem becomes apparent when I add a land texture:
Each mountain blocks out a chunk of the map below its baseline.  I added this because when tightly packed, the ridgeline of the back mountain often peeks out below the front mountain.  But this seems to be less of a problem with this method of filling the mountain areas, so I can probably reduce the size of the masking.
That looks pretty good; no peeking problems, at least on this map.

The last problem (at least for now) that I want to address is the straight lines on the mountain sides.  In my analysis of the original map I noted that almost all the mountains had straight sides:
But straight sides don't look that good on my maps.  Reviewing the original map I think that the sides tend to have subtle curves that break up the monotony.  I can add slight curves and some more hand-drawn jitter to my mountains to try to make the mountains look less mechanical:
I've kept the effect pretty subtle here and may increase it later, but I think it helps to keep the mountains from looking so mechanical and repetitive.

Next time I'll work on developing an SVG filter to make these look more like they were drawn with a pencil.


Monday, January 13, 2020

New Mountain Style (Part 7)

In the previous posting, I created the code to fill a polygon with mountains by putting down some mountain chains and then filling in around them:
I'll now take this routine and use it to fill in mountain areas on a map.  (Small areas will still be filled in with random mountains.)

Here I'm using a black & white map style like the original map.   I've filled the main mountain areas with two mountain chains and filled in around them with some random mountains.  Overall this isn't too bad, but it does have some problems that I need to address.

Looking specifically at the mountain chains I think they're pretty good overall, but I see a couple of problems.  ( I always have outsized expectations for new features, and I'm disappointed when they don't look indistinguishable from the work of a human artist.)  First of all, the mountains in those chains are all fairly close to the same size, and that's not particularly appealing.  Partially this happens because the underlying terrain looks that way; partially it happens because very small mountains don't work well in mountain chains so they've been suppressed.  One possibility to address this is to force the chain to peak in the middle:
I experimented with this during testing, and I think it looks pretty good and helps to better define the mountain chain.  I'm a little concerned that this might become repetitive on a large map with many mountain areas, so that's something to watch out for.

Another problem with the chains is that on the left side of the main mountain chain the slope of the chain is almost the same as the slopes on the right side of the toplines and it creates a clumsy looking progression where all the mountain sides align:
A human artist wouldn't make this mistake.  One way a human would avoid this problem would be not to draw adjacent mountains with the same slopes (so that they couldn't line up).  I can implement something like this by forcing the slopes of the mountains along the chain to alternate between wide and narrow:
I was worried that strict alternation would be obvious, but it doesn't seem to be a problem.  This fix isn't a panacea.  It worked pretty well for the lower mountain chain, but note that the top mountain chain now has some similar problems.

Another approach to eliminating the collinear sides is to detect when this is happening and perturb mountains left or right to break up the visual line.  To detect collinear sides is pretty difficult, but it's fairly easy to tell when the peak of the front mountain is close to the right topline of the back mountain, and this is a good enough indicator.  When this happens, I can move the mountain away from the topline.  Moving the mountain randomly doesn't work very well; it's better to move it along the normal of the topline.
You can see that this has broken up the visual line in the top mountain chain.  The drawback of this approach is that it also tends to break up the visual continuity of the mountain chain (and may in fact require drawing an extra line to connect the ridgeline of the back mountain to the topline of the front mountain) but that's probably better than leaving the toplines aligned.

In the maps above, the angle for the mountain chains has been selected to be the same as the longest chord in the polygon that defines the mountains.  One way to have better mountain chains is to force the mountain ranges to lie at one of the angles that works well for drawing mountain chains.
This creates nice mountain chains, but they tend to be shorter than the other approach because they're not going the long way across the polygon.

The drawback with both of these approaches is that drawing the mountain chains as an angled line doesn't do a good job of defining the shape of the polygon, and creates a bunch of parallel valleys, which is unrealistic.  A better approach might be to draw a mountain chain down the “spine" of the region, and then fill in around it.

The spine of a polygon is usually called the “centerline."  It's hard to find an exact definition for the centerline of a polygon, but as the name suggests it's intended to be the longest line that runs roughly in the center of the polygon.  This page has a nice interactive example of generating the centerline of a polygon for use in labeling.  The short version is that you create a Voronoi diagram based on the points in the polygon and then find the longest path through the Voronoi edges.  This is the result for the map I'm currently using:
This works but you can see that in both polygons the line curves back around at the ends to be longer.  For the purposes of drawing mountain chains I prefer straighter lines, even if they're not the longest possible.  To select straighter lines, I have to incorporate that in the metric for picking the path.  I introduced the idea of sinuosity when placing path labels, so I'll combine that with length to pick a path:
This helps find a more reasonable backbone for the mountains.  Here's what it looks like to put down the centerline as a backbone and then fill in with random mountains:
There's something of a glitch where the line takes a sharp turn in the middle of the larger region.  In general it is difficult for the mountain ranges to follow abrupt changes of direction.  Smoothing the centerline helps with this:
The drawback is that aggressively smoothing the line means it is no longer a very faithful spine for the mountains area.  I like that this is thematically more interesting than a mass of random mountains, or than parallel rows of mountains, but I wonder if it will be problematic for larger mountain areas.

Here are some example maps (reduced in size to fit in the blog) to see how this looks on a full map:
Both of these mountain ranges happen to be almost vertical, an orientation that works well for mountain ranges because the ridgelines can connect to the peaks.
Here we have one long mountain chain with a capital city on the slopes of one of the biggest mountains -- a pretty nice combination.  The chain itself looks pretty good as well.
This is the least successful of the example maps, although all the chains are generally at good angles for mountain chains.

Placing a chain of mountains down the centerline and then filling the region sparsely with other mountains seems to work pretty well.  The centerline gives the mountain area an identifiable structure, and the random mountains define the total area.  At least right at the moment I like this better than filling the area completely with random mountains or filling the area with parallel mountain chains.

Next time I'll take a look at fixing a few lingering problems.  (One of these can be seen in the white spaces under mountains in the last example map.)

Tuesday, January 7, 2020

New Mountain Style (Part 6)

Now that I'm able to draw mountains in the new style and piece them together to make mountain chains, I want to work on using them on maps.

In the current approach Dragons Abound uses, mountains are drawn by looking at all the locations in the world from highest to lowest and trying to draw a mountain in each location.  If a mountain is drawn and it overlaps too much with mountains that have already been drawn it is rejected and the next location is tested.  With proper tweaking, this produces areas of mountains that are nicely filled with a pleasing amount of overlap that visually connects the individual mountains into a mass:
But as noted previously, this doesn't create mountain chains except accidentally.

Using mountain chains on the map requires a different approach to drawing mountains.  Rather than looking at individual map locations,  I will have to identify areas of mountains and then try to use mountain chains to fill in those areas.  Fortunately I already have a routine that subsets the map and draws polygons around the identified areas:
Here the red line (somewhat relaxed) circles groups of map locations with mountain height.  I've excluded smaller areas, since they're likely too small to fit a mountain chain.

Once I have a mountain area, how do I fill that with mountain chains?  My initial approach is to find the long axis of the area and run mountain chains parallel to that axis:
This is very similar to the way I add hatching to an area of shadows.

To figure this out, let me first set up a test polygon:
Now I'll re-purpose the shading code to identify some lines for mountain chains:
Here I just picked an arbitrary slope for the lines.  Let me find the longest chord for the polygon and use that as the slope instead:
So now I can use my line-following routine to draw mountains along those lines.
One thing to note is that the lines are inside the polygon, and the mountain centers are on the lines, but the mountains themselves may stray outside the polygon.  Generally I don't think this will be a problem on the map, because there's no indications of the areas other than the mountains themselves.  

In the above example, the mountain chains are too obviously regular, so let me add some noise to the lines:
Here I'm using the same noise source for all the chains, so the perturbations are somewhat correlated.  Note that this worsens the problems of straying outside the polygon, because perturbing the lines can cause them to be outside the polygon.

When filling in an area with mountain chains like this, not all mountains should be so obviously part of the chain, so I can put in some more mountains to fill out the area.  To do this I'll use Poisson disc sampling (which I described here) to fill the polygon with a psuedo-random locations:
And then I'll try putting a mountain at each blue dot and if it doesn't overlap too badly with an existing mountain, I'll keep it:
Here I've drawn the fill mountains in red.  One problem with filling in after the chains are drawn is that the fill mountains aren't drawn from the top to the bottom, so they overlap incorrectly.  At the end of all mountain drawing, I need to go through the list of all mountains from top to bottom moving them up to the top of the drawing.  This puts them all in the correct order.
It doesn't take many fill mountains to break up the uniformity of the mountain chains, but by looking at more points and accepting more overlap, I can make it more dense:
Although I think even here the mountain chains are evident.

Next time I'll try the mountains out on a map.

Tuesday, December 31, 2019

New Mountain Style (Part 5)

In the previous posting I concluded the work on drawing individual mountains.  Now I'll work on drawing groups of mountains.

The current algorithm in Dragons Abound for drawing groups looks at each mountain location on the map in height order (tallest to smallest), draws an appropriately sized mountain there and then checks how much it overlaps previously drawn mountains.  If it overlaps too much, it's removed.  By tweaking the allowed amount of overlap, I can get different densities of mountains.  (Usually between 5-35% overlap.)
This creates a nice even density that is moderately attractive.  The main shortcoming is that it doesn't (except accidentally) give the impression of a mountain chain.  Often it produces what you can see in the example above, which looks like rows of horizontal mountains.

So how should I draw groups of mountains on a map?  I asked /u/greypawz (the author of the reference map I'm using) and he said this:
I generally start off with a line to draw around. In the case of western coast, the line traced a subduction zone I envisioned off the coast. It's really only a rough guideline. I fill in the area mostly randomly, trying to form parallel mountain ranges and/or perpendicular mountain ridges coming off of high peaks.
If I can project a bit from his description, it sounds like he uses parallel (and sometimes perpendicular) mountain chains to fill in an a mountain area.  You can see a little bit of this in parts of the reference map, as in this example:
Here you can see how roughly parallel mountain chains fill the mountain area.  (With some other mountains thrown in fill out the area.)  This is similar to the way parallel hatching lines fill in the shaded areas, except the hatching lines are mountain chains.

To try this out, I'm going to need the capability to draw mountain chains rather than just single mountains.  The reference map I'm using for this mountain style connects individual mountains in a number of ways to make a more coherent grouping.  I covered these in detail back in the post that started this series, so I'll just recap here.

One way to chain mountains is to connect the left end of a topline with the bottom end of the ridgeline of the mountain that is to the back and left of the front mountain:
This creates a chain of mountains going right and down across the page.  

The reverse of this connects the ridgeline of the rear mountain to the right topline of the front mountain:
This creates a chain of mountains going left and down the page.

Another way to chain is by connecting the end of a ridgeline to the peak of another mountain to form a continuous ridgeline across several mountains:
This creates a chain of mountains going straight down the page.

I'll begin by trying to draw mountains which connect the left end of a topline with the bottom end of a ridgeline to create a ridge of mountains going down and right.  I do this by drawing the mountains from back to front, and setting the origin of each mountain (which is the left end of the topline) to be the end of the previous ridgeline.
I had expected this approach to need some tweaking, but this looks remarkably good as is.  (Note that I'm just randomly selecting mountain sizes at this point.)

The flip of this approach connects the end of the ridgeline to the right sides of the topline, to create a chain that goes down and to the left.
Because mountains are broader than they are tall, this creates a line with a shallow slope.

One minor problem with drawing mountains this way is that the ridgelines and the toplines can fade out near the end.  When this happens the lines do not meet up to form a continuous line through the whole chain.  Visually this isn't a huge problem, but it's easy enough to turn off the line fade when I'm drawing a mountain chain:

The final chaining approach is to connect the end of the ridgeline to the peak of the next mountain to create a chain that runs roughly vertical.
This doesn't work as well, at least partly because the resulting spine down the chain of mountains looks too regular.  I can address that by using noise to snake the mountains a bit:
This looks better, but now the ridgelines don't always connect up to the following peak.  I can fix that by drawing in an additional line segment.
This is occasionally a little awkward when a small mountain is next to a big mountain.  I don't think that will happen a lot on the maps but we'll see.

So now I can chain mountains, but only in three directions: a slight slope left, a slight slope right, and vertically.  But there's an easily generalization of this chaining that allows other directions.  The key insight is that the chaining connects a point on the topline of the front mountain to the end of the ridgeline of the previous mountain:
To chain to the right you connect the left end of the topline to the previous ridgeline (red).  To chain straight downward, you connect the middle of the topline to to the previous ridgeline (blue).  And to chain  to the left you connect the right end of the topline to the previous ridgeline (green).  But you're not limited to connecting at those three points.  You can connect at any point on the topline to create an arbitrary direction for the mountain chain.

(Note that I'm straying from my “new" philosophy not to over-generalize all of the code.  In this case, I think it's necessary to make a more flexible routine to fill areas with mountains, but I recognize this is probably just justification for my natural inclinations.)

It's difficult to calculate where on the topline you should intersect to create a chain at a given angle, but extrapolating along the length of the topline gives a rough approximation.  For example, a 45 degree-ish angle:
This is not quite as visually pleasing as the three cardinal directions.  I suspect there are some ways to draw this that emphasizes the mountain chain more.  For example, I did a quick experiment where I eliminated the right top line after the transition to the ridgeline:
This makes the chain of mountains as a long ridge much more visually obvious.  It's getting close to a style of mountain illustration that uses long ridges rather than individual mountains.  This quick experiment has some obvious problems, but it's an idea that might be worth revisiting another day.

Arguably this method of creating a mountain chain is not much different/better than just overlapping mountains along the same angle, but I think the connection of the ridgeline to the following topline helps the chain look more unified than mere overlapping.

As I did with the vertical mountains, I can use some noise to perturb the line of the mountains slightly.  With the right parameters, this often creates mountain chains with a pleasing slight arc to them:
Or a slight S shape:
Although as with all uses of noise you're somewhat at the mercy of the random numbers.

Finally, here's an experiment where the mountains are higher in the middle of the chain rather than entirely random:
Perhaps that helps create the illusion of a connected range.  

For reasons that will eventually become apparent, it would be nice if I could extend this mountain chaining technique to follow a line.  This turns out to be considerably more difficult than the algorithm above.  As I place mountains along the line, I need to find the spot where the center of the next mountain is on the line *and* the end of the previous ridgeline touches the topline of the mountain.  Solving either constraint is easy, but solving them both simultaneously is very difficult. 

My solution was to place the new mountain on the line and then slide it back and forth on the line to find a spot where the end of the previous ridgeline just touches the topline of the new mountain.  An iterative and not particularly efficient approach:
The advantage of this approach is that the centerpoints of all the mountain lie along the line, so the mountain chain follows the line perfectly.  The disadvantage is that mountains don't always connect the same way, so there's some loss of visual continuity.  For example, in the vertical stretch of mountains above, they don't all connect ridgeline to peak, so there isn't as clear a “ridge" of mountains.

Now if I want to add some natural looking variation, I can use noise to perturb the line and the mountain chain will follow along:
Next time I'll experiment with using these mountain chains to fill in mountain areas on the map.