fpumath.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * Copyright 2011-2013 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. // FPU math lib
  6. #ifndef FPU_MATH_H_HEADER_GUARD
  7. #define FPU_MATH_H_HEADER_GUARD
  8. #define _USE_MATH_DEFINES
  9. #include <math.h>
  10. #include <string.h>
  11. #if BX_COMPILER_MSVC
  12. inline float fminf(float _a, float _b)
  13. {
  14. return _a < _b ? _a : _b;
  15. }
  16. inline float fmaxf(float _a, float _b)
  17. {
  18. return _a > _b ? _a : _b;
  19. }
  20. #endif // BX_COMPILER_MSVC
  21. inline float fclamp(float _a, float _min, float _max)
  22. {
  23. return fminf(fmaxf(_a, _min), _max);
  24. }
  25. inline float fsaturate(float _a)
  26. {
  27. return fclamp(_a, 0.0f, 1.0f);
  28. }
  29. inline float flerp(float _a, float _b, float _t)
  30. {
  31. return _a + (_b - _a) * _t;
  32. }
  33. inline float fsign(float _a)
  34. {
  35. return _a < 0.0f ? -1.0f : 1.0f;
  36. }
  37. inline void vec3Move(float* __restrict _result, const float* __restrict _a)
  38. {
  39. _result[0] = _a[0];
  40. _result[1] = _a[1];
  41. _result[2] = _a[2];
  42. }
  43. inline void vec3Abs(float* __restrict _result, const float* __restrict _a)
  44. {
  45. _result[0] = fabsf(_a[0]);
  46. _result[1] = fabsf(_a[1]);
  47. _result[2] = fabsf(_a[2]);
  48. }
  49. inline void vec3Neg(float* __restrict _result, const float* __restrict _a)
  50. {
  51. _result[0] = -_a[0];
  52. _result[1] = -_a[1];
  53. _result[2] = -_a[2];
  54. }
  55. inline void vec3Add(float* __restrict _result, const float* __restrict _a, const float* __restrict _b)
  56. {
  57. _result[0] = _a[0] + _b[0];
  58. _result[1] = _a[1] + _b[1];
  59. _result[2] = _a[2] + _b[2];
  60. }
  61. inline void vec3Sub(float* __restrict _result, const float* __restrict _a, const float* __restrict _b)
  62. {
  63. _result[0] = _a[0] - _b[0];
  64. _result[1] = _a[1] - _b[1];
  65. _result[2] = _a[2] - _b[2];
  66. }
  67. inline void vec3Mul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b)
  68. {
  69. _result[0] = _a[0] * _b[0];
  70. _result[1] = _a[1] * _b[1];
  71. _result[2] = _a[2] * _b[2];
  72. }
  73. inline void vec3Mul(float* __restrict _result, const float* __restrict _a, float _b)
  74. {
  75. _result[0] = _a[0] * _b;
  76. _result[1] = _a[1] * _b;
  77. _result[2] = _a[2] * _b;
  78. }
  79. inline float vec3Dot(const float* __restrict _a, const float* __restrict _b)
  80. {
  81. return _a[0]*_b[0] + _a[1]*_b[1] + _a[2]*_b[2];
  82. }
  83. inline void vec3Cross(float* __restrict _result, const float* __restrict _a, const float* __restrict _b)
  84. {
  85. _result[0] = _a[1]*_b[2] - _a[2]*_b[1];
  86. _result[1] = _a[2]*_b[0] - _a[0]*_b[2];
  87. _result[2] = _a[0]*_b[1] - _a[1]*_b[0];
  88. }
  89. inline float vec3Length(const float* _a)
  90. {
  91. return sqrtf(vec3Dot(_a, _a) );
  92. }
  93. inline float vec3Norm(float* __restrict _result, const float* __restrict _a)
  94. {
  95. const float len = vec3Length(_a);
  96. const float invLen = 1.0f/len;
  97. _result[0] = _a[0] * invLen;
  98. _result[1] = _a[1] * invLen;
  99. _result[2] = _a[2] * invLen;
  100. return len;
  101. }
  102. inline void mtxIdentity(float* _result)
  103. {
  104. memset(_result, 0, sizeof(float)*16);
  105. _result[0] = _result[5] = _result[10] = _result[15] = 1.0f;
  106. }
  107. inline void mtxTranslate(float* _result, float _x, float _y, float _z)
  108. {
  109. mtxIdentity(_result);
  110. _result[12] = _x;
  111. _result[13] = _y;
  112. _result[14] = _z;
  113. }
  114. inline void mtxScale(float* _result, float _x, float _y, float _z)
  115. {
  116. memset(_result, 0, sizeof(float) * 16);
  117. _result[0] = _x;
  118. _result[5] = _y;
  119. _result[10] = _z;
  120. _result[15] = 1.0f;
  121. }
  122. inline void mtxLookAt(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at)
  123. {
  124. float tmp[4];
  125. vec3Sub(tmp, _at, _eye);
  126. float view[4];
  127. vec3Norm(view, tmp);
  128. float up[3] = { 0.0f, 1.0f, 0.0f };
  129. vec3Cross(tmp, up, view);
  130. float right[4];
  131. vec3Norm(right, tmp);
  132. vec3Cross(up, view, right);
  133. memset(_result, 0, sizeof(float)*16);
  134. _result[ 0] = right[0];
  135. _result[ 1] = up[0];
  136. _result[ 2] = view[0];
  137. _result[ 4] = right[1];
  138. _result[ 5] = up[1];
  139. _result[ 6] = view[1];
  140. _result[ 8] = right[2];
  141. _result[ 9] = up[2];
  142. _result[10] = view[2];
  143. _result[12] = -vec3Dot(right, _eye);
  144. _result[13] = -vec3Dot(up, _eye);
  145. _result[14] = -vec3Dot(view, _eye);
  146. _result[15] = 1.0f;
  147. }
  148. inline void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far)
  149. {
  150. float height = 1.0f/tanf(_fovy*( (float)M_PI/180.0f)*0.5f);
  151. float width = height * 1.0f/_aspect;
  152. float aa = _far/(_far-_near);
  153. float bb = -_near * aa;
  154. memset(_result, 0, sizeof(float)*16);
  155. _result[0] = width;
  156. _result[5] = height;
  157. _result[10] = aa;
  158. _result[11] = 1.0f;
  159. _result[14] = bb;
  160. }
  161. inline void mtxOrtho(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far)
  162. {
  163. const float aa = 2.0f/(_right - _left);
  164. const float bb = 2.0f/(_top - _bottom);
  165. const float cc = 1.0f/(_far - _near);
  166. const float dd = (_left + _right)/(_left - _right);
  167. const float ee = (_top + _bottom)/(_bottom - _top);
  168. const float ff = _near / (_near - _far);
  169. memset(_result, 0, sizeof(float)*16);
  170. _result[0] = aa;
  171. _result[5] = bb;
  172. _result[10] = cc;
  173. _result[12] = dd;
  174. _result[13] = ee;
  175. _result[14] = ff;
  176. _result[15] = 1.0f;
  177. }
  178. inline void mtxRotateX(float* _result, float _ax)
  179. {
  180. float sx = sinf(_ax);
  181. float cx = cosf(_ax);
  182. memset(_result, 0, sizeof(float)*16);
  183. _result[ 0] = 1.0f;
  184. _result[ 5] = cx;
  185. _result[ 6] = -sx;
  186. _result[ 9] = sx;
  187. _result[10] = cx;
  188. _result[15] = 1.0f;
  189. }
  190. inline void mtxRotateY(float* _result, float _ay)
  191. {
  192. float sy = sinf(_ay);
  193. float cy = cosf(_ay);
  194. memset(_result, 0, sizeof(float)*16);
  195. _result[ 0] = cy;
  196. _result[ 2] = sy;
  197. _result[ 5] = 1.0f;
  198. _result[ 8] = -sy;
  199. _result[10] = cy;
  200. _result[15] = 1.0f;
  201. }
  202. inline void mtxRotateZ(float* _result, float _az)
  203. {
  204. float sz = sinf(_az);
  205. float cz = cosf(_az);
  206. memset(_result, 0, sizeof(float)*16);
  207. _result[ 0] = cz;
  208. _result[ 1] = -sz;
  209. _result[ 4] = sz;
  210. _result[ 5] = cz;
  211. _result[10] = 1.0f;
  212. _result[15] = 1.0f;
  213. }
  214. inline void mtxRotateXY(float* _result, float _ax, float _ay)
  215. {
  216. float sx = sinf(_ax);
  217. float cx = cosf(_ax);
  218. float sy = sinf(_ay);
  219. float cy = cosf(_ay);
  220. memset(_result, 0, sizeof(float)*16);
  221. _result[ 0] = cy;
  222. _result[ 2] = -sy;
  223. _result[ 4] = -sx*sy;
  224. _result[ 5] = cx;
  225. _result[ 6] = -sx*cy;
  226. _result[ 8] = cx*sy;
  227. _result[ 9] = sx;
  228. _result[10] = cx*cy;
  229. _result[15] = 1.0f;
  230. }
  231. inline void mtxRotateXYZ(float* _result, float _ax, float _ay, float _az)
  232. {
  233. float sx = sinf(_ax);
  234. float cx = cosf(_ax);
  235. float sy = sinf(_ay);
  236. float cy = cosf(_ay);
  237. float sz = sinf(_az);
  238. float cz = cosf(_az);
  239. memset(_result, 0, sizeof(float)*16);
  240. _result[ 0] = cy*cz;
  241. _result[ 1] = -cy*sz;
  242. _result[ 2] = sy;
  243. _result[ 4] = cz*sx*sy + cx*sz;
  244. _result[ 5] = cx*cz - sx*sy*sz;
  245. _result[ 6] = -cy*sx;
  246. _result[ 8] = -cx*cz*sy + sx*sz;
  247. _result[ 9] = cz*sx + cx*sy*sz;
  248. _result[10] = cx*cy;
  249. _result[15] = 1.0f;
  250. }
  251. inline void mtxRotateZYX(float* _result, float _ax, float _ay, float _az)
  252. {
  253. float sx = sinf(_ax);
  254. float cx = cosf(_ax);
  255. float sy = sinf(_ay);
  256. float cy = cosf(_ay);
  257. float sz = sinf(_az);
  258. float cz = cosf(_az);
  259. memset(_result, 0, sizeof(float)*16);
  260. _result[ 0] = cy*cz;
  261. _result[ 1] = cz*sx*sy-cx*sz;
  262. _result[ 2] = cx*cz*sy+sx*sz;
  263. _result[ 4] = cy*sz;
  264. _result[ 5] = cx*cz + sx*sy*sz;
  265. _result[ 6] = -cz*sx + cx*sy*sz;
  266. _result[ 8] = -sy;
  267. _result[ 9] = cy*sx;
  268. _result[10] = cx*cy;
  269. _result[15] = 1.0f;
  270. };
  271. inline void vec3MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat)
  272. {
  273. _result[0] = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _mat[12];
  274. _result[1] = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _mat[13];
  275. _result[2] = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _mat[14];
  276. }
  277. inline void vec3MulMtxH(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat)
  278. {
  279. float xx = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _mat[12];
  280. float yy = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _mat[13];
  281. float zz = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _mat[14];
  282. float ww = _vec[0] * _mat[ 3] + _vec[1] * _mat[7] + _vec[2] * _mat[11] + _mat[15];
  283. float invW = fsign(ww)/ww;
  284. _result[0] = xx*invW;
  285. _result[1] = yy*invW;
  286. _result[2] = zz*invW;
  287. }
  288. inline void vec4MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat)
  289. {
  290. _result[0] = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _vec[3] * _mat[12];
  291. _result[1] = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _vec[3] * _mat[13];
  292. _result[2] = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _vec[3] * _mat[14];
  293. _result[3] = _vec[0] * _mat[ 3] + _vec[1] * _mat[7] + _vec[2] * _mat[11] + _vec[3] * _mat[15];
  294. }
  295. inline void mtxMul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b)
  296. {
  297. vec4MulMtx(&_result[ 0], &_a[ 0], _b);
  298. vec4MulMtx(&_result[ 4], &_a[ 4], _b);
  299. vec4MulMtx(&_result[ 8], &_a[ 8], _b);
  300. vec4MulMtx(&_result[12], &_a[12], _b);
  301. }
  302. inline void mtxTranspose(float* __restrict _result, const float* __restrict _a)
  303. {
  304. _result[ 0] = _a[ 0];
  305. _result[ 4] = _a[ 1];
  306. _result[ 8] = _a[ 2];
  307. _result[12] = _a[ 3];
  308. _result[ 1] = _a[ 4];
  309. _result[ 5] = _a[ 5];
  310. _result[ 9] = _a[ 6];
  311. _result[13] = _a[ 7];
  312. _result[ 2] = _a[ 8];
  313. _result[ 6] = _a[ 9];
  314. _result[10] = _a[10];
  315. _result[14] = _a[11];
  316. _result[ 3] = _a[12];
  317. _result[ 7] = _a[13];
  318. _result[11] = _a[14];
  319. _result[15] = _a[15];
  320. }
  321. inline void mtx3Inverse(float* __restrict _result, const float* __restrict _a)
  322. {
  323. float xx = _a[0];
  324. float xy = _a[1];
  325. float xz = _a[2];
  326. float yx = _a[3];
  327. float yy = _a[4];
  328. float yz = _a[5];
  329. float zx = _a[6];
  330. float zy = _a[7];
  331. float zz = _a[8];
  332. float det = 0.0f;
  333. det += xx * (yy*zz - yz*zy);
  334. det -= xy * (yx*zz - yz*zx);
  335. det += xz * (yx*zy - yy*zx);
  336. float invDet = 1.0f/det;
  337. _result[0] = +(yy*zz - yz*zy) * invDet;
  338. _result[1] = -(xy*zz - xz*zy) * invDet;
  339. _result[2] = +(xy*yz - xz*yy) * invDet;
  340. _result[3] = -(yx*zz - yz*zx) * invDet;
  341. _result[4] = +(xx*zz - xz*zx) * invDet;
  342. _result[5] = -(xx*yz - xz*yx) * invDet;
  343. _result[6] = +(yx*zy - yy*zx) * invDet;
  344. _result[7] = -(xx*zy - xy*zx) * invDet;
  345. _result[8] = +(xx*yy - xy*yx) * invDet;
  346. }
  347. inline void mtxInverse(float* __restrict _result, const float* __restrict _a)
  348. {
  349. float xx = _a[ 0];
  350. float xy = _a[ 1];
  351. float xz = _a[ 2];
  352. float xw = _a[ 3];
  353. float yx = _a[ 4];
  354. float yy = _a[ 5];
  355. float yz = _a[ 6];
  356. float yw = _a[ 7];
  357. float zx = _a[ 8];
  358. float zy = _a[ 9];
  359. float zz = _a[10];
  360. float zw = _a[11];
  361. float wx = _a[12];
  362. float wy = _a[13];
  363. float wz = _a[14];
  364. float ww = _a[15];
  365. float det = 0.0f;
  366. det += xx * (yy*(zz*ww - zw*wz) - yz*(zy*ww - zw*wy) + yw*(zy*wz - zz*wy) );
  367. det -= xy * (yx*(zz*ww - zw*wz) - yz*(zx*ww - zw*wx) + yw*(zx*wz - zz*wx) );
  368. det += xz * (yx*(zy*ww - zw*wy) - yy*(zx*ww - zw*wx) + yw*(zx*wy - zy*wx) );
  369. det -= xw * (yx*(zy*wz - zz*wy) - yy*(zx*wz - zz*wx) + yz*(zx*wy - zy*wx) );
  370. float invDet = 1.0f/det;
  371. _result[ 0] = +(yy*(zz*ww - wz*zw) - yz*(zy*ww - wy*zw) + yw*(zy*wz - wy*zz) ) * invDet;
  372. _result[ 1] = -(xy*(zz*ww - wz*zw) - xz*(zy*ww - wy*zw) + xw*(zy*wz - wy*zz) ) * invDet;
  373. _result[ 2] = +(xy*(yz*ww - wz*yw) - xz*(yy*ww - wy*yw) + xw*(yy*wz - wy*yz) ) * invDet;
  374. _result[ 3] = -(xy*(yz*zw - zz*yw) - xz*(yy*zw - zy*yw) + xw*(yy*zz - zy*yz) ) * invDet;
  375. _result[ 4] = -(yx*(zz*ww - wz*zw) - yz*(zx*ww - wx*zw) + yw*(zx*wz - wx*zz) ) * invDet;
  376. _result[ 5] = +(xx*(zz*ww - wz*zw) - xz*(zx*ww - wx*zw) + xw*(zx*wz - wx*zz) ) * invDet;
  377. _result[ 6] = -(xx*(yz*ww - wz*yw) - xz*(yx*ww - wx*yw) + xw*(yx*wz - wx*yz) ) * invDet;
  378. _result[ 7] = +(xx*(yz*zw - zz*yw) - xz*(yx*zw - zx*yw) + xw*(yx*zz - zx*yz) ) * invDet;
  379. _result[ 8] = +(yx*(zy*ww - wy*zw) - yy*(zx*ww - wx*zw) + yw*(zx*wy - wx*zy) ) * invDet;
  380. _result[ 9] = -(xx*(zy*ww - wy*zw) - xy*(zx*ww - wx*zw) + xw*(zx*wy - wx*zy) ) * invDet;
  381. _result[10] = +(xx*(yy*ww - wy*yw) - xy*(yx*ww - wx*yw) + xw*(yx*wy - wx*yy) ) * invDet;
  382. _result[11] = -(xx*(yy*zw - zy*yw) - xy*(yx*zw - zx*yw) + xw*(yx*zy - zx*yy) ) * invDet;
  383. _result[12] = -(yx*(zy*wz - wy*zz) - yy*(zx*wz - wx*zz) + yz*(zx*wy - wx*zy) ) * invDet;
  384. _result[13] = +(xx*(zy*wz - wy*zz) - xy*(zx*wz - wx*zz) + xz*(zx*wy - wx*zy) ) * invDet;
  385. _result[14] = -(xx*(yy*wz - wy*yz) - xy*(yx*wz - wx*yz) + xz*(yx*wy - wx*yy) ) * invDet;
  386. _result[15] = +(xx*(yy*zz - zy*yz) - xy*(yx*zz - zx*yz) + xz*(yx*zy - zx*yy) ) * invDet;
  387. }
  388. /// Convert LH to RH projection matrix and vice versa.
  389. inline void mtxProjFlipHandedness(float* __restrict _dst, const float* __restrict _src)
  390. {
  391. _dst[ 0] = -_src[ 0];
  392. _dst[ 1] = -_src[ 1];
  393. _dst[ 2] = -_src[ 2];
  394. _dst[ 3] = -_src[ 3];
  395. _dst[ 4] = _src[ 4];
  396. _dst[ 5] = _src[ 5];
  397. _dst[ 6] = _src[ 6];
  398. _dst[ 7] = _src[ 7];
  399. _dst[ 8] = -_src[ 8];
  400. _dst[ 9] = -_src[ 9];
  401. _dst[10] = -_src[10];
  402. _dst[11] = -_src[11];
  403. _dst[12] = _src[12];
  404. _dst[13] = _src[13];
  405. _dst[14] = _src[14];
  406. _dst[15] = _src[15];
  407. }
  408. /// Convert LH to RH view matrix and vice versa.
  409. inline void mtxViewFlipHandedness(float* __restrict _dst, const float* __restrict _src)
  410. {
  411. _dst[ 0] = -_src[ 0];
  412. _dst[ 1] = _src[ 1];
  413. _dst[ 2] = -_src[ 2];
  414. _dst[ 3] = _src[ 3];
  415. _dst[ 4] = -_src[ 4];
  416. _dst[ 5] = _src[ 5];
  417. _dst[ 6] = -_src[ 6];
  418. _dst[ 7] = _src[ 7];
  419. _dst[ 8] = -_src[ 8];
  420. _dst[ 9] = _src[ 9];
  421. _dst[10] = -_src[10];
  422. _dst[11] = _src[11];
  423. _dst[12] = -_src[12];
  424. _dst[13] = _src[13];
  425. _dst[14] = -_src[14];
  426. _dst[15] = _src[15];
  427. }
  428. inline void calcNormal(float _result[3], float _va[3], float _vb[3], float _vc[3])
  429. {
  430. float ba[3];
  431. vec3Sub(ba, _vb, _va);
  432. float ca[3];
  433. vec3Sub(ca, _vc, _va);
  434. float baxca[3];
  435. vec3Cross(baxca, ba, ca);
  436. vec3Norm(_result, baxca);
  437. }
  438. inline void calcPlane(float _result[4], float _va[3], float _vb[3], float _vc[3])
  439. {
  440. float normal[3];
  441. calcNormal(normal, _va, _vb, _vc);
  442. _result[0] = normal[0];
  443. _result[1] = normal[1];
  444. _result[2] = normal[2];
  445. _result[3] = -vec3Dot(normal, _va);
  446. }
  447. #endif // FPU_MATH_H_HEADER_GUARD