<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
	<title>Math and Physics - Articles</title>
	<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/</link>
	<pubDate>Wed, 22 May 2013 09:52:48 +0000</pubDate>
	<ttl>86400</ttl>
	<description>Resources for mathematics and physics that relate to game development, including collisions and algorithms</description>
	<item>
		<title>Math for Game Developers: Intro to Matrices</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/math-for-game-developers-intro-to-matrices-r3097</link>
		<description><![CDATA[Math for Game Developers is exactly what it sounds like - a weekly instructional YouTube series wherein I show you how to use math to make your games. Every Thursday we'll learn how to implement one game design, starting from the underlying mathematical concept and ending with its C++ implementation. The videos will teach you everything you need to know, all you need is a basic understanding of algebra and trigonometry. If you want to follow along with the code sections, it will help to know a bit of programming already, but it's not necessary. You can download the source code that I'm using from GitHub, from the description of each video. If you have questions about the topics covered or requests for future topics, I would love to hear them! Leave a comment, or ask me on my Twitter, @<a href='https://twitter.com/VinoBS' class='bbc_url' title='External link' rel='nofollow external'>VinoBS</a><br />
<br />
<p class="message note">

<strong>Note:</strong>&nbsp;&nbsp;<br />
The video below contains the playlist for all the videos in this series, which can be accessed via the playlist icon in the bottom-right corner of the embedded video frame once the video is playing. The first video in the series is loaded automatically<br />

				
</p><br />
<p class="message note">

<strong>Note:</strong>&nbsp;&nbsp;<br />
This is an ongoing series of videos that will be updated every week. When a new video is posted we will update the publishing date of this article and the new video will be found at the end of the playlist<br />

				
</p><br />
<h1>Intro to Matrices</h1><p style='text-align:center'><br />
<iframe src="http://www.youtube.com/embed/videoseries?list=PLW3Zl3wyJwWNQjMz941uyOIq3Nw6bcDYC" 
width="100%" height="500" frameborder="0"></iframe><br />
</p>]]></description>
		<pubDate>Tue, 30 Apr 2013 05:36:31 +0000</pubDate>
		<guid isPermaLink="false">220222df17837f0fd0d46fa5c6466eec</guid>
	</item>
	<item>
		<title>Math for Game Developers: Advanced Vectors</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/math-for-game-developers-advanced-vectors-r3096</link>
		<description><![CDATA[Math for Game Developers is exactly what it sounds like - a weekly instructional YouTube series wherein I show you how to use math to make your games. Every Thursday we'll learn how to implement one game design, starting from the underlying mathematical concept and ending with its C++ implementation. The videos will teach you everything you need to know, all you need is a basic understanding of algebra and trigonometry. If you want to follow along with the code sections, it will help to know a bit of programming already, but it's not necessary. You can download the source code that I'm using from GitHub, from the description of each video. If you have questions about the topics covered or requests for future topics, I would love to hear them! Leave a comment, or ask me on my Twitter, @<a href='https://twitter.com/VinoBS' class='bbc_url' title='External link' rel='nofollow external'>VinoBS</a><br />
<br />
<p class="message note">

<strong>Note:</strong>&nbsp;&nbsp;<br />
The video below contains the playlist for all the videos in this series, which can be accessed via the playlist icon in the bottom-right corner of the embedded video frame once the video is playing. The first video in the series is loaded automatically<br />

				
</p><br />
<h1>Advanced Vectors</h1><p style='text-align:center'><br />
<iframe src="http://www.youtube.com/embed/videoseries?list=PLW3Zl3wyJwWMcLmUYXMIIxCiLKGOWLETh" 
width="100%" height="500" frameborder="0"></iframe><br />
</p>]]></description>
		<pubDate>Tue, 30 Apr 2013 05:19:59 +0000</pubDate>
		<guid isPermaLink="false">571df53e6b6fc55ba413313a42bb4cf5</guid>
	</item>
	<item>
		<title>Math for Game Developers: Intro to Vectors</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/math-for-game-developers-intro-to-vectors-r3071</link>
		<description><![CDATA[Math for Game Developers is exactly what it sounds like - a weekly instructional YouTube series wherein I show you how to use math to make your games. Every Thursday we'll learn how to implement one game design, starting from the underlying mathematical concept and ending with its C++ implementation. The videos will teach you everything you need to know, all you need is a basic understanding of algebra and trigonometry. If you want to follow along with the code sections, it will help to know a bit of programming already, but it's not necessary.<br />
<br />
Starting with the second series, "<a href='http://www.gamedev.net/page/resources/_/technical/math-and-physics/math-for-game-developers-advanced-vectors-r3096' class='bbc_url' title=''>Advanced Vectors</a>", you can download the source code that I'm using from GitHub, from the description of each video. If you have questions about the topics covered or requests for future topics, I would love to hear them! Leave a comment, or ask me on my Twitter, @<a href='https://twitter.com/VinoBS' class='bbc_url' title='External link' rel='nofollow external'>VinoBS</a><br />
<br />
<p class="message note">

<strong>Note:</strong>&nbsp;&nbsp;<br />
The video below contains the playlist for all the videos in this series, which can be accessed via the playlist icon in the bottom-right corner of the embedded video frame once the video is playing. The first video in the series is loaded automatically<br />

				
</p><br />
<h1>Intro to Vectors</h1><p style='text-align:center'><br />
<iframe src="http://www.youtube.com/embed/videoseries?list=PLW3Zl3wyJwWMduel9Luo0ex2JdKLVjYYp" 
width="100%" height="500" frameborder="0"></iframe><br />
</p>]]></description>
		<pubDate>Sun, 21 Apr 2013 13:03:25 +0000</pubDate>
		<guid isPermaLink="false">57947ed4d4130c7ff0a057c8654dd1a3</guid>
	</item>
	<item>
		<title>Vectors and Matrices: A Primer</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/vectors-and-matrices-a-primer-r3064</link>
		<description><![CDATA[<h1>Preface</h1><br />
This article is designed for those who need to brush up on your maths. Here we will discuss vectors, the operations we can perform on them, and why we find them so useful. We’ll then move onto what matrices and determinants are, and how we can use them to help us solve systems of equations. Finally, we’ll move onto using matrices to define transformations in space.<br />
<br />
<p class="message note">

<strong>Note:</strong>&nbsp;&nbsp;<br />
This article was originally published to GameDev.net back in 2002. It was revised by the original author in 2008 and published in the book <a href='http://www.amazon.com/Beginning-Game-Programming-GameDev-net-Collection/dp/159863805X/ref=pd_sim_b_1' class='bbc_url' title='External link' rel='nofollow external'>Beginning Game Programming: A GameDev.net Collection</a>, which is one of 4 books collecting both popular GameDev.net articls and new original content in print format.<br />

				
</p><br />
<h1>Vectors</h1><br />
<h2>Vector Basics – What is a vector?</h2><br />
Vectors are the backbone of games. They are the foundation of graphics, physics modelling, and a number of other things. Vectors can be of any dimension, but are most commonly seen in two, three, or four dimensions. They essentially represent a direction, and a magnitude. Thus, consider the velocity of a ball in a football game. It will have a direction (where it's travelling), and a magnitude (the speed at which it is travelling). Normal numbers (i.e. single dimensional numbers) are called <i>scalars</i>.<br />
<br />
The notation for a vector is that of a bold lower-case letter, like <strong>i</strong>, or an italic letter with an underscore, like <u><i>i</i></u>. I'll use the former in this text. You can write vectors in a number of ways, however I'll only use two here: vector equations and column vectors. <br />
<br />
Vectors can be written in terms of its starting and ending position, using the two end points with an arrow above them. So, if you have a vector between the two points A and B, you can write that as:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15009-0-17143000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15009" title="ccs-8549-0-74933000-1311406833_thumb.gif - Size: 133bytes, Downloads: 24"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-89602100-1366365429.gif" id='ipb-attach-img-15009-0-17143000-1369216368' style='width:59;height:25' class='attach' width="59" height="25" alt="Attached Image: ccs-8549-0-74933000-1311406833_thumb.gif" /></a><br />
<br />
A vector equation takes the form:<br />
<br />
<strong>a</strong> = x<strong>i</strong> + y<strong>j</strong> + z<strong>k</strong><br />
<br />
The coefficients of the <strong>i</strong>, <strong>j</strong>, and <strong>k</strong> parts of the equation are the vectors <i>components</i>. These are how long each vector is in each of the 3 axis.<br />
<br />
For example, the vector equation pointing to the point ( 3, 2, 5 ) from the origin ( 0, 0, 0 ) in 3D space would be:<br />
<br />
<strong>a</strong> = 2<strong>i</strong> + 3<strong>j</strong> + 5<strong>k</strong><br />
 <br />
The second way I will represent vectors is as <i>column vectors</i>. These are vectors written in the following form:<br />
<br />
<a class='resized_img' rel='lightbox[]' id='ipb-attach-url-15010-0-17175900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15010" title="ccs-8549-0-13322100-1311406871_thumb.gif - Size: 293bytes, Downloads: 24"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-31491500-1366365612.gif" id='ipb-attach-img-15010-0-17175900-1369216368' style='width:53;height:75' class='attach' width="53" height="75" alt="Attached Image: ccs-8549-0-13322100-1311406871_thumb.gif" /></a><br />
 <br />
Where <i>x</i>, <i>y</i>, and <i>z</i> are the components of that vector in the respective directions. These are exactly the same as the respective components of the vector equation. Thus in column vector form, the previous example could be written as:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15011-0-17222100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15011" title="ccs-8549-0-41119900-1311406881_thumb.gif - Size: 300bytes, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-33719800-1366365643.gif" id='ipb-attach-img-15011-0-17222100-1369216368' style='width:52;height:75' class='attach' width="52" height="75" alt="Attached Image: ccs-8549-0-41119900-1311406881_thumb.gif" /></a><br />
 <br />
There are various advantages to both of the above forms, although column vectors will continue to be used. Various mathematic texts may use the vector equation form.<br />
<br />
<h2>Vector Mathematics</h2><br />
There are many ways in which you can operate on vectors, including scalar multiplication, addition, scalar product, vector product and modulus.<br />
<br />
<strong>Modulus</strong><br />
<br />
The <i>modulus</i> or <i>magnitude</i> of a vector is simply its length. This can easily be found using Pythagorean Theorem with the vector components. The modulus is written like so:<br />
 <br />
<strong>a</strong> = |<strong>a</strong>|<br />
<br />
Given:<br />
<br />
<a class='resized_img' rel='lightbox[]' id='ipb-attach-url-15010-0-17184100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15010" title="ccs-8549-0-13322100-1311406871_thumb.gif - Size: 293bytes, Downloads: 24"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-31491500-1366365612.gif" id='ipb-attach-img-15010-0-17184100-1369216368' style='width:53;height:75' class='attach' width="53" height="75" alt="Attached Image: ccs-8549-0-13322100-1311406871_thumb.gif" /></a><br />
 <br />
Then, <br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15012-0-17241800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15012" title="ccs-8549-0-18438000-1311406906_thumb.gif - Size: 275bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-07449700-1366365771.gif" id='ipb-attach-img-15012-0-17241800-1369216368' style='width:127;height:31' class='attach' width="127" height="31" alt="Attached Image: ccs-8549-0-18438000-1311406906_thumb.gif" /></a><br />
 <br />
Where <i>x</i>, <i>y</i> and <i>z</i> are the components of the vector in the respective axis.<br />
<br />
<strong>Addition</strong><br />
<br />
Vector addition is rather simple. You just add the individual components together. For instance, given:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15013-0-17259500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15013" title="ccs-8549-0-52337300-1311406947_thumb.gif - Size: 341bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-26724300-1366365807.gif" id='ipb-attach-img-15013-0-17259500-1369216368' style='width:65;height:75' class='attach' width="65" height="75" alt="Attached Image: ccs-8549-0-52337300-1311406947_thumb.gif" /></a><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
The addition of these vectors would be:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15014-0-17277500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15014" title="ccs-8549-0-28558500-1311406958_thumb.gif - Size: 856bytes, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-76794300-1366365824.gif" id='ipb-attach-img-15014-0-17277500-1369216368' style='width:200;height:75' class='attach' width="200" height="75" alt="Attached Image: ccs-8549-0-28558500-1311406958_thumb.gif" /></a><br />
 <br />
This can be represented very easily in a diagram, for example:<br />
&nbsp;&nbsp;<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15015-0-17295100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15015" title="ccs-8549-0-12549800-1311406970_thumb.gif - Size: 228bytes, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-23601300-1366365864.gif" id='ipb-attach-img-15015-0-17295100-1369216368' style='width:52;height:48' class='attach' width="52" height="48" alt="Attached Image: ccs-8549-0-12549800-1311406970_thumb.gif" /></a> <a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15016-0-17313300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15016" title="ccs-8549-0-52518500-1311406982_thumb.gif - Size: 240bytes, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-19200400-1366365878.gif" id='ipb-attach-img-15016-0-17313300-1369216368' style='width:65;height:48' class='attach' width="65" height="48" alt="Attached Image: ccs-8549-0-52518500-1311406982_thumb.gif" /></a><br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15017-0-17333000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15017" title="ccs-8549-0-25839100-1311406994_thumb.gif - Size: 408bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-26777800-1366365892.gif" id='ipb-attach-img-15017-0-17333000-1369216368' style='width:104;height:104' class='attach' width="104" height="104" alt="Attached Image: ccs-8549-0-25839100-1311406994_thumb.gif" /></a><br />
 <br />
This works in the same way as moving the second vector so that its beginning is at the first vector's end, and taking the vector from the beginning of the first vector to the end of the second one. So, in a diagram, using the above example, this would be:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15018-0-17351400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15018" title="ccs-8549-0-06202600-1311407005_thumb.gif - Size: 364bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-45402000-1366365915.gif" id='ipb-attach-img-15018-0-17351400-1369216368' style='width:76;height:95' class='attach' width="76" height="95" alt="Attached Image: ccs-8549-0-06202600-1311407005_thumb.gif" /></a><br />
 <br />
This means that you can add multiple vectors together to get the resultant vector. This is used extensively in mechanics for finding resultant forces.<br />
<br />
<strong>Subtracting</strong><br />
<br />
Subtracting is very similar to adding, and is also quite helpful. The individual components are simply subtracted from each other. The geometric representation however is quite different from addition. For example:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15019-0-17369500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15019" title="ccs-8549-0-83651900-1311407019_thumb.gif - Size: 223bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-77487100-1366365961.gif" id='ipb-attach-img-15019-0-17369500-1369216368' style='width:52;height:48' class='attach' width="52" height="48" alt="Attached Image: ccs-8549-0-83651900-1311407019_thumb.gif" /></a> <a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15020-0-17387500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15020" title="ccs-8549-0-31746600-1311407031_thumb.gif - Size: 231bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-69727100-1366365972.gif" id='ipb-attach-img-15020-0-17387500-1369216368' style='width:53;height:48' class='attach' width="53" height="48" alt="Attached Image: ccs-8549-0-31746600-1311407031_thumb.gif" /></a><br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15021-0-17405600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15021" title="ccs-8549-0-13826600-1311407045_thumb.gif - Size: 576bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-12961500-1366365986.gif" id='ipb-attach-img-15021-0-17405600-1369216368' style='width:189;height:48' class='attach' width="189" height="48" alt="Attached Image: ccs-8549-0-13826600-1311407045_thumb.gif" /></a><br />
 <br />
The visual representation is:<br />
<br />
<a class='resized_img' rel='lightbox[]' id='ipb-attach-url-15022-0-17439100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15022" title="ccs-8549-0-75087900-1311407058_thumb.gif - Size: 462bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-31279700-1366366003.gif" id='ipb-attach-img-15022-0-17439100-1369216368' style='width:142;height:104' class='attach' width="142" height="104" alt="Attached Image: ccs-8549-0-75087900-1311407058_thumb.gif" /></a><br />
 <br />
Here, <strong>a</strong> and <strong>b</strong> are set to be from the same origin. The vector <strong>c</strong> is the vector from the end of the second vector to the end of the first, which in this case is from the end of <strong>b</strong> to the end of <strong>a</strong>. <br />
<br />
It may be easier to think of this as a vector addition, where instead of having:<br />
<br />
<strong>c</strong> = <strong>a</strong> – <strong>b</strong><br />
<br />
We have:<br />
<br />
<strong>c</strong> = -<strong>b</strong> + <strong>a</strong><br />
<br />
Which according to what was said about the addition of vectors would produce:<br />
<br />
<a class='resized_img' rel='lightbox[]' id='ipb-attach-url-15022-0-17447100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15022" title="ccs-8549-0-75087900-1311407058_thumb.gif - Size: 462bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-31279700-1366366003.gif" id='ipb-attach-img-15022-0-17447100-1369216368' style='width:142;height:104' class='attach' width="142" height="104" alt="Attached Image: ccs-8549-0-75087900-1311407058_thumb.gif" /></a><br />
 <br />
You can see that putting <strong>a</strong> on the end of –<strong>b</strong> has the same result.<br />
<br />
<strong>Scalar Multiplication</strong><br />
<br />
This is another simple operation; all you need to do is multiply each component by that scalar. For example, let us suggest that you have a vector <strong>a</strong> and a scalar <i>k</i>. To perform a scalar multiplication you would multiply each component of the vector by that scalar, thus:<br />
 <br />
<a class='resized_img' rel='lightbox[]' id='ipb-attach-url-15010-0-17191500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15010" title="ccs-8549-0-13322100-1311406871_thumb.gif - Size: 293bytes, Downloads: 24"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-31491500-1366365612.gif" id='ipb-attach-img-15010-0-17191500-1369216368' style='width:53;height:75' class='attach' width="53" height="75" alt="Attached Image: ccs-8549-0-13322100-1311406871_thumb.gif" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15023-0-17469600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15023" title="ccs-8549-0-84633600-1311407105_thumb.gif - Size: 376bytes, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-70035900-1366366199.gif" id='ipb-attach-img-15023-0-17469600-1369216368' style='width:67;height:75' class='attach' width="67" height="75" alt="Attached Image: ccs-8549-0-84633600-1311407105_thumb.gif" /></a><br />
 <br />
This has the effect of lengthening or shortening the vector by the amount <i>k</i>. For instance, take <i>k</i> = 2; this would make the vector a twice as long. Multiplying by a negative scalar reverses the direction of the vector. <br />
<br />
<strong>The Scalar Product (Dot Product)</strong><br />
<br />
The <i>scalar product</i>, also known as the <i>dot product</i>, is very useful in 3D graphics applications. The scalar product is written:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15024-0-17488400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15024" title="dot.png - Size: 425bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-11847700-1366366446.png" id='ipb-attach-img-15024-0-17488400-1369216368' style='width:66;height:32' class='attach' width="66" height="32" alt="Attached Image: dot.png" /></a><br />
 <br />
This is read “a dot b”.<br />
<br />
The definition of the scalar product is:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15025-0-17506600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15025" title="scalar.png - Size: 803bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-36939800-1366366466.png" id='ipb-attach-img-15025-0-17506600-1369216368' style='width:129;height:32' class='attach' width="129" height="32" alt="Attached Image: scalar.png" /></a><br />
 <br />
Θ is the angle between the two vectors <strong>a</strong> and <strong>b</strong>. This produces a scalar result, hence the name scalar product. This operation has the result of giving the length of the projection of <strong>a</strong> on <strong>b</strong>. For example:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15032-0-17628500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15032" title="BegGameProg_VectorsAndMatricesAPrimer_Dadd_5.jpg - Size: 4.95K, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-01792600-1366366958.jpg" id='ipb-attach-img-15032-0-17628500-1369216368' style='width:250;height:118' class='attach' width="250" height="118" alt="Attached Image: BegGameProg_VectorsAndMatricesAPrimer_Dadd_5.jpg" /></a><br />
 <br />
The length of the thick gray horizontal line segment would be the dot product.<br />
<br />
The scalar product can also be written in terms of Cartesian components as:<br />
<br />
<a class='resized_img' rel='lightbox[]' id='ipb-attach-url-15027-0-17540400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15027" title="ccs-8549-0-11366200-1311407231_thumb.gif - Size: 327bytes, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-50455800-1366366633.gif" id='ipb-attach-img-15027-0-17540400-1369216368' style='width:59;height:75' class='attach' width="59" height="75" alt="Attached Image: ccs-8549-0-11366200-1311407231_thumb.gif" /></a> <a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15028-0-17570900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15028" title="ccs-8549-0-25055400-1311407243_thumb.gif - Size: 341bytes, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-60140700-1366366649.gif" id='ipb-attach-img-15028-0-17570900-1369216368' style='width:61;height:75' class='attach' width="61" height="75" alt="Attached Image: ccs-8549-0-25055400-1311407243_thumb.gif" /></a><br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15029-0-17589500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15029" title="ccs-8549-0-12617400-1311407255_thumb.gif - Size: 275bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-88504800-1366366661.gif" id='ipb-attach-img-15029-0-17589500-1369216368' style='width:161;height:23' class='attach' width="161" height="23" alt="Attached Image: ccs-8549-0-12617400-1311407255_thumb.gif" /></a><br />
 <br />
We can put the two dot product equations equal to each other to yield:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15030-0-17608100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15030" title="ccs-8549-0-33111200-1311407287_thumb.gif - Size: 383bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-83762000-1366366692.gif" id='ipb-attach-img-15030-0-17608100-1369216368' style='width:197;height:27' class='attach' width="197" height="27" alt="Attached Image: ccs-8549-0-33111200-1311407287_thumb.gif" /></a><br />
 <br />
With this, we can find angles between vectors. <br />
<br />
Scalar products are used extensively in the graphics pipeline to see if triangles are facing towards or away from the viewer, whether they are in the current view (known as frustum culling), and other forms of culling.<br />
<br />
<strong>The Vector Product (Cross Product)</strong><br />
<br />
The <i>vector product</i>, also commonly known as the <i>cross product</i>, is one of the more complex operations performed on vectors. In simple terms, the vector product produces a vector that is perpendicular to the vectors having the operation applied. Great for finding normal vectors to surfaces!<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15033-0-17648500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15033" title="BegGameProg_VectorsAndMatricesAPrimer_Dadd_6.jpg - Size: 7.99K, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-20614400-1366366958.jpg" id='ipb-attach-img-15033-0-17648500-1369216368' style='width:250;height:257' class='attach' width="250" height="257" alt="Attached Image: BegGameProg_VectorsAndMatricesAPrimer_Dadd_6.jpg" /></a><br />
 <br />
I’m not going to get into the derivation of the vector product here, but in expanded form it is:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15034-0-17668100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15034" title="index.gif - Size: 1.38K, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-37472100-1366367062.gif" id='ipb-attach-img-15034-0-17668100-1369216368' style='width:341;height:18' class='attach' width="341" height="18" alt="Attached Image: index.gif" /></a><br />
 <br />
Read “a cross b”.<br />
<br />
Since the cross product finds the perpendicular vector, we can say that:<br />
 <br />
<strong>i</strong> x <strong>j</strong> = <strong>k</strong><br />
<br />
<strong>j</strong> x <strong>k</strong> = <strong>i</strong><br />
<br />
<strong>k</strong> x <strong>i</strong> = <strong>j</strong><br />
 <br />
Note that the resultant vectors are perpendicular in accordance with the “right hand screw rule”. That is, if you make your thumb, index and middle fingers perpendicular, the cross product of your middle finger with your thumb will produce your index finger.<br />
<br />
Using scalar multiplication along with the vector product we can find the "normal" vector to a plane. A plane can be defined by two vectors, <strong>a</strong> and <strong>b</strong>. The normal vector is a vector that is perpendicular to a plane and is also a unit vector. Using the formulas discussed earlier, we have:<br />
 <br />
<strong>c</strong> = <strong>a</strong> x <strong>b</strong><br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15035-0-17687400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15035" title="ccs-8549-0-47469800-1311407367_thumb.gif - Size: 164bytes, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-72044000-1366367194.gif" id='ipb-attach-img-15035-0-17687400-1369216368' style='width:44;height:47' class='attach' width="44" height="47" alt="Attached Image: ccs-8549-0-47469800-1311407367_thumb.gif" /></a><br />
<br />
This first finds the vector perpendicular to the plane made by <strong>a</strong> and <strong>b</strong> then scales that vector so it has a magnitude of 1. <br />
<br />
One important point about the vector product is that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15036-0-17706400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15036" title="index.gif - Size: 263bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-25722900-1366367239.gif" id='ipb-attach-img-15036-0-17706400-1369216368' style='width:79;height:19' class='attach' width="79" height="19" alt="Attached Image: index.gif" /></a><br />
 <br />
This is a very important point. If you put the inputs the wrong way round then you will not get the correct normal.<br />
<br />
<strong>Unit Vectors</strong><br />
<br />
These are vectors that have a unit length, i.e. a modulus of one. The <strong>i</strong>, <strong>j</strong> and <strong>k</strong> vectors are examples of unit vectors aligned to the respective axis. You should now be able to recognise that vector equations are quite simply just that. Adding together 3 vectors scaled by varying degrees to produce a single resultant vector. <br />
<br />
To find the unit vector of another vector, we use the modulus operator and scalar multiplication like so:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15037-0-17727100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15037" title="UV1.png - Size: 518bytes, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-97764200-1366367483.png" id='ipb-attach-img-15037-0-17727100-1369216368' style='width:59;height:58' class='attach' width="59" height="58" alt="Attached Image: UV1.png" /></a><br />
<br />
For example:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15038-0-17746100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15038" title="UV2.png - Size: 804bytes, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-12944200-1366367484.png" id='ipb-attach-img-15038-0-17746100-1369216368' style='width:65;height:88' class='attach' width="65" height="88" alt="Attached Image: UV2.png" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15039-0-17766000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15039" title="UV3.png - Size: 1.42K, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-27344800-1366367484.png" id='ipb-attach-img-15039-0-17766000-1369216368' style='width:325;height:36' class='attach' width="325" height="36" alt="Attached Image: UV3.png" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15040-0-17785700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15040" title="UV4.png - Size: 2.53K, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-42489400-1366367484.png" id='ipb-attach-img-15040-0-17785700-1369216368' style='width:191;height:143' class='attach' width="191" height="143" alt="Attached Image: UV4.png" /></a><br />
 <br />
That is the unit vector <strong>b</strong> in the direction of <strong>a</strong>. <br />
<br />
<strong>Position Vectors</strong><br />
<br />
These are the only type of vectors that have a position to speak of. They take their starting point as the origin of the coordinate system in which they are defined. Thus, they can be used to represent points in that space.<br />
<br />
<strong>The Vector Equation of a Straight Line</strong><br />
<br />
The vector equation of a straight line is very useful, and is given by a point on the line and a vector parallel to it:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15041-0-17805400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15041" title="index.gif - Size: 313bytes, Downloads: 13"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-30324500-1366367578.gif" id='ipb-attach-img-15041-0-17805400-1369216368' style='width:91;height:24' class='attach' width="91" height="24" alt="Attached Image: index.gif" /></a><br />
<br />
Where <strong>p</strong>0 is a point on the line, and <strong>v</strong> is the unit vector giving its direction. <i>t</i> is called the parameter and scales <strong>v</strong>. From this you can see that as <i>t</i> varies a line is formed in the direction of <strong>v</strong>.<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15042-0-17826200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15042" title="BegGameProg_VectorsAndMatricesAPrimer_Dadd_7.jpg - Size: 5.89K, Downloads: 27"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-90310100-1366367739.jpg" id='ipb-attach-img-15042-0-17826200-1369216368' style='width:250;height:192' class='attach' width="250" height="192" alt="Attached Image: BegGameProg_VectorsAndMatricesAPrimer_Dadd_7.jpg" /></a><br />
 <br />
This equation is called the <i>parametric</i> form of a straight line. Using this to find the vector equation of a line through two points is easy:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15043-0-17846200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15043" title="ccs-8549-0-39434100-1311407462_thumb.gif - Size: 290bytes, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-97300400-1366367775.gif" id='ipb-attach-img-15043-0-17846200-1369216368' style='width:140;height:24' class='attach' width="140" height="24" alt="Attached Image: ccs-8549-0-39434100-1311407462_thumb.gif" /></a><br />
 <br />
If <i>t</i> is constrained to values between 0 and 1, then we have a <i>line segment</i> starting at the point <strong>p</strong>0 and <strong>p</strong>1.<br />
<br />
Using the vector equation we can define planes and test for intersections. A plane can be defined as a point on the plane, and two vectors that are parallel to the plane.<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15044-0-17866100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15044" title="ccs-8549-0-74851200-1311407475_thumb.gif - Size: 256bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-09597200-1366367934.gif" id='ipb-attach-img-15044-0-17866100-1369216368' style='width:136;height:24' class='attach' width="136" height="24" alt="Attached Image: ccs-8549-0-74851200-1311407475_thumb.gif" /></a><br />
 <br />
Where <i>s</i> and <i>t</i> are the parameters, and <strong>u</strong> and <strong>v</strong> are the vectors that are parallel to the plane. Using this, you can find the intersection of a line and a plane, as the point of intersection must line on both the plane at the line. Thus, we simply make the two equations equal to each other.<br />
<br />
Given the line and plane:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15045-0-17886200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15045" title="vline1.png - Size: 1.62K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-74719800-1366368099.png" id='ipb-attach-img-15045-0-17886200-1369216368' style='width:163;height:79' class='attach' width="163" height="79" alt="Attached Image: vline1.png" /></a><br />
<br />
To find the intersection we equate so that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15046-0-17906000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15046" title="vline2.png - Size: 881bytes, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-87205400-1366368099.png" id='ipb-attach-img-15046-0-17906000-1369216368' style='width:176;height:25' class='attach' width="176" height="25" alt="Attached Image: vline2.png" /></a><br />
<br />
We then solve for <i>w</i>, <i>s</i> and <i>t</i>, and plug them into either the line or plane equation to find the point. When testing for a line segment <i>w</i> must be in the range 0 to 1.<br />
<br />
Another representation of a plane is the normal-distance. This combines the normal of the plane, and its distance from the origin along that normal. This is especially useful for finding out what sides of a plane points are. For example, given the plane <strong>p</strong> and point <strong>a</strong>:<br />
 <br />
<a class='resized_img' rel='lightbox[]' id='ipb-attach-url-15027-0-17549300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15027" title="ccs-8549-0-11366200-1311407231_thumb.gif - Size: 327bytes, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-50455800-1366366633.gif" id='ipb-attach-img-15027-0-17549300-1369216368' style='width:59;height:75' class='attach' width="59" height="75" alt="Attached Image: ccs-8549-0-11366200-1311407231_thumb.gif" /></a><br />
 <br />
<strong>p</strong> = <strong>n</strong> + <i>d</i><br />
<br />
Where,<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15047-0-17927200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15047" title="neq.png - Size: 951bytes, Downloads: 15"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-00385000-1366368277.png" id='ipb-attach-img-15047-0-17927200-1369216368' style='width:84;height:92' class='attach' width="84" height="92" alt="Attached Image: neq.png" /></a><br />
 <br />
The point <strong>a</strong> is in front of the plane <strong>p</strong> if:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15048-0-17946800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15048" title="neq2.png - Size: 859bytes, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-75809400-1366368351.png" id='ipb-attach-img-15048-0-17946800-1369216368' style='width:145;height:30' class='attach' width="145" height="30" alt="Attached Image: neq2.png" /></a><br />
 <br />
This is used extensively in various culling mechanisms.<br />
<br />
<h1>Matrices</h1><br />
<h2>What is a Matrix anyway?</h2><br />
A matrix can be considered a 2D array of numbers, and take the form:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15049-0-17966800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15049" title="ccs-8549-0-61157600-1311407567_thumb.gif - Size: 464bytes, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-53525600-1366368465.gif" id='ipb-attach-img-15049-0-17966800-1369216368' style='width:101;height:75' class='attach' width="101" height="75" alt="Attached Image: ccs-8549-0-61157600-1311407567_thumb.gif" /></a><br />
 <br />
Matrices are very powerful, and form the basis of all modern computer graphics. We define a matrix with an upper-case bold type letter, as shown above. The dimension of a matrix is its height followed by its width, so the above example has dimension 3x3. Matrices can be of any dimensions, but in terms of computer graphics, they are usually kept to 3x3 or 4x4. There are a few types of special matrices; these are the <i>column matrix</i>, <i>row matrix</i>, <i>square matrix</i>, <i>identity matrix</i> and <i>zero matrix</i>. A column matrix is one that has a width of 1, and a height of greater than 1. A row matrix is a matrix that has a width of greater than 1, and a height of 1. A square matrix is when the dimensions are the same. For instance, the above example is a square matrix, because the width equals the height. The identity matrix is a special type of matrix that has values in the diagonal from top left to bottom right as 1 and the rest as 0. The identity matrix is known by the letter <strong>I</strong>, where:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15050-0-17986400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15050" title="ccs-8549-0-35181600-1311407600_thumb.gif - Size: 453bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-14522700-1366368528.gif" id='ipb-attach-img-15050-0-17986400-1369216368' style='width:96;height:75' class='attach' width="96" height="75" alt="Attached Image: ccs-8549-0-35181600-1311407600_thumb.gif" /></a><br />
 <br />
The identity matrix can be any dimension, as long as it is also a square matrix. <br />
<br />
The <i>elements</i> of a matrix are all the numbers within it. They are numbered by the row/column position such that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15051-0-18006300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15051" title="ccs-8549-0-86930600-1311407611_thumb.gif - Size: 529bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-48084400-1366368566.gif" id='ipb-attach-img-15051-0-18006300-1369216368' style='width:109;height:75' class='attach' width="109" height="75" alt="Attached Image: ccs-8549-0-86930600-1311407611_thumb.gif" /></a><br />
 <br />
The zero matrix is one that has all its elements set to 0.<br />
<br />
Vectors can also be used in column or row matrices. I will use column matrices here, as that is what I have been using in the previous section. A 3D vector <strong>a</strong> in matrix form will use a matrix <strong>A</strong> with dimension 3x1 so that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15052-0-18027900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15052" title="ccs-8549-0-72535500-1311407625_thumb.gif - Size: 314bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-23486000-1366368603.gif" id='ipb-attach-img-15052-0-18027900-1369216368' style='width:57;height:75' class='attach' width="57" height="75" alt="Attached Image: ccs-8549-0-72535500-1311407625_thumb.gif" /></a><br />
 <br />
Which as you can see is the same layout as using column vectors.<br />
<br />
<h2>Matrix Arithmetic</h2><br />
I’m not going to go into every possible matrix manipulation (we would be here some time), instead I’ll focus on the important ones.<br />
<br />
<strong>Scalar / Matrix Multiplication</strong><br />
<br />
To perform this operation all you need to do is simply multiply each element by the scalar. Thus, given matrix <strong>A</strong> and scalar <i>k</i>:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15053-0-18047900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15053" title="scalarX.png - Size: 1.59K, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-46504700-1366368744.png" id='ipb-attach-img-15053-0-18047900-1369216368' style='width:168;height:96' class='attach' width="168" height="96" alt="Attached Image: scalarX.png" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15054-0-18068400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15054" title="scalarX2.png - Size: 2.75K, Downloads: 25"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-62289400-1366368744.png" id='ipb-attach-img-15054-0-18068400-1369216368' style='width:342;height:91' class='attach' width="342" height="91" alt="Attached Image: scalarX2.png" /></a><br />
 <br />
<strong>Matrix / Matrix Multiplication</strong><br />
<br />
Multiplying a matrix by another matrix is more difficult. First, we need to know if the two matrices are <i>conformable</i>. For a matrix to be conformable with another matrix, the number of rows in <strong>A</strong> needs to equal the number of columns in <strong>B</strong>. For instance, take matrix <strong>A</strong> as having dimension 3x3 and matrix <strong>B</strong> having dimension 3x2. These two matrices are conformable because the number of rows in <strong>A</strong> is the same as the number of columns in <strong>B</strong>. This is important as you'll see later. The product of these two matrices is another matrix with dimension 3x2. <br />
<br />
So generally, given three matrices <strong>A</strong>, <strong>B</strong> and <strong>C</strong>, where <strong>C</strong> is the product of <strong>A</strong> and <strong>B</strong>. <strong>A</strong> and <strong>B</strong> have dimension <i>m</i>x<i>n</i> and <i>p</i>x<i>q</i> respectively. They are conformable if <i>n</i>=<i>p</i>. The matrix <strong>C</strong> has dimension <i>m</i>x<i>q</i>. It is said that the two matrices are conformable if their <i>inner dimensions</i> are equal (<i>n</i> and <i>p</i> here).<br />
<br />
The multiplication is performed by multiplying each row in <strong>A</strong> by each column in <strong>B</strong>. Given:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15055-0-18089300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15055" title="ccs-8549-0-58828200-1311407689_thumb.gif - Size: 609bytes, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-94127100-1366368970.gif" id='ipb-attach-img-15055-0-18089300-1369216368' style='width:137;height:75' class='attach' width="137" height="75" alt="Attached Image: ccs-8549-0-58828200-1311407689_thumb.gif" /></a> <a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15056-0-18109500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15056" title="ccs-8549-0-75807400-1311407700_thumb.gif - Size: 508bytes, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-07274200-1366368971.gif" id='ipb-attach-img-15056-0-18109500-1369216368' style='width:100;height:75' class='attach' width="100" height="75" alt="Attached Image: ccs-8549-0-75807400-1311407700_thumb.gif" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15057-0-18131300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15057" title="index.gif - Size: 2.43K, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-40885100-1366368971_thumb.gif" id='ipb-attach-img-15057-0-18131300-1369216368' style='width:480;height:63' class='attach' width="480" height="63" alt="Attached Image: index.gif" /></a><br />
 <br />
So, with that in mind let us try an example!<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15059-0-18172400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15059" title="ccs-8549-0-79987200-1311407726_thumb.gif - Size: 596bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-19305200-1366369031.gif" id='ipb-attach-img-15059-0-18172400-1369216368' style='width:108;height:96' class='attach' width="108" height="96" alt="Attached Image: ccs-8549-0-79987200-1311407726_thumb.gif" /></a>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15058-0-18151900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15058" title="ccs-8549-0-00678700-1311407738_thumb.gif - Size: 386bytes, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-06477900-1366369031.gif" id='ipb-attach-img-15058-0-18151900-1369216368' style='width:76;height:75' class='attach' width="76" height="75" alt="Attached Image: ccs-8549-0-00678700-1311407738_thumb.gif" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15060-0-18192600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15060" title="index.gif - Size: 2.75K, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-32368700-1366369031_thumb.gif" id='ipb-attach-img-15060-0-18192600-1369216368' style='width:480;height:83' class='attach' width="480" height="83" alt="Attached Image: index.gif" /></a><br />
<br />
It’s as simple as that! Some things to note:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15061-0-18213300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15061" title="ccs-8549-0-29109000-1311407760_thumb.gif - Size: 156bytes, Downloads: 28"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-22830300-1366369104.gif" id='ipb-attach-img-15061-0-18213300-1369216368' style='width:68;height:17' class='attach' width="68" height="17" alt="Attached Image: ccs-8549-0-29109000-1311407760_thumb.gif" /></a><br />
 <br />
A matrix multiplied by the identity matrix is the same, so:<br />
<br />
<strong>AI</strong> = <strong>IA</strong> = <strong>A</strong><br />
 <br />
<strong>The Transpose</strong><br />
<br />
The <i>transpose</i> of a matrix is it flipped along the diagonal from the top left to the bottom right and is denoted by using a superscript <i>T</i>, for example:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15063-0-18256000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15063" title="ccs-8549-0-93459600-1311407784_thumb.gif - Size: 459bytes, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-99649000-1366369163.gif" id='ipb-attach-img-15063-0-18256000-1369216368' style='width:101;height:75' class='attach' width="101" height="75" alt="Attached Image: ccs-8549-0-93459600-1311407784_thumb.gif" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15062-0-18235400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15062" title="ccs-8549-0-35495300-1311407805_thumb.gif - Size: 482bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-79304500-1366369163.gif" id='ipb-attach-img-15062-0-18235400-1369216368' style='width:111;height:75' class='attach' width="111" height="75" alt="Attached Image: ccs-8549-0-35495300-1311407805_thumb.gif" /></a><br />
<br />
<h2>Determinants</h2><br />
Determinants are a useful tool for solving certain types of equations, and are used rather extensively.<br />
<br />
Let’s take a 2x2 matrix <strong>A</strong>:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15064-0-18276600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15064" title="ccs-8549-0-76083400-1311407842_thumb.gif - Size: 376bytes, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-54989000-1366369203.gif" id='ipb-attach-img-15064-0-18276600-1369216368' style='width:103;height:51' class='attach' width="103" height="51" alt="Attached Image: ccs-8549-0-76083400-1311407842_thumb.gif" /></a><br />
<br />
The determinant of matrix <strong>A</strong> is written |<strong>A</strong>| and is defined to be:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15065-0-18296900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15065" title="ccs-8549-0-61430500-1311407863_thumb.gif - Size: 268bytes, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-98992800-1366369231.gif" id='ipb-attach-img-15065-0-18296900-1369216368' style='width:128;height:27' class='attach' width="128" height="27" alt="Attached Image: ccs-8549-0-61430500-1311407863_thumb.gif" /></a><br />
 <br />
That is the top left to bottom right diagonal multiplied together subtracting the top right to bottom left diagonal. Things get a bit more complicated with higher dimensional determinants, let us discuss a 3x3 determinant first. Take <strong>A</strong> as:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15066-0-18317400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15066" title="ccs-8549-0-93920700-1311407878_thumb.gif - Size: 609bytes, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-24781100-1366369264.gif" id='ipb-attach-img-15066-0-18317400-1369216368' style='width:137;height:75' class='attach' width="137" height="75" alt="Attached Image: ccs-8549-0-93920700-1311407878_thumb.gif" /></a><br />
<br />
Step 1: move to the first value in the top row, a11. Take out the row and column that intersects with that value. <br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15067-0-18339800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15067" title="ccs-8549-0-41315500-1311407890_thumb.gif - Size: 458bytes, Downloads: 24"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-56856500-1366369292.gif" id='ipb-attach-img-15067-0-18339800-1369216368' style='width:108;height:75' class='attach' width="108" height="75" alt="Attached Image: ccs-8549-0-41315500-1311407890_thumb.gif" /></a><br />
 <br />
Step 2: multiply that determinant by a11.<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15068-0-18360700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15068" title="ccs-8549-0-76373600-1311407901_thumb.gif - Size: 315bytes, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-14375000-1366369307.gif" id='ipb-attach-img-15068-0-18360700-1369216368' style='width:84;height:51' class='attach' width="84" height="51" alt="Attached Image: ccs-8549-0-76373600-1311407901_thumb.gif" /></a><br />
 <br />
We repeat this along the top row, with the sign in front of the result of step 2 alternating between a “+” and a “-“. Given this, the determinant of <strong>A</strong> becomes:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15069-0-18381400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15069" title="index.gif - Size: 958bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-89567700-1366369335.gif" id='ipb-attach-img-15069-0-18381400-1369216368' style='width:305;height:51' class='attach' width="305" height="51" alt="Attached Image: index.gif" /></a><br />
 <br />
Now, how do we use these for equation solving? Good question. <br />
<br />
Given a pair of simultaneous equations with two unknowns:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15070-0-18402300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15070" title="ccs-8549-0-36208700-1311407930_thumb.gif - Size: 329bytes, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-46865300-1366369369.gif" id='ipb-attach-img-15070-0-18402300-1369216368' style='width:96;height:48' class='attach' width="96" height="48" alt="Attached Image: ccs-8549-0-36208700-1311407930_thumb.gif" /></a><br />
<br />
We first <i>push</i> these coefficients of the variables into a determinant, producing:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15071-0-18424900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15071" title="ccs-8549-0-95740300-1311407941_thumb.gif - Size: 250bytes, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-99950900-1366369413.gif" id='ipb-attach-img-15071-0-18424900-1369216368' style='width:55;height:51' class='attach' width="55" height="51" alt="Attached Image: ccs-8549-0-95740300-1311407941_thumb.gif" /></a><br />
 <br />
You can see that it is laid out in the same way. To solve the equation in terms of <i>x</i>, we replace the <i>x</i> coefficients in the determinant with the constants <i>k1</i> and <i>k2</i>, dividing the result by the original determinant:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15072-0-18446200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15072" title="det1.png - Size: 1.31K, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-75427700-1366369748.png" id='ipb-attach-img-15072-0-18446200-1369216368' style='width:100;height:117' class='attach' width="100" height="117" alt="Attached Image: det1.png" /></a><br />
 <br />
To solve for <i>y</i> we replace the <i>y</i> coefficients with the constants instead. This algorithm is called <i>Cramers Rule</i>.<br />
<br />
Let’s try an example to see this working, given the equations:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15073-0-18467900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15073" title="det2.png - Size: 989bytes, Downloads: 24"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-90101700-1366369748.png" id='ipb-attach-img-15073-0-18467900-1369216368' style='width:100;height:65' class='attach' width="100" height="65" alt="Attached Image: det2.png" /></a><br />
 <br />
We push the coefficients into a determinant and solve:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15074-0-18489000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15074" title="det3.png - Size: 1.29K, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-04738700-1366369749.png" id='ipb-attach-img-15074-0-18489000-1369216368' style='width:220;height:60' class='attach' width="220" height="60" alt="Attached Image: det3.png" /></a><br />
 <br />
To find <i>x</i> substitute the constants into the <i>x</i> coefficients, and divide by <strong>D</strong>:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15075-0-18511000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15075" title="det4.png - Size: 1.63K, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-20338000-1366369749.png" id='ipb-attach-img-15075-0-18511000-1369216368' style='width:244;height:82' class='attach' width="244" height="82" alt="Attached Image: det4.png" /></a><br />
 <br />
To find <i>y</i> substitute the constants into the <i>y</i> coefficients, and divide by <strong>D</strong>:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15076-0-18534100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15076" title="det5.png - Size: 1.61K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-40155500-1366369749.png" id='ipb-attach-img-15076-0-18534100-1369216368' style='width:253;height:82' class='attach' width="253" height="82" alt="Attached Image: det5.png" /></a><br />
 <br />
It’s as simple as that! For good measure, let’s do an example using 3 unknowns in 3 equations:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15077-0-18555800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15077" title="det6.png - Size: 5.31K, Downloads: 26"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-11006900-1366369998_thumb.png" id='ipb-attach-img-15077-0-18555800-1369216368' style='width:480;height:231' class='attach' width="480" height="231" alt="Attached Image: det6.png" /></a> <br />
 <br />
Solve for <i>x</i>:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15078-0-18577700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15078" title="det7.png - Size: 3.92K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-43688100-1366369998_thumb.png" id='ipb-attach-img-15078-0-18577700-1369216368' style='width:480;height:88' class='attach' width="480" height="88" alt="Attached Image: det7.png" /></a><br />
 <br />
Solve for <i>y</i>:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15079-0-18600400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15079" title="det8.png - Size: 3.79K, Downloads: 27"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-61205300-1366369998_thumb.png" id='ipb-attach-img-15079-0-18600400-1369216368' style='width:480;height:88' class='attach' width="480" height="88" alt="Attached Image: det8.png" /></a><br />
 <br />
Solve for <i>z</i>:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15080-0-18623900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15080" title="det9.png - Size: 3.67K, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-78349500-1366369998_thumb.png" id='ipb-attach-img-15080-0-18623900-1369216368' style='width:480;height:96' class='attach' width="480" height="96" alt="Attached Image: det9.png" /></a><br />
 <br />
And there we have it, how to solve a series of simultaneous equations using determinants, something that can be very useful.<br />
<br />
<strong>Matrix Inversion</strong><br />
<br />
Equations can also be solved by inverting a matrix. Using the same equations as before:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15081-0-18646400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15081" title="ccs-8549-0-56571200-1311408118_thumb.gif - Size: 437bytes, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-58409200-1366370087.gif" id='ipb-attach-img-15081-0-18646400-1369216368' style='width:109;height:69' class='attach' width="109" height="69" alt="Attached Image: ccs-8549-0-56571200-1311408118_thumb.gif" /></a><br />
 <br />
We first push these into three matrices to solve:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15082-0-18668600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15082" title="ccs-8549-0-90083900-1311408131_thumb.gif - Size: 795bytes, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-87563200-1366370107.gif" id='ipb-attach-img-15082-0-18668600-1369216368' style='width:157;height:75' class='attach' width="157" height="75" alt="Attached Image: ccs-8549-0-90083900-1311408131_thumb.gif" /></a><br />
&nbsp;&nbsp;<br />
Let’s give these names such that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15083-0-18690400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15083" title="ccs-8549-0-02710700-1311408147_thumb.gif - Size: 132bytes, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-31618300-1366370162.gif" id='ipb-attach-img-15083-0-18690400-1369216368' style='width:56;height:17' class='attach' width="56" height="17" alt="Attached Image: ccs-8549-0-02710700-1311408147_thumb.gif" /></a><br />
 <br />
We need to solve for <strong>B</strong> (this contains the unknowns after all). Since there is no “matrix divide” operation, we need to invert <strong>A</strong> and multiply it by <strong>D</strong> such that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15084-0-18712400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15084" title="ccs-8549-0-35483900-1311408160_thumb.gif - Size: 147bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-51415700-1366370162.gif" id='ipb-attach-img-15084-0-18712400-1369216368' style='width:68;height:20' class='attach' width="68" height="20" alt="Attached Image: ccs-8549-0-35483900-1311408160_thumb.gif" /></a><br />
 <br />
Now we need to know how to actually do the matrix inversion. There are many ways to do this, and the way that I’m going to use here is by no means the fastest.<br />
<br />
To find the inverse of a matrix, we need to first find its <i>co-factor</i>. We use a method similar to what we used when finding the determinant. What you do is this: at every element, eliminate the row and column that intersects it, and make it equal the determinant of the remaining part of the matrix, multiplied by the following expression:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15085-0-18736100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15085" title="index.gif - Size: 234bytes, Downloads: 14"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-85624500-1366370213.gif" id='ipb-attach-img-15085-0-18736100-1369216368' style='width:47;height:24' class='attach' width="47" height="24" alt="Attached Image: index.gif" /></a><br />
<br />
Where <i>i</i> and <i>j</i> is the position in the matrix.<br />
<br />
For example, given a 3x3 matrix <strong>A</strong>, and its co-factor <strong>C</strong>. To calculate the fist element in the cofactor matrix (c11), we first need to get rid of the row and column that intersects this so that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15086-0-18758200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15086" title="ccs-8549-0-44070200-1311408176_thumb.gif - Size: 458bytes, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-72609600-1366370253.gif" id='ipb-attach-img-15086-0-18758200-1369216368' style='width:108;height:75' class='attach' width="108" height="75" alt="Attached Image: ccs-8549-0-44070200-1311408176_thumb.gif" /></a><br />
 <br />
c11 would then take the value of the following:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15087-0-18780500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15087" title="fig.png - Size: 1.18K, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-56040200-1366370338.png" id='ipb-attach-img-15087-0-18780500-1369216368' style='width:135;height:63' class='attach' width="135" height="63" alt="Attached Image: fig.png" /></a><br />
 <br />
We would then repeat for all elements in matrix <strong>A</strong> to build up the co-factor matrix <strong>C</strong>. The inverse of matrix <strong>A</strong> can then be calculated using the following formula.<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15088-0-18803100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15088" title="ccs-8549-0-23509400-1311408221_thumb.gif - Size: 231bytes, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-62273200-1366370368.gif" id='ipb-attach-img-15088-0-18803100-1369216368' style='width:69;height:49' class='attach' width="69" height="49" alt="Attached Image: ccs-8549-0-23509400-1311408221_thumb.gif" /></a><br />
 <br />
The transpose of the co-factor matrix is also referred to as the <i>adjoint</i>.<br />
<br />
Given the previous example and equations, let’s find the inverse matrix of <strong>A</strong>.<br />
<br />
Firstly, the co-factor matrix <strong>C</strong> would be:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15089-0-18826900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15089" title="index.gif - Size: 2.28K, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-50335800-1366370406.gif" id='ipb-attach-img-15089-0-18826900-1369216368' style='width:309;height:141' class='attach' width="309" height="141" alt="Attached Image: index.gif" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15090-0-18850700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15090" title="ccs-8549-0-53635100-1311408248_thumb.gif - Size: 534bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-71753900-1366370429.gif" id='ipb-attach-img-15090-0-18850700-1369216368' style='width:139;height:75' class='attach' width="139" height="75" alt="Attached Image: ccs-8549-0-53635100-1311408248_thumb.gif" /></a><br />
 <br />
|<strong>A</strong>| is:<br />
<br />
|<strong>A</strong>| = -2<br />
 <br />
Thus, the inverse of <strong>A</strong> is:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15091-0-18873900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15091" title="inverse.png - Size: 4.68K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-98117900-1366370531_thumb.png" id='ipb-attach-img-15091-0-18873900-1369216368' style='width:480;height:134' class='attach' width="480" height="134" alt="Attached Image: inverse.png" /></a><br />
 <br />
We can then solve the equations by using:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15092-0-18896800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15092" title="ccs-8549-0-36524500-1311408291_thumb.gif - Size: 147bytes, Downloads: 17"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-38761100-1366370557.gif" id='ipb-attach-img-15092-0-18896800-1369216368' style='width:68;height:20' class='attach' width="68" height="20" alt="Attached Image: ccs-8549-0-36524500-1311408291_thumb.gif" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15093-0-18919500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15093" title="index.gif - Size: 1.26K, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-53197300-1366370557.gif" id='ipb-attach-img-15093-0-18919500-1369216368' style='width:275;height:75' class='attach' width="275" height="75" alt="Attached Image: index.gif" /></a><br />
 <br />
We can find the values of <i>x</i>, <strong>y</strong> and <i>z</i> by pulling them out of the resultant matrix, such that:<br />
<br />
<i>x</i> = -62<br />
<br />
<i>y</i> = 39<br />
<br />
<i>z</i> = 3<br />
 <br />
Which is exactly what we got by using Cramer’s rule!<br />
<br />
Matrices are said to be <i>orthogonal</i> if its transpose equals its inverse, which can be a useful property to quick inverting of matrices.<br />
<br />
<h2>Matrix Transformations</h2><br />
Graphics APIs use a set of matrices to define transformations in space. A transformation is a change, be it translation, rotation, or whatever. Using position vector in a column a matrix to define a point in space, a <i>vertex</i>, we can define matrices that alter that point in some way.<br />
<br />
<strong>Transformation Matrices</strong><br />
<br />
Most graphics APIs use three different types of primary transformations. These are translation; scaling; and rotation. We can transform a point <strong>p</strong> using a transformation matrix <strong>T</strong> to a point <strong>p'</strong> like so:<br />
 <br />
<strong>p'</strong> = <strong>Tp</strong><br />
<br />
We use 4 dimensional vectors from now on, of the form:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15094-0-18944300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15094" title="4d.png - Size: 1.07K, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-62095300-1366370906.png" id='ipb-attach-img-15094-0-18944300-1369216368' style='width:71;height:118' class='attach' width="71" height="118" alt="Attached Image: 4d.png" /></a><br />
 <br />
We then use 4x4 transformation matrices. The reason for the 4th component here is to help us perform translations using matrix multiplication. These are called <i>homogeneous</i> coordinates. I won’t go into their full derivation here, as that is quite beyond the scope of this article (their true meaning and purpose comes from points in projective space).<br />
<br />
<strong>Translation</strong><br />
<br />
To translate a point onto another point, there needs to be a vector of movement, so that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15095-0-18967200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15095" title="BegGameProg_VectorsAndMatricesAPrimer_Dadd_8.jpg - Size: 4.93K, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-16928100-1366370944.jpg" id='ipb-attach-img-15095-0-18967200-1369216368' style='width:250;height:167' class='attach' width="250" height="167" alt="Attached Image: BegGameProg_VectorsAndMatricesAPrimer_Dadd_8.jpg" /></a><br />
 <br />
Where <strong>p’</strong> is the translated point, <strong>p</strong> is the original point and <strong>v</strong> is the vector along which the translation has taken place.<br />
<br />
By keeping the w component of the vector as 1, we can represent this transformation in matrix form as:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15096-0-18990300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15096" title="transform.png - Size: 1.71K, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-74955900-1366371032.png" id='ipb-attach-img-15096-0-18990300-1369216368' style='width:164;height:119' class='attach' width="164" height="119" alt="Attached Image: transform.png" /></a><br />
 <br />
<strong>Scaling</strong><br />
<br />
You can scale a vertex by multiplying it by a scalar value, such that:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15097-0-19013300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15097" title="index.gif - Size: 2.8K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-16983200-1366371078_thumb.gif" id='ipb-attach-img-15097-0-19013300-1369216368' style='width:480;height:196' class='attach' width="480" height="196" alt="Attached Image: index.gif" /></a><br />
 <br />
Where <i>k</i> is the scalar constant. You can multiply each component of <strong>p</strong> by a different constant. This will make it so you can scale each axis by a different amount.<br />
<br />
In matrix form this becomes:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15098-0-19038100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15098" title="scaling.png - Size: 1.76K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-84139400-1366371186.png" id='ipb-attach-img-15098-0-19038100-1369216368' style='width:173;height:117' class='attach' width="173" height="117" alt="Attached Image: scaling.png" /></a><br />
 <br />
Where <i>kx</i>, <i>ky</i>, and <i>kz</i> are the scaling factors in the respective axis.<br />
<br />
<strong>Rotation</strong><br />
<br />
Rotation is a more complex transformation, so I’ll give a more thorough derivation for this than I have the others.<br />
<br />
Rotation in a plane (i.e. in 2D) can be described in the following diagram:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15099-0-19061600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15099" title="BegGameProg_VectorsAndMatricesAPrimer_Dadd_10.jpg - Size: 6.61K, Downloads: 43"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-43187700-1366371253.jpg" id='ipb-attach-img-15099-0-19061600-1369216368' style='width:250;height:224' class='attach' width="250" height="224" alt="Attached Image: BegGameProg_VectorsAndMatricesAPrimer_Dadd_10.jpg" /></a><br />
 <br />
This diagram shows that we want to rotate some point <strong>p</strong> by ω degrees to point <strong>p'</strong>. From this we can deduce the following equations:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15100-0-19085100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15100" title="rotation.png - Size: 1.88K, Downloads: 23"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-44061500-1366371338.png" id='ipb-attach-img-15100-0-19085100-1369216368' style='width:148;height:79' class='attach' width="148" height="79" alt="Attached Image: rotation.png" /></a><br />
 <br />
We are dealing with rotations about the origin, thus the following can be said:<br />
<br />
|<strong>P</strong>'| = |<strong>P</strong>|<br />
 <br />
Using the trigonometric identities for the sum of angles:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15102-0-19108500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15102" title="rotation2.png - Size: 2.63K, Downloads: 25"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-55711800-1366371658.png" id='ipb-attach-img-15102-0-19108500-1369216368' style='width:321;height:74' class='attach' width="321" height="74" alt="Attached Image: rotation2.png" /></a><br />
 <br />
We can expand the previous equations to:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15103-0-19133500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15103" title="rotation3.png - Size: 2.73K, Downloads: 21"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-69720200-1366371658.png" id='ipb-attach-img-15103-0-19133500-1369216368' style='width:291;height:78' class='attach' width="291" height="78" alt="Attached Image: rotation3.png" /></a><br />
 <br />
From looking at the diagram, you can also see that:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15104-0-19157000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15104" title="rotation4.png - Size: 1.43K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-85859300-1366371658.png" id='ipb-attach-img-15104-0-19157000-1369216368' style='width:112;height:78' class='attach' width="112" height="78" alt="Attached Image: rotation4.png" /></a><br />
 <br />
Substituting those into our equations, we end up with:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15105-0-19180700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15105" title="rotation5.png - Size: 2.15K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-99756400-1366371658.png" id='ipb-attach-img-15105-0-19180700-1369216368' style='width:206;height:77' class='attach' width="206" height="77" alt="Attached Image: rotation5.png" /></a><br />
 <br />
Which is what we want (the second point as a function of the first point).<br />
<br />
We can then push this into matrix form:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15106-0-19204200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15106" title="rotation6.png - Size: 1.8K, Downloads: 26"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-15207300-1366371659.png" id='ipb-attach-img-15106-0-19204200-1369216368' style='width:196;height:60' class='attach' width="196" height="60" alt="Attached Image: rotation6.png" /></a><br />
 <br />
Here, we have the rotation matrix for rotating a point in the x-y plane. We can expand this into 3D by having three different rotation matrices, one for rotating along the x axis, one in the y axis, and another for the z axis (this one is effectively what we have just done). The unused axis in each rotation remains unchanged. These rotation matrices become:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15107-0-19229400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15107" title="rotation7.png - Size: 2.49K, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-33266000-1366371659.png" id='ipb-attach-img-15107-0-19229400-1369216368' style='width:245;height:116' class='attach' width="245" height="116" alt="Attached Image: rotation7.png" /></a><br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15108-0-19253300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15108" title="rotation8.png - Size: 3.93K, Downloads: 22"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-53077300-1366371659.png" id='ipb-attach-img-15108-0-19253300-1369216368' style='width:246;height:246' class='attach' width="246" height="246" alt="Attached Image: rotation8.png" /></a><br />
 <br />
Any rotation about an axis by θ can be undone by a successive rotation by –θ, thus:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15109-0-19277200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15109" title="rotation9.png - Size: 820bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-73497900-1366371659.png" id='ipb-attach-img-15109-0-19277200-1369216368' style='width:129;height:31' class='attach' width="129" height="31" alt="Attached Image: rotation9.png" /></a><br />
 <br />
Also, notice that the cosine terms are always on the top left to bottom right diagonal, and notice the symmetry of the sine terms along this axis. This means, we can also say:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15110-0-19300400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15110" title="rotation10.png - Size: 843bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-89675700-1366371659.png" id='ipb-attach-img-15110-0-19300400-1369216368' style='width:129;height:31' class='attach' width="129" height="31" alt="Attached Image: rotation10.png" /></a><br />
 <br />
Rotation matrices that act upon the origin are orthogonal.<br />
<br />
One important point to consider is the order of rotations (and transformations in general). A rotation along the x axis followed by a rotation along the y axis is <i>not</i> the same as if it were applied in reverse. Similarly, a translation followed by a rotation does <i>not</i> produce the same result as a rotation followed by a translation.<br />
<br />
<strong>Frames</strong><br />
<br />
A frame can be considered a local coordinate system, or <i>frame of reference</i>. That is, a set of three <i>basis vectors</i> (unit vectors perpendicular to each other), plus a position, relative to some other frame. So, given the basis vectors and position:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15111-0-19325400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15111" title="frames.png - Size: 2.09K, Downloads: 24"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-51967400-1366372005.png" id='ipb-attach-img-15111-0-19325400-1369216368' style='width:240;height:89' class='attach' width="240" height="89" alt="Attached Image: frames.png" /></a><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
That is <strong>a</strong>, <strong>b</strong>, and <strong>c</strong> defines the basis vectors, with <strong>p</strong> being its position.<br />
<br />
We can push this into a matrix, defining the frame, like so:<br />
 <br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15112-0-19349500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15112" title="frames2.png - Size: 2.66K, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-66712000-1366372005.png" id='ipb-attach-img-15112-0-19349500-1369216368' style='width:314;height:120' class='attach' width="314" height="120" alt="Attached Image: frames2.png" /></a><br />
<br />
This matrix is useful, as it lets us transform points into a second frame – so long as those points exist in the same frame as the second frame. Thus, consider a point in some frame:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15113-0-19374300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15113" title="frames3.png - Size: 889bytes, Downloads: 18"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-81717700-1366372005.png" id='ipb-attach-img-15113-0-19374300-1369216368' style='width:78;height:118' class='attach' width="78" height="118" alt="Attached Image: frames3.png" /></a><br />
&nbsp;&nbsp;<br />
Assuming the frame we defined above is in the same frame as that point, we can transform this point to be in our frame like so:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15114-0-19397900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15114" title="frames4.png - Size: 467bytes, Downloads: 20"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-96757000-1366372005.png" id='ipb-attach-img-15114-0-19397900-1369216368' style='width:78;height:28' class='attach' width="78" height="28" alt="Attached Image: frames4.png" /></a><br />
 <br />
That is:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15115-0-19421500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15115" title="frames5.png - Size: 2.21K, Downloads: 19"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-17281100-1366372006.png" id='ipb-attach-img-15115-0-19421500-1369216368' style='width:255;height:116' class='attach' width="255" height="116" alt="Attached Image: frames5.png" /></a><br />
 <br />
Which if you think about it is what you would expect. If you have a point at -1 along the x axis, and you transform it into a frame that is at +1 along the x axis and orientated the same, then <i>relative to that second frame</i> the point appears at -2 along <i>its</i> x axis. <br />
<br />
This is useful for transforming vertices between different frames, and is incredibly useful for having objects moving relative to one frame, while that frame itself is moving relative to another one. You can simply multiply a vertex first by its parent frame, then by its parents frame, and so forth to eventually get its position in <i>world space</i>, or the global frame.<br />
<br />
You can also use the standard transformation matrices previously to transform frames with ease. For instance, we can transform the above frame to rotate by 90º along the y axis like so:<br />
<br />
<a class='resized_img' rel='lightbox[0b27790ee5a9cc89b927d5b1228012ea]' id='ipb-attach-url-15116-0-19447600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=15116" title="frames6.png - Size: 2.83K, Downloads: 16"><img src="http://uploads.gamedev.net/monthly_04_2013/ccs-209764-0-37693700-1366372006.png" id='ipb-attach-img-15116-0-19447600-1369216368' style='width:427;height:116' class='attach' width="427" height="116" alt="Attached Image: frames6.png" /></a><br />
 <br />
This is exactly what you would expect (the z axis to move to where the x axis was, and the x axis point in the opposite direction to the original z axis).<br />
<br />
<h1>Summary</h1><br />
Well that’s it for this article. We’ve gone through what vectors are, the operations that we can perform on them and why we find them useful. We then moved onto matrices, how they help us solve sets of equations, including how to use determinants. We then moved on to how to use matrices to help us perform transformations in space, and how we can represent that space as a matrix.<br />
<br />
I hope you’ve found this article useful!<br />
<br />
<h2>References</h2><br />
<i>Interactive Computer Graphics – A Top Down Approach with OpenGL</i> – Edward Angel<br />
<br />
<i>Mathematics for Computer Graphics Applications – Second Edition</i> – M.E Mortenson<br />
<br />
<i>Advanced National Certificate Mathematics Vol.: 2</i> – Pedoe]]></description>
		<pubDate>Fri, 19 Apr 2013 10:14:30 +0000</pubDate>
		<guid isPermaLink="false">709f5f3e2479cb21f8f3976dbb3ebd53</guid>
	</item>
	<item>
		<title><![CDATA[Intersection Math & Algorithms - Learn to Derive]]></title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/intersection-math-algorithms-learn-to-derive-r3033</link>
		<description><![CDATA[One of the most important group of algorithms inside game engines are intersection algorithms. Even though there are plenty of sites showing code for intersection algorithms, there are only a few describing the math backround behind this, and algorithm derivation. To understand this article you need to know just a bit about linear algebra.<br /><br /><h1>Primitive description</h1><br />Let's start with a mathematical description of primitives we're going to intersect. For this article I've used just ray (line), plane, sphere, axis-aligned bounding box and triangle ... these should be enough for a basic game engine.<br />&nbsp;&nbsp;&nbsp;&nbsp;<br /><h2>Ray</h2><br />This is the simplest (and very useful) primitive you can think about. Let us define it with two 4-component numbers, point (further referred as origin) and direction. Mathematically the definition is:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cboldsymbol%7Bx%7D=%5Cboldsymbol%7Bo%7D+t%5Ccdot%5Cboldsymbol%7Bd%7D" alt="eq.latex?%20%5Cboldsymbol%7Bx%7D=%5Cbold"></span><br /><br />Where:<br /><ul class='bbc'><li><strong>x</strong> represents any point on a line</li><li><strong>o</strong> represents some exact specified point on line (e.g. origin)</li><li><strong>d</strong> represents direction vector of line</li><li>t is parameter within some specified range</li></ul>The range specifies whether our line is infinite in both directions (+d and -d), whether it's just in a single direction, or whether it's finite.<br /><br />Writing a ray object in some programming language is straight-forward of course, you should end up with something like this:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
class Ray
{
public:
&nbsp;&nbsp;&nbsp;&nbsp;float4 origin;
&nbsp;&nbsp;&nbsp;&nbsp;float4 direction;
	
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;constructor&gt;&gt;
	
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;methods&gt;&gt;
};
</pre><br />Constructor and methods are straight-forward (and should be also inline for performance reasons).<br /><br /><h2>Plane</h2><br />Another basic primitive. There are more ways to define a plane, but we will derive one that is well known and used. What is a plane? It's a point set that contains every such point in space, that when we create vector from that point to our known point on a plane, that vector has to be perpendicular to plane normal. And we know that perpendicular vectors are those whose dot product is equal to zero. So:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cvec%7B%5Cboldsymbol%7Bn%7D%7D%5Ccdot(%5Cboldsymbol%7Bx%7D-%5Cboldsymbol%7Bp%7D)=0" alt="eq.latex?%20%5Cvec%7B%5Cboldsymbol%7Bn%7"></span><br /><br />Where:<br /><ul class='bbc'><li><strong>n</strong> is unit vector in the plane normal direction</li><li><strong>x</strong> is every point on the plane</li><li><strong>p</strong> is our specified point on the plane</li></ul>Expanding this yields:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7Bx%7D%5Ccdot(x-p_%7Bx%7D)+n_%7By%7D%5Ccdot(y-p_%7By%7D)+n_%7Bz%7D%5Ccdot(z-p_%7Bz%7D)=0" alt="eq.latex?%20n_%7Bx%7D%5Ccdot(x-p_%7Bx%7D"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7Bx%7D%5Ccdot%20x%20+%20n_%7Bz%7D%5Ccdot%20z%20+%20n_%7Bz%7D%5Ccdot%20z%20-%20(n_%7Bx%7D%5Ccdot%20p_%7Bx%7D%20+%20n_%7By%7D%5Ccdot%20p_%7By%7D%20+%20n_%7Bz%7D%5Ccdot%20p_%7Bz%7D)=0" alt="eq.latex?%20n_%7Bx%7D%5Ccdot%20x%20+%20n"></span><br /><br />Substitute:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20-(n_%7Bx%7D%5Ccdot%20p_%7Bx%7D%20+%20n_%7By%7D%5Ccdot%20p_%7By%7D%20+%20n_%7Bz%7D%5Ccdot%20p_%7Bz%7D)=-%5Cvec%7B%5Cbold%7Bn%7D%7D%5Ccdot%5Cbold%7Bp%7D=d" alt="eq.latex?%20-(n_%7Bx%7D%5Ccdot%20p_%7Bx%"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7Bx%7D=a" alt="eq.latex?%20n_%7Bx%7D=a"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7By%7D=b" alt="eq.latex?%20n_%7By%7D=b"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7Bz%7D=c" alt="eq.latex?%20n_%7Bz%7D=c"></span><br /><br />And we get something very familiar:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20a%20%5Ccdot%20x%20+%20b%20%5Ccdot%20y%20+%20c%20%5Ccdot%20z%20+%20d%20=%200" alt="eq.latex?%20a%20%5Ccdot%20x%20+%20b%20%5"></span><br /><br />Which is a plane equation (so we proved that the definition we use is actually a plane). Definition in programming language could be like this:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
class Plane
{
public:
&nbsp;&nbsp;&nbsp;&nbsp;float4 point;
&nbsp;&nbsp;&nbsp;&nbsp;float4 normal;

&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;constructor&gt;&gt;
	
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;methods&gt;&gt;
};
</pre><br />A very simple definition. Let's jump ahead.<br /><br /><h2>Sphere</h2><br />Yet another basic primitive, that is widely used. The definition is surface containing all points in distance from sphere's center less-or-equal to sphere's radius. We will define it using an analytic equation:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20(x%20-%20p_%7Bx%7D)%5E2%20+%20(y%20-%20p_%7By%7D)%5E2%20+%20(z%20-%20p_%7Bz%7D)%5E2%20=%20r%5E2" alt="eq.latex?%20(x%20-%20p_%7Bx%7D)%5E2%20+%"></span><br /><br />Where:<br /><ul class='bbc'><li>x, y and z are coordinates of point in sphere</li><li>p represents sphere's center</li><li>r represents sphere's radius</li></ul>A sphere class is again very trivial:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
class Sphere
{
public:
&nbsp;&nbsp;&nbsp;&nbsp;float4 center;
&nbsp;&nbsp;&nbsp;&nbsp;float radius;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;constructor&gt;&gt;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;methods&gt;&gt;
};
</pre><br />So much for sphere; simple, yet very useful primitive.<br /><br /><h2>Axis-aligned Box</h2><br />From here on I'll call this one just AABB (which stands for Axis-Aligned Bounding Box). Definition is very simple, as we work in Cartesian coordinate system, we have perpendicular axes X, Y and Z - AABB is defined as volume between minimum and maximum point in this system, the sides are made by planes orthogonal to planes formed by all 3 combinations of 2 base axis (XY, XZ and YZ). Mathematically we can define it as:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bmin_%7Bp%7D%7D%20%5Cleq%20%5Cbold%7Bx%7D%20%5Cleq%20%5Cbold%7Bmax_%7Bp%7D%7D" alt="eq.latex?%20%5Cbold%7Bmin_%7Bp%7D%7D%20%"></span><br /><br />Where:<br /><ul class='bbc'><li>min_p stands for AABB minimum point</li><li>max_p stands for AABB maximum point</li><li><strong>x</strong> represents points inside AABB</li></ul>In programming language it can look like:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
class AABB
{
public:
&nbsp;&nbsp;&nbsp;&nbsp;float4 min_p;
&nbsp;&nbsp;&nbsp;&nbsp;float4 max_p;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;constructor&gt;&gt;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;methods&gt;&gt;
};
</pre><br />Let's jump ahead to last object we're going to use.<br /><br /><h2>Triangle</h2><br />The first and only primitive in this article that is going to be defined by more than 2 values, yet very important. Most of the game worlds are described by triangles, most of the simulation use objects described as triangles, and every more (or less) complex 3D object can be decomposed into triangles. They're awesome; as opposed to other boring N-gons, triangles are never concave!<br /><br />Let's define triangle with 3 points, then any point on triangle can be described as:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold%7BA%7D%5Ccdot%20%5Calpha%20+%20%5Cbold%7BB%7D%5Ccdot%20%5Cbeta%20+%20%5Cbold%7BC%7D%5Ccdot%20%5Cgamma" alt="eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold"></span><br /><br />With conditions:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Calpha+%5Cbeta+%5Cgamma=1,%5Calpha%5Cgeq0,%5Cbeta%5Cgeq0,%5Cgamma%5Cgeq0" alt="eq.latex?%20%5Calpha+%5Cbeta+%5Cgamma=1,"></span><br /><br />Where:<br /><ul class='bbc'><li><strong>x</strong> is every point in triangle</li><li><strong>A</strong>, <strong>B</strong>, <strong>C</strong> are points defining triangle</li><li>a, ß, ? are so called barycentric coordinates (e.g. parameters in the equation above)</li></ul>A triangle inside of a program could be defined as:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
class Triangle
{
public:
&nbsp;&nbsp;&nbsp;&nbsp;float4 p[3];
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;constructor&gt;&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;&lt;methods&gt;&gt;
};
</pre><br /><h1>Intersections</h1><br />So now that we have defined some of the basic primitives, it's time to derive intersection equation and also intersection algorithms between the primitives. As I want to keep the article short (and I don't want to storm you with zillion of equations and exhausting equation solving), I will just show you 4 derivations - Ray-Plane (analytic derivation), Ray-Sphere (geometric derivation), Ray-AABB (tricky derivation) and Ray-Triangle (more complex analytic derivation). You should get an idea of how the intersection equation can be derived and in the end you should be able to derive the rest of them on your own.<br /><br /><h2>Ray-Plane intersection</h2><br />I will derive Ray-Plane intersection analytically, as this is one of the most simple approaches to the derivation. When we want to derive some intersection algorithm analytically, we should write equations of those 2 objects right away, so (I intentionally used commonly known plane equation, instead of our definition):<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cboldsymbol%7Bx%7D=%5Cboldsymbol%7Bo%7D+t%5Ccdot%5Cboldsymbol%7Bd%7D" alt="eq.latex?%20%5Cboldsymbol%7Bx%7D=%5Cbold"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20a%20%5Ccdot%20x%20+%20b%20%5Ccdot%20y%20+%20c%20%5Ccdot%20z%20+%20d%20=%200" alt="eq.latex?%20a%20%5Ccdot%20x%20+%20b%20%5"></span><br /><br />Now we're looking for a point that lies on both, the ray and the plane - so we're looking for <strong>x</strong>. So we first write the first equation in scalar form:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20x=o_%7Bx%7D+t%5Ccdot%20d_%7Bx%7D" alt="eq.latex?%20x=o_%7Bx%7D+t%5Ccdot%20d_%7B"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20y=o_%7By%7D+t%5Ccdot%20d_%7By%7D" alt="eq.latex?%20y=o_%7By%7D+t%5Ccdot%20d_%7B"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20z=o_%7Bz%7D+t%5Ccdot%20d_%7Bz%7D" alt="eq.latex?%20z=o_%7Bz%7D+t%5Ccdot%20d_%7B"></span><br /><br />Let's substitute these 3 to plane equation:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20a%20%5Ccdot%20(o_%7Bx%7D+t%5Ccdot%20d_%7Bx%7D)%20+%20b%20%5Ccdot%20(o_%7By%7D+t%5Ccdot%20d_%7By%7D)%20+%20c%20%5Ccdot%20(o_%7Bz%7D+t%5Ccdot%20d_%7Bz%7D)%20+%20d%20=%200" alt="eq.latex?%20a%20%5Ccdot%20(o_%7Bx%7D+t%5"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20a%20%5Ccdot%20o_%7Bx%7D+%20a%20%5Ccdot%20t%20%5Ccdot%20d_%7Bx%7D%20+%20b%20%5Ccdot%20o_%7By%7D%20+%20b%20%5Ccdot%20t%20%5Ccdot%20d_%7By%7D%20+%20c%20%5Ccdot%20o_%7Bz%7D%20+%20c%20%5Ccdot%20t%20%5Ccdot%20d_%7Bz%7D%20+%20d%20=%200" alt="eq.latex?%20a%20%5Ccdot%20o_%7Bx%7D+%20a"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20a%20%5Ccdot%20t%20%5Ccdot%20d_%7Bx%7D%20+%20b%20%5Ccdot%20t%20%5Ccdot%20d_%7By%7D%20+%20c%20%5Ccdot%20t%20%5Ccdot%20d_%7Bz%7D%20=%20-(a%20%5Ccdot%20o_%7Bx%7D%20+%20b%20%5Ccdot%20o_%7By%7D%20+%20c%20%5Ccdot%20o_%7Bz%7D%20+%20d)" alt="eq.latex?%20a%20%5Ccdot%20t%20%5Ccdot%20"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t%20%5Ccdot%20(a%20%5Ccdot%20d_%7Bx%7D%20+%20b%20%5Ccdot%20d_%7By%7D%20+%20c%20%5Ccdot%20d_%7Bz%7D)%20=%20-(a%20%5Ccdot%20o_%7Bx%7D%20+%20b%20%5Ccdot%20o_%7By%7D%20+%20c%20%5Ccdot%20o_%7Bz%7D%20+%20d)" alt="eq.latex?%20t%20%5Ccdot%20(a%20%5Ccdot%2"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t%20=%20-%7Ba%20%5Ccdot%20o_%7Bx%7D%20+%20b%20%5Ccdot%20o_%7By%7D%20+%20c%20%5Ccdot%20o_%7Bz%7D%20+%20d%20%5Cover%20%7Ba%20%5Ccdot%20d_%7Bx%7D%20+%20b%20%5Ccdot%20d_%7By%7D%20+%20c%20%5Ccdot%20d_%7Bz%7D%7D%7D" alt="eq.latex?%20t%20=%20-%7Ba%20%5Ccdot%20o_"></span><br /><br />It's time to reverse substitution we did when "deriving" plane equation, e.g.:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20-(n_%7Bx%7D%5Ccdot%20p_%7Bx%7D%20+%20n_%7By%7D%5Ccdot%20p_%7By%7D%20+%20n_%7Bz%7D%5Ccdot%20p_%7Bz%7D)=-%5Cvec%7B%5Cbold%7Bn%7D%7D%5Ccdot%5Cbold%7Bp%7D=d" alt="eq.latex?%20-(n_%7Bx%7D%5Ccdot%20p_%7Bx%"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7Bx%7D=a" alt="eq.latex?%20n_%7Bx%7D=a"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7By%7D=b" alt="eq.latex?%20n_%7By%7D=b"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20n_%7Bz%7D=c" alt="eq.latex?%20n_%7Bz%7D=c"></span><br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t%20=%20-%7B%7Bn_%7Bx%7D%20%5Ccdot%20o_%7Bx%7D%20+%20n_%7By%7D%20%5Ccdot%20o_%7By%7D%20+%20n_%7Bz%7D%20%5Ccdot%20o_%7Bz%7D%20-%20(n_%7Bx%7D%5Ccdot%20p_%7Bx%7D%20+%20n_%7By%7D%5Ccdot%20p_%7By%7D%20+%20n_%7Bz%7D%5Ccdot%20p_%7Bz%7D)%7D%20%5Cover%20%7Bn_%7Bx%7D%20%5Ccdot%20d_%7Bx%7D%20+%20n_%7By%7D%20%5Ccdot%20d_%7By%7D%20+%20n_%7Bz%7D%20%5Ccdot%20d_%7Bz%7D%7D%7D" alt="eq.latex?%20t%20=%20-%7B%7Bn_%7Bx%7D%20%"></span><br /><br />And transformed to vector form we get:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t%20=%20%7B-%7B%7B%5Cvec%7B%5Cbold%7Bn%7D%7D%5Ccdot%5Cbold%7Bo%7D-%5Cvec%7B%5Cbold%7Bn%7D%7D%5Ccdot%5Cbold%7Bp%7D%7D%5Cover%7B%5Cvec%7B%5Cbold%7Bn%7D%7D%5Ccdot%5Cvec%7B%5Cbold%7Bd%7D%7D%7D%7D%7D" alt="eq.latex?%20t%20=%20%7B-%7B%7B%5Cvec%7B%"></span><br /><br />But we can optimize this a little bit:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t%20=%20%7B-%7B%7B%5Cvec%7B%5Cbold%7Bn%7D%7D%5Ccdot(%5Cbold%7Bo%7D-%5Cbold%7Bp%7D)%7D%5Cover%7B%5Cvec%7B%5Cbold%7Bn%7D%7D%5Ccdot%5Cvec%7B%5Cbold%7Bd%7D%7D%7D%7D%7D" alt="eq.latex?%20t%20=%20%7B-%7B%7B%5Cvec%7B%"></span><br /><br />Voila, that's what we have been looking for! So basically we need just subtraction, 2 dot products and 1 division. In program this can look like (assuming we want to intersect planes in front of ray origin in direction of ray):<br /><br /><pre class='prettyprint lang-auto linenums:0'>
bool IntrRayPlane(const Ray* r, const Plane* p, float* t)
{
&nbsp;&nbsp;&nbsp;&nbsp;float denom = dot(p-&gt;normal, r-&gt;direction);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;// Test whether ray and plane aren't parallel
&nbsp;&nbsp;&nbsp;&nbsp;if(fabsf(dotND) &lt; EPSILON)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;*t = -(dot(p-&gt;normal, r-&gt;origin - p-&gt;point) / denom);
&nbsp;&nbsp;&nbsp;&nbsp;return ((*t) &gt; 0.0f);
}
</pre><br />Almost as simple as the equation. Let's jump ahead, time for spheres!<br /><br /><h2>Ray-Sphere intersection</h2><br />I could perform analytic derivation like in the Ray-Plane intersection derivation, although Ray-Sphere intersection is just one of the cases that can be easily derived using geometry. Let's start with an image:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://uploads.gamedev5.net/gallery/album_282/gallery_102163_282_11168.jpg" alt="gallery_102163_282_11168.jpg"></span><br /><br />We're now looking for 2 distances:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t_%7B0%7D%20=%20%7C%5Cbold%7BO%7D%20-%20%5Cbold%7BP%7D%7C" alt="eq.latex?%20t_%7B0%7D%20=%20%7C%5Cbold%7"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t_%7B1%7D%20=%20%7C%5Cbold%7BO%7D%20-%20%5Cbold%7BP'%7D%7C" alt="eq.latex?%20t_%7B1%7D%20=%20%7C%5Cbold%7"></span><br /><br />Finding <strong>C</strong>-<strong>O</strong> is quite straightforward, it's just simple:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7BL%7D=%5Cbold%7Bp%7D-%5Cbold%7Bo%7D" alt="eq.latex?%20%5Cbold%7BL%7D=%5Cbold%7Bp%7"></span><br /><br />Another thing we need to find is distance along the ray to point X, but as we know ray direction, it's just simple projection of <strong>L</strong>.<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t_x%20=%20%5Cbold%7BL%7D%5Ccdot%7B%5Cvec%7B%5Cbold%7Bd%7D%7D%7D" alt="eq.latex?%20t_x%20=%20%5Cbold%7BL%7D%5Cc"></span><br /><br />Right now we should look again at the image, we can see 3 important right angle triangle, one formed by {d, OX and OC}, another one {d, r, PX} and last one {d, r, P'X}. We need to know distance PX (respectively P'X, they're equal). So let's use Pythagorean theorem twice:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20d%5E2%20=%20%5Cbold%7BL%7D%5Ccdot%7B%5Cbold%7BL%7D%7D+t_%7Bx%7D%5E2" alt="eq.latex?%20d%5E2%20=%20%5Cbold%7BL%7D%5"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t_%7BPX%7D=%5Csqrt%7Br%5E2-d%5E2%7D" alt="eq.latex?%20t_%7BPX%7D=%5Csqrt%7Br%5E2-d"></span><br /><br />And our 2 hit distances are:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t_%7B0%7D%20=%20t_%7Bx%7D%20-%20t_%7BPX%7D" alt="eq.latex?%20t_%7B0%7D%20=%20t_%7Bx%7D%20"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20t_%7B1%7D%20=%20t_%7Bx%7D%20+%20t_%7BPX%7D" alt="eq.latex?%20t_%7B1%7D%20=%20t_%7Bx%7D%20"></span><br /><br />Time for the code (searching just nearest hit):<br /><br /><pre class='prettyprint lang-auto linenums:0'>
bool IntrRaySphere(const Ray* r, const Sphere* s, float* t)
{
&nbsp;&nbsp;&nbsp;&nbsp;float rad2 = s-&gt;radius * s-&gt;radius;
&nbsp;&nbsp;&nbsp;&nbsp;float4 L = s-&gt;center - r-&gt;origin;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float tPX = dot(L, r-&gt;direction);
&nbsp;&nbsp;&nbsp;&nbsp;if(tPX &lt; 0.0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float dsq = dot(L, L) - tPX * tPX;
&nbsp;&nbsp;&nbsp;&nbsp;if(dsq &gt; rad2)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float thit = sqrt(rad2 - dsq);
&nbsp;&nbsp;&nbsp;&nbsp;*t = tPX - thit;
&nbsp;&nbsp;&nbsp;&nbsp;if(*t &lt; 0.0f)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*t = tPX + thit;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;return ((*t) &lt; 0.0f);
}&nbsp;&nbsp;&nbsp;&nbsp;
</pre><br />Just a side note. Analytic derivation in this case is also very trivial, you will end up with quadratic equation, where determinant is negative in case of no hit, zero in case of single point hit (e.g. tangent line), and positive in case of secant.<br /><br />Let's jump ahead to boxes!<br /><br /><h2>Ray-AABB intersection</h2><br />Another important one, although a bit tricky. Let's start with an image again:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://uploads.gamedev5.net/gallery/album_282/gallery_102163_282_5470.png" alt="gallery_102163_282_5470.png"></span><br /><br />You can see, that box in 2D is formed by 2 slabs, horizontal and vertical. 3D is analogous to this, but of course it's formed by 3 slabs. For each slab we want to find minimum distance and maximum distance, e.g.:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bt_%7Bmin%7D%7D%20=%20%7B%7B%28%5Cbold%7Ba%7D%20-%20%5Cbold%7Bo%7D%29%7D%20%5Cover%20%7B%5Cvec%7B%5Cbold%7Bd%7D%7D%7D%7D" alt="eq.latex?%20%5Cbold%7Bt_%7Bmin%7D%7D%20="></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bt_%7Bmin%7D%7D%20=%20%7B%7B%28%5Cbold%7Bb%7D%20-%20%5Cbold%7Bo%7D%29%7D%20%5Cover%20%7B%5Cvec%7B%5Cbold%7Bd%7D%7D%7D%7D" alt="eq.latex?%20%5Cbold%7Bt_%7Bmin%7D%7D%20="></span><br /><br />Where <strong>a</strong> and <strong>b</strong> represents minimum (respectively maximum) point of our AABB. What we get is the minimum and maximum distance to each slab. Now we have to correctly order the distances along the ray direction, this is quite simple:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bt_%7Bnear%7D%7D%20=%20min%28%5Cbold%7Bt_%7Bmin%7D%7D,%20%5Cbold%7Bt_%7Bmax%7D%7D%29" alt="eq.latex?%20%5Cbold%7Bt_%7Bnear%7D%7D%20"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bt_%7Bfar%7D%7D%20=%20max%28%5Cbold%7Bt_%7Bmin%7D%7D,%20%5Cbold%7Bt_%7Bmax%7D%7D%29" alt="eq.latex?%20%5Cbold%7Bt_%7Bfar%7D%7D%20="></span><br /><br />Where min/max is defined as:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20min%28%5Cbold%7Ba%7D,%20%5Cbold%7Bb%7D%29%20=%20%5Clbrace%20min%28a_%7Bx%7D,%20b_%7Bx%7D%29,%20min%28a_%7By%7D,%20b_%7By%7D%29,%20...%20,%20min%28a_%7Bn%7D,%20b_%7Bn%7D%29%20%5Crbrace" alt="eq.latex?%20min%28%5Cbold%7Ba%7D,%20%5Cb"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20max%28%5Cbold%7Ba%7D,%20%5Cbold%7Bb%7D%29%20=%20%5Clbrace%20max%28a_%7Bx%7D,%20b_%7Bx%7D%29,%20max%28a_%7By%7D,%20b_%7By%7D%29,%20...%20,%20max%28a_%7Bn%7D,%20b_%7Bn%7D%29%20%5Crbrace" alt="eq.latex?%20max%28%5Cbold%7Ba%7D,%20%5Cb"></span><br /><br />Entry/exit point is then defined as maximum of near distances (see the image), thus:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20enter%20=%20hmax%28%5Cbold%7Bt_%7Bmin%7D%7D%29" alt="eq.latex?%20enter%20=%20hmax%28%5Cbold%7"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20enter%20=%20hmin%28%5Cbold%7Bt_%7Bmax%7D%7D%29" alt="eq.latex?%20enter%20=%20hmin%28%5Cbold%7"></span><br /><br />Where hmax/hmin function is horizontal minimum/maximum, defined as:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20hmin%28%5Cbold%7Ba%7D%29%20=%20min%28a_%7Bx%7D,%20a_%7By%7D,%20...%20,%20a_%7Bn%7D%29" alt="eq.latex?%20hmin%28%5Cbold%7Ba%7D%29%20="></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20hmax%28%5Cbold%7Ba%7D%29%20=%20max%28a_%7Bx%7D,%20a_%7By%7D,%20...%20,%20a_%7Bn%7D%29" alt="eq.latex?%20hmax%28%5Cbold%7Ba%7D%29%20="></span><br /><br />Of course a hit only occurs when the exit point is larger than zero, and the exit point is further than the entry point (if it isn't, we missed the AABB). Time to code:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
bool IntrRayAABB(const Ray* r, const AABB* b, float* enter, float* exit)
{
&nbsp;&nbsp;&nbsp;&nbsp;float4 tmin = (b-&gt;minimum - r-&gt;origin) / r-&gt;direction;
&nbsp;&nbsp;&nbsp;&nbsp;float4 tmax = (b-&gt;maximum - r-&gt;origin) / r-&gt;direction;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float4 tnear = f4min(tmin, tmax);
&nbsp;&nbsp;&nbsp;&nbsp;float4 tfar = f4min(tmin, tmax);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;*enter = max(max(tnear.x, 0.0f), max(tnear.y, tnear.z));
&nbsp;&nbsp;&nbsp;&nbsp;*exit = min(tfar.x, min(tfar.y, tfar.z));
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;return (*exit &gt; 0.0f &amp;&amp; *enter &lt; *exit);
}
</pre><br />It can be a little more optimized, although I'll leave that to reader as an exercise.<br /><br /><h2>Ray-Triangle intersection</h2><br />I'd like to say, there is like a dozen of ways to intersect a ray with a triangle. Lots of them don't even use a triangle defined by 3 points, and re-define it in better suited way. I'll show you how to derive plain good old Barycentric test with one huge advantage, you don't have to precompute a triangle in any way, just use the standard definition with 3 points.<br /><br />Let's start with equations we already have:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cboldsymbol%7Bx%7D=%5Cboldsymbol%7Bo%7D+t%5Ccdot%5Cboldsymbol%7Bd%7D" alt="eq.latex?%20%5Cboldsymbol%7Bx%7D=%5Cbold"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold%7BA%7D%5Ccdot%20%5Calpha%20+%20%5Cbold%7BB%7D%5Ccdot%20%5Cbeta%20+%20%5Cbold%7BC%7D%5Ccdot%20%5Cgamma" alt="eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold"></span><br /><br />The triangle equation actually is equal to this:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold%7BA%7D%20%5Ccdot%20%281%20-%20%5Cbeta%20-%20%5Cgamma%29%20+%20%5Cbold%7BB%7D%20%5Ccdot%20%5Cbeta%20+%20%5Cbold%7BC%7D%20%5Ccdot%20%5Cgamma" alt="eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold"></span><br /><br />And let's arrange it like this:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold%7BA%7D%20+%20%28%5Cbold%7BB%7D%20-%20%5Cbold%7BA%7D%29%20%5Ccdot%20%5Cbeta%20+%20%28%5Cbold%7BC%7D%20-%20%5Cbold%7BA%7D%29%20%5Ccdot%20%5Cgamma" alt="eq.latex?%20%5Cbold%7Bx%7D%20=%20%5Cbold"></span><br /><br />Substituting line equation for <strong>x</strong> yields:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbold%7Bo%7D%20+%20t%20%5Ccdot%20%5Cvec%7B%5Cbold%7Bd%7D%7D%20=%20%5Cbold%7BA%7D%20+%20%28%5Cbold%7BB%7D%20-%20%5Cbold%7BA%7D%29%20%5Ccdot%20%5Cbeta%20+%20%28%5Cbold%7BC%7D%20-%20%5Cbold%7BA%7D%29%20%5Ccdot%20%5Cgamma" alt="eq.latex?%20%5Cbold%7Bo%7D%20+%20t%20%5C"></span><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20-t%20%5Ccdot%20%5Cvec%7B%5Cbold%7Bd%7D%7D%20+%20%5Cbeta%20%5Ccdot%20%28%5Cbold%7BB%7D%20-%20%5Cbold%7BA%7D%29%20+%20%5Cgamma%20%5Ccdot%20%28%5Cbold%7BC%7D%20-%20%5Cbold%7BA%7D%29%20=%20%5Cbold%7Bo%7D%20-%20%5Cbold%7BA%7D" alt="eq.latex?%20-t%20%5Ccdot%20%5Cvec%7B%5Cb"></span><br /><br />Those are 3 equations with 3 unknown variables. Instead of thinking about some more clever way, let's solve it in brute force manner with Cramer's rule. First let's re-arrange it to better form:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbegin%7Bpmatrix%7D-%7B%5Cvec%7B%5Cbold%7Bd%7D%7D&%28%5Cbold%7BB%7D-%5Cbold%7BA%7D%29&%28%5Cbold%7BC%7D-%5Cbold%7BA%7D%29%5Cend%7Bpmatrix%7D%20%5Cbegin%7Bpmatrix%7Dt%5C%5C%5Cbeta%5C%5C%5Cgamma%5Cend%7Bpmatrix%7D=%5Cbold%7Bo%7D-%5Cbold%7BA%7D" alt="eq.latex?%20%5Cbegin%7Bpmatrix%7D-%7B%5C"></span><br /><br />For clarity let's substitute e1 for B-A, e2 for C-A and p for o-A.<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbegin%7Bpmatrix%7D-%7B%5Cvec%7B%5Cbold%7Bd%7D%7D&%5Cvec%7B%5Cbold%7Be1%7D%7D&%5Cvec%7B%5Cbold%7Be2%7D%7D%5Cend%7Bpmatrix%7D%20%5Cbegin%7Bpmatrix%7Dt%5C%5C%5Cbeta%5C%5C%5Cgamma%5Cend%7Bpmatrix%7D=%5Cvec%7B%5Cbold%7Bp%7D%7D" alt="eq.latex?%20%5Cbegin%7Bpmatrix%7D-%7B%5C"></span><br /><br />Now it's time to apply Cramer's rule, e.g.:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbegin%7Bpmatrix%7Dt%5C%5C%5Cbeta%5C%5C%5Cgamma%5Cend%7Bpmatrix%7D=%7B1%5Cover%7B%5Cbegin%7Bvmatrix%7D-%7B%5Cvec%7B%5Cbold%7Bd%7D%7D&%5Cvec%7B%5Cbold%7Be1%7D%7D&%5Cvec%7B%5Cbold%7Be2%7D%7D%5Cend%7Bvmatrix%7D%7D%7D%5Ccdot%5Cbegin%7Bpmatrix%7D%5Cbegin%7Bvmatrix%7D%5Cvec%7B%5Cbold%7Bp%7D%7D&%5Cvec%7B%5Cbold%7Be1%7D%7D&%5Cvec%7B%5Cbold%7Be2%7D%7D%5Cend%7Bvmatrix%7D%5C%5C%5Cbegin%7Bvmatrix%7D-%7B%5Cvec%7B%5Cbold%7Bd%7D%7D%7D&%5Cvec%7B%5Cbold%7Bp%7D%7D&%5Cvec%7B%5Cbold%7Be2%7D%7D%5Cend%7Bvmatrix%7D%5C%5C%5Cbegin%7Bvmatrix%7D-%7B%5Cvec%7B%5Cbold%7Bd%7D%7D%7D&%5Cvec%7B%5Cbold%7Be1%7D%7D&%5Cvec%7B%5Cbold%7Bp%7D%7D%5Cend%7Bvmatrix%7D%5Cend%7Bpmatrix%7D" alt="eq.latex?%20%5Cbegin%7Bpmatrix%7Dt%5C%5C"></span><br /><br />But matrix determinant can be written as scalar triple product, so:<br /><br /><span rel='lightbox'><img class='bbc_img' src="http://www.codecogs.com/eq.latex?%20%5Cbegin%7Bpmatrix%7Dt%5C%5C%5Cbeta%5C%5C%5Cgamma%5Cend%7Bpmatrix%7D=%7B1%5Cover%7B%28%5Cvec%7B%5Cbold%7Bd%7D%7D%5Ctimes%5Cvec%7B%5Cbold%7Be2%7D%7D%29%5Ccdot%5Cvec%7B%5Cbold%7Be1%7D%7D%7D%7D%5Ccdot%5Cbegin%7Bpmatrix%7D%28%5Cvec%7B%5Cbold%7Bp%7D%7D%5Ctimes%5Cvec%7B%5Cbold%7Be1%7D%7D%29%5Ccdot%5Cvec%7B%5Cbold%7Be2%7D%7D%5C%5C%28%5Cvec%7B%5Cbold%7Bd%7D%7D%5Ctimes%5Cvec%7B%5Cbold%7Be2%7D%7D%29%5Ccdot%5Cvec%7B%5Cbold%7Bp%7D%7D%5C%5C%28%5Cvec%7B%5Cbold%7Bp%7D%7D%5Ctimes%5Cvec%7B%5Cbold%7Be1%7D%7D%29%5Ccdot%5Cvec%7B%5Cbold%7Bd%7D%7D%5Cend%7Bpmatrix%7D" alt="eq.latex?%20%5Cbegin%7Bpmatrix%7Dt%5C%5C"></span><br /><br />I know this might look scary right now, but it really is simple. For those that understand code easier than math I also add code:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
bool IntrRayTriangle( const Ray* r, const Triangle* t, float* thit, float* u, float* v)
{
&nbsp;&nbsp;&nbsp;&nbsp;float4 e1 = t-&gt;v[1] - t-&gt;v[0];
&nbsp;&nbsp;&nbsp;&nbsp;float4 e2 = t-&gt;v[2] - t-&gt;v[0];
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float4 pvec = cross(r-&gt;direction, e2);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float det = dot(e1, pvec);
&nbsp;&nbsp;&nbsp;&nbsp;if(det &gt; -EPSILON &amp;&amp; det &lt; EPSILON)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float inv_det = 1.0f / det;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float4 tvec = r-&gt;origin - t-&gt;v[0];
&nbsp;&nbsp;&nbsp;&nbsp;*u = dot(tvec, pvec) * inv_det;
&nbsp;&nbsp;&nbsp;&nbsp;if(*u &lt; 0.0f || *u &gt; 1.0f)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;float4 qvec = cross(tvec, e1);
&nbsp;&nbsp;&nbsp;&nbsp;*v = dot(r-&gt;direction, qvec) * inv_det;
&nbsp;&nbsp;&nbsp;&nbsp;if(*v &lt; 0.0f || *u + *v &gt; 1.0f)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;*thit = dot(e2, qvec) * inv_det;
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;return (*thit &gt; 0.0f);
}
</pre><br /><h1>Conclusion</h1><br />Intersection algorithms, as I've said, are core algorithms for practically every game engine! And not just game engines, ray-tracers, physics simulators, collision detection libraries, even some AI simulations use them, etc. If you made it here, then I have to say thanks for reading my article, and I hope you've learned something new.<br /><br /><strong class='bbc'>9 Apr 2013</strong>: Initial release]]></description>
		<pubDate>Tue, 09 Apr 2013 14:59:51 +0000</pubDate>
		<guid isPermaLink="false">527490f08486bf8af2b8d0bf6e73911b</guid>
	</item>
	<item>
		<title>Practical use of Vector Math in Games</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/practical-use-of-vector-math-in-games-r2968</link>
		<description><![CDATA[<i>For a beginner, geometry in 3D space may seem a bit daunting. 2D on paper was hard enough, but now, geometry in 3D?</i><br /><br />Good news: use of trigonometry in graphics is rare and avoided for multitude of reasons. We have other tools which are easier to understand and use. You may recognize our old friend here - a vector.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14267-0-22139000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14267" title="file(2).png - Size: 31.71K, Downloads: 271"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-83041100-1363380057_thumb.png" id='ipb-attach-img-14267-0-22139000-1369216368' style='width:480;height:92' class='attach' width="480" height="92" alt="Attached Image: file(2).png" /></a><br /><br />This article will introduce you to 3D vectors and will walk you through several real-world usage examples. Even though it focuses on 3D, most things explained here also work for 2D.<br /><br /><i>Article assumes familiarity with algebra and geometry, some programming language, a basic knowledge of <a href='http://en.wikipedia.org/wiki/Object-oriented_programming' class='bbc_url' title='External link' rel='nofollow external'>OOP</a>.</i><br /><br /><h1>Vector Math in Games</h1><br /><h2>Concepts</h2><br />In mathematics, a vector is a construct that represents both a <strong>direction</strong> as well as a <strong>magnitude</strong>.&nbsp;&nbsp;In game development it often can be used to describe a change in position, and can be added or subtracted to other vectors.&nbsp;&nbsp;You would usually find a vector object as part of some math or physics library.<br /><br />They typically contain one or more components such as x, y and z. Vectors can be 1D (contain only x), 2D (contain x, y), 3D (contain x, y, z), even 4D. 4D vectors can be used to describe something else, for example a color with an extra alpha value.<br /><br />One of the toughest things beginners have difficulty with when it comes to vectors is to understand how something that seemingly looks like a point in space can be used to describe a direction.<br /><br />Take the 2D vector (3,3).&nbsp;&nbsp;To understand how this represents a direction you need only look at the following graph.&nbsp;&nbsp;We all know that it takes two points to form a line.&nbsp;&nbsp;So what is the second point?&nbsp;&nbsp;The missing point is the <strong>origin</strong> located at (0,0).&nbsp;&nbsp;If we draw a line from the origin at (0,0) to (3,3) we get the following:<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14311-0-22332700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14311" title="vector.png - Size: 15.32K, Downloads: 234"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-5-0-31676700-1363537994_thumb.png" id='ipb-attach-img-14311-0-22332700-1369216368' style='width:480;height:445' class='attach' width="480" height="445" alt="Attached Image: vector.png" /></a><br /><br />As you can see, the introduction of the origin as the second point gives our vector a direction.&nbsp;&nbsp; But you can also see that the first point (3,3) can be moved (or <strong>translated</strong>) closer to or farther away from the origin.&nbsp;&nbsp;<br /><br />The distance from the origin is known as the magnitude and is given by the quadratic equation <tt>a^2 + b^2 = c^2</tt>.&nbsp;&nbsp;In this case <tt>3^2 + 3^2 = c^2</tt> and <tt>c = sqrt(18) ~= 4.24</tt>.&nbsp;&nbsp;If we divide each of the components of this vector by 4.24 we can <i>scale</i> the vector back to a point where it has a magnitude of just 1.&nbsp;&nbsp;We will learn in upcoming examples how this process of <i>normalizing</i> the vector can be very useful since this process retains the direction, but gives us an ability to scale the vector up or down quickly with simple multiplication by some numeric (aka scalar) value. <br /><br />For the upcoming examples, I am going to assume that your math library uses <i>Vector2</i> for a 2D vector and <i>Vector3</i> for a 3D vector. There are various differences in naming across libaries and programming languages, for example <i>vector, vector3, Vector3f, vec3, point, point3f</i> and similar. Your math library must have some documentation and examples for them.<br /><br /><p class="message note">

<strong>Note:</strong>&nbsp;&nbsp;In the world of programming programmers have utilized the vector type to represent both vectors in the traditional mathematical/physics sense as well as points or arbitrary n-tuplet units at their own discretion.&nbsp;&nbsp;Be advised.
				
</p><br /><br />Like any other variable, the vector in your code has a meaning which is up to you: it can be a position, direction, velocity. <br /><br /><ul class='bbc'><li><strong>Position</strong> - a vector represents <i>an offset</i> from your <i>world origin</i> point (0, 0, 0).</li><li><strong>Direction</strong> - vector looks very much like an arrow pointing at some direction. That is indeed what it can be used for. For example, if you have a vector that points south, you can make all your units go south.</li><li>A special case of direction vector is a vector of length 1. It is called a <strong>normalized vector</strong>, or <strong>normal</strong> for short.</li><li>A <strong>velocity</strong> vector can describe a movement. In that case, it is a <i>difference in position</i> over <i>specific amount of time</i>.</li></ul><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14268-0-22153700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14268" title="file_pos.png - Size: 6.86K, Downloads: 66"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-75174000-1363382404.png" id='ipb-attach-img-14268-0-22153700-1369216368' style='width:249;height:108' class='attach' width="249" height="108" alt="Attached Image: file_pos.png" /></a><br /><br /><h2>Remember the Basics - Vector Addition and Subtraction</h2><br />Vector addition is used to accumulate the difference described by both vectors into the final vector.<br />For example, if an object moves by A vector, and then by B vector, the result is the same as if it would have moved by C vector.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14269-0-22166800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14269" title="file(4).png - Size: 4.34K, Downloads: 45"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-41739700-1363382913.png" id='ipb-attach-img-14269-0-22166800-1369216368' style='width:147;height:107' class='attach' width="147" height="107" alt="Attached Image: file(4).png" /></a><br /><br />For subtraction, the second vector is simply inverted and added to the first one.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14270-0-22179800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14270" title="file(5).png - Size: 5.9K, Downloads: 42"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-49532000-1363382936.png" id='ipb-attach-img-14270-0-22179800-1369216368' style='width:147;height:107' class='attach' width="147" height="107" alt="Attached Image: file(5).png" /></a><br /><br /><h2>Example: a Distance Between Objects</h2><br />If your vectors represent positions of objects A and B, then <i>B - A</i> will be a difference vector between positions. The result would represent <i>a direction and a distance</i> A must travel to get to B.<br /><br />For example, to get a distance vector to that tree you need to subtract your position from the tree position.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14272-0-22200900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14272" title="file(7).png - Size: 20.62K, Downloads: 47"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-87770400-1363385231.png" id='ipb-attach-img-14272-0-22200900-1369216368' style='width:388;height:161' class='attach' width="388" height="161" alt="Attached Image: file(7).png" /></a><br /><br /><i>I am using <a href='http://en.wikipedia.org/wiki/Pseudo_code' class='bbc_url' title='External link' rel='nofollow external'>pseudo-code</a> to keep the code clean. Three numbers in parentheses (x, y, z) represent a vector.</i><br /><br /><pre class='prettyprint lang-auto linenums:0'>
tree_position = (10, 10, 0)
my_position = (3, 3, 0)
# distance and direction you would need to move 
# to get exactly where the tree is
vector_to_tree = tree_position - my_position
</pre><br /><h2>Example: Velocity</h2><br />Besides a position vector, object may have a velocity vector.<br />For example, the velocity vector for a cannon ball may describe the distance it is going to move over the next second.<br /><br />When first fired, cannon ball may have these properties:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
position = (0, 10, 10) # position: 10 units in Y and Z direction
velocity = (500, 0, 0) # initial movement is 500 units in X direction over the next second
</pre><br />Every second, you would update cannon position based on the velocity:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
position += velocity # add velocity to position and update position
</pre><br /><h2>Concept: Simulation</h2><br />Wait! We do not want to update object once per second. In fact, we want to do it as often as possible.<br />But we can not expect the time between updates to be fixed. So we use a delta time, which is the time since the last update.<br /><br />Since our delta time represents a fraction of the time passed, we can use it to get only that fraction of our velocity for the next position update.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
position += velocity * delta
</pre><br />This is a very basic <i><a href='http://en.wikipedia.org/wiki/Simulation' class='bbc_url' title='External link' rel='nofollow external'>simulation</a></i>. To make one, we <i>model</i> how our objects <i>behave in our world</i> (cannon ball has constant velocity forever). Then we load initial <i>game state</i> (cannon ball starts with initial velocity and position).<br /><br />The final piece where everything comes together is an <i>update</i> loop, which is executed regularly&nbsp;&nbsp;We use the <i>delta time</i> (time interval) since the previous update, and update every simulated object to be where it should on the <i>rules we defined</i> (update cannon ball position based on its velocity). <br /><br /><h2>Example: Gravity, Air Resistance and Wind</h2><br />Our cannon ball is quite boring: it will move to the same direction and at the same speed forever. We need it to react to the world around. For example, let there be gravity for it to fall, air resistance for it to slow down, and the wind just for kicks.<br /><br />What the gravity actually means in a game? Well, it has a side effect of increasing velocity of objects to one direction: down. So in case our Y axis is up, our gravity vector would be:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
# increase velocity of every object -2 down per second
gravity_vector = (0, -2, 0)
</pre><br />So, before every update, we can modify our velocity:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
velocity += gravity_vector * delta # apply gravity effect
position += velocity * delta # update position
</pre><br />Let's just say our air is thick. So thick it slows down cannon balls by half every second.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
velocity += gravity_vector * delta # apply gravity effect
velocity *= 0.5 * delta # apply 0.5 slowdown per second
&nbsp;&nbsp;&nbsp;&nbsp;
position += velocity * delta # update position
</pre><br />Velocity had the force because of the cannon ball being the cannon ball. Kinetic energy.<br />However, there might be another constant force to change the movement of cannon ball: like the wind.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
# modify kinetic energy / velocity
velocity += gravity_vector * delta # apply gravity effect
velocity *= 0.5 * delta # apply 0.5 slowdown per second
&nbsp;&nbsp;&nbsp;&nbsp;
# add all forces
final_change_per_second = velocity + wind_force_per_second
&nbsp;&nbsp;&nbsp;&nbsp;
# update position
position += final_change_per_second * delta
</pre><br />The main point of this example is to demonstrate how easy it is to create quite complex behavior using a simple vector math.<br /><br /><h2>Concept: Direction</h2><br />Often you will not need a distance from A to B, just the direction for A to face the B. A distance vector B - A can represent the direction, but what if you need to move "just a bit" towards B, at the exact speed you like?<br /><br />In such case vector length should be irrelevant&nbsp;&nbsp;If we reduce a direction vector to the length of 1, we can use it for this, and other purposes. We call this reduction the <i>normalization</i> and the resulting vector the <i>normal vector</i>.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14273-0-22213300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14273" title="file(8).png - Size: 21.42K, Downloads: 46"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-24146000-1363391280.png" id='ipb-attach-img-14273-0-22213300-1369216368' style='width:388;height:161' class='attach' width="388" height="161" alt="Attached Image: file(8).png" /></a><br /><br />So, a normal vector always should be the length of 1, otherwise it is not a normal vector.<br />A normal vector represents an angle without any actual "angles" required as a possible change in position. If we multiply the vector by a scalar number, we get the direction vector that has the same length as the scalar.<br /><br />There should be a "normalize" function in your math library to get a normal vector from any other vector.<br /><br />So we can get a movement by exactly the 3 units towards B.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
final_change = (B - A).normalize() * 3
</pre><br /><h2>Concept: Surface Plane</h2><br />A normal vector can also be used to describe a direction a surface plane is facing. You can imagine the plane as an infinite slice of the world in half at a particular point P. Rotation of this slice is defined by the normal vector N. <br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14299-0-22317100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14299" title="file(12)_no_j.png - Size: 6.86K, Downloads: 48"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-55836500-1363480624.png" id='ipb-attach-img-14299-0-22317100-1369216368' style='width:247;height:150' class='attach' width="247" height="150" alt="Attached Image: file(12)_no_j.png" /></a><br /><br />To rotate this slice/plane, you would change its normal vector.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14285-0-22276400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14285" title="g3841.png - Size: 14.09K, Downloads: 50"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-99093600-1363443588_thumb.png" id='ipb-attach-img-14285-0-22276400-1369216368' style='width:480;height:165' class='attach' width="480" height="165" alt="Attached Image: g3841.png" /></a><br /><br /><h2>Concept: Dot Product</h2><br />A dot product is an operation on two vectors, which returns a number. You can think of this number as a way to compare the two vectors.<br /><br /><i>Usually written as:</i><br /><pre class='prettyprint lang-auto linenums:0'>
result = A dot B
</pre><br />This comparison is particularly useful between two <strong>normal vectors</strong>, because it represents a <i>difference in rotation</i> between them.<br /><br /><ul class='bbc'><li>If dot product is 1, normals face the same direction.</li><li>If dot product is 0, normals are perpendicular.</li><li>If dot product is -1, normals face opposite directions.</li></ul><br />Here are the normal values in the illustration:<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14276-0-22236600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14276" title="file(10).png - Size: 21.66K, Downloads: 51"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-91961700-1363393109.png" id='ipb-attach-img-14276-0-22236600-1369216368' style='width:184;height:179' class='attach' width="184" height="179" alt="Attached Image: file(10).png" /></a><br /><br />Note that change from 1 to 0 and from 0 to -1 is not linear, but follows a cosine curve. So, to get an angle from a dot product, you need to calculate arc-cosine of it:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
angle = acos(A dot B)
</pre><br /><h2>Example: Light</h2><br />Suppose we are writing a light shader and we need to calculate the brightness of a pixel at a particular surface point. We have:<br /><br /><ul class='bbc'><li>A normal vector which represent the direction of surface at this point.</li><li>Position of the light.</li><li>Position of this surface point.</li></ul><br />We can get the distance vector from our point to the light:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
distance_vec = light_pos - point_pos
</pre><br />As well as the direction of the light for this particular point as a normal vector:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
light_direction = distance_vec.normalize()
</pre><br />Then, using our knowledge about angle and dot product relationship, we can use dot product of point-to-light normal to calculate the brightness of the point. In simplest case it will be exactly equal the dot product!<br /><br /><pre class='prettyprint lang-auto linenums:0'>
brightness = surface_normal dot light_direction
</pre><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14277-0-22249200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14277" title="file(11).png - Size: 35.86K, Downloads: 54"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-22543900-1363394751_thumb.png" id='ipb-attach-img-14277-0-22249200-1369216368' style='width:480;height:182' class='attach' width="480" height="182" alt="Attached Image: file(11).png" /></a><br /><br />Believe it or not, this is the bare bones of a simple light shader. An actual fragment shader in OpenGL would look like this (do not worry if you have no knowledge of the shaders: this is just an example to demonstrate the practical application of dot product):<br /><br /><pre class='prettyprint lang-auto linenums:0'>
varying vec3 surface_normal;
varying vec3 vertex_to_light_vector;

void main(void)
{
vec4 diffuse_color = vec3(1.0, 1.0, 1.0); // the color of surface - white
float diffuse_term = dot(surface_normal, normalize(vertex_to_light_vector));
gl_FragColor = diffuse_color * diffuse_term;
}
</pre><br />Note that the way "dot" and "normalize" functions are used is the only difference from previous examples.<br /><br /><h2>Example: Distance from a point to a plane</h2><br />To calculate the shortest distance from some point to a plane, first get distance vector to <i>any</i> point of that plane, <i>do not normalize it</i>, and <i>multiply it with plane's normal vector</i>.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
distance_to_a_plane = (point - plane_point) dot plane_normal;
</pre><br /><h2>Example: Is a point on a plane?</h2><br />If it's distance to a plane is 0, yes.<br /><br /><h2>Example: Is a vector parallel to a plane?</h2><br />If this vector is perpendicular to plane's surface normal, then yes.<br />We already know that two vectors are perpendicular when their dot product is 0.<br /><br />So vector is parallel to the plane when <strong>vector dot plane_normal == 0</strong><br /><br /><h2>Example: Line intersection with a plane</h2><br />Let's say our line starts at <i>P1</i> and ends at <i>P2</i>. A point on plane surface <i>SP</i> and surface normal is <i>SN</i>.<br /><br />If we make an imaginary plane run through the first line point P1, the solution boils down to calculating which point (P2 or SP) is both <i>closer to P1</i> and <i>more parallel to SN</i>. This value for can be calculated by using a dot product.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14288-0-22289800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14288" title="g3842.png - Size: 12.58K, Downloads: 54"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-96963000-1363447249_thumb.png" id='ipb-attach-img-14288-0-22289800-1369216368' style='width:480;height:197' class='attach' width="480" height="197" alt="Attached Image: g3842.png" /></a><br /><br /><pre class='prettyprint lang-auto linenums:0'>
dot1 = SN dot (SP - P1)
dot2 = SN dot (P2 - P1)
</pre><br />You can calculate "how much" it intersects the plane by comparing (dividing) these two values.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
u = (SN dot (SP - P1)) / (SN dot (P2 - P1))
</pre><br /><ul class='bbc'><li>if u == 0, line is parallel the plane.</li><li>if u &lt;= 1 and u &gt; 0, line intersects the plane.</li><li>if u &gt; 1, no intersection.</li></ul><br />You can calculate the exact intersection point by multiplying line vector to u:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
intersection point = (P2 - P1) * u
</pre><br /><h2>Concept: Cross Product</h2><br />A cross product is also an operation on two vectors. The result is a third vector, which is perpendicular to the first two, and it's length is an average of the both lengths.<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14280-0-22263000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14280" title="file(13).png - Size: 7.98K, Downloads: 44"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-26355900-1363397062.png" id='ipb-attach-img-14280-0-22263000-1369216368' style='width:147;height:137' class='attach' width="147" height="137" alt="Attached Image: file(13).png" /></a><br /><br />Note that for cross product, the order of arguments matters. If you switch order, the result will be a vector of the same length, but facing the opposite direction.<br /><br /><h2>Example: Collision</h2><br />Let's say an object moves into a wall at an angle. But wall is friction-less and object should slide along its surface instead of stopping. How to calculate its new position for that?<br /><br /><a class='resized_img' rel='lightbox[12a137d6cff869c6c3913c361a20c3d7]' id='ipb-attach-url-14289-0-22303300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=14289" title="file(14).png - Size: 13.44K, Downloads: 40"><img src="http://uploads.gamedev.net/monthly_03_2013/ccs-208401-0-45315200-1363449309.png" id='ipb-attach-img-14289-0-22303300-1369216368' style='width:272;height:194' class='attach' width="272" height="194" alt="Attached Image: file(14).png" /></a><br /><br />First of all, we have a vector which represents the distance the object should have moved if there were no wall. We are going to call it a "change". Then, we are going to assume object is touching the wall. And we will also need the normal vector of this surface.<br /><br />We will use the cross product to get a new vector which is perpendicular to the change and the normal:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
temp_vector = change cross plane_normal
</pre><br />Then, the final direction is perpendicular to this new vector and the same normal:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
new_direction = temp_vector cross plane_normal
</pre><br />That's it:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
new_direction = (change cross plane_normal) cross plane_normal
</pre><br /><h1>Now what?</h1><br />With this article, I have tried to bridge the gap between the theory and the real practical application of it in game development. However, it means that I had to skip a lot of things in between.<br /><br />But I hope the picture is a bit clearer. If anything, this walk-through may serve as a quick overview of the way Vector Math is used in Games.<br /><br /><h1>More in-depth reading</h1><ul class='bbc'><li><a href='http://www.arcsynthesis.org/gltut/Basics/Introduction.html' class='bbc_url' title='External link' rel='nofollow external'>Vector Math</a> - Addition, subtraction, negation, normalization.</li><li><a href='http://betterexplained.com/articles/vector-calculus-understanding-the-dot-product/' class='bbc_url' title='External link' rel='nofollow external'>Better Explained Dot Product</a> - Follows similar style of explaining dot product by examples</li><li><a href='http://nic-gamedev.blogspot.com/2011/11/using-vector-mathematics-dot-products.html' class='bbc_url' title='External link' rel='nofollow external'>Dot Product</a> and <a href='http://nic-gamedev.blogspot.com/2011/11/using-vector-mathematics-cross-products.html' class='bbc_url' title='External link' rel='nofollow external'>Cross Product</a> - More in-depth explanation of dot and cross products</li><li><a href='http://gamedev.tutsplus.com/articles/glossary/quick-tip-what-is-the-game-loop/' class='bbc_url' title='External link' rel='nofollow external'>What is a game loop?</a> - Short explanation of the game loop</li><li><a href='http://blog.nuclex-games.com/tutorials/xna/game-loops/' class='bbc_url' title='External link' rel='nofollow external'>More in-depth look at the different update loop types</a></li></ul>]]></description>
		<pubDate>Fri, 15 Mar 2013 20:42:55 +0000</pubDate>
		<guid isPermaLink="false">78c784cf4f1360d2c590de5146e67b4c</guid>
	</item>
	<item>
		<title>A Verlet based approach for 2D game physics</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/a-verlet-based-approach-for-2d-game-physics-r2714</link>
		<description><![CDATA[<span style='font-size: 18px;'> <strong class='bbc'>Introduction</strong></span><br /><br />The purpose of this article is to describe a way to simulate game physics in two dimensions. We will use an approach known as Verlet integration, go over the basics of moving points and building shapes to topics like collision detection and response. The reader should know the basics of vector maths, meaning addition, subtraction, multiplication with a scalar and the dot product. More than that is not required, however, for deeper understanding more knowledge of Euclidean geometry in two dimensions wouldn't hurt.<br /><br /> <br /><span style='font-size: 18px;'><strong class='bbc'>Verlet integration</strong></span><br /><br />First of all, what is Verlet integration? The Verlet integration is a way of numerically integrating the equations of motion. For this article, you really don't have to know what numerical integration means; basically, the Verlet integration describes the movement of a point trough time. There are different methods to do that - I guess, most of you know the Euler method:<br /><br /> <a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5793-0-24036000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5793" title="Formula1.png - Size: 2.72K, Downloads: 504"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-28695500-1319079808_thumb.png" id='ipb-attach-img-5793-0-24036000-1369216368' style='width:250;height:37' class='attach' width="250" height="37" alt="Attached Image: Formula1.png" /></a><br /><br /> If we merge these two equations into one, meaning we substitute the Velocity<sub class='bbc'>New</sub> in the second equation by the right hand side of the first equation, we get:<br /><br /> <a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5794-0-24053700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5794" title="Formula2.png - Size: 2.27K, Downloads: 733"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-26889700-1319079869_thumb.png" id='ipb-attach-img-5794-0-24053700-1369216368' style='width:250;height:18' class='attach' width="250" height="18" alt="Attached Image: Formula2.png" /></a><br /><br /> There are different types of Verlet integration methods - Position Verlet, Velocity Verlet and Leapfrog. For this article, we will choose the position version, because it has some nice features that we're going to take advantage of.<br /><br /> The corresponding equation for position Verlet is actually not much different from the one shown above:<br /><br /> <a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5795-0-24070600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5795" title="Formula3.png - Size: 3.01K, Downloads: 765"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-06022000-1319079902_thumb.png" id='ipb-attach-img-5795-0-24070600-1369216368' style='width:250;height:24' class='attach' width="250" height="24" alt="Attached Image: Formula3.png" /></a><br /><br /> As we can see now, the term (Position<sub class='bbc'>Current</sub> – Position<sub class='bbc'>Old</sub>) in the Verlet equation replaces the velocity if we compare it with the Euler approach. Consequently, this means that this approach doesn't deal with velocities at all - one thing less to worry about. This integration method is not always quite accurate, since (Position<sub class='bbc'>Current</sub> – Position<sub class='bbc'>Old</sub>) is only an approximation of the actual velocity. However, it's fast and stable, which is why it is well suited for games. Also, using this approach the collision response gets really simple. Let us consider a point as shown in figure 1.<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5796-0-24087000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5796" title="Figure1.png - Size: 1.39K, Downloads: 760"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-63486300-1319079930_thumb.png" id='ipb-attach-img-5796-0-24087000-1369216368' style='width:250;height:167' class='attach' width="250" height="167" alt="Attached Image: Figure1.png" /></a><br /></p>&nbsp;&nbsp;The starting conditions for Position<sub class='bbc'>Old</sub> and Position<sub class='bbc'>Current</sub> are chosen such that the point moves slowly to the right. After a certain amount of time steps, the point will intersect with the square on the right. Once the collision is detected, we only have to move the point out of the square and we are done with the collision response. Since the integration uses (Position<sub class='bbc'>Current</sub> – Position<sub class='bbc'>Old</sub>) as its velocity, the speed of the point will subsequently change if we change either CurrentPosition or OldPosition - which is what we did in the collision response (we moved the point out of the square). As we can see in figure 2, the point will automatically decelerate and eventually stop.<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5797-0-24103500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5797" title="Figure2.png - Size: 5.99K, Downloads: 473"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-73570500-1319079959_thumb.png" id='ipb-attach-img-5797-0-24103500-1369216368' style='width:250;height:100' class='attach' width="250" height="100" alt="Attached Image: Figure2.png" /></a><br /></p>&nbsp;&nbsp;If we put the formula above in code, we get something like this (assuming you have a working vector-class, that is):<br /><br /><pre class='prettyprint lang-auto linenums:0'>struct Point {
&nbsp;&nbsp;Vec2 Position;
&nbsp;&nbsp;Vec2 OldPosition;
&nbsp;&nbsp;Vec2 Acceleration;
};

class Physics {
&nbsp;&nbsp;int PointCount;
&nbsp;&nbsp;Point* Points[ MAX_VERTICES ];

&nbsp;&nbsp;float Timestep;

public:
&nbsp;&nbsp;void&nbsp;&nbsp;UpdateVerlet();

&nbsp;&nbsp;//Constructors, getters/setters etc. omitted
};

void Physics::UpdateVerlet() {
&nbsp;&nbsp;for( int I = 0; I &lt; PointCount; I++ ) {
&nbsp;&nbsp;&nbsp;&nbsp;Point&amp; P = *Points[ I ];

&nbsp;&nbsp;&nbsp;&nbsp;Vec2 Temp = P.Position;
&nbsp;&nbsp;&nbsp;&nbsp;P.Position += P.Position - P.OldPosition + P.Acceleration*Timestep*Timestep;
&nbsp;&nbsp;&nbsp;&nbsp;P.OldPosition = Temp;
&nbsp;&nbsp;}
}</pre>Now we have a working physics code that will calculate the trajectories of arbitrary points just fine. But points alone are not very useful, except when you're programming a particle simulation. Since that's normally not the case if you're into game programming, we have to extend the points in some way so we can simulate rigid body behaviour as well. If we look at rigid bodies in nature, we see that they are actually a huge amount of points (=atoms) held together by various forces. <br /><br />We could of course try and create thousands of particles and connect them in some way to approximate the behaviour of rigid bodies, which would work indeed. However, that would cause a huge amount of calculations to be done for e.g. a single cube, let alone a whole game filled with physics bodies, so this isn't really an optimal solution. Luckily, it shows to be sufficient only to model the vertices of a body. If we were to simulate a box, we would simply create the four vertices that make up the shape of a box, connect them somehow and we're done.<br /><br /> The problem left to compute is now only that of the connections. If we again imagine a box and the four vertices, it should become clear that the distance of a vertex to another should always remain constant. If the distance between two vertices changes, this always means that the shape of the body gets deformed, and we don't want that - who would like to have a crate in his game that collapses once you stand on it? Therefore, we have to find a way to keep the distance between two vertices at a constant value.<br /><br /> If we had the same problem in reality, the solution would be simple - just insert some kind of pole in-between and the vertices won't approach each other anymore. We will do the exact same thing in our program; create a new class that represents an 'imaginary pole'. It connects two vertices and keeps those vertices at a constant distance. The algorithm to update these 'poles' is called once the Verlet is calculated. The algorithm itself is actually quite simple. First of all, we have to calculate the vector between the two vertices that are connected by the pole. The current distance between the two vertices is simply the length of that vector. Once we have the current length, the difference of the original length of the pole should be calculated. We can now use the difference to push the vertices to a position where the distance constraint is satisfied.<br /><br /><pre class='prettyprint lang-auto linenums:0'>struct Edge {
&nbsp;&nbsp;Vertex* V1;
&nbsp;&nbsp;Vertex* V2;

&nbsp;&nbsp;float OriginalLength; //The length of the edge when it was created

&nbsp;&nbsp;//Constructors etc. omitted
};

void Physics::UpdateEdges() {
&nbsp;&nbsp;for( int I = 0; I &lt; EdgeCount; I++ ) {
&nbsp;&nbsp;&nbsp;&nbsp;Edge&amp; E = *Edges[ I ];

&nbsp;&nbsp;&nbsp;&nbsp;//Calculate the vector mentioned above
&nbsp;&nbsp;&nbsp;&nbsp;Vec2 V1V2 = E.V2-&gt;Position - E.V1-&gt;Position; 

&nbsp;&nbsp;&nbsp;&nbsp;//Calculate the current distance
&nbsp;&nbsp;&nbsp;&nbsp;float V1V2Length = V1V2.Length(); 
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//Calculate the difference from the original length
&nbsp;&nbsp;&nbsp;&nbsp;float Diff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = V1V2Length - E.OriginalLength; 
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;V1V2.Normalize();

&nbsp;&nbsp;&nbsp;&nbsp;//Push both vertices apart by half of the difference respectively 
&nbsp;&nbsp;&nbsp;&nbsp;//so the distance between them equals the original length
&nbsp;&nbsp;&nbsp;&nbsp;E.V1-&gt;Position += V1V2*Diff*0.5f; 
&nbsp;&nbsp;&nbsp;&nbsp;E.V2-&gt;Position -= V1V2*Diff*0.5f;
&nbsp;&nbsp;}
}</pre>That's it - if we created a few points and connected them with our newly created edge struct, the resulting body would show very nice rigid body-behaviour, including rotational effects when it hits the floor. But why does that work? The code isn't much different from before, we only added a few lines to satisfy the distance constraint and suddenly we have rigid bodies. The reason behind this lies within our integration method. If we recall that the Verlet integration doesn't work with velocity but rather with the difference between the current position and the position before the last integration step, it should become clear that the speed of the point will change if we change its position. Therefore, since we change its position in the UpdateEdges method, its velocity will also change. The overall change in velocity looks exactly like we would expect it from a vertex of a rigid body; it is not totally correct, but good enough for games.<br /><br /> To be honest, I lied when I said before that the code would work just fine if we executed it like that. As the code is now, bodies would not be totally rigid. If a body collides with the floor, the distance between it's vertices is not totally constant, which means that the body is more or less deformed, depending on the it's speed before the collision. Why does that happen? The UpdateEdges method is totally correct, but still the distance between two vertices may vary. If we look at figure 3, this should become clear: If a vertex is connected to more than just one edge (which is normally the case), the length correction of one edge may disturb the length of another edge, which is why the bodies get deformed.<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5798-0-24120300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5798" title="Figure3.png - Size: 6.64K, Downloads: 438"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-60735200-1319080139_thumb.png" id='ipb-attach-img-5798-0-24120300-1369216368' style='width:250;height:100' class='attach' width="250" height="100" alt="Attached Image: Figure3.png" /></a><br /></p>&nbsp;&nbsp;The only way to get rid of this problem is to execute the edge correction method more than just once per frame. The more this method is called, the more perfect the situation gets approximated, where all vertices have the right distance to each other. This gives game programmers a scalable physics algorithm - the more time is left at the end of the main loop, the more iterations can be used for the distance correction (and the collision response that will be introduced later). Vice-versa, if the main loop takes more time to execute, the iterations used for physics can be reduced so the game runs at a more or less constant frame rate.<br /><br /> <br /><span style='font-size: 18px;'><strong class='bbc'>Collision Detection</strong></span><br /><br />Now that our algorithm supports the simulation of (almost) rigid bodies, let's proceed to the next problem - collision detection! In this article, we will use an algorithm known as the 'Separating Axis Theorem'. If you already now how it works, you might as well just skip this part and go straight to the collision response. So, how does the Separating Axis Theorem work? As the title suggests, it states that two bodies don't collide, as long we are able to put a straight line between the two, that doesn't intersect either body. Figure 4 demonstrates this.<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5799-0-24139100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5799" title="Figure4.png - Size: 8.69K, Downloads: 240"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-14037800-1319080199_thumb.png" id='ipb-attach-img-5799-0-24139100-1369216368' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: Figure4.png" /></a><br /></p>&nbsp;&nbsp;The only limitation of this algorithm is that it only works correctly with convex shapes. If we tested two concave shapes, the algorithm will fail, meaning that it would detect a collision when there is none. The reason should become evident if you take a look at figure 5.<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5800-0-24155700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5800" title="Figure5.png - Size: 8.76K, Downloads: 223"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-88362700-1319080228_thumb.png" id='ipb-attach-img-5800-0-24155700-1369216368' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: Figure5.png" /></a><br /></p>&nbsp;&nbsp;We could deal with that by breaking up each concave polygon into convex subshapes and then test each subshape separately, but for simplicity reasons, we will just stick to convex polygons in this article - feel free to add concave support later.<br /><br /> So, how do we find out whether we could put a line in-between? We could of course just test every possible line for intersection, but it is evident that this is completely inefficient. To do this, we will take advantage of projection. If we put a new line in figure 4 that is perpendicular to the separating line, we can see that the projections of the two bodies on this line do not overlap (as shown in figure 6). However, if we chose a line that does intersect, the projections of the two bodies do also overlap.<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5801-0-24172400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5801" title="Figure6.png - Size: 16.8K, Downloads: 220"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-04196200-1319080251_thumb.png" id='ipb-attach-img-5801-0-24172400-1369216368' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: Figure6.png" /></a><br /></p>&nbsp;&nbsp;It is irrelevant where we place the line that we project to, since the resulting projection is one-dimensional anyway - only its direction is important. This means that we don't have to look for a line that fits perfectly in-between the two bodies anymore, but for a direction where the projections don't overlap. Finding this direction shows to be quite easy. Let's consider the case where there is only one possible line that separates the two bodies (see figure 7).<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5802-0-24189000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5802" title="Figure7.png - Size: 11.96K, Downloads: 217"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-73015800-1319080270_thumb.png" id='ipb-attach-img-5802-0-24189000-1369216368' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: Figure7.png" /></a><br /></p>&nbsp;&nbsp;It is evident that this line is parallel to the left edge of the right body. Therefore, to find the direction of a separating line, we simply have to iterate over all edges of both bodies and check, if the projection of the bodies onto the perpendicular of the edge overlap. If they don't, the bodies don't collide and we can end the search. If they do, we go on to the next edge. If there is no such edge, the entities are colliding and we have to proceed with the collision response.<br /><br /> Let's put this into code! But before we can implement the collision detection, we first have to write a body class that contains its respective vertices and edges:<br /><br /><pre class='prettyprint lang-auto linenums:0'>struct PhysicsBody {
&nbsp;&nbsp;int VertexCount;
&nbsp;&nbsp;int EdgeCount;

&nbsp;&nbsp;Vertex* Vertices[ MAX_BODY_VERTICES ];
&nbsp;&nbsp;Edge*&nbsp;&nbsp; Edges&nbsp;&nbsp; [ MAX_BODY_EDGES&nbsp;&nbsp;&nbsp;&nbsp;];

&nbsp;&nbsp;void ProjectToAxis( Vec2&amp; Axis, float&amp; Min, float&amp; Max );

&nbsp;&nbsp;//Again, constructors etc. omitted
};</pre>The ProjectToAxis method will project the body onto the passed axis and change the Min and Max variables to the result of the projection. Since a projection of a 2D-shape onto 1D results in a mere interval of a line, the result of the projection can be stored in two floats that denote the beginning and the end of the interval. The projection method is quite simple: <br /><br /><pre class='prettyprint lang-auto linenums:0'>void PhysicsBody::ProjectToAxis( Vec2&amp; Axis, float&amp; Min, float&amp; Max ) {
&nbsp;&nbsp;float DotP = Axis*Vertices[ 0 ]-&gt;Position;

&nbsp;&nbsp;//Set the minimum and maximum values to the projection of the first vertex
&nbsp;&nbsp;Min = Max = DotP; 

&nbsp;&nbsp;for( int I = 1; I &lt; VertexCount; I++ ) {
&nbsp;&nbsp;&nbsp;&nbsp;//Project the rest of the vertices onto the axis and extend 
&nbsp;&nbsp;&nbsp;&nbsp;//the interval to the left/right if necessary
&nbsp;&nbsp;&nbsp;&nbsp;DotP = Axis*Vertices[ I ]-&gt;Position; 

&nbsp;&nbsp;&nbsp;&nbsp;Min = MIN( DotP, Min );
&nbsp;&nbsp;&nbsp;&nbsp;Max = MAX( DotP, Max );
&nbsp;&nbsp;}
}</pre> As you can see, projection in 2D is simply a dot product of the projection axis and the point we want to project. The collision detection may look like this:<br /><br /><pre class='prettyprint lang-auto linenums:0'>bool Physics::DetectCollision( PhysicsBody* B1, PhysicsBody* B2 ) {
&nbsp;&nbsp;//Just a fancy way of iterating through all of the edges of both bodies at once
&nbsp;&nbsp;for( int I = 0; I &lt; B1-&gt;EdgeCount + B2-&gt;EdgeCount; I++ ) { 
&nbsp;&nbsp;&nbsp;&nbsp;Edge* E;

&nbsp;&nbsp;&nbsp;&nbsp;if( I &lt; B1-&gt;EdgeCount )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E = B1-&gt;Edges[ I ];
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E = B2-&gt;Edges[ I - B1-&gt;EdgeCount ];
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//Calculate the axis perpendicular to this edge and normalize it
&nbsp;&nbsp;&nbsp;&nbsp;Vec2 Axis( E-&gt;V1-&gt;Position.Y - E-&gt;V2-&gt;Position.Y, E-&gt;V2-&gt;Position.X - E-&gt;V1-&gt;Position.X ); 
&nbsp;&nbsp;&nbsp;&nbsp;Axis.Normalize();

&nbsp;&nbsp;&nbsp;&nbsp;float MinA, MinB, MaxA, MaxB; //Project both bodies onto the perpendicular axis
&nbsp;&nbsp;&nbsp;&nbsp;B1-&gt;ProjectToAxis( Axis, MinA, MaxA );
&nbsp;&nbsp;&nbsp;&nbsp;B2-&gt;ProjectToAxis( Axis, MinB, MaxB );

&nbsp;&nbsp;&nbsp;&nbsp;//Calculate the distance between the two intervals - see below
&nbsp;&nbsp;&nbsp;&nbsp;float Distance = IntervalDistance( MinA, MaxA, MinB, MaxB ); 

&nbsp;&nbsp;&nbsp;&nbsp;if( Distance &gt; 0.0f ) //If the intervals don't overlap, return, since there is no collision
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;}

&nbsp;&nbsp;return true; //There is no separating axis. Report a collision!
}</pre>The algorithm works just like described above; if something isn't clear, I would suggest rereading the explanations step by step. The IntervalDistance method that is mentioned in the code is actually quite simple:<br /><br /><pre class='prettyprint lang-auto linenums:0'>float Physics::IntervalDistance( float MinA, float MaxA, float MinB, float MaxB ) {
&nbsp;&nbsp;if( MinA &lt; MinB )
&nbsp;&nbsp;&nbsp;&nbsp;return MinB - MaxA;
&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;return MinA - MaxB;
}</pre>Since we don't know if body A will lie on the left and body B on the right or vice-versa, we have to check which interval begins sooner. We then subtract the end of the left interval from the beginning of the right interval to get the distance between the two - if this value is smaller than zero, they overlap. <br /><br />That's it for collision detection! ...well, not yet. Apart from detecting whether or not the two bodies collide, the collision detection should also provide certain information about the collision. We also have to calculate a so-called collision vector that is big enough to push the two bodies apart so they don't collide anymore, but touch each other. There are of course arbitrarily much vectors that could accomplish this, but for our physics to look right we have to find the smallest of those vectors. The vector we're looking for has the pleasant property that it's always parallel to one of the lines we projected to, which means that we only have to check each edge and calculate the length of the vector needed to push the two bodies apart. Figuring out the length isn't really a hard thing to do, if we take a look at figure 8.<br /><br /><p class='bbc_center'>&nbsp;&nbsp;<a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5803-0-24205700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5803" title="Figure8.png - Size: 16.88K, Downloads: 228"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-38727200-1319080569_thumb.png" id='ipb-attach-img-5803-0-24205700-1369216368' style='width:200;height:200' class='attach' width="200" height="200" alt="Attached Image: Figure8.png" /></a><br /></p>&nbsp;&nbsp;In the code above we projected both bodies onto the axis given by the (normalized!) vector 'Axis'. We then called the method IntervalDistance to check whether or not the intervals are overlapping. The length of the vector (which is parallel to the axis we projected to) needed to push the two bodies apart is simply the amount of overlapping. To allow the information calculated in the DetectCollision method to pass smoothly to the collision response, we add a new struct to our Physics class:<br /><br /><pre class='prettyprint lang-auto linenums:0'>class Physics {
&nbsp;&nbsp;struct {
&nbsp;&nbsp;&nbsp;&nbsp;float Depth;
&nbsp;&nbsp;&nbsp;&nbsp;Vec2&nbsp;&nbsp;Normal;
&nbsp;&nbsp;} CollisionInfo;

&nbsp;&nbsp;//Everything else omitted
}</pre>The 'Depth' is the length of the vector, the 'Normal' is the direction of the vector discussed above. <br /><br />Our new DetectCollision method would now look like this:<br /><br /><pre class='prettyprint lang-auto linenums:0'>bool Physics::DetectCollision( PhysicsBody* B1, PhysicsBody* B2 ) {
&nbsp;&nbsp;float MinLength = 10000.0f; //Initialize the length of the collision vector to a relatively large value
&nbsp;&nbsp;for( int I = 0; I &lt; B1-&gt;EdgeCount + B2-&gt;EdgeCount; I++ ) {
&nbsp;&nbsp;&nbsp;&nbsp;Edge* E;

&nbsp;&nbsp;&nbsp;&nbsp;if( I &lt; B1-&gt;EdgeCount )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E = B1-&gt;Edges[ I ];
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E = B2-&gt;Edges[ I - B1-&gt;EdgeCount ];

&nbsp;&nbsp;&nbsp;&nbsp;Vec2 Axis( E-&gt;V1-&gt;Position.Y - E-&gt;V2-&gt;Position.Y, E-&gt;V2-&gt;Position.X - E-&gt;V1-&gt;Position.X );
&nbsp;&nbsp;&nbsp;&nbsp;Axis.Normalize();

&nbsp;&nbsp;&nbsp;&nbsp;float MinA, MinB, MaxA, MaxB;
&nbsp;&nbsp;&nbsp;&nbsp;B1-&gt;ProjectToAxis( Axis, MinA, MaxA );
&nbsp;&nbsp;&nbsp;&nbsp;B2-&gt;ProjectToAxis( Axis, MinB, MaxB );

&nbsp;&nbsp;&nbsp;&nbsp;float Distance = IntervalDistance( MinA, MaxA, MinB, MaxB );

&nbsp;&nbsp;&nbsp;&nbsp;if( Distance &gt; 0.0f )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;//If the intervals overlap, check, whether the vector length on this 
&nbsp;&nbsp;&nbsp;&nbsp;//edge is smaller than the smallest length that has been reported so far
&nbsp;&nbsp;&nbsp;&nbsp;else if( abs( Distance ) &lt; MinDistance ) { 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MinDistance = abs( Distance );

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CollisionInfo.Normal = Axis; //Save collision information for later
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;CollisionInfo.Depth = MinDistance;

&nbsp;&nbsp;return true; //There is no separating axis. Report a collision!
}</pre>Once we have this, we'd be already able to write a very simple collision response. Since the collision vector we calculated pushes the two bodies apart so they don't collide anymore, we could just move all vertices of both bodies back by half the vector and we'd be done. This would work, since interpenetrations are resolved, but it wouldn't look right. The bodies would simply glide off each other, meaning they don't start to spin like a real object when hit. <br /><br />The problem is that a body in our approach only spins if the velocities of its vertices differ. In the same manner, a body only changes its rotational velocity if its vertices experience different acceleration. Acceleration is change in velocity, and in Verlet integration change in velocity is equal to change in position. Therefore, if we move the two bodies back by the collision vector, we change the velocity of all vertices of both bodies by the same amount, which means that there is no change in the rotational velocity. For this reason, we need to write a better collision response.<br /><br /> This is where the advantage of our approach kicks in! In a rigid body system, we would have to use complicated formulas to calculate the momentum and then treat the linear and angular case separately. In our system, the whole thing is much easier - we just have to move the edge and the vertex participating in the collision backwards so they don’t intersect, but touch each other. Since both the edge and the vertex are connected to the rest of their respective body, the position (and therefore the velocity) of the other vertices will change immediately to fulfil the length constraint. Both bodies will start spinning self-actingly. The whole collision response reduces to identifying the edge and the vertex that participate in the collision and separating them from each other; everything else will be done automatically by the edge correction step.<br /><br /> Identifying the collision edge and vertex is not that hard. The collision vertex is the vertex that lies closest to the other body. Therefore, we simply have to create a line whose normal vector is the collision normal (its starting point doesn't really matter). We then measure the distance of each vertex of the first body from the line using the line equation in vector geometry, which is<br /><br /> <a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5804-0-24224000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5804" title="Formula4.png - Size: 751bytes, Downloads: 214"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-49227200-1319080662_thumb.png" id='ipb-attach-img-5804-0-24224000-1369216368' style='width:120;height:36' class='attach' width="120" height="36" alt="Attached Image: Formula4.png" /></a><br /><br /> where N is the normal vector, R<sub class='bbc'>0</sub> the origin of the line, R the point to be tested and d the distance of the point from the line. The set of all points that form a line are given by d = 0 (all points that have zero distance from the line), just as a side note. Once we have the distance of each vertex from the line, we choose the one with the lowest distance - that's the collision vertex we were looking for. Please note that d can also be negative. A line separates a two dimensional space in two halves; if the point R lies in the half the line normal points into, the distance will be positive, but if it lies on the other side, the distance will be negative. Therefore, it is important in which direction the collision normal points (in the implementation presented below, it’s always made sure that the collision normal points at the body containing the collision vertex).<br /><br /> The collision edge is even easier to find. Remember when we projected the bodies on the perpendicular of an edge to find the smallest collision vector? The collision edge is simply the edge that resulted in the smallest vector.<br /><br /> Time to put this in code! First of all, we have to extend the collision info struct in the physics class to contain the collision edge and vertex:<br /><br /><pre class='prettyprint lang-auto linenums:0'>struct {
&nbsp;&nbsp;float Depth;
&nbsp;&nbsp;Vec2&nbsp;&nbsp;Normal;

&nbsp;&nbsp;Edge*&nbsp;&nbsp; E;
&nbsp;&nbsp;Vertex* V;
} CollisionInfo;</pre>Now we can rewrite our DetectCollision method to detect the additional information:&nbsp;&nbsp;<br /><br /><pre class='prettyprint lang-auto linenums:0'>bool Physics::DetectCollision( PhysicsBody* B1, PhysicsBody* B2 ) {
&nbsp;&nbsp;float MinDistance = 10000.0f;
&nbsp;&nbsp;for( int I = 0; I &lt; B1-&gt;EdgeCount + B2-&gt;EdgeCount; I++ ) { //Same old
&nbsp;&nbsp;&nbsp;&nbsp;Edge* E;

&nbsp;&nbsp;&nbsp;&nbsp;if( I &lt; B1-&gt;EdgeCount )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E = B1-&gt;Edges[ I ];
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;E = B2-&gt;Edges[ I - B1-&gt;EdgeCount ];

&nbsp;&nbsp;&nbsp;&nbsp;Vec2 Axis( E-&gt;V1-&gt;Position.Y - E-&gt;V2-&gt;Position.Y, E-&gt;V2-&gt;Position.X - E-&gt;V1-&gt;Position.X );
&nbsp;&nbsp;&nbsp;&nbsp;Axis.Normalize();

&nbsp;&nbsp;&nbsp;&nbsp;float MinA, MinB, MaxA, MaxB;
&nbsp;&nbsp;&nbsp;&nbsp;B1-&gt;ProjectToAxis( Axis, MinA, MaxA );
&nbsp;&nbsp;&nbsp;&nbsp;B2-&gt;ProjectToAxis( Axis, MinB, MaxB );

&nbsp;&nbsp;&nbsp;&nbsp;float Distance = IntervalDistance( MinA, MaxA, MinB, MaxB );

&nbsp;&nbsp;&nbsp;&nbsp;if( Distance &gt; 0.0f )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;
&nbsp;&nbsp;&nbsp;&nbsp;else if( abs( Distance ) &lt; MinDistance ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MinDistance = abs( Distance );

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CollisionInfo.Normal = Axis;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CollisionInfo.E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= E; //Store the edge, as it is the collision edge
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;CollisionInfo.Depth = MinDistance;

&nbsp;&nbsp;//Ensure that the body containing the collision edge lies in 
&nbsp;&nbsp;//B2 and the one containing the collision vertex in B1
&nbsp;&nbsp;if( CollisionInfo.E-&gt;Parent != B2 ) { 
&nbsp;&nbsp;&nbsp;&nbsp;PhysicsBody* Temp = B2;
&nbsp;&nbsp;&nbsp;&nbsp;B2 = B1;
&nbsp;&nbsp;&nbsp;&nbsp;B1 = Temp;
&nbsp;&nbsp;}

&nbsp;&nbsp;//This is needed to make sure that the collision normal is pointing at B1
&nbsp;&nbsp;int Sign = SGN( CollisionInfo.Normal*( B1-&gt;Center - B2-&gt;Center ) ); 

&nbsp;&nbsp;//Remember that the line equation is N*( R - R0 ). We choose B2-&gt;Center 
&nbsp;&nbsp;//as R0; the normal N is given by the collision normal

&nbsp;&nbsp;if( Sign != 1 )
&nbsp;&nbsp;&nbsp;&nbsp;CollisionInfo.Normal = -CollisionInfo.Normal; //Revert the collision normal if it points away from B1


&nbsp;&nbsp;float SmallestD = 10000.0f; //Initialize the smallest distance to a high value
&nbsp;&nbsp;for( int I = 0; I &lt; B1-&gt;VertexCount; I++ ) {
&nbsp;&nbsp;&nbsp;&nbsp;//Measure the distance of the vertex from the line using the line equation
&nbsp;&nbsp;&nbsp;&nbsp;float Distance = CollisionInfo.Normal*( B1-&gt;Vertices[ I ]-&gt;Position - B2-&gt;Center ); 

&nbsp;&nbsp;&nbsp;&nbsp;//If the measured distance is smaller than the smallest distance reported 
&nbsp;&nbsp;&nbsp;&nbsp;//so far, set the smallest distance and the collision vertex
&nbsp;&nbsp;&nbsp;&nbsp;if( Distance &lt; SmallestD ) { 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SmallestD = Distance;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CollisionInfo.V = B1-&gt;Vertices[ I ];
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;return true;
}</pre>In the above code, we introduced a new variable in the PhysicsBody struct, the center. It will be recalculated before the collision step and is simply the average of all vertices of the body. <br /><strong class='bbc'><br /><br /><span style='font-size: 18px;'>Collision Response</span></strong><br /><br />Finally, we're done with collision detection. The only thing left to do is the collision response, which is luckily not that hard. As explained above, we just have to push the collision vertex and the collision edge apart by the collision vector and we're done. This is trivial for the collision vertex. Since we already ensured that the collision normal points at the first body which contains the collision vertex, we just have to add half of the collision vector to the position of the vertex:&nbsp;&nbsp;<br /><br /><pre class='prettyprint lang-auto linenums:0'>void Physics::ProcessCollision() {
&nbsp;&nbsp;Vec2 CollisionVector = CollisionInfo.Normal*CollisionInfo.Depth;

&nbsp;&nbsp;CollisionInfo.V-&gt;Position += CollisionVector*0.5f;
}</pre>For the edge case, this will become a bit more complicated. The edge consists of two vertices that will move differently, depending on where the collision vertex lies. The closer it lies to the one end of the edge, the more this end will move and vice-versa. This means that we first have to calculate where on the edge the collision vertex lies. This is done using the following equation: <br /><br /><a class='resized_img' rel='lightbox[fd542985689b454489faca5d169bdd73]' id='ipb-attach-url-5805-0-24240900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5805" title="Formula5.png - Size: 709bytes, Downloads: 220"><img src="http://uploads.gamedev.net/monthly_10_2011/ccs-8549-0-98095700-1319081150_thumb.png" id='ipb-attach-img-5805-0-24240900-1369216368' style='width:86;height:51' class='attach' width="86" height="51" alt="Attached Image: Formula5.png" /></a><br /><br /> Where V is the position of the collision vertex and E<sub class='bbc'>1</sub> and E<sub class='bbc'>2</sub> are the two vertices connected by the edge. t is the factor that determines where on the edge the vertex lies, reaching from 0 to 1. It doesn't matter whether we choose the X or the Y coordinate to calculate t, since both would result in the same value. The X case would look like this:<br /><br /><pre class='prettyprint lang-auto linenums:0'>Vertex* E1 = CollisionInfo.E-&gt;V1;
Vertex* E2 = CollisionInfo.E-&gt;V2;

float T = ( CollisionInfo.V-&gt;Position.X - CollisionVector.X - E1-&gt;Position.X )/(&nbsp;&nbsp;E2-&gt;Position.X - E1-&gt;Position.X );</pre>But be careful! If E2 lies directly above E1, the program would divide by zero. Therefore, we should build in a small check to avoid this:&nbsp;&nbsp;<br /><br /><pre class='prettyprint lang-auto linenums:0'>float T;
if( abs( E1-&gt;Position.X - E2-&gt;Position.X ) &gt; abs( E1-&gt;Position.Y - E2-&gt;Position.Y ) )
&nbsp;&nbsp;T = ( CollisionInfo.V-&gt;Position.X - CollisionVector.X - E1-&gt;Position.X )/(&nbsp;&nbsp;E2-&gt;Position.X - E1-&gt;Position.X );
else
&nbsp;&nbsp;T = ( CollisionInfo.V-&gt;Position.Y - CollisionVector.Y - E1-&gt;Position.Y )/(&nbsp;&nbsp;E2-&gt;Position.Y - E1-&gt;Position.Y );</pre>This basically divides by the X denominator if it is bigger than the Y denominator and vice-versa. <br /><br />We then use the following neat formula to calculate a scaling factor that ensures that the collision vertex lies on the collision edge after the collision response. We could derive it by solving a few equations, but I don't think the derivation is really important, so I'll just leave this here:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verletPhys/Formula6.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> Once we put all of this in code, we get:<br /><br /><pre class='prettyprint lang-auto linenums:0'>void Physics::ProcessCollision() {
&nbsp;&nbsp;Vec2 CollisionVector = CollisionInfo.Normal*CollisionInfo.Depth;

&nbsp;&nbsp;Vertex* E1 = CollisionInfo.E-&gt;V1;
&nbsp;&nbsp;Vertex* E2 = CollisionInfo.E-&gt;V2;

&nbsp;&nbsp;float T;
&nbsp;&nbsp;if( abs( E1-&gt;Position.X - E2-&gt;Position.X ) &gt; abs( E1-&gt;Position.Y - E2-&gt;Position.Y ) )
&nbsp;&nbsp;&nbsp;&nbsp;T = ( CollisionInfo.V-&gt;Position.X - CollisionVector.X - E1-&gt;Position.X )/(&nbsp;&nbsp;E2-&gt;Position.X - E1-&gt;Position.X);
&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;T = ( CollisionInfo.V-&gt;Position.Y - CollisionVector.Y - E1-&gt;Position.Y )/(&nbsp;&nbsp;E2-&gt;Position.Y - E1-&gt;Position.Y);

&nbsp;&nbsp;float Lambda = 1.0f/( T*T + ( 1 - T )*( 1 - T ) );

&nbsp;&nbsp;E1-&gt;Position -= CollisionVector*( 1 - T )*0.5f*Lambda;
&nbsp;&nbsp;E2-&gt;Position -= CollisionVector*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;&nbsp;*0.5f*Lambda;

&nbsp;&nbsp;CollisionInfo.V-&gt;Position += CollisionVector*0.5f;
}</pre>That's it. We're done with collision response - easy, wasn't it? <br /><br />All that's left to do is to put all of the methods we wrote into a single update method:<br /><br /><pre class='prettyprint lang-auto linenums:0'>void Physics::Update() {
&nbsp;&nbsp;UpdateForces();
&nbsp;&nbsp;UpdateVerlet();
&nbsp;&nbsp;IterateCollisions();
}</pre>IterateCollisions is a method that does multiple things. It iterates over all bodies, calls the respective UpdateEdges method, recalculates the body center and then does the collision detection (and the collision response, if necessary). Of course, it doesn't just do this once, but repeats those steps a few times. The more repetitions are made, the more realistic the physics will look. The reason was explained above (if you've forgotten, better read it again ;) ). <br /><br /><br /><span style='font-size: 18px;'><strong class='bbc'>Final Words</strong></span><br /><br />You can download a working implementation using GLUT and OGL as a Visual C++ 2008 project via the attached resource file. It is basically the same code as discussed in this article with a few optimizations and a very simple rendering and input function. I hope you enjoyed this article and found it useful. If you have any questions or suggestions, please let me know. Since I'm not a native English speaker, there might be a few mistakes here and there; please bear with it.]]></description>
		<pubDate>Thu, 19 Nov 2009 22:49:22 +0000</pubDate>
		<guid isPermaLink="false">9e69fd6d1c5d1cef75ffbe159c1f322e</guid>
	</item>
	<item>
		<title>2D Car Physics</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/2d-car-physics-r2443</link>
		<description><![CDATA[<br />
<br />
<h1>Introduction</h1><p>Someone asked me in the #gamedev IRC channel about how to make a 2d vehicle simulator. Instead of spending all day trying to explain the concepts to him, I decided just to write this tutorial.<br />
Please bear with me, this is my first tutorial.</p><br />
<p>So as I mentioned we&rsquo;re going to be learning how to make a basic 2d vehicle simulator. We&rsquo;re going to do it in C# and try do use as few hacks as possible. I&rsquo;ve broken the process<br />
down into three steps. First, we will learn how to setup a basic game application in C#.NET and how to draw some basic graphics (emphasis on basic.) Next, we will learn how to create a rigid body<br />
simulator using a simple Euler integrator with a variable time step. And last but not least, we will calculate vehicle forces simulating the tire patch contacting the road. And that&rsquo;s all there<br />
is to it! Let&rsquo;s get started.</p><br />
<h2>Math Requirements</h2>There are two ways to get through this tutorial: you can rush to the end and download the project, or you can read through it and hopefully I&rsquo;ll be able to explain things clearly. If you choose<br />
the second route, you&rsquo;re going to need to have a bit of math background. In a 2D simulation this is mostly in the form of a vector object. You&rsquo;ll need to be able to add, subtract, dot,<br />
and project 2 vectors. Also you&rsquo;ll need to be able to use a cross product. In 2D this is kind of a fake situation since we know the result will point in the screen&rsquo;s direction, so the<br />
result is returned as a scalar. If you&rsquo;re not familiar with any of these terms please look them up now. I tried to write this tutorial without using a matrix object but eventually I cracked and<br />
used the Drawing2D.Matrix object to transform and inversely transform a vector between spaces. If you don&rsquo;t know what I&rsquo;m talking about let me give you an example. Let&rsquo;s say your<br />
personal body is your &ldquo;local space&rdquo; and the room you&rsquo;re sitting in is the &ldquo;world space.&rdquo; Let&rsquo;s also say that your monitor is the front of the world, and your eyes<br />
look in the forward direction of your local space. If you turn sideways, and transform the monitor&rsquo;s direction into your space, it is now the side direction. Vise versa, if you transform your<br />
facing direction into world space, it is the opposite side direction. This is a critical concept so please, if that didn&rsquo;t make sense, do some searching on Google for transforming between<br />
spaces. The reason this is so important is because we will be doing all of our vehicle force calculations in local vehicle space. Yet the vehicle itself, and its integrator, persist in world space.<br />
<h1>Phase One</h1><p>Phase one, as I mentioned, is to create the renderer; something graphical so we can actually see what our simulation is doing. This will make it a lot easier to debug. Create a windows form<br />
project in C# and place a picturebox control on it (name it "screen"). This control is where we will display our simulation. We could just start drawing to this screen but we&rsquo;re going to be<br />
using double buffering as well to avoid flicker, so we need to create the back buffer now. That bit of code looks like this.</p><br />
<pre class="code">

Graphics graphics; //gdi+

Bitmap backbuffer;

Size buffersize;



//intialize rendering

private void Init(Size size)

{

&nbsp;&nbsp;//setup rendering device

&nbsp;&nbsp;buffersize = size;

&nbsp;&nbsp;backbuffer = new Bitmap(buffersize.Width, buffersize.Height);

&nbsp;&nbsp;graphics = Graphics.FromImage(backbuffer);

}

</pre><br />
The <code>Init</code> function must be called with the size of the &ldquo;screen&rdquo; control that you created on the form. This will create a bitmap &ldquo;backbuffer&rdquo; to which we can do our<br />
offscreen rendering. We&rsquo;ll then take this backbuffer and draw it to the screen to illiminate any flickering. This is how you draw a basic shape to the backbuffer, and present it to the screen.<br />
<pre class="code">

//main rendering function

private void Render(Graphics g)

{

&nbsp;&nbsp;//clear back buffer

&nbsp;&nbsp;graphics.Clear(Color.Black);



&nbsp;&nbsp;//draw to back buffer

&nbsp;&nbsp;graphics.DrawLine(new Pen(Color.Yellow), 1, 0, 1, 5);



&nbsp;&nbsp;//present back buffer

&nbsp;&nbsp;g.DrawImage(backbuffer, new Rectangle(0, 0, buffersize.Width, buffersize.Height), 0, 0, buffersize.Width, buffersize.Height, GraphicsUnit.Pixel);

}

</pre><br />
This function is called from the <code>on_paint</code> method of the "screen" control placed on our form. The <code>on_paint</code> method has a parameter &ldquo;e&rdquo; that contains a graphics<br />
object we can use to draw to the control. We pass this graphics object to the render function and as you can see, we draw the backbuffer to it as the very last step.<br />
<p>Now by default, the graphics of a picturebox control has the origin in the top-left corner, and extends downward for +y and to the right for +x. This is highly unnatural for most cases. In<br />
addition to that, it has extremely large units. Since we will be simulating in the metric system, I recommend introducing a scale factor to scale up the simulation and make it much more visible. The<br />
transformation looks like this and takes place after <code>Graphics.Clear()</code> is called.</p><br />
<pre class="code">

graphics.ResetTransform();

graphics.ScaleTransform(screenScale, -screenScale);

graphics.TranslateTransform(buffersize.Width / 2.0f / screenScale, -buffersize.Height / 2.0f / screenScale);

</pre><br />
That transformation flips the Y axis so that +Y points up. It simultaneously scales the space by our &ldquo;screenScale&rdquo; factor (something like 3.0f should work fine). Next, we translate the<br />
graphics space into the center of the screen control by half of the screen dimensions divided by our scale (since we are now in the scaled space.)<br />
<p>Now the line should draw starting right at the center of the screen.</p><br />
<h2>Forms Wiring</h2><p>Up until now, I havn&rsquo;t explained how to connect all the functions. The first thing you&rsquo;ll need to do is call the <code>Render</code> function from your <code>on_paint</code> event.<br />
Next, you&rsquo;ll need to create a function that gets called continously to update the simulation. It is preferred to call this function on the <code>Application_Idle</code> event. So create an<br />
event handler for <code>Application_Idle</code> and have it call your <code>DoFrame</code> function. Inside this function you&rsquo;ll need to</p><br />
<ol class='bbc'><li>Process input</li><li>Update the simulation</li><li>Invalidate the screen control</li></ol>The last step is so that an <code>On_Paint</code> gets triggerd and the simulation gets drawn. You&rsquo;ll also want to wire up some &ldquo;key_down&rdquo; and &ldquo;key_up&rdquo; events to keep<br />
track of key states.<br />
<h2>The Timer</h2><p>Since we don&rsquo;t know how often our <code>DoFrame</code> function will be getting called, we need to code everything to handle a variable time step. To utilize this we must measure the time<br />
between <code>DoFrame</code> calls. So I&rsquo;ll introduce the timer which, very simply, queries the number of milliseconds that have passed since the computer was turned on. So we store this number<br />
every frame and on a subsequent frame we compute the difference, which gives us the amount of time that has passed since the last frame. Here is my very simple timer object. <strong class='bbc'>Note:</strong> you will<br />
need to call <code>GetETime</code> in your intialize function in order to clear the timer, otherwise the first call to it will return the amount of time that has passed since the computer was turned<br />
on.</p><br />
<pre class="code">

class Timer

{

&nbsp;&nbsp;//store last time sample

&nbsp;&nbsp;private int lastTime = Environment.TickCount;

&nbsp;&nbsp;private float etime;



&nbsp;&nbsp;//calculate and return elapsed time since last call

&nbsp;&nbsp;public float GetETime()

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;etime = (Environment.TickCount - lastTime) / 1000.0f;

&nbsp;&nbsp;&nbsp;&nbsp;lastTime = Environment.TickCount;



&nbsp;&nbsp;&nbsp;&nbsp;return etime;

&nbsp;&nbsp;}

}

</pre><br />
<h2>Conclusion of Phase One</h2><p>So up until now we&rsquo;ve covered: setting up a rendering surface using GDI, wiring a form to process a game loop and draw it to the screen, and computing the time that has passed since the last<br />
frame. Our application looks like this:</p><br />
<pre class="code">

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Text;

using System.Windows.Forms;



namespace racing_simulation_2d

{

&nbsp;&nbsp;//our main application form

&nbsp;&nbsp;public partial class frmMain : Form

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;//graphics

&nbsp;&nbsp;&nbsp;&nbsp;Graphics graphics; //gdi+

&nbsp;&nbsp;&nbsp;&nbsp;Bitmap backbuffer;

&nbsp;&nbsp;&nbsp;&nbsp;Size buffersize;

&nbsp;&nbsp;&nbsp;&nbsp;const float screenScale = 3.0f;

&nbsp;&nbsp;&nbsp;&nbsp;Timer timer = new Timer();



&nbsp;&nbsp;&nbsp;&nbsp;//keyboard controls

&nbsp;&nbsp;&nbsp;&nbsp;bool leftHeld = false, rightHeld = false;

&nbsp;&nbsp;&nbsp;&nbsp;bool upHeld = false, downHeld = false;



&nbsp;&nbsp;&nbsp;&nbsp;//vehicle controls

&nbsp;&nbsp;&nbsp;&nbsp;float steering = 0; //-1 is left, 0 is center, 1 is right

&nbsp;&nbsp;&nbsp;&nbsp;float throttle = 0; //0 is coasting, 1 is full throttle

&nbsp;&nbsp;&nbsp;&nbsp;float brakes = 0; //0 is no brakes, 1 is full brakes



&nbsp;&nbsp;&nbsp;&nbsp;public frmMain()

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application.Idle += new EventHandler(ApplicationIdle);



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;screen.Paint += new PaintEventHandler(screen_Paint);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.KeyDown += new KeyEventHandler(onKeyDown);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.KeyUp += new KeyEventHandler(onKeyUp);



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Init(screen.Size);

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;//intialize rendering

&nbsp;&nbsp;&nbsp;&nbsp;private void Init(Size size)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//setup rendering device

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffersize = size;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;backbuffer = new Bitmap(buffersize.Width, buffersize.Height);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics = Graphics.FromImage(backbuffer);



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer.GetETime(); //reset timer

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;//main rendering function

&nbsp;&nbsp;&nbsp;&nbsp;private void Render(Graphics g)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//clear back buffer

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.Clear(Color.Black);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.ResetTransform();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.ScaleTransform(screenScale, -screenScale);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.TranslateTransform(buffersize.Width / 2.0f /

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;screenScale, -buffersize.Height / 2.0f / screenScale);



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//draw to back buffer

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DrawScreen();



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//present back buffer

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.DrawImage(backbuffer, new Rectangle(0, 0, buffersize.Width,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffersize.Height), 0, 0, buffersize.Width, 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffersize.Height, GraphicsUnit.Pixel);

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;//draw the screen

&nbsp;&nbsp;&nbsp;&nbsp;private void DrawScreen()

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//draw our simulation here

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;//process game logic

&nbsp;&nbsp;&nbsp;&nbsp;private void DoFrame()

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//get elapsed time since last frame

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float etime = timer.GetETime();



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//process input

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProcessInput();



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;////////////////////////////////

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//integrate our simulation here

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;////////////////////////////////



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//redraw our screen

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;screen.Invalidate();

&nbsp;&nbsp;&nbsp;&nbsp;}





&nbsp;&nbsp;&nbsp;&nbsp;//process keyboard input

&nbsp;&nbsp;&nbsp;&nbsp;private void ProcessInput()

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (leftHeld)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steering = -1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (rightHeld)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steering = 1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;steering = 0;



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (upHeld)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throttle = 1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throttle = 0;



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (downHeld)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;brakes = 1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;brakes = 0;

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;private void onKeyDown(object sender, KeyEventArgs e)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (e.KeyCode)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Left:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leftHeld = true;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Right:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rightHeld = true;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Up:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;upHeld = true;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Down:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;downHeld = true;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default: //no match found

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return; //return so handled dosnt get set

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//match found

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.Handled = true;

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;private void onKeyUp(object sender, KeyEventArgs e)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (e.KeyCode)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Left:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leftHeld = false;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Right:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rightHeld = false;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Up:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;upHeld = false;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case Keys.Down:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;downHeld = false;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default: //no match found

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return; //return so handled dosnt get set

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//match found

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.Handled = true;

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;//rendering - only when screen is invalidated

&nbsp;&nbsp;&nbsp;&nbsp;private void screen_Paint(object sender, PaintEventArgs e)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Render(e.Graphics);

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;//when the os gives us time, run the game

&nbsp;&nbsp;&nbsp;&nbsp;private void ApplicationIdle(object sender, EventArgs e)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// While the application is still idle, run frame routine.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoFrame();

&nbsp;&nbsp;&nbsp;&nbsp;}



&nbsp;&nbsp;&nbsp;&nbsp;private void MenuExit_Click(object sender, EventArgs e)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Close();

&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;}



&nbsp;&nbsp;//keep track of time between frames

&nbsp;&nbsp;class Timer

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;//store last time sample

&nbsp;&nbsp;&nbsp;&nbsp;private int lastTime = Environment.TickCount;

&nbsp;&nbsp;&nbsp;&nbsp;private float etime;



&nbsp;&nbsp;&nbsp;&nbsp;//calculate and return elapsed time since last call

&nbsp;&nbsp;&nbsp;&nbsp;public float GetETime()

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;etime = (Environment.TickCount - lastTime) / 1000.0f;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastTime = Environment.TickCount;



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return etime;

&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;}

}

</pre><br />
<h1>Phase Two - Rigid Body Simulation</h1><p>Ok, now we&rsquo;re getting into some good stuff here. Let's put everything we just covered on the back burner now and talk about some physics. We&rsquo;re going to be using a very simple Euler<br />
integration method. Basically, each frame we accumulate a bunch of forces (in our case from each wheel of the vehicle) and calculate the resultant acceleration, which is in the form of A=F/M (the<br />
same as F=MA, Newton&rsquo;s second law of motion). We use this to modify Newton&rsquo;s first law of motion, &ldquo;an object in motion stays in motion&hellip;&rdquo; So we calculate our A, and we<br />
integrate it into our V. Without an A, V would be constant, hence staying in motion, if no forces should act on it. Newton's third law gets applied in the form that any potential force the vehicle is<br />
applying to the ground, gets applied in the opposite direction to the vehicle (I'll explain this in the vehicle section). This topic is much easier to explain with symbols. So, P is our vehicle<br />
position, V is its linear velocity, F is the net force acting on it, M is its mass, A is the resultant acceleration, and T is the time step (the value our timer gave us from the last frame).</p><br />
<pre>

&nbsp;&nbsp;A = F / M

&nbsp;&nbsp;V = V + A * T

&nbsp;&nbsp;P = P + V * T

</pre><br />
So with a constant mass, and some force, we will generate acceleration, which will in turn generate velocity, which will in turn generate a displacement (a change in P).<br />
<p>This is a basic linear rigid body simulator. Each frame, we total up some F, integrate it, and then zero out F to restart the accumulation the next frame. Now let&rsquo;s talk about rotation. The<br />
angular case is nearly identical to the linear case (especially in 2D). Instead of P we have an Angle, instead of V we have an Angular Velocity, instead of F we have a torque, and instead of M we<br />
have inertia. So the angular model looks like this</p><br />
<pre>

&nbsp;&nbsp;AngA = Torque / Inertia

&nbsp;&nbsp;AngV = AngV + AngA * T

&nbsp;&nbsp;Angle = Angle + AngV * T

</pre><br />
Simple huh? Now you may be wondering where this Torque came from. A torque is generated every time you apply a force. Lay a book down on your desk and push on the corner of it. The book should slide<br />
across the desk, but it should also begin to rotate. The slide is caused by the force. This rotation is caused by the torque, and the magnitude of the torque is directly proportional to how far away<br />
from the center of the object the force was applied. If you applied the force directly to the center of the object, the torque would be zero. We need to construct an <code>AddForce</code> function<br />
for our rigid body. This is what gets called every frame, once per wheel, to accumulate the chassis' rigid body force/torque. The linear case is simple, Force = Force + newForce. The angular case is<br />
a little trickier. We take the cross product of the force direction and the torque arm (the offset between where the force was applied and the center of mass of the body.) In 2D, this results in a<br />
scalar value that we can just add to Torque. So, Torque = Torque + TorqueArm.Cross(Force)<br />
<p>This is what that bit of code looks like. % is the cross product operator for my vector class.</p><br />
<pre class="code">

public void AddForce(Vector worldForce, Vector worldOffset)

{

&nbsp;&nbsp;//add linar force

&nbsp;&nbsp;m_forces += worldForce;

&nbsp;&nbsp;//and it's associated torque

&nbsp;&nbsp;m_torque += worldOffset % worldForce;

}

</pre><br />
You&rsquo;ll notice the &ldquo;world" prefix on the parameters. This is because all computation of the rigid body happens in world space. So as your book is rotating on the desk, the worldOffset<br />
value is changing, even though your finger is not moving on the book (this would be the relativeOffset). So if we know we&rsquo;re applying a force &ldquo;across the book, at the top right corner" we<br />
need to convert both &ldquo;across" and &ldquo;top right corner" into world space vectors, then add them to the rigid body.<br />
<h2>Code Dump</h2><p>Here is my rigid body object. You&rsquo;ll notice all the properties I mentioned above. It has a <code>Draw</code> function which will draw its rectangle to the provided graphics object. It has an<br />
<code>AddForce</code> function, a space conversion method, to and from world space (very handy), and a function that returns the velocity of a point on the body (in world space). This point velocity<br />
is a combination of the linear velocity and the angular velocity. But the angular velocity is multiplied by the distance the point is from the center of rotation and perpendicular to its offset<br />
direction. So to kill two birds with one stone, I simply find the orthogonal vector to the point offset and multiply it by the angular velocity (then add the linear velocity.)</p><br />
<p>One thing you may be curious about is how I calculate the inertia value. That is a generalized formula I found at <a href='http://howard.nebrwesleyan.edu/hhmi/fellows/pgomez/inertforms.html' class='bbc_url' title='External link' rel='nofollow external'>this<br />
link</a>.</p><br />
<pre class="code">

//our simulation object

class RigidBody

{

&nbsp;&nbsp;//linear properties

&nbsp;&nbsp;private Vector m_position = new Vector();

&nbsp;&nbsp;private Vector m_velocity = new Vector();

&nbsp;&nbsp;private Vector m_forces = new Vector();

&nbsp;&nbsp;private float m_mass;



&nbsp;&nbsp;//angular properties

&nbsp;&nbsp;private float m_angle;

&nbsp;&nbsp;private float m_angularVelocity;

&nbsp;&nbsp;private float m_torque;

&nbsp;&nbsp;private float m_inertia;



&nbsp;&nbsp;//graphical properties

&nbsp;&nbsp;private Vector m_halfSize = new Vector();

&nbsp;&nbsp;Rectangle rect = new Rectangle();

&nbsp;&nbsp;private Color m_color;



&nbsp;&nbsp;public RigidBody()

&nbsp;&nbsp;{ 

&nbsp;&nbsp;&nbsp;&nbsp;//set these defaults so we dont get divide by zeros

&nbsp;&nbsp;&nbsp;&nbsp;m_mass = 1.0f; 

&nbsp;&nbsp;&nbsp;&nbsp;m_inertia = 1.0f; 

&nbsp;&nbsp;}



&nbsp;&nbsp;//intialize out parameters

&nbsp;&nbsp;public void Setup(Vector halfSize, float mass, Color color)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;//store physical parameters

&nbsp;&nbsp;&nbsp;&nbsp;m_halfSize = halfSize;

&nbsp;&nbsp;&nbsp;&nbsp;m_mass = mass;

&nbsp;&nbsp;&nbsp;&nbsp;m_color = color;

&nbsp;&nbsp;&nbsp;&nbsp;m_inertia = (1.0f / 12.0f) * (halfSize.X * halfSize.X)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * (halfSize.Y * halfSize.Y) * mass;



&nbsp;&nbsp;&nbsp;&nbsp;//generate our viewable rectangle

&nbsp;&nbsp;&nbsp;&nbsp;rect.X = (int)-m_halfSize.X;

&nbsp;&nbsp;&nbsp;&nbsp;rect.Y = (int)-m_halfSize.Y;

&nbsp;&nbsp;&nbsp;&nbsp;rect.Width = (int)(m_halfSize.X * 2.0f);

&nbsp;&nbsp;&nbsp;&nbsp;rect.Height = (int)(m_halfSize.Y * 2.0f);

&nbsp;&nbsp;}



&nbsp;&nbsp;public void SetLocation(Vector position, float angle)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;m_position = position;

&nbsp;&nbsp;&nbsp;&nbsp;m_angle = angle;

&nbsp;&nbsp;}



&nbsp;&nbsp;public Vector GetPosition()

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;return m_position;

&nbsp;&nbsp;}



&nbsp;&nbsp;public void Update(float timeStep)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;//integrate physics

&nbsp;&nbsp;&nbsp;&nbsp;//linear

&nbsp;&nbsp;&nbsp;&nbsp;Vector acceleration = m_forces / m_mass;

&nbsp;&nbsp;&nbsp;&nbsp;m_velocity += acceleration * timeStep;

&nbsp;&nbsp;&nbsp;&nbsp;m_position += m_velocity * timeStep;

&nbsp;&nbsp;&nbsp;&nbsp;m_forces = new Vector(0,0); //clear forces



&nbsp;&nbsp;&nbsp;&nbsp;//angular

&nbsp;&nbsp;&nbsp;&nbsp;float angAcc = m_torque / m_inertia;

&nbsp;&nbsp;&nbsp;&nbsp;m_angularVelocity += angAcc * timeStep;

&nbsp;&nbsp;&nbsp;&nbsp;m_angle += m_angularVelocity * timeStep;

&nbsp;&nbsp;&nbsp;&nbsp;m_torque = 0; //clear torque

&nbsp;&nbsp;}



&nbsp;&nbsp;public void Draw(Graphics graphics, Size buffersize)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;//store transform, (like opengl's glPushMatrix())

&nbsp;&nbsp;&nbsp;&nbsp;Matrix mat1 = graphics.Transform;



&nbsp;&nbsp;&nbsp;&nbsp;//transform into position

&nbsp;&nbsp;&nbsp;&nbsp;graphics.TranslateTransform(m_position.X, m_position.Y);

&nbsp;&nbsp;&nbsp;&nbsp;graphics.RotateTransform(m_angle/(float)Math.PI * 180.0f);



&nbsp;&nbsp;&nbsp;&nbsp;try

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//draw body

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.DrawRectangle(new Pen(m_color), rect);



&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//draw line in the "forward direction"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.DrawLine(new Pen(Color.Yellow), 1, 0, 1, 5);

&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;catch(OverflowException exc)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//physics overflow :(

&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;



&nbsp;&nbsp;&nbsp;&nbsp;//restore transform

&nbsp;&nbsp;&nbsp;&nbsp;graphics.Transform = mat1;

&nbsp;&nbsp;}



&nbsp;&nbsp;//take a relative vector and make it a world vector

&nbsp;&nbsp;public Vector RelativeToWorld(Vector relative)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;Matrix mat = new Matrix();

&nbsp;&nbsp;&nbsp;&nbsp;PointF[] vectors = new PointF[1];



&nbsp;&nbsp;&nbsp;&nbsp;vectors[0].X = relative.X;

&nbsp;&nbsp;&nbsp;&nbsp;vectors[0].Y = relative.Y;



&nbsp;&nbsp;&nbsp;&nbsp;mat.Rotate(m_angle / (float)Math.PI * 180.0f);

&nbsp;&nbsp;&nbsp;&nbsp;mat.TransformVectors(vectors);



&nbsp;&nbsp;&nbsp;&nbsp;return new Vector(vectors[0].X, vectors[0].Y);

&nbsp;&nbsp;}



&nbsp;&nbsp;//take a world vector and make it a relative vector

&nbsp;&nbsp;public Vector WorldToRelative(Vector world)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;Matrix mat = new Matrix();

&nbsp;&nbsp;&nbsp;&nbsp;PointF[] vectors = new PointF[1];



&nbsp;&nbsp;&nbsp;&nbsp;vectors[0].X = world.X;

&nbsp;&nbsp;&nbsp;&nbsp;vectors[0].Y = world.Y;



&nbsp;&nbsp;&nbsp;&nbsp;mat.Rotate(-m_angle / (float)Math.PI * 180.0f);

&nbsp;&nbsp;&nbsp;&nbsp;mat.TransformVectors(vectors);



&nbsp;&nbsp;&nbsp;&nbsp;return new Vector(vectors[0].X, vectors[0].Y);

&nbsp;&nbsp;}



&nbsp;&nbsp;//velocity of a point on body

&nbsp;&nbsp;public Vector PointVel(Vector worldOffset)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;Vector tangent = new Vector(-worldOffset.Y, worldOffset.X);

&nbsp;&nbsp;&nbsp;&nbsp;return tangent * m_angularVelocity + m_velocity;

&nbsp;&nbsp;}



&nbsp;&nbsp;public void AddForce(Vector worldForce, Vector worldOffset)

&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;//add linar force

&nbsp;&nbsp;&nbsp;&nbsp;m_forces += worldForce;

&nbsp;&nbsp;&nbsp;&nbsp;//and it's associated torque

&nbsp;&nbsp;&nbsp;&nbsp;m_torque += worldOffset % worldForce;

&nbsp;&nbsp;}

}

</pre><br />
<h2>Testing</h2><p>To make sure your rigid body works, instantiate one in your <code>Init()</code> function and apply a force with some offset in the <code>DoFrame</code> function. If you apply a constant<br />
worldOffset, the body will continue to accelerate its angular velocity. If you take your offset and run it through the <code>RelativeToWorld</code> function, the body will angularly accelerate in one<br />
direction and then come back the other way, like a pendulum as the point the force is applied to changes. Play around with this for a while, this has to work and make sense in order for the next<br />
section to work.</p><br />
<h1>Phase Three - The Vehicle</h1><p>Assuming everything has gone well above, you should have a rigid body actor in your scene that you can apply forces to and watch move around. Now all that&rsquo;s left is to calculate these forces<br />
in a way that will simulate a vehicle. For that we are going to need a vehicle object. I recommend deriving directly from you rigid body object since the chassis is essentially a rigid body. In<br />
addition to that we will need to construct a &ldquo;wheel" object. This wheel will handle the steering direction of each wheel, the velocity the wheel is spinning, and calculate the forces that that<br />
particular wheel applies to the chassis (all in vehicle space). Since our wheel is known to be constrained to the vehicle, we don&rsquo;t need to simulate it as another rigid body (though you could,<br />
but not in the 2D case.) We will simply duplicate the angular properties of the rigid body in the wheel object.</p><br />
<p>So we&rsquo;ll need: Wheel Velocity, Wheel Inertia, and and Wheel Torque. We&rsquo;ll also need the relative offset of the wheel in the vehicle space, and the angle the wheel is facing (this is<br />
constant for the back wheels, unless you want 4 wheel steering.) Just like the rigid body, the wheel's torque function acts as an accumulator, we add torques to it and after it gets integrated the<br />
torque is zeroed out. The <code>AddTorque</code> function is where you will apply a wheel torque from either the transmission (to make you go) or from the brakes (to make you stop). Internally the<br />
wheel will generate a torque caused by the friction on the road.</p><br />
<p>The wheel object also needs a <code>SetSteering</code> function. This function calculates two vectors: an effective Side Direction, and an effective Forward Direction (both in vehicle space) that<br />
the tire patch will act on. The force applied on the tire by the ground acting in the side direction will directly translate into the chassis. Meanwhile the force acting in the forward direction will<br />
not only act on the chassis, but it will induce a rotation of the tire. Here is the <code>SetSteering</code> function; you will see I used the <code>Drawing2D.Matrix</code> to transform the initial<br />
forward and side vectors by the steering angle (I had to convert the vectors to &ldquo;points" in order to transform them by the matrix.)</p><br />
<pre class="code">

public void SetSteeringAngle(float newAngle)

{

&nbsp;&nbsp;Matrix mat = new Matrix();

&nbsp;&nbsp;PointF[] vectors = new PointF[2];



&nbsp;&nbsp;//foward vector

&nbsp;&nbsp;vectors[0].X = 0;

&nbsp;&nbsp;vectors[0].Y = 1;

&nbsp;&nbsp;//side vector

&nbsp;&nbsp;vectors[1].X = -1;

&nbsp;&nbsp;vectors[1].Y = 0;



&nbsp;&nbsp;mat.Rotate(newAngle / (float)Math.PI * 180.0f);

&nbsp;&nbsp;mat.TransformVectors(vectors);



&nbsp;&nbsp;m_forwardAxis = new Vector(vectors[0].X, vectors[0].Y);

&nbsp;&nbsp;m_sideAxis = new Vector(vectors[1].X, vectors[1].Y);

}

</pre><br />
<h2>Force Calculation</h2><p>So, if the vehicle is sitting there not moving with its front wheels turned, and you push it, a force will be generated in the opposite direction you push. This force gets projected onto these two<br />
directions. If the wheels were straight there would be no side force. So the vehicle would simply roll forward. But since the wheels are turned, there is a bit of the force that acts in the<br />
&ldquo;effective side direction&rdquo; so we apply an opposite force to the chassis. This is what causes you to turn when you steer the wheels. To get this force that gets projected onto the two<br />
directions, we need to first determine the velocity difference between the tire patch and the road. If the wheel is spinning at the same speed the ground is wizzing by, then there is effectively no<br />
force acting on the vehicle. But as soon as you slam on the brakes and stop the wheel, there is a huge velocity difference and this is what causes the force that stops your car.</p><br />
<p>So here is the process broken down into 6 steps, for each wheel.</p><br />
<p><strong class='bbc'>Step 1</strong>, calculate the effective direction vectors (with steering function).</p><br />
<p><strong class='bbc'>Step 2</strong>, calculate velocity difference. The ground speed is determined via the &ldquo;PointVel&rdquo; function on the rigidbody, given the current wheel&rsquo;s world offset.</p><br />
<p><strong class='bbc'>Step 3</strong>, project this velocity onto the two effective directions.</p><br />
<p><strong class='bbc'>Step 4</strong>, generate an equal and opposite force for the two direction and call this the &ldquo;response force&rdquo;. This is what gets added to the chassis for each wheel.</p><br />
<p><strong class='bbc'>Step 5</strong>, calculate the torque that the forward response force created on the wheel, and add this to the wheel torque.</p><br />
<p><strong class='bbc'>Step 6</strong>, integrate the wheel torques into the wheel velocity.</p><br />
<p>That bit of code looks like this:</p><br />
<pre class="code">

public Vector CalculateForce(Vector relativeGroundSpeed, float timeStep)

{

&nbsp;&nbsp;//calculate speed of tire patch at ground

&nbsp;&nbsp;Vector patchSpeed = -m_forwardAxis * m_wheelSpeed *

&nbsp;&nbsp;&nbsp;&nbsp;m_wheelRadius;



&nbsp;&nbsp;//get velocity difference between ground and patch

&nbsp;&nbsp;Vector velDifference = relativeGroundSpeed + patchSpeed;



&nbsp;&nbsp;//project ground speed onto side axis

&nbsp;&nbsp;float forwardMag = 0;

&nbsp;&nbsp;Vector sideVel = velDifference.Project(m_sideAxis);

&nbsp;&nbsp;Vector forwardVel = velDifference.Project(m_forwardAxis, out forwardMag);



&nbsp;&nbsp;//calculate super fake friction forces

&nbsp;&nbsp;//calculate response force

&nbsp;&nbsp;Vector responseForce = -sideVel * 2.0f;

&nbsp;&nbsp;responseForce -= forwardVel;



&nbsp;&nbsp;//calculate torque on wheel

&nbsp;&nbsp;m_wheelTorque += forwardMag * m_wheelRadius;



&nbsp;&nbsp;//integrate total torque into wheel

&nbsp;&nbsp;m_wheelSpeed += m_wheelTorque / m_wheelInertia * timeStep;



&nbsp;&nbsp;//clear our transmission torque accumulator

&nbsp;&nbsp;m_wheelTorque = 0;



&nbsp;&nbsp;//return force acting on body

&nbsp;&nbsp;return responseForce;

}

</pre><br />
<h2>Almost Done!</h2><p>We&rsquo;re in the home stretch here now. Now we have a way to calculate the force each wheel generates on the chassis. Every frame, all we have to do is set our transmission and brake torques,<br />
our steering angle, calculate each wheel force, add these to the chassis, and integrate the rigid body. Badaboom badabing, vehicle done! :)</p><br />
<h1>Conclusion</h1><p>Here is the <a href='http://downloads.gamedev.net/features/programming/2dcarphys/racing%20simulation%202d.zip' class='bbc_url' title='External link' rel='nofollow external'>entire source code</a> for the project. If you have any questions or comments please<br />
feel free to post them here and either I can make things more clear or maybe someone else could offer some better expertise. If you&rsquo;d like you can email me at Kincaid05 on google's fine<br />
emailing service.</p><br />
<p>Thanks for reading and I hope this was informative.<br />
-Matt Kincaid</p><br />
<br />
]]></description>
		<pubDate>Sat, 15 Dec 2007 02:36:46 +0000</pubDate>
		<guid isPermaLink="false">8e9cd191d3eaf58c4d262677292270e5</guid>
	</item>
	<item>
		<title>Randomness without Replacement</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/randomness-without-replacement-r2206</link>
		<description><![CDATA[A blade spider is at your throat. It hits and you miss. It hits again and you miss again. And again and again, until there's nothing left of you to hit. You're dead and there's a two-ton arachnid gloating over your corpse. Impossible? No. Improbable? Yes. But given enough players and given enough time, the improbable becomes almost certain. It wasn't that the blade spider was hard, it was just bad luck. How frustrating. It's enough to make a player want to quit.<br /><br /> "Game mechanics" is one of those terms that every designer talks about. Everybody agrees that game mechanics is an important subject within game design. Yet almost nobody discusses, in detail, how the design of a mechanism may satisfy a player. In this article, I'm going to dissect a mechanism germane to role-playing games, the randomization function for determining whether a player's attack hits or misses its target. Roll up your sleeves for a modest amount of mathematics—just enough to demonstrate what a game mechanism is.<br /><br /> <br /><strong class='bbc'>Reducing Frustration</strong><br /> In the opening story, one way to prevent frustrating results is to reduce randomness. Several massively multiplayer role-playing games, such as <em class='bbc'>Lineage 2</em>, reduce variance of hits and misses and reduce the variance of damage. Reason? As Alex Chacha stated, if the probability for a string of failures is above zero, then the probability for that string occurring at least once in the lifespan of a long game is very high ("Randomness," <em class='bbc'><a href='http://www.kanga.nu' class='bbc_url' title='External link' rel='nofollow external'>MUD-Dev Mailing List</a></em>, February 2004.). And once it does, it is a frustrating experience. So, in this article, let us call such a long string of consecutive failures <em class='bbc'>frustration</em>.<br /><br /> To reduce the occurrence of frustration, one possibility is to change the mechanism that models the randomness. For instance, let's change the method from sampling with replacement to sampling without replacement.<br /><br /> But first, to understand this lingo, we need to know a little probability theory. It shouldn't be too hard for us, since probability theory was commissioned, in 1654, as the science of dice and card games. So we're in familiar territory: the mathematics of dice and cards. In probability, when a result of a random function is taken, it is called <em class='bbc'>sampling</em>. There are two basic methods for sampling: <em class='bbc'>with replacement</em> (as in a die roll), or <em class='bbc'>without replacement</em> (as in drawing cards from a deck). The difference seems simple, but the implications, as we shall see, may be dramatic.<br /><br /> Back to the problem at hand: To reduce frustration, change from sampling with replacement to sampling without replacement. Basically, instead of rolling a die, draw a card. Let's use Open Game Content (OGC) as shared vocabulary. This is the system that Wizards of the Coasts based <em class='bbc'>Dungeons & Dragons</em> 3.5 on. So, instead of rolling a twenty-sided die (1d20), draw from a deck of twenty cards, perfectly shuffled.<br /><br /> The key difference in the mechanism may be illustrated by a deck of cards alone. With replacement, after each draw, the card is shuffled back into the deck. Without replacement, the drawn cards are then discarded. Only after the deck has been consumed is the discard pile shuffled to reconstitute a full deck. To keep the analysis simple and further reduce frustration, remove one of the hit cards from the deck, and shuffle the remaining 19 cards. Then place this hit card on top of the shuffled deck.<br /><br /> Suppose, in OGC terms, that the player has a melee attack of +0, then he would hit armor class 11 about 50% of the time. This may be modeled, with replacement, as a probability of success of 50%. To model this probability, without replacement, imagine there are 10 hit cards and 10 miss cards. If details are required to account for modifiers, then there may be 20 cards, valued from 1 to 20. Either way, 10 of these cards will result in a hit, and 10 will result in a miss. Without replacement, the player could sample 10 misses in a row, but the probability of this frustration is much less than by sampling with replacement. But how much less probable is it?<br /><br /> <br /><strong class='bbc'>Counting Cards</strong><br /> Calculating the probability of frustration with replacement is simple. Suppose <em class='bbc'>f</em> equals the number of consecutive misses that will result in frustration, which we shall consider at 10 consecutive misses. With replacement, this is equivalent to a binomial distribution with a given probability of missing being the measure of consecutive trials. With a probability of a single failure being 50%, we may understand Equation 1. This logic is simple. The probability of failure ten times a row is the multiplication of the probability of failure ten times. So, in a sequence of ten attacks, the probability of frustration is about one in a thousand.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image001.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 1. The probability of frustration, with replacement.<br /><br /> Calculating the probability of frustration without replacement is complicated, because the probability of each attack hitting depends on the success or failure of the previous attacks. A general method to solve problems of discrete probability is to count all the ways in which the event may occur, and divide this number by the count of all ways in which any outcome may occur.<br /><br /> In order to count possible occurrences of frustration, recall that the probability equals the number of ways to have a consecutive string of 10 misses out of 20 attacks. To simplify analysis and further limit frustration, set the first attack to be one of the hits. This corresponds to rolling a natural 20 in OGC. Since frustration (i.e., the string of 10 misses) is immutable, this is equivalent to the number of ways to select a single string of 1 out of 10. Recalling the basics of <em class='bbc'>combinatorics</em> (which is the mathematics of counting), this simplification makes computation trivial, as shown in Equation 2.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image002.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 2. How many ways an attacker may be frustrated, without replacement.<br /><br /> Then count the total number of ways to have 9 hits and 10 misses in a sequence of 19 attacks, as shown in Equation 3.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image003.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 3. How many ways an attacker may attack, without replacement.<br /><br /> By dividing the count of frustrations by the count of all attacks, we arrive at the probability of frustration, as demonstrated in Equation 4. So, the probability of frustration in the course of twenty attacks is about one in ten thousand.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image004.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 4. The probability of frustration, without replacement.<br /><br /> By dividing the solution of Equation 4 by Equation 1, we see that the sample without replacement decreases the probability of frustration by an order of magnitude, shown in Equation 5. To keep the analysis simple, multiply the probability of frustration with replacement by 2 (or divide without replacement by 2), since the probability in a sequence of 20 attacks (without replacement) is being compared to a sequence of 10 attacks (with replacement).<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image005.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 5. Nonreplacement dramatically decreases frustration.<br /><br /> Clearly, this mechanism reduces frustration. Furthermore, the mechanism without replacement guarantees never to have more than 10 consecutive misses (since the 1+20<em class='bbc'>k</em>th occurrence always hits).<br /><br /> Although the above analysis is only a solution for one of the parameters that a player may have of hitting an opponent (i.e., melee attack of +0 versus armor class 11), the same analysis can be carried out on all possible parameters. Likewise, this analysis can be carried out for any given lower bound to frustration. If worst-case analysis of player satisfaction had predetermined 5 consecutive misses to be the maximum tolerance before frustration occurs, then the deck could be divided into two separate decks, each without replacement, so long as each deck had no more than 5 in it. For the sake of uniformity, two decks might be evenly divided (i.e., 75% success rate = 7 out of 10 and 8 out of 10).<br /><br /> <br /><strong class='bbc'>God Does Not Play Dice—He Plays Cards</strong><br /> This deck mechanism is not without its costs. A little detour from the mathematics department and into the computer science department will explain why. Each mechanism is implemented from an <em class='bbc'>algorithm</em> (which is a precise procedure for the rules of the game). Computing the amount of time required for the die mechanism is straightforward, as listed in Table 1.<br /><br /> <br /><br />&nbsp;&nbsp; <strong class='bbc'>Step in the algorithm</strong> <strong class='bbc'>Computations</strong>&nbsp;&nbsp; For 20 attacks: 20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roll a die.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em class='bbc'>d</em>&nbsp;&nbsp; <strong class='bbc'>Total Time Complexity</strong> 20 <em class='bbc'>d</em>&nbsp;&nbsp; <br />Table 1. Algorithm outline of a die mechanism. The deck mechanism is not much more complicated. A naive shuffling algorithm can shuffle in linear time with one random call per element. So, this implies a running time not worse than 19 fold of the running time of the die mechanism. This shuffling only needs to be called once every 20 attacks. As listed in Table 2, the <em class='bbc'>time complexity</em> (which is an abstraction of the amount of time required to execute the algorithm) for a card mechanism is greater than the die mechanism, but not by much. Although there are two operations to perform instead of one, the drawing of a card (<em class='bbc'>c</em>) from a shuffled deck is a trivial operation. In addition, within an efficient shuffling algorithm, shuffling one card in a deck of 19 (<em class='bbc'>s</em>) is approximately comparable to rolling a die with 19 sides (<em class='bbc'>d</em>).<br /><br /> <br /><br />&nbsp;&nbsp; <strong class='bbc'>Step in the algorithm</strong> <strong class='bbc'>Computations</strong>&nbsp;&nbsp; Shuffle a deck of 19 cards. 19 <em class='bbc'>s</em>&nbsp;&nbsp; For 19 attacks: 19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Draw a card.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em class='bbc'>c</em>&nbsp;&nbsp; <strong class='bbc'>Total Time Complexity</strong> 19 <em class='bbc'>c</em> + 19 <em class='bbc'>s</em> = 19 (<em class='bbc'>c</em> + <em class='bbc'>s</em>)&nbsp;&nbsp; <br />Table 2. Algorithm outline of a card mechanism. A more elegant algorithm may shuffle one card per attack, which means one randomization per attack, as listed in Table 3. This does not alter the total time complexity, but does distribute the computations more evenly, so that there is not a delay (for shuffling) after each 20th attack.<br /><br /> <br /><br />&nbsp;&nbsp; <strong class='bbc'>Step in the algorithm</strong> <strong class='bbc'>Computations</strong>&nbsp;&nbsp; For 19 attacks: 19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Draw a card.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em class='bbc'>c</em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Shuffle that card.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em class='bbc'>s</em>&nbsp;&nbsp; <strong class='bbc'>Total Time Complexity</strong> 19 (<em class='bbc'>c</em> + <em class='bbc'>s</em>)&nbsp;&nbsp; <br />Table 3. Algorithm outline of a gradually shuffled card mechanism. Of course, compared to the die, the deck requires memory, but this may be as little as an additional 19 bits per player to as much as 50 bytes per player.<br /><br /> Albert Einstein once remarked on another detailed mechanism, a mechanism for the elementary fabric of the universe. When presented with the random mechanism for modeling quantum physics, Einstein said, "God does not play dice." In the case of our RPG, maybe the Creator plays cards, instead.<br /><br /> <br /><strong class='bbc'>Does it Matter?</strong><br /> Does it matter whether a die or deck is used? Both probabilities are negligible, making it unlikely for a designer to encounter such frustration. Yet even small probabilities, such as one in a thousand, are worth considering given enough players.<br /><br /> To understand, first we need to learn another distribution common to discrete probability. We want to know how many instances of player frustration will occur. Each instance is rare, so the mean of a Poisson distribution, <em class='bbc'>E</em>(<em class='bbc'>X</em>), is a good approximation, as formulated in Equation 6.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image006.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 6. Poisson distribution models the count of frustrations.<br /><br /> In general, the Poisson distribution is used to measure the number of occurrences (<em class='bbc'>λ</em>) per unit time. We have already calculated the probability of a single instance of frustration (<em class='bbc'>p</em>). What remains to be determined are the number of attack strings in which frustration may occur (<em class='bbc'>n</em>). Let's consider two scenarios with sufficient sequences of player attacks, both in massively multiplayer games and in single-player games.<br /><br /> <br /><strong class='bbc'>Case Study: Massively Multiplayer RPG</strong><br /> For a simple example in a massively multiplayer role-playing game (MMORPG), there could average 1000 attacks per player per hour. To be crude, this could be coarsened to 100 strings of 10 attacks (Actually, only one of the ten possible combinations of ten consecutive failures conform to this demarcation). If—admittedly oversimplified—there were, for a reasonably small MMORPG, an average of 100 simultaneous players per day with uniform distribution of attacks, and independence of attacks, then there would be 100 strings / hour (24 hours / day) 30 days / month. The arithmetic equals 72,000 strings per month. Since this is very large and the probability is very small, the Poisson distribution approximates, with a rate of <em class='bbc'>λ</em> = <em class='bbc'>n p</em>. The expected number of frustrations is solved in Equation 7.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image007.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 7. Expected number of frustrations per month, with replacement.<br /><br /> So there's going to be, on average for a low-traffic MMP, given these simplistic preconditions, 70 strings of frustration (i.e., 10 consecutive misses) per month using a mechanism analogous to a 1d20 die roll. Whereas, without replacement (a mechanism analogous to a 20-card deck), the expected number of frustrations is computed in Equation 8. For approximation, the number of trials is divided by two, because this is a sequence of 20, instead of a sequence of 10.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image008.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Equation 8. Expected number of frustrations per month, without replacement.<br /><br /> So, there are about 18 times fewer occurrences of frustration. A distribution of the frustration may be estimated by the Poisson distribution, as shown in Figure 1. Because only whole numbers can occur, the distribution has been stepped at the rounded (midpoint) value of a continuous Poisson distribution.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/design/randomness/image009.gif' alt='Posted Image' class='bbc_img' /></span></span><br />Figure 1. Distribution of frustration without replacement (blue) or with replacement (magenta).<br /><br /> From comparing the distributions, it is obvious that without replacement, there are almost certainly going to be fewer cases of frustration.<br /><br /> <br /><strong class='bbc'>Case Study: Single-Player RPG</strong><br /> There's no theoretical or practical reason why such methods could not be applied to single-player and multiplayer RPG combat. The fact is, a game that sells a million copies, can expect similar figures to an MMP. It is a difference of penetration and time. The same Poisson distribution applies. Suppose the average player of a single-player RPG spends 10 hours with the game (since many more players quit sooner than those that play longer). If the rate of attacks remains constant (1000 attacks per hour), then only 7200 copies of the game need be sold to have the equivalent of a month of the modestly populated MMORPG above.<br /><br /> <br /><strong class='bbc'>Every Mechanism Should be Designed as Simple as Possible, but Not Simpler</strong><br /> Einstein also said, "Everything should be made as simple as possible, but not simpler." Don't let mathematical precision dominate your analysis of a mechanism. While understanding the subtleties of a mechanism can make or break the design of a game, the relevance of the number crunching must be maintained.<br /><br /> In this example, we computed the difference, not in terms of all kinds of player frustration that may occur, but only with one single variation to a mechanism within the game. We simplified the situation in order to keep the math brief. We did not consider players with probabilities to hit at above or below 50%, nor did we strictly adhere to the definition of independence for a Poisson distribution in the die mechanism. Astute readers will have also noted that the deck mechanism does not randomize the first card drawn. Doing so would further complicate the calculation of probability. Therefore, our result is only an approximation for a special deck.<br /><br /> A more precise analysis was not necessary to prove the fitness of the deck mechanism. Bear in mind that a designer can correctly solve a problem but fail to solve the right problem. In this article, we honed in on one mechanism, ignoring the rest of the game and its effect on the player's satisfaction. Even if it were mathematically tractable, computing the distribution of loss of players due to this careful definition of one type of frustration is a tougher problem.<br /><br /> <br /><strong class='bbc'>About the Author</strong><br /> David Kennerly directed five massively multiplayer games in the US and Korea. He localized Korea's first world, <em class='bbc'>The Kingdom of the Winds</em>, and designed the social system of <em class='bbc'>Dark Ages: Online Roleplaying</em>. Before joining Nexon in 1997, he designed <em class='bbc'>The X-Files Trivia Game</em> for 20th Century Fox, and troubleshot US Army networks in Korea.<br /><br /> David encourages creativity among developers and players. He helped organize MUD-Dev Conferences, and founded an online library of fan fiction. David has authored on game design for Charles River Media, ITT Tech, Westwood College, Gamasutra.com, and IGDA. To discuss this article with the author, please visit his website <a href='http://www.finegamedesign.com/' class='bbc_url' title='External link' rel='nofollow external'>www.finegamedesign.com</a><br /><br /> <br /><strong class='bbc'>Further Reading</strong><br /> Jay L. Devore, <em class='bbc'>Probability and Statistics for Engineering and the Sciences</em>. "Chapter 3: Discrete Random Variables and Probability Distributions." 6 ed. Brooks/Cole: USA, 2004.<br /><br />]]></description>
		<pubDate>Wed, 16 Feb 2005 16:11:45 +0000</pubDate>
		<guid isPermaLink="false">dfcebbaf79842c2e6fca7b77741de3a6</guid>
	</item>
	<item>
		<title>A Simple Time-Corrected Verlet Integration Method</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/a-simple-time-corrected-verlet-integration-method-r2200</link>
		<description><![CDATA[<br /><strong class='bbc'>Introduction</strong><br /> Verlet integration is a nifty method for numerically integrating the equations of motion (typically linear, though you can use the same idea for rotational). It is a finite difference method that's popular with the Molecular Dynamics people. Actually, it comes in three flavors: the basic Position, the Leapfrog and the Velocity versions. We will be discussing the Position Verlet algorithm in this paper. It has the benefit of being quite stable, especially in the face of enforced boundary conditions (there is no explicit velocity term with which the position term can get out of sync). It is also very fast to compute (almost as fast as Euler integration), and under the right conditions it is 4<sup class='bbc'>th</sup> order accurate (by comparison, the Euler method is only 1<sup class='bbc'>st</sup> order accurate, and the second order Runge-Kutta method is only 2<sup class='bbc'>nd</sup> order accurate [go figure]).<br /><br /> The disadvantages of the Verlet method are that it handles changing time steps badly, it is not a self-starter (it requires 2 steps to get going, so initial conditions are crucial), and it is unclear from the formulation how it handles changing accelerations. In this paper we will discuss all of these shortcomings, and see how to minimize their impact. The modified Verlet integrator is referred to as the Time-Corrected Verlet (TCV) and is shown below with its original counterpart. The computations used to generate the graphs for this paper are included in <a href='http://downloads.gamedev.net/features/programming/verlet/TimeCorrectedVerlet.xls' class='bbc_url' title='External link' rel='nofollow external'>this Excel file</a>.<br /><br /> Original Verlet:<br />x<sub class='bbc'>i+1</sub> = x<sub class='bbc'>i</sub> + (x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub>) <sub class='bbc'>+</sub> a * dt * dt<br /><br /> Time-Corrected Verlet:<br />x<sub class='bbc'>i+1</sub> = x<sub class='bbc'>i</sub> + (x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1)</sub> * (dt<sub class='bbc'>i</sub> / dt<sub class='bbc'>i-1</sub>) + a * dt<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub><br /><br /> To see why the TCV is an improvement, we need to see the math behind the original Verlet method.<br /><br /> <br /><strong class='bbc'>Math</strong><br /> In this paper we will be talking exclusively about point masses, which are acted on by forces. Well, we all know about Newton's little equation: <em class='bbc'>Force=d(Momentum)/dt</em>. <em class='bbc'>Momentum=mass*velocity</em> and for non-relativistic speeds the mass is constant, removing our need for the chain rule, and yielding our familiar <em class='bbc'>F=ma</em>. So if all the forces acting on the point mass are summed (the vector <em class='bbc'>F</em>), then scaled by (<em class='bbc'>1.0/m</em>) we have the acceleration (<em class='bbc'>a</em>) of the point mass. Since we know how to go from force to acceleration, we will be starting from the acceleration term to keep the math less cluttered. In actual applications you will almost always be summing forces, then converting to accelerations.<br /><br /> Most of the graphs presented in this paper include the matching Euler simulation, just for reference. The Euler algorithm is extremely simple, and it will not be derived here. However, the equations are included below for your reference (order is important):<br /><br /> v = v + a * dt<br />x = x + v * dt<br /><br /> There is a more accurate version, but it is not strictly the Euler method, so it will not be used for this paper. However it does give 2<sup class='bbc'>nd</sup> order accurate results, instead of merely 1<sup class='bbc'>st</sup> order:<br /><br /> x = x + v * dt + 0.5 * a * dt * dt<br />v = v + a * dt<br /><br /> Please note that there is a faster way to derive the Verlet method's math* than what will be shown here, however it does not provide the insight needed to overcome the issues mentioned in the introduction. So we'll start from a few basic principles: <em class='bbc'>a=dv/dt</em>, and <em class='bbc'>v=dx/dt</em>. So for any given point mass, if we know the current position, velocity and acceleration (the acceleration must be constant over the given time step), we can compute exactly where it will be after the time step (<em class='bbc'>dt</em>) has elapsed.<br /><br /> (1)&nbsp;&nbsp; x<sub class='bbc'>i+1</sub> = x<sub class='bbc'>i</sub> + v<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub> + 0.5 * a<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub><br /><br /> or<br /><br /> (1a)&nbsp;&nbsp; x<sub class='bbc'>i+1</sub> - x<sub class='bbc'>i</sub> = v<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub> + 0.5 * a<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub><br /><br /> Now, if we wanted that equation formulated without the velocity term, we could replace it with some other known state variable, such as the position x.&nbsp;&nbsp;But since we don't know x<sub class='bbc'>i+1</sub> yet, we shift the whole equation back a step:<br /><br /> (2)&nbsp;&nbsp; x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub> = v<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub> + 0.5 * a<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub><br /><br /> and we can use simple integration to see that:<br /><br /> (3)&nbsp;&nbsp; v<sub class='bbc'>i</sub> = v<sub class='bbc'>i-1</sub> + a<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub><br /><br /> or<br /><br /> (3a)&nbsp;&nbsp; v<sub class='bbc'>i-1</sub> = v<sub class='bbc'>i</sub> - a<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub><br /><br /> and we substitute that into equation (2):<br /><br /> (4)&nbsp;&nbsp; x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub> = (v<sub class='bbc'>i</sub> - a<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub>) * dt<sub class='bbc'>i-1</sub> + 0.5 * a<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub><br /><br /> or<br /><br /> (4a)&nbsp;&nbsp; x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub> = v<sub class='bbc'>i</sub> * dt<sub class='bbc'>i-1</sub> - 0.5 * a<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub><br /><br /> For this next step we need to make a big assumption, the importance of which will be seen later: If we assume that neither the acceleration nor the time step vary between steps (i.e. that a<sub class='bbc'>i-1</sub> = a<sub class='bbc'>i</sub> = a and that dt<sub class='bbc'>i-1</sub> = dt<sub class='bbc'>i</sub> = dt) then we note that:<br /><br /> (5)&nbsp;&nbsp; x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1 +</sub> a * dt * dt = v<sub class='bbc'>i</sub> * dt - 0.5 * a * dt * dt + a * dt * dt<br /><br /> or<br /><br /> (5a)&nbsp;&nbsp; x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1 +</sub> a * dt * dt = v<sub class='bbc'>i</sub> * dt + 0.5 * a * dt * dt<br /><br /> You'll notice that the right hand side of equation (5a) is exactly the last half of equation (1), so we can work the modified equation (5a) back into equation (1):<br /><br /> (6)&nbsp;&nbsp; x<sub class='bbc'>i+1</sub> = x<sub class='bbc'>i</sub> + (x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub>) <sub class='bbc'>+</sub> a * dt * dt<br /><br /> and there you have the traditional Verlet Position integration method.<br /><br /> <br /><strong class='bbc'>Fundamental Problems</strong><br /> As you saw from the derivation's step (5), the two criteria needed to make the Verlet algorithm exact are constant acceleration and constant time step. For most practical cases we cannot guarantee either of these criteria. Of course, there are some simple cases where both criteria will be met. For example, simple projectile physics simulated by a physics engine which uses fixed time steps will yield perfect results. As soon as you add friction, springs or constraints of any kind you nullify the constant acceleration criterion, and adapting your time step to your game's framerate will nullify the constant time step criterion.<br /><br /> I am not going to address the constant acceleration criterion, mainly because explicit integrators (such as this one) must assume the constant acceleration principle, which is violated the instant you start simulating a complex system. Take the example of a point mass connected to a spring: as soon as it starts to move, the spring force, and thus the acceleration, changes. Even equation (1) required that the acceleration be constant throughout a time step. The error introduced by assuming that a<sub class='bbc'>i-1 =</sub> a<sub class='bbc'>i</sub> is actually implicit in our choosing an explicit scheme without knowing how the acceleration changes. We are effectively setting d(a)/dt (a.k.a. the "jerk") to 0.0. The other reason I will ignore this issue is that, empirically, the standard Verlet method already handles changing accelerations better than the Euler method (or even the improved variation on the Euler method), as long as the time step is fixed. Note that the Time-Corrected Verlet will be identical to the original Verlet when the time step is fixed. Observe the following graphs:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verlet/proj-test.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verlet/poly-test.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verlet/sine-test.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> The error introduced by the constant time step assumption is something that can be easily ameliorated. This will be shown in the section entitled "A Simple Time-Correction Scheme".<br /><br /> <br /><strong class='bbc'>Implementation Problems</strong><br /> A large source of inaccuracy when using the Verlet scheme stems from the improper specification of initial conditions. Looking at equation (6) and trying to fit it into the form of equation (1) (which may be more familiar) may yield (improper) reasoning like this: the first (x<sub class='bbc'>i</sub>) term is the position contribution, the second (x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub>) term is basically the velocity contribution, and the (a * dt * dt) term is clearly the acceleration contribution. So when simulating the traditional projectile path, setting x<sub class='bbc'>0</sub> = 0.0, and x<sub class='bbc'>-1</sub>=x<sub class='bbc'>0</sub> - v<sub class='bbc'>0</sub> * dt<sub class='bbc'>0</sub>, and running the simulation from there will give the wrong results, as can be seen in the following graph:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verlet/projectile-ic.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> This is because both the second and third terms include acceleration information. So, when setting the current state explicitly (i.e. the position and velocity initial conditions), remember to use equation (2). Shooting simulations depend upon starting with accurate initial conditions. The larger the initial time step, the less accurate your computed initial state will be if you do not use equation (2).<br /><br /> <br /><strong class='bbc'>A Simple Time-Correction Scheme</strong><br /> The remaining fundamental problem with the Verlet integration method lies with its assumption of a constant time step. The (x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub>) term from equation (4a) is the portion of the equation which is dependent on the constant acceleration and constant time step assumptions. It has been explained (OK, hand-waved away) why the usage of the last time step's acceleration will not be corrected, but we still have the problem of dt<sub class='bbc'>i-1</sub> being stale information. Rewriting equation (4) yet again, we see that:<br /><br /> (4b)&nbsp;&nbsp; x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1</sub> = (v<sub class='bbc'>i</sub> - 0.5 * a<sub class='bbc'>i-1</sub> * dt<sub class='bbc'>i-1</sub>) * dt<sub class='bbc'>i-1</sub><br /><br /> so taking the easy way out and ignoring the dt<sub class='bbc'>i-1</sub> linked with the acceleration, I can swap out the old dt<sub class='bbc'>i-1</sub> for my new dt<sub class='bbc'>i</sub> by multiplying (4b) by (dt<sub class='bbc'>i</sub> / dt<sub class='bbc'>i-1</sub>). Plugging all of this in yields my final form of the Time-Corrected Verlet integration method:<br /><br /> (7)&nbsp;&nbsp; x<sub class='bbc'>i+1</sub> = x<sub class='bbc'>i</sub> + (x<sub class='bbc'>i</sub> - x<sub class='bbc'>i-1)</sub> * (dt<sub class='bbc'>i</sub> / dt<sub class='bbc'>i-1</sub>) + a * dt<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub><br /><br /> You will notice that when the last frame's time step equals the current frame's time step, the modifier term becomes 1.0, yielding the traditional form of the Verlet equation. As an optimization note, only one value needs to be stored per frame, as the dt was constant for all points in the last frame. So the term (dt<sub class='bbc'>i</sub> / dt<sub class='bbc'>i-1</sub>) can be computed once per frame and stored in a variable. At the end of the Verlet update subroutine simply store the current frame's dt as old_dt. Likewise, dt<sub class='bbc'>i</sub> * dt<sub class='bbc'>i</sub> can be computed once and stored in a variable, saving a multiplication.<br /><br /> To show how the Time-Corrected Verlet behaves, a spreadsheet was set up with the TCV, the original Verlet and Euler's method, each simulating three different problems with known solutions. These are the same tests as were performed earlier, but with randomized time steps. Of course since every time step (except the first) was random, the graph looked different each time a simulation was "run". Sometimes both the original Verlet and the TCV simulations were similar, however the original Verlet always fell further away from the exact solution than the TCV version eventually. Here are some sample graphs:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verlet/proj-rand.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verlet/poly-rand.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/features/programming/verlet/sine-rand.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> <br /><strong class='bbc'>Conclusion</strong><br /> Using the Time-Corrected form of the Verlet integration method with the proper equation for initializing the state makes the TCV integration scheme a simple, yet powerful method for doing game physics, even with changing frame rates.<br /><br /> It restores some of the accuracy of the method (still 4th order with constant time steps, between 2nd and 4th with changing dt), while maintaining its cheap numerical cost. I hope this helps a bit when implementing your own physics simulation code.<br /><br /> * Hint: remember the central difference 2<sup class='bbc'>nd</sup> derivative approximation?<br />d<sup class='bbc'>2</sup>x / dt<sup class='bbc'>2</sup> = a<sub class='bbc'>i</sub><sup class='bbc'>2</sup>= (x<sub class='bbc'>i+1</sub> - 2*x<sub class='bbc'>i</sub> + x<sub class='bbc'>i+1</sub>) / dt<sup class='bbc'>2</sup><br /><br />]]></description>
		<pubDate>Sun, 06 Feb 2005 23:50:36 +0000</pubDate>
		<guid isPermaLink="false">b62973ddb1a4d7a0ea30a1052012af19</guid>
	</item>
	<item>
		<title>Opposing Face Geometry</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/opposing-face-geometry-r2045</link>
		<description><![CDATA[<strong class='bbc'>Abstract:</strong><br />OFG presents a new method for collision detection optimizations by performing a simple pre-calculation on both input objects. It is possible to reduce the number of faces necessary to check for intersection dramatically, from an order of <strong class='bbc'><em class='bbc'>O(mn)</em></strong> intersection tests to an order of <strong class='bbc'><em class='bbc'>O(k<sup class='bbc'>2</sup>)</em></strong>, or rather to a maximum of <strong class='bbc'><em class='bbc'>k<sup class='bbc'>2</sup> + 3k</em></strong> test operations, where <em class='bbc'>k</em> is a predetermined constant. The pre-calculation phase is of the order of <strong class='bbc'><em class='bbc'>O(m + n)</em></strong>. Therefore, for increasingly complex convex objects, the OFG method saves more and more processing time. The method's downside is that increasingly complex objects might need a very high constant and small faces are less suited for this type of optimization. The method is much better for relatively low detail 3D objects.<br /><br /> <br /><strong class='bbc'>Introduction</strong><br /> Collision detection is generalized as the means to detect whether any two objects in 3D space overlap. Over the years many models and ideas were suggested that attempt to either solve the problem entirely or approximate a solution. Of course, it has been shown that detecting collisions in a very accurate way is extremely computation intensive. Yet new ways and methods have been invented to optimize or accelerate the collision detection algorithms so those will be useable in real-time environments such as 3D simulations or 3D games. The method proposed here is called OFG and attempts to do the exact same thing - to optimize the collision detection algorithm by eliminating as many checks as possible.<br /><br /> This article assumes the reader knows simple vector notation and operations, namely the dot product and vector sizes.<br /><br /> <br /><strong class='bbc'>The problem</strong><br /> In real life, collision detection is a fact, it's simply how things work. Objects cannot occupy the same space, at least not usually. However, when dealing with computer programs it is clear that it's impossible to simulate the detail levels of the real world. In computer simulations the only way to actually define a 3D object is by defining the points from which its polygons are made. Each of these points is called a vertex, in plural - vertices. Defining a 3D object using only points connected by lines is the only way to represent a 3D object in a way that allows real-time simulations. This method is of course only an approximation, but when there are enough polygons making up an object, the approximation is very good.<br /><br /> The representation of a 3D object is very simple. Vertices can be connected by lines to create closed shapes called 'polygons'<sup class='bbc'>1</sup>(usually triangles). A collection of faces constitutes a closed 3D object and therefore the only information at our disposal for collision detection testing is the vertices information. The problem begins by trying to create a model for collision detection. It seems highly unlikely that objects collide at exactly their vertices, and this is logically correct as well. Consider two normal cubes the same size. The two cubes can collide in an infinite number of ways and orientations, even without their vertices touching each other's or any connecting line between vertices (edges)<sup class='bbc'>2</sup>. What is more logical is that either edges themselves pierce the other object's <em class='bbc'>faces</em>, or some variation to that effect. The question then arises, how to detect faces intersecting each other? or better yet, how to detect edges piercing other faces?<br /><br /> Well, the good news is that there are already good ways of testing for edges piercing faces. The bad news is that representing complex 3D objects requires a great deal of faces to look reasonably well, and since detecting intersection in an accurate way is slow in comparison to other optimized methods, this creates a big problem. In this article we will assume that detecting whether two faces intersect is a problem solved in a reasonable way and hence this article will not deal with methods for detecting actual intersection of a pair of faces, which is the most elementary test. For convenience a few methods are given in the appendix but it must be clear that OFG is a method for optimizing the entire process of object to object collision tests by dramatically reducing the number of faces needed for testing.<br /><br /> <br /><strong class='bbc'>Basic assumptions and the most general case</strong><br /> In order to simplify the problem some basic assumptions need to be made. Of course these might present some problems but it must be clear that the assumptions help solve the most simple case. Later on the algorithm will be improved to circumvent some of the problems arising from the assumptions.<br /><br /> The assumptions that we make are as follows:<br /><br /> <ul class='bbc'><li>The objects that the algorithm is dealing with are convex<sup class='bbc'>3</sup> 3D objects <em class='bbc'>only</em>. It is true that the algorithm will work for some concave<sup class='bbc'>4</sup> objects but care must be taken<sup class='bbc'>5</sup>. </li><li>Detection of any pair of faces colliding is a well-defined and solved problem. </li><li>Both objects have a pre-calculated center point. </li><li>The accuracy constant <em class='bbc'>k</em> is set to be <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img5.png' alt='Posted Image' class='bbc_img' /></span></span> (min/max estimates) </li><li>Object A has exactly <em class='bbc'>n</em> faces while object B has <em class='bbc'>m</em> faces.</li></ul> Under these assumptions, in order to detect a collision between objects, the most simple but inefficient method of checking every face in object A against every face in object B can be used. Actually, using the brute force method works for all types of objects, convex or concave. It makes no difference to the algorithm. For the brute force method therefore an order magnitude of <strong class='bbc'><em class='bbc'>O(nm)</em></strong> represents the algorithm's time complexity. The problem with this approach is obvious - detecting collision between complex objects becomes a very long operation. The more faces objects have, the more checks are needed. For two normal cubes, each with 6 sides (two faces per side, assuming each face is a triangle), the number of checks is: <strong class='bbc'>12 * 12 = 144</strong> tests between pairs of faces.<br /><br /> For two objects with 100 faces each, the number increases very fast: <strong class='bbc'>100 * 100 = 10,000</strong><br /><br /> For two objects with 200 faces each, the number increases again to: <strong class='bbc'>200 * 200 = 40,000</strong><br /><br /> It is clear that this method is highly inefficient when dealing with more and more complex objects.<br /><br /> <br /><strong class='bbc'>The Opposing Face Geometry algorithm</strong><br /> OFG is a method that at its basic level attempts to find in the simplest way the closest geometry elements two objects have. The algorithm attempts to find the closest faces both objects have in relation to one another while the number of desired faces to be found is determined by the accuracy constant <em class='bbc'>k</em>.<br /><br /> The OFG method consists of the following steps, each described in more detail in the following sections:<br /><br /> <ul class='bbcol decimal'><li>Optimization: check collision between object A's bounding sphere and object B's bounding sphere. </li><li>Find the closest <em class='bbc'>k</em> faces of object A relative to object B. </li><li>Calculate the geometric center of the new selection and the bounding sphere radius. </li><li>Find the closest <em class='bbc'>k</em> faces of object B relative to object A's <strong class='bbc'><em class='bbc'>new selection</em></strong> of <em class='bbc'>k</em> faces. </li><li>Calculate the geometric center of object B's new selection of faces and their maximal bounding sphere radius. </li><li>Optimization: check collision between spheres to determine if there is even a chance for face collisions. </li><li>Sort the two sets of faces by increasing distance (optional, might be replaces by a good insertion algorithm). </li><li>Test the two sets of faces against each other, starting with the closest pairs of faces.</li></ul> Analysis:<br /><br /> It's clear from the above steps that there are some preliminary preparations before any actual checks are done between faces. The time complexity of steps 1, 3, 5 and 6 is rather fixed: 2 operations, 3<em class='bbc'>k</em> operations, 3<em class='bbc'>k</em> operations and 2 operations again respectively and therefore contribute only little overhead to the entire process. Step 7 is basically a sorting operation for an array of <em class='bbc'>k</em> elements. If care is taken to insert the elements in an almost-sorted fashion, it is possible to use sorting algorithms that operate at almost O(<em class='bbc'>n</em>) on each of the arrays, or better. Since n=k in this case, O(2k) can be added to the overhead of the algorithm however up until now the overhead presented by these steps is rather constant no matter the complexity of the objects and is said to be geometry independent.<br /><br /> It will be shown that step 2 requires a time complexity of O(<em class='bbc'>n</em>) while step 4 requires a time complexity of O(<em class='bbc'>m</em>). Therefore the geometry dependant time complexity (and hence the most important one) is O(<em class='bbc'>n+m</em>).<br /><br /> As for step 8, the worst case scenario of testing <em class='bbc'>k</em> faces against <em class='bbc'>k</em> faces is <strong class='bbc'><em class='bbc'>O(k<sup class='bbc'>2</sup>)</em></strong>.<br /><br /> <em class='bbc'>Note: The accuracy constant</em> k plays a major role in the OFG algorithm. The higher <em class='bbc'>k</em> is, more faces are selected for testing and therefore more accurate collisions can be detected. Typical values are from 4 to 8 faces and the reasoning for this is explained later on in the appendix.<br /><br /> <br /><strong class='bbc'>Step 1 - Checking for the <em class='bbc'>possibility</em> of a collision</strong><br /> There is no real need to test <em class='bbc'>any</em> faces at all if the objects are far away from each other. This is logical but presents a problem: since objects are almost always non-spherical, one has to define a range from which no face testing will be performed and for a shorter range, face testing will be performed. But if the objects are non-spherical, what kind of range can be used that will also be efficient enough?<br /><br /> Well, the answer is of course, compounding each of the objects within their own bounding spheres. If the spheres don't overlap, it is certain that there is no collision. If the spheres overlap, there is the <em class='bbc'>possibility</em> of a collision and tests must be performed. It is quite simple creating a bounding sphere for each object and since a sphere is always the same when rotated (invariant when rotated), calculation of the bounding sphere and the object's geometrical center can be done at the initialization stage, usually when objects are loaded.<br /><br /> Calculating the geometric center is exactly finding the average of all the vertices that comprise an object:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img9.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> This relation gives the X coordinate of the object's center point by summing all X coordinates of all vertices in the object. Notice that in this relation <em class='bbc'>n</em> is NOT the number of faces but the number of vertices of the object. The same calculation can be done for the Y and Z coordinates. The weight functions W can be used to give different weights to vertices but in order to find the geometric center it is usually sufficient to use 1 for any W of any vertex.<br /><br /> After the center is found it is simply a matter of iterating the vertices again and finding the farthest vertex from the center and using that distance as the compound radius.<br /><br /> <br /><strong class='bbc'>Step 2 - Finding the closest <em class='bbc'>k</em> faces of object A relative to B</strong><br /> The first step in the OFG algorithm is to find the closest geometry object A has in relation to object B. In order to do this in an efficient manner, one very important assumption must be made:<br /><br /> <ul class='bbc'><li>Object B can be considered as a point object located at its center (object centers have been shown in step 1).</li></ul> This assumption is not a simple one, there is a lot of reasoning behind it. Mainly, in order to find the closest faces object A has relative to B, it is obvious that distances of faces must be considered. The problem is that finding the smallest distances between <em class='bbc'>every</em> face in A and <em class='bbc'>every</em> face in B has a time complexity of <strong class='bbc'><em class='bbc'>O(nm)</em></strong>, just as the easiest brute force method presented as the general case. Of course, this will not do.<br /><br /> The idea is to attempt to find distances of all faces in object A, relative to only <em class='bbc'>one</em> geometry property in B. That way, checking every face in A against only one geometry property of object B yields a time complexity of <strong class='bbc'><em class='bbc'>O(n)</em></strong>, where <em class='bbc'>n</em> is the number of faces in object A. The question then arises: what kind of geometric property an entire object has that can be used to represent the <em class='bbc'>entire</em> object?<br /><br /> Physicists sometimes assume very distant objects are a point object when trying to simplify problems in physics because when an object is very far, the contribution from any irregularities in the object's geometry are negligible.<br /><br /> For our purposes, this assumption is correct for <em class='bbc'>any</em> distance, mainly due to the fact that this algorithm deals strictly with convex 3D objects. For that reason, the closest faces an object can have to another object are the faces closest to the other object's center.<br /><br /> It is always true that if a certain face is closer to object B's center than another face, it is generally closer to object B than the other face.<br /><br /> Taking the 3 vertices (or more, depending on the engine involved) that constitute a face, it is possible to find that face's center in exactly the same way as finding an object's center. Using the center coordinate coupled with the two object's positions it is possible to automatically calculate a vector from the center of any face to the center of the other object.<br /><br /> In summary, the steps necessary to find the closest <em class='bbc'>k</em> faces of object A are:<br /><br /> <ul class='bbcol decimal'><li>Using both object's positions, calculate the relative position vector. Assuming <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img11.png' alt='Posted Image' class='bbc_img' /></span></span> is the center of object A (x,y,z - a 3D vector) and <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img12.png' alt='Posted Image' class='bbc_img' /></span></span> the center of object B, the vector connecting the center points is then: <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img13.png' alt='Posted Image' class='bbc_img' /></span></span> </li><li>Start looping through all faces of object A, find each face center relative to object A's center. Total time complexity is <strong class='bbc'><em class='bbc'>O(n)</em></strong>. It takes less operations to calculate the faces centers than to do it in the beginning and apply transformations on them. </li><li>For each face, find the vector connecting its center with object B's center, using the simple relation: <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img14.png' alt='Posted Image' class='bbc_img' /></span></span>, where <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img15.png' alt='Posted Image' class='bbc_img' /></span></span> is the vector connecting the center of face <strong class='bbc'><em class='bbc'>i</em></strong> with the center of object B, <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img17.png' alt='Posted Image' class='bbc_img' /></span></span> the relative positions of the two object's centers and <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img18.png' alt='Posted Image' class='bbc_img' /></span></span> is the position of the face relative to object A's center (the object it belongs to). Of course, <strong class='bbc'><em class='bbc'>i</em></strong> = 0,1,2,3...,<em class='bbc'>n</em>. </li><li>For each <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img15.png' alt='Posted Image' class='bbc_img' /></span></span>, find the vector's size: <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img19.png' alt='Posted Image' class='bbc_img' /></span></span> and store into selection*. Of course, the size itself is irrelevant, as is the direction of the vector. The only important quantity is the vector's size squared. Note that there is no need to take the square root because if a certain face's squared vector size is larger than another face's squared vector size, the same holds for the actual sizes themselves. </li><li>Depending on the insertion technique used to insert the distances (squared sizes of the relative position vectors), find the smallest <em class='bbc'>k</em> distances which should be straightforward if the insertion was done in an efficient way, and remember their corresponding faces.</li></ul> * Note: Several methods are available that create a semi-sorted array of <em class='bbc'>k</em> elements.<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/OFG_step1_gimped.png' alt='Posted Image' class='bbc_img' /></span></span><br />Figure: Finding object A face vectors relative to object B's center<br /><br /> <br /><strong class='bbc'>Step 3 - Calculate the geometric center of the selection and its bounding sphere</strong><br /> After finding the closest <em class='bbc'>k</em> faces of object A relative to B it is important to be able to do quick tests in order to check the <em class='bbc'>possibility</em> of a collision between faces. For that reason and another reason outlined in step 4, the center of the new selection must be found and its bounding sphere.<br /><br /> Assuming the previous step has found the necessary <em class='bbc'>k</em> faces, finding the center is as simple as finding the average of all the selected faces centers. Remember, the selection itself is just a means to remember which faces are the closest, and each face has its center coordinate and a vector connecting the center of the face with the center of object B. Therefore we have:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img20.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> Where <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img21.png' alt='Posted Image' class='bbc_img' /></span></span> is of course the center of the new selection and <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img18.png' alt='Posted Image' class='bbc_img' /></span></span> is the position of the <em class='bbc'>i</em>'th face center relative to the object's center (as always). The resulting vector is the position of the new selection center relative to our object's (A) center.<br /><br /> Once the center is found, the farthest vertex from the new selection center gives the bounding sphere radius. This is a preparation phase for a later step where the possibility of face collision should be tested.<br /><br /> <br /><strong class='bbc'>Step 4 - Finding the closest <em class='bbc'>k</em> faces of object B relative to the <em class='bbc'>new selection</em></strong><br /> This part of the algorithm is very similar to step 2 in that it finds the closest faces in B relative to some point. However in this case the point that distances are calculated to is NOT object A's center. Rather, taking the center of the new selection found in step 2 and calculated in step 3 is better. True, for truly convex objects such as spheres there is no difference. Finding the faces in B that are closest to the generally closest faces in A yields better results. Not only is that more accurate but it helps the algorithm deal with objects that are not truly convex but only close to being convex.<br /><br /> Since this step is so similar to step 2, only the summary of the steps needed is presented:<br /><br /> <ul class='bbcol decimal'><li>Calculate the relative position vector between object B's center and the center of the new selection of <em class='bbc'>k</em> faces found earlier. Assuming <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img12.png' alt='Posted Image' class='bbc_img' /></span></span> is the center of object B and <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img22.png' alt='Posted Image' class='bbc_img' /></span></span> the center of the selection in object A, the vector connecting the center points is then: <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img23.png' alt='Posted Image' class='bbc_img' /></span></span> </li><li>Start looping through all faces of object B, find each face center relative to the center of the selection in object A. Total time complexity is <strong class='bbc'><em class='bbc'>O(m)</em></strong>. It takes less operations to calculate the faces centers than to do it in the beginning and apply transformations on them. </li><li>For each face, find the vector connecting its center with the center of the selection in object A, using the simple relation: <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img25.png' alt='Posted Image' class='bbc_img' /></span></span>, where <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img26.png' alt='Posted Image' class='bbc_img' /></span></span> is the vector connecting the center of face <strong class='bbc'><em class='bbc'>i</em></strong> with the center of the selection in object A, <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img27.png' alt='Posted Image' class='bbc_img' /></span></span> the relative positions of the center of object B and the center of the selection in object A and <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img18.png' alt='Posted Image' class='bbc_img' /></span></span> is the position of the face relative to object B's center (the object it belongs to). Of course, <strong class='bbc'><em class='bbc'>i</em></strong> = 0,1,2,3...,<em class='bbc'>m</em>. </li><li>For each <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img26.png' alt='Posted Image' class='bbc_img' /></span></span>, find the vector's size: <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img28.png' alt='Posted Image' class='bbc_img' /></span></span> and store into selection*. </li><li>Depending on the insertion technique used to insert the distances (squared sizes of the relative position vectors), find the smallest <em class='bbc'>k</em> distances which should be straightforward if the insertion was done in an efficient way, and remember their corresponding faces.</li></ul> * Note: Several methods are available that create a semi-sorted array of <em class='bbc'>k</em> elements.<br /><br /> <br /><strong class='bbc'>Step 5 - Calculate the geometric center of the new selection and its bounding sphere</strong><br /> In essence, step 5 is identical to step 3 only it operates on the newly selected faces in object B. Averaging the faces with the following relation:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img20.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> Will give the center of the newly selected faces in object B relative to B's center naturally. Once the bounding sphere radii of both the selection from object A and B are known it is a simple matter to accomplish the next step, step 6.<br /><br /> <br /><strong class='bbc'>Step 6 - Test collision between the two selections' bounding spheres</strong><br /> The last step before any accurate collision tests is the bounding sphere test for the two selections. Up until now the only test done is the bounding sphere test for the two objects that determine if there is a chance for a collision. Now that there are two sets of faces that have a bounding sphere, it is a simple matter of testing whether or not the spheres intersect in order to determine whether real geometry tests should be performed.<br /><br /> Denoting with <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img29.png' alt='Posted Image' class='bbc_img' /></span></span> the center of the selection in object A and <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img30.png' alt='Posted Image' class='bbc_img' /></span></span> the center of the selection in object B, the radii as <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img31.png' alt='Posted Image' class='bbc_img' /></span></span> and <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img32.png' alt='Posted Image' class='bbc_img' /></span></span> respectively, in order to determine if there is intersection the following relation holds:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img33.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> What this relation means is that if the size of the vector that connects the centers, squared, is smaller/equal to the sum of the radii, squared, there is the possibility of a collision between faces in the selections. Actually, the real check is against the square roots of both expressions but it holds for the squares too. There is no need to waste valuable processing time in order to perform two square root operations. The size of the vector is naturally a dot product of it with itself.<br /><br /> <br /><strong class='bbc'>Step 7 - Sort the two selections in ascending order</strong><br /> This step can be omitted if wanted but it can help gain a small performance boost. Assuming two selections exist with <em class='bbc'>k</em> elements in each (the elements being the faces to be checked), this step just sorts each of the selections, from the face with the smallest distance to the face with the largest distance. The order of each sorting operation can vary depending on the algorithm and the insertion technique used earlier when building the selection sets. If the selections are <em class='bbc'>almost</em> sorted, even a simple algorithm such as bubble sort can work in a reasonable time (bubblesort works at <em class='bbc'>O</em>(<em class='bbc'>k</em>) for almost sorted arrays).<br /><br /> The algorithm to choose from is really up to the programmers implementing this step. It depends entirely on the insertion method used earlier and there are several good sorting algorithms.<br /><br /> <br /><strong class='bbc'>Step 8 - Perform intersection tests on the two selection sets</strong><br /> If the algorithm made it this far, it is now time to examine the geometry itself for collision. As input, there are two selections of <em class='bbc'>k</em> faces each, the closest faces between the two objects. Under the assumptions made earlier, the problem of testing for intersection of a pair of faces is a well solved problem (again, see the appendix for ways of doing this), therefore in this subsection a summary of the testing method is described. As mentioned earlier, <em class='bbc'>k</em> can be between 4 and 8.<br /><br /> It is possible to examine all the faces in one set against all the faces in the other set. After all, there are <em class='bbc'>k</em> faces in each set and there are two sets, thus the worst case time complexity is <strong class='bbc'><em class='bbc'>O(k<sup class='bbc'>2</sup>)</em></strong>. This holds true no matter what but certain optimizations on the order of the tests can make a difference.<br /><br /> <br /><strong class='bbc'>Problems with the basic OFG algorithm</strong><br /> The OFG algorithm suffers from three very serious problems:<br /><br /> <ul class='bbc'><li>The algorithm supports detection of mostly convex objects. Some concave objects will work as well but there are bound to be degenerate cases that cause the algorithm to fail. It hasn't been proven mathematically that there are any cases that will cause failure but assuming there aren't is not a good idea. </li><li>Moving objects in computer simulations are by nature problematic because time in computer systems is discrete. In numerical approximations, time is discrete and therefore object positions are calculated in time steps and are really "teleporting" in small steps to create the illusion of motion. The problem arises when the velocity of objects is very large and/or objects are very small. It is quite possible that an object will be close to another object while not colliding, yet at the next time step will be half intersecting with the other object. The problem is then what faces to test. After all, the "closest" faces the object previously had are now <em class='bbc'>inside</em> the other close object. Even more so, it's possible that if the velocity is large enough, the object might pass right through the other object without any way of us detecting this. </li><li>In a similar fashion, rotating objects pose another problem. If objects have an angular velocity (or momentum, whichever you prefer) it's possible that before the collision some faces are the closest selection while after a small time step, other faces should be the closest selection. For example, consider a normal cube floating above a table at a small height. The closest faces to the table are naturally the two faces (triangles) that comprise the base of the cube. If the cube is about to rotate 45 degrees in one time step (very fast rotation) it wouldn't be correct checking the base of the cube against the table.</li></ul> In the following subsections some solutions are presented that deal with said problems.<br /><br /> <br /><strong class='bbc'>Solving the concavity problem</strong><br /> Since some objects are almost convex and some are not even close to being convex, a method is required that can handle these objects. It just so happens that concave objects can be represented by a collection of convex objects. This is implied since any object can be approximated by triangles, which are convex polygons. If there is any doubt about whether an object will cause problems with the OFG algorithm, it is best to represent it using two or more convex objects.<br /><br /> This presents another slight difficulty: if an object is really a collection of objects, which object's geometry is used when building the selection set?<br /><br /> Well, the solution to this lies in the OFG method itself, but at the object level. Just as faces, it is possible to generalize the algorithm for objects. For example, if two concave objects exists that are made out of an assortment of convex objects each, consider the following scheme:<br /><br /> <ul class='bbcol decimal'><li>Find the closest object in collection A relative to the entire collection B. This implies each object in A has to have a center (this is mandatory for OFG anyway) and the entire collection has to have a center as well (averaging the centers of the objects, should be a part of initialization). </li><li>Find the closest object in collection B relative to the object found earlier in collection A. </li><li>Feed the two objects found to the OFG algorithm.</li></ul><strong class='bbc'>Solving the discrete time problem</strong><br /> A technique exists that makes this very easy to accomplish. Consider a 2D face passing <em class='bbc'>through</em> a wall straight to the other side. This is only possible in a computer simulation if the face is moving fast enough. If it is, it can find itself on the other side of the wall after a small time unit.<br /><br /> Consider connecting each vertex that comprise the face with the same vertex on an exact copy of the face but on the other side of the wall. Not only that, the copy face's position is in fact the position of the original face at the next time step (after one time unit has elapsed, this is easy to calculate). With this in mind, each pair of "connected" vertices make up an edge. Then, testing the new virtual edges created for intersection with the other object (in this case, the wall) will determine if there is a collision.<br /><br /> Actually, this is not enough. The following steps are in order:<br /><br /> <ul class='bbcol decimal'><li>Calculate the translation of object A after a time unit elapses. </li><li>Feed the two objects into the OFG algorithm, forgoing step 6 completely and without the bounding sphere calculations in steps 3 and 5. Also, there is no need to perform step 8 (the final step) of the OFG algorithm just yet. </li><li>Connect each vertex in selection A with the same vertex on the virtual selection of A that is translated by the amount calculated in step 1. This gives a vector that represents the edge to test against object B. </li><li>Test the newly created edges against the selection in object B found by the OFG algorithm. They are the most likely to be intersecting object B. </li><li>Test the original faces in selection A against the selection in B, as was intended in step 8 of the OFG algorithm. </li><li>Test the translated virtual selection of A against the selection of B using step 8 of the OFG algorithm.</li></ul> Naturally if any collision is found the entire process is stopped and action is taken. However, since objects are "teleporting", it isn't clear which faces should have collided provided time was not discrete. Figuring out which faces collided will help determine what action to take.<br /><br /> There are generally two ways of solving this, others may exists:<br /><br /> <ul class='bbcol decimal'><li>Using the translation found in step 1 earlier and given that it's easily possible to calculate the relative velocity of the two objects, it's possible to estimate the time of collision (therefore obtaining the delta time needed for the objects to collide). </li><li>Moving half of the distance (half a time unit) and checking for collisions. If collision occurred, great. If not, move another half, so on and so forth. This has a time complexity of log(<em class='bbc'>n</em>) times of performing all the collision tests.</li></ul> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/OFG_step2_gimped.png' alt='Posted Image' class='bbc_img' /></span></span><br />Figure: One face of the selection in A translated after one time unit.<br /><br /> These two methods should only be used in case a collision occurred in between time steps. If a collision occurred with the original selection or the virtual selection (the beginning position and the ending position respectively), there is no need to interpolate the collision time since the intersecting faces are known.<br /><br /> <br /><strong class='bbc'>Solving for rotating objects</strong><br /> For the general case of rotating objects, the same approach as in the discrete time solution can be applied. Instead of only translating the vertices and using them to create virtual edges, rotating and then translating the vertices solves the problem. Instead of having the selection in its starting position and ending position, have the virtual selection rotated before translation so it'll be rotated at its new position. Vertices are connected in exactly the same way and figuring the moment of collision if one occurred works in exactly the same way but with rotation in mind.<br /><br /> <br /><strong class='bbc'>Appendix A - Detecting collision between two faces</strong><br /> Up until now the problem of testing for collision between a pair of faces was a well solved problem. That meant that the algorithm assumed detecting if two faces intersect is a black box operation, the details weren't important for the algorithm itself. Still, in order to create a solid implementation of any collision detection scheme, the problem of intersecting faces must be solved. In this section two methods are presented that attempt this.<br /><br /> The first method is called the intersection-based collision detection and is basically an accurate way of detecting whether any two faces intersect each other. Other methods exist as well, however, the second method presented here is a hybrid method that incorporates bounding spheres and some basic geometry testing.<br /><br /> <br /><strong class='bbc'>Intersection-based collision detection</strong><br /> The problem of collision detection between faces can be broken down to two stages. A well known fact is that any two planes that are parallel don't intersect each other. A plane of course is a flat, infinitely thin, infinitely long surface in 3D space. Unless the planes that contain the faces are parallel, those two planes are going to intersect each other. The first stage would be to detect if any edges of the first face intersect the <em class='bbc'>plane</em> of the second face. That ensures that the first face at least intersects the plane that contains the second face, but it is not sufficient in order to determine if the first face intersects the actual second face. This will be dealt with in the second stage.<br /><br /> In order to determine if any edges in the first face pierce the second face's plane, the vertices making up the edges must be examined. For simplicity, if two points that define an edge fall on one side of the plane (containing the second face), the edge does not pierce that plane. Then, generalizing for the entire face, if all edges don't pierce the plane, the face does not pierce the plane. If any edge pierces the plane it is assured that at least one edge pierces the plane. For convex polygons there are <em class='bbc'>exactly</em> two edges piercing the plane.<br /><br /> The only thing left to solve is how to find whether an edge pierces the plane. It so happens that all points in space that satisfy the following equation fall on the plane:<br /><br /> <span rel='lightbox'><span rel='lightbox'><img class='bbc_img' src='http://images.gamedev.net/columns/hardcore/ofg/img34.png' alt='Posted Image' class='bbc_img' /></span></span><br /><br /> This might be familiar to you. It is called the <em class='bbc'>plane equation</em>. Any point that lies on the plane itself will evaluate the equation to be true. It so happens that any points on one "side" of the plane produce a positive sign (instead of 0) and all the points on the other "side" produce a negative sign. Therefore, if an edge is defined by two points (vertices) and solving for both vertices gives the same sign, the edge is definitely not piercing the plane. The logical extension to this is to check all edges against the plane. The check becomes very simple:<br /><br /> <ul class='bbc'><li>Solve the plane equation of the second face for each vertex in the first face. If all vertices produce the same sign, the first face definitely doesn't pierce the plane in question. Creating the plane equation is easy given two vectors on that plane (three vertices of one face can give two vectors). If any vertex gives the other sign, there is a possibility of collision.</li></ul> If there was any piercing by any edge, the second stage should be used to actually detect whether the edges actually pierce the second face <em class='bbc'>itself</em>, unlike the plane tested against in the first step. Actually, this step is all that is needed in order to determine if two faces intersect. However, the second stage is much slower in comparison with stage one. Stage one can be used as an optimization to rule out any faces that definitely <em class='bbc'>don't</em> collide.<br /><br /> Because this algorithm deals with convex polygons (faces actually), this stage will assume the same. Since step one stopped when an edge that pierces the second plane was found, and there are actually two such edges (again, for convex polygons such as triangles), there must be exactly two intersection points between the face and the plane of the other face. Using the plane equation and solving for the x,y and z coordinates of the point that represent the intersection between the plane and the edge it is possible to find those two intersection points. Those points are naturally on the plane itself.<br /><br /> Once two intersection points are found, in order to determine whether the edge pierced the second face itself, at least one of the points must be <em class='bbc'>within</em> the second face!<br /><br /> What is left then is to determine whether a point is within a convex polygon or not. If one of them is within it, there is a definite collision. If both are not within it, there is definitely no collision. There is one very simple solution to this problem, called the <em class='bbc'>half-space</em> method. The halfspace method is a method to determine if a point lies within a convex polygon. For 2D polygons this is simple. Using the line equations of the edges and solving for the point gives either 0, a negative sign or a positive sign, just like in the previous step. However, our edges are vectors in 3D space so this doesn't apply here.<br /><br /> What can be done instead is create a plane that is perpendicular both to the normal of the face and the edge vector. That plane divides space into two parts and therefore the point must lie either on it, or on one of its sides. The same logic from the previous stage applies here as well:<br /><br /> <ul class='bbc'><li>Calculate the intersection points of the edges found piercing the plane in stage one using the second face's plane equation. </li><li>For each edge in the second face, take the cross product of the edge vector with the normal to the face, giving a perpendicular plane. </li><li>The points must lie either on the plane or on either side. Using the same logic as in stage one can determine this for each edge plane. </li><li>If the point lies in the same part of space ("side") for all planes corresponding to the edges of the face, the point is within the face and therefore a collision has occurred </li><li>If both points lie outside the planes of the edges (not all signs are the same for each point checked against the edge planes), there is definitely no collision.</li></ul><strong class='bbc'>Hybrid collision detection between two faces</strong><br /> This method is a proposed method that approximates intersection between a pair of faces. The idea is to find a bounding sphere for both faces. If the bounding spheres intersect (an easy and fast check), there is a need for a better check. If the bounding spheres do not intersect, there is definitely no intersection.<br /><br /> For intersecting bounding spheres, there is the possibility of collision. Consider using the logic in the previous method's stage one to determine whether edges on the first face pierce the second. Although this alone does not guarantee collision of course, coupled with the bounding spheres check it gives a reasonable chance for collision. That is, if the spheres collided AND an edge was found to be piercing the other face, most chances there is a collision. Of course, this method is only an approximation and will not give accurate results such as those provided by the intersection method. However, this method is by far much faster than the intersection based method.<br /><br /> Generally, the smaller the faces, the better this method works. This is because when the faces are smaller, there is less and less "free space" within the sphere. Less free space that can generate a collision between spheres but might not actually generate a collision between the faces themselves.<br /><br /> <br /><strong class='bbc'>Appendix B - Determining <em class='bbc'>k</em>, the accuracy constant</strong><br /> The reasoning behind assigning a proper <em class='bbc'>k</em> value are totally up to the engine in question. In most cases in a normal 3D surface, each vertex will share a maximum of four polygons (each made of two triangles). Of course, there are cases, such as the tip of a pyramid with <em class='bbc'>n</em> sides that do not satisfy this condition. For the first case, a normal 3D surface, each vertex can be shared by 8 triangles at most and 4 at the very minimum. Therefore those values are chosen as the default accuracy range for most purposes. Assigning a different value might serve different types of geometry better though, it has to be considered carefully.<br /><br /> For the cases where a vertex does not share only 8 triangles (such as the tip of an n-sided pyramid), it is a definite fact that if the vertex falls within another 3D object, all of the n-sides of the pyramid will intersect the other object. Therefore, any value for <em class='bbc'>k</em> that is one or more will suffice for this type of degenerate case. It happens that any 3D geometry can be represented either by the former representation or the latter. The latter has no bearing on the assignment of <em class='bbc'>k</em>. The former has and it has been shown that a value of 6 is the best average while 8 should give good accuracy.<br /><br /> <br /><strong class='bbc'>About this document...</strong><br /> <strong class='bbc'>Opposing Face Geometry<br />A Collision Detection Optimization Scheme</strong> This document was generated using the <a href='http://www.latex2html.org/' class='bbc_url' title='External link' rel='nofollow external'><strong class='bbc'>LaTeX</strong>2HTML</a> translator Version 2002 (1.62)<br /><br /> Copyright © 1993, 1994, 1995, 1996, <a href='http://cbl.leeds.ac.uk/nikos/personal.html' class='bbc_url' title='External link' rel='nofollow external'>Nikos Drakos</a>, Computer Based Learning Unit, University of Leeds.<br />Copyright © 1997, 1998, 1999, <a href='http://www.maths.mq.edu.au/%7Eross/' class='bbc_url' title='External link' rel='nofollow external'>Ross Moore</a>, Mathematics Department, Macquarie University, Sydney.<br /><br /> The translation was initiated by Lord Soth on 2004-01-05<br /><br /> <strong class='bbc'>Footnotes</strong><br /><br />&nbsp;&nbsp; &lt;a href="#tex2html1"&gt;1&nbsp;&nbsp;&nbsp;&nbsp; In this article the term 'polygon' will be replaced by 'face'&nbsp;&nbsp; 2 Lines connecting two vertices are called 'edges'&nbsp;&nbsp; 3 Convex - A polygon (face) that has no "dents" in it.&nbsp;&nbsp; 4 Concave - A face that has "dents" in it. An edge connecting 2 vertices might fall outside the face.&nbsp;&nbsp; 5 Later on the problem of concave objects will be discussed&nbsp;&nbsp;&nbsp;&nbsp;Lord Soth 2004-01-05<br /><a href='mailto:lordsoth8@bigfoot.com' class='bbc_url' title='External link' rel='nofollow external'>lordsoth8@bigfoot.com</a><br /><a href='mailto:voguemaster@walla.co.il' class='bbc_url' title='External link' rel='nofollow external'>voguemaster@walla.co.il</a><br />ICQ: 5178515<br />Copyright © 2003 All Rights Reserved]]></description>
		<pubDate>Thu, 19 Feb 2004 01:31:28 +0000</pubDate>
		<guid isPermaLink="false">fb598cb494b6e98253995d800fab908d</guid>
	</item>
	<item>
		<title>A Simple Quaternion-based Camera</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/a-simple-quaternion-based-camera-r1997</link>
		<description><![CDATA[I looked through a thousand web pages for a good quaternion camera tutorial, and I could not find one. There is a good example on gametutorials.com that uses quaternions, but it uses them to rotate general objects and makes things a little more difficult than they actually need to be to use quaternions to make a camera. Therefore, in this article I am going to present a simple quaternion-based camera that can be used to rotate the view of your camera using the mouse.<br /><br /><h2>So, what is a Quaternion?</h2><br />Quaternions aren't actually as scary as they sound. Everything I read regarding quaternions talked about imaginary numbers, hyper-complex numbers, spinors, and other scary sounding things. There was too much maths jargon for my liking. If you understand what a vector is, it isn't very hard to understand what a quaternion is. One way to represent a quaternion is<br /><br /><pre class='prettyprint lang-auto linenums:0'>
Q = xi + yj + zk + w&nbsp;&nbsp;
</pre><br />where <em class='bbc'>i,j</em> & <em class='bbc'>k</em> are coordinate basis vectors for three dimensions.<br /><br />I don't particularly like this representation for computer graphics, especially where cameras are concerned. I prefer thinking of a quaternion as an object that contains a vector and a scalar. We'll call the vector <strong class='bbc'>v</strong> and keep the scalar as w.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
Q = [ w, [b]v[/b] ]
</pre><br />where <strong class='bbc'>v</strong> = x<em class='bbc'>i</em> + y<em class='bbc'>j</em> + z<em class='bbc'>k</em>.<br /><br />For use in the sample code below, here's a quaternion data structure:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
struct quaternion
{
&nbsp;&nbsp;double x, y, z, w;
};
</pre><br />This is a much easier representation to comprehend for me. Now for our purposes, quaternion addition, subtraction, etc., aren't needed. We only need to know how to normalize (scale to length=1), multiply and compute the conjugate of a quaternion in order to generate a rotation. These tasks are actually very simple and are described below.<br /><br /><h2>Normalizing a quaternion</h2><br />Normalizing a quaternion is almost the same as normalizing a vector. We start by computing the length of the quaternion to be normalized, which is done using the Euclidean distance forumula:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
|Q| = sqrt( w^2 + x^2 + y^2 + z^2)
</pre><br />A function to implement this formula might look like this:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
double length(quaternion quat)
{
&nbsp;&nbsp;return sqrt(quat.x * quat.x + quat.y * quat.y +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quat.z * quat.z + quat.w * quat.w);
}
</pre><br />Not too hard is it? Now to get the normalized vector Q, which we'll call Q*, we just divide every element of Q by |Q|.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
Q* = Q/|Q| = [w/|Q|, [b]v[/b]/|Q|]
</pre><br />Here's some sample code for this function:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
quaternion normalize(quaternion quat)
{
&nbsp;&nbsp;double L = length(quat);

&nbsp;&nbsp;quat.x /= L;
&nbsp;&nbsp;quat.y /= L;
&nbsp;&nbsp;quat.z /= L;
&nbsp;&nbsp;quat.w /= L;

&nbsp;&nbsp;return quat;
}
</pre><br />This will give us a quaternion of length 1 (which is very important for rotations). Still nothing scary right? Well, it doesn't really get much harder than this.<br /><br /><h2>The conjugate of a quaternion</h2><br />Let's compute the conjugate of a quaternion and call it Q'. The conjugate is simply<br /><br /><pre class='prettyprint lang-auto linenums:0'>
Q' = [ w, -[b]v[/b] ]
</pre><br />Here's the code for the conjugate:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
quaternion conjugate(quaternion quat)
{
&nbsp;&nbsp;quat.x = -quat.x;
&nbsp;&nbsp;quat.y = -quat.y;
&nbsp;&nbsp;quat.z = -quat.z;
&nbsp;&nbsp;return quat;
}
</pre><br />The last thing you need to know is quaternion multiplication. Then you'll be ready to make a quaternion based camera.<br /><br /><h2>Multiplying quaternions</h2><br />Multiplication with quaternions is a little complicated as it involves dot-products cross-products. However, if you just use the following forumula that expands these operations, it isn't too hard. To multiply quaternion A by quaternion B, just do the following:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
C = A * B
</pre><br />such that:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
C.x = | A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y |
C.y = | A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x |
C.z = | A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w |
C.w = | A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z |
</pre><br />Here's some code for multiplication:<br /><br /><pre class='prettyprint lang-auto linenums:0'>
quaternion mult(quaternion A, quaternion B)
{
&nbsp;&nbsp;quaternion C;

&nbsp;&nbsp;C.x = A.w*B.x + A.x*B.w + A.y*B.z - A.z*B.y;
&nbsp;&nbsp;C.y = A.w*B.y - A.x*B.z + A.y*B.w + A.z*B.x;
&nbsp;&nbsp;C.z = A.w*B.z + A.x*B.y - A.y*B.x + A.z*B.w;
&nbsp;&nbsp;C.w = A.w*B.w - A.x*B.x - A.y*B.y - A.z*B.z;
&nbsp;&nbsp;return C;
}
</pre><br />That's not too that hard is it? Now we'll look at how to use these operations to make a quaternion based camera.<br /><br /><h2>The quaternion camera</h2><br />To make a camera you typically use three vectors: Position, View, and Up (or you may call them what you like). For a first person camera - which we will be using - we're only going to consider rotating the View vector. With quaternions we can rotate a vector around an arbitrary axis (same as with axis-angles) very easily.<br /><br />To achieve this, first we need to turn our View vector into a quaternion, then define a rotation quaternion and lastly, apply the rotation quaternion to the View quaternion to make the rotation.<br /><br />To make the View quaternion, V, the x, y, and z values are taken from the View vector and we simply add a 0 for the scalar component w. Thus,<br /><br /><pre class='prettyprint lang-auto linenums:0'>
V = [0, View]
</pre><br />Then you need to make a quaternion to represent the rotation. To do this, you need the vector you want to rotate about, and the angle you wish to rotate by. We'll just simply term the vector to rotate about A, and the angle theta. Here is the formula to build your rotation quaternion, which we'll call R.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
vector A = [x, y, z] 
R.x = A.x * sin(theta/2)
R.y = A.y * sin(theta/2)
R.z = A.z * sin(theta/2)
R.w = cos(theta/2)
</pre><br />So now we have the vector (View) and its quaternion V that we want to rotate by an angle theta about the vector A. The rotation quaternion R defines this rotation. After the rotation, we'll have the new quaternion representing our view, given by W. The rotation operation is simply<br /><br /><pre class='prettyprint lang-auto linenums:0'>
W = R * V * R'
</pre><br />where R' is the conjugate of R. To get our new view vector, we just take the vector components out of W.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
NewView = [W.x W.y W.z]
</pre><br />The following function (using SDL, use glut or whatever you like) sets the view based on the distance from the current mouse coordinates to the centre of the screen. I learned how to do this from gametutorials.com, and modified the code for my purposes. In this code, positive x is to the right and positive y is down the screen.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
void Camera::SetViewByMouse(void)
{
&nbsp;&nbsp;// the coordinates of our mouse coordinates
&nbsp;&nbsp;int MouseX, MouseY;

&nbsp;&nbsp;// the middle of the screen in the x direction
&nbsp;&nbsp;int MiddleX = SCREENWIDTH/2;

&nbsp;&nbsp;// the middle of the screen in the y direction
&nbsp;&nbsp;int MiddleY = SCREENHEIGHT/2;

&nbsp;&nbsp;// vector that describes mouseposition - center
&nbsp;&nbsp;Vector MouseDirection(0, 0, 0);

&nbsp;&nbsp;// static variable to store the rotation about the x-axis, since
&nbsp;&nbsp;// we want to limit how far up or down we can look.
&nbsp;&nbsp;// We don't need to cap the rotation about the y-axis as we
&nbsp;&nbsp;// want to be able to turn around 360 degrees
&nbsp;&nbsp;static double CurrentRotationAboutX = 0.0;

&nbsp;&nbsp;// The maximum angle we can look up or down, in radians
&nbsp;&nbsp;double maxAngle = 1;

&nbsp;&nbsp;// This function gets the position of the mouse
&nbsp;&nbsp;SDL_GetMouseState(&amp;MouseX, &amp;MouseY);

&nbsp;&nbsp;// if the mouse hasn't moved, return without doing
&nbsp;&nbsp;// anything to our view
&nbsp;&nbsp;if((MouseX == MiddleX) &amp;&amp; (MouseY == MiddleY))
&nbsp;&nbsp;&nbsp;&nbsp;return;

&nbsp;&nbsp;// otherwise move the mouse back to the middle of the screen
&nbsp;&nbsp;SDL_WarpMouse(MiddleX, MiddleY);

&nbsp;&nbsp;// get the distance and direction the mouse moved in x (in
&nbsp;&nbsp;// pixels). We can't use the actual number of pixels in radians,
&nbsp;&nbsp;// as only six pixels&nbsp;&nbsp;would cause a full 360 degree rotation.
&nbsp;&nbsp;// So we use a mousesensitivity variable that can be changed to
&nbsp;&nbsp;// vary how many radians we want to turn in the x-direction for
&nbsp;&nbsp;// a given mouse movement distance

&nbsp;&nbsp;// We have to remember that positive rotation is counter-clockwise. 
&nbsp;&nbsp;// Moving the mouse down is a negative rotation about the x axis
&nbsp;&nbsp;// Moving the mouse right is a negative rotation about the y axis
&nbsp;&nbsp;MouseDirection.x = (MiddleX - MouseX)/MouseSensitivity; 
&nbsp;&nbsp;MouseDirection.y = (MiddleY - MouseY)/MouseSensitivity;

&nbsp;&nbsp;CurrentRotationX += MouseDirection.y;
&nbsp;&nbsp;
&nbsp;&nbsp;// We don't want to rotate up more than one radian, so we cap it.
&nbsp;&nbsp;if(CurrentRotationX &gt; 1)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;CurrentRotationX = 1;
&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;}
&nbsp;&nbsp;// We don't want to rotate down more than one radian, so we cap it.
&nbsp;&nbsp;if(CurrentRotationX &lt; -1)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;CurrentRotationX = -1;
&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;}
&nbsp;&nbsp;else
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;// get the axis to rotate around the x-axis. 
&nbsp;&nbsp;&nbsp;&nbsp;Vector Axis = CrossProduct(View - Position, Up);
&nbsp;&nbsp;&nbsp;&nbsp;// To be able to use the quaternion conjugate, the axis to
&nbsp;&nbsp;&nbsp;&nbsp;// rotate around must be normalized.
&nbsp;&nbsp;&nbsp;&nbsp;Axis = Normalize(Axis);

&nbsp;&nbsp;&nbsp;&nbsp;// Rotate around the y axis
&nbsp;&nbsp;&nbsp;&nbsp;RotateCamera(MouseDirection.y, Axis.x, Axis.y, Axis.z);
&nbsp;&nbsp;&nbsp;&nbsp;// Rotate around the x axis
&nbsp;&nbsp;&nbsp;&nbsp;RotateCamera(MouseDirection.x, 0, 1, 0);
&nbsp;&nbsp;}
}
</pre><br />This function actually rotates our view. After we are done, just plug your camera vectors (Position, View, and Up) into gluLookAt(Position.x, Position.y, Position.z, View.x, View.y, View.z, Up.x, Up.y, Up.z). Here is the code for the rotation.<br /><br /><pre class='prettyprint lang-auto linenums:0'>
void RotateCamera(double Angle, double x, double y, double z)
{
&nbsp;&nbsp;quaternion temp, quat_view, result;

&nbsp;&nbsp;temp.x = x * sin(Angle/2);
&nbsp;&nbsp;temp.y = y * sin(Angle/2);
&nbsp;&nbsp;temp.z = z * sin(Angle/2);
&nbsp;&nbsp;temp.w = cos(Angle/2);

&nbsp;&nbsp;quat_view.x = View.x;
&nbsp;&nbsp;quat_view.y = View.y;
&nbsp;&nbsp;quat_view.z = View.z;
&nbsp;&nbsp;quat_view.w = 0;

&nbsp;&nbsp;result = mult(mult(temp, quat_view), conjugate(temp));

&nbsp;&nbsp;View.x = result.x;
&nbsp;&nbsp;View.y = result.y;
&nbsp;&nbsp;View.z = result.z;
}
</pre><br />Again, at the end of the above functions, you should call<br /><br /><pre class='prettyprint lang-auto linenums:0'>
gluLookAt(Position.x, Position.y, Position.z,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;View.x, View.y, View.z, Up.x, Up.y, Up.z).
</pre><br />and your camera should work just perfectly. Maybe some other time, I'll do a third person camera tutorial, and explain how to use SLERP.]]></description>
		<pubDate>Mon, 22 Sep 2003 00:58:47 +0000</pubDate>
		<guid isPermaLink="false">e33d974aae13e4d877477d51d8bafdc4</guid>
	</item>
	<item>
		<title>Beat Detection Algorithms</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/beat-detection-algorithms-r1952</link>
		<description><![CDATA[<p><span style="font-size:18px;"><strong>Disclaimer</strong></span></p><br />
<p><br />
This document is to be distributed for free and without any modification from its original state. The author declines all responsibility in the damage this document or any of the things you will do with it might do to anyone or to anything. This document and any of its contents is not copyrighted and is free of all rights, you may thus use it, modify it or destroy it without breaking any international law. However according to the author's will, you may not use this document for commercial profit directly, but you may use indirectly its intellectual contents; in which case I would be pleased to receive a mail of notice or even thanks. This is my first tutorial and I am still a student, you must assume that this document is probably not free of small errors and bugs. In the same state of mind, those algorithms are not fully optimised, they are explained for pedagogical purposes and you may find some redundant computations or other voluntary clumsiness. Please be indulgent and self criticise everything you might read. Hopefully, lots of this stuff was taken in sources and books of reference; as for the stuff I did: it has proven some true efficiency in test programs I made and which work as wanted. As said in the introduction: If you have any question or any comment about this text, please send it to the above email address, I'll be happy to answer as soon as possible.</p><br />
<p><br />
<span style="font-size:18px;"><strong>Introduction</strong></span></p><br />
<p><br />
Simulating a physical phenomena which obeys to known mathematical equations is, with a number of approximations, always feasable. But what about more abstract concepts, such as feelings, which do not follow any laws? The simplest things we can feel are often the hardest things to capture in a program. Beat detection follows this rule : feeling the beat of a song comes naturally to humans or animals. Indeed it is only a feeling one gets when listening to a melody, a feeling which will make you dance in rhythm or hit a table with your hands on the melody beats. Therefore, how can we teach this beat detection to a machine that can only compute logical operations? In fact there are a number of algorithms which manage to approximate, more or less accurately, this beat detection. We will first study the statistical approach of beat detection on a streaming source and secondly a filtering approach of rhythm extraction on a static song.</p><br />
<p><br />
This guide assumes the reader has basic signal processing understanding (FFT, convolutions and correlations should sound common) maybe some stuff in statistics will also help (Variance, Average, Principal Components Analysis, will be quoted among others). The point here is not to actually write the code of these algorithms, but more to understand how they work and to be able to adapt or create the appropriate algorithm to a situation. If you have a question or a comment about this text, please send it to the above email address, I'll be happy to answer as soon as possible. Anyway, the aim here is to give more precise ideas on the subject of beat detection to the reader. Enjoy.</p><br />
<p><br />
<strong><span style="font-size:18px;">I – Statistical streaming beat detection</span></strong></p><br />
<p><br />
<strong><span style="font-size:14px;">1 – Simple sound energy</span></strong></p><br />
<p><br />
<em><strong>a - A first analysis</strong></em></p><br />
<p><br />
The human listening system determines the rhythm of music by detecting a pseudo – periodical succession of beats. The signal which is intercepted by the ear contains a certain energy, this energy is converted into an electrical signal which the brain interprets. Obviously, The more energy the sound transports, the louder the sound will seem. But a sound will be heard as a <strong>beat </strong>only if his energy is largely superior to the sound's energy history, that is to say if the brain detects a <strong>brutal variation in sound energy</strong>. Therefore if the ear intercepts a monotonous sound with sometimes big energy peaks it will detect beats, however, if you play a continuous loud sound you will not perceive any beats. Thus, the beats are big variations of sound energy. This first analysis will bring us to our simplest model : <em><strong>Sound energy peaks</strong></em>.</p><br />
<p><br />
In this model we will detect sound energy variations by computing <strong>the average sound energy </strong>of the signal and comparing it to the <strong>instant sound energy</strong>. Lets say we are working in stereo mode with two lists of values : (an) and (bn). (an) contains the list of sound amplitude values captured every Te seconds for the left channel, (bn) the list of sound amplitude values captured every Te seconds for the right channel. So we want to compute the instant energy and the average energy of the signal. The instant energy will in fact be the energy contained in 1024 samples (1024 values of a[n] and b[n]), 1024 samples represent about 5 hundreds of second which is pretty much 'instant'. The average energy should not be computed on the entire song, some songs have both intense passages and more calm parts. The instant energy must be compared to the nearby average energy, for example if a song has an intense ending, the energy contained in this ending shouldn't influence the beat detection at the beginning. <strong>We detect a beat only when the energy is superior to a local energy average</strong>. Thus we will compute the average energy on say : 44032 samples which is about 1 second, that is to say we will assume that the hearing system only remembers of 1 second of song to detect beat. This 1 second time (44032 samples) is what we could call the human ear energy persistence model; it is a compromise between being to big and taking into account too far away energies, and being too small and becoming to close to the instant energy to make a valuable comparison.</p><br />
<p><br />
The history buffer where we will keep the last 44032 samples wil contain in fact too lists of samples (B[0]) and (B[1]) corresponding to the left (an) and to the right (bn) channels history.</p><br />
<p><br />
<em>Simple sound energy algorithm #1:</em></p><br />
<p><br />
Every 1024 samples:</p><br />
<br /><ul class="bbc"><li>Use the 1024 new samples taken in a[n] and b[n] to compute the instant energy 'e', using the following formula (i0 is the position of the 1024 samples to process):&nbsp;&nbsp; <br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12771-0-31468500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12771" title="formula1.png - Size: 1.21K, Downloads: 70"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-42452600-1355405727.png" id='ipb-attach-img-12771-0-31468500-1369216368' style='width:327;height:64' class='attach' width="327" height="64" alt="Attached Image: formula1.png" /></a><strong>(R1)</strong></li><li>Compute the local average energy '&lt;E>' on the 44100 samples of a history buffer (B):<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12772-0-31487700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12772" title="formula2.png - Size: 1.5K, Downloads: 72"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-56747900-1355405749.png" id='ipb-attach-img-12772-0-31487700-1369216368' style='width:356;height:52' class='attach' width="356" height="52" alt="Attached Image: formula2.png" /></a><strong>(R2)</strong></li><li>Shift the 44032 history buffer (B) of 1024 indexes to the right so that we make room for the 1024 new samples and evacuate the oldest 1024 samples.</li><li>Move the 1024 new samples on top of the history buffer.</li><li>Compare 'e' to 'C * ' where C is a constant which will determine the sensibility of the algorithm to beats. A good value for this constant is 1.3. If 'e' is superior to 'C * ' then we have a beat!</li></ul><br />
<p><em><strong>b - Some direct optimisations</strong></em></p><br />
<p><br />
This was the basic version of the algorithm, its speed and accurecy can be improved quite easily. The algorithm can be optimised by <strong>keeping the energy values computed on 1024 samples in history instead of the samples themselves</strong>, so that we don't have to compute the average energy on the 44100 samples buffer (B) but on the instant energies history we will call (E). This sound energy history buffer (E) <strong>must </strong>correspond to approximately <strong>1 second of music</strong>, that is to say it must contain the energy history of 44032 samples (calculated on groups of 1024) if the sample rate is 44100 samples per second. Thus E[0] will contain the newest energy computed on the newest 1024 samples, and E[42] will contain the oldest energy computed on the oldest 1024 samples. We have 43 energy values in history, each computed on 1024 samples which makes 44032 samples energy history, which is equivalent to 1 second in real time. The count is good. The value of 1 second represents the persistance of the music energy in the human ear, it was obtain with experimentations but it may varry a little from a person to another, just adjust it as you feal. So here is what the algorithm becomes:</p><br />
<p><br />
<em>Simple sound energy algorithm #2:</em></p><br />
<p> </p><br />
<p>Every 1024 samples:</p><br />
<br /><ul class="bbc"><li>Compute the instant sound energy 'e' on the 1024 new sample values taken in (an) and (bn) using the formula <strong>(R1)</strong></li><li>Compute the average local energy &lt;E> with (E) sound energy history buffer:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12773-0-31506300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12773" title="formula3.png - Size: 829bytes, Downloads: 72"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-60854200-1355405848.png" id='ipb-attach-img-12773-0-31506300-1369216368' style='width:173;height:53' class='attach' width="173" height="53" alt="Attached Image: formula3.png" /></a><strong>(R3)</strong></li><li>Shift the sound energy history buffer (E) of 1 index to the right. We make room for the new energy value and flush the oldest.</li><li>Pile in the new energy value 'e' at E[0].</li><li>Compare 'e' to 'C*&lt;E>'.</li></ul><br />
<p><em><strong>c - Sensitivity detection</strong></em></p><br />
<p><br />
The imediate draw back of this algorithm is <strong>the choice of the 'C' constant</strong>. For example in techno and rap music beats are quite intense and precise so 'C' should be quite high (about 1.4); whereas for rock and roll, or hard rock which contains a lot of noise, the beats are more confused and 'C' should be low (about 1.1 or 1.0). There is a way, to make the algorithm determine automatically the good choice for the 'C' constant. We must compute <strong>the variance of the energies </strong>contained in the energy history buffer (E). This variance, which is nothing but the average of ( Energy Values – Energy average = (E) - &lt;E>), will quantify how marked the beats of the song are and thus will give us a way to compute the value of the 'C' constant. The formula to calculate the variance of the 43 E[i&#93;values is described below <strong>(R4)</strong>. Finally, the greater the variance is the more sensitive the algorithm should be and thus the smaller 'C' will become. We can choose a linear decrease of 'C' with 'V' (the variance) and for example when V&nbsp;&nbsp;200, C -> 1.0 and when V -> 25, C -> 1.45 <strong>(R5)</strong>. This is our new version of the sound energy beat detection algorithm:</p><br />
<p><br />
<em>Simple sound energy algorithm #3:</em></p><br />
<p><br />
&nbsp;&nbsp; Every 1024 samples:</p><br />
<br /><ul class="bbc"><li>Compute the instant sound energy 'e' on the 1024 new samples taken in (an) and (bn) using the following formula <strong>(R1)</strong>.</li><li>Compute the average local energy &lt;E> with (E) sound energy history buffer using formula <strong>(R3)</strong>.</li><li>Compute the variance 'V' of the energies in (E) using the following formula:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12774-0-31526200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12774" title="formula4.png - Size: 1.08K, Downloads: 69"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-07165500-1355406003.png" id='ipb-attach-img-12774-0-31526200-1369216368' style='width:231;height:56' class='attach' width="231" height="56" alt="Attached Image: formula4.png" /></a><strong>(R4)</strong><br />Compute the 'C' constant using a linear degression of 'C' with 'V', using a linear regression with values <strong>(R5)</strong>:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12775-0-31544800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12775" title="formula5.png - Size: 874bytes, Downloads: 72"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-20943100-1355406039.png" id='ipb-attach-img-12775-0-31544800-1369216368' style='width:263;height:24' class='attach' width="263" height="24" alt="Attached Image: formula5.png" /></a><strong>(R6)</strong></li><li>Shift the sound energy history buffer (E) of 1 index to the right. We make room for the new energy value and flush the oldest.</li><li>Pile in the new energy value 'e' at E[0].</li><li>Compare 'e' to 'C*[lessthanE>', if superior we have a beat!</li></ul><br />
<p>&nbsp;&nbsp; Those three algorithms were tested with several types of music, among others : pop, rock, metal, techno, rap, classical, punk. The fact is the results are quite unpredictable. I will only talk about <em>Simple beat detection algorithm #3</em> as <em>#2</em> and <em>#1</em> are only pedagogical intermediates to get to the <em>#3</em>.</p><br />
<p><br />
Clearly, <strong>the beat detection is very accurate and sounds right with techno and rap</strong>, the beats are very precise and the music contains very few noise. The algorithm is quite satisfying for that kind of music and if you aim to use beat detection on techno you can stop reading here, the rest won't change anything to your beat detection. However, even if the improvement of the dynamic 'C' calculations ameliorates things alot, <strong>the beat detection on punk, rock and hard rock, is sometimes quite approximate</strong>. We can feel it doesn't really get the rythm of the song. Indeed the algorithm detects energy peaks. Sometimes you can hear a drum beat which is sank among other noises and which goes trough the algorithm without being detected as a beat.</p><br />
<p><br />
To explain this phenomena lets say a guitare and flute make alternatively an amplitude constant note. Each time the first finishes the other starts. The note made by the guitare and the note made by the flute have the same energy but the ear detects a certain rhythm because the notes of the instruments are at different pitch. For our algorithm (who is one might say colorblind) it is just an amplitude constant noise with no energy peaks. This partly explains why the algorithm doesn't detect precisely beats in songs with a lot of instruments playing at different rythms and simultaneously. Our next analysis will make us walk through this difficulty.</p><br />
<p><br />
Comparing the results we have obtained with the <em>Simple beat detection algorithm #3 </em>to its computing cost, this algorithm is very efficient. If you are not looking for a perfect beat detection than I recommend you use it. Here is a screenshot of a program I made using this algorithm. You fill find the binaries and the sources on my homepage.</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12776-0-31562800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12776" title="image020.png - Size: 7.77K, Downloads: 71"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-14245000-1355406889_thumb.png" id='ipb-attach-img-12776-0-31562800-1369216368' style='width:480;height:361' class='attach' width="480" height="361" alt="Attached Image: image020.png" /></a><br />
<strong>Figure 1: </strong>The spectrum analyser is not useful for the beat detection it is only for visual matters, but you can see at the top some of the parameters the program computes to execute the algorithm.</p><br />
<p> </p><br />
<p><strong>2 – Frequency selected sound energy</strong></p><br />
<p><br />
<em><strong>a - The idea and the algorithm</strong></em></p><br />
<p><br />
The issue with our last analysis of beat detection is that it is colorblind. We have seen that this could raise quite a few problems for noisy like songs in rock or pop music. What we must do is give our algorithm the abbility to determine on which frequency subband we have a beat and if it is powerful enough to take it into account. Basically we will try to <strong>detect big sound energy variations in particular frequency subbands</strong>, just like in our last analysis; unless this time we will be able to seperate beats regarding their color ( frequency subband ). Thus If we want to give more importants to low frequency beats or to high frequency beats it should be more easy. Notice that the energy computed in the time domain is the same as the energy computed in the frequency domain, so we don't have any difference between computing the energy in time domain or in frequency domain. For maths freaks this is called the Parseval Theorem.</p><br />
<p><br />
Okay that was just a bit of sport, lets go back to the mainstream; Here is how the <strong><em>Frequency selected sound energy </em></strong>algorithm works: The source signals are still coming from (an) and (bn). (an) and (bn) can be taken from a wave file, or directly from a streaming microphone or line input. Each time we have accumulated 1024 new samples, we will pass to the frequency domain with a <strong>Fast Fourier Transform (FFT)</strong>. We will thus obtain a 1024 frequency spectrum. We then divide this spectrum into however many subbands we like, here I will take 32. The more subbands you have, the more sensitive the algorithm will be but the harder it will become to adapt it to lots of different kinds of songs. Then we compute the <strong>sound energy </strong>contained in <strong>each of the subbands </strong>and we compare it to the <strong>recent energy average corresponding to this subband</strong>. If one or more subbands have an energy superior to their average we have detected a beat. <br />
 <br />
The great progress with the last algorithm is that we now know more about our beats, and thus we can use this information to change an animation, for example. So here is more precisely the <em>Frequency selected sound energy algorithm #1:</em></p><br />
<p><br />
&nbsp;&nbsp; Every 1024 samples:</p><br />
<br /><ul class="bbc"><li>Compute the FFT on the 1024 new samples taken in (an) and (bn). The FFT inputs a complex numeric signal. We will say (an) is the real part of the signal and (bn) the imagenary part. Thus the FFT will be made on the 1024 complex values of:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12777-0-31581200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12777" title="formula6.png - Size: 524bytes, Downloads: 68"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-47790500-1355407009.png" id='ipb-attach-img-12777-0-31581200-1369216368' style='width:109;height:31' class='attach' width="109" height="31" alt="Attached Image: formula6.png" /></a><em>You can find FFT tutorials and codes in C, Visual Basic or C++ on my homepage in the 'tutorials' section or by typing 'FFT' on Google.</em></li><li>From the FFT we obtain 1024 complex numbers. We compute the square of their module and store it into a new 1024 buffer. This buffer (B) contains the 1024 frequency amplitudes of our signal.</li><li>Divide the buffer into 32 subbands, compute the energy on each of these subbands and store it at (Es). Thus (Es) will be 32 sized and Es[i&#93; will contain the energy of subband 'i':<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12778-0-31599100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12778" title="formula7.png - Size: 1.43K, Downloads: 57"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-70090500-1355407035.png" id='ipb-attach-img-12778-0-31599100-1369216368' style='width:248;height:61' class='attach' width="248" height="61" alt="Attached Image: formula7.png" /></a><strong>(R7)</strong></li><li>Now, to each subband 'i' corresponds an energy history buffer called (Ei). This buffer contains the last 43 energy computations for the 'i' subband. We compute the average energy &lt;E> for the 'i' subband simply by using:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12779-0-31617500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12779" title="formula8.png - Size: 1.07K, Downloads: 52"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-47958200-1355407054.png" id='ipb-attach-img-12779-0-31617500-1369216368' style='width:205;height:60' class='attach' width="205" height="60" alt="Attached Image: formula8.png" /></a><strong>(R8)</strong></li><li>Shift the sound energy history buffers (Ei) of 1 index to the right. We make room for the new energy value of the subband 'i' and flush the oldest.</li><li>Pile in the new energy value of subband 'i' : Es[i&#93; at Ei[0].<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12780-0-31637700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12780" title="formula9.png - Size: 592bytes, Downloads: 59"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-40276400-1355407088.png" id='ipb-attach-img-12780-0-31637700-1369216368' style='width:129;height:33' class='attach' width="129" height="33" alt="Attached Image: formula9.png" /></a><strong>(R9)</strong></li><li>For each subband 'i' if Es[i&#93; > (C*&lt;E>) we have a beat !</li></ul><br />
<p>&nbsp;&nbsp; To help out visualising how the data piles work have a look at this scheme:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12781-0-31656100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12781" title="image032.png - Size: 6.87K, Downloads: 61"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-83766800-1355407134_thumb.png" id='ipb-attach-img-12781-0-31656100-1369216368' style='width:480;height:261' class='attach' width="480" height="261" alt="Attached Image: image032.png" /></a><br />
<strong>Figure 2: </strong>This is how the energy data is organized.</p><br />
<p> </p><br />
<p>Now the 'C' constant of this algorithm has nothing to do with the 'C' of the first algorithm, because we deal here with separated subbands the energy varies globally much more than with colorblind algorithms. Thus 'C' must be about 250. The results of this algorithm are convincing, it detects for example a symbal rhythm among other heavy noises in metal rock, and indeed the algorithm separates the signal into subbands, therefore the <strong>symbal rhythm cannot pass trough the algorithm without being recognized because it is isolated in the frequency domain from other sounds</strong>. However the complexity of the algorithm makes it useful only if you are dealing with very noisy sounds, in other cases, <em>Simple beat detection algorithm #3 </em>will do the job.</p><br />
<p><br />
<em><strong>b - Enhancements and beat decision factors.</strong></em></p><br />
<p><br />
There are ways to enhance a bit more our <em>Frequency selected sound energy algorithm #1</em>.</p><br />
<p><br />
First we will increase the <strong>number of subbands from 32 to 64</strong>. This will take obviously more computing time but it will also give us more precision in our beat detection. The second way to develop the accuracy of the algorithm uses the defaults of human ears. Human hearing system is not perfect; in fact its transfer function is more like a low pass filter. We hear more easily and more clearly low pitched noises than high pitch noises. This is why it is preferable to make a logarithmic repartition of the subbands. That is to say that subband 0 will contain only say 2 frequencies whereas the last subband, will contain say 20. <strong>More precisely the width 'wi' of the 'n' subbands indexed 'i' can be obtained using this argument:</strong></p><br />
<br /><ul class="bbc"><li>Linear increase of the width of the subband with its index:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12782-0-31675100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12782" title="formula10.png - Size: 626bytes, Downloads: 59"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-12031500-1355407221.png" id='ipb-attach-img-12782-0-31675100-1369216368' style='width:123;height:25' class='attach' width="123" height="25" alt="Attached Image: formula10.png" /></a><strong>(R10)</strong></li><li>We can choose for example the width of the first subband:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12783-0-31693400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12783" title="formula11.png - Size: 525bytes, Downloads: 56"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-89251300-1355407237.png" id='ipb-attach-img-12783-0-31693400-1369216368' style='width:97;height:25' class='attach' width="97" height="25" alt="Attached Image: formula11.png" /></a><strong>(R11)</strong></li><li>The sum of all the widths must not exceed 1024 ((B)'s size):<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12784-0-31711600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12784" title="formula12.png - Size: 2.15K, Downloads: 69"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-78864100-1355407266_thumb.png" id='ipb-attach-img-12784-0-31711600-1369216368' style='width:480;height:58' class='attach' width="480" height="58" alt="Attached Image: formula12.png" /></a><strong>(R12)</strong></li></ul><br />
<p>&nbsp;&nbsp; Once you have equations <strong>(R11)</strong> and <strong>(R12)</strong> it is fairly easy to extract 'a' and 'b', and thus to find the law of the 'wi'. This calculus of 'a' and 'b' must be made manually and 'a' and 'b' defined as constants in the source; indeed they do not vary during the song.</p><br />
<p><br />
So in fact in <em>Frequency selected sound energy algorithm #1</em>, all we have to modify is the number of subbands we will take equal to 64 and the <strong>(R7) </strong>relation. This relation becomes:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12785-0-31732100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12785" title="forumla7-2.png - Size: 2.43K, Downloads: 60"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-26648500-1355407326.png" id='ipb-attach-img-12785-0-31732100-1369216368' style='width:312;height:137' class='attach' width="312" height="137" alt="Attached Image: forumla7-2.png" /></a><br />
<strong>(R7)'</strong></p><br />
<p> </p><br />
<p>It may seem rather complicated but in fact it is not. Replacing this relation <strong>(R7)</strong> with <strong>(R7)'</strong> we have created <em>Frequency selected sound energy algorithm #2</em>. If you have musics with very tight and rapid beats, you may want to compute the stuff more frequently than every 1024 samples, but this is only for special cases, normally the beat should not be shorter than 1/40 of second.</p><br />
<p><br />
Using the advantages of Frequency selected beat detection you can also enhance the beat decision factor. Up to now it was based on a simple comparison between the instant energy of the subband and the average energy of the subband. This algorithm enables you to decide beats differently. You may want for examples to cut beats which correspond to high pitch sounds if you run techno music or you may want to keep only [50-4000Hz] beats if you are working with speech signal. This algorithm has the advantage of being perfectly adaptable to any kind or category of signal which was not the case of <em>Simple beat detection algorithm #3</em>. Notice that the correspondants between index 'i' of the FFT transform and real frequency is given by formula:</p><br />
<br /><ul class="bbc"><li>If 'i' &lt; 'N/2' then:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12786-0-31751500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12786" title="formula13.png - Size: 743bytes, Downloads: 56"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-24621500-1355407430.png" id='ipb-attach-img-12786-0-31751500-1369216368' style='width:96;height:53' class='attach' width="96" height="53" alt="Attached Image: formula13.png" /></a><strong>(R13)</strong></li><li>Else 'i' >= 'N/2' then:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12787-0-31770400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12787" title="formula14.png - Size: 930bytes, Downloads: 58"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-77182700-1355407450.png" id='ipb-attach-img-12787-0-31770400-1369216368' style='width:153;height:53' class='attach' width="153" height="53" alt="Attached Image: formula14.png" /></a><strong>(R14)</strong></li></ul><br />
<p>&nbsp;&nbsp; So 'i' is the index of the value in the FFT output buffer, N is the size of the FFT transform (here 1024), fe is the sample frequency (here 44100). Thus index 256 corresponds to 10025 Hz. This formula may be useful if you want to create your own subbands and you want to know what the correspondants <strong>between indexes and real frequency </strong>are.</p><br />
<p><br />
Another way of filtering the beats, or selecting them, is choosing only those which are marked and precise enough. As we have seen before, <strong>to detect the accuracy of beats we must compute the variance of the energy histories for each subband</strong>. If this variance is high it means that we have great differences of energy and thus that the beat are very intense. Thus all we have to do is compute this variance for each subband and add a test in the beat detection decision. To the "Es[i&#93; > (C*&lt;Ei>)" condition we will add "and V((Ei))>V0". V0 will be the variance limit, with experience 150 is a reasonable value. Now the V((Ei)) value is easy to compute, just follow the following equality if you don't see how:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12788-0-31789000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12788" title="formula15.png - Size: 1.7K, Downloads: 70"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-11052500-1355407515.png" id='ipb-attach-img-12788-0-31789000-1369216368' style='width:323;height:60' class='attach' width="323" height="60" alt="Attached Image: formula15.png" /></a><br />
<strong>(R15)</strong></p><br />
<p> </p><br />
<p>The last (finally) way to enhance your beat detection, is to make the source signal pass through a <strong>derivation filter</strong>. Indeed differentiating the signal makes big variations of amplitude more marked and thus makes energy variations more marked and recognisable later in the algorithm. I haven't tried this optimisation but according to some sources this is quite useful. If you try it please give me your opinion on it!</p><br />
<p><br />
Concerning the results of the <em>Frequency selected sound energy algorithm #2 </em>I must admit they are way more satisfying than the <em>Simple sound energy algorithm #3</em>. In a song the algorithm catches the bass beats as well as the tight cymbals hits. I insist on the fact that you may also select the beats in very different ways, which becomes quite useful if you know you are going to run techno music with low pitch beats for example. You may also select the beats differently according to there accuracy with the variance criteria. There are many other ways to decide beats; it is up to you to explore them and find the one which fits the most your needs.</p><br />
<p><br />
I used <em>Frequency selected sound energy algorithm #2 </em>algorithm in a demo program of which you can see some screenshots just below. One can see quite clearly that there is a beat in low frequencies (probably a bass or drum hit) and also a high pitch beat (probably a cymbal or such):</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12789-0-31807800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12789" title="image052.png - Size: 11.52K, Downloads: 71"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-44231400-1355407635_thumb.png" id='ipb-attach-img-12789-0-31807800-1369216368' style='width:480;height:361' class='attach' width="480" height="361" alt="Attached Image: image052.png" /></a><br />
<strong>Figure 3: </strong>The histogram represents the instant energy of the 128 subbands.</p><br />
<p style="text-align: center;"><br />
<a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12790-0-31828400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12790" title="image054.png - Size: 11.01K, Downloads: 77"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-53226800-1355407658_thumb.png" id='ipb-attach-img-12790-0-31828400-1369216368' style='width:480;height:360' class='attach' width="480" height="360" alt="Attached Image: image054.png" /></a><br />
<strong>Figure 4: </strong>On this screenshot you can see the 128 subbands E/&lt;E> ratios, and the bandwidth of the subbands. When the algorithm detects a beat in a subband, it overwrites the ratio in red.</p><br />
<p> </p><br />
<p>The reason why I called this part of the document, 'Statistical streaming beat detection', is that the energy can be considered as a random variable, of which we have been calculating values over time. Thus we could interpret those values as a sampling for the statistical analysis of a random variable. But one can push this approach further. When we have separated the energies histories into 128 subbands we created in fact 128 random energy variables. We can then apply some of the general statistical methods of analysis. For example, the principal components analysis method will enable you to determine if some of the subbands are directly linked or independent. This would help us to regroup some subbands which are directly linked and thus make the beat decision more efficient. However, this method is basically just far too computing expensive and maybe just too hard to implement comparing to the results we want. If you are looking for a really good challenge in beat detection you could push in this direction.</p><br />
<p><br />
<span style="font-size:18px;"><strong>II – Filtering rhythm detection</strong></span></p><br />
<p> </p><br />
<p><span style="font-size:14px;"><strong>1 – Derivation and Comb filters</strong></span></p><br />
<p> </p><br />
<p><em><strong>a - Intercorrelation and train of impulses</strong></em></p><br />
<p><br />
While in the first part of this document we had seen beat detection as a statistical sound energy problem, we will approach it here as a <strong>signal processing issue</strong>. I haven't tried myself this algorithm but I greatly inspired myself of some work which was done and tested with this algorithm (see the sources section), so it really works but I won't detail so much its implementation as I did in the first part. The basic idea is the following. <strong>If we have two signals x(t) and y(t)</strong>, we can evaluate a function which will give us an idea of how <strong>much those two signals are similar</strong>. This function called 'inter correlation function' is the following:</p><br />
<p style="text-align: center;"><br />
<a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12791-0-31847900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12791" title="formula16.png - Size: 1.89K, Downloads: 73"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-93477800-1355407745.png" id='ipb-attach-img-12791-0-31847900-1369216368' style='width:328;height:59' class='attach' width="328" height="59" alt="Attached Image: formula16.png" /></a><br />
<strong>(R16)</strong></p><br />
<p> </p><br />
<p>For our purposes we will always take alpha=1. This function quantifies the energy that can be exchanged between the signal x(t) and the signal y(t – b), it gives an evaluation of how much those two functions look like each other. The role of the 'b' is to eliminate the time origin problem; two signals should be compared without regarding their possible time axis translation. As you may have noticed, we are creating this algorithm for a computer to execute; basically we have to re-write this formula in discrete mode, it becomes:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12792-0-31867400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12792" title="formula17.png - Size: 1.28K, Downloads: 62"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-27795800-1355407788.png" id='ipb-attach-img-12792-0-31867400-1369216368' style='width:267;height:57' class='attach' width="267" height="57" alt="Attached Image: formula17.png" /></a><br />
<strong>(R17)</strong></p><br />
<p> </p><br />
<p>Now the point is we can valuate the similarity of our song and of a train of impulses using this function. <strong>The train of impulses being at a known frequency </strong>(the beats per minute we want to test) is what we call a comb filter. The energy of the Y function gives us an evaluation of the similarity between our song and this train of impulses, thus it quantifies how much the rhythm of the train of impulses is present in the song. If we compute the energy of the ? function for different train of impulses, we will be able to see for which of them the energy is the biggest, and thus we will know what is the principal Betas Per Minute rate. This is called <strong>combfilter processing</strong>. We will note 'Ey' this energy, where x[k] is our song signal and y[k] our train of impulses:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12793-0-31900700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12793" title="formula18.png - Size: 1K, Downloads: 55"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-52949000-1355407832.png" id='ipb-attach-img-12793-0-31900700-1369216368' style='width:160;height:72' class='attach' width="160" height="72" alt="Attached Image: formula18.png" /></a><br />
<strong>(R18)</strong></p><br />
<p> </p><br />
<p>By the way, here is what a train of impulses looks like:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12794-0-31926700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12794" title="image067.png - Size: 4.38K, Downloads: 69"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-01485400-1355407875_thumb.png" id='ipb-attach-img-12794-0-31926700-1369216368' style='width:480;height:261' class='attach' width="480" height="261" alt="Attached Image: image067.png" /></a><br />
<strong>Figure 5: </strong>This is the train of impulses function, it is caracterised by its period Ti.</p><br />
<p> </p><br />
<p>So the period Ti of the impulses must correspond to the beats per minutes we want to test on our song. The formula that links a beat per minute value with the Ti in discrete time is the following:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12795-0-31947100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12795" title="formula19.png - Size: 1.05K, Downloads: 61"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-97156500-1355407916.png" id='ipb-attach-img-12795-0-31947100-1369216368' style='width:153;height:53' class='attach' width="153" height="53" alt="Attached Image: formula19.png" /></a><br />
<strong>(R19)</strong></p><br />
<p> </p><br />
<p>fs is the sample frequency, if you are using good quality wave files, it is usually of 44100. BPM is the beats per minute rate. Finally, Ti is the number of indexes between each impulse.</p><br />
<p><br />
&nbsp;&nbsp; Now because it is quite computing expensive to compute the <strong>(R17)</strong> formula, <strong>we pass to the frequency domain with a FFT and compute the product of the X[v] and Y[v] </strong>(FFT's of x[k] and y[k]). Then we compute the energy of the ? function directly in the frequency domain, thus Ey is given with by the following formula:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12796-0-31967200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12796" title="formula17-2.png - Size: 1.19K, Downloads: 55"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-73734000-1355407968.png" id='ipb-attach-img-12796-0-31967200-1369216368' style='width:213;height:71' class='attach' width="213" height="71" alt="Attached Image: formula17-2.png" /></a><br />
<strong>(R17)'</strong></p><br />
<p> </p><br />
<p><em><strong>b - The algorithm</strong></em></p><br />
<p>Note that this algorithm is much too computing expensive to be ran on a streaming source, or on a song in a whole. It is executed on a part of the song, like 5 seconds taken somewhere in the middle. Thus we assume that the tempo of the song is overall constant and that the middle of the song is tempo-representative of the rest of the song. So finally here are the steps of our algorithm:</p><br />
<p><br />
<em>Derivation and Combfilter algorithm #1:</em></p><br />
<br /><ul class="bbc"><li>Choose roughly 5 seconds of data in the middle of the song and copy it to the 'a[k]' and 'b[k]' lists. The dimension of those lists is noted N. As usual 'a[k]' is the array for the left values, and 'b[k]' is the array for the right values.</li><li>Compute the FFT of the complex signal made with a[k] for the real part of the complex signal and b[k] the imaginary part of the complex signal as seen in Frequency selected sound energy algorithm #1. Store the real part of the result in ta[k] and the imaginary in tb[k].</li><li>For all the beats per minute you want to test, for example from 60 BPM to 180 BPM per step of 10, we will note BPMc the current BPM tested:<br /><ul class="bbc"><li>Compute the Ti value corresponding to BPMc using formula <strong>(R19)</strong>.</li><li>Compute the train of impulses signal and store it in (l) and (j). (l) and (j) are purely identical, we take two lists of values to have a stereo signal so that we don't have dimension issues further on. Here is how the train of impulses is generated:<br /><br /><span style="font-family:courier new,courier,monospace;">for (k = 0; k &lt; N; k++)<br />{<br />&nbsp;&nbsp;if ((k % Ti) == 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;l[k] = j[k] = AmpMax;<br />&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;&nbsp;l[k] = j[k] = 0;<br />}</span></li><li>Compute the FFT of the complex signal made of (l) and (j). Store the result in tl[k] and tj[k].</li><li>Finally compute the energy of the correlation between the train of impulses and the 5 seconds signal using <strong>(R17)'</strong> which becomes:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12797-0-31987200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12797" title="formula20.png - Size: 2.04K, Downloads: 60"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-07491700-1355408086.png" id='ipb-attach-img-12797-0-31987200-1369216368' style='width:465;height:67' class='attach' width="465" height="67" alt="Attached Image: formula20.png" /></a><strong>(R20)</strong></li><li>Save E(BPMc) in a list.</li></ul><br />
</li><br />
<li>The rhythm of the song is given by the BPMmax, where the max of all the E(BPMc) is taken. We have the beat rate of the song!</li><br />
</ul><br />
<p>&nbsp;&nbsp; The AmpMax constant which appears in the train of impulse generation, is given by the sample size of the source file. Usually the sample size is 16 bits, for a good quality .wav. If you are working in non-signed mode, the AmpMax value will be of 65535, and more often if you work with 16 bits signed samples the AmpMax will be 32767.</p><br />
<p><br />
One of the first ameliorations that could be given to <em>Derivation and Combfilter algorithm #1 </em>is indeed adding a <strong>derivation filter </strong>before the combfilter processing. <strong>To make beats more detectable, we differentiate the signal</strong>. This accentuates when the sound amplitude changes. So instead of dealing with a[k] and b[k] directly we first transform them using the formula below. This modification added before the second step of <em>Derivation and Combfilter algorithm #1 </em>constitutes <em>Derivation and Combfilter algorithm #2.</em></p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12798-0-32007100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12798" title="formula21.png - Size: 2.57K, Downloads: 57"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-01010700-1355408166.png" id='ipb-attach-img-12798-0-32007100-1369216368' style='width:308;height:155' class='attach' width="308" height="155" alt="Attached Image: formula21.png" /></a><br />
<strong>(R21)</strong></p><br />
<p> </p><br />
<p>As I said before, I haven't tested this algorithm myself; I can't compare its results with the algorithms of the first part. However, throughout the researches I made this seems to be the algorithm universally accepted as being the most accurate. It does have disadvantages: Great computing power consumption, can only be done on a small part of a song, assumes the rhythm is constant throughout the song, no possible streaming input (for example from a microphone), the signal needs to be known in advance. However it returns a deeper analysis than the first part algorithms, indeed for each BPM rate you have a value of its importance in the song.</p><br />
<p><br />
<strong>2 – Frequency selected processing</strong></p><br />
<p> </p><br />
<p><em><strong>a - Curing colorblindness</strong></em></p><br />
<p><br />
As in the first part of the tutorial, we have the same problem our last algorithm doesn't make the difference between cymbals beat or a drum beat, so the beat detection becomes a bit dodgy on very noisy music like hard rock. To heal our algorithm we will proceed as we had done in <em>Frequency selected sound energy algorithm #1 </em><strong>we will separate our source signal into several subbands</strong>. Only this time we have much more computing to do on each subband so we will be much more limited in their number. I think that 16 is a good value. <strong>We will use a logarithmic repartition of these subbands</strong> as we had done before.</p><br />
<p><br />
Let's modify the <em>Derivation and Combfilter algorithm #2</em>. The values particular to a subband will be characterized with a little 's' at the end of the name of the variable. So we will separate ta[k] and tb[k] into 16 subbands. Each subbands values array will be called tas[k] and tbs[k] ('s' varies from 1 to 16).</p><br />
<p><br />
<em>Frequency selected processing combfilters algorithm #1:</em></p><br />
<br /><ul class="bbc"><li>Choose roughly 5 seconds of data in the middle of the song and copy it to the 'a[k]' and 'b[k]' lists. The dimension of those lists is noted N. As usual 'a[k]' is the array for the left values, and 'b[k]' is the array for the right values.</li><li>Differentiate the a[k] and b[k] signals using <strong>(R21)</strong>.</li><li>Compute the FFT of the complex signal made with a[k] for the real part of the complex signal and b[k] the imaginary part of the complex signal as seen in Frequency selected sound energy algorithm #1. Store the real part of the result in ta[k] and the imaginary in tb[k].</li><li>Generate the 16 subband array values tas[k] and tbs[k] by cutting ta[k] and tb[k] with a logarithmic rule.</li><li>For all the subbands tas[k] and tbs[k] (s goes from 1 to 16). Ws is the length of the 's' subband.</li><li>For all the beats per minute you want to test, for example from 60 BPM to 180 BPM per step of 10, we will note BPMc the current BPM tested :<br /><ul class="bbc"><li>Compute the Ti value corresponding to BPMc using formula <strong>(R19)</strong>.</li><li>Compute the train of impulses signal and store it in (l) and (j). (l) and (j) are purely identical, we take two lists of values to have a stereo signal so that we don't have dimension issues further on. Here is how the train of impulses is generated:<br /><br /><span style="font-family:courier new,courier,monospace;">for (k = 0; k &lt; ws; k++)<br />{<br />&nbsp;&nbsp;if ((k % Ti) == 0)&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;l[k] = k[k] = AmpMax;<br />&nbsp;&nbsp;else&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;l[k] = j[k] = 0;<br />}</span></li><li>Compute the FFT of the complex signal made of (l) and (j). Store the result in tl[k] and tj[k].<br />Finally compute the energy of the correlation between the train of impulses and the 5 seconds signal using <strong>(R17)'</strong> which becomes:<br /><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12799-0-32028900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12799" title="formula22.png - Size: 2.16K, Downloads: 55"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-57939200-1355408321_thumb.png" id='ipb-attach-img-12799-0-32028900-1369216368' style='width:480;height:61' class='attach' width="480" height="61" alt="Attached Image: formula22.png" /></a><strong>(R22)</strong></li><li>Save E(BPMc,s) in a list.</li></ul><br />
</li><br />
<li>The rhythm of the subband is given by the BPMmaxs, where the max of all the E(BPMc,s) is taken (s is fixed). We will call this max EBPMmaxs. We have the beat rate of the subband we store it in a list.</li><br />
<li>We do this for all the subbands, we have a list of BPMmaxs for all subbands, we can than decide which one to consider.</li><br />
</ul><br />
<p>&nbsp;&nbsp; As in <em>Frequency selected sound energy algorithm #2 </em>we will then be able to decide the rhythm according to frequency bandwidth criteria. Or, if you want to take all the subbands into account you can compute the final BPM of the song, by calculating the barycentre of all the BPMmaxs affected with their max of E(BPMc,s). Like this:</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12800-0-32049100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12800" title="formula23.png - Size: 2.91K, Downloads: 54"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-00404800-1355408354_thumb.png" id='ipb-attach-img-12800-0-32049100-1369216368' style='width:480;height:75' class='attach' width="480" height="75" alt="Attached Image: formula23.png" /></a><br />
<strong>(R23)</strong></p><br />
<p> </p><br />
<p>I must admit I haven't concretely tested this algorithm. Others have done this already and here an overview of the results for Derivation and Combfilter algorithm #2 (source: <a href='http://www.owlnet.rice.edu/~elec301/Projects01/beat_sync/beatalgo.html' class='bbc_url' title='External link' rel='nofollow external'>http://www.owlnet.ri...c/beatalgo.html</a>).</p><br />
<p> </p><br />
<p style="text-align: center;"><a class='resized_img' rel='lightbox[09517546bca04de48ff1656742533b7f]' id='ipb-attach-url-12801-0-32069400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=12801" title="image090.png - Size: 6.79K, Downloads: 59"><img src="http://uploads.gamedev.net/monthly_12_2012/ccs-8549-0-72942700-1355408405_thumb.png" id='ipb-attach-img-12801-0-32069400-1369216368' style='width:480;height:375' class='attach' width="480" height="375" alt="Attached Image: image090.png" /></a><br />
<strong>Figure 6: </strong>This is plot of the EBPMc values function of BPMc. The algorithm will take the max of the EBPMc value to find the final BPM of the song. Here we see this max is reached for BPMc=75. The final BPM is 75!</p><br />
<p> </p><br />
<p><span style="font-size:18px;"><strong>Conclusion</strong></span></p><br />
<p> </p><br />
<p>Finding algorithms for beat detection is very frustrating. It seems so obvious to us, humans, to hear those beats and somehow so hard to formalise it. We managed to approximate more or less accurately and more or less efficiently this beat detection. But the best algorithms are always the ones you make yourself, the ones which are adapted to your problem. The more the situation is precise and defined the easier it is! This guide should be used as a source of ideas. Even if beat detection is far from being a crucial topic in the programming scene, it has the advantage of using lots of signal processing and mathematical concepts. More than an end in itself, for me, beat detection was a way to train to signal processing. I hope you will find some of this stuff useful.</p><br />
<p><br />
<strong>Sources and Links</strong></p><br />
<br /><ul class="bbc"><li><a href='http://www.owlnet.rice.edu/~elec301/Projects01/beat_sync/beatalgo.html' class='bbc_url' title='External link' rel='nofollow external'>http://www.owlnet.ri...c/beatalgo.html</a>: This site greatly inspired me for the second part of the tutorial, very well explained.</li><li><a href='http://www.cs.princeton.edu/~gessl/papers/amta2001.pdf' class='bbc_url' title='External link' rel='nofollow external'>http://www.cs.prince...rs/amta2001.pdf</a>: Audio analysis using the discrete wavelet transform.</li><li><a href='http://web.media.mit.edu/~eds/beat.pdf' class='bbc_url' title='External link' rel='nofollow external'>Tempo and beat analysis of acoustic musical signals</a> by Eric D. Scheirer</li><li><a href='http://www.sunpoint.net/~oparviai/pacemaker/' class='bbc_url' title='External link' rel='nofollow external'>Pacemaker</a> by Olli Parviainen</li></ul><br />]]></description>
		<pubDate>Sat, 07 Jun 2003 20:39:13 +0000</pubDate>
		<guid isPermaLink="false">b8c78ee23d4f42c6c58cede44fedb0cd</guid>
	</item>
	<item>
		<title>Vectors and Matrices: A Primer</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/vectors-and-matrices-a-primer-r1832</link>
		<description><![CDATA[<p class="message note">

<strong>Note:</strong>&nbsp;&nbsp;<br />This article has since been <a href='http://www.gamedev.net/page/resources/_/technical/math-and-physics/vectors-and-matrices-a-primer-r3064' class='bbc_url' title=''>revised and updated</a> from its original published version you see here.<br />
				
</p><br /><br /><span style='font-size: 18px;'><strong class='bbc'>Preface</strong></span><br /><br />Hey there! This tutorial is for those who are new to 3D programming, and need to brush up on that math. I will teach you two primary things here, Vectors and Matrices (with determinants). I'm not going to go into everything, so this isn't designed as a standalone reference. A lot of mathematics books can probably discuss this much better, but anyway, without further ado, lets get on with it shall we?<br /><br /> <br /><span style='font-size: 18px;'><strong class='bbc'>Vectors</strong></span><br /> <br /><span style='font-size: 12px;'><strong class='bbc'>Vector basics – What is a vector?</strong></span><br /><br />Vectors are the backbone of games. They are the foundation of graphics, physics modelling, and a number of other things. Vectors can be of any dimension, but are most commonly seen in 2 or 3 dimensions. I will focus on 2D and 3D vectors in this text. Vectors are derived from hyper-numbers, a sub-set of hyper-complex numbers. But enough of that, you just want to know how to use them right? Good.<br /><br /> The notation for a vector is that of a bold lower-case letter, like <strong class='bbc'>i</strong>, or an italic letter with an underscore, like <em class='bbc'><span class='bbc_underline'>i</span></em>. I'll use the former in this text. You can write vectors in a number of ways, and I will teach you 2 of them: <em class='bbc'>vector equations</em> and <em class='bbc'>column vectors</em>. Vectors can also be written using the two end points with an arrow above them. So, if you have a vector between the two points A and B, you can write that as <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4331-0-36883100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4331" title="image002.gif - Size: 240bytes, Downloads: 266"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-74933000-1311406833_thumb.gif" id='ipb-attach-img-4331-0-36883100-1369216368' style='width:59;height:25' class='attach' width="59" height="25" alt="Attached Image: image002.gif" /></a>.<br /><br /> A vector equation takes the form <strong class='bbc'>a=</strong> <em class='bbc'>x</em><strong class='bbc'>i</strong> + <em class='bbc'>y</em><strong class='bbc'>j</strong> + <em class='bbc'>z</em><strong class='bbc'>k</strong><br /><br /> <strong class='bbc'>i</strong>, <strong class='bbc'>j</strong> and <strong class='bbc'>k</strong> are unit vectors in the 3 standard Cartesian directions. <strong class='bbc'>i</strong> is a unit vector aligned with the x axis, <strong class='bbc'>j</strong> is a unit vector aligned with the y axis, and <strong class='bbc'>k</strong> is a unit vector aligned with the z axis. Unit vectors are discussed later.<br /><br /> The coefficients of the <strong class='bbc'>i</strong>, <strong class='bbc'>j</strong> and <strong class='bbc'>k</strong> parts of the equation are the vector's <em class='bbc'>components</em>. These are how long each vector is in each of the 3 axes. This may be easier to understand with the aid of a diagram.<br /><br /><p class='bbc_center'> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4332-0-36903000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4332" title="image003.gif - Size: 1.93K, Downloads: 277"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-74324700-1311406850_thumb.gif" id='ipb-attach-img-4332-0-36903000-1369216368' style='width:203;height:200' class='attach' width="203" height="200" alt="Attached Image: image003.gif" /></a><br /></p> This diagram shows a vector from the origin to the point ( 3, 2, 5 ) in 3D space. The <em class='bbc'>components</em> of this vector are the <strong class='bbc'>i</strong>, <strong class='bbc'>j</strong> and <strong class='bbc'>k</strong> coefficients ( 2, 3 and 5 ). So, in the above example, the vector equation would be:<br /><br /> <strong class='bbc'>a</strong> = 2<strong class='bbc'>i</strong> + 3<strong class='bbc'>j</strong> + 5<strong class='bbc'>k</strong><br /><br /> This can also be related to the deltas of a line going through 2 points.<br /><br /> The second way of writing vectors is as <em class='bbc'>column vectors</em>. These are written in the following form<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4333-0-36921800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4333" title="image005.gif - Size: 397bytes, Downloads: 257"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-13322100-1311406871_thumb.gif" id='ipb-attach-img-4333-0-36921800-1369216368' style='width:53;height:75' class='attach' width="53" height="75" alt="Attached Image: image005.gif" /></a><br /><br /> where <em class='bbc'>x</em>, <em class='bbc'>y</em> and <em class='bbc'>z</em> are the components of that vector in the respective directions. These are exactly the same as the components of the vector equation. So in column vector form, the above example could be written as:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4334-0-36942000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4334" title="image007.gif - Size: 402bytes, Downloads: 231"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-41119900-1311406881_thumb.gif" id='ipb-attach-img-4334-0-36942000-1369216368' style='width:52;height:75' class='attach' width="52" height="75" alt="Attached Image: image007.gif" /></a><br /><br /> There are various advantages to both of the above forms, but I will continue to use the column vector form, as it is easier when it comes to matrices. <em class='bbc'>Position vectors</em> are those that originate from the origin. These can define points in space, relative to the origin.<br /><br /> <span style='font-size: 12px;'><strong class='bbc'>Vector Math</strong></span><br /><br />You can manipulate vectors in various ways, including scalar multiplication, addition, scalar product and vector product. The latter two are extremely useful in 3D applications.<br /><br /> There are a few things you should know before moving to the methods above. The first is finding the <em class='bbc'>modulus</em> (also called the <em class='bbc'>magnitude</em>) of a vector. This is basically its length. This can be easily found using Pythagorean theorem, using the vector components. The modulus of <strong class='bbc'>a</strong> is written |<strong class='bbc'>a</strong>|.<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4335-0-36960600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4335" title="image009.gif - Size: 368bytes, Downloads: 231"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-18438000-1311406906_thumb.gif" id='ipb-attach-img-4335-0-36960600-1369216368' style='width:127;height:31' class='attach' width="127" height="31" alt="Attached Image: image009.gif" /></a> in 3D and <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4336-0-36978600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4336" title="image011.gif - Size: 330bytes, Downloads: 236"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-71439500-1311406918_thumb.gif" id='ipb-attach-img-4336-0-36978600-1369216368' style='width:95;height:31' class='attach' width="95" height="31" alt="Attached Image: image011.gif" /></a> in 2D, where <em class='bbc'>x</em>, <em class='bbc'>y</em> and <em class='bbc'>z</em> are the components of the vector in the 3 axes of movement. <em class='bbc'>Unit vectors</em> are vectors with a magnitude of 1, so |<strong class='bbc'>a</strong>| = 1.<br /><br /> <strong class='bbc'>Addition</strong><br /><br /> Vector addition is pretty easy. All you do is add the respective components together. So for instance, take the vectors:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4337-0-36996700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4337" title="image013.gif - Size: 404bytes, Downloads: 236"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-39555400-1311406937_thumb.gif" id='ipb-attach-img-4337-0-36996700-1369216368' style='width:52;height:75' class='attach' width="52" height="75" alt="Attached Image: image013.gif" /></a>&nbsp;&nbsp;&nbsp;&nbsp;<a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4338-0-37014800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4338" title="image015.gif - Size: 441bytes, Downloads: 231"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-52337300-1311406947_thumb.gif" id='ipb-attach-img-4338-0-37014800-1369216368' style='width:65;height:75' class='attach' width="65" height="75" alt="Attached Image: image015.gif" /></a><br /><br /> The addition of these vectors would be:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4339-0-37034500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4339" title="image017.gif - Size: 951bytes, Downloads: 235"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-28558500-1311406958_thumb.gif" id='ipb-attach-img-4339-0-37034500-1369216368' style='width:200;height:75' class='attach' width="200" height="75" alt="Attached Image: image017.gif" /></a><br /><br /> Get it? This can also be represented very easily in a diagram, but I will only consider this in 2D, because it's easier to draw.<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4340-0-37052800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4340" title="image019.gif - Size: 338bytes, Downloads: 244"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-12549800-1311406970_thumb.gif" id='ipb-attach-img-4340-0-37052800-1369216368' style='width:52;height:48' class='attach' width="52" height="48" alt="Attached Image: image019.gif" /></a>&nbsp;&nbsp;&nbsp;&nbsp;<a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4341-0-37071400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4341" title="image021.gif - Size: 346bytes, Downloads: 233"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-52518500-1311406982_thumb.gif" id='ipb-attach-img-4341-0-37071400-1369216368' style='width:65;height:48' class='attach' width="65" height="48" alt="Attached Image: image021.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4342-0-37089600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4342" title="image022.gif - Size: 1.25K, Downloads: 250"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-25839100-1311406994_thumb.gif" id='ipb-attach-img-4342-0-37089600-1369216368' style='width:104;height:104' class='attach' width="104" height="104" alt="Attached Image: image022.gif" /></a><br /><br /> This works in the same way as moving the second vector so that its beginning is at the first vector's end, and taking the vector from the beginning of the first vector to the end of the second one. So, in a diagram, using the above example, this would be:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4343-0-37108400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4343" title="image023.gif - Size: 1.21K, Downloads: 234"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-06202600-1311407005_thumb.gif" id='ipb-attach-img-4343-0-37108400-1369216368' style='width:76;height:95' class='attach' width="76" height="95" alt="Attached Image: image023.gif" /></a><br /><br /> This means that you can add multiple vectors together to get the <em class='bbc'>resultant</em> vector. This is used extensively in mechanics for finding resultant forces.<br /><br /> <strong class='bbc'>Subtracting</strong><br /><br /> Subtracting is very similar to adding, and is also quite helpful. All you do is subtract the components in one vector from the components in the other. The geometric representation however is very different.<br /><br /> Let <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4344-0-37128800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4344" title="image025.gif - Size: 331bytes, Downloads: 232"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-83651900-1311407019_thumb.gif" id='ipb-attach-img-4344-0-37128800-1369216368' style='width:52;height:48' class='attach' width="52" height="48" alt="Attached Image: image025.gif" /></a> and <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4345-0-37147500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4345" title="image027.gif - Size: 341bytes, Downloads: 240"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-31746600-1311407031_thumb.gif" id='ipb-attach-img-4345-0-37147500-1369216368' style='width:53;height:48' class='attach' width="53" height="48" alt="Attached Image: image027.gif" /></a><br /><br /> Then <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4346-0-37166300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4346" title="image029.gif - Size: 682bytes, Downloads: 246"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-13826600-1311407045_thumb.gif" id='ipb-attach-img-4346-0-37166300-1369216368' style='width:189;height:48' class='attach' width="189" height="48" alt="Attached Image: image029.gif" /></a><br /><br /> The visual representation of this is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4347-0-37184800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4347" title="image030.gif - Size: 1.31K, Downloads: 261"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-75087900-1311407058_thumb.gif" id='ipb-attach-img-4347-0-37184800-1369216368' style='width:142;height:104' class='attach' width="142" height="104" alt="Attached Image: image030.gif" /></a><br /><br /> Here, <strong class='bbc'>a</strong> and <strong class='bbc'>b</strong> are set to be from the same origin. The vector <strong class='bbc'>c</strong> is the vector from the end of the second vector to the end of the first, which in this case is from the end of <strong class='bbc'>b</strong> to the end of <strong class='bbc'>a</strong>. It may be easier to think of this as a vector addition.<br /><br /> Where instead of having:<br /><br /> <strong class='bbc'>c</strong> = <strong class='bbc'>a</strong> – <strong class='bbc'>b</strong><br /><br /> we have<br /><br /> <strong class='bbc'>c</strong> = -<strong class='bbc'>b</strong> + <strong class='bbc'>a</strong><br /><br /> which, according to what was said about the addition of vectors would produce:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4348-0-37203800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4348" title="image031.gif - Size: 1.32K, Downloads: 243"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-65773600-1311407075_thumb.gif" id='ipb-attach-img-4348-0-37203800-1369216368' style='width:141;height:104' class='attach' width="141" height="104" alt="Attached Image: image031.gif" /></a><br /><br /> You can see that putting <strong class='bbc'>a</strong> on the end of –<strong class='bbc'>b</strong> has the same result.<br /><br /> <strong class='bbc'>Scalar multiplication</strong><br /><br /> Scalar multiplication is easy to come to grips with. All you do is multiply each component by that scalar.<br /><br /> So, say you had the vector <strong class='bbc'>a</strong> and a scalar <em class='bbc'>k</em>, you would multiply each component by the scalar, getting this result:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4349-0-37224400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4349" title="image033.gif - Size: 397bytes, Downloads: 243"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-89365300-1311407094_thumb.gif" id='ipb-attach-img-4349-0-37224400-1369216368' style='width:53;height:75' class='attach' width="53" height="75" alt="Attached Image: image033.gif" /></a>&nbsp;&nbsp;&nbsp;&nbsp;<a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4350-0-37243400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4350" title="image035.gif - Size: 478bytes, Downloads: 247"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-84633600-1311407105_thumb.gif" id='ipb-attach-img-4350-0-37243400-1369216368' style='width:67;height:75' class='attach' width="67" height="75" alt="Attached Image: image035.gif" /></a><br /><br /> This has the effect of lengthening or shortening the vector by the amount <em class='bbc'>k</em>. For instance, take <em class='bbc'>k</em> = 2; this would make the vector <strong class='bbc'>a</strong> twice as long. Multiplying by a negative scalar reverses the direction of the vector. You can use scalar multiplication to find the unit vector of another vector. So, take the following example:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4351-0-37262300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4351" title="image037.gif - Size: 402bytes, Downloads: 228"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-32990100-1311407143_thumb.gif" id='ipb-attach-img-4351-0-37262300-1369216368' style='width:52;height:75' class='attach' width="52" height="75" alt="Attached Image: image037.gif" /></a><br /><br /> To find the unit vector of this, we would divide <strong class='bbc'>a</strong> by |<strong class='bbc'>a</strong>|. Calling the unit vector "<strong class='bbc'>b</strong>":<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4352-0-37281100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4352" title="image039.gif - Size: 725bytes, Downloads: 264"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-93077400-1311407155_thumb.gif" id='ipb-attach-img-4352-0-37281100-1369216368' style='width:250;height:21' class='attach' width="250" height="21" alt="Attached Image: image039.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4353-0-37299900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4353" title="image041.gif - Size: 1.16K, Downloads: 238"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-58857500-1311407165_thumb.gif" id='ipb-attach-img-4353-0-37299900-1369216368' style='width:168;height:133' class='attach' width="168" height="133" alt="Attached Image: image041.gif" /></a><br /><br /> That is the unit vector <strong class='bbc'>b</strong> in the direction of <strong class='bbc'>a</strong>. This just scales each of the components, so that the magnitude is equal to 1.<br /><br /> Scalar multiplication is also used in the vector equation discussed earlier. The constants <em class='bbc'>x</em>, <em class='bbc'>y</em> and <em class='bbc'>z</em> are the scalars that scale the <strong class='bbc'>i</strong>, <strong class='bbc'>j</strong> and <strong class='bbc'>k</strong> vectors, before adding them to find the resultant vector.<br /><br /> <strong class='bbc'>The Scalar Product (Dot Product)</strong><br /><br /> The <em class='bbc'>scalar product</em>, also known as the <em class='bbc'>dot product</em>, is very useful in 3D graphics applications. The scalar product is written <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4354-0-37319300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4354" title="image043.gif - Size: 198bytes, Downloads: 259"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-51442000-1311407185_thumb.gif" id='ipb-attach-img-4354-0-37319300-1369216368' style='width:31;height:19' class='attach' width="31" height="19" alt="Attached Image: image043.gif" /></a> and is read "<strong class='bbc'>a</strong> dot <strong class='bbc'>b</strong>".<br /><br /> The definition the scalar product is the following:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4355-0-37340000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4355" title="image045.gif - Size: 354bytes, Downloads: 245"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-52876200-1311407198_thumb.gif" id='ipb-attach-img-4355-0-37340000-1369216368' style='width:107;height:27' class='attach' width="107" height="27" alt="Attached Image: image045.gif" /></a><br /><br /> Where q is the angle between the 2 vectors <strong class='bbc'>a</strong> and <strong class='bbc'>b</strong>. This produces a scalar result, hence the name scalar product. From this you can see that the scalar product of 2 parallel unit vectors is 1, as |<strong class='bbc'>a</strong>||<strong class='bbc'>b</strong>| = 1, and cos(0) also is 1. You should also have seen that the scalar product of two perpendicular vectors is 0, as cos(90) = 0, which makes the rest of the expression 0. The geometric interpretation is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4356-0-37359100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4356" title="image046.gif - Size: 1.12K, Downloads: 238"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-98098700-1311407218_thumb.gif" id='ipb-attach-img-4356-0-37359100-1369216368' style='width:67;height:86' class='attach' width="67" height="86" alt="Attached Image: image046.gif" /></a><br /><br /> The scalar product can also be written in terms of Cartesian components., I will not go into how this is derived, but the final, simplified formula of <strong class='bbc'>a</strong>.<strong class='bbc'>b</strong> is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4357-0-37378600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4357" title="image048.gif - Size: 428bytes, Downloads: 238"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-11366200-1311407231_thumb.gif" id='ipb-attach-img-4357-0-37378600-1369216368' style='width:59;height:75' class='attach' width="59" height="75" alt="Attached Image: image048.gif" /></a>&nbsp;&nbsp;&nbsp;&nbsp;<a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4358-0-37397800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4358" title="image050.gif - Size: 441bytes, Downloads: 223"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-25055400-1311407243_thumb.gif" id='ipb-attach-img-4358-0-37397800-1369216368' style='width:61;height:75' class='attach' width="61" height="75" alt="Attached Image: image050.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4359-0-37417000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4359" title="image052.gif - Size: 365bytes, Downloads: 230"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-12617400-1311407255_thumb.gif" id='ipb-attach-img-4359-0-37417000-1369216368' style='width:161;height:23' class='attach' width="161" height="23" alt="Attached Image: image052.gif" /></a><br /><br /> We can now put these two equations equal to each other, yielding the equation:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4360-0-37438200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4360" title="image054.gif - Size: 475bytes, Downloads: 246"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-33111200-1311407287_thumb.gif" id='ipb-attach-img-4360-0-37438200-1369216368' style='width:197;height:27' class='attach' width="197" height="27" alt="Attached Image: image054.gif" /></a><br /><br /> With this, we can find angles between vectors. This is used extensively in the lighting part of the graphics pipeline, as it can see whether a polygon is facing towards or away from the light source. This is also used in deciding what side of planes points are on, which is also used extensively for culling.<br /><br /><strong class='bbc'>The Vector Product (Cross Product)</strong><br /> <br />The <em class='bbc'>vector product</em>, which is also commonly known as the <em class='bbc'>cross product</em> is also useful. The vector product basically finds a vector perpendicular to two other vectors. Great for finding normal vectors to surfaces.<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4361-0-37458000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4361" title="image055.gif - Size: 1.47K, Downloads: 236"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-74723000-1311407304_thumb.gif" id='ipb-attach-img-4361-0-37458000-1369216368' style='width:152;height:161' class='attach' width="152" height="161" alt="Attached Image: image055.gif" /></a><br /><br /> For those that are already familiar with determinants, the vector product is basically the expansion of the following determinant:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4362-0-37477800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4362" title="image057.gif - Size: 468bytes, Downloads: 238"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-41178500-1311407317_thumb.gif" id='ipb-attach-img-4362-0-37477800-1369216368' style='width:82;height:71' class='attach' width="82" height="71" alt="Attached Image: image057.gif" /></a><br /><br /> For those that aren't, the vector product in expanded form is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4363-0-37497100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4363" title="image059.gif - Size: 1.38K, Downloads: 227"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-86172900-1311407330_thumb.gif" id='ipb-attach-img-4363-0-37497100-1369216368' style='width:250;height:14' class='attach' width="250" height="14" alt="Attached Image: image059.gif" /></a><br /><br /> Read "<strong class='bbc'>a</strong> cross <strong class='bbc'>b</strong>".<br /><br /> Since the cross product finds the perpendicular vector, we can say that:<br /><br /> <strong class='bbc'>i</strong> x <strong class='bbc'>j</strong> = <strong class='bbc'>k</strong><br /><br /> <strong class='bbc'>j</strong> x <strong class='bbc'>k</strong> = <strong class='bbc'>i</strong><br /><br /> <strong class='bbc'>k</strong> x <strong class='bbc'>i</strong> = <strong class='bbc'>j</strong><br /><br /> Using scalar multiplication along with the vector product we can find the "normal" vector to a plane. A plane can be defined by two vectors, <strong class='bbc'>a</strong> and <strong class='bbc'>b</strong>. The normal vector is a vector that is perpendicular to a plane and is also a unit vector. Using the formulas discussed earlier, we have:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4364-0-37517000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4364" title="image061.gif - Size: 231bytes, Downloads: 248"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-54267700-1311407346_thumb.gif" id='ipb-attach-img-4364-0-37517000-1369216368' style='width:59;height:19' class='attach' width="59" height="19" alt="Attached Image: image061.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4365-0-37538300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4365" title="image063.gif - Size: 263bytes, Downloads: 242"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-47469800-1311407367_thumb.gif" id='ipb-attach-img-4365-0-37538300-1369216368' style='width:44;height:47' class='attach' width="44" height="47" alt="Attached Image: image063.gif" /></a><br /><br /> This first finds the vector perpendicular to the plane made by <strong class='bbc'>a</strong> and <strong class='bbc'>b</strong> then scales that vector so it has a magnitude of 1. Note however, that there are 2 possible normals to the plane defined by <strong class='bbc'>a</strong> and <strong class='bbc'>b</strong>. You will get different results by swapping <strong class='bbc'>a</strong> and <strong class='bbc'>b</strong> in the vector product. That is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4366-0-37558100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4366" title="image065.gif - Size: 263bytes, Downloads: 236"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-65487900-1311407379_thumb.gif" id='ipb-attach-img-4366-0-37558100-1369216368' style='width:79;height:19' class='attach' width="79" height="19" alt="Attached Image: image065.gif" /></a><br /><br /> This is a very important point. If you put the inputs the wrong way round, the graphics API will not produce the desired lighting, as the normal will be facing in the opposite direction.<br /><br /> <strong class='bbc'>The Vector Equation of a Straight Line</strong><br /><br /> The vector equation of a straight line is very useful, and is given by a point on the line and a vector parallel to it:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4367-0-37577700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4367" title="image067.gif - Size: 313bytes, Downloads: 250"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-26869600-1311407396_thumb.gif" id='ipb-attach-img-4367-0-37577700-1369216368' style='width:91;height:24' class='attach' width="91" height="24" alt="Attached Image: image067.gif" /></a><br /><br /> Where <strong class='bbc'>p</strong><sub class='bbc'>0</sub> is a point on the line and <strong class='bbc'>v</strong> is the vector. <em class='bbc'>t</em> is called the parameter, and scales <strong class='bbc'>v</strong>. From this it is easy to see that as <em class='bbc'>t</em> varies, a line is formed in the direction of <strong class='bbc'>v</strong>. If <em class='bbc'>t</em> only takes positive values, then <strong class='bbc'>p</strong><sub class='bbc'>0</sub> is the starting point of the line. Diagrammatically, this is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4368-0-37597400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4368" title="image068.gif - Size: 2.06K, Downloads: 235"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-46310300-1311407412_thumb.gif" id='ipb-attach-img-4368-0-37597400-1369216368' style='width:250;height:196' class='attach' width="250" height="196" alt="Attached Image: image068.gif" /></a><br /><br /> In expanded form, the equation becomes:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4369-0-37617600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4369" title="image070.gif - Size: 259bytes, Downloads: 246"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-92978700-1311407426_thumb.gif" id='ipb-attach-img-4369-0-37617600-1369216368' style='width:81;height:24' class='attach' width="81" height="24" alt="Attached Image: image070.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4370-0-37639100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4370" title="image072.gif - Size: 272bytes, Downloads: 235"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-41873900-1311407439_thumb.gif" id='ipb-attach-img-4370-0-37639100-1369216368' style='width:83;height:25' class='attach' width="83" height="25" alt="Attached Image: image072.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4371-0-37659200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4371" title="image074.gif - Size: 259bytes, Downloads: 246"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-94295200-1311407450_thumb.gif" id='ipb-attach-img-4371-0-37659200-1369216368' style='width:80;height:23' class='attach' width="80" height="23" alt="Attached Image: image074.gif" /></a><br /><br /> This is called the <em class='bbc'>parametric</em> form of a straight line.<br /><br /> Using this to find the vector equation of a line through two points is easy:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4372-0-37679100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4372" title="image076.gif - Size: 382bytes, Downloads: 234"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-39434100-1311407462_thumb.gif" id='ipb-attach-img-4372-0-37679100-1369216368' style='width:140;height:24' class='attach' width="140" height="24" alt="Attached Image: image076.gif" /></a><br /><br /> If <em class='bbc'>t</em> is confined to values between 0 and 1, then what you have is a <em class='bbc'>line segment</em> between the points <strong class='bbc'>p</strong><sub class='bbc'>0</sub> and <strong class='bbc'>p</strong><sub class='bbc'>1</sub>.<br /><br /> Using the vector equation we can define planes, and test for intersections. I won't go into planes much here, as there are many tutorials on them elsewhere, I'll just skim over it.<br /><br /> A plane can be defined as a point on the plane, and two vectors that are parallel to the plane, or:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4373-0-37698900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4373" title="image078.gif - Size: 345bytes, Downloads: 225"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-74851200-1311407475_thumb.gif" id='ipb-attach-img-4373-0-37698900-1369216368' style='width:136;height:24' class='attach' width="136" height="24" alt="Attached Image: image078.gif" /></a><br /><br /> where <em class='bbc'>s</em> and <em class='bbc'>t</em> the parameters and <strong class='bbc'>u</strong> and <strong class='bbc'>v</strong> are the vectors that are parallel to the plane. Using this, it becomes easy to find the intersection of a line and a plane, because the point of intersection must lie on both the line and the plane, so we simply make the two equations equal to each other.<br /><br /> Take the line:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4374-0-37718700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4374" title="image080.gif - Size: 323bytes, Downloads: 233"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-27028600-1311407486_thumb.gif" id='ipb-attach-img-4374-0-37718700-1369216368' style='width:101;height:24' class='attach' width="101" height="24" alt="Attached Image: image080.gif" /></a><br /><br /> and the plane:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4375-0-37740400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4375" title="image082.gif - Size: 357bytes, Downloads: 232"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-05625300-1311407497_thumb.gif" id='ipb-attach-img-4375-0-37740400-1369216368' style='width:133;height:23' class='attach' width="133" height="23" alt="Attached Image: image082.gif" /></a><br /><br /> To find the intersection point we simply equate, so that:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4376-0-37760700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4376" title="image084.gif - Size: 340bytes, Downloads: 230"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-81188500-1311407507_thumb.gif" id='ipb-attach-img-4376-0-37760700-1369216368' style='width:147;height:24' class='attach' width="147" height="24" alt="Attached Image: image084.gif" /></a><br /><br /> Ed. note: The <strong class='bbc'>v</strong> on the left in the above equation is not the same vector as the <strong class='bbc'>v</strong> on the right.<br /><br /> We then solve for <em class='bbc'>w</em>, <em class='bbc'>s</em> and <em class='bbc'>t</em>, and then plug into either the line or plane equation to find the point. When testing for a line segment intersection, <em class='bbc'>w</em> must be between 0 and 1.<br /><br /> There are many benefits for using the normal-distance form of a plane too. It's especially useful for testing what sides of a plane points or other shaped objects are. To do this, you dot the normal vector and the position vector of the point being tested, and add the distance of the plane from the origin.<br /><br /> So, if you have the plane<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4377-0-37780700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4377" title="image086.gif - Size: 243bytes, Downloads: 247"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-79430400-1311407522_thumb.gif" id='ipb-attach-img-4377-0-37780700-1369216368' style='width:64;height:21' class='attach' width="64" height="21" alt="Attached Image: image086.gif" /></a><br /><br /> and the point <em class='bbc'>( x, y, z )</em>, the point is in front of the plane if<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4378-0-37800800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4378" title="image088.gif - Size: 364bytes, Downloads: 241"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-44983900-1311407537_thumb.gif" id='ipb-attach-img-4378-0-37800800-1369216368' style='width:151;height:25' class='attach' width="151" height="25" alt="Attached Image: image088.gif" /></a><br /><br /> and behind if it is &lt; 0. If the result equals zero, the point is on the plane. This is used heavily in culling and BSP trees.<br /><br /> <br /><span style='font-size: 18px;'><strong class='bbc'>Matrices</strong></span><br /> <br /><span style='font-size: 12px;'><strong class='bbc'>What is a Matrix anyway?</strong></span><br /><br />A matrix can be considered a 2D array of numbers. They take the form:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4379-0-37820900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4379" title="image090.gif - Size: 565bytes, Downloads: 242"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-61157600-1311407567_thumb.gif" id='ipb-attach-img-4379-0-37820900-1369216368' style='width:101;height:75' class='attach' width="101" height="75" alt="Attached Image: image090.gif" /></a><br /><br /> Matrices are very powerful, and form the basis of all modern computer graphics, the advantage of them being that they are so fast. We define a matrix with an upper-case bold type letter. Look at the above example. The dimension of a matrix is its height followed by its width, so the above example has dimension 3x3. Matrices can be of any dimensions, but in terms of computer graphics, they are usually kept to 3x3 or 4x4. There are a few types of special matrices; these are the <em class='bbc'>column matrix</em>, <em class='bbc'>row matrix</em>, <em class='bbc'>square matrix</em>, <em class='bbc'>identity matrix</em> and <em class='bbc'>zero matrix</em>. A column matrix is one that has a width of 1, and a height of greater than 1. A row matrix is a matrix that has a width of greater than 1, and a height of 1. A square matrix is when the dimensions are the same. For instance, the above example is a square matrix, because the width equals the height. The identity matrix is a special type of matrix that has values in the diagonal from top left to bottom right as 1 and the rest as 0. The identity matrix is known by the letter <span style='font-family: Times New Roman'><strong class='bbc'>I</strong></span>, where<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4380-0-37843000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4380" title="image092.gif - Size: 546bytes, Downloads: 233"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-35181600-1311407600_thumb.gif" id='ipb-attach-img-4380-0-37843000-1369216368' style='width:96;height:75' class='attach' width="96" height="75" alt="Attached Image: image092.gif" /></a><br /><br /> The identity matrix can be any dimension, as long as it is also a square matrix. The zero matrix is a matrix that has all its elements set to 0.<br /><br /> The <em class='bbc'>elements</em> of a matrix are all the numbers in it. They are numbered by the row/column position so that :<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4381-0-37863600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4381" title="image094.gif - Size: 613bytes, Downloads: 233"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-86930600-1311407611_thumb.gif" id='ipb-attach-img-4381-0-37863600-1369216368' style='width:109;height:75' class='attach' width="109" height="75" alt="Attached Image: image094.gif" /></a><br /><br /> Vectors can also be used in column or row matrices. I will use column matrices here so that it is easier to understand. A 3D vector <strong class='bbc'>a</strong> in matrix form will use a matrix <strong class='bbc'>A</strong> with dimension 3x1 so that:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4382-0-37884000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4382" title="image096.gif - Size: 415bytes, Downloads: 250"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-72535500-1311407625_thumb.gif" id='ipb-attach-img-4382-0-37884000-1369216368' style='width:57;height:75' class='attach' width="57" height="75" alt="Attached Image: image096.gif" /></a><br /><br /> which you can see is the same layout as using column vectors.<br /><br /> <span style='font-size: 12px;'><strong class='bbc'>Matrix arithmetic</strong></span><br /><br />I won't go into every matrix manipulation, but instead I'll focus on the ones that are used extensively in computer graphics.<br /><br /><strong class='bbc'>Matrix Multiplication</strong><br /> <br />There are two ways to multiply a matrix: by a scalar, and by another conformable matrix. First, let's deal with the matrix/scalar multiplication.<br /><br /> This is pretty easy, all you do is multiply each element by the scalar. So, let <strong class='bbc'>A</strong> be the original matrix, <strong class='bbc'>B</strong> be the matrix after multiplication, and <em class='bbc'>k</em> the constant. We perform:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4384-0-37904500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4384" title="image098.gif - Size: 257bytes, Downloads: 235"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-96283500-1311407655_thumb.gif" id='ipb-attach-img-4384-0-37904500-1369216368' style='width:59;height:25' class='attach' width="59" height="25" alt="Attached Image: image098.gif" /></a> where <em class='bbc'>i</em> and <em class='bbc'>j</em> are the positions in the matrix.<br /><br /> this can also be written as:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4385-0-37926700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4385" title="image100.gif - Size: 1.34K, Downloads: 240"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-60416100-1311407669_thumb.gif" id='ipb-attach-img-4385-0-37926700-1369216368' style='width:250;height:59' class='attach' width="250" height="59" alt="Attached Image: image100.gif" /></a><br /><br /> Multiplying a matrix by another matrix is more difficult. First, we need to know if the two matrices are <em class='bbc'>conformable</em>. For a matrix to be conformable with another matrix, the number of rows in <strong class='bbc'>A</strong> needs to equal the number of columns in <strong class='bbc'>B</strong>. For instance, take matrix <strong class='bbc'>A</strong> as having dimension 3x3 and matrix <strong class='bbc'>B</strong> having dimension 3x2. These two matrices are conformable because the number of rows in <strong class='bbc'>A</strong> is the same as the number of columns in <strong class='bbc'>B</strong>. This is important as you'll see later. The product of these two matrices is another matrix with dimension 3x2. So, in general terms:<br /><br /> Take three matrices <strong class='bbc'>A</strong>, <strong class='bbc'>B</strong> and <strong class='bbc'>C</strong> where <strong class='bbc'>C</strong> is the product of <strong class='bbc'>A</strong> and <strong class='bbc'>B</strong>. <strong class='bbc'>A</strong> and <strong class='bbc'>B</strong> have dimension <em class='bbc'>m</em>x<em class='bbc'>n</em> and <em class='bbc'>p</em>x<em class='bbc'>q</em> respectively. They are conformable if <em class='bbc'>n=p</em>. The matrix <strong class='bbc'>C</strong> has dimension <em class='bbc'>m</em>x<em class='bbc'>q</em>.<br /><br /> You perform the multiplication by multiplying each row in <strong class='bbc'>A</strong> by each column in <strong class='bbc'>B</strong>. So let <strong class='bbc'>A</strong> have dimension 3x3 and <strong class='bbc'>B</strong> have dimension 3x2.<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4386-0-37948400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4386" title="image102.gif - Size: 709bytes, Downloads: 242"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-58828200-1311407689_thumb.gif" id='ipb-attach-img-4386-0-37948400-1369216368' style='width:137;height:75' class='attach' width="137" height="75" alt="Attached Image: image102.gif" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4387-0-37969300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4387" title="image104.gif - Size: 609bytes, Downloads: 308"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-75807400-1311407700_thumb.gif" id='ipb-attach-img-4387-0-37969300-1369216368' style='width:100;height:75' class='attach' width="100" height="75" alt="Attached Image: image104.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4388-0-37990000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4388" title="image106.gif - Size: 2.43K, Downloads: 340"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-93812800-1311407713_thumb.gif" id='ipb-attach-img-4388-0-37990000-1369216368' style='width:250;height:33' class='attach' width="250" height="33" alt="Attached Image: image106.gif" /></a><br /><br /> So, with that in mind, let's try an example:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4389-0-38011100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4389" title="image108.gif - Size: 700bytes, Downloads: 318"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-79987200-1311407726_thumb.gif" id='ipb-attach-img-4389-0-38011100-1369216368' style='width:108;height:96' class='attach' width="108" height="96" alt="Attached Image: image108.gif" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4390-0-38033600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4390" title="image110.gif - Size: 487bytes, Downloads: 288"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-00678700-1311407738_thumb.gif" id='ipb-attach-img-4390-0-38033600-1369216368' style='width:76;height:75' class='attach' width="76" height="75" alt="Attached Image: image110.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4391-0-38054600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4391" title="image112.gif - Size: 2.75K, Downloads: 306"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-91982600-1311407747_thumb.gif" id='ipb-attach-img-4391-0-38054600-1369216368' style='width:250;height:43' class='attach' width="250" height="43" alt="Attached Image: image112.gif" /></a><br /><br /> It's as simple as that! Some things to note:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4392-0-38076000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4392" title="image114.gif - Size: 252bytes, Downloads: 296"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-29109000-1311407760_thumb.gif" id='ipb-attach-img-4392-0-38076000-1369216368' style='width:68;height:17' class='attach' width="68" height="17" alt="Attached Image: image114.gif" /></a><br /><br /> A matrix multiplied by the identity matrix is the same, so:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4393-0-38097100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4393" title="image116.gif - Size: 265bytes, Downloads: 235"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-52847700-1311407772_thumb.gif" id='ipb-attach-img-4393-0-38097100-1369216368' style='width:88;height:17' class='attach' width="88" height="17" alt="Attached Image: image116.gif" /></a><br /><br /> The <em class='bbc'>transpose</em> of a matrix is it flipped on the diagonal from the top left to the bottom right, so for example:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4394-0-38118300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4394" title="image118.gif - Size: 561bytes, Downloads: 231"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-93459600-1311407784_thumb.gif" id='ipb-attach-img-4394-0-38118300-1369216368' style='width:101;height:75' class='attach' width="101" height="75" alt="Attached Image: image118.gif" /></a><br /><br /> The transpose of this matrix would be:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4395-0-38141400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4395" title="image120.gif - Size: 576bytes, Downloads: 228"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-35495300-1311407805_thumb.gif" id='ipb-attach-img-4395-0-38141400-1369216368' style='width:111;height:75' class='attach' width="111" height="75" alt="Attached Image: image120.gif" /></a><br /><br /> Simple enough eh? And you thought it was going to be hard!<br /><br /> <span style='font-size: 12px;'><strong class='bbc'>Determinants</strong></span><br /><br />I'm going to talk a little bit about determinants now, as they are useful for solving certain types of equations. I will discuss easy 2x2 determinants first.<br /><br /> Take a 2x2 matrix:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4396-0-38163200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4396" title="image122.gif - Size: 474bytes, Downloads: 247"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-76083400-1311407842_thumb.gif" id='ipb-attach-img-4396-0-38163200-1369216368' style='width:103;height:51' class='attach' width="103" height="51" alt="Attached Image: image122.gif" /></a><br /><br /> The determinant of a matrix <strong class='bbc'>A</strong> is written |<strong class='bbc'>A</strong>| and is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4397-0-38184500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4397" title="image124.gif - Size: 362bytes, Downloads: 238"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-61430500-1311407863_thumb.gif" id='ipb-attach-img-4397-0-38184500-1369216368' style='width:128;height:27' class='attach' width="128" height="27" alt="Attached Image: image124.gif" /></a><br /><br /> For higher dimension matrices, the determinant gets more complicated. Let's discuss a 3x3 matrix. You pass along the first row, and at each element, you discount the row and column that intersects it, and calculate the determinant of the resultant 2x2 matrix multiplied by that value.<br /><br /> So, for example, take this 3x3 matrix:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4398-0-38205900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4398" title="image126.gif - Size: 709bytes, Downloads: 224"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-93920700-1311407878_thumb.gif" id='ipb-attach-img-4398-0-38205900-1369216368' style='width:137;height:75' class='attach' width="137" height="75" alt="Attached Image: image126.gif" /></a><br /><br /> Ok then, Step 1: move to the first value in the top row, <em class='bbc'>a</em><sub class='bbc'>11</sub> . Take out the row and column that intersects with that value. Step 2: multiply that determinant by <em class='bbc'>a</em><sub class='bbc'>11</sub>. So, using diagrams:<br /><br /> Step1:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4399-0-38229100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4399" title="image128.gif - Size: 542bytes, Downloads: 229"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-41315500-1311407890_thumb.gif" id='ipb-attach-img-4399-0-38229100-1369216368' style='width:108;height:75' class='attach' width="108" height="75" alt="Attached Image: image128.gif" /></a><br /><br /> Step2:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4400-0-38250700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4400" title="image130.gif - Size: 420bytes, Downloads: 230"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-76373600-1311407901_thumb.gif" id='ipb-attach-img-4400-0-38250700-1369216368' style='width:84;height:51' class='attach' width="84" height="51" alt="Attached Image: image130.gif" /></a><br /><br /> We repeat this all along the top row, with the sign in front of the value of the top row alternating between a "+" and a "-", so the determinant of <strong class='bbc'>A</strong> would be:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4401-0-38272600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4401" title="image132.gif - Size: 958bytes, Downloads: 234"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-62269500-1311407916_thumb.gif" id='ipb-attach-img-4401-0-38272600-1369216368' style='width:250;height:42' class='attach' width="250" height="42" alt="Attached Image: image132.gif" /></a><br /><br /> Now, how do we use these for equation solving? Good question. I will first show you how to solve a pair of equations with 2 unknowns.<br /><br /> Take the two equations:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4402-0-38294200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4402" title="image134.gif - Size: 429bytes, Downloads: 235"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-36208700-1311407930_thumb.gif" id='ipb-attach-img-4402-0-38294200-1369216368' style='width:96;height:48' class='attach' width="96" height="48" alt="Attached Image: image134.gif" /></a><br /><br /> We first <em class='bbc'>push</em> the coefficients of the variables into a determinant, producing:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4403-0-38315800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4403" title="image136.gif - Size: 332bytes, Downloads: 215"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-95740300-1311407941_thumb.gif" id='ipb-attach-img-4403-0-38315800-1369216368' style='width:55;height:51' class='attach' width="55" height="51" alt="Attached Image: image136.gif" /></a><br /><br /> You can see it's laid out in the same way, which makes it easy. Now, to solve the equation in terms of <em class='bbc'>x</em>, we replace the x coefficients in the determinant with the constants <em class='bbc'>k<sub class='bbc'>1</sub></em> and <em class='bbc'>k<sub class='bbc'>2</sub></em>, dividing the result by the original determinant. So, that would be:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4404-0-38339300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4404" title="image138.gif - Size: 608bytes, Downloads: 227"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-46880800-1311407957_thumb.gif" id='ipb-attach-img-4404-0-38339300-1369216368' style='width:145;height:51' class='attach' width="145" height="51" alt="Attached Image: image138.gif" /></a><br /><br /> To solve for <em class='bbc'>y</em> we replace the y coefficients with the constants instead.<br /><br /> Let's try an example to see this working:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4405-0-38361500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4405" title="image140.gif - Size: 368bytes, Downloads: 232"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-74094200-1311407970_thumb.gif" id='ipb-attach-img-4405-0-38361500-1369216368' style='width:88;height:45' class='attach' width="88" height="45" alt="Attached Image: image140.gif" /></a><br /><br /> We push the coefficients into a determinant, and solve:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4406-0-38383400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4406" title="image142.gif - Size: 540bytes, Downloads: 229"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-03371400-1311407986_thumb.gif" id='ipb-attach-img-4406-0-38383400-1369216368' style='width:189;height:48' class='attach' width="189" height="48" alt="Attached Image: image142.gif" /></a><br /><br /> To find <em class='bbc'>x</em> substitute constants into <em class='bbc'>x</em> co-efficients, and divide by <strong class='bbc'>D</strong>:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4407-0-38405300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4407" title="image144.gif - Size: 776bytes, Downloads: 230"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-34552100-1311407997_thumb.gif" id='ipb-attach-img-4407-0-38405300-1369216368' style='width:228;height:72' class='attach' width="228" height="72" alt="Attached Image: image144.gif" /></a><br /><br /> To find <em class='bbc'>y</em> substitute constants into <em class='bbc'>y</em> co-efficients and divide by <strong class='bbc'>D</strong>:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4408-0-38429300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4408" title="image146.gif - Size: 790bytes, Downloads: 242"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-60848100-1311408028_thumb.gif" id='ipb-attach-img-4408-0-38429300-1369216368' style='width:229;height:72' class='attach' width="229" height="72" alt="Attached Image: image146.gif" /></a><br /><br /> See, it's as simple as that! Just for good measure, I'll do an example using 3 unknowns in 3 equations:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4409-0-38451400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4409" title="image148.gif - Size: 534bytes, Downloads: 240"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-66491000-1311408041_thumb.gif" id='ipb-attach-img-4409-0-38451400-1369216368' style='width:109;height:69' class='attach' width="109" height="69" alt="Attached Image: image148.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4410-0-38473700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4410" title="image150.gif - Size: 1.32K, Downloads: 244"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-60304700-1311408056_thumb.gif" id='ipb-attach-img-4410-0-38473700-1369216368' style='width:250;height:59' class='attach' width="250" height="59" alt="Attached Image: image150.gif" /></a><br /><br /> Solve for <em class='bbc'>x</em>:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4411-0-38496500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4411" title="image152.gif - Size: 1.51K, Downloads: 247"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-07028100-1311408071_thumb.gif" id='ipb-attach-img-4411-0-38496500-1369216368' style='width:250;height:57' class='attach' width="250" height="57" alt="Attached Image: image152.gif" /></a><br /><br /> Solve for <em class='bbc'>y</em>:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4412-0-38519200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4412" title="image154.gif - Size: 1.51K, Downloads: 240"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-35264300-1311408084_thumb.gif" id='ipb-attach-img-4412-0-38519200-1369216368' style='width:250;height:58' class='attach' width="250" height="58" alt="Attached Image: image154.gif" /></a><br /><br /> Solve for <em class='bbc'>z</em>:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4413-0-38543800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4413" title="image156.gif - Size: 1.42K, Downloads: 240"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-88537000-1311408097_thumb.gif" id='ipb-attach-img-4413-0-38543800-1369216368' style='width:250;height:61' class='attach' width="250" height="61" alt="Attached Image: image156.gif" /></a><br /><br /> And there we have it, how to solve a series of simultaneous equations using determinants, something that can be very useful.<br /><br /> <strong class='bbc'>Matrix Inversion</strong><br /><br /> Equations can also be solved by inverting a matrix. Take the following equations again:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4414-0-38567000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4414" title="image157.gif - Size: 534bytes, Downloads: 239"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-56571200-1311408118_thumb.gif" id='ipb-attach-img-4414-0-38567000-1369216368' style='width:109;height:69' class='attach' width="109" height="69" alt="Attached Image: image157.gif" /></a><br /><br /> We push these into 3 matrices to solve:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4415-0-38589700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4415" title="image159.gif - Size: 865bytes, Downloads: 231"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-90083900-1311408131_thumb.gif" id='ipb-attach-img-4415-0-38589700-1369216368' style='width:157;height:75' class='attach' width="157" height="75" alt="Attached Image: image159.gif" /></a><br /><br /> Let's give these names such that:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4416-0-38612500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4416" title="image161.gif - Size: 233bytes, Downloads: 240"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-02710700-1311408147_thumb.gif" id='ipb-attach-img-4416-0-38612500-1369216368' style='width:56;height:17' class='attach' width="56" height="17" alt="Attached Image: image161.gif" /></a><br /><br /> We need to solve for B, and since there is no "matrix divide" operation, we need to invert the matrix <strong class='bbc'>A</strong> and multiply it by <strong class='bbc'>D</strong>, such that:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4417-0-38636800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4417" title="image163.gif - Size: 254bytes, Downloads: 230"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-35483900-1311408160_thumb.gif" id='ipb-attach-img-4417-0-38636800-1369216368' style='width:68;height:20' class='attach' width="68" height="20" alt="Attached Image: image163.gif" /></a><br /><br /> Now we need to know how to actually do the matrix inversion. There are many ways to do this, and the way I am going to show you is by no means the fastest.<br /><br /> To find the inverse of a matrix, we need to first find its <em class='bbc'>co-factor</em>. We use a method similar to what we used when finding the determinant. What you do is this: at every element, eliminate the row and column that intersects it, and make it equal the determinant of the remaining part of the matrix. Let's find the first element in a 3x3 matrix. Let's call it c<sub class='bbc'>11</sub>. We need to get rid of the row and column that intersects this, so that:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4418-0-38659900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4418" title="image164.gif - Size: 542bytes, Downloads: 219"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-44070200-1311408176_thumb.gif" id='ipb-attach-img-4418-0-38659900-1369216368' style='width:108;height:75' class='attach' width="108" height="75" alt="Attached Image: image164.gif" /></a><br /><br /> c<sub class='bbc'>11</sub> will then take the value of the following determinant:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4419-0-38682700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4419" title="image166.gif - Size: 366bytes, Downloads: 226"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-22853200-1311408190_thumb.gif" id='ipb-attach-img-4419-0-38682700-1369216368' style='width:65;height:51' class='attach' width="65" height="51" alt="Attached Image: image166.gif" /></a><br /><br /> The sign in front of c<sub class='bbc'>11</sub> is decided by the expression:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4420-0-38705700-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4420" title="image168.gif - Size: 234bytes, Downloads: 229"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-42517300-1311408207_thumb.gif" id='ipb-attach-img-4420-0-38705700-1369216368' style='width:47;height:24' class='attach' width="47" height="24" alt="Attached Image: image168.gif" /></a><br /><br /> Where <em class='bbc'>i</em> and <em class='bbc'>j</em> are the positions of the element in the matrix.<br /><br /> That's easy enough isn't it? Thought so J. Just do the same for every element, and build up the co-factor matrix. Done? Good. Now that the co-factor matrix has been found, the inverse matrix can be calculated using the following equation:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4421-0-38730100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4421" title="image170.gif - Size: 338bytes, Downloads: 221"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-23509400-1311408221_thumb.gif" id='ipb-attach-img-4421-0-38730100-1369216368' style='width:69;height:49' class='attach' width="69" height="49" alt="Attached Image: image170.gif" /></a><br /><br /> Taking the previous example and equations, let's find the inverse matrix of <strong class='bbc'>A</strong>.<br /><br /> First, the co-factor matrix <strong class='bbc'>C</strong> would be:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4422-0-38753100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4422" title="image172.gif - Size: 2.28K, Downloads: 242"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-40859400-1311408235_thumb.gif" id='ipb-attach-img-4422-0-38753100-1369216368' style='width:250;height:115' class='attach' width="250" height="115" alt="Attached Image: image172.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4423-0-38776800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4423" title="image174.gif - Size: 632bytes, Downloads: 224"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-53635100-1311408248_thumb.gif" id='ipb-attach-img-4423-0-38776800-1369216368' style='width:139;height:75' class='attach' width="139" height="75" alt="Attached Image: image174.gif" /></a><br /><br /> and |<strong class='bbc'>A</strong>| is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4424-0-38801300-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4424" title="image176.gif - Size: 253bytes, Downloads: 238"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-60668100-1311408264_thumb.gif" id='ipb-attach-img-4424-0-38801300-1369216368' style='width:56;height:27' class='attach' width="56" height="27" alt="Attached Image: image176.gif" /></a><br /><br /> So <strong class='bbc'>A</strong>­­<sup class='bbc'>-1</sup> is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4425-0-38827100-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4425" title="image178.gif - Size: 2.08K, Downloads: 228"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-22468900-1311408277_thumb.gif" id='ipb-attach-img-4425-0-38827100-1369216368' style='width:250;height:61' class='attach' width="250" height="61" alt="Attached Image: image178.gif" /></a><br /><br /> To solve the equations, we then do:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4426-0-38851600-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4426" title="image163.gif - Size: 254bytes, Downloads: 235"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-36524500-1311408291_thumb.gif" id='ipb-attach-img-4426-0-38851600-1369216368' style='width:68;height:20' class='attach' width="68" height="20" alt="Attached Image: image163.gif" /></a><br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4427-0-38875400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4427" title="image182.gif - Size: 1.26K, Downloads: 238"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-70122200-1311408302_thumb.gif" id='ipb-attach-img-4427-0-38875400-1369216368' style='width:250;height:69' class='attach' width="250" height="69" alt="Attached Image: image182.gif" /></a><br /><br /> We can then find the values of <em class='bbc'>x</em>,<em class='bbc'>y</em> and <em class='bbc'>z</em> by pulling them out of the last matrix, such that x = -62, y = 39 and z = 3, which is what the other method using determinants found.<br /><br /> A matrix is called <em class='bbc'>orthogonal</em> if its inverse equals its transpose.<br /><br /> <span style='font-size: 12px;'><strong class='bbc'>Matrices in computer graphics</strong></span><br /><br />All graphics APIs use a set of matrices to define transformations in space. A transformation is a change, be it translation, rotation, or whatever. Using column a matrix to define a point in space, a <em class='bbc'>vertex</em>, we can define matrices that alter that point in some way.<br /><br /> <strong class='bbc'>Transformation Matrices</strong><br /><br /> Most graphics APIs use 3 different types of primary transformations. These are:<br /> <ul class='bbcol decimal'><li>Translation</li><li>Scale</li><li>Rotation</li></ul> I won't go into the derivation of the matrices for these transformations, as that will take up far too much space. Any good math book that explains affine space transformations will explain their derivations. You have to pre-multiply points by the transformation matrix, as it is impossible to post-multiply because of the dimensions.<br /><br /> Therefore, a point <strong class='bbc'>p</strong> can be transformed to point <strong class='bbc'>p'</strong> using a transformation matrix <strong class='bbc'>T</strong> so that:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4428-0-38899400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4428" title="image184.gif - Size: 232bytes, Downloads: 233"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-21418000-1311408329_thumb.gif" id='ipb-attach-img-4428-0-38899400-1369216368' style='width:49;height:21' class='attach' width="49" height="21" alt="Attached Image: image184.gif" /></a><br /><br /> <strong class='bbc'>Translation</strong><br /><br /> To translate a point onto another point, there needs to be a vector of movement, so that<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4429-0-38924500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4429" title="image185.gif - Size: 2.08K, Downloads: 247"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-33354500-1311408346_thumb.gif" id='ipb-attach-img-4429-0-38924500-1369216368' style='width:250;height:132' class='attach' width="250" height="132" alt="Attached Image: image185.gif" /></a><br /><br /> where <strong class='bbc'>p</strong><sup class='bbc'>'</sup> is the translated point, <strong class='bbc'>p</strong> is the original point, and <strong class='bbc'>v</strong> is the vector along which to translate.<br /><br /> In matrix form, this turns into:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4430-0-38949400-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4430" title="image187.gif - Size: 819bytes, Downloads: 255"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-82034400-1311408360_thumb.gif" id='ipb-attach-img-4430-0-38949400-1369216368' style='width:131;height:96' class='attach' width="131" height="96" alt="Attached Image: image187.gif" /></a><br /><br /> Where <em class='bbc'>dx</em>, <em class='bbc'>dy</em> and <em class='bbc'>dz</em> are the components of the vector in the respective axis of movement. Note that a 4D vertex is used. These are called <em class='bbc'>homogeneous</em> co-ordinates, BUT I will not discuss them here.<br /><br /> <strong class='bbc'>Scaling</strong><br /><br /> You can scale a vertex by multiplying it by a scalar value, so that<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4431-0-38973500-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4431" title="image188.gif - Size: 2.8K, Downloads: 247"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-08438100-1311408378_thumb.gif" id='ipb-attach-img-4431-0-38973500-1369216368' style='width:250;height:102' class='attach' width="250" height="102" alt="Attached Image: image188.gif" /></a><br /><br /> where <em class='bbc'>k</em> is the scalar constant. You can multiply each component of <strong class='bbc'>p</strong> by a different constant. This will make it so you can scale each axis by a different amount.<br /><br /> In matrix form this is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4432-0-38998000-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4432" title="image190.gif - Size: 846bytes, Downloads: 290"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-03040100-1311408393_thumb.gif" id='ipb-attach-img-4432-0-38998000-1369216368' style='width:140;height:96' class='attach' width="140" height="96" alt="Attached Image: image190.gif" /></a><br /><br /> <strong class='bbc'>Rotation</strong><br /><br /> Rotation is the most complex transformation. Rotation can be performed around the 3 Cartesian axes.<br /><br /> The rotation matrices around these axis are:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4433-0-39021800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4433" title="image192.gif - Size: 2.38K, Downloads: 295"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-30845900-1311408411_thumb.gif" id='ipb-attach-img-4433-0-39021800-1369216368' style='width:132;height:200' class='attach' width="132" height="200" alt="Attached Image: image192.gif" /></a><br /><br /> To find out more about how these matrices are derived, please pick up a good math book, I haven't got the time to write it here. Some things about these matrices though:<br /><br /> Any rotation about an axis by q can be undone by a successive rotation by -q. So:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4434-0-39047900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4434" title="image194.gif - Size: 332bytes, Downloads: 282"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-63177900-1311408429_thumb.gif" id='ipb-attach-img-4434-0-39047900-1369216368' style='width:109;height:24' class='attach' width="109" height="24" alt="Attached Image: image194.gif" /></a><br /><br /> Also, notice that the cosine terms are always on the top-left to bottom-right diagonal, and the sine terms are always on the top-right to bottom-left diagonal, we can also say that:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4435-0-39071900-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4435" title="image196.gif - Size: 337bytes, Downloads: 274"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-56985200-1311408443_thumb.gif" id='ipb-attach-img-4435-0-39071900-1369216368' style='width:109;height:24' class='attach' width="109" height="24" alt="Attached Image: image196.gif" /></a><br /><br /> Rotations matrices that act about the origin are orthogonal.<br /><br /> Note that these transformations are cumulative. That is, if you multiplied a vertex by a translation matrix, then by a scale matrix, it would have the effect of moving the vertex, then scaling it. The order that you multiply becomes very important when you multiply rotation and translation matrices together, as <strong class='bbc'>RT</strong> does NOT equal <strong class='bbc'>TR</strong>!<br /><br /> <strong class='bbc'>Projection Matrices</strong><br /><br /> These are also complicated matrices. They come in two flavours, <em class='bbc'>perspective correct</em> and <em class='bbc'>orthographic</em>. There are some very good books that derive these matrices in an understandable way, so I won't cover it here. Since I don't work with projection matrices very often, I had to look a lot of this material up using the book <a href='http://www.gamedev.net/columns/books/featuredbook.asp?ProductID=111' class='bbc_url' title=''>Interactive Computer Graphics</a> by Edward Angel. A very good book that I suggest you buy.<br /><br /> Anyway, on to the matrices.<br /><br /> The orthographic projection matrix:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4436-0-39095800-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4436" title="image198.gif - Size: 1.77K, Downloads: 283"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-55531000-1311408467_thumb.gif" id='ipb-attach-img-4436-0-39095800-1369216368' style='width:250;height:97' class='attach' width="250" height="97" alt="Attached Image: image198.gif" /></a><br /><br /> The <em class='bbc'>x</em>, <em class='bbc'>y</em> and <em class='bbc'>z</em> <em class='bbc'>max/min</em> variables define the viewing volume.<br /><br /> The perspective correct projection matrix is:<br /><br /> <a class='resized_img' rel='lightbox[a8270dc4702b462f801bfae27a070d86]' id='ipb-attach-url-4437-0-39120200-1369216368' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=4437" title="image200.gif - Size: 1.92K, Downloads: 288"><img src="http://uploads.gamedev.net/monthly_07_2011/ccs-8549-0-56064000-1311408486_thumb.gif" id='ipb-attach-img-4437-0-39120200-1369216368' style='width:250;height:94' class='attach' width="250" height="94" alt="Attached Image: image200.gif" /></a><br /><br /> <br /><span style='font-size: 18px;'><strong class='bbc'>Conclusion</strong></span><br /><br />Well, that's it for this tutorial. I hope that I've helped you understand vectors and matrices including how to use them. For further reading I can recommend a few books that I have found really useful, these are:<br /><br /> <a href='http://www.gamedev.net/columns/books/featuredbook.asp?ProductID=111' class='bbc_url' title=''>Interactive Computer Graphics – A Top Down Approach with OpenGL" –</a> Edward Angel: Covers a lot of theory in computer graphics, including how we perceive the world around us. This book covers a lot of the matrix derivations that I left out. All in all, a very good book on graphics programming and theory. With exercises too, which is nice.<br /><br /> <a href='http://www.gamedev.net/columns/books/featuredbook.asp?productid=135' class='bbc_url' title=''>Mathematics for Computer Graphics Applications – Second Edition</a> – M.E Mortenson: This is solely about the mathematics behind computer graphics, and explains a lot of material in a very easy to understand manner. There are loads of exercises to keep you occupied. The book explains things such as vectors, matrices, transformations, topology and continuity, symmetry, polyhedra, half-spaces, constructive solid geometry, points, lines, curves, surfaces, and more! A must for anyone serious in graphics programming. You won't see a line of code or pseudo-code though.<br /><br /> <span class='bbc_underline'>Advanced National Certificate Mathematics Vol.: 2</span> – Pedoe: I don't know whether you can actually get this book anymore, but if you can get a copy! This book explains mathematical concepts well, and is easy to learn from. This book is about general mathematics though, each volume expands on the other. So vol. 1 introduces concepts, vol. 2 expands on them. A book well worth the money (although I have no idea how much it is, as I got my copy off my dad ).<br /><br /> That's about it! I hope I haven't scared you off graphics programming. Most APIs, including Direct3D and OpenGL, will hide some of this away from you.<br /><br /> If you need to contact me at all, my email address is: <a href='mailto:phil.dadd@btinternet.com' class='bbc_url' title='External link' rel='nofollow external'>phil.dadd@btinternet.com</a>. I don't want any abuse though - if you don't like this tutorial I accept constructive advice only.<br /><br /> <br /><strong class='bbc'><span style='font-size: 18px;'>Credits</span><br /><br /></strong> I'd like to give credit to "Advanced National Certificate Mathematics Vol.: 2" as that's where I got the simultaneous equations from in the part on determinants, so I knew the answers were whole, and that they worked out. I would also like to give credit to Miss. A Miller who proof read this tutorial for me.]]></description>
		<pubDate>Tue, 04 Jun 2002 23:47:26 +0000</pubDate>
		<guid isPermaLink="false">d20d9896e5f7a733d09c07acb323154f</guid>
	</item>
	<item>
		<title>The Matrix and Quaternions FAQ</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/the-matrix-and-quaternions-faq-r1691</link>
		<description><![CDATA[<span style='font-family: Courier New'><strong class='bbc'>(Editor's Note - This article requires additional formatting work and is incomplete)</strong><br /><br />Version 1.21&nbsp;&nbsp;30th November 2003<br />-------------------------------<br />Please mail feedback to <a href='mailto:matrix_faq@j3d.org' class='bbc_url' title='External link' rel='nofollow external'>matrix_faq@j3d.org</a><br />with a subject starting with&nbsp;&nbsp;<strong class='bbc'>MATRIX-FAQ </strong><br /><br />(otherwise my spam filter will simply kill your message).<br />Any additional suggestions or related questions are welcome.<br />Just send E-mail to the above address.<br />The latest copy of this FAQ can be found at the following web page:<br /><br /><a href='http://www.j3d.org/matrix_faq/matrfaq_latest.html' class='bbc_url' title='External link' rel='nofollow external'>http://www.j3d.org/matrix_faq/matrfaq_latest.html</a><br />Feel free to distribute or copy this FAQ as you please.<br /><br />Contributions<br />-------------<br /><br />&nbsp;&nbsp;<a href='#I1' class='bbc_url' title='External link' rel='nofollow external'>Introduction I1</a>: <a href='mailto:steve@%28no-spam%29mred.bgm.link.com' class='bbc_url' title='External link' rel='nofollow external'>Steve ?????</a><br />&nbsp;&nbsp;Correction to <a href='#Q55' class='bbc_url' title='External link' rel='nofollow external'>Q55</a> until <a href='#Q59' class='bbc_url' title='External link' rel='nofollow external'>Q59</a>:<br />&nbsp;&nbsp;<a href='mailto:andreas.junghanns@%28no-spam%29dcx.com' class='bbc_url' title='External link' rel='nofollow external'>Andreas Junghanns</a><br /><br />&nbsp;&nbsp;Correction to <a href='#Q50' class='bbc_url' title='External link' rel='nofollow external'>Q50</a>: <a href='mailto:morten@%28no-spam%29innerloop.no' class='bbc_url' title='External link' rel='nofollow external'>Morten Ofstad</a><br />&nbsp;&nbsp;Note to <a href='#Q39' class='bbc_url' title='External link' rel='nofollow external'>Q39</a>: <a href='mailto:t.nuydens@%28no-spam%29vrcontext.com' class='bbc_url' title='External link' rel='nofollow external'>Tom Nuydens</a><br />&nbsp;&nbsp;Corrections to <a href='#Q29' class='bbc_url' title='External link' rel='nofollow external'>Q29</a> and <a href='#Q37' class='bbc_url' title='External link' rel='nofollow external'>Q37</a>: </span><a href='mailto:eric@%28no-spam%29ee.pitt.edu' class='bbc_url' title='External link' rel='nofollow external'><span style='font-family: Courier New'>Eric Reiss</span></a><span style='font-family: Courier New'><br />&nbsp;&nbsp;Clarification to <a href='#Q56' class='bbc_url' title='External link' rel='nofollow external'>Q56</a>: <a href='mailto:murdoch@%28no-spam%29fisher.stats.uwo.ca' class='bbc_url' title='External link' rel='nofollow external'>Duncan Murdoch</a><br />&nbsp;&nbsp;Clarification to <a href='#Q37' class='bbc_url' title='External link' rel='nofollow external'>Q37</a>: <a href='mailto:avitzur@%28no-spam%29PacificT.com' class='bbc_url' title='External link' rel='nofollow external'>Ron Avitzur</a><br />&nbsp;&nbsp;Correction to <a href='#Q1' class='bbc_url' title='External link' rel='nofollow external'>Q1</a>: <a href='mailto:mona@%28no-spam%29ncmir.ucsd.edu' class='bbc_url' title='External link' rel='nofollow external'>Mona Wong</a><br /><br />&nbsp;&nbsp;Corrections to <a href='#Q36' class='bbc_url' title='External link' rel='nofollow external'>Q36</a> and <a href='#Q37' class='bbc_url' title='External link' rel='nofollow external'>Q37</a>: <a href='mailto:eric@%28no-spam%29ee.pitt.edu' class='bbc_url' title='External link' rel='nofollow external'>Eric Reiss</a><br />&nbsp;&nbsp;Improvement to <a href='#Q34' class='bbc_url' title='External link' rel='nofollow external'>Q34</a> and <a href='#Q38' class='bbc_url' title='External link' rel='nofollow external'>Q38</a>: <a href='mailto:hplus-mail@%28no-spam%29mindcontrol.org' class='bbc_url' title='External link' rel='nofollow external'>Jon Watte</a><br /><br />&nbsp;&nbsp;Warning and alternative to <a href='#Q58' class='bbc_url' title='External link' rel='nofollow external'>Q58</a> and <a href='#Q59' class='bbc_url' title='External link' rel='nofollow external'>Q59</a>: <a href='mailto:PPedriana@%28no-spam%29maxis.com' class='bbc_url' title='External link' rel='nofollow external'>Paul Pedriana</a><br />&nbsp;&nbsp;Correction (and optimization [Lee]) to <a href='#Q53' class='bbc_url' title='External link' rel='nofollow external'>Q53</a>: <a href='mailto:ellieg@%28no-spam%29cableinet.co.uk' class='bbc_url' title='External link' rel='nofollow external'>Eleanor Groundwater</a> and <a href='mailto:LeeMorgan@%28no-spam%29lee-morgan.net' class='bbc_url' title='External link' rel='nofollow external'>Lee Morgan</a><br /><br />&nbsp;&nbsp;Improvement to <a href='#Q39' class='bbc_url' title='External link' rel='nofollow external'>Q39</a>: <a href='mailto:jhunpingco@%28no-spam%29yahoo.com' class='bbc_url' title='External link' rel='nofollow external'>jhunpingco</a><br />&nbsp;&nbsp;Corrections to <a href='#Q11' class='bbc_url' title='External link' rel='nofollow external'>Q11</a> and optimization to <a href='#Q12' class='bbc_url' title='External link' rel='nofollow external'>Q12</a>: <a href='mailto:GDW33@%28no-spam%29student.canterbury.ac.nz' class='bbc_url' title='External link' rel='nofollow external'>Gordon</a><br />&nbsp;&nbsp;Corrections to <a href='#Q54' class='bbc_url' title='External link' rel='nofollow external'>Q54</a> to <a href='#Q60' class='bbc_url' title='External link' rel='nofollow external'>Q60</a>: <a href='mailto:eleanorg@%28no-spam%29owl.co.uk' class='bbc_url' title='External link' rel='nofollow external'>Eleanor Groundwater</a><br /><br />&nbsp;&nbsp;Corrections and improvements to <a href='#Q23' class='bbc_url' title='External link' rel='nofollow external'>Q23</a> and <a href='#Q24' class='bbc_url' title='External link' rel='nofollow external'>Q24</a>: <a href='mailto:ben@%28no-spam%29exocortex.org' class='bbc_url' title='External link' rel='nofollow external'>Ben Houston</a><br />&nbsp;&nbsp;Addition to <a href='#Q39' class='bbc_url' title='External link' rel='nofollow external'>Q39</a>: <a href='mailto:hplus@%28no-spam%29mindcontrol.org' class='bbc_url' title='External link' rel='nofollow external'>Jon Watte</a><br />&nbsp;&nbsp;Correction to <a href='#Q61' class='bbc_url' title='External link' rel='nofollow external'>Q61</a>: <a href='mailto:adam@%28no-spam%29gimp.org' class='bbc_url' title='External link' rel='nofollow external'>Adam D. Moss</a><br /><br />&nbsp;&nbsp;Addition of <a href='#Q63' class='bbc_url' title='External link' rel='nofollow external'>Q63</a>: <a href='mailto:cline@%28no-spam%29cs.ubc.ca' class='bbc_url' title='External link' rel='nofollow external'>Mike Cline</a><br />&nbsp;&nbsp;Addition of <a href='#I2' class='bbc_url' title='External link' rel='nofollow external'>I2</a>: <a href='mailto:jacob@%28no-spam%29marner.dk' class='bbc_url' title='External link' rel='nofollow external'>Jacob Marner</a><br />&nbsp;&nbsp;Correction to <a href='#Q38' class='bbc_url' title='External link' rel='nofollow external'>Q38</a> and inception of <a href='#I2' class='bbc_url' title='External link' rel='nofollow external'>I2</a>: <a href='mailto:armuller@%28no-spam%29ira.uka.de' class='bbc_url' title='External link' rel='nofollow external'>Armin M?ller</a><br /><br />&nbsp;&nbsp;Addition of <a href='#Q60' class='bbc_url' title='External link' rel='nofollow external'>Q60</a>: <a href='mailto:pfiguero@%28no-spam%29cs.ualberta.ca' class='bbc_url' title='External link' rel='nofollow external'>Pablo Figueroa</a><br />&nbsp;&nbsp;Correntions and additions to <a href='#Q14' class='bbc_url' title='External link' rel='nofollow external'>Q14</a>, <a href='#Q16' class='bbc_url' title='External link' rel='nofollow external'>Q16</a>, <a href='#Q21' class='bbc_url' title='External link' rel='nofollow external'>Q21</a> and <a href='#Q34' class='bbc_url' title='External link' rel='nofollow external'>Q34</a>: <a href='mailto:tronster321@%28no-spam%29hotmail.com' class='bbc_url' title='External link' rel='nofollow external'>Tronster Hartley</a><br /><br />&nbsp;&nbsp;Correction to <a href='#Q12' class='bbc_url' title='External link' rel='nofollow external'>Q12</a> and <a href='#Q54' class='bbc_url' title='External link' rel='nofollow external'>Q54</a>: <a href='mailto:frankdj@%28no-spam%29mailhost.ph.tn.tudelft.nl' class='bbc_url' title='External link' rel='nofollow external'>Frank DJ</a><br />&nbsp;&nbsp;Correction to <a href='#Q34' class='bbc_url' title='External link' rel='nofollow external'>Q34</a>: <a href='mailto:robert.funnell@i%28no-spam%29mcgill.ca' class='bbc_url' title='External link' rel='nofollow external'>Robert Funnell</a><br /><br /><br />History<br />-------<br />I (Andreas) tried to find "<a href='mailto:hexapod@%28no-spam%29netcom.com' class='bbc_url' title='External link' rel='nofollow external'>hexapod@(no-spam)netcom.com</a>" who seemed to have maintained<br />this for a while, but the site at netcom.com doesn't exist anymore,<br />emails bounce.&nbsp;&nbsp;Since I (and colleques) wasted quite some time figuring out<br />what was wrong with some of the algorithms given in the earlier versions of<br />this document, I decided to correct it and put it back on the web.<br />The formerly given sites for the location of these documents do<br />not exist anymore:<br />&nbsp;&nbsp;<a href='ftp://ftp.netcom.com/pub/he/hexapod/index.html' class='bbc_url' title='External link' rel='nofollow external'>ftp://ftp.netcom.com/pub/he/hexapod/index.html</a><br />&nbsp;&nbsp;<a href='http://www.glue.umd.edu/~rsrodger' class='bbc_url' title='External link' rel='nofollow external'>http://www.glue.umd.edu/~rsrodger</a><br />&nbsp;&nbsp;Versions, dates and links to local copies (so you can compare):<br />matrfaq_1.02.html: Version 1.2&nbsp;&nbsp;2nd September 1997<br />matrfaq_1.04.html: Version 1.4&nbsp;&nbsp;26th December 1998<br />matrfaq_1.06.html: Version 1.6&nbsp;&nbsp;30th September 2000<br />matrfaq_1.07.html: Version 1.7&nbsp;&nbsp;20th December 2000<br />matrfaq_1.08.html: Version 1.8&nbsp;&nbsp;21th December 2000<br />matrfaq_1.09.html: Version 1.9&nbsp;&nbsp;16th January 2001<br />matrfaq_1.10.html: Version 1.10&nbsp;&nbsp;30th January 2001<br /><br />matrfaq_1.11.html: Version 1.11&nbsp;&nbsp;9th February 2001<br />matrfaq_1.12.html: Version 1.12&nbsp;&nbsp;26th March 2001<br />matrfaq_1.13.html: Version 1.13&nbsp;&nbsp;20th July 2001<br />matrfaq_1.14.html: Version 1.14&nbsp;&nbsp;17th August 2001<br />matrfaq_1.15.html: Version 1.15&nbsp;&nbsp;20th August 2001<br />matrfaq_1.16.html: Version 1.16&nbsp;&nbsp;2nd October 2001<br />matrfaq_1.17.html: Version 1.17&nbsp;&nbsp;30th November 2001<br />matrfaq_1.18.html: Version 1.18&nbsp;&nbsp;27th January 2002<br />matrfaq_1.19.html: Version 1.19&nbsp;&nbsp;20th March 2002<br /><br />matrfaq_1.20.html: Version 1.20&nbsp;&nbsp;31st January 2002<br />matrfaq_1.21.html: Version 1.21&nbsp;&nbsp;30th November 2003<br /> <br /><br />Please refrain from asking me math questions. I am only maintaining this FAQ<br />and have very little knowledge about the subject. But, if you have a<br />question that is not answered by this FAQ and later happen to find the<br />answer and believe it to be relevant for this FAQ (or its readers), please<br />send all relevant information, hopefully in a pre-digested form, to me to<br />be included here. Thanks!<br />If you prefer to appear as "anonymous" in the contributions list, let me<br />know, otherwise I'll just put you down with whatever name I can gather from<br />your email header.<br /><br />Introduction<br />------------<br /><a href='#I1' class='bbc_url' title='External link' rel='nofollow external'>I1.&nbsp;&nbsp;Important note relating to OpenGL and this document</a><br /><a href='#I2' class='bbc_url' title='External link' rel='nofollow external'>I2.&nbsp;&nbsp;Important note with respect to normalized inputs</a><br /><br />Questions<br />---------<br /><br />BASICS<br />======<br />&nbsp;<a href='#Q1' class='bbc_url' title='External link' rel='nofollow external'>Q1. What is a matrix?</a><br />&nbsp;<a href='#Q2' class='bbc_url' title='External link' rel='nofollow external'>Q2. What is the order of a matrix?</a><br /><br />&nbsp;<a href='#Q3' class='bbc_url' title='External link' rel='nofollow external'>Q3. How do I represent a matrix using the C/C++ programming languages?</a><br />&nbsp;<a href='#Q4' class='bbc_url' title='External link' rel='nofollow external'>Q4. What are the advantages of using matrices?</a><br />&nbsp;<a href='#Q5' class='bbc_url' title='External link' rel='nofollow external'>Q5. How do matrices relate to coordinate systems?</a><br /><br />ARITHMETIC<br />==========<br />&nbsp;<a href='#Q6' class='bbc_url' title='External link' rel='nofollow external'>Q6. What is the identity matrix?</a><br />&nbsp;<a href='#Q7' class='bbc_url' title='External link' rel='nofollow external'>Q7. What is the major diagonal matrix of a matrix?</a><br /><br />&nbsp;<a href='#Q8' class='bbc_url' title='External link' rel='nofollow external'>Q8. What is the transpose of a matrix?</a><br />&nbsp;<a href='#Q9' class='bbc_url' title='External link' rel='nofollow external'>Q9. How do I add two matrices together?</a><br /><a href='#Q10' class='bbc_url' title='External link' rel='nofollow external'>Q10. How do I subtract two matrices?</a></span><span style='font-family: Courier New'><br /><a href='#Q11' class='bbc_url' title='External link' rel='nofollow external'>Q11. How do I multiply two matrices together?</a><br /><a href='#Q12' class='bbc_url' title='External link' rel='nofollow external'>Q12. How do I square or raise a matrix to a power?</a><br /><a href='#Q13' class='bbc_url' title='External link' rel='nofollow external'>Q13. How do I multiply one or more vectors by a matrix?</a><br /><br />DETERMINANTS AND INVERSES<br />=========================<br /><a href='#Q14' class='bbc_url' title='External link' rel='nofollow external'>Q14. What is the determinant of a matrix?</a><br /><br /><a href='#Q15' class='bbc_url' title='External link' rel='nofollow external'>Q15. How do I calculate the determinant of a matrix?</a><br /><a href='#Q16' class='bbc_url' title='External link' rel='nofollow external'>Q16. What are Isotropic and Anisotropic matrices?</a><br /><a href='#Q17' class='bbc_url' title='External link' rel='nofollow external'>Q17. What is the inverse of a matrix?</a><br /><a href='#Q18' class='bbc_url' title='External link' rel='nofollow external'>Q18. How do I calculate the inverse of an arbitrary matrix?</a><br /><a href='#Q19' class='bbc_url' title='External link' rel='nofollow external'>Q19. How do I calculate the inverse of an identity matrix?</a><br /><a href='#Q20' class='bbc_url' title='External link' rel='nofollow external'>Q20. How do I calculate the inverse of a rotation matrix?</a><br /><a href='#Q21' class='bbc_url' title='External link' rel='nofollow external'>Q21. How do I calculate the inverse of a matrix using Kramer's rule?</a><br /><a href='#Q22' class='bbc_url' title='External link' rel='nofollow external'>Q22. How do I calculate the inverse of a 2x2 matrix?</a><br /><a href='#Q23' class='bbc_url' title='External link' rel='nofollow external'>Q23. How do I calculate the inverse of a 3x3 matrix?</a><br /><br /><a href='#Q24' class='bbc_url' title='External link' rel='nofollow external'>Q24. How do I calculate the inverse of a 4x4 matrix?</a><br /><a href='#Q25' class='bbc_url' title='External link' rel='nofollow external'>Q25. How do I calculate the inverse of a matrix using linear equations?</a><br /><br />TRANSFORMS<br />==========<br /><a href='#Q26' class='bbc_url' title='External link' rel='nofollow external'>Q26. What is a rotation matrix?</a><br /><a href='#Q27' class='bbc_url' title='External link' rel='nofollow external'>Q27. How do rotation matrices relate to coordinate systems?</a><br /><a href='#Q28' class='bbc_url' title='External link' rel='nofollow external'>Q28. How do I generate a rotation matrix in the X-axis?</a><br /><a href='#Q29' class='bbc_url' title='External link' rel='nofollow external'>Q29. How do I generate a rotation matrix in the Y-axis?</a><br /><a href='#Q30' class='bbc_url' title='External link' rel='nofollow external'>Q30. How do I generate a rotation matrix in the Z-axis?</a><br /><a href='#Q31' class='bbc_url' title='External link' rel='nofollow external'>Q31. What are Euler angles?</a><br /><br /><a href='#Q32' class='bbc_url' title='External link' rel='nofollow external'>Q32. What are yaw, roll and pitch?</a><br /><a href='#Q33' class='bbc_url' title='External link' rel='nofollow external'>Q33. How do I combine rotation matrices?</a><br /><a href='#Q34' class='bbc_url' title='External link' rel='nofollow external'>Q34. What is Gimbal Lock?</a><br />Q35. What is the correct way to combine rotation matrices?<br />Q36. How do I generate a rotation matrix from Euler angles?<br />Q37. How do I generate Euler angles from a rotation matrix?<br />Q38. How do I generate a rotation matrix for a selected axis and angle?<br />Q39. How do I generate a rotation matrix to map one vector onto another?<br />Q40. How do I use matrices to convert between two coordinate systems?<br /><br />Q41. What is a translation matrix?<br />Q42. What is a scaling matrix?<br />Q43. What is a shearing matrix?<br />Q44. How do I perform linear interpolation between two matrices?<br />Q45. How do I perform cubic interpolation between four matrices?<br />Q46. How can I render a matrix?<br /><br />QUATERNIONS<br />===========<br />Q47.&nbsp;&nbsp;What are quaternions?<br />Q48.&nbsp;&nbsp;How do quaternions relate to 3D animation?<br /><br />Q49.&nbsp;&nbsp;How do I calculate the conjugate of a quaternion?<br />Q50.&nbsp;&nbsp;How do I calculate the inverse of a quaternion?<br />Q51.&nbsp;&nbsp;How do I calculate the magnitude of a quaternion?<br />Q52.&nbsp;&nbsp;How do I normalise a quaternion?<br />Q53.&nbsp;&nbsp;How do I multiply two quaternions together?<br />Q54.&nbsp;&nbsp;How do I convert a quaternion to a rotation matrix?<br />Q55.&nbsp;&nbsp;How do I convert a rotation matrix to a quaternion?<br />Q56.&nbsp;&nbsp;How do I convert a rotation axis and angle to a quaternion?<br />Q57.&nbsp;&nbsp;How do I convert a quaternion to a rotation axis and angle?<br /><br />Q58.&nbsp;&nbsp;How do I convert spherical rotation angles to a quaternion?<br />Q59.&nbsp;&nbsp;How do I convert a quaternion to spherical rotation angles?<br />Q60.&nbsp;&nbsp;How do I convert Euler rotation angles to a quaternion?<br />Q61.&nbsp;&nbsp;How do I use quaternions to perform linear interpolation between matrices?<br />Q62.&nbsp;&nbsp;How do I use quaternions to perform cubic interpolation between matrices?<br />Q63.&nbsp;&nbsp;How do I use quaternions to rotate a vector?<br /></span><br /><span style='font-family: Courier New'>Introduction<br />------------ <br /><br /><a name='I1'></a>I1. Important note relating to OpenGl and this document<br />-------------------------------------------------------<br />&nbsp;&nbsp;In this document (as in most math textbooks), all matrices are drawn<br />&nbsp;&nbsp;in the standard mathematical manner.&nbsp;&nbsp;Unfortunately graphics libraries<br />&nbsp;&nbsp;like IrisGL, OpenGL and SGI's Performer all represent them with the<br />&nbsp;&nbsp;rows and columns swapped.<br />&nbsp;&nbsp;Hence, in this document you will see (for example) a 4x4 Translation<br />&nbsp;&nbsp;matrix represented as follows:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 1&nbsp;&nbsp;0&nbsp;&nbsp;0&nbsp;&nbsp;X |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 0&nbsp;&nbsp;1&nbsp;&nbsp;0&nbsp;&nbsp;Y |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;M = |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 0&nbsp;&nbsp;0&nbsp;&nbsp;1&nbsp;&nbsp;Z |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 0&nbsp;&nbsp;0&nbsp;&nbsp;0&nbsp;&nbsp;1 |<br /><br />&nbsp;&nbsp;In Performer (for example) this would be populated as follows:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;M[0][1] = M[0][2] = M[0][3] =<br />&nbsp;&nbsp;&nbsp;&nbsp;M[1][0] = M[1][2] = M[1][3] =<br />&nbsp;&nbsp;&nbsp;&nbsp;M[2][0] = M[2][1] = M[2][3] = 0 ;<br />&nbsp;&nbsp;&nbsp;&nbsp;M[0][0] = M[1][1] = M[2][2] = m[3][3] = 1 ;<br />&nbsp;&nbsp;&nbsp;&nbsp;M[3][0] = X ;<br />&nbsp;&nbsp;&nbsp;&nbsp;M[3][1] = Y ;<br />&nbsp;&nbsp;&nbsp;&nbsp;M[3][2] = Z ;<br /><br />&nbsp;&nbsp;ie, the matrix is stored like this:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| M[0][0]&nbsp;&nbsp;M[1][0]&nbsp;&nbsp;M[2][0]&nbsp;&nbsp;M[3][0] |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| M[0][1]&nbsp;&nbsp;M[1][1]&nbsp;&nbsp;M[2][1]&nbsp;&nbsp;M[3][1] |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;M = |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| M[0][2]&nbsp;&nbsp;M[1][2]&nbsp;&nbsp;M[2][2]&nbsp;&nbsp;M[3][2] |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| M[0][3]&nbsp;&nbsp;M[1][3]&nbsp;&nbsp;M[2][3]&nbsp;&nbsp;M[3][3] |<br /><br />&nbsp;&nbsp;OpenGL uses a one-dimensional array to store matrices - but fortunately,<br />&nbsp;&nbsp;the packing order results in the same layout of bytes in memory - so<br />&nbsp;&nbsp;taking the address of a pfMatrix and casting it to a float* will allow<br />&nbsp;&nbsp;you to pass it directly into routines like glLoadMatrixf.<br />&nbsp;&nbsp;In the code snippets scattered throughout this document, a one-dimensional<br />&nbsp;&nbsp;array is used to store a matrix. The ordering of the array elements is<br />&nbsp;&nbsp;transposed with respect to OpenGL.<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;This Document&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OpenGL<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 0&nbsp;&nbsp;1&nbsp;&nbsp;2&nbsp;&nbsp;3&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 0&nbsp;&nbsp;4&nbsp;&nbsp;8&nbsp;&nbsp;12 |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 4&nbsp;&nbsp;5&nbsp;&nbsp;6&nbsp;&nbsp;7&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 1&nbsp;&nbsp;5&nbsp;&nbsp;9&nbsp;&nbsp;13 |<br />&nbsp;&nbsp;&nbsp;&nbsp;M = |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;M = |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 8&nbsp;&nbsp;9&nbsp;&nbsp;10 11 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 2&nbsp;&nbsp;6&nbsp;&nbsp;10 14 |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 12 13 14 15 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 3&nbsp;&nbsp;7&nbsp;&nbsp;11 15 |<br /><br /><a name='I2'></a>I2. Important note with respect to normalized inputs<br />----------------------------------------------------<br />&nbsp;&nbsp;Note that most algorithms assume normalized inputs, such as vectors of<br />&nbsp;&nbsp;union length, or matrices with normalized main diagonal etc. It is possible,<br />&nbsp;&nbsp;and often enough the case, that algorithms (and the code snippets provided here)<br />&nbsp;&nbsp;work correctly with arbitrary inputs, but it is usually considered bad practise<br />&nbsp;&nbsp;(and you will pay in debugging time if you fail to observe this suggestion) to<br />&nbsp;&nbsp;rely on this property.<br />&nbsp;&nbsp;<br /><br />Answers<br />-------<br /><br />BASICS<br />======<br /><br /><a name='Q1'></a>Q1.&nbsp;&nbsp;What is a matrix?<br />----------------------<br />&nbsp;&nbsp;A matrix is a two dimensional array of numeric data, where each<br />&nbsp;&nbsp;row or column consists of one or more numeric values.<br />&nbsp;&nbsp;Arithmetic operations which can be performed with matrices include<br />&nbsp;&nbsp;addition, subtraction, multiplication and division.<br />&nbsp;&nbsp;The size of a matrix is defined in terms of the number of rows<br />&nbsp;&nbsp;and columns.<br />&nbsp;&nbsp;A matrix with M rows and N columns is defined as a MxN matrix.<br />&nbsp;&nbsp;Individual elements of the matrix are referenced using two index<br />&nbsp;&nbsp;values. Using mathematical notation these are usually assigned the<br />&nbsp;&nbsp;variables 'i' and 'j'. The order is row first, column second<br />&nbsp;&nbsp;For example, if a matrix M with order 4x4 exists, then the elements<br />&nbsp;&nbsp;of the matrix are indexed by the following row:column pairs:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 00 01 02 03 |<br />&nbsp;&nbsp;&nbsp;&nbsp;M = | 10 11 12 13 |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 20 21 22 23 |<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| 30 31 32 33 |<br /><br />&nbsp;&nbsp;The element at the top right of the matrix has i=0 and j=3<br />&nbsp;&nbsp;This is referenced as follows:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;M&nbsp;&nbsp;&nbsp;&nbsp;= M<br />&nbsp;&nbsp;&nbsp;&nbsp; i,j&nbsp;&nbsp;&nbsp;&nbsp;0,3<br /><br />&nbsp;&nbsp;In computer animation, the most commonly used matrices have either<br />&nbsp;&nbsp;2, 3 or 4 rows and columns. These are referred to as 2x2, 3x3 and 4x4<br />&nbsp;&nbsp;matrices respectively.<br />&nbsp;&nbsp;2x2 matrices are used to perform rotations, shears and other types<br />&nbsp;&nbsp;of image processing. General purpose NxN matrices can be used to<br />&nbsp;&nbsp;perform image processing functions such as convolution.<br />&nbsp;&nbsp;3x3 matrices are used to perform low-budget 3D animation. Operations<br />&nbsp;&nbsp;such as rotation and multiplication can be performed using matrix<br />&nbsp;&nbsp;operations, but perspective depth projection is performed using<br />&nbsp;&nbsp;standard optimised into pure divide operations.<br />&nbsp;&nbsp;4x4 matrices are used to perform high-end 3D animation. Operations<br />&nbsp;&nbsp;such as multiplication and perspective depth projection can be<br />&nbsp;&nbsp;performed using matrix mathematics.<br />&nbsp;&nbsp;<br /><a name='Q2'></a>Q2.&nbsp;&nbsp;What is the "order" of a matrix?<br />-------------------------------------<br />&nbsp;&nbsp;The "order" of a matrix is another name for the size of the matrix.<br />&nbsp;&nbsp;A matrix with M rows and N columns is said to have order MxN.<br />&nbsp;&nbsp;<br /><a name='Q3'></a>Q3.&nbsp;&nbsp;How do I represent a matrix using the C/C++ programming languages?<br />-----------------------------------------------------------------------<br />&nbsp;&nbsp;The simplest way of defining a matrix using the C/C++ programming<br />&nbsp;&nbsp;languages is to make use of the "typedef" keyword. Both 3x3 and 4x4<br />&nbsp;&nbsp;matrices may be defined in this way ie:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;typedef float MATRIX3[9];<br />&nbsp;&nbsp;&nbsp;&nbsp;typedef float MATRIX4[16];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;Since each type of matrix has dimensions 3x3 and 4x4, this requires<br />&nbsp;&nbsp;9 and 16 data elements respectively.<br />&nbsp;&nbsp;At first glance, the use of a single linear array of data values may<br />&nbsp;&nbsp;seem counter-intuitive. The use of two dimensional arrays may seem<br />&nbsp;&nbsp;more convenient ie.<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;typedef float MATRIX3[3][3];<br />&nbsp;&nbsp;&nbsp;&nbsp;typedef float MATRIX4[4][4];<br /><br />&nbsp;&nbsp;However, the use of two reference systems for each matrix element<br />&nbsp;&nbsp;very often leads to confusion. With mathemetics, the order is row<br />&nbsp;&nbsp;first (i), column second (j) ie.<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; Mij<br /><br />&nbsp;&nbsp;Using C/C++, this becomes<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; matrix[j][i]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; Using two dimensional arrays also incurs a CPU performance penalty in<br />&nbsp;&nbsp;that C compilers will often make use of multiplication operations to<br />&nbsp;&nbsp;resolve array index operations.<br />&nbsp;&nbsp;So, it is more efficient to stick with linear arrays. However, one issue<br />&nbsp;&nbsp;still remains to be resolved. How is an two dimensional matrix mapped<br />&nbsp;&nbsp;onto a linear array? Since there are only two methods (row first/column<br />&nbsp;&nbsp;second or column first/row column).<br />&nbsp;&nbsp;The performance differences between the two are subtle. If all for-next<br />&nbsp;&nbsp;loops are unravelled, then there is very little difference in the<br />&nbsp;&nbsp;performance for operations such as matrix-matrix multiplication.<br />&nbsp;&nbsp;Using the C/C++ programming languages the linear ordering of each<br />&nbsp;&nbsp;matrix is as follows:<br /><br />&nbsp;&nbsp;mat[0][nbsp][nbsp]= M[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]mat[3][nbsp][nbsp]= M<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] 00[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] 03<br />[nbsp][nbsp]mat[12] = M[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]mat[15] = M<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] 30[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] 33<br /><br />	|[nbsp][nbsp]0[nbsp][nbsp]1[nbsp][nbsp]2[nbsp][nbsp]3 |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]|[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] |[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| 0 1 2 |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]|[nbsp][nbsp]4[nbsp][nbsp]5[nbsp][nbsp]6[nbsp][nbsp]7 |[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]|[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] |<br />[nbsp][nbsp][nbsp][nbsp]M = |[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] |[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]M = | 3 4 5 |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]|[nbsp][nbsp]8[nbsp][nbsp]9 10 11 |[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]|[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]|[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] |[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| 6 7 8 |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| 12 13 14 15 |<br /><br /><a name='Q4'></a>Q4.[nbsp][nbsp]What are the advantages of using matrices?<br />-----------------------------------------------<br />[nbsp][nbsp]One of the first questions asked about the use of matrices in computer<br />[nbsp][nbsp]animation is why they should be used at all in the first place.<br />[nbsp][nbsp]Intuitively, it would appear that the overhead of for-next loops and<br />[nbsp][nbsp]matrix multiplication would slow down an application.<br />[nbsp][nbsp]Arguments that resolve these objections can be pointed out. These include<br />[nbsp][nbsp]the use of CPU registers to handle loop counters on-board data caches<br />[nbsp][nbsp]to optimise memory accesses.<br />[nbsp][nbsp]Advantages can also be pointed out. By following a mathematical approach<br />[nbsp][nbsp]to defining 3D algorithms, it is possible to predict and plan the<br />[nbsp][nbsp]design of a 3D animation system. Such mathematical approaches allow<br />[nbsp][nbsp]for the implementation of character animation, spline curves and inverse<br />[nbsp][nbsp]kinematics.<br />[nbsp][nbsp]However, one objection that frequently comes up is that it would be<br />[nbsp][nbsp]quicker to just multiply each pair of coordinates by the rotation<br />[nbsp][nbsp]coefficients for that axis, rather than perform a full vector-matrix<br />[nbsp][nbsp]multiplication.<br />[nbsp][nbsp]ie. Rotation in X transforms Y and Z<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]Rotation in Y transforms X and Z<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]Rotation in Z transforms X and Y<br />[nbsp][nbsp]The argument to this goes as follows:<br />[nbsp][nbsp]Given a vertex V = (x,y,z), rotation angles (A,B and C) and translation<br />[nbsp][nbsp](D,E,F). A[nbsp][nbsp]the algorithm<br />[nbsp][nbsp]is defined as follows:<br />[nbsp][nbsp][nbsp][nbsp]---------------------------<br />[nbsp][nbsp][nbsp][nbsp]sx = sin(A)[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] // Setup - only done once<br />[nbsp][nbsp][nbsp][nbsp]cx = cos(A)<br />[nbsp][nbsp][nbsp][nbsp]sy = sin(B)<br />[nbsp][nbsp][nbsp][nbsp]cy = cos(B)<br />[nbsp][nbsp][nbsp][nbsp]sz = sin&copy;<br />[nbsp][nbsp][nbsp][nbsp]cz = cos&copy;<br />[nbsp][nbsp][nbsp][nbsp]x1 =[nbsp][nbsp]x * cz +[nbsp][nbsp]y * sz[nbsp][nbsp]// Rotation of each vertex<br />[nbsp][nbsp][nbsp][nbsp]y1 =[nbsp][nbsp]y * cz -[nbsp][nbsp]x * sz<br />[nbsp][nbsp][nbsp][nbsp]z1 =[nbsp][nbsp]z<br />[nbsp][nbsp][nbsp][nbsp]x2 = x1 * cy + z1 * sy<br />[nbsp][nbsp][nbsp][nbsp]y2 = z1<br />[nbsp][nbsp][nbsp][nbsp]z2 = z1 * cy - x1 * sy<br />[nbsp][nbsp][nbsp][nbsp]x3 = x2<br />[nbsp][nbsp][nbsp][nbsp]y3 = y2 * cx + z1 * sx<br />[nbsp][nbsp][nbsp][nbsp]z3 = z2 * cx - x1 * sx<br />[nbsp][nbsp][nbsp][nbsp]xr = x3 + D[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] // Translation of each vertex<br />[nbsp][nbsp][nbsp][nbsp]yr = y3 + E<br />[nbsp][nbsp][nbsp][nbsp]zr = z3 + F<br />[nbsp][nbsp][nbsp][nbsp]---------------------------<br />[nbsp][nbsp]Altogether, this algorithm will use the following amounts of processing<br />[nbsp][nbsp]time:<br />[nbsp][nbsp][nbsp][nbsp]Set-up[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] Per-vertex<br />[nbsp][nbsp][nbsp][nbsp]-------------------------[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]------------------------<br />[nbsp][nbsp][nbsp][nbsp]6 trigonometric functions<br />[nbsp][nbsp][nbsp][nbsp]6 assignment operations.[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] 12 assignment<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] 12 multiplication<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]9 addition<br />[nbsp][nbsp][nbsp][nbsp]-------------------------[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]------------------------<br />[nbsp][nbsp]Assume that the same operations is being performed using matrix<br />[nbsp][nbsp]multiplication.<br />[nbsp][nbsp]With a 4x4 matrix, the procesing time is used as follows:<br />[nbsp][nbsp][nbsp][nbsp]Set-up[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] Change[nbsp][nbsp][nbsp][nbsp]Per-vertex[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] Change<br />[nbsp][nbsp][nbsp][nbsp]--------------------------[nbsp][nbsp] ------[nbsp][nbsp][nbsp][nbsp]------------------------ ------<br />[nbsp][nbsp][nbsp][nbsp]6[nbsp][nbsp]trigonometric functions[nbsp][nbsp][nbsp][nbsp]0[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]0<br />[nbsp][nbsp][nbsp][nbsp]18 assignment operation[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]-12[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]3[nbsp][nbsp]assignment[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] -9<br />[nbsp][nbsp][nbsp][nbsp]12 multiplication[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]+12[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]9[nbsp][nbsp]multiplication[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] -3<br />[nbsp][nbsp][nbsp][nbsp]6[nbsp][nbsp]subtraction[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] +6[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] 6[nbsp][nbsp]addition[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp] -3<br />[nbsp][nbsp][nbsp][nbsp]--------------------------[nbsp][nbsp] ------[nbsp][nbsp][nbsp][nbsp]------------------------ ------<br />[nbsp][nbsp]Comparing the two tables, it can be seen that setting up a rotation<br />[nbsp][nbsp]matrix costs at least 12 multiplication calculations and an extra<br />[nbsp][nbsp]18 assignment calls.<br />[nbsp][nbsp]However, while this may seem extravagant, the savings come from<br />[nbsp][nbsp]processing each vertex. Using matrix multiplication, the savings made<br />[nbsp][nbsp]from processing just 4 vertices, will outweigh the additional set-up<br />[nbsp][nbsp]cost.<br />[nbsp][nbsp]<br /><a name='Q5'></a>Q5.[nbsp][nbsp]How do matrices relate to coordinate systems?<br />--------------------------------------------------<br />[nbsp][nbsp]With either 3x3 or 4x4 rotation, translation or shearing matrices, there<br />[nbsp][nbsp]is a simple relationship between each matrix and the resulting coordinate<br />[nbsp][nbsp]system.<br />[nbsp][nbsp]The first three columns of the matrix define the direction vector of the<br />[nbsp][nbsp]X, Y and Z axii respectively.<br />[nbsp][nbsp]If a 4x4 matrix is defined as:<br /><br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| A B C D |<br />[nbsp][nbsp][nbsp][nbsp]M = | E F G H |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| I J K L |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| M N O P |<br /><br />[nbsp][nbsp]Then the direction vector for each axis is as follows:<br /><br />[nbsp][nbsp][nbsp][nbsp] X-axis = [ A E I ]<br />[nbsp][nbsp][nbsp][nbsp] Y-axis = [ B F J ]<br />[nbsp][nbsp][nbsp][nbsp] Z-axis = [ C G K ]<br />[nbsp][nbsp][nbsp][nbsp] <br />ARITHMETIC<br />==========<br /><br /><a name='Q6'></a>Q6.[nbsp][nbsp]What is the identity matrix?<br />---------------------------------<br />[nbsp][nbsp]The identity matrix is matrix in which has an identical number of rows<br />[nbsp][nbsp]and columns. Also, all the elements in which i=j are set one. All others<br />[nbsp][nbsp]are set to zero. For example a 4x4 identity matrix is as follows:<br /><br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| 1 0 0 0 |<br />[nbsp][nbsp][nbsp][nbsp]M = | 0 1 0 0 |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| 0 0 1 0 |<br />[nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp][nbsp]| 0 0 0 1 |<br /><br /><a name='Q7'></a>Q7.[nbsp][nbsp]What is the major diagonal of a matrix?<br />--------------------------------------------<br />[nbsp][nbsp]The major diagonal of a matrix is the set of elements where the<br />[nbsp][nbsp]row number is equal to the column number ie.<br /><br />[nbsp][nbsp][nbsp][nbsp]M[nbsp][nbsp] where i=j<br />[nbsp][nbsp][nbsp][nbsp] ij<br /><br />[nbsp][nbsp]In the case of the identity matrix, only the elements on the major<br />[nbsp][nbsp]diagonal are set to 1, while all others are set to 0.<br />[nbsp][nbsp]<br /></span>]]></description>
		<pubDate>Mon, 11 Feb 2002 11:46:49 +0000</pubDate>
		<guid isPermaLink="false">cc823b8f1c307b292c42b8d70c7a1714</guid>
	</item>
	<item>
		<title>The Physics of Racing, Part 18:</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/the-physics-of-racing-part-18-r1627</link>
		<description>Download the article PDF via the attached resource file</description>
		<pubDate>Mon, 07 Jan 2002 15:28:22 +0000</pubDate>
		<guid isPermaLink="false">c28180798c5c9bc681b3b23b2b4ce398</guid>
	</item>
	<item>
		<title>The Physics of Racing, Part 17:</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/the-physics-of-racing-part-17-r1626</link>
		<description>Download the article PDF via the attached resource file</description>
		<pubDate>Mon, 07 Jan 2002 15:26:58 +0000</pubDate>
		<guid isPermaLink="false">e27c71957d1e6c223e0d48a165da2ee1</guid>
	</item>
	<item>
		<title>The Physics of Racing, Part 16: RARS, A Simple Racing Simulator</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/the-physics-of-racing-part-16-rars-a-simple-r1625</link>
		<description>Download the article PDF via the attached resource file</description>
		<pubDate>Mon, 07 Jan 2002 15:24:43 +0000</pubDate>
		<guid isPermaLink="false">cb2653f548f8709598e8b5156738cc51</guid>
	</item>
	<item>
		<title>The Physics of Racing, Part 15: Bumps In The Road</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/the-physics-of-racing-part-15-bumps-in-the-road-r1624</link>
		<description>Download the PDF article via the attached resource file</description>
		<pubDate>Mon, 07 Jan 2002 15:24:27 +0000</pubDate>
		<guid isPermaLink="false">e1c1c18c55ad8fad38e352a95bf4192e</guid>
	</item>
	<item>
		<title>The Physics of Racing, Part 14: Why Smoothness?</title>
		<link>http://www.gamedev.net/page/resources/_/technical/math-and-physics/the-physics-of-racing-part-14-why-smoothness-r1623</link>
		<description>Download the PDF of this article via the attached resource file</description>
		<pubDate>Mon, 07 Jan 2002 15:24:04 +0000</pubDate>
		<guid isPermaLink="false">4abe8aa8f6fad818f0a9e15f657d75e9</guid>
	</item>
</channel>
</rss>