0
\$\begingroup\$

I'm rendering model at the origin with a fixed camera looking at it positioned on the z axis.

I want to be able to rotate the model up/down and left/right. Currently I have 2 variables, HorizontalRotation and VerticalRotation. When calculating the world matrix I rotate about the Y axis by HorizontalRotation and about the X axis by VerticalRotation.

The ..Rotation variables are controlled by pressing up/down/left/right arrow keys.

The problem I'm having is that the rotations are happening relative to the object.

Lets say it's a model of the world. Pressing Up a bit would let me look at the north pole.
Currently when i press right the earth spins infront of the camera on its axis; I'm still looking at the north pole.

How can i get it so that no matter what rotations are currently applied i can always rotate my model relative to the camera/world axis?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

First of all, you cannot describe an arbitrary rotation obtained by such combinations of left/right and up/down rotations using only two angles. You need either a third angle somewhere, or another method to describe rotations.

  • Third angle: using a third angle will not necessarily be easy. You would probably use Euler angles (using three angles but only two axes) or Tait-Bryan angles (using three angles around three axes, in some cases called yaw-pitch-roll). (Note: Tait-Bryan angles are often confused with Euler angles, sometimes deliberately because they are very similar after all).

  • Rotation matrix: If you use Euler angles, you will find out that computing the new angle values when the user presses left/right etc. is not trivial at all. In fact this is often done by computing the resulting matrix transformation and going back to Euler angles. So why not directly store a rotation matrix and just ditch the angle variables?.

  • Quaternions: If you feel comfortable with quaternions, you could try storing the camera orientation using a unit quaternion, which will be more efficient both in storage and in computation. However you should first try to get comfortable with the matrix way.

So what should you do? The way I see it, you start with an identity matrix:

Matrix ModelMatrix = Matrix.Identity;

When the user presses left/right, you compute a rotation matrix around the vertical axis and you multiply ModelMatrix by it:

ModelMatrix = ModelMatrix * Matrix.CreateRotationX(angle);

And when the user presses up/down, you do the same around the horizontal axis:

ModelMatrix = ModelMatrix * Matrix.CreateRotationY(angle);

The key here is the multiplication order. The new rotation must be performed after the already applied rotation.

\$\endgroup\$
1
\$\begingroup\$

Creating the desired behaviour using quaternions would look something like that (using XNA built-in Matrix and Quaternion structures):

    Quaternion rotation = Quaternion.Identity

    /// <summary>
    /// Moves the camera in specified direction around an arbitrary axis.
    /// </summary>
    /// <param name="direction">The direction to move to.</param>
    /// <param name="amount">The amount to move in radians around the sphere's origin.</param>
    public void Move(Vector2 direction, float amount)
    {
        if (direction != Vector2.Zero)
        {
            Rotation *= Quaternion.CreateFromRotationMatrix(
                Matrix.CreateRotationX(direction.Y * amount) *
                Matrix.CreateRotationY(direction.X * amount));
        }
    }           

As with matrices, it is important to multiply the new rotation after the current rotation is applied!

\$\endgroup\$

You must log in to answer this question.

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