matrices_and_transforms.rst 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. .. _doc_matrices_and_transforms:
  2. Matrices and transforms
  3. =======================
  4. Introduction
  5. ------------
  6. Before reading this tutorial, we recommend that you thoroughly read
  7. and understand the :ref:`doc_vector_math` tutorial, as this tutorial
  8. requires a knowledge of vectors.
  9. This tutorial is about *transformations* and how we represent them
  10. in Godot using matrices. It is not a full in-depth guide to matrices.
  11. Transformations are most of the time applied as translation, rotation,
  12. and scale, so we will focus on how to represent those with matrices.
  13. Most of this guide focuses on 2D, using :ref:`class_Transform2D` and
  14. :ref:`class_Vector2`, but the way things work in 3D is very similar.
  15. .. note:: As mentioned in the previous tutorial, it is important to
  16. remember that in Godot, the Y axis points *down* in 2D.
  17. This is the opposite of how most schools teach linear
  18. algebra, with the Y axis pointing up.
  19. .. note:: The convention is that the X axis is red, the Y axis is
  20. green, and the Z axis is blue. This tutorial is color-coded
  21. to match these conventions, but we will also represent
  22. the origin vector with a blue color.
  23. Matrix components and the Identity matrix
  24. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25. The identity matrix represents a transform with no translation,
  26. no rotation, and no scale. Let's start by looking at the identity
  27. matrix and how its components relate to how it visually appears.
  28. .. image:: img/matrices_and_transforms/identity.png
  29. Matrices have rows and columns, and a transformation matrix has
  30. specific conventions on what each does.
  31. In the image above, we can see that the red X vector is represented
  32. by the first column of the matrix, and the green Y vector is
  33. likewise represented by the second column. A change to the columns
  34. will change these vectors. We will see how they can be manipulated
  35. in the next few examples.
  36. You should not worry about manipulating rows directly, as we usually
  37. work with columns. However, you can think of the rows of the matrix
  38. as showing which vectors contribute to moving in a given direction.
  39. When we refer to a value such as `t.x.y`, that's the Y component of
  40. the X column vector. In other words, the bottom-left of the matrix.
  41. Similarly, `t.x.x` is top-left, `t.y.x` is top-right, and `t.y.y`
  42. is bottom-right, where `t` is the Transform2D.
  43. Scaling the transformation matrix
  44. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  45. Applying a scale is one of the easiest operations to understand.
  46. Let's start by placing the Godot logo underneath our vectors
  47. so that we can visually see the effects on an object:
  48. .. image:: img/matrices_and_transforms/identity-godot.png
  49. Now, to scale the matrix, all we need to do is multiply each
  50. component by the scale we want. Let's scale it up by 2. 1 times 2
  51. becomes 2, and 0 times 2 becomes 0, so we end up with this:
  52. .. image:: img/matrices_and_transforms/scale.png
  53. To do this in code, we can simply multiply each of the vectors:
  54. .. tabs::
  55. .. code-tab:: gdscript GDScript
  56. var t = Transform2D()
  57. # Scale
  58. t.x *= 2
  59. t.y *= 2
  60. transform = t # Change the node's transform to what we just calculated.
  61. .. code-tab:: csharp
  62. Transform2D t = Transform2D.Identity;
  63. // Scale
  64. t.x *= 2;
  65. t.y *= 2;
  66. Transform = t; // Change the node's transform to what we just calculated.
  67. If we wanted to return it to its original scale, we can multiply
  68. each component by 0.5. That's pretty much all there is to scaling
  69. a transformation matrix.
  70. To calculate the object's scale from an existing transformation
  71. matrix, you can use `length()` on each of the column vectors.
  72. .. note:: In actual projects, you can use the `scaled()`
  73. method to perform scaling.
  74. Rotating the transformation matrix
  75. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  76. We'll start the same way as earlier, with the Godot logo underneath
  77. the identity matrix:
  78. .. image:: img/matrices_and_transforms/identity-godot.png
  79. As an example, let's say we want to rotate our Godot logo clockwise
  80. by 90 degrees. Right now the X axis points right and the Y axis
  81. points down. If we rotate these in our head, we would logically
  82. see that the new X axis should point down and the new Y axis
  83. should point left.
  84. You can imagine that you grab both the Godot logo and its vectors,
  85. and then spin it around the center. Wherever you finish spinning,
  86. the orientation of the vectors determines what the matrix is.
  87. We need to represent "down" and "left" in normal coordinates,
  88. so means we'll set X to (0, 1) and Y to (-1, 0). These are
  89. also the values of `Vector2.DOWN` and `Vector2.LEFT`.
  90. When we do this, we get the desired result of rotating the object:
  91. .. image:: img/matrices_and_transforms/rotate1.png
  92. If you have trouble understanding the above, try this exercise:
  93. Cut a square of paper, draw X and Y vectors on top of it, place
  94. it on graph paper, then rotate it and note the endpoints.
  95. To perform rotation in code, we need to be able to calculate
  96. the values programmatically. This image shows the formulas needed
  97. to calculate the transformation matrix from a rotation angle.
  98. Don't worry if this part seems complicated, I promise it's the
  99. hardest thing you need to know.
  100. .. image:: img/matrices_and_transforms/rotate2.png
  101. .. note:: Godot represents all rotations with radians, not degrees.
  102. A full turn is `TAU` or `PI*2` radians, and a quarter
  103. turn of 90 degrees is `TAU/4` or `PI/2` radians. Working
  104. with `TAU` usually results in more readable code.
  105. .. note:: Fun fact: In addition to Y being *down* in Godot, rotation
  106. is represented clockwise. This means that all the math and
  107. trig functions behave the same as a Y-is-up CCW system,
  108. since these differences "cancel out". You can think of
  109. rotations in both systems being "from X to Y".
  110. In order to perform a rotation of 0.5 radians (about 28.65 degrees),
  111. we simply plug in a value of 0.5 to the formula above and evaluate
  112. to find what the actual values should be:
  113. .. image:: img/matrices_and_transforms/rotate3.png
  114. Here's how that would be done in code (place the script on a Node2D):
  115. .. tabs::
  116. .. code-tab:: gdscript GDScript
  117. var rot = 0.5 # The rotation to apply.
  118. var t = Transform2D()
  119. t.x.x = cos(rot)
  120. t.y.y = cos(rot)
  121. t.x.y = sin(rot)
  122. t.y.x = -sin(rot)
  123. transform = t # Change the node's transform to what we just calculated.
  124. .. code-tab:: csharp
  125. float rot = 0.5f; // The rotation to apply.
  126. Transform2D t = Transform2D.Identity;
  127. t.x.x = t.y.y = Mathf.Cos(rot);
  128. t.x.y = t.y.x = Mathf.Sin(rot);
  129. t.y.x *= -1;
  130. Transform = t; // Change the node's transform to what we just calculated.
  131. To calculate the object's rotation from an existing transformation
  132. matrix, you can use `atan2(t.x.y, t.x.x)`, where t is the Transform2D.
  133. .. note:: In actual projects, you can use the `rotated()`
  134. method to perform rotations.
  135. Basis of the transformation matrix
  136. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  137. So far we have only been working with the `x` and `y`, vectors, which
  138. are in charge of representing rotation, scale, and/or shearing
  139. (advanced, covered at the end). The X and Y vectors are together
  140. called the *basis* of the transformation matrix. The terms "basis"
  141. and "basis vectors" are important to know.
  142. You might have noticed that :ref:`class_Transform2D` actually
  143. has three :ref:`class_Vector2` values: `x`, `y`, and `origin`.
  144. The `origin` value is not part of the basis, but it is part of the
  145. transform, and we need it to represent position. From now on we'll
  146. keep track of the origin vector in all examples. You can think of
  147. origin as another column, but it's often better to think of it as
  148. completely separate.
  149. Note that in 3D, Godot has a separate :ref:`class_Basis` structure
  150. for holding the three :ref:`class_Vector3` values of the basis,
  151. since the code can get complex and it makes sense to separate
  152. it from :ref:`class_Transform` (which is composed of one
  153. :ref:`class_Basis` and one extra :ref:`class_Vector3` for the origin).
  154. Translating the transformation matrix
  155. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  156. Changing the `origin` vector is called a *translating* the transformation
  157. matrix. Translating is basically a technical term for "moving" the
  158. object, but it explicitly does not involve any rotation.
  159. Let's work through an example to help understand this. We will start
  160. with the identity transform like last time, except we will keep track
  161. of the origin vector this time.
  162. .. image:: img/matrices_and_transforms/identity-origin.png
  163. If we want the object to move to a position of (1, 2), we simply need
  164. to set its `origin` vector to (1, 2):
  165. .. image:: img/matrices_and_transforms/translate.png
  166. There is also a `translated()` method, which performs a different
  167. operation to adding or changing `origin` directly. The `translated()`
  168. method will translate the object *relative to its own rotation*.
  169. For example, an object rotated 90 degrees clockwise will move to
  170. the right when `translated()` with `Vector2.UP`.
  171. .. note:: Godot's 2D uses coordinates based on pixels, so in actual
  172. projects you will want to translate by hundreds of units.
  173. Putting it all together
  174. ~~~~~~~~~~~~~~~~~~~~~~~
  175. We're going to apply everything we mentioned so far onto one transform.
  176. To follow along, create a simple project with a Sprite node and use the
  177. Godot logo for the texture resource.
  178. Let's set the translation to (350, 150), rotate by -0.5 rad, and scale by 3.
  179. I've posted a screenshot, and the code to reproduce it, but I encourage
  180. you to try and reproduce the screenshot without looking at the code!
  181. .. image:: img/matrices_and_transforms/putting-all-together.png
  182. .. tabs::
  183. .. code-tab:: gdscript GDScript
  184. var t = Transform2D()
  185. # Translation
  186. t.origin = Vector2(350, 150)
  187. # Rotation
  188. var rot = -0.5 # The rotation to apply.
  189. t.x.x = cos(rot)
  190. t.y.y = cos(rot)
  191. t.x.y = sin(rot)
  192. t.y.x = -sin(rot)
  193. # Scale
  194. t.x *= 3
  195. t.y *= 3
  196. transform = t # Change the node's transform to what we just calculated.
  197. .. code-tab:: csharp
  198. Transform2D t = Transform2D.Identity;
  199. // Translation
  200. t.origin = new Vector2(350, 150);
  201. // Rotation
  202. float rot = -0.5f; // The rotation to apply.
  203. t.x.x = t.y.y = Mathf.Cos(rot);
  204. t.x.y = t.y.x = Mathf.Sin(rot);
  205. t.y.x *= -1;
  206. // Scale
  207. t.x *= 3;
  208. t.y *= 3;
  209. Transform = t; // Change the node's transform to what we just calculated.
  210. Shearing the transformation matrix (advanced)
  211. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  212. .. note:: If you are only looking for how to *use* transformation matrices,
  213. feel free to skip this section of the tutorial. This section
  214. explores an uncommonly used aspect of transformation matrices
  215. for the purpose of building an understanding of them.
  216. You may have noticed that a transform has more degrees of freedom than
  217. the combination of the above actions. The basis of a 2D transformation
  218. matrix has four total numbers in two :ref:`class_Vector2` values, while
  219. a rotation value and a Vector2 for scale only has 3 numbers. The high-level
  220. concept for the missing degree of freedom is called *shearing*.
  221. Normally, you will always have the basis vectors perpendicular to each
  222. other. However, shearing can be useful in some situations, and
  223. understanding shearing helps you understand how transforms work.
  224. To show you visually how it will look, let's overlay a grid onto the Godot
  225. logo:
  226. .. image:: img/matrices_and_transforms/identity-grid.png
  227. Each point on this grid is obtained by adding the basis vectors together.
  228. The bottom-right corner is X + Y, while the top-right corner is X - Y.
  229. If we change the basis vectors, the entire grid moves with it, as the
  230. grid is composed of the basis vectors. All lines on the grid that are
  231. currently parallel will remain parallel no matter what changes we make to
  232. the basis vectors.
  233. As an example, let's set Y to (1, 1):
  234. .. image:: img/matrices_and_transforms/shear.png
  235. .. tabs::
  236. .. code-tab:: gdscript GDScript
  237. var t = Transform2D()
  238. # Shear by setting Y to (1, 1)
  239. t.y = Vector2.ONE
  240. transform = t # Change the node's transform to what we just calculated.
  241. .. code-tab:: csharp
  242. Transform2D t = Transform2D.Identity;
  243. // Shear by setting Y to (1, 1)
  244. t.y = Vector2.One;
  245. Transform = t; // Change the node's transform to what we just calculated.
  246. .. note:: You can't set the raw values of a Transform2D in the editor,
  247. so you *must* use code if you want to shear the object.
  248. Due to the vectors no longer being perpendicular, the object has been
  249. sheared. The bottom-center of the grid, which is (0, 1) relative
  250. to itself, is now located at a world position of (1, 1).
  251. The intra-object coordinates are called UV coordinates in textures,
  252. so let's borrow that terminology for here. To find the world position
  253. from a relative position, the formula is U * X + V * Y, where U and V
  254. are numbers and X and Y are the basis vectors.
  255. The bottom-right corner of the grid, which is always at the UV position
  256. of (1, 1), is at the world position of (2, 1), which is calculated from
  257. X*1 + Y*1, which is (1, 0) + (1, 1), or (1 + 1, 0 + 1), or (2, 1).
  258. This matches up with our observation of where the bottom-right corner
  259. of the image is.
  260. Similarly, the top-right corner of the grid, which is always at the UV
  261. position of (1, -1), is at the world position of (0, -1), which is calculated
  262. from X*1 + Y*-1, which is (1, 0) - (1, 1), or (1 - 1, 0 - 1), or (0, -1).
  263. This matches up with our observation of where the top-right corner
  264. of the image is.
  265. Hopefully you now fully understand the how a transformation matrix affects
  266. the object, and the relationship between the basis vectors and how the
  267. object's "UV" or "intra-coordinates" have their world position changed.
  268. .. note:: In Godot, all transform math is done relative to the parent node.
  269. When we refer to "world position", that would be relative to the
  270. node's parent instead, if the node had a parent.
  271. If you would like additional explanation, you should check out
  272. 3Blue1Brown's excellent video about linear transformations:
  273. https://www.youtube.com/watch?v=kYB8IZa5AuE
  274. Practical applications of transforms
  275. ------------------------------------
  276. In actual projects, you will usually be working with transforms inside
  277. transforms by having multiple :ref:`class_Node2D` or :ref:`class_Spatial`
  278. nodes parented to each other.
  279. However, sometimes it's very useful to manually calculate the values we
  280. need. We will go over how you could use :ref:`class_Transform2D` or
  281. :ref:`class_Transform` to manually calculate transforms of nodes.
  282. Converting positions between transforms
  283. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  284. There are many cases where you'd want to convert a position in and out of
  285. a transform. For example, if you have a position relative to the player
  286. and would like to find the world (parent-relative) position, or if you
  287. have a world position and want to know where it is relative to the player.
  288. We can find what a vector relative to the player would be defined in
  289. world space as using the "xform" method:
  290. .. tabs::
  291. .. code-tab:: gdscript GDScript
  292. # World space vector 100 units below the player.
  293. print(transform.xform(Vector2(0, 100)))
  294. .. code-tab:: csharp
  295. // World space vector 100 units below the player.
  296. GD.Print(Transform.Xform(new Vector2(0, 100)));
  297. And we can use the "xform_inv" method to find a what world space position
  298. would be if it was instead defined relative to the player:
  299. .. tabs::
  300. .. code-tab:: gdscript GDScript
  301. # Where is (0, 100) relative to the player?
  302. print(transform.xform_inv(Vector2(0, 100)))
  303. .. code-tab:: csharp
  304. // Where is (0, 100) relative to the player?
  305. GD.Print(Transform.XformInv(new Vector2(0, 100)));
  306. .. note:: If you know in advance that the transform is positioned at
  307. (0, 0), you can use the "basis_xform" or "basis_xform_inv"
  308. methods instead, which skip dealing with translation.
  309. Moving an object relative to itself
  310. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  311. A common operation, especially in 3D games, is to move an object relative
  312. to itself. For example, in first-person shooter games, you would want the
  313. character to move forward (-Z axis) when you press :kbd:`W`.
  314. Since the basis vectors are the orientation relative to the parent,
  315. and the origin vector is the position relative to the parent, we can simply
  316. add multiples of the basis vectors to move an object relative to itself.
  317. This code moves an object 100 units to its own right:
  318. .. tabs::
  319. .. code-tab:: gdscript GDScript
  320. transform.origin += transform.x * 100
  321. .. code-tab:: csharp
  322. Transform2D t = Transform;
  323. t.origin += t.x * 100;
  324. Transform = t;
  325. For moving in 3D, you would need to replace "x" with "basis.x".
  326. .. note:: In actual projects, you can use `translate_object_local` in 3D
  327. or `move_local_x` and `move_local_y` in 2D to do this.
  328. Applying transforms onto transforms
  329. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  330. One of the most important things to know about transforms is how you
  331. can use several of them together. A parent node's transform affects
  332. all of its children. Let's dissect an example.
  333. In this image, the child node has a "2" after the component names
  334. to distinguish them from the parent node. It might look a bit
  335. overwhelming with so many numbers, but remember that each number
  336. is displayed twice (next to the arrows and also in the matrices),
  337. and that almost half of the numbers are zero.
  338. .. image:: img/matrices_and_transforms/apply.png
  339. The only transformations going on here are that the parent node has
  340. been given a scale of (2, 1), the child has been given a scale of
  341. (0.5, 0.5), and both nodes have been given positions.
  342. All child transformations are affected by the parent transformations.
  343. The child has a scale of (0.5, 0.5), so you would expect it to be
  344. a 1:1 ratio square, and it is, but only relative to the parent.
  345. The child's X vector ends up being (1, 0) in world space, because
  346. it is scaled by the parent's basis vectors.
  347. Similarly, the child node's `origin` vector is set to (1, 1), but this
  348. actually moves it (2, 1) in world space, due to the parent node's
  349. basis vectors.
  350. To calculate a child transform's world space transform manually, this is
  351. the code we would use:
  352. .. tabs::
  353. .. code-tab:: gdscript GDScript
  354. # Set up transforms just like in the image, except make positions be 100 times bigger.
  355. var parent = Transform2D(Vector2(2, 0), Vector2(0, 1), Vector2(100, 200))
  356. var child = Transform2D(Vector2(0.5, 0), Vector2(0, 0.5), Vector2(100, 100))
  357. # Calculate the child's world space transform
  358. # origin = (2, 0) * 100 + (0, 1) * 100 + (100, 200)
  359. var origin = parent.x * child.origin.x + parent.y * child.origin.y + parent.origin
  360. # basis_x = (2, 0) * 0.5 + (0, 1) * 0
  361. var basis_x = parent.x * child.x.x + parent.y * child.x.y
  362. # basis_y = (2, 0) * 0 + (0, 1) * 0.5
  363. var basis_y = parent.x * child.y.x + parent.y * child.y.y
  364. # Change the node's transform to what we just calculated.
  365. transform = Transform2D(basis_x, basis_y, origin)
  366. .. code-tab:: csharp
  367. // Set up transforms just like in the image, except make positions be 100 times bigger.
  368. Transform2D parent = new Transform2D(2, 0, 0, 1, 100, 200);
  369. Transform2D child = new Transform2D(0.5f, 0, 0, 0.5f, 100, 100);
  370. // Calculate the child's world space transform
  371. // origin = (2, 0) * 100 + (0, 1) * 100 + (100, 200)
  372. Vector2 origin = parent.x * child.origin.x + parent.y * child.origin.y + parent.origin;
  373. // basisX = (2, 0) * 0.5 + (0, 1) * 0 = (0.5, 0)
  374. Vector2 basisX = parent.x * child.x.x + parent.y * child.x.y;
  375. // basisY = (2, 0) * 0 + (0, 1) * 0.5 = (0.5, 0)
  376. Vector2 basisY = parent.x * child.y.x + parent.y * child.y.y;
  377. // Change the node's transform to what we just calculated.
  378. Transform = new Transform2D(basisX, basisY, origin);
  379. In actual projects, we can find the world transform of the child by
  380. applying one transform onto another using the `*` operator:
  381. .. tabs::
  382. .. code-tab:: gdscript GDScript
  383. # Set up transforms just like in the image, except make positions be 100 times bigger.
  384. var parent = Transform2D(Vector2(2, 0), Vector2(0, 1), Vector2(100, 200))
  385. var child = Transform2D(Vector2(0.5, 0), Vector2(0, 0.5), Vector2(100, 100))
  386. # Change the node's transform to what would be the child's world transform.
  387. transform = parent * child
  388. .. code-tab:: csharp
  389. // Set up transforms just like in the image, except make positions be 100 times bigger.
  390. Transform2D parent = new Transform2D(2, 0, 0, 1, 100, 200);
  391. Transform2D child = new Transform2D(0.5f, 0, 0, 0.5f, 100, 100);
  392. // Change the node's transform to what would be the child's world transform.
  393. Transform = parent * child;
  394. .. note:: When multiplying matrices, order matters! Don't mix them up.
  395. Lastly, applying the identity transform will always do nothing.
  396. If you would like additional explanation, you should check out
  397. 3Blue1Brown's excellent video about matrix composition:
  398. https://www.youtube.com/watch?v=XkY2DOUCWMU
  399. Inverting a transformation matrix
  400. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  401. The "affine_inverse" function returns a transform that "undoes" the
  402. previous transform. This can be useful in some situations, but it's
  403. easier to just provide a few examples.
  404. Multiplying an inverse transform by the normal transform undoes all
  405. transformations:
  406. .. tabs::
  407. .. code-tab:: gdscript GDScript
  408. var ti = transform.affine_inverse()
  409. var t = ti * transform
  410. # The transform is the identity transform.
  411. .. code-tab:: csharp
  412. Transform2D ti = Transform.AffineInverse();
  413. Transform2D t = ti * Transform;
  414. // The transform is the identity transform.
  415. Transforming a position by a transform and its inverse results in the
  416. same position (same for "xform_inv"):
  417. .. tabs::
  418. .. code-tab:: gdscript GDScript
  419. var ti = transform.affine_inverse()
  420. position = transform.xform(position)
  421. position = ti.xform(position)
  422. # The position is the same as before.
  423. .. code-tab:: csharp
  424. Transform2D ti = Transform.AffineInverse();
  425. Position = Transform.Xform(Position);
  426. Position = ti.Xform(Position);
  427. // The position is the same as before.
  428. How does it all work in 3D?
  429. ---------------------------
  430. One of the great things about transformation matrices is that they
  431. work very similarly between 2D and 3D transformations.
  432. All the code and formulas used above for 2D work the same in 3D,
  433. with 3 exceptions: the addition of a third axis, that each
  434. axis is of type :ref:`class_Vector3`, and also that Godot stores
  435. the :ref:`class_Basis` separately from the :ref:`class_Transform`,
  436. since the math can get complex and it makes sense to separate it.
  437. All of the concepts for how translation, rotation, scale, and shearing
  438. work in 3D are all the same compared to 2D. To scale, we take each
  439. component and multiply it; to rotate, we change where each basis vector
  440. is pointing; to translate, we manipulate the origin; and to shear, we
  441. change the basis vectors to be non-perpendicular.
  442. .. image:: img/matrices_and_transforms/3d-identity.png
  443. If you would like, it's a good idea to play around with transforms
  444. to get an understanding of how they work. Godot allows you to edit
  445. 3D transform matrices directly from the inspector. You can download
  446. this project which has colored lines and cubes to help visualize the
  447. :ref:`class_Basis` vectors and the origin in both 2D and 3D:
  448. https://github.com/godotengine/godot-demo-projects/tree/master/misc/matrix_transform
  449. .. note:: Spatial's "Matrix" section in Godot 3.2's inspector
  450. displays the matrix as transposed, with the columns
  451. horizontal and the rows vertical. This may be changed
  452. to be less confusing in a future release of Godot.
  453. .. note:: You cannot edit Node2D's transform matrix directly in Godot 3.2's
  454. inspector. This may be changed in a future release of Godot.
  455. If you would like additional explanation, you should check out
  456. 3Blue1Brown's excellent video about 3D linear transformations:
  457. https://www.youtube.com/watch?v=rHLEWRxRGiM
  458. Representing rotation in 3D (advanced)
  459. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  460. The biggest difference between 2D and 3D transformation matrices is
  461. how you represent rotation by itself without the basis vectors.
  462. With 2D, we have an easy way (atan2) to switch between a transformation
  463. matrix and an angle. In 3D, we can't simply represent rotation as one
  464. number. There is something called Euler angles, which can represent
  465. rotations as a set of 3 numbers, however, they are limited and not very
  466. useful, except for trivial cases.
  467. In 3D we do not typically use angles, we either use a transformation basis
  468. (used pretty much everywhere in Godot), or we use quaternions. Godot can
  469. represent quaternions using the :ref:`class_Quat` struct. My suggestion
  470. to you is to completely ignore how they work under-the-hood, because
  471. they are very complicated and unintuitive.
  472. However, if you really must know how it works, here are some great
  473. resources, which you can follow in order:
  474. https://www.youtube.com/watch?v=mvmuCPvRoWQ
  475. https://www.youtube.com/watch?v=d4EgbgTm0Bg
  476. https://eater.net/quaternions