Tuesday, February 20, 2018

City Symbols (Part 12): Fantasy Elements

One element that distinguishes the large city icons on the Torfani map is that the icons contains some fantastical-looking buildings -- mostly fanciful towers:
And since I am doing fantasy maps, I'd like to include some fantasy elements in my icons as well.

I'll start with fantasy towers like the ones above.  These are basically skinny windowless towers with some "donuts" around them.  I already have a mechanism for creating towers with different sized floors that I used for creating towers that get narrower, and I can reuse that to create these sorts of towers by making some of the floors bigger:
We'll see how those look in icons, but for the moment I think that's good enough.

Another fantasy element I want to add is onion dome roofs.  Although to be fair, this isn't really a fantasy feature, since these roofs are common on Russian churches:

The S shape of the side of an onion dome requires that I implement a cubic Bezier curve, but since I have a quadratic Bezier curve implemented already and the equations aren't that different, that isn't too difficult.  Calculating the proper control points is actually the more difficult job, but with some experimentation I get something that looks okay:
Note that this "curve" is actually 9 line segments.  SVG natively supports Bezier curves and can draw this beautifully, but for my purposes it's best to have it as line segments.  I can make this as smooth as necessary by generating more line segments, but at map scale 9 will be more than sufficient.

Using this as a profile for a roof yields this:
What else?  This excerpt from a fantasy cities wallpaper suggests some ideas:
Cupolas and skybridges between buildings.

Let me tackle cupolas first. As in the picture above, these are often round, domed structures on domed roofs.  In fact, it's often a miniature version of the building it sits upon, which suggests I can recreate this by stacking a smaller building on top of a larger building, as I did to create the fantasy towers above.  
Although cupolas typically do have windows (they often serve to let light into the area below the dome) I've turned them off here; it's simply too much detail for such a tiny icon.  (I'm also not allowing cupolas on cupolas, I'm not crazy!)  Cupolas don't look very good on one story buildings, so I should probably turn them off there, too.

It turns out that cupolas look good for some other roof types as well, such as pagoda roofs:
Doing cupolas correctly in faux-3D is a little more challenging.  The cupola needs to line up correctly with the house roof on both the front and the side, which requires some calculation.  But once that's done, it pretty much works automatically for all the different roof styles.
A natural extension of this idea is to have just a second roof on top of roof.  This may sound odd, but it's not entirely uncommon:
That's basically a stack of different roof types.  Or in a pagoda:
This is actually a bit more complicated to implement than cupolas.  An initial thought is to stack roofs by essentially making a cupola with a zero stories or a single story of zero height, but either of those solutions will break a fair bit of code that assumes houses have to have at least one reasonable story.  So instead I'll have to allow a building to have multiple roofs.  A second problem is the the current roof code expects a roof to sit on a house; that will have to change to allow a roof to sit on a roof.

Peaked roofs are fairly straightforward, so I'll implement them first to see how it looks:

That's not too bad.  This initial attempt isn't too visible at map scale, but I think it has enough potential to do the other roof styles.  Next up is pagoda roofs:
Hmm.  There seems to be a problem, but I can't quite put my finger on it.  :-)  The problem here is that the "dip" in the side of the roof is big enough that the sides of the roof get inverted.  With that fixed and some adjustments I have this:
Somewhat visible at map scale; this might benefit from having (say) three roofs.  Here's what it looks like in 2D:
The last roof type are eaved roofs that come to a single point.  (That name doesn't make a lot of sense, I know.)  On round buildings these look like this:
And on square buildings:
That looks somewhat absurd in the full-size drawing, but much better at icon size.  This roof has a different appeal if there's no overhang on the extra roof:
Domed roofs get you variants of this:
Not particularly interesting and possibly NSFW.  And finally, onion roofs:
That looks interesting at the icon scale.  Of course, none of these doubled roofs look particularly "realistic" but the point of these elements is to give a fantasy feel to the map, so that isn't really a drawback.

Now let me work on skybridges.  The first step is to draw two identical towers.  A tower (as I covered in a previous post) is just a tall skinny building.  To get two identical towers, I create a first tower and then copy it and draw it offset to the first tower: 
(In general the problem of making a deep copy of a Javascript object is complex and fraught with danger, but for this particular application I can get away with a solution crafted just for copying these buildings.)  The next step is to add the skybridge between the two buildings. 

As a first step, let me insert a one-story building to fit in-between the two towers:
I've made these round buildings, and they obviously don't look anything like a bridge.  Now I'm going to take advantage of how round buildings are drawn by using a negative offset for the bottom of the building.
Obviously the roof of these "buildings" are broken, but the bottom looks like we'd expect for a skybridge.  So I need to turn the roof off and hoist the building up the tower:
There are a couple of problems with these bridges.  The worst is probably that the shading in faux-3D is wrong.  Since these are really "round" houses, they get shaded accordingly.  Since they're actually flat, they should be a solid shade rather than a right-to-left gradient.  That isn't too bad a problem, so I'm inclined to just leave it "as is" rather than add some more special cases to the code.

No comments:

Post a Comment