/quat/matrix.c

https://gitlab.com/sat-metalab/vrpn · C · 302 lines · 135 code · 55 blank · 112 comment · 17 complexity · a28f0a370ca263adf01212ab5ad47dcf MD5 · raw file

  1. /*****************************************************************************
  2. *
  3. matrix.c- code for matrix utilities for quaternion library; routines
  4. here are only those that have nothing to do with quaternions.
  5. (see quat.h for revision history and more documentation.)
  6. *
  7. *****************************************************************************/
  8. #include <math.h> // for atan2, cos, sin, fabs, sqrt
  9. #include <stdio.h> // for printf
  10. #include "quat.h" // for q_matrix_type, etc
  11. /* define local X, Y, Z, W to override any external definition; don't use
  12. * Q_X, etc, because it makes this code a LOT harder to read; don't use
  13. * pphigs definition of X-W since it could theoretically change.
  14. */
  15. #undef X
  16. #undef Y
  17. #undef Z
  18. #undef W
  19. #define X Q_X
  20. #define Y Q_Y
  21. #define Z Q_Z
  22. #define W Q_W
  23. /*
  24. * q_print_matrix - prints a 4x4 matrix
  25. */
  26. void q_print_matrix(const q_matrix_type matrix)
  27. {
  28. int i, j;
  29. for ( i = 0; i < 4; i++ )
  30. {
  31. printf(" ");
  32. for ( j = 0; j < 4; j++ )
  33. printf("%10lf", matrix[i][j]);
  34. printf("\n");
  35. }
  36. } /* q_print_matrix */
  37. /*****************************************************************************
  38. *
  39. q_euler_to_col_matrix - euler angles should be in radians
  40. computed assuming the order of rotation is: yaw, pitch, roll.
  41. This means the following:
  42. p' = roll( pitch( yaw(p) ) )
  43. or
  44. p' = Mr * Mp * My * p
  45. Yaw is rotation about Z axis, pitch is rotation about Y axis, and roll
  46. is rotation about X axis. In terms of these axes, then, the process is:
  47. p' = Mx * My * Mz * p
  48. where Mx = the standard Foley and van Dam column matrix for rotation
  49. about the X axis, and similarly for Y and Z.
  50. Thus the calling sequence in terms of X, Y, Z is:
  51. q_euler_to_col_matrix(destMatrix, zRot, yRot, xRot);
  52. *
  53. *****************************************************************************/
  54. void q_euler_to_col_matrix(q_matrix_type destMatrix,
  55. double yaw, double pitch, double roll)
  56. {
  57. double cosYaw, sinYaw, cosPitch, sinPitch, cosRoll, sinRoll;
  58. cosYaw = cos(yaw);
  59. sinYaw = sin(yaw);
  60. cosPitch = cos(pitch);
  61. sinPitch = sin(pitch);
  62. cosRoll = cos(roll);
  63. sinRoll = sin(roll);
  64. /*
  65. * compute transformation destMatrix
  66. */
  67. destMatrix[0][0] = cosYaw * cosPitch;
  68. destMatrix[0][1] = cosYaw * sinPitch * sinRoll - sinYaw * cosRoll;
  69. destMatrix[0][2] = cosYaw * sinPitch * cosRoll + sinYaw * sinRoll;
  70. destMatrix[0][3] = 0.0;
  71. destMatrix[1][0] = sinYaw * cosPitch;
  72. destMatrix[1][1] = cosYaw * cosRoll + sinYaw * sinPitch * sinRoll;
  73. destMatrix[1][2] = sinYaw * sinPitch * cosRoll - cosYaw * sinRoll;
  74. destMatrix[1][3] = 0.0;
  75. destMatrix[2][0] = -sinPitch;
  76. destMatrix[2][1] = cosPitch * sinRoll;
  77. destMatrix[2][2] = cosPitch * cosRoll;
  78. destMatrix[2][3] = 0.0;
  79. destMatrix[3][0] = 0.0;
  80. destMatrix[3][1] = 0.0;
  81. destMatrix[3][2] = 0.0;
  82. destMatrix[3][3] = 1.0;
  83. } /* q_euler_to_col_matrix */
  84. /*****************************************************************************
  85. *
  86. q_col_matrix_to_euler- convert a column matrix to euler angles
  87. input:
  88. - vector to hold euler angles
  89. - src column matrix
  90. q_vec_type angles : Holds outgoing roll, pitch, yaw
  91. q_matrix_type colMatrix : Holds incoming rotation
  92. output:
  93. - euler angles in radians in the range -pi to pi;
  94. vec[0] = yaw, vec[1] = pitch, vec[2] = roll
  95. yaw is rotation about Z axis, pitch is about Y, roll -> X rot.
  96. notes:
  97. - written by Gary Bishop
  98. - you cannot use Q_X, Q_Y, and Q_Z to pull the elements out of
  99. the Euler as if they were rotations about these angles --
  100. this will invert X and Z. You need to instead use Q_YAW
  101. (rotation about Z), Q_PITCH (rotation about Y) and Q_ROLL
  102. (rotation about X) to get them.
  103. *
  104. *****************************************************************************/
  105. void q_col_matrix_to_euler(q_vec_type yawpitchroll, const q_matrix_type colMatrix)
  106. {
  107. double sinPitch, cosPitch, sinRoll, cosRoll, sinYaw, cosYaw;
  108. sinPitch = -colMatrix[2][0];
  109. cosPitch = sqrt(1 - sinPitch*sinPitch);
  110. if ( fabs(cosPitch) > Q_EPSILON )
  111. {
  112. sinRoll = colMatrix[2][1] / cosPitch;
  113. cosRoll = colMatrix[2][2] / cosPitch;
  114. sinYaw = colMatrix[1][0] / cosPitch;
  115. cosYaw = colMatrix[0][0] / cosPitch;
  116. }
  117. else
  118. {
  119. sinRoll = -colMatrix[1][2];
  120. cosRoll = colMatrix[1][1];
  121. sinYaw = 0;
  122. cosYaw = 1;
  123. }
  124. /* yaw */
  125. yawpitchroll[Q_YAW] = atan2(sinYaw, cosYaw);
  126. /* pitch */
  127. yawpitchroll[Q_PITCH] = atan2(sinPitch, cosPitch);
  128. /* roll */
  129. yawpitchroll[Q_ROLL] = atan2(sinRoll, cosRoll);
  130. } /* col_matrix_to_euler */
  131. /*****************************************************************************
  132. *
  133. q_matrix_mult - does a 4x4 matrix multiply (the input matrices are 4x4) and
  134. puts the result in a 4x4 matrix. src == dest ok.
  135. *
  136. *****************************************************************************/
  137. void q_matrix_mult(q_matrix_type resultMatrix, const q_matrix_type leftMatrix,
  138. const q_matrix_type rightMatrix)
  139. {
  140. int i;
  141. int r, c;
  142. q_matrix_type tmpResultMatrix;
  143. /* pick up a row of the multiplier matrix and multiply by a column of the
  144. * multiplicand
  145. */
  146. for ( r = 0; r < 4; r++ )
  147. /* multiply each column of the multiplicand by row r of the multiplier */
  148. for ( c = 0; c < 4; c++ )
  149. {
  150. tmpResultMatrix[r][c] = 0.0;
  151. /*
  152. * for each element in the multiplier row, multiply it with each
  153. * element in column c of the multiplicand.
  154. * i ranges over the length of the rows in multiplier and the length
  155. * of the columns in the multiplicand
  156. */
  157. for ( i = 0; i < 4; i++ )
  158. /*
  159. * uses
  160. * C[r][c] += A[r][i] * B[i][c]
  161. */
  162. tmpResultMatrix[r][c] += leftMatrix[r][i] * rightMatrix[i][c];
  163. }
  164. q_matrix_copy(resultMatrix, ( const double (*)[4] ) tmpResultMatrix);
  165. } /* q_matrix_mult */
  166. /*
  167. * multiplication of OpenGL-style matrices
  168. */
  169. void qogl_matrix_mult(qogl_matrix_type result, const qogl_matrix_type left,
  170. const qogl_matrix_type right )
  171. {
  172. int i, r, c;
  173. qogl_matrix_type tmp;
  174. /* straightforward matrix multiplication */
  175. for ( r = 0; r < 4; r++ ) {
  176. for( c = 0; c < 4; c++ ) {
  177. tmp[r*4+c] = 0.0;
  178. for( i = 0; i < 4; i++ ) {
  179. tmp[r*4+c] += left[i*4+c] * right[r*4+i];
  180. }
  181. }
  182. }
  183. qogl_matrix_copy( result, tmp );
  184. }
  185. /*****************************************************************************
  186. *
  187. q_matrix_copy - copies srcMatrix to destMatrix (both matrices are 4x4)
  188. *
  189. *****************************************************************************/
  190. void q_matrix_copy(q_matrix_type destMatrix, const q_matrix_type srcMatrix)
  191. {
  192. int i, j;
  193. for ( i = 0; i < 4; i++ )
  194. for ( j = 0; j < 4; j++ )
  195. destMatrix[i][j] = srcMatrix[i][j];
  196. } /* q_matrix_copy */
  197. /*
  198. * qogl_matrix_copy - copies src to dest, both OpenGL matrices
  199. */
  200. void qogl_matrix_copy(qogl_matrix_type dest, const qogl_matrix_type src )
  201. {
  202. int i;
  203. for( i = 0; i < 16; i++ )
  204. dest[i] = src[i];
  205. }
  206. /*****************************************************************************
  207. *
  208. qgl_print_matrix - print gl-style matrix
  209. *
  210. *****************************************************************************/
  211. void qgl_print_matrix(const qgl_matrix_type matrix)
  212. {
  213. int i, j;
  214. for ( i = 0; i < 4; i++ )
  215. {
  216. printf(" ");
  217. for ( j = 0; j < 4; j++ )
  218. printf("%10f", matrix[i][j]);
  219. printf("\n");
  220. }
  221. } /* qgl_print_matrix */
  222. /*
  223. * print OpenGL-style matrix
  224. */
  225. void qogl_print_matrix(const qogl_matrix_type m )
  226. {
  227. int i, j;
  228. for( j = 0; j < 4; j++ ) {
  229. for( i = 0; i < 4; i++ )
  230. printf( "%10lf", m[i*4+j] );
  231. printf( "\n" );
  232. }
  233. } /* qogl_print_matrix */