Monday, November 25, 2019

New Mountain Style (Part 2)

In the last posting I talked about my motivation for a new design approach, and reviewed in some detail a mountain style that I'm going to implement as an exploration of that approach.  In this posting I start working on the implementation.

The first element of a mountain is the topline.  The topline runs across the top of the mountain from left to right.  In the simple example below, I've traced the topline in blue:

In the style I'm trying to recreate, almost all the toplines are either simple carat shapes (as above) or a carat with a small secondary peak to one side or the other.  Here's the sample of toplines I traced from one section of the map:

The tallest mountains (about 1 in 20, or 5%) have a flattened peak.  Other parameters are how symmetrical the mountains are (these are very symmetrical) and their proportion (these are generally 3-4x longer in the horizontal direction).

My initial function creates a carat shape with the provided possible peak locations (pretty close to the middle) and proportions.  (Part of my design approach splits the creation from the drawing of the mountain, so for now I'll use simple lines when drawing the mountain.)
Next I create sub-peaks by putting a jog in the mountain's side:
Comparing these to the original subpeaks above, I can see these aren't quite right.  These subpeaks are symmetrical, while the subpeaks in the original mountains have about the same proportions as the mountains themselves.  The mountains with subpeaks are also wider, to maintain their proportion.  And there are too many mountains with subpeaks on both sides.  Let me try to address those issues:
This looks better, although there need to be more mountains with no subpeaks.  Placing these with the toplines from the original drawing looks pretty plausible:
As noted in the previous posting, the original drawing has most mountains slanted to the right; not sure if I'm going to implement that or not.  (Update: In a discussion with /u/greypawz, he said that he was aware of the slant but it was unintentional.)

There are two types of large mountains as well.  They are larger than the other mountains, and have either a flat top or a sharp peak.  These are constructed by adding the flat top or the sharp peak to the regular mountain shape.  Here are some examples:
Finally, let me take a mix of toplines and compare them to the reference map:
I created this mix manually and it's not as dense as the reference map, but to my eye looks very similar.  It's worth noting that the reference map doesn't have a uniform mix of mountain sizes.  There are more small mountains than big ones; that's something I'll need to replicate.

Now let me move on to the ridgelines.  Here's the illustration from the previous posting where I drew in the ridglines in blue:
To summarize the last posting, ridgelines appear on almost every mountain, come more-or-less straight downward from the peak for about half the height of the mountain and then alternate sharp angles, each segment being about a quarter to half the height of the mountain, and generally ending after crossing the baseline of the mountain.

I will start by drawing the first segment of the ridgeline down from the peak of the mountain about half the height of the mountain and keeping it roughly vertical:
(Here I've started coloring my generated mountains with the same color scheme as I used when analyzing the reference mountains.)  The next step is to add alternating left and right segments until the ridgeline extends as far as the baseline.
One problem that can arise is that the ridgeline can be too close to one side or the other of the mountain.  I can guard against this by putting the end of the first segment in a middle region of the mountain, even if that means it is less vertical.  That also lets me generate some first segments that are more slanted, since there are a few of those in the original map:
There are also secondary ridgelines that come down from secondary peaks.  I've identified some here in yellow:
These are two lines, one of which comes down from the secondary peak and one which comes downward from the adjacent valley.  They meet down around the baseline.  (Note that these get reverse shaded: dark if they're on the light side of the mountain and light if they're on the dark side.)  Not all secondary peaks get these ridgelines.  These are fairly easy to create:
The next step is the secondary toplines.  These originated on the corners of the ridgeline and run parallel to the topline.  Here's the reference map showing ridgelines (blue) and secondary toplines (green):
The secondary toplines generally start at the corners that are the furthest from the centerline of the ridge.  Most commonly there is one secondary topline on the shadowed side of the mountain.  Less frequently there is also a secondary topline on the lit side of the mountain, or a second topline on the shadowed side.  All told, secondary toplines appear on about half the mountains, and never on the smallest mountains.
Here I've made the green secondary toplines about the same slope as the red topline and long enough to sometimes cross the baseline.

One lesson I've learned is that in routines like this, with lots of different parts, it's easy for them to occasionally clash with each other, or to have other minor problems.  But even if this only happens very infrequently, if you use the routine a lot (as I will to generate many mountains on each map) these problems will show up enough to spoil maps.  Here's an example of a problem:
Here a long secondary top line is being drawn across a secondary ridgeline.  This doesn't happen very often, and in many cases the overlap is minor.  But this will look bad on a map, and isn't the kind of error a human artist would make.  So I'll put in a check to keep that from ever happening.

That completes the basic construction of the mountain.  In the next posting I'll start working on drawing the individual mountains.

Wednesday, November 13, 2019

New Mountains (and A New Approach) (Part 1)

In many parts of Dragons Abound I've used a design philosophy that aims towards general code that can be controlled through parameters to create a wide range of different outputs.  (You might call this “parameter-driven software.")  One example of this is the code that draws mountains.  This code has many different parameters (knobs) that allow it produce a wide variety of mountain styles, as I've demonstrated in several different posts.  The code has proven to be fairly flexible and yet I'm not entirely satisfied with how this design philosophy has played out.  The resulting code is often fragile (small changes can create large breakages), difficult to understand, and requires very careful tweaking to get acceptable results.

I chose the parameter-driven approach for a number of reasons.  First of all, when I'm implementing something complex like drawing mountains or city icons, I don't know for sure how to do that.  Having lots of parameters lets me tweak the behavior of the code in case my initial guesses are not correct.  Second, I've always wanted Dragons Abound to be able to draw the same map in a variety of different styles, so reflecting that in the code seemed useful.  Finally, I've wanted to see if setting the knobs randomly could produce some interesting and unexpected results.

That first use of parameters has been useful.  Even when I have the right general idea about how to do something, I rarely get the details right without some iteration and adjustment.  The other uses of the parameters haven't been as fruitful.  For one thing, randomly selected parameters don't usually produce anything very interesting.  The main reason is that only one or two parameters have to be “bad" to ruin the output.  When the random parameters offer up (say) bright pink house icons for cities, it really doesn't matter if the rest of the map is great.  Dragons Abound has several thousand parameters, so even if most of them rarely produce anything bad, if you pick them all randomly,  chances are very high that one of them will be bad.

On the other hand, even if random parameters usually serve up bad maps, I can look at those maps and pull out the parts that worked well.   An example of this happened while I was developing the Iskloft mountains, and stumbled across a nice mountain style:
I captured the parameters that led to that style so I could reuse it later.  So this philosophy does have some value in generating ideas that can be curated to identify the best ones.

But perhaps the most important factor to me is the code fragility.  Having lots of different ways to work also means there are lots of different ways to break.  At times I've found myself spending a lot of effort to fix some code in order to make some particular random combination of parameters work ... only to find that it doesn't produce anything particularly interesting anyway.

So overall my design philosophy hasn't been entirely successful, and I'd like to explore whether a different approach might be better.  (Although just because this philosophy hasn't been entirely successful doesn't mean that there's any better approach!)  One possibility is to leverage my experience in implementing general-purpose code for a particular feature to rewrite the code in a more specific style.  This will probably mean sacrificing the creative part of the code, but might result in code that is more reliable and works better for a small subset of the feature space.

Initially I'm going to try out this idea with mountains, inspired by this map that Reddit user /u/Greypawz posted to /r/mapmaking (excerpt):
I could carry on for some time about the nice features of this map, but in particular I like the mountains. They're in a simple style that gives a great impression of rocky texture.  So I'm going to try writing fresh code to produce these mountains specifically, with some parameters where necessary, but not trying to be completely general.  And I'll see how that works out.

But before I can start working on implementing these mountains using my new design philosophy, I have to try to figure out how to draw them.  From my previous work on drawing mountains I have something of an internal model of drawing mountains with a number of particular elements: toplines, ridgelines, secondary toplines, secondary ridgelines and shading.  Let me analyze these mountains in those terms.

To start with I'll look at the topline of the mountain -- the line that goes from one side of the mountain up over the peak and down the other side.  Here I have roughly traced all those lines on the upper mountains in red:
Here they are isolated:
There are a couple of things to note about the toplines in this sample.  First, they are remarkably consistent.  They split (almost exactly) into two shapes:  either a simple carat shape, or the carat shape interrupted by a short peak on one or both sides.  The highest/biggest mountains are flattened at the peak.  These are rare -- about 1 in 20 mountains.

In the part of the mountains pictured above, the toplines are almost all straight segments.  In the lower middle part of the map many of the mountains have the left side of the topline (the side that is lit) drawn as a curve:
This gives this section of the mountains something up a more rugged, upthrusting atmosphere.

Another element to look at is the proportions of the topline.  I'm aware from my previous mountain experiments that this is an important style element.  I measured the proportion of each mountain by enclosing the topline in the smallest possible (axis-aligned) bounding box, as so:
The mountains have a range of proportions (width/height) from about 2.25 to 5.  The largest mountains tend to be the more square, with proportions in the range of 1.9 to 3.9, but otherwise the distribution of proportions is pretty random.

Another aspect that is related to the proportions is the baseline.  This is the line that connects the two ends of the topline.  Here I've drawn in the baselines and also the peak line that connects the baseline to the highest point on the mountain -- this helps see if the mountain is symmetrical.  (I've left out mountains where I couldn't easily identify the baseline because they were obscured by other mountains.)
Here are the isolated baselines and peak lines:
It's obvious in this view that many of the mountain baselines slant downward to the right.  As far as the peak lines go, most of the mountains are symmetrical.  Most of the ones that aren't symmetrical have a sub-peak on the long side that extends that side of the baseline.

It's interesting that the baselines have a consistent slant.  This area of mountains is in the left center portion of the map on one side of a river valley:
It's possible that the author slanted the mountains on that side of the mountain to “cradle" the river valley.  To test that idea, I isolated baselines on the other side of the river valley:
These baselines also mostly slant down to the right.  I also looked at the mountains near the bottom middle of the map:
These are more consistently level, but there are still a number that slant downward to the right.

There are a couple of possible explanations.  One is that the slant simply reflects the direction in which the mountains are drawn.  I naturally draw mountains left to right -- possibly because that's the direction we write, or perhaps because I'm right-handed -- and this might lead to a downward slant in that direction. Another possibility has to do with the lighting.  On this map, the light is from the left.  If you want the mountains to be mostly lit sides, it is easiest to do this if the faces proceed downward and to the right, because the lit sides are in front of the shadowed sides.  If they go upward and to the right the shadows are in front of the lit faces.
I suspect this predisposes artists to draw downward to the right, even when drawing a single mountain.  Whatever the reason, an interesting quirk of this map.

(Update from Greypawz:  The right slant is not intentional, and it’s been something I’ve been working on fixing.)

I next tried to isolate just the toplines to look at how the lines are actually drawn:
This didn't work perfectly, but a few things are still evident.  The quality of the toplines is pretty consistent from end to end.  On the larger mountains, there is a more emphasis in the form of darker lines at the tops of the mountains.  This is a little more obvious at full size:
If you compare the lines in the red circles to the lines in the blue circles you'll see that the toplines near the peak of the mountains are generally darker.  But note that the line still remains quite dark even at the base of the mountain, and the thickness remains about the same.  (All the lines also have a lovely pencil quality that is quite hard to replicate in SVG.)  On the other end of the spectrum, the smallest mountains are only lightly sketched in.

Another important element of this style of mountain is the ridge line.  This line comes out from the peak of the mountain and runs vertically  “downward" to define a ridge running from the mountain top toward the viewer.  It also deviates left and right to follow the contour of the ridge:
Here I've traced the ridgelines in blue.  Note first that nearly every mountain has a ridgeline; the only exceptions are the smallest faint mountains (hills).  Now let me compare the ridgelines to the baselines.
Here you can see that the ridgelines generally extend past the baselines except on the tallest mountains.  (This helps with the oblique perspective by compressing the vertical dimension of the map.)

Now let's look at the shapes of the ridgelines:
A couple of things are obvious from inspecting these lines.  First, the first segment of the ridgeline almost always comes straight down and is usually about half of the vertical extent of the ridgeline.  Second, the following segments are at sharp alternating angles.  (This, too, is an artifact of the compression of the vertical dimension caused by the oblique perspective.) At most there are four segments to each ridgeline, and the final segments are often much shorter than the first segment.

In terms of line quality, the ridgelines are drawn much like the toplines and are equally dark at the peak of the mountain.

There are also secondary ridgelines that come down from secondary peaks.  I've highlighted some here in yellow:
These are usually two lines, one of which comes down from the secondary peak and one which comes downward from the adjacent valley and meet down around the baseline.  Note that these get reverse shaded: dark if they're on the lit side of the mountain and light if they're on the unlit side.

Where the ridgelines have sharp angles there are sometimes secondary toplines that come out from the point of the angle and run parallel to the mountain topline.  These lines define ridges running parallel to the plane of the viewer:
And here with the background removed:
These secondary toplines appear most often on the larger mountains, but do sometimes appear on a smaller mountain that has a long ridgeline.  Most commonly, the secondary topline comes out from a angle in the ridgeline that points toward the unlit side and runs downward, roughly paralleling the corresponding topline segment.  Less frequently they come out of a lit-pointing angle in the ridgeline and run downward to the (in this case) left.  They appear on about 20% of the candidate ridgeline angles.  The secondary toplines are slightly fainter than the toplines but still significantly darker than the lines used in the shadows hashing.

Now let me look at the shadows.  Because the light comes from the left side of the map, at its simplest the shadow for a mountain fills the right side of the mountain between the ridgeline and the topline.  This is most obvious in the small mountains:

Note how the shading fills the space between the topline, the ridgeline, and the baseline.  Shading is done with simple hatching, and while the hatching usually runs perpendicular to the topline, in some cases it runs parallel to the topline or at some random angle.

The shading is more complicated on some of the larger mountains:
In this excerpt there are three mountains, each with a ridgeline that changes direction several times.  The shading for each mountain is broken up into regions bounded by the ridgeline, the baseline and the secondary ridgelines.  In each adjacent region the direction of the hatching for the shaded areas rotates 90 degrees.  This helps define the shaded area as 3D planes at different angles to the viewer, and is one of the reasons these mountains have such a striking texture.

In my initial appreciation of this map, I thought that the artist also alternated hatching direction to help distinguish one mountain from another mountain in front or in back; but upon closer inspection this isn't true.  Most mountains with only a single shadow facet use a hatching pattern perpendicular to the topline.

Finally, I want to look at how the mountains are connected.  These mountains are mostly drawn individually, but there are a few cases where mountains are chained together.  In the first case, mountains are connected by starting the left end of a topline at the right end of a ridgeline, as in these examples:
This creates a chain of mountains going right and down across the page (as I illustrated in a previous example).  In these examples you can also see a variant that connects the ridgeline to the middle of the next topline.

The reverse of this connects the ridgeline of the rear mountain to the right topline of the front mountain, to create a chain of mountains going left and down the page, as in these examples:
In both cases, you can think of this as overlapping mountains from back to front.  If a mountain is in front of another mountain it is down the page and to the left or the right, depending upon which way the chain of mountains is intended to run.  In several places on the map you can see how the artist has created marching chains of mountains:
Another kind of connection is created by connecting the end of a ridgeline to the peak of another mountain to form a continuous ridgeline across several mountains.  This creates a vertical mountain chain, as in this example:
This technique is not much used on this map; the above example is the only really prominent use.

Of note on this map is that the end of one topline never meets the start of another topline.  When toplines touch, it is in the middle of the toplines.
If two toplines touch end to end it gives the impression of two side-by-side mountains at the same distance from the viewer.  This tends to flatten out the perception of the mountains and make them seem like cutouts.  By never meeting this way, the mountains give a greater sense of a profusion of different distances from the viewer and that creates a more palpable feeling of three dimensions.

Enough analysis for now; next time I move on to implementation.