Brenta Engine 1.2
Loading...
Searching...
No Matches
camera.cpp
1// SPDX-License-Identifier: MIT
2// Author: Giovanni Santini
3// Mail: giovanni.santini@proton.me
4// Github: @San7o
5
6#include <brenta/renderer/camera.hpp>
7#include <brenta/logger.hpp>
8
9#include <cmath>
10
11using namespace brenta;
12
13Camera::Camera(Config conf)
14{
15 this->proj_type = conf.proj_type;
16 this->fov = conf.fov;
17 this->world_up = conf.world_up;
18 this->front = conf.front;
19 this->up = conf.up;
20 this->right = conf.right;
21
22 this->set_pos(conf.pos); // updates world_pos and other members
23 return;
24}
25
26Camera::Camera(Builder& builder)
27{
28 *this = builder.build();
29}
30
31glm::mat4 Camera::get_view_matrix() const
32{
33 try
34 {
35 Spherical spos = std::get<Spherical>(this->pos);
36 return glm::lookAt(this->transform.get_pos(), spos.center, this->world_up);
37
38 }
39 catch ([[maybe_unused]] const std::bad_variant_access& ex)
40 {
41 return glm::lookAt(this->transform.get_pos(),
42 this->transform.get_pos() + this->front, this->up);
43 }
44}
45
46// The projection matrix maps the verticies inside a cube called the
47// Canonical Cube where all axis are between -1 and 1
48glm::mat4 Camera::get_projection_matrix(int window_width,
49 int window_height) const
50{
51 switch (this->proj_type)
52 {
53 case ProjectionType::Perspective:
54
55 // The perspective calculates the position of a vertex from 3D
56 // view space to clip space using a technique base on triangle
57 // similarity.
58 return glm::perspective(glm::radians(this->fov),
59 (float) window_width
60 / (float) window_height,
61 0.1f, 1000.0f);
62 case ProjectionType::Orthographic:
63 return glm::ortho((float) -window_width / 2.0f,
64 (float) window_width / 2.0f,
65 (float) -window_height / 2.0f,
66 (float) window_height / 2.0f, 0.1f, 100.0f);
67 default:
68 return glm::mat4(1.0f);
69 }
70}
71
72void Camera::update_spherical(Spherical pos)
73{
74 this->transform.set_x(sin(pos.theta) * cos(pos.phi) * pos.radius + pos.center.x);
75 this->transform.set_y(cos(pos.theta) * pos.radius + pos.center.y);
76 this->transform.set_z(sin(pos.theta) * sin(pos.phi) * pos.radius + pos.center.z);
77
78 return;
79}
80
81void Camera::update_aircraft(Aircraft pos)
82{
83 // calculate the new Front vector
84 glm::vec3 new_front;
85 new_front.x =
86 cos(glm::radians(pos.yaw)) * cos(glm::radians(pos.pitch));
87 new_front.y = sin(glm::radians(pos.pitch));
88 new_front.z =
89 sin(glm::radians(pos.yaw)) * cos(glm::radians(pos.pitch));
90 this->front = glm::normalize(new_front);
91 // also re-calculate the Right and Up vector
92 this->right = glm::normalize(glm::cross(this->front, this->world_up));
93 this->up = glm::normalize(glm::cross(this->right, this->front));
94 this->transform.set_pos(pos.pos);
95 return;
96}
97
98//
99// Getters
100//
101
102Camera::ProjectionType Camera::get_projection_type() const
103{
104 return this->proj_type;
105}
106
107std::variant<Camera::Spherical, Camera::Aircraft> Camera::get_pos() const
108{
109 return this->pos;
110}
111
112Transform Camera::get_transform()
113{
114 return this->transform;
115}
116
117float Camera::get_fov() const
118{
119 return this->fov;
120}
121
122glm::vec3 Camera::get_front() const
123{
124 return this->front;
125}
126
127glm::vec3 Camera::get_up() const
128{
129 return this->up;
130}
131
132glm::vec3 Camera::get_right() const
133{
134 return this->right;
135}
136
137//
138// Setters
139//
140
141void Camera::set_projection_type(ProjectionType projection_type)
142{
143 this->proj_type = projection_type;
144}
145
146void Camera::set_pos(std::variant<Spherical, Aircraft> new_pos)
147{
148 this->pos = new_pos;
149
150 try
151 {
152 this->update_spherical(std::get<Spherical>(this->pos));
153 }
154 catch ([[maybe_unused]] const std::bad_variant_access& ex)
155 {
156 this->update_aircraft(std::get<Aircraft>(this->pos));
157 }
158
159 return;
160}
161
162glm::vec3 Camera::get_world_up() const
163{
164 return this->world_up;
165}
166
167void Camera::set_world_up(glm::vec3 world_up)
168{
169 this->world_up = world_up;
170}
171
172void Camera::set_fov(float fov)
173{
174 this->fov = fov;
175}
176
177void Camera::set_front(glm::vec3 front)
178{
179 this->front = front;
180}
181
182void Camera::set_up(glm::vec3 up)
183{
184 this->up = up;
185}
186
187void Camera::set_right(glm::vec3 right)
188{
189 this->right = right;
190}
191
192//
193// Builder
194//
195
196// Camera::Spherical builder
197
199Camera::Spherical::Builder::center(glm::vec3 center)
200{
201 this->scam.center = center;
202 return *this;
203}
204
206Camera::Spherical::Builder::theta(float theta)
207{
208 this->scam.theta = theta;
209 return *this;
210}
211
213Camera::Spherical::Builder::phi(float phi)
214{
215 this->scam.phi = phi;
216 return *this;
217}
218
220Camera::Spherical::Builder::radius(float radius)
221{
222 this->scam.radius = radius;
223 return *this;
224}
225
226Camera::Spherical Camera::Spherical::Builder::build()
227{
228 return this->scam;
229}
230
231// Camera::aircraft Builder
232
234Camera::Aircraft::Builder::pos(glm::vec3 pos)
235{
236 this->acam.pos = pos;
237 return *this;
238}
239
241Camera::Aircraft::Builder::yaw(float yaw)
242{
243 this->acam.yaw = yaw;
244 return *this;
245}
246
248Camera::Aircraft::Builder::pitch(float pitch)
249{
250 this->acam.pitch = pitch;
251 return *this;
252}
253
255Camera::Aircraft::Builder::roll(float roll)
256{
257 this->acam.roll = roll;
258 return *this;
259}
260
261Camera::Aircraft Camera::Aircraft::Builder::build()
262{
263 return this->acam;
264}
265
266// Camera Builder
267
269Camera::Builder::projection_type(Camera::ProjectionType projection_type)
270{
271 this->conf.proj_type = projection_type;
272 return *this;
273}
274
275Camera::Builder &Camera::Builder::position(std::variant<Camera::Spherical,
276 Camera::Aircraft> pos)
277{
278 this->conf.pos = pos;
279 return *this;
280}
281
282Camera::Builder &Camera::Builder::fov(float fov)
283{
284 this->conf.fov = fov;
285 return *this;
286}
287
288Camera::Builder &Camera::Builder::world_up(glm::vec3 world_up)
289{
290 this->conf.world_up = world_up;
291 return *this;
292}
293
294Camera::Builder &Camera::Builder::front(glm::vec3 front)
295{
296 this->conf.front = front;
297 return *this;
298}
299
300Camera::Builder &Camera::Builder::up(glm::vec3 up)
301{
302 this->conf.up = up;
303 return *this;
304}
305
306Camera::Builder &Camera::Builder::right(glm::vec3 right)
307{
308 this->conf.right = right;
309 return *this;
310}
311
312brenta::Camera Camera::Builder::build()
313{
314 return Camera(this->conf);
315}