diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-12-09 12:01:44 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-12-09 12:01:44 +0300 |
commit | 9e365069afe156f33fadfad9705e1325f894cd54 (patch) | |
tree | 78373044d029feb51f987b45208e0c1a36958625 /source/blender/blenlib/BLI_math_rotation.h | |
parent | d8b42751625c915113b64f5a2d9c72f19f009fee (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.h | 206 |
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 |