1 static CGM_INLINE cgm_quat cgm_qcons(float x, float y, float z, float w)
11 static CGM_INLINE cgm_quat cgm_qneg(cgm_quat q)
13 return cgm_qcons(-q.x, -q.y, -q.z, -q.w);
16 static CGM_INLINE cgm_quat cgm_qadd(cgm_quat a, cgm_quat b)
18 return cgm_qcons(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
21 static CGM_INLINE cgm_quat cgm_qsub(cgm_quat a, cgm_quat b)
23 return cgm_qcons(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
26 static CGM_INLINE cgm_quat cgm_qmul(cgm_quat a, cgm_quat b)
32 dot = a.x * b.x + a.y * b.y + a.z * b.z;
33 cross = cgm_vcross(cgm_vcons(a.x, a.y, a.z), cgm_vcons(b.x, b.y, b.z));
34 res.x = a.w * b.x + b.w * a.x + cross.x;
35 res.y = a.w * b.y + b.w * a.y + cross.y;
36 res.z = a.w * b.z + b.w * a.z + cross.z;
37 res.w = a.w * b.w - dot;
41 static CGM_INLINE float cgm_qlength(cgm_quat q)
43 return sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
46 static CGM_INLINE float cgm_qlength_sq(cgm_quat q)
48 return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
51 static CGM_INLINE cgm_quat cgm_qnormalize(cgm_quat q)
68 static CGM_INLINE cgm_quat cgm_qconjugate(cgm_quat q)
70 return cgm_qcons(-q.x, -q.y, -q.z, q.w);
73 static CGM_INLINE cgm_quat cgm_qinvert(cgm_quat q)
78 if((len_sq = cgm_qlength_sq(q)) == 0.0f) {
89 static CGM_INLINE cgm_quat cgm_qrotation(float angle, float x, float y, float z)
92 float hangle = angle * 0.5f;
93 float sin_ha = sin(hangle);
101 static CGM_INLINE void cgm_qrotate(cgm_quat *q, float angle, float x, float y, float z)
103 cgm_quat qrot = cgm_qrotation(angle, x, y, z);
104 *q = cgm_qmul(*q, qrot);
107 static CGM_INLINE cgm_quat cgm_qslerp(cgm_quat q1, cgm_quat q2, float t)
110 float angle, dot, a, b, sin_angle;
112 dot = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
114 /* make sure we inteprolate across the shortest arc */
119 /* clamp dot to [-1, 1] in order to avoid domain errors in acos due to
120 * floating point imprecisions
122 if(dot < -1.0f) dot = -1.0f;
123 if(dot > 1.0f) dot = 1.0f;
126 sin_angle = sin(angle);
127 if(sin_angle == 0.0f) {
128 /* use linear interpolation to avoid div/zero */
132 a = sin((1.0f - t) * angle) / sin_angle;
133 b = sin(t * angle) / sin_angle;
136 res.x = q1.x * a + q2.x * b;
137 res.y = q1.y * a + q2.y * b;
138 res.z = q1.z * a + q2.z * b;
139 res.w = q1.w * a + q2.w * b;
143 static CGM_INLINE cgm_quat cgm_qlerp(cgm_quat a, cgm_quat b, float t)
146 res.x = a.x + (b.x - a.x) * t;
147 res.y = a.y + (b.y - a.y) * t;
148 res.z = a.z + (b.z - a.z) * t;
149 res.w = a.w + (b.w - a.w) * t;