sandbox
Loading...
Searching...
No Matches
matrix_cast.hpp
1#ifndef LIBSBX_MATH_MATRIX_CAST_HPP_
2#define LIBSBX_MATH_MATRIX_CAST_HPP_
3
4#include <type_traits>
5#include <concepts>
6#include <utility>
7
8#include <libsbx/math/fwd.hpp>
9#include <libsbx/math/concepts.hpp>
10#include <libsbx/math/matrix.hpp>
11#include <libsbx/math/matrix3x3.hpp>
12#include <libsbx/math/matrix4x4.hpp>
13#include <libsbx/math/quaternion.hpp>
14
15namespace sbx::math {
16
17template<typename Type, typename Return, typename... Args>
18concept dispatcher_for = requires() {
19 { std::remove_cvref_t<Type>::invoke(std::declval<Args>()...) } -> std::same_as<Return>;
20}; // concept dispatcher_for
21
22template<typename Type, typename Fallback, typename = void>
24 using type = float;
25};
26
27template<typename Type, typename Fallback>
28struct value_type_or<Type, Fallback, std::void_t<typename std::remove_cvref_t<Type>::value_type>> {
29 using type = typename std::remove_cvref_t<Type>::value_type;
30};
31
32template<typename Type, typename Fallback>
33using value_type_or_t = typename value_type_or<Type, Fallback>::type;
34
35template<typename Type>
36using value_type_t = value_type_or_t<Type, std::float_t>;
37
38namespace detail {
39
40template<scalar Type>
41struct matrix_cast_impl<3, 3, basic_matrix4x4<Type>> {
42 [[nodiscard]] static constexpr auto invoke(const basic_matrix4x4<Type>& matrix) -> basic_matrix3x3<Type> {
44 static_cast<Type>(matrix[0][0]), static_cast<Type>(matrix[1][0]), static_cast<Type>(matrix[2][0]),
45 static_cast<Type>(matrix[0][1]), static_cast<Type>(matrix[1][1]), static_cast<Type>(matrix[2][1]),
46 static_cast<Type>(matrix[0][2]), static_cast<Type>(matrix[1][2]), static_cast<Type>(matrix[2][2])
47 };
48 }
49};
50
51template<scalar Type>
52struct matrix_cast_impl<4, 4, basic_matrix3x3<Type>> {
53 [[nodiscard]] static constexpr auto invoke(const basic_matrix<3, 3, Type>& matrix) -> basic_matrix4x4<Type> {
55 static_cast<Type>(matrix[0][0]), static_cast<Type>(matrix[1][0]), static_cast<Type>(matrix[2][0]), static_cast<Type>(0),
56 static_cast<Type>(matrix[0][1]), static_cast<Type>(matrix[1][1]), static_cast<Type>(matrix[2][1]), static_cast<Type>(0),
57 static_cast<Type>(matrix[0][2]), static_cast<Type>(matrix[1][2]), static_cast<Type>(matrix[2][2]), static_cast<Type>(0),
58 static_cast<Type>(0), static_cast<Type>(0), static_cast<Type>(0), static_cast<Type>(1),
59 };
60 }
61};
62
63template<scalar Type>
65 [[nodiscard]] static constexpr auto invoke(const basic_quaternion<Type>& quaternion) -> basic_matrix4x4<Type> {
67
68 const auto xx = quaternion.x() * quaternion.x();
69 const auto yy = quaternion.y() * quaternion.y();
70 const auto zz = quaternion.z() * quaternion.z();
71 const auto xy = quaternion.x() * quaternion.y();
72 const auto xz = quaternion.x() * quaternion.z();
73 const auto yz = quaternion.y() * quaternion.z();
74 const auto wx = quaternion.w() * quaternion.x();
75 const auto wy = quaternion.w() * quaternion.y();
76 const auto wz = quaternion.w() * quaternion.z();
77
78 matrix[0][0] = 1.0f - 2.0f * (yy + zz);
79 matrix[0][1] = 2.0f * (xy + wz);
80 matrix[0][2] = 2.0f * (xz - wy);
81
82 matrix[1][0] = 2.0f * (xy - wz);
83 matrix[1][1] = 1.0f - 2.0f * (xx + zz);
84 matrix[1][2] = 2.0f * (yz + wx);
85
86 matrix[2][0] = 2.0f * (xz + wy);
87 matrix[2][1] = 2.0f * (yz - wx);
88 matrix[2][2] = 1.0f - 2.0f * (xx + yy);
89
90 return matrix;
91 }
92};
93
94template<scalar Type>
96 [[nodiscard]] static constexpr auto invoke(const basic_quaternion<Type>& quaternion) -> basic_matrix3x3<Type> {
98 }
99};
100
101// template<>
102// struct matrix_cast_impl<4, 4, transform> {
103// [[nodiscard]] static constexpr auto invoke(const transform& transform) -> matrix4x4 {
104// const auto translation = matrix4x4::translated(matrix4x4::identity, transform._position);
105// const auto scale = matrix4x4::scaled(matrix4x4::identity, transform._scale);
106
107// return translation *transform. _rotation_matrix * scale;
108// }
109// };
110
111} // namespace detail
112
113template<std::size_t Columns, std::size_t Rows, typename From>
114requires (dispatcher_for<detail::matrix_cast_impl<Columns, Rows, std::remove_cvref_t<From>>, concrete_matrix_t<Columns, Rows, value_type_t<From>>, From>)
115[[nodiscard]] constexpr auto matrix_cast(const From& from) -> concrete_matrix_t<Columns, Rows, value_type_t<From>> {
117}
118
120 vector3 position;
121 quaternion rotation;
122 vector3 scale;
123}; // struct decompose_result
124
125[[nodiscard]] constexpr auto decompose(const matrix4x4& matrix) noexcept -> decompose_result {
126 auto result = decompose_result{};
127
128 // Extract translation
129 result.position = vector3{matrix[3][0], matrix[3][1], matrix[3][2]};
130
131 // Extract scale factors
132 result.scale.x() = vector3{matrix[0][0], matrix[0][1], matrix[0][2]}.length();
133 result.scale.y() = vector3{matrix[1][0], matrix[1][1], matrix[1][2]}.length();
134 result.scale.z() = vector3{matrix[2][0], matrix[2][1], matrix[2][2]}.length();
135
136 // Normalize the rotation part of the matrix
137 auto rotation_matrix = matrix4x4{matrix};
138 rotation_matrix[0][0] /= result.scale.x();
139 rotation_matrix[0][1] /= result.scale.x();
140 rotation_matrix[0][2] /= result.scale.x();
141
142 rotation_matrix[1][0] /= result.scale.y();
143 rotation_matrix[1][1] /= result.scale.y();
144 rotation_matrix[1][2] /= result.scale.y();
145
146 rotation_matrix[2][0] /= result.scale.z();
147 rotation_matrix[2][1] /= result.scale.z();
148 rotation_matrix[2][2] /= result.scale.z();
149
150 result.rotation = quaternion{rotation_matrix};
151
152 return result;
153}
154
155} // namespace sbx::math
156
157#endif // LIBSBX_MATH_MATRIX_CAST_HPP_
Definition: matrix3x3.hpp:25
Definition: matrix4x4.hpp:26
Definition: matrix.hpp:13
Definition: quaternion.hpp:24
Definition: vector3.hpp:22
Definition: matrix_cast.hpp:119
Definition: matrix_cast.hpp:23