Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

euler update: use Ken Shoemake's algorithm (gemsiv/euler_angle) #128

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,19 @@ https://forums.khronos.org/showthread.php/10651-Animation-TCB-Spline-Interpolati
12. vec2 cross product
http://allenchou.net/2013/07/cross-product-of-2d-vectors/

13. Ken Shoemake's algorithm Implementation and Euler
Ken Shoemake's algorithm impl. is taken from this repo by permission:
https://github.com/erich666/GraphicsGems/blob/master/gemsiv/euler_angle

* -------------------------- GraphicsGems EULA ----------------------------- *
| http://www.realtimerendering.com/resources/GraphicsGems/ |
| |
| EULA: The Graphics Gems code is copyright-protected. In other words, you |
| cannot claim the text of the code as your own and resell it. Using the |
| code is permitted in any program, product, or library, non-commercial or |
| commercial. Giving credit is not required, though is a nice gesture. |
| The code comes as-is, and if there are any flaws or problems with any Gems |
| code, nobody involved with Gems - authors, editors, publishers, or |
| webmasters - are to be held responsible. Basically, don't be a jerk, and |
| remember that anything free comes with no guarantee. |
* -------------------------------- END --------------------------------------*/
160 changes: 148 additions & 12 deletions include/cglm/euler.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,160 @@
enum glm_euler_seq

