[Bf-blender-cvs] [7a58ff928c2] master: Math Lib: signed versions of quaternion angle

Campbell Barton noreply at git.blender.org
Tue Dec 19 04:05:56 CET 2017


Commit: 7a58ff928c21110d9798e0d94ed2be1de7400f90
Author: Campbell Barton
Date:   Tue Dec 19 13:59:18 2017 +1100
Branches: master
https://developer.blender.org/rB7a58ff928c21110d9798e0d94ed2be1de7400f90

Math Lib: signed versions of quaternion angle

There was no simple way to get the shortest quaternion angle.

===================================================================

M	source/blender/blenlib/BLI_math_rotation.h
M	source/blender/blenlib/intern/math_rotation.c

===================================================================

diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index e059327a490..1f206e5e234 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -97,6 +97,11 @@ float angle_normalized_qtqt(const float q1[4], const float q2[4]);
 float angle_qt(const float q[4]);
 float angle_qtqt(const float q1[4], const float q2[4]);
 
+float angle_signed_normalized_qt(const float q[4]);
+float angle_signed_normalized_qtqt(const float q1[4], const float q2[4]);
+float angle_signed_qt(const float q[4]);
+float angle_signed_qtqt(const float q1[4], const float q2[4]);
+
 /* TODO: don't what this is, but it's not the same as mat3_to_quat */
 void mat3_to_quat_is_ok(float q[4], float mat[3][3]);
 
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 23bd5e60e22..29e7cf32ddc 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -511,6 +511,14 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q
 }
 
 
+/* -------------------------------------------------------------------- */
+/** \name Quaternion Angle
+ *
+ * Unlike the angle between vectors, this does NOT return the shortest angle.
+ * See signed functions below for this.
+ *
+ * \{ */
+
 float angle_normalized_qt(const float q[4])
 {
 	BLI_ASSERT_UNIT_QUAT(q);
@@ -548,6 +556,64 @@ float angle_qtqt(const float q1[4], const float q2[4])
 	return angle_normalized_qtqt(quat1, quat2);
 }
 
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Quaternion Angle (Signed)
+ *
+ * Angles with quaternion calculation can exceed 180d,
+ * Having signed versions of these functions allows 'fabsf(angle_signed_qtqt(...))'
+ * to give us the shortest angle between quaternions.
+ * With higher precision than subtracting pi afterwards.
+ *
+ * \{ */
+
+float angle_signed_normalized_qt(const float q[4])
+{
+	BLI_ASSERT_UNIT_QUAT(q);
+	if (q[0] >= 0.0f) {
+		return 2.0f * saacos(q[0]);
+	}
+	else {
+		return -2.0f * saacos(-q[0]);
+	}
+}
+
+float angle_signed_normalized_qtqt(const float q1[4], const float q2[4])
+{
+	if (dot_qtqt(q1, q2) >= 0.0f) {
+		return angle_normalized_qtqt(q1, q2);
+	}
+	else {
+		float q2_copy[4];
+		negate_v4_v4(q2_copy, q2);
+		return -angle_normalized_qtqt(q1, q2_copy);
+	}
+}
+
+float angle_signed_qt(const float q[4])
+{
+	float tquat[4];
+
+	normalize_qt_qt(tquat, q);
+
+	return angle_signed_normalized_qt(tquat);
+}
+
+float angle_signed_qtqt(const float q1[4], const float q2[4])
+{
+	if (dot_qtqt(q1, q2) >= 0.0f) {
+		return angle_qtqt(q1, q2);
+	}
+	else {
+		float q2_copy[4];
+		negate_v4_v4(q2_copy, q2);
+		return -angle_qtqt(q1, q2_copy);
+	}
+}
+
+/** \} */
+
 void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
 {
 	const float eps = 1e-4f;



More information about the Bf-blender-cvs mailing list