PageRenderTime 26ms CodeModel.GetById 46ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib3ds.lib/quat.c

https://github.com/shadoof/CW2
C | 392 lines | 244 code | 55 blank | 93 comment | 24 complexity | f4573c8b6cd92be0f29ec5a8c07d8d70 MD5 | raw file
  1. /*
  2. * The 3D Studio File Format Library
  3. * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
  4. * All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  14. * License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. *
  20. * $Id: quat.c,v 1.5 2001/01/12 10:29:17 jeh Exp $
  21. */
  22. #define LIB3DS_EXPORT
  23. #include <lib3ds/quat.h>
  24. #include <math.h>
  25. /*!
  26. * \defgroup quat Quaternion Mathematics
  27. *
  28. * \author J.E. Hoffmann <je-h@gmx.net>
  29. */
  30. /*!
  31. * \typedef Lib3dsQuat
  32. * \ingroup quat
  33. */
  34. /*!
  35. * \ingroup quat
  36. */
  37. void
  38. lib3ds_quat_zero(Lib3dsQuat c)
  39. {
  40. c[0]=c[1]=c[2]=c[3]=0.0f;
  41. }
  42. /*!
  43. * \ingroup quat
  44. */
  45. void
  46. lib3ds_quat_identity(Lib3dsQuat c)
  47. {
  48. c[0]=c[1]=c[2]=0.0f;
  49. c[3]=1.0f;
  50. }
  51. /*!
  52. * \ingroup quat
  53. */
  54. void
  55. lib3ds_quat_copy(Lib3dsQuat dest, Lib3dsQuat src)
  56. {
  57. int i;
  58. for (i=0; i<4; ++i) {
  59. dest[i]=src[i];
  60. }
  61. }
  62. /*!
  63. * \ingroup quat
  64. */
  65. void
  66. lib3ds_quat_axis_angle(Lib3dsQuat c, Lib3dsVector axis, Lib3dsFloat angle)
  67. {
  68. Lib3dsDouble omega,s;
  69. Lib3dsDouble l;
  70. l=sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
  71. if (l<LIB3DS_EPSILON) {
  72. c[0]=c[1]=c[2]=0.0f;
  73. c[3]=1.0f;
  74. }
  75. else {
  76. omega=-0.5*angle;
  77. s=sin(omega)/l;
  78. c[0]=(Lib3dsFloat)s*axis[0];
  79. c[1]=(Lib3dsFloat)s*axis[1];
  80. c[2]=(Lib3dsFloat)s*axis[2];
  81. c[3]=(Lib3dsFloat)cos(omega);
  82. }
  83. }
  84. /*!
  85. * \ingroup quat
  86. */
  87. void
  88. lib3ds_quat_neg(Lib3dsQuat c)
  89. {
  90. int i;
  91. for (i=0; i<4; ++i) {
  92. c[i]=-c[i];
  93. }
  94. }
  95. /*!
  96. * \ingroup quat
  97. */
  98. void
  99. lib3ds_quat_abs(Lib3dsQuat c)
  100. {
  101. int i;
  102. for (i=0; i<4; ++i) {
  103. c[i]=(Lib3dsFloat)fabs(c[i]);
  104. }
  105. }
  106. /*!
  107. * \ingroup quat
  108. */
  109. void
  110. lib3ds_quat_cnj(Lib3dsQuat c)
  111. {
  112. int i;
  113. for (i=0; i<3; ++i) {
  114. c[i]=-c[i];
  115. }
  116. }
  117. /*!
  118. * \ingroup quat
  119. */
  120. void
  121. lib3ds_quat_mul(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b)
  122. {
  123. c[0]=a[3]*b[0] + a[0]*b[3] + a[1]*b[2] - a[2]*b[1];
  124. c[1]=a[3]*b[1] + a[1]*b[3] + a[2]*b[0] - a[0]*b[2];
  125. c[2]=a[3]*b[2] + a[2]*b[3] + a[0]*b[1] - a[1]*b[0];
  126. c[3]=a[3]*b[3] - a[0]*b[0] - a[1]*b[1] - a[2]*b[2];
  127. }
  128. /*!
  129. * \ingroup quat
  130. */
  131. void
  132. lib3ds_quat_scalar(Lib3dsQuat c, Lib3dsFloat k)
  133. {
  134. int i;
  135. for (i=0; i<4; ++i) {
  136. c[i]*=k;
  137. }
  138. }
  139. /*!
  140. * \ingroup quat
  141. */
  142. void
  143. lib3ds_quat_normalize(Lib3dsQuat c)
  144. {
  145. Lib3dsDouble l,m;
  146. l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
  147. if (fabs(l)<LIB3DS_EPSILON) {
  148. c[0]=c[1]=c[2]=0.0f;
  149. c[3]=1.0f;
  150. }
  151. else {
  152. int i;
  153. m=1.0f/l;
  154. for (i=0; i<4; ++i) {
  155. c[i]=(Lib3dsFloat)(c[i]*m);
  156. }
  157. }
  158. }
  159. /*!
  160. * \ingroup quat
  161. */
  162. void
  163. lib3ds_quat_inv(Lib3dsQuat c)
  164. {
  165. Lib3dsDouble l,m;
  166. l=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
  167. if (fabs(l)<LIB3DS_EPSILON) {
  168. c[0]=c[1]=c[2]=0.0f;
  169. c[3]=1.0f;
  170. }
  171. else {
  172. m=1.0f/l;
  173. c[0]=(Lib3dsFloat)(-c[0]*m);
  174. c[1]=(Lib3dsFloat)(-c[1]*m);
  175. c[2]=(Lib3dsFloat)(-c[2]*m);
  176. c[3]=(Lib3dsFloat)(c[3]*m);
  177. }
  178. }
  179. /*!
  180. * \ingroup quat
  181. */
  182. Lib3dsFloat
  183. lib3ds_quat_dot(Lib3dsQuat a, Lib3dsQuat b)
  184. {
  185. return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]);
  186. }
  187. /*!
  188. * \ingroup quat
  189. */
  190. Lib3dsFloat
  191. lib3ds_quat_squared(Lib3dsQuat c)
  192. {
  193. return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
  194. }
  195. /*!
  196. * \ingroup quat
  197. */
  198. Lib3dsFloat
  199. lib3ds_quat_length(Lib3dsQuat c)
  200. {
  201. return((Lib3dsFloat)sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]));
  202. }
  203. /*!
  204. * \ingroup quat
  205. */
  206. void
  207. lib3ds_quat_ln(Lib3dsQuat c)
  208. {
  209. Lib3dsDouble om,s,t;
  210. s=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
  211. om=atan2(s,c[3]);
  212. if (fabs(s)<LIB3DS_EPSILON) {
  213. t=0.0f;
  214. }
  215. else {
  216. t=om/s;
  217. }
  218. {
  219. int i;
  220. for (i=0; i<3; ++i) {
  221. c[i]=(Lib3dsFloat)(c[i]*t);
  222. }
  223. c[3]=0.0f;
  224. }
  225. }
  226. /*!
  227. * \ingroup quat
  228. */
  229. void
  230. lib3ds_quat_ln_dif(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b)
  231. {
  232. Lib3dsQuat invp;
  233. lib3ds_quat_copy(invp, a);
  234. lib3ds_quat_inv(invp);
  235. lib3ds_quat_mul(c, invp, b);
  236. lib3ds_quat_ln(c);
  237. }
  238. /*!
  239. * \ingroup quat
  240. */
  241. void
  242. lib3ds_quat_exp(Lib3dsQuat c)
  243. {
  244. Lib3dsDouble om,sinom;
  245. om=sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
  246. if (fabs(om)<LIB3DS_EPSILON) {
  247. sinom=1.0f;
  248. }
  249. else {
  250. sinom=sin(om)/om;
  251. }
  252. {
  253. int i;
  254. for (i=0; i<3; ++i) {
  255. c[i]=(Lib3dsFloat)(c[i]*sinom);
  256. }
  257. c[3]=(Lib3dsFloat)cos(om);
  258. }
  259. }
  260. /*!
  261. * \ingroup quat
  262. */
  263. void
  264. lib3ds_quat_slerp(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat b, Lib3dsFloat t)
  265. {
  266. Lib3dsDouble l;
  267. Lib3dsDouble om,sinom;
  268. Lib3dsDouble sp,sq;
  269. Lib3dsQuat q;
  270. l=a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
  271. if ((1.0+l)>LIB3DS_EPSILON) {
  272. if (fabs(l)>1.0f) l/=fabs(l);
  273. om=acos(l);
  274. sinom=sin(om);
  275. if (fabs(sinom)>LIB3DS_EPSILON) {
  276. sp=sin((1.0f-t)*om)/sinom;
  277. sq=sin(t*om)/sinom;
  278. }
  279. else {
  280. sp=1.0f-t;
  281. sq=t;
  282. }
  283. c[0]=(Lib3dsFloat)(sp*a[0] + sq*b[0]);
  284. c[1]=(Lib3dsFloat)(sp*a[1] + sq*b[1]);
  285. c[2]=(Lib3dsFloat)(sp*a[2] + sq*b[2]);
  286. c[3]=(Lib3dsFloat)(sp*a[3] + sq*b[3]);
  287. }
  288. else {
  289. q[0]=-a[1];
  290. q[1]=a[0];
  291. q[2]=-a[3];
  292. q[3]=a[2];
  293. sp=sin((1.0-t)*LIB3DS_HALFPI);
  294. sq=sin(t*LIB3DS_HALFPI);
  295. c[0]=(Lib3dsFloat)(sp*a[0] + sq*q[0]);
  296. c[1]=(Lib3dsFloat)(sp*a[1] + sq*q[1]);
  297. c[2]=(Lib3dsFloat)(sp*a[2] + sq*q[2]);
  298. c[3]=(Lib3dsFloat)(sp*a[3] + sq*q[3]);
  299. }
  300. }
  301. /*!
  302. * \ingroup quat
  303. */
  304. void
  305. lib3ds_quat_squad(Lib3dsQuat c, Lib3dsQuat a, Lib3dsQuat p, Lib3dsQuat q,
  306. Lib3dsQuat b, Lib3dsFloat t)
  307. {
  308. Lib3dsQuat ab;
  309. Lib3dsQuat pq;
  310. lib3ds_quat_slerp(ab,a,b,t);
  311. lib3ds_quat_slerp(pq,p,q,t);
  312. lib3ds_quat_slerp(c,ab,pq,2*t*(1-t));
  313. }
  314. /*!
  315. * \ingroup quat
  316. */
  317. void
  318. lib3ds_quat_tangent(Lib3dsQuat c, Lib3dsQuat p, Lib3dsQuat q, Lib3dsQuat n)
  319. {
  320. Lib3dsQuat dn,dp,x;
  321. int i;
  322. lib3ds_quat_ln_dif(dn, q, n);
  323. lib3ds_quat_ln_dif(dp, q, p);
  324. for (i=0; i<4; i++) {
  325. x[i]=-1.0f/4.0f*(dn[i]+dp[i]);
  326. }
  327. lib3ds_quat_exp(x);
  328. lib3ds_quat_mul(c,q,x);
  329. }
  330. /*!
  331. * \ingroup quat
  332. */
  333. void
  334. lib3ds_quat_dump(Lib3dsQuat q)
  335. {
  336. printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]);
  337. }