/src/shared/vmath.cpp

https://bitbucket.org/vivkin/gam3b00bs/ · C++ · 359 lines · 283 code · 51 blank · 25 comment · 4 complexity · 0f048b9d6716053978191e1fea7f1870 MD5 · raw file

  1. #include "vmath.h"
  2. ///////////////////////////////////////////////////////////////////////////
  3. // SIMD
  4. ///////////////////////////////////////////////////////////////////////////
  5. const __m128 SIMD_EPSILON = _mm_set_ps1(EPSILON);
  6. const __m128 SIMD_ZERO = _mm_setzero_ps();
  7. const __m128 SIMD_ONE = _mm_set_ps1(1.0f);
  8. const __m128 SIMD_1110 = _mm_set_ps(0.0f, 1.0f, 1.0, 1.0f);
  9. const __m128 SIMD_1000 = _mm_set_ps(0.0f, 0.0f, 0.0, 1.0f);
  10. const __m128 SIMD_0100 = _mm_set_ps(0.0f, 0.0f, 1.0, 0.0f);
  11. const __m128 SIMD_0010 = _mm_set_ps(0.0f, 1.0f, 0.0, 0.0f);
  12. const __m128 SIMD_0001 = _mm_set_ps(1.0f, 0.0f, 0.0, 0.0f);
  13. __declspec(align(16)) const int SIMD_INT_MASK_AND_XYZ0[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0};
  14. __declspec(align(16)) const int SIMD_INT_MASK_AND_ABS[4] = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
  15. __declspec(align(16)) const int SIMD_INT_MASK_XOR_SIGN_XYZ0[4] = {0x80000000, 0x80000000, 0x80000000, 0x00000000};
  16. __declspec(align(16)) const int SIMD_INT_MASK_XOR_SIGN_0Y00[4] = {0, 0x80000000, 0, 0};
  17. __declspec(align(16)) const int SIMD_INT_MASK_XOR_SIGN_000W[4] = {0, 0, 0, 0x80000000};
  18. const __m128 SIMD_MASK_AND_XYZ0 = *reinterpret_cast<const __m128 *>(SIMD_INT_MASK_AND_XYZ0);
  19. const __m128 SIMD_MASK_AND_ABS = *reinterpret_cast<const __m128 *>(SIMD_INT_MASK_AND_ABS);
  20. const __m128 SIMD_MASK_XOR_SIGN_XYZ0 = *reinterpret_cast<const __m128 *>(SIMD_INT_MASK_XOR_SIGN_XYZ0);
  21. const __m128 SIMD_MASK_XOR_SIGN_0Y00 = *reinterpret_cast<const __m128 *>(SIMD_INT_MASK_XOR_SIGN_0Y00);
  22. const __m128 SIMD_MASK_XOR_SIGN_000W = *reinterpret_cast<const __m128 *>(SIMD_INT_MASK_XOR_SIGN_000W);
  23. const __m128 SIMD_MATRIX_INVERSE_SIGN_A = _mm_set_ps(1.0f, -1.0f, 1.0f, -1.0f);
  24. const __m128 SIMD_MATRIX_INVERSE_SIGN_B = _mm_set_ps(-1.0f, 1.0f, -1.0f, 1.0f);
  25. ///////////////////////////////////////////////////////////////////////////
  26. // 4D vector
  27. ///////////////////////////////////////////////////////////////////////////
  28. const vec4 vec4::ZERO = vec4(SIMD_ZERO);
  29. const vec4 vec4::ONE = vec4(SIMD_ONE);
  30. const vec4 vec4::UNIT_X = vec4(SIMD_1000);
  31. const vec4 vec4::UNIT_Y = vec4(SIMD_0100);
  32. const vec4 vec4::UNIT_Z = vec4(SIMD_0010);
  33. const vec4 vec4::UNIT_W = vec4(SIMD_0001);
  34. ///////////////////////////////////////////////////////////////////////////
  35. // Quaternion
  36. ///////////////////////////////////////////////////////////////////////////
  37. const vec4 QUAT_IDENTITY = vec4(SIMD_0001);
  38. // multiply quaternions
  39. vec4 quat_mult(const vec4 &lhs, const vec4 &rhs)
  40. {
  41. __m128 a1 = _mm_shuffle_ps(lhs.xyzw, lhs.xyzw, _MM_SHUFFLE(1, 3, 2, 0));
  42. __m128 a2 = _mm_shuffle_ps(lhs.xyzw, lhs.xyzw, _MM_SHUFFLE(0, 2, 3, 1));
  43. __m128 a3 = _mm_shuffle_ps(lhs.xyzw, lhs.xyzw, _MM_SHUFFLE(3, 1, 0, 2));
  44. __m128 a4 = _mm_shuffle_ps(lhs.xyzw, lhs.xyzw, _MM_SHUFFLE(2, 0, 1, 3));
  45. __m128 b1 = _mm_shuffle_ps(rhs.xyzw, rhs.xyzw, _MM_SHUFFLE(1, 2, 0, 3));
  46. __m128 b2 = _mm_shuffle_ps(rhs.xyzw, rhs.xyzw, _MM_SHUFFLE(0, 3, 1, 2));
  47. __m128 b3 = _mm_shuffle_ps(rhs.xyzw, rhs.xyzw, _MM_SHUFFLE(3, 0, 2, 1));
  48. __m128 b4 = _mm_shuffle_ps(rhs.xyzw, rhs.xyzw, _MM_SHUFFLE(2, 1, 3, 0));
  49. return vec4(_mm_xor_ps(
  50. _mm_add_ps(
  51. _mm_add_ps(_mm_mul_ps(a2, b2), _mm_mul_ps(a1, b1)),
  52. _mm_sub_ps(_mm_mul_ps(a4, b4), _mm_mul_ps(a3, b3))),
  53. SIMD_MASK_XOR_SIGN_000W));
  54. }
  55. // spherical linear interpolation
  56. vec4 quat_slerp(const vec4 &v0, const vec4 &v1, float t)
  57. {
  58. __m128 cosa = _mm_dot_ps(v0.xyzw, v1.xyzw);
  59. __m128 abscosa = _mm_and_ps(cosa, SIMD_MASK_AND_ABS);
  60. if (_mm_movemask_ps(_mm_cmpgt_ps(_mm_sub_ps(SIMD_ONE, abscosa), SIMD_EPSILON)) == 0xF)
  61. {
  62. float a;
  63. _mm_store_ss(&a, abscosa);
  64. a = acos(a);
  65. float sina = 1.0f / sin(a);
  66. float s0 = sin((1.0f - t) * a) * sina;
  67. float s1 = sin(t * a) * sina;
  68. __m128 scale0 = _mm_load_ps1(&s0);
  69. __m128 scale1 = _mm_load_ps1(&s1);
  70. if (_mm_movemask_ps(_mm_cmplt_ps(cosa, SIMD_ZERO)) == 0xF)
  71. {
  72. scale1 = _mm_sub_ps(SIMD_ZERO, scale1);
  73. }
  74. return vec4(_mm_add_ps(_mm_mul_ps(scale0, v0.xyzw), _mm_mul_ps(scale1, v1.xyzw)));
  75. }
  76. return v0;
  77. }
  78. ///////////////////////////////////////////////////////////////////////////
  79. // 4x4 matrix
  80. ///////////////////////////////////////////////////////////////////////////
  81. const mat4 mat4::ZERO = mat4(SIMD_ZERO, SIMD_ZERO, SIMD_ZERO, SIMD_ZERO);
  82. const mat4 mat4::IDENTITY = mat4(SIMD_1000, SIMD_0100, SIMD_0010, SIMD_0001);
  83. // mul
  84. mat4 &operator*=(mat4 &lhs, const mat4 &rhs)
  85. {
  86. lhs = lhs * rhs;
  87. return lhs;
  88. }
  89. const mat4 operator*(const mat4 &lhs, const mat4 &rhs)
  90. {
  91. mat4 m;
  92. m.row0 = _mm_add_ps(
  93. _mm_add_ps(
  94. _mm_mul_ps(rhs.row0, _mm_shuffle_ps(lhs.row0, lhs.row0, _MM_SHUFFLE(0, 0, 0, 0))),
  95. _mm_mul_ps(rhs.row1, _mm_shuffle_ps(lhs.row0, lhs.row0, _MM_SHUFFLE(1, 1, 1, 1)))),
  96. _mm_add_ps(
  97. _mm_mul_ps(rhs.row2, _mm_shuffle_ps(lhs.row0, lhs.row0, _MM_SHUFFLE(2, 2, 2, 2))),
  98. _mm_mul_ps(rhs.row3, _mm_shuffle_ps(lhs.row0, lhs.row0, _MM_SHUFFLE(3, 3, 3, 3)))));
  99. m.row1 = _mm_add_ps(
  100. _mm_add_ps(
  101. _mm_mul_ps(rhs.row0, _mm_shuffle_ps(lhs.row1, lhs.row1, _MM_SHUFFLE(0, 0, 0, 0))),
  102. _mm_mul_ps(rhs.row1, _mm_shuffle_ps(lhs.row1, lhs.row1, _MM_SHUFFLE(1, 1, 1, 1)))),
  103. _mm_add_ps(
  104. _mm_mul_ps(rhs.row2, _mm_shuffle_ps(lhs.row1, lhs.row1, _MM_SHUFFLE(2, 2, 2, 2))),
  105. _mm_mul_ps(rhs.row3, _mm_shuffle_ps(lhs.row1, lhs.row1, _MM_SHUFFLE(3, 3, 3, 3)))));
  106. m.row2 = _mm_add_ps(
  107. _mm_add_ps(
  108. _mm_mul_ps(rhs.row0, _mm_shuffle_ps(lhs.row2, lhs.row2, _MM_SHUFFLE(0, 0, 0, 0))),
  109. _mm_mul_ps(rhs.row1, _mm_shuffle_ps(lhs.row2, lhs.row2, _MM_SHUFFLE(1, 1, 1, 1)))),
  110. _mm_add_ps(
  111. _mm_mul_ps(rhs.row2, _mm_shuffle_ps(lhs.row2, lhs.row2, _MM_SHUFFLE(2, 2, 2, 2))),
  112. _mm_mul_ps(rhs.row3, _mm_shuffle_ps(lhs.row2, lhs.row2, _MM_SHUFFLE(3, 3, 3, 3)))));
  113. m.row3 = _mm_add_ps(
  114. _mm_add_ps(
  115. _mm_mul_ps(rhs.row0, _mm_shuffle_ps(lhs.row3, lhs.row3, _MM_SHUFFLE(0, 0, 0, 0))),
  116. _mm_mul_ps(rhs.row1, _mm_shuffle_ps(lhs.row3, lhs.row3, _MM_SHUFFLE(1, 1, 1, 1)))),
  117. _mm_add_ps(
  118. _mm_mul_ps(rhs.row2, _mm_shuffle_ps(lhs.row3, lhs.row3, _MM_SHUFFLE(2, 2, 2, 2))),
  119. _mm_mul_ps(rhs.row3, _mm_shuffle_ps(lhs.row3, lhs.row3, _MM_SHUFFLE(3, 3, 3, 3)))));
  120. return m;
  121. }
  122. // inverse matrix4x4
  123. mat4 matrix_inverse(const mat4 &v)
  124. {
  125. // http://www.devmaster.net/forums/showthread.php?t=14569
  126. __m128 Swp0a, Swp0b, Swp00, Swp01, Swp02, Swp03, Temp;
  127. Swp0a = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(3, 3, 3, 3));
  128. Swp0b = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(2, 2, 2, 2));
  129. Swp00 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(2, 2, 2, 2));
  130. Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0));
  131. Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0));
  132. Swp03 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(3, 3, 3, 3));
  133. __m128 Fac0 = _mm_sub_ps(_mm_mul_ps(Swp00, Swp01), _mm_mul_ps(Swp02, Swp03));
  134. Swp0a = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(3, 3, 3, 3));
  135. Swp0b = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(1, 1, 1, 1));
  136. Swp00 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(1, 1, 1, 1));
  137. Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0));
  138. Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0));
  139. Swp03 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(3, 3, 3, 3));
  140. __m128 Fac1 = _mm_sub_ps(_mm_mul_ps(Swp00, Swp01), _mm_mul_ps(Swp02, Swp03));
  141. Swp0a = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(2, 2, 2, 2));
  142. Swp0b = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(1, 1, 1, 1));
  143. Swp00 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(1, 1, 1, 1));
  144. Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0));
  145. Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0));
  146. Swp03 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(2, 2, 2, 2));
  147. __m128 Fac2 = _mm_sub_ps(_mm_mul_ps(Swp00, Swp01), _mm_mul_ps(Swp02, Swp03));
  148. Swp0a = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(3, 3, 3, 3));
  149. Swp0b = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(0, 0, 0, 0));
  150. Swp00 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(0, 0, 0, 0));
  151. Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0));
  152. Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0));
  153. Swp03 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(3, 3, 3, 3));
  154. __m128 Fac3 = _mm_sub_ps(_mm_mul_ps(Swp00, Swp01), _mm_mul_ps(Swp02, Swp03));
  155. Swp0a = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(2, 2, 2, 2));
  156. Swp0b = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(0, 0, 0, 0));
  157. Swp00 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(0, 0, 0, 0));
  158. Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0));
  159. Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0));
  160. Swp03 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(2, 2, 2, 2));
  161. __m128 Fac4 = _mm_sub_ps(_mm_mul_ps(Swp00, Swp01), _mm_mul_ps(Swp02, Swp03));
  162. Swp0a = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(1, 1, 1, 1));
  163. Swp0b = _mm_shuffle_ps(v.row3, v.row2, _MM_SHUFFLE(0, 0, 0, 0));
  164. Swp00 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(0, 0, 0, 0));
  165. Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0));
  166. Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0));
  167. Swp03 = _mm_shuffle_ps(v.row2, v.row1, _MM_SHUFFLE(1, 1, 1, 1));
  168. __m128 Fac5 = _mm_sub_ps(_mm_mul_ps(Swp00, Swp01), _mm_mul_ps(Swp02, Swp03));
  169. Temp = _mm_shuffle_ps(v.row1, v.row0, _MM_SHUFFLE(0, 0, 0, 0));
  170. __m128 Vec0 = _mm_shuffle_ps(Temp, Temp, _MM_SHUFFLE(2, 2, 2, 0));
  171. Temp = _mm_shuffle_ps(v.row1, v.row0, _MM_SHUFFLE(1, 1, 1, 1));
  172. __m128 Vec1 = _mm_shuffle_ps(Temp, Temp, _MM_SHUFFLE(2, 2, 2, 0));
  173. Temp = _mm_shuffle_ps(v.row1, v.row0, _MM_SHUFFLE(2, 2, 2, 2));
  174. __m128 Vec2 = _mm_shuffle_ps(Temp, Temp, _MM_SHUFFLE(2, 2, 2, 0));
  175. Temp = _mm_shuffle_ps(v.row1, v.row0, _MM_SHUFFLE(3, 3, 3, 3));
  176. __m128 Vec3 = _mm_shuffle_ps(Temp, Temp, _MM_SHUFFLE(2, 2, 2, 0));
  177. __m128 Inv0 = _mm_mul_ps(
  178. _mm_add_ps(
  179. _mm_mul_ps(Vec3, Fac2),
  180. _mm_sub_ps(
  181. _mm_mul_ps(Vec1, Fac0),
  182. _mm_mul_ps(Vec2, Fac1))),
  183. SIMD_MATRIX_INVERSE_SIGN_B);
  184. __m128 Inv1 = _mm_mul_ps(
  185. _mm_add_ps(
  186. _mm_mul_ps(Vec3, Fac4),
  187. _mm_sub_ps(
  188. _mm_mul_ps(Vec0, Fac0),
  189. _mm_mul_ps(Vec2, Fac3))),
  190. SIMD_MATRIX_INVERSE_SIGN_A);
  191. __m128 Inv2 = _mm_mul_ps(
  192. _mm_add_ps(
  193. _mm_mul_ps(Vec3, Fac5),
  194. _mm_sub_ps(
  195. _mm_mul_ps(Vec0, Fac1),
  196. _mm_mul_ps(Vec1, Fac3))),
  197. SIMD_MATRIX_INVERSE_SIGN_B);
  198. __m128 Inv3 = _mm_mul_ps(
  199. _mm_add_ps(
  200. _mm_mul_ps(Vec2, Fac5),
  201. _mm_sub_ps(
  202. _mm_mul_ps(Vec0, Fac2),
  203. _mm_mul_ps(Vec1, Fac4))),
  204. SIMD_MATRIX_INVERSE_SIGN_A);
  205. __m128 Det = _mm_dot_ps(
  206. _mm_shuffle_ps(
  207. _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)),
  208. _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)),
  209. _MM_SHUFFLE(2, 0, 2, 0)),
  210. v.row0);
  211. Det = _mm_div_ps(SIMD_ONE, Det);
  212. //Det = _mm_rcp_ps(Det);
  213. // Inverse /= Determinant;
  214. mat4 m;
  215. m.row0 = _mm_mul_ps(Inv0, Det);
  216. m.row1 = _mm_mul_ps(Inv1, Det);
  217. m.row2 = _mm_mul_ps(Inv2, Det);
  218. m.row3 = _mm_mul_ps(Inv3, Det);
  219. return m;
  220. }
  221. // scale matrix
  222. mat4 matrix_scaling(const vec4 &v)
  223. {
  224. mat4 m;
  225. m.row0 = _mm_mul_ps(v.xyzw, SIMD_1000);
  226. m.row1 = _mm_mul_ps(v.xyzw, SIMD_0100);
  227. m.row2 = _mm_mul_ps(v.xyzw, SIMD_0010);
  228. m.row3 = SIMD_0001;
  229. return m;
  230. }
  231. // translation matrix
  232. mat4 matrix_translation(const vec4 &v)
  233. {
  234. mat4 m;
  235. m.row0 = SIMD_1000;
  236. m.row1 = SIMD_0100;
  237. m.row2 = SIMD_0010;
  238. m.row3 = _mm_merge_ps(v.xyzw, SIMD_1000);
  239. return m;
  240. }
  241. // rotation matrix from quaternion
  242. mat4 matrix_rotation(const vec4 &v)
  243. {
  244. __m128 v2 = _mm_and_ps(_mm_add_ps(v.xyzw, v.xyzw), SIMD_MASK_AND_XYZ0);
  245. __m128 wv = _mm_xor_ps(_mm_mul_ps(_mm_shuffle_ps(v.xyzw, v.xyzw, _MM_SHUFFLE(3, 3, 3, 3)), v2), SIMD_MASK_XOR_SIGN_0Y00);
  246. __m128 xy_yz_xz = _mm_mul_ps(_mm_shuffle_ps(v.xyzw, v.xyzw, _MM_SHUFFLE(0, 0, 2, 1)), v2);
  247. __m128 yz_xz_xy = _mm_shuffle_ps(xy_yz_xz, xy_yz_xz, _MM_SHUFFLE(3, 0, 2, 1));
  248. __m128 a = _mm_add_ps(yz_xz_xy, wv);
  249. __m128 b = _mm_sub_ps(yz_xz_xy, wv);
  250. __m128 vv = _mm_mul_ps(v.xyzw, v2);
  251. __m128 yy_xx_xx = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(3, 0, 0, 1));
  252. __m128 zz_zz_yy = _mm_shuffle_ps(vv, vv, _MM_SHUFFLE(3, 1, 2, 2));
  253. __m128 c = _mm_sub_ps(SIMD_1110, _mm_add_ps(yy_xx_xx, zz_zz_yy));
  254. mat4 m;
  255. m.row0 = _mm_shuffle_ps(c, a, _MM_SHUFFLE(1, 2, 3, 0));
  256. m.row0 = _mm_shuffle_ps(m.row0, m.row0, _MM_SHUFFLE(1, 3, 2, 0));
  257. m.row1 = _mm_shuffle_ps(_mm_shuffle_ps(b, c, _MM_SHUFFLE(1, 1, 2, 2)), a, _MM_SHUFFLE(3, 0, 2, 0));
  258. m.row2 = _mm_shuffle_ps(b, c, _MM_SHUFFLE(3, 2, 0, 1));
  259. m.row3 = SIMD_0001;
  260. return m;
  261. }
  262. mat4 matrix_lookat(const vec4 &eye, const vec4 &at, const vec4 &up)
  263. {
  264. vec4 zaxis = normalize(at - eye);
  265. vec4 xaxis = normalize(cross(up, zaxis));
  266. vec4 yaxis = cross(zaxis, xaxis);
  267. __m128 tmp = _mm_hadd_ps(
  268. _mm_hadd_ps(_mm_mul_ps(xaxis.xyzw, eye.xyzw), _mm_mul_ps(yaxis.xyzw, eye.xyzw)),
  269. _mm_hadd_ps(_mm_mul_ps(zaxis.xyzw, eye.xyzw), _mm_setzero_ps()));
  270. tmp = _mm_merge_ps(_mm_sub_ps(_mm_setzero_ps(), tmp), SIMD_1000);
  271. mat4 m;
  272. m.row0 = xaxis.xyzw;
  273. m.row1 = yaxis.xyzw;
  274. m.row2 = zaxis.xyzw;
  275. m.row3 = _mm_setzero_ps();
  276. m.transpose();
  277. m.row3 = tmp;
  278. return m;
  279. }
  280. mat4 matrix_perspective(float fov, float aspect, float znear, float zfar)
  281. {
  282. float y = 1.0f / tan(fov / 2.0f);
  283. float x = y / aspect;
  284. float a = zfar / (zfar - znear);
  285. float b = -znear * zfar / (zfar - znear);
  286. return mat4(
  287. x, 0.0f, 0.0f, 0.0f,
  288. 0.0f, y, 0.0f, 0.0f,
  289. 0.0f, 0.0f, a, 1.0f,
  290. 0.0f, 0.0f, b, 0.0f);
  291. }
  292. mat4 matrix_ortho(float w, float h, float znear, float zfar)
  293. {
  294. float x = w / 2.0f;
  295. float y = h / 2.0f;
  296. float a = 1.0f / (zfar - znear);
  297. float b = -znear / (zfar - znear);
  298. return mat4(
  299. x, 0.0f, 0.0f, 0.0f,
  300. 0.0f, y, 0.0f, 0.0f,
  301. 0.0f, 0.0f, a, 0.0f,
  302. 0.0f, 0.0f, b, 1.0f);
  303. }
  304. ///////////////////////////////////////////////////////////////////////////
  305. // Axis aligned bounding box
  306. ///////////////////////////////////////////////////////////////////////////
  307. const bbox bbox::ZERO = bbox(vec4::ZERO, vec4::ZERO);
  308. const bbox bbox::DEGENERATE = bbox(vec4(INFINITY), vec4(-INFINITY));