glmatrix.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include <string.h>
  2. #define _USE_MATH_DEFINES
  3. #include <math.h>
  4. #include "glmatrix.h"
  5. #ifndef M_PI
  6. #define M_PI 3.141592653589793
  7. #endif
  8. #define MMODE_IDX(x) ((x) - GL_MODELVIEW)
  9. #define MAT_STACK_SIZE 32
  10. #define MAT_IDENT {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
  11. static int mm_idx = 0;
  12. static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}};
  13. static int stack_top[3];
  14. void gl_matrix_mode(int mm)
  15. {
  16. mm_idx = MMODE_IDX(mm);
  17. }
  18. void gl_push_matrix(void)
  19. {
  20. int top = stack_top[mm_idx];
  21. memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float));
  22. stack_top[mm_idx]++;
  23. }
  24. void gl_pop_matrix(void)
  25. {
  26. stack_top[mm_idx]--;
  27. }
  28. void gl_load_identity(void)
  29. {
  30. static const float idmat[] = MAT_IDENT;
  31. int top = stack_top[mm_idx];
  32. float *mat = mat_stack[mm_idx][top];
  33. memcpy(mat, idmat, sizeof idmat);
  34. }
  35. void gl_load_matrixf(const float *m)
  36. {
  37. int top = stack_top[mm_idx];
  38. float *mat = mat_stack[mm_idx][top];
  39. memcpy(mat, m, 16 * sizeof *mat);
  40. }
  41. #define M4(i, j) ((i << 2) + j)
  42. void gl_mult_matrixf(const float *m2)
  43. {
  44. int i, j;
  45. int top = stack_top[mm_idx];
  46. float *m1 = mat_stack[mm_idx][top];
  47. float res[16];
  48. for(i=0; i<4; i++) {
  49. for(j=0; j<4; j++) {
  50. res[M4(i,j)] = m1[M4(i,0)] * m2[M4(0,j)] +
  51. m1[M4(i,1)] * m2[M4(1,j)] +
  52. m1[M4(i,2)] * m2[M4(2,j)] +
  53. m1[M4(i,3)] * m2[M4(3,j)];
  54. }
  55. }
  56. memcpy(m1, res, sizeof res);
  57. }
  58. void gl_translatef(float x, float y, float z)
  59. {
  60. float mat[] = MAT_IDENT;
  61. mat[12] = x;
  62. mat[13] = y;
  63. mat[14] = z;
  64. gl_mult_matrixf(mat);
  65. }
  66. void gl_rotatef(float angle, float x, float y, float z)
  67. {
  68. float mat[] = MAT_IDENT;
  69. float angle_rad = (float)M_PI * angle / 180.f;
  70. float sina = (float)sin(angle_rad);
  71. float cosa = (float)cos(angle_rad);
  72. float one_minus_cosa = 1.f - cosa;
  73. float nxsq = x * x;
  74. float nysq = y * y;
  75. float nzsq = z * z;
  76. mat[0] = nxsq + (1.f - nxsq) * cosa;
  77. mat[4] = x * y * one_minus_cosa - z * sina;
  78. mat[8] = x * z * one_minus_cosa + y * sina;
  79. mat[1] = x * y * one_minus_cosa + z * sina;
  80. mat[5] = nysq + (1.f - nysq) * cosa;
  81. mat[9] = y * z * one_minus_cosa - x * sina;
  82. mat[2] = x * z * one_minus_cosa - y * sina;
  83. mat[6] = y * z * one_minus_cosa + x * sina;
  84. mat[10] = nzsq + (1.f - nzsq) * cosa;
  85. gl_mult_matrixf(mat);
  86. }
  87. void gl_scalef(float x, float y, float z)
  88. {
  89. float mat[] = MAT_IDENT;
  90. mat[0] = x;
  91. mat[5] = y;
  92. mat[10] = z;
  93. gl_mult_matrixf(mat);
  94. }
  95. void gl_ortho(float left, float right, float bottom, float top, float znear, float zfar)
  96. {
  97. float mat[] = MAT_IDENT;
  98. float dx = right - left;
  99. float dy = top - bottom;
  100. float dz = zfar - znear;
  101. float tx = -(right + left) / dx;
  102. float ty = -(top + bottom) / dy;
  103. float tz = -(zfar + znear) / dz;
  104. float sx = 2.f / dx;
  105. float sy = 2.f / dy;
  106. float sz = -2.f / dz;
  107. mat[0] = sx;
  108. mat[5] = sy;
  109. mat[10] = sz;
  110. mat[12] = tx;
  111. mat[13] = ty;
  112. mat[14] = tz;
  113. gl_mult_matrixf(mat);
  114. }
  115. void gl_frustum(float left, float right, float bottom, float top, float znear, float zfar)
  116. {
  117. float mat[] = MAT_IDENT;
  118. float dx = right - left;
  119. float dy = top - bottom;
  120. float dz = zfar - znear;
  121. float a = (right + left) / dx;
  122. float b = (top + bottom) / dy;
  123. float c = -(zfar + znear) / dz;
  124. float d = -2.f * zfar * znear / dz;
  125. mat[0] = 2.f * znear / dx;
  126. mat[5] = 2.f * znear / dy;
  127. mat[8] = a;
  128. mat[9] = b;
  129. mat[10] = c;
  130. mat[11] = -1.f;
  131. mat[14] = d;
  132. mat[15] = 0;
  133. gl_mult_matrixf(mat);
  134. }
  135. void glu_perspective(float vfov, float aspect, float znear, float zfar)
  136. {
  137. float vfov_rad = (float)M_PI * vfov / 180.f;
  138. float x = znear * (float)tan(vfov_rad / 2.f);
  139. gl_frustum(-aspect * x, aspect * x, -x, x, znear, zfar);
  140. }
  141. /* return the matrix (16 elements, 4x4 matrix, row-major order */
  142. float* get_matrix(int mm)
  143. {
  144. int idx = MMODE_IDX(mm);
  145. int top = stack_top[idx];
  146. return mat_stack[idx][top];
  147. }
  148. #define M3(i, j) ((i * 3) + j)
  149. static float inv_transpose_result[9];
  150. /* return the inverse transpose of the left-upper 3x3 of a matrix
  151. The returned pointer is only valid until the next time this function is
  152. called, so make a deep copy when you want to keep it around.
  153. */
  154. float* get_inv_transpose_3x3(int mm)
  155. {
  156. int idx = MMODE_IDX(mm);
  157. int top = stack_top[idx];
  158. float *m1 = mat_stack[idx][top];
  159. float determinant = +m1[M4(0,0)]*(m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])
  160. -m1[M4(0,1)]*(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])
  161. +m1[M4(0,2)]*(m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(1,1)]*m1[M4(2,0)]);
  162. float invdet = 1/determinant;
  163. inv_transpose_result[M3(0,0)] = (m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])*invdet;
  164. inv_transpose_result[M3(1,0)] = -(m1[M4(0,1)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,1)])*invdet;
  165. inv_transpose_result[M3(2,0)] = (m1[M4(0,1)]*m1[M4(1,2)]-m1[M4(0,2)]*m1[M4(1,1)])*invdet;
  166. inv_transpose_result[M3(0,1)] = -(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])*invdet;
  167. inv_transpose_result[M3(1,1)] = (m1[M4(0,0)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,0)])*invdet;
  168. inv_transpose_result[M3(2,1)] = -(m1[M4(0,0)]*m1[M4(1,2)]-m1[M4(1,0)]*m1[M4(0,2)])*invdet;
  169. inv_transpose_result[M3(0,2)] = (m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(1,1)])*invdet;
  170. inv_transpose_result[M3(1,2)] = -(m1[M4(0,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(0,1)])*invdet;
  171. inv_transpose_result[M3(2,2)] = (m1[M4(0,0)]*m1[M4(1,1)]-m1[M4(1,0)]*m1[M4(0,1)])*invdet;
  172. return inv_transpose_result;
  173. }