1#ifndef LIBSBX_MATH_QUATERNION_HPP_
2#define LIBSBX_MATH_QUATERNION_HPP_
9#include <yaml-cpp/yaml.h>
11#include <fmt/format.h>
13#include <libsbx/math/concepts.hpp>
14#include <libsbx/math/constants.hpp>
15#include <libsbx/math/algorithm.hpp>
16#include <libsbx/math/vector3.hpp>
17#include <libsbx/math/vector4.hpp>
18#include <libsbx/math/matrix4x4.hpp>
19#include <libsbx/math/angle.hpp>
23template<
floating_po
int Type>
26 template<
floating_po
int Other>
29 template<
floating_po
int Other>
32 template<
floating_po
int Other>
35 template<
floating_po
int Other>
40 using value_type = Type;
41 using reference = value_type&;
42 using const_reference =
const value_type&;
43 using size_type = std::size_t;
44 using length_type = std::float_t;
49 inline static constexpr basic_quaternion identity{vector_type::zero, value_type{1}};
51 template<
floating_po
int Other = value_type>
54 template<
floating_po
int Complex = value_type,
floating_po
int Scalar = value_type>
57 template<
floating_po
int Other = value_type>
60 template<
floating_po
int Other = value_type>
63 template<
floating_po
int Complex = value_type,
floating_po
int Scalar = value_type>
66 template<
floating_po
int Other = value_type>
69 template<
floating_po
int Other = value_type>
72 template<
floating_po
int Other = value_type>
73 [[nodiscard]]
static constexpr auto wxyz(Other w, Other x, Other y, Other z)
noexcept ->
basic_quaternion {
84 if(length <=
static_cast<value_type
>(0)) {
85 return basic_quaternion{
static_cast<value_type
>(0),
static_cast<value_type
>(0),
static_cast<value_type
>(0),
static_cast<value_type
>(1)};
88 const auto one_over_length =
static_cast<value_type
>(1) / length;
93 return lhs.x() * rhs.x() + lhs.y() * rhs.y() + lhs.z() * rhs.z() + lhs.w() * rhs.w();
97 return start * (1.0f - t) + end * t;
110 utility::assert_that(a >= 0.0f && a <= 1.0f,
"Interpolation factor out of bounds in quaternion slerp");
114 auto cos_theta = dot(x, y);
118 if(cos_theta <
static_cast<value_type
>(0)) {
120 cos_theta = -cos_theta;
124 if(cos_theta >
static_cast<value_type
>(1) - math::epsilon_v<value_type>) {
126 return basic_quaternion::wxyz(
127 math::mix(x.w(), z.w(), a),
128 math::mix(x.x(), z.x(), a),
129 math::mix(x.y(), z.y(), a),
130 math::mix(x.z(), z.z(), a)
134 const auto angle = std::acos(cos_theta);
135 return (std::sin((
static_cast<value_type
>(1) - a) *
angle) * x + std::sin(a *
angle) * z) / std::sin(
angle);
139 template<
floating_po
int Other = value_type>
142 template<
floating_po
int Other = value_type>
145 template<
floating_po
int Other = value_type>
148 template<
floating_po
int Other = value_type>
151 template<
floating_po
int Other = value_type>
154 [[nodiscard]]
constexpr auto x() noexcept -> reference;
156 [[nodiscard]] constexpr auto x() const noexcept -> const_reference;
158 [[nodiscard]] constexpr auto y() noexcept -> reference;
160 [[nodiscard]] constexpr auto y() const noexcept -> const_reference;
162 [[nodiscard]] constexpr auto z() noexcept -> reference;
164 [[nodiscard]] constexpr auto z() const noexcept -> const_reference;
166 [[nodiscard]] constexpr auto w() noexcept -> reference;
168 [[nodiscard]] constexpr auto w() const noexcept -> const_reference;
170 [[nodiscard]] constexpr auto complex() noexcept -> vector_type&;
172 [[nodiscard]] constexpr auto complex() const noexcept -> const vector_type&;
174 [[nodiscard]] constexpr auto scalar() noexcept -> reference;
176 [[nodiscard]] constexpr auto scalar() const noexcept -> const_reference;
178 [[nodiscard]] constexpr auto length_squared() const noexcept -> length_type;
180 [[nodiscard]] constexpr auto length() const noexcept -> length_type;
186 vector_type _complex;
191template<floating_point Lhs, floating_point Rhs>
194template<floating_point Lhs, floating_point Rhs>
197template<floating_point Lhs, floating_point Rhs>
200template<floating_point Type>
203template<floating_point Lhs, floating_point Rhs>
206template<floating_point Lhs, floating_point Rhs>
209template<floating_point Lhs, floating_point Rhs>
212template<floating_point Lhs, floating_point Rhs>
223template<sbx::math::floating_point Type>
224struct std::hash<sbx::math::basic_quaternion<Type>> {
230template<sbx::math::
floating_po
int Type>
231struct YAML::convert<sbx::math::basic_quaternion<Type>> {
239template<sbx::math::
floating_po
int Type>
241 return out << YAML::convert<sbx::math::basic_quaternion<Type>>::encode(quaternion);
244template<sbx::math::
floating_po
int Type>
245struct fmt::formatter<sbx::math::basic_quaternion<Type>> {
247 template<
typename ParseContext>
248 constexpr auto parse(ParseContext& context) ->
decltype(context.begin());
250 template<
typename FormatContext>
255#include <libsbx/math/quaternion.ipp>
Definition: angle.hpp:279
Definition: matrix3x3.hpp:25
Definition: matrix4x4.hpp:26
Definition: quaternion.hpp:24
static constexpr auto slerp(const basic_quaternion &x, basic_quaternion y, const value_type a) noexcept -> basic_quaternion
Spherical linear interpolation between two quaternions.
Definition: quaternion.hpp:109
Definition: vector3.hpp:22