/* SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once /** \file * \ingroup bli */ #include "BLI_math_axis_angle_types.hh" #include "BLI_math_euler_types.hh" #include "BLI_math_quaternion_types.hh" #include "BLI_math_axis_angle.hh" #include "BLI_math_matrix.hh" #include "BLI_math_quaternion.hh" namespace blender::math { /* -------------------------------------------------------------------- */ /** \name EulerXYZ * \{ */ template EulerXYZBase EulerXYZBase::wrapped() const { EulerXYZBase result(*this); result.x() = AngleRadianBase(result.x()).wrapped().radian(); result.y() = AngleRadianBase(result.y()).wrapped().radian(); result.z() = AngleRadianBase(result.z()).wrapped().radian(); return result; } template EulerXYZBase EulerXYZBase::wrapped_around(const EulerXYZBase &reference) const { EulerXYZBase result(*this); result.x() = AngleRadianBase(result.x()).wrapped_around(reference.x()).radian(); result.y() = AngleRadianBase(result.y()).wrapped_around(reference.y()).radian(); result.z() = AngleRadianBase(result.z()).wrapped_around(reference.z()).radian(); return result; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Conversion to Quaternions * \{ */ template QuaternionBase to_quaternion(const EulerXYZBase &eul) { using AngleT = typename EulerXYZBase::AngleT; const AngleT h_angle_i = eul.x() / 2; const AngleT h_angle_j = eul.y() / 2; const AngleT h_angle_k = eul.z() / 2; const T cos_i = math::cos(h_angle_i); const T cos_j = math::cos(h_angle_j); const T cos_k = math::cos(h_angle_k); const T sin_i = math::sin(h_angle_i); const T sin_j = math::sin(h_angle_j); const T sin_k = math::sin(h_angle_k); const T cos_cos = cos_i * cos_k; const T cos_sin = cos_i * sin_k; const T sin_cos = sin_i * cos_k; const T sin_sin = sin_i * sin_k; QuaternionBase quat; quat.w = cos_j * cos_cos + sin_j * sin_sin; quat.x = cos_j * sin_cos - sin_j * cos_sin; quat.y = cos_j * sin_sin + sin_j * cos_cos; quat.z = cos_j * cos_sin - sin_j * sin_cos; return quat; } template QuaternionBase to_quaternion(const Euler3Base &eulO) { /* Swizzle to XYZ. */ EulerXYZBase eul_xyz{eulO.ijk()}; /* Flip with parity. */ eul_xyz.y() = eulO.parity() ? -eul_xyz.y() : eul_xyz.y(); /* Quaternion conversion. */ QuaternionBase quat = to_quaternion(eul_xyz); /* Swizzle back from XYZ. */ VecBase quat_xyz; quat_xyz[eulO.i_index()] = quat.x; quat_xyz[eulO.j_index()] = eulO.parity() ? -quat.y : quat.y; quat_xyz[eulO.k_index()] = quat.z; return {quat.w, UNPACK3(quat_xyz)}; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Conversion to axis angles * \{ */ template AxisAngleBase to_axis_angle(const EulerXYZBase &euler) { /* Use quaternions as intermediate representation for now... */ return to_axis_angle(to_quaternion(euler)); } template AxisAngleBase to_axis_angle(const Euler3Base &euler) { /* Use quaternions as intermediate representation for now... */ return to_axis_angle(to_quaternion(euler)); } /** \} */ } // namespace blender::math /** \} */