gs_math.h 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. #ifndef __GS_MATH_H__
  2. #define __GS_MATH_H__
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #include <math.h>
  7. #include "common/gs_types.h"
  8. // Defines
  9. #define gs_pi 3.1415926535897932
  10. #define gs_tau 2.0 * gs_pi
  11. // Useful Utility
  12. #define gs_v2(...) (gs_vec2){ __VA_ARGS__ }
  13. #define gs_v3(...) (gs_vec3){ __VA_ARGS__ }
  14. #define gs_v4(...) (gs_vec4){ __VA_ARGS__ }
  15. /*================================================================================
  16. // Useful Common Functions
  17. ================================================================================*/
  18. #define gs_rad_to_deg( rad )\
  19. ( f32 )( ( rad * 180.0 ) / gs_pi )
  20. #define gs_deg_to_rad( deg )\
  21. ( f32 )( ( deg * gs_pi ) / 180.0 )
  22. // Interpolation
  23. // Source: https://codeplea.com/simple-interpolation
  24. _inline f32
  25. gs_interp_linear( f32 a, f32 b, f32 t )
  26. {
  27. return ( a + t * ( b - a ) );
  28. }
  29. _inline f32
  30. gs_interp_smooth_step( f32 a, f32 b, f32 t )
  31. {
  32. return gs_interp_linear( a, b, t * t * ( 3.0 - 2.0 * t ) );
  33. }
  34. _inline f32
  35. gs_interp_cosine( f32 a, f32 b, f32 t )
  36. {
  37. return gs_interp_linear( a, b, -cos( gs_pi * t ) * 0.5 + 0.5 );
  38. }
  39. _inline f32
  40. gs_interp_acceleration( f32 a, f32 b, f32 t )
  41. {
  42. return gs_interp_linear( a, b, t * t );
  43. }
  44. _inline f32
  45. gs_interp_deceleration( f32 a, f32 b, f32 t )
  46. {
  47. return gs_interp_linear( a, b, 1.0 - ( 1.0 - t ) * ( 1.0 - t ) );
  48. }
  49. _inline f32
  50. gs_round( f32 val )
  51. {
  52. return floor( val + 0.5f );
  53. }
  54. _inline f32
  55. gs_map_range( f32 input_start, f32 input_end, f32 output_start, f32 output_end, f32 val )
  56. {
  57. f32 slope = ( output_end - output_start ) / ( input_end - input_start );
  58. return ( output_start + ( slope * ( val - input_start ) ) );
  59. }
  60. /*================================================================================
  61. // Vec2
  62. ================================================================================*/
  63. typedef struct
  64. {
  65. f32 x;
  66. f32 y;
  67. } gs_vec2;
  68. _inline gs_vec2
  69. gs_vec2_ctor( f32 _x, f32 _y )
  70. {
  71. gs_vec2 v;
  72. v.x = _x;
  73. v.y = _y;
  74. return v;
  75. }
  76. _inline gs_vec2
  77. gs_vec2_add( gs_vec2 v0, gs_vec2 v1 )
  78. {
  79. return gs_vec2_ctor( v0.x + v1.x, v0.y + v1.y );
  80. }
  81. _inline gs_vec2
  82. gs_vec2_sub( gs_vec2 v0, gs_vec2 v1 )
  83. {
  84. return gs_vec2_ctor( v0.x - v1.x, v0.y - v1.y );
  85. }
  86. _inline gs_vec2
  87. gs_vec2_mul( gs_vec2 v0, gs_vec2 v1 )
  88. {
  89. return gs_vec2_ctor( v0.x * v1.x, v0.y * v1.y );
  90. }
  91. _inline gs_vec2
  92. gs_vec2_div( gs_vec2 v0, gs_vec2 v1 )
  93. {
  94. return gs_vec2_ctor( v0.x / v1.x, v0.y / v1.y );
  95. }
  96. _inline gs_vec2
  97. gs_vec2_scale( gs_vec2 v, f32 s )
  98. {
  99. return gs_vec2_ctor( v.x * s, v.y * s );
  100. }
  101. _inline f32
  102. gs_vec2_dot( gs_vec2 v0, gs_vec2 v1 )
  103. {
  104. return ( f32 )( v0.x * v1.x + v0.y * v1.y );
  105. }
  106. _inline f32
  107. gs_vec2_len( gs_vec2 v )
  108. {
  109. return ( f32 )sqrt( gs_vec2_dot( v, v ) );
  110. }
  111. _inline gs_vec2
  112. gs_vec2_project_onto( gs_vec2 v0, gs_vec2 v1 )
  113. {
  114. f32 dot = gs_vec2_dot( v0, v1 );
  115. f32 len = gs_vec2_dot( v1, v1 );
  116. // Orthogonal, so return v1
  117. if ( len == 0.f ) return v1;
  118. return gs_vec2_scale( v1, dot / len );
  119. }
  120. _inline gs_vec2 gs_vec2_norm( gs_vec2 v )
  121. {
  122. return gs_vec2_scale( v, 1.0f / gs_vec2_len( v ) );
  123. }
  124. _inline
  125. f32 gs_vec2_dist( gs_vec2 a, gs_vec2 b )
  126. {
  127. f32 dx = (a.x - b.x);
  128. f32 dy = (a.y - b.y);
  129. return ( sqrt(dx * dx + dy * dy) );
  130. }
  131. _inline
  132. f32 gs_vec2_cross( gs_vec2 a, gs_vec2 b )
  133. {
  134. return a.x * b.y - a.y * b.x;
  135. }
  136. _inline
  137. f32 gs_vec2_angle( gs_vec2 a, gs_vec2 b )
  138. {
  139. return acos( gs_vec2_dot(a, b) / ( gs_vec2_len(a) * gs_vec2_len(b) ) );
  140. }
  141. _inline
  142. b32 gs_vec2_equal( gs_vec2 a, gs_vec2 b )
  143. {
  144. return (a.x == b.x && a.y == b.y);
  145. }
  146. /*================================================================================
  147. // Vec3
  148. ================================================================================*/
  149. typedef struct
  150. {
  151. f32 x;
  152. f32 y;
  153. f32 z;
  154. } gs_vec3;
  155. _inline gs_vec3
  156. gs_vec3_ctor( f32 _x, f32 _y, f32 _z )
  157. {
  158. gs_vec3 v;
  159. v.x = _x;
  160. v.y = _y;
  161. v.z = _z;
  162. return v;
  163. }
  164. _inline gs_vec3
  165. gs_vec3_add( gs_vec3 v0, gs_vec3 v1 )
  166. {
  167. return gs_vec3_ctor( v0.x + v1.x, v0.y + v1.y, v0.z + v1.z );
  168. }
  169. _inline gs_vec3
  170. gs_vec3_sub( gs_vec3 v0, gs_vec3 v1 )
  171. {
  172. return gs_vec3_ctor( v0.x - v1.x, v0.y - v1.y, v0.z - v1.z );
  173. }
  174. _inline gs_vec3
  175. gs_vec3_mul( gs_vec3 v0, gs_vec3 v1 )
  176. {
  177. return gs_vec3_ctor( v0.x * v1.x, v0.y * v1.y, v0.z * v1.z );
  178. }
  179. _inline gs_vec3
  180. gs_vec3_div( gs_vec3 v0, gs_vec3 v1 )
  181. {
  182. return gs_vec3_ctor( v0.x / v1.x, v0.y / v1.y, v0.z / v1.z );
  183. }
  184. _inline gs_vec3
  185. gs_vec3_scale( gs_vec3 v, f32 s )
  186. {
  187. return gs_vec3_ctor( v.x * s, v.y * s, v.z * s );
  188. }
  189. _inline f32
  190. gs_vec3_dot( gs_vec3 v0, gs_vec3 v1 )
  191. {
  192. f32 dot = ( f32 )( (v0.x * v1.x) + (v0.y * v1.y) + v0.z * v1.z );
  193. return dot;
  194. }
  195. _inline f32
  196. gs_vec3_len( gs_vec3 v )
  197. {
  198. return ( f32 )sqrt( gs_vec3_dot( v, v ) );
  199. }
  200. _inline gs_vec3
  201. gs_vec3_project_onto( gs_vec3 v0, gs_vec3 v1 )
  202. {
  203. f32 dot = gs_vec3_dot( v0, v1 );
  204. f32 len = gs_vec3_dot( v1, v1 );
  205. // Orthogonal, so return v1
  206. if ( len == 0.f ) return v1;
  207. return gs_vec3_scale( v1, dot / len );
  208. }
  209. _inline
  210. f32 gs_vec3_dist( gs_vec3 a, gs_vec3 b )
  211. {
  212. f32 dx = (a.x - b.x);
  213. f32 dy = (a.y - b.y);
  214. f32 dz = (a.z - b.z);
  215. return ( sqrt(dx * dx + dy * dy + dz * dz) );
  216. }
  217. _inline gs_vec3
  218. gs_vec3_norm( gs_vec3 v )
  219. {
  220. f32 len = gs_vec3_len( v );
  221. return len == 0.f ? v : gs_vec3_scale( v, 1.f / len );
  222. }
  223. _inline gs_vec3
  224. gs_vec3_cross( gs_vec3 v0, gs_vec3 v1 )
  225. {
  226. return gs_vec3_ctor
  227. (
  228. v0.y * v1.z - v0.z * v1.y,
  229. v0.z * v1.x - v0.x * v1.z,
  230. v0.x * v1.y - v0.y * v1.x
  231. );
  232. }
  233. _inline void gs_vec3_scale_ip( gs_vec3* vp, f32 s )
  234. {
  235. vp->x *= s;
  236. vp->y *= s;
  237. vp->z *= s;
  238. }
  239. /*================================================================================
  240. // Vec4
  241. ================================================================================*/
  242. typedef struct
  243. {
  244. f32 x;
  245. f32 y;
  246. f32 z;
  247. f32 w;
  248. } gs_vec4;
  249. _inline gs_vec4
  250. gs_vec4_ctor( f32 _x, f32 _y, f32 _z, f32 _w )
  251. {
  252. gs_vec4 v;
  253. v.x = _x;
  254. v.y = _y;
  255. v.z = _z;
  256. v.w = _w;
  257. return v;
  258. }
  259. _inline gs_vec4
  260. gs_vec4_add( gs_vec4 v0, gs_vec4 v1 )
  261. {
  262. return gs_vec4_ctor( v0.x + v1.y, v0.y + v1.y, v0.z + v1.z, v0.w + v1.w );
  263. }
  264. _inline gs_vec4
  265. gs_vec4_sub( gs_vec4 v0, gs_vec4 v1 )
  266. {
  267. return gs_vec4_ctor( v0.x - v1.y, v0.y - v1.y, v0.z - v1.z, v0.w - v1.w );
  268. }
  269. _inline gs_vec4
  270. gs_vec4_div( gs_vec4 v0, gs_vec4 v1 )
  271. {
  272. return gs_vec4_ctor( v0.x / v1.x, v0.y / v1.y, v0.z / v1.z, v0.w / v1.w );
  273. }
  274. _inline gs_vec4
  275. gs_vec4_scale( gs_vec4 v, f32 s )
  276. {
  277. return gs_vec4_ctor( v.x / s, v.y / s, v.z / s, v.w / s );
  278. }
  279. _inline f32
  280. gs_vec4_dot( gs_vec4 v0, gs_vec4 v1 )
  281. {
  282. return ( f32 )( v0.x * v1.x + v0.y * v1.y + v0.z * v1.z + v0.w * v1.w );
  283. }
  284. _inline f32
  285. gs_vec4_len( gs_vec4 v )
  286. {
  287. return ( f32 )sqrt( gs_vec4_dot( v, v ) );
  288. }
  289. _inline gs_vec4
  290. gs_vec4_project_onto( gs_vec4 v0, gs_vec4 v1 )
  291. {
  292. f32 dot = gs_vec4_dot( v0, v1 );
  293. f32 len = gs_vec4_dot( v1, v1 );
  294. // Orthogonal, so return v1
  295. if ( len == 0.f ) return v1;
  296. return gs_vec4_scale( v1, dot / len );
  297. }
  298. _inline gs_vec4
  299. gs_vec4_norm( gs_vec4 v )
  300. {
  301. return gs_vec4_scale( v, 1.0f / gs_vec4_len( v ) );
  302. }
  303. _inline f32
  304. gs_vec4_dist( gs_vec4 v0, gs_vec4 v1 )
  305. {
  306. f32 dx = (v0.x - v1.x);
  307. f32 dy = (v0.y - v1.y);
  308. f32 dz = (v0.z - v1.z);
  309. f32 dw = (v0.w - v1.w);
  310. return ( sqrt(dx * dx + dy * dy + dz * dz + dw * dw) );
  311. }
  312. /*================================================================================
  313. // Mat4x4
  314. ================================================================================*/
  315. /*
  316. Matrices are stored in linear, contiguous memory and assume a column-major ordering.
  317. */
  318. typedef struct gs_mat4
  319. {
  320. f32 elements[16];
  321. } gs_mat4;
  322. _inline gs_mat4
  323. gs_mat4_diag( f32 val )
  324. {
  325. gs_mat4 m;
  326. memset(m.elements, 0, sizeof(m.elements));
  327. m.elements[ 0 + 0 * 4 ] = val;
  328. m.elements[ 1 + 1 * 4 ] = val;
  329. m.elements[ 2 + 2 * 4 ] = val;
  330. m.elements[ 3 + 3 * 4 ] = val;
  331. return m;
  332. }
  333. #define gs_mat4_identity()\
  334. gs_mat4_diag( 1.0f )
  335. #define gs_mat4_ctor()\
  336. ( gs_mat4 ){ 0 }
  337. _inline gs_mat4
  338. gs_mat4_mul( gs_mat4 m0, gs_mat4 m1 )
  339. {
  340. gs_mat4 m_res = gs_mat4_ctor();
  341. for ( u32 y = 0; y < 4; ++y )
  342. {
  343. for ( u32 x = 0; x < 4; ++x )
  344. {
  345. f32 sum = 0.0f;
  346. for ( u32 e = 0; e < 4; ++e )
  347. {
  348. sum += m0.elements[ x + e * 4 ] * m1.elements[ e + y * 4 ];
  349. }
  350. m_res.elements[ x + y * 4 ] = sum;
  351. }
  352. }
  353. return m_res;
  354. }
  355. _inline
  356. gs_mat4 gs_mat4_transpose( gs_mat4 m )
  357. {
  358. gs_mat4 t = gs_mat4_identity();
  359. // First row
  360. t.elements[ 0 * 4 + 0 ] = m.elements[ 0 * 4 + 0 ];
  361. t.elements[ 1 * 4 + 0 ] = m.elements[ 0 * 4 + 1 ];
  362. t.elements[ 2 * 4 + 0 ] = m.elements[ 0 * 4 + 2 ];
  363. t.elements[ 3 * 4 + 0 ] = m.elements[ 0 * 4 + 3 ];
  364. // Second row
  365. t.elements[ 0 * 4 + 1 ] = m.elements[ 1 * 4 + 0 ];
  366. t.elements[ 1 * 4 + 1 ] = m.elements[ 1 * 4 + 1 ];
  367. t.elements[ 2 * 4 + 1 ] = m.elements[ 1 * 4 + 2 ];
  368. t.elements[ 3 * 4 + 1 ] = m.elements[ 1 * 4 + 3 ];
  369. // Third row
  370. t.elements[ 0 * 4 + 2 ] = m.elements[ 2 * 4 + 0 ];
  371. t.elements[ 1 * 4 + 2 ] = m.elements[ 2 * 4 + 1 ];
  372. t.elements[ 2 * 4 + 2 ] = m.elements[ 2 * 4 + 2 ];
  373. t.elements[ 3 * 4 + 2 ] = m.elements[ 2 * 4 + 3 ];
  374. // Fourth row
  375. t.elements[ 0 * 4 + 3 ] = m.elements[ 3 * 4 + 0 ];
  376. t.elements[ 1 * 4 + 3 ] = m.elements[ 3 * 4 + 1 ];
  377. t.elements[ 2 * 4 + 3 ] = m.elements[ 3 * 4 + 2 ];
  378. t.elements[ 3 * 4 + 3 ] = m.elements[ 3 * 4 + 3 ];
  379. return t;
  380. }
  381. _inline
  382. gs_mat4 gs_mat4_inverse( gs_mat4 m )
  383. {
  384. gs_mat4 res = gs_mat4_identity();
  385. f32 temp[16];
  386. temp[0] = m.elements[5] * m.elements[10] * m.elements[15] -
  387. m.elements[5] * m.elements[11] * m.elements[14] -
  388. m.elements[9] * m.elements[6] * m.elements[15] +
  389. m.elements[9] * m.elements[7] * m.elements[14] +
  390. m.elements[13] * m.elements[6] * m.elements[11] -
  391. m.elements[13] * m.elements[7] * m.elements[10];
  392. temp[4] = -m.elements[4] * m.elements[10] * m.elements[15] +
  393. m.elements[4] * m.elements[11] * m.elements[14] +
  394. m.elements[8] * m.elements[6] * m.elements[15] -
  395. m.elements[8] * m.elements[7] * m.elements[14] -
  396. m.elements[12] * m.elements[6] * m.elements[11] +
  397. m.elements[12] * m.elements[7] * m.elements[10];
  398. temp[8] = m.elements[4] * m.elements[9] * m.elements[15] -
  399. m.elements[4] * m.elements[11] * m.elements[13] -
  400. m.elements[8] * m.elements[5] * m.elements[15] +
  401. m.elements[8] * m.elements[7] * m.elements[13] +
  402. m.elements[12] * m.elements[5] * m.elements[11] -
  403. m.elements[12] * m.elements[7] * m.elements[9];
  404. temp[12] = -m.elements[4] * m.elements[9] * m.elements[14] +
  405. m.elements[4] * m.elements[10] * m.elements[13] +
  406. m.elements[8] * m.elements[5] * m.elements[14] -
  407. m.elements[8] * m.elements[6] * m.elements[13] -
  408. m.elements[12] * m.elements[5] * m.elements[10] +
  409. m.elements[12] * m.elements[6] * m.elements[9];
  410. temp[1] = -m.elements[1] * m.elements[10] * m.elements[15] +
  411. m.elements[1] * m.elements[11] * m.elements[14] +
  412. m.elements[9] * m.elements[2] * m.elements[15] -
  413. m.elements[9] * m.elements[3] * m.elements[14] -
  414. m.elements[13] * m.elements[2] * m.elements[11] +
  415. m.elements[13] * m.elements[3] * m.elements[10];
  416. temp[5] = m.elements[0] * m.elements[10] * m.elements[15] -
  417. m.elements[0] * m.elements[11] * m.elements[14] -
  418. m.elements[8] * m.elements[2] * m.elements[15] +
  419. m.elements[8] * m.elements[3] * m.elements[14] +
  420. m.elements[12] * m.elements[2] * m.elements[11] -
  421. m.elements[12] * m.elements[3] * m.elements[10];
  422. temp[9] = -m.elements[0] * m.elements[9] * m.elements[15] +
  423. m.elements[0] * m.elements[11] * m.elements[13] +
  424. m.elements[8] * m.elements[1] * m.elements[15] -
  425. m.elements[8] * m.elements[3] * m.elements[13] -
  426. m.elements[12] * m.elements[1] * m.elements[11] +
  427. m.elements[12] * m.elements[3] * m.elements[9];
  428. temp[13] = m.elements[0] * m.elements[9] * m.elements[14] -
  429. m.elements[0] * m.elements[10] * m.elements[13] -
  430. m.elements[8] * m.elements[1] * m.elements[14] +
  431. m.elements[8] * m.elements[2] * m.elements[13] +
  432. m.elements[12] * m.elements[1] * m.elements[10] -
  433. m.elements[12] * m.elements[2] * m.elements[9];
  434. temp[2] = m.elements[1] * m.elements[6] * m.elements[15] -
  435. m.elements[1] * m.elements[7] * m.elements[14] -
  436. m.elements[5] * m.elements[2] * m.elements[15] +
  437. m.elements[5] * m.elements[3] * m.elements[14] +
  438. m.elements[13] * m.elements[2] * m.elements[7] -
  439. m.elements[13] * m.elements[3] * m.elements[6];
  440. temp[6] = -m.elements[0] * m.elements[6] * m.elements[15] +
  441. m.elements[0] * m.elements[7] * m.elements[14] +
  442. m.elements[4] * m.elements[2] * m.elements[15] -
  443. m.elements[4] * m.elements[3] * m.elements[14] -
  444. m.elements[12] * m.elements[2] * m.elements[7] +
  445. m.elements[12] * m.elements[3] * m.elements[6];
  446. temp[10] = m.elements[0] * m.elements[5] * m.elements[15] -
  447. m.elements[0] * m.elements[7] * m.elements[13] -
  448. m.elements[4] * m.elements[1] * m.elements[15] +
  449. m.elements[4] * m.elements[3] * m.elements[13] +
  450. m.elements[12] * m.elements[1] * m.elements[7] -
  451. m.elements[12] * m.elements[3] * m.elements[5];
  452. temp[14] = -m.elements[0] * m.elements[5] * m.elements[14] +
  453. m.elements[0] * m.elements[6] * m.elements[13] +
  454. m.elements[4] * m.elements[1] * m.elements[14] -
  455. m.elements[4] * m.elements[2] * m.elements[13] -
  456. m.elements[12] * m.elements[1] * m.elements[6] +
  457. m.elements[12] * m.elements[2] * m.elements[5];
  458. temp[3] = -m.elements[1] * m.elements[6] * m.elements[11] +
  459. m.elements[1] * m.elements[7] * m.elements[10] +
  460. m.elements[5] * m.elements[2] * m.elements[11] -
  461. m.elements[5] * m.elements[3] * m.elements[10] -
  462. m.elements[9] * m.elements[2] * m.elements[7] +
  463. m.elements[9] * m.elements[3] * m.elements[6];
  464. temp[7] = m.elements[0] * m.elements[6] * m.elements[11] -
  465. m.elements[0] * m.elements[7] * m.elements[10] -
  466. m.elements[4] * m.elements[2] * m.elements[11] +
  467. m.elements[4] * m.elements[3] * m.elements[10] +
  468. m.elements[8] * m.elements[2] * m.elements[7] -
  469. m.elements[8] * m.elements[3] * m.elements[6];
  470. temp[11] = -m.elements[0] * m.elements[5] * m.elements[11] +
  471. m.elements[0] * m.elements[7] * m.elements[9] +
  472. m.elements[4] * m.elements[1] * m.elements[11] -
  473. m.elements[4] * m.elements[3] * m.elements[9] -
  474. m.elements[8] * m.elements[1] * m.elements[7] +
  475. m.elements[8] * m.elements[3] * m.elements[5];
  476. temp[15] = m.elements[0] * m.elements[5] * m.elements[10] -
  477. m.elements[0] * m.elements[6] * m.elements[9] -
  478. m.elements[4] * m.elements[1] * m.elements[10] +
  479. m.elements[4] * m.elements[2] * m.elements[9] +
  480. m.elements[8] * m.elements[1] * m.elements[6] -
  481. m.elements[8] * m.elements[2] * m.elements[5];
  482. f64 determinant = m.elements[0] * temp[0] + m.elements[1] * temp[4] + m.elements[2] * temp[8] + m.elements[3] * temp[12];
  483. determinant = 1.0 / determinant;
  484. for (int i = 0; i < 4 * 4; i++)
  485. res.elements[i] = temp[i] * determinant;
  486. return res;
  487. }
  488. /*
  489. f32 l : left
  490. f32 r : right
  491. f32 b : bottom
  492. f32 t : top
  493. f32 n : near
  494. f32 f : far
  495. */
  496. _inline gs_mat4
  497. gs_mat4_ortho( f32 l, f32 r, f32 b, f32 t, f32 n, f32 f )
  498. {
  499. gs_mat4 m_res = gs_mat4_identity();
  500. // Main diagonal
  501. m_res.elements[ 0 + 0 * 4 ] = 2.0f / ( r - l );
  502. m_res.elements[ 1 + 1 * 4 ] = 2.0f / ( t - b );
  503. m_res.elements[ 2 + 2 * 4 ] = -2.0f / ( f - n );
  504. // Last column
  505. m_res.elements[ 0 + 3 * 4 ] = -( r + l ) / ( r - l );
  506. m_res.elements[ 1 + 3 * 4 ] = -( t + b ) / ( t - b );
  507. m_res.elements[ 2 + 3 * 4 ] = -( f + n ) / ( f - n );
  508. return m_res;
  509. }
  510. _inline gs_mat4
  511. gs_mat4_perspective( f32 fov, f32 asp_ratio, f32 n, f32 f )
  512. {
  513. // Zero matrix
  514. gs_mat4 m_res = gs_mat4_ctor();
  515. f32 q = 1.0f / tan( gs_deg_to_rad( 0.5f * fov ) );
  516. f32 a = q / asp_ratio;
  517. f32 b = ( n + f ) / ( n - f );
  518. f32 c = ( 2.0f * n * f ) / ( n - f );
  519. m_res.elements[ 0 + 0 * 4 ] = a;
  520. m_res.elements[ 1 + 1 * 4 ] = q;
  521. m_res.elements[ 2 + 2 * 4 ] = b;
  522. m_res.elements[ 2 + 3 * 4 ] = c;
  523. m_res.elements[ 3 + 2 * 4 ] = -1.0f;
  524. return m_res;
  525. }
  526. _inline gs_mat4
  527. gs_mat4_translate( const gs_vec3 v )
  528. {
  529. gs_mat4 m_res = gs_mat4_identity();
  530. m_res.elements[ 0 + 4 * 3 ] = v.x;
  531. m_res.elements[ 1 + 4 * 3 ] = v.y;
  532. m_res.elements[ 2 + 4 * 3 ] = v.z;
  533. return m_res;
  534. }
  535. _inline gs_mat4
  536. gs_mat4_scale( const gs_vec3 v )
  537. {
  538. gs_mat4 m_res = gs_mat4_identity();
  539. m_res.elements[ 0 + 0 * 4 ] = v.x;
  540. m_res.elements[ 1 + 1 * 4 ] = v.y;
  541. m_res.elements[ 2 + 2 * 4 ] = v.z;
  542. return m_res;
  543. }
  544. _inline gs_mat4 gs_mat4_rotate( f32 angle, gs_vec3 axis )
  545. {
  546. gs_mat4 m_res = gs_mat4_identity();
  547. f32 a = gs_deg_to_rad( angle );
  548. f32 c = cos( a );
  549. f32 s = sin( a );
  550. f32 x = axis.x;
  551. f32 y = axis.y;
  552. f32 z = axis.z;
  553. //First column
  554. m_res.elements[ 0 + 0 * 4 ] = x * x * ( 1 - c ) + c;
  555. m_res.elements[ 1 + 0 * 4 ] = x * y * ( 1 - c ) + z * s;
  556. m_res.elements[ 2 + 0 * 4 ] = x * z * ( 1 - c ) - y * s;
  557. //Second column
  558. m_res.elements[ 0 + 1 * 4 ] = x * y * ( 1 - c ) - z * s;
  559. m_res.elements[ 1 + 1 * 4 ] = y * y * ( 1 - c ) + c;
  560. m_res.elements[ 2 + 1 * 4 ] = y * z * ( 1 - c ) + x * s;
  561. //Third column
  562. m_res.elements[ 0 + 2 * 4 ] = x * z * ( 1 - c ) + y * s;
  563. m_res.elements[ 1 + 2 * 4 ] = y * z * ( 1 - c ) - x * s;
  564. m_res.elements[ 2 + 2 * 4 ] = z * z * ( 1 - c ) + c;
  565. return m_res;
  566. }
  567. _inline gs_mat4
  568. gs_mat4_look_at( gs_vec3 position, gs_vec3 target, gs_vec3 up )
  569. {
  570. gs_vec3 f = gs_vec3_norm( gs_vec3_sub( target, position ) );
  571. gs_vec3 s = gs_vec3_norm( gs_vec3_cross( f, up ) );
  572. gs_vec3 u = gs_vec3_cross( s, f );
  573. gs_mat4 m_res = gs_mat4_identity();
  574. m_res.elements[ 0 * 4 + 0 ] = s.x;
  575. m_res.elements[ 1 * 4 + 0 ] = s.y;
  576. m_res.elements[ 2 * 4 + 0 ] = s.z;
  577. m_res.elements[ 0 * 4 + 1 ] = u.x;
  578. m_res.elements[ 1 * 4 + 1 ] = u.y;
  579. m_res.elements[ 2 * 4 + 1 ] = u.z;
  580. m_res.elements[ 0 * 4 + 2 ] = -f.x;
  581. m_res.elements[ 1 * 4 + 2 ] = -f.y;
  582. m_res.elements[ 2 * 4 + 2 ] = -f.z;
  583. m_res.elements[ 3 * 4 + 0 ] = -gs_vec3_dot( s, position );;
  584. m_res.elements[ 3 * 4 + 1 ] = -gs_vec3_dot( u, position );
  585. m_res.elements[ 3 * 4 + 2 ] = gs_vec3_dot( f, position );
  586. return m_res;
  587. }
  588. _inline
  589. gs_vec3 gs_mat4_mul_vec3( gs_mat4 m, gs_vec3 v )
  590. {
  591. m = gs_mat4_transpose(m);
  592. return gs_vec3_ctor
  593. (
  594. m.elements[0 * 4 + 0] * v.x + m.elements[0 * 4 + 1] * v.y + m.elements[0 * 4 + 2] * v.z,
  595. m.elements[1 * 4 + 0] * v.x + m.elements[1 * 4 + 1] * v.y + m.elements[1 * 4 + 2] * v.z,
  596. m.elements[2 * 4 + 0] * v.x + m.elements[2 * 4 + 1] * v.y + m.elements[2 * 4 + 2] * v.z
  597. );
  598. }
  599. _inline
  600. gs_vec4 gs_mat4_mul_vec4( gs_mat4 m, gs_vec4 v )
  601. {
  602. m = gs_mat4_transpose(m);
  603. return gs_vec4_ctor
  604. (
  605. m.elements[0 * 4 + 0] * v.x + m.elements[0 * 4 + 1] * v.y + m.elements[0 * 4 + 2] * v.z + m.elements[0 * 4 + 3] * v.w,
  606. m.elements[1 * 4 + 0] * v.x + m.elements[1 * 4 + 1] * v.y + m.elements[1 * 4 + 2] * v.z + m.elements[1 * 4 + 3] * v.w,
  607. m.elements[2 * 4 + 0] * v.x + m.elements[2 * 4 + 1] * v.y + m.elements[2 * 4 + 2] * v.z + m.elements[2 * 4 + 3] * v.w,
  608. m.elements[3 * 4 + 0] * v.x + m.elements[3 * 4 + 1] * v.y + m.elements[3 * 4 + 2] * v.z + m.elements[3 * 4 + 3] * v.w
  609. );
  610. }
  611. /*================================================================================
  612. // Quaternion
  613. ================================================================================*/
  614. typedef struct
  615. {
  616. f32 x;
  617. f32 y;
  618. f32 z;
  619. f32 w;
  620. } gs_quat;
  621. _inline
  622. gs_quat gs_quat_default()
  623. {
  624. gs_quat q;
  625. q.x = 0.f;
  626. q.y = 0.f;
  627. q.z = 0.f;
  628. q.w = 0.f;
  629. return q;
  630. }
  631. _inline
  632. gs_quat gs_quat_ctor( f32 _x, f32 _y, f32 _z, f32 _w )
  633. {
  634. gs_quat q;
  635. q.x = _x;
  636. q.y = _y;
  637. q.z = _z;
  638. q.w = _w;
  639. return q;
  640. }
  641. _inline gs_quat
  642. gs_quat_add( gs_quat q0, gs_quat q1 )
  643. {
  644. return gs_quat_ctor( q0.x + q1.x, q0.y + q1.y, q0.z + q1.z, q0.w + q1.w );
  645. }
  646. _inline gs_quat
  647. gs_quat_sub( gs_quat q0, gs_quat q1 )
  648. {
  649. return gs_quat_ctor( q0.x - q1.x, q0.y - q1.y, q0.z - q1.z, q0.w - q1.w );
  650. }
  651. _inline gs_quat
  652. gs_quat_mul( gs_quat q0, gs_quat q1 )
  653. {
  654. return gs_quat_ctor(
  655. q0.w * q1.x + q1.w * q0.x + q0.y * q1.z - q1.y * q0.z,
  656. q0.w * q1.y + q1.w * q0.y + q0.z * q1.x - q1.z * q0.x,
  657. q0.w * q1.z + q1.w * q0.z + q0.x * q1.y - q1.x * q0.y,
  658. q0.w * q1.w - q0.x * q1.x - q0.y * q1.y - q0.z * q1.z
  659. );
  660. }
  661. _inline gs_quat
  662. gs_quat_mul_quat( gs_quat q0, gs_quat q1 )
  663. {
  664. return gs_quat_ctor(
  665. q0.w * q1.x + q1.w * q0.x + q0.y * q1.z - q1.y * q0.z,
  666. q0.w * q1.y + q1.w * q0.y + q0.z * q1.x - q1.z * q0.x,
  667. q0.w * q1.z + q1.w * q0.z + q0.x * q1.y - q1.x * q0.y,
  668. q0.w * q1.w - q0.x * q1.x - q0.y * q1.y - q0.z * q1.z
  669. );
  670. }
  671. _inline
  672. gs_quat gs_quat_scale( gs_quat q, f32 s )
  673. {
  674. return gs_quat_ctor( q.x * s, q.y * s, q.z * s, q.w * s );
  675. }
  676. _inline f32
  677. gs_quat_dot( gs_quat q0, gs_quat q1 )
  678. {
  679. return ( f32 )( q0.x * q1.x + q0.y * q1.y + q0.z * q1.z + q0.w * q1.w );
  680. }
  681. _inline
  682. gs_quat gs_quat_conjugate( gs_quat q )
  683. {
  684. return ( gs_quat_ctor( -q.x, -q.y, -q.z, q.w ) );
  685. }
  686. _inline f32
  687. gs_quat_len( gs_quat q )
  688. {
  689. return ( f32 )sqrt( gs_quat_dot( q, q ) );
  690. }
  691. _inline gs_quat
  692. gs_quat_norm( gs_quat q )
  693. {
  694. return gs_quat_scale( q, 1.0f / gs_quat_len( q ) );
  695. }
  696. _inline gs_quat
  697. gs_quat_cross( gs_quat q0, gs_quat q1 )
  698. {
  699. return gs_quat_ctor (
  700. q0.x * q1.x + q0.x * q1.w + q0.y * q1.z - q0.z * q1.y,
  701. q0.w * q1.y + q0.y * q1.w + q0.z * q1.x - q0.x * q1.z,
  702. q0.w * q1.z + q0.z * q1.w + q0.x * q1.y - q0.y * q1.x,
  703. q0.w * q1.w - q0.x * q1.x - q0.y * q1.y - q0.z * q1.z
  704. );
  705. }
  706. // Inverse := Conjugate / Dot;
  707. _inline
  708. gs_quat gs_quat_inverse( gs_quat q )
  709. {
  710. return ( gs_quat_scale( gs_quat_conjugate( q ), 1.0f / gs_quat_dot( q, q ) ) );
  711. }
  712. _inline gs_vec3 gs_quat_rotate( gs_quat q, gs_vec3 v )
  713. {
  714. // nVidia SDK implementation
  715. gs_vec3 qvec = gs_vec3_ctor( q.x, q.y, q.z );
  716. gs_vec3 uv = gs_vec3_cross( qvec, v );
  717. gs_vec3 uuv = gs_vec3_cross( qvec, uv );
  718. uv = gs_vec3_scale(uv, 2.f * q.w);
  719. uuv = gs_vec3_scale(uuv, 2.f);
  720. return ( gs_vec3_add( v, gs_vec3_add( uv, uuv ) ) );
  721. }
  722. _inline gs_quat gs_quat_angle_axis( f32 rad, gs_vec3 axis )
  723. {
  724. // Normalize axis
  725. gs_vec3 a = gs_vec3_norm( axis );
  726. // Get scalar
  727. f32 half_angle = 0.5f * rad;
  728. f32 s = sin( half_angle );
  729. return gs_quat_ctor( a.x * s, a.y * s, a.z * s, cos( half_angle ) );
  730. }
  731. _inline
  732. gs_quat gs_quat_slerp( gs_quat a, gs_quat b, f32 t )
  733. {
  734. f32 c = gs_quat_dot(a, b);
  735. gs_quat end = b;
  736. if ( c < 0.0f )
  737. {
  738. // Reverse all signs
  739. c *= -1.0f;
  740. end.x *= -1.0f;
  741. end.y *= -1.0f;
  742. end.z *= -1.0f;
  743. end.w *= -1.0f;
  744. }
  745. // Calculate coefficients
  746. f32 sclp, sclq;
  747. if ( ( 1.0f - c ) > 0.0001f )
  748. {
  749. f32 omega = acosf( c );
  750. f32 s = sinf( omega );
  751. sclp = sinf( ( 1.0f - t ) * omega ) / s;
  752. sclq = sinf( t * omega ) / s;
  753. }
  754. else
  755. {
  756. sclp = 1.0f - t;
  757. sclq = t;
  758. }
  759. gs_quat q;
  760. q.x = sclp * a.x + sclq * end.x;
  761. q.y = sclp * a.y + sclq * end.y;
  762. q.z = sclp * a.z + sclq * end.z;
  763. q.w = sclp * a.w + sclq * end.w;
  764. return q;
  765. }
  766. #define quat_axis_angle( axis, angle )\
  767. gs_quat_angle_axis( angle, axis )
  768. /*
  769. * @brief Convert given quaternion param into equivalent 4x4 rotation matrix
  770. * @note: From http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
  771. */
  772. _inline gs_mat4 gs_quat_to_mat4( gs_quat _q )
  773. {
  774. gs_mat4 mat = gs_mat4_identity();
  775. gs_quat q = gs_quat_norm( _q );
  776. f32 xx = q.x * q.x;
  777. f32 yy = q.y * q.y;
  778. f32 zz = q.z * q.z;
  779. f32 xy = q.x * q.y;
  780. f32 xz = q.x * q.z;
  781. f32 yz = q.y * q.z;
  782. f32 wx = q.w * q.x;
  783. f32 wy = q.w * q.y;
  784. f32 wz = q.w * q.z;
  785. mat.elements[ 0 * 4 + 0 ] = 1.0f - 2.0f * ( yy + zz );
  786. mat.elements[ 1 * 4 + 0 ] = 2.0f * ( xy - wz );
  787. mat.elements[ 2 * 4 + 0 ] = 2.0f * ( xz + wy );
  788. mat.elements[ 0 * 4 + 1 ] = 2.0f * ( xy + wz );
  789. mat.elements[ 1 * 4 + 1 ] = 1.0f - 2.0f * ( xx + zz );
  790. mat.elements[ 2 * 4 + 1 ] = 2.0f * ( yz - wx );
  791. mat.elements[ 0 * 4 + 2 ] = 2.0f * ( xz - wy );
  792. mat.elements[ 1 * 4 + 2 ] = 2.0f * ( yz + wx );
  793. mat.elements[ 2 * 4 + 2 ] = 1.0f - 2.0f * ( xx + yy );
  794. return mat;
  795. }
  796. _inline
  797. gs_quat gs_quat_from_euler( f32 yaw_deg, f32 pitch_deg, f32 roll_deg )
  798. {
  799. f32 yaw = gs_deg_to_rad(yaw_deg);
  800. f32 pitch = gs_deg_to_rad(pitch_deg);
  801. f32 roll = gs_deg_to_rad(roll_deg);
  802. gs_quat q;
  803. f32 cy = cos( yaw * 0.5f );
  804. f32 sy = sin( yaw * 0.5f );
  805. f32 cr = cos( roll * 0.5f );
  806. f32 sr = sin( roll * 0.5f );
  807. f32 cp = cos( pitch * 0.5f );
  808. f32 sp = sin( pitch * 0.5f );
  809. q.x = cy * sr * cp - sy * cr * sp;
  810. q.y = cy * cr * sp + sy * sr * cp;
  811. q.z = sy * cr * cp - cy * sr * sp;
  812. q.w = cy * cr * cp + sy * sr * sp;
  813. return q;
  814. }
  815. /*================================================================================
  816. // Transform ( Non-Uniform Scalar VQS )
  817. ================================================================================*/
  818. /*
  819. - This follows a traditional 'VQS' structure for complex object transformations,
  820. however it differs from the standard in that it allows for non-uniform
  821. scaling in the form of a vec3.
  822. */
  823. // Source: https://www.eurosis.org/cms/files/conf/gameon-asia/gameon-asia2007/R-SESSION/G1.pdf
  824. typedef struct
  825. {
  826. gs_vec3 position;
  827. gs_quat rotation;
  828. gs_vec3 scale;
  829. } gs_vqs;
  830. _inline gs_vqs gs_vqs_ctor( gs_vec3 tns, gs_quat rot, gs_vec3 scl )
  831. {
  832. gs_vqs t;
  833. t.position = tns;
  834. t.rotation = rot;
  835. t.scale = scl;
  836. return t;
  837. }
  838. _inline
  839. gs_vqs gs_vqs_default()
  840. {
  841. gs_vqs t = gs_vqs_ctor
  842. (
  843. gs_vec3_ctor( 0.0f, 0.0f, 0.0f ),
  844. gs_quat_ctor( 0.0f, 0.0f, 0.0f, 1.0f ),
  845. gs_vec3_ctor( 1.0f, 1.0f, 1.0f )
  846. );
  847. return t;
  848. }
  849. // AbsScale = ParentScale * LocalScale
  850. // AbsRot = LocalRot * ParentRot
  851. // AbsTrans = ParentPos + [ ParentRot * ( ParentScale * LocalPos ) ]
  852. _inline gs_vqs gs_vqs_absolute_transform( const gs_vqs* local, const gs_vqs* parent )
  853. {
  854. // Normalized rotations
  855. gs_quat p_rot_norm = gs_quat_norm( parent->rotation );
  856. gs_quat l_rot_norm = gs_quat_norm( local->rotation );
  857. // Scale
  858. gs_vec3 scl = gs_vec3_mul( local->scale, parent->scale );
  859. // Rotation
  860. gs_quat rot = gs_quat_norm( gs_quat_mul( p_rot_norm, l_rot_norm ) );
  861. // position
  862. gs_vec3 tns = gs_vec3_add( parent->position, gs_quat_rotate( p_rot_norm, gs_vec3_mul( parent->scale, local->position ) ) );
  863. return gs_vqs_ctor( tns, rot, scl );
  864. }
  865. // RelScale = AbsScale / ParentScale
  866. // RelRot = Inverse(ParentRot) * AbsRot
  867. // RelTrans = [Inverse(ParentRot) * (AbsPos - ParentPosition)] / ParentScale;
  868. _inline gs_vqs gs_vqs_relative_transform( const gs_vqs* absolute, const gs_vqs* parent )
  869. {
  870. // Get inverse rotation normalized
  871. gs_quat p_rot_inv = gs_quat_norm( gs_quat_inverse( parent->rotation ) );
  872. // Normalized abs rotation
  873. gs_quat a_rot_norm = gs_quat_norm( absolute->rotation );
  874. // Scale
  875. gs_vec3 scl = gs_vec3_div( absolute->scale, parent->scale );
  876. // Rotation
  877. gs_quat rot = gs_quat_norm( gs_quat_mul( p_rot_inv, a_rot_norm ) );
  878. // position
  879. gs_vec3 tns = gs_vec3_div( gs_quat_rotate( p_rot_inv, gs_vec3_sub( absolute->position, parent->position ) ), parent->scale );
  880. return gs_vqs_ctor( tns, rot, scl );
  881. }
  882. _inline gs_mat4 gs_vqs_to_mat4( const gs_vqs* transform )
  883. {
  884. gs_mat4 mat = gs_mat4_identity();
  885. gs_mat4 trans = gs_mat4_translate( transform->position );
  886. gs_mat4 rot = gs_quat_to_mat4( transform->rotation );
  887. gs_mat4 scl = gs_mat4_scale( transform->scale );
  888. mat = gs_mat4_mul( mat, trans );
  889. mat = gs_mat4_mul( mat, rot );
  890. mat = gs_mat4_mul( mat, scl );
  891. return mat;
  892. }
  893. /*================================================================================
  894. // Ray
  895. ================================================================================*/
  896. typedef struct
  897. {
  898. gs_vec3 point;
  899. gs_vec3 direction;
  900. } gs_ray;
  901. _inline gs_ray gs_ray_ctor( gs_vec3 pt, gs_vec3 dir )
  902. {
  903. gs_ray r;
  904. r.point = pt;
  905. r.direction = dir;
  906. return r;
  907. }
  908. /*================================================================================
  909. // Plane
  910. ================================================================================*/
  911. typedef struct
  912. {
  913. f32 a;
  914. f32 b;
  915. f32 c;
  916. f32 d;
  917. } gs_plane;
  918. #ifdef __cplusplus
  919. }
  920. #endif // c++
  921. #endif // __GS_MATH_H__