how to rotate camera to new orientation?

Started by
2 comments, last by Spencer Bowers 12 years, 7 months ago
Hi all, I've been playing with a new idea that I had and I need help with the math, as I only have a basic understanding of linear algebra. I have a first-person camera in a hollow cube. I can adjust the gravity so that a wall becomes the new floor, and the camera falls appropriately. I can orient the camera to any side of the cube and the camera rotates correctly with mouse movements. Now I want a smooth transition from one orientation to another and I haven't quite figured it out. For example, if the current orientation is (0, 1, 0) = up, how do I get a smooth camera rotation if it changes to (-1, 0 0) = up? Is there a general solution to this problem or will I have to handle special cases?

Currently I accumulate the mouse's X and Y movements in yaw and pitch variables. Every frame I use yaw and pitch to build a quaternion which is then used to transform the camera's up and forward vectors for the view matrix. Is this sufficient for what I'm trying to accomplish or should I be doing something different?

Here is an example I found of what I'm trying to accomplish. The relevant part starts about 1:20.
Advertisement
I found this thread that seems to describe what I'm after. This is from the first reply:

[color=#1C2837][size=2]1. Construct a quaternion that rotates (over the shortest arc) the player's current up vector into alignment with the target up vector.[color=#1C2837][size=2]
2. Multiply this quaternion with your current orientation quaternion to yield your target orientation.

3. Slerp between the current and target orientations as you're doing currently.[/quote]

How do I do find the quaternion that rotates the current up vector to match the new up vector?

How do I do find the quaternion that rotates the current up vector to match the new up vector?

Find rotation axis - if your up vectors are V1 and V2, then

[font="Courier New"]Vaxis = V1 X V2[/font]

Find rotation angle

[font="Courier New"]cos(angle) = normalize (V1) . normalize (V2)[/font]

Now you can either use rotation axis-angle directly for interpolation, or convert it to quaternion.

Read more from The Matrix and Quaternions FAQ
Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/
I found this solution here that works perfectly for my purposes, although I don't quite understand why the world matrices work for this. Here's my XNA/C# code:


// create a quaternion to represent the old orientation
// oldForward and oldUp are the current camera orientation
Matrix oldOrientation = Matrix.CreateWorld(Vector3.Zero, oldForward, oldUp);
Quaternion oq = Quaternion.CreateFromRotationMatrix(oldOrientation);

// create another quaterion to represent the new orientation
// camForward and camUp are the new orientation
Matrix newOrientation= Matrix.CreateWorld(Vector3.Zero, camForward, camUp);
Quaternion nq = Quaternion.CreateFromRotationMatrix(newOrientation);

// interpolate from old to new orientation
// s now represents the intermediate orientation
// slerpAmount ranges from 0 to 1
Quaternion s = Quaternion.Slerp(oq, nq, slerpAmount);

// turn the intermediate quaternion into a matrix
Matrix rm = Matrix.CreateFromQuaternion(s);

// extract vectors from the matrix
Vector3 up = rm.Up;
Vector3 forward = rm.Forward;
Vector3 right = rm.Right;

// use the extracted vectors to create a rotation quaternion for the camera this frame
Quaternion rotation = Quaternion.CreateFromAxisAngle(up, yaw);
rotation = rotation * Quaternion.CreateFromAxisAngle(right, pitch);

// use the extracted vectors and the rotation quaternion to construct our view matrix for this frame

forward = Vector3.Transform(forward, rotation);
Vector3 cameraLookat = forward + cameraPosition;
up = Vector3.Transform(up, rotation);

viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookat, up);


Hope this helps someone else.

This topic is closed to new replies.

Advertisement