8#ifndef SEN_LIBS_UTIL_SRC_DR_QUAT_H
9#define SEN_LIBS_UTIL_SRC_DR_QUAT_H
31 Quat(T x, T y, T z, T w) noexcept;
35 Quat(T yaw, T pitch, T bank) noexcept;
37 explicit
Quat(const
Vec3<T>& eulerAngles) noexcept;
42 bool operator==(const
Quat& v) const noexcept;
44 bool operator!=(const
Quat& v) const noexcept;
46 bool operator<(const
Quat& v) const noexcept;
48 Quat operator*(T rhs) const;
50 Quat& operator*=(T rhs) noexcept;
52 Quat operator*(const
Quat& rhs) const noexcept;
54 Vec3<T> operator*(const
Vec3<T>& v) const noexcept;
58 Quat operator/(const
Quat& denom) const noexcept;
62 Quat operator+(const
Quat& rhs) const noexcept;
64 Quat operator/(const T rhs) const noexcept;
66 Quat& operator/=(T rhs) noexcept;
70 Quat operator-(const
Quat& rhs) const noexcept;
74 Quat operator-() const noexcept;
77 [[nodiscard]] T
dot(const
Quat<T>& other) const noexcept;
82 void set(T x, T y, T z, T w) noexcept;
84 [[nodiscard]] T
getX() const noexcept;
85 [[nodiscard]] T
getY() const noexcept;
86 [[nodiscard]] T
getZ() const noexcept;
87 [[nodiscard]] T
getW() const noexcept;
120 const
Vec3<T>& axis1,
122 const
Vec3<T>& axis2,
124 const
Vec3<T>& axis3) noexcept;
145 T v_[4] {0, 0, 0, 1};
167 v_[0] =
static_cast<T
>(0.0);
168 v_[1] =
static_cast<T
>(0.0);
169 v_[2] =
static_cast<T
>(0.0);
170 v_[3] =
static_cast<T
>(1.0);
190 return v_[0] == v.v_[0] && v_[1] == v.v_[1] && v_[2] == v.v_[2] && v_[3] == v.v_[3];
196 return v_[0] != v.v_[0] || v_[1] != v.v_[1] || v_[2] != v.v_[2] || v_[3] != v.v_[3];
232 return (v_[3] < v.v_[3]);
238 return Vec3<T> {v_[0], v_[1], v_[2]};
301 return v_[0] == 0.0 && v_[1] == 0.0 && v_[2] == 0.0 && v_[3] == 1.0;
307 return {v_[0] * rhs, v_[1] * rhs, v_[2] * rhs, v_[3] * rhs};
323 return {rhs.v_[3] * v_[0] + rhs.v_[0] * v_[3] + rhs.v_[1] * v_[2] - rhs.v_[2] * v_[1],
324 rhs.v_[3] * v_[1] - rhs.v_[0] * v_[2] + rhs.v_[1] * v_[3] + rhs.v_[2] * v_[0],
325 rhs.v_[3] * v_[2] + rhs.v_[0] * v_[1] - rhs.v_[1] * v_[0] + rhs.v_[2] * v_[3],
326 rhs.v_[3] * v_[3] - rhs.v_[0] * v_[0] - rhs.v_[1] * v_[1] - rhs.v_[2] * v_[2]};
332 T x = rhs.v_[3] * v_[0] + rhs.v_[0] * v_[3] + rhs.v_[1] * v_[2] - rhs.v_[2] * v_[1];
333 T y = rhs.v_[3] * v_[1] - rhs.v_[0] * v_[2] + rhs.v_[1] * v_[3] + rhs.v_[2] * v_[0];
334 T z = rhs.v_[3] * v_[2] + rhs.v_[0] * v_[1] - rhs.v_[1] * v_[0] + rhs.v_[2] * v_[3];
335 v_[3] = rhs.v_[3] * v_[3] - rhs.v_[0] * v_[0] - rhs.v_[1] * v_[1] - rhs.v_[2] * v_[2];
348 return {v_[0] * div, v_[1] * div, v_[2] * div, v_[3] * div};
365 return ((*
this) * denom.inverse());
371 (*this) = (*this) * denom.inverse();
378 return {v_[0] + rhs.v_[0], v_[1] + rhs.v_[1], v_[2] + rhs.v_[2], v_[3] + rhs.v_[3]};
394 return {v_[0] - rhs.v_[0], v_[1] - rhs.v_[1], v_[2] - rhs.v_[2], v_[3] - rhs.v_[3]};
410 return {-v_[0], -v_[1], -v_[2], -v_[3]};
416 return v_[0] * other.v_[0] + v_[1] * other.v_[1] + v_[2] * other.v_[2] + v_[3] * other.v_[3];
428 return v_[0] * v_[0] + v_[1] * v_[1] + v_[2] * v_[2] + v_[3] * v_[3];
434 return {-v_[0], -v_[1], -v_[2], v_[3]};
446 constexpr T
epsilon = 0.0000001;
448 T
length = std::sqrt(x * x + y * y + z * z);
454 T cosHalfAngle = cos(0.5 *
angle);
455 T sinHalfAngle = sin(0.5 *
angle);
457 T quatX = x * sinHalfAngle /
length;
458 T quatY = y * sinHalfAngle /
length;
459 T quatZ = z * sinHalfAngle /
length;
460 T quatW = cosHalfAngle;
462 Quat rotationQuat {quatX, quatY, quatZ, quatW};
464 *
this = *
this * rotationQuat;
476 auto sourceVector = from;
477 auto targetVector = to;
479 T fromLen2 = from.length2();
482 if ((fromLen2 < 1.0 - 1e-7) || (fromLen2 > 1.0 + 1e-7))
484 fromLen = sqrt(fromLen2);
485 sourceVector /= fromLen;
492 T toLen2 = to.length2();
493 if ((toLen2 < 1.0 - 1e-7) || (toLen2 > 1.0 + 1e-7))
496 if ((toLen2 > fromLen2 - 1e-7) && (toLen2 < fromLen2 + 1e-7))
502 toLen = sqrt(toLen2);
504 targetVector /= toLen;
507 T dotProdPlus1 = 1.0 + sourceVector * targetVector;
509 if (dotProdPlus1 < 1e-7)
511 if (fabs(sourceVector.getX()) < 0.6)
513 const auto norm = sqrt(1.0 - sourceVector.getX() * sourceVector.getX());
515 v_[1] = sourceVector.getZ() / norm;
516 v_[2] = -sourceVector.getY() / norm;
519 else if (fabs(sourceVector.getY()) < 0.6)
521 const auto norm = sqrt(1.0 - sourceVector.getY() * sourceVector.getY());
522 v_[0] = -sourceVector.getZ() / norm;
524 v_[2] = sourceVector.getX() / norm;
529 const auto norm = sqrt(1.0 - sourceVector.getZ() * sourceVector.getZ());
530 v_[0] = sourceVector.getY() / norm;
531 v_[1] = -sourceVector.getX() / norm;
538 const auto s = sqrt(0.5 * dotProdPlus1);
539 const auto tmp = sourceVector ^ targetVector / (2.0 * s);
562 *
this = q1 * q2 * q3;
568 makeRotate(bank, {1.0, 0.0, 0.0}, pitch, {0.0, 1.0, 0.0}, yaw, {0.0, 0.0, 1.0});
574 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});
592 T sinhalfangle = std::sqrt(v_[0] * v_[0] + v_[1] * v_[1] + v_[2] * v_[2]);
594 angle = 2.0 * std::atan2(sinhalfangle, v_[3]);
596 if constexpr (std::is_same_v<f32, T>)
605 if (sinhalfangle != 0.0)
607 x = v_[0] / sinhalfangle;
608 y = v_[1] / sinhalfangle;
609 z = v_[2] / sinhalfangle;
622 T sqw = v_[3] * v_[3];
623 T sqx = v_[0] * v_[0];
624 T sqy = v_[1] * v_[1];
625 T sqz = v_[2] * v_[2];
627 T yaw = atan2(2.0 * (v_[0] * v_[1] + v_[2] * v_[3]), (sqx - sqy - sqz + sqw));
628 T pitch = asin(-2.0 * (v_[0] * v_[2] - v_[1] * v_[3]) / (sqx + sqy + sqz + sqw));
629 T bank = atan2(2.0 * (v_[1] * v_[2] + v_[0] * v_[3]), (-sqx - sqy + sqz + sqw));
631 return {yaw, pitch, bank};
639 Vec3<T> qvec(v_[0], v_[1], v_[2]);
650 const double epsilon = 0.00001;
659 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];
661 if ((1.0 - cosOmega) >
epsilon)
663 omega = acos(cosOmega);
664 sinOmega = sin(omega);
665 scaleFrom = sin((1.0 - t) * omega) / sinOmega;
666 scaleTo = sin(t * omega) / sinOmega;
674 *
this = (from * scaleFrom) + (quatTo * scaleTo);
Quaternion. Represents the orientation of an object in space.
Definition quat.h:24
Quat & operator*=(T rhs) noexcept
Definition quat.h:311
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:188
Quat operator/(const Quat &denom) const noexcept
Definition quat.h:363
f32 getX() const noexcept
void setX(f32 x) noexcept
Quat & operator-=(const Quat &rhs) noexcept
Definition quat.h:398
Vec3< f32 > asVec3() const noexcept
Quat operator+(const Quat &rhs) const noexcept
Definition quat.h:376
bool operator<(const Quat &v) const noexcept
Definition quat.h:200
void setW(f32 w) noexcept
Quat & operator/=(const Quat &denom) noexcept
Definition quat.h:369
bool operator!=(const Quat &v) const noexcept
Definition quat.h:194
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:408
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
f32 getW() const noexcept
Quat & operator+=(const Quat &rhs) noexcept
Definition quat.h:382
Quat operator*(T rhs) const
Definition quat.h:305
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:149
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:148
constexpr f64 pi
PI constant.
Definition util/src/dr/constants.h:18