{"id":5237,"date":"2009-09-28T15:44:05","date_gmt":"2009-09-28T19:44:05","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=5237"},"modified":"2009-09-28T15:56:27","modified_gmt":"2009-09-28T19:56:27","slug":"fuel-roads","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=5237","title":{"rendered":"Fuel: Roads"},"content":{"rendered":"<p><table width='150'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/fuel_map.jpg' class='insetimage' width='150' alt='This shows the zooming in, just to give you a sense of scale of the world.' title='This shows the zooming in, just to give you a sense of scale of the world.'\/><\/td><\/tr><tr><td class='insetcaption'>This shows the zooming in, just to give you a sense of scale of the world.<\/td><\/tr><\/table>I mentioned earlier that I wrote a road-generating program.  I want to talk about that project a bit and then compare it to what we see in Fuel. <\/p>\n<p>Roads are interesting because of how organic they look.  They bend and twist and split and have overpasses \/ underpasses, change width and (from a distance) tend to resemble more a circulatory system than a circuit board. <\/p>\n<p>Roads have rules which most of us intuit even when we don&#8217;t think about it, and when a virtual road breaks those rules it tends to break immersion as well.  Proper public roads generally don&#8217;t bank (or only do so very slightly) but are graded such that they are higher in the middle, so rainwater will run off. Roads tend to change direction more readily than elevation.  When circumnavigating a hill, the road generally cuts into a hill a bit, (as opposed to jutting out) so you&#8217;ll have a steep bank upwards on the inside and a drop downwards on the outside. If that drop is steep enough or the road curves abruptly enough, there&#8217;s usually a guard rail. Roads bend all over the place, and it&#8217;s not uncommon for you to find yourself on a &#8220;northbound&#8221; highway heading due east or west. And there is a limit on how steep a road can get.  <\/p>\n<p>And these are just the rules for a single road, which is what my program dealt with. (It was eventually going to be a screensaver.  If I were to do it again I&#8217;d no doubt put the thing on Google code for safekeeping.)  The program would load in or generate some hills of dubious realism. (This was before I did my <a href=\"?p=141\">terrain project<\/a>, so the terrain system here would have been crap.) Then it would plot a road to go from the south edge to the north edge.  It would examine the angle between its current location and its desired endpoint, and would try to head in that general direction while staying as level as possible. It ran on a flexible scale: The bigger the deviation between it&#8217;s current heading and its desired heading, the more willing it was to go up or down hill.  This worked amazingly well at producing a road that wasn&#8217;t too hilly but didn&#8217;t get lost.  It had a &#8220;create a bridge&#8221; fail-safe for when it just couldn&#8217;t find a proper solution, which happened whenever it was cut off by a steep valley.  The &#8220;bridge&#8221; was just a section where the road would run straight and level until it ran into the opposite wall of the valley.  All told, it wasn&#8217;t a flawless system but it produced some amazingly plausible roads on some challenging topography.<\/p>\n<p>Check out this heightmap I swiped from Google Image Search:<\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/fuel_heightmap.jpg' class='insetimage' width='600' alt='fuel_heightmap.jpg' title='fuel_heightmap.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>On the left is a straightforward heightmap.  It&#8217;s like a satellite view, with brighter pixels representing higher elevations.  The right is the same thing, but with a particular elevation set to red.  If you were standing on that red area, you could obviously go pretty far without needing to go up or down, as long as you didn&#8217;t mind swerving around a bit.  This swerving is basically the exact behavior you see on a road. My program would basically travel on the red as much as possible.  If it was forced to go up or down, then the &#8220;red&#8221; area would shift radially &#8211; outward from the tip of the hill if it was moving down, inward if it was moving up.  <\/p>\n<p><table width='350'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/fuel_map_flat.jpg' class='insetimage' width='350' alt='Top: The road system on perfectly flat terrain.  Bottom: The road system in pervasively hilly country.' title='Top: The road system on perfectly flat terrain.  Bottom: The road system in pervasively hilly country.'\/><\/td><\/tr><tr><td class='insetcaption'>Top: The road system on perfectly flat terrain.  Bottom: The road system in pervasively hilly country.<\/td><\/tr><\/table>Fuel seems to take a similar approach.  It works out a network of roads.  It begins with a couple of backbone highways that cut across the zone.  Between those, it will form a loose grid of evenly spaced secondary roads.  And between those it makes a network of dirt roads. It deliberately tries to make them a bit convoluted. You can see this in action in White Flats, one of the last zones in the game to be unlocked.  (I cheated, as unlocking this zone would have been <em>way<\/em> beyond my skill.)  The land is, as the name suggests, perfectly flat.  Yet the road system doesn&#8217;t just default to an axis-aligned grid.  Roads intersect at odd angles and form a plausible network. However, the individual roads are perfectly straight.  This suggests that the road system works not unlike the one I came up with, where roads bend due to topography.  This means the bends in the road are emergent, which is pretty cool.  (As opposed to the programmer trying to force the road to bend around arbitrarily to make it more &#8220;realistic&#8221;.)<\/p>\n<p><table width='350'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/fuel_bend.jpg' class='insetimage' width='350' alt='While not completely unrealistic, this abrupt curve is a little dubious. (There is actually a turn like this not far from where I live.  The people who live on the outside of this bend have placed a row of massive rocks in their front yard, just in case some drunk or fool is careening down the road without paying attention.  They&#8217;ll be stopped by the rocks instead of the house.  In the above picture, note the blank gray area on the outer part of the corner, no doubt that exists to hide the awful distortion in the road lines.' title='While not completely unrealistic, this abrupt curve is a little dubious. (There is actually a turn like this not far from where I live.  The people who live on the outside of this bend have placed a row of massive rocks in their front yard, just in case some drunk or fool is careening down the road without paying attention.  They&#8217;ll be stopped by the rocks instead of the house.  In the above picture, note the blank gray area on the outer part of the corner, no doubt that exists to hide the awful distortion in the road lines.'\/><\/td><\/tr><tr><td class='insetcaption'>While not completely unrealistic, this abrupt curve is a little dubious. (There is actually a turn like this not far from where I live.  The people who live on the outside of this bend have placed a row of massive rocks in their front yard, just in case some drunk or fool is careening down the road without paying attention.  They&#8217;ll be stopped by the rocks instead of the house.  In the above picture, note the blank gray area on the outer part of the corner, no doubt that exists to hide the awful distortion in the road lines.<\/td><\/tr><\/table><br \/>\nThe one thing that bedeviled me was the difficulty of splicing roads together.  This has gotten way, way harder as graphics have gotten better.  Merging two strips of flat gray polygons is trivial, but a real road isn&#8217;t flat gray. Real roads have a very distinct pattern of light and dark stripes, which I assume are the result of tires depositing slight amounts of rubber into the asphalt. Real roads have white lines at the edges, and dashed lines (or double yellow) down the middle.  Splicing two of these together is murderously complex, because you can&#8217;t allow the texture to distort at all.  If you stretch one texture at the point of the splice, the lines in the road will get longer or shorter, and that will look really, really obviously bad.  You can&#8217;t do a hard join and simply end one road as it intersects with the other, as the patterns of light and dark won&#8217;t match up and you&#8217;ll get a huge seam.  The problem gets even harder when you take into account the fact that some roads will have different numbers of lanes, and they&#8217;ll be joining at unpredictable angles.  I never did come up with a way to do it without needing multiple texture passes.  <\/p>\n<p><table width='350'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/fuel_seams.jpg' class='insetimage' width='350' alt='It&#8217;s hard to see, but just above my driver there is a staircase-shaped seam where the two roads were stitched together.' title='It&#8217;s hard to see, but just above my driver there is a staircase-shaped seam where the two roads were stitched together.'\/><\/td><\/tr><tr><td class='insetcaption'>It&#8217;s hard to see, but just above my driver there is a staircase-shaped seam where the two roads were stitched together.<\/td><\/tr><\/table>It seems like team Asobo ran into the exact same problems.  They have all the seam issues I anticipated, although they to manage to make a bulk of the road joins look passable by blurring and fading the textures where they meet. Still, every once in a while you&#8217;ll see a spot where it just couldn&#8217;t solve the splice, and you&#8217;ll get all sorts of strange artifacts.  (Although to be fair, you won&#8217;t notice these bits if you&#8217;re just roaring along at 100mph, which is more likely than not.) There are a pair of extra-large four-lane highways in Fuel, and they join just southeast of the center of the map.  The texture mapping is predictably wonky, but the real hilarity is that one of them brings its guard rail into the merge, thus cutting off a lane of traffic with a completely inappropriate guard rail:<\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/fuel_merge.jpg' class='insetimage' width='600' alt='Guardrail fail.' title='Guardrail fail.'\/><\/td><\/tr><tr><td class='insetcaption'>Guardrail fail.<\/td><\/tr><\/table><\/p>\n<p>You could solve this problem by having artists make pre-fab intersections.  For example, the artists could make the four-way intersection pieces, the forks, and the merges, and the program could use those the way a plumber uses pipe fixtures:  Just bend the roads around and plug them in.  But that only works on level land, and flattening the land around every single intersection will instantly make the world a lot more generic and repetitive.<\/p>\n<p><table width='350'  cellpadding='0' cellspacing='0' border='0' align='right'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/fuel_seams2.jpg' class='insetimage' width='350' alt='In many cases you can get away with joining two roads with a hard edge, as is done here. It&#8217;s not perfect, but it&#8217;s not awful, either.' title='In many cases you can get away with joining two roads with a hard edge, as is done here. It&#8217;s not perfect, but it&#8217;s not awful, either.'\/><\/td><\/tr><tr><td class='insetcaption'>In many cases you can get away with joining two roads with a hard edge, as is done here. It&#8217;s not perfect, but it&#8217;s not awful, either.<\/td><\/tr><\/table>There are no over passes in Fuel, and no clover leaf intersections.  I can understand why. Knowing when to place one or the other, and making them look acceptable on arbitrary topography, is a huge problem to solve.  Engineers design these things do so on a case-by-case basis, and in games these things are made by hand, by artists. This is the first game I&#8217;ve seen where someone took a crack at doing this with code. Sometimes you need to take away earth.  Sometimes you need to build up.  Often you need to do quite a bit  of both.  You need enough clearance on the bridge yet the ramps of a cloverleaf can&#8217;t be too steep nor turn too sharply.  And of course, cloverleafs would look naked without the copious signage required to make use of them, and placing those signs where they will look right and not cause problems for either of the intersecting roads is a non-trivial problem.  <\/p>\n<p>To the people that have been pointing to Dwarf Fortress as the zenith of procedural content: Being unfettered by graphics, DF will never have to face the worst of the procedural challenges. That&#8217;s fine. It doesn&#8217;t need to. But the really humbling challenges will be for programmers who have to work with polygons to realize their world.  <\/p>\n<p>One of these days I&#8217;d like to take another crack at the highway system problem.  It&#8217;s a toughie, but if you can solve it you&#8217;ll have gone a long way to making game content turnkey.  Even in fixed worlds like GTA, I&#8217;ll bet the art team would love a tool that let them make roads by drawing simple lines, and having the software work out all the messy details and landscaping. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>This shows the zooming in, just to give you a sense of scale of the world.I mentioned earlier that I wrote a road-generating program. I want to talk about that project a bit and then compare it to what we see in Fuel. Roads are interesting because of how organic they look. They bend and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55],"tags":[],"class_list":["post-5237","post","type-post","status-publish","format-standard","hentry","category-game-design"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/5237","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5237"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/5237\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5237"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5237"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5237"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}