Original Post
I recentley whippped up a first person style camera class, lightly based off of other various 3D cameras online. However, it doesn't really work all that well. There is one line in specific that I think is causing the problem, which is the rotation on the x-axis line (see the line in the MouseLook function with the "THIS DOESN'T WORK" comment). If I comment this line out, the rest of the camera works fine (rotation on y-axis, moving back & forward, strafing) however when I leave it there, the camera goes insane. Here is the related camera source code (The language is C++, one line of graphics done with OpenGL, mouse input done with SDL) : Camera.h Camera.cpp I have a feeling that the problem is the second parameter I pass in to the function on the line that doesn't work, but I have no idea I should put there in it's place. However, I could be completly wrong about this, it's just a hunch. Thanks for reading my problem. If you can tell what's wrong, please let me know.
#ifndef _CAMERA_H_
#define _CAMERA_H_
#include "Main.h"
#include "Vector3.h"
#include "Timer.h"
class Camera
{
public:
Camera(Vector3 pos,Vector3 v,Vector3 u);
void Move(float distance);
void Strafe(float distance);
void MouseLook();
void Update();
int height;
int width;
Vector3 view;
Vector3 position;
Vector3 up;
private:
void Rotate(float angle, Vector3 speed);
float angle;
};
#endif
#include "Camera.h"
Camera::Camera(Vector3 pos, Vector3 v, Vector3 u)
{
angle = 0;
position = pos;
view = v;
up = u;
}
// Source code removed for brevity.
void Camera::MouseLook()
{
int middleX = width / 2;
int middleY = height / 2;
int mouseX, mouseY;
SDL_GetMouseState(&mouseX,&mouseY);
SDL_WarpMouse(middleX, middleY);
if(mouseX == middleX && mouseY == middleY) return;
float xRotation = (float)((middleX - mouseX)) / (float) width;
float yRotation = (float)((middleY - mouseY)) / (float) height;
angle -= yRotation;
if(angle > 1.0f)
{
float difference = angle - 1.0f;
yRotation -= difference;
angle = 1.0f;
}
else if(angle < -1.0f)
{
float difference = -angle - 1.0f;
yRotation += difference;
angle = -1.0f;
}
Vector3 look(view - position);
Vector3 xCameraAxis = look.Cross(up);
xCameraAxis.Normalize();
Rotate(yRotation, xCameraAxis); //THIS DOESN'T WORK
Rotate(xRotation, up);
}
void Camera::Update()
{
gluLookAt(position.x, position.y, position.z, view.x, view.y, view.z, up.x, up.y, up.z);
}
void Camera::Rotate(float angle, Vector3 speed)
{
float cosine = (float)cos(angle);
float sine = (float)sin(angle);
Vector3 look(view-position);
look.Normalize();
Vector3 newLook;
newLook.x = look.x * (speed.x * (1 - cosine) + cosine) +
look.y * (speed.x * speed.y * (1 - cosine) - speed.z * sine) +
look.z * (speed.x * speed.z * (1 - cosine) + speed.y * sine);
newLook.y = look.y * (speed.y * (1 - cosine) + cosine) +
look.x * (speed.x * speed.y * (1 - cosine) + speed.z * sine) +
look.z * (speed.y * speed.z * (1 - cosine) - speed.x * sine);
newLook.z = look.z * (speed.z * (1 - cosine) + cosine) +
look.y * (speed.y * speed.z * (1 - cosine) + speed.x * sine) +
look.x * (speed.x * speed.z * (1 - cosine) - speed.y * sine);
view = position + newLook;
}