Home > 3d Programming > Matrix Basics. How to step away from storing an orientation as ‘3 angles’

Matrix Basics. How to step away from storing an orientation as ‘3 angles’

While participating in the XNA forums over the last several years, I often see folks posting questions about how to get their rotations the way they want them. Most of the time they post a code snippet and it shows they are trying to store and manipulate their model’s orientation using ‘3 angles’, typically stored in a Vector3 for convenience. Usually there is much frustration involved. The ‘3 angles’ approach does not lend itself to concatenating (combining) rotations. It is also complex to resolve a rotation around a non-aligned axis in terms of getting the order and proportion correct.

I’ll go out on a limb here and say that eventually, anyone who continues on in XNA (or 3d programming in general) past the rock bottom beginner level, migrates away from this ‘3 angles’ approach. The sooner you give up the ‘3 angle’ approach (AKA Euler Angle Representation), the sooner (I believe) you will be effective as a 3d programmer. Although the ‘3 angles’ representation is a legitimate way of expressing an orientation and I guess there is a time & place for everything, I haven’t found a serious project that uses this method. Maybe there is some out there, but I’ll bet they are rare and unusual enough to deem them not exemplar of game programming anything more complex than beginner projects.

I’ll have to admit the ‘3 angles’ approach is initially intuative and possibly some beginner level tutorials use this approach for that reason. I have an opinion that that is a dis-service to the student since it seems lure them into the realm of 3d programming but in short order directs them right into a brick wall… But what good is expressing an opinion without offering also some possibility of an alternative. So this article is an attempt at offering an alternative. And, happily, no math will be required.

Amongst the other approaches that are out there to represent an orientation, in this article I am going to push the Matrix. I think others are good too but learning about and  using a matrix will facilitate 3d programming knowledge and get you ready to explore other approaches without turning you into any brick walls. Additionally, since you must ultimately pass the model’s orientation onto the shader in matrix form anyway, there is an added minor benefit in not having to convert to a matrix before doing so.

As intuitive as the ‘3 angle’ approach is, the Matrix approach might be that daunting to the beginner. But it doesn’t have to be. I believe that after learning the basics of a matrix and how to visualize a matrix in the mind’s eye while manipulating it, it will be very easy for the beginner to pick up. So for the cost of investing a little time to understand the Matrix, your effectiveness in 3d programming will increase dramatically and you can stop the insanity of banging your head against the ‘3 angles’ brick wall.

So what is a matrix, and how do I go from my understanding of ‘3 angles’ to an understanding and implementation of matrices? I believe the key is in the ability to visualize a matrix as you are coding changes to it. OK, let’s start by showing a sample demo code that utilizes a matrix approach instead of a ‘3 angles’ approach. All the supporting code necessary to render an object has been stripped away just so you could see how the matrix code fits in to a game class.

Class Game1 : Game

{

//Declare a matrix with sufficient scope to access it in the Update & Draw methods

Matrix modelOrientation;

void Initialize()

{

modelOrientation = Matrix.Identity; // initialize the matrix to a starting point

modelOrientation *= Matrix.CreateScale(?);//This is the place to apply scale if necessary

}

void Update()

{

//manipulate the matrix

modelOrientation *= Matrix.CreateFromAxisAngle( someVector, someAngle); 

//manipulate the matrix a second time if necessary

modelOrientation *= Matrix.CreateFromAxisAngle(differentVector, differentAngle);

//manipulate the matrix yet a third time, or as many times as you want

modelOrientation *= Matrix.CreateTranslation(yetAnotherVector);

}

void Draw()

{

effect.World = modelOrientation; // pass the matrix onto the effect for drawing

}

}

So if you implemented this, a model would be rotating and moving depending on what values you place for ‘someVector’, ‘someAngle’, …etc.

A very important thing to understand from the above example is the ease of how movements or rotations can be concatenated to each other (combined to each other). When working with matrices, you can break your movements/rotations down into a series of understandable operations and simply perform them one after another. That was one source of problems with the ‘3 angles’ approach, It was very very difficult to do the following: ” first I want to rotate it a little about this world axis, then a little around that world axis, then that 3rd axis, then that other world axis, etc… The ‘3 angles’ representation does not support that because after the first rotation, one of the subsequent rotations could produce an undesirable result, but the matrix representation does not have that problem. There is no limit to how many rotations you can combine and all rotation axis will work out just like you expect.

One thing to notice is how interchangeable the word “Matrix” is with the word “Model” during this discussion. If we say ‘I am rotating the matrix some angle about some axis’, we may as well say ‘I am rotating the model some angle about some axis’. The end result is identical and the same meaning is conveyed.

