Wizard Engine
2D cross-platform game engine built around SDL2
 
Loading...
Searching...
No Matches
camera.cpp
1/*
2 Wizard Engine
3 Copyright (C) 2023-2024 Zana Domán
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
23#define __WIZARD_ENGINE_INTERNAL__
24
28
29float wze::camera::_x = {};
30float wze::camera::_y = {};
31float wze::camera::_z = {};
32float wze::camera::_angle = {};
33std::array<float, 4> wze::camera::_transformation_matrix = {};
34float wze::camera::_focus = {};
35
36float wze::camera::x() {
37 return _x;
38}
39
40void wze::camera::set_x(float x) {
41 _x = x;
42}
43
44float wze::camera::y() {
45 return _y;
46}
47
48void wze::camera::set_y(float y) {
49 _y = y;
50}
51
52float wze::camera::z() {
53 return _z;
54}
55
56void wze::camera::set_z(float z) {
57 _z = z;
58}
59
60float wze::camera::angle() {
61 return _angle;
62}
63
64void wze::camera::set_angle(float angle) {
65 _angle = angle;
66 _transformation_matrix = math::transformation_matrix(-camera::angle(), 1);
67}
68
69std::array<float, 4> const& wze::camera::transformation_matrix() {
70 return _transformation_matrix;
71}
72
73float wze::camera::focus() {
74 return _focus;
75}
76
77void wze::camera::set_focus(float focus) {
78 _focus = focus;
79}
80
81void wze::camera::initialize() {
82 constexpr float field_of_view = math::to_radians(90);
83
84 set_x(0);
85 set_y(0);
86 set_z(0);
87 set_angle(0);
88 set_focus(math::length(window::width(), window::height()) /
89 (2 * tanf(field_of_view / 2)));
90}
91
92void wze::camera::project(renderable& instance) {
93 float x;
94 float y;
95 float z;
96
97 if (!instance.spatial()) {
98 instance.set_screen_area(
99 {instance.x(), instance.y(), instance.width(), instance.height()});
100 instance.set_screen_angle(instance.angle());
101 return;
102 }
103
104 instance.set_screen_angle(instance.angle() - angle());
105
106 if (instance.z() == camera::z()) {
107 instance.set_screen_area({0, 0, 0, 0});
108 return;
109 }
110
111 x = instance.x() - camera::x();
112 y = instance.y() - camera::y();
113 z = instance.z() - camera::z();
114
115 if (z == focus()) {
116 instance.set_screen_area(
117 {math::transform_x(x, y, transformation_matrix()),
118 math::transform_y(x, y, transformation_matrix()), instance.width(),
119 instance.height()});
120 return;
121 }
122
123 z = focus() / z;
124 x *= z;
125 y *= z;
126 instance.set_screen_area({math::transform_x(x, y, transformation_matrix()),
127 math::transform_y(x, y, transformation_matrix()),
128 instance.width() * z, instance.height() * z});
129}
130
131std::pair<float, float> wze::camera::project(float x, float y, float z) {
132 if (z == camera::z()) {
133 return {0, 0};
134 }
135
136 x -= camera::x();
137 y -= camera::y();
138 z -= camera::z();
139
140 if (z != focus()) {
141 z = focus() / z;
142 x *= z;
143 y *= z;
144 }
145
146 return {math::transform_x(x, y, transformation_matrix()),
147 math::transform_y(x, y, transformation_matrix())};
148}
149
150std::pair<float, float> wze::camera::unproject(float x, float y, float z) {
151 float determinant;
152
153 if (!(bool)focus()) {
154 return {0, 0};
155 }
156
157 z -= camera::z();
158 determinant =
159 transformation_matrix().at(0) * transformation_matrix().at(3) -
160 transformation_matrix().at(1) * transformation_matrix().at(2);
161
162 if (z == focus()) {
163 return {camera::x() + (x * transformation_matrix().at(3) -
164 y * transformation_matrix().at(1)) /
165 determinant,
166 camera::y() + (y * transformation_matrix().at(0) -
167 x * transformation_matrix().at(2)) /
168 determinant};
169 }
170
171 z /= focus();
172 return {camera::x() + (x * transformation_matrix().at(3) -
173 y * transformation_matrix().at(1)) /
174 determinant * z,
175 camera::y() + (y * transformation_matrix().at(0) -
176 x * transformation_matrix().at(2)) /
177 determinant * z};
178}
Subsystem to handle transformations and spatial projections.
static constexpr float to_radians(float degrees)
Converts degrees to radians.
Definition math.hpp:65
static constexpr float transform_y(float x, float y, std::array< float, 4 > const &transformation_matrix)
Transforms the y component of a vector.
Definition math.hpp:162
static std::array< float, 4 > transformation_matrix(float angle, float scale)
Creates a transformation matrix.
Definition math.cpp:57
static float length(float x, float y)
Returns the length of a vector.
Definition math.cpp:33
static constexpr float transform_x(float x, float y, std::array< float, 4 > const &transformation_matrix)
Transforms the x component of a vector.
Definition math.hpp:148
Math modul.
Subsystem to handle game window.