#ifndef RAYLIB_CPP_INCLUDE_QUATERNION_HPP_ #define RAYLIB_CPP_INCLUDE_QUATERNION_HPP_ #ifndef RAYLIB_CPP_NO_MATH #include #include #endif #include #include "./raylib-cpp-utils.hpp" #include "./raylib.hpp" #include "./raymath.hpp" namespace raylib { class Vector4 : public ::Vector4 {}; /** * Quaternion type */ class Quaternion : public ::Quaternion { public: constexpr Quaternion(const ::Quaternion& quat) : ::Quaternion{quat.x, quat.y, quat.z, quat.w} {} explicit constexpr Quaternion(const raylib::Vector4 vec4) : ::Quaternion{vec4.x, vec4.y, vec4.z, vec4.w} {} explicit constexpr Quaternion(const float x = 0, const float y = 0, const float z = 0, const float w = 1) : ::Quaternion{x, y, z, w} {} GETTERSETTER(float, X, x) GETTERSETTER(float, Y, y) GETTERSETTER(float, Z, z) GETTERSETTER(float, W, w) Quaternion& operator=(const ::Quaternion& quaternion) { set(quaternion); return *this; } /* * An exact value by value equality comparison. * Due to floating point inaccuracies consider using Equals instead. */ constexpr bool operator==(const ::Quaternion& other) const { return x == other.x && y == other.y && z == other.z && w == other.w; } /* * An exact value by value inequality comparison. * Due to floating point inaccuracies consider using Equals instead. */ constexpr bool operator!=(const ::Quaternion& other) const { return !(*this == other); } RLCPP_NODISCARD std::string ToString() const { return ::TextFormat("Quaternion(%f, %f, %f, %f)", x, y, z, w); } operator std::string() const { return ToString(); } #ifndef RAYLIB_CPP_NO_MATH /** * Add two quaternions */ RLCPP_NODISCARD Quaternion Add(const ::Quaternion& quaternion) const { return ::QuaternionAdd(*this, quaternion); } /** * Add two quaternions */ Quaternion operator+(const ::Quaternion& quaternion) const { return ::QuaternionAdd(*this, quaternion); } Quaternion& operator+=(const ::Quaternion& quaternion) { set(::QuaternionAdd(*this, quaternion)); return *this; } /** * Add quaternion and float value */ RLCPP_NODISCARD Quaternion Add(const float value) const { return ::QuaternionAddValue(*this, value); } /** * Add quaternion and float value */ Quaternion operator+(const float value) const { return ::QuaternionAddValue(*this, value); } /** * Add quaternion and float value */ Quaternion& operator+=(const float value) { set(::QuaternionAddValue(*this, value)); return *this; } /** * Add quaternion and float value */ friend Quaternion operator+(const float lhs, const Quaternion& rhs) { return rhs + lhs; } /** * Subtract two quaternions. */ RLCPP_NODISCARD Quaternion Subtract(const ::Quaternion& quaternion) const { return ::QuaternionSubtract(*this, quaternion); } /** * Subtract two quaternions. */ Quaternion operator-(const ::Quaternion& quaternion) const { return ::QuaternionSubtract(*this, quaternion); } Quaternion& operator-=(const ::Quaternion& quaternion) { set(::QuaternionSubtract(*this, quaternion)); return *this; } /** * Subtract quaternion by float value */ RLCPP_NODISCARD Quaternion Subtract(const float value) const { return ::QuaternionSubtractValue(*this, value); } /** * Get identity quaternion */ static RLCPP_NODISCARD Quaternion Identity() { return ::QuaternionIdentity(); } RLCPP_NODISCARD float Length() const { return ::QuaternionLength(*this); } RLCPP_NODISCARD Quaternion Normalize() const { return ::QuaternionNormalize(*this); } RLCPP_NODISCARD Quaternion Invert() const { return ::QuaternionInvert(*this); } /** * Multiply quaternion by quaternion */ RLCPP_NODISCARD Quaternion Multiply(const ::Quaternion& other) const { return ::QuaternionMultiply(*this, other); } /** * Multiply quaternion by quaternion */ Quaternion operator*(const ::Quaternion& other) const { return ::QuaternionMultiply(*this, other); } /** * Multiply quaternion by quaternion */ Quaternion& operator*=(const ::Quaternion& other) { set(::QuaternionMultiply(*this, other)); return *this; } /** * Scale quaternion components by value (multiply) */ RLCPP_NODISCARD Quaternion Scale(const float scale) const { return ::QuaternionScale(*this, scale); } /** * Divide quaternion by quaternion */ RLCPP_NODISCARD Quaternion Divide(const ::Quaternion& quaternion) const { return ::QuaternionDivide(*this, quaternion); } /** * Divide quaternion by quaternion */ Quaternion operator/(const ::Quaternion& quaternion) const { return ::QuaternionDivide(*this, quaternion); } /** * Divide quaternion by quaternion */ Quaternion& operator/=(const ::Quaternion& quaternion) { set(::QuaternionDivide(*this, quaternion)); return *this; } /** * Divide quaternion components by value */ RLCPP_NODISCARD constexpr Quaternion Divide(const float div) const { return ::Quaternion{x / div, y / div, z / div, w / div}; } RLCPP_NODISCARD Quaternion Lerp(const ::Quaternion& v2, const float amount) const { return ::QuaternionLerp(*this, v2, amount); } /** * Calculate normalized linear interpolation between two quaternions */ RLCPP_NODISCARD Quaternion Nlerp(const ::Quaternion& v2, const float amount) const { return ::QuaternionNlerp(*this, v2, amount); } /** * Calculates spherical linear interpolation between two quaternions */ RLCPP_NODISCARD Quaternion Slerp(const ::Quaternion& v2, const float amount) const { return ::QuaternionSlerp(*this, v2, amount); } /** * Calculate quaternion cubic spline interpolation using Cubic Hermite Spline */ RLCPP_NODISCARD Quaternion CubicHermiteSpline( const ::Quaternion& outTangent1, const ::Quaternion& q2, const ::Quaternion& inTangent2, const float t ) const { return ::QuaternionCubicHermiteSpline(*this, outTangent1, q2, inTangent2, t); } /** * Calculate quaternion based on the rotation from one vector to another */ static RLCPP_NODISCARD Quaternion FromVector3ToVector3(const ::Vector3& from, const ::Vector3& to) { return ::QuaternionFromVector3ToVector3(from, to); } /** * Get a quaternion for a given rotation matrix */ static RLCPP_NODISCARD Quaternion FromMatrix(const ::Matrix& mat) { return ::QuaternionFromMatrix(mat); } /** * Get a matrix for this quaternion */ RLCPP_NODISCARD ::Matrix ToMatrix() const { return ::QuaternionToMatrix(*this); } /** * Get rotation quaternion for an angle and axis * NOTE: Angle must be provided in radians */ static RLCPP_NODISCARD Quaternion FromAxisAngle(const ::Vector3& axis, const float angle) { return ::QuaternionFromAxisAngle(axis, angle); } /** * Get the rotation angle and axis for this quaternion */ void ToAxisAngle(::Vector3* outAxis, float* outAngle) const { ::QuaternionToAxisAngle(*this, outAxis, outAngle); } /** * Get the quaternion equivalent to Euler angles * NOTE: Rotation order is ZYX */ static RLCPP_NODISCARD Quaternion FromEuler(const float pitch, const float yaw, const float roll) { return ::QuaternionFromEuler(pitch, yaw, roll); } /** * Get the Euler angles equivalent to quaternion * NOTE: Angles are returned in radians */ RLCPP_NODISCARD ::Vector3 ToEuler() const { return ::QuaternionToEuler(*this); } /** * Transform quaternion given transformation matrix */ RLCPP_NODISCARD Quaternion Transform(const ::Matrix& mat) const { return ::QuaternionTransform(*this, mat); } /* * Check whether two given quaternions are almost equal */ RLCPP_NODISCARD bool Equals(const ::Quaternion& other) const { return static_cast(::QuaternionEquals(*this, other)); } #endif protected: void set(const ::Quaternion& quat) { x = quat.x; y = quat.y; z = quat.z; w = quat.w; } }; } // namespace raylib using RQuaternion = raylib::Quaternion; #endif // RAYLIB_CPP_INCLUDE_QUATERNION_HPP_