Functions:
CGLM_INLINE glm_euler_seq glm_euler_order(int newOrder[3]);
CGLM_INLINE void glm_euler_angles(mat4 m, vec3 dest);
CGLM_INLINE void glm_euler(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_xyz(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_zyx(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_zxy(vec3 angles, mat4 dest);
CGLM_INLINE void glm_euler_xzy(vec3 angles, mat4 dest);
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_seq ord,
mat4 dest);
CGLM_INLINE glm_eul_mat4(vec3 ea, int order, mat4 dest)
*/

#ifndef cglm_euler_h
#define cglm_euler_h

#include "common.h"
#include "util.h"

/* ---------- Notice for Ken Shoemake's algorithm Implementation -------------*
| Ken Shoemake's algorithm impl. is taken from this repo by permission: |
| https://github.com/erich666/GraphicsGems/blob/master/gemsiv/euler_angle |
| |
| cglm doesn't claim the ownership of GraphicsGems source codes |
| and the algorithm itself. But cglm may change variable names or some piece |
| of codes in order to apply optimizations or to make it usable in cglm. |
| |
| Related issue: https://github.com/recp/cglm/issues/30 |
| |
* -------------------------- GraphicsGems EULA ----------------------------- *
| Related EULA for GraphicsGems can be found at below, plus in CREDITS: |
| http://www.realtimerendering.com/resources/GraphicsGems/ |
| |
| EULA: The Graphics Gems code is copyright-protected. In other words, you |
| cannot claim the text of the code as your own and resell it. Using the |
| code is permitted in any program, product, or library, non-commercial or |
| commercial. Giving credit is not required, though is a nice gesture. |
| The code comes as-is, and if there are any flaws or problems with any Gems |
| code, nobody involved with Gems - authors, editors, publishers, or |
| webmasters - are to be held responsible. Basically, don't be a jerk, and |
| remember that anything free comes with no guarantee. |
* -------------------------------- END --------------------------------------*/

/* Order type constants, constructors, extractors
* There are 24 possible conventions, designated by:
* o EulAxI = axis used initially
* o EulPar = parity of axis permutation
* o EulRep = repetition of initial axis as last
* o EulFrm = frame from which axes are taken
* Axes I,J,K will be a permutation of X,Y,Z.
* Axis H will be either I or K, depending on EulRep.
* Frame S takes axes from initial static frame.
* If ord = (AxI=X, Par=Even, Rep=No, Frm=S), then
* {a,b,c,ord} means Rz(c)Ry(b)Rx(a), where Rz(c)v
* rotates v around Z by c radians.
*/

#define EulRep(ord) (((unsigned)(ord)>>1)&1)
#define EulFrm(ord) ((unsigned)(ord)&1)
#define EulPar(ord) (((unsigned)(ord)>>2)&1)

/*! this code is merely a quick (and legal!) way to set arrays,
EulSafe being 0,1,2,0 */
#define EulSafe "\000\001\002\000"
#define EulNext "\001\002\000\001"
#define EulAxI(ord) ((int)(EulSafe[(((unsigned)(ord)>>3)&3)]))
#define EulAxJ(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)==EulParOdd)]))
#define EulAxK(ord) ((int)(EulNext[EulAxI(ord)+(EulPar(ord)!=EulParOdd)]))
#define EulAxH(ord) ((EulRep(ord)==EulRepNo)?EulAxK(ord):EulAxI(ord))

/*! EulGetOrd unpacks all useful information about order simultaneously. */
#define EulGetOrd(ord,i,j,k,h,n,s,f) \
{unsigned o=(unsigned)ord;f=o&1;o>>=1;s=o&1;o>>=1;\
n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}

typedef enum glm_eul_order {
/*! Static axes */
GLM_EUL_XYZs = 0,
GLM_EUL_XYXs = 2,
GLM_EUL_XZYs = 4,
GLM_EUL_XZXs = 6,
GLM_EUL_YZXs = 8,
GLM_EUL_YZYs = 10,
GLM_EUL_YXZs = 12,
GLM_EUL_YXYs = 14,
GLM_EUL_ZXYs = 16,
GLM_EUL_ZXZs = 18,
GLM_EUL_ZYXs = 20,
GLM_EUL_ZYZs = 22,

/*! Rotating axes */
GLM_EUL_ZYXr = 1,
GLM_EUL_XYXr = 3,
GLM_EUL_YZXr = 5,
GLM_EUL_XZXr = 7,
GLM_EUL_XZYr = 9,
GLM_EUL_YZYr = 11,
GLM_EUL_ZXYr = 13,
GLM_EUL_YXYr = 15,
GLM_EUL_YXZr = 17,
GLM_EUL_ZXZr = 19,
GLM_EUL_XYZr = 21,
GLM_EUL_ZYZr = 23
} glm_eul_order;

/*!
* @brief build matrix from euler angles
*
* @param[in] ea [Xangle, Yangle, Zangle]
* @param[out] dest rotation matrix
*/
CGLM_INLINE
void
glm_eul_mat4(vec3 ea, glm_eul_order order, mat4 dest) {
float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
int i, j, k, h, parOdd, repYes, frmR;

EulGetOrd(order, i, j, k, h, parOdd, repYes, frmR);

if (frmR == 1)
glm_swapf(&ea[0], &ea[2]);

if (parOdd == 1)
glm_vec3_negate(ea);

ti = ea[0]; tj = ea[1]; th = ea[2];

ci = cosf(ti); cj = cosf(tj);
ch = cosf(th); si = sinf(ti);
sj = sinf(tj); sh = sinf(th);

cc = ci * ch; cs = ci * sh;
sc = si * ch; ss = si * sh;

if (repYes == 1) {
dest[i][i] = cj;
dest[i][j] = sj * si;
dest[i][k] = sj * ci;
dest[j][i] = sj * sh;
dest[j][j] = -cj * ss + cc;
dest[j][k] = -cj * cs - sc;
dest[k][i] = -sj * ch;
dest[k][j] = cj * sc + cs;
dest[k][k] = cj * cc - ss;
} else {
dest[i][i] = cj * ch;
dest[i][j] = sj * sc - cs;
dest[i][k] = sj * cc + ss;
dest[j][i] = cj * sh;
dest[j][j] = sj * ss + cc;
dest[j][k] = sj * cs - sc;
dest[k][i] = -sj;
dest[k][j] = cj * si;
dest[k][k] = cj * ci;
}

dest[3][0] = 0.f;
dest[3][1] = 0.f;
dest[3][2] = 0.f;
dest[0][3] = 0.f;
dest[1][3] = 0.f;
dest[2][3] = 0.f;
dest[3][3] = 1.f;
}

/*!
* if you have axis order like vec3 orderVec = [0, 1, 2] or [0, 2, 1]...
Expand Down