gl_transform.hh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #ifndef GL_TRANSFORM_HH
  2. #define GL_TRANSFORM_HH
  3. // OpenGLES 2.0 removed functions like
  4. // glRotate(), glTranslate(), glScale(), ...
  5. // This code can be used to replace them.
  6. //
  7. // This code was inspired by the 'glm' library (though written from scratch).
  8. // Compared to glm this code is much simpler but offers much less functionality.
  9. // http://glm.g-truc.net
  10. #include "gl_mat.hh"
  11. #include "gl_vec.hh"
  12. namespace gl {
  13. // Returns a 4x4 scaling matrix for the given xyz scale factors.
  14. // Comparable to the glScale() function.
  15. inline mat4 scale(const vec3& xyz)
  16. {
  17. return mat4(vec4(xyz, 1.0f));
  18. }
  19. // Multiplies the given matrix by a scaling matrix. Equivalent to (but more
  20. // efficient than) 'A * scale(xyz)'.
  21. inline mat4 scale(const mat4& A, const vec3& xyz)
  22. {
  23. return {A[0] * xyz[0],
  24. A[1] * xyz[1],
  25. A[2] * xyz[2],
  26. A[3]};
  27. }
  28. // Returns a 4x4 translation matrix for the given xyz translation vector.
  29. // Comparable to the gltranslate() function.
  30. inline mat4 translate(const vec3& xyz)
  31. {
  32. mat4 result;
  33. result[3] = vec4(xyz, 1.0f);
  34. return result;
  35. }
  36. // Multiplies the given matrix by a translation matrix. Equivalent to (but
  37. // more efficient than) 'A * translate(xyz)'.
  38. inline mat4 translate(mat4& A, const vec3& xyz)
  39. {
  40. return {A[0],
  41. A[1],
  42. A[2],
  43. A[0] * xyz[0] + A[1] * xyz[1] + A[2] * xyz[2] + A[3]};
  44. }
  45. // Returns a 4x4 rotation matrix for rotation of the given 'angle' around the
  46. // 'xyz' axis.
  47. // Comparable to the glRotate() function, but with these differences:
  48. // - 'angle' is in radians instead of degrees
  49. // - 'axis' must be a normalized vector
  50. inline mat4 rotate(float angle, const vec3& axis)
  51. {
  52. float s = sinf(angle);
  53. float c = cosf(angle);
  54. vec3 temp = (1.0f - c) * axis;
  55. return {vec4(axis[0] * temp[0] + c,
  56. axis[1] * temp[0] + s * axis[2],
  57. axis[2] * temp[0] - s * axis[1],
  58. 0.0f),
  59. vec4(axis[0] * temp[1] - s * axis[2],
  60. axis[1] * temp[1] + c,
  61. axis[2] * temp[1] + s * axis[0],
  62. 0.0f),
  63. vec4(axis[0] * temp[2] + s * axis[1],
  64. axis[1] * temp[2] - s * axis[0],
  65. axis[2] * temp[2] + c,
  66. 0.0f),
  67. vec4(0.0f,
  68. 0.0f,
  69. 0.0f,
  70. 1.0f)};
  71. }
  72. // Multiplies the given matrix by a rotation matrix. Equivalent to
  73. // 'A * rotate(angle, axis)'.
  74. inline mat4 rotate(const mat4& A, float angle, const vec3& axis)
  75. {
  76. // TODO this could be optimized (only a little), though it's rarely used
  77. return A * rotate(angle, axis);
  78. }
  79. // Returns a 4x4 rotation matrix for rotation around the X-axis. Much more
  80. // efficient than calling the generic rotate() function with a vec3(1,0,0)
  81. // axis.
  82. inline mat4 rotateX(float angle)
  83. {
  84. float s = sinf(angle);
  85. float c = cosf(angle);
  86. return {vec4(1.0f, 0.0f, 0.0f, 0.0f),
  87. vec4(0.0f, c , s , 0.0f),
  88. vec4(0.0f, -s , c , 0.0f),
  89. vec4(0.0f, 0.0f, 0.0f, 1.0f)};
  90. }
  91. // Multiplies the given matrix by a X-rotation matrix. Equivalent to (but more
  92. // efficient than) 'A * rotateX(angle)'.
  93. inline mat4 rotateX(const mat4& A, float angle)
  94. {
  95. float s = sinf(angle);
  96. float c = cosf(angle);
  97. return {A[0],
  98. A[1] * c + A[2] * s,
  99. A[2] * c - A[1] * s,
  100. A[3]};
  101. }
  102. // Returns a 4x4 rotation matrix for rotation around the Y-axis. Much more
  103. // efficient than calling the generic rotate() function with a vec3(0,1,0)
  104. // axis.
  105. inline mat4 rotateY(float angle)
  106. {
  107. float s = sinf(angle);
  108. float c = cosf(angle);
  109. return {vec4( c , 0.0f, -s , 0.0f),
  110. vec4(0.0f, 1.0f, 0.0f, 0.0f),
  111. vec4( s , 0.0f, c , 0.0f),
  112. vec4(0.0f, 0.0f, 0.0f, 1.0f)};
  113. }
  114. // Multiplies the given matrix by a Y-rotation matrix. Equivalent to (but more
  115. // efficient than) 'A * rotateY(angle)'.
  116. inline mat4 rotateY(const mat4& A, float angle)
  117. {
  118. float s = sinf(angle);
  119. float c = cosf(angle);
  120. return {A[0] * c - A[2] * s,
  121. A[1],
  122. A[2] * c + A[0] * s,
  123. A[3]};
  124. }
  125. // Returns a 4x4 rotation matrix for rotation around the Z-axis. Much more
  126. // efficient than calling the generic rotate() function with a vec3(0,0,1)
  127. // axis.
  128. inline mat4 rotateZ(float angle)
  129. {
  130. float s = sinf(angle);
  131. float c = cosf(angle);
  132. return {vec4( c , s , 0.0f, 0.0f),
  133. vec4(-s , c , 0.0f, 0.0f),
  134. vec4(0.0f, 0.0f, 1.0f, 0.0f),
  135. vec4(0.0f, 0.0f, 0.0f, 1.0f)};
  136. }
  137. // Multiplies the given matrix by a Z-rotation matrix. Equivalent to (but more
  138. // efficient than) 'A * rotateZ(angle)'.
  139. inline mat4 rotateZ(const mat4& A, float angle)
  140. {
  141. float s = sinf(angle);
  142. float c = cosf(angle);
  143. return {A[0] * c + A[1] * s,
  144. A[1] * c - A[0] * s,
  145. A[2],
  146. A[3]};
  147. }
  148. // Note: Don't use "near" or "far" as names since those are macros on Windows.
  149. // Returns a 4x4 orthographic projection matrix. Comparable to
  150. // the glOrtho() function.
  151. inline mat4 ortho(float left, float right,
  152. float bottom, float top,
  153. float nearVal, float farVal)
  154. {
  155. return {vec4(-2.0f / (left - right), 0.0f, 0.0f, 0.0f),
  156. vec4( 0.0f, -2.0f / (bottom - top), 0.0f, 0.0f),
  157. vec4( 0.0f, 0.0f, 2.0f / (nearVal - farVal), 0.0f),
  158. vec4((left + right ) / (left - right ),
  159. (bottom + top ) / (bottom - top ),
  160. (nearVal + farVal) / (nearVal - farVal),
  161. 1.0f)};
  162. }
  163. // Returns a 4x4 frustum projection matrix. Comparable to
  164. // the glFrustum() function.
  165. inline mat4 frustum(float left, float right,
  166. float bottom, float top,
  167. float nearVal, float farVal)
  168. {
  169. return {vec4((2.0f * nearVal) / (right - left), 0.0f, 0.0f, 0.0f),
  170. vec4(0.0f, (2.0f * nearVal) / (top - bottom), 0.0f, 0.0f),
  171. vec4((right + left ) / (right - left ),
  172. (top + bottom) / (top - bottom),
  173. (nearVal + farVal) / (nearVal - farVal),
  174. -1.0f),
  175. vec4(0.0f,
  176. 0.0f,
  177. (2.0f * farVal * nearVal) / (nearVal - farVal),
  178. 0.0f)};
  179. }
  180. } // namespace gl
  181. #endif