fpumath.h 14 KB

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