1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <numbers>
namespace Donut
{
enum class CameraMode
{
FPS,
Orbital
};
class Camera
{
public:
Camera(float fov = 45.0f, float aspect_ratio = 16.0f / 9.0f,
float near_plane = 0.1f, float far_plane = 100.0f);
~Camera() = default;
void set_position(const glm::vec3& position) { m_position = position; recalculate_view_matrix(); }
void set_rotation(const glm::vec3& rotation) { m_rotation = rotation; recalculate_view_matrix(); }
const glm::vec3& get_position() const { return m_position; }
const glm::vec3& get_rotation() const { return m_rotation; }
glm::vec3 get_forward_direction() const;
glm::vec3 get_right_direction() const;
glm::vec3 get_up_direction() const;
const glm::mat4& get_projection_matrix() const { return m_projection_matrix; }
const glm::mat4& get_view_matrix() const { return m_view_matrix; }
const glm::mat4& get_view_projection_matrix() const { return m_view_projection_matrix; }
void set_projection(float fov, float aspect_ratio, float near_plane, float far_plane);
void on_mouse_move(float x_offset, float y_offset, bool constrain_pitch = true);
void move_forward(float delta_time);
void move_backward(float delta_time);
void move_right(float delta_time);
void move_left(float delta_time);
void move_up(float delta_time);
void move_down(float delta_time);
void set_mouse_sensitivity(float sensitivity) { m_mouse_sensitivity = sensitivity; }
float get_mouse_sensitivity() const { return m_mouse_sensitivity; }
void set_movement_speed(float speed) { m_movement_speed = speed; }
float get_movement_speed() const { return m_movement_speed; }
void set_orbital_target(const glm::vec3& target) { m_orbital_target = target; }
const glm::vec3& get_orbital_target() const { return m_orbital_target; }
void set_orbital_radius(double radius) { m_orbital_radius = radius; }
double get_orbital_radius() const { return m_orbital_radius; }
void set_orbital_limits(double min_radius, double max_radius)
{
m_orbital_min_radius = min_radius;
m_orbital_max_radius = max_radius;
}
void set_orbital_speed(float speed) { m_orbital_speed = speed; }
float get_orbital_speed() const { return m_orbital_speed; }
void set_zoom_speed(double speed) { m_zoom_speed = speed; }
double get_zoom_speed() const { return m_zoom_speed; }
void set_azimuth(float azimuth) { m_azimuth = azimuth; }
float get_azimuth() const { return m_azimuth; }
void set_elevation(float elevation) { m_elevation = elevation; }
float get_elevation() const { return m_elevation; }
glm::vec3 get_orbital_position() const;
void update_orbital();
void process_orbital_mouse_move(double x, double y);
void process_orbital_mouse_button(int button, int action, int mods);
void process_orbital_scroll(double x_offset, double y_offset);
void set_camera_mode(CameraMode mode) { m_camera_mode = mode; }
CameraMode get_camera_mode() const { return m_camera_mode; }
bool is_dragging() const { return m_dragging; }
bool is_panning() const { return m_panning; }
bool is_moving() const { return m_moving; }
double get_last_x() const { return m_last_x; }
double get_last_y() const { return m_last_y; }
private:
void recalculate_view_matrix();
void recalculate_projection_matrix();
private:
CameraMode m_camera_mode = CameraMode::FPS;
glm::mat4 m_projection_matrix;
glm::mat4 m_view_matrix;
glm::mat4 m_view_projection_matrix;
glm::vec3 m_position = { 0.0f, 0.0f, 3.0f };
glm::vec3 m_rotation = { 0.0f, 0.0f, 0.0f };
float m_fov = 45.0f;
float m_aspect_ratio = 16.0f / 9.0f;
float m_near_plane = 0.1f;
float m_far_plane = 100.0f;
float m_mouse_sensitivity = 0.1f;
float m_movement_speed = 5.0f;
bool m_first_mouse = true;
float m_last_x = 0.0f;
float m_last_y = 0.0f;
glm::vec3 m_orbital_target = glm::vec3(0.0f, 0.0f, 0.0f);
double m_orbital_radius = 6.34194e10;
double m_orbital_min_radius = 1e10;
double m_orbital_max_radius = 1e12;
float m_azimuth = 0.0f;
float m_elevation = static_cast<float>(std::numbers::pi) / 2.0f;
float m_orbital_speed = 0.01f;
double m_zoom_speed = 25e9f;
bool m_dragging = false;
bool m_panning = false;
bool m_moving = false;
double m_last_x_orbital = 0.0;
double m_last_y_orbital = 0.0;
};
}
|