{"id":12167,"date":"2011-06-29T09:30:01","date_gmt":"2011-06-29T14:30:01","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12167"},"modified":"2011-06-29T12:51:56","modified_gmt":"2011-06-29T17:51:56","slug":"project-frontier-10-more-trees","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12167","title":{"rendered":"Project Frontier #10: More Trees"},"content":{"rendered":"<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><a href='images\/frontier10_trees_big.jpg'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_trees.jpg' class='insetimage' width='600' alt='frontier10_trees.jpg' title='frontier10_trees.jpg'\/><\/a><\/td><\/tr><\/table><\/p>\n<p>My tree-building code is a lot <em>less<\/em> sophisticated than I planned.  This is really rare in programming. (And, I expect, in most other forms of engineering.  Problems usually become more complex as you examine them in greater detail.) Still, this is in keeping with the spirit of this project, which is to solve 90% of the problem with 10% of the effort.<\/p>\n<p><!--more--><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_4.jpg' class='insetimage'   alt='frontier10_4.jpg' title='frontier10_4.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>The first step in creating trees is to generate the trunk. I&#8217;ve got a few parameters governing how much they bend, how tall they are, the width of the base, and a few other minor details.  <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_5.jpg' class='insetimage'   alt='frontier10_5.jpg' title='frontier10_5.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Most trees have branches. (Two exceptions:  Conifer trees have their foliage affixed directly to the trunk. Trees intended to form a canopy simply have one huge umbrella of foliage at the top of the trunk.) Branches reach upward from their point of origin, but there are two ways of doing this.  On the left you can see branches that reach outward, then upward.   On the right you can see ones that go up, then out.  The latter makes the branches look &#8220;droopy&#8221; and heavy.  The former makes the tree look strong and vibrant.  <\/p>\n<p>I originally had branches that extended down from their point of origin, or ran level.  Those looked wrong, or boring, so I removed that option.<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_6.jpg' class='insetimage'   alt='frontier10_6.jpg' title='frontier10_6.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Branches all end in a cluster of foliage.  Foliage shapes vary. Some are roughly (VERY roughly) spherical. Some are bowl-shaped.  Some are umbrella shaped.  Some are big droopy things.  I used to have foliage clusters that were made of intersecting panels (like the <a href=\"?p=12038\">grass<\/a>) but they were kind of hit-or-miss.  Even the &#8220;good&#8221; ones seemed poor compared to the other types. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_7.jpg' class='insetimage'   alt='frontier10_7.jpg' title='frontier10_7.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>The last step is to hang some moss or vines on the branches.  This is only done to trees that will grow in the hottest, wettest climates. As it builds the branches, it keeps track of the points along the underside of the branch.  If the tree ends up flagged for moss, it uses these points to hang a &#8220;curtain&#8221; of polygons under the branch.  <\/p>\n<p>This was intended to be my prototype.  I was going to build this much, see how things looked, and then add to the system once I saw what was needed.  It turned out that my prototype looked good enough.  I&#8217;d hit the right style on the first try.  The only real improvement I&#8217;ve made is to remove the various options that made boring trees.  (Level branches, etc.) The process was more about taking away options than adding features. <\/p>\n<p>What I quickly discovered was the the whole thing more or less hinged on the texture and coloring.  That&#8217;s what makes these trees work. See, each tree has it&#8217;s own texture:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_8.jpg' class='insetimage'   alt='frontier10_8.jpg' title='frontier10_8.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>When a species of tree is generated, the program creates a texture just for that tree.  The texture is 1024&#215;256, and is divided into four panels. The first is the bark, the second is the foliage, the third is the hanging moss \/ vines, and the fourth is a picture of the tree itself, which I&#8217;ll talk about in a minute. Doing things this way allows me to draw an entire tree with a single pass, since there&#8217;s no need for any sort of texture-switching. Panel three is a bit wasteful, though.  It&#8217;s mostly transparent empty space. I guess I can pretend that empty space is reserved for future use, and not wasted.  Doing so doesn&#8217;t make the program perform any better, but it lets me stop feeling guilty about it. <\/p>\n<p>Here is how it makes that texture:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_2.jpg' class='insetimage'   alt='frontier10_2.jpg' title='frontier10_2.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>These are the available bark textures.  The first two I made by hand, by scribbling in Paint Shop Pro.  The second two are just filters built into PSP.  Like the trees themselves, I designed these quickly, planning to replace them with &#8220;real&#8221; art later on, only to discover the prototype stuff looked pretty darn good. <\/p>\n<p>First, it draws a flat-color box into that first frame, colored to whatever bark color I&#8217;ve chosen for the tree. Then it takes one of these bark textures and blends it, darkening it in places. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_1.jpg' class='insetimage'   alt='frontier10_1.jpg' title='frontier10_1.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>For the foliage&#8230; I&#8217;m not much of a pixel artist, but I managed to come up with some assets that get the job done.  When a tree is generated, it selects one of these foliage types.  Then it renders a whole bunch of them into that second frame.  I called these little splotches &#8220;leaves&#8221;, even though they&#8217;re really &#8220;pictures of groups of leaves&#8221;. Now that I&#8217;m writing this post, I&#8217;m seeing that a bug has cropped up.  I designed it to draw each leaf a slightly different color.  It&#8217;s supposed to scatter them a bit around a common hue.  I can see now that at some point I broke that functionality, because the foliage is a solid color.  I wonder when I did that? <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_3.jpg' class='insetimage'   alt='frontier10_3.jpg' title='frontier10_3.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>The third frame gets a random stripe of moss \/ vines \/ whatever this crap is, colored to match the tree itself, but slightly darker.  (I tried using a different hue.  I mean, it&#8217;s another plant, growing on the tree, so it shouldn&#8217;t <em>have<\/em> to be the same color.  Surprisingly, it looked wrong.  It looked like there was something wrong with the texture, not like the moss was just a different color.)<\/p>\n<p>There are three levels of detail for trees.  Up close, the branches and trunk are round and smooth.  At a distance, the trunk is reduced to just 3 points around, so it&#8217;s sort of wedge-shaped.  If you were to chop it down, the stump would be a triangle.  The branches are only two segments around, which makes them 2-dimensional.  It sounds awful, but they look passable even at thirty meters or so.  (And the player will never get that close.  I don&#8217;t think you can get closer than 100 meters before it swaps out the cheap tree for the good one.)<\/p>\n<p>At extreme distances, it takes the picture of the tree from panel four and just puts it on a billboard.  Here is a normal tree:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_9.jpg' class='insetimage'   alt='frontier10_9.jpg' title='frontier10_9.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>And here is the same tree in glorious 2D mode:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_10.jpg' class='insetimage'   alt='frontier10_10.jpg' title='frontier10_10.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Wow.  You know, seeing these side-by-side, I have to say the cheap trees don&#8217;t look half bad, considering.  Of course, the player will never be able to get anywhere near these things. <\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><a href='images\/frontier10_11_big.jpg'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier10_11.jpg' class='insetimage' width='600' alt='As requested, a screen shot without the development text. Click for larger view.' title='As requested, a screen shot without the development text. Click for larger view.'\/><\/a><\/td><\/tr><tr><td class='insetcaption'>As requested, a screen shot without the development text. Click for larger view.<\/td><\/tr><\/table><\/p>\n<p>Trees are very much a feature to be tinkered with.  Unlike terrain, where my goal was to finish the feature and move on, trees are an informal, self-contained system that I can revisit again and again as I get new ideas or feel the sudden urge to experiment. <\/p>\n<p>I don&#8217;t think we&#8217;ll have a &#8220;week 5&#8221; video this Friday. I&#8217;m busy with other work, and I haven&#8217;t added anything that I can put in a video.  (It&#8217;s pretty hard to demo &#8220;better memory management&#8221; in a video.) <\/p>\n<p>Please tell all of your rich investor game publisher friends about my project.  Thank you. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>My tree-building code is a lot less sophisticated than I planned. This is really rare in programming. (And, I expect, in most other forms of engineering. Problems usually become more complex as you examine them in greater detail.) Still, this is in keeping with the spirit of this project, which is to solve 90% of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-12167","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/12167","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=12167"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/12167\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=12167"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=12167"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=12167"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}