Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-12-09 12:01:44 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-12-09 12:01:44 +0300
commit9e365069afe156f33fadfad9705e1325f894cd54 (patch)
tree78373044d029feb51f987b45208e0c1a36958625 /source/blender/blenlib/BLI_math_rotation.h
parentd8b42751625c915113b64f5a2d9c72f19f009fee (diff)
Cleanup: move public doc-strings into headers for 'blenlib'
- Added space below non doc-string comments to make it clear these aren't comments for the symbols directly below them. - Use doxy sections for some headers. - Minor improvements to doc-strings. Ref T92709
Diffstat (limited to 'source/blender/blenlib/BLI_math_rotation.h')
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h206
1 files changed, 195 insertions, 11 deletions
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index 461b5a60c9d..bf447d954bc 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -38,25 +38,62 @@ extern "C" {
#define RAD2DEGF(_rad) ((_rad) * (float)(180.0 / M_PI))
#define DEG2RADF(_deg) ((_deg) * (float)(M_PI / 180.0))
-/******************************** Quaternions ********************************/
-/* stored in (w, x, y, z) order */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Quaternions
+ * Stored in (w, x, y, z) order.
+ * \{ */
+
+/* Initialize */
+
+/* Convenience, avoids setting Y axis everywhere. */
-/* init */
void unit_axis_angle(float axis[3], float *angle);
void unit_qt(float q[4]);
void copy_qt_qt(float q[4], const float a[4]);
/* arithmetic */
void mul_qt_qtqt(float q[4], const float a[4], const float b[4]);
+/**
+ * \note
+ * Assumes a unit quaternion?
+ *
+ * in fact not, but you may want to use a unit quaternion read on...
+ *
+ * Shortcut for 'q v q*' when \a v is actually a quaternion.
+ * This removes the need for converting a vector to a quaternion,
+ * calculating q's conjugate and converting back to a vector.
+ * It also happens to be faster (17+,24* vs * 24+,32*).
+ * If \a q is not a unit quaternion, then \a v will be both rotated by
+ * the same amount as if q was a unit quaternion, and scaled by the square of
+ * the length of q.
+ *
+ * For people used to python mathutils, its like:
+ * def mul_qt_v3(q, v): (q * Quaternion((0.0, v[0], v[1], v[2])) * q.conjugated())[1:]
+ *
+ * \note Multiplying by 3x3 matrix is ~25% faster.
+ */
void mul_qt_v3(const float q[4], float r[3]);
+/**
+ * Simple multiply.
+ */
void mul_qt_fl(float q[4], const float f);
+/**
+ * Raise a unit quaternion to the specified power.
+ */
void pow_qt_fl_normalized(float q[4], const float f);
void sub_qt_qtqt(float q[4], const float a[4], const float b[4]);
void invert_qt(float q[4]);
void invert_qt_qt(float q1[4], const float q2[4]);
+/**
+ * This is just conjugate_qt for cases we know \a q is unit-length.
+ * we could use #conjugate_qt directly, but use this function to show intent,
+ * and assert if its ever becomes non-unit-length.
+ */
void invert_qt_normalized(float q[4]);
void invert_qt_qt_normalized(float q1[4], const float q2[4]);
void conjugate_qt(float q[4]);
@@ -69,6 +106,14 @@ float normalize_qt_qt(float r[4], const float q[4]);
bool is_zero_qt(const float q[4]);
/* interpolation */
+/**
+ * Generic function for implementing slerp
+ * (quaternions and spherical vector coords).
+ *
+ * \param t: factor in [0..1]
+ * \param cosom: dot product from normalized vectors/quats.
+ * \param r_w: calculated weights.
+ */
void interp_dot_slerp(const float t, const float cosom, float w[2]);
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], const float t);
void add_qt_qtqt(float q[4], const float a[4], const float b[4], const float t);
@@ -77,24 +122,51 @@ void add_qt_qtqt(float q[4], const float a[4], const float b[4], const float t);
void quat_to_mat3(float mat[3][3], const float q[4]);
void quat_to_mat4(float mat[4][4], const float q[4]);
+/**
+ * Apply the rotation of \a a to \a q keeping the values compatible with \a old.
+ * Avoid axis flipping for animated f-curves for eg.
+ */
void quat_to_compatible_quat(float q[4], const float a[4], const float old[4]);
void mat3_normalized_to_quat(float q[4], const float mat[3][3]);
void mat4_normalized_to_quat(float q[4], const float mat[4][4]);
void mat3_to_quat(float q[4], const float mat[3][3]);
void mat4_to_quat(float q[4], const float mat[4][4]);
+/**
+ * Same as tri_to_quat() but takes pre-computed normal from the triangle
+ * used for ngons when we know their normal.
+ */
void tri_to_quat_ex(float quat[4],
const float v1[3],
const float v2[3],
const float v3[3],
const float no_orig[3]);
+/**
+ * \return the length of the normal, use to test for degenerate triangles.
+ */
float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3]);
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag);
-/* NOTE: v1 and v2 must be normalized. */
+/**
+ * Calculate a rotation matrix from 2 normalized vectors.
+ * \note `v1` and `v2` must be normalized.
+ */
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3]);
+/**
+ * \note Expects vectors to be normalized.
+ */
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]);
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4]);
+/**
+ * Decompose a quaternion into a swing rotation (quaternion with the selected
+ * axis component locked at zero), followed by a twist rotation around the axis.
+ *
+ * \param q: input quaternion.
+ * \param axis: twist axis in [0,1,2]
+ * \param r_swing: if not NULL, receives the swing quaternion.
+ * \param r_twist: if not NULL, receives the twist quaternion.
+ * \returns twist angle.
+ */
float quat_split_swing_and_twist(const float q[4], int axis, float r_swing[4], float r_twist[4]);
float angle_normalized_qt(const float q[4]);
@@ -107,7 +179,9 @@ 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 */
+/**
+ * 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], const float mat[3][3]);
/* other */
@@ -115,61 +189,120 @@ void print_qt(const char *str, const float q[4]);
#define print_qt_id(q) print_qt(STRINGIFY(q), q)
-/******************************** Axis Angle *********************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Axis Angle
+ * \{ */
/* conversion */
void axis_angle_normalized_to_quat(float r[4], const float axis[3], const float angle);
void axis_angle_to_quat(float r[4], const float axis[3], const float angle);
+/**
+ * Axis angle to 3x3 matrix - safer version (normalization of axis performed).
+ */
void axis_angle_to_mat3(float R[3][3], const float axis[3], const float angle);
+/**
+ * axis angle to 3x3 matrix
+ *
+ * This takes the angle with sin/cos applied so we can avoid calculating it in some cases.
+ *
+ * \param axis: rotation axis (must be normalized).
+ * \param angle_sin: sin(angle)
+ * \param angle_cos: cos(angle)
+ */
void axis_angle_normalized_to_mat3_ex(float mat[3][3],
const float axis[3],
const float angle_sin,
const float angle_cos);
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], const float angle);
+/**
+ * Axis angle to 4x4 matrix - safer version (normalization of axis performed).
+ */
void axis_angle_to_mat4(float R[4][4], const float axis[3], const float angle);
+/**
+ * 3x3 matrix to axis angle.
+ */
void mat3_normalized_to_axis_angle(float axis[3], float *angle, const float M[3][3]);
+/**
+ * 4x4 matrix to axis angle.
+ */
void mat4_normalized_to_axis_angle(float axis[3], float *angle, const float M[4][4]);
void mat3_to_axis_angle(float axis[3], float *angle, const float M[3][3]);
+/**
+ * 4x4 matrix to axis angle.
+ */
void mat4_to_axis_angle(float axis[3], float *angle, const float M[4][4]);
+/**
+ * Quaternions to Axis Angle.
+ */
void quat_to_axis_angle(float axis[3], float *angle, const float q[4]);
void angle_to_mat2(float R[2][2], const float angle);
+/**
+ * Create a 3x3 rotation matrix from a single axis.
+ */
void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle);
+/**
+ * Create a 4x4 rotation matrix from a single axis.
+ */
void axis_angle_to_mat4_single(float R[4][4], const char axis, const float angle);
void axis_angle_to_quat_single(float q[4], const char axis, const float angle);
-/****************************** Exponential Map ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Exponential Map
+ * \{ */
+
void quat_to_expmap(float expmap[3], const float q[4]);
void quat_normalized_to_expmap(float expmap[3], const float q[4]);
void expmap_to_quat(float r[4], const float expmap[3]);
-/******************************** XYZ Eulers *********************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name XYZ Eulers
+ * \{ */
+/* XYZ order. */
void eul_to_quat(float quat[4], const float eul[3]);
+/* XYZ order */
void eul_to_mat3(float mat[3][3], const float eul[3]);
+/* XYZ order */
void eul_to_mat4(float mat[4][4], const float eul[3]);
+/* XYZ order */
void mat3_normalized_to_eul(float eul[3], const float mat[3][3]);
+/* XYZ order */
void mat4_normalized_to_eul(float eul[3], const float mat[4][4]);
void mat3_to_eul(float eul[3], const float mat[3][3]);
void mat4_to_eul(float eul[3], const float mat[4][4]);
+/* XYZ order */
void quat_to_eul(float eul[3], const float quat[4]);
+/* XYZ order */
void mat3_normalized_to_compatible_eul(float eul[3], const float old[3], float mat[3][3]);
void mat3_to_compatible_eul(float eul[3], const float old[3], float mat[3][3]);
void quat_to_compatible_eul(float eul[3], const float oldrot[3], const float quat[4]);
+/* order independent! */
void compatible_eul(float eul[3], const float old[3]);
+/* XYZ order */
void rotate_eul(float eul[3], const char axis, const float angle);
void add_eul_euleul(float r_eul[3], float a[3], float b[3], const short order);
void sub_eul_euleul(float r_eul[3], float a[3], float b[3], const short order);
-/************************** Arbitrary Order Eulers ***************************/
+/** \} */
-/* warning: must match the eRotationModes in DNA_action_types.h
+/* -------------------------------------------------------------------- */
+/** \name Arbitrary Order Eulers
+ * \{ */
+
+/* WARNING: must match the #eRotationModes in `DNA_action_types.h`
* order matters - types are saved to file. */
typedef enum eEulerRotationOrders {
@@ -183,19 +316,48 @@ typedef enum eEulerRotationOrders {
/* There are 6 more entries with duplicate entries included. */
} eEulerRotationOrders;
+/**
+ * Construct quaternion from Euler angles (in radians).
+ */
void eulO_to_quat(float quat[4], const float eul[3], const short order);
+/**
+ * Construct 3x3 matrix from Euler angles (in radians).
+ */
void eulO_to_mat3(float mat[3][3], const float eul[3], const short order);
+/**
+ * Construct 4x4 matrix from Euler angles (in radians).
+ */
void eulO_to_mat4(float mat[4][4], const float eul[3], const short order);
+/**
+ * Euler Rotation to Axis Angle.
+ */
void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], const short order);
+/**
+ * The matrix is written to as 3 axis vectors.
+ */
void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order);
+/**
+ * Convert 3x3 matrix to Euler angles (in radians).
+ */
void mat3_normalized_to_eulO(float eul[3], const short order, const float mat[3][3]);
+/**
+ * Convert 4x4 matrix to Euler angles (in radians).
+ */
void mat4_normalized_to_eulO(float eul[3], const short order, const float mat[4][4]);
void mat3_to_eulO(float eul[3], const short order, const float mat[3][3]);
void mat4_to_eulO(float eul[3], const short order, const float mat[4][4]);
+/**
+ * Convert quaternion to Euler angles (in radians).
+ */
void quat_to_eulO(float eul[3], const short order, const float quat[4]);
+/**
+ * Axis Angle to Euler Rotation.
+ */
void axis_angle_to_eulO(float eul[3], const short order, const float axis[3], const float angle);
+/* Uses 2 methods to retrieve eulers, and picks the closest. */
+
void mat3_normalized_to_compatible_eulO(float eul[3],
const float old[3],
const short order,
@@ -219,7 +381,11 @@ void quat_to_compatible_eulO(float eul[3],
void rotate_eulO(float eul[3], const short order, char axis, float angle);
-/******************************* Dual Quaternions ****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Dual Quaternions
+ * \{ */
void copy_dq_dq(DualQuat *r, const DualQuat *dq);
void normalize_dq(DualQuat *dq, float totw);
@@ -229,21 +395,39 @@ void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq);
void mat4_to_dquat(DualQuat *dq, const float basemat[4][4], const float mat[4][4]);
void dquat_to_mat4(float R[4][4], const DualQuat *dq);
+/**
+ * Axis matches #eTrackToAxis_Modes.
+ */
void quat_apply_track(float quat[4], short axis, short upflag);
void vec_apply_track(float vec[3], short axis);
+/**
+ * Lens/angle conversion (radians).
+ */
float focallength_to_fov(float focal_length, float sensor);
float fov_to_focallength(float fov, float sensor);
float angle_wrap_rad(float angle);
float angle_wrap_deg(float angle);
+/**
+ * Returns an angle compatible with angle_compat.
+ */
float angle_compat_rad(float angle, float angle_compat);
+/**
+ * Each argument us an axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z']
+ * where the first 2 are a source and the second 2 are the target.
+ */
bool mat3_from_axis_conversion(
int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3]);
+/**
+ * Use when the second axis can be guessed.
+ */
bool mat3_from_axis_conversion_single(int src_axis, int dst_axis, float r_mat[3][3]);
+/** \} */
+
#ifdef __cplusplus
}
#endif