# euler angles

You may wonder what glm_euler_sq type ( _sq stands for sequence ) and `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 `glm_euler_by_order()` is your friend. For more information check `glm_euler_order()` documentation

You must pass arrays as array, if you use C compiler then you can use something like this:

```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 `glm_euler()` function is the short name of `glm_euler_xyz()` this is why you can’t see `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

```float pitch, yaw, roll;
mat4  rot;

/* pitch = degrees; yaw = degrees; roll = degrees */
```
1. 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

2. cglm may implemented it wrong, consider to create an issue to report it or pull request to fix it

Types:

1. glm_euler_sq

Functions:

## Functions documentation

glm_euler_sq glm_euler_order(int ord[3])
packs euler angles order to glm_euler_sq enum.

To use `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

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]
void glm_euler(vec3 angles, mat4 dest)
build rotation matrix from euler angles

this is alias of glm_euler_xyz function

Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] dest rotation matrix
void glm_euler_xyz(vec3 angles, mat4 dest)
build rotation matrix from euler angles
Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] dest rotation matrix
void glm_euler_zyx(vec3 angles, mat4 dest)
build rotation matrix from euler angles
Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] dest rotation matrix
void glm_euler_zxy(vec3 angles, mat4 dest)
build rotation matrix from euler angles
Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] dest rotation matrix
void glm_euler_xzy(vec3 angles, mat4 dest)
build rotation matrix from euler angles
Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] dest rotation matrix
void glm_euler_yzx(vec3 angles, mat4 dest)

build rotation matrix from euler angles

Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] dest rotation matrix
void glm_euler_yxz(vec3 angles, mat4 dest)
build rotation matrix from euler angles
Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] dest rotation matrix
void glm_euler_by_order(vec3 angles, glm_euler_sq ord, mat4 dest)
build rotation matrix from euler angles with given euler order.

Use `glm_euler_order()` function to build ord parameter

Parameters:
[in] angles angles as vector [Xangle, Yangle, Zangle]
[in] ord euler order
[in] dest rotation matrix