Blender V5.0
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
10
14
15#include "BLI_math_matrix.hh"
17
18namespace blender::math {
19
20/* -------------------------------------------------------------------- */
23
24template<typename T, typename AngleT>
26{
28 axis_ = axis;
29 angle_ = angle;
30}
31
32template<typename T, typename AngleT>
34{
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
65
66/* -------------------------------------------------------------------- */
69
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
84
85/* -------------------------------------------------------------------- */
88
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 if (axis.y == T(1)) {
105 return EulerXYZBase<T>(T(0), T(axis_angle.angle()), T(0));
106 }
107 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
115
116} // namespace blender::math
#define BLI_assert(a)
Definition BLI_assert.h:46
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
#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)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &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)