Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

632 строки
15 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #if defined _XBOX
  14. # define _USE_MATH_DEFINES /* for M_PI */
  15. # include <xtl.h>
  16. # undef near /* Fuck Microsoft */
  17. # undef far /* Fuck Microsoft again */
  18. #elif defined _WIN32
  19. # define _USE_MATH_DEFINES /* for M_PI */
  20. # define WIN32_LEAN_AND_MEAN
  21. # include <windows.h>
  22. # undef near /* Fuck Microsoft */
  23. # undef far /* Fuck Microsoft again */
  24. #endif
  25. #include <cmath> /* for M_PI */
  26. #include <cstdlib> /* free() */
  27. #include <cstring> /* strdup() */
  28. #include "core.h"
  29. using namespace std;
  30. namespace lol
  31. {
  32. static inline float det2(float a, float b,
  33. float c, float d)
  34. {
  35. return a * d - b * c;
  36. }
  37. static inline float det3(float a, float b, float c,
  38. float d, float e, float f,
  39. float g, float h, float i)
  40. {
  41. return a * (e * i - h * f)
  42. + b * (f * g - i * d)
  43. + c * (d * h - g * e);
  44. }
  45. static inline float cofact(mat2 const &mat, int i, int j)
  46. {
  47. return mat[(i + 1) & 1][(j + 1) & 1] * (((i + j) & 1) ? -1.0f : 1.0f);
  48. }
  49. static inline float cofact(mat3 const &mat, int i, int j)
  50. {
  51. return det2(mat[(i + 1) % 3][(j + 1) % 3],
  52. mat[(i + 2) % 3][(j + 1) % 3],
  53. mat[(i + 1) % 3][(j + 2) % 3],
  54. mat[(i + 2) % 3][(j + 2) % 3]);
  55. }
  56. static inline float cofact(mat4 const &mat, int i, int j)
  57. {
  58. return det3(mat[(i + 1) & 3][(j + 1) & 3],
  59. mat[(i + 2) & 3][(j + 1) & 3],
  60. mat[(i + 3) & 3][(j + 1) & 3],
  61. mat[(i + 1) & 3][(j + 2) & 3],
  62. mat[(i + 2) & 3][(j + 2) & 3],
  63. mat[(i + 3) & 3][(j + 2) & 3],
  64. mat[(i + 1) & 3][(j + 3) & 3],
  65. mat[(i + 2) & 3][(j + 3) & 3],
  66. mat[(i + 3) & 3][(j + 3) & 3]) * (((i + j) & 1) ? -1.0f : 1.0f);
  67. }
  68. template<> float determinant(mat2 const &mat)
  69. {
  70. return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0];
  71. }
  72. template<> mat2 transpose(mat2 const &mat)
  73. {
  74. mat2 ret;
  75. for (int j = 0; j < 2; j++)
  76. for (int i = 0; i < 2; i++)
  77. ret[j][i] = mat[i][j];
  78. return ret;
  79. }
  80. template<> mat2 inverse(mat2 const &mat)
  81. {
  82. mat2 ret;
  83. float d = determinant(mat);
  84. if (d)
  85. {
  86. d = 1.0f / d;
  87. for (int j = 0; j < 2; j++)
  88. for (int i = 0; i < 2; i++)
  89. ret[j][i] = cofact(mat, i, j) * d;
  90. }
  91. return ret;
  92. }
  93. template<> float determinant(mat3 const &mat)
  94. {
  95. return det3(mat[0][0], mat[0][1], mat[0][2],
  96. mat[1][0], mat[1][1], mat[1][2],
  97. mat[2][0], mat[2][1], mat[2][2]);
  98. }
  99. template<> mat3 transpose(mat3 const &mat)
  100. {
  101. mat3 ret;
  102. for (int j = 0; j < 3; j++)
  103. for (int i = 0; i < 3; i++)
  104. ret[j][i] = mat[i][j];
  105. return ret;
  106. }
  107. template<> mat3 inverse(mat3 const &mat)
  108. {
  109. mat3 ret;
  110. float d = determinant(mat);
  111. if (d)
  112. {
  113. d = 1.0f / d;
  114. for (int j = 0; j < 3; j++)
  115. for (int i = 0; i < 3; i++)
  116. ret[j][i] = cofact(mat, i, j) * d;
  117. }
  118. return ret;
  119. }
  120. template<> float determinant(mat4 const &mat)
  121. {
  122. float ret = 0;
  123. for (int n = 0; n < 4; n++)
  124. ret += mat[n][0] * cofact(mat, n, 0);
  125. return ret;
  126. }
  127. template<> mat4 transpose(mat4 const &mat)
  128. {
  129. mat4 ret;
  130. for (int j = 0; j < 4; j++)
  131. for (int i = 0; i < 4; i++)
  132. ret[j][i] = mat[i][j];
  133. return ret;
  134. }
  135. template<> mat4 inverse(mat4 const &mat)
  136. {
  137. mat4 ret;
  138. float d = determinant(mat);
  139. if (d)
  140. {
  141. d = 1.0f / d;
  142. for (int j = 0; j < 4; j++)
  143. for (int i = 0; i < 4; i++)
  144. ret[j][i] = cofact(mat, i, j) * d;
  145. }
  146. return ret;
  147. }
  148. template<> void vec2::printf() const
  149. {
  150. Log::Debug("[ %6.6f %6.6f ]\n", x, y);
  151. }
  152. template<> void ivec2::printf() const
  153. {
  154. Log::Debug("[ %i %i ]\n", x, y);
  155. }
  156. template<> void cmplx::printf() const
  157. {
  158. Log::Debug("[ %6.6f %6.6f ]\n", x, y);
  159. }
  160. template<> void vec3::printf() const
  161. {
  162. Log::Debug("[ %6.6f %6.6f %6.6f ]\n", x, y, z);
  163. }
  164. template<> void ivec3::printf() const
  165. {
  166. Log::Debug("[ %i %i %i ]\n", x, y, z);
  167. }
  168. template<> void vec4::printf() const
  169. {
  170. Log::Debug("[ %6.6f %6.6f %6.6f %6.6f ]\n", x, y, z, w);
  171. }
  172. template<> void ivec4::printf() const
  173. {
  174. Log::Debug("[ %i %i %i %i ]\n", x, y, z, w);
  175. }
  176. template<> void quat::printf() const
  177. {
  178. Log::Debug("[ %6.6f %6.6f %6.6f %6.6f ]\n", w, x, y, z);
  179. }
  180. template<> void mat2::printf() const
  181. {
  182. mat2 const &p = *this;
  183. Log::Debug("[ %6.6f %6.6f\n", p[0][0], p[1][0]);
  184. Log::Debug(" %6.6f %6.6f ]\n", p[0][1], p[1][1]);
  185. }
  186. template<> void mat3::printf() const
  187. {
  188. mat3 const &p = *this;
  189. Log::Debug("[ %6.6f %6.6f %6.6f\n", p[0][0], p[1][0], p[2][0]);
  190. Log::Debug(" %6.6f %6.6f %6.6f\n", p[0][1], p[1][1], p[2][1]);
  191. Log::Debug(" %6.6f %6.6f %6.6f ]\n", p[0][2], p[1][2], p[2][2]);
  192. }
  193. template<> void mat4::printf() const
  194. {
  195. mat4 const &p = *this;
  196. Log::Debug("[ %6.6f %6.6f %6.6f %6.6f\n",
  197. p[0][0], p[1][0], p[2][0], p[3][0]);
  198. Log::Debug(" %6.6f %6.6f %6.6f %6.6f\n",
  199. p[0][1], p[1][1], p[2][1], p[3][1]);
  200. Log::Debug(" %6.6f %6.6f %6.6f %6.6f\n",
  201. p[0][2], p[1][2], p[2][2], p[3][2]);
  202. Log::Debug(" %6.6f %6.6f %6.6f %6.6f ]\n",
  203. p[0][3], p[1][3], p[2][3], p[3][3]);
  204. }
  205. #if !defined __ANDROID__
  206. template<> std::ostream &operator<<(std::ostream &stream, ivec2 const &v)
  207. {
  208. return stream << "(" << v.x << ", " << v.y << ")";
  209. }
  210. template<> std::ostream &operator<<(std::ostream &stream, icmplx const &v)
  211. {
  212. return stream << "(" << v.x << ", " << v.y << ")";
  213. }
  214. template<> std::ostream &operator<<(std::ostream &stream, ivec3 const &v)
  215. {
  216. return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
  217. }
  218. template<> std::ostream &operator<<(std::ostream &stream, ivec4 const &v)
  219. {
  220. return stream << "(" << v.x << ", " << v.y << ", "
  221. << v.z << ", " << v.w << ")";
  222. }
  223. template<> std::ostream &operator<<(std::ostream &stream, iquat const &v)
  224. {
  225. return stream << "(" << v.x << ", " << v.y << ", "
  226. << v.z << ", " << v.w << ")";
  227. }
  228. template<> std::ostream &operator<<(std::ostream &stream, vec2 const &v)
  229. {
  230. return stream << "(" << v.x << ", " << v.y << ")";
  231. }
  232. template<> std::ostream &operator<<(std::ostream &stream, cmplx const &v)
  233. {
  234. return stream << "(" << v.x << ", " << v.y << ")";
  235. }
  236. template<> std::ostream &operator<<(std::ostream &stream, vec3 const &v)
  237. {
  238. return stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
  239. }
  240. template<> std::ostream &operator<<(std::ostream &stream, vec4 const &v)
  241. {
  242. return stream << "(" << v.x << ", " << v.y << ", "
  243. << v.z << ", " << v.w << ")";
  244. }
  245. template<> std::ostream &operator<<(std::ostream &stream, quat const &v)
  246. {
  247. return stream << "(" << v.x << ", " << v.y << ", "
  248. << v.z << ", " << v.w << ")";
  249. }
  250. template<> std::ostream &operator<<(std::ostream &stream, mat4 const &m)
  251. {
  252. stream << "((" << m[0][0] << ", " << m[1][0]
  253. << ", " << m[2][0] << ", " << m[3][0] << "), ";
  254. stream << "(" << m[0][1] << ", " << m[1][1]
  255. << ", " << m[2][1] << ", " << m[3][1] << "), ";
  256. stream << "(" << m[0][2] << ", " << m[1][2]
  257. << ", " << m[2][2] << ", " << m[3][2] << "), ";
  258. stream << "(" << m[0][3] << ", " << m[1][3]
  259. << ", " << m[2][3] << ", " << m[3][3] << "))";
  260. return stream;
  261. }
  262. #endif
  263. template<> mat3 mat3::scale(float x, float y, float z)
  264. {
  265. mat3 ret(1.0f);
  266. ret[0][0] = x;
  267. ret[1][1] = y;
  268. ret[2][2] = z;
  269. return ret;
  270. }
  271. template<> mat3 mat3::scale(vec3 v)
  272. {
  273. return scale(v.x, v.y, v.z);
  274. }
  275. template<> mat4 mat4::translate(float x, float y, float z)
  276. {
  277. mat4 ret(1.0f);
  278. ret[3][0] = x;
  279. ret[3][1] = y;
  280. ret[3][2] = z;
  281. return ret;
  282. }
  283. template<> mat4 mat4::translate(vec3 v)
  284. {
  285. return translate(v.x, v.y, v.z);
  286. }
  287. template<> mat2 mat2::rotate(float angle)
  288. {
  289. angle *= (M_PI / 180.0f);
  290. float st = std::sin(angle);
  291. float ct = std::cos(angle);
  292. mat2 ret;
  293. ret[0][0] = ct;
  294. ret[0][1] = st;
  295. ret[1][0] = -st;
  296. ret[1][1] = ct;
  297. return ret;
  298. }
  299. template<> mat3 mat3::rotate(float angle, float x, float y, float z)
  300. {
  301. angle *= (M_PI / 180.0f);
  302. float st = std::sin(angle);
  303. float ct = std::cos(angle);
  304. float len = std::sqrt(x * x + y * y + z * z);
  305. float invlen = len ? 1.0f / len : 0.0f;
  306. x *= invlen;
  307. y *= invlen;
  308. z *= invlen;
  309. float mtx = (1.0f - ct) * x;
  310. float mty = (1.0f - ct) * y;
  311. float mtz = (1.0f - ct) * z;
  312. mat3 ret;
  313. ret[0][0] = x * mtx + ct;
  314. ret[0][1] = x * mty + st * z;
  315. ret[0][2] = x * mtz - st * y;
  316. ret[1][0] = y * mtx - st * z;
  317. ret[1][1] = y * mty + ct;
  318. ret[1][2] = y * mtz + st * x;
  319. ret[2][0] = z * mtx + st * y;
  320. ret[2][1] = z * mty - st * x;
  321. ret[2][2] = z * mtz + ct;
  322. return ret;
  323. }
  324. template<> mat3 mat3::rotate(float angle, vec3 v)
  325. {
  326. return rotate(angle, v.x, v.y, v.z);
  327. }
  328. template<> mat3::Mat3(quat const &q)
  329. {
  330. float n = norm(q);
  331. if (!n)
  332. {
  333. for (int j = 0; j < 3; j++)
  334. for (int i = 0; i < 3; i++)
  335. (*this)[i][j] = (i == j) ? 1.f : 0.f;
  336. return;
  337. }
  338. float s = 2.0f / n;
  339. v0[0] = 1.0f - s * (q.y * q.y + q.z * q.z);
  340. v0[1] = s * (q.x * q.y + q.z * q.w);
  341. v0[2] = s * (q.x * q.z - q.y * q.w);
  342. v1[0] = s * (q.x * q.y - q.z * q.w);
  343. v1[1] = 1.0f - s * (q.z * q.z + q.x * q.x);
  344. v1[2] = s * (q.y * q.z + q.x * q.w);
  345. v2[0] = s * (q.x * q.z + q.y * q.w);
  346. v2[1] = s * (q.y * q.z - q.x * q.w);
  347. v2[2] = 1.0f - s * (q.x * q.x + q.y * q.y);
  348. }
  349. template<> mat4::Mat4(quat const &q)
  350. {
  351. *this = mat4(mat3(q), 1.f);
  352. }
  353. static inline void MatrixToQuat(quat &that, mat3 const &m)
  354. {
  355. /* See http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/christian.htm for a version with no branches */
  356. float t = m[0][0] + m[1][1] + m[2][2];
  357. if (t > 0)
  358. {
  359. that.w = 0.5f * std::sqrt(1.0f + t);
  360. float s = 0.25f / that.w;
  361. that.x = s * (m[1][2] - m[2][1]);
  362. that.y = s * (m[2][0] - m[0][2]);
  363. that.z = s * (m[0][1] - m[1][0]);
  364. }
  365. else if (m[0][0] > m[1][1] && m[0][0] > m[2][2])
  366. {
  367. that.x = 0.5f * std::sqrt(1.0f + m[0][0] - m[1][1] - m[2][2]);
  368. float s = 0.25f / that.x;
  369. that.y = s * (m[0][1] + m[1][0]);
  370. that.z = s * (m[2][0] + m[0][2]);
  371. that.w = s * (m[1][2] - m[2][1]);
  372. }
  373. else if (m[1][1] > m[2][2])
  374. {
  375. that.y = 0.5f * std::sqrt(1.0f - m[0][0] + m[1][1] - m[2][2]);
  376. float s = 0.25f / that.y;
  377. that.x = s * (m[0][1] + m[1][0]);
  378. that.z = s * (m[1][2] + m[2][1]);
  379. that.w = s * (m[2][0] - m[0][2]);
  380. }
  381. else
  382. {
  383. that.z = 0.5f * std::sqrt(1.0f - m[0][0] - m[1][1] + m[2][2]);
  384. float s = 0.25f / that.z;
  385. that.x = s * (m[2][0] + m[0][2]);
  386. that.y = s * (m[1][2] + m[2][1]);
  387. that.w = s * (m[0][1] - m[1][0]);
  388. }
  389. }
  390. template<> quat::Quat(mat3 const &m)
  391. {
  392. MatrixToQuat(*this, m);
  393. }
  394. template<> quat::Quat(mat4 const &m)
  395. {
  396. MatrixToQuat(*this, mat3(m));
  397. }
  398. template<> quat quat::rotate(float angle, vec3 const &v)
  399. {
  400. angle *= (M_PI / 360.0f);
  401. vec3 tmp = normalize(v) * std::sin(angle);
  402. return quat(std::cos(angle), tmp.x, tmp.y, tmp.z);
  403. }
  404. template<> quat quat::rotate(float angle, float x, float y, float z)
  405. {
  406. return quat::rotate(angle, vec3(x, y, z));
  407. }
  408. template<> vec3 vec3::toeuler(quat const &q)
  409. {
  410. using std::atan2;
  411. using std::asin;
  412. float n = norm(q);
  413. if (!n)
  414. return vec3(0.f);
  415. vec3 ret(atan2(2.f * (q.w * q.x + q.y * q.z),
  416. 1.f - 2.f * (q.x * q.x + q.y * q.y)),
  417. asin(2.f * (q.w * q.y - q.z * q.x)),
  418. atan2(2.f * (q.w * q.z + q.y * q.x),
  419. 1.f - 2.f * (q.z * q.z + q.y * q.y)));
  420. return (180.0f / M_PI / n) * ret;
  421. }
  422. template<> mat3 mat3::fromeuler(vec3 const &v)
  423. {
  424. using std::sin;
  425. using std::cos;
  426. mat3 ret;
  427. vec3 radians = (M_PI / 180.0f) * v;
  428. float sx = sin(radians.x), cx = cos(radians.x);
  429. float sy = sin(radians.y), cy = cos(radians.y);
  430. float sz = sin(radians.z), cz = cos(radians.z);
  431. ret[0][0] = cy * cz;
  432. ret[1][0] = - cx * sz + sx * sy * cz;
  433. ret[2][0] = sx * sz + cx * sy * cz;
  434. ret[0][1] = cy * sz;
  435. ret[1][1] = cx * cz + sx * sy * sz;
  436. ret[2][1] = - sx * cz + cx * sy * sz;
  437. ret[0][2] = - sy;
  438. ret[1][2] = sx * cy;
  439. ret[2][2] = cx * cy;
  440. return ret;
  441. }
  442. template<> mat3 mat3::fromeuler(float x, float y, float z)
  443. {
  444. return mat3::fromeuler(vec3(x, y, z));
  445. }
  446. template<> quat quat::fromeuler(vec3 const &v)
  447. {
  448. using std::sin;
  449. using std::cos;
  450. vec3 half_angles = (M_PI / 360.0f) * v;
  451. float sx = sin(half_angles.x), cx = cos(half_angles.x);
  452. float sy = sin(half_angles.y), cy = cos(half_angles.y);
  453. float sz = sin(half_angles.z), cz = cos(half_angles.z);
  454. return quat(cx * cy * cz + sx * sy * sz,
  455. sx * cy * cz - cx * sy * sz,
  456. cx * sy * cz + sx * cy * sz,
  457. cx * cy * sz - sx * sy * cz);
  458. }
  459. template<> quat quat::fromeuler(float x, float y, float z)
  460. {
  461. return quat::fromeuler(vec3(x, y, z));
  462. }
  463. template<> mat4 mat4::lookat(vec3 eye, vec3 center, vec3 up)
  464. {
  465. vec3 v3 = normalize(eye - center);
  466. vec3 v2 = normalize(up);
  467. vec3 v1 = normalize(cross(v2, v3));
  468. v2 = cross(v3, v1);
  469. mat4 orient(1.0f);
  470. orient[0][0] = v1.x;
  471. orient[0][1] = v2.x;
  472. orient[0][2] = v3.x;
  473. orient[1][0] = v1.y;
  474. orient[1][1] = v2.y;
  475. orient[1][2] = v3.y;
  476. orient[2][0] = v1.z;
  477. orient[2][1] = v2.z;
  478. orient[2][2] = v3.z;
  479. return orient * mat4::translate(-eye);
  480. }
  481. template<> mat4 mat4::ortho(float left, float right, float bottom,
  482. float top, float near, float far)
  483. {
  484. float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
  485. float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
  486. float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
  487. mat4 ret(0.0f);
  488. ret[0][0] = 2.0f * invrl;
  489. ret[1][1] = 2.0f * invtb;
  490. ret[2][2] = -2.0f * invfn;
  491. ret[3][0] = - (right + left) * invrl;
  492. ret[3][1] = - (top + bottom) * invtb;
  493. ret[3][2] = - (far + near) * invfn;
  494. ret[3][3] = 1.0f;
  495. return ret;
  496. }
  497. template<> mat4 mat4::frustum(float left, float right, float bottom,
  498. float top, float near, float far)
  499. {
  500. float invrl = (right != left) ? 1.0f / (right - left) : 0.0f;
  501. float invtb = (top != bottom) ? 1.0f / (top - bottom) : 0.0f;
  502. float invfn = (far != near) ? 1.0f / (far - near) : 0.0f;
  503. mat4 ret(0.0f);
  504. ret[0][0] = 2.0f * near * invrl;
  505. ret[1][1] = 2.0f * near * invtb;
  506. ret[2][0] = (right + left) * invrl;
  507. ret[2][1] = (top + bottom) * invtb;
  508. ret[2][2] = - (far + near) * invfn;
  509. ret[2][3] = -1.0f;
  510. ret[3][2] = -2.0f * far * near * invfn;
  511. return ret;
  512. }
  513. template<> mat4 mat4::perspective(float fov_y, float width,
  514. float height, float near, float far)
  515. {
  516. fov_y *= (M_PI / 180.0f);
  517. float t2 = tanf(fov_y * 0.5f);
  518. float t1 = t2 * width / height;
  519. return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far);
  520. }
  521. } /* namespace lol */