From 1fd0a744786a8ef74e11c024a4fc39f4caabef97 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Thu, 1 Mar 2018 18:27:56 +0300 Subject: [PATCH] docs: euler angles documentation --- docs/source/api.rst | 1 + docs/source/euler.rst | 171 ++++++++++++++++++++++++++++++++++++++++++ include/cglm/euler.h | 54 ++++++++++--- 3 files changed, 216 insertions(+), 10 deletions(-) create mode 100644 docs/source/euler.rst diff --git a/docs/source/api.rst b/docs/source/api.rst index 496b9ca..7db4f83 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -30,6 +30,7 @@ Follow the :doc:`build` documentation for this affine-mat cam quat + euler mat4 mat3 vec3 diff --git a/docs/source/euler.rst b/docs/source/euler.rst new file mode 100644 index 0000000..1cf64ed --- /dev/null +++ b/docs/source/euler.rst @@ -0,0 +1,171 @@ +.. default-domain:: C + +Euler Angles +============ + +Header: cglm/euler.h + +You may wonder what **glm_euler_sq** type ( **_sq** stands for sequence ) and +:c:func:`glm_euler_by_order` do. +I used them to convert euler angles in one coordinate system to another. For +instance if you have **Z_UP** euler angles and if you want to convert it +to **Y_UP** axis then :c:func:`glm_euler_by_order` is your friend. For more +information check :c:func:`glm_euler_order` documentation + +You must pass arrays as array, if you use C compiler then you can use something +like this: + +.. code-block:: c + + float pitch, yaw, roll; + mat4 rot; + + /* pitch = ...; yaw = ...; roll = ... */ + glm_euler((vec3){pitch, yaw, roll}, rot); + +Rotation Conveniention +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Current *cglm*'s euler functions uses these convention: + +* Tait–Bryan angles (x-y-z convention) +* Intrinsic rotations (pitch, yaw and roll). + This is reserve order of extrinsic (elevation, heading and bank) rotation +* Right hand rule (actually all rotations in *cglm* use **RH**) +* All angles used in *cglm* are **RADIANS** not degrees + + +**NOTE**: The default :c:func:`glm_euler` function is the short name of +:c:func:`glm_euler_xyz` this is why you can't see :c:func:`glm_euler_xyz`. +When you see an euler function which doesn't have any X, Y, Z suffix then +assume that uses **_xyz** (or instead it accept order as parameter). + +If rotation doesn't work properly, your options: + +1. If you use (or paste) degrees convert it to radians before calling an euler function + +.. code-block:: c + + float pitch, yaw, roll; + mat4 rot; + + /* pitch = degrees; yaw = degrees; roll = degrees */ + glm_euler((vec3){glm_rad(pitch), glm_rad(yaw), glm_rad(roll)}, rot); + +2. Convention mismatch. You may have extrinsic angles, + if you do (if you must) then consider to use reverse order e.g if you have + **xyz** extrinsic then use **zyx** + +3. *cglm* may implemented it wrong, consider to create an issue to report it + or pull request to fix it + +Table of contents (click to go): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Types: + +1. glm_euler_sq + +Functions: + +1. :c:func:`glm_euler_order` +#. :c:func:`glm_euler_angles` +#. :c:func:`glm_euler` +#. :c:func:`glm_euler_zyx` +#. :c:func:`glm_euler_zxy` +#. :c:func:`glm_euler_xzy` +#. :c:func:`glm_euler_yzx` +#. :c:func:`glm_euler_yxz` +#. :c:func:`glm_euler_by_order` + +Functions documentation +~~~~~~~~~~~~~~~~~~~~~~~ + +.. c:function:: glm_euler_sq glm_euler_order(int ord[3]) + + | packs euler angles order to glm_euler_sq enum. + + To use :c:func:`glm_euler_by_order` function you need *glm_euler_sq*. You + can get it with this function. + + You can build param like this: + + | X = 0, Y = 1, Z = 2 + + if you have ZYX order then you pass this: [2, 1, 0] = ZYX. + if you have YXZ order then you pass this: [1, 0, 2] = YXZ + + As you can see first item specifies which axis will be first then the + second one specifies which one will be next an so on. + + Parameters: + | *[in]* **ord** euler angles order [Angle1, Angle2, Angle2] + + Returns: + packed euler order + +.. c:function:: void glm_euler_angles(mat4 m, vec3 dest) + + | extract euler angles (in radians) using xyz order + + Parameters: + | *[in]* **m** affine transform + | *[out]* **dest** angles vector [x, y, z] + +.. c:function:: void glm_euler(vec3 angles, mat4 dest) + + | build rotation matrix from euler angles + + Parameters: + | *[in]* **angles** angles as vector [Ex, Ey, Ez] + | *[in]* **dest** rotation matrix + +.. c:function:: void glm_euler_zyx(vec3 angles, mat4 dest) + + | build rotation matrix from euler angles + + Parameters: + | *[in]* **angles** angles as vector [Ez, Ey, Ex] + | *[in]* **dest** rotation matrix + +.. c:function:: void glm_euler_zxy(vec3 angles, mat4 dest) + + | build rotation matrix from euler angles + + Parameters: + | *[in]* **angles** angles as vector [Ez, Ex, Ey] + | *[in]* **dest** rotation matrix + +.. c:function:: void glm_euler_xzy(vec3 angles, mat4 dest) + + | build rotation matrix from euler angles + + Parameters: + | *[in]* **angles** angles as vector [Ex, Ez, Ey] + | *[in]* **dest** rotation matrix + +.. c:function:: void glm_euler_yzx(vec3 angles, mat4 dest) + + build rotation matrix from euler angles + + Parameters: + | *[in]* **angles** angles as vector [Ey, Ez, Ex] + | *[in]* **dest** rotation matrix + +.. c:function:: void glm_euler_yxz(vec3 angles, mat4 dest) + + | build rotation matrix from euler angles + + Parameters: + | *[in]* **angles** angles as vector [Ey, Ex, Ez] + | *[in]* **dest** rotation matrix + +.. c:function:: void glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest) + + | build rotation matrix from euler angles with given euler order. + + Use :c:func:`glm_euler_order` function to build *ord* parameter + + Parameters: + | *[in]* **angles** angles as vector (ord parameter spceifies angles order) + | *[in]* **ord** euler order + | *[in]* **dest** rotation matrix diff --git a/include/cglm/euler.h b/include/cglm/euler.h index bf62bb7..2289b04 100644 --- a/include/cglm/euler.h +++ b/include/cglm/euler.h @@ -8,7 +8,7 @@ /* Types: enum glm_euler_sq - + Functions: CGLM_INLINE glm_euler_sq glm_euler_order(int newOrder[3]); CGLM_INLINE void glm_euler_angles(mat4 m, vec3 dest); @@ -19,7 +19,7 @@ CGLM_INLINE void glm_euler_yzx(vec3 angles, mat4 dest); CGLM_INLINE void glm_euler_yxz(vec3 angles, mat4 dest); CGLM_INLINE void glm_euler_by_order(vec3 angles, - glm_euler_sq axis, + glm_euler_sq ord, mat4 dest); */ @@ -48,12 +48,12 @@ typedef enum glm_euler_sq { CGLM_INLINE glm_euler_sq -glm_euler_order(int newOrder[3]) { - return (glm_euler_sq)(newOrder[0] | newOrder[1] << 2 | newOrder[2] << 4); +glm_euler_order(int ord[3]) { + return (glm_euler_sq)(ord[0] << 0 | ord[1] << 2 | ord[2] << 4); } /*! - * @brief euler angles (in radian) using xyz sequence + * @brief extract euler angles (in radians) using xyz order * * @param[in] m affine transform * @param[out] dest angles vector [x, y, z] @@ -66,7 +66,7 @@ glm_euler_angles(mat4 m, vec3 dest) { vec3 a[2]; float cy1, cy2; int path; - + a[0][1] = asinf(-m[0][2]); a[1][1] = CGLM_PI - a[0][1]; @@ -96,7 +96,7 @@ glm_euler_angles(mat4 m, vec3 dest) { } /*! - * @brief build rotation matrix from euler angles(ExEyEz/RzRyRx) + * @brief build rotation matrix from euler angles * * @param[in] angles angles as vector [Ex, Ey, Ez] * @param[out] dest rotation matrix @@ -130,7 +130,10 @@ glm_euler(vec3 angles, mat4 dest) { } /*! - * @brief build rotation matrix from euler angles (EzEyEx/RxRyRz) + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Ez, Ey, Ex] + * @param[out] dest rotation matrix */ CGLM_INLINE void @@ -161,6 +164,12 @@ glm_euler_zyx(vec3 angles, dest[3][3] = 1.0f; } +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Ez, Ex, Ey] + * @param[out] dest rotation matrix + */ CGLM_INLINE void glm_euler_zxy(vec3 angles, @@ -190,6 +199,12 @@ glm_euler_zxy(vec3 angles, dest[3][3] = 1.0f; } +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Ex, Ez, Ey] + * @param[out] dest rotation matrix + */ CGLM_INLINE void glm_euler_xzy(vec3 angles, @@ -219,6 +234,12 @@ glm_euler_xzy(vec3 angles, dest[3][3] = 1.0f; } +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Ey, Ez, Ex] + * @param[out] dest rotation matrix + */ CGLM_INLINE void glm_euler_yzx(vec3 angles, @@ -248,6 +269,12 @@ glm_euler_yzx(vec3 angles, dest[3][3] = 1.0f; } +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector [Ey, Ex, Ez] + * @param[out] dest rotation matrix + */ CGLM_INLINE void glm_euler_yxz(vec3 angles, @@ -277,9 +304,16 @@ glm_euler_yxz(vec3 angles, dest[3][3] = 1.0f; } +/*! + * @brief build rotation matrix from euler angles + * + * @param[in] angles angles as vector (ord parameter spceifies angles order) + * @param[in] ord euler order + * @param[out] dest rotation matrix + */ CGLM_INLINE void -glm_euler_by_order(vec3 angles, glm_euler_sq axis, mat4 dest) { +glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest) { float cx, cy, cz, sx, sy, sz; @@ -297,7 +331,7 @@ glm_euler_by_order(vec3 angles, glm_euler_sq axis, mat4 dest) { czsx = cz * sx; cxsz = cx * sz; sysz = sy * sz; - switch (axis) { + switch (ord) { case GLM_EULER_XYZ: dest[0][0] = cycz; dest[0][1] = cysz;