1
\$\begingroup\$

I have created a player model out of primitive types. To do this I have created a Model class and Component (mesh) class. Each model consists of one or more components my problems start when you have to rotate the model as a whole. When you manually create a mesh, you have to also specify it's origin, my problem is that the player is not rotating, before it worked somewhat (it turned each mesh indivialy) but then I changed the order of the Matrices and now it doesn't rotate at all, I think it is my matrix order:

effect.Parameters["World"].SetValue(Matrix.Identity *  Matrix.CreateTranslation(component.RelativePosition) * Matrix.CreateRotationY(player.Rotation.Y) * Matrix.CreateTranslation(player.Position)  * Matrix.CreateTranslation(player.Model.Origin));

How can I fix this?

Edit:

The update code is (I added the "0, 0, -1" so I can actually see it) but it is rotating each component idividally rather then as a whole model:

effect.Parameters["World"].SetValue(Matrix.CreateTranslation(-player.Model.Origin)  * Matrix.CreateRotationY(player.Rotation.Y) * Matrix.CreateTranslation(component.RelativePosition) * Matrix.CreateTranslation(player.Position) * Matrix.CreateTranslation(0, 0, -1));

enter image description here

\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

I don't really know exactly what your RelativePosition and Model.Origin stand for, so it's hard to say for certain, but usually the origin part should come at the beggining of the world matrix and be negated (i.e. Matrix.CreateTranslation(-player.Model.Origin)).

Scaling, rotation and translation usually come in SRT order, which you did right.

As for the RelativePosition I'm not sure what it is. But if that's like the transform of the parent object, then I think it needs to go at the end (at least that's how it worked for me here).

Anyway, for future reference, here's a rundown of what is usually the order for each situation:

Simple Transformations

The order of multiplication for a world matrix is typically:

// World Matrix
Scale * Rotation * Translation

And the order of multiplication for a view matrix is typically:

// View Matrix
-Translation * -Rotation * Zoom

Transformations with Origin

However, especially in 2D games, you frequently need to add an origin displacement to your transformation. That's usually added to the beggining, and must be negated too, so:

// World Matrix with Origin
-OriginTranslation * Scale * Rotation * PositionTranslation

The same thing can also be done with a view matrix, but you add it to the end and this time you don't negate it:

// View Matrix with Origin
-PositionTranslation * -Rotation * Zoom * OriginTranslation

Transformations with Selective Origin

There are also some cases where you want to have an origin displacement, but you want it to affect only your scale and rotation, but not your translation. The way to handle that is to undo the origin transformation before reaching the translation component. For example, with the world matrix:

// World Matrix with Origin for Scale and Rotation
-OriginTranslation * Scale * Rotation * OriginTranslation * PositionTranslation

And the view matrix:

// View Matrix with Origin
-PositionTranslation * -OriginTranslation * -Rotation * Zoom * OriginTranslation

Orbiting around Target

Finally, there's the special case where you want something that orbits around another point. In that situation, you simply switch rotation and translation and it becomes:

// Orbit matrix
Scale * Translation * Rotation

Edit

From your picture I now understand you're trying to create a sort of bone hierarchy where the character is composed by several pieces each with their own transformations, which in turn are grouped together and work as a whole.

In this situation it's easier to understand if you divide the process into two separate matrices, one for the character as a whole, and one for the piece, and then combine them into one as:

Piece Absolute World Matrix = Piece Relative World Matrix * Character World Matrix

So for full flexibility let's say your character has its own Position, Rotation, Scale and Origin in the world, and each piece has its own Position, Rotation, Scale and Origin relative to the origin of the character. You would then calculate the actual world matrix as:

Matrix characterMatrix = Matrix.CreateTranslation(-character.Origin) *
                         Matrix.CreateScale(character.Scale) *
                         Matrix.CreateRotationY(character.Rotation) *
                         Matrix.CreateTranslation(character.Position);

foreach(Piece piece in character.Pieces)
{
    Matrix pieceMatrix = Matrix.CreateTranslation(-piece.Origin) *
                         Matrix.CreateScale(piece.Scale) *
                         Matrix.CreateRotationY(piece.Rotation) *
                         Matrix.CreateTranslation(piece.Position);

    Matrix finalMatrix = pieceMatrix * characterMatrix;
}

Since you only seem to use a small subset of this values, you can remove everything that isn't being used, and if you want you can also inline everything into a single expression (the problem is that you will be recalculating the character's world matrix over and over and again for each piece, which is wasteful).

I think the result would then be, using the values you provided:

effect.Parameters["World"].SetValue(
    Matrix.CreateTranslation(component.RelativePosition) *   // Piece Matrix
    Matrix.CreateTranslation(-player.Model.Origin)  *        // Character Matrix
    Matrix.CreateRotationY(player.Rotation.Y) * 
    Matrix.CreateTranslation(player.Position) * 
    Matrix.CreateTranslation(0, 0, -1)
);
\$\endgroup\$
6
  • 2
    \$\begingroup\$ Again, these multiplication orders are only correct for the row vector convention. Which is fine, since that's what people usually use in XNA, but it's worth noting. \$\endgroup\$ Commented Mar 2, 2012 at 20:42
  • \$\begingroup\$ @NathanReed That's a good point. I had the feeling it was that way, but wasn't sure since I've only worked with row vectors so far. :) \$\endgroup\$ Commented Mar 2, 2012 at 20:54
  • \$\begingroup\$ @DavidGouveia Well, I Have now tryed it in that order, but does seem to work, and is rotating each component indivially, I'll post a screen shot and updated code above. \$\endgroup\$
    – Darestium
    Commented Mar 4, 2012 at 2:18
  • \$\begingroup\$ @Darestium You're trying to create kind of bone hierarchy so it's a bit more complicated than that. First create a normal world matrix for the character as a whole, with its position in the world, rotation and scale. Then for each piece in the body create a world matrix for that piece but considering that the character is the center of the world, so all values should be relative to the character. Finally, the real world matrix for each piece is the multiplication of both matrices above (I think the character one comes last). Don't try everything as a single step. \$\endgroup\$ Commented Mar 4, 2012 at 14:02
  • \$\begingroup\$ @Darestium Check the edit. \$\endgroup\$ Commented Mar 4, 2012 at 21:55
2
\$\begingroup\$

You should always have your transformations in order: scale * rotation * translation

It's because matrix multiplication is not commutative. For demonstration, look at this:enter image description here

If you use transform and then rotation, it's different from rotation and then transform.

EDIT: Of course if you want special behaviour like Earth rotation around Sun, you can first translate (all the time the same direction) Earth from Sun and then rotate (rotation is changing in time), which will do the trick.

\$\endgroup\$
3
  • \$\begingroup\$ Just a note: scale * rotation * translation is only correct when using the row vector convention (as people usually do in XNA). For column vectors it would be the opposite order. \$\endgroup\$ Commented Mar 2, 2012 at 20:41
  • \$\begingroup\$ Author has tag XNA, so I'm expecting, he is using built in matrices. \$\endgroup\$
    – zacharmarz
    Commented Mar 2, 2012 at 21:18
  • \$\begingroup\$ Well, I Have now tryed it in that order, but does seem to work, and is rotating each component indivially, I'll post a screen shot and updated code above. \$\endgroup\$
    – Darestium
    Commented Mar 3, 2012 at 23:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .