quaternion.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Quaternion arithmetic:
  11. * qadd(q, r) returns q+r
  12. * qsub(q, r) returns q-r
  13. * qneg(q) returns -q
  14. * qmul(q, r) returns q*r
  15. * qdiv(q, r) returns q/r, can divide check.
  16. * qinv(q) returns 1/q, can divide check.
  17. * double qlen(p) returns modulus of p
  18. * qunit(q) returns a unit quaternion parallel to q
  19. * The following only work on unit quaternions and rotation matrices:
  20. * slerp(q, r, a) returns q*(r*q^-1)^a
  21. * qmid(q, r) slerp(q, r, .5)
  22. * qsqrt(q) qmid(q, (Quaternion){1,0,0,0})
  23. * qtom(m, q) converts a unit quaternion q into a rotation matrix m
  24. * mtoq(m) returns a quaternion equivalent to a rotation matrix m
  25. */
  26. #include <u.h>
  27. #include <libc.h>
  28. #include <draw.h>
  29. #include <geometry.h>
  30. void qtom(Matrix m, Quaternion q){
  31. #ifndef new
  32. m[0][0]=1-2*(q.j*q.j+q.k*q.k);
  33. m[0][1]=2*(q.i*q.j+q.r*q.k);
  34. m[0][2]=2*(q.i*q.k-q.r*q.j);
  35. m[0][3]=0;
  36. m[1][0]=2*(q.i*q.j-q.r*q.k);
  37. m[1][1]=1-2*(q.i*q.i+q.k*q.k);
  38. m[1][2]=2*(q.j*q.k+q.r*q.i);
  39. m[1][3]=0;
  40. m[2][0]=2*(q.i*q.k+q.r*q.j);
  41. m[2][1]=2*(q.j*q.k-q.r*q.i);
  42. m[2][2]=1-2*(q.i*q.i+q.j*q.j);
  43. m[2][3]=0;
  44. m[3][0]=0;
  45. m[3][1]=0;
  46. m[3][2]=0;
  47. m[3][3]=1;
  48. #else
  49. /*
  50. * Transcribed from Ken Shoemake's new code -- not known to work
  51. */
  52. double Nq = q.r*q.r+q.i*q.i+q.j*q.j+q.k*q.k;
  53. double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;
  54. double xs = q.i*s, ys = q.j*s, zs = q.k*s;
  55. double wx = q.r*xs, wy = q.r*ys, wz = q.r*zs;
  56. double xx = q.i*xs, xy = q.i*ys, xz = q.i*zs;
  57. double yy = q.j*ys, yz = q.j*zs, zz = q.k*zs;
  58. m[0][0] = 1.0 - (yy + zz); m[1][0] = xy + wz; m[2][0] = xz - wy;
  59. m[0][1] = xy - wz; m[1][1] = 1.0 - (xx + zz); m[2][1] = yz + wx;
  60. m[0][2] = xz + wy; m[1][2] = yz - wx; m[2][2] = 1.0 - (xx + yy);
  61. m[0][3] = m[1][3] = m[2][3] = m[3][0] = m[3][1] = m[3][2] = 0.0;
  62. m[3][3] = 1.0;
  63. #endif
  64. }
  65. Quaternion mtoq(Matrix mat){
  66. #ifndef new
  67. #define EPS 1.387778780781445675529539585113525e-17 /* 2^-56 */
  68. double t;
  69. Quaternion q;
  70. q.r=0.;
  71. q.i=0.;
  72. q.j=0.;
  73. q.k=1.;
  74. if((t=.25*(1+mat[0][0]+mat[1][1]+mat[2][2]))>EPS){
  75. q.r=sqrt(t);
  76. t=4*q.r;
  77. q.i=(mat[1][2]-mat[2][1])/t;
  78. q.j=(mat[2][0]-mat[0][2])/t;
  79. q.k=(mat[0][1]-mat[1][0])/t;
  80. }
  81. else if((t=-.5*(mat[1][1]+mat[2][2]))>EPS){
  82. q.i=sqrt(t);
  83. t=2*q.i;
  84. q.j=mat[0][1]/t;
  85. q.k=mat[0][2]/t;
  86. }
  87. else if((t=.5*(1-mat[2][2]))>EPS){
  88. q.j=sqrt(t);
  89. q.k=mat[1][2]/(2*q.j);
  90. }
  91. return q;
  92. #else
  93. /*
  94. * Transcribed from Ken Shoemake's new code -- not known to work
  95. */
  96. /* This algorithm avoids near-zero divides by looking for a large
  97. * component -- first r, then i, j, or k. When the trace is greater than zero,
  98. * |r| is greater than 1/2, which is as small as a largest component can be.
  99. * Otherwise, the largest diagonal entry corresponds to the largest of |i|,
  100. * |j|, or |k|, one of which must be larger than |r|, and at least 1/2.
  101. */
  102. Quaternion qu;
  103. double tr, s;
  104. tr = mat[0][0] + mat[1][1] + mat[2][2];
  105. if (tr >= 0.0) {
  106. s = sqrt(tr + mat[3][3]);
  107. qu.r = s*0.5;
  108. s = 0.5 / s;
  109. qu.i = (mat[2][1] - mat[1][2]) * s;
  110. qu.j = (mat[0][2] - mat[2][0]) * s;
  111. qu.k = (mat[1][0] - mat[0][1]) * s;
  112. }
  113. else {
  114. int i = 0;
  115. if (mat[1][1] > mat[0][0]) i = 1;
  116. if (mat[2][2] > mat[i][i]) i = 2;
  117. switch(i){
  118. case 0:
  119. s = sqrt( (mat[0][0] - (mat[1][1]+mat[2][2])) + mat[3][3] );
  120. qu.i = s*0.5;
  121. s = 0.5 / s;
  122. qu.j = (mat[0][1] + mat[1][0]) * s;
  123. qu.k = (mat[2][0] + mat[0][2]) * s;
  124. qu.r = (mat[2][1] - mat[1][2]) * s;
  125. break;
  126. case 1:
  127. s = sqrt( (mat[1][1] - (mat[2][2]+mat[0][0])) + mat[3][3] );
  128. qu.j = s*0.5;
  129. s = 0.5 / s;
  130. qu.k = (mat[1][2] + mat[2][1]) * s;
  131. qu.i = (mat[0][1] + mat[1][0]) * s;
  132. qu.r = (mat[0][2] - mat[2][0]) * s;
  133. break;
  134. case 2:
  135. s = sqrt( (mat[2][2] - (mat[0][0]+mat[1][1])) + mat[3][3] );
  136. qu.k = s*0.5;
  137. s = 0.5 / s;
  138. qu.i = (mat[2][0] + mat[0][2]) * s;
  139. qu.j = (mat[1][2] + mat[2][1]) * s;
  140. qu.r = (mat[1][0] - mat[0][1]) * s;
  141. break;
  142. }
  143. }
  144. if (mat[3][3] != 1.0){
  145. s=1/sqrt(mat[3][3]);
  146. qu.r*=s;
  147. qu.i*=s;
  148. qu.j*=s;
  149. qu.k*=s;
  150. }
  151. return (qu);
  152. #endif
  153. }
  154. Quaternion qadd(Quaternion q, Quaternion r){
  155. q.r+=r.r;
  156. q.i+=r.i;
  157. q.j+=r.j;
  158. q.k+=r.k;
  159. return q;
  160. }
  161. Quaternion qsub(Quaternion q, Quaternion r){
  162. q.r-=r.r;
  163. q.i-=r.i;
  164. q.j-=r.j;
  165. q.k-=r.k;
  166. return q;
  167. }
  168. Quaternion qneg(Quaternion q){
  169. q.r=-q.r;
  170. q.i=-q.i;
  171. q.j=-q.j;
  172. q.k=-q.k;
  173. return q;
  174. }
  175. Quaternion qmul(Quaternion q, Quaternion r){
  176. Quaternion s;
  177. s.r=q.r*r.r-q.i*r.i-q.j*r.j-q.k*r.k;
  178. s.i=q.r*r.i+r.r*q.i+q.j*r.k-q.k*r.j;
  179. s.j=q.r*r.j+r.r*q.j+q.k*r.i-q.i*r.k;
  180. s.k=q.r*r.k+r.r*q.k+q.i*r.j-q.j*r.i;
  181. return s;
  182. }
  183. Quaternion qdiv(Quaternion q, Quaternion r){
  184. return qmul(q, qinv(r));
  185. }
  186. Quaternion qunit(Quaternion q){
  187. double l=qlen(q);
  188. q.r/=l;
  189. q.i/=l;
  190. q.j/=l;
  191. q.k/=l;
  192. return q;
  193. }
  194. /*
  195. * Bug?: takes no action on divide check
  196. */
  197. Quaternion qinv(Quaternion q){
  198. double l=q.r*q.r+q.i*q.i+q.j*q.j+q.k*q.k;
  199. q.r/=l;
  200. q.i=-q.i/l;
  201. q.j=-q.j/l;
  202. q.k=-q.k/l;
  203. return q;
  204. }
  205. double qlen(Quaternion p){
  206. return sqrt(p.r*p.r+p.i*p.i+p.j*p.j+p.k*p.k);
  207. }
  208. Quaternion slerp(Quaternion q, Quaternion r, double a){
  209. double u, v, ang, s;
  210. double dot=q.r*r.r+q.i*r.i+q.j*r.j+q.k*r.k;
  211. ang=dot<-1?PI:dot>1?0:acos(dot); /* acos gives NaN for dot slightly out of range */
  212. s=sin(ang);
  213. if(s==0) return ang<PI/2?q:r;
  214. u=sin((1-a)*ang)/s;
  215. v=sin(a*ang)/s;
  216. q.r=u*q.r+v*r.r;
  217. q.i=u*q.i+v*r.i;
  218. q.j=u*q.j+v*r.j;
  219. q.k=u*q.k+v*r.k;
  220. return q;
  221. }
  222. /*
  223. * Only works if qlen(q)==qlen(r)==1
  224. */
  225. Quaternion qmid(Quaternion q, Quaternion r){
  226. double l;
  227. q=qadd(q, r);
  228. l=qlen(q);
  229. if(l<1e-12){
  230. q.r=r.i;
  231. q.i=-r.r;
  232. q.j=r.k;
  233. q.k=-r.j;
  234. }
  235. else{
  236. q.r/=l;
  237. q.i/=l;
  238. q.j/=l;
  239. q.k/=l;
  240. }
  241. return q;
  242. }
  243. /*
  244. * Only works if qlen(q)==1
  245. */
  246. static Quaternion qident={1,0,0,0};
  247. Quaternion qsqrt(Quaternion q){
  248. return qmid(q, qident);
  249. }