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.
how to rotate camera to new orientation?
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
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:
Hope this helps someone else.
// 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
Popular Topics
Advertisement