Blogs - Tags - collision urn:lsid:ibm.com:blogs:entries22014-06-24T14:44:53-04:00IBM Connections - Blogsurn:lsid:ibm.com:blogs:entry-8e7a1620-8421-46c0-bb0d-6408ab093174Underlying Mechanics: Collision DetectionNicholasIbarluzea270005QS76activeComment EntriesLikes2012-10-31T09:07:37-04:002012-10-31T09:14:27-04:00
<div>During our initial brainstorming sessions we acknowledged the need to
spend some time exploring the physics-related aspects of the game.
However, looking back, I think it's fair to say that we underestimated
the complexity of the required computations. Naively thinking that our
faint recollection of various formulas from old physics classes would
suffice, we charged forward and planned to tackle all physics-related
requirements as they arose. This resulted in quite a few learning
experiences and code refactoring sessions as the overall complexity
gradually rose over time. In the end we decided to integrate a robust,
third party physics engine into the game. But before arriving at this
final conclusion we implemented a number of our own home-brewed
solutions.</div><div> </div><div>In this post I will describe our original method for collision
detection (such as between two cars). Although we are now using a
powerful physics engine to handle much of this work for us, the engine
itself also uses this method (among others) underneath the hood. My
intention is to perhaps offer some guidance to anyone wishing to
implement their own game physics or to just give a quick look at some of
the inner-workings of what you see in the game.</div><div> </div><div><hr size="2" width="100%" /></div><div> </div><div>At the core of our method of collision detection is the Separating Axis Theorem (<a href="http://en.wikipedia.org/wiki/Hyperplane_separation_theorem">Wikipedia link</a>).
The theorem simply states that if two convex objects are not
intersecting, then there exists an axis for which the projections of the
two objects do not overlap. Note that if you wish to test a concave
object you must first break it down to multiple convex objects and
individually test each one. SAT is an efficient, generic algorithm for
detecting overlap between two entities and its ability to execute
relatively quickly makes it often ideal for collision detection in
games.</div><div> </div><div>To picture this concept of "overlapping projections", take a look at the image below. In diagram <b>a</b>
you see two squares which are clearly not intersecting. If you were to
project their respective images onto the horizontal axis as pictured,
their projections would not intersect either. As soon as you have found
an axis in which these projections do not overlap, you can assert that
the objects do not intersect. Conversely, the two squares are clearly
intersecting in diagram <b>b</b>. For every possible axis, the
projections of the two objects will also overlap, allowing you to assert
that the objects themselves are overlapping. For any two polygons, the
only axes you must test against are the normals of each edge. To obtain
the normal of a vector you simply swap the coordinates and negate one
(ie. [5,3] becomes [-3,5]).<br /></div><div><a href="https://www.ibm.com/developerworks/mydeveloperworks/blogs/DevGame/resource/BLOGS_UPLOADED_IMAGES/diagram.png" target="_blank"><img alt="image" src="https://dw1.s81c.com/developerworks/mydeveloperworks/blogs/DevGame/resource/BLOGS_UPLOADED_IMAGES/diagram.png" style=" display:block; margin: 0 auto;text-align: center; position:relative;" /></a>Unlike
the previous image, objects being tested for collision won't usually be
simple, un-rotated squares. You might be dealing with a complex polygon
with many vertices. You may be wondering then, what the best way to
programatically project these polygons onto an axis is. The answer,
luckily, isn't very difficult. You would simply loop over all of a
polygon's vertices, perform a <a href="http://en.wikipedia.org/wiki/Dot_product">dot product</a>
between the vertex and the normalized axis to be projected on, and
store the minimum and maximum result. Remember that there is a
difference between a vector's <b>normal</b> and a <b>normalized</b> vector! In simple pseudocode, this would look similar to the following:</div><div> </div><blockquote style="background-color: rgb(211, 211, 211);"><div><font color="#000000">Projection function project {<br /></font></div><div align="left"><font color="#000000"> for (i = 0; i < vertices.length; i++) {</font></div><div><font color="#000000"> dp = axis.dot(vertices[i]);</font></div><div><font color="#000000"> if (dp < min)<br /> min = dp;<br /> else if (dp > max)</font></div><div><font color="#000000"> max = dp ;<br /></font></div><div><font color="#000000"> }</font></div><div><font color="#000000"> return new Projection(min, max);</font></div><div><font color="#000000">}</font><br /></div></blockquote><div> </div><div> We
now know enough to be able to assemble a simple function for
determining whether or not two objects are intersecting. But in our
racing game, we needed more than simply knowing if two cars are
colliding. We also wanted to prevent them from simply driving right over
the top of each other. For this reason it is beneficial to calculate
the Minimum Translation Vector - a vector which tells us the shortest
path to push the two objects apart to keep them from intersecting. Your
final collision detection code might look similar to the following
pseudocode:</div><div> </div><blockquote style="background-color: rgb(211, 211, 211);"><div><font color="#000000" style="background-color: rgb(211, 211, 211);">for (i = 0; i < axes.length; i++) {<br /> Projection p1 = polygon1.project(axes[i]);<br /> Projection p2 = polygon2.project(axes[i]);</font></div><div><font color="#000000"> if (p1 overlaps p2)<br /> overlap = p1.getOverlap(p2);<br /> if (overlap < mtv.getOverlap())<br /></font></div><div><font color="#000000"> mtv = new MTV(axis, overlap);<br /> else</font></div><div><font color="#000000"> // We can assert that the polygons are not intersecting<br />}</font></div><div><font color="#000000">// If we get to this point, we know that all axes are overlapping and the polygons are indeed intersecting </font><br /></div></blockquote><div> </div><div> Don't forget that the array of axes in the above code would have to consist of <i>both</i> objects' axes needing testing.</div><div> <hr size="2" width="100%" /></div><div> </div><div>This
was a very simplistic overview of the algorithm we employed for
collision detection in our beginning stages of development. Before using
it yourself, you would likely want to spend some time making the
algorithm more efficient (such as by not testing parallel axes) and
adding additional functionality to handle curved features or to properly
handle the case in which one object is completely engulfed by the
other.<br /><br />Collision detection is just one facet of our
physics-related computations. Things seem to get exponentially more
complex when you begin to account for resultant forces due to a
collision, cancelling out a car's lateral movement due to traction,
applying the appropriate amount of torque to turn a car just the right
amount, etc. In future blog posts we will discuss our move to the JBox2D
physics engine, how much easier this made our lives, and all the cool
physics stuff we've been able to put into the game.<br /></div>
During our initial brainstorming sessions we acknowledged the need to
spend some time exploring the physics-related aspects of the game.
However, looking back, I think it's fair to say that we underestimated
the complexity of the required computations....002046urn:lsid:ibm.com:blogs:entry-6349e2fb-b124-46a3-9cde-2fb027ef5ae2Underlying Mechanics: Collision DetectionNicholasIbarluzea270005QS76activeComment Entriesapplication/atom+xml;type=entryLikes2012-10-29T11:57:13-04:002012-10-29T11:58:29-04:00
<div>During our initial brainstorming sessions we acknowledged the need to
spend some time exploring the physics-related aspects of the game.
However, looking back, I think it's fair to say that we underestimated
the complexity of the required computations. Naively thinking that our
faint recollection of various formulas from old physics classes would
suffice, we charged forward and planned to tackle all physics-related
requirements as they arose. This resulted in quite a few learning
experiences and code refactoring sessions as the overall complexity
gradually rose over time. In the end we decided to integrate a robust,
third party physics engine into the game. But before arriving at this
final conclusion we implemented a number of our own home-brewed
solutions.</div><div> </div><div>In this post I will describe our original method for collision
detection (such as between two cars). Although we are now using a
powerful physics engine to handle much of this work for us, the engine
itself also uses this method (among others) underneath the hood. My
intention is to perhaps offer some guidance to anyone wishing to
implement their own game physics or to just give a quick look at some of
the inner-workings of what you see in the game.</div><div> </div><div><hr size="2" width="100%" /></div><div> </div><div>At the core of our method of collision detection is the Separating Axis Theorem (<a href="http://en.wikipedia.org/wiki/Hyperplane_separation_theorem">Wikipedia link</a>). The theorem simply states that if two convex objects are not intersecting, then there exists an axis for which the projections of the two objects do not overlap. Note that if you wish to test a concave object you must first break it down to multiple convex objects and individually test each one. SAT is an efficient, generic algorithm for detecting overlap between two entities and its ability to execute relatively quickly makes it often ideal for collision detection in games.</div><div> </div><div>To picture this concept of "overlapping projections", take a look at the image below. In diagram <b>a</b> you see two squares which are clearly not intersecting. If you were to project their respective images onto the horizontal axis as pictured, their projections would not intersect either. As soon as you have found an axis in which these projections do not overlap, you can assert that the objects do not intersect. Conversely, the two squares are clearly intersecting in diagram <b>b</b>. For every possible axis, the projections of the two objects will also overlap, allowing you to assert that the objects themselves are overlapping. For any two polygons, the only axes you must test against are the normals of each edge. To obtain the normal of a vector you simply swap the coordinates and negate one (ie. [5,3] becomes [-3,5]).<br /></div><div><a '="" href="https://www.ibm.com/developerworks/mydeveloperworks/blogs/DevGame/resource/BLOGS_UPLOADED_IMAGES/diagram.png" target="_blank"><img alt="image" src="https://dw1.s81c.com/developerworks/mydeveloperworks/blogs/DevGame/resource/BLOGS_UPLOADED_IMAGES/diagram.png" style=" display:block; margin: 0 auto;text-align: center; position:relative;" /></a>Unlike the previous image, objects being tested for collision won't usually be simple, un-rotated squares. You might be dealing with a complex polygon with many vertices. You may be wondering then, what the best way to programatically project these polygons onto an axis is. The answer, luckily, isn't very difficult. You would simply loop over all of a polygon's vertices, perform a <a href="http://en.wikipedia.org/wiki/Dot_product">dot product</a> between the vertex and the normalized axis to be projected on, and store the minimum and maximum result. Remember that there is a difference between a vector's <b>normal</b> and a <b>normalized</b> vector! In simple pseudocode, this would look similar to the following:</div><div> </div><blockquote style="background-color: rgb(211, 211, 211);"><div><font color="#000000">Projection function project {<br /></font></div><div align="left"><font color="#000000"> for (i = 0; i < vertices.length; i++) {</font></div><div><font color="#000000"> dp = axis.dot(vertices[i]);</font></div><div><font color="#000000"> if (dp < min)<br /> min = dp;<br /> else if (dp > max)</font></div><div><font color="#000000"> max = dp ;<br /></font></div><div><font color="#000000"> }</font></div><div><font color="#000000"> return new Projection(min, max);</font></div><div><font color="#000000">}</font><br /></div></blockquote><div> </div><div> We now know enough to be able to assemble a simple function for determining whether or not two objects are intersecting. But in our racing game, we needed more than simply knowing if two cars are colliding. We also wanted to prevent them from simply driving right over the top of each other. For this reason it is beneficial to calculate the Minimum Translation Vector - a vector which tells us the shortest path to push the two objects apart to keep them from intersecting. Your final collision detection code might look similar to the following pseudocode:</div><div> </div><blockquote style="background-color: rgb(211, 211, 211);"><div><font color="#000000" style="background-color: rgb(211, 211, 211);">for (i = 0; i < axes.length; i++) {<br /> Projection p1 = polygon1.project(axes[i]);<br /> Projection p2 = polygon2.project(axes[i]);</font></div><div><font color="#000000"> if (p1 overlaps p2)<br /> overlap = p1.getOverlap(p2);<br /> if (overlap < mtv.getOverlap())<br /></font></div><div><font color="#000000"> mtv = new MTV(axis, overlap);<br /> else</font></div><div><font color="#000000"> // We can assert that the polygons are not intersecting<br />}</font></div><div><font color="#000000">// If we get to this point, we know that all axes are overlapping and the polygons are indeed intersecting </font><br /></div></blockquote><div> </div><div> Don't forget that the array of axes in the above code would have to consist of <i>both</i> objects' axes needing testing.</div><div> <hr size="2" width="100%" /></div><div> </div><div>This was a very simplistic overview of the algorithm we employed for collision detection in our beginning stages of development. Before using it yourself, you would likely want to spend some time making the algorithm more efficient (such as by not testing parallel axes) and adding additional functionality to handle curved features or to properly handle the case in which one object is completely engulfed by the other.<br /><br />Collision detection is just one facet of our physics-related computations. Things seem to get exponentially more complex when you begin to account for resultant forces due to a collision, cancelling out a car's lateral movement due to traction, applying the appropriate amount of torque to turn a car just the right amount, etc. In future blog posts we will discuss our move to the JBox2D physics engine, how much easier this made our lives, and all the cool physics stuff we've been able to put into the game.<br /></div>
During our initial brainstorming sessions we acknowledged the need to
spend some time exploring the physics-related aspects of the game.
However, looking back, I think it's fair to say that we underestimated
the complexity of the required computations....10674