Reputation: 35
I'm trying to implement a first person movement system using GLUT and OpenGL. So far I have the strafing left to right, and forward/backward movement working correctly. However, my problem comes with the looking around. I want to be able to use the movement of the mouse to look around, like most/all FPS games. I'm using gluLookAt for all of my movement/looking around. Currently, for the looking around section, I have this (taken from a tutorial)
gluLookAt(position.x, position.y, position.z,
position.x + direction.x, position.y + direction.y, position.z + direction.z,
up_vector.x, up_vector.y, up_vector.z);
Then for when there is a passive mouse movement, I check for it and do this:
horizontal_angle += 0.005* float(x - origin_x);
vertical_angle += 0.005* float(y - origin_y);
direction_vector.x = cos(vertical_angle) * sin(horizontal_angle);
direction_vector.y = sin(vertical_angle);
direction_vector.z = cos(vertical_angle) * cos(horizontal_angle);
position.x = sin(horizontal_angle - 3.14f/2.0f);
position.y = 0.0f;
position.z = cos(horizontal_angle - 3.14f/2.0f);
up_vector = crossProduct(right_vector, direction_vector);
However, this is giving me some really weird, wobbly effect, not particularly close to the one I want.
Upvotes: 0
Views: 3079
Reputation: 588
First off, as far as I know gluLookAt is deprecated, you should consider looking at GLM its a math library that handles pretty much all the mathy stuff for you if you don't want to delve down to that level.
Secondly, you could look at using quaternionsfor your rotation of your camera, they are a lot smoother that just using normal trigonometry for your camera rotation and they also don't suffer from gimbal lock. As far as I can remember GLM does have an implementation for quaternions but you can always implement it yourself as well I've done it a long time back and I got it right, so I couldn't have been to hard. :P
If you do want to stick to the trig for now though, here is my old rotate function before I changed to quaternions:
void Camera::rotateCamera(int xDelta, int yDelta, int xMid, int yMid)
{
const GLfloat X_SCALED = (GLfloat)xDelta / (GLfloat)xMid;
const GLfloat Y_SCALED = (GLfloat)yDelta / (GLfloat)yMid;
const GLfloat ANGLE_DELTA = 2 * 360.0f / 360.0f * 3.14f;
const GLfloat LEFT_RIGHT_ROT = X_SCALED * ANGLE_DELTA;
const GLfloat UP_DOWN_ROT = Y_SCALED * ANGLE_DELTA;
direction = d - r;
vec3 right = cross(direction, u);
vec4 temp(direction.x, direction.y, direction.z, 0.0f);
mat4 identity;
identity = rotate(identity, UP_DOWN_ROT, right);
identity = rotate(identity, LEFT_RIGHT_ROT, u) ;
temp = identity * temp;
d = r;
d[0] += temp[0];
d[1] += temp[1];
d[2] += temp[2];
view = lookAt(r,d,u);
}
xDelta is the amount that your mouse has moved from the centre of your screen, and xMid is the middle of your screen. r is the eye of your camera, d is the direction its facing and u is its up vector.
If you have any questions just ask me :)
UPDATE:
Here is the initial article that I used for my implementation of a quaternion based camera.
My best advice would just be to try and stay away from euler angles, they lose precision and can cause weird artefacts for movement and rotation.
Upvotes: 2
Reputation: 578
The way you are doing it seems right to me except the position part:
position.x = sin(horizontal_angle - 3.14f/2.0f);
position.y = 0.0f;
position.z = cos(horizontal_angle - 3.14f/2.0f);
it should be like that:
vector right_vector = crossProduct(direction_vector, vector(0, 1, 0)); // maybe crossProduct(vector(0, 1, 0), direction_vector)
float speed = 3; // you decide the value.
if ( GetKey(Key_Forward) == Key_Pressed ) {
position.x += (direction_vector.x * speed);
position.y += (direction_vector.y * speed);
position.z += (direction_vector.z * speed);
} else if ( GetKey(Key_Back) == Key_Pressed ) {
position.x -= (direction_vector.x * speed);
position.y -= (direction_vector.y * speed);
position.z -= (direction_vector.z * speed);
}
if ( GetKey(Key_Right) == Key_Pressed ) {
position.x += (right_vector.x * speed);
position.y += (right_vector.y * speed);
position.z += (right_vector.z * speed);
} else if ( GetKey(Key_Back) == Key_Pressed ) {
position.x -= (right_vector.x * speed);
position.y -= (right_vector.y * speed);
position.z -= (right_vector.z * speed);
}
GetKey() and Key_Pressed depends on the API you use hope it works for you, :).
Upvotes: 2