Blender V4.3
BLI_math_axis_angle.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
14
15#include "BLI_math_matrix.hh"
17
18namespace blender::math {
19
20/* -------------------------------------------------------------------- */
24template<typename T, typename AngleT>
26{
28 axis_ = axis;
29 angle_ = angle;
30}
31
32template<typename T, typename AngleT>
34{
35 axis_ = to_vector<VecBase<T, 3>>(axis);
36 angle_ = angle;
37}
38
39template<typename T, typename AngleT>
41{
44
45 T sin;
46 T cos = dot(from, to);
47 axis_ = normalize_and_get_length(cross(from, to), sin);
48
49 if (sin <= std::numeric_limits<T>::epsilon()) {
50 if (cos > T(0)) {
51 /* Same vectors, zero rotation... */
52 *this = identity();
53 return;
54 }
55 /* Colinear but opposed vectors, 180 rotation... */
56 axis_ = normalize(orthogonal(from));
57 sin = T(0);
58 cos = T(-1);
59 }
60 /* Avoid calculating the angle if possible. */
61 angle_ = AngleT(cos, sin);
62}
63
66/* -------------------------------------------------------------------- */
70template<typename T, typename AngleT>
72{
73 BLI_assert(math::is_unit_scale(axis_angle.axis()));
74
75 AngleT half_angle = axis_angle.angle() / 2;
76 T hs = math::sin(half_angle);
77 T hc = math::cos(half_angle);
78
79 VecBase<T, 3> xyz = axis_angle.axis() * hs;
80 return QuaternionBase<T>(hc, xyz.x, xyz.y, xyz.z);
81}
82
85/* -------------------------------------------------------------------- */
89template<typename T, typename AngleT>
91{
92 /* Use quaternions as intermediate representation for now... */
93 return to_euler(to_quaternion(axis_angle), order);
94}
95
96template<typename T, typename AngleT>
98{
99 /* Check easy and exact conversions first. */
100 const VecBase<T, 3> axis = axis_angle.axis();
101 if (axis.x == T(1)) {
102 return EulerXYZBase<T>(T(axis_angle.angle()), T(0), T(0));
103 }
104 else if (axis.y == T(1)) {
105 return EulerXYZBase<T>(T(0), T(axis_angle.angle()), T(0));
106 }
107 else if (axis.z == T(1)) {
108 return EulerXYZBase<T>(T(0), T(0), T(axis_angle.angle()));
109 }
110 /* Use quaternions as intermediate representation for now... */
111 return to_euler(to_quaternion(axis_angle));
112}
113
116} // namespace blender::math
#define BLI_assert(a)
Definition BLI_assert.h:50
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
#define T
T cos(const AngleRadianBase< T > &a)
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
T to_vector(const Axis axis)
QuaternionBase< T > normalize_and_get_length(const QuaternionBase< T > &q, T &out_length)
bool is_unit_scale(const MatBase< T, NumCol, NumRow > &m)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
T sin(const AngleRadianBase< T > &a)
VecBase< T, 3 > orthogonal(const VecBase< T, 3 > &v)
Euler3Base< T > to_euler(const AxisAngleBase< T, AngleT > &axis_angle, EulerOrder order)