/math.c

https://github.com/andersonsp/Myr · C · 376 lines · 308 code · 61 blank · 7 comment · 35 complexity · ca73ff844f03e2be9a0be4800074c832 MD5 · raw file

  1. #include "myr.h"
  2. // GMat4
  3. void g_mat4_identity( GMat4 *mat ) {
  4. float *m = (float*) mat;
  5. m[0] = 1; m[4] = 0; m[8] = 0; m[12] = 0;
  6. m[1] = 0; m[5] = 1; m[9] = 0; m[13] = 0;
  7. m[2] = 0; m[6] = 0; m[10] = 1; m[14] = 0;
  8. m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;
  9. }
  10. void g_mat4_add( GMat4 *out, GMat4 *m1, GMat4 *m2 ) {
  11. float *r = (float *) out, *m = (float *) m1, *n = (float *) m2;
  12. int i;
  13. for( i=0; i<16; i++ ) r[i] = m[i] + n[i];
  14. }
  15. void g_mat4_mul_scalar( GMat4 *out, GMat4 *m1, float scalar ) {
  16. float *r = (float *) out, *m = (float *) m1;
  17. int i;
  18. for( i = 0; i<16; i++ ) r[i] = m[i] * scalar;
  19. }
  20. void g_mat4_mul( GMat4 *out, GMat4 *m1, GMat4 *m2 ) {
  21. GMat4 temp1, temp2;
  22. int i,j;
  23. if( m1 == out ){ temp1 = *m1; m1 = &temp1; }
  24. if( m2 == out ){ temp2 = *m2; m2 = &temp2; }
  25. float *r = (float*) out, *m = (float*) m1, *n = (float*) m2;
  26. for( j=0; j < 4; ++j ) {
  27. for (i=0; i < 4; ++i)
  28. r[4*j+i] = m[i]*n[4*j] + m[4+i]*n[4*j+1] + m[8+i]*n[4*j+2] + m[12+i]*n[4*j+3];
  29. }
  30. }
  31. void g_mat4_vec_mul( GVec *out, GMat4 *mat, GVec *in ) {
  32. float *m = (float*) mat;
  33. GVec v;
  34. if( in == out ){ v = *in; in = &v; } // copy if it's in-place
  35. out->x = m[0] * in->x + m[4] * in->y + m[8] * in->z + m[12];
  36. out->y = m[1] * in->x + m[5] * in->y + m[9] * in->z + m[13];
  37. out->z = m[2] * in->x + m[6] * in->y + m[10] * in->z + m[14];
  38. }
  39. void g_mat4_transpose( GMat4 *mat ) {
  40. float *m = (float *) mat;
  41. int i,j;
  42. for( j=0; j < 4; ++j ) {
  43. for( i=j+1; i < 4; ++i ) {
  44. float t = m[i*4+j];
  45. m[i*4+j] = m[j*4+i];
  46. m[j*4+i] = t;
  47. }
  48. }
  49. }
  50. void g_mat4_from_quat_vec(GMat4 *m, GQuat *q, GVec *v) {
  51. float x2 = 2 * q->x;
  52. float qx2_2 = x2 * q->x;
  53. float qxy_2 = x2 * q->y;
  54. float qxz_2 = x2 * q->z;
  55. float qxw_2 = x2 * q->w;
  56. float y2 = 2 * q->y;
  57. float qy2_2 = y2 * q->y;
  58. float qyz_2 = y2 * q->z;
  59. float qyw_2 = y2 * q->w;
  60. float z2 = 2 * q->z;
  61. float qz2_2 = z2 * q->z;
  62. float qzw_2 = z2 * q->w;
  63. m->v[0].x = 1 - qy2_2 - qz2_2;
  64. m->v[1].x = qxy_2 - qzw_2;
  65. m->v[2].x = qxz_2 + qyw_2;
  66. m->v[3].x = v->x;
  67. m->v[0].y = qxy_2 + qzw_2;
  68. m->v[1].y = 1 - qx2_2 - qz2_2;
  69. m->v[2].y = qyz_2 - qxw_2;
  70. m->v[3].y = v->y;
  71. m->v[0].z = qxz_2 - qyw_2;
  72. m->v[1].z = qyz_2 + qxw_2;
  73. m->v[2].z = 1 - qx2_2 - qy2_2;
  74. m->v[3].z = v->z;
  75. m->v[0].w = 0;
  76. m->v[1].w = 0;
  77. m->v[2].w = 0;
  78. m->v[3].w = 1;
  79. }
  80. void g_mat4_ortho( GMat4 *m, float w, float h, float n, float f ) {
  81. g_mat4_identity( m );
  82. m->v[0].x = 2.0f/w;
  83. m->v[1].y = 2.0f/h;
  84. m->v[2].z = -2.0f/(f - n);
  85. m->v[3].z = -(f + n)/(f - n);
  86. }
  87. void g_mat4_persp( GMat4 *m, float fovy, float aspect, float znear, float zfar ) {
  88. float f = 1.0/tanf(fovy/360.0*G_PI);
  89. g_mat4_identity( m );
  90. m->v[0].x = f/aspect;
  91. m->v[1].y = f;
  92. m->v[2].z = (zfar + znear)/(znear - zfar);
  93. m->v[2].w = -1.0f;
  94. m->v[3].z = 2.0f*zfar*znear/(znear - zfar);
  95. }
  96. void g_mat4_look_at( GMat4 *m, GVec *eye, GVec *target, GVec *up ){
  97. GVec x_vec, y_vec, z_vec;
  98. g_vec_sub( &z_vec, eye, target);
  99. g_vec_normalize( &z_vec );
  100. g_vec_cross( &x_vec, up, &z_vec );
  101. g_vec_normalize( &x_vec );
  102. g_vec_cross( &y_vec, &z_vec, &x_vec );
  103. g_vec_normalize( &y_vec );
  104. m->v[0].x = x_vec.x;
  105. m->v[1].x = x_vec.y;
  106. m->v[2].x = x_vec.z;
  107. m->v[3].x = -g_vec_dot( &x_vec, eye );
  108. m->v[0].y = y_vec.x;
  109. m->v[1].y = y_vec.y;
  110. m->v[2].y = y_vec.z;
  111. m->v[3].y = -g_vec_dot( &y_vec, eye );
  112. m->v[0].z = z_vec.x;
  113. m->v[1].z = z_vec.y;
  114. m->v[2].z = z_vec.z;
  115. m->v[3].z = -g_vec_dot( &z_vec, eye );
  116. m->v[0].w = 0;
  117. m->v[1].w = 0;
  118. m->v[2].w = 0;
  119. m->v[3].w = 1;
  120. }
  121. //GVec
  122. void g_vec_add( GVec *r, GVec *u, GVec *v ) {
  123. r->x = u->x + v->x;
  124. r->y = u->y + v->y;
  125. r->z = u->z + v->z;
  126. }
  127. void g_vec_sub( GVec *r, GVec *u, GVec *v ) {
  128. r->x = u->x - v->x;
  129. r->y = u->y - v->y;
  130. r->z = u->z - v->z;
  131. }
  132. void g_vec_mul_scalar( GVec *r, GVec *u, float scalar ) {
  133. r->x = u->x * scalar;
  134. r->y = u->y * scalar;
  135. r->z = u->z * scalar;
  136. }
  137. float g_vec_dot( GVec *v0, GVec *v1 ) {
  138. return v0->x*v1->x + v0->y*v1->y + v0->z*v1->z;
  139. }
  140. void g_vec_cross( GVec *r, GVec *v0, GVec *v1 ) {
  141. r->x = v0->y * v1->z - v0->z * v1->y;
  142. r->y = v0->z * v1->x - v0->x * v1->z;
  143. r->z = v0->x * v1->y - v0->y * v1->x; // right hand rule: i x j = k
  144. }
  145. void g_vec_lerp( GVec *r, GVec *a, GVec *b, float t ) {
  146. r->x = a->x + t * (b->x - a->x);
  147. r->y = a->y + t * (b->y - a->y);
  148. r->z = a->z + t * (b->z - a->z);
  149. }
  150. void g_vec_scale_add( GVec *r, GVec *q, float sc ) {
  151. r->x += q->x * sc;
  152. r->y += q->y * sc;
  153. r->z += q->z * sc;
  154. }
  155. float g_vec_mag( GVec *v ) {
  156. return (float) sqrt( v->x*v->x + v->y*v->y + v->z*v->z );
  157. }
  158. float g_vec_dist( GVec *v0, GVec *v1 ) {
  159. float x = v0->x - v1->x;
  160. float y = v0->y - v1->y;
  161. float z = v0->z - v1->z;
  162. return (float) sqrt( x*x + y*y + z*z );
  163. }
  164. void g_vec_normalize( GVec *v ) {
  165. float mag = g_vec_mag(v);
  166. v->x /= mag;
  167. v->y /= mag;
  168. v->z /= mag;
  169. }
  170. // GQuat
  171. void g_quat_identity( GQuat *q ) {
  172. q->x = q->y = q->z = 0;
  173. q->w = 1;
  174. }
  175. void g_quat_invert( GQuat *q ) {
  176. q->x = -q->x;
  177. q->y = -q->y;
  178. q->z = -q->z;
  179. }
  180. void g_quat_normalize( GQuat *q ) {
  181. float d = (float) sqrt(q->x*q->x + q->y*q->y + q->z*q->z + q->w*q->w);
  182. if (d >= 0.00001) {
  183. d = 1/d;
  184. q->x *= d;
  185. q->y *= d;
  186. q->z *= d;
  187. q->w *= d;
  188. } else {
  189. g_quat_identity(q);
  190. }
  191. }
  192. void g_quat_mul( GQuat *r, GQuat *q1, GQuat *q2 ) {
  193. GQuat temp;
  194. if (r == q1) { temp = *q1; q1 = &temp; }
  195. if (r == q2) { temp = *q2; q2 = &temp; }
  196. r->x = q1->w*q2->x + q1->x*q2->w + q1->y*q2->z - q1->z*q2->y;
  197. r->y = q1->w*q2->y - q1->x*q2->z + q1->y*q2->w + q1->z*q2->x;
  198. r->z = q1->w*q2->z + q1->x*q2->y - q1->y*q2->x + q1->z*q2->w;
  199. r->w = q1->w*q2->w - q1->x*q2->x - q1->y*q2->y - q1->z*q2->z;
  200. }
  201. void g_quat_scale_add( GQuat *r, GQuat *q, float sc ) {
  202. r->x += q->x * sc;
  203. r->y += q->y * sc;
  204. r->z += q->z * sc;
  205. r->w += q->w * sc;
  206. }
  207. void g_quat_vec_mul( GVec *r, GQuat *q, GVec *v ) {
  208. GQuat qvec = { v->x, v->y, v->z, 0 };
  209. GQuat qinv = { -q->x, -q->y, -q->z, q->w };
  210. GQuat temp;
  211. g_quat_mul( &temp, q, &qvec );
  212. g_quat_mul( &temp, &temp, &qinv );
  213. r->x = temp.x;
  214. r->y = temp.y;
  215. r->z = temp.z;
  216. }
  217. void g_quat_from_axis_angle( GQuat *q, GVec *axis, float ang ) {
  218. q->w = (float) cos(ang/2);
  219. g_vec_mul_scalar((GVec *) q, axis, (float) sin(ang/2));
  220. }
  221. void g_quat_from_mat4( GQuat* q, GMat4* m ){
  222. q->x = 1 + m->v[0].x - m->v[1].y - m->v[2].z;
  223. if( q->x < 0 ) q->x = 0;
  224. else q->x = (float) sqrt(q->x)/2;
  225. q->y = 1 - m->v[0].x + m->v[1].y - m->v[2].z;
  226. if( q->y < 0 ) q->y = 0;
  227. else q->y = (float) sqrt(q->y)/2;
  228. q->z = 1 - m->v[0].x - m->v[1].y + m->v[2].z;
  229. if( q->z < 0 ) q->z = 0;
  230. else q->z = (float) sqrt(q->z)/2;
  231. q->w = 1 + m->v[0].x + m->v[1].y + m->v[2].z;
  232. if( q->w < 0 ) q->w = 0;
  233. else q->w = (float) sqrt(q->w)/2;
  234. if( m->v[1].z - m->v[2].y < 0 ) q->x = -q->x;
  235. if( m->v[2].x - m->v[0].z < 0 ) q->y = -q->y;
  236. if( m->v[0].y - m->v[1].x < 0 ) q->z = -q->z;
  237. }
  238. // Dual Quaternions
  239. void g_dual_quat_scale_add( GDualQuat* r, GDualQuat* dq, float t ){
  240. float dot_real = r->q.x*dq->q.x + r->q.y*dq->q.y + r->q.z*dq->q.z + r->q.w*dq->q.w;
  241. float k = dot_real < 0 ? -t : t;
  242. g_quat_scale_add( &r->q, &dq->q, k );
  243. g_quat_scale_add( &r->d, &dq->d, k );
  244. }
  245. void g_dual_quat_lerp( GDualQuat* r, GDualQuat* d1, GDualQuat* d2, float t ) {
  246. float dot_real = d1->q.x*d2->q.x + d1->q.y*d2->q.y + d1->q.z*d2->q.z + d1->q.w*d2->q.w;
  247. float k = dot_real < 0 ? -t : t;
  248. r->q.x = d1->q.x*(1-t) + d2->q.x*k;
  249. r->q.y = d1->q.y*(1-t) + d2->q.y*k;
  250. r->q.z = d1->q.z*(1-t) + d2->q.z*k;
  251. r->q.w = d1->q.w*(1-t) + d2->q.w*k;
  252. r->d.x = d1->d.x*(1-t) + d2->d.x*k;
  253. r->d.y = d1->d.y*(1-t) + d2->d.y*k;
  254. r->d.z = d1->d.z*(1-t) + d2->d.z*k;
  255. r->d.w = d1->d.w*(1-t) + d2->d.w*k;
  256. }
  257. void g_dual_quat_from_quat_vec( GDualQuat *dq, GQuat *q, GVec *v ) {
  258. dq->q = *q;
  259. GQuat qvec = { 0.5*v->x, 0.5*v->y, 0.5*v->z, 0 };
  260. g_quat_mul( &dq->d, &qvec, q );
  261. }
  262. void g_dual_quat_invert( GDualQuat *r, GDualQuat *dq ) {
  263. //compute the dual normal
  264. double real = dq->q.w*dq->q.w + dq->q.x*dq->q.x + dq->q.y*dq->q.y + dq->q.z*dq->q.z;
  265. double dual = 2.0 * (dq->q.w*dq->d.w + dq->q.x*dq->d.x + dq->q.y*dq->d.y + dq->q.z*dq->d.z);
  266. //set the inverse dual_quat
  267. r->q.x = -dq->q.x * real;
  268. r->q.y = -dq->q.y * real;
  269. r->q.z = -dq->q.z * real;
  270. r->q.w = dq->q.w * real;
  271. r->d.x = dq->d.x * (dual-real);
  272. r->d.y = dq->d.y * (dual-real);
  273. r->d.z = dq->d.z * (dual-real);
  274. r->d.w = dq->d.w * (real-dual);
  275. }
  276. void g_dual_quat_mul( GDualQuat *dq, GDualQuat *a, GDualQuat *b ) {
  277. GDualQuat temp;
  278. if (dq == a) { temp = *a; a = &temp; }
  279. if (dq == b) { temp = *b; b = &temp; }
  280. dq->q.w = a->q.w*b->q.w - a->q.x*b->q.x - a->q.y*b->q.y - a->q.z*b->q.z;
  281. dq->q.x = a->q.w*b->q.x + a->q.x*b->q.w + a->q.y*b->q.z - a->q.z*b->q.y;
  282. dq->q.y = a->q.w*b->q.y + a->q.y*b->q.w - a->q.x*b->q.z + a->q.z*b->q.x;
  283. dq->q.z = a->q.w*b->q.z + a->q.z*b->q.w + a->q.x*b->q.y - a->q.y*b->q.x;
  284. // Dual unit Quaternion.
  285. dq->d.x = a->d.x*b->q.w + a->q.w*b->d.x + a->d.w*b->q.x + a->q.x*b->d.w -
  286. a->d.z*b->q.y + a->q.y*b->d.z + a->d.y*b->q.z - a->q.z*b->d.y;
  287. dq->d.y = a->d.y*b->q.w + a->q.w*b->d.y + a->d.z*b->q.x - a->q.x*b->d.z +
  288. a->d.w*b->q.y + a->q.y*b->d.w - a->d.x*b->q.z + a->q.z*b->d.x;
  289. dq->d.z = a->d.z*b->q.w + a->q.w*b->d.z - a->d.y*b->q.x + a->q.x*b->d.y +
  290. a->d.x*b->q.y - a->q.y*b->d.x + a->d.w*b->q.z + a->q.z*b->d.w;
  291. dq->d.w = a->d.w*b->q.w + a->q.w*b->d.w - a->q.x*b->d.x - a->d.x*b->q.x -
  292. a->q.y*b->d.y - a->d.y*b->q.y - a->q.z*b->d.z - a->d.z*b->q.z;
  293. }
  294. void g_dual_quat_vec_mul( GVec *r, GDualQuat *dq, GVec *v ) {
  295. g_quat_vec_mul( r, &dq->q, v );
  296. r->x += 2.0 * ( dq->q.w*dq->d.x - dq->q.x*dq->d.w + dq->q.y*dq->d.z - dq->q.z*dq->d.y );
  297. r->y += 2.0 * ( dq->q.w*dq->d.y - dq->q.y*dq->d.w - dq->q.x*dq->d.z + dq->q.z*dq->d.x );
  298. r->z += 2.0 * ( dq->q.w*dq->d.z - dq->q.z*dq->d.w + dq->q.x*dq->d.y - dq->q.y*dq->d.x );
  299. }
  300. void g_dual_quat_normalize( GDualQuat *dq ) {
  301. float d = sqrtf( dq->q.x*dq->q.x + dq->q.y*dq->q.y + dq->q.z*dq->q.z + dq->q.w*dq->q.w );
  302. if( d >= 0.00001 ) {
  303. d = 1/d;
  304. dq->q.x *= d;
  305. dq->q.y *= d;
  306. dq->q.z *= d;
  307. dq->q.w *= d;
  308. dq->d.x *= d;
  309. dq->d.y *= d;
  310. dq->d.z *= d;
  311. dq->d.w *= d;
  312. } else {
  313. *dq = (GDualQuat){{.0, .0, .0, 1.0}, {.0, .0, .0, .0}};
  314. }
  315. }