Engine²
Open-source game engine written in C++.
Loading...
Searching...
No Matches
OrbitalChaseBehavior.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cmath>
5
6#include <GLFW/glfw3.h>
7#include <glm/glm.hpp>
8#include <glm/gtc/quaternion.hpp>
9
10#include "component/Camera.hpp"
12#include "core/Core.hpp"
15#include "resource/Window.hpp"
17#include "utils/CameraUtils.hpp"
18#include "utils/InputUtils.hpp"
19
20namespace CameraMovement::Utils {
22 public:
23 explicit OrbitalChaseBehavior(Engine::Core &core, Engine::Entity target) : _core(&core), _target(target)
24 {
26 {
27 Log::Warning("InputManager resource not found in core. OrbitalChaseBehavior will not function properly.");
28 return;
29 }
31 {
32 Log::Warning("CameraManager resource not found in core. OrbitalChaseBehavior will not function properly.");
33 return;
34 }
35
36 auto &inputManager = core.GetResource<Input::Resource::InputManager>();
38 inputManager.RegisterMouseButtonCallback([this](Engine::Core &core, int button, int action, int mods) {
39 HandleMouseButton(core, button, action, mods);
40 });
41
42 _cursorPosCallbackId = inputManager.RegisterCursorPosCallback(
43 [this](Engine::Core &core, double xpos, double ypos) { HandleCursorPos(core, xpos, ypos); });
44
45 _scrollCallbackId = inputManager.RegisterScrollCallback(
46 [this](Engine::Core &core, double xoffset, double yoffset) { HandleScroll(core, xoffset, yoffset); });
47
48 auto &cameraManager = core.GetResource<CameraMovement::Resource::CameraManager>();
49 _lastMouseX = cameraManager.GetLastMouseX();
50 _lastMouseY = cameraManager.GetLastMouseY();
51 }
52
54 {
55 try
56 {
57 if (_core->HasResource<Input::Resource::InputManager>())
58 {
59 auto &inputManager = _core->GetResource<Input::Resource::InputManager>();
61 {
62 inputManager.DeleteMouseButtonCallback(_mouseButtonCallbackId);
63 }
64 if (_cursorPosCallbackId != 0)
65 {
66 inputManager.DeleteCursorPosCallback(_cursorPosCallbackId);
67 }
68 if (_scrollCallbackId != 0)
69 {
70 inputManager.DeleteScrollCallback(_scrollCallbackId);
71 }
72 }
73 }
74 catch (const std::exception &e)
75 {
76 try
77 {
78 Log::Error(fmt::format("Failed to unregister camera behavior callbacks: {}", e.what()));
79 }
80 catch (const std::exception &logError)
81 {
82 }
83 }
84 }
85
87 Object::Component::Transform &cameraTransform, Object::Component::Camera &, float) override
88 {
89 auto &window = core.GetResource<Window::Resource::Window>();
90
91 if (!_target.IsAlive())
92 {
94 {
95 Log::Warning("Camera target entity is not alive. OrbitalChaseBehavior will not update.");
97 }
98 return;
99 }
101
102 manager.SetWasCursorMasked(window.IsCursorMasked());
103
104 this->UpdatePosition(cameraTransform);
105 this->UpdateRotation(cameraTransform);
106 }
107
108 Engine::Entity GetTarget() const { return _target; }
109
110 void SetTarget(Engine::Entity newTarget) { _target = newTarget; }
111
112 float GetScrollSensitivity() const { return _scrollSensitivity; }
113
114 void SetScrollSensitivity(float newScrollSensitivity) { _scrollSensitivity = newScrollSensitivity; }
115
116 float GetMinDistance() const { return _minDistance; }
117
118 void SetMinDistance(float newMinDistance)
119 {
120 _minDistance = newMinDistance;
122 {
123 Log::Warning("MinDistance of OrbitalChaseBehavior is greater than MaxDistance");
124 }
125 }
126
127 float GetMaxDistance() const { return _maxDistance; }
128
129 void SetMaxDistance(float newMaxDistance)
130 {
131 _maxDistance = newMaxDistance;
133 {
134 Log::Warning("MaxDistance of OrbitalChaseBehavior is less than MinDistance");
135 }
136 }
137
138 private:
140 {
141 auto &targetTransform = _target.GetComponents<Object::Component::Transform>();
142 const auto &targetPos = targetTransform.GetPosition();
143 const auto &targetRot = targetTransform.GetRotation();
144
145 float horizontalDistance = _distance * std::cos(_pitch);
146 glm::vec3 localOffset;
147 localOffset.x = horizontalDistance * std::sin(_yaw);
148 localOffset.y = _distance * std::sin(_pitch);
149 localOffset.z = -horizontalDistance * std::cos(_yaw);
150
151 glm::vec3 horizontalOffset = targetRot * glm::vec3(localOffset.x, 0.0f, localOffset.z);
152 glm::vec3 cameraPosition = targetPos + horizontalOffset + glm::vec3(0.0f, localOffset.y, 0.0f);
153
154 cameraTransform.SetPosition(cameraPosition);
155 }
156
158 {
159 const auto &targetPosition = _target.GetComponents<Object::Component::Transform>().GetPosition();
160 glm::quat lookRotation = CameraMovement::Utils::ComputeLookAtQuaternion(
161 cameraTransform.GetPosition(), targetPosition, glm::vec3(0.0f, 1.0f, 0.0f));
162 cameraTransform.SetRotation(lookRotation);
163 }
164
165 void HandleMouseButton(Engine::Core &, int button, int action, int)
166 {
167 if (button == GLFW_MOUSE_BUTTON_RIGHT)
168 {
169 _isDragging = (action == GLFW_PRESS);
170 }
171 }
172
173 void HandleCursorPos(Engine::Core &core, float xpos, float ypos)
174 {
175 auto &cameraManager = core.GetResource<CameraMovement::Resource::CameraManager>();
176 auto &window = core.GetResource<Window::Resource::Window>();
177
178 bool shouldRotate =
179 (window.IsCursorMasked() || _isDragging) && !(window.IsCursorMasked() && !cameraManager.WasCursorMasked());
180
181 if (shouldRotate)
182 {
183 float sensitivity = cameraManager.GetMouseSensitivity() * 2.0f;
184
185 float dx = xpos - _lastMouseX;
186 float dy = ypos - _lastMouseY;
187
188 _yaw -= dx * sensitivity;
189 _pitch += dy * sensitivity;
190
191 _yaw = glm::mod(_yaw, 2.0f * glm::pi<float>());
192 _pitch = glm::clamp(_pitch, -glm::half_pi<float>() + 0.01f, glm::half_pi<float>() - 0.01f);
193 }
194
195 _lastMouseX = xpos;
196 _lastMouseY = ypos;
197 }
198
199 void HandleScroll(Engine::Core &, double, double yoffset)
200 {
201 _distance -= yoffset * _scrollSensitivity;
202 _distance = std::max(_minDistance, std::min(_maxDistance, _distance));
203 }
204
207
208 float _yaw = 0.0f;
209 float _pitch = 0.35f;
210 float _distance = 8.0f;
211 float _minDistance = 0.001f;
212 float _maxDistance = 50.0f;
213
214 float _scrollSensitivity = 1.1f;
215
216 bool _isDragging = false;
217 float _lastMouseX = 0.0;
218 float _lastMouseY = 0.0;
219
223
225};
226} // namespace CameraMovement::Utils
CameraManager is a resource that manages the active camera entity.
Definition CameraManager.hpp:24
void SetWasCursorMasked(bool masked)
Set whether the cursor was masked in the previous frame.
Definition CameraManager.hpp:177
bool WasCursorMasked() const
Check if the cursor was masked in the previous frame.
Definition CameraManager.hpp:184
Base interface for camera behaviors.
Definition CameraBehavior.hpp:18
void HandleScroll(Engine::Core &, double, double yoffset)
Definition OrbitalChaseBehavior.hpp:199
float GetMaxDistance() const
Definition OrbitalChaseBehavior.hpp:127
float _distance
Definition OrbitalChaseBehavior.hpp:210
FunctionUtils::FunctionID _cursorPosCallbackId
Definition OrbitalChaseBehavior.hpp:221
void SetMinDistance(float newMinDistance)
Definition OrbitalChaseBehavior.hpp:118
Engine::Entity _target
Definition OrbitalChaseBehavior.hpp:206
float GetMinDistance() const
Definition OrbitalChaseBehavior.hpp:116
float _scrollSensitivity
Definition OrbitalChaseBehavior.hpp:214
bool _hasWarnedInvalidTarget
Definition OrbitalChaseBehavior.hpp:224
float _minDistance
Definition OrbitalChaseBehavior.hpp:211
Engine::Entity GetTarget() const
Definition OrbitalChaseBehavior.hpp:108
void HandleCursorPos(Engine::Core &core, float xpos, float ypos)
Definition OrbitalChaseBehavior.hpp:173
void SetMaxDistance(float newMaxDistance)
Definition OrbitalChaseBehavior.hpp:129
bool _isDragging
Definition OrbitalChaseBehavior.hpp:216
Engine::Core * _core
Definition OrbitalChaseBehavior.hpp:205
void UpdateRotation(Object::Component::Transform &cameraTransform)
Definition OrbitalChaseBehavior.hpp:157
float _yaw
Definition OrbitalChaseBehavior.hpp:208
void Update(Engine::Core &core, CameraMovement::Resource::CameraManager &manager, Object::Component::Transform &cameraTransform, Object::Component::Camera &, float) override
Update the camera behavior.
Definition OrbitalChaseBehavior.hpp:86
FunctionUtils::FunctionID _scrollCallbackId
Definition OrbitalChaseBehavior.hpp:222
float GetScrollSensitivity() const
Definition OrbitalChaseBehavior.hpp:112
FunctionUtils::FunctionID _mouseButtonCallbackId
Definition OrbitalChaseBehavior.hpp:220
float _pitch
Definition OrbitalChaseBehavior.hpp:209
float _lastMouseY
Definition OrbitalChaseBehavior.hpp:218
void UpdatePosition(Object::Component::Transform &cameraTransform)
Definition OrbitalChaseBehavior.hpp:139
void SetScrollSensitivity(float newScrollSensitivity)
Definition OrbitalChaseBehavior.hpp:114
void HandleMouseButton(Engine::Core &, int button, int action, int)
Definition OrbitalChaseBehavior.hpp:165
void SetTarget(Engine::Entity newTarget)
Definition OrbitalChaseBehavior.hpp:110
float _maxDistance
Definition OrbitalChaseBehavior.hpp:212
OrbitalChaseBehavior(Engine::Core &core, Engine::Entity target)
Definition OrbitalChaseBehavior.hpp:23
float _lastMouseX
Definition OrbitalChaseBehavior.hpp:217
~OrbitalChaseBehavior() override
Definition OrbitalChaseBehavior.hpp:53
The core is the place where all the data of the engine is stored. It contains the registry (entities)...
Definition Core.hpp:33
TResource & GetResource()
Get a reference of a resource.
Definition Core.ipp:14
bool HasResource() const
Check if a resource is registered in the core.
Definition Core.ipp:24
Wrapper class providing a convenient interface for entity manipulation with the Core....
Definition Entity.hpp:20
Definition InputManager.hpp:18
Definition Window.hpp:25
Definition CameraManager.hpp:12
glm::quat ComputeLookAtQuaternion(const glm::vec3 &eye, const glm::vec3 &target, const glm::vec3 &up)
Compute a quaternion that represents a "look at" rotation.
Definition CameraUtils.hpp:19
std::size_t FunctionID
FunctionID class to represent a unique identifier for functions.
Definition FunctionID.hpp:9
void Error(const T &msg) noexcept(false)
Definition Logger.hpp:34
void Warning(const T &msg) noexcept(false)
Definition Logger.hpp:32
Definition Camera.hpp:10
Definition Transform.hpp:18
void SetPosition(const glm::vec3 &newPosition)
Definition Transform.hpp:42
const glm::vec3 & GetPosition() const
Definition Transform.hpp:37
void SetRotation(const glm::quat &newRotation)
Definition Transform.hpp:62