Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
CameraComponent.cpp
Go to the documentation of this file.
5#include <glm/gtc/matrix_transform.hpp>
6#include <plog/Log.h>
7
8namespace EngineCore {
9
10 // Static pointer to track the active camera
12
14 std::shared_ptr<SceneNode> sceneNode,
15 float fov,
16 float nearPlane,
17 float farPlane)
18 : LogicComponent(owningScene)
19 , sceneNode_(std::move(sceneNode))
20 , fov_(fov)
21 , nearPlane_(nearPlane)
22 , farPlane_(farPlane)
23 {
24 setCanTick(false); // Camera doesn't need to tick by default
25 }
26
29
30 auto& registry = Ecs::RegistryManager::get();
31 cameraEntity_ = registry.create();
32
33 // Store camera properties in ECS for easy querying
34 auto& props = registry.emplace<Ecs::CameraProperties>(cameraEntity_);
35 props.fov = fov_;
36 props.nearPlane = nearPlane_;
37 props.farPlane = farPlane_;
38 props.aspectRatio = aspectRatio_;
39
41
42 PLOGD << "CameraComponent initialized with FOV=" << fov_ << " near=" << nearPlane_ << " far=" << farPlane_;
43 }
44
45 void CameraComponent::tick(double /*deltaTime*/) {
46 // Camera component doesn't need to tick - view matrix is computed on demand from SceneNode
47 // Projection matrix is only updated when parameters change
48 }
49
51 // Clear the static pointer if this was the active camera
52 if (s_activeCamera == this) {
53 s_activeCamera = nullptr;
54 }
55
56 if (cameraEntity_ != entt::null) {
57 auto& registry = Ecs::RegistryManager::get();
58 // Remove active tag if present
59 registry.remove<Ecs::ActiveCamera>(cameraEntity_);
60 registry.destroy(cameraEntity_);
61 cameraEntity_ = entt::null;
62 }
63
65 }
66
67 void CameraComponent::setActive(bool active) {
68 auto& registry = Ecs::RegistryManager::get();
69
70 if (active) {
71 // First, remove ActiveCamera tag from any other cameras
72 auto view = registry.view<Ecs::ActiveCamera>();
73 for (auto entity : view) {
74 registry.remove<Ecs::ActiveCamera>(entity);
75 }
76
77 // Clear previous active camera pointer
78 s_activeCamera = nullptr;
79
80 // Add ActiveCamera tag to this camera's entity
81 if (cameraEntity_ != entt::null && !registry.all_of<Ecs::ActiveCamera>(cameraEntity_)) {
82 registry.emplace<Ecs::ActiveCamera>(cameraEntity_);
83 }
84
85 // Set this as the active camera
86 s_activeCamera = this;
87 PLOGD << "Camera set as active";
88 } else {
89 // Remove ActiveCamera tag from this camera
90 if (cameraEntity_ != entt::null) {
91 registry.remove<Ecs::ActiveCamera>(cameraEntity_);
92 }
93
94 // Clear the static pointer if this was the active camera
95 if (s_activeCamera == this) {
96 s_activeCamera = nullptr;
97 }
98 }
99 }
100
102 if (cameraEntity_ == entt::null) {
103 return false;
104 }
105 auto& registry = Ecs::RegistryManager::get();
106 return registry.all_of<Ecs::ActiveCamera>(cameraEntity_);
107 }
108
110 if (!sceneNode_) {
111 return glm::mat4(1.0f);
112 }
113
114 // The view matrix is the inverse of the camera's world transform
115 // Camera looks down -Z in its local space (OpenGL/Vulkan convention)
116 return glm::inverse(sceneNode_->getWorldMatrix());
117 }
118
120 if (projectionDirty_) {
121 const_cast<CameraComponent*>(this)->updateProjectionMatrix();
122 }
124 }
125
129
130 void CameraComponent::setFov(float fov) {
131 fov_ = fov;
132 projectionDirty_ = true;
133
134 if (cameraEntity_ != entt::null) {
135 auto& registry = Ecs::RegistryManager::get();
136 if (auto* props = registry.try_get<Ecs::CameraProperties>(cameraEntity_)) {
137 props->fov = fov;
138 }
139 }
140 }
141
142 void CameraComponent::setAspectRatio(float aspectRatio) {
143 aspectRatio_ = aspectRatio;
144 projectionDirty_ = true;
145
146 if (cameraEntity_ != entt::null) {
147 auto& registry = Ecs::RegistryManager::get();
148 if (auto* props = registry.try_get<Ecs::CameraProperties>(cameraEntity_)) {
149 props->aspectRatio = aspectRatio;
150 }
151 }
152 }
153
154 void CameraComponent::setNearPlane(float nearPlane) {
155 nearPlane_ = nearPlane;
156 projectionDirty_ = true;
157
158 if (cameraEntity_ != entt::null) {
159 auto& registry = Ecs::RegistryManager::get();
160 if (auto* props = registry.try_get<Ecs::CameraProperties>(cameraEntity_)) {
161 props->nearPlane = nearPlane;
162 }
163 }
164 }
165
166 void CameraComponent::setFarPlane(float farPlane) {
167 farPlane_ = farPlane;
168 projectionDirty_ = true;
169
170 if (cameraEntity_ != entt::null) {
171 auto& registry = Ecs::RegistryManager::get();
172 if (auto* props = registry.try_get<Ecs::CameraProperties>(cameraEntity_)) {
173 props->farPlane = farPlane;
174 }
175 }
176 }
177
179 if (!sceneNode_) {
180 return glm::vec3(0.0f);
181 }
182 const auto& worldMatrix = sceneNode_->getWorldMatrix();
183 return glm::vec3(worldMatrix[3]);
184 }
185
187 if (!sceneNode_) {
188 return glm::vec3(0.0f, 0.0f, -1.0f);
189 }
190 const auto& worldMatrix = sceneNode_->getWorldMatrix();
191 // Forward is -Z in camera space
192 return -glm::normalize(glm::vec3(worldMatrix[2]));
193 }
194
196 if (!sceneNode_) {
197 return glm::vec3(1.0f, 0.0f, 0.0f);
198 }
199 const auto& worldMatrix = sceneNode_->getWorldMatrix();
200 // Right is +X in camera space
201 return glm::normalize(glm::vec3(worldMatrix[0]));
202 }
203
205 if (!sceneNode_) {
206 return glm::vec3(0.0f, 1.0f, 0.0f);
207 }
208 const auto& worldMatrix = sceneNode_->getWorldMatrix();
209 // Up is +Y in camera space
210 return glm::normalize(glm::vec3(worldMatrix[1]));
211 }
212
214 // Reverse-Z perspective projection for better depth precision
215 // Near plane maps to 1.0, far plane maps to 0.0
216 float fovRadians = glm::radians(fov_);
217 float tanHalfFov = glm::tan(fovRadians * 0.5f);
218
219 cachedProjectionMatrix_ = glm::mat4(0.0f);
220 cachedProjectionMatrix_[0][0] = 1.0f / (aspectRatio_ * tanHalfFov);
221 cachedProjectionMatrix_[1][1] = 1.0f / tanHalfFov;
223 cachedProjectionMatrix_[2][3] = -1.0f;
225
226 // Vulkan uses a different clip space convention - flip Y
227 cachedProjectionMatrix_[1][1] *= -1.0f;
228
229 projectionDirty_ = false;
230 }
231
235
237 return s_activeCamera != nullptr;
238 }
239}
static entt::registry & get()
Gets the registry for all components.
A camera component that provides view and projection matrices based on its SceneNode transform....
void endPlay() override
Called when the component is removed or the game ends.
bool isActive() const
Checks if this camera is currently the active camera.
void setAspectRatio(float aspectRatio)
Sets the aspect ratio (width / height)
glm::vec3 getForwardVector() const
Gets the forward direction vector of the camera.
glm::mat4 getProjectionMatrix() const
Gets the projection matrix based on FOV, aspect ratio, and clipping planes.
CameraComponent(Scene *owningScene, std::shared_ptr< SceneNode > sceneNode, float fov=60.0f, float nearPlane=0.01f, float farPlane=1000.0f)
Constructs a camera component with default parameters.
glm::mat4 getViewProjectionMatrix() const
Gets the combined view-projection matrix.
glm::vec3 getWorldPosition() const
Gets the camera's world position from its scene node.
glm::vec3 getUpVector() const
Gets the up direction vector of the camera.
glm::vec3 getRightVector() const
Gets the right direction vector of the camera.
void setActive(bool active)
Sets this camera as the active camera for rendering.
glm::mat4 getViewMatrix() const
Gets the view matrix computed from the camera's world transform.
void setFov(float fov)
Sets the vertical field of view.
void tick(double deltaTime) override
Called every frame if ticking is enabled.
void beginPlay() override
Called when the component is added to the scene or the game starts.
void setNearPlane(float nearPlane)
Sets the near clipping plane distance.
std::shared_ptr< SceneNode > sceneNode_
void setFarPlane(float farPlane)
Sets the far clipping plane distance.
virtual void endPlay()
Called when the component is removed or the game ends.
void setCanTick(bool enable)
Enables or disables ticking for this component.
virtual void beginPlay()
Called when the component is added to the scene or the game starts.
LogicComponent(Scene *owningScene)
A scene is the overarching structure which can spawn actors.
Definition Scene.h:17
Log category system implementation.
static CameraComponent * s_activeCamera
bool hasActiveCamera()
Checks if there is an active camera set.
CameraComponent * getActiveCamera()
Gets the currently active camera.
STL namespace.
Tag for the active camera in the scene.
Definition EcsData.h:317
Camera properties for projection matrix calculation.
Definition EcsData.h:322
float fov
Vertical field of view in degrees.
Definition EcsData.h:323