I wish to implement a free roam camera that I can control with a mouse in OpenGL. Unfortunately, moving the mouse seems to rotate the camera incorrectly (along weird axes) when my camera is facing a certain direction. Here are my camera functions.. any idea where I might be going wrong?
Camera::Camera() :
m_right( vec3(1.0f, 0.0f, 0.0f) ),
m_up( vec3(0.0f, 1.0f, 0.0f) ),
m_forward( vec3(0.0f, 0.0f, 1.0f) ),
m_fovy( DEFAULT_FOVY ),
m_ar( DEFAULT_AR ),
m_znear( DEFAULT_ZN ),
m_zfar( DEFAULT_ZF )
{
m_world_view = mat4(1);
mat_persp = glm::perspective(m_fovy, m_ar, m_znear, m_zfar);
}
void Camera::reset_uvn()
{
float* mat = glm::value_ptr(m_world_view);
m_right.x = mat[0];
m_right.y = mat[1];
m_right.z = mat[2];
m_up.x = mat[4];
m_up.y = mat[5];
m_up.z = mat[6];
m_forward.x = mat[8];
m_forward.y = mat[9];
m_forward.z = mat[10];
m_right = glm::normalize(m_right);
m_up = glm::normalize(m_up);
m_forward = glm::normalize(m_forward);
}
void Camera::translate( vec3 disp )
{
float* mat = glm::value_ptr(m_world_view);
mat[12] += disp.x;
mat[13] += disp.y;
mat[14] += disp.z;
}
void Camera::rotate( quat rotation )
{
m_world_view = glm::toMat4(rotation) * m_world_view;
reset_uvn();
}
void Camera::rotate( float theta, vec3& axis )
{
m_world_view = glm::rotate(m_world_view, theta, axis);
reset_uvn();
}
void Camera::set_position( vec3& pos )
{
set_translation(&m_world_view, pos); //works like translate()
}
void Camera::set_orientation( quat& orientation )
{
vec3 prev_pos;
get_translation(m_world_view, &prev_pos);
m_world_view = glm::toMat4(orientation);
set_translation(&m_world_view, prev_pos);
}
void Camera::pitch( float theta )
{
m_world_view = glm::rotate(m_world_view, theta, m_right);
reset_uvn();
}
void Camera::yaw( float theta )
{
m_world_view = glm::rotate(m_world_view, theta, m_up);
reset_uvn();
}
void Camera::roll( float theta )
{
m_world_view = glm::rotate(m_world_view, theta, m_forward);
reset_uvn();
}
void Camera::move_forward( float units )
{
translate(m_forward * units);
}
void Camera::strafe_right( float units )
{
translate(m_right * units);
}
And here's how I'm trying to use it:
void MovementController::update()
{
MouseInput::get_relative_mouse_pos(rel_mouse_pos, rel_mouse_pos+1);
//MouseInput::setMousePos(100, 100);
//rotate camera based on mouse
float scl = Timer::frame_time * m_look_sensitivity;
float yaw = scl * rel_mouse_pos[0];
m_camera->yaw(yaw);
float pitch = scl * rel_mouse_pos[1];
m_camera->pitch(pitch);
//now handle movement
if(KeyboardInput::key_held(VCKEY_W))
m_camera->move_forward(m_movement_speed * Timer::frame_time * -1.0);
if(KeyboardInput::key_held(VCKEY_A))
m_camera->strafe_right(m_movement_speed * Timer::frame_time );
if(KeyboardInput::key_held(VCKEY_S))
m_camera->move_forward(m_movement_speed * Timer::frame_time );
if(KeyboardInput::key_held(VCKEY_D))
m_camera->strafe_right(m_movement_speed * Timer::frame_time * -1.0);
}