Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Matrix.cpp 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. /*================================================================
  3. *
  4. * Project : Freyja
  5. * Author : Terry 'Mongoose' Hendrix II
  6. * Website : http://www.westga.edu/~stu7440/
  7. * Email : stu7440@westga.edu
  8. * Object : Matrix
  9. * License : No use w/o permission (C) 2002 Mongoose
  10. * Comments: 3d Matrix class
  11. *
  12. *
  13. * This file was generated using Mongoose's C++
  14. * template generator script. <stu7440@westga.edu>
  15. *
  16. *-- History -------------------------------------------------
  17. *
  18. * 2002.05.11:
  19. * Mongoose - Created
  20. =================================================================*/
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include <Matrix.h>
  24. ////////////////////////////////////////////////////////////
  25. // Constructors
  26. ////////////////////////////////////////////////////////////
  27. Matrix::Matrix()
  28. {
  29. setIdentity();
  30. }
  31. Matrix::Matrix(matrix_t m)
  32. {
  33. setMatrix(m);
  34. }
  35. Matrix::Matrix(Quaternion &q)
  36. {
  37. matrix_t m;
  38. q.getMatrix(m);
  39. setMatrix(m);
  40. }
  41. Matrix::~Matrix()
  42. {
  43. }
  44. ////////////////////////////////////////////////////////////
  45. // Public Accessors
  46. ////////////////////////////////////////////////////////////
  47. bool Matrix::getInvert(matrix_t out)
  48. {
  49. matrix_t m;
  50. #ifdef COLUMN_ORDER
  51. getMatrix(m);
  52. #else
  53. getTransposeMatrix(m);
  54. #endif
  55. /* Mongoose: This code was from a Jeff Lander tutorial which was based
  56. on MESA GL's InvertMatrix */
  57. /* NB. OpenGL Matrices are COLUMN major. */
  58. #define SWAP_ROWS(a, b) { float *_tmp = a; (a)=(b); (b)=_tmp; }
  59. #define MAT(m,r,c) (m)[(c)*4+(r)]
  60. float wtmp[4][8];
  61. float m0, m1, m2, m3, s;
  62. float *r0, *r1, *r2, *r3;
  63. r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
  64. r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1),
  65. r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3),
  66. r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
  67. r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1),
  68. r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3),
  69. r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
  70. r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1),
  71. r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3),
  72. r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
  73. r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1),
  74. r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3),
  75. r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
  76. /* choose pivot - or die */
  77. if (fabs(r3[0])>fabs(r2[0])) SWAP_ROWS(r3, r2);
  78. if (fabs(r2[0])>fabs(r1[0])) SWAP_ROWS(r2, r1);
  79. if (fabs(r1[0])>fabs(r0[0])) SWAP_ROWS(r1, r0);
  80. if (0.0 == r0[0]) return false;
  81. /* eliminate first variable */
  82. m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0];
  83. s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s;
  84. s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s;
  85. s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s;
  86. s = r0[4];
  87. if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; }
  88. s = r0[5];
  89. if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; }
  90. s = r0[6];
  91. if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; }
  92. s = r0[7];
  93. if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; }
  94. /* choose pivot - or die */
  95. if (fabs(r3[1])>fabs(r2[1])) SWAP_ROWS(r3, r2);
  96. if (fabs(r2[1])>fabs(r1[1])) SWAP_ROWS(r2, r1);
  97. if (0.0 == r1[1]) return false;
  98. /* eliminate second variable */
  99. m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1];
  100. r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2];
  101. r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3];
  102. s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; }
  103. s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; }
  104. s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; }
  105. s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; }
  106. /* choose pivot - or die */
  107. if (fabs(r3[2])>fabs(r2[2])) SWAP_ROWS(r3, r2);
  108. if (0.0 == r2[2]) return false;
  109. /* eliminate third variable */
  110. m3 = r3[2]/r2[2];
  111. r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
  112. r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6],
  113. r3[7] -= m3 * r2[7];
  114. /* last check */
  115. if (0.0 == r3[3]) return false;
  116. s = 1.0/r3[3]; /* now back substitute row 3 */
  117. r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s;
  118. m2 = r2[3]; /* now back substitute row 2 */
  119. s = 1.0/r2[2];
  120. r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
  121. r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
  122. m1 = r1[3];
  123. r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
  124. r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
  125. m0 = r0[3];
  126. r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
  127. r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
  128. m1 = r1[2]; /* now back substitute row 1 */
  129. s = 1.0/r1[1];
  130. r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
  131. r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
  132. m0 = r0[2];
  133. r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
  134. r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
  135. m0 = r0[1]; /* now back substitute row 0 */
  136. s = 1.0/r0[0];
  137. r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
  138. r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
  139. MAT(out,0,0) = r0[4];
  140. MAT(out,0,1) = r0[5], MAT(out,0,2) = r0[6];
  141. MAT(out,0,3) = r0[7], MAT(out,1,0) = r1[4];
  142. MAT(out,1,1) = r1[5], MAT(out,1,2) = r1[6];
  143. MAT(out,1,3) = r1[7], MAT(out,2,0) = r2[4];
  144. MAT(out,2,1) = r2[5], MAT(out,2,2) = r2[6];
  145. MAT(out,2,3) = r2[7], MAT(out,3,0) = r3[4];
  146. MAT(out,3,1) = r3[5], MAT(out,3,2) = r3[6];
  147. MAT(out,3,3) = r3[7];
  148. return true;
  149. #undef MAT
  150. #undef SWAP_ROWS
  151. }
  152. void Matrix::getMatrix(matrix_t mat)
  153. {
  154. copy(mMatrix, mat);
  155. }
  156. void Matrix::getTransposeMatrix(matrix_t m)
  157. {
  158. m[ 0]= mMatrix[0]; m[ 1]= mMatrix[4]; m[ 2]= mMatrix[ 8]; m[ 3]=mMatrix[12];
  159. m[ 4]= mMatrix[1]; m[ 5]= mMatrix[5]; m[ 6]= mMatrix[ 9]; m[ 7]=mMatrix[13];
  160. m[ 8]= mMatrix[2]; m[ 9]= mMatrix[6]; m[10]= mMatrix[10]; m[11]=mMatrix[14];
  161. m[12]= mMatrix[3]; m[13]= mMatrix[7]; m[14]= mMatrix[11]; m[15]=mMatrix[15];
  162. }
  163. Matrix Matrix::multiply(const Matrix &a, const Matrix &b)
  164. {
  165. Matrix c;
  166. multiply(a.mMatrix, b.mMatrix, c.mMatrix);
  167. return c;
  168. }
  169. Matrix Matrix::operator *(const Matrix &a)
  170. {
  171. return multiply(a, *this);
  172. }
  173. Vector3d Matrix::operator *(Vector3d v)
  174. {
  175. vec_t x = v.mVec[0], y = v.mVec[1], z = v.mVec[2];
  176. #ifdef COLUMN_ORDER
  177. // Column order
  178. return Vector3d(mMatrix[0]*x + mMatrix[4]*y + mMatrix[ 8]*z + mMatrix[12],
  179. mMatrix[1]*x + mMatrix[5]*y + mMatrix[ 9]*z + mMatrix[13],
  180. mMatrix[2]*x + mMatrix[6]*y + mMatrix[10]*z + mMatrix[14]);
  181. #else
  182. // Row order
  183. return Vector3d(mMatrix[0]*x + mMatrix[1]*y + mMatrix[ 2]*z + mMatrix[ 3],
  184. mMatrix[4]*x + mMatrix[5]*y + mMatrix[ 6]*z + mMatrix[ 7],
  185. mMatrix[8]*x + mMatrix[9]*y + mMatrix[10]*z + mMatrix[11]);
  186. #endif
  187. }
  188. void Matrix::multiply3v(vec3_t v, vec3_t result)
  189. {
  190. vec_t x = v[0], y = v[1], z = v[2];
  191. result[0] = mMatrix[0]*x + mMatrix[1]*y + mMatrix[ 2]*z + mMatrix[ 3];
  192. result[1] = mMatrix[4]*x + mMatrix[5]*y + mMatrix[ 6]*z + mMatrix[ 7];
  193. result[2] = mMatrix[8]*x + mMatrix[9]*y + mMatrix[10]*z + mMatrix[11];
  194. }
  195. void Matrix::multiply4d(double *v, double *result)
  196. {
  197. double x = v[0], y = v[1], z = v[2], w = v[3];
  198. result[0] = mMatrix[ 0]*x + mMatrix[ 1]*y + mMatrix[ 2]*z + mMatrix[ 3]*w;
  199. result[1] = mMatrix[ 4]*x + mMatrix[ 5]*y + mMatrix[ 6]*z + mMatrix[ 7]*w;
  200. result[2] = mMatrix[ 8]*x + mMatrix[ 9]*y + mMatrix[10]*z + mMatrix[11]*w;
  201. result[3] = mMatrix[12]*x + mMatrix[13]*y + mMatrix[14]*z + mMatrix[15]*w;
  202. }
  203. void Matrix::multiply4v(vec4_t v, vec4_t result)
  204. {
  205. vec_t x = v[0], y = v[1], z = v[2], w = v[3];
  206. result[0] = mMatrix[ 0]*x + mMatrix[ 1]*y + mMatrix[ 2]*z + mMatrix[ 3]*w;
  207. result[1] = mMatrix[ 4]*x + mMatrix[ 5]*y + mMatrix[ 6]*z + mMatrix[ 7]*w;
  208. result[2] = mMatrix[ 8]*x + mMatrix[ 9]*y + mMatrix[10]*z + mMatrix[11]*w;
  209. result[3] = mMatrix[12]*x + mMatrix[13]*y + mMatrix[14]*z + mMatrix[15]*w;
  210. }
  211. void Matrix::print()
  212. {
  213. #ifdef COLUMN_ORDER
  214. printf("{\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n}\n",
  215. mMatrix[0], mMatrix[4], mMatrix[ 8], mMatrix[12],
  216. mMatrix[1], mMatrix[5], mMatrix[ 9], mMatrix[13],
  217. mMatrix[2], mMatrix[6], mMatrix[10], mMatrix[14],
  218. mMatrix[3], mMatrix[7], mMatrix[11], mMatrix[15]);
  219. #else
  220. printf("{\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n}\n",
  221. mMatrix[ 0], mMatrix[ 1], mMatrix[ 2], mMatrix[ 3],
  222. mMatrix[ 4], mMatrix[ 5], mMatrix[ 6], mMatrix[ 7],
  223. mMatrix[ 8], mMatrix[ 9], mMatrix[10], mMatrix[11],
  224. mMatrix[12], mMatrix[13], mMatrix[14], mMatrix[15]);
  225. #endif
  226. }
  227. bool Matrix::isIdentity()
  228. {
  229. // Hhhmm... floating point using direct comparisions
  230. if (mMatrix[ 0] == 1 && mMatrix[ 1] == 0 && mMatrix[ 2] == 0 &&
  231. mMatrix[ 3] == 0 && mMatrix[ 4] == 0 && mMatrix[ 5] == 1 &&
  232. mMatrix[ 6] == 0 && mMatrix[ 7] == 0 && mMatrix[ 8] == 0 &&
  233. mMatrix[ 9] == 0 && mMatrix[10] == 1 && mMatrix[11] == 0 &&
  234. mMatrix[12] == 0 && mMatrix[13] == 0 && mMatrix[14] == 0 &&
  235. mMatrix[15] == 1)
  236. return true;
  237. return false;
  238. }
  239. ////////////////////////////////////////////////////////////
  240. // Public Mutators
  241. ////////////////////////////////////////////////////////////
  242. void Matrix::setMatrix(matrix_t mat)
  243. {
  244. copy(mat, mMatrix);
  245. }
  246. void Matrix::setIdentity()
  247. {
  248. mMatrix[ 0] = 1; mMatrix[ 1] = 0; mMatrix[ 2] = 0; mMatrix[ 3] = 0;
  249. mMatrix[ 4] = 0; mMatrix[ 5] = 1; mMatrix[ 6] = 0; mMatrix[ 7] = 0;
  250. mMatrix[ 8] = 0; mMatrix[ 9] = 0; mMatrix[10] = 1; mMatrix[11] = 0;
  251. mMatrix[12] = 0; mMatrix[13] = 0; mMatrix[14] = 0; mMatrix[15] = 1;
  252. }
  253. void Matrix::scale(const vec_t *xyz)
  254. {
  255. scale(xyz[0], xyz[1], xyz[2]);
  256. }
  257. void Matrix::scale(vec_t sx, vec_t sy, vec_t sz)
  258. {
  259. matrix_t smatrix;
  260. matrix_t tmp;
  261. smatrix[ 0] = sx;smatrix[ 1] = 0; smatrix[ 2] = 0; smatrix[ 3] = 0;
  262. smatrix[ 4] = 0; smatrix[ 5] = sy;smatrix[ 6] = 0; smatrix[ 7] = 0;
  263. smatrix[ 8] = 0; smatrix[ 9] = 0; smatrix[10] = sz;smatrix[11] = 0;
  264. smatrix[12] = 0; smatrix[13] = 0; smatrix[14] = 0; smatrix[15] = 1;
  265. copy(mMatrix, tmp);
  266. multiply(tmp, smatrix, mMatrix);
  267. }
  268. void Matrix::rotate(const vec_t *xyz)
  269. {
  270. rotate(xyz[0], xyz[1], xyz[2]);
  271. }
  272. void Matrix::rotate(vec_t ax, vec_t ay, vec_t az)
  273. {
  274. matrix_t xmat, ymat, zmat, tmp, tmp2;
  275. xmat[ 0]=1; xmat[ 1]=0; xmat[ 2]=0; xmat[ 3]=0;
  276. xmat[ 4]=0; xmat[ 5]=cos(ax); xmat[ 6]=sin(ax); xmat[ 7]=0;
  277. xmat[ 8]=0; xmat[ 9]=-sin(ax); xmat[10]=cos(ax); xmat[11]=0;
  278. xmat[12]=0; xmat[13]=0; xmat[14]=0; xmat[15]=1;
  279. ymat[ 0]=cos(ay); ymat[ 1]=0; ymat[ 2]=-sin(ay); ymat[ 3]=0;
  280. ymat[ 4]=0; ymat[ 5]=1; ymat[ 6]=0; ymat[ 7]=0;
  281. ymat[ 8]=sin(ay); ymat[ 9]=0; ymat[10]=cos(ay); ymat[11]=0;
  282. ymat[12]=0; ymat[13]=0; ymat[14]=0; ymat[15]=1;
  283. zmat[ 0]=cos(az); zmat[ 1]=sin(az); zmat[ 2]=0; zmat[ 3]=0;
  284. zmat[ 4]=-sin(az); zmat[ 5]=cos(az); zmat[ 6]=0; zmat[ 7]=0;
  285. zmat[ 8]=0; zmat[ 9]=0; zmat[10]=1; zmat[11]=0;
  286. zmat[12]=0; zmat[13]=0; zmat[14]=0; zmat[15]=1;
  287. multiply(mMatrix, ymat, tmp);
  288. multiply(tmp, xmat, tmp2);
  289. multiply(tmp2, zmat, mMatrix);
  290. }
  291. void Matrix::translate(const vec_t *xyz)
  292. {
  293. translate(xyz[0], xyz[1], xyz[2]);
  294. }
  295. void Matrix::translate(vec_t tx, vec_t ty, vec_t tz)
  296. {
  297. matrix_t tmat, tmp;
  298. tmat[ 0]=1; tmat[ 1]=0; tmat[ 2]=0; tmat[ 3]=0;
  299. tmat[ 4]=0; tmat[ 5]=1; tmat[ 6]=0; tmat[ 7]=0;
  300. tmat[ 8]=0; tmat[ 9]=0; tmat[10]=1; tmat[11]=0;
  301. tmat[12]=tx; tmat[13]=ty; tmat[14]=tz; tmat[15]=1;
  302. copy(mMatrix, tmp);
  303. multiply(tmp, tmat, mMatrix);
  304. }
  305. ////////////////////////////////////////////////////////////
  306. // Private Accessors
  307. ////////////////////////////////////////////////////////////
  308. ////////////////////////////////////////////////////////////
  309. // Private Mutators
  310. ////////////////////////////////////////////////////////////
  311. void Matrix::copy(matrix_t source, matrix_t dest)
  312. {
  313. #ifdef FASTER_MATRIX
  314. memcpy(dest, source, sizeof(matrix_t));
  315. #else
  316. dest[ 0] = source[ 0];
  317. dest[ 1] = source[ 1];
  318. dest[ 2] = source[ 2];
  319. dest[ 3] = source[ 3];
  320. dest[ 4] = source[ 4];
  321. dest[ 5] = source[ 5];
  322. dest[ 6] = source[ 6];
  323. dest[ 7] = source[ 7];
  324. dest[ 8] = source[8];
  325. dest[ 9] = source[9];
  326. dest[10] = source[10];
  327. dest[11] = source[11];
  328. dest[12] = source[12];
  329. dest[13] = source[13];
  330. dest[14] = source[14];
  331. dest[15] = source[15];
  332. #endif
  333. }
  334. void Matrix::multiply(const matrix_t a, const matrix_t b, matrix_t result)
  335. {
  336. /* Generated code for matrix mult
  337. * Code used:
  338. // char order is argument
  339. int i, j, k;
  340. if (order == 'r')
  341. {
  342. printf("// Row order\n");
  343. }
  344. else
  345. {
  346. printf("// Column order\n");
  347. }
  348. for (i = 0; i < 4; ++i)
  349. {
  350. for (j = 0; j < 4; ++j)
  351. {
  352. if (order == 'r')
  353. {
  354. printf("result[%2i] = ", j+i*4);
  355. }
  356. else
  357. {
  358. printf("result[%2i] = ", j+i*4);
  359. }
  360. for (k = 0; k < 4; ++k)
  361. {
  362. if (order == 'r')
  363. {
  364. printf("a[%2i] * b[%2i]%s",
  365. k+i*4, j+k*4, (k == 3) ? ";\n" : " + ");
  366. }
  367. else
  368. {
  369. printf("a[%2i] * b[%2i]%s",
  370. i+k*4, k+j*4, (k == 3) ? ";\n" : " + ");
  371. }
  372. //sum+=(elements[i+k*4]*m.elements[k+j*4]);
  373. }
  374. //result.elements[i+j*4]=sum;
  375. }
  376. printf("\n");
  377. }
  378. printf("\n");
  379. printf("// Transpose\n");
  380. for(i = 0; i < 4; ++i)
  381. {
  382. for (j = 0; j < 4; ++j)
  383. {
  384. printf("a[%2i] = b[%2i]%s",
  385. j+i*4, i+j*4, (j == 3) ? ";\n" : "; ");
  386. }
  387. }
  388. * was in test/Matrix.cpp
  389. */
  390. #ifdef COLUMN_ORDER
  391. /* Column order */
  392. result[ 0] = a[ 0] * b[ 0] + a[ 4] * b[ 1] + a[ 8] * b[ 2] + a[12] * b[ 3];
  393. result[ 1] = a[ 0] * b[ 4] + a[ 4] * b[ 5] + a[ 8] * b[ 6] + a[12] * b[ 7];
  394. result[ 2] = a[ 0] * b[ 8] + a[ 4] * b[ 9] + a[ 8] * b[10] + a[12] * b[11];
  395. result[ 3] = a[ 0] * b[12] + a[ 4] * b[13] + a[ 8] * b[14] + a[12] * b[15];
  396. result[ 4] = a[ 1] * b[ 0] + a[ 5] * b[ 1] + a[ 9] * b[ 2] + a[13] * b[ 3];
  397. result[ 5] = a[ 1] * b[ 4] + a[ 5] * b[ 5] + a[ 9] * b[ 6] + a[13] * b[ 7];
  398. result[ 6] = a[ 1] * b[ 8] + a[ 5] * b[ 9] + a[ 9] * b[10] + a[13] * b[11];
  399. result[ 7] = a[ 1] * b[12] + a[ 5] * b[13] + a[ 9] * b[14] + a[13] * b[15];
  400. result[ 8] = a[ 2] * b[ 0] + a[ 6] * b[ 1] + a[10] * b[ 2] + a[14] * b[ 3];
  401. result[ 9] = a[ 2] * b[ 4] + a[ 6] * b[ 5] + a[10] * b[ 6] + a[14] * b[ 7];
  402. result[10] = a[ 2] * b[ 8] + a[ 6] * b[ 9] + a[10] * b[10] + a[14] * b[11];
  403. result[11] = a[ 2] * b[12] + a[ 6] * b[13] + a[10] * b[14] + a[14] * b[15];
  404. result[12] = a[ 3] * b[ 0] + a[ 7] * b[ 1] + a[11] * b[ 2] + a[15] * b[ 3];
  405. result[13] = a[ 3] * b[ 4] + a[ 7] * b[ 5] + a[11] * b[ 6] + a[15] * b[ 7];
  406. result[14] = a[ 3] * b[ 8] + a[ 7] * b[ 9] + a[11] * b[10] + a[15] * b[11];
  407. result[15] = a[ 3] * b[12] + a[ 7] * b[13] + a[11] * b[14] + a[15] * b[15];
  408. #else
  409. /* Row order */
  410. result[ 0] = a[ 0] * b[ 0] + a[ 1] * b[ 4] + a[ 2] * b[ 8] + a[ 3] * b[12];
  411. result[ 1] = a[ 0] * b[ 1] + a[ 1] * b[ 5] + a[ 2] * b[ 9] + a[ 3] * b[13];
  412. result[ 2] = a[ 0] * b[ 2] + a[ 1] * b[ 6] + a[ 2] * b[10] + a[ 3] * b[14];
  413. result[ 3] = a[ 0] * b[ 3] + a[ 1] * b[ 7] + a[ 2] * b[11] + a[ 3] * b[15];
  414. result[ 4] = a[ 4] * b[ 0] + a[ 5] * b[ 4] + a[ 6] * b[ 8] + a[ 7] * b[12];
  415. result[ 5] = a[ 4] * b[ 1] + a[ 5] * b[ 5] + a[ 6] * b[ 9] + a[ 7] * b[13];
  416. result[ 6] = a[ 4] * b[ 2] + a[ 5] * b[ 6] + a[ 6] * b[10] + a[ 7] * b[14];
  417. result[ 7] = a[ 4] * b[ 3] + a[ 5] * b[ 7] + a[ 6] * b[11] + a[ 7] * b[15];
  418. result[ 8] = a[ 8] * b[ 0] + a[ 9] * b[ 4] + a[10] * b[ 8] + a[11] * b[12];
  419. result[ 9] = a[ 8] * b[ 1] + a[ 9] * b[ 5] + a[10] * b[ 9] + a[11] * b[13];
  420. result[10] = a[ 8] * b[ 2] + a[ 9] * b[ 6] + a[10] * b[10] + a[11] * b[14];
  421. result[11] = a[ 8] * b[ 3] + a[ 9] * b[ 7] + a[10] * b[11] + a[11] * b[15];
  422. result[12] = a[12] * b[ 0] + a[13] * b[ 4] + a[14] * b[ 8] + a[15] * b[12];
  423. result[13] = a[12] * b[ 1] + a[13] * b[ 5] + a[14] * b[ 9] + a[15] * b[13];
  424. result[14] = a[12] * b[ 2] + a[13] * b[ 6] + a[14] * b[10] + a[15] * b[14];
  425. result[15] = a[12] * b[ 3] + a[13] * b[ 7] + a[14] * b[11] + a[15] * b[15];
  426. #endif
  427. }