tutorial.html 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2. "http://www.w3.org/TR/html4/loose.dtd">
  3. <html >
  4. <head><title></title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  6. <meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)">
  7. <meta name="originator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)">
  8. <!-- html -->
  9. <meta name="src" content="tutorial.tex">
  10. <meta name="date" content="2009-10-07 00:28:00">
  11. <link rel="stylesheet" type="text/css" href="tutorial.css">
  12. </head><body
  13. >
  14. <h3 class="sectionHead"><span class="titlemark">1 </span> <a
  15. id="x1-10001"></a>Introduction to 3D Math</h3>
  16. <!--l. 27--><p class="noindent" >
  17. <h4 class="subsectionHead"><span class="titlemark">1.1 </span> <a
  18. id="x1-20001.1"></a>Introduction</h4>
  19. <!--l. 29--><p class="noindent" >There are many approaches to understanding the type of 3D math used in video
  20. games, modelling, ray-tracing, etc. The usual is through vector algebra, matrices, and
  21. linear transformations and, while they are not completely necesary to understand
  22. most of the aspects of 3D game programming (from the theorical point of view), they
  23. provide a common language to communicate with other programmers or
  24. engineers.
  25. <!--l. 36--><p class="indent" > This tutorial will focus on explaining all the basic concepts needed for a
  26. programmer to understand how to develop 3D games without getting too deep into
  27. algebra. Instead of a math-oriented language, code examples will be given instead
  28. when possible. The reason for this is that. while programmers may have
  29. different backgrounds or experience (be it scientific, engineering or self taught),
  30. code is the most familiar language and the lowest common denominator for
  31. understanding.
  32. <!--l. 45--><p class="noindent" >
  33. <h4 class="subsectionHead"><span class="titlemark">1.2 </span> <a
  34. id="x1-30001.2"></a>Vectors</h4>
  35. <!--l. 48--><p class="noindent" >
  36. <h5 class="subsubsectionHead"><span class="titlemark">1.2.1 </span> <a
  37. id="x1-40001.2.1"></a>Brief Introduction</h5>
  38. <!--l. 50--><p class="noindent" >When writing 2D games, interfaces and other applications, the typical convention is
  39. to define coordinates as an <span
  40. class="ecti-1000">x,y </span>pair, <span
  41. class="ecti-1000">x </span>representing the horizontal offset and <span
  42. class="ecti-1000">y </span>the
  43. vertical one. In most cases, the unit for both is <span
  44. class="ecti-1000">pixels</span>. This makes sense given the
  45. screen is just a rectangle in two dimensions.
  46. <!--l. 56--><p class="indent" > An <span
  47. class="ecti-1000">x,y </span>pair can be used for two purposes. It can be an absolute position (screen
  48. cordinate in the previous case), or a relative direction, if we trace an arrow from the
  49. origin (0,0 coordinates) to it&#8217;s position.
  50. <div class="center"
  51. >
  52. <!--l. 60--><p class="noindent" >
  53. <div class="tabular">
  54. <table id="TBL-1" class="tabular"
  55. cellspacing="0" cellpadding="0"
  56. ><colgroup id="TBL-1-1g"><col
  57. id="TBL-1-1"><col
  58. id="TBL-1-2"><col
  59. id="TBL-1-3"></colgroup><tr
  60. style="vertical-align:baseline;" id="TBL-1-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-1"
  61. class="td11"><img
  62. src="tutorial0x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics
  63. name="tutorial0x.png" src="0_home_red_coding_godot_doc_math_position.eps"
  64. --></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-2"
  65. class="td11"></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-3"
  66. class="td11"><img
  67. src="tutorial1x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics
  68. name="tutorial1x.png" src="1_home_red_coding_godot_doc_math_direction.eps"
  69. --></td>
  70. </tr><tr
  71. style="vertical-align:baseline;" id="TBL-1-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-1"
  72. class="td11"> <span
  73. class="ecti-0700">Position </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-2"
  74. class="td11"></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-3"
  75. class="td11"> <span
  76. class="ecti-0700">Direction </span></td>
  77. </tr><tr
  78. style="vertical-align:baseline;" id="TBL-1-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-3-1"
  79. class="td11"> </td>
  80. </tr></table></div>
  81. </div>
  82. <!--l. 67--><p class="indent" > When used as a direction, this pair is called a <span
  83. class="ecti-1000">vector</span>, and two properties can be
  84. observed: The first is the <span
  85. class="ecti-1000">magnitude </span>or <span
  86. class="ecti-1000">length </span>, and the second is the direction. In
  87. two dimensions, direction can be an angle. The <span
  88. class="ecti-1000">magnitude </span>or <span
  89. class="ecti-1000">length </span>can be computed
  90. by simply using Pithagoras theorem:
  91. <div class="center"
  92. >
  93. <!--l. 73--><p class="noindent" >
  94. <div class="tabular"> <table id="TBL-2" class="tabular"
  95. cellspacing="0" cellpadding="0"
  96. ><colgroup id="TBL-2-1g"><col
  97. id="TBL-2-1"><col
  98. id="TBL-2-2"></colgroup><tr
  99. style="vertical-align:baseline;" id="TBL-2-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-1-1"
  100. class="td11"><img
  101. src="tutorial2x.png" alt="&#x2218;x2-+-y2-" class="sqrt" ></td><td style="white-space:nowrap; text-align:center;" id="TBL-2-1-2"
  102. class="td11"><img
  103. src="tutorial3x.png" alt="&#x2218;x2-+-y2 +-z2" class="sqrt" ></td>
  104. </tr><tr
  105. style="vertical-align:baseline;" id="TBL-2-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-2-1"
  106. class="td11"> <span
  107. class="ecti-0700">2D </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-2-2-2"
  108. class="td11"> <span
  109. class="ecti-0700">3D </span></td>
  110. </tr><tr
  111. style="vertical-align:baseline;" id="TBL-2-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-3-1"
  112. class="td11"> </td>
  113. </tr></table></div>
  114. </div>
  115. <!--l. 80--><p class="indent" > The direction can be an arbitrary angle from either the <span
  116. class="ecti-1000">x </span>or <span
  117. class="ecti-1000">y </span>axis, and could be
  118. computed by using trigonometry, or just using the usual <span
  119. class="ecti-1000">atan2 </span>function present in
  120. most math libraries. However, when dealing with 3D, the direction can&#8217;t be described
  121. as an angle. To separate magnitude and direction, 3D uses the concept of <span
  122. class="ecti-1000">normal</span>
  123. <span
  124. class="ecti-1000">vectors.</span>
  125. <!--l. 88--><p class="noindent" >
  126. <h5 class="subsubsectionHead"><span class="titlemark">1.2.2 </span> <a
  127. id="x1-50001.2.2"></a>Implementation</h5>
  128. <!--l. 90--><p class="noindent" >Vectors are implemented in Godot Engine as a class named <span
  129. class="ecti-1000">Vector3 </span>for 3D, and as
  130. both <span
  131. class="ecti-1000">Vector2</span>, <span
  132. class="ecti-1000">Point2 </span>or <span
  133. class="ecti-1000">Size2 </span>in 2D (they are all aliases). They are used for any
  134. purpose where a pair of 2D or 3D values (described as <span
  135. class="ecti-1000">x,y </span>or <span
  136. class="ecti-1000">x,y,z) </span>is needed. This is
  137. somewhat a standard in most libraries or engines. In the script API, they can be
  138. instanced like this:
  139. <!--l. 98-->
  140. <div class="lstlisting"><span class="label"><a
  141. id="x1-5001r1"></a></span>a&#x00A0;=&#x00A0;Vector3()&#x00A0;<br /><span class="label"><a
  142. id="x1-5002r2"></a></span>a&#x00A0;=&#x00A0;Vector2(&#x00A0;2.0,&#x00A0;3.4&#x00A0;)
  143. </div>
  144. <!--l. 104--><p class="indent" > Vectors also support the common operators <span
  145. class="ecti-1000">+, -, / and * </span>for addition,
  146. substraction, multiplication and division.
  147. <!--l. 108-->
  148. <div class="lstlisting"><span class="label"><a
  149. id="x1-5003r1"></a></span>a&#x00A0;=&#x00A0;Vector3(1,2,3)&#x00A0;<br /><span class="label"><a
  150. id="x1-5004r2"></a></span>b&#x00A0;=&#x00A0;Vector3(4,5,6)&#x00A0;<br /><span class="label"><a
  151. id="x1-5005r3"></a></span>c&#x00A0;=&#x00A0;Vector3()&#x00A0;<br /><span class="label"><a
  152. id="x1-5006r4"></a></span>&#x00A0;<br /><span class="label"><a
  153. id="x1-5007r5"></a></span>//&#x00A0;writing&#x00A0;<br /><span class="label"><a
  154. id="x1-5008r6"></a></span>&#x00A0;<br /><span class="label"><a
  155. id="x1-5009r7"></a></span>c&#x00A0;=&#x00A0;a&#x00A0;+&#x00A0;b&#x00A0;<br /><span class="label"><a
  156. id="x1-5010r8"></a></span>&#x00A0;<br /><span class="label"><a
  157. id="x1-5011r9"></a></span>//&#x00A0;is&#x00A0;the&#x00A0;same&#x00A0;as&#x00A0;writing&#x00A0;<br /><span class="label"><a
  158. id="x1-5012r10"></a></span>&#x00A0;<br /><span class="label"><a
  159. id="x1-5013r11"></a></span>c.x&#x00A0;=&#x00A0;a.x&#x00A0;+&#x00A0;b.x&#x00A0;<br /><span class="label"><a
  160. id="x1-5014r12"></a></span>c.y&#x00A0;=&#x00A0;a.y&#x00A0;+&#x00A0;b.y&#x00A0;<br /><span class="label"><a
  161. id="x1-5015r13"></a></span>c.z&#x00A0;=&#x00A0;a.z&#x00A0;+&#x00A0;b.z&#x00A0;<br /><span class="label"><a
  162. id="x1-5016r14"></a></span>&#x00A0;<br /><span class="label"><a
  163. id="x1-5017r15"></a></span>//&#x00A0;both&#x00A0;will&#x00A0;result&#x00A0;in&#x00A0;a&#x00A0;vector&#x00A0;containing&#x00A0;(5,7,9).&#x00A0;<br /><span class="label"><a
  164. id="x1-5018r16"></a></span>//&#x00A0;the&#x00A0;same&#x00A0;happens&#x00A0;for&#x00A0;the&#x00A0;rest&#x00A0;of&#x00A0;the&#x00A0;operators.
  165. </div>
  166. <!--l. 128--><p class="indent" > Vectors also can perform a wide variety of built-in functions, their most common
  167. usages will be explored next.
  168. <!--l. 132--><p class="noindent" >
  169. <h5 class="subsubsectionHead"><span class="titlemark">1.2.3 </span> <a
  170. id="x1-60001.2.3"></a>Normal Vectors</h5>
  171. <!--l. 134--><p class="noindent" >Two points ago, it was mentioned that 3D vectors can&#8217;t describe their direction as an
  172. agle (as 2D vectors can). Because of this, <span
  173. class="ecti-1000">normal vectors </span>become important for
  174. separating a vector between <span
  175. class="ecti-1000">direction </span>and <span
  176. class="ecti-1000">magnitude.</span>
  177. <!--l. 139--><p class="indent" > A <span
  178. class="ecti-1000">normal vector </span>is a vector with a <span
  179. class="ecti-1000">magnitude </span>of <span
  180. class="ecti-1000">1. </span>This means, no matter where
  181. the vector is pointing to, it&#8217;s length is always <span
  182. class="ecti-1000">1</span>.
  183. <div class="tabular">
  184. <table id="TBL-3" class="tabular"
  185. cellspacing="0" cellpadding="0"
  186. ><colgroup id="TBL-3-1g"><col
  187. id="TBL-3-1"></colgroup><tr
  188. style="vertical-align:baseline;" id="TBL-3-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-1-1"
  189. class="td11"><img
  190. src="tutorial4x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics
  191. name="tutorial4x.png" src="2_home_red_coding_godot_doc_math_normals.eps"
  192. --></td>
  193. </tr><tr
  194. style="vertical-align:baseline;" id="TBL-3-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-2-1"
  195. class="td11"> <span
  196. class="ecrm-0700">Normal vectors aroud the origin. </span></td>
  197. </tr><tr
  198. style="vertical-align:baseline;" id="TBL-3-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-3-1"
  199. class="td11"> </td> </tr></table>
  200. </div>
  201. <!--l. 148--><p class="indent" > Normal vectors have endless uses in 3D graphics programming, so it&#8217;s
  202. recommended to get familiar with them as much as possible.
  203. <!--l. 152--><p class="noindent" >
  204. <h5 class="subsubsectionHead"><span class="titlemark">1.2.4 </span> <a
  205. id="x1-70001.2.4"></a>Normalization</h5>
  206. <!--l. 154--><p class="noindent" >Normalization is the process through which normal vectors are obtained
  207. from regular vectors. In other words, normalization is used to reduce the
  208. <span
  209. class="ecti-1000">magnitude </span>of any vector to <span
  210. class="ecti-1000">1</span>. (except of course, unless the vector is (0,0,0)
  211. ).
  212. <!--l. 159--><p class="indent" > To normalize a vector, it must be divided by its magnitude (which should be
  213. greater than zero):
  214. <!--l. 163-->
  215. <div class="lstlisting"><span class="label"><a
  216. id="x1-7001r1"></a></span><span
  217. class="ecti-1000">//</span><span
  218. class="ecti-1000">&#x00A0;</span><span
  219. class="ecti-1000">a</span><span
  220. class="ecti-1000">&#x00A0;</span><span
  221. class="ecti-1000">custom</span><span
  222. class="ecti-1000">&#x00A0;</span><span
  223. class="ecti-1000">vector</span><span
  224. class="ecti-1000">&#x00A0;</span><span
  225. class="ecti-1000">is</span><span
  226. class="ecti-1000">&#x00A0;</span><span
  227. class="ecti-1000">created</span>&#x00A0;<br /><span class="label"><a
  228. id="x1-7002r2"></a></span>a&#x00A0;=&#x00A0;Vector3(4,5,6)&#x00A0;<br /><span class="label"><a
  229. id="x1-7003r3"></a></span><span
  230. class="ecti-1000">//</span><span
  231. class="ecti-1000">&#x00A0;</span><span
  232. class="ecti-1000">&#8217;</span><span
  233. class="ecti-1000">l</span><span
  234. class="ecti-1000">&#8217;</span><span
  235. class="ecti-1000">&#x00A0;</span><span
  236. class="ecti-1000">is</span><span
  237. class="ecti-1000">&#x00A0;</span><span
  238. class="ecti-1000">a</span><span
  239. class="ecti-1000">&#x00A0;</span><span
  240. class="ecti-1000">single</span><span
  241. class="ecti-1000">&#x00A0;</span><span
  242. class="ecti-1000">real</span><span
  243. class="ecti-1000">&#x00A0;</span><span
  244. class="ecti-1000">number</span><span
  245. class="ecti-1000">&#x00A0;</span><span
  246. class="ecti-1000">(</span><span
  247. class="ecti-1000">or</span><span
  248. class="ecti-1000">&#x00A0;</span><span
  249. class="ecti-1000">scalar</span><span
  250. class="ecti-1000">)</span><span
  251. class="ecti-1000">&#x00A0;</span><span
  252. class="ecti-1000">containight</span><span
  253. class="ecti-1000">&#x00A0;</span><span
  254. class="ecti-1000">the</span><span
  255. class="ecti-1000">&#x00A0;</span><span
  256. class="ecti-1000">length</span>&#x00A0;<br /><span class="label"><a
  257. id="x1-7004r4"></a></span>l&#x00A0;=&#x00A0;Math.sqrt(&#x00A0;a.x<span
  258. class="cmsy-10">*</span>a.x&#x00A0;+&#x00A0;a.y<span
  259. class="cmsy-10">*</span>a.y&#x00A0;+&#x00A0;a.z<span
  260. class="cmsy-10">*</span>a.z&#x00A0;)&#x00A0;<br /><span class="label"><a
  261. id="x1-7005r5"></a></span><span
  262. class="ecti-1000">//</span><span
  263. class="ecti-1000">&#x00A0;</span><span
  264. class="ecti-1000">the</span><span
  265. class="ecti-1000">&#x00A0;</span><span
  266. class="ecti-1000">vector</span><span
  267. class="ecti-1000">&#x00A0;</span><span
  268. class="ecti-1000">&#8217;</span><span
  269. class="ecti-1000">a</span><span
  270. class="ecti-1000">&#8217;</span><span
  271. class="ecti-1000">&#x00A0;</span><span
  272. class="ecti-1000">is</span><span
  273. class="ecti-1000">&#x00A0;</span><span
  274. class="ecti-1000">divided</span><span
  275. class="ecti-1000">&#x00A0;</span><span
  276. class="ecti-1000">by</span><span
  277. class="ecti-1000">&#x00A0;</span><span
  278. class="ecti-1000">its</span><span
  279. class="ecti-1000">&#x00A0;</span><span
  280. class="ecti-1000">length</span><span
  281. class="ecti-1000">,</span><span
  282. class="ecti-1000">&#x00A0;</span><span
  283. class="ecti-1000">by</span><span
  284. class="ecti-1000">&#x00A0;</span><span
  285. class="ecti-1000">performing</span><span
  286. class="ecti-1000">&#x00A0;</span><span
  287. class="ecti-1000">scalar</span><span
  288. class="ecti-1000">&#x00A0;</span><span
  289. class="ecti-1000">divide</span>&#x00A0;<br /><span class="label"><a
  290. id="x1-7006r6"></a></span>a&#x00A0;=&#x00A0;a&#x00A0;/&#x00A0;l&#x00A0;<br /><span class="label"><a
  291. id="x1-7007r7"></a></span><span
  292. class="ecti-1000">//</span><span
  293. class="ecti-1000">&#x00A0;</span><span
  294. class="ecti-1000">which</span><span
  295. class="ecti-1000">&#x00A0;</span><span
  296. class="ecti-1000">is</span><span
  297. class="ecti-1000">&#x00A0;</span><span
  298. class="ecti-1000">the</span><span
  299. class="ecti-1000">&#x00A0;</span><span
  300. class="ecti-1000">same</span><span
  301. class="ecti-1000">&#x00A0;</span><span
  302. class="ecti-1000">as</span>&#x00A0;<br /><span class="label"><a
  303. id="x1-7008r8"></a></span>a.x&#x00A0;=&#x00A0;a.x&#x00A0;/&#x00A0;l&#x00A0;<br /><span class="label"><a
  304. id="x1-7009r9"></a></span>a.y&#x00A0;=&#x00A0;a.y&#x00A0;/&#x00A0;l&#x00A0;<br /><span class="label"><a
  305. id="x1-7010r10"></a></span>a.z&#x00A0;=&#x00A0;a.z&#x00A0;/&#x00A0;l
  306. </div>
  307. <!--l. 177--><p class="indent" > Vector3 contains two built in functions for normalization:
  308. <!--l. 180-->
  309. <div class="lstlisting"><span class="label"><a
  310. id="x1-7011r1"></a></span>a&#x00A0;=&#x00A0;Vector3(4,5,6)&#x00A0;<br /><span class="label"><a
  311. id="x1-7012r2"></a></span>a.normalize()&#x00A0;<span
  312. class="ecti-1000">//</span><span
  313. class="ecti-1000">&#x00A0;</span><span
  314. class="ecti-1000">in</span><span
  315. class="cmsy-10">-</span><span
  316. class="ecti-1000">place</span><span
  317. class="ecti-1000">&#x00A0;</span><span
  318. class="ecti-1000">normalization</span>&#x00A0;<br /><span class="label"><a
  319. id="x1-7013r3"></a></span>b&#x00A0;=&#x00A0;a.normalized()&#x00A0;<span
  320. class="ecti-1000">//</span><span
  321. class="ecti-1000">&#x00A0;</span><span
  322. class="ecti-1000">returns</span><span
  323. class="ecti-1000">&#x00A0;</span><span
  324. class="ecti-1000">a</span><span
  325. class="ecti-1000">&#x00A0;</span><span
  326. class="ecti-1000">copy</span><span
  327. class="ecti-1000">&#x00A0;</span><span
  328. class="ecti-1000">of</span><span
  329. class="ecti-1000">&#x00A0;</span><span
  330. class="ecti-1000">a</span><span
  331. class="ecti-1000">,</span><span
  332. class="ecti-1000">&#x00A0;</span><span
  333. class="ecti-1000">normalized</span>
  334. </div>
  335. <!--l. 188--><p class="noindent" >
  336. <h5 class="subsubsectionHead"><span class="titlemark">1.2.5 </span> <a
  337. id="x1-80001.2.5"></a>Dot Product</h5>
  338. <!--l. 190--><p class="noindent" >The dot product is, pheraps, the most useful operation that can be applied to 3D
  339. vectors. In the surface, it&#8217;s multiple usages are not very obvious, but in depth it can
  340. provide very useful information between two vectors (be it direction or just points in
  341. space).
  342. <!--l. 195--><p class="indent" > The dot product takes two vectors (<span
  343. class="ecti-1000">a </span>and <span
  344. class="ecti-1000">b </span>in the example) and returns a scalar
  345. (single real number):
  346. <div class="center"
  347. >
  348. <!--l. 198--><p class="noindent" >
  349. <!--l. 199--><p class="noindent" ><span
  350. class="cmmi-10">a</span><sub><span
  351. class="cmmi-7">x</span></sub><span
  352. class="cmmi-10">b</span><sub><span
  353. class="cmmi-7">x</span></sub> <span
  354. class="cmr-10">+ </span><span
  355. class="cmmi-10">a</span><sub><span
  356. class="cmmi-7">y</span></sub><span
  357. class="cmmi-10">b</span><sub><span
  358. class="cmmi-7">y</span></sub> <span
  359. class="cmr-10">+ </span><span
  360. class="cmmi-10">a</span><sub><span
  361. class="cmmi-7">z</span></sub><span
  362. class="cmmi-10">b</span><sub><span
  363. class="cmmi-7">z</span></sub>
  364. </div>
  365. <!--l. 202--><p class="indent" > The same expressed in code:
  366. <!--l. 205-->
  367. <div class="lstlisting"><span class="label"><a
  368. id="x1-8001r1"></a></span>a&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  369. id="x1-8002r2"></a></span>b&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  370. id="x1-8003r3"></a></span>&#x00A0;<br /><span class="label"><a
  371. id="x1-8004r4"></a></span>c&#x00A0;=&#x00A0;a.x<span
  372. class="cmsy-10">*</span>b.x&#x00A0;+&#x00A0;a.y<span
  373. class="cmsy-10">*</span>b.y&#x00A0;+&#x00A0;a.z<span
  374. class="cmsy-10">*</span>b.z&#x00A0;<br /><span class="label"><a
  375. id="x1-8005r5"></a></span>&#x00A0;<br /><span class="label"><a
  376. id="x1-8006r6"></a></span><span
  377. class="ecti-1000">//</span><span
  378. class="ecti-1000">&#x00A0;</span><span
  379. class="ecti-1000">using</span><span
  380. class="ecti-1000">&#x00A0;</span><span
  381. class="ecti-1000">built</span><span
  382. class="cmsy-10">-</span><span
  383. class="ecti-1000">in</span><span
  384. class="ecti-1000">&#x00A0;</span><span
  385. class="ecti-1000">dot</span><span
  386. class="ecti-1000">()</span><span
  387. class="ecti-1000">&#x00A0;</span><span
  388. class="ecti-1000">function</span>&#x00A0;<br /><span class="label"><a
  389. id="x1-8007r7"></a></span>&#x00A0;<br /><span class="label"><a
  390. id="x1-8008r8"></a></span>c&#x00A0;=&#x00A0;a.dot(b)
  391. </div>
  392. <!--l. 218--><p class="indent" > The dot product presents several useful properties:
  393. <ul class="itemize1">
  394. <li class="itemize">If both <span
  395. class="ecti-1000">a </span>and <span
  396. class="ecti-1000">b </span>parameters to a <span
  397. class="ecti-1000">dot product </span>are direction vectors, dot
  398. product will return positive if both point towards the same direction,
  399. negative if both point towards opposite directions, and zero if they are
  400. orthogonal (one is perpendicular to the other).
  401. </li>
  402. <li class="itemize">If both <span
  403. class="ecti-1000">a </span>and <span
  404. class="ecti-1000">b </span>parameters to a <span
  405. class="ecti-1000">dot product </span>are <span
  406. class="ecti-1000">normalized </span>direction
  407. vectors, then the dot product will return the cosine of the angle between
  408. them (ranging from 1 if they are equal, 0 if they are orthogonal, and -1 if
  409. they are opposed (a == -b)).
  410. </li>
  411. <li class="itemize">If <span
  412. class="ecti-1000">a </span>is a <span
  413. class="ecti-1000">normalized </span>direction vector and <span
  414. class="ecti-1000">b </span>is a point, the dot product will
  415. return the distance from <span
  416. class="ecti-1000">b </span>to the plane passing through the origin, with
  417. normal <span
  418. class="ecti-1000">a (see item about planes)</span>
  419. </li>
  420. <li class="itemize">More uses will be presented later in this tutorial.</li></ul>
  421. <!--l. 236--><p class="noindent" >
  422. <h5 class="subsubsectionHead"><span class="titlemark">1.2.6 </span> <a
  423. id="x1-90001.2.6"></a>Cross Product</h5>
  424. <!--l. 238--><p class="noindent" >The <span
  425. class="ecti-1000">cross product </span>also takes two vectors <span
  426. class="ecti-1000">a </span>and <span
  427. class="ecti-1000">b</span>, but returns another vector <span
  428. class="ecti-1000">c </span>that is
  429. orthogonal to the two previous ones.
  430. <div class="center"
  431. >
  432. <!--l. 242--><p class="noindent" >
  433. <!--l. 243--><p class="noindent" ><span
  434. class="cmmi-10">c</span><sub><span
  435. class="cmmi-7">x</span></sub> <span
  436. class="cmr-10">= </span><span
  437. class="cmmi-10">a</span><sub><span
  438. class="cmmi-7">x</span></sub><span
  439. class="cmmi-10">b</span><sub><span
  440. class="cmmi-7">z</span></sub> <span
  441. class="cmsy-10">- </span><span
  442. class="cmmi-10">a</span><sub><span
  443. class="cmmi-7">z</span></sub><span
  444. class="cmmi-10">b</span><sub><span
  445. class="cmmi-7">y</span></sub>
  446. </div>
  447. <div class="center"
  448. >
  449. <!--l. 246--><p class="noindent" >
  450. <!--l. 247--><p class="noindent" ><span
  451. class="cmmi-10">c</span><sub><span
  452. class="cmmi-7">y</span></sub> <span
  453. class="cmr-10">= </span><span
  454. class="cmmi-10">a</span><sub><span
  455. class="cmmi-7">z</span></sub><span
  456. class="cmmi-10">b</span><sub><span
  457. class="cmmi-7">x</span></sub> <span
  458. class="cmsy-10">- </span><span
  459. class="cmmi-10">a</span><sub><span
  460. class="cmmi-7">x</span></sub><span
  461. class="cmmi-10">b</span><sub><span
  462. class="cmmi-7">z</span></sub>
  463. </div>
  464. <div class="center"
  465. >
  466. <!--l. 250--><p class="noindent" >
  467. <!--l. 251--><p class="noindent" ><span
  468. class="cmmi-10">c</span><sub><span
  469. class="cmmi-7">z</span></sub> <span
  470. class="cmr-10">= </span><span
  471. class="cmmi-10">a</span><sub><span
  472. class="cmmi-7">x</span></sub><span
  473. class="cmmi-10">b</span><sub><span
  474. class="cmmi-7">y</span></sub> <span
  475. class="cmsy-10">- </span><span
  476. class="cmmi-10">a</span><sub><span
  477. class="cmmi-7">y</span></sub><span
  478. class="cmmi-10">b</span><sub><span
  479. class="cmmi-7">x</span></sub>
  480. </div>
  481. <!--l. 254--><p class="indent" > The same in code:
  482. <!--l. 257-->
  483. <div class="lstlisting"><span class="label"><a
  484. id="x1-9001r1"></a></span>a&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  485. id="x1-9002r2"></a></span>b&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  486. id="x1-9003r3"></a></span>c&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  487. id="x1-9004r4"></a></span>&#x00A0;<br /><span class="label"><a
  488. id="x1-9005r5"></a></span>c.x&#x00A0;=&#x00A0;a.x<span
  489. class="cmsy-10">*</span>b.z&#x00A0;<span
  490. class="cmsy-10">-</span>&#x00A0;a.z<span
  491. class="cmsy-10">*</span>b.y&#x00A0;<br /><span class="label"><a
  492. id="x1-9006r6"></a></span>c.y&#x00A0;=&#x00A0;a.z<span
  493. class="cmsy-10">*</span>b.x&#x00A0;<span
  494. class="cmsy-10">-</span>&#x00A0;a.x<span
  495. class="cmsy-10">*</span>b.z&#x00A0;<br /><span class="label"><a
  496. id="x1-9007r7"></a></span>c.z&#x00A0;=&#x00A0;a.x<span
  497. class="cmsy-10">*</span>b.y&#x00A0;<span
  498. class="cmsy-10">-</span>&#x00A0;a.y<span
  499. class="cmsy-10">*</span>b.x&#x00A0;<br /><span class="label"><a
  500. id="x1-9008r8"></a></span>&#x00A0;<br /><span class="label"><a
  501. id="x1-9009r9"></a></span>//&#x00A0;or&#x00A0;using&#x00A0;the&#x00A0;built<span
  502. class="cmsy-10">-</span>in&#x00A0;function&#x00A0;<br /><span class="label"><a
  503. id="x1-9010r10"></a></span>&#x00A0;<br /><span class="label"><a
  504. id="x1-9011r11"></a></span>c&#x00A0;=&#x00A0;a.cross(b)
  505. </div>
  506. <!--l. 273--><p class="indent" > The <span
  507. class="ecti-1000">cross product </span>also presents several useful properties:
  508. <ul class="itemize1">
  509. <li class="itemize">As mentioned, the resulting vector <span
  510. class="ecti-1000">c </span>is orthogonal to the input vectors <span
  511. class="ecti-1000">a</span>
  512. and <span
  513. class="ecti-1000">b.</span>
  514. </li>
  515. <li class="itemize">Since the <span
  516. class="ecti-1000">cross product </span>is anticommutative, swapping <span
  517. class="ecti-1000">a </span>and <span
  518. class="ecti-1000">b </span>will result
  519. in a negated vector <span
  520. class="ecti-1000">c.</span>
  521. </li>
  522. <li class="itemize">if <span
  523. class="ecti-1000">a </span>and <span
  524. class="ecti-1000">b </span>are taken from two of the segmets <span
  525. class="ecti-1000">AB</span>, <span
  526. class="ecti-1000">BC </span>or <span
  527. class="ecti-1000">CA </span>that form a
  528. 3D triangle, the magnitude of the resulting vector divided by 2 is the area
  529. of that triangle.
  530. </li>
  531. <li class="itemize">The direction of the resulting vector <span
  532. class="ecti-1000">c </span>in the previous triangle example
  533. determines wether the points A,B and C are arranged in clocwise or
  534. counter-clockwise order.</li></ul>
  535. <!--l. 287--><p class="noindent" >
  536. <h4 class="subsectionHead"><span class="titlemark">1.3 </span> <a
  537. id="x1-100001.3"></a>Plane</h4>
  538. <!--l. 290--><p class="noindent" >
  539. <h5 class="subsubsectionHead"><span class="titlemark">1.3.1 </span> <a
  540. id="x1-110001.3.1"></a>Theory</h5>
  541. <!--l. 292--><p class="noindent" >A plane can be considered as an infinite, flat surface that splits space in two halves,
  542. usually one named positive and one named negative. In regular mathematics, a plane
  543. formula is described as:
  544. <div class="center"
  545. >
  546. <!--l. 296--><p class="noindent" >
  547. <!--l. 297--><p class="noindent" ><span
  548. class="cmmi-10">ax </span><span
  549. class="cmr-10">+ </span><span
  550. class="cmmi-10">by </span><span
  551. class="cmr-10">+ </span><span
  552. class="cmmi-10">cz </span><span
  553. class="cmr-10">+ </span><span
  554. class="cmmi-10">d</span>
  555. </div>
  556. <!--l. 300--><p class="indent" > However, in 3D programming, this form alone is often of little use. For planes to
  557. become useful, they must be in normalized form.
  558. <!--l. 303--><p class="indent" > A normalized plane consists of a <span
  559. class="ecti-1000">normal vector n </span>and a <span
  560. class="ecti-1000">distance d. </span>To normalize
  561. a plane, a vector <span
  562. class="ecti-1000">n </span>and distance <span
  563. class="ecti-1000">d&#8217; </span>are created this way:
  564. <!--l. 307--><p class="indent" > <span
  565. class="cmmi-10">n</span><sub><span
  566. class="cmmi-7">x</span></sub> <span
  567. class="cmr-10">= </span><span
  568. class="cmmi-10">a</span>
  569. <!--l. 309--><p class="indent" > <span
  570. class="cmmi-10">n</span><sub><span
  571. class="cmmi-7">y</span></sub> <span
  572. class="cmr-10">= </span><span
  573. class="cmmi-10">b</span>
  574. <!--l. 311--><p class="indent" > <span
  575. class="cmmi-10">n</span><sub><span
  576. class="cmmi-7">z</span></sub> <span
  577. class="cmr-10">= </span><span
  578. class="cmmi-10">c</span>
  579. <!--l. 313--><p class="indent" > <span
  580. class="cmmi-10">d</span><span
  581. class="cmsy-10">&#x2032; </span><span
  582. class="cmr-10">= </span><span
  583. class="cmmi-10">d</span>
  584. <!--l. 315--><p class="indent" > Finally, both <span
  585. class="ecti-1000">n </span>and <span
  586. class="ecti-1000">d&#8217; </span>are both divided by the magnitude of n.
  587. <!--l. 318--><p class="indent" > In any case, normalizing planes is not often needed (this was mostly for
  588. explanation purposes), and normalized planes are useful because they can be created
  589. and used easily.
  590. <!--l. 322--><p class="indent" > A normalized plane could be visualized as a plane pointing towards normal <span
  591. class="ecti-1000">n,</span>
  592. offseted by <span
  593. class="ecti-1000">d </span>in the direction of <span
  594. class="ecti-1000">n</span>.
  595. <!--l. 325--><p class="indent" > In other words, take <span
  596. class="ecti-1000">n</span>, multiply it by scalar <span
  597. class="ecti-1000">d </span>and the resulting point will be part
  598. of the plane. This may need some thinking, so an example with a 2D normal vector
  599. (z is 0, so plane is orthogonal to it) is provided:
  600. <!--l. 330--><p class="indent" > Some operations can be done with normalized planes:
  601. <ul class="itemize1">
  602. <li class="itemize">Given any point <span
  603. class="ecti-1000">p</span>, the distance from it to a plane can be computed by
  604. doing: n.dot(p) - d
  605. </li>
  606. <li class="itemize">If the resulting distance in the previous point is negative, the point is
  607. below the plane.
  608. </li>
  609. <li class="itemize">Convex polygonal shapes can be defined by enclosing them in planes (the
  610. physics engine uses this property)</li></ul>
  611. <!--l. 340--><p class="noindent" >
  612. <h5 class="subsubsectionHead"><span class="titlemark">1.3.2 </span> <a
  613. id="x1-120001.3.2"></a>Implementation</h5>
  614. <!--l. 342--><p class="noindent" >Godot Engine implements normalized planes by using the <span
  615. class="ecti-1000">Plane </span>class.
  616. <!--l. 346-->
  617. <div class="lstlisting"><span class="label"><a
  618. id="x1-12001r1"></a></span>//creates&#x00A0;a&#x00A0;plane&#x00A0;with&#x00A0;normal&#x00A0;(0,1,0)&#x00A0;and&#x00A0;distance&#x00A0;5&#x00A0;<br /><span class="label"><a
  619. id="x1-12002r2"></a></span>p&#x00A0;=&#x00A0;Plane(&#x00A0;Vector3(0,1,0),&#x00A0;5&#x00A0;)&#x00A0;<br /><span class="label"><a
  620. id="x1-12003r3"></a></span>//&#x00A0;get&#x00A0;the&#x00A0;distance&#x00A0;to&#x00A0;a&#x00A0;point&#x00A0;<br /><span class="label"><a
  621. id="x1-12004r4"></a></span>d&#x00A0;=&#x00A0;p.distance(&#x00A0;Vector3(4,5,6)&#x00A0;)
  622. </div>
  623. <!--l. 355--><p class="noindent" >
  624. <h4 class="subsectionHead"><span class="titlemark">1.4 </span> <a
  625. id="x1-130001.4"></a>Matrices, Quaternions and Coordinate Systems</h4>
  626. <!--l. 357--><p class="noindent" >It is very often needed to store the location/rotation of something. In 2D, it is often
  627. enough to store an <span
  628. class="ecti-1000">x,y </span>location and maybe an angle as the rotation, as that should
  629. be enough to represent any posible position.
  630. <!--l. 362--><p class="indent" > In 3D this becomes a little more difficult, as there is nothing as simple as an angle
  631. to store a 3-axis rotation.
  632. <!--l. 365--><p class="indent" > The first think that may come to mind is to use 3 angles, one for x, one for y and
  633. one for z. However this suffers from the problem that it becomes very cumbersome to
  634. use, as the individual rotations in each axis need to be performed one after another
  635. (they can&#8217;t be performed at the same time), leading to a problem called &#8220;gimbal
  636. lock&#8221;. Also, it becomes impossible to accumulate rotations (add a rotation to an
  637. existing one).
  638. <!--l. 373--><p class="indent" > To solve this, there are two known diferent approaches that aid in solving
  639. rotation, <span
  640. class="ecti-1000">Quaternions </span>and <span
  641. class="ecti-1000">Oriented Coordinate Systems.</span>
  642. <!--l. 378--><p class="noindent" >
  643. <h5 class="subsubsectionHead"><span class="titlemark">1.4.1 </span> <a
  644. id="x1-140001.4.1"></a>Oriented Coordinate Systems</h5>
  645. <!--l. 380--><p class="noindent" ><span
  646. class="ecti-1000">Oriented Coordinate Systems </span>(<span
  647. class="ecti-1000">OCS</span>) are a way of representing a coordinate system
  648. inside the cartesian coordinate system. They are mainly composed of 3 Vectors, one
  649. for each axis. The first vector is the <span
  650. class="ecti-1000">x </span>axis, the second the <span
  651. class="ecti-1000">y </span>axis, and the third is the
  652. <span
  653. class="ecti-1000">z </span>axis. The OCS vectors can be rotated around freely as long as they are kept the
  654. same length (as changing the length of an axis changes its cale), and as long as they
  655. remain orthogonal to eachother (as in, the same as the default cartesian system,
  656. with <span
  657. class="ecti-1000">y </span>pointing up, <span
  658. class="ecti-1000">x </span>pointing left and <span
  659. class="ecti-1000">z </span>pointing front, but all rotated
  660. together).
  661. <!--l. 391--><p class="indent" > <span
  662. class="ecti-1000">Oriented Coordinate Systems </span>are represented in 3D programming as a 3x3 matrix,
  663. where each row (or column, depending on the implementation) contains one of the
  664. axis vectors. Transforming a Vector by a rotated OCS Matrix results in the rotation
  665. being applied to the resulting vector. OCS Matrices can also be multiplied to
  666. accumulate their transformations.
  667. <!--l. 397--><p class="indent" > Godot Engine implements OCS Matrices in the <span
  668. class="ecti-1000">Matrix3 </span>class:
  669. <!--l. 400-->
  670. <div class="lstlisting"><span class="label"><a
  671. id="x1-14001r1"></a></span><span
  672. class="ecti-1000">//</span><span
  673. class="ecti-1000">create</span><span
  674. class="ecti-1000">&#x00A0;</span><span
  675. class="ecti-1000">a</span><span
  676. class="ecti-1000">&#x00A0;</span><span
  677. class="ecti-1000">3</span><span
  678. class="ecti-1000">x3</span><span
  679. class="ecti-1000">&#x00A0;</span><span
  680. class="ecti-1000">matrix</span>&#x00A0;<br /><span class="label"><a
  681. id="x1-14002r2"></a></span>m&#x00A0;=&#x00A0;Matrix3()&#x00A0;<br /><span class="label"><a
  682. id="x1-14003r3"></a></span><span
  683. class="ecti-1000">//</span><span
  684. class="ecti-1000">rotate</span><span
  685. class="ecti-1000">&#x00A0;</span><span
  686. class="ecti-1000">the</span><span
  687. class="ecti-1000">&#x00A0;</span><span
  688. class="ecti-1000">matrix</span><span
  689. class="ecti-1000">&#x00A0;</span><span
  690. class="ecti-1000">in</span><span
  691. class="ecti-1000">&#x00A0;</span><span
  692. class="ecti-1000">the</span><span
  693. class="ecti-1000">&#x00A0;</span><span
  694. class="ecti-1000">y</span><span
  695. class="ecti-1000">&#x00A0;</span><span
  696. class="ecti-1000">axis</span><span
  697. class="ecti-1000">,</span><span
  698. class="ecti-1000">&#x00A0;</span><span
  699. class="ecti-1000">by</span><span
  700. class="ecti-1000">&#x00A0;</span><span
  701. class="ecti-1000">45</span><span
  702. class="ecti-1000">&#x00A0;</span><span
  703. class="ecti-1000">degrees</span>&#x00A0;<br /><span class="label"><a
  704. id="x1-14004r4"></a></span>m.rotate(&#x00A0;Vector3(0,1,0),&#x00A0;Math.deg2rad(45)&#x00A0;)&#x00A0;<br /><span class="label"><a
  705. id="x1-14005r5"></a></span><span
  706. class="ecti-1000">//</span><span
  707. class="ecti-1000">transform</span><span
  708. class="ecti-1000">&#x00A0;</span><span
  709. class="ecti-1000">a</span><span
  710. class="ecti-1000">&#x00A0;</span><span
  711. class="ecti-1000">vector</span><span
  712. class="ecti-1000">&#x00A0;</span><span
  713. class="ecti-1000">v</span><span
  714. class="ecti-1000">&#x00A0;</span><span
  715. class="ecti-1000">(</span><span
  716. class="ecti-1000">xform</span><span
  717. class="ecti-1000">&#x00A0;</span><span
  718. class="ecti-1000">method</span><span
  719. class="ecti-1000">&#x00A0;</span><span
  720. class="ecti-1000">is</span><span
  721. class="ecti-1000">&#x00A0;</span><span
  722. class="ecti-1000">used</span><span
  723. class="ecti-1000">)</span>&#x00A0;<br /><span class="label"><a
  724. id="x1-14006r6"></a></span>v&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  725. id="x1-14007r7"></a></span>result&#x00A0;=&#x00A0;m.xform(&#x00A0;v&#x00A0;)
  726. </div>
  727. <!--l. 412--><p class="indent" > However, in most usage cases, one wants to store a translation together with the
  728. rotation. For this, an <span
  729. class="ecti-1000">origin </span>vector must be added to the OCS, thus transforming it
  730. into a 3x4 (or 4x3, depending on preference) matrix. Godot engine implements this
  731. functionality in the <span
  732. class="ecti-1000">Transform </span>class:
  733. <!--l. 419-->
  734. <div class="lstlisting"><span class="label"><a
  735. id="x1-14010r1"></a></span>t&#x00A0;=&#x00A0;Transform()&#x00A0;<br /><span class="label"><a
  736. id="x1-14011r2"></a></span>//rotate&#x00A0;the&#x00A0;transform&#x00A0;in&#x00A0;the&#x00A0;y&#x00A0;axis,&#x00A0;by&#x00A0;45&#x00A0;degrees&#x00A0;<br /><span class="label"><a
  737. id="x1-14012r3"></a></span>t.rotate(&#x00A0;Vector3(0,1,0),&#x00A0;Math.deg2rad(45)&#x00A0;)&#x00A0;<br /><span class="label"><a
  738. id="x1-14013r4"></a></span>//translate&#x00A0;the&#x00A0;transform&#x00A0;by&#x00A0;5&#x00A0;in&#x00A0;the&#x00A0;z&#x00A0;axis&#x00A0;<br /><span class="label"><a
  739. id="x1-14014r5"></a></span>t.translate(&#x00A0;Vector3(&#x00A0;0,0,5&#x00A0;)&#x00A0;)&#x00A0;<br /><span class="label"><a
  740. id="x1-14015r6"></a></span>//transform&#x00A0;a&#x00A0;vector&#x00A0;v&#x00A0;(xform&#x00A0;method&#x00A0;is&#x00A0;used)&#x00A0;<br /><span class="label"><a
  741. id="x1-14016r7"></a></span>v&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  742. id="x1-14017r8"></a></span>result&#x00A0;=&#x00A0;t.xform(&#x00A0;v&#x00A0;)
  743. </div>
  744. <!--l. 431--><p class="indent" > Transform contains internally a Matrix3 &#8220;basis&#8221; and a Vector3 &#8220;origin&#8221; (which can
  745. be modified individually).
  746. <!--l. 435--><p class="noindent" >
  747. <h5 class="subsubsectionHead"><span class="titlemark">1.4.2 </span> <a
  748. id="x1-150001.4.2"></a>Transform Internals</h5>
  749. <!--l. 437--><p class="noindent" >Internally, the xform() process is quite simple, to apply a 3x3 transform to a vector,
  750. the transposed axis vectors are used (as using the regular axis vectors will result on
  751. an inverse of the desired transform):
  752. <!--l. 442-->
  753. <div class="lstlisting"><span class="label"><a
  754. id="x1-15001r1"></a></span>m&#x00A0;=&#x00A0;Matrix3(...)&#x00A0;<br /><span class="label"><a
  755. id="x1-15002r2"></a></span>v&#x00A0;=&#x00A0;Vector3(..)&#x00A0;<br /><span class="label"><a
  756. id="x1-15003r3"></a></span>result&#x00A0;=&#x00A0;Vector3(...)&#x00A0;<br /><span class="label"><a
  757. id="x1-15004r4"></a></span>&#x00A0;<br /><span class="label"><a
  758. id="x1-15005r5"></a></span>x_axis&#x00A0;=&#x00A0;m.get_axis(0)&#x00A0;<br /><span class="label"><a
  759. id="x1-15006r6"></a></span>y_axis&#x00A0;=&#x00A0;m.get_axis(1)&#x00A0;<br /><span class="label"><a
  760. id="x1-15007r7"></a></span>z_axis&#x00A0;=&#x00A0;m.get_axis(2)&#x00A0;<br /><span class="label"><a
  761. id="x1-15008r8"></a></span>&#x00A0;<br /><span class="label"><a
  762. id="x1-15009r9"></a></span>result.x&#x00A0;=&#x00A0;Vector3(x_axis.x,&#x00A0;y_axis.x,&#x00A0;z_axis.x).dot(v)&#x00A0;<br /><span class="label"><a
  763. id="x1-15010r10"></a></span>result.y&#x00A0;=&#x00A0;Vector3(x_axis.y,&#x00A0;y_axis.y,&#x00A0;z_axis.y).dot(v)&#x00A0;<br /><span class="label"><a
  764. id="x1-15011r11"></a></span>result.z&#x00A0;=&#x00A0;Vector3(x_axis.z,&#x00A0;y_axis.z,&#x00A0;z_axis.z).dot(v)&#x00A0;<br /><span class="label"><a
  765. id="x1-15012r12"></a></span>&#x00A0;<br /><span class="label"><a
  766. id="x1-15013r13"></a></span>//&#x00A0;is&#x00A0;the&#x00A0;same&#x00A0;as&#x00A0;doing&#x00A0;<br /><span class="label"><a
  767. id="x1-15014r14"></a></span>&#x00A0;<br /><span class="label"><a
  768. id="x1-15015r15"></a></span>result&#x00A0;=&#x00A0;m.xform(v)&#x00A0;<br /><span class="label"><a
  769. id="x1-15016r16"></a></span>&#x00A0;<br /><span class="label"><a
  770. id="x1-15017r17"></a></span>//&#x00A0;if&#x00A0;m&#x00A0;this&#x00A0;was&#x00A0;a&#x00A0;Transform(),&#x00A0;the&#x00A0;origin&#x00A0;would&#x00A0;be&#x00A0;added&#x00A0;<br /><span class="label"><a
  771. id="x1-15018r18"></a></span>//&#x00A0;like&#x00A0;this:&#x00A0;<br /><span class="label"><a
  772. id="x1-15019r19"></a></span>&#x00A0;<br /><span class="label"><a
  773. id="x1-15020r20"></a></span>result&#x00A0;=&#x00A0;result&#x00A0;+&#x00A0;t.get_origin()
  774. </div>
  775. <!--l. 468--><p class="noindent" >
  776. <h5 class="subsubsectionHead"><span class="titlemark">1.4.3 </span> <a
  777. id="x1-160001.4.3"></a>Using The Transform</h5>
  778. <!--l. 470--><p class="noindent" >So, it is often desired apply sucessive operations to a transformation. For example,
  779. let&#8217;s a assume that there is a turtle sitting at the origin (the turtle is a logo reference,
  780. for those familiar with it). The <span
  781. class="ecti-1000">y </span>axis is up, and the the turtle&#8217;s nose is pointing
  782. towards the <span
  783. class="ecti-1000">z </span>axis.
  784. <!--l. 476--><p class="indent" > The turtle (like many other animals, or vehicles!) can only walk towards the
  785. direction it&#8217;s looking at. So, moving the turtle around a little should be something
  786. like this:
  787. <!--l. 481-->
  788. <div class="lstlisting"><span class="label"><a
  789. id="x1-16001r1"></a></span><span
  790. class="ecti-1000">//</span><span
  791. class="ecti-1000">&#x00A0;</span><span
  792. class="ecti-1000">turtle</span><span
  793. class="ecti-1000">&#x00A0;</span><span
  794. class="ecti-1000">at</span><span
  795. class="ecti-1000">&#x00A0;</span><span
  796. class="ecti-1000">the</span><span
  797. class="ecti-1000">&#x00A0;</span><span
  798. class="ecti-1000">origin</span>&#x00A0;<br /><span class="label"><a
  799. id="x1-16002r2"></a></span>turtle&#x00A0;=&#x00A0;Transform()&#x00A0;<br /><span class="label"><a
  800. id="x1-16003r3"></a></span><span
  801. class="ecti-1000">//</span><span
  802. class="ecti-1000">&#x00A0;</span><span
  803. class="ecti-1000">turtle</span><span
  804. class="ecti-1000">&#x00A0;</span><span
  805. class="ecti-1000">will</span><span
  806. class="ecti-1000">&#x00A0;</span><span
  807. class="ecti-1000">walk</span><span
  808. class="ecti-1000">&#x00A0;</span><span
  809. class="ecti-1000">5</span><span
  810. class="ecti-1000">&#x00A0;</span><span
  811. class="ecti-1000">units</span><span
  812. class="ecti-1000">&#x00A0;</span><span
  813. class="ecti-1000">in</span><span
  814. class="ecti-1000">&#x00A0;</span><span
  815. class="ecti-1000">z</span><span
  816. class="ecti-1000">&#x00A0;</span><span
  817. class="ecti-1000">axis</span>&#x00A0;<br /><span class="label"><a
  818. id="x1-16004r4"></a></span>turtle.translate(&#x00A0;Vector3(0,0,5)&#x00A0;)&#x00A0;<br /><span class="label"><a
  819. id="x1-16005r5"></a></span><span
  820. class="ecti-1000">//</span><span
  821. class="ecti-1000">&#x00A0;</span><span
  822. class="ecti-1000">turtle</span><span
  823. class="ecti-1000">&#x00A0;</span><span
  824. class="ecti-1000">eyes</span><span
  825. class="ecti-1000">&#x00A0;</span><span
  826. class="ecti-1000">a</span><span
  827. class="ecti-1000">&#x00A0;</span><span
  828. class="ecti-1000">lettuce</span><span
  829. class="ecti-1000">&#x00A0;</span><span
  830. class="ecti-1000">3</span><span
  831. class="ecti-1000">&#x00A0;</span><span
  832. class="ecti-1000">units</span><span
  833. class="ecti-1000">&#x00A0;</span><span
  834. class="ecti-1000">away</span><span
  835. class="ecti-1000">,</span><span
  836. class="ecti-1000">&#x00A0;</span><span
  837. class="ecti-1000">will</span><span
  838. class="ecti-1000">&#x00A0;</span><span
  839. class="ecti-1000">rotate</span><span
  840. class="ecti-1000">&#x00A0;</span><span
  841. class="ecti-1000">45</span><span
  842. class="ecti-1000">&#x00A0;</span><span
  843. class="ecti-1000">degrees</span><span
  844. class="ecti-1000">&#x00A0;</span><span
  845. class="ecti-1000">right</span>&#x00A0;<br /><span class="label"><a
  846. id="x1-16006r6"></a></span>turtle.rotate(&#x00A0;Vector3(0,1,0),&#x00A0;Math.deg2rad(45)&#x00A0;)&#x00A0;<br /><span class="label"><a
  847. id="x1-16007r7"></a></span><span
  848. class="ecti-1000">//</span><span
  849. class="ecti-1000">&#x00A0;</span><span
  850. class="ecti-1000">turtle</span><span
  851. class="ecti-1000">&#x00A0;</span><span
  852. class="ecti-1000">approaches</span><span
  853. class="ecti-1000">&#x00A0;</span><span
  854. class="ecti-1000">the</span><span
  855. class="ecti-1000">&#x00A0;</span><span
  856. class="ecti-1000">lettuce</span>&#x00A0;<br /><span class="label"><a
  857. id="x1-16008r8"></a></span>turtle.translate(&#x00A0;Vector3(0,0,5)&#x00A0;)&#x00A0;<br /><span class="label"><a
  858. id="x1-16009r9"></a></span><span
  859. class="ecti-1000">//</span><span
  860. class="ecti-1000">&#x00A0;</span><span
  861. class="ecti-1000">happy</span><span
  862. class="ecti-1000">&#x00A0;</span><span
  863. class="ecti-1000">turtle</span><span
  864. class="ecti-1000">&#x00A0;</span><span
  865. class="ecti-1000">over</span><span
  866. class="ecti-1000">&#x00A0;</span><span
  867. class="ecti-1000">lettuce</span><span
  868. class="ecti-1000">&#x00A0;</span><span
  869. class="ecti-1000">is</span><span
  870. class="ecti-1000">&#x00A0;</span><span
  871. class="ecti-1000">at</span>&#x00A0;<br /><span class="label"><a
  872. id="x1-16010r10"></a></span>print(turtle.get_origin())
  873. </div>
  874. <!--l. 496--><p class="indent" > As can be seen, every new action the turtle takes is based on the previous one it
  875. took. Had the order of actions been different and the turtle would have never reached
  876. the lettuce.
  877. <!--l. 500--><p class="indent" > Transforms are just that, a mean of &#8220;accumulating&#8221; rotation, translation, scale,
  878. etc.
  879. <!--l. 504--><p class="noindent" >
  880. <h5 class="subsubsectionHead"><span class="titlemark">1.4.4 </span> <a
  881. id="x1-170001.4.4"></a>A Warning about Numerical Precision</h5>
  882. <!--l. 506--><p class="noindent" >Performing several actions over a transform will slowly and gradually lead to
  883. precision loss (objects that draw according to a transform may get jittery, bigger,
  884. smaller, skewed, etc). This happens due to the nature of floating point numbers. if
  885. transforms/matrices are created from other kind of values (like a position and
  886. some angular rotation) this is not needed, but if has been accumulating
  887. transformations and was never recreated, it can be normalized by calling the
  888. .orthonormalize() built-in function. This function has little cost and calling it every
  889. now and then will avoid the effects from precision loss to become visible.
  890. </body></html>