{"id":15892,"date":"2012-05-14T04:47:31","date_gmt":"2012-05-14T09:47:31","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=15892"},"modified":"2012-05-14T23:31:34","modified_gmt":"2012-05-15T04:31:34","slug":"project-octant-part-7slopes","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=15892","title":{"rendered":"Project Octant Part 7:Slopes"},"content":{"rendered":"<p>Now that we have a world based entirely around the idea of cubes, you know what we need? Slopes. This is something that&#8217;s been on my mind for ages.  I&#8217;ve run around the Minecraft landscape and wondered, &#8220;What would this look like if the cubes could slope to form beveled outlines?&#8221;<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant6_14.jpg' class='insetimage'   alt='octant6_14.jpg' title='octant6_14.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Slopes aren&#8217;t really a foreign idea to an octree-based world. Minecraft has steps, which are basically slopes for the purposes of blocking light (they don&#8217;t) and collision. I want to take this one further and make slopes a part of the natural landscape. Like a lot of the stuff with this project, I&#8217;m not sure how well this will work out.  <\/p>\n<p>The trick here will be that the software needs to be able to look at a landscape and figure out which blocks should be turned into ramps, which ones should be turned into corners, which ones should remain cubes, and which way the slopes should face.  <\/p>\n<p>First, I need to set some parameters:<\/p>\n<p><!--more--><\/p>\n<ol>\n<li><strong>Slopes should happen automatically.<\/strong>  I&#8217;m picturing some sort of special block that has auto-sloping properties associated with it.  For my tests here, I&#8217;ll be doing it on grass, but I imagine it would also apply to sand, gravel, and that sort of thing. I&#8217;ll be calling these blocks &#8220;soft&#8221; blocks.  So now there are three states for a cube of space: It&#8217;s either solid (like stone) soft (like grass) or empty. (Like, air, see?)\n<\/li>\n<li><strong>No deep analysis.<\/strong> When analyzing which way to slope, individual blocks can only examine their immediate neighbors, and not look at more distant blocks.  Two reasons for this: First, there&#8217;s a tiny bit of overhead to looking up blocks.  Alone, it&#8217;s not a big deal. But if every soft block needs to look two or three spaces away, then we&#8217;re talking about a LOT of lookups.  Also, if the orientation of a block can change based on stuff happening three blocks away, then this might lead to madness and confusion for a player. Example: You change\/remove a block in front of you, and 3 meters away a bunch of landscape suddenly changes. Yuck.<\/li>\n<li><strong>Soft blocks must be blind to the orientation of other soft blocks.<\/strong> I want to orient all soft blocks in a single pass. If block A needs to know what block B is doing (is it sloping away from me? Towards me?) then that means I need to do block B first. But what if B isn&#8217;t done yet? What if B is waiting on C? What if B doesn&#8217;t exist yet because it&#8217;s on the edge where terrain is still being created \/ loaded?  Since we&#8217;re doing this with an octree, we can&#8217;t count on blocks appearing in any particular order. <\/li>\n<li><strong>These slopes are only for making hills.<\/strong>  Walls will still run at ninety degree angles and we&#8217;re not going to slope ceilings.  While it might be kind of interesting to make some kind of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Non-uniform_rational_B-spline\">NURBS<\/a>-based scenery, that&#8217;s not what I&#8217;m after today. Still, that would make for an amazing experiment.  It&#8217;s insane how, over a year after Minecraft became a mega-hit, we&#8217;re still not seeing more people at least <em>play around<\/em> with these ideas. I think you could spend a year pumping out different octree-based cube prototypes and still not see everything this technology has to offer. I mean, check out <a href=\"http:\/\/www.sea-of-memes.com\/LetsCode22\/LetsCode22.html\">Sea of Memes<\/a>, where Michael Goodfellow was remixing Minecraft like a DJ.  You could read through that series and run off with half a dozen game designs.\n<\/li>\n<\/ol>\n<p>The solution I came up with is that the program will make one quick pass over the scenery.  It looks for soft blocks. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_1.jpg' class='insetimage'   alt='octant7_1.jpg' title='octant7_1.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Overhead view. Green = soft blocks. Red=hard blocks. White = empty space.  It looks like this:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_4.jpg' class='insetimage'   alt='octant7_4.jpg' title='octant7_4.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>I apologize for how hard it is to make out shapes. This will stop being a problem once we have proper lighting.<\/p>\n<p>It examines each soft block. If there&#8217;s another block on top of it, it&#8217;s marked as solid.  If it&#8217;s surrounded on four sides by other blocks (soft or solid) then it&#8217;s marked as solid.  <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_2.jpg' class='insetimage'   alt='octant7_2.jpg' title='octant7_2.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Now it runs through the soft blocks again, this time making them &#8220;lean&#8221; against any nearby solids.  <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_3.jpg' class='insetimage'   alt='octant7_3.jpg' title='octant7_3.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>This was kind of crazy. I spent a lot of time experimenting with rules for which blocks would slope, and under what circumstances. <\/p>\n<p>Sadly, I got pretty wrapped up in the process and forgot about taking screenshots, so I can&#8217;t show you all the ways that this went hilariously wrong and stupid and was broken in ways that I hadn&#8217;t even considered. Here&#8217;s one example:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_5.jpg' class='insetimage'   alt='octant7_5.jpg' title='octant7_5.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Two opposing slopes wound up next to each other. The resulting gap in the scenery lets you see through the ground to the&#8230; lava. (Disclosure: Not really lava, from a gameplay perspective. I just re-colored my checkerboard base with a lava texture for fun, and found it was super-helpful in letting me spot gaps in the terrain at a distance.)<\/p>\n<p>Remember that when slopes are being created, they can&#8217;t query each other and see which way the others are facing, because those other slopes might not be in position yet.  I could have it look for neighbors that <em>have<\/em> been set, but that would create relationships that are difficult or impossible for the player to understand.  You&#8217;d wind up with stuff like, &#8220;If you&#8217;re building on an odd-numbered block on the world grid then the south-most or west-most neighbor dictates which way the slope will go, while on even-numbered blocks you&#8217;ll get&#8230;&#8221;  And so on.<\/p>\n<p>The upshot is that if slopes are decided by looking at neighbors, then a player would be able to build the same exact arrangement of blocks in 4 different places and end up getting 4 different results, depending on where their structures fell on the world grid and the powers-of-two scale. Madness.  No, if this is going to work, then soft blocks have to make their decisions without regard to what other soft blocks are doing.<\/p>\n<p>Not to keep you in suspense, I do manage to come up with a working set of rules that produces slopes and (so far) doesn&#8217;t seem to leave holes in the terrain.  The result is a set of rules that is so complicated I can barely follow them.  If I have to come back to this in six months I&#8217;m going to hate myself. Here is my little test scene, now with slopes:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_6.jpg' class='insetimage'   alt='octant7_6.jpg' title='octant7_6.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Here is what that looks like in my example drawing:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_3.jpg' class='insetimage'   alt='octant7_3.jpg' title='octant7_3.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Note the block in column 4, row 3.  That&#8217;s an inside corner. To give you an idea of the complexity involved, here are the rules controlling this block:<\/p>\n<ol>\n<li>The northwest block must be empty.\n<\/li>\n<li>The north and west blocks must be soft. (We can&#8217;t know which way they&#8217;re facing, but we know they&#8217;re soft.)\n<\/li>\n<li>The northeast and southeast blocks must be non-empty. (Solid or soft.)\n<\/li>\n<li>The east, south, and southeast neighbors must be solid.\n<\/li>\n<\/ol>\n<p>In code, it looks like this:<\/p>\n<pre lang=\"c\" line=\"1\">\r\n  \/\/The diagrams below represent this cell (center) and the cells directly\r\n  \/\/adjacent to it.\r\n  \/\/# Indicates a cell that MUST be solid.\r\n  \/\/@ Indicates a cell must be non-empty. (Solid or soft.)\r\n  \/\/x Indicates a cell that MUST be empty.\r\n  \/\/? Indicates the contents of the cell are ignored.\r\n  \/\/S The cell MUST be soft.\r\n\r\n  \/\/    xS@\r\n  \/\/    S\/#\r\n  \/\/    @##\r\n  if (cell[C_NORTHWEST].Empty () && cell[C_NORTH].Soft () &&\r\n             !cell[C_NORTHEAST].Empty () && cell[C_WEST].Soft () &&\r\n             cell[C_EAST].Solid () && !cell[C_SOUTHWEST].Empty () &&\r\n             cell[C_SOUTH].Solid () && cell[C_SOUTHEAST].Solid ()) {\r\n    facing = FACING_NW_INNER;\r\n    \/\/etc... \r\n  }\r\n<\/pre>\n<p>Yes, those comments are really part of the code.  The code on lines 13-17 might be the most complicated conditional statement I&#8217;ve ever personally written. <\/p>\n<p>In practice, the world looks like this:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_7.jpg' class='insetimage'   alt='octant7_7.jpg' title='octant7_7.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>(Ignore the stray single floating blocks.  I built those as part of my testing \/ screwing around process.)<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_8.jpg' class='insetimage'   alt='octant7_8.jpg' title='octant7_8.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Was it worth it? I dunno. It&#8217;s kind of different.  I think the gameplay fares better than the visual aspect of the thing.  You can run up and down these hills without needing to hop like Q-Bert, which makes getting around kind of fun. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant7_9.jpg' class='insetimage'   alt='octant7_9.jpg' title='octant7_9.jpg'\/><\/td><\/tr><\/table><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now that we have a world based entirely around the idea of cubes, you know what we need? Slopes. This is something that&#8217;s been on my mind for ages. I&#8217;ve run around the Minecraft landscape and wondered, &#8220;What would this look like if the cubes could slope to form beveled outlines?&#8221; Slopes aren&#8217;t really a [&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":[233],"class_list":["post-15892","post","type-post","status-publish","format-standard","hentry","category-programming","tag-octant"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/15892","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=15892"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/15892\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=15892"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=15892"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=15892"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}