/** * @file * * @author Max Lammers * @author Mamadou Babaei * * @section LICENSE * * Copyright (c) 2020 - 2023 SenseGlove * * @section DESCRIPTION * * A Quaternion is a representation of a rotation in 3D space without the * problem of Gimbal Lock that exists in Euler representations. */ #pragma once #include #include #include "Platform.hpp" namespace SGCore { namespace Kinematics { /// A rotation in 3D space that can be applied to a 3D vector or converted into Euler Angles. class SGCORE_API Quat; class Vect3D; }// namespace Kinematics }// namespace SGCore /// A rotation in 3D space that can be applied to a 3D vector or converted into Euler Angles. class SGCORE_API SGCore::Kinematics::Quat { public: /// Quaternion representing no rotation (0.0f, 0.0f, 0.0f, 1.0f) static const Quat& Identity(); /// Parse a Quaternion from a string. static bool Deserialize(const std::string& str, Quat& out_result, char delimiter = ','); /// Create a new Quaternion Rotation from its euler angle representation. static Quat FromEuler(float xAngle, float yAngle, float zAngle); /// Create a new Quaternion Rotation from its euler angle representation. static Quat FromEuler(const Vect3D& euler); /// Create a new Quaternion Rotation from an angle-axis representation. static Quat FromAngleAxis(float angle, float xAxis, float yAxis, float zAxis); /// Create a new Quaternion Rotation from an angle-axis representation. static Quat FromAngleAxis(float angle, const Vect3D& axis); /// Returns the inverse if q (a.k.a. a rotation in the other direction) static Quat Invert(const Quat& quat);// -x-y-z w /// Normalizes a quaternion to have a length of 1. /// static Quat Normalize(const Quat& quat); private: struct Impl; std::unique_ptr Pimpl; public: /// Create a new Quaternion rotation of 0, 0, 0, 1. Quat(); /// Create a new Quaternion rotation. Quat(float x, float y, float z, float w); /** * The copy constructor. */ Quat(const Quat& rhs); /** * The move constructor. */ Quat(Quat&& rhs) noexcept; /// Default Destructor. virtual ~Quat(); public: /** * The copy assignment operator. */ Quat& operator=(const Quat& rhs); /** * The move assignment operator. */ Quat& operator=(Quat&& rhs) noexcept; public: /// /// Add two quaternions together Using a Hamilton product. /// NOTE: Q2 is applies first, followed by Q1, as per multiplication order of quaternions! /// /// /// A rotation by Q1 followed by one of Q2 requires to operation Q2*Q1, using the Hamilton Multiplication. /// https://en.wikipedia.org/wiki/Quaternion /// // multiply this quaternion by another Quat - by quaternion law, that is the first rotation, followed by this. Quat operator*(const Quat& quat) const; //multiply this quaternion with a Vect3D, a.k.a. rotate it. Vect3D operator*(const Vect3D& vect3D) const; public: #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ float GetX() const; void SetX(float x); #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ float GetY() const; void SetY(float y); #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ float GetZ() const; void SetZ(float z); #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ float GetW() const; void SetW(float w); public: /// Retrieve this Quaternion's euler angle notation. #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ Vect3D ToEuler() const; /// Rotate Vect3D by this quaternion rotation. #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ Vect3D Rotate(const Vect3D& vect3D) const; /// Check if two quaternions have equal values. #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ bool Equals(const Quat& quat) const; /// Check if this Quaternion is the identity quaternion (meaning it does not rotate anything.) #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ bool IsIdentity() const; /// Returns the magnitude of this Quaternion. Used in normalization. /// #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ float Magnitude() const; /// Create a string representation of the Quaternion rotation. #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ std::string ToString() const; public: #if !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) [[nodiscard]] #endif /* !defined ( SENSEGLOVE_UNREAL_ENGINE_PLUGIN ) */ std::string Serialize(const char delimiter = ',') const; };