Wednesday, January 29, 2014

Mathematics behind rotation part 3

Back to Part 2

In this final part I will show how you can use the last two parts of the tutorial in code for XNA. First we'll look at the Draw command from XNA's SpriteBatch and to conclude this series a little abstraction to rotating 3D models.

XNA is a very powerful game-development tool, and it surprisingly easy to use for rotations. If we want to draw the green square from part 1 in the Draw function from XNA, the code would look like this:
// The standard Draw method
Texture2D square; // Your square texture
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{            
    Vector2 position = Vector2.Zero;
    Vector2 origin = new Vector2(square.Width / 2, square.Height / 2);
    float rotation = (float)Math.PI / 4;
    float scale = 1.0f;
    float depth = 0.0f;
    spriteBatch.Draw(square, position, null, Color.White, rotation, origin, scale, SpriteEffects.None, depth);
}

This special overload for the Draw function allows us to rotate the sprite with a certain amount. It takes a radian as input, represented in a float value of $\frac{\pi}{4}$ which equals 45 degrees. I'm not going throught the rest of the arguments you have to fill in as most of them are quite obvious and is out of scope for this tutorial. All of the theory that I've explained about rotations is well hidden in the code of XNA itself. You only have to define an origin and then draw the texture in this special overload of the Draw.

For creating rotations in 3D you will have to use rotation matrices. You can use them to rotate in 2D as well if you use the rotation over the Z-axis of course. To define a rotation matrix you can use the following code:
Vector3 position = Vector3.Zero;
float angle = (float)Math.PI / 4;
Matrix rotationX = Matrix.CreateRotationX(angle);
Matrix rotationY = Matrix.CreateRotationY(angle);
Matrix rotationZ = Matrix.CreateRotationZ(angle);
position = Vector3.Transform(position, rotationZ)

This will create a rotation over the Z-asix for our defined position here. I've also included the X and Y matrices, just for example. These matrices are in fact the matrices we've talked about in the last part. Note here that Vector3.Transform() does not apply any "magic" behind the scenes, it only rotates around the origin. An example to demonstrate this:



The green circle here represents only a rotation applied to an object. If, however, you first chose to do a translation on the object (the red arrow) and then apply a rotation, it will still rotate around the origin, being the center of the axis here. So my tip (and warning) here is to apply the rotations first and then apply other matrix operations. This will make the model rotate on the spot and then translate to the position, which is hopefully the result you wanted :).

This is it for this tutorial series on rotations, I hope you learned something from all of this and definitely hope to see you back for my next blog entry! If you have any questions, you can leave a comment below.

Sunday, January 26, 2014

Mathematics behind rotation part 2

Back to Part 1

In this part I will show how to define a matrix for the rotation. Once we have seen all this in 2D we can rather easily transfer this knowledge, and create a 3D rotation. If you don’t know what a matrix is, you can always look it up on Wikipedia, even though you can understand this tutorial with pretty basic knowledge about matrices!

Continuing from the last part, we’ll have a look at rotation the green square again. Let's first focus on a matrix to rotate our square with a certain amount of degrees denoted by $\theta$. We'll take each point on the square as a vector in 2D. For rotating by an arbitrary degree we can use the following formulas for the x and y:

$x'=x\cdot \cos\theta -y\cdot \sin\theta$

$y'=x\cdot \sin\theta +y\cdot \cos\theta$

This would rotate a vector, initially aligned with the x-axis, $\theta$ degrees counterclockwise. To get our output results x' and y' we have to apply a rotation matrix on the vector. By taking the above formulas we can setup the required matrix to rotate counterclockwise rather easily:

$\begin{pmatrix}x'\\y'\end{pmatrix}=\begin{pmatrix}cos\theta&-sin\theta\\sin\theta&cos\theta\end{pmatrix}\begin{pmatrix}x\\y\end{pmatrix}$

To see this in action, I will provide an example by rotating 90 degrees counterclockwise. Taking the cosine of 90 degrees, or rather, $\frac{\pi}{2}$ radians is equal to 0. And the sine of 90 degrees is equal to 1. This leaves us with a rather easy to use Matrix:

$R(\frac{\pi}{2})=\begin{pmatrix}0&-1\\1&0\end{pmatrix}$

For example, filling in the vector (4, 1) would produce the following result:

$\begin{pmatrix}-1\\4\end{pmatrix}=\begin{pmatrix}0&-1\\1&0\end{pmatrix}\begin{pmatrix}4\\1\end{pmatrix}$

Now we got this all sorted out in 2D let's make a quick stop at creating the same rotation in 3D. We got a brand new vector in 3D with an x, y and z coordinate. To rotate this vector we have to specify around which axis we want to rotate. We will fill in nearly the same matrix as for 2D rotations, only now for the axis we are rotating on. For the other axis we just leave the matrix blank except the multiplier for the coordinate itself, which we want to multiply by 1. A little mindboggle to explain the previous 2D rotation: If you imagine the rotation in 2D, its actually rotating around the (invisible) Z-axis in 3D. If you see that, you will see the next matrices for 3D rotations are no different at all.

$R_{x}=\begin{pmatrix}1&0&0\\0&\cos\theta&\sin\theta\\0&\sin\theta&\cos\theta\end{pmatrix}R_{y}=\begin{pmatrix}\cos\theta&0&\sin\theta\\0&1&0\\\sin\theta&0&\cos\theta\end{pmatrix}R_{z}=\begin{pmatrix}\cos\theta&\sin\theta&0\\\sin\theta&\cos\theta&0\\0&0&1\end{pmatrix}$

If you would fill in our test vector of (4, 1, 0) and rotate it over the Z-axis you would get the same result as before. The only difference is an extra coordinate.

This is all you need to know about matrix rotations to create a nice rotation in 3D. In the next part I will show some code samples on how all of these matrices are predefined in Microsoft's XNA, and how you can use them with the theory from part 1.

Continue to part 3

Thursday, January 23, 2014

Mathematics behind rotation Part 1


This will be a tutorial series on rotating sprites and 3D models. The first part will take you through the mindset of rotation and explain in theory how rotations work. The second part is the more mathematical part about rotation using matrices and applying this for 3D rotations.

This short part of the tutorial will be on rotating sprites. First I will explain about rotation in general, define ‘good’ and ‘bad’ rotations, and after that I will continue by pointing out how we can define this in the ‘digital world’ as I will call it from now on.

Lets start with the basics behind rotation in 2D. Say you have a nice image you wish to rotate shown here as the green square. If you want to rotate it by 45 degrees, you will want to expect the yellow square here. For some of you this will be perfectly normal, and it should be. However, usually when you rotate an image in your code and look at what happens, we see the red squares appear when rotating 90 or 225 degrees. How does this happen, and more importantly how do we fix this?



Going back to the digital world, we have some other sense of logic. It will all make complete sense in a moment but bear with me. An image is usually represented as a 2 dimensional array of information, starting at [0,0] and ending at [X,Y] with X as width and Y as height of your image. So the least you know about your image is it starts at [0, 0], right? Thats exactly why this ‘bad’ rotation from green to the red squares happens. I marked the top left corner of the image with a blue dot, this is the position [0,0] of your image. As you'll see this blue dot will stay pretty much on the axis I’ve drawn. So, if you would just say to your compiler:
"rotate my image 90 degrees!" Your compiler would just say: "okay, I will rotate it around the origin for you, you have not specified anything so I will assume your origin is centered at [0, 0]!" Hence the result shown in the image above shows up.

So how do we fix this? We want to get the result shown as the yellow square above. To realise this we have to rotate the image around its own axis. Shown in the image is the center of the green square with a black dot. What we want to do here is set the axis for the rotation on this point. So basically you just put a hinge in the center of the square and rotate it around that. Now to represent this in the digital world, lets go back to the origin of your image: [0, 0]. We want this origin to be the center of the green square.



For the complete rotation to work you will have to move the square so that the center of the image is positioned at the axis, shown here in the image above. Once you have done this you can rotate your image freely without consequences. At the end don’t forget to return it to its original position!

This was it for part 1 of this tutorial. In the next part we will continue on doing this correct rotation by using matrices and then applying it on 3D models.

Continue to part 2