50 lines
1.6 KiB
C++
50 lines
1.6 KiB
C++
#include "camera.hpp"
|
|
|
|
#include <glm/ext/matrix_clip_space.hpp>
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <glm/geometric.hpp>
|
|
#include <glm/trigonometric.hpp>
|
|
|
|
const float zoom_speed_scale = 30.0f;
|
|
|
|
Viewport make_viewport(float win_w, float win_h, float fov_degrees = 45.0f) {
|
|
return { .fov_degrees = fov_degrees, .width = win_w, .height = win_h };
|
|
}
|
|
|
|
glm::mat4 camera_to_projection(Viewport &v) {
|
|
return glm::infinitePerspective(glm::radians(v.fov_degrees), v.width / v.height, 0.1f);
|
|
}
|
|
|
|
Camera make_camera(glm::vec3 focus = glm::vec3(0, 0, 0), float distance = 1.0f) {
|
|
return {
|
|
.focus = focus,
|
|
.theta = 0,
|
|
.phi = 0,
|
|
.distance = distance
|
|
};
|
|
}
|
|
void pan_camera(Camera& c, glm::vec2 dxdy) {
|
|
dxdy.y *= -1;
|
|
c.focus += camera_to_world(c) * glm::vec4(dxdy, 0, 0) * c.distance / 1000.0f;
|
|
}
|
|
|
|
void rotate_camera(Camera& c, glm::vec2 dxdy) {
|
|
c.theta += dxdy.x / 100.0f;
|
|
c.phi += dxdy.y / 100.0f;
|
|
}
|
|
|
|
void zoom_camera(Camera& c, float dz) {
|
|
c.distance = std::max(0.0f, c.distance - (dz * zoom_speed_scale));
|
|
}
|
|
|
|
glm::mat4 world_to_camera(Camera& c) {
|
|
glm::mat4 world_to_focus = glm::translate(glm::mat4(1), c.focus);
|
|
glm::mat4 rotation_theta = glm::rotate(glm::mat4(1), c.theta, {0, 1, 0});
|
|
glm::mat4 rotation_phi = glm::rotate(glm::mat4(1), c.phi, {1, 0, 0});
|
|
glm::mat4 rotated_focus_to_camera = glm::translate(glm::mat4(1), { 0, 0, -c.distance });
|
|
glm::mat4 res = rotated_focus_to_camera * rotation_phi * rotation_theta * world_to_focus;
|
|
return res;
|
|
}
|
|
|
|
glm::mat4 camera_to_world(Camera& c) { return glm::inverse(world_to_camera(c)); }
|