vector_math.rst 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. .. _doc_vector_math:
  2. Vector math
  3. ===========
  4. Introduction
  5. ~~~~~~~~~~~~
  6. This tutorial is a short and practical introduction to linear algebra as it
  7. applies to game development. Linear algebra is the study of vectors and their
  8. uses. Vectors have many applications in both 2D and 3D development and Godot
  9. uses them extensively. Developing a good understanding of vector math is
  10. essential to becoming a strong game developer.
  11. .. note:: This tutorial is **not** a formal textbook on linear algebra. We will
  12. only be looking at how it is applied to game development. For a
  13. broader look at the mathematics, see
  14. https://www.khanacademy.org/math/linear-algebra
  15. Coordinate systems (2D)
  16. ~~~~~~~~~~~~~~~~~~~~~~~
  17. In 2D space, coordinates are defined using a horizontal axis (``x``) and a
  18. vertical axis (``y``). A particular position in 2D space is written as a pair of
  19. values such as ``(4, 3)``.
  20. .. image:: img/vector_axis1.png
  21. .. note:: If you're new to computer graphics, it might seem odd that the
  22. positive ``y`` axis points **downwards** instead of upwards, as you
  23. probably learned in math class. However, this is common in most
  24. computer graphics applications.
  25. Any position in the 2D plane can be identified by a pair of numbers in this way.
  26. However, we can also think of the position ``(4, 3)`` as an **offset** from the
  27. ``(0, 0)`` point, or **origin**. Draw an arrow pointing from the origin to the
  28. point:
  29. .. image:: img/vector_xy1.png
  30. This is a **vector**. A vector represents a lot of useful information. As well
  31. as telling us that the point is at ``(4, 3)``, we can also think of it as an
  32. angle ``θ`` (theta) and a length (or magnitude) ``m``. In this case, the arrow
  33. is a **position vector** - it denotes a position in space, relative to the
  34. origin.
  35. A very important point to consider about vectors is that they only represent
  36. **relative** direction and magnitude. There is no concept of a vector's
  37. position. The following two vectors are identical:
  38. .. image:: img/vector_xy2.png
  39. Both vectors represent a point 4 units to the right and 3 units below some
  40. starting point. It does not matter where on the plane you draw the vector, it
  41. always represents a relative direction and magnitude.
  42. Vector operations
  43. ~~~~~~~~~~~~~~~~~
  44. You can use either method (x and y coordinates or angle and magnitude) to refer
  45. to a vector, but for convenience, programmers typically use the coordinate
  46. notation. For example, in Godot, the origin is the top-left corner of the
  47. screen, so to place a 2D node named ``Node2D`` 400 pixels to the right and 300
  48. pixels down, use the following code:
  49. .. tabs::
  50. .. code-tab:: gdscript GDScript
  51. $Node2D.position = Vector2(400, 300)
  52. .. code-tab:: csharp
  53. var node2D = GetNode<Node2D>("Node2D");
  54. node2D.Position = new Vector2(400, 300);
  55. Godot supports both :ref:`Vector2 <class_Vector2>` and :ref:`Vector3
  56. <class_Vector3>` for 2D and 3D usage, respectively. The same mathematical rules
  57. discussed in this article apply to both types, and wherever we link to
  58. ``Vector2`` methods in the class reference, you can also check out their
  59. ``Vector3`` counterparts.
  60. Member access
  61. -------------
  62. The individual components of the vector can be accessed directly by name.
  63. .. tabs::
  64. .. code-tab:: gdscript GDScript
  65. # Create a vector with coordinates (2, 5).
  66. var a = Vector2(2, 5)
  67. # Create a vector and assign x and y manually.
  68. var b = Vector2()
  69. b.x = 3
  70. b.y = 1
  71. .. code-tab:: csharp
  72. // Create a vector with coordinates (2, 5).
  73. var a = new Vector2(2, 5);
  74. // Create a vector and assign x and y manually.
  75. var b = new Vector2();
  76. b.X = 3;
  77. b.Y = 1;
  78. Adding vectors
  79. --------------
  80. When adding or subtracting two vectors, the corresponding components are added:
  81. .. tabs::
  82. .. code-tab:: gdscript GDScript
  83. var c = a + b # (2, 5) + (3, 1) = (5, 6)
  84. .. code-tab:: csharp
  85. var c = a + b; // (2, 5) + (3, 1) = (5, 6)
  86. We can also see this visually by adding the second vector at the end of
  87. the first:
  88. .. image:: img/vector_add1.png
  89. Note that adding ``a + b`` gives the same result as ``b + a``.
  90. Scalar multiplication
  91. ---------------------
  92. .. note:: Vectors represent both direction and magnitude. A value representing
  93. only magnitude is called a **scalar**. Scalars use the
  94. :ref:`class_float` type in Godot.
  95. A vector can be multiplied by a **scalar**:
  96. .. tabs::
  97. .. code-tab:: gdscript GDScript
  98. var c = a * 2 # (2, 5) * 2 = (4, 10)
  99. var d = b / 3 # (3, 6) / 3 = (1, 2)
  100. var e = d * -2 # (1, 2) * -2 = (-2, -4)
  101. .. code-tab:: csharp
  102. var c = a * 2; // (2, 5) * 2 = (4, 10)
  103. var d = b / 3; // (3, 6) / 3 = (1, 2)
  104. var e = d * -2; // (1, 2) * -2 = (-2, -4)
  105. .. image:: img/vector_mult1.png
  106. .. note:: Multiplying a vector by a positive scalar does not change its direction, only
  107. its magnitude. Multiplying with a negative scalar results in a vector in the
  108. opposite direction. This is how you **scale** a vector.
  109. Practical applications
  110. ~~~~~~~~~~~~~~~~~~~~~~
  111. Let's look at two common uses for vector addition and subtraction.
  112. Movement
  113. --------
  114. A vector can represent **any** quantity with a magnitude and direction. Typical
  115. examples are: position, velocity, acceleration, and force. In this image, the
  116. spaceship at step 1 has a position vector of ``(1, 3)`` and a velocity vector of
  117. ``(2, 1)``. The velocity vector represents how far the ship moves each step. We
  118. can find the position for step 2 by adding the velocity to the current position.
  119. .. image:: img/vector_movement1.png
  120. .. tip:: Velocity measures the **change** in position per unit of time. The new
  121. position is found by adding the velocity multiplied by the elapsed time
  122. (here assumed to be one unit, e.g. 1 s) to the previous position.
  123. In a typical 2D game scenario, you would have a velocity in pixels per
  124. second, and multiply it by the ``delta`` parameter (time elapsed since
  125. the previous frame) from the :ref:`_process() <class_Node_private_method__process>`
  126. or :ref:`_physics_process() <class_Node_private_method__physics_process>`
  127. callbacks.
  128. Pointing toward a target
  129. ------------------------
  130. In this scenario, you have a tank that wishes to point its turret at a robot.
  131. Subtracting the tank's position from the robot's position gives the vector
  132. pointing from the tank to the robot.
  133. .. image:: img/vector_subtract2.webp
  134. .. tip:: To find a vector pointing from ``A`` to ``B``, use ``B - A``.
  135. Unit vectors
  136. ~~~~~~~~~~~~
  137. A vector with **magnitude** of ``1`` is called a **unit vector**. They are also
  138. sometimes referred to as **direction vectors** or **normals**. Unit vectors are
  139. helpful when you need to keep track of a direction.
  140. Normalization
  141. -------------
  142. **Normalizing** a vector means reducing its length to ``1`` while preserving its
  143. direction. This is done by dividing each of its components by its magnitude.
  144. Because this is such a common operation, Godot provides a dedicated
  145. :ref:`normalized() <class_Vector2_method_normalized>` method for this:
  146. .. tabs::
  147. .. code-tab:: gdscript GDScript
  148. a = a.normalized()
  149. .. code-tab:: csharp
  150. a = a.Normalized();
  151. .. warning:: Because normalization involves dividing by the vector's length, you
  152. cannot normalize a vector of length ``0``. Attempting to do so
  153. would normally result in an error. In GDScript though, trying to
  154. call the ``normalized()`` method on a vector of length 0 leaves the
  155. value untouched and avoids the error for you.
  156. Reflection
  157. ----------
  158. A common use of unit vectors is to indicate **normals**. Normal vectors are unit
  159. vectors aligned perpendicularly to a surface, defining its direction. They are
  160. commonly used for lighting, collisions, and other operations involving surfaces.
  161. For example, imagine we have a moving ball that we want to bounce off a wall or
  162. other object:
  163. .. image:: img/vector_reflect1.png
  164. The surface normal has a value of ``(0, -1)`` because this is a horizontal
  165. surface. When the ball collides, we take its remaining motion (the amount left
  166. over when it hits the surface) and reflect it using the normal. In Godot, there
  167. is a :ref:`bounce() <class_Vector2_method_bounce>` method to handle this.
  168. Here is a code example of the above diagram using a :ref:`CharacterBody2D
  169. <class_CharacterBody2D>`:
  170. .. tabs::
  171. .. code-tab:: gdscript GDScript
  172. var collision: KinematicCollision2D = move_and_collide(velocity * delta)
  173. if collision:
  174. var reflect = collision.get_remainder().bounce(collision.get_normal())
  175. velocity = velocity.bounce(collision.get_normal())
  176. move_and_collide(reflect)
  177. .. code-tab:: csharp
  178. KinematicCollision2D collision = MoveAndCollide(_velocity * (float)delta);
  179. if (collision != null)
  180. {
  181. var reflect = collision.GetRemainder().Bounce(collision.GetNormal());
  182. _velocity = _velocity.Bounce(collision.GetNormal());
  183. MoveAndCollide(reflect);
  184. }
  185. Dot product
  186. ~~~~~~~~~~~
  187. The **dot product** is one of the most important concepts in vector math, but is
  188. often misunderstood. Dot product is an operation on two vectors that returns a
  189. **scalar**. Unlike a vector, which contains both magnitude and direction, a
  190. scalar value has only magnitude.
  191. The formula for dot product takes two common forms:
  192. .. image:: img/vector_dot1.png
  193. and
  194. .. image:: img/vector_dot2.png
  195. The mathematical notation *||A||* represents the magnitude of vector ``A``, and
  196. *A*\ :sub:`x` means the ``x`` component of vector ``A``.
  197. However, in most cases it is easiest to use the built-in :ref:`dot()
  198. <class_Vector2_method_dot>` method. Note that the order of the two vectors does not matter:
  199. .. tabs::
  200. .. code-tab:: gdscript GDScript
  201. var c = a.dot(b)
  202. var d = b.dot(a) # These are equivalent.
  203. .. code-tab:: csharp
  204. float c = a.Dot(b);
  205. float d = b.Dot(a); // These are equivalent.
  206. The dot product is most useful when used with unit vectors, making the first
  207. formula reduce to just ``cos(θ)``. This means we can use the dot product to tell
  208. us something about the angle between two vectors:
  209. .. image:: img/vector_dot3.png
  210. When using unit vectors, the result will always be between ``-1`` (180°) and
  211. ``1`` (0°).
  212. Facing
  213. ------
  214. We can use this fact to detect whether an object is facing toward another
  215. object. In the diagram below, the player ``P`` is trying to avoid the zombies
  216. ``A`` and ``B``. Assuming a zombie's field of view is **180°**, can they see the
  217. player?
  218. .. image:: img/vector_facing2.png
  219. The green arrows ``fA`` and ``fB`` are **unit vectors** representing the
  220. zombie's facing direction and the blue semicircle represents its field of view.
  221. For zombie ``A``, we find the direction vector ``AP`` pointing to the player
  222. using ``P - A`` and normalize it, however, Godot has a helper method to do this
  223. called :ref:`direction_to() <class_Vector2_method_direction_to>`. If the angle
  224. between this vector and the facing vector is less than 90°, then the zombie can
  225. see the player.
  226. In code it would look like this:
  227. .. tabs::
  228. .. code-tab:: gdscript GDScript
  229. var AP = A.direction_to(P)
  230. if AP.dot(fA) > 0:
  231. print("A sees P!")
  232. .. code-tab:: csharp
  233. var AP = A.DirectionTo(P);
  234. if (AP.Dot(fA) > 0)
  235. {
  236. GD.Print("A sees P!");
  237. }
  238. Cross product
  239. ~~~~~~~~~~~~~
  240. Like the dot product, the **cross product** is an operation on two vectors.
  241. However, the result of the cross product is a vector with a direction that is
  242. perpendicular to both. Its magnitude depends on their relative angle. If two
  243. vectors are parallel, the result of their cross product will be a null vector.
  244. .. image:: img/vector_cross1.png
  245. .. image:: img/vector_cross2.png
  246. The cross product is calculated like this:
  247. .. tabs::
  248. .. code-tab:: gdscript GDScript
  249. var c = Vector3()
  250. c.x = (a.y * b.z) - (a.z * b.y)
  251. c.y = (a.z * b.x) - (a.x * b.z)
  252. c.z = (a.x * b.y) - (a.y * b.x)
  253. .. code-tab:: csharp
  254. var c = new Vector3();
  255. c.X = (a.Y * b.Z) - (a.Z * b.Y);
  256. c.Y = (a.Z * b.X) - (a.X * b.Z);
  257. c.Z = (a.X * b.Y) - (a.Y * b.X);
  258. With Godot, you can use the built-in :ref:`Vector3.cross() <class_Vector3_method_cross>`
  259. method:
  260. .. tabs::
  261. .. code-tab:: gdscript GDScript
  262. var c = a.cross(b)
  263. .. code-tab:: csharp
  264. var c = a.Cross(b);
  265. The cross product is not mathematically defined in 2D. The :ref:`Vector2.cross()
  266. <class_Vector2_method_cross>` method is a commonly used analog of the 3D cross
  267. product for 2D vectors.
  268. .. note:: In the cross product, order matters. ``a.cross(b)`` does not give the
  269. same result as ``b.cross(a)``. The resulting vectors point in
  270. **opposite** directions.
  271. Calculating normals
  272. -------------------
  273. One common use of cross products is to find the surface normal of a plane or
  274. surface in 3D space. If we have the triangle ``ABC`` we can use vector
  275. subtraction to find two edges ``AB`` and ``AC``. Using the cross product,
  276. ``AB × AC`` produces a vector perpendicular to both: the surface normal.
  277. Here is a function to calculate a triangle's normal:
  278. .. tabs::
  279. .. code-tab:: gdscript GDScript
  280. func get_triangle_normal(a, b, c):
  281. # Find the surface normal given 3 vertices.
  282. var side1 = b - a
  283. var side2 = c - a
  284. var normal = side1.cross(side2)
  285. return normal
  286. .. code-tab:: csharp
  287. Vector3 GetTriangleNormal(Vector3 a, Vector3 b, Vector3 c)
  288. {
  289. // Find the surface normal given 3 vertices.
  290. var side1 = b - a;
  291. var side2 = c - a;
  292. var normal = side1.Cross(side2);
  293. return normal;
  294. }
  295. Pointing to a target
  296. --------------------
  297. In the dot product section above, we saw how it could be used to find the angle
  298. between two vectors. However, in 3D, this is not enough information. We also
  299. need to know what axis to rotate around. We can find that by calculating the
  300. cross product of the current facing direction and the target direction. The
  301. resulting perpendicular vector is the axis of rotation.
  302. More information
  303. ~~~~~~~~~~~~~~~~
  304. For more information on using vector math in Godot, see the following articles:
  305. - :ref:`doc_vectors_advanced`
  306. - :ref:`doc_matrices_and_transforms`