8#ifndef SEN_LIBS_UTIL_SRC_DR_QUAT_H
9#define SEN_LIBS_UTIL_SRC_DR_QUAT_H
35 Quat(T x, T y, T z, T w) noexcept;
39 Quat(T yaw, T pitch, T bank) noexcept;
41 explicit
Quat(const
Vec3<T>& eulerAngles) noexcept;
46 bool operator==(const
Quat& v) const noexcept;
48 bool operator!=(const
Quat& v) const noexcept;
50 bool operator<(const
Quat& v) const noexcept;
52 Quat operator*(T rhs) const;
54 Quat& operator*=(T rhs) noexcept;
56 Quat operator*(const
Quat& rhs) const noexcept;
58 Vec3<T> operator*(const
Vec3<T>& v) const noexcept;
62 Quat operator/(const
Quat& denom) const noexcept;
66 Quat operator+(const
Quat& rhs) const noexcept;
68 Quat operator/(const T rhs) const noexcept;
70 Quat& operator/=(T rhs) noexcept;
74 Quat operator-(const
Quat& rhs) const noexcept;
78 Quat operator-() const noexcept;
81 [[nodiscard]] T
dot(const
Quat<T>& other) const noexcept;
86 void set(T x, T y, T z, T w) noexcept;
88 [[nodiscard]] T
getX() const noexcept;
89 [[nodiscard]] T
getY() const noexcept;
90 [[nodiscard]] T
getZ() const noexcept;
91 [[nodiscard]] T
getW() const noexcept;
127 const
Vec3<T>& axis1,
129 const
Vec3<T>& axis2,
131 const
Vec3<T>& axis3) noexcept;
152 T v_[4] {0, 0, 0, 1};
192 return v_[0] == v.v_[0] && v_[1] == v.v_[1] && v_[2] == v.v_[2] && v_[3] == v.v_[3];
198 return v_[0] != v.v_[0] || v_[1] != v.v_[1] || v_[2] != v.v_[2] || v_[3] != v.v_[3];
234 return (v_[3] < v.v_[3]);
240 return Vec3<T> {v_[0], v_[1], v_[2]};
303 return v_[0] == 0.0 && v_[1] == 0.0 && v_[2] == 0.0 && v_[3] == 1.0;
309 return {v_[0] * rhs, v_[1] * rhs, v_[2] * rhs, v_[3] * rhs};
325 return {rhs.v_[3] * v_[0] + rhs.v_[0] * v_[3] + rhs.v_[1] * v_[2] - rhs.v_[2] * v_[1],
326 rhs.v_[3] * v_[1] - rhs.v_[0] * v_[2] + rhs.v_[1] * v_[3] + rhs.v_[2] * v_[0],
327 rhs.v_[3] * v_[2] + rhs.v_[0] * v_[1] - rhs.v_[1] * v_[0] + rhs.v_[2] * v_[3],
328 rhs.v_[3] * v_[3] - rhs.v_[0] * v_[0] - rhs.v_[1] * v_[1] - rhs.v_[2] * v_[2]};
334 T x = rhs.v_[3] * v_[0] + rhs.v_[0] * v_[3] + rhs.v_[1] * v_[2] - rhs.v_[2] * v_[1];
335 T y = rhs.v_[3] * v_[1] - rhs.v_[0] * v_[2] + rhs.v_[1] * v_[3] + rhs.v_[2] * v_[0];
336 T z = rhs.v_[3] * v_[2] + rhs.v_[0] * v_[1] - rhs.v_[1] * v_[0] + rhs.v_[2] * v_[3];
337 v_[3] = rhs.v_[3] * v_[3] - rhs.v_[0] * v_[0] - rhs.v_[1] * v_[1] - rhs.v_[2] * v_[2];
350 return {v_[0] * div, v_[1] * div, v_[2] * div, v_[3] * div};
367 return ((*
this) * denom.inverse());
373 (*this) = (*this) * denom.inverse();
380 return {v_[0] + rhs.v_[0], v_[1] + rhs.v_[1], v_[2] + rhs.v_[2], v_[3] + rhs.v_[3]};
396 return {v_[0] - rhs.v_[0], v_[1] - rhs.v_[1], v_[2] - rhs.v_[2], v_[3] - rhs.v_[3]};
412 return {-v_[0], -v_[1], -v_[2], -v_[3]};
418 return v_[0] * other.v_[0] + v_[1] * other.v_[1] + v_[2] * other.v_[2] + v_[3] * other.v_[3];
430 return v_[0] * v_[0] + v_[1] * v_[1] + v_[2] * v_[2] + v_[3] * v_[3];
436 return {-v_[0], -v_[1], -v_[2], v_[3]};
448 constexpr T
epsilon = 0.0000001;
450 T
length = std::sqrt(x * x + y * y + z * z);
456 T cosHalfAngle = cos(0.5 *
angle);
457 T sinHalfAngle = sin(0.5 *
angle);
459 T quatX = x * sinHalfAngle /
length;
460 T quatY = y * sinHalfAngle /
length;
461 T quatZ = z * sinHalfAngle /
length;
462 T quatW = cosHalfAngle;
464 Quat rotationQuat {quatX, quatY, quatZ, quatW};
466 *
this = *
this * rotationQuat;
478 auto sourceVector = from;
479 auto targetVector = to;
481 T fromLen2 = from.length2();
484 if ((fromLen2 < 1.0 - 1e-7) || (fromLen2 > 1.0 + 1e-7))
486 fromLen = sqrt(fromLen2);
487 sourceVector /= fromLen;
494 T toLen2 = to.length2();
495 if ((toLen2 < 1.0 - 1e-7) || (toLen2 > 1.0 + 1e-7))
498 if ((toLen2 > fromLen2 - 1e-7) && (toLen2 < fromLen2 + 1e-7))
504 toLen = sqrt(toLen2);
506 targetVector /= toLen;
509 T dotProdPlus1 = 1.0 + sourceVector * targetVector;
511 if (dotProdPlus1 < 1e-7)
513 if (fabs(sourceVector.getX()) < 0.6)
515 const auto norm = sqrt(1.0 - sourceVector.getX() * sourceVector.getX());
517 v_[1] = sourceVector.getZ() / norm;
518 v_[2] = -sourceVector.getY() / norm;
521 else if (fabs(sourceVector.getY()) < 0.6)
523 const auto norm = sqrt(1.0 - sourceVector.getY() * sourceVector.getY());
524 v_[0] = -sourceVector.getZ() / norm;
526 v_[2] = sourceVector.getX() / norm;
531 const auto norm = sqrt(1.0 - sourceVector.getZ() * sourceVector.getZ());
532 v_[0] = sourceVector.getY() / norm;
533 v_[1] = -sourceVector.getX() / norm;
540 const auto s = sqrt(0.5 * dotProdPlus1);
541 const auto tmp = sourceVector ^ targetVector / (2.0 * s);
563 constexpr T
epsilon = 0.0000001;
565 const T
length2 = axis.getX() * axis.getX() + axis.getY() * axis.getY() + axis.getZ() * axis.getZ();
572 const T cosHalfAngle = cos(0.5 *
angle);
573 const T sinHalfAngle = sin(0.5 *
angle);
578 return {axis.getX() * sinHalfAngle, axis.getY() * sinHalfAngle, axis.getZ() * sinHalfAngle, cosHalfAngle};
583 return {axis.getX() * sinHalfAngle /
length,
584 axis.getY() * sinHalfAngle /
length,
585 axis.getZ() * sinHalfAngle /
length,
592 makeRotate(bank, {1.0, 0.0, 0.0}, pitch, {0.0, 1.0, 0.0}, yaw, {0.0, 0.0, 1.0});
598 makeRotate(eulerAngles.z(), {1.0, 0.0, 0.0}, eulerAngles.y(), {0.0, 1.0, 0.0}, eulerAngles.x(), {0.0, 0.0, 1.0});
616 T sinhalfangle = std::sqrt(v_[0] * v_[0] + v_[1] * v_[1] + v_[2] * v_[2]);
618 angle = 2.0 * std::atan2(sinhalfangle, v_[3]);
620 if constexpr (std::is_same_v<f32, T>)
629 if (sinhalfangle != 0.0)
631 x = v_[0] / sinhalfangle;
632 y = v_[1] / sinhalfangle;
633 z = v_[2] / sinhalfangle;
646 const T sqw = v_[3] * v_[3];
647 const T sqx = v_[0] * v_[0];
648 const T sqy = v_[1] * v_[1];
649 const T sqz = v_[2] * v_[2];
651 const T sine = -2.0 * (v_[0] * v_[2] - v_[1] * v_[3]) / (sqx + sqy + sqz + sqw);
656 constexpr T gimbalLimit =
static_cast<T
>(1) -
static_cast<T
>(1e-14);
658 if (std::abs(sine) > gimbalLimit)
660 return {
static_cast<T
>(2) * atan2(v_[2], v_[3]),
661 asin(std::clamp(sine,
static_cast<T
>(-1),
static_cast<T
>(1))),
665 const T yaw = atan2(2.0 * (v_[0] * v_[1] + v_[2] * v_[3]), (sqx - sqy - sqz + sqw));
666 const T pitch = asin(std::clamp(sine,
static_cast<T
>(-1),
static_cast<T
>(1)));
667 const T bank = atan2(2.0 * (v_[1] * v_[2] + v_[0] * v_[3]), (-sqx - sqy + sqz + sqw));
669 return {yaw, pitch, bank};
677 Vec3<T> qvec(v_[0], v_[1], v_[2]);
688 const double epsilon = 0.00001;
697 cosOmega = from.v_[0] * to.v_[0] + from.v_[1] * to.v_[1] + from.v_[2] * to.v_[2] + from.v_[3] * to.v_[3];
699 if ((1.0 - cosOmega) >
epsilon)
701 omega = acos(cosOmega);
702 sinOmega = sin(omega);
703 scaleFrom = sin((1.0 - t) * omega) / sinOmega;
704 scaleTo = sin(t * omega) / sinOmega;
712 *
this = (from * scaleFrom) + (quatTo * scaleTo);
Quaternion. Represents the orientation of an object in space.
Definition quat.h:28
Quat & operator*=(T rhs) noexcept
Definition quat.h:313
f32 length() const noexcept
void slerp(f32 t, const Quat &from, const Quat &to) noexcept
bool operator==(const Quat &v) const noexcept
Definition quat.h:190
Quat operator/(const Quat &denom) const noexcept
Definition quat.h:365
f32 getX() const noexcept
void setX(f32 x) noexcept
Quat & operator-=(const Quat &rhs) noexcept
Definition quat.h:400
Vec3< f32 > asVec3() const noexcept
Quat operator+(const Quat &rhs) const noexcept
Definition quat.h:378
bool operator<(const Quat &v) const noexcept
Definition quat.h:202
void setW(f32 w) noexcept
Quat & operator/=(const Quat &denom) noexcept
Definition quat.h:371
bool operator!=(const Quat &v) const noexcept
Definition quat.h:196
Vec3< f32 > getRotateInEulerYPB() const noexcept
void getRotate(f32 &angle, f32 &x, f32 &y, f32 &z) const noexcept
f32 length2() const noexcept
f32 getZ() const noexcept
Quat operator-() const noexcept
Definition quat.h:410
void set(f32 x, f32 y, f32 z, f32 w) noexcept
void makeRotate(f32 angle, f32 x, f32 y, f32 z) noexcept
void makeRotateFromEulerYPB(f32 yaw, f32 pitch, f32 bank) noexcept
f32 dot(const Quat< f32 > &other) const noexcept
void setY(f32 y) noexcept
f32 getY() const noexcept
void setZ(f32 z) noexcept
static Quat makeAxisRotation(f32 angle, const Vec3< f32 > &axis) noexcept
f32 getW() const noexcept
Quat & operator+=(const Quat &rhs) noexcept
Definition quat.h:384
Quat operator*(T rhs) const
Definition quat.h:307
bool zeroRotation() const noexcept
Handles all mathematical ops involving 3D Vectors.
Definition vec3.h:24
@ angle
Definition unit.h:35
Definition iterator_adapters.h:16
Quat< f64 > Quatd
Definition quat.h:156
constexpr f32 epsilon
Min value used to determine that an entity is not moving/accelerating.
Definition util/src/dr/constants.h:37
constexpr f32 pif
Definition util/src/dr/constants.h:19
Quat< f32 > Quatf
Definition quat.h:155
constexpr f64 pi
PI constant.
Definition util/src/dr/constants.h:18