/Libraries/glut-3.7.6/lib/gle/urotate.c

https://github.com/metrixcreate/RepSnapper · C · 217 lines · 94 code · 31 blank · 92 comment · 3 complexity · 876bd6a505c6b73a27783969b9a0ad08 MD5 · raw file

  1. /*
  2. * MODULE: urotate.c
  3. *
  4. * FUNCTION:
  5. * This module contains three different routines that compute rotation
  6. * matricies and return these to user.
  7. * Detailed description is provided below.
  8. *
  9. * HISTORY:
  10. * Developed & written, Linas Vepstas, Septmeber 1991
  11. * double precision port, March 1993
  12. *
  13. * DETAILED DESCRIPTION:
  14. * This module contains three routines:
  15. * --------------------------------------------------------------------
  16. *
  17. * void urot_about_axis (float m[4][4], --- returned
  18. * float angle, --- input
  19. * float axis[3]) --- input
  20. * Computes a rotation matrix.
  21. * The rotation is around the the direction specified by the argument
  22. * argument axis[3]. User may specify vector which is not of unit
  23. * length. The angle of rotation is specified in degrees, and is in the
  24. * right-handed direction.
  25. *
  26. * void rot_about_axis (float angle, --- input
  27. * float axis[3]) --- input
  28. * Same as above routine, except that the matrix is multiplied into the
  29. * GL matrix stack.
  30. *
  31. * --------------------------------------------------------------------
  32. *
  33. * void urot_axis (float m[4][4], --- returned
  34. * float omega, --- input
  35. * float axis[3]) --- input
  36. * Same as urot_about_axis(), but angle specified in radians.
  37. * It is assumed that the argument axis[3] is a vector of unit length.
  38. * If it is not of unit length, the returned matrix will not be correct.
  39. *
  40. * void rot_axis (float omega, --- input
  41. * float axis[3]) --- input
  42. * Same as above routine, except that the matrix is multiplied into the
  43. * GL matrix stack.
  44. *
  45. * --------------------------------------------------------------------
  46. *
  47. * void urot_omega (float m[4][4], --- returned
  48. * float omega[3]) --- input
  49. * same as urot_axis(), but the angle is taken as the length of the
  50. * vector omega[3]
  51. *
  52. * void rot_omega (float omega[3]) --- input
  53. * Same as above routine, except that the matrix is multiplied into the
  54. * GL matrix stack.
  55. *
  56. * --------------------------------------------------------------------
  57. */
  58. #include <math.h>
  59. #include "gutil.h"
  60. /* Some <math.h> files do not define M_PI... */
  61. #ifndef M_PI
  62. #define M_PI 3.14159265358979323846
  63. #endif
  64. /* ========================================================== */
  65. #ifdef __GUTIL_DOUBLE
  66. void urot_axis_d (double m[4][4], /* returned */
  67. double omega, /* input */
  68. double axis[3]) /* input */
  69. #else
  70. void urot_axis_f (float m[4][4], /* returned */
  71. float omega, /* input */
  72. float axis[3]) /* input */
  73. #endif
  74. {
  75. double s, c, ssq, csq, cts;
  76. double tmp;
  77. /*
  78. * The formula coded up below can be derived by using the
  79. * homomorphism between SU(2) and O(3), namely, that the
  80. * 3x3 rotation matrix R is given by
  81. * t.R.v = S(-1) t.v S
  82. * where
  83. * t are the Pauli matrices (similar to Quaternions, easier to use)
  84. * v is an arbitrary 3-vector
  85. * and S is a 2x2 hermitian matrix:
  86. * S = exp ( i omega t.axis / 2 )
  87. *
  88. * (Also, remember that computer graphics uses the transpose of R).
  89. *
  90. * The Pauli matrices are:
  91. *
  92. * tx = (0 1) ty = (0 -i) tz = (1 0)
  93. * (1 0) (i 0) (0 -1)
  94. *
  95. * Note that no error checking is done -- if the axis vector is not
  96. * of unit length, you'll get strange results.
  97. */
  98. tmp = (double) omega / 2.0;
  99. s = sin (tmp);
  100. c = cos (tmp);
  101. ssq = s*s;
  102. csq = c*c;
  103. m[0][0] = m[1][1] = m[2][2] = csq - ssq;
  104. ssq *= 2.0;
  105. /* on-diagonal entries */
  106. m[0][0] += ssq * axis[0]*axis[0];
  107. m[1][1] += ssq * axis[1]*axis[1];
  108. m[2][2] += ssq * axis[2]*axis[2];
  109. /* off-diagonal entries */
  110. m[0][1] = m[1][0] = axis[0] * axis[1] * ssq;
  111. m[1][2] = m[2][1] = axis[1] * axis[2] * ssq;
  112. m[2][0] = m[0][2] = axis[2] * axis[0] * ssq;
  113. cts = 2.0 * c * s;
  114. tmp = cts * axis[2];
  115. m[0][1] += tmp;
  116. m[1][0] -= tmp;
  117. tmp = cts * axis[0];
  118. m[1][2] += tmp;
  119. m[2][1] -= tmp;
  120. tmp = cts * axis[1];
  121. m[2][0] += tmp;
  122. m[0][2] -= tmp;
  123. /* homogeneous entries */
  124. m[0][3] = m[1][3] = m[2][3] = m[3][2] = m[3][1] = m[3][0] = 0.0;
  125. m[3][3] = 1.0;
  126. }
  127. /* ========================================================== */
  128. #ifdef __GUTIL_DOUBLE
  129. void urot_about_axis_d (double m[4][4], /* returned */
  130. double angle, /* input */
  131. double axis[3]) /* input */
  132. #else
  133. void urot_about_axis_f (float m[4][4], /* returned */
  134. float angle, /* input */
  135. float axis[3]) /* input */
  136. #endif
  137. {
  138. gutDouble len, ax[3];
  139. angle *= M_PI/180.0; /* convert to radians */
  140. /* renormalize axis vector, if needed */
  141. len = axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2];
  142. /* we can save some machine instructions by normalizing only
  143. * if needed. The compiler should be able to schedule in the
  144. * if test "for free". */
  145. if (len != 1.0) {
  146. len = (gutDouble) (1.0 / sqrt ((double) len));
  147. ax[0] = axis[0] * len;
  148. ax[1] = axis[1] * len;
  149. ax[2] = axis[2] * len;
  150. #ifdef __GUTIL_DOUBLE
  151. urot_axis_d (m, angle, ax);
  152. #else
  153. urot_axis_f (m, angle, ax);
  154. #endif
  155. } else {
  156. #ifdef __GUTIL_DOUBLE
  157. urot_axis_d (m, angle, axis);
  158. #else
  159. urot_axis_f (m, angle, axis);
  160. #endif
  161. }
  162. }
  163. /* ========================================================== */
  164. #ifdef __GUTIL_DOUBLE
  165. void urot_omega_d (double m[4][4], /* returned */
  166. double axis[3]) /* input */
  167. #else
  168. void urot_omega_f (float m[4][4], /* returned */
  169. float axis[3]) /* input */
  170. #endif
  171. {
  172. gutDouble len, ax[3];
  173. /* normalize axis vector */
  174. len = axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2];
  175. len = (gutDouble) (1.0 / sqrt ((double) len));
  176. ax[0] = axis[0] * len;
  177. ax[1] = axis[1] * len;
  178. ax[2] = axis[2] * len;
  179. /* the amount of rotation is equal to the length, in radians */
  180. #ifdef __GUTIL_DOUBLE
  181. urot_axis_d (m, len, ax);
  182. #else
  183. urot_axis_f (m, len, ax);
  184. #endif
  185. }
  186. /* ======================= END OF FILE ========================== */