I know after seeing the code above you may want to jump right into examples of moving and rotating, like figuring out how to determine what ‘someVector’ and ‘someOtherVector’ should be.  But first I want to go over the basics of what the Matrix is and why it works and what it can do for you. Most importantly, I believe it will be most helpful for you to learn how to visualize a matrix in your mind’s eye. I keep repeating that, don’t I? I must think it’s important.

A Matrix in XNA is made up of 16 numbers, and mathematically, they fit into a 4 row by 4 column structure. Here is a matrix in textual form. It happens to be an Identity matrix:

1    0    0    0          row 1

0    1    0    0          row 2

0    0    1    0          row 3

0    0    0    1          row 4

So the first way you should think of a matrix is simply a group of four vectors. Each row is a like a Vector4 but you can disregard the 4th element of each row for the moment. They’re one of those things that when you get to the point that you need them, you will understand them. The first 3 elements of each row are all you need to understand to manipulate models in 3d space. So think of the first 3 columns as holding the X, Y, & Z components of each row’s vector.  The first 3 rows of the matrix are what sets the model’s orientation/rotation and the 4th row is the one that sets the position of the model.

An identity matrix is a matrix that applies an orientation to the model that has a specific alignment with the world axis (the X, Y, Z). It also places it’s position at the world origin. Generally, it should position and orient the model just as it was in your 3d modeling app. The textual matrix above is an Identity matrix. Here is a graphic of an Identity matrix.

In this graphic, each of the rows becomes a vector. The upper three vectors(rows) are depicted as the colored arrows. Whenever you visualize working with matrices, always try to visualize these three vectors. Not in terms of their X, Y, Z values but in terms of what direction these three vectors are pointing.  On the 1st row, for example, the st value is 1 so that vector’s X component is 1. The 2nd & 3rd values are 0, so the Y & Z components of that vector are 0. that makes a vector3 like this: (1, 0, 0) which point straight down the x axis just like the red vector/arrow in the graphic. One of the nice things about working with matrices is that you rarely need to know the actual numerical values of any of the 16 numbers.

Now, there are a couple things to learn about these vectors. When we use a matrix to represent an orientation or rotation, we always want these three vectors to be 90 degrees to each other. They will not always be aligned with the world axis like they are in this graphic, but they must always be 90 degrees to each other. Also, notice they all have a length of 1. This is important, if one of the three vectors had a length of, say, 2, the model would stretch in that direction when drawn. If all 3 vectors had a length of 2, the model would scale to be twice as long, wide, & tall as the original. That is actually the basis of a scaling transform. But for now, let’s keep visualizing the matrices we work with here as having a length of 1. When the 3 vectors are 90 degrees to each other, they are said to be orthogonal. When a vector has a length of 1, it is said to be normalized. When a matrix’s vectors meet these two criteria, the matrix is said to be orthonormal. If your matrix is not orthonormal, your model will be either skewed, distorted, or scaled. This may or may not be desirable depending on your project.

Another thing to notice on the graphic above is the way all three vectors meet at the world origin. Technically speaking, a vector always emanates from the world origin no matter what so for the life of the matrix, The these three vectors will stay put and simply rotate together around this origin. Here is a short video showing these three vectors rotating together.

Notice all three vectors rotate as if they were one assembly and always stay 90 degrees to each other.

So let’s introduce the 4th row’s vector into this mix. The 4th vector represents the position the model occupies in the game world. Say we added a line of code to add an arbitrary position to this Matrix.

modelOrientation *= Matrix.CreateTranslation(new Vector3(1.25f, 1.25f, -1.0f));

Here is a graphic to represent this:

If we were to draw a model using this matrix, the model would be drawn at the end of the translation vector; like this.

So just remember that the model is always drawn at the end of the translation vector (the 4th row vector). Let’s remove the model for a few moments and show some rotations. In the next video, we are going to place an arbitrary rotation axis vector to use to rotate the matrix around.

Vector3 someArbitraryRotationAxis = new Vector3(-0.8f, 0.8f, -0.4f);

float someArbitraryAngle = MathHelper.ToRadians(83);

modelMatrix *= Matrix.CreateFromAxisAngle(someArbitraryRotationAxis, someArbitraryAngle);

So in this video, the vector ‘someArbitraryRotationAxis’ is depicted by a yellow vector and you will see that ALL 4 vectors of modelMatrix rotate around that axis.

So the rotation angle was about 83 degrees around that arbitrary axis. Aren’t you happy you were able to do that without having to calculate how much should have been around the global X, global Y, & global Z axis and what order to perform the three rotations??  Good… The reason I emphasized the word ‘all 4′ is because often times we want an object to rotate in place rather than orbit the origin and we forget that the position of the model will be affected by rotations.Wanting a model to rotate in place would be like rotating the three Rotation vectors (the ones making the tripod) while keeping the translation vector (the 4th row vector) stationary.  That won’t happen though… all 4 vectors rotate when you apply a rotation to a matrix. But don’t worry, there is a way to make a model rotate in place. We’ll get to how to do that soon. But for now, just know that when a matrix rotates, all 4 vectors rotate and since the translation vector is one of them and is going to rotate, the model will be displaced.

Now I am going to throw you a curve ball. I’m going to do this in the name of ‘improved visualization’ technique. We’re going to move the 3 rotation vectors from the world origin to the end of the translation vector. Like this

This is not technically a correct depiction of reality because all vectors must emanate from the world origin. They can not be just sitting ‘out there’. But as long as we know that and account for that when needed, this viewing style can improve our ability to visualize what we need to do with the matrix while working with it. Consider these two pictures

Both of these pictures have the exact rotation applied to the 4 vectors. They are identical matrices. The only difference is how we are viewing them. The upper one is technically correct but the lower one is more visually helpful. Now, knowing that an aircraft pitches around it’s own lateral axis, which picture makes it more obvious that to pitch the nose of the aircraft up, we would need to rotate it around the matrix’s red vector. Hopefully, you would agree that the lower one makes it more obvious. I always tend to visualize a matrix as my model with the three vectors sticking out of it.

In the next video, I include both view styles to demonstrate that either style produces the same relationship between the model and the 3 rotation vectors. Check this out & pause it at different places to note that the 3 vectors at the origin are always parallel to the 3 vectors at the model.

So you can decide which of those two viewing styles you prefer when you are visualizing your matrices. A purest may want to keep the 3 rotation vectors at the origin, but a practical person may want to think of them as being at the model. Who knows, maybe there are times when you might find it convenient to go either way. No problem there. But for the remainder of this article, we’ll choose the style that places the vectors at the model.

Moving on from that point, there is another thing I want to reiterate from that video. It is important to know that the three vectors never move or rotate relative to the model. The three vectors are always pointing out the top/right/back of the model no matter how the matrix/model rotates. It is as if they are glued together. This is one of the reasons that matrices make it so easy to work with when doing rotations. Often, the rotation desired is one that pitches, rolls, or yaws (or a combination of) around these vectors. To pitch this aircraft up the rotation method would be as simple as:

modelMatrix *= Matrix.CreateFromAxisAngle(modelMatrix.Right, someAngle);

That’s it, absolutely no need to calculate any angles about global axis. This method simply takes that red vector, and rotates the whole matrix around it appropriately. I hope you are starting to see the ease of working with matrices instead of the ‘3 angles’ approach.

So that introduces a new term; ‘modelMatrix.Right‘. What’s this ‘Right‘ thing?  The XNA Matrix has seven properties which are these vectors we’ve been talking about (well, more than just the 4) and are readily available to you at any time. Here is a graphic showing these properties. Notice that the red vector, which is a matrix’s 1st row vector, is called Right. The green vector ( the matrix’s 2nd row), is called Up. The third row vector, the blue one, is called Backward.

The Forward, Left, & Down vectors are simply opposites of the three vectors that make up the matrix. When you access the Forward property, for example, the XNA framework will go to your matrix, grab the Backward Vector, Negate it, and make that the result of the Forward‘s getter. The 7th property is the Translation vector with, as you know by now, represent the world space location of your model.

Every time you apply a rotation or translation to a matrix, it automatically calculates and updates all the changed components that make up these 7 vectors (the X, Y, & Z components). It does this every time a rotation or translation method is called in every frame. This allows you accurate access to any of these vectors at any time. For instance, Let’s say the matrix has an arbitrary orientation to it, you could do a test like this:

If( modelMatrix.Forward.Y > 0.0f )

{

//the model is pointing somewhat upwards (inclined)

}

Now let’s bring the aircraft back in & touch on translating it. Hopefully, you should be able to imagine your model with the six vectors sticking out of it and know that your translation vector is going from the world origin to the model. So if you were told,  say, picture in your mind’s eye a model and it’s matrix in the world at some slight rotation, you should be able to see something like the following graphic in your mind’s eye:

So since this is an aircraft and aircraft generally go forward, let’s talk about how to move this matrix/model forward without rotating it. For now, we’ll just use that Matrix.Forward vector as our direction. We’ll choose a speed to go, and create a velocity vector to move our matrix.

float speed = 0.15f; // or whatever value suits your game

Vector3 velocity = modelMatrix.Forward * speed;

modelMatrix *= Matrix.CreateTranslation(velocity);

So if this was run, every frame the aircraft would go forward 0.15 units. That might look something like this. [Note, you must imagine the translation vector, my 3ds movie making skills are not sufficient to make it animate properly]

One last thing I want to go over before closing this article is the way to rotate a model in place. Remember that when you rotate a matrix, all 4 vectors rotate about whatever axis you are using (including the 4th row translation Vector) which can make the model orbit the axis. To rotate a model in place, you must separate the changes in position from the changes in rotation.  To do that, you must zero out the translation vector before applying any rotations. Look at this code here:

//assume the matrix’s translation vector is representing a position some distance from the origin

Vector3 position = modelMatrix.Translation;

modelMatrix *= Matrix.CreateFromAxisAngle(someAxis, someAngle);

//although the previous line rotated the 4th vector, we don’t care because…

modelMatrix.Translation = position;//we simply reset it to what it was before the rotation

So if you are beginning to visualize what the matrix is doing as you read/write your code, we might not need a video to show what’s happening.  As you read/write the above code, you would see it rotate a little bit around the appropriate axis, then because we noted the exact position that it was at when we started, we move only the translation vector back to where it was. It is now sitting in it’s same spot but rotated to some extent. Do this frame after frame after frame and you have a model spinning in place. So, if you don’t capture the Translation vector before rotating the matrix, then reset the translation vector after the rotation to what it was before, your model will orbit the axis instead of rotate in place.

So the main objective of this article has been to offer someone starting in XNA programming an introductory visualization technique to effectively work with matrices and to encourage that someone to store and represent your model’s orientation in matrix form. To be comfortable and effective with matrix representation, I feel that the ability to be able to realistically visualize what is happening as you contemplate your code is paramount. Hopefully, this article has assisted some folks down that path. Thanks for reading.

About these ads
Categories: 3d Programming
  1. Simone
    February 20, 2010 at 4:04 am

    Great post! I was losing my mind with Euler angles and I found this solution to be easier to understand and more effective.

    I have a question about the order of the transformations: where do I have to put the scaling and the translation (in case I want to move the model forward or backward as written in this article)?

    Thanks

    • Steve
      February 20, 2010 at 5:50 am

      The rule of thumb is that you always scale first, then rotate, then translate. The reasoning behind this is that scaling & rotating the matrix affects all four vectors and usually when you scale or rotate, you are wanting to do that to just the model’s size or orientation but not the translation. So by leaving the translation at zero until the last operation, the scaling & rotating isn’t affecting where the model ends up location-wise.

      However, that mentality is somewhat left over from the ‘3 angles’ days where you built a completely new matrix in the draw call.

      A scaling approach that better suits the methodology I pushed in the post would be to scale the matrix in the Initialize(). If you do this, you scale the matrix once and be done with it, never needing to scale it again in the Update or draw calls. The way to do that is to instead of setting your matrix to the Identity matrix, set it to the Identity matrix times your scale matrix.
      Or, easier yet, if you intend uniform scaling (all three axis get scaled the same), use the content processor by right clicking your model in the content folder of the solution explorer, select properties, then in the property panel below, set the scale there, it will implement scale during build time and you won’t need to add any code at all to deal with scale.

      Concerning translation, if your movement logic is such that you don’t want the model to orbit whatever rotation axis you happen to be rotating the model’s orientation by, you would save the matrix’s translation vector in a temporary vector3, zero out the matrix’s translation vector, rotate the matrix, apply change in position to the temp vector, reset the matrix’s translation vector to that temp vector and you good. I realize that explanation may be a bit brief, I may expand that concept into a separate post to make it more clear.

  2. February 24, 2010 at 1:33 am

    Hi Steve, that’s a great post! I remember the awesome feeling of wonder when I first worked out what a Matrix really meant in 3D transformation terms. I totally agree that caching a rotation matrix at runtime is the way to go, but was also thinking that Euler angles still have a valid place in game projects. Specifically in configuration – since they are so easy to visualise it makes sense to store these in your config files… artists are very used to them as the art packages still make extensive use of them. How would you propose to effectively store the Axis-Angle style rotation?

    • Steve
      February 24, 2010 at 7:23 am

      Yes, I very much agree with your statement. There is a time and place for everything, including Euler angles. My main point is that they just don’t belong inside the game loop.
      Axis/Angle is another legitimate orientation representation. It can be effectively stored in a Vector3 where the vector’s direction represents the rotation axis & the magnitude represents the angular amount (for instance, if the magnitude was 3.141, the orientation would be 180 degrees around the axis represented by the vector from wherever you determined zero is (usually the identity orientation)). When you refer to this concept as ‘scaled axis’, it becomes more of a relative rotation from one frame to the next & is useful when dealing with motions (ie. lienear and angular velocities). Alternatively, Axis/Angle can be stored as a unit length vector and a float for the angle for the sake of code readability. For anyone who may read this: Just because Axis/Angle (or scaled Axis) is also stored in a Vector3, it should not be confused with Euler Angle representation, which is also commonly stored in a vector3. Completely different animals.

      Aranda, nice blog site, great art!.

  3. Kermitt
    March 11, 2010 at 1:21 am

    I’m trying to use this method to apply joystick movement to a camera and generally it works except for one major snag. I’m using left/right to apply yaw, and up/down to apply pitch by storing one matrix and updating it by the necessary angles each frame. The problem I’m having is that some amount of roll seems to be creeping into it and I want that to remain “flat”. Having a bit of trouble visualizing what’s really going on here but I have a suspicion that this is just what happens when u keep applying various amounts on the other two angles. Do you have any idea how to stop this happening or maybe some way to reset the roll component? Or is this why people usually just create a new matrix each time for this kind of thing?

  4. Alex
    March 28, 2010 at 1:07 am

    @Kermitt

    You have encountered a perennial problem of rotations: they aren’t commutative. For example, choose any two axes. Rotate 90 degrees around the first axis, then 90 degrees around the second axis, then “undo” your first rotation by going 90 degrees the other way around the first axis. You will find that you have rotated your object 90 degrees around the third axis that you never even touched. This is why roll is “creeping into it”.

    As for your problem, you might try the following snippet (untested, should work):

    myMatrix = Matrix.CreateLookAt(myMatrix.Translation, myMatrix.Translation + myMatrix.Forward, Vector3.Up);

  5. Matt
    April 6, 2010 at 8:15 am

    With this approach, how would you handle changing scale in the game loop? For example, perhaps one would want the model to grow or shrink in place. Also, how would you handle turning a model to face another model?

    • Steve
      April 15, 2010 at 4:33 am

      Matt,
      For scale, you generally want to scale only the size of the model, while leaving the position alone. To do this, after scaling the matrix, set the translation back to what it was before scaling:
      Vector3 position = matrix.Translation;
      matrix *= Matrix.CreateScale(?);
      matrix.Translation = position;

      One way a matrix can be turned to face another model/matrix is by crossing vectors and using the vector dotProduct. First let’s assume that it is the matrix’s forward vector that represent the ‘face’ side of the model. The matrix you want to turn is matrixA and the other model’s matrix is matrixB.

      Vector3 directionToOtherModel = matrixB.Translation – matrixA.Translation;
      directionToOtherModel.Normalize();
      float angleFactor = Vector3.Dot(directionToOtherModel, matrixA.Forward);
      float quadrantFactor = angleFactor < 0 ? mathHelper.Pi * 0.5f : 0f;
      float angleToRotate = (float)Math.Acos(angleFactor + quadrantFactor);
      Vector3 rotationAxis = Vector3.Cross(matrixA.Forward, directionToOtherModel);
      rotationAxis.Normalize();
      MatrixA *= Matrix.CreateFromAxisAngle(rotationAxis, angleToRotate);

      Another way would be to simply build a new matrix that happens to be pointing directly at the other model as Jon Watte explains in this post: http://forums.xna.com/forums/p/10228/53647.aspx#53647
      In his method, he eliminates the trig function which saves cpu operations but the matrix's up vector is reset to vertical (which may or may not be desirable).

  6. May 4, 2010 at 10:08 am

    Absolutely fantastic explanation! One read, 3D maths problems went ‘click’ and have worked since!

  7. Ben
    July 6, 2010 at 7:58 am

    Great article!

    Is there anything wrong with storing the rotation as a Vector and converting it whenever it’s manipulated?

    • Steve
      July 8, 2010 at 5:05 pm

      Ben, If you store it as a vector, then convert it, then manipulate it, now what values are you going to put back in your Vector? You would have to go through the trouble of extracting the Euler angles out of the matrix. Only to convert it back to a matrix before manipulating it again? That doesn’t make sense.

      If you decide instead to manipulate the angles first, then convert, you are back to square one… the beginning of this article. In this mode, think of a model yawed, pitched, and rolled some arbitrary orientation, now you want to change the pitch by rotating it about the model’s lateral axis (it’s X axis). That will require a combination of world axis yaw, pitch, and roll, but how much of each and the order applied has consequences. Whereas if you simply rotate the matrix about its own .Right vector, you’re done with it.

  8. Rens Loing
    July 19, 2010 at 10:35 am

    Hi Steve,

    I’ve been reading a lot about 3d manipulation lately, and yours is the only article I’ve found that really explains things the way I needed them explained. Thanks for that. :-)

    I do have a technical question, however. Having applied your examples to my little pet project (just a little simulation of a spaceship in empty space moving around), I ran into something that I can’t seem to solve.

    In my simulation, I’m using these two matrixes (or matrices, or however that’s supposed to be spelled):

    Matrix Inertia { get; set; }
    Matrix Position { get; set; }

    Seeing as my object is flying around in empty space, every nudge I give it makes it tumble around in a specific direction, and the inertia matrix represents the continued tumbling – inertia – of the object. So, every update, I apply the inertia to the object’s position like so:

    if (Inertia != new Matrix())
    Position *= Inertia;

    So far, so good. If I apply rotation like so, my spaceship tumbles about happily in whichever direction I’ve chosen:

    if(Inertia == new Matrix())
    Inertia = Matrix.CreateFromAxisAngle(axis, radians);
    else
    Inertia *= Matrix.CreateFromAxisAngle(axis, radians);

    If I apply thrust while the ship is in zero rotation, the ship moves forward like I’d expect it to:

    private void FireThruster(Vector3 axis)
    {
    Vector3 translation = axis * _thrusterPower * _thrustSetting;

    if (Inertia == new Matrix())
    Inertia = Matrix.CreateTranslation(translation);
    else
    Inertia *= Matrix.CreateTranslation(translation);
    }

    However, when I get it moving a bit, then no longer apply the ‘thruster’ (expecting it to continue on course, which it does) and then apply rotation, the ship deviates from course and starts curving or spiraling (depending on the axis of the rotation). I’m positive I’m not applying any more transformation to the matrix, only rotation.

    So here’s the question: how would I go about separating the movement inertia from the rotation inertia? Any help would be most appreciated.

    • Steve
      July 19, 2010 at 1:17 pm

      Well, there are many ways to skin a cat and the way I would approach this is by using only one matrix that represents the ship’s orientation and position. I would then employ two vectors. One representing linear velocity and one representing angular velocity.

      the matrix gets updated each frame according to the two velocity vectors. The forces that act on the ship, whether they are linear or angular (torque), act to modify those two vectors slightly and in-turn the vectors then influence the matrix.

      The linearVelocity vector uses the vector’s direction to represent the direction the ship is going, and the length (magnitude) of the vector is the speed at which the ship is traveling (xna units per second).

      The angularVelocity vector uses the vector’s direction to represent the axis that the ship is rotating about, and the length (magnitude) of the vector is the speed that it is rotating (rotation rate in radians(degrees) per second).

      So each update you rotate the matrix by the angularVelocity vector & update the position like this:

      float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
      Vector3 position = matrix.Translation;
      matrix.Translation = Vector3.Zero;
      Vector3 axis = Vector3.Normalize(angularVelocity);
      float angle = angularVelocity.Length() * deltaTime;
      matrix *= Matrix.CreateFromAxisAngle(axis, angle);//
      position += linearVelocity;
      matrix.Translation = position * deltaTime;

      Anytime a force or torque should act on the ship, you add it to either the linearVelocity or angularVelocity. These forces and/or torques should also be represented by vectors. For instance, when the main engines thrust the craft, they push in a particular direction, forward. That direction becomes the force vector’s direction and the length of that vector is directly proportional to the amount (Lb or Kg) of thrust. Now you take that force vector, and add it to the linearVelocity vector and next frame, the amount of position shift is different from last frame (due to the linearVelocity vector being different) reflecting the acceleration due to the force.


      Vector3 force = matrix.Forward * amountOfThrustInMainEngine;
      linearVelocity += force;

      For rotational forces (torques) you do a similar thing, if a retro rocket fires that would, say, cause the ship to rotate more nose up, that torque would have a rotational axis that would be parallel to the matrix.Right property. So, for that torque, you would code it up like this:

      Vector3 torque = matrix.Right * amount of torque;
      angularVelocity += torque;

      One of the cool things about working with vectors is that you can sum up multiple forces or torques into one vector. So for instance, let’s say you had two retro rockets burning causing rotation about two different axis.


      Vector3 torque1 = matrix.Right * amountOfTorqueFromThisRetro;
      Vector3 torque2 = matrix.Up * amountOfTorqueFromThisOtherRetro;
      Vector3 totalTorque = torque1 + torque2;
      angularVelocity += totalTorque;

      Now the proper order of things in an update cycle is to:
      1.) calculate force & torque vectors.
      2.) Update both velocity vectors with the new forces & torques.
      3.) Update the matrix per the velocities.

      The last tid bit about forces and torques is that they go hand in hand with mass (the weight of an object) when you use them to update a velocity. For clarity, I didn’t add that above as I was mainly trying to convey the general way the vectors influence the matrix. But to briefly cover it now, when you have a force it would influence the velocity of something that weights 1000 pounds 1/2 as much as it would something weighing only 500 pounds. So mass (weight) is important to factor in. The way you factor it into the above snippets is like this:

      linearVelocity += force / mass;
      angularVelocity += torque / mass;

      For the angularVelocity, you should technically use an inertial tensor instead of mass. But for the learning process, simply use mass for now, or another scalar that fits a little better. I’m planning to write all this up into a tutorial at some point so stay tuned for that. thanks for your question

    • Steve
      July 19, 2010 at 1:49 pm

      Rens, I just re-read the last couple paragraphs of your post. It might be that you could fix your problem by doing this:

      private void FireThruster(Vector3 axis)
      {
      Vector3 translation = axis * _thrusterPower * _thrustSetting + Inertia.Translation;
      Inertia.Translation = Vector3.Zero;
      if (Inertia == new Matrix())
      Inertia = Matrix.CreateTranslation(translation);
      else
      Inertia *= Matrix.CreateTranslation(translation);
      }

  9. Rens Loing
    July 20, 2010 at 2:18 am

    Hey Steve, thanks for the quick replies. After reading them and fiddling a bit with my code, I found that the following actually did the trick:

    // Where I used to do just Position *= Inertia:
    Vector3 oldTranslation = Position.Translation;
    Position *= Inertia; // Movement
    Position.Translation = oldTranslation + Inertia.Translation;

    Nothing else in my code needed to change, so I guess I’d just failed to apply the part of your article where you explained object turning in place to my problem.

    As for ways to skin a cat, I think you’ve helped me skin mine very efficiently. Thanks for that. :-)

  10. Ryan
    August 23, 2010 at 11:49 am

    Thank you so much for this post. It is the most clear explanation of vectors, matrices, the related math and how it impacts the way models are displayed in a game that I have ever seen. How can I buy you a beer?

    • Steve
      August 25, 2010 at 11:34 am

      Thanks, a beer sounds good. I’ll try to get the others in the series done before the end of October.

  11. badescu alex
    September 28, 2010 at 6:28 am

    Thanks very much for the tutorial!

  12. Joel
    October 14, 2010 at 4:48 pm

    Greate article, just wanted to say thanks!

  13. Justin McConnell
    November 25, 2010 at 1:39 am

    hello ive been having trouble with matrix regarding up vectors maybe you can help when i am creating a matrix and i want a look at matrix i dont always know witch direction is going to be up for the matrix and i cant just put in a rotation because it needs to be specific

    lookatmatrix = createlookat(vector(1,1,1), vector(2,2,2), ?)
    now i know the upvector for this one it is (2,0,0)

  14. Ricky Casavecchia
    January 17, 2011 at 4:09 pm

    Thank you very much, your awesome. Great article!

  15. Ashok
    January 24, 2011 at 8:46 am

    A Wonderfull Post.I will remember you everytime i work with a Matrix

  16. January 31, 2011 at 2:43 pm

    Great post Steve. I have come back here a few times for reference and suggest it to other who are still using the Euler approach.

    Now how about an article on Quaternions? ;)

  17. Christopher Rosendahl
    February 15, 2011 at 1:34 am

    Awesome article!

    I’ve been doing 2d graphics for a couple of years, and recently im learning 3D.
    Some more code snippets combined with each demo in the article would help alot.

    At the moment im trying to implement this technique to manipulate the direction of my directional lights.

    Feels like this is exactly whats needed, ive spent a few hours so far trying to get it right.
    Currently my test code looks like this:

    Dim objDirLight As cXNADirectionalLight = objSelectedLight.Light
    Dim mtxOritention As Matrix = Matrix.Identity
    Dim v3Start As Vector3 = objDirLight.Direction

    mtxOritention *= Matrix.CreateFromAxisAngle(New Vector3(0.0, 0.0, 1.0), (msPreviousState.X – msState.X) * 0.05)
    mtxOritention *= Matrix.CreateFromAxisAngle(New Vector3(1.0, 0.0, 0.0), (msPreviousState.Y – msState.Y) * 0.05)
    mtxOritention *= Matrix.CreateTranslation(objDirLight.Direction * objSelectedLight.DIR_LIGHT_SPHERE_SCALE)

    objDirLight.Direction = Vector3.Transform(objDirLight.Direction, mtxOritention)

    objDirLight.Direction.Normalize()

    It seems to work properly when i move the mouse just a few pixels.. But if i do farther movement with the mouse, the light vector becomes Single.NaN

  18. Tony
    April 1, 2011 at 3:54 pm

    Steve, Thank you for taking the time to write this up. It’s clear, concise and very helpful to the beginner. I’ll buy the second round ;-)

  19. Paul
    July 3, 2011 at 7:31 am

    I agree with Christopher. More code snippets, or example programs would improve this a lot. I understand visualizations better if I can actually take a look at the example, both as code and as a funcioning program.

  20. Andrea
    July 14, 2011 at 11:32 pm

    Thank You! This post is a life-saver!

  21. Fabien
    September 26, 2011 at 5:07 am

    Thank you for this “Matrices for dummies” post.

    Would you recommend to go that way when working with 2d games?

    Doing so i could easily switch to 3D later on, but wouldn’t that be overkill ?

  22. miki-bgd
    October 8, 2011 at 3:39 am

    This is really great post, it should be in school books! I am beginner in 3D, and this cleared me a lot of things, really good explained! Keep up with good work!

  23. Piranha
    December 27, 2011 at 7:34 am

    This post is fu**ing awesome!

  24. yannlarocque
    March 12, 2012 at 3:10 pm

    seriously you rock!
    this is an amazing way to think the way a matrix look like and how to process it!
    im new to xna and i apreciate your work this is a great tutorial.

    thank you

  25. Connor Abra
    March 24, 2012 at 11:09 pm

    How would I put this into practice on a model? What code would I use? I am only just starting XNA game creation and I usually learn well from examples of code and things like that.

  26. Simon
    April 6, 2012 at 11:49 pm

    Just wanted to say thanks for the article and videos. It’s certainly made things a lot clearer.

  27. jon
    April 16, 2012 at 5:19 pm

    thank you. this was one the the main things giving me problems. i have read a ton of stuff about matrix and still didnt understand what was actually happening. this article makes it pretty clear. i wish i found it earlier.

  28. April 29, 2012 at 4:15 pm

    This is an awesome article, thanks a ton for taking the time to write it! It’s helped me a ton

  29. April 29, 2012 at 4:18 pm

    I have a question now regarding matrices. If I understand the article correctly, you apply a matrix to your models to perform translation/rotation. What if you are wanting to move a camera around in the 3D scene? Do you use a matrix for cameras, and if so, how do you move the viewport camera around? I’m new to using 3D (Mostly done 2D or used existing engines) so I’m not sure how you would move around without having to update every object matrix in the game. Any tips?

    • Steve
      April 29, 2012 at 5:21 pm

      Hi Scionwest, I generally move a camera around by manipulating the camera’s position vector and/or its target vector. In fact, I just was answering a forum question about that when I saw your post. here it is: http://forums.create.msdn.com/forums/p/103684/613957.aspx#613957

      Saw your twitter intro, I’m a huge Formula 1 fan too. I was in Austin Texas last week and made a point to drive around the track construction…. Looks like they have a long way to go… Hope they make it.

      • April 30, 2012 at 5:20 pm

        Thanks for the tip, I’ll definitely check it out.

        Wow that’s really cool regarding Austin. We wanted to go this year but will probably end up waiting for next years Grand Prix. Formula 1 is the only sport I watch, get up every weekend it’s on to watch all the sessions. Greatest racing sport on earth for sure!

  30. Max
    December 5, 2012 at 10:42 am

    Hi Steve. First of all great post!

    I have a question regarding comparing two objects’ world matrices. I’m trying to compare the locations of two objects using their world.Translation vectors but it appears that the translations affect the two objects differently. For one object, a translation vector of say (0,0,10) is equivalent to a translation vector of (0,-235,0) for the other object. I would have thought that transformations would be applied the same for all objects. Do you know why this happens?

    Thanks

    • Steve
      December 8, 2012 at 7:45 am

      I can’t tell why this happens without seeing more of your project. But your initial though is correct though, the translation vectors of two objects in world space will use the same coordinate systems and their component values hold the same meanings. This would be a good question on the app hub.

      • Max
        December 10, 2012 at 12:06 am

        After playing around for a while I found that using .X files for my models instead of .FBX files fixed the problem. I don’t know why the FBX files were making things so strange…

  31. Martin Svensson
    April 26, 2013 at 2:48 am

    Hi Steve, thank you for a great blog post.
    i’m working on a project where a part of the project is to rotate a model around its own axis with a controller.

    The problem I’m having is understanding how to do this without having the model sliding out of picture. This only happens when use multiply two vectors in the matrix. For example: Matrix.CreateAxisFromAngle(new Vector3(0.0f, 1.0f, 1.0f), 1.0f).

    Posting the code via pastebin below:

    http://pastebin.com/qGBcH5pq

    I hope that you can help me.

    Thank you!

    • Steve
      April 27, 2013 at 5:24 am

      To cause a model to rotate in place rather than swing wildly around it is necessary to translate the model to the world origin before applying the rotation, then translating it back after the rotation.

      Vector3 position = modelOrientation.Translation;
      modelOrientation.Translation = Vector3.Zero;//this translates the model to the world origin.
      modelOrientation *= Matrix.CreateFromAxisAngle(new Vector3(1.0f, 1.0f, 0.0f), 0.2f);
      modelOrientation.Translation = position;//this translates the model back to where you want it.
      base.Update(gameTime);

      • Martin Svensson
        April 28, 2013 at 12:21 am

        Hi Steve, thank you for the answer!

        Unfortunately this did not solve my problem. I’m starting to think that the problem might be elsewhere in the code.

        Since I’m not at all experienced with 3D-programming, all help possible would be highly appreciated.

        Could it be that I’m changing the world camera somewhere?

        Regards,
        Martin

  32. Chapron
    December 1, 2013 at 3:51 am

    Tx a lot man, it really helped.
    BTW, you can read in mind when you said “I know after seeing the code above you may want to jump right into examples of moving and rotating,[… )”

    But then, I came back and then read the article entirely :)

  1. April 5, 2010 at 6:36 am
  2. April 5, 2011 at 2:19 pm
  3. August 29, 2012 at 10:18 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: