2 * Quaternion arithmetic:
3 * qadd(q, r) returns q+r
4 * qsub(q, r) returns q-r
6 * qmul(q, r) returns q*r
7 * qdiv(q, r) returns q/r, can divide check.
8 * qinv(q) returns 1/q, can divide check.
9 * double qlen(p) returns modulus of p
10 * qunit(q) returns a unit quaternion parallel to q
11 * The following only work on unit quaternions and rotation matrices:
12 * slerp(q, r, a) returns q*(r*q^-1)^a
13 * qmid(q, r) slerp(q, r, .5)
14 * qsqrt(q) qmid(q, (Quaternion){1,0,0,0})
15 * qtom(m, q) converts a unit quaternion q into a rotation matrix m
16 * mtoq(m) returns a quaternion equivalent to a rotation matrix m
22 void qtom(Matrix m, Quaternion q){
24 m[0][0]=1-2*(q.j*q.j+q.k*q.k);
25 m[0][1]=2*(q.i*q.j+q.r*q.k);
26 m[0][2]=2*(q.i*q.k-q.r*q.j);
28 m[1][0]=2*(q.i*q.j-q.r*q.k);
29 m[1][1]=1-2*(q.i*q.i+q.k*q.k);
30 m[1][2]=2*(q.j*q.k+q.r*q.i);
32 m[2][0]=2*(q.i*q.k+q.r*q.j);
33 m[2][1]=2*(q.j*q.k-q.r*q.i);
34 m[2][2]=1-2*(q.i*q.i+q.j*q.j);
42 * Transcribed from Ken Shoemake's new code -- not known to work
44 double Nq = q.r*q.r+q.i*q.i+q.j*q.j+q.k*q.k;
45 double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
46 double xs = q.i*s, ys = q.j*s, zs = q.k*s;
47 double wx = q.r*xs, wy = q.r*ys, wz = q.r*zs;
48 double xx = q.i*xs, xy = q.i*ys, xz = q.i*zs;
49 double yy = q.j*ys, yz = q.j*zs, zz = q.k*zs;
50 m[0][0] = 1.0 - (yy + zz); m[1][0] = xy + wz; m[2][0] = xz - wy;
51 m[0][1] = xy - wz; m[1][1] = 1.0 - (xx + zz); m[2][1] = yz + wx;
52 m[0][2] = xz + wy; m[1][2] = yz - wx; m[2][2] = 1.0 - (xx + yy);
53 m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0;
57 Quaternion mtoq(Matrix mat){
59 #define EPS 1.387778780781445675529539585113525e-17 /* 2^-56 */
66 if((t=.25*(1+mat[0][0]+mat[1][1]+mat[2][2]))>EPS){
69 q.i=(mat[1][2]-mat[2][1])/t;
70 q.j=(mat[2][0]-mat[0][2])/t;
71 q.k=(mat[0][1]-mat[1][0])/t;
73 else if((t=-.5*(mat[1][1]+mat[2][2]))>EPS){
79 else if((t=.5*(1-mat[2][2]))>EPS){
81 q.k=mat[1][2]/(2*q.j);
86 * Transcribed from Ken Shoemake's new code -- not known to work
88 /* This algorithm avoids near-zero divides by looking for a large
89 * component -- first r, then i, j, or k. When the trace is greater than zero,
90 * |r| is greater than 1/2, which is as small as a largest component can be.
91 * Otherwise, the largest diagonal entry corresponds to the largest of |i|,
92 * |j|, or |k|, one of which must be larger than |r|, and at least 1/2.
97 tr = mat[0][0] + mat[1][1] + mat[2][2];
99 s = sqrt(tr + mat[3][3]);
102 qu.i = (mat[2][1] - mat[1][2]) * s;
103 qu.j = (mat[0][2] - mat[2][0]) * s;
104 qu.k = (mat[1][0] - mat[0][1]) * s;
108 if (mat[1][1] > mat[0][0]) i = 1;
109 if (mat[2][2] > mat[i][i]) i = 2;
112 s = sqrt( (mat[0][0] - (mat[1][1]+mat[2][2])) + mat[3][3] );
115 qu.j = (mat[0][1] + mat[1][0]) * s;
116 qu.k = (mat[2][0] + mat[0][2]) * s;
117 qu.r = (mat[2][1] - mat[1][2]) * s;
120 s = sqrt( (mat[1][1] - (mat[2][2]+mat[0][0])) + mat[3][3] );
123 qu.k = (mat[1][2] + mat[2][1]) * s;
124 qu.i = (mat[0][1] + mat[1][0]) * s;
125 qu.r = (mat[0][2] - mat[2][0]) * s;
128 s = sqrt( (mat[2][2] - (mat[0][0]+mat[1][1])) + mat[3][3] );
131 qu.i = (mat[2][0] + mat[0][2]) * s;
132 qu.j = (mat[1][2] + mat[2][1]) * s;
133 qu.r = (mat[1][0] - mat[0][1]) * s;
137 if (mat[3][3] != 1.0){
147 Quaternion qadd(Quaternion q, Quaternion r){
154 Quaternion qsub(Quaternion q, Quaternion r){
161 Quaternion qneg(Quaternion q){
168 Quaternion qmul(Quaternion q, Quaternion r){
170 s.r=q.r*r.r-q.i*r.i-q.j*r.j-q.k*r.k;
171 s.i=q.r*r.i+r.r*q.i+q.j*r.k-q.k*r.j;
172 s.j=q.r*r.j+r.r*q.j+q.k*r.i-q.i*r.k;
173 s.k=q.r*r.k+r.r*q.k+q.i*r.j-q.j*r.i;
176 Quaternion qdiv(Quaternion q, Quaternion r){
177 return qmul(q, qinv(r));
179 Quaternion qunit(Quaternion q){
188 * Bug?: takes no action on divide check
190 Quaternion qinv(Quaternion q){
191 double l=q.r*q.r+q.i*q.i+q.j*q.j+q.k*q.k;
198 double qlen(Quaternion p){
199 return sqrt(p.r*p.r+p.i*p.i+p.j*p.j+p.k*p.k);
201 Quaternion slerp(Quaternion q, Quaternion r, double a){
203 double dot=q.r*r.r+q.i*r.i+q.j*r.j+q.k*r.k;
204 ang=dot<-1?PI:dot>1?0:acos(dot); /* acos gives NaN for dot slightly out of range */
206 if(s==0) return ang<PI/2?q:r;
216 * Only works if qlen(q)==qlen(r)==1
218 Quaternion qmid(Quaternion q, Quaternion r){
237 * Only works if qlen(q)==1
239 static Quaternion qident={1,0,0,0};
240 Quaternion qsqrt(Quaternion q){
241 return qmid(q, qident);