/// Creates a 3D 3 * 3 rotation matrix from euler angles (Y * X * Z).
/// @see gtx_euler_angles
template<typename T, qualifier Q>
GLM_FUNC_DECL mat<3, 3, T, Q> orientate3(vec<3, T, Q> const& angles);
/// Returns euler angles, pitch as x, yaw as y, roll as z.
/// The result is expressed in radians.
///
/// @tparam T Floating-point scalar types.
///
/// @see gtc_quaternion
template<typename T, qualifier Q>
GLM_FUNC_DECL vec<3, T, Q> eulerAngles(qua<T, Q> const& x);
/// Returns roll value of euler angles expressed in radians.
///
/// @tparam T Floating-point scalar types.
///
/// @see gtc_quaternion
template<typename T, qualifier Q>
GLM_FUNC_DECL T roll(qua<T, Q> const& x);
/// Returns pitch value of euler angles expressed in radians.
///
/// @tparam T Floating-point scalar types.
///
/// @see gtc_quaternion
template<typename T, qualifier Q>
GLM_FUNC_DECL T pitch(qua<T, Q> const& x);
/// Returns yaw value of euler angles expressed in radians.
///
/// @tparam T Floating-point scalar types.
///
/// @see gtc_quaternion
template<typename T, qualifier Q>
GLM_FUNC_DECL T yaw(qua<T, Q> const& x);
// inl file:
GLM_FUNC_QUALIFIER vec<3, T, Q> eulerAngles(qua<T, Q> const& x)
{
return vec<3, T, Q>(pitch(x), yaw(x), roll(x));
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER T roll(qua<T, Q> const& q)
{
T const y = static_cast<T>(2) * (q.x * q.y + q.w * q.z);
T const x = q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z;
if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon<T>()))) //avoid atan2(0,0) - handle singularity - Matiis
return static_cast<T>(0);
return static_cast<T>(atan(y, x));
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER T pitch(qua<T, Q> const& q)
{
//return T(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z));
T const y = static_cast<T>(2) * (q.y * q.z + q.w * q.x);
T const x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z;
if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon<T>()))) //avoid atan2(0,0) - handle singularity - Matiis
return static_cast<T>(static_cast<T>(2) * atan(q.x, q.w));
return static_cast<T>(atan(y, x));
}
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER T yaw(qua<T, Q> const& q)
{
return asin(clamp(static_cast<T>(-2) * (q.x * q.z - q.w * q.y), static_cast<T>(-1), static_cast<T>(1)));
}
In
gtx/euler_angles.hpp, vec3 euler means xyz axis components of a YXZ transform:Whereas in
gtc/quaternion.hpp, vec3 euler means xyz axis components of a ZYX transform:For reference of which order is the quat implementation, compare with this file.
It seems there were issues with similar problems (#535 ) in the past.