Oxygen Engine
Modern C++ 3D Engine using OpenGL
Loading...
Searching...
No Matches
fps_camera.h
1#ifndef OE_COMPONENT_FPS_CAMERA_H
2#define OE_COMPONENT_FPS_CAMERA_H
3
4#include <chrono>
5#include <glm/gtx/vector_angle.hpp>
6
7#include "../scene/camera.h"
8#include "../core/event_handler.h"
9
10namespace oe::component
11{
15 struct FpsCamera
16 {
17 FpsCamera(oe::scene::Camera* camera) noexcept:
18 ptr_camera(camera)
19 {}
20
24 void update(const core::EventHandler& event_handler, const std::chrono::nanoseconds delta)
25 {
26 assert(ptr_camera);
27
28 auto& camera = *ptr_camera;
29
30 glm::vec2 offset = event_handler.getCursorOffset();
31 float delta_nanoseconds = std::chrono::duration_cast<std::chrono::duration<float>>(delta).count();
32
33 static constexpr float min_pitch_angle = -glm::half_pi<float>(); // Should not go below -pi/2, (must be clamped in setter)
34 static constexpr float max_pitch_angle = glm::half_pi<float>(); // Should not go above pi/2, (must be clamped in setter)
35
36 glm::vec3 forward = camera.getRotation() * glm::vec3{0.0f, 0.0f, 1.0f};
37 // Take the orientation of the player node into account
38 glm::vec3 local_up = glm::vec3{0.0f, -1.0f, 0.0f};
39 // Cannot use cross product here since forward and local_up are almost colinear when looking strait up or down
40 glm::vec3 sideway = camera.getRotation() * glm::vec3{1.0f, 0.0f, 0.0f};
41
42 float delta_yaw = sensitivity * offset.x;
43 float delta_pitch = sensitivity * offset.y;
44
45 float pitch_before = glm::half_pi<float>() - glm::orientedAngle(forward, local_up, sideway);
46 float pitch_after = std::clamp(pitch_before + delta_pitch, min_pitch_angle, max_pitch_angle);
47 delta_pitch = pitch_after - pitch_before;
48
49 // Apply the rotation
50 camera.relativeRotate(glm::angleAxis(delta_yaw, local_up) * glm::angleAxis(delta_pitch, sideway));
51
52 // Compute translation amount based on inputs
53 bool move_forward = event_handler.isKeyPressed(controls.forward);
54 bool move_backward = event_handler.isKeyPressed(controls.backward);
55 bool move_left = event_handler.isKeyPressed(controls.left);
56 bool move_right = event_handler.isKeyPressed(controls.right);
57 bool move_upward = event_handler.isKeyPressed(controls.up);
58 bool move_downward = event_handler.isKeyPressed(controls.down);
59
60 bool move_walk = event_handler.isKeyPressed(controls.walk);
61 bool move_run = event_handler.isKeyPressed(controls.run);
62
63 // -1.0f or +1.0f depending on the inputs for a given axis
64 float front_direction = static_cast<float>(move_forward) - static_cast<float>(move_backward);
65 float strafe_direction = static_cast<float>(move_left) - static_cast<float>(move_right);
66 float upward_direction = static_cast<float>(move_upward) - static_cast<float>(move_downward);
67
68 float camera_speed = default_speed * delta_nanoseconds;
69
70 if (move_walk)
71 {
72 camera_speed *= slow_factor;
73 }
74
75 if (move_run)
76 {
77 camera_speed *= speed_factor;
78 }
79
80 float forward_delta = front_direction * camera_speed;
81 float sideway_delta = strafe_direction * camera_speed;
82 float upward_delta = upward_direction * camera_speed;
83
84 glm::vec3 translation = forward_delta * forward + sideway_delta * sideway + upward_delta * local_up;
85
86 camera.relativeTranslate(-translation);
87 }
88
93 {
94 std::uint32_t forward = core::KeyboardKey::KEY_W;
95 std::uint32_t backward = core::KeyboardKey::KEY_S;
96 std::uint32_t left = core::KeyboardKey::KEY_A;
97 std::uint32_t right = core::KeyboardKey::KEY_D;
98 std::uint32_t up = core::KeyboardKey::KEY_Q;
99 std::uint32_t down = core::KeyboardKey::KEY_Z;
100 std::uint32_t walk = core::KeyboardKey::KEY_LEFT_SHIFT;
101 std::uint32_t run = core::KeyboardKey::KEY_LEFT_CONTROL;
102 };
103
108
112 float default_speed = 6.0f;
113
117 float sensitivity = 0.001f;
118
124 float speed_factor = 4.f;
125
129 float slow_factor = 0.05f;
130
135 };
136}
137
138#endif
Event handler.
Definition event_handler.h:18
bool isKeyPressed(const key_code_t &key, const bool &strict=false) const noexcept
Check if a keyboard key is pressed.
The "eye of the scene".
Definition camera.h:31
const glm::quat & getRotation() const noexcept
Get Rotation component value of the transform.
Definition transform.h:125
void relativeRotate(const glm::quat &quaternion) noexcept
Rotate the transform relative to current rotation.
Definition transform.h:323
void relativeTranslate(const glm::vec3 &translation) noexcept
Translate the transform from current position.
Definition transform.h:281
Scene / node components (camera, lighting, ...).
Definition debug.h:17
Controls to move the FPS Camera.
Definition fps_camera.h:93
KeyBindings controls
Keybindings to control the FPS Camera.
Definition fps_camera.h:107
oe::scene::Camera * ptr_camera
pointer to a camera to control
Definition fps_camera.h:134
void update(const core::EventHandler &event_handler, const std::chrono::nanoseconds delta)
Update camera transform from the input.
Definition fps_camera.h:24
float speed_factor
Speed factor.
Definition fps_camera.h:124
float slow_factor
Slow factor.
Definition fps_camera.h:129
float default_speed
Camera Speed.
Definition fps_camera.h:112
float sensitivity
FPS Camera mouse sensitivity.
Definition fps_camera.h:117