tags:

views:

360

answers:

4

I'm programming a game in C# using the XNA3.1 engine. However I'm having a small issue with my camera, basically my camera tends to "flip" when it rotates more than 180 degrees on its roll (when the camera reaches 180 degrees, it seems to flip back to 0 degrees). The code for obtaining the view matrix is as follows:

Globals.g_GameProcessingInfo.camera.viewMat = Matrix.CreateLookAt(Globals.g_GameProcessingInfo.camera.target.pos, Globals.g_GameProcessingInfo.camera.LookAt, up);                //Calculate the view matrix

The Globals.g_GameProcessingInfo.camera.LookAt variable the position 1 unit directly in front of the camera, relative to the rotation of the camera, and the "up" variable is obtained with the following function:

static Vector3 GetUp()      //Get the up Vector of the camera
{
    Vector3 up = Vector3.Zero;
    Quaternion quat = Quaternion.Identity;
    Quaternion.CreateFromYawPitchRoll(Globals.g_GameProcessingInfo.camera.target.rot.Y, Globals.g_GameProcessingInfo.camera.target.rot.X, Globals.g_GameProcessingInfo.camera.target.rot.Z, out quat);

    up.X = 2 * quat.X * quat.Y - 2 * quat.W * quat.Z;       //Set the up x-value based on the orientation of the camera
    up.Y = 1 - 2 * quat.X * quat.Z - 2 * quat.Z * quat.Z;   //Set the up y-value based on the orientation of the camera
    up.Z = 2 * quat.Z * quat.Y + 2 * quat.W * quat.X;       //Set the up z-value based on the orientation of the camera
    return up;      //Return the up Vector3
}
A: 

meh was hoping to see a tan in there somewhere.

can you link to where you got your equation from please? (am at work and really don;t want to sit down myself and derive it)

how are you setting your camera rotation? are you sure nothing is going on there?

John Nicholas
I got the equation from some old lecture slides i viewed when completing my programming degree. It's the pure mathematical way of calculating the up vector based on a quaternion rotation. I'm setting the camera rotation at various areas throughout the game through the use of a Vector3 (pitch,yaw,roll) and i cant see anything funny going on there.
Ice Phoenix
A: 

I'm a bit unsure about the math in your GetUp method. Could you elaborate on the math behind it?

In my lookat camera I initialize my up-vector once and then rotate that vector using a quaternion. This removes the possibility of trying to do a cross-product on parallel vectors in order to calculate the up vector.

Some semicode to clarify perhaps:

var up = Vector3.Up;
var target = <some point in space>;
var rotation = <current rotation quaternion>;

var forward = target - position;
forward = Vector3.Transform(forward, rotation);

var updatedPosition = target - forward;
var updatedUp = Vector3.Transform(up, rotation);

var view = Matrix.CreateLookAt(updatedPosition, target, updatedUp);
Peter Lillevold
The code in the GetUp method is a snippet from camera code that i normally use, which i originally got off my lecture slides from my programming degree. It's been a while since i analyzed the actual mathematics behind it, but we were basically told "this will give you the up direction based on an orientation" (and it's worked in previous projects i've worked on). I see the way you're explaining it and i'll try and give it a go as it is less complicated and it would rule out any mathematical error.
Ice Phoenix
I agree, Up.z feels like it needs a "-" somewhere.
Jason Hernandez
+1  A: 

This is probably slower but the only way I know to do with would be the with the rotation matrix for 3D. Wikipedia Link

alt text

Where

alt text

and U = (Camera.position - Camera.lookat).norm

... Now, I believe that would give you the rotation part of the view matrix. However, I'm not 100% on it. I'm still looking into this though.

Buttink
hmmm looks interesting, i'll take a look into it, but i'm pretty sure i'm getting the up direction correctly. Thanks for the info tho
Ice Phoenix
+1  A: 

I got same problems in OpenGL with gluLookAt. I fixed that problem with my own camera class:

void Camera::ComputeVectors()
{
    Matrix4x4 rotX, rotZ;
    Quaternion q_x, q_y, q_z;
    Quaternion q_yx, q_yz;
    q_x.FromAngleAxis(radians.x, startAxisX);
    q_y.FromAngleAxis(radians.y, startAxisY);
    q_z.FromAngleAxis(radians.z, startAxisZ);
    q_yx = q_y * q_x;
    q_yx.ToMatrix(rotZ);
    q_yz = q_y * q_z;
    q_yz.ToMatrix(rotX);
    axisX = startAxisX;
    axisZ = startAxisZ; 
    axisX.Transform(rotX);
    axisZ.Transform(rotZ);
    axisY = axisX.Cross(axisZ);

    position = startPosition;
    position -= center;
    position.Transform(q_yx);
    position += center;
}

It is maybe overcomplicated, but working. axisY is your up vector. Full code listing is at: http://github.com/filipkunc/opengl-editor-cocoa/blob/master/PureCpp/MathCore/Camera.cpp

Hope it helps.

Filip Kunc
hey dude, thanks heaps for that, it definitely helped out and the problem is now solved, don't know what may have been going wrong but this function has solved the issue :D.
Ice Phoenix