matrices_and_transforms.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. .. _doc_matrices_and_transforms:
  2. Matrices and transforms
  3. =======================
  4. Introduction
  5. ------------
  6. Before reading this tutorial, it is advised to read the previous one
  7. about :ref:`doc_vector_math` as this one is a direct continuation.
  8. This tutorial will be about *transformations* and will cover a little
  9. about matrices (but not in-depth).
  10. Transformations are most of the time applied as translation, rotation
  11. and scale so they will be considered as priority here.
  12. Oriented coordinate system (OCS)
  13. --------------------------------
  14. Imagine we have a spaceship somewhere in space. In Godot this is easy,
  15. just move the ship somewhere and rotate it:
  16. .. image:: /img/tutomat1.png
  17. Ok, so in 2D this looks simple, a position and an angle for a rotation.
  18. But remember, we are grown ups here and don't use angles (plus, angles
  19. are not really even that useful when working in 3D).
  20. We should realize that at some point, someone *designed* this
  21. spaceship. Be it for 2D in a drawing such as Paint.net, Gimp,
  22. Photoshop, etc. or in 3D through a 3D DCC tool such as Blender, Max,
  23. Maya, etc.
  24. When it was designed, it was not rotated. It was designed in its own
  25. *coordinate system*.
  26. .. image:: /img/tutomat2.png
  27. This means that the tip of the ship has a coordinate, the fin has
  28. another, etc. Be it in pixels (2D) or vertices (3D).
  29. So, let's recall again that the ship was somewhere in space:
  30. .. image:: /img/tutomat3.png
  31. How did it get there? What moved it and rotated it from the place it was
  32. designed to its current position? The answer is... a **transform**, the
  33. ship was *transformed* from their original position to the new one. This
  34. allows the ship to be displayed where it is.
  35. But transform is too generic of a term to describe this process. To solve this
  36. puzzle, we will superimpose the ship's original design position at their
  37. current position:
  38. .. image:: /img/tutomat4.png
  39. So, we can see that the "design space" has been transformed too. How can
  40. we best represent this transformation? Let's use 3 vectors for this (in
  41. 2D), a unit vector pointing towards X positive, a unit vector pointing
  42. towards Y positive and a translation.
  43. .. image:: /img/tutomat5.png
  44. Let's call the 3 vectors "X", "Y" and "Origin", and let's also
  45. superimpose them over the ship so it makes more sense:
  46. .. image:: /img/tutomat6.png
  47. Ok, this is nicer, but it still does not make sense. What do X,Y and
  48. Origin have to do with how the ship got there?
  49. Well, let's take the point from top tip of the ship as reference:
  50. .. image:: /img/tutomat7.png
  51. And let's apply the following operation to it (and to all the points in
  52. the ship too, but we'll track the top tip as our reference point):
  53. ::
  54. var new_pos = pos - origin
  55. Doing this to the selected point will move it back to the center:
  56. .. image:: /img/tutomat8.png
  57. This was expected, but then let's do something more interesting. Use the
  58. dot product of X and the point, and add it to the dot product of Y and
  59. the point:
  60. ::
  61. var final_pos = x.dot(new_pos) + y.dot(new_pos)
  62. Then what we have is.. wait a minute, it's the ship in its design
  63. position!
  64. .. image:: /img/tutomat9.png
  65. How did this black magic happen? The ship was lost in space, and now
  66. it's back home!
  67. It might seem strange, but it does have plenty of logic. Remember, as
  68. we have seen in the :ref:`doc_vector_math`, what
  69. happened is that the distance to X axis, and the distance to Y axis
  70. were computed. Calculating distance in a direction or plane was one of
  71. the uses for the dot product. This was enough to obtain back the
  72. design coordinates for every point in the ship.
  73. So, what he have been working with so far (with X, Y and Origin) is an
  74. *Oriented Coordinate System\*. X an Y are the **Basis**, and \*Origin*
  75. is the offset.
  76. Basis
  77. -----
  78. We know what the Origin is. It's where the 0,0 (origin) of the design
  79. coordinate system ended up after being transformed to a new position.
  80. This is why it's called *Origin*, But in practice, it's just an offset
  81. to the new position.
  82. The Basis is more interesting. The basis is the direction of X and Y in the OCS
  83. from the new, transformed location. It tells what has changed, in either 2D or
  84. 3D. The Origin (offset) and Basis (direction) communicate "Hey, the original X
  85. and Y axes of your design are *right here*, pointing towards *these
  86. directions*."
  87. So, let's change the representation of the basis. Instead of 2 vectors,
  88. let's use a *matrix*.
  89. .. image:: /img/tutomat10.png
  90. The vectors are up there in the matrix, horizontally. The next problem
  91. now is that.. what is this matrix thing? Well, we'll assume you've never
  92. heard of a matrix.
  93. Transforms in Godot
  94. -------------------
  95. This tutorial will not explain matrix math (and their operations) in
  96. depth, only its practical use. There is plenty of material for that,
  97. which should be a lot simpler to understand after completing this
  98. tutorial. We'll just explain how to use transforms.
  99. Matrix32
  100. --------
  101. :ref:`Matrix32 <class_Matrix32>` is a 3x2 matrix. It has 3 Vector2 elements and
  102. it's used for 2D. The "X" axis is the element 0, "Y" axis is the element 1 and
  103. "Origin" is element 2. It's not divided in basis/origin for convenience, due to
  104. its simplicity.
  105. ::
  106. var m = Matrix32()
  107. var x = m[0] # 'X'
  108. var y = m[1] # 'Y'
  109. var o = m[2] # 'Origin'
  110. Most operations will be explained with this datatype (Matrix32), but the
  111. same logic applies to 3D.
  112. Identity
  113. --------
  114. By default, Matrix32 is created as an "identity" matrix. This means:
  115. - 'X' Points right: Vector2(1,0)
  116. - 'Y' Points up (or down in pixels): Vector2(0,1)
  117. - 'Origin' is the origin Vector2(0,0)
  118. .. image:: /img/tutomat11.png
  119. It's easy to guess that an *identity* matrix is just a matrix that
  120. aligns the transform to its parent coordinate system. It's an *OCS*
  121. that hasn't been translated, rotated or scaled. All transform types in
  122. Godot are created with *identity*.
  123. Operations
  124. ----------
  125. Rotation
  126. --------
  127. Rotating Matrix32 is done by using the "rotated" function:
  128. ::
  129. var m = Matrix32()
  130. m = m.rotated(PI/2) # rotate 90°
  131. .. image:: /img/tutomat12.png
  132. Translation
  133. -----------
  134. There are two ways to translate a Matrix32, the first one is just moving
  135. the origin:
  136. ::
  137. # Move 2 units to the right
  138. var m = Matrix32()
  139. m = m.rotated(PI/2) # rotate 90°
  140. m[2]+=Vector2(2,0)
  141. .. image:: /img/tutomat13.png
  142. This will always work in global coordinates.
  143. If instead, translation is desired in *local* coordinates of the
  144. matrix (towards where the *basis* is oriented), there is the
  145. :ref:`Matrix32.translated() <class_Matrix32_translated>`
  146. method:
  147. ::
  148. # Move 2 units towards where the basis is oriented
  149. var m = Matrix32()
  150. m = m.rotated(PI/2) # rotate 90°
  151. m=m.translated( Vector2(2,0) )
  152. .. image:: /img/tutomat14.png
  153. Scale
  154. -----
  155. A matrix can be scaled too. Scaling will multiply the basis vectors by a
  156. vector (X vector by x component of the scale, Y vector by y component of
  157. the scale). It will leave the origin alone:
  158. ::
  159. # Make the basis twice its size.
  160. var m = Matrix32()
  161. m = m.scaled( Vector2(2,2) )
  162. .. image:: /img/tutomat15.png
  163. These kind of operations in matrices are accumulative. It means every
  164. one starts relative to the previous one. For those who have been living
  165. on this planet long enough, a good reference of how transform works is
  166. this:
  167. .. image:: /img/tutomat16.png
  168. A matrix is used similarly to a turtle. The turtle most likely had a
  169. matrix inside (and you are likely learning this many years *after*
  170. discovering Santa is not real).
  171. Transform
  172. ---------
  173. Transform is the act of switching between coordinate systems. To convert
  174. a position (either 2D or 3D) from "designer" coordinate system to the
  175. OCS, the "xform" method is used.
  176. ::
  177. var new_pos = m.xform(pos)
  178. And only for basis (no translation):
  179. ::
  180. var new_pos = m.basis_xform(pos)
  181. Post - multiplying is also valid:
  182. ::
  183. var new_pos = m * pos
  184. Inverse transform
  185. -----------------
  186. To do the opposite operation (what we did up there with the rocket), the
  187. "xform_inv" method is used:
  188. ::
  189. var new_pos = m.xform_inv(pos)
  190. Only for Basis:
  191. ::
  192. var new_pos = m.basis_xform_inv(pos)
  193. Or pre-multiplication:
  194. ::
  195. var new_pos = pos * m
  196. Orthonormal matrices
  197. --------------------
  198. However, if the Matrix has been scaled (vectors are not unit length),
  199. or the basis vectors are not orthogonal (90°), the inverse transform
  200. will not work.
  201. In other words, inverse transform is only valid in *orthonormal*
  202. matrices. For this, these cases an affine inverse must be computed.
  203. The transform, or inverse transform of an identity matrix will return
  204. the position unchanged:
  205. ::
  206. # Does nothing, pos is unchanged
  207. pos = Matrix32().xform(pos)
  208. Affine inverse
  209. --------------
  210. The affine inverse is a matrix that does the inverse operation of
  211. another matrix, no matter if the matrix has scale or the axis vectors
  212. are not orthogonal. The affine inverse is calculated with the
  213. affine_inverse() method:
  214. ::
  215. var mi = m.affine_inverse()
  216. var pos = m.xform(pos)
  217. pos = mi.xform(pos)
  218. # pos is unchanged
  219. If the matrix is orthonormal, then:
  220. ::
  221. # if m is orthonormal, then
  222. pos = mi.xform(pos)
  223. # is the same is
  224. pos = m.xform_inv(pos)
  225. Matrix multiplication
  226. ---------------------
  227. Matrices can be multiplied. Multiplication of two matrices "chains"
  228. (concatenates) their transforms.
  229. However, as per convention, multiplication takes place in reverse
  230. order.
  231. Example:
  232. ::
  233. var m = more_transforms * some_transforms
  234. To make it a little clearer, this:
  235. ::
  236. pos = transform1.xform(pos)
  237. pos = transform2.xform(pos)
  238. Is the same as:
  239. ::
  240. # note the inverse order
  241. pos = (transform2 * transform1).xform(pos)
  242. However, this is not the same:
  243. ::
  244. # yields a different results
  245. pos = (transform1 * transform2).xform(pos)
  246. Because in matrix math, A + B is not the same as B + A.
  247. Multiplication by inverse
  248. -------------------------
  249. Multiplying a matrix by its inverse, results in identity
  250. ::
  251. # No matter what A is, B will be identity
  252. B = A.affine_inverse() * A
  253. Multiplication by identity
  254. --------------------------
  255. Multiplying a matrix by identity, will result in the unchanged matrix:
  256. ::
  257. # B will be equal to A
  258. B = A * Matrix32()
  259. Matrix tips
  260. -----------
  261. When using a transform hierarchy, remember that matrix multiplication is
  262. reversed! To obtain the global transform for a hierarchy, do:
  263. ::
  264. var global_xform = parent_matrix * child_matrix
  265. For 3 levels:
  266. ::
  267. # due to reverse order, parenthesis are needed
  268. var global_xform = gradparent_matrix + (parent_matrix + child_matrix)
  269. To make a matrix relative to the parent, use the affine inverse (or
  270. regular inverse for orthonormal matrices).
  271. ::
  272. # transform B from a global matrix to one local to A
  273. var B_local_to_A = A.affine_inverse() * B
  274. Revert it just like the example above:
  275. ::
  276. # transform back local B to global B
  277. var B = A * B_local_to_A
  278. OK, hopefully this should be enough! Let's complete the tutorial by
  279. moving to 3D matrices.
  280. Matrices & transforms in 3D
  281. ---------------------------
  282. As mentioned before, for 3D, we deal with 3 :ref:`Vector3 <class_Vector3>`
  283. vectors for the rotation matrix, and an extra one for the origin.
  284. Matrix3
  285. -------
  286. Godot has a special type for a 3x3 matrix, named :ref:`Matrix3 <class_Matrix3>`.
  287. It can be used to represent a 3D rotation and scale. Sub vectors can be
  288. accessed as:
  289. ::
  290. var m = Matrix3()
  291. var x = m[0] # Vector3
  292. var y = m[1] # Vector3
  293. var z = m[2] # Vector3
  294. Or, alternatively as:
  295. ::
  296. var m = Matrix3()
  297. var x = m.x # Vector3
  298. var y = m.y # Vector3
  299. var z = m.z # Vector3
  300. Matrix3 is also initialized to Identity by default:
  301. .. image:: /img/tutomat17.png
  302. Rotation in 3D
  303. --------------
  304. Rotation in 3D is more complex than in 2D (translation and scale are the
  305. same), because rotation is an implicit 2D operation. To rotate in 3D, an
  306. *axis*, must be picked. Rotation, then, happens around this axis.
  307. The axis for the rotation must be a *normal vector*. As in, a vector
  308. that can point to any direction, but length must be one (1.0).
  309. ::
  310. #rotate in Y axis
  311. var m3 = Matrix3()
  312. m3 = m3.rotated( Vector3(0,1,0), PI/2 )
  313. Transform
  314. ---------
  315. To add the final component to the mix, Godot provides the
  316. :ref:`Transform <class_Transform>` type. Transform has two members:
  317. - *basis* (of type :ref:`Matrix3 <class_Matrix3>`
  318. - *origin* (of type :ref:`Vector3 <class_Vector3>`
  319. Any 3D transform can be represented with Transform, and the separation
  320. of basis and origin makes it easier to work translation and rotation
  321. separately.
  322. An example:
  323. ::
  324. var t = Transform()
  325. pos = t.xform(pos) # transform 3D position
  326. pos = t.basis.xform(pos) # (only rotate)
  327. pos = t.origin + pos (only translate)