{"id":12229,"date":"2011-07-04T09:59:19","date_gmt":"2011-07-04T14:59:19","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12229"},"modified":"2011-07-04T10:00:00","modified_gmt":"2011-07-04T15:00:00","slug":"project-frontier-13-an-animated-topic","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12229","title":{"rendered":"Project Frontier #13: An Animated Topic"},"content":{"rendered":"<p>Heads up, <a href=\"?p=12210\">I did a weekend post on project frontier<\/a>, so if you&#8217;re one of the many Monday-Friday readers (aren&#8217;t you supposed to be working?) then you might have missed it. In that post, Reader Jordi <a href=\"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12210&#038;cpage=1#comment-219892\">asks<\/a>:<\/p>\n<blockquote><p>Hi Shamus, why don&#39;t you make your own file formats that are maximally efficient for your situation? Although writing a compiler\/converter from a third party file format to your own takes some extra effort (although I imagine this would be fairly easy), I think it has 2 major advantages:<br \/>\n1) You get to select the third party format purely based on what modeling\/animation tools you want to use, or how easy the format is to parse without having to worry about efficiency (both in terms of extra data\/memory and parsing speed).<br \/>\n2) In your game you get to use maximally efficient and flexible file formats because you can custom tailor them to your own unique situation.\n<\/p><\/blockquote>\n<p>Ah. I really wanted to take this route.  But my art path begins with Blender. (I&#8217;ll get into why later.  I&#8217;m not planning on using it myself, I&#8217;ll tell you that.)  If I knew Python and knew how to make Python talk to Blender, then I&#8217;d do this in a heartbeat.  But I don&#8217;t and &#8220;learn a new language so you can avoid learning a new file format&#8221; isn&#8217;t really the most efficient way of doing things.  Particularly since I&#8217;d still have to write the Python scripts, and then write C++ code to read the resulting files.  <\/p>\n<p><!--more--><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier12_3.jpg' class='insetimage'   alt='frontier12_3.jpg' title='frontier12_3.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>So we&#8217;re stuck with whatever goofball lame-brain files we can wring out of Blender.  Now, my first instinct is to write a model importer and replace Sticky the Stickman with proper geometry.  But, I remind myself, we&#8217;re working <em>backwards<\/em> this time.  So instead of bringing in a model, we&#8217;re going to bring in an animation and have Sticky perform it. <\/p>\n<p>I search around and find this Creative Commons character: <a href=\"http:\/\/opengameart.org\/content\/very-low-poly-human\">http:\/\/opengameart.org\/content\/very-low-poly-human<\/a><\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier13_1.jpg' class='insetimage'   alt='frontier13_1.jpg' title='frontier13_1.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>He&#8217;s perfect for my tests:<\/p>\n<ol>\n<li><strong>He&#8217;s low poly<\/strong>.  Later, when I&#8217;m working on a model importer, it will be a lot easier to test on this 400 polygon guy than on some 10,000 polygon beast.  When points go out of place, I&#8217;ll have a sporting chance at being able to spot the problem, instead of finding myself looking at a dense tangle of visually indecipherable geometry.\n<\/li>\n<li><strong>He comes with several animations.<\/strong> In Blender, he can run, punch, and stand.  This gives me a variety of animations for testing.\n<\/li>\n<li><strong>He&#8217;s a minimalist humanoid.<\/strong> No guns, armor, furry sidekicks, fancy clothing, or wild anime hair.  It&#8217;s just a guy, and nothing else.  Again, simplicity is clarity.\n<\/li>\n<\/ol>\n<p>Note that this is NOT something to be used in the game.  This is only for research.  My research begins with the following highly rigorous scientific approach:<\/p>\n<p>I open the guy up in Blender.  After just ten minutes I figure out how to select his animations, and then I go to <tt>File &raquo; Export<\/tt> and save the animation in every format available. COLLADA, Stanford .ply, Motion Capture .bvh, Stl, 3ds, obj, fbx, and x3d.  Once I have a nice, even coating of random files spewed all over my desktop, I start opening up the files in a text editor.  Most files are binary. (And thus gibberish in a text editor.)  I set those aside.  Text files are far easier to work with than binary files.  You can read a text file yourself, which lets you know what the file &#8220;really&#8221; says.  This makes it fairly easy to spot the difference between a design problem (I&#8217;m misunderstanding the format) and an implementation problem. (A regular old software bug.)<\/p>\n<p>I inspect the files, and find that .bvh files look very, very straightforward. It&#8217;s a description of a skeleton (which I don&#8217;t need, because I already have one) followed by a pure list of rotations.  &#8220;Turn the shoulder 30 degrees.  Twist the spine -15 degrees.  Rotate the knee 20 degrees.&#8221;  Smashing. This is exactly what I want.  Some animations files (perhaps most animation files) are inextricably linked to a particular skeleton.  So every skeleton in the game (say, men and women) needs to have its own animations.  That&#8217;s fine if you&#8217;re a big studio and you can solve problems with money, but indies can&#8217;t go around doubling their workload on a whim.<\/p>\n<div class=\"dmnotes\">The downside to using interchangeable animations is that different skeletons will end up with different results.  If your artist designs an animation for a full-grown man to put his hands on his knees, and then you apply that animation to a sixteen year old girl, the different proportions of their bodies may lead to undesired results.  Her hands might end up clipping though her knees slightly, or floating a bit above them.  In a cartoon-y world these aberrations  would go completely unnoticed, but in a photo-realistic world you end up chucking your characters into the Uncanny Valley.  Just one of thousands of ways photo-realism ends up costing so damn much.<\/div>\n<p>There&#8217;s a bit of ambiguity that confuses me for a while.  The designer of this model has joints for both &#8220;shoulders&#8221; and &#8220;upper arms&#8221;, and my model has a single joint for the shoulders.  This leads to some puzzling movement until I discover the problem.  The coordinate systems don&#8217;t agree, either.  My world is set up so that positive X is east, positive Y is south, and positive Z is up.  Better than half of the graphics engines out there use use Y for vertical and Z for north \/ south.  (<a href=\"http:\/\/notch.tumblr.com\/\">Notch<\/a> is a loose cannon.  He uses Z for east \/ west.  I&#8217;ve NEVER seen that before.) My coordinate system was chosen carefully.  1 unit = 1 meter = 1 square of terrain detail.  I can covert between &#8220;map coords&#8221; and &#8220;world coords&#8221; by just throwing away the Z value.  (In my previous job where Y was &#8220;up&#8221;, this was done by throwing away Y, then making Z the new Y, then dividing the new X, Y values by 10.  I&#8217;m sure you can see how this could lead to occasional confusion.)   <\/p>\n<p>But the person who made this animation has another system in mind, and so I have to sort that out.  The shoulders rotate on the wrong axis for me. Instead of swinging forward, they rotate in place. (Imagine your arms at your sides. Now turn your arm so that the palm of your hand faces forward, then behind you, etc.)  The knees move backwards for a while and things are generally creepy and strange until I get it all sorted.  I really wish I&#8217;d taken a screenshot of the process. <\/p>\n<p>In any event, I manage to figure it out. I have an animation system, and Sticky the Stickman can now run in place. I forgot to take screenshots, but he&#8217;re&#8217;s a shot of Sticky doing the sine-wave animations from earlier, which we can pretend is a victory dance. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier13_2.jpg' class='insetimage'   alt='frontier13_2.jpg' title='frontier13_2.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Just one step left.  I have to read in a skeleton, vertex points, and polygons.  It&#8217;s the hardest step, but at least i know everything underneath it works properly. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Heads up, I did a weekend post on project frontier, so if you&#8217;re one of the many Monday-Friday readers (aren&#8217;t you supposed to be working?) then you might have missed it. In that post, Reader Jordi asks: Hi Shamus, why don&#39;t you make your own file formats that are maximally efficient for your situation? Although [&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-12229","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\/12229","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=12229"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/12229\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=12229"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=12229"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=12229"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}