Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

303 Zeilen
7.4 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #pragma once
  13. #include <cassert>
  14. #include <cmath> // std::tan
  15. #include <algorithm> // std::max
  16. #if _MSC_VER
  17. # pragma push_macro("min")
  18. # pragma push_macro("max")
  19. # pragma push_macro("near")
  20. # pragma push_macro("far")
  21. # undef min
  22. # undef max
  23. # undef near
  24. # undef far
  25. #endif
  26. namespace lol
  27. {
  28. template<>
  29. inline std::string mat2::tostring() const
  30. {
  31. mat2 const &p = *this;
  32. return format("[ %6.6f %6.6f\n", p[0][0], p[1][0]) +
  33. format(" %6.6f %6.6f ]\n", p[0][1], p[1][1]);
  34. }
  35. template<>
  36. inline std::string mat3::tostring() const
  37. {
  38. mat3 const &p = *this;
  39. return format("[ %6.6f %6.6f %6.6f\n", p[0][0], p[1][0], p[2][0]) +
  40. format(" %6.6f %6.6f %6.6f\n", p[0][1], p[1][1], p[2][1]) +
  41. format(" %6.6f %6.6f %6.6f ]\n", p[0][2], p[1][2], p[2][2]);
  42. }
  43. template<>
  44. inline std::string mat4::tostring() const
  45. {
  46. mat4 const &p = *this;
  47. return format("[ %6.6f %6.6f %6.6f %6.6f\n",
  48. p[0][0], p[1][0], p[2][0], p[3][0]) +
  49. format(" %6.6f %6.6f %6.6f %6.6f\n",
  50. p[0][1], p[1][1], p[2][1], p[3][1]) +
  51. format(" %6.6f %6.6f %6.6f %6.6f\n",
  52. p[0][2], p[1][2], p[2][2], p[3][2]) +
  53. format(" %6.6f %6.6f %6.6f %6.6f ]\n",
  54. p[0][3], p[1][3], p[2][3], p[3][3]);
  55. }
  56. template<typename T>
  57. mat_t<T,3,3> mat_t<T,3,3>::scale(T x, T y, T z)
  58. {
  59. mat_t<T,3,3> ret(T(1));
  60. ret[0][0] = x;
  61. ret[1][1] = y;
  62. ret[2][2] = z;
  63. return ret;
  64. }
  65. template<typename T>
  66. mat_t<T,3,3> mat_t<T,3,3>::scale(T x)
  67. {
  68. return scale(x, x, x);
  69. }
  70. template<typename T>
  71. mat_t<T,3,3> mat_t<T,3,3>::scale(vec_t<T,3> v)
  72. {
  73. return scale(v.x, v.y, v.z);
  74. }
  75. template<typename T>
  76. mat_t<T,4,4> mat_t<T,4,4>::translate(T x, T y, T z)
  77. {
  78. mat_t<T,4,4> ret(T(1));
  79. ret[3][0] = x;
  80. ret[3][1] = y;
  81. ret[3][2] = z;
  82. return ret;
  83. }
  84. template<typename T>
  85. mat_t<T,4,4> mat_t<T,4,4>::translate(vec_t<T,3> v)
  86. {
  87. return translate(v.x, v.y, v.z);
  88. }
  89. template<typename T>
  90. mat_t<T,2,2> mat_t<T,2,2>::rotate(T radians)
  91. {
  92. T st = sin(radians);
  93. T ct = cos(radians);
  94. mat_t<T,2,2> ret;
  95. ret[0][0] = ct;
  96. ret[0][1] = st;
  97. ret[1][0] = -st;
  98. ret[1][1] = ct;
  99. return ret;
  100. }
  101. template<typename T>
  102. mat_t<T,3,3> mat_t<T,3,3>::rotate(T radians, T x, T y, T z)
  103. {
  104. T st = sin(radians);
  105. T ct = cos(radians);
  106. T len = std::sqrt(x * x + y * y + z * z);
  107. T invlen = len ? T(1) / len : T(0);
  108. x *= invlen;
  109. y *= invlen;
  110. z *= invlen;
  111. T mtx = (T(1) - ct) * x;
  112. T mty = (T(1) - ct) * y;
  113. T mtz = (T(1) - ct) * z;
  114. mat_t<T,3,3> ret;
  115. ret[0][0] = x * mtx + ct;
  116. ret[0][1] = x * mty + st * z;
  117. ret[0][2] = x * mtz - st * y;
  118. ret[1][0] = y * mtx - st * z;
  119. ret[1][1] = y * mty + ct;
  120. ret[1][2] = y * mtz + st * x;
  121. ret[2][0] = z * mtx + st * y;
  122. ret[2][1] = z * mty - st * x;
  123. ret[2][2] = z * mtz + ct;
  124. return ret;
  125. }
  126. template<typename T>
  127. mat_t<T,3,3> mat_t<T,3,3>::rotate(T radians, vec_t<T,3> v)
  128. {
  129. return rotate(radians, v.x, v.y, v.z);
  130. }
  131. template<typename T>
  132. mat_t<T,3,3>::mat_t(quat_t<T> const &q)
  133. {
  134. T n = norm(q);
  135. if (!n)
  136. {
  137. for (int j = 0; j < 3; j++)
  138. for (int i = 0; i < 3; i++)
  139. (*this)[i][j] = (i == j) ? T(1) : T(0);
  140. return;
  141. }
  142. T s = T(2) / n;
  143. (*this)[0][0] = T(1) - s * (q.y * q.y + q.z * q.z);
  144. (*this)[0][1] = s * (q.x * q.y + q.z * q.w);
  145. (*this)[0][2] = s * (q.x * q.z - q.y * q.w);
  146. (*this)[1][0] = s * (q.x * q.y - q.z * q.w);
  147. (*this)[1][1] = T(1) - s * (q.z * q.z + q.x * q.x);
  148. (*this)[1][2] = s * (q.y * q.z + q.x * q.w);
  149. (*this)[2][0] = s * (q.x * q.z + q.y * q.w);
  150. (*this)[2][1] = s * (q.y * q.z - q.x * q.w);
  151. (*this)[2][2] = T(1) - s * (q.x * q.x + q.y * q.y);
  152. }
  153. template<typename T>
  154. mat_t<T,4,4>::mat_t(quat_t<T> const &q)
  155. {
  156. *this = mat_t<T,4,4>(mat_t<T,3,3>(q), T(1));
  157. }
  158. // These are only specialised for float type, but could be extended
  159. // to anything else. I’m just not sure it’s worth it.
  160. template<>
  161. inline mat4 mat4::lookat(vec3 eye, vec3 center, vec3 up)
  162. {
  163. vec3 v3 = normalize(eye - center);
  164. vec3 v1 = normalize(cross(up, v3));
  165. vec3 v2 = cross(v3, v1);
  166. return mat4(vec4(v1.x, v2.x, v3.x, 0.f),
  167. vec4(v1.y, v2.y, v3.y, 0.f),
  168. vec4(v1.z, v2.z, v3.z, 0.f),
  169. vec4(-dot(eye, v1), -dot(eye, v2), -dot(eye, v3), 1.f));
  170. }
  171. template<>
  172. inline mat4 mat4::ortho(float left, float right, float bottom,
  173. float top, float near, float far)
  174. {
  175. float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
  176. float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
  177. float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
  178. mat4 ret(0.0f);
  179. ret[0][0] = 2.0f * invrl;
  180. ret[1][1] = 2.0f * invtb;
  181. ret[2][2] = -2.0f * invfn;
  182. ret[3][0] = - (right + left) * invrl;
  183. ret[3][1] = - (top + bottom) * invtb;
  184. ret[3][2] = - (far + near) * invfn;
  185. ret[3][3] = 1.0f;
  186. return ret;
  187. }
  188. template<>
  189. inline mat4 mat4::ortho(float width, float height,
  190. float near, float far)
  191. {
  192. return mat4::ortho(-0.5f * width, 0.5f * width,
  193. -0.5f * height, 0.5f * height, near, far);
  194. }
  195. template<>
  196. inline mat4 mat4::frustum(float left, float right, float bottom,
  197. float top, float near, float far)
  198. {
  199. float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
  200. float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
  201. float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
  202. mat4 ret(0.0f);
  203. ret[0][0] = 2.0f * near * invrl;
  204. ret[1][1] = 2.0f * near * invtb;
  205. ret[2][0] = (right + left) * invrl;
  206. ret[2][1] = (top + bottom) * invtb;
  207. ret[2][2] = - (far + near) * invfn;
  208. ret[2][3] = -1.0f;
  209. ret[3][2] = -2.0f * far * near * invfn;
  210. return ret;
  211. }
  212. /*
  213. * Return a standard perspective matrix
  214. */
  215. template<>
  216. inline mat4 mat4::perspective(float fov_y, float width,
  217. float height, float near, float far)
  218. {
  219. using std::tan;
  220. float t2 = tan(fov_y * 0.5f);
  221. float t1 = t2 * width / height;
  222. return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far);
  223. }
  224. /*
  225. * Return a perspective matrix with the camera location shifted to be on
  226. * the near plane
  227. */
  228. template<>
  229. inline mat4 mat4::shifted_perspective(float fov_y, float screen_size,
  230. float screen_ratio_yx,
  231. float near, float far)
  232. {
  233. using std::tan;
  234. float tan_y = tan(fov_y * .5f);
  235. assert(tan_y > 0.000001f);
  236. float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y;
  237. return mat4::perspective(fov_y, screen_size, screen_size * screen_ratio_yx,
  238. std::max(.001f, dist_scr + near),
  239. std::max(.001f, dist_scr + far)) *
  240. mat4::translate(.0f, .0f, -dist_scr);
  241. }
  242. } /* namespace lol */
  243. #if _WIN32
  244. # pragma pop_macro("min")
  245. # pragma pop_macro("max")
  246. # pragma pop_macro("near")
  247. # pragma pop_macro("far")
  248. #endif