fpumath.h 12 KB

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