This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/BLI_math_axis_angle.hh
Clément Foucault 4805a54525 BLI: Math: Move rotation types template out of math::detail
The reasoning is that the detail namespace is not to be used
outside the module itself. But one might want to use different
number types with these templates.

The `Base` suffix was chosen in order to be consistent with `MatBase`
and `Vector` naming convention.
2023-03-10 11:48:15 +01:00

115 lines
2.9 KiB
C++

/* 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_matrix.hh"
#include "BLI_math_quaternion.hh"
namespace blender::math {
/* -------------------------------------------------------------------- */
/** \name Constructors
* \{ */
template<typename T, typename AngleT>
AxisAngleBase<T, AngleT>::AxisAngleBase(const VecBase<T, 3> &axis, const AngleT &angle)
{
BLI_assert(is_unit_scale(axis));
axis_ = axis;
angle_ = angle;
}
template<typename T, typename AngleT>
AxisAngleBase<T, AngleT>::AxisAngleBase(const AxisSigned axis, const AngleT &angle)
{
axis_ = to_vector<VecBase<T, 3>>(axis);
angle_ = angle;
}
template<typename T, typename AngleT>
AxisAngleBase<T, AngleT>::AxisAngleBase(const VecBase<T, 3> &from, const VecBase<T, 3> &to)
{
BLI_assert(is_unit_scale(from));
BLI_assert(is_unit_scale(to));
T sin;
T cos = dot(from, to);
axis_ = normalize_and_get_length(cross(from, to), sin);
if (sin <= FLT_EPSILON) {
if (cos > T(0)) {
/* Same vectors, zero rotation... */
*this = identity();
return;
}
/* Colinear but opposed vectors, 180 rotation... */
axis_ = normalize(orthogonal(from));
sin = T(0);
cos = T(-1);
}
/* Avoid calculating the angle if possible. */
angle_ = AngleT(cos, sin);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Conversion to Quaternions
* \{ */
template<typename T, typename AngleT>
QuaternionBase<T> to_quaternion(const AxisAngleBase<T, AngleT> &axis_angle)
{
BLI_assert(math::is_unit_scale(axis_angle.axis()));
AngleT half_angle = axis_angle.angle() / 2;
T hs = math::sin(half_angle);
T hc = math::cos(half_angle);
VecBase<T, 3> xyz = axis_angle.axis() * hs;
return QuaternionBase<T>(hc, xyz.x, xyz.y, xyz.z);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Conversion to Euler
* \{ */
template<typename T, typename AngleT>
Euler3Base<T> to_euler(const AxisAngleBase<T, AngleT> &axis_angle, EulerOrder order)
{
/* Use quaternions as intermediate representation for now... */
return to_euler(to_quaternion(axis_angle), order);
}
template<typename T, typename AngleT>
EulerXYZBase<T> to_euler(const AxisAngleBase<T, AngleT> &axis_angle)
{
/* Check easy and exact conversions first. */
const VecBase<T, 3> axis = axis_angle.axis();
if (axis.x == T(1)) {
return EulerXYZBase<T>(T(axis_angle.angle()), T(0), T(0));
}
else if (axis.y == T(1)) {
return EulerXYZBase<T>(T(0), T(axis_angle.angle()), T(0));
}
else if (axis.z == T(1)) {
return EulerXYZBase<T>(T(0), T(0), T(axis_angle.angle()));
}
/* Use quaternions as intermediate representation for now... */
return to_euler(to_quaternion(axis_angle));
}
/** \} */
} // namespace blender::math