gedeng/include/Gedeng/Camera.h

92 lines
2.7 KiB
C++

#pragma once
#include <GLFW/glfw3.h>
#include <glm/ext/matrix_transform.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/dual_quaternion.hpp>
#include "Gedeng/Logger.h"
#include "Gedeng/Ray.h"
#include "Input.h"
#include "Spatial.h"
namespace Gedeng {
class Camera : public Spatial {
public:
/// Create a camera with a field of view (in degrees), width and height (in any unit) and near
/// and far distances
Camera(float fov, float width, float height, float near, float far)
: projection(glm::perspective(glm::radians(fov), width / height, near, far)) {
}
glm::mat4 get_projection() const {
return projection;
}
glm::mat4 get_view() const {
return glm::inverse(get_matrix());
}
Ray get_view_ray() const {
return Ray(get_translation(), forward());
}
private:
glm::mat4 projection;
};
class FPSCamera : public Camera {
public:
FPSCamera(float fov, float width, float height, float near, float far)
: Camera(fov, width, height, near, far), move_speed(glm::vec3(5.0, 5.0, 5.0)), mouse_sensitivity(0.1),
last_mouse_position(Input::get_mouse_position()), pitch(0.0), yaw(0.0) {
}
void update(float delta) {
if (Input::is_key_down(GLFW_KEY_W)) {
translate(glm::vec3(0.0, 0.0, -1.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_S)) {
translate(-glm::vec3(0.0, 0.0, -1.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_D)) {
translate(glm::vec3(1.0, 0.0, 0.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_A)) {
translate(-glm::vec3(1.0, 0.0, 0.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_Q)) {
translate(glm::vec3(0.0, 1.0, 0.0) * move_speed * delta);
}
if (Input::is_key_down(GLFW_KEY_E)) {
translate(-glm::vec3(0.0, 1.0, 0.0) * move_speed * delta);
}
glm::vec2 mouse_difference = Input::get_mouse_position() - last_mouse_position;
yaw -= mouse_difference.x * mouse_sensitivity;
pitch -= mouse_difference.y * mouse_sensitivity;
if (pitch > 80.0f) pitch = 80.0f;
if (pitch < -80.0f) pitch = -80.0f;
glm::qua rotation = glm::angleAxis(glm::radians((float)yaw), glm::vec3(0.f, 1.f, 0.f));
rotation *= glm::angleAxis(glm::radians((float)pitch), glm::vec3(1.f, 0.f, 0.f));
set_rotation_from_quat(rotation);
last_mouse_position = Input::get_mouse_position();
}
private:
glm::vec3 move_speed;
float mouse_sensitivity;
glm::vec2 last_mouse_position;
float pitch;
float yaw;
};
} // namespace Gedeng