Thanks to visit codestin.com
Credit goes to canreader.github.io

SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
FreeLookCameraControllerComponent.cpp
Go to the documentation of this file.
4#include <Core/Window.hpp>
5#include <SDL3/SDL.h>
6#include <Events/Event.hpp>
7#include <Math/Math.hpp>
8#include <Math/Quaternion.hpp>
9
10namespace Sleak {
11
13 : CameraController(object) {
14
15 speed = 5.0f;
16 sensitivity = 0.01f;
17 acceleration = 13.5f;
18 damping = 8.0f;
19 maxSpeed = 10.0f;
20
21 YawRange = Math::Vector2D(-360, 360);
22 PitchRange = Math::Vector2D(-89, 89);
23 RollRange = Math::Vector2D(-89, 89);
24
26 velocity = Math::Vector3D::Zero();
27
30 }
31
36
39 return false;
40
41 if (camera) {
43 yaw = atan2(forward.GetX(), forward.GetZ());
44 pitch = -asin(forward.GetY());
45 pitch = Math::Clamp(pitch,
46 static_cast<float>(PitchRange.GetX() * D2R),
47 static_cast<float>(PitchRange.GetY() * D2R));
48 }
49
50 return true;
51 }
52
53 void FreeLookCameraController::Update(float deltaTime) {
54 if (!bIsInitialized || !isEnabled) return;
55
56 UpdateInput(deltaTime);
57 UpdateCamera(deltaTime);
58 }
59
61 bool cursor_set = enabled ? SDL_ShowCursor() : SDL_HideCursor();
62
63 if(!cursor_set) {
64 SLEAK_ERROR("Failed to set cursor visibility {}", SDL_GetError());
65 }
66 }
67
68 void FreeLookCameraController::UpdateInput(float deltaTime) {
69 // TODO: Make a class to handle keyboard LATER
70 // TODO: Make a class to handle mouse inputs LATER
71
72 float x, y;
73 SDL_GetRelativeMouseState(&x, &y);
74
75 if (m_firstFrame) {
76 m_firstFrame = false;
77 return;
78 }
79
80 // Smooth mouse movement using lerp
81 MousePosition = Math::Lerp(MousePosition, Math::Vector2D(x, y), 0.2f);
82
83 // Apply mouse sensitivity
85 pitch += MousePosition.GetY() * sensitivity * (isInvertY ? -1.0f : 1.0f);
86
87 // Clamp pitch to prevent gimbal lock
88 pitch = Math::Clamp(pitch, static_cast<float>(PitchRange.GetX() * D2R), static_cast<float>(PitchRange.GetY() * D2R));
89 }
90
91 void FreeLookCameraController::UpdateCamera(float deltaTime) {
92 if(!camera)
93 return;
94
95 // Calculate rotation using clamped pitch and yaw
96 Math::Quaternion yawRotation = Math::Quaternion(Math::Vector3D::Up(), yaw);
97 Math::Quaternion pitchRotation = Math::Quaternion(Math::Vector3D::Right(), pitch);
98 Math::Quaternion combinedRotation = yawRotation * pitchRotation;
99
100 // Calculate camera axes
101 Math::Vector3D forward = combinedRotation * Math::Vector3D::Forward();
102 Math::Vector3D up = Math::Vector3D::Up();
103 Math::Vector3D right = forward.Cross(up).Normalized();
104
105 // Calculate acceleration based on input
106 Math::Vector3D targetVelocity(
107 translationInput.GetX() * speed, // Right/Left
108 translationInput.GetY() * speed, // Up/Down
109 translationInput.GetZ() * speed // Forward/Backward
110 );
111
112 // Smooth velocity interpolation
113 velocity = Math::Lerp(velocity, targetVelocity, deltaTime * acceleration);
114
115 // Project velocity onto camera's local axes
116 Math::Vector3D worldVelocity =
117 (right * velocity.GetX()) +
118 (up * velocity.GetY()) +
119 (forward * velocity.GetZ());
120
121 // Clamp total velocity magnitude
122 if (worldVelocity.Magnitude() > maxSpeed) {
123 worldVelocity = worldVelocity.Normalized() * maxSpeed;
124 }
125
126 // Apply damping more consistently
127 velocity = velocity * (1.0f - damping * deltaTime);
128
129 // Cancel velocity component along collision normal for smooth sliding
130 auto* rb = owner->GetComponent<RigidbodyComponent>();
131 if (rb && rb->HadCollision()) {
132 Math::Vector3D normal = rb->GetLastCollisionNormal();
133 float dot = worldVelocity.Dot(normal);
134 if (dot < 0.0f) {
135 worldVelocity = worldVelocity - normal * dot;
136 }
137 }
138
139 // Update camera position (collision handled by ColliderComponent + RigidbodyComponent)
140 camera->AddPosition(worldVelocity * deltaTime);
141
142 // Update look target
143 Math::Vector3D lookTarget = camera->GetPosition() + forward;
144 camera->SetLookTarget(lookTarget);
145 }
146
158
170
171 void FreeLookCameraController::ApplyDamping(float deltaTime)
172 {
173 if (translationInput.Magnitude() == 0) {
174 velocity = velocity * (1.0f - damping * deltaTime);
175 if (velocity.Magnitude() < 0.01f) {
176 velocity = Math::Vector3D::Zero();
177 }
178 }
179 }
180
181
182 void FreeLookCameraController::ClampVelocity() {
183 if(velocity.Magnitude() > maxSpeed) {
184 velocity = velocity.Normalize() * maxSpeed;
185 }
186 }
187
190
191 if(!camera)
192 return;
193
194 auto* app = Application::GetInstance();
195 if (app) app->GetWindow().SetRelativeMouseMode(enabled);
196
197 ToggleCursor(!enabled);
198
199 if (enabled) {
200 // Reset velocity and input when enabling
201 velocity = Math::Vector3D::Zero();
203 m_firstFrame = true;
204
205 // Reset yaw and pitch to match the current camera direction
207 yaw = atan2(forward.GetX(), forward.GetZ());
208 pitch = -asin(forward.GetY());
209
210 // Clamp pitch to avoid gimbal lock
211 pitch = Math::Clamp(pitch, static_cast<float>(PitchRange.GetX() * D2R), static_cast<float>(PitchRange.GetY() * D2R));
212 }
213 }
214
215}
#define SLEAK_ERROR(...)
Definition Logger.hpp:22
#define D2R
Definition Math.hpp:8
static Application * GetInstance()
The one Application for this process, or null before construction.
virtual void SetEnabled(bool enabled)
CameraController(GameObject *object)
bool Initialize() override
One-time setup, called after the component is attached and the owner is initialized.
Math::Vector3D GetPosition() const
Definition Camera.hpp:80
Math::Vector3D GetDirection() const
Definition Camera.hpp:82
void SetLookTarget(const Math::Vector3D &target)
Definition Camera.hpp:90
void AddPosition(const Math::Vector3D &position)
Definition Camera.hpp:79
GameObject * owner
Definition Component.hpp:81
static void UnregisterEvent(EventType type, std::string id)
Removes the single handler with matching id from type's handler list.
Definition Event.hpp:163
static std::string RegisterEventHandler(T *instance, void(T::*memberFunction)(const EventT &))
Registers a member-function handler bound to instance, returning an ID for later unregistration.
Definition Event.hpp:149
bool Initialize() override
Derives initial yaw/pitch from the camera's current facing direction.
void ToggleCursor(bool enable) override
Shows or hides the OS cursor and, typically, toggles relative mouse mode.
void SetEnabled(bool enabled) override
Toggles relative mouse mode and, when re-enabling, resets velocity and re-syncs yaw/pitch.
virtual void OnKeyPressed(const Sleak::Events::Input::KeyPressedEvent &e)
Updates translation input state from a key-down event; doubles speed while LCTRL is held.
virtual void OnKeyReleased(const Sleak::Events::Input::KeyReleasedEvent &e)
Clears translation input state from a key-up event.
T * GetComponent()
Finds the first attached component of type T, or nullptr.
constexpr float GetY() const
Definition Vector.hpp:218
constexpr float GetX() const
Definition Vector.hpp:217
static Vector3D Right()
Definition Vector.hpp:500
float GetY() const
Definition Vector.hpp:362
void SetY(float val)
Definition Vector.hpp:367
float GetX() const
Definition Vector.hpp:361
float GetZ() const
Definition Vector.hpp:363
static Vector3D Forward()
Definition Vector.hpp:502
void SetX(float val)
Definition Vector.hpp:366
static Vector3D Zero()
Definition Vector.hpp:496
float Magnitude() const
Definition Vector.hpp:431
void SetZ(float val)
Definition Vector.hpp:368
static Vector3D Up()
Definition Vector.hpp:498
constexpr T Lerp(const T &start, const T &end, float t)
Linear interpolation from start to end; t is clamped to [0,1].
Definition Math.hpp:41
constexpr T Clamp(const T &value, T min, T max)
Definition Math.hpp:17
Root namespace for everything the engine exposes.
Definition Camera.hpp:10