Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am using an FPS-like camera, and it uses quaternions. But, whenever I try looking up and then sideways, it tilts, and sometimes it can turn upside down. How can I fix this?

share|improve this question
2  
(Will Self-answer in 7 hours)... –  Aeodyn Jun 15 '12 at 4:59
add comment

3 Answers 3

This is a problem I had for a while, and I couldn't find any answers for, so I thought I would post it here.

It is actually quite simple. How you are most likely doing the rotations is like this:

currentDirection * newRotation;

But, doing it like this doesn't work either.

newRotation * currentDirection;

What you have to do, is do it in the first order for the up and down rotations, and in the second order for the sideways rotations.

For me, it was like this:

        if (keyboard.IsKeyDown(Keys.Up))
            Direction *= Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), TurnSpeed);
        if (keyboard.IsKeyDown(Keys.Down))
            Direction *= Quaternion.CreateFromAxisAngle(new Vector3(-1, 0, 0), TurnSpeed);
        if (keyboard.IsKeyDown(Keys.Left))
            Direction = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), TurnSpeed) * Direction;
        if (keyboard.IsKeyDown(Keys.Right))
            Direction = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, -1), TurnSpeed) * Direction;

For a reason why, the first way has the rotation relative to the current sideways direction, which you want for up and down, but you don't want that for the sideways rotations, which is why the second order is needed.

share|improve this answer
    
I had to wait 7 hours to answer my own... –  Aeodyn Jun 15 '12 at 17:00
    
sorry, can you explain this with some screenshots? "first order" and "second order" is a bit confusing - thanks! –  BBz Jun 16 '12 at 3:26
    
When working with Quaternions, order does matter, as it always does with 3D rotations. In my example, "Direction *= newRotation" is the same as "Direction = Direction * newRotation". But, with left and right rotations, we want it the other way around. This makes it not dependent on the up and down tilt, which causes roll. –  Aeodyn Jun 16 '12 at 18:37
    
Oh I though lt the point of quarternions was that it avoided gimbal lock and the rotations were all independent, but I may have misread the textbook. So just to clarify, are you saying that if you reverse the order of the rotation transformations, you can prevent the camera from tilting? Or are manually setting the roll and pitch transformations to 0 when you rotate yaw? –  BBz Jun 16 '12 at 19:45
add comment

You could decompose your quaternion into a yaw/pitch/roll set of angles, but that's overkill usually.

Instead of composing your quaternions like this:

cameraOrientation = cameraOrientation * framePitch * frameYaw;

Try this:

cameraOrientation = framePitch * cameraOrientation * frameYaw;

It will then never generate tilt/roll and is equivalent to storing yaw and pitch separately

share|improve this answer
    
This. This is exactly what I was looking for. Solved my problem in a one-liner. Nice! –  aardvarkk Apr 18 '13 at 4:25
add comment

For an FPS camera you usually don't want roll and are limited to +/- 90 degrees pitch, so I'd just keep track of the current state using yaw and pitch angles. The full power of quaternions isn't really helpful for this.

You can still convert the yaw/pitch angles to and from quaternions in case you want to transition between the FPS camera and animated cameras using quaternion keyframe interpolation, or something like that.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.