

Rotations and translations 
This chapter we;ll make our triangle spin around. Since we are using world space coordinates, this is very easy to do. Let's first add a variable 'angle' to our class to store the current rotation angle. Just add this one to your variables.
private float angle = 0f;
Now, we should increase this variable with 0.05f every frame. The Update method is an excellent place to put this code, as it is called 60 times each second:
angle += 0.005f;
With our angle increasing automatically, all we have to do is to rotate the world coordinates. I hope you remember from your math class this is done using transformation matrices ;) Luckily, all you have to do is specify the rotation axis and the rotation angle. All the rest is done by XNA!
The rotation is stored in what is called the World matrix. In your Draw method, replace the line where you set your xWorld parameter with this code:
Matrix worldMatrix = Matrix.CreateRotationY(3 * angle); effect.Parameters["xWorld"].SetValue(worldMatrix);
The first line creates our World matrix, which holds a rotation around the Y axis. The second line passes this World matrix to the effect, which it needs to perform its job. From now on, everything we draw will be rotated along the Y axis by the amount currently stored in ‘angle’!
Learn all about World matrices in Recipe 42.
When you run the application, you will see that your triangle is spinning around its (0,0,0) point! This is of course because the Y axis runs through this point, so the (0,0,0) point is the only point of our triangle that remains the same. Now imagine we would like to spin it through the center of the triangle. One possibility is to redefine the triangle so the (0,0,0) would be in the center of our triangle. The better solution would be to first move (=translate) the triangle a bit to the left and down, and then rotate it. To do this, simply first multiply your World matrix with a translation matrix:
Matrix worldMatrix = Matrix.CreateTranslation(20.0f/3.0f, 10.0f / 3.0f, 0) * Matrix.CreateRotationZ(angle);
This will move the triangle so its center point is in our (0,0,0) 3D World origin. Next, our triangle is rotated around this point, along the Z axis, giving us the desired result.
Note the order of transformations. Go ahead and place the translation AFTER the rotation. You will see a triangle rotating around one point, moved to the left and below. This is because in matrix multiplications M1*M2 is NOT the same as M2*M1! All possible combinations of World matrix multiplications are discussed in Recipe 42.
You can easily change the code to make the triangle rotate around the X or Y axis. Remember that one point of our triangle has a Z coordinate of 5, which explains why the triangle won’t seem to rotate symmetrically sometimes.
A bit more complex is the Matrix CreateFromAxisAngle, where you can specify your own custom rotation axis :
Vector3 rotAxis = new Vector3(3*angle, angle, 2*angle); rotAxis.Normalize(); Matrix worldMatrix = Matrix.CreateTranslation(20.0f/3.0f, 10.0f / 3.0f, 0) * Matrix.CreateFromAxisAngle(rotAxis, angle);
This will make our triangle spin around an ever changing axis. The first line defines this axis (which is changed every frame as it depends on the angle variable). The second line normalizes this axis, which is needed to make the CreateFromAxisAngle method work properly (Normalize() changes the coordinates of the vector, so the distance between the vector and the (0, 0, 0) point is exactly 1).
Click here to go to the forum on this chapter!
Or click on one of the topics on this chapter to go there: worldMatrix not defined I do not understand how this would compile.
I hav...Use gametime in milliseconds in update? so i internally say , ok units is .05 "meters per ...Triangle Keeps Vanishing Hi, I was just trying out the brilliant tutorial. ...Minor translation matrix mistake If you want the center of the triangle to be on (0...Matrix operation order. In the first 2D tutorial I was told that matrix op...error I seem to have a problem with this line of code th...The vector is not everchanging The following lines would always result the same v...exception error help me with this minor problem. why is it the gam...exception error System.InvalidOperationException was unhandled
...Which way does it spin?
In the first example in this chapter, when the t...none effect I know everything is already setted in HLSL effect...Minor type error Hello,
I think there is a minor type error in t...Defitinition of tha rotation axis
Riemer, thanks a lot for this excellent tutorial...The problem about alpha blending HI Riemer! I feel so excitement when i saw this se...
You can try these exercises to practice what you've learned:
Try to rotate your triangle 180 degrees over its bottom edge.
Here's our code:
using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; namespace Series3D1 { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; GraphicsDevice device; Effect effect; VertexPositionColor[] vertices; Matrix viewMatrix; Matrix projectionMatrix;
private float angle = 0f;
public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { graphics.PreferredBackBufferWidth = 500; graphics.PreferredBackBufferHeight = 500; graphics.IsFullScreen = false; graphics.ApplyChanges(); Window.Title = "Riemer's XNA Tutorials  3D Series 1"; base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); device = graphics.GraphicsDevice;
effect = Content.Load<Effect>
("effects"); SetUpCamera();
SetUpVertices(); }
protected override void UnloadContent() { }
private void SetUpVertices() { vertices = new VertexPositionColor[3];
vertices[0].Position = new Vector3(0f, 0f, 0f); vertices[0].Color = Color.Red; vertices[1].Position = new Vector3(10f, 10f, 0f); vertices[1].Color = Color.Yellow; vertices[2].Position = new Vector3(10f, 0f, 5f); vertices[2].Color = Color.Green; }
private void SetUpCamera() { viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 50), new Vector3(0, 0, 0), new Vector3(0, 1, 0)); projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 300.0f); }
protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit();
angle += 0.005f;
base.Update(gameTime); } protected override void Draw(GameTime gameTime) { device.Clear(Color.DarkSlateBlue); RasterizerState rs = new RasterizerState(); rs.CullMode = CullMode.None; device.RasterizerState = rs; effect.CurrentTechnique = effect.Techniques["ColoredNoShading"]; effect.Parameters["xView"].SetValue(viewMatrix); effect.Parameters["xProjection"].SetValue(projectionMatrix);
Vector3 rotAxis = new Vector3(3 * angle, angle, 2 * angle); rotAxis.Normalize(); Matrix worldMatrix = Matrix.CreateTranslation(20.0f / 3.0f, 10.0f / 3.0f, 0) * Matrix.CreateFromAxisAngle(rotAxis, angle); effect.Parameters["xWorld"].SetValue(worldMatrix);
foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, 1, VertexPositionColor.VertexDeclaration); } base.Draw(gameTime); } } }
 Website design & XNA + DirectX code : Riemer Grootjans  ©2003  2011 Riemer Grootjans



