/OpenSceneGraph/src/osgPlugins/3ds/lib3ds/lib3ds_quat.c

https://github.com/rpavlik/openscenegraph-oldstable-ubuntu · C · 294 lines · 192 code · 48 blank · 54 comment · 22 complexity · 0256e63cb8784c27499dbb9d5069a832 MD5 · raw file

  1. /*
  2. Copyright (C) 1996-2008 by Jan Eric Kyprianidis <www.kyprianidis.com>
  3. All rights reserved.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation, either version 2.1 of the License, or
  7. (at your option) any later version.
  8. Thisprogram is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program; If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "lib3ds_impl.h"
  16. /*!
  17. * Set a quaternion to Identity
  18. */
  19. void
  20. lib3ds_quat_identity(float c[4]) {
  21. c[0] = c[1] = c[2] = 0.0f;
  22. c[3] = 1.0f;
  23. }
  24. /*!
  25. * Copy a quaternion.
  26. */
  27. void
  28. lib3ds_quat_copy(float dest[4], float src[4]) {
  29. int i;
  30. for (i = 0; i < 4; ++i) {
  31. dest[i] = src[i];
  32. }
  33. }
  34. /*!
  35. * Compute a quaternion from axis and angle.
  36. *
  37. * \param c Computed quaternion
  38. * \param axis Rotation axis
  39. * \param angle Angle of rotation, radians.
  40. */
  41. void
  42. lib3ds_quat_axis_angle(float c[4], float axis[3], float angle) {
  43. double omega, s;
  44. double l;
  45. l = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
  46. if (l < LIB3DS_EPSILON) {
  47. c[0] = c[1] = c[2] = 0.0f;
  48. c[3] = 1.0f;
  49. } else {
  50. omega = -0.5 * angle;
  51. s = sin(omega) / l;
  52. c[0] = (float)s * axis[0];
  53. c[1] = (float)s * axis[1];
  54. c[2] = (float)s * axis[2];
  55. c[3] = (float)cos(omega);
  56. }
  57. }
  58. /*!
  59. * Negate a quaternion
  60. */
  61. void
  62. lib3ds_quat_neg(float c[4]) {
  63. int i;
  64. for (i = 0; i < 4; ++i) {
  65. c[i] = -c[i];
  66. }
  67. }
  68. /*!
  69. * Compute the conjugate of a quaternion
  70. */
  71. void
  72. lib3ds_quat_cnj(float c[4]) {
  73. int i;
  74. for (i = 0; i < 3; ++i) {
  75. c[i] = -c[i];
  76. }
  77. }
  78. /*!
  79. * Multiply two quaternions.
  80. *
  81. * \param c Result
  82. * \param a,b Inputs
  83. */
  84. void
  85. lib3ds_quat_mul(float c[4], float a[4], float b[4]) {
  86. float qa[4], qb[4];
  87. lib3ds_quat_copy(qa, a);
  88. lib3ds_quat_copy(qb, b);
  89. c[0] = qa[3] * qb[0] + qa[0] * qb[3] + qa[1] * qb[2] - qa[2] * qb[1];
  90. c[1] = qa[3] * qb[1] + qa[1] * qb[3] + qa[2] * qb[0] - qa[0] * qb[2];
  91. c[2] = qa[3] * qb[2] + qa[2] * qb[3] + qa[0] * qb[1] - qa[1] * qb[0];
  92. c[3] = qa[3] * qb[3] - qa[0] * qb[0] - qa[1] * qb[1] - qa[2] * qb[2];
  93. }
  94. /*!
  95. * Multiply a quaternion by a scalar.
  96. */
  97. void
  98. lib3ds_quat_scalar(float c[4], float k) {
  99. int i;
  100. for (i = 0; i < 4; ++i) {
  101. c[i] *= k;
  102. }
  103. }
  104. /*!
  105. * Normalize a quaternion.
  106. */
  107. void
  108. lib3ds_quat_normalize(float c[4]) {
  109. double l, m;
  110. l = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
  111. if (fabs(l) < LIB3DS_EPSILON) {
  112. c[0] = c[1] = c[2] = 0.0f;
  113. c[3] = 1.0f;
  114. } else {
  115. int i;
  116. m = 1.0f / l;
  117. for (i = 0; i < 4; ++i) {
  118. c[i] = (float)(c[i] * m);
  119. }
  120. }
  121. }
  122. /*!
  123. * Compute the inverse of a quaternion.
  124. */
  125. void
  126. lib3ds_quat_inv(float c[4]) {
  127. double l, m;
  128. l = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2] + c[3] * c[3]);
  129. if (fabs(l) < LIB3DS_EPSILON) {
  130. c[0] = c[1] = c[2] = 0.0f;
  131. c[3] = 1.0f;
  132. } else {
  133. m = 1.0f / l;
  134. c[0] = (float)(-c[0] * m);
  135. c[1] = (float)(-c[1] * m);
  136. c[2] = (float)(-c[2] * m);
  137. c[3] = (float)(c[3] * m);
  138. }
  139. }
  140. /*!
  141. * Compute the dot-product of a quaternion.
  142. */
  143. float
  144. lib3ds_quat_dot(float a[4], float b[4]) {
  145. return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]);
  146. }
  147. float
  148. lib3ds_quat_norm(float c[4]) {
  149. return(c[0]*c[0] + c[1]*c[1] + c[2]*c[2] + c[3]*c[3]);
  150. }
  151. void
  152. lib3ds_quat_ln(float c[4]) {
  153. double om, s, t;
  154. s = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
  155. om = atan2(s, (double)c[3]);
  156. if (fabs(s) < LIB3DS_EPSILON) {
  157. t = 0.0f;
  158. } else {
  159. t = om / s;
  160. }
  161. {
  162. int i;
  163. for (i = 0; i < 3; ++i) {
  164. c[i] = (float)(c[i] * t);
  165. }
  166. c[3] = 0.0f;
  167. }
  168. }
  169. void
  170. lib3ds_quat_ln_dif(float c[4], float a[4], float b[4]) {
  171. float invp[4];
  172. lib3ds_quat_copy(invp, a);
  173. lib3ds_quat_inv(invp);
  174. lib3ds_quat_mul(c, invp, b);
  175. lib3ds_quat_ln(c);
  176. }
  177. void
  178. lib3ds_quat_exp(float c[4]) {
  179. double om, sinom;
  180. om = sqrt(c[0] * c[0] + c[1] * c[1] + c[2] * c[2]);
  181. if (fabs(om) < LIB3DS_EPSILON) {
  182. sinom = 1.0f;
  183. } else {
  184. sinom = sin(om) / om;
  185. }
  186. {
  187. int i;
  188. for (i = 0; i < 3; ++i) {
  189. c[i] = (float)(c[i] * sinom);
  190. }
  191. c[3] = (float)cos(om);
  192. }
  193. }
  194. void
  195. lib3ds_quat_slerp(float c[4], float a[4], float b[4], float t) {
  196. double l;
  197. double om, sinom;
  198. double sp, sq;
  199. float flip = 1.0f;
  200. int i;
  201. l = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  202. if (l < 0) {
  203. flip = -1.0f;
  204. l = -l;
  205. }
  206. om = acos(l);
  207. sinom = sin(om);
  208. if (fabs(sinom) > LIB3DS_EPSILON) {
  209. sp = sin((1.0f - t) * om) / sinom;
  210. sq = sin(t * om) / sinom;
  211. } else {
  212. sp = 1.0f - t;
  213. sq = t;
  214. }
  215. sq *= flip;
  216. for (i = 0; i < 4; ++i) {
  217. c[i] = (float)(sp * a[i] + sq * b[i]);
  218. }
  219. }
  220. void
  221. lib3ds_quat_squad(float c[4], float a[4], float p[4], float q[4], float b[4], float t) {
  222. float ab[4];
  223. float pq[4];
  224. lib3ds_quat_slerp(ab, a, b, t);
  225. lib3ds_quat_slerp(pq, p, q, t);
  226. lib3ds_quat_slerp(c, ab, pq, 2*t*(1 - t));
  227. }
  228. void
  229. lib3ds_quat_tangent(float c[4], float p[4], float q[4], float n[4]) {
  230. float dn[4], dp[4], x[4];
  231. int i;
  232. lib3ds_quat_ln_dif(dn, q, n);
  233. lib3ds_quat_ln_dif(dp, q, p);
  234. for (i = 0; i < 4; i++) {
  235. x[i] = -1.0f / 4.0f * (dn[i] + dp[i]);
  236. }
  237. lib3ds_quat_exp(x);
  238. lib3ds_quat_mul(c, q, x);
  239. }
  240. void
  241. lib3ds_quat_dump(float q[4]) {
  242. printf("%f %f %f %f\n", q[0], q[1], q[2], q[3]);
  243. }