{"id":12242,"date":"2011-07-06T05:19:44","date_gmt":"2011-07-06T10:19:44","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12242"},"modified":"2011-07-06T05:21:27","modified_gmt":"2011-07-06T10:21:27","slug":"project-frontier-14-import-models","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12242","title":{"rendered":"Project Frontier #14: Import Models"},"content":{"rendered":"<p>So I have an animation system that works.  I also have a system to import animations from bvh files. Now all I need is a figure to animate.<\/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>I have a look at the various file formats available to Blender. There aren&#8217;t many. (The previous version of Blender had a LOT more file formats, but I didn&#8217;t know about that when I was working on this.)  The Direct X format, creatively named &#8220;X&#8221;, is a likely candidate.<\/p>\n<div class=\"dmnotes\">I would like to meet the guy who chose the name &#8220;X&#8221; for their file format, so I can thank him with a surprise elbow to the face.  Do you know what a pain in the ass it is trying to search for information on &#8220;.X files&#8221;?  I want to know about the file format, and most search results are focused on Mulder and Scully.  Even when you search for &#8220;.X 3D file format&#8221;, you&#8217;re still going to find your results sprinkled with stuff about the Smoking Man and aliens. <\/div>\n<p>Still, you can go a long way to figuring out X files (see?) by just reading the file itself.  It&#8217;s a parser&#8217;s dream: A unique word (like &#8220;Mesh&#8221; or &#8220;MeshMaterialList&#8221;) marks each part of the file.  Then there&#8217;s a number, saying how many things it&#8217;s about to list for you.  Then it lists them.  Example:<\/p>\n<p><!--more--><\/p>\n<pre lang=\"c\">Mesh {\r\n1632;\r\n-0.795500; 0.006100; 1.484800;,\r\n-0.802100; 0.015600; 1.523800;,\r\n-0.832800; 0.015700; 1.526000;,\r\n<\/pre>\n<p>This part is the &#8220;mesh&#8221; &#8211; the geometry part of the file.  It has 1,632 vertices.  Then it lists them. 1,632 X,Y, and Z values, separated by easily parsed commas and semicolons.  At the end of that long list of XYZ values, we see:<\/p>\n<pre lang=\"c\">-0.140900; 0.085100; 0.572700;,\r\n-0.153400; 0.132200; 0.429600;,\r\n-0.229300; 0.082400; 0.434900;,\r\n-0.195500; 0.055400; 0.578900;;\r\n408;\r\n4; 0, 1, 2, 3;,\r\n4; 4, 5, 6, 7;,\r\n4; 8, 9, 10, 11;,\r\n4; 12, 13, 14, 15;,\r\n4; 16, 17, 18, 19;,\r\n4; 20, 21, 22, 23;,<\/pre>\n<p>As the list of XYZ values end, we see a 408.  That must be the number of polygons. After that is the list of polygons.  It begins with the number of verts in the polygon.  (All of the ones you see here start with a 4, which means they are quads. After the 4 are the indexes.  Remember that drawing polygons is like playing connect-the-dots. This is a list describing the order in which to connect the dots. (The list of 1,632 XYZ values are the &#8220;dots&#8221;.)  <\/p>\n<p>I&#8217;m able to figure all of this out on my own, without needing to consult any documentation.  (Which is good, because there isn&#8217;t much.) When I&#8217;m done:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier14_1.jpg' class='insetimage'   alt='frontier14_1.jpg' title='frontier14_1.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Don&#8217;t applaud yet.  This guy is about as animated as Mt. Rushmore. To get him moving, I need two more pieces of information from the file: the vertex weights, and the skeleton.  <\/p>\n<p>For whatever reason, inventors of file formats insist on describing skeletons in terms of a series of transformation matrices. I know the term &#8220;transformation matrix&#8221; sounds technical and scary, but it&#8217;s just fancy-pants talk for a grid of numbers.  The numbers act like a magic box.  When you want to move stuff around in a 3D world, you use a matrix.  Remember <a href=\"http:\/\/xkcd.com\/184\/\">this<\/a> XKCD comic?<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='http:\/\/imgs.xkcd.com\/comics\/matrix_transform.png' class='insetimage'   alt='http:\/\/imgs.xkcd.com\/comics\/matrix_transform.png' title='http:\/\/imgs.xkcd.com\/comics\/matrix_transform.png'\/><\/td><\/tr><\/table><\/p>\n<p>When you want to position some stuff in a 3D world, you take your X, Y, and Z values and crank them through a matrix.  You multiply XYZ across the columns, add up the results, and the resulting output is your new XYZ position.  I use this when I build trees and want to move &#038; rotate (that is &#8220;transform&#8221;) the foliage into place at the end of a branch.  I use it again when I want to transform a single tree into place as I add it to a forest.  <\/p>\n<p>You take your grid of numbers, do some trigonometric hoodoo on it, and then it can rotate stuff and move stuff anywhere you like.  If you feed it the points that make up (say) a flagpole or a humanoid or a 200 foot tall Godzilla, the result will still have the same shape. The points might be far away, or turned 90 degrees, or whatever you were trying to accomplish, but it will still be shaped like the original thing. <\/p>\n<p>I hate this part.  All I want is to know the XYZ values of the joints.  It could list them the same way it lists vertex positions, but instead I have to parse and process a matrix hierarchy.  It would be like if I wanted to give you directions.  I could say, &#8220;Meet me by McDonald&#8217;s.&#8221;  Or I could give you directions along the lines of &#8220;Drive at sixty miles an hour for two minutes, then turn ninety degrees left, then forty miles an hour for one minute. Ninety degrees left. Then twenty miles an hour for fifteen seconds, then turn thirty degrees right.  <\/p>\n<p>Later, when you arrive at the Jazzercise studio, you&#8217;ll have no idea where you went wrong.  The slightest mistake in any part of the instructions will lead to vastly different ending locations.  <\/p>\n<p>So. I have to read in a matrix.  It looks like this:<\/p>\n<pre lang=\"c\">Frame RootFrame {\r\n\r\n  FrameTransformMatrix {\r\n    1.000000,0.000000,0.000000,0.000000,\r\n    0.000000,1.000000,0.000000,0.000000,\r\n    0.000000,0.000000,1.000000,0.000000,\r\n    0.000000,0.000000,0.000000,1.000000;;\r\n  }<\/pre>\n<p>I have to parse those numbers, stick them in a matrix.  I keep a stack of them.  When it creates a new joint, I add its matrix to the end of the stack.  Then, to find my XYZ values, I multiply each matrix by the one before.  Then I stick the value 0, 0, 0, into this final matrix, and out the other side will come the number I actually care about, which tells me where this joint is in space. <\/p>\n<p>Once I have my XYZ values for the joints, I can <em>throw all that other crap away<\/em> because I don&#8217;t need it.<\/p>\n<p>Now I can stick my skeleton inside of my model.<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier14_2.jpg' class='insetimage'   alt='frontier14_2.jpg' title='frontier14_2.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>We&#8217;re not done yet, though.  The skeleton can move, but there&#8217;s no information linking the model to the skeleton.  The bones move, the body remains rigid.  To finish the job, we need vertex weights. <\/p>\n<p>Vertex weights tell my program how each vertex should move.  For a particular vertex, the file might tell me that the point is 75% shoulder, 15% torso, 10% upper arm. (Or whatever.  The shoulder is one of the hardest parts of a model to articulate, because the extreme mobility and range of the human shoulder makes it hard to set up the weights right.)   I apply the vertex weights.  The result:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier14_3.jpg' class='insetimage'   alt='frontier14_3.jpg' title='frontier14_3.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Hm.  Does that look right to you?  It seems off. Bah.  I&#8217;m sure nobody will notice.  Let&#8217;s call it done.<\/p>\n<p>Sorting this one out is tricky.  After some experimenting, I discover I was reading the skeleton wrong.  The wrist was where the elbow should be, the elbow was where the shoulder should be, the shoulder was stuck inside the spine.  Basically, every point was positioned where its parent should be.  The devil of it was, the result still formed a stickman, so it looked correct. Then when the limbs go flailing around like this because they&#8217;re pivoting around the wrong point in space, it&#8217;s really hard to tell what the trouble is.  <\/p>\n<p>I solve that one, but it&#8217;s still broken.  The vertex weights on this model are&#8230; odd. There are weights like, &#8220;this point is 0.00000% upper arm&#8221;.  Uh? That&#8217;s zero? Why is it listed?  Also, the weights seem to add up to more than 100% in some places. I&#8217;m not sure how. Also, each vertex is attached to a LOT of bones.  I did a count.  Even ignoring the superfluous 0.00000% listings, some points seemed to be connected to more bones than was reasonable. This might be a problem with the model.  Or with my importer.  Or with by animation system.  Hm.<\/p>\n<p>I have an artist who has expressed an interest in working with me on this. I don&#8217;t want to tweak this system to work well with a model I&#8217;m not even planning to use, so I think I&#8217;ll wait until I have one of his models before I examine this further.  For now I just affix each vertex to one bone, no fancy weighting.  On a high-polygon model this would look awful, but on Mr. 408 Polygons here, it should be fine. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier14_4.jpg' class='insetimage'   alt='frontier14_4.jpg' title='frontier14_4.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>One problem remains. The right leg is moving with the left leg of the skeleton and vice versa. And the right arm with the left arm, and so on. (I don&#8217;t actually know if the above screenshot is from this exact point in the process.  I can&#8217;t tell.  I have these shots of mangled avatars, and they all sort of look the same.) <\/p>\n<p>I had been kind of expecting to run into something like this.  <a href=\"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=12229&#038;cpage=1#comment-219921\">As we discussed<\/a> in the comments, my coordinate system is a bit unconventional, so incoming geometry needs to be altered to fit.  I knew this would happen, but I couldn&#8217;t picture in my head how it would work out.  So, I just waited until it failed and then tried to figure out what I needed to do by examining the model visually. I was expecting to have to swap Y and Z values, or turn the model on one axis, or something else tricky. It turns out that to go from Blender to my program, all I have to do is mirror it on the X axis.  Easy. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier14_5.jpg' class='insetimage'   alt='frontier14_5.jpg' title='frontier14_5.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>It works!  And yes, this game is going to be third person. I wasn&#8217;t 100% sure of this at the outset, and I was willing to settle for first-person if this didn&#8217;t work out, but now that I&#8217;ve switched to a third-person camera I&#8217;m sold on it.  This is the way to go.  The extra distance between the camera and the ground hides the shortcomings of the grass.  Being able to see your avatar eliminates the visual confusion over size.  Instead of saying, &#8220;I&#8217;m six inches tall&#8221;, you say, &#8220;Wow.  This is very tall grass.&#8221;  <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier14_6.jpg' class='insetimage'   alt='frontier14_6.jpg' title='frontier14_6.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>One last thing.  I&#8217;m going to be stuck with Mr. 408 until my artist can produce the models.  (I want both male and female.) In the meantime, I want to see if I can make Mr. 408 a little more visually appealing. By using the vertex weights, I can identify the points for the head, hands, and feet. I can then &#8220;inflate&#8221; these parts to sort of approximate the whimsical style I&#8217;m aiming for. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/frontier14_7.jpg' class='insetimage'   alt='frontier14_7.jpg' title='frontier14_7.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Eh. There really is no substitute for having a proper artist. <\/p>\n<p>At any rate, it works. I&#8217;ll probably have to revisit this once I start dropping real art assets in, but this is good enough for now. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>So I have an animation system that works. I also have a system to import animations from bvh files. Now all I need is a figure to animate. I have a look at the various file formats available to Blender. There aren&#8217;t many. (The previous version of Blender had a LOT more file formats, but [&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-12242","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\/12242","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=12242"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/12242\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=12242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=12242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=12242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}