sandbox
Loading...
Searching...
No Matches
camera.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_SCENES_COMPONENTS_CAMERA_HPP_
3#define LIBSBX_SCENES_COMPONENTS_CAMERA_HPP_
4
5#include <variant>
6
7#include <array>
8#include <cstdint>
9
10#include <libsbx/utility/enum.hpp>
11
12#include <libsbx/math/vector3.hpp>
13#include <libsbx/math/matrix3x3.hpp>
14#include <libsbx/math/matrix4x4.hpp>
15#include <libsbx/math/volume.hpp>
16#include <libsbx/math/sphere.hpp>
17#include <libsbx/math/plane.hpp>
18#include <libsbx/math/box.hpp>
19
20#include <libsbx/containers/static_vector.hpp>
21
22#include <libsbx/core/engine.hpp>
23
24// #include <libsbx/devices/devices_module.hpp>
25// #include <libsbx/devices/window.hpp>
26
27#include <libsbx/graphics/graphics_module.hpp>
28
29namespace sbx::scenes {
30
31class frustum : public math::box {
32
33 inline static constexpr auto left_plane = std::size_t{0u};
34 inline static constexpr auto right_plane = std::size_t{0u};
35 inline static constexpr auto top_plane = std::size_t{1u};
36 inline static constexpr auto bottom_plane = std::size_t{1u};
37 inline static constexpr auto near_plane = std::size_t{2u};
38 inline static constexpr auto far_plane = std::size_t{2u};
39
40 inline static constexpr auto margin = std::float_t{0.5f};
41
42public:
43
44 frustum(const math::matrix4x4& view_projection)
45 : math::box{_extract_planes(view_projection)} { }
46
47 auto intersects(const math::volume& aabb, const math::matrix4x4& model) const noexcept -> bool {
48 const auto world_volume = math::volume::transformed(aabb, model);
49
50 for (const auto& plane : planes()) {
51 const auto positive = math::vector3{
52 (plane.normal().x() >= 0 ? world_volume.max().x() : world_volume.min().x()),
53 (plane.normal().y() >= 0 ? world_volume.max().y() : world_volume.min().y()),
54 (plane.normal().z() >= 0 ? world_volume.max().z() : world_volume.min().z())
55 };
56
57 const auto distance = plane.distance_to_point(positive);
58
59 if (distance < -margin) {
60 return false;
61 }
62 }
63
64 return true;
65 }
66
67private:
68
69 static auto _extract_planes(const math::matrix4x4& matrix) -> std::array<math::plane, 6u> {
70 return std::array<math::plane, 6u>{
71 _extract_plane<right_plane>(matrix),
72 _extract_plane<left_plane>(matrix),
73 _extract_plane<bottom_plane>(matrix),
74 _extract_plane<top_plane>(matrix),
75 _extract_plane<far_plane>(matrix),
76 _extract_plane<near_plane>(matrix)
77 };
78 }
79
80 template<std::size_t Side>
81 static auto _extract_plane(const math::matrix4x4& matrix) -> math::plane {
82 constexpr auto sign = (Side == right_plane || Side == top_plane || Side == far_plane) ? -1.0f : 1.0f;
83
84 const auto plane = math::vector4{
85 matrix[0][3] + sign * matrix[0][Side],
86 matrix[1][3] + sign * matrix[1][Side],
87 matrix[2][3] + sign * matrix[2][Side],
88 matrix[3][3] + sign * matrix[3][Side]
89 };
90
91 return math::plane::normalized(math::plane{plane});
92 }
93
94}; // struct frustum
95
96class camera {
97
98public:
99
100 camera(const math::angle& field_of_view, std::float_t near_plane, std::float_t far_plane)
101 : _field_of_view{field_of_view},
102 _near_plane{near_plane},
103 _far_plane{far_plane} { }
104
105 auto field_of_view() const noexcept -> const math::angle& {
106 return _field_of_view;
107 }
108
109 auto set_field_of_view(const math::angle& field_of_view) noexcept -> void {
110 _field_of_view = field_of_view;
111 }
112
113 auto near_plane() const noexcept -> std::float_t {
114 return _near_plane;
115 }
116
117 auto far_plane() const noexcept -> std::float_t {
118 return _far_plane;
119 }
120
121 auto projection(std::float_t aspect_ratio) const noexcept -> math::matrix4x4 {
122 return math::matrix4x4::perspective(_field_of_view, aspect_ratio, _near_plane, _far_plane);
123 }
124
125 auto projection(std::float_t aspect_ratio, std::float_t near, std::float_t far) const noexcept -> math::matrix4x4 {
126 return math::matrix4x4::perspective(_field_of_view, aspect_ratio, near, far);
127 }
128
129private:
130
131 math::angle _field_of_view;
132 std::float_t _near_plane;
133 std::float_t _far_plane;
134
135}; // class camera
136
137} // namespace sbx::scenes
138
139#endif // LIBSBX_SCENES_COMPONENTS_CAMERA_HPP_
Box / frustum-style volume intersection helpers.
Unified angle type stored internally in radians.
Definition: angle.hpp:591
Plane-based box represented by six clipping planes.
Definition: box.hpp:46
auto plane(const size_type index) const noexcept -> const plane_type &
Returns the plane at a given index.
Definition: box.ipp:39
auto planes() const noexcept -> const std::array< plane_type, 6u > &
Returns the plane array backing this box.
Definition: box.ipp:33
Definition: matrix4x4.hpp:26
Definition: plane.hpp:12
Definition: vector3.hpp:23
Definition: vector4.hpp:24
Definition: volume.hpp:14
Definition: camera.hpp:96
Definition: camera.hpp:31