{"id":11241,"date":"2011-04-04T05:41:12","date_gmt":"2011-04-04T10:41:12","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=11241"},"modified":"2011-04-04T05:41:12","modified_gmt":"2011-04-04T10:41:12","slug":"transformation-matrix","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=11241","title":{"rendered":"Transformation Matrix"},"content":{"rendered":"<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/splash_keyboard.jpg' class='insetimage'   alt='splash_keyboard.jpg' title='splash_keyboard.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>So you&#8217;re curious about the math involved in graphics programming.  Well, <em>someone<\/em> is. People ask me about this stuff now and again. But a subject like &#8220;the math of graphics programming&#8221; is large enough to fill one of those great, big reference books that nobody likes to use because they&#8217;re so heavy and they take up so much space. <\/p>\n<p>Years ago I had a devil of a time learning this for myself. Most tutorials are dense with Greek symbols and mercilessly heavy on jargon. It&#8217;s one of those situations where you have to already understand the subject before you can comprehend the lessons to teach you the subject. So I offer my own explanation here for the curious. This won&#8217;t teach you everything you need to know, but it might help give you a frame of reference so the other lessons make sense. Or it might just be a fun way to blow five minutes. Whatever.<\/p>\n<p><!--more-->Naturally, making computer graphics starts with things that have x, y, and z coordinates. Even in 2D games. (Remember that 2D games are called this because the <em>gameplay<\/em> is 2D.  You still have backgrounds and other elements that need to be drawn in the distance.  You&#8217;ve got scenery behind the main character, the game pieces, the Pokemans, or whatever else you&#8217;ve got going on there in your little game.  <\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/3dmatrix_shank.jpg' class='insetimage' width='600' alt='It&#8217;s a 2D game, but there&#8217;s still depth as far as the programmer is concerned.' title='It&#8217;s a 2D game, but there&#8217;s still depth as far as the programmer is concerned.'\/><\/td><\/tr><tr><td class='insetcaption'>It&#8217;s a 2D game, but there&#8217;s still depth as far as the programmer is concerned.<\/td><\/tr><\/table><\/p>\n<p>Observe programmers sometime and you&#8217;ll notice that there is no right way to do something, only a dozen wrong ones with varying drawbacks and annoyances. In 3D, one of those annoyances is in deciding what x, y, and z <em>mean<\/em>.  X is the one variable we mostly agree on.  X is for east \/ west positioning, although nobody can say for sure if positive x should go east and negative x should go west, or the other way around. It gets even trickier with y and z, since we can&#8217;t agree on which one is up and which one controls north \/ south movement, and which way they point.  <\/p>\n<p>These distinctions are not meaningless. Even in a game where the player doesn&#8217;t have a sense of which way is objectively &#8220;up&#8221;, the level designers had one in mind when they built the thing.  Even if the player doesn&#8217;t think of the world in terms of up \/ down, left \/ right, the artists and designers did, if for no other reason than they needed a common language with which to discuss their work.<\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/3dmatrix_eden.jpg' class='insetimage' width='600' alt='In Child of Eden, you don&#8217;t really have a sense of direction. But the designers did.' title='In Child of Eden, you don&#8217;t really have a sense of direction. But the designers did.'\/><\/td><\/tr><tr><td class='insetcaption'>In Child of Eden, you don&#8217;t really have a sense of direction. But the designers did.<\/td><\/tr><\/table><\/p>\n<p>If you&#8217;re writing a game, it&#8217;s very, very common to have some sort of variable to hold these three values in one handy package. Confusingly, this package is usually called a vector. (It&#8217;s been called a vector in every project I&#8217;ve worked on that <em>had<\/em> a name for it.)  This is confusing because x, y, z might be used as a vector or as a position. But I suppose &#8220;vector&#8221; is a better name than &#8220;three numbers thing&#8221; or &#8220;ecks why zee&#8221; or even &#8220;Donald&#8221;. <\/p>\n<p>So drawing a gameworld involves setting up some kind of space with some agreed-on orientation. Then you need to make 3D stuff move around in that space.  For that we need a <strong>Transformation Matrix<\/strong>.  It might sound like some techno-babble made up by the Wachowski Brothers, but it&#8217;s a real thing. &#8220;Transformation&#8221; for changing a set of numbers into another set, and &#8220;matrix&#8221; because we use a grid of values to do it. <\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/3dmatrix_minecraft1.jpg' class='insetimage' width='600' alt='3dmatrix_minecraft1.jpg' title='3dmatrix_minecraft1.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>So we&#8217;ve got some geometry.  We&#8217;ve created this cool 3D model of the player&#8217;s avatar. We&#8217;ve got all these 3d vertex positions that define the shape of this character. His head is a box, which has 8 corners. We draw a pair of triangles (in modern graphics, everything is always triangles &#8211; even rectangles are made from pairs of triangles) for each face of that cube.  So, 12 triangles in all.  The body is another cube, each of the arms is another, and the legs are two more. The Minecraft Guy is made from six cubes, which means means 72 triangles, which means 48 total vertex positions. We can just send those positions off to be rendered and call it a day. <\/p>\n<p>Except, players are notoriously impatient.  As nice as your model is, sooner or later these brats are going to want to <em>move that guy around<\/em>.  Great.  Thanks players. So the player tries to walk forward, or maybe turn to one side, and suddenly we&#8217;ve got to do something to this 3D character to reflect that. For that, we use the Transformation Matrix, which looks like this:<\/p>\n<table align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tr>\n<td>1<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>1<\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<\/tr>\n<\/table>\n<p>This grid of numbers allows us to <em>transform<\/em> the 48 positions from local-space to world-space, which is programming talk for &#8220;move that guy around&#8221;.  <\/p>\n<p>It works like this:<\/p>\n<p>The first row is for calculating our x position. Multiply our current x times the value in the first box.  Multiply y times the value in the second. Multiply z times the value in the third. Now add those three numbers together.  That will be the new, translated x position.<\/p>\n<p>Similarly, the second row is for calculating y. Multiply our current x times the value in the first box.  Multiply y times the value in the second. Multiply z times the value in the third. Now add those three numbers together.  That will be the new y position.<\/p>\n<p>Finally, the last row is for calculating z. Multiply our current x times the value in the first box.  Multiply y times the value in the second. Multiply z times the value in the third. Now add those three numbers together.  That will be the new z position.<\/p>\n<p>If you are very clever you will notice that I just did:<\/p>\n<p><tt>x = x * 1 + y * 0 + z * 0<\/tt><\/p>\n<p>And if you&#8217;re super-clever and have a bit of algebra, you might notice that the above operation does precisely nothing. The value of x will not change at all. Like the famous <a href=\"http:\/\/www.youtube.com\/watch?v=B3KBuQHHKx0\">cheese shop sketch<\/a>, I&#8217;ve just deliberately wasted your time.  Likewise the second row will do a bunch of math and set the value of y to what it was when you started, and the third row will work out that z should be&#8230; z.  Hm.<\/p>\n<p>The matrix I gave above is called the &#8220;identity matrix&#8221;.  When the grid is all zero except for a diagonal of one, then the output is going to be the same as the input. Don&#8217;t worry, the computer doesn&#8217;t mind the senseless work.<\/p>\n<p>But if we change the matrix to this:<\/p>\n<table align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tr>\n<td>0<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>1<\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>-1<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<\/tr>\n<\/table>\n<p>Now if we crank our values through this, x will end up with the value of z, and z will end up with the value of negative x.  Assuming y is used for up \/ down, this will have the result of making your avatar turn 90 degrees to one side. <\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/3dmatrix_minecraft2.jpg' class='insetimage' width='600' alt='3dmatrix_minecraft2.jpg' title='3dmatrix_minecraft2.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Crank all 48 vertex positions through this, and the Minecraft guy is now facing (say) east.  (This is just an example, I don&#8217;t actually know how Notch sets up his coordinate system.)  <\/p>\n<p>Usually the matrix is not filled with nice, neat numbers like ones and zeros.  See, you use sine and cosine to move these values around, so&#8230;<\/p>\n<table align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tr>\n<td>0.984808<\/td>\n<td>0<\/td>\n<td>-0.173648<\/td>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>1<\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td>0.173648<\/td>\n<td>0<\/td>\n<td>0.984808<\/td>\n<\/tr>\n<\/table>\n<p>Just happens to be the matrix that would rotate our guy ten degrees to the right. <\/p>\n<p>Done? Not quite. See, he&#8217;s still standing at the exact center of the world, and this will eventually bore players.   He needs to move as well as rotate.  I know the matrix I&#8217;ve been working with is a 3&#215;3 grid of numbers, but a proper matrix is 4&#215;4.  I just lied to you earlier in hopes that you would keep reading instead of getting scared and running off.  Here is a proper identity matrix:<\/p>\n<table align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tr>\n<td>1<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<td bgcolor=\"#ffff99\">1<\/td>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>1<\/td>\n<td>0<\/td>\n<td bgcolor=\"#ffff99\">1<\/td>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<td bgcolor=\"#ffff99\">1<\/td>\n<\/tr>\n<tr>\n<td bgcolor=\"#99ff99\">0<\/td>\n<td bgcolor=\"#99ff99\">0<\/td>\n<td bgcolor=\"#99ff99\">0<\/td>\n<td bgcolor=\"#ff9999\">1<\/td>\n<\/tr>\n<\/table>\n<p>The yellow boxes are used for scaling. So, after you go across that first row and figure out the value of x, you multiply the result by that last yellow box. Most of the time this box is simply set to one, and the result does not change. However, you could change this number to (say) ten, and suddenly the object being transformed will become ten times larger.<\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><a href='http:\/\/www.youtube.com\/watch?v=LGKB6VI7Pao'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/3dmatrix_minecraft3.jpg' class='insetimage' width='600' alt='3dmatrix_minecraft3.jpg' title='3dmatrix_minecraft3.jpg'\/><\/a><\/td><\/tr><\/table><\/p>\n<p>The green boxes are used for translation, which is fancy programmer talk for &#8220;moving&#8221;.  (<em>Translation<\/em> is moving something from one place to another. <em>Transformation<\/em> is the process of moving, rotating and scaling, combined.)   This is a bit odd, but once you&#8217;re done with x on the first row you add the first green box to the result. <\/p>\n<p>The red box is not used. By convention, people put a one in that box, just because it makes it seem like the thing has purpose, but setting this value at all is the equivalent of vacuuming behind the couch where nobody will ever, ever see. You can put in zero, or last night&#8217;s lottery number, or whatever else strikes your fancy, because no matrix math uses it.  I&#8217;m personally a fan of not setting it to any value in particular, which means it will be filled with random trash values. <\/p>\n<p>And no, I don&#8217;t move the couch when I vacuum.<\/p>\n<p>So to calculate x, you do:<\/p>\n<p><tt>x = x * 1 + y * 0 + z * 0<\/tt><\/p>\n<p>Then multiply the result by the yellow box.  Then add the result to the first green box.<\/p>\n<p>For y, you run the numbers on the second row, and add the second green box. z is the third row, added to the third green box.<\/p>\n<p>For the curious, in C++ the code might look like this:<\/p>\n<pre lang=\"c\" line=\"1\">\r\nGLvector glMatrixTransformPoint (GLmatrix m, GLvector in)\r\n{\r\n\r\n  GLvector              out;\r\n\r\n  out.x = M(m,0,3) * (M(m,0,0) * in.x + M(m,1,0) * in.y + M(m,2,0) * in.z) + M(m,3,0);\r\n  out.y = M(m,1,3) * (M(m,0,1) * in.x + M(m,1,1) * in.y + M(m,2,1) * in.z) + M(m,3,1);\r\n  out.z = M(m,2,3) * (M(m,0,2) * in.x + M(m,1,2) * in.y + M(m,2,2) * in.z) + M(m,3,2);\r\n  return out;\r\n\r\n}<\/pre>\n<p>Crank all of our 48 vertex positions through that sucker, and the Minecraft guy will be able to move around the world and rotate, just like your favorite videogame characters. In this way, our matrix can be thought of as a magic box.  Put stuff in, and it comes out in a different location and facing a different direction.  It&#8217;s a bit like the prism crates in the upcoming Portal 2:<\/p>\n<p><table class='nomargin' cellspacing='0' width='100%' cellpadding='0' align='center' border='0'><tr><td><iframe loading=\"lazy\" width=\"1024\" height=\"576\" src=\"https:\/\/www.youtube.com\/embed\/9DGPRiMWhEc\" frameborder=\"0\" allowfullscreen class=\"embed\"><\/iframe><br\/><small><a href='http:\/\/www.youtube.com\/watch?v=9DGPRiMWhEc'>Link (YouTube)<\/a><\/small><\/td><\/tr><\/table><\/p>\n<p>We can then stop worrying about the math under the hood.  Just rotate this matrix (by messing with the 3&#215;3 grid of numbers) or translate it (by changing the values of the green boxes) and crank our vertex positions through it. <\/p>\n<p><table width='600'  cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/3dmatrix_minecraft4.jpg' class='insetimage' width='600' alt='3dmatrix_minecraft4.jpg' title='3dmatrix_minecraft4.jpg'\/><\/td><\/tr><\/table><\/p>\n<p><em>But Shamus, the arms and legs move on the Minecraft guy.  How does your matrix thing do <\/em><em>THAT<\/em>?<\/p>\n<p>&#8230;<\/p>\n<p>You savage bastard. We&#8217;re 1,700 words into this explanation and now you&#8217;re going to ask a question like that? What kind of monster are you? Sigh. Okay. Basically, there&#8217;s another matrix for each of the moving parts. So you crank the arms through the full-body &#8220;avatar&#8221; matrix, then you run them through the &#8220;arm&#8221; matrix. One matrix can be nested in another.  <\/p>\n<p>Wrapping your head around matrix math is pretty much the cover charge to get into graphics programming. It&#8217;s a roundhouse kick to the left hemisphere of your brain, but if you can hang on long enough things will start to get easier. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>So you&#8217;re curious about the math involved in graphics programming. Well, someone is. People ask me about this stuff now and again. But a subject like &#8220;the math of graphics programming&#8221; is large enough to fill one of those great, big reference books that nobody likes to use because they&#8217;re so heavy and they take [&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-11241","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\/11241","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=11241"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/11241\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11241"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11241"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11241"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}