Farseer Physics Engine does not know about its object’s orientation. It has no clue about what is up and what is down. It only needs to know where other objects are in the physics world – nothing else. Sometimes it is good to know what is left, right, top and bottom. In this blog post I will describe a way of determining the side on which an object is hit, no matter the rotation of the object.
Let’s take a simple box as an example:
We can easily determine what is left, right, top and bottom on that box. We do it all the time in the real world. In geometry though, we need to calculate it. Imagine a circle inside the box. This circle is made up of 360 degrees or 2*π in radians. We can now use this circle to find out where the box was hit (left, right, top, bottom) by determining the angle at which the other object hit.
A good reference to how radians are laid out on a circle can be found on Wikipedia.
Now we end up with something like this:
Now we need to determine the intervals of the angle values that makes up the 4 parts.
Right side: π*1.75 to π*2 and 0 to π*0.25
Bottom side: π*0.25 to π*0.75
Left side: π*0.75 to π*1.25
Top side: π*1.25 to π*1.75
But since we are using the Atan2 function that has a range from –π to π, we need a interval that is adjusted to that range:
Right side: –π to (-3*π)/4 and (3*π)/4 to π
Bottom side: (-3*π)/4 to –π
Left side: 0 to π/4 and –π/4 to 0
Top side: π/4 to (3*π)/4
Now that we know the interval of angle values to test against, we need something to test it with. Farseer Physics provide you with the normal of the collisionpoints (called contact). This is a vector pointing directly from the first geometry to the second.
It looks like we can measure the angle of the normal and then see what interval it is within right? Wrong… What if this happens:
Remember, the object is rotated, the intervals are not! If we measured the angle against the intervals now, it would say that the right side of the box is hit, when it is the top that gets hit.
The solution is to rotate either the intervals or the normal. I took the latter of the two. It can all be seen in the sample project below (Based on Farseer Physics Simple Samples for XNA):
(click the folder icon – XNA 3.1 needed to run it)