Okay, I'm creating a camera class that is based on an object class that I already have done. This camera should act like a first person space shooter camera, allowing all rotations and movement in any direction relative to itself at any time. The problem I'm having is that things eventually get "out of whack," best explained by saying that the rotations are being performed about the wrong axes (trying to rotate left will rotate the view diagonally downwards, etc.). This is being done in OpenGL using the glLookAt function, giving it the camera's position, the camera's lookAt vector, and the camera's up vector.
Some background information:
The "Camera" is an "Object." And Object has: position, rotation, velocity, acceleration, rot_vel (rotational velocity), rot_accel (rotational acceleration), up, right, forward vectors, and a boolean has_friction variable. If has_friction is true, a friction will be applied to the object's velocity and rot_vel during its update to slow it down.
The Object's update function does the following:
-Updates the velocity with the acceleration with respect to how many milliseconds have passed in the last frame
-Applies that velocity to the position
-Updates the rot_vel with rot_accel
-Applies rot_vel to rotation
-Updates the up, right, and forward vectors. Here's where the problem may lie. I got my equations through
this site. I've used those and I've also made some adjustments to them because I think there's a sign error. Everything I've tried still gives me crazy rotation problems.
bool Object::Update(int ms)
{
velocity += acceleration * ms / 1000;
position += velocity * ms / 1000;
rot_vel += rot_accel * ms / 50;
rotation += rot_vel * ms / 50;
right = right*cos(rotation.getZ()) + up*sin(rotation.getZ());
up = right* -sin(rotation.getZ()) + up*cos(rotation.getZ());
forward = forward*cos(rotation.getY()) + right * -sin(rotation.getY());
right = forward * -sin(rotation.getY()) + right*cos(rotation.getY());
forward = forward*cos(rotation.getX()) + up*sin(rotation.getX());
up = forward * -sin(rotation.getX()) + up*cos(rotation.getX());
right.normalize();
up.normalize();
forward.normalize();
if(has_friction)
{
acceleration = velocity * fric;
rot_accel = rot_vel * fric / 30;
}
else
{
rot_accel = 0;
acceleration = 0;
}
return true
}
So the problem either lies with my math right there, or something I'm doing wrong with the movement.
My Camera is a child of Object with one extra variable: a lookAt vector, which is given to gluLookAt every frame to update orientation. The only thing my camera's update does is call Object's update, then sets the lookAt vector to position + forward. As far as I know, this works correctly, because moving around works fine. The orientation only gets screwed up when I look around (rotate).
Finally, here's my code for rotating the camera:
void Camera::moveForward(double ms)
{
acceleration += forward * 100;
}
void Camera::rollRight(double ms)
{
rot_accel += forward * 0.03f;
}
void Camera::rotateLeft(double ms)
{
rot_accel += up * 0.03f;
}
I think you can figure out the rest of the functions...they work in the same manner.
Wow, this was a long post. If I've confused you, let me know what you'd like me to elaborate on. I have the project to send if you want to check it out. I'm using SDL, so in order to run it, SDL has to be set up from libsdl.org.
Thanks for any suggestions,
Ben