9#ifndef XCMATH_QUATERNION_HPP
10#define XCMATH_QUATERNION_HPP
18template <
typename _Tp,
size_t _rows,
size_t _cols>
26template <
typename _Tp>
50 constexpr static auto datatype = TypeName<DataType>;
55 constexpr static auto itemtype = TypeName<ItemType>;
73 using vec<_Tp, 4>::operator[];
78 using vec<_Tp, 4>::operator=;
80 template <
typename _OTp>
81 requires(std::is_convertible_v<ItemType, _OTp>)
98 requires std::is_convertible_v<_T, _Tp>
114 requires std::is_arithmetic_v<_Tp>
116 _T half_angle =
angle / 2;
117 _T s = std::sin(half_angle);
118 this->
r() = std::cos(half_angle);
119 this->
i() = axis.
x() * s;
120 this->
j() = axis.
y() * s;
121 this->
k() = axis.
z() * s;
132 res.
r() =
r() * other.
r() -
i() * other.
i() -
j() * other.
j() -
134 res.
i() =
r() * other.
i() +
i() * other.
r() +
j() * other.
k() -
136 res.
j() =
r() * other.
j() -
i() * other.
k() +
j() * other.
r() +
138 res.
k() =
r() * other.
k() +
i() * other.
j() -
j() * other.
i() +
152 res.
r() = (
r() * other.
r() +
i() * other.
i() +
j() * other.
j() +
155 res.
i() = (
r() * other.
i() -
i() * other.
r() -
j() * other.
k() +
158 res.
j() = (
r() * other.
j() +
i() * other.
k() -
j() * other.
r() -
161 res.
k() = (
r() * other.
k() -
i() * other.
j() +
j() * other.
i() -
173 return r() *
r() +
i() *
i() +
j() *
j() +
k() *
k();
220 constexpr inline _Tp &
r() {
return this->
data[3]; }
227 constexpr inline _Tp &
i() {
return this->
data[0]; }
234 constexpr inline _Tp &
j() {
return this->
data[1]; }
241 constexpr inline _Tp &
k() {
return this->
data[2]; }
248 constexpr inline const _Tp &
r()
const {
return this->
data[3]; }
255 constexpr inline const _Tp &
i()
const {
return this->
data[0]; }
262 constexpr inline const _Tp &
j()
const {
return this->
data[1]; }
269 constexpr inline const _Tp &
k()
const {
return this->
data[2]; }
279 template <
class _ItemType>
280 requires(!std::is_same_v<_ItemType, Self<_Tp>>)
281 auto operator+(
const _ItemType &other) {
283 res.
r() =
r() + other;
298 template <
class _ItemType>
299 requires(!std::is_same_v<_ItemType, Self<_Tp>>)
300 auto operator-(
const _ItemType &other) {
302 res.
r() =
r() - other;
308 template <
class _ItemType>
310 Self<
decltype(
r() + other.
r())> res;
311 res.
r() =
r() - other.
r();
312 res.i() =
i() - other.
i();
313 res.j() =
j() - other.
j();
314 res.k() =
k() - other.
k();
317 template <
class _ItemType>
319 Self<
decltype(
r() - other.
r())> res;
320 res.
r() =
r() + other.
r();
321 res.i() =
i() + other.
i();
322 res.j() =
j() + other.
j();
323 res.k() =
k() + other.
k();
337template <
class _Tp,
class _ItemType>
338 requires(!std::is_same_v<_Tp, quaternion<_ItemType>>)
340 quaternion<
decltype(_Tp{} + _ItemType{})> res;
341 res.
r() = other + v.
r();
357template <
class _Tp,
class _ItemType>
358 requires(!std::is_same_v<_Tp, quaternion<_ItemType>>)
360 quaternion<
decltype(_Tp{} - _ItemType{})> res;
361 res.
r() = other - v.
r();
379 vec<T, 3>{one - 2 * j() * j() - 2 * k() * k(),
380 2 * i() * j() - 2 * r() * k(), 2 * r() * j() + 2 * i() * k()},
382 one - 2 * i() * i() - 2 * k() * k(),
383 2 * j() * k() - 2 * r() * i()},
384 vec<T, 3>{2 * r() * j() - 2 * i() * k(), 2 * j() * k() + 2 * r() * i(),
385 one - 2 * i() * i() - 2 * j() * j()},
399 T tr =
mat[0][0] +
mat[1][1] +
mat[2][2];
401 T S = std::sqrt(tr + 1) * 2;
403 res.
i() = (
mat[2][1] -
mat[1][2]) / S;
404 res.
j() = (
mat[0][2] -
mat[2][0]) / S;
405 res.
k() = (
mat[1][0] -
mat[0][1]) / S;
406 }
else if ((
mat[0][0] >
mat[1][1]) && (
mat[0][0] >
mat[2][2])) {
407 T S = std::sqrt(1.0 +
mat[0][0] -
mat[1][1] -
mat[2][2]) * 2;
408 res.
r() = (
mat[2][1] -
mat[1][2]) / S;
410 res.
j() = (
mat[0][1] +
mat[1][0]) / S;
411 res.
k() = (
mat[0][2] +
mat[2][0]) / S;
412 }
else if (
mat[1][1] >
mat[2][2]) {
413 T S = std::sqrt(1.0 +
mat[1][1] -
mat[0][0] -
mat[2][2]) * 2;
414 res.
r() = (
mat[0][2] -
mat[2][0]) / S;
415 res.
i() = (
mat[0][1] +
mat[1][0]) / S;
417 res.
k() = (
mat[1][2] +
mat[2][1]) / S;
419 T S = std::sqrt(1.0 +
mat[2][2] -
mat[0][0] -
mat[1][1]) * 2;
420 res.
r() = (
mat[1][0] -
mat[0][1]) / S;
421 res.
i() = (
mat[0][2] +
mat[2][0]) / S;
422 res.
j() = (
mat[1][2] +
mat[2][1]) / S;
Quaternion class template
quaternion(_Tp r, _Tp i, _Tp j, _Tp k)
auto operator-(const Self< _ItemType > &other)
constexpr const _Tp & i() const
Get i-component of the quaternion (const version)
static constexpr auto datatype
Name of the data type
VecInfo< ItemType >::DataType DataType
Type of data stored in the vector
constexpr _Tp & r()
Get scalar part of the quaternion
constexpr vec3< _Tp > v()
Get vector part of the quaternion
constexpr quaternion< _Tp > inverse()
Compute inverse of the quaternion
constexpr const _Tp & j() const
Get j-component of the quaternion (const version)
constexpr mat< _Tp, 3, 3 > to_mat() const
Convert quaternion to rotation matrix
constexpr _Tp & i()
Get i-component of the quaternion
_Tp ItemType
Type of elements in the vector
constexpr const _Tp & r() const
Get scalar part of the quaternion (const version)
constexpr quaternion(const vec3< _Tp > &axis, const _T &angle)
Construct a quaternion from an axis and angle
constexpr _Tp & k()
Get k-component of the quaternion
static constexpr auto itemtype
Name of the item type
constexpr quaternion< _Tp > operator*(const quaternion< _Tp > &other) const
Quaternion multiplication operator
constexpr const _Tp & k() const
Get k-component of the quaternion (const version)
constexpr quaternion< _Tp > operator/(const quaternion< _Tp > &other) const
Quaternion division operator
constexpr quaternion(const _T &r)
Construct a quaternion from a scalar
constexpr _Tp norm() const
Compute norm of the quaternion
static constexpr quaternion< _Tp > from_mat(const mat< _Tp, 3, 3 > &mat)
Create quaternion from rotation matrix
constexpr _Tp & j()
Get j-component of the quaternion
auto operator+(const Self< _ItemType > &other)
static constexpr auto length
Length of the vector
constexpr _Tp angle(const vec< _Tp, _length > &other) const
Compute angle with another vector
constexpr _Tp & x()
Get the item at index 0
_Tp data[_length]
Component storage array
constexpr _Tp & y()
Get the item at index 1
constexpr _Tp & z()
Get the item at index 2
Compiler-specific type information handling for MSVC
decltype([]() { if constexpr(Vec< _Tp >) return VecInfo< typename _Tp::ItemType >::Zero DataType