diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /doc/html/tutorial01 | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) |
GODOT IS OPEN SOURCE
Diffstat (limited to 'doc/html/tutorial01')
-rw-r--r-- | doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.png | bin | 0 -> 1679 bytes | |||
-rw-r--r-- | doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.png | bin | 0 -> 3600 bytes | |||
-rw-r--r-- | doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.png | bin | 0 -> 2452 bytes | |||
-rw-r--r-- | doc/html/tutorial01/tutorial.css | 128 | ||||
-rw-r--r-- | doc/html/tutorial01/tutorial.html | 902 | ||||
-rw-r--r-- | doc/html/tutorial01/tutorial0x.png | bin | 0 -> 2056 bytes | |||
-rw-r--r-- | doc/html/tutorial01/tutorial1x.png | bin | 0 -> 4122 bytes | |||
-rw-r--r-- | doc/html/tutorial01/tutorial2x.png | bin | 0 -> 618 bytes | |||
-rw-r--r-- | doc/html/tutorial01/tutorial3x.png | bin | 0 -> 754 bytes | |||
-rw-r--r-- | doc/html/tutorial01/tutorial4x.png | bin | 0 -> 2961 bytes |
10 files changed, 1030 insertions, 0 deletions
diff --git a/doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.png b/doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.png Binary files differnew file mode 100644 index 0000000000..df52c05462 --- /dev/null +++ b/doc/html/tutorial01/0_home_red_coding_godot_doc_math_position.png diff --git a/doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.png b/doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.png Binary files differnew file mode 100644 index 0000000000..5b58274bcb --- /dev/null +++ b/doc/html/tutorial01/1_home_red_coding_godot_doc_math_direction.png diff --git a/doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.png b/doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.png Binary files differnew file mode 100644 index 0000000000..73681a58ce --- /dev/null +++ b/doc/html/tutorial01/2_home_red_coding_godot_doc_math_normals.png diff --git a/doc/html/tutorial01/tutorial.css b/doc/html/tutorial01/tutorial.css new file mode 100644 index 0000000000..a518c6dff7 --- /dev/null +++ b/doc/html/tutorial01/tutorial.css @@ -0,0 +1,128 @@ + +/* start css.sty */ +.cmr-7{font-size:70%;} +.cmmi-7{font-size:70%;font-style: italic;} +.cmmi-10{font-style: italic;} +.ectt-1000{ font-family: monospace;} +.ectt-1000{ font-family: monospace;} +.ectt-1000{ font-family: monospace;} +.ectt-1000{ font-family: monospace;} +.ectt-1000{ font-family: monospace;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-1000{ font-style: italic;} +.ecti-0700{font-size:70%; font-style: italic;} +.ecti-0700{ font-style: italic;} +.ecti-0700{ font-style: italic;} +.ecti-0700{ font-style: italic;} +.ecti-0700{ font-style: italic;} +.ecrm-0700{font-size:70%;} +p.noindent { text-indent: 0em } +td p.noindent { text-indent: 0em; margin-top:0em; } +p.nopar { text-indent: 0em; } +p.indent{ text-indent: 1.5em } +@media print {div.crosslinks {visibility:hidden;}} +a img { border-top: 0; border-left: 0; border-right: 0; } +center { margin-top:1em; margin-bottom:1em; } +td center { margin-top:0em; margin-bottom:0em; } +.Canvas { position:relative; } +img.math{vertical-align:middle;} +li p.indent { text-indent: 0em } +.enumerate1 {list-style-type:decimal;} +.enumerate2 {list-style-type:lower-alpha;} +.enumerate3 {list-style-type:lower-roman;} +.enumerate4 {list-style-type:upper-alpha;} +div.newtheorem { margin-bottom: 2em; margin-top: 2em;} +.obeylines-h,.obeylines-v {white-space: nowrap; } +div.obeylines-v p { margin-top:0; margin-bottom:0; } +.overline{ text-decoration:overline; } +.overline img{ border-top: 1px solid black; } +td.displaylines {text-align:center; white-space:nowrap;} +.centerline {text-align:center;} +.rightline {text-align:right;} +div.verbatim {font-family: monospace; white-space: nowrap; text-align:left; clear:both; } +.fbox {padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +div.fbox {display:table} +div.center div.fbox {text-align:center; clear:both; padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +table.minipage{width:100%;} +div.center, div.center div.center {text-align: center; margin-left:1em; margin-right:1em;} +div.center div {text-align: left;} +div.flushright, div.flushright div.flushright {text-align: right;} +div.flushright div {text-align: left;} +div.flushleft {text-align: left;} +.underline{ text-decoration:underline; } +.underline img{ border-bottom: 1px solid black; margin-bottom:1pt; } +.framebox-c, .framebox-l, .framebox-r { padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +.framebox-c {text-align:center;} +.framebox-l {text-align:left;} +.framebox-r {text-align:right;} +span.thank-mark{ vertical-align: super } +span.footnote-mark sup.textsuperscript, span.footnote-mark a sup.textsuperscript{ font-size:80%; } +div.tabular, div.center div.tabular {text-align: center; margin-top:0.5em; margin-bottom:0.5em; } +table.tabular td p{margin-top:0em;} +table.tabular {margin-left: auto; margin-right: auto;} +div.td00{ margin-left:0pt; margin-right:0pt; } +div.td01{ margin-left:0pt; margin-right:5pt; } +div.td10{ margin-left:5pt; margin-right:0pt; } +div.td11{ margin-left:5pt; margin-right:5pt; } +table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; } +td.td00{ padding-left:0pt; padding-right:0pt; } +td.td01{ padding-left:0pt; padding-right:5pt; } +td.td10{ padding-left:5pt; padding-right:0pt; } +td.td11{ padding-left:5pt; padding-right:5pt; } +table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; } +.hline hr, .cline hr{ height : 1px; margin:0px; } +.tabbing-right {text-align:right;} +span.TEX {letter-spacing: -0.125em; } +span.TEX span.E{ position:relative;top:0.5ex;left:-0.0417em;} +a span.TEX span.E {text-decoration: none; } +span.LATEX span.A{ position:relative; top:-0.5ex; left:-0.4em; font-size:85%;} +span.LATEX span.TEX{ position:relative; left: -0.4em; } +div.float img, div.float .caption {text-align:center;} +div.figure img, div.figure .caption {text-align:center;} +.marginpar {width:20%; float:right; text-align:left; margin-left:auto; margin-top:0.5em; font-size:85%; text-decoration:underline;} +.marginpar p{margin-top:0.4em; margin-bottom:0.4em;} +table.equation {width:100%;} +.equation td{text-align:center; } +td.equation { margin-top:1em; margin-bottom:1em; } +td.equation-label { width:5%; text-align:center; } +td.eqnarray4 { width:5%; white-space: normal; } +td.eqnarray2 { width:5%; } +table.eqnarray-star, table.eqnarray {width:100%;} +div.eqnarray{text-align:center;} +div.array {text-align:center;} +div.pmatrix {text-align:center;} +table.pmatrix {width:100%;} +span.pmatrix img{vertical-align:middle;} +div.pmatrix {text-align:center;} +table.pmatrix {width:100%;} +img.cdots{vertical-align:middle;} +.partToc a, .partToc, .likepartToc a, .likepartToc {line-height: 200%; font-weight:bold; font-size:110%;} +.index-item, .index-subitem, .index-subsubitem {display:block} +.caption td.id{font-weight: bold; white-space: nowrap; } +table.caption {text-align:center;} +h1.partHead{text-align: center} +p.bibitem { text-indent: -2em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } +p.bibitem-p { text-indent: 0em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } +.paragraphHead, .likeparagraphHead { margin-top:2em; font-weight: bold;} +.subparagraphHead, .likesubparagraphHead { font-weight: bold;} +.quote {margin-bottom:0.25em; margin-top:0.25em; margin-left:1em; margin-right:1em; text-align:justify;} +.verse{white-space:nowrap; margin-left:2em} +div.maketitle {text-align:center;} +h2.titleHead{text-align:center;} +div.maketitle{ margin-bottom: 2em; } +div.author, div.date {text-align:center;} +div.thanks{text-align:left; margin-left:10%; font-size:85%; font-style:italic; } +div.author{white-space: nowrap;} +.quotation {margin-bottom:0.25em; margin-top:0.25em; margin-left:1em; } +.abstract p {margin-left:5%; margin-right:5%;} +table.abstract {width:100%;} +.lstlisting .label{margin-right:0.5em; } +div.lstlisting{font-family: monospace; white-space: nowrap; margin-top:0.5em; margin-bottom:0.5em; } +div.lstinputlisting{ font-family: monospace; white-space: nowrap; } +.lstinputlisting .label{margin-right:0.5em;} +.figure img.graphics {margin-left:10%;} +/* end css.sty */ + diff --git a/doc/html/tutorial01/tutorial.html b/doc/html/tutorial01/tutorial.html new file mode 100644 index 0000000000..45c0258709 --- /dev/null +++ b/doc/html/tutorial01/tutorial.html @@ -0,0 +1,902 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html > +<head><title></title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)"> +<meta name="originator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)"> +<!-- html --> +<meta name="src" content="tutorial.tex"> +<meta name="date" content="2009-10-07 00:28:00"> +<link rel="stylesheet" type="text/css" href="tutorial.css"> +</head><body +> + <h3 class="sectionHead"><span class="titlemark">1 </span> <a + id="x1-10001"></a>Introduction to 3D Math</h3> +<!--l. 27--><p class="noindent" > + <h4 class="subsectionHead"><span class="titlemark">1.1 </span> <a + id="x1-20001.1"></a>Introduction</h4> +<!--l. 29--><p class="noindent" >There are many approaches to understanding the type of 3D math used in video +games, modelling, ray-tracing, etc. The usual is through vector algebra, matrices, and +linear transformations and, while they are not completely necesary to understand +most of the aspects of 3D game programming (from the theorical point of view), they +provide a common language to communicate with other programmers or +engineers. +<!--l. 36--><p class="indent" > This tutorial will focus on explaining all the basic concepts needed for a +programmer to understand how to develop 3D games without getting too deep into +algebra. Instead of a math-oriented language, code examples will be given instead +when possible. The reason for this is that. while programmers may have +different backgrounds or experience (be it scientific, engineering or self taught), +code is the most familiar language and the lowest common denominator for +understanding. +<!--l. 45--><p class="noindent" > + <h4 class="subsectionHead"><span class="titlemark">1.2 </span> <a + id="x1-30001.2"></a>Vectors</h4> +<!--l. 48--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.2.1 </span> <a + id="x1-40001.2.1"></a>Brief Introduction</h5> +<!--l. 50--><p class="noindent" >When writing 2D games, interfaces and other applications, the typical convention is +to define coordinates as an <span +class="ecti-1000">x,y </span>pair, <span +class="ecti-1000">x </span>representing the horizontal offset and <span +class="ecti-1000">y </span>the +vertical one. In most cases, the unit for both is <span +class="ecti-1000">pixels</span>. This makes sense given the +screen is just a rectangle in two dimensions. +<!--l. 56--><p class="indent" > An <span +class="ecti-1000">x,y </span>pair can be used for two purposes. It can be an absolute position (screen +cordinate in the previous case), or a relative direction, if we trace an arrow from the +origin (0,0 coordinates) to it’s position. +<div class="center" +> +<!--l. 60--><p class="noindent" > + +<div class="tabular"> + <table id="TBL-1" class="tabular" +cellspacing="0" cellpadding="0" +><colgroup id="TBL-1-1g"><col +id="TBL-1-1"><col +id="TBL-1-2"><col +id="TBL-1-3"></colgroup><tr + style="vertical-align:baseline;" id="TBL-1-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-1" +class="td11"><img +src="tutorial0x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics +name="tutorial0x.png" src="0_home_red_coding_godot_doc_math_position.eps" +--></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-2" +class="td11"></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-1-3" +class="td11"><img +src="tutorial1x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics +name="tutorial1x.png" src="1_home_red_coding_godot_doc_math_direction.eps" +--></td> +</tr><tr + style="vertical-align:baseline;" id="TBL-1-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-1" +class="td11"> <span +class="ecti-0700">Position </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-2" +class="td11"></td><td style="white-space:nowrap; text-align:center;" id="TBL-1-2-3" +class="td11"> <span +class="ecti-0700">Direction </span></td> +</tr><tr + style="vertical-align:baseline;" id="TBL-1-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-1-3-1" +class="td11"> </td> +</tr></table></div> +</div> +<!--l. 67--><p class="indent" > When used as a direction, this pair is called a <span +class="ecti-1000">vector</span>, and two properties can be +observed: The first is the <span +class="ecti-1000">magnitude </span>or <span +class="ecti-1000">length </span>, and the second is the direction. In +two dimensions, direction can be an angle. The <span +class="ecti-1000">magnitude </span>or <span +class="ecti-1000">length </span>can be computed +by simply using Pithagoras theorem: +<div class="center" +> +<!--l. 73--><p class="noindent" > +<div class="tabular"> <table id="TBL-2" class="tabular" +cellspacing="0" cellpadding="0" +><colgroup id="TBL-2-1g"><col +id="TBL-2-1"><col +id="TBL-2-2"></colgroup><tr + style="vertical-align:baseline;" id="TBL-2-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-1-1" +class="td11"><img +src="tutorial2x.png" alt="∘x2-+-y2-" class="sqrt" ></td><td style="white-space:nowrap; text-align:center;" id="TBL-2-1-2" +class="td11"><img +src="tutorial3x.png" alt="∘x2-+-y2 +-z2" class="sqrt" ></td> +</tr><tr + style="vertical-align:baseline;" id="TBL-2-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-2-1" +class="td11"> <span +class="ecti-0700">2D </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-2-2-2" +class="td11"> <span +class="ecti-0700">3D </span></td> +</tr><tr + style="vertical-align:baseline;" id="TBL-2-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-2-3-1" +class="td11"> </td> +</tr></table></div> +</div> +<!--l. 80--><p class="indent" > The direction can be an arbitrary angle from either the <span +class="ecti-1000">x </span>or <span +class="ecti-1000">y </span>axis, and could be +computed by using trigonometry, or just using the usual <span +class="ecti-1000">atan2 </span>function present in +most math libraries. However, when dealing with 3D, the direction can’t be described +as an angle. To separate magnitude and direction, 3D uses the concept of <span +class="ecti-1000">normal</span> +<span +class="ecti-1000">vectors.</span> +<!--l. 88--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.2.2 </span> <a + id="x1-50001.2.2"></a>Implementation</h5> +<!--l. 90--><p class="noindent" >Vectors are implemented in Godot Engine as a class named <span +class="ecti-1000">Vector3 </span>for 3D, and as +both <span +class="ecti-1000">Vector2</span>, <span +class="ecti-1000">Point2 </span>or <span +class="ecti-1000">Size2 </span>in 2D (they are all aliases). They are used for any +purpose where a pair of 2D or 3D values (described as <span +class="ecti-1000">x,y </span>or <span +class="ecti-1000">x,y,z) </span>is needed. This is +somewhat a standard in most libraries or engines. In the script API, they can be +instanced like this: + <!--l. 98--> + <div class="lstlisting"><span class="label"><a + id="x1-5001r1"></a></span>a = Vector3() <br /><span class="label"><a + id="x1-5002r2"></a></span>a = Vector2( 2.0, 3.4 ) + </div> + +<!--l. 104--><p class="indent" > Vectors also support the common operators <span +class="ecti-1000">+, -, / and * </span>for addition, +substraction, multiplication and division. + <!--l. 108--> + <div class="lstlisting"><span class="label"><a + id="x1-5003r1"></a></span>a = Vector3(1,2,3) <br /><span class="label"><a + id="x1-5004r2"></a></span>b = Vector3(4,5,6) <br /><span class="label"><a + id="x1-5005r3"></a></span>c = Vector3() <br /><span class="label"><a + id="x1-5006r4"></a></span> <br /><span class="label"><a + id="x1-5007r5"></a></span>// writing <br /><span class="label"><a + id="x1-5008r6"></a></span> <br /><span class="label"><a + id="x1-5009r7"></a></span>c = a + b <br /><span class="label"><a + id="x1-5010r8"></a></span> <br /><span class="label"><a + id="x1-5011r9"></a></span>// is the same as writing <br /><span class="label"><a + id="x1-5012r10"></a></span> <br /><span class="label"><a + id="x1-5013r11"></a></span>c.x = a.x + b.x <br /><span class="label"><a + id="x1-5014r12"></a></span>c.y = a.y + b.y <br /><span class="label"><a + id="x1-5015r13"></a></span>c.z = a.z + b.z <br /><span class="label"><a + id="x1-5016r14"></a></span> <br /><span class="label"><a + id="x1-5017r15"></a></span>// both will result in a vector containing (5,7,9). <br /><span class="label"><a + id="x1-5018r16"></a></span>// the same happens for the rest of the operators. + </div> +<!--l. 128--><p class="indent" > Vectors also can perform a wide variety of built-in functions, their most common +usages will be explored next. +<!--l. 132--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.2.3 </span> <a + id="x1-60001.2.3"></a>Normal Vectors</h5> +<!--l. 134--><p class="noindent" >Two points ago, it was mentioned that 3D vectors can’t describe their direction as an +agle (as 2D vectors can). Because of this, <span +class="ecti-1000">normal vectors </span>become important for +separating a vector between <span +class="ecti-1000">direction </span>and <span +class="ecti-1000">magnitude.</span> +<!--l. 139--><p class="indent" > A <span +class="ecti-1000">normal vector </span>is a vector with a <span +class="ecti-1000">magnitude </span>of <span +class="ecti-1000">1. </span>This means, no matter where +the vector is pointing to, it’s length is always <span +class="ecti-1000">1</span>. + <div class="tabular"> + <table id="TBL-3" class="tabular" +cellspacing="0" cellpadding="0" +><colgroup id="TBL-3-1g"><col +id="TBL-3-1"></colgroup><tr + style="vertical-align:baseline;" id="TBL-3-1-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-1-1" +class="td11"><img +src="tutorial4x.png" alt="PIC" class="graphics" width="100.375pt" height="100.375pt" ><!--tex4ht:graphics +name="tutorial4x.png" src="2_home_red_coding_godot_doc_math_normals.eps" +--></td> +</tr><tr + style="vertical-align:baseline;" id="TBL-3-2-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-2-1" +class="td11"> <span +class="ecrm-0700">Normal vectors aroud the origin. </span></td> +</tr><tr + style="vertical-align:baseline;" id="TBL-3-3-"><td style="white-space:nowrap; text-align:center;" id="TBL-3-3-1" +class="td11"> </td> </tr></table> +</div> +<!--l. 148--><p class="indent" > Normal vectors have endless uses in 3D graphics programming, so it’s +recommended to get familiar with them as much as possible. +<!--l. 152--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.2.4 </span> <a + id="x1-70001.2.4"></a>Normalization</h5> +<!--l. 154--><p class="noindent" >Normalization is the process through which normal vectors are obtained +from regular vectors. In other words, normalization is used to reduce the +<span +class="ecti-1000">magnitude </span>of any vector to <span +class="ecti-1000">1</span>. (except of course, unless the vector is (0,0,0) +). +<!--l. 159--><p class="indent" > To normalize a vector, it must be divided by its magnitude (which should be +greater than zero): + <!--l. 163--> + <div class="lstlisting"><span class="label"><a + id="x1-7001r1"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">a</span><span +class="ecti-1000"> </span><span +class="ecti-1000">custom</span><span +class="ecti-1000"> </span><span +class="ecti-1000">vector</span><span +class="ecti-1000"> </span><span +class="ecti-1000">is</span><span +class="ecti-1000"> </span><span +class="ecti-1000">created</span> <br /><span class="label"><a + id="x1-7002r2"></a></span>a = Vector3(4,5,6) <br /><span class="label"><a + id="x1-7003r3"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">’</span><span +class="ecti-1000">l</span><span +class="ecti-1000">’</span><span +class="ecti-1000"> </span><span +class="ecti-1000">is</span><span +class="ecti-1000"> </span><span +class="ecti-1000">a</span><span +class="ecti-1000"> </span><span +class="ecti-1000">single</span><span +class="ecti-1000"> </span><span +class="ecti-1000">real</span><span +class="ecti-1000"> </span><span +class="ecti-1000">number</span><span +class="ecti-1000"> </span><span +class="ecti-1000">(</span><span +class="ecti-1000">or</span><span +class="ecti-1000"> </span><span +class="ecti-1000">scalar</span><span +class="ecti-1000">)</span><span +class="ecti-1000"> </span><span +class="ecti-1000">containight</span><span +class="ecti-1000"> </span><span +class="ecti-1000">the</span><span +class="ecti-1000"> </span><span +class="ecti-1000">length</span> <br /><span class="label"><a + id="x1-7004r4"></a></span>l = Math.sqrt( a.x<span +class="cmsy-10">*</span>a.x + a.y<span +class="cmsy-10">*</span>a.y + a.z<span +class="cmsy-10">*</span>a.z ) <br /><span class="label"><a + id="x1-7005r5"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">the</span><span +class="ecti-1000"> </span><span +class="ecti-1000">vector</span><span +class="ecti-1000"> </span><span +class="ecti-1000">’</span><span +class="ecti-1000">a</span><span +class="ecti-1000">’</span><span +class="ecti-1000"> </span><span +class="ecti-1000">is</span><span +class="ecti-1000"> </span><span +class="ecti-1000">divided</span><span +class="ecti-1000"> </span><span +class="ecti-1000">by</span><span +class="ecti-1000"> </span><span +class="ecti-1000">its</span><span +class="ecti-1000"> </span><span +class="ecti-1000">length</span><span +class="ecti-1000">,</span><span +class="ecti-1000"> </span><span +class="ecti-1000">by</span><span +class="ecti-1000"> </span><span +class="ecti-1000">performing</span><span +class="ecti-1000"> </span><span +class="ecti-1000">scalar</span><span +class="ecti-1000"> </span><span +class="ecti-1000">divide</span> <br /><span class="label"><a + id="x1-7006r6"></a></span>a = a / l <br /><span class="label"><a + id="x1-7007r7"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">which</span><span +class="ecti-1000"> </span><span +class="ecti-1000">is</span><span +class="ecti-1000"> </span><span +class="ecti-1000">the</span><span +class="ecti-1000"> </span><span +class="ecti-1000">same</span><span +class="ecti-1000"> </span><span +class="ecti-1000">as</span> <br /><span class="label"><a + id="x1-7008r8"></a></span>a.x = a.x / l <br /><span class="label"><a + id="x1-7009r9"></a></span>a.y = a.y / l <br /><span class="label"><a + id="x1-7010r10"></a></span>a.z = a.z / l + + </div> +<!--l. 177--><p class="indent" > Vector3 contains two built in functions for normalization: + <!--l. 180--> + <div class="lstlisting"><span class="label"><a + id="x1-7011r1"></a></span>a = Vector3(4,5,6) <br /><span class="label"><a + id="x1-7012r2"></a></span>a.normalize() <span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">in</span><span +class="cmsy-10">-</span><span +class="ecti-1000">place</span><span +class="ecti-1000"> </span><span +class="ecti-1000">normalization</span> <br /><span class="label"><a + id="x1-7013r3"></a></span>b = a.normalized() <span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">returns</span><span +class="ecti-1000"> </span><span +class="ecti-1000">a</span><span +class="ecti-1000"> </span><span +class="ecti-1000">copy</span><span +class="ecti-1000"> </span><span +class="ecti-1000">of</span><span +class="ecti-1000"> </span><span +class="ecti-1000">a</span><span +class="ecti-1000">,</span><span +class="ecti-1000"> </span><span +class="ecti-1000">normalized</span> + </div> +<!--l. 188--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.2.5 </span> <a + id="x1-80001.2.5"></a>Dot Product</h5> +<!--l. 190--><p class="noindent" >The dot product is, pheraps, the most useful operation that can be applied to 3D +vectors. In the surface, it’s multiple usages are not very obvious, but in depth it can +provide very useful information between two vectors (be it direction or just points in +space). +<!--l. 195--><p class="indent" > The dot product takes two vectors (<span +class="ecti-1000">a </span>and <span +class="ecti-1000">b </span>in the example) and returns a scalar +(single real number): +<div class="center" +> +<!--l. 198--><p class="noindent" > +<!--l. 199--><p class="noindent" ><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">x</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">x</span></sub> <span +class="cmr-10">+ </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">y</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">y</span></sub> <span +class="cmr-10">+ </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">z</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">z</span></sub> +</div> +<!--l. 202--><p class="indent" > The same expressed in code: + <!--l. 205--> + <div class="lstlisting"><span class="label"><a + id="x1-8001r1"></a></span>a = Vector3(...) <br /><span class="label"><a + id="x1-8002r2"></a></span>b = Vector3(...) <br /><span class="label"><a + id="x1-8003r3"></a></span> <br /><span class="label"><a + id="x1-8004r4"></a></span>c = a.x<span +class="cmsy-10">*</span>b.x + a.y<span +class="cmsy-10">*</span>b.y + a.z<span +class="cmsy-10">*</span>b.z <br /><span class="label"><a + id="x1-8005r5"></a></span> <br /><span class="label"><a + id="x1-8006r6"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">using</span><span +class="ecti-1000"> </span><span +class="ecti-1000">built</span><span +class="cmsy-10">-</span><span +class="ecti-1000">in</span><span +class="ecti-1000"> </span><span +class="ecti-1000">dot</span><span +class="ecti-1000">()</span><span +class="ecti-1000"> </span><span +class="ecti-1000">function</span> <br /><span class="label"><a + id="x1-8007r7"></a></span> <br /><span class="label"><a + id="x1-8008r8"></a></span>c = a.dot(b) + </div> +<!--l. 218--><p class="indent" > The dot product presents several useful properties: + <ul class="itemize1"> + <li class="itemize">If both <span +class="ecti-1000">a </span>and <span +class="ecti-1000">b </span>parameters to a <span +class="ecti-1000">dot product </span>are direction vectors, dot + product will return positive if both point towards the same direction, + negative if both point towards opposite directions, and zero if they are + orthogonal (one is perpendicular to the other). + </li> + <li class="itemize">If both <span +class="ecti-1000">a </span>and <span +class="ecti-1000">b </span>parameters to a <span +class="ecti-1000">dot product </span>are <span +class="ecti-1000">normalized </span>direction + vectors, then the dot product will return the cosine of the angle between + them (ranging from 1 if they are equal, 0 if they are orthogonal, and -1 if + they are opposed (a == -b)). + </li> + <li class="itemize">If <span +class="ecti-1000">a </span>is a <span +class="ecti-1000">normalized </span>direction vector and <span +class="ecti-1000">b </span>is a point, the dot product will + return the distance from <span +class="ecti-1000">b </span>to the plane passing through the origin, with + normal <span +class="ecti-1000">a (see item about planes)</span> + + </li> + <li class="itemize">More uses will be presented later in this tutorial.</li></ul> +<!--l. 236--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.2.6 </span> <a + id="x1-90001.2.6"></a>Cross Product</h5> +<!--l. 238--><p class="noindent" >The <span +class="ecti-1000">cross product </span>also takes two vectors <span +class="ecti-1000">a </span>and <span +class="ecti-1000">b</span>, but returns another vector <span +class="ecti-1000">c </span>that is +orthogonal to the two previous ones. +<div class="center" +> +<!--l. 242--><p class="noindent" > +<!--l. 243--><p class="noindent" ><span +class="cmmi-10">c</span><sub><span +class="cmmi-7">x</span></sub> <span +class="cmr-10">= </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">x</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">z</span></sub> <span +class="cmsy-10">- </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">z</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">y</span></sub> +</div> +<div class="center" +> +<!--l. 246--><p class="noindent" > +<!--l. 247--><p class="noindent" ><span +class="cmmi-10">c</span><sub><span +class="cmmi-7">y</span></sub> <span +class="cmr-10">= </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">z</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">x</span></sub> <span +class="cmsy-10">- </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">x</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">z</span></sub> +</div> +<div class="center" +> +<!--l. 250--><p class="noindent" > +<!--l. 251--><p class="noindent" ><span +class="cmmi-10">c</span><sub><span +class="cmmi-7">z</span></sub> <span +class="cmr-10">= </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">x</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">y</span></sub> <span +class="cmsy-10">- </span><span +class="cmmi-10">a</span><sub><span +class="cmmi-7">y</span></sub><span +class="cmmi-10">b</span><sub><span +class="cmmi-7">x</span></sub> +</div> +<!--l. 254--><p class="indent" > The same in code: + <!--l. 257--> + <div class="lstlisting"><span class="label"><a + id="x1-9001r1"></a></span>a = Vector3(...) <br /><span class="label"><a + id="x1-9002r2"></a></span>b = Vector3(...) <br /><span class="label"><a + id="x1-9003r3"></a></span>c = Vector3(...) <br /><span class="label"><a + id="x1-9004r4"></a></span> <br /><span class="label"><a + id="x1-9005r5"></a></span>c.x = a.x<span +class="cmsy-10">*</span>b.z <span +class="cmsy-10">-</span> a.z<span +class="cmsy-10">*</span>b.y <br /><span class="label"><a + id="x1-9006r6"></a></span>c.y = a.z<span +class="cmsy-10">*</span>b.x <span +class="cmsy-10">-</span> a.x<span +class="cmsy-10">*</span>b.z <br /><span class="label"><a + id="x1-9007r7"></a></span>c.z = a.x<span +class="cmsy-10">*</span>b.y <span +class="cmsy-10">-</span> a.y<span +class="cmsy-10">*</span>b.x <br /><span class="label"><a + id="x1-9008r8"></a></span> <br /><span class="label"><a + id="x1-9009r9"></a></span>// or using the built<span +class="cmsy-10">-</span>in function <br /><span class="label"><a + id="x1-9010r10"></a></span> <br /><span class="label"><a + id="x1-9011r11"></a></span>c = a.cross(b) + </div> +<!--l. 273--><p class="indent" > The <span +class="ecti-1000">cross product </span>also presents several useful properties: + <ul class="itemize1"> + <li class="itemize">As mentioned, the resulting vector <span +class="ecti-1000">c </span>is orthogonal to the input vectors <span +class="ecti-1000">a</span> + and <span +class="ecti-1000">b.</span> + </li> + <li class="itemize">Since the <span +class="ecti-1000">cross product </span>is anticommutative, swapping <span +class="ecti-1000">a </span>and <span +class="ecti-1000">b </span>will result + in a negated vector <span +class="ecti-1000">c.</span> + + </li> + <li class="itemize">if <span +class="ecti-1000">a </span>and <span +class="ecti-1000">b </span>are taken from two of the segmets <span +class="ecti-1000">AB</span>, <span +class="ecti-1000">BC </span>or <span +class="ecti-1000">CA </span>that form a + 3D triangle, the magnitude of the resulting vector divided by 2 is the area + of that triangle. + </li> + <li class="itemize">The direction of the resulting vector <span +class="ecti-1000">c </span>in the previous triangle example + determines wether the points A,B and C are arranged in clocwise or + counter-clockwise order.</li></ul> +<!--l. 287--><p class="noindent" > + <h4 class="subsectionHead"><span class="titlemark">1.3 </span> <a + id="x1-100001.3"></a>Plane</h4> +<!--l. 290--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.3.1 </span> <a + id="x1-110001.3.1"></a>Theory</h5> +<!--l. 292--><p class="noindent" >A plane can be considered as an infinite, flat surface that splits space in two halves, +usually one named positive and one named negative. In regular mathematics, a plane +formula is described as: +<div class="center" +> +<!--l. 296--><p class="noindent" > +<!--l. 297--><p class="noindent" ><span +class="cmmi-10">ax </span><span +class="cmr-10">+ </span><span +class="cmmi-10">by </span><span +class="cmr-10">+ </span><span +class="cmmi-10">cz </span><span +class="cmr-10">+ </span><span +class="cmmi-10">d</span> +</div> +<!--l. 300--><p class="indent" > However, in 3D programming, this form alone is often of little use. For planes to +become useful, they must be in normalized form. +<!--l. 303--><p class="indent" > A normalized plane consists of a <span +class="ecti-1000">normal vector n </span>and a <span +class="ecti-1000">distance d. </span>To normalize +a plane, a vector <span +class="ecti-1000">n </span>and distance <span +class="ecti-1000">d’ </span>are created this way: +<!--l. 307--><p class="indent" > <span +class="cmmi-10">n</span><sub><span +class="cmmi-7">x</span></sub> <span +class="cmr-10">= </span><span +class="cmmi-10">a</span> +<!--l. 309--><p class="indent" > <span +class="cmmi-10">n</span><sub><span +class="cmmi-7">y</span></sub> <span +class="cmr-10">= </span><span +class="cmmi-10">b</span> +<!--l. 311--><p class="indent" > <span +class="cmmi-10">n</span><sub><span +class="cmmi-7">z</span></sub> <span +class="cmr-10">= </span><span +class="cmmi-10">c</span> +<!--l. 313--><p class="indent" > <span +class="cmmi-10">d</span><span +class="cmsy-10">′ </span><span +class="cmr-10">= </span><span +class="cmmi-10">d</span> +<!--l. 315--><p class="indent" > Finally, both <span +class="ecti-1000">n </span>and <span +class="ecti-1000">d’ </span>are both divided by the magnitude of n. +<!--l. 318--><p class="indent" > In any case, normalizing planes is not often needed (this was mostly for +explanation purposes), and normalized planes are useful because they can be created +and used easily. +<!--l. 322--><p class="indent" > A normalized plane could be visualized as a plane pointing towards normal <span +class="ecti-1000">n,</span> +offseted by <span +class="ecti-1000">d </span>in the direction of <span +class="ecti-1000">n</span>. +<!--l. 325--><p class="indent" > In other words, take <span +class="ecti-1000">n</span>, multiply it by scalar <span +class="ecti-1000">d </span>and the resulting point will be part +of the plane. This may need some thinking, so an example with a 2D normal vector +(z is 0, so plane is orthogonal to it) is provided: +<!--l. 330--><p class="indent" > Some operations can be done with normalized planes: + + <ul class="itemize1"> + <li class="itemize">Given any point <span +class="ecti-1000">p</span>, the distance from it to a plane can be computed by + doing: n.dot(p) - d + </li> + <li class="itemize">If the resulting distance in the previous point is negative, the point is + below the plane. + </li> + <li class="itemize">Convex polygonal shapes can be defined by enclosing them in planes (the + physics engine uses this property)</li></ul> +<!--l. 340--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.3.2 </span> <a + id="x1-120001.3.2"></a>Implementation</h5> +<!--l. 342--><p class="noindent" >Godot Engine implements normalized planes by using the <span +class="ecti-1000">Plane </span>class. + <!--l. 346--> + <div class="lstlisting"><span class="label"><a + id="x1-12001r1"></a></span>//creates a plane with normal (0,1,0) and distance 5 <br /><span class="label"><a + id="x1-12002r2"></a></span>p = Plane( Vector3(0,1,0), 5 ) <br /><span class="label"><a + id="x1-12003r3"></a></span>// get the distance to a point <br /><span class="label"><a + id="x1-12004r4"></a></span>d = p.distance( Vector3(4,5,6) ) + </div> +<!--l. 355--><p class="noindent" > + <h4 class="subsectionHead"><span class="titlemark">1.4 </span> <a + id="x1-130001.4"></a>Matrices, Quaternions and Coordinate Systems</h4> +<!--l. 357--><p class="noindent" >It is very often needed to store the location/rotation of something. In 2D, it is often +enough to store an <span +class="ecti-1000">x,y </span>location and maybe an angle as the rotation, as that should +be enough to represent any posible position. +<!--l. 362--><p class="indent" > In 3D this becomes a little more difficult, as there is nothing as simple as an angle +to store a 3-axis rotation. +<!--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 +one for z. However this suffers from the problem that it becomes very cumbersome to +use, as the individual rotations in each axis need to be performed one after another +(they can’t be performed at the same time), leading to a problem called “gimbal +lock”. Also, it becomes impossible to accumulate rotations (add a rotation to an +existing one). +<!--l. 373--><p class="indent" > To solve this, there are two known diferent approaches that aid in solving +rotation, <span +class="ecti-1000">Quaternions </span>and <span +class="ecti-1000">Oriented Coordinate Systems.</span> +<!--l. 378--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.4.1 </span> <a + id="x1-140001.4.1"></a>Oriented Coordinate Systems</h5> +<!--l. 380--><p class="noindent" ><span +class="ecti-1000">Oriented Coordinate Systems </span>(<span +class="ecti-1000">OCS</span>) are a way of representing a coordinate system +inside the cartesian coordinate system. They are mainly composed of 3 Vectors, one +for each axis. The first vector is the <span +class="ecti-1000">x </span>axis, the second the <span +class="ecti-1000">y </span>axis, and the third is the + +<span +class="ecti-1000">z </span>axis. The OCS vectors can be rotated around freely as long as they are kept the +same length (as changing the length of an axis changes its cale), and as long as they +remain orthogonal to eachother (as in, the same as the default cartesian system, +with <span +class="ecti-1000">y </span>pointing up, <span +class="ecti-1000">x </span>pointing left and <span +class="ecti-1000">z </span>pointing front, but all rotated +together). +<!--l. 391--><p class="indent" > <span +class="ecti-1000">Oriented Coordinate Systems </span>are represented in 3D programming as a 3x3 matrix, +where each row (or column, depending on the implementation) contains one of the +axis vectors. Transforming a Vector by a rotated OCS Matrix results in the rotation +being applied to the resulting vector. OCS Matrices can also be multiplied to +accumulate their transformations. +<!--l. 397--><p class="indent" > Godot Engine implements OCS Matrices in the <span +class="ecti-1000">Matrix3 </span>class: + <!--l. 400--> + <div class="lstlisting"><span class="label"><a + id="x1-14001r1"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000">create</span><span +class="ecti-1000"> </span><span +class="ecti-1000">a</span><span +class="ecti-1000"> </span><span +class="ecti-1000">3</span><span +class="ecti-1000">x3</span><span +class="ecti-1000"> </span><span +class="ecti-1000">matrix</span> <br /><span class="label"><a + id="x1-14002r2"></a></span>m = Matrix3() <br /><span class="label"><a + id="x1-14003r3"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000">rotate</span><span +class="ecti-1000"> </span><span +class="ecti-1000">the</span><span +class="ecti-1000"> </span><span +class="ecti-1000">matrix</span><span +class="ecti-1000"> </span><span +class="ecti-1000">in</span><span +class="ecti-1000"> </span><span +class="ecti-1000">the</span><span +class="ecti-1000"> </span><span +class="ecti-1000">y</span><span +class="ecti-1000"> </span><span +class="ecti-1000">axis</span><span +class="ecti-1000">,</span><span +class="ecti-1000"> </span><span +class="ecti-1000">by</span><span +class="ecti-1000"> </span><span +class="ecti-1000">45</span><span +class="ecti-1000"> </span><span +class="ecti-1000">degrees</span> <br /><span class="label"><a + id="x1-14004r4"></a></span>m.rotate( Vector3(0,1,0), Math.deg2rad(45) ) <br /><span class="label"><a + id="x1-14005r5"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000">transform</span><span +class="ecti-1000"> </span><span +class="ecti-1000">a</span><span +class="ecti-1000"> </span><span +class="ecti-1000">vector</span><span +class="ecti-1000"> </span><span +class="ecti-1000">v</span><span +class="ecti-1000"> </span><span +class="ecti-1000">(</span><span +class="ecti-1000">xform</span><span +class="ecti-1000"> </span><span +class="ecti-1000">method</span><span +class="ecti-1000"> </span><span +class="ecti-1000">is</span><span +class="ecti-1000"> </span><span +class="ecti-1000">used</span><span +class="ecti-1000">)</span> <br /><span class="label"><a + id="x1-14006r6"></a></span>v = Vector3(...) <br /><span class="label"><a + id="x1-14007r7"></a></span>result = m.xform( v ) + </div> +<!--l. 412--><p class="indent" > However, in most usage cases, one wants to store a translation together with the +rotation. For this, an <span +class="ecti-1000">origin </span>vector must be added to the OCS, thus transforming it +into a 3x4 (or 4x3, depending on preference) matrix. Godot engine implements this +functionality in the <span +class="ecti-1000">Transform </span>class: + <!--l. 419--> + <div class="lstlisting"><span class="label"><a + id="x1-14010r1"></a></span>t = Transform() <br /><span class="label"><a + id="x1-14011r2"></a></span>//rotate the transform in the y axis, by 45 degrees <br /><span class="label"><a + id="x1-14012r3"></a></span>t.rotate( Vector3(0,1,0), Math.deg2rad(45) ) <br /><span class="label"><a + id="x1-14013r4"></a></span>//translate the transform by 5 in the z axis <br /><span class="label"><a + id="x1-14014r5"></a></span>t.translate( Vector3( 0,0,5 ) ) <br /><span class="label"><a + id="x1-14015r6"></a></span>//transform a vector v (xform method is used) <br /><span class="label"><a + id="x1-14016r7"></a></span>v = Vector3(...) <br /><span class="label"><a + id="x1-14017r8"></a></span>result = t.xform( v ) + </div> +<!--l. 431--><p class="indent" > Transform contains internally a Matrix3 “basis” and a Vector3 “origin” (which can +be modified individually). +<!--l. 435--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.4.2 </span> <a + id="x1-150001.4.2"></a>Transform Internals</h5> +<!--l. 437--><p class="noindent" >Internally, the xform() process is quite simple, to apply a 3x3 transform to a vector, +the transposed axis vectors are used (as using the regular axis vectors will result on +an inverse of the desired transform): + <!--l. 442--> + <div class="lstlisting"><span class="label"><a + id="x1-15001r1"></a></span>m = Matrix3(...) <br /><span class="label"><a + id="x1-15002r2"></a></span>v = Vector3(..) <br /><span class="label"><a + id="x1-15003r3"></a></span>result = Vector3(...) <br /><span class="label"><a + id="x1-15004r4"></a></span> <br /><span class="label"><a + id="x1-15005r5"></a></span>x_axis = m.get_axis(0) <br /><span class="label"><a + id="x1-15006r6"></a></span>y_axis = m.get_axis(1) <br /><span class="label"><a + id="x1-15007r7"></a></span>z_axis = m.get_axis(2) <br /><span class="label"><a + id="x1-15008r8"></a></span> <br /><span class="label"><a + id="x1-15009r9"></a></span>result.x = Vector3(x_axis.x, y_axis.x, z_axis.x).dot(v) <br /><span class="label"><a + id="x1-15010r10"></a></span>result.y = Vector3(x_axis.y, y_axis.y, z_axis.y).dot(v) <br /><span class="label"><a + id="x1-15011r11"></a></span>result.z = Vector3(x_axis.z, y_axis.z, z_axis.z).dot(v) <br /><span class="label"><a + id="x1-15012r12"></a></span> <br /><span class="label"><a + id="x1-15013r13"></a></span>// is the same as doing <br /><span class="label"><a + id="x1-15014r14"></a></span> <br /><span class="label"><a + id="x1-15015r15"></a></span>result = m.xform(v) <br /><span class="label"><a + id="x1-15016r16"></a></span> <br /><span class="label"><a + id="x1-15017r17"></a></span>// if m this was a Transform(), the origin would be added <br /><span class="label"><a + id="x1-15018r18"></a></span>// like this: <br /><span class="label"><a + id="x1-15019r19"></a></span> <br /><span class="label"><a + id="x1-15020r20"></a></span>result = result + t.get_origin() + </div> +<!--l. 468--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.4.3 </span> <a + id="x1-160001.4.3"></a>Using The Transform</h5> +<!--l. 470--><p class="noindent" >So, it is often desired apply sucessive operations to a transformation. For example, +let’s a assume that there is a turtle sitting at the origin (the turtle is a logo reference, + +for those familiar with it). The <span +class="ecti-1000">y </span>axis is up, and the the turtle’s nose is pointing +towards the <span +class="ecti-1000">z </span>axis. +<!--l. 476--><p class="indent" > The turtle (like many other animals, or vehicles!) can only walk towards the +direction it’s looking at. So, moving the turtle around a little should be something +like this: + <!--l. 481--> + <div class="lstlisting"><span class="label"><a + id="x1-16001r1"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">turtle</span><span +class="ecti-1000"> </span><span +class="ecti-1000">at</span><span +class="ecti-1000"> </span><span +class="ecti-1000">the</span><span +class="ecti-1000"> </span><span +class="ecti-1000">origin</span> <br /><span class="label"><a + id="x1-16002r2"></a></span>turtle = Transform() <br /><span class="label"><a + id="x1-16003r3"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">turtle</span><span +class="ecti-1000"> </span><span +class="ecti-1000">will</span><span +class="ecti-1000"> </span><span +class="ecti-1000">walk</span><span +class="ecti-1000"> </span><span +class="ecti-1000">5</span><span +class="ecti-1000"> </span><span +class="ecti-1000">units</span><span +class="ecti-1000"> </span><span +class="ecti-1000">in</span><span +class="ecti-1000"> </span><span +class="ecti-1000">z</span><span +class="ecti-1000"> </span><span +class="ecti-1000">axis</span> <br /><span class="label"><a + id="x1-16004r4"></a></span>turtle.translate( Vector3(0,0,5) ) <br /><span class="label"><a + id="x1-16005r5"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">turtle</span><span +class="ecti-1000"> </span><span +class="ecti-1000">eyes</span><span +class="ecti-1000"> </span><span +class="ecti-1000">a</span><span +class="ecti-1000"> </span><span +class="ecti-1000">lettuce</span><span +class="ecti-1000"> </span><span +class="ecti-1000">3</span><span +class="ecti-1000"> </span><span +class="ecti-1000">units</span><span +class="ecti-1000"> </span><span +class="ecti-1000">away</span><span +class="ecti-1000">,</span><span +class="ecti-1000"> </span><span +class="ecti-1000">will</span><span +class="ecti-1000"> </span><span +class="ecti-1000">rotate</span><span +class="ecti-1000"> </span><span +class="ecti-1000">45</span><span +class="ecti-1000"> </span><span +class="ecti-1000">degrees</span><span +class="ecti-1000"> </span><span +class="ecti-1000">right</span> <br /><span class="label"><a + id="x1-16006r6"></a></span>turtle.rotate( Vector3(0,1,0), Math.deg2rad(45) ) <br /><span class="label"><a + id="x1-16007r7"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">turtle</span><span +class="ecti-1000"> </span><span +class="ecti-1000">approaches</span><span +class="ecti-1000"> </span><span +class="ecti-1000">the</span><span +class="ecti-1000"> </span><span +class="ecti-1000">lettuce</span> <br /><span class="label"><a + id="x1-16008r8"></a></span>turtle.translate( Vector3(0,0,5) ) <br /><span class="label"><a + id="x1-16009r9"></a></span><span +class="ecti-1000">//</span><span +class="ecti-1000"> </span><span +class="ecti-1000">happy</span><span +class="ecti-1000"> </span><span +class="ecti-1000">turtle</span><span +class="ecti-1000"> </span><span +class="ecti-1000">over</span><span +class="ecti-1000"> </span><span +class="ecti-1000">lettuce</span><span +class="ecti-1000"> </span><span +class="ecti-1000">is</span><span +class="ecti-1000"> </span><span +class="ecti-1000">at</span> <br /><span class="label"><a + id="x1-16010r10"></a></span>print(turtle.get_origin()) + </div> +<!--l. 496--><p class="indent" > As can be seen, every new action the turtle takes is based on the previous one it +took. Had the order of actions been different and the turtle would have never reached +the lettuce. +<!--l. 500--><p class="indent" > Transforms are just that, a mean of “accumulating” rotation, translation, scale, +etc. +<!--l. 504--><p class="noindent" > + <h5 class="subsubsectionHead"><span class="titlemark">1.4.4 </span> <a + id="x1-170001.4.4"></a>A Warning about Numerical Precision</h5> +<!--l. 506--><p class="noindent" >Performing several actions over a transform will slowly and gradually lead to +precision loss (objects that draw according to a transform may get jittery, bigger, +smaller, skewed, etc). This happens due to the nature of floating point numbers. if +transforms/matrices are created from other kind of values (like a position and +some angular rotation) this is not needed, but if has been accumulating +transformations and was never recreated, it can be normalized by calling the +.orthonormalize() built-in function. This function has little cost and calling it every +now and then will avoid the effects from precision loss to become visible. + +</body></html> + + + diff --git a/doc/html/tutorial01/tutorial0x.png b/doc/html/tutorial01/tutorial0x.png Binary files differnew file mode 100644 index 0000000000..a0ed4f53ff --- /dev/null +++ b/doc/html/tutorial01/tutorial0x.png diff --git a/doc/html/tutorial01/tutorial1x.png b/doc/html/tutorial01/tutorial1x.png Binary files differnew file mode 100644 index 0000000000..80f0d099f7 --- /dev/null +++ b/doc/html/tutorial01/tutorial1x.png diff --git a/doc/html/tutorial01/tutorial2x.png b/doc/html/tutorial01/tutorial2x.png Binary files differnew file mode 100644 index 0000000000..76c502b6da --- /dev/null +++ b/doc/html/tutorial01/tutorial2x.png diff --git a/doc/html/tutorial01/tutorial3x.png b/doc/html/tutorial01/tutorial3x.png Binary files differnew file mode 100644 index 0000000000..8431e9d15c --- /dev/null +++ b/doc/html/tutorial01/tutorial3x.png diff --git a/doc/html/tutorial01/tutorial4x.png b/doc/html/tutorial01/tutorial4x.png Binary files differnew file mode 100644 index 0000000000..1ce7a2bb45 --- /dev/null +++ b/doc/html/tutorial01/tutorial4x.png |