Tatooine
camera_controller.h
Go to the documentation of this file.
1#ifndef TATOOINE_RENDERING_CAMERA_CONTROLLER_H
2#define TATOOINE_RENDERING_CAMERA_CONTROLLER_H
3//==============================================================================
7
8#include <chrono>
9//==============================================================================
10namespace tatooine::rendering {
11//==============================================================================
12template <typename Real>
13struct camera_controller;
14// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
15template <typename Real>
16struct fps_camera_controller;
17// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
18template <typename Real>
19struct orthographic_camera_controller;
20//==============================================================================
21template <typename Real>
27 private:
29 //----------------------------------------------------------------------------
30 public:
33 virtual ~camera_controller_interface() = default;
34
35 auto perspective_camera() -> auto& {
36 return m_controller->perspective_camera();
37 }
38 auto perspective_camera() const -> auto const& {
39 return m_controller->perspective_camera();
40 }
41 auto orthographic_camera() -> auto& {
42 return m_controller->orthographic_camera();
43 }
44 auto orthographic_camera() const -> auto const& {
45 return m_controller->orthographic_camera();
46 }
47 void look_at(vec3 const& eye, vec3 const& lookat,
48 vec3 const& up = {0, 1, 0}) {
49 m_controller->look_at(eye, lookat, up);
50 }
51 auto controller() -> auto& {
52 return *m_controller;
53 }
54 auto controller() const -> auto const& {
55 return *m_controller;
56 }
57 //----------------------------------------------------------------------------
58 virtual auto type() const -> std::type_info const& = 0;
59 //----------------------------------------------------------------------------
60 virtual void update(std::chrono::duration<double> const& /*dt*/) {}
61};
62//==============================================================================
63template <typename Real>
69 friend struct camera_controller_interface<Real>;
74 std::unique_ptr<camera_controller_interface<Real>> m_controller;
75 //============================================================================
76 camera_controller(size_t const res_x, size_t const res_y)
77 : m_pcam{{Real(0), Real(0), Real(0)},
78 {Real(0), Real(0), Real(1)},
79 60,
80 static_cast<Real>(0.01),
81 100,
82 res_x,
83 res_y},
84 m_ocam{{Real(0), Real(0), Real(0)},
85 {Real(0), Real(0), Real(-1)},
86 m_orthographic_height,
87 -100,
88 100,
89 res_x,
90 res_y},
91 m_active_cam{&m_pcam} {
92 use_fps_controller();
93 }
94 //============================================================================
95 auto set_orthographic_height(Real const h) {
96 m_orthographic_height = h;
97 m_ocam.set_projection_matrix(m_orthographic_height);
98 }
99 auto orthographic_height() { return m_orthographic_height; }
100 auto active_camera() const -> auto const& { return *m_active_cam; }
101 auto unproject(Vec2<Real> const& x) {
102 return m_active_cam->unproject(x);
103 }
104 auto unproject(Vec4<Real> const& x) {
105 return m_active_cam->unproject(x);
106 }
108 m_active_cam = &m_pcam;
109 }
111 m_active_cam = &m_ocam;
112 }
114 m_controller = std::make_unique<fps_camera_controller<Real>>(this);
115 }
117 m_controller = std::make_unique<orthographic_camera_controller<Real>>(this);
118 }
119 auto perspective_camera() -> auto& {
120 return m_pcam;
121 }
122 auto perspective_camera() const -> auto const& {
123 return m_pcam;
124 }
125 auto orthographic_camera() -> auto& {
126 return m_ocam;
127 }
128 auto orthographic_camera() const -> auto const& { return m_ocam; }
129 auto controller() const -> auto const& { return *m_controller; }
130 auto projection_matrix() const { return m_active_cam->projection_matrix(); }
131 auto transform_matrix() const -> mat4 {
132 return m_active_cam->transform_matrix();
133 }
134 auto view_matrix() const { return m_active_cam->view_matrix(); }
135 auto eye() const { return m_active_cam->eye(); }
136 auto right_direction() const { return m_active_cam->right_direction(); }
137 auto up_direction() const { return m_active_cam->up_direction(); }
138 auto view_direction() const { return m_active_cam->view_direction(); }
139 auto look_at(vec3 const& eye, vec3 const& lookat,
140 vec3 const& up = {0, 1, 0}) {
141 m_pcam.look_at(eye, lookat, up);
142 m_ocam.look_at(eye, lookat, up);
143 }
144 auto look_at(vec3 const& eye, arithmetic auto const pitch,
145 arithmetic auto const yaw) {
146 m_pcam.look_at(eye, pitch, yaw);
147 m_ocam.look_at(eye, pitch, yaw);
148 }
149 auto plane_width() { return m_active_cam->plane_width(); }
151 return m_active_cam->plane_height();
152 }
153 auto ray(int x, int y) const { return m_active_cam->ray(x, y); }
154 //------------------------------------------------------------------------------
155 void on_key_pressed(gl::key k) override {
156 if (m_controller) {
157 m_controller->on_key_pressed(k);
158 }
159 }
160 void on_key_released(gl::key k) override {
161 if (m_controller) {
162 m_controller->on_key_released(k);
163 }
164 }
165 void on_button_pressed(gl::button b) override {
166 if (m_controller) {
167 m_controller->on_button_pressed(b);
168 }
169 }
171 if (m_controller) {
172 m_controller->on_button_released(b);
173 }
174 }
175 void on_cursor_moved(double x, double y) override {
176 if (m_controller) {
177 m_controller->on_cursor_moved(x, y);
178 }
179 }
180 void on_wheel_up() override {
181 if (m_controller) {
182 m_controller->on_wheel_up();
183 }
184 }
185 void on_wheel_down() override {
186 if (m_controller) {
187 m_controller->on_wheel_down();
188 }
189 }
190 void on_wheel_left() override {
191 if (m_controller) {
192 m_controller->on_wheel_left();
193 }
194 }
195 void on_wheel_right() override {
196 if (m_controller) {
197 m_controller->on_wheel_right();
198 }
199 }
200 void on_resize(int w, int h) override {
201 m_pcam.set_resolution(static_cast<std::size_t>(w), static_cast<std::size_t>(h));
202 m_ocam.set_resolution(static_cast<std::size_t>(w), static_cast<std::size_t>(h));
203 m_pcam.set_projection_matrix(60, static_cast<Real>(0.001), 1000);
204 m_ocam.set_projection_matrix(m_orthographic_height);
205 if (m_controller) {
206 m_controller->on_resize(w, h);
207 }
208 }
209 void update(std::chrono::duration<double> const& dt) {
210 if (m_controller) {
211 m_controller->update(dt);
212 }
213 }
214};
215//==============================================================================
216template <typename Real>
224 using parent_type::controller;
225
226 enum buttons : std::uint8_t { w = 1, a = 2, s = 4, d = 8, q = 16, e = 32 };
227
228 std::uint8_t m_buttons_down = 0;
229 Real m_mouse_pos_x, m_mouse_pos_y;
230 bool m_right_button_down = false;
231 bool m_shift_down = false;
232 bool m_ctrl_down = false;
233 //----------------------------------------------------------------------------
235 : camera_controller_interface<Real>{controller} {
236 //controller->look_at(controller->eye(), controller->eye() + vec{0, 0, 1});
237 }
238 virtual ~fps_camera_controller() = default;
239 //----------------------------------------------------------------------------
240 auto on_key_pressed(gl::key k) -> void override {
241 if (k == gl::key::KEY_CTRL_L || k == gl::key::KEY_CTRL_R) {
242 m_ctrl_down = true;
243 }
244 if (k == gl::key::KEY_SHIFT_L || k == gl::key::KEY_SHIFT_R) {
245 m_shift_down = true;
246 }
247 if (k == gl::key::KEY_W) {
248 m_buttons_down = m_buttons_down | buttons::w;
249 }
250 if (k == gl::key::KEY_S) {
251 m_buttons_down = m_buttons_down | static_cast<std::uint8_t>(buttons::s);
252 }
253 if (k == gl::key::KEY_A) {
254 m_buttons_down = m_buttons_down | static_cast<std::uint8_t>(buttons::a);
255 }
256 if (k == gl::key::KEY_D) {
257 m_buttons_down = m_buttons_down | static_cast<std::uint8_t>(buttons::d);
258 }
259 if (k == gl::key::KEY_Q) {
260 m_buttons_down = m_buttons_down | static_cast<std::uint8_t>(buttons::q);
261 }
262 if (k == gl::key::KEY_E) {
263 m_buttons_down = m_buttons_down | static_cast<std::uint8_t>(buttons::e);
264 }
265 }
266 //----------------------------------------------------------------------------
267 void on_key_released(gl::key k) override {
268 if (k == gl::key::KEY_CTRL_L || k == gl::key::KEY_CTRL_R) {
269 m_ctrl_down = false;
270 }
271 if (k == gl::key::KEY_SHIFT_L || k == gl::key::KEY_SHIFT_R) {
272 m_shift_down = false;
273 }
274 if (k == gl::key::KEY_W) {
275 m_buttons_down = static_cast<std::uint8_t>(m_buttons_down & ~buttons::w);
276 }
277 if (k == gl::key::KEY_S) {
278 m_buttons_down = static_cast<std::uint8_t>(m_buttons_down & ~buttons::s);
279 }
280 if (k == gl::key::KEY_A) {
281 m_buttons_down = static_cast<std::uint8_t>(m_buttons_down & ~buttons::a);
282 }
283 if (k == gl::key::KEY_D) {
284 m_buttons_down = static_cast<std::uint8_t>(m_buttons_down & ~buttons::d);
285 }
286 if (k == gl::key::KEY_Q) {
287 m_buttons_down = static_cast<std::uint8_t>(m_buttons_down & ~buttons::q);
288 }
289 if (k == gl::key::KEY_E) {
290 m_buttons_down = static_cast<std::uint8_t>(m_buttons_down & ~buttons::e);
291 }
292 }
293 //----------------------------------------------------------------------------
294 void on_button_pressed(gl::button b) override {
295 if (b == gl::button::right) {
296 m_right_button_down = true;
297 }
298 }
299 //----------------------------------------------------------------------------
301 if (b == gl::button::right) {
302 m_right_button_down = false;
303 }
304 }
305 //----------------------------------------------------------------------------
306 void on_cursor_moved(double x, double y) override {
307 if (m_right_button_down) {
308 auto const offset_x = static_cast<Real>(gcem::ceil(x)) - m_mouse_pos_x;
309 auto const offset_y = static_cast<Real>(gcem::ceil(y)) - m_mouse_pos_y;
310
311 auto const old_view_dir = -controller().view_direction();
312 auto yaw = gcem::atan2(old_view_dir(2), old_view_dir(0));
313 auto pitch = gcem::asin(old_view_dir(1));
314
315 yaw += offset_x * Real(0.001);
316 pitch = std::clamp<Real>(pitch + offset_y * Real(0.001),
317 static_cast<Real>(-M_PI * 0.5 * 0.7),
318 static_cast<Real>(M_PI * 0.5 * 0.7));
319 auto const cos_pitch = gcem::cos(pitch);
320 auto const sin_pitch = gcem::sin(pitch);
321 auto const cos_yaw = gcem::cos(yaw);
322 auto const sin_yaw = gcem::sin(yaw);
323 auto const eye = controller().eye();
324 auto const new_view_dir =
325 vec{cos_pitch * cos_yaw, sin_pitch, cos_pitch * sin_yaw};
326 controller().look_at(eye, eye + normalize(new_view_dir));
327 }
328 m_mouse_pos_x = static_cast<Real>(gcem::ceil(x));
329 m_mouse_pos_y = static_cast<Real>(gcem::ceil(y));
330 }
331 auto speed() const {
332 if (m_shift_down) {
333 return Real(1) / 250;
334 }
335 if (m_ctrl_down) {
336 return Real(1) / 1000;
337 }
338 return Real(1) / 500;
339 }
340 //----------------------------------------------------------------------------
341 void update(std::chrono::duration<double> const& dt) override {
342 auto const look_dir = controller().view_direction();
343 auto const right_dir = controller().right_direction();
344 auto move_direction = vec3::zeros();
345 if (m_buttons_down & buttons::w) {
346 move_direction -= look_dir;
347 }
348 if (m_buttons_down & buttons::s) {
349 move_direction += look_dir;
350 }
351 if (m_buttons_down & buttons::a) {
352 move_direction -= right_dir;
353 }
354 if (m_buttons_down & buttons::d) {
355 move_direction += right_dir;
356 }
357 if (m_buttons_down & buttons::q) {
358 move_direction(1) += 1;
359 }
360 if (m_buttons_down & buttons::e) {
361 move_direction(1) -= 1;
362 }
363 auto const passed_time = static_cast<Real>(
364 std::chrono::duration_cast<std::chrono::milliseconds>(dt).count());
365 auto const new_eye =
366 controller().eye() + normalize(move_direction) * passed_time * speed();
367 controller().look_at(new_eye, new_eye - look_dir);
368
369 }
370 //----------------------------------------------------------------------------
371 auto type() const -> std::type_info const& override {
372 return typeid(this_type);
373 }
374};
375//==============================================================================
376template <typename Real>
384 using parent_type::controller;
385 //============================================================================
386 // members
387 //============================================================================
388 Real m_mouse_pos_x, m_mouse_pos_y;
389 bool m_right_button_down = false;
390 //============================================================================
391 // ctor
392 //============================================================================
394 : camera_controller_interface<Real>{controller} {}
396 //============================================================================
397 // methods
398 //============================================================================
399 void on_button_pressed(gl::button b) override {
400 if (b == gl::button::right) {
401 m_right_button_down = true;
402 }
403 }
404 //----------------------------------------------------------------------------
406 if (b == gl::button::right) {
407 m_right_button_down = false;
408 }
409 }
410 //----------------------------------------------------------------------------
411 auto on_cursor_moved(double x, double y) -> void override {
412 if (m_right_button_down) {
413 auto offset_x = static_cast<Real>(gcem::ceil(x)) - m_mouse_pos_x;
414 auto offset_y = static_cast<Real>(gcem::ceil(y)) - m_mouse_pos_y;
415 auto new_eye = controller().eye();
416 new_eye(0) -=
417 static_cast<Real>(offset_x) *
418 controller().orthographic_camera().aspect_ratio() /
419 static_cast<Real>(controller().orthographic_camera().plane_width()) *
420 controller().orthographic_camera().height();
421 new_eye(1) -=
422 static_cast<Real>(offset_y) /
423 static_cast<Real>(controller().orthographic_camera().plane_height()) *
424 controller().orthographic_camera().height();
425 this->look_at(new_eye, new_eye + vec{0, 0, -1});
426 }
427 m_mouse_pos_x = static_cast<Real>(gcem::ceil(x));
428 m_mouse_pos_y = static_cast<Real>(gcem::ceil(y));
429 }
430 //----------------------------------------------------------------------------
431 auto on_wheel_down() -> void override {
432 controller().set_orthographic_height(controller().orthographic_height() /
433 static_cast<Real>(0.9));
434 // controller().orthographic_camera().setup(
435 // controller().eye(), controller().lookat(), controller().up(),
436 // controller().orthographic_camera().width() / 0.9,
437 // controller().orthographic_camera().height() / 0.9,
438 // controller().orthographic_camera().near(),
439 // controller().orthographic_camera().far(),
440 // controller().plane_width(), controller().plane_height());
441 }
442 //----------------------------------------------------------------------------
443 auto on_wheel_up() -> void override {
444 controller().set_orthographic_height(controller().orthographic_height() *
445 static_cast<Real>(0.9));
446 //controller().orthographic_camera().setup(
447 // controller().eye(), controller().lookat(), controller().up(),
448 // controller().orthographic_camera().width() * 0.9,
449 // controller().orthographic_camera().height() * 0.9,
450 // controller().orthographic_camera().near(),
451 // controller().orthographic_camera().far(),
452 // controller().plane_width(), controller().plane_height());
453 }
454 //----------------------------------------------------------------------------
455 auto type() const -> std::type_info const& override {
456 return typeid(this_type);
457 }
458};
459//==============================================================================
460} // namespace tatooine::rendering
461//==============================================================================
462#endif
Definition: concepts.h:33
button
Definition: mouse.h:8
key
Definition: keyboard.h:9
Definition: camera.h:12
constexpr auto normalize(base_tensor< Tensor, T, N > const &t_in) -> vec< T, N >
Definition: tensor_operations.h:100
Definition: window_listener.h:10
Definition: mat.h:14
Definition: camera_controller.h:22
auto perspective_camera() const -> auto const &
Definition: camera_controller.h:38
auto perspective_camera() -> auto &
Definition: camera_controller.h:35
camera_controller< Real > * m_controller
Definition: camera_controller.h:28
virtual void update(std::chrono::duration< double > const &)
Definition: camera_controller.h:60
auto controller() const -> auto const &
Definition: camera_controller.h:54
auto controller() -> auto &
Definition: camera_controller.h:51
virtual auto type() const -> std::type_info const &=0
void look_at(vec3 const &eye, vec3 const &lookat, vec3 const &up={0, 1, 0})
Definition: camera_controller.h:47
auto orthographic_camera() const -> auto const &
Definition: camera_controller.h:44
camera_controller_interface(camera_controller< Real > *controller)
Definition: camera_controller.h:31
auto orthographic_camera() -> auto &
Definition: camera_controller.h:41
Definition: camera_controller.h:64
camera_interface< Real > * m_active_cam
Definition: camera_controller.h:73
auto transform_matrix() const -> mat4
Definition: camera_controller.h:131
auto projection_matrix() const
Definition: camera_controller.h:130
void on_wheel_right() override
Definition: camera_controller.h:195
auto plane_height()
Definition: camera_controller.h:150
camera_controller(size_t const res_x, size_t const res_y)
Definition: camera_controller.h:76
void on_button_released(gl::button b) override
Definition: camera_controller.h:170
auto orthographic_height()
Definition: camera_controller.h:99
auto unproject(Vec2< Real > const &x)
Definition: camera_controller.h:101
auto look_at(vec3 const &eye, arithmetic auto const pitch, arithmetic auto const yaw)
Definition: camera_controller.h:144
void on_resize(int w, int h) override
Definition: camera_controller.h:200
auto perspective_camera() const -> auto const &
Definition: camera_controller.h:122
auto right_direction() const
Definition: camera_controller.h:136
auto controller() const -> auto const &
Definition: camera_controller.h:129
Real m_orthographic_height
Definition: camera_controller.h:70
void use_orthographic_controller()
Definition: camera_controller.h:116
auto perspective_camera() -> auto &
Definition: camera_controller.h:119
auto set_orthographic_height(Real const h)
Definition: camera_controller.h:95
auto plane_width()
Definition: camera_controller.h:149
void use_fps_controller()
Definition: camera_controller.h:113
auto ray(int x, int y) const
Definition: camera_controller.h:153
auto up_direction() const
Definition: camera_controller.h:137
auto look_at(vec3 const &eye, vec3 const &lookat, vec3 const &up={0, 1, 0})
Definition: camera_controller.h:139
auto view_direction() const
Definition: camera_controller.h:138
void on_cursor_moved(double x, double y) override
Definition: camera_controller.h:175
struct perspective_camera< Real > m_pcam
Definition: camera_controller.h:71
void on_wheel_up() override
Definition: camera_controller.h:180
void update(std::chrono::duration< double > const &dt)
Definition: camera_controller.h:209
void use_orthographic_camera()
Definition: camera_controller.h:110
void on_key_pressed(gl::key k) override
Definition: camera_controller.h:155
auto orthographic_camera() const -> auto const &
Definition: camera_controller.h:128
void on_wheel_down() override
Definition: camera_controller.h:185
auto eye() const
Definition: camera_controller.h:135
struct orthographic_camera< Real > m_ocam
Definition: camera_controller.h:72
void on_button_pressed(gl::button b) override
Definition: camera_controller.h:165
auto view_matrix() const
Definition: camera_controller.h:134
auto unproject(Vec4< Real > const &x)
Definition: camera_controller.h:104
auto active_camera() const -> auto const &
Definition: camera_controller.h:100
std::unique_ptr< camera_controller_interface< Real > > m_controller
Definition: camera_controller.h:74
void on_wheel_left() override
Definition: camera_controller.h:190
void use_perspective_camera()
Definition: camera_controller.h:107
void on_key_released(gl::key k) override
Definition: camera_controller.h:160
auto orthographic_camera() -> auto &
Definition: camera_controller.h:125
Interface for camera implementations.
Definition: camera.h:19
Definition: camera_controller.h:217
Real m_mouse_pos_x
Definition: camera_controller.h:229
fps_camera_controller(camera_controller< Real > *controller)
Definition: camera_controller.h:234
void on_button_released(gl::button b) override
Definition: camera_controller.h:300
auto speed() const
Definition: camera_controller.h:331
void update(std::chrono::duration< double > const &dt) override
Definition: camera_controller.h:341
auto type() const -> std::type_info const &override
Definition: camera_controller.h:371
void on_button_pressed(gl::button b) override
Definition: camera_controller.h:294
auto on_key_pressed(gl::key k) -> void override
Definition: camera_controller.h:240
void on_cursor_moved(double x, double y) override
Definition: camera_controller.h:306
buttons
Definition: camera_controller.h:226
void on_key_released(gl::key k) override
Definition: camera_controller.h:267
Definition: camera_controller.h:377
auto on_wheel_up() -> void override
Definition: camera_controller.h:443
void on_button_pressed(gl::button b) override
Definition: camera_controller.h:399
auto on_wheel_down() -> void override
Definition: camera_controller.h:431
auto type() const -> std::type_info const &override
Definition: camera_controller.h:455
orthographic_camera_controller(camera_controller< Real > *controller)
Definition: camera_controller.h:393
Real m_mouse_pos_x
Definition: camera_controller.h:388
auto on_cursor_moved(double x, double y) -> void override
Definition: camera_controller.h:411
void on_button_released(gl::button b) override
Definition: camera_controller.h:405
Definition: orthographic_camera.h:14
Perspective cameras are able to cast rays from one point called 'eye' through an image plane.
Definition: perspective_camera.h:15
Definition: vec.h:12