sandbox
Loading...
Searching...
No Matches
vector3.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_MATH_VECTOR3_HPP_
3#define LIBSBX_MATH_VECTOR3_HPP_
4
5#include <concepts>
6#include <cstddef>
7#include <cmath>
8#include <fstream>
9#include <ostream>
10#include <type_traits>
11
12#include <yaml-cpp/yaml.h>
13
14#include <fmt/format.h>
15
18#include <libsbx/math/vector2.hpp>
19
20namespace sbx::math {
21
22template<scalar Type>
23class basic_vector3 : public basic_vector<3u, Type> {
24
26
27 inline static constexpr auto x_axis = std::size_t{0u};
28 inline static constexpr auto y_axis = std::size_t{1u};
29 inline static constexpr auto z_axis = std::size_t{2u};
30
31public:
32
33 using value_type = base_type::value_type;
34 using reference = base_type::reference;
35 using const_reference = base_type::const_reference;
36 using size_type = base_type::size_type;
37 using length_type = base_type::length_type;
38
39 inline static constexpr basic_vector3 zero{base_type::fill(value_type{0})};
40 inline static constexpr basic_vector3 one{base_type::fill(value_type{1})};
41 inline static constexpr basic_vector3 right{base_type::template axis<x_axis>(value_type{1})};
42 inline static constexpr basic_vector3 left{base_type::template axis<x_axis>(value_type{-1})};
43 inline static constexpr basic_vector3 up{base_type::template axis<y_axis>(value_type{1})};
44 inline static constexpr basic_vector3 down{base_type::template axis<y_axis>(value_type{-1})};
45 inline static constexpr basic_vector3 forward{base_type::template axis<z_axis>(value_type{-1})};
46 inline static constexpr basic_vector3 backward{base_type::template axis<z_axis>(value_type{1})};
47
48 using base_type::base_type;
49
50 constexpr basic_vector3(const base_type& base) noexcept;
51
52 template<scalar X, scalar Y, scalar Z>
53 constexpr basic_vector3(X x, Y y, Z z) noexcept;
54
55 template<scalar Other, scalar Scalar = Other>
56 constexpr basic_vector3(const basic_vector2<Other>& vector, Scalar z = Scalar{0}) noexcept;
57
58 [[nodiscard]] static constexpr auto cross(const basic_vector3& lhs, const basic_vector3& rhs) noexcept -> basic_vector3;
59
60 [[nodiscard]] static constexpr auto dot(const basic_vector3& lhs, const basic_vector3& rhs) noexcept -> length_type;
61
62 [[nodiscard]] static constexpr auto normalized(const basic_vector3& vector) noexcept -> basic_vector3;
63
64 [[nodiscard]] static constexpr auto reflect(const basic_vector3& vector, const basic_vector3& normal) noexcept -> basic_vector3;
65
66 // [[nodiscard]] static constexpr auto abs(const basic_vector3& vector) noexcept -> basic_vector3;
67
68 [[nodiscard]] static constexpr auto distance_squared(const basic_vector3& lhs, const basic_vector3& rhs) noexcept -> value_type;
69
70 [[nodiscard]] static constexpr auto distance(const basic_vector3& lhs, const basic_vector3& rhs) noexcept -> value_type;
71
72 [[nodiscard]] static constexpr auto orthogonal(const basic_vector3& vector) noexcept -> basic_vector3 {
73 if (vector.length_squared() < 1e-12f) {
74 return {1.0f, 0.0f, 0.0f};
75 }
76
77 const auto ax = std::abs(vector.x());
78 const auto ay = std::abs(vector.y());
79 const auto az = std::abs(vector.z());
80
81 // choose the axis least aligned with vector
82 auto other = (ax < ay && ax < az) ? basic_vector3{1, 0, 0} : (ay < az) ? basic_vector3{0, 1, 0} : basic_vector3{0, 0, 1};
83
84 auto orthogonal = cross(vector, other);
85
86 // last resort (should almost never happen)
87 if (orthogonal.length_squared() < 1e-12f) {
88 other = basic_vector3{0, 1, 0};
89 orthogonal = cross(vector, other);
90 }
91
92 return normalized(orthogonal);
93 }
94
95 [[nodiscard]] static constexpr auto splat_x(const basic_vector3& vector) noexcept -> basic_vector3 {
96 return base_type::template splat<x_axis>(vector);
97 }
98
99 [[nodiscard]] static constexpr auto splat_y(const basic_vector3& vector) noexcept -> basic_vector3 {
100 return base_type::template splat<y_axis>(vector);
101 }
102
103 [[nodiscard]] static constexpr auto splat_z(const basic_vector3& vector) noexcept -> basic_vector3 {
104 return base_type::template splat<z_axis>(vector);
105 }
106
107 // /**
108 // * @brief Linearly interpolates between two vectors.
109 // *
110 // * @param start The starting vector.
111 // * @param end The ending vector.
112 // * @param t The interpolation factor [0.0f, 1.0f].
113 // *
114 // * @return A new vector that is the result of the linear interpolation.
115 // */
116 // [[nodiscard]] static constexpr auto lerp(const basic_vector3& start, const basic_vector3& end, const value_type t) noexcept -> basic_vector3 {
117 // utility::assert_that(t >= 0.0f && t <= 1.0f, "Interpolation factor out of bounds in vector3 lerp");
118 // return start * (1.0f - t) + end * t;
119 // }
120
121 [[nodiscard]] constexpr operator basic_vector2<Type>() const noexcept;
122
123 [[nodiscard]] constexpr auto x() noexcept -> reference;
124
125 [[nodiscard]] constexpr auto x() const noexcept -> const_reference;
126
127 [[nodiscard]] constexpr auto y() noexcept -> reference;
128
129 [[nodiscard]] constexpr auto y() const noexcept -> const_reference;
130
131 [[nodiscard]] constexpr auto z() noexcept -> reference;
132
133 [[nodiscard]] constexpr auto z() const noexcept -> const_reference;
134
135 constexpr auto normalize() noexcept -> basic_vector3&;
136
137}; // template<scalar Type>
138
139template<scalar Lhs, scalar Rhs>
140[[nodiscard]] constexpr auto operator+(basic_vector3<Lhs> lhs, const basic_vector3<Rhs>& rhs) noexcept -> basic_vector3<Lhs>;
141
142template<scalar Lhs, scalar Rhs>
143[[nodiscard]] constexpr auto operator-(basic_vector3<Lhs> lhs, const basic_vector3<Rhs>& rhs) noexcept -> basic_vector3<Lhs>;
144
145template<scalar Type>
146[[nodiscard]] constexpr auto operator-(basic_vector3<Type> vector) noexcept -> basic_vector3<Type>;
147
148template<scalar Lhs, scalar Rhs>
149[[nodiscard]] constexpr auto operator*(basic_vector3<Lhs> lhs, Rhs scalar) noexcept -> basic_vector3<Lhs>;
150
151template<scalar Lhs, scalar Rhs>
152[[nodiscard]] constexpr auto operator*(Lhs scalar, basic_vector3<Rhs> rhs) noexcept -> basic_vector3<Rhs>;
153
154template<scalar Lhs, std::convertible_to<Lhs> Rhs>
155requires (!is_scalar_v<Rhs>)
156[[nodiscard]] constexpr auto operator*(basic_vector3<Lhs> lhs, const Rhs& rhs) noexcept -> basic_vector3<Lhs>;
157
158template<scalar Lhs, scalar Rhs>
159[[nodiscard]] constexpr auto operator*(basic_vector3<Lhs> lhs, const basic_vector3<Rhs>& rhs) noexcept -> basic_vector3<Lhs>;
160
161template<scalar Lhs, scalar Rhs>
162[[nodiscard]] constexpr auto operator/(basic_vector3<Lhs> lhs, Rhs scalar) noexcept -> basic_vector3<Lhs>;
163
164template<scalar Lhs, std::convertible_to<Lhs> Rhs>
165requires (!is_scalar_v<Rhs>)
166[[nodiscard]] constexpr auto operator/(basic_vector3<Lhs> lhs, const Rhs& rhs) noexcept -> basic_vector3<Lhs>;
167
169
171
173
174using vector3 = vector3f;
175
176} // namespace sbx::math
177
178template<sbx::math::scalar Type>
179struct std::hash<sbx::math::basic_vector3<Type>> {
180
181 inline auto operator()(const sbx::math::basic_vector3<Type>& vector) const noexcept -> std::size_t;
182
183}; // struct std::hash<sbx::math::basic_vector3<Type>>
184
185template<sbx::math::scalar Type>
186struct fmt::formatter<sbx::math::basic_vector3<Type>> {
187
188 template<typename ParseContext>
189 constexpr auto parse(ParseContext& context) noexcept -> decltype(context.begin());
190
191 template<typename FormatContext>
192 auto format(const sbx::math::basic_vector3<Type>& vector, FormatContext& context) const noexcept -> decltype(context.out());
193
194}; // struct fmt::formatter<sbx::math::basic_vector3<Type>>
195
196template<sbx::math::scalar Type>
197struct YAML::convert<sbx::math::basic_vector3<Type>> {
198
199 static auto encode(const sbx::math::basic_vector3<Type>& rhs) -> YAML::Node {
200 auto node = Node{};
201
202 node.SetStyle(YAML::EmitterStyle::Flow);
203
204 node["x"] = rhs.x();
205 node["y"] = rhs.y();
206 node["z"] = rhs.z();
207
208 return node;
209 }
210
211 static auto decode(const YAML::Node& node, sbx::math::basic_vector3<Type>& rhs) -> bool {
212 if (!node.IsMap()) {
213 return false;
214 }
215
216 rhs.x() = node["x"].as<Type>();
217 rhs.y() = node["y"].as<Type>();
218 rhs.z() = node["z"].as<Type>();
219
220 return true;
221 }
222
223}; // struct YAML::convert<sbx::math::basic_vector3<Type>>
224
225template<sbx::math::scalar Type>
226auto operator<<(YAML::Emitter& out, const sbx::math::basic_vector3<Type>& vector) -> YAML::Emitter& {
227 return out << YAML::convert<sbx::math::basic_vector3<Type>>::encode(vector);
228}
229
230#include <libsbx/math/vector3.ipp>
231
232#endif // LIBSBX_MATH_VECTOR3_HPP_
233
constexpr auto operator/(basic_degree< Type > lhs, const Other rhs) noexcept -> basic_degree< Type >
Divides a degree value by a scalar factor.
Definition: angle.ipp:112
constexpr auto operator+(basic_degree< Type > lhs, const basic_degree< Other > &rhs) noexcept -> basic_degree< Type >
Adds two degree values.
Definition: angle.ipp:90
constexpr auto operator*(basic_degree< Type > lhs, const Other rhs) noexcept -> basic_degree< Type >
Multiplies a degree value by a scalar factor.
Definition: angle.ipp:105
Definition: tests.cpp:6
A vector in two-dimensional space.
Definition: vector2.hpp:28
Definition: vector3.hpp:23
Fixed-size vector type.
Definition: vector.hpp:55
constexpr auto length_squared() const noexcept -> length_type
Returns the squared length of the vector.
Definition: vector.ipp:190
Concept for scalar numeric types.
Definition: concepts.hpp:150
Core numeric concepts and type traits.
Generic fixed-size vector type.