Source: mat4.js

  1. import * as glMatrix from "./common.js";
  2. /**
  3. * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.
  4. * @module mat4
  5. */
  6. /**
  7. * Creates a new identity mat4
  8. *
  9. * @returns {mat4} a new 4x4 matrix
  10. */
  11. export function create() {
  12. let out = new glMatrix.ARRAY_TYPE(16);
  13. if(glMatrix.ARRAY_TYPE != Float32Array) {
  14. out[1] = 0;
  15. out[2] = 0;
  16. out[3] = 0;
  17. out[4] = 0;
  18. out[6] = 0;
  19. out[7] = 0;
  20. out[8] = 0;
  21. out[9] = 0;
  22. out[11] = 0;
  23. out[12] = 0;
  24. out[13] = 0;
  25. out[14] = 0;
  26. }
  27. out[0] = 1;
  28. out[5] = 1;
  29. out[10] = 1;
  30. out[15] = 1;
  31. return out;
  32. }
  33. /**
  34. * Creates a new mat4 initialized with values from an existing matrix
  35. *
  36. * @param {mat4} a matrix to clone
  37. * @returns {mat4} a new 4x4 matrix
  38. */
  39. export function clone(a) {
  40. let out = new glMatrix.ARRAY_TYPE(16);
  41. out[0] = a[0];
  42. out[1] = a[1];
  43. out[2] = a[2];
  44. out[3] = a[3];
  45. out[4] = a[4];
  46. out[5] = a[5];
  47. out[6] = a[6];
  48. out[7] = a[7];
  49. out[8] = a[8];
  50. out[9] = a[9];
  51. out[10] = a[10];
  52. out[11] = a[11];
  53. out[12] = a[12];
  54. out[13] = a[13];
  55. out[14] = a[14];
  56. out[15] = a[15];
  57. return out;
  58. }
  59. /**
  60. * Copy the values from one mat4 to another
  61. *
  62. * @param {mat4} out the receiving matrix
  63. * @param {mat4} a the source matrix
  64. * @returns {mat4} out
  65. */
  66. export function copy(out, a) {
  67. out[0] = a[0];
  68. out[1] = a[1];
  69. out[2] = a[2];
  70. out[3] = a[3];
  71. out[4] = a[4];
  72. out[5] = a[5];
  73. out[6] = a[6];
  74. out[7] = a[7];
  75. out[8] = a[8];
  76. out[9] = a[9];
  77. out[10] = a[10];
  78. out[11] = a[11];
  79. out[12] = a[12];
  80. out[13] = a[13];
  81. out[14] = a[14];
  82. out[15] = a[15];
  83. return out;
  84. }
  85. /**
  86. * Create a new mat4 with the given values
  87. *
  88. * @param {Number} m00 Component in column 0, row 0 position (index 0)
  89. * @param {Number} m01 Component in column 0, row 1 position (index 1)
  90. * @param {Number} m02 Component in column 0, row 2 position (index 2)
  91. * @param {Number} m03 Component in column 0, row 3 position (index 3)
  92. * @param {Number} m10 Component in column 1, row 0 position (index 4)
  93. * @param {Number} m11 Component in column 1, row 1 position (index 5)
  94. * @param {Number} m12 Component in column 1, row 2 position (index 6)
  95. * @param {Number} m13 Component in column 1, row 3 position (index 7)
  96. * @param {Number} m20 Component in column 2, row 0 position (index 8)
  97. * @param {Number} m21 Component in column 2, row 1 position (index 9)
  98. * @param {Number} m22 Component in column 2, row 2 position (index 10)
  99. * @param {Number} m23 Component in column 2, row 3 position (index 11)
  100. * @param {Number} m30 Component in column 3, row 0 position (index 12)
  101. * @param {Number} m31 Component in column 3, row 1 position (index 13)
  102. * @param {Number} m32 Component in column 3, row 2 position (index 14)
  103. * @param {Number} m33 Component in column 3, row 3 position (index 15)
  104. * @returns {mat4} A new mat4
  105. */
  106. export function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
  107. let out = new glMatrix.ARRAY_TYPE(16);
  108. out[0] = m00;
  109. out[1] = m01;
  110. out[2] = m02;
  111. out[3] = m03;
  112. out[4] = m10;
  113. out[5] = m11;
  114. out[6] = m12;
  115. out[7] = m13;
  116. out[8] = m20;
  117. out[9] = m21;
  118. out[10] = m22;
  119. out[11] = m23;
  120. out[12] = m30;
  121. out[13] = m31;
  122. out[14] = m32;
  123. out[15] = m33;
  124. return out;
  125. }
  126. /**
  127. * Set the components of a mat4 to the given values
  128. *
  129. * @param {mat4} out the receiving matrix
  130. * @param {Number} m00 Component in column 0, row 0 position (index 0)
  131. * @param {Number} m01 Component in column 0, row 1 position (index 1)
  132. * @param {Number} m02 Component in column 0, row 2 position (index 2)
  133. * @param {Number} m03 Component in column 0, row 3 position (index 3)
  134. * @param {Number} m10 Component in column 1, row 0 position (index 4)
  135. * @param {Number} m11 Component in column 1, row 1 position (index 5)
  136. * @param {Number} m12 Component in column 1, row 2 position (index 6)
  137. * @param {Number} m13 Component in column 1, row 3 position (index 7)
  138. * @param {Number} m20 Component in column 2, row 0 position (index 8)
  139. * @param {Number} m21 Component in column 2, row 1 position (index 9)
  140. * @param {Number} m22 Component in column 2, row 2 position (index 10)
  141. * @param {Number} m23 Component in column 2, row 3 position (index 11)
  142. * @param {Number} m30 Component in column 3, row 0 position (index 12)
  143. * @param {Number} m31 Component in column 3, row 1 position (index 13)
  144. * @param {Number} m32 Component in column 3, row 2 position (index 14)
  145. * @param {Number} m33 Component in column 3, row 3 position (index 15)
  146. * @returns {mat4} out
  147. */
  148. export function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
  149. out[0] = m00;
  150. out[1] = m01;
  151. out[2] = m02;
  152. out[3] = m03;
  153. out[4] = m10;
  154. out[5] = m11;
  155. out[6] = m12;
  156. out[7] = m13;
  157. out[8] = m20;
  158. out[9] = m21;
  159. out[10] = m22;
  160. out[11] = m23;
  161. out[12] = m30;
  162. out[13] = m31;
  163. out[14] = m32;
  164. out[15] = m33;
  165. return out;
  166. }
  167. /**
  168. * Set a mat4 to the identity matrix
  169. *
  170. * @param {mat4} out the receiving matrix
  171. * @returns {mat4} out
  172. */
  173. export function identity(out) {
  174. out[0] = 1;
  175. out[1] = 0;
  176. out[2] = 0;
  177. out[3] = 0;
  178. out[4] = 0;
  179. out[5] = 1;
  180. out[6] = 0;
  181. out[7] = 0;
  182. out[8] = 0;
  183. out[9] = 0;
  184. out[10] = 1;
  185. out[11] = 0;
  186. out[12] = 0;
  187. out[13] = 0;
  188. out[14] = 0;
  189. out[15] = 1;
  190. return out;
  191. }
  192. /**
  193. * Transpose the values of a mat4
  194. *
  195. * @param {mat4} out the receiving matrix
  196. * @param {mat4} a the source matrix
  197. * @returns {mat4} out
  198. */
  199. export function transpose(out, a) {
  200. // If we are transposing ourselves we can skip a few steps but have to cache some values
  201. if (out === a) {
  202. let a01 = a[1], a02 = a[2], a03 = a[3];
  203. let a12 = a[6], a13 = a[7];
  204. let a23 = a[11];
  205. out[1] = a[4];
  206. out[2] = a[8];
  207. out[3] = a[12];
  208. out[4] = a01;
  209. out[6] = a[9];
  210. out[7] = a[13];
  211. out[8] = a02;
  212. out[9] = a12;
  213. out[11] = a[14];
  214. out[12] = a03;
  215. out[13] = a13;
  216. out[14] = a23;
  217. } else {
  218. out[0] = a[0];
  219. out[1] = a[4];
  220. out[2] = a[8];
  221. out[3] = a[12];
  222. out[4] = a[1];
  223. out[5] = a[5];
  224. out[6] = a[9];
  225. out[7] = a[13];
  226. out[8] = a[2];
  227. out[9] = a[6];
  228. out[10] = a[10];
  229. out[11] = a[14];
  230. out[12] = a[3];
  231. out[13] = a[7];
  232. out[14] = a[11];
  233. out[15] = a[15];
  234. }
  235. return out;
  236. }
  237. /**
  238. * Inverts a mat4
  239. *
  240. * @param {mat4} out the receiving matrix
  241. * @param {mat4} a the source matrix
  242. * @returns {mat4} out
  243. */
  244. export function invert(out, a) {
  245. let a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
  246. let a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
  247. let a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
  248. let a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  249. let b00 = a00 * a11 - a01 * a10;
  250. let b01 = a00 * a12 - a02 * a10;
  251. let b02 = a00 * a13 - a03 * a10;
  252. let b03 = a01 * a12 - a02 * a11;
  253. let b04 = a01 * a13 - a03 * a11;
  254. let b05 = a02 * a13 - a03 * a12;
  255. let b06 = a20 * a31 - a21 * a30;
  256. let b07 = a20 * a32 - a22 * a30;
  257. let b08 = a20 * a33 - a23 * a30;
  258. let b09 = a21 * a32 - a22 * a31;
  259. let b10 = a21 * a33 - a23 * a31;
  260. let b11 = a22 * a33 - a23 * a32;
  261. // Calculate the determinant
  262. let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  263. if (!det) {
  264. return null;
  265. }
  266. det = 1.0 / det;
  267. out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
  268. out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
  269. out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
  270. out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
  271. out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
  272. out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
  273. out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
  274. out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
  275. out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  276. out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  277. out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  278. out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
  279. out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
  280. out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
  281. out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
  282. out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  283. return out;
  284. }
  285. /**
  286. * Calculates the adjugate of a mat4
  287. *
  288. * @param {mat4} out the receiving matrix
  289. * @param {mat4} a the source matrix
  290. * @returns {mat4} out
  291. */
  292. export function adjoint(out, a) {
  293. let a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
  294. let a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
  295. let a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
  296. let a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  297. out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
  298. out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
  299. out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
  300. out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
  301. out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
  302. out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
  303. out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
  304. out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
  305. out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
  306. out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
  307. out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
  308. out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
  309. out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
  310. out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
  311. out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
  312. out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
  313. return out;
  314. }
  315. /**
  316. * Calculates the determinant of a mat4
  317. *
  318. * @param {mat4} a the source matrix
  319. * @returns {Number} determinant of a
  320. */
  321. export function determinant(a) {
  322. let a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
  323. let a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
  324. let a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
  325. let a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  326. let b00 = a00 * a11 - a01 * a10;
  327. let b01 = a00 * a12 - a02 * a10;
  328. let b02 = a00 * a13 - a03 * a10;
  329. let b03 = a01 * a12 - a02 * a11;
  330. let b04 = a01 * a13 - a03 * a11;
  331. let b05 = a02 * a13 - a03 * a12;
  332. let b06 = a20 * a31 - a21 * a30;
  333. let b07 = a20 * a32 - a22 * a30;
  334. let b08 = a20 * a33 - a23 * a30;
  335. let b09 = a21 * a32 - a22 * a31;
  336. let b10 = a21 * a33 - a23 * a31;
  337. let b11 = a22 * a33 - a23 * a32;
  338. // Calculate the determinant
  339. return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  340. }
  341. /**
  342. * Multiplies two mat4s
  343. *
  344. * @param {mat4} out the receiving matrix
  345. * @param {mat4} a the first operand
  346. * @param {mat4} b the second operand
  347. * @returns {mat4} out
  348. */
  349. export function multiply(out, a, b) {
  350. let a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
  351. let a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
  352. let a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
  353. let a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  354. // Cache only the current line of the second matrix
  355. let b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
  356. out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
  357. out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
  358. out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
  359. out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  360. b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
  361. out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
  362. out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
  363. out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
  364. out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  365. b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
  366. out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
  367. out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
  368. out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
  369. out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  370. b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
  371. out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
  372. out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
  373. out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
  374. out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  375. return out;
  376. }
  377. /**
  378. * Translate a mat4 by the given vector
  379. *
  380. * @param {mat4} out the receiving matrix
  381. * @param {mat4} a the matrix to translate
  382. * @param {vec3} v vector to translate by
  383. * @returns {mat4} out
  384. */
  385. export function translate(out, a, v) {
  386. let x = v[0], y = v[1], z = v[2];
  387. let a00, a01, a02, a03;
  388. let a10, a11, a12, a13;
  389. let a20, a21, a22, a23;
  390. if (a === out) {
  391. out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
  392. out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
  393. out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
  394. out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
  395. } else {
  396. a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
  397. a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
  398. a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
  399. out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
  400. out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
  401. out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
  402. out[12] = a00 * x + a10 * y + a20 * z + a[12];
  403. out[13] = a01 * x + a11 * y + a21 * z + a[13];
  404. out[14] = a02 * x + a12 * y + a22 * z + a[14];
  405. out[15] = a03 * x + a13 * y + a23 * z + a[15];
  406. }
  407. return out;
  408. }
  409. /**
  410. * Scales the mat4 by the dimensions in the given vec3 not using vectorization
  411. *
  412. * @param {mat4} out the receiving matrix
  413. * @param {mat4} a the matrix to scale
  414. * @param {vec3} v the vec3 to scale the matrix by
  415. * @returns {mat4} out
  416. **/
  417. export function scale(out, a, v) {
  418. let x = v[0], y = v[1], z = v[2];
  419. out[0] = a[0] * x;
  420. out[1] = a[1] * x;
  421. out[2] = a[2] * x;
  422. out[3] = a[3] * x;
  423. out[4] = a[4] * y;
  424. out[5] = a[5] * y;
  425. out[6] = a[6] * y;
  426. out[7] = a[7] * y;
  427. out[8] = a[8] * z;
  428. out[9] = a[9] * z;
  429. out[10] = a[10] * z;
  430. out[11] = a[11] * z;
  431. out[12] = a[12];
  432. out[13] = a[13];
  433. out[14] = a[14];
  434. out[15] = a[15];
  435. return out;
  436. }
  437. /**
  438. * Rotates a mat4 by the given angle around the given axis
  439. *
  440. * @param {mat4} out the receiving matrix
  441. * @param {mat4} a the matrix to rotate
  442. * @param {Number} rad the angle to rotate the matrix by
  443. * @param {vec3} axis the axis to rotate around
  444. * @returns {mat4} out
  445. */
  446. export function rotate(out, a, rad, axis) {
  447. let x = axis[0], y = axis[1], z = axis[2];
  448. let len = Math.sqrt(x * x + y * y + z * z);
  449. let s, c, t;
  450. let a00, a01, a02, a03;
  451. let a10, a11, a12, a13;
  452. let a20, a21, a22, a23;
  453. let b00, b01, b02;
  454. let b10, b11, b12;
  455. let b20, b21, b22;
  456. if (len < glMatrix.EPSILON) { return null; }
  457. len = 1 / len;
  458. x *= len;
  459. y *= len;
  460. z *= len;
  461. s = Math.sin(rad);
  462. c = Math.cos(rad);
  463. t = 1 - c;
  464. a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
  465. a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
  466. a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
  467. // Construct the elements of the rotation matrix
  468. b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
  469. b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
  470. b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
  471. // Perform rotation-specific matrix multiplication
  472. out[0] = a00 * b00 + a10 * b01 + a20 * b02;
  473. out[1] = a01 * b00 + a11 * b01 + a21 * b02;
  474. out[2] = a02 * b00 + a12 * b01 + a22 * b02;
  475. out[3] = a03 * b00 + a13 * b01 + a23 * b02;
  476. out[4] = a00 * b10 + a10 * b11 + a20 * b12;
  477. out[5] = a01 * b10 + a11 * b11 + a21 * b12;
  478. out[6] = a02 * b10 + a12 * b11 + a22 * b12;
  479. out[7] = a03 * b10 + a13 * b11 + a23 * b12;
  480. out[8] = a00 * b20 + a10 * b21 + a20 * b22;
  481. out[9] = a01 * b20 + a11 * b21 + a21 * b22;
  482. out[10] = a02 * b20 + a12 * b21 + a22 * b22;
  483. out[11] = a03 * b20 + a13 * b21 + a23 * b22;
  484. if (a !== out) { // If the source and destination differ, copy the unchanged last row
  485. out[12] = a[12];
  486. out[13] = a[13];
  487. out[14] = a[14];
  488. out[15] = a[15];
  489. }
  490. return out;
  491. }
  492. /**
  493. * Rotates a matrix by the given angle around the X axis
  494. *
  495. * @param {mat4} out the receiving matrix
  496. * @param {mat4} a the matrix to rotate
  497. * @param {Number} rad the angle to rotate the matrix by
  498. * @returns {mat4} out
  499. */
  500. export function rotateX(out, a, rad) {
  501. let s = Math.sin(rad);
  502. let c = Math.cos(rad);
  503. let a10 = a[4];
  504. let a11 = a[5];
  505. let a12 = a[6];
  506. let a13 = a[7];
  507. let a20 = a[8];
  508. let a21 = a[9];
  509. let a22 = a[10];
  510. let a23 = a[11];
  511. if (a !== out) { // If the source and destination differ, copy the unchanged rows
  512. out[0] = a[0];
  513. out[1] = a[1];
  514. out[2] = a[2];
  515. out[3] = a[3];
  516. out[12] = a[12];
  517. out[13] = a[13];
  518. out[14] = a[14];
  519. out[15] = a[15];
  520. }
  521. // Perform axis-specific matrix multiplication
  522. out[4] = a10 * c + a20 * s;
  523. out[5] = a11 * c + a21 * s;
  524. out[6] = a12 * c + a22 * s;
  525. out[7] = a13 * c + a23 * s;
  526. out[8] = a20 * c - a10 * s;
  527. out[9] = a21 * c - a11 * s;
  528. out[10] = a22 * c - a12 * s;
  529. out[11] = a23 * c - a13 * s;
  530. return out;
  531. }
  532. /**
  533. * Rotates a matrix by the given angle around the Y axis
  534. *
  535. * @param {mat4} out the receiving matrix
  536. * @param {mat4} a the matrix to rotate
  537. * @param {Number} rad the angle to rotate the matrix by
  538. * @returns {mat4} out
  539. */
  540. export function rotateY(out, a, rad) {
  541. let s = Math.sin(rad);
  542. let c = Math.cos(rad);
  543. let a00 = a[0];
  544. let a01 = a[1];
  545. let a02 = a[2];
  546. let a03 = a[3];
  547. let a20 = a[8];
  548. let a21 = a[9];
  549. let a22 = a[10];
  550. let a23 = a[11];
  551. if (a !== out) { // If the source and destination differ, copy the unchanged rows
  552. out[4] = a[4];
  553. out[5] = a[5];
  554. out[6] = a[6];
  555. out[7] = a[7];
  556. out[12] = a[12];
  557. out[13] = a[13];
  558. out[14] = a[14];
  559. out[15] = a[15];
  560. }
  561. // Perform axis-specific matrix multiplication
  562. out[0] = a00 * c - a20 * s;
  563. out[1] = a01 * c - a21 * s;
  564. out[2] = a02 * c - a22 * s;
  565. out[3] = a03 * c - a23 * s;
  566. out[8] = a00 * s + a20 * c;
  567. out[9] = a01 * s + a21 * c;
  568. out[10] = a02 * s + a22 * c;
  569. out[11] = a03 * s + a23 * c;
  570. return out;
  571. }
  572. /**
  573. * Rotates a matrix by the given angle around the Z axis
  574. *
  575. * @param {mat4} out the receiving matrix
  576. * @param {mat4} a the matrix to rotate
  577. * @param {Number} rad the angle to rotate the matrix by
  578. * @returns {mat4} out
  579. */
  580. export function rotateZ(out, a, rad) {
  581. let s = Math.sin(rad);
  582. let c = Math.cos(rad);
  583. let a00 = a[0];
  584. let a01 = a[1];
  585. let a02 = a[2];
  586. let a03 = a[3];
  587. let a10 = a[4];
  588. let a11 = a[5];
  589. let a12 = a[6];
  590. let a13 = a[7];
  591. if (a !== out) { // If the source and destination differ, copy the unchanged last row
  592. out[8] = a[8];
  593. out[9] = a[9];
  594. out[10] = a[10];
  595. out[11] = a[11];
  596. out[12] = a[12];
  597. out[13] = a[13];
  598. out[14] = a[14];
  599. out[15] = a[15];
  600. }
  601. // Perform axis-specific matrix multiplication
  602. out[0] = a00 * c + a10 * s;
  603. out[1] = a01 * c + a11 * s;
  604. out[2] = a02 * c + a12 * s;
  605. out[3] = a03 * c + a13 * s;
  606. out[4] = a10 * c - a00 * s;
  607. out[5] = a11 * c - a01 * s;
  608. out[6] = a12 * c - a02 * s;
  609. out[7] = a13 * c - a03 * s;
  610. return out;
  611. }
  612. /**
  613. * Creates a matrix from a vector translation
  614. * This is equivalent to (but much faster than):
  615. *
  616. * mat4.identity(dest);
  617. * mat4.translate(dest, dest, vec);
  618. *
  619. * @param {mat4} out mat4 receiving operation result
  620. * @param {vec3} v Translation vector
  621. * @returns {mat4} out
  622. */
  623. export function fromTranslation(out, v) {
  624. out[0] = 1;
  625. out[1] = 0;
  626. out[2] = 0;
  627. out[3] = 0;
  628. out[4] = 0;
  629. out[5] = 1;
  630. out[6] = 0;
  631. out[7] = 0;
  632. out[8] = 0;
  633. out[9] = 0;
  634. out[10] = 1;
  635. out[11] = 0;
  636. out[12] = v[0];
  637. out[13] = v[1];
  638. out[14] = v[2];
  639. out[15] = 1;
  640. return out;
  641. }
  642. /**
  643. * Creates a matrix from a vector scaling
  644. * This is equivalent to (but much faster than):
  645. *
  646. * mat4.identity(dest);
  647. * mat4.scale(dest, dest, vec);
  648. *
  649. * @param {mat4} out mat4 receiving operation result
  650. * @param {vec3} v Scaling vector
  651. * @returns {mat4} out
  652. */
  653. export function fromScaling(out, v) {
  654. out[0] = v[0];
  655. out[1] = 0;
  656. out[2] = 0;
  657. out[3] = 0;
  658. out[4] = 0;
  659. out[5] = v[1];
  660. out[6] = 0;
  661. out[7] = 0;
  662. out[8] = 0;
  663. out[9] = 0;
  664. out[10] = v[2];
  665. out[11] = 0;
  666. out[12] = 0;
  667. out[13] = 0;
  668. out[14] = 0;
  669. out[15] = 1;
  670. return out;
  671. }
  672. /**
  673. * Creates a matrix from a given angle around a given axis
  674. * This is equivalent to (but much faster than):
  675. *
  676. * mat4.identity(dest);
  677. * mat4.rotate(dest, dest, rad, axis);
  678. *
  679. * @param {mat4} out mat4 receiving operation result
  680. * @param {Number} rad the angle to rotate the matrix by
  681. * @param {vec3} axis the axis to rotate around
  682. * @returns {mat4} out
  683. */
  684. export function fromRotation(out, rad, axis) {
  685. let x = axis[0], y = axis[1], z = axis[2];
  686. let len = Math.sqrt(x * x + y * y + z * z);
  687. let s, c, t;
  688. if (len < glMatrix.EPSILON) { return null; }
  689. len = 1 / len;
  690. x *= len;
  691. y *= len;
  692. z *= len;
  693. s = Math.sin(rad);
  694. c = Math.cos(rad);
  695. t = 1 - c;
  696. // Perform rotation-specific matrix multiplication
  697. out[0] = x * x * t + c;
  698. out[1] = y * x * t + z * s;
  699. out[2] = z * x * t - y * s;
  700. out[3] = 0;
  701. out[4] = x * y * t - z * s;
  702. out[5] = y * y * t + c;
  703. out[6] = z * y * t + x * s;
  704. out[7] = 0;
  705. out[8] = x * z * t + y * s;
  706. out[9] = y * z * t - x * s;
  707. out[10] = z * z * t + c;
  708. out[11] = 0;
  709. out[12] = 0;
  710. out[13] = 0;
  711. out[14] = 0;
  712. out[15] = 1;
  713. return out;
  714. }
  715. /**
  716. * Creates a matrix from the given angle around the X axis
  717. * This is equivalent to (but much faster than):
  718. *
  719. * mat4.identity(dest);
  720. * mat4.rotateX(dest, dest, rad);
  721. *
  722. * @param {mat4} out mat4 receiving operation result
  723. * @param {Number} rad the angle to rotate the matrix by
  724. * @returns {mat4} out
  725. */
  726. export function fromXRotation(out, rad) {
  727. let s = Math.sin(rad);
  728. let c = Math.cos(rad);
  729. // Perform axis-specific matrix multiplication
  730. out[0] = 1;
  731. out[1] = 0;
  732. out[2] = 0;
  733. out[3] = 0;
  734. out[4] = 0;
  735. out[5] = c;
  736. out[6] = s;
  737. out[7] = 0;
  738. out[8] = 0;
  739. out[9] = -s;
  740. out[10] = c;
  741. out[11] = 0;
  742. out[12] = 0;
  743. out[13] = 0;
  744. out[14] = 0;
  745. out[15] = 1;
  746. return out;
  747. }
  748. /**
  749. * Creates a matrix from the given angle around the Y axis
  750. * This is equivalent to (but much faster than):
  751. *
  752. * mat4.identity(dest);
  753. * mat4.rotateY(dest, dest, rad);
  754. *
  755. * @param {mat4} out mat4 receiving operation result
  756. * @param {Number} rad the angle to rotate the matrix by
  757. * @returns {mat4} out
  758. */
  759. export function fromYRotation(out, rad) {
  760. let s = Math.sin(rad);
  761. let c = Math.cos(rad);
  762. // Perform axis-specific matrix multiplication
  763. out[0] = c;
  764. out[1] = 0;
  765. out[2] = -s;
  766. out[3] = 0;
  767. out[4] = 0;
  768. out[5] = 1;
  769. out[6] = 0;
  770. out[7] = 0;
  771. out[8] = s;
  772. out[9] = 0;
  773. out[10] = c;
  774. out[11] = 0;
  775. out[12] = 0;
  776. out[13] = 0;
  777. out[14] = 0;
  778. out[15] = 1;
  779. return out;
  780. }
  781. /**
  782. * Creates a matrix from the given angle around the Z axis
  783. * This is equivalent to (but much faster than):
  784. *
  785. * mat4.identity(dest);
  786. * mat4.rotateZ(dest, dest, rad);
  787. *
  788. * @param {mat4} out mat4 receiving operation result
  789. * @param {Number} rad the angle to rotate the matrix by
  790. * @returns {mat4} out
  791. */
  792. export function fromZRotation(out, rad) {
  793. let s = Math.sin(rad);
  794. let c = Math.cos(rad);
  795. // Perform axis-specific matrix multiplication
  796. out[0] = c;
  797. out[1] = s;
  798. out[2] = 0;
  799. out[3] = 0;
  800. out[4] = -s;
  801. out[5] = c;
  802. out[6] = 0;
  803. out[7] = 0;
  804. out[8] = 0;
  805. out[9] = 0;
  806. out[10] = 1;
  807. out[11] = 0;
  808. out[12] = 0;
  809. out[13] = 0;
  810. out[14] = 0;
  811. out[15] = 1;
  812. return out;
  813. }
  814. /**
  815. * Creates a matrix from a quaternion rotation and vector translation
  816. * This is equivalent to (but much faster than):
  817. *
  818. * mat4.identity(dest);
  819. * mat4.translate(dest, vec);
  820. * let quatMat = mat4.create();
  821. * quat4.toMat4(quat, quatMat);
  822. * mat4.multiply(dest, quatMat);
  823. *
  824. * @param {mat4} out mat4 receiving operation result
  825. * @param {quat4} q Rotation quaternion
  826. * @param {vec3} v Translation vector
  827. * @returns {mat4} out
  828. */
  829. export function fromRotationTranslation(out, q, v) {
  830. // Quaternion math
  831. let x = q[0], y = q[1], z = q[2], w = q[3];
  832. let x2 = x + x;
  833. let y2 = y + y;
  834. let z2 = z + z;
  835. let xx = x * x2;
  836. let xy = x * y2;
  837. let xz = x * z2;
  838. let yy = y * y2;
  839. let yz = y * z2;
  840. let zz = z * z2;
  841. let wx = w * x2;
  842. let wy = w * y2;
  843. let wz = w * z2;
  844. out[0] = 1 - (yy + zz);
  845. out[1] = xy + wz;
  846. out[2] = xz - wy;
  847. out[3] = 0;
  848. out[4] = xy - wz;
  849. out[5] = 1 - (xx + zz);
  850. out[6] = yz + wx;
  851. out[7] = 0;
  852. out[8] = xz + wy;
  853. out[9] = yz - wx;
  854. out[10] = 1 - (xx + yy);
  855. out[11] = 0;
  856. out[12] = v[0];
  857. out[13] = v[1];
  858. out[14] = v[2];
  859. out[15] = 1;
  860. return out;
  861. }
  862. /**
  863. * Creates a new mat4 from a dual quat.
  864. *
  865. * @param {mat4} out Matrix
  866. * @param {quat2} a Dual Quaternion
  867. * @returns {mat4} mat4 receiving operation result
  868. */
  869. export function fromQuat2(out, a) {
  870. let translation = new glMatrix.ARRAY_TYPE(3);
  871. let bx = -a[0], by = -a[1], bz = -a[2], bw = a[3],
  872. ax = a[4], ay = a[5], az = a[6], aw = a[7];
  873. let magnitude = bx * bx + by * by + bz * bz + bw * bw;
  874. //Only scale if it makes sense
  875. if (magnitude > 0) {
  876. translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;
  877. translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;
  878. translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;
  879. } else {
  880. translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
  881. translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
  882. translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
  883. }
  884. fromRotationTranslation(out, a, translation);
  885. return out;
  886. }
  887. /**
  888. * Returns the translation vector component of a transformation
  889. * matrix. If a matrix is built with fromRotationTranslation,
  890. * the returned vector will be the same as the translation vector
  891. * originally supplied.
  892. * @param {vec3} out Vector to receive translation component
  893. * @param {mat4} mat Matrix to be decomposed (input)
  894. * @return {vec3} out
  895. */
  896. export function getTranslation(out, mat) {
  897. out[0] = mat[12];
  898. out[1] = mat[13];
  899. out[2] = mat[14];
  900. return out;
  901. }
  902. /**
  903. * Returns the scaling factor component of a transformation
  904. * matrix. If a matrix is built with fromRotationTranslationScale
  905. * with a normalized Quaternion paramter, the returned vector will be
  906. * the same as the scaling vector
  907. * originally supplied.
  908. * @param {vec3} out Vector to receive scaling factor component
  909. * @param {mat4} mat Matrix to be decomposed (input)
  910. * @return {vec3} out
  911. */
  912. export function getScaling(out, mat) {
  913. let m11 = mat[0];
  914. let m12 = mat[1];
  915. let m13 = mat[2];
  916. let m21 = mat[4];
  917. let m22 = mat[5];
  918. let m23 = mat[6];
  919. let m31 = mat[8];
  920. let m32 = mat[9];
  921. let m33 = mat[10];
  922. out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);
  923. out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);
  924. out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);
  925. return out;
  926. }
  927. /**
  928. * Returns a quaternion representing the rotational component
  929. * of a transformation matrix. If a matrix is built with
  930. * fromRotationTranslation, the returned quaternion will be the
  931. * same as the quaternion originally supplied.
  932. * @param {quat} out Quaternion to receive the rotation component
  933. * @param {mat4} mat Matrix to be decomposed (input)
  934. * @return {quat} out
  935. */
  936. export function getRotation(out, mat) {
  937. // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
  938. let trace = mat[0] + mat[5] + mat[10];
  939. let S = 0;
  940. if (trace > 0) {
  941. S = Math.sqrt(trace + 1.0) * 2;
  942. out[3] = 0.25 * S;
  943. out[0] = (mat[6] - mat[9]) / S;
  944. out[1] = (mat[8] - mat[2]) / S;
  945. out[2] = (mat[1] - mat[4]) / S;
  946. } else if ((mat[0] > mat[5]) && (mat[0] > mat[10])) {
  947. S = Math.sqrt(1.0 + mat[0] - mat[5] - mat[10]) * 2;
  948. out[3] = (mat[6] - mat[9]) / S;
  949. out[0] = 0.25 * S;
  950. out[1] = (mat[1] + mat[4]) / S;
  951. out[2] = (mat[8] + mat[2]) / S;
  952. } else if (mat[5] > mat[10]) {
  953. S = Math.sqrt(1.0 + mat[5] - mat[0] - mat[10]) * 2;
  954. out[3] = (mat[8] - mat[2]) / S;
  955. out[0] = (mat[1] + mat[4]) / S;
  956. out[1] = 0.25 * S;
  957. out[2] = (mat[6] + mat[9]) / S;
  958. } else {
  959. S = Math.sqrt(1.0 + mat[10] - mat[0] - mat[5]) * 2;
  960. out[3] = (mat[1] - mat[4]) / S;
  961. out[0] = (mat[8] + mat[2]) / S;
  962. out[1] = (mat[6] + mat[9]) / S;
  963. out[2] = 0.25 * S;
  964. }
  965. return out;
  966. }
  967. /**
  968. * Creates a matrix from a quaternion rotation, vector translation and vector scale
  969. * This is equivalent to (but much faster than):
  970. *
  971. * mat4.identity(dest);
  972. * mat4.translate(dest, vec);
  973. * let quatMat = mat4.create();
  974. * quat4.toMat4(quat, quatMat);
  975. * mat4.multiply(dest, quatMat);
  976. * mat4.scale(dest, scale)
  977. *
  978. * @param {mat4} out mat4 receiving operation result
  979. * @param {quat4} q Rotation quaternion
  980. * @param {vec3} v Translation vector
  981. * @param {vec3} s Scaling vector
  982. * @returns {mat4} out
  983. */
  984. export function fromRotationTranslationScale(out, q, v, s) {
  985. // Quaternion math
  986. let x = q[0], y = q[1], z = q[2], w = q[3];
  987. let x2 = x + x;
  988. let y2 = y + y;
  989. let z2 = z + z;
  990. let xx = x * x2;
  991. let xy = x * y2;
  992. let xz = x * z2;
  993. let yy = y * y2;
  994. let yz = y * z2;
  995. let zz = z * z2;
  996. let wx = w * x2;
  997. let wy = w * y2;
  998. let wz = w * z2;
  999. let sx = s[0];
  1000. let sy = s[1];
  1001. let sz = s[2];
  1002. out[0] = (1 - (yy + zz)) * sx;
  1003. out[1] = (xy + wz) * sx;
  1004. out[2] = (xz - wy) * sx;
  1005. out[3] = 0;
  1006. out[4] = (xy - wz) * sy;
  1007. out[5] = (1 - (xx + zz)) * sy;
  1008. out[6] = (yz + wx) * sy;
  1009. out[7] = 0;
  1010. out[8] = (xz + wy) * sz;
  1011. out[9] = (yz - wx) * sz;
  1012. out[10] = (1 - (xx + yy)) * sz;
  1013. out[11] = 0;
  1014. out[12] = v[0];
  1015. out[13] = v[1];
  1016. out[14] = v[2];
  1017. out[15] = 1;
  1018. return out;
  1019. }
  1020. /**
  1021. * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
  1022. * This is equivalent to (but much faster than):
  1023. *
  1024. * mat4.identity(dest);
  1025. * mat4.translate(dest, vec);
  1026. * mat4.translate(dest, origin);
  1027. * let quatMat = mat4.create();
  1028. * quat4.toMat4(quat, quatMat);
  1029. * mat4.multiply(dest, quatMat);
  1030. * mat4.scale(dest, scale)
  1031. * mat4.translate(dest, negativeOrigin);
  1032. *
  1033. * @param {mat4} out mat4 receiving operation result
  1034. * @param {quat4} q Rotation quaternion
  1035. * @param {vec3} v Translation vector
  1036. * @param {vec3} s Scaling vector
  1037. * @param {vec3} o The origin vector around which to scale and rotate
  1038. * @returns {mat4} out
  1039. */
  1040. export function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
  1041. // Quaternion math
  1042. let x = q[0], y = q[1], z = q[2], w = q[3];
  1043. let x2 = x + x;
  1044. let y2 = y + y;
  1045. let z2 = z + z;
  1046. let xx = x * x2;
  1047. let xy = x * y2;
  1048. let xz = x * z2;
  1049. let yy = y * y2;
  1050. let yz = y * z2;
  1051. let zz = z * z2;
  1052. let wx = w * x2;
  1053. let wy = w * y2;
  1054. let wz = w * z2;
  1055. let sx = s[0];
  1056. let sy = s[1];
  1057. let sz = s[2];
  1058. let ox = o[0];
  1059. let oy = o[1];
  1060. let oz = o[2];
  1061. let out0 = (1 - (yy + zz)) * sx;
  1062. let out1 = (xy + wz) * sx;
  1063. let out2 = (xz - wy) * sx;
  1064. let out4 = (xy - wz) * sy;
  1065. let out5 = (1 - (xx + zz)) * sy;
  1066. let out6 = (yz + wx) * sy;
  1067. let out8 = (xz + wy) * sz;
  1068. let out9 = (yz - wx) * sz;
  1069. let out10 = (1 - (xx + yy)) * sz;
  1070. out[0] = out0;
  1071. out[1] = out1;
  1072. out[2] = out2;
  1073. out[3] = 0;
  1074. out[4] = out4;
  1075. out[5] = out5;
  1076. out[6] = out6;
  1077. out[7] = 0;
  1078. out[8] = out8;
  1079. out[9] = out9;
  1080. out[10] = out10;
  1081. out[11] = 0;
  1082. out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);
  1083. out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);
  1084. out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);
  1085. out[15] = 1;
  1086. return out;
  1087. }
  1088. /**
  1089. * Calculates a 4x4 matrix from the given quaternion
  1090. *
  1091. * @param {mat4} out mat4 receiving operation result
  1092. * @param {quat} q Quaternion to create matrix from
  1093. *
  1094. * @returns {mat4} out
  1095. */
  1096. export function fromQuat(out, q) {
  1097. let x = q[0], y = q[1], z = q[2], w = q[3];
  1098. let x2 = x + x;
  1099. let y2 = y + y;
  1100. let z2 = z + z;
  1101. let xx = x * x2;
  1102. let yx = y * x2;
  1103. let yy = y * y2;
  1104. let zx = z * x2;
  1105. let zy = z * y2;
  1106. let zz = z * z2;
  1107. let wx = w * x2;
  1108. let wy = w * y2;
  1109. let wz = w * z2;
  1110. out[0] = 1 - yy - zz;
  1111. out[1] = yx + wz;
  1112. out[2] = zx - wy;
  1113. out[3] = 0;
  1114. out[4] = yx - wz;
  1115. out[5] = 1 - xx - zz;
  1116. out[6] = zy + wx;
  1117. out[7] = 0;
  1118. out[8] = zx + wy;
  1119. out[9] = zy - wx;
  1120. out[10] = 1 - xx - yy;
  1121. out[11] = 0;
  1122. out[12] = 0;
  1123. out[13] = 0;
  1124. out[14] = 0;
  1125. out[15] = 1;
  1126. return out;
  1127. }
  1128. /**
  1129. * Generates a frustum matrix with the given bounds
  1130. *
  1131. * @param {mat4} out mat4 frustum matrix will be written into
  1132. * @param {Number} left Left bound of the frustum
  1133. * @param {Number} right Right bound of the frustum
  1134. * @param {Number} bottom Bottom bound of the frustum
  1135. * @param {Number} top Top bound of the frustum
  1136. * @param {Number} near Near bound of the frustum
  1137. * @param {Number} far Far bound of the frustum
  1138. * @returns {mat4} out
  1139. */
  1140. export function frustum(out, left, right, bottom, top, near, far) {
  1141. let rl = 1 / (right - left);
  1142. let tb = 1 / (top - bottom);
  1143. let nf = 1 / (near - far);
  1144. out[0] = (near * 2) * rl;
  1145. out[1] = 0;
  1146. out[2] = 0;
  1147. out[3] = 0;
  1148. out[4] = 0;
  1149. out[5] = (near * 2) * tb;
  1150. out[6] = 0;
  1151. out[7] = 0;
  1152. out[8] = (right + left) * rl;
  1153. out[9] = (top + bottom) * tb;
  1154. out[10] = (far + near) * nf;
  1155. out[11] = -1;
  1156. out[12] = 0;
  1157. out[13] = 0;
  1158. out[14] = (far * near * 2) * nf;
  1159. out[15] = 0;
  1160. return out;
  1161. }
  1162. /**
  1163. * Generates a perspective projection matrix with the given bounds.
  1164. * Passing null/undefined/no value for far will generate infinite projection matrix.
  1165. *
  1166. * @param {mat4} out mat4 frustum matrix will be written into
  1167. * @param {number} fovy Vertical field of view in radians
  1168. * @param {number} aspect Aspect ratio. typically viewport width/height
  1169. * @param {number} near Near bound of the frustum
  1170. * @param {number} far Far bound of the frustum, can be null or Infinity
  1171. * @returns {mat4} out
  1172. */
  1173. export function perspective(out, fovy, aspect, near, far) {
  1174. let f = 1.0 / Math.tan(fovy / 2), nf;
  1175. out[0] = f / aspect;
  1176. out[1] = 0;
  1177. out[2] = 0;
  1178. out[3] = 0;
  1179. out[4] = 0;
  1180. out[5] = f;
  1181. out[6] = 0;
  1182. out[7] = 0;
  1183. out[8] = 0;
  1184. out[9] = 0;
  1185. out[11] = -1;
  1186. out[12] = 0;
  1187. out[13] = 0;
  1188. out[15] = 0;
  1189. if (far != null && far !== Infinity) {
  1190. nf = 1 / (near - far);
  1191. out[10] = (far + near) * nf;
  1192. out[14] = (2 * far * near) * nf;
  1193. } else {
  1194. out[10] = -1;
  1195. out[14] = -2 * near;
  1196. }
  1197. return out;
  1198. }
  1199. /**
  1200. * Generates a perspective projection matrix with the given field of view.
  1201. * This is primarily useful for generating projection matrices to be used
  1202. * with the still experiemental WebVR API.
  1203. *
  1204. * @param {mat4} out mat4 frustum matrix will be written into
  1205. * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
  1206. * @param {number} near Near bound of the frustum
  1207. * @param {number} far Far bound of the frustum
  1208. * @returns {mat4} out
  1209. */
  1210. export function perspectiveFromFieldOfView(out, fov, near, far) {
  1211. let upTan = Math.tan(fov.upDegrees * Math.PI/180.0);
  1212. let downTan = Math.tan(fov.downDegrees * Math.PI/180.0);
  1213. let leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0);
  1214. let rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0);
  1215. let xScale = 2.0 / (leftTan + rightTan);
  1216. let yScale = 2.0 / (upTan + downTan);
  1217. out[0] = xScale;
  1218. out[1] = 0.0;
  1219. out[2] = 0.0;
  1220. out[3] = 0.0;
  1221. out[4] = 0.0;
  1222. out[5] = yScale;
  1223. out[6] = 0.0;
  1224. out[7] = 0.0;
  1225. out[8] = -((leftTan - rightTan) * xScale * 0.5);
  1226. out[9] = ((upTan - downTan) * yScale * 0.5);
  1227. out[10] = far / (near - far);
  1228. out[11] = -1.0;
  1229. out[12] = 0.0;
  1230. out[13] = 0.0;
  1231. out[14] = (far * near) / (near - far);
  1232. out[15] = 0.0;
  1233. return out;
  1234. }
  1235. /**
  1236. * Generates a orthogonal projection matrix with the given bounds
  1237. *
  1238. * @param {mat4} out mat4 frustum matrix will be written into
  1239. * @param {number} left Left bound of the frustum
  1240. * @param {number} right Right bound of the frustum
  1241. * @param {number} bottom Bottom bound of the frustum
  1242. * @param {number} top Top bound of the frustum
  1243. * @param {number} near Near bound of the frustum
  1244. * @param {number} far Far bound of the frustum
  1245. * @returns {mat4} out
  1246. */
  1247. export function ortho(out, left, right, bottom, top, near, far) {
  1248. let lr = 1 / (left - right);
  1249. let bt = 1 / (bottom - top);
  1250. let nf = 1 / (near - far);
  1251. out[0] = -2 * lr;
  1252. out[1] = 0;
  1253. out[2] = 0;
  1254. out[3] = 0;
  1255. out[4] = 0;
  1256. out[5] = -2 * bt;
  1257. out[6] = 0;
  1258. out[7] = 0;
  1259. out[8] = 0;
  1260. out[9] = 0;
  1261. out[10] = 2 * nf;
  1262. out[11] = 0;
  1263. out[12] = (left + right) * lr;
  1264. out[13] = (top + bottom) * bt;
  1265. out[14] = (far + near) * nf;
  1266. out[15] = 1;
  1267. return out;
  1268. }
  1269. /**
  1270. * Generates a look-at matrix with the given eye position, focal point, and up axis.
  1271. * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
  1272. *
  1273. * @param {mat4} out mat4 frustum matrix will be written into
  1274. * @param {vec3} eye Position of the viewer
  1275. * @param {vec3} center Point the viewer is looking at
  1276. * @param {vec3} up vec3 pointing up
  1277. * @returns {mat4} out
  1278. */
  1279. export function lookAt(out, eye, center, up) {
  1280. let x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
  1281. let eyex = eye[0];
  1282. let eyey = eye[1];
  1283. let eyez = eye[2];
  1284. let upx = up[0];
  1285. let upy = up[1];
  1286. let upz = up[2];
  1287. let centerx = center[0];
  1288. let centery = center[1];
  1289. let centerz = center[2];
  1290. if (Math.abs(eyex - centerx) < glMatrix.EPSILON &&
  1291. Math.abs(eyey - centery) < glMatrix.EPSILON &&
  1292. Math.abs(eyez - centerz) < glMatrix.EPSILON) {
  1293. return identity(out);
  1294. }
  1295. z0 = eyex - centerx;
  1296. z1 = eyey - centery;
  1297. z2 = eyez - centerz;
  1298. len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
  1299. z0 *= len;
  1300. z1 *= len;
  1301. z2 *= len;
  1302. x0 = upy * z2 - upz * z1;
  1303. x1 = upz * z0 - upx * z2;
  1304. x2 = upx * z1 - upy * z0;
  1305. len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
  1306. if (!len) {
  1307. x0 = 0;
  1308. x1 = 0;
  1309. x2 = 0;
  1310. } else {
  1311. len = 1 / len;
  1312. x0 *= len;
  1313. x1 *= len;
  1314. x2 *= len;
  1315. }
  1316. y0 = z1 * x2 - z2 * x1;
  1317. y1 = z2 * x0 - z0 * x2;
  1318. y2 = z0 * x1 - z1 * x0;
  1319. len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
  1320. if (!len) {
  1321. y0 = 0;
  1322. y1 = 0;
  1323. y2 = 0;
  1324. } else {
  1325. len = 1 / len;
  1326. y0 *= len;
  1327. y1 *= len;
  1328. y2 *= len;
  1329. }
  1330. out[0] = x0;
  1331. out[1] = y0;
  1332. out[2] = z0;
  1333. out[3] = 0;
  1334. out[4] = x1;
  1335. out[5] = y1;
  1336. out[6] = z1;
  1337. out[7] = 0;
  1338. out[8] = x2;
  1339. out[9] = y2;
  1340. out[10] = z2;
  1341. out[11] = 0;
  1342. out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
  1343. out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
  1344. out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
  1345. out[15] = 1;
  1346. return out;
  1347. }
  1348. /**
  1349. * Generates a matrix that makes something look at something else.
  1350. *
  1351. * @param {mat4} out mat4 frustum matrix will be written into
  1352. * @param {vec3} eye Position of the viewer
  1353. * @param {vec3} center Point the viewer is looking at
  1354. * @param {vec3} up vec3 pointing up
  1355. * @returns {mat4} out
  1356. */
  1357. export function targetTo(out, eye, target, up) {
  1358. let eyex = eye[0],
  1359. eyey = eye[1],
  1360. eyez = eye[2],
  1361. upx = up[0],
  1362. upy = up[1],
  1363. upz = up[2];
  1364. let z0 = eyex - target[0],
  1365. z1 = eyey - target[1],
  1366. z2 = eyez - target[2];
  1367. let len = z0*z0 + z1*z1 + z2*z2;
  1368. if (len > 0) {
  1369. len = 1 / Math.sqrt(len);
  1370. z0 *= len;
  1371. z1 *= len;
  1372. z2 *= len;
  1373. }
  1374. let x0 = upy * z2 - upz * z1,
  1375. x1 = upz * z0 - upx * z2,
  1376. x2 = upx * z1 - upy * z0;
  1377. len = x0*x0 + x1*x1 + x2*x2;
  1378. if (len > 0) {
  1379. len = 1 / Math.sqrt(len);
  1380. x0 *= len;
  1381. x1 *= len;
  1382. x2 *= len;
  1383. }
  1384. out[0] = x0;
  1385. out[1] = x1;
  1386. out[2] = x2;
  1387. out[3] = 0;
  1388. out[4] = z1 * x2 - z2 * x1;
  1389. out[5] = z2 * x0 - z0 * x2;
  1390. out[6] = z0 * x1 - z1 * x0;
  1391. out[7] = 0;
  1392. out[8] = z0;
  1393. out[9] = z1;
  1394. out[10] = z2;
  1395. out[11] = 0;
  1396. out[12] = eyex;
  1397. out[13] = eyey;
  1398. out[14] = eyez;
  1399. out[15] = 1;
  1400. return out;
  1401. };
  1402. /**
  1403. * Returns a string representation of a mat4
  1404. *
  1405. * @param {mat4} a matrix to represent as a string
  1406. * @returns {String} string representation of the matrix
  1407. */
  1408. export function str(a) {
  1409. return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
  1410. a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
  1411. a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
  1412. a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
  1413. }
  1414. /**
  1415. * Returns Frobenius norm of a mat4
  1416. *
  1417. * @param {mat4} a the matrix to calculate Frobenius norm of
  1418. * @returns {Number} Frobenius norm
  1419. */
  1420. export function frob(a) {
  1421. return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
  1422. }
  1423. /**
  1424. * Adds two mat4's
  1425. *
  1426. * @param {mat4} out the receiving matrix
  1427. * @param {mat4} a the first operand
  1428. * @param {mat4} b the second operand
  1429. * @returns {mat4} out
  1430. */
  1431. export function add(out, a, b) {
  1432. out[0] = a[0] + b[0];
  1433. out[1] = a[1] + b[1];
  1434. out[2] = a[2] + b[2];
  1435. out[3] = a[3] + b[3];
  1436. out[4] = a[4] + b[4];
  1437. out[5] = a[5] + b[5];
  1438. out[6] = a[6] + b[6];
  1439. out[7] = a[7] + b[7];
  1440. out[8] = a[8] + b[8];
  1441. out[9] = a[9] + b[9];
  1442. out[10] = a[10] + b[10];
  1443. out[11] = a[11] + b[11];
  1444. out[12] = a[12] + b[12];
  1445. out[13] = a[13] + b[13];
  1446. out[14] = a[14] + b[14];
  1447. out[15] = a[15] + b[15];
  1448. return out;
  1449. }
  1450. /**
  1451. * Subtracts matrix b from matrix a
  1452. *
  1453. * @param {mat4} out the receiving matrix
  1454. * @param {mat4} a the first operand
  1455. * @param {mat4} b the second operand
  1456. * @returns {mat4} out
  1457. */
  1458. export function subtract(out, a, b) {
  1459. out[0] = a[0] - b[0];
  1460. out[1] = a[1] - b[1];
  1461. out[2] = a[2] - b[2];
  1462. out[3] = a[3] - b[3];
  1463. out[4] = a[4] - b[4];
  1464. out[5] = a[5] - b[5];
  1465. out[6] = a[6] - b[6];
  1466. out[7] = a[7] - b[7];
  1467. out[8] = a[8] - b[8];
  1468. out[9] = a[9] - b[9];
  1469. out[10] = a[10] - b[10];
  1470. out[11] = a[11] - b[11];
  1471. out[12] = a[12] - b[12];
  1472. out[13] = a[13] - b[13];
  1473. out[14] = a[14] - b[14];
  1474. out[15] = a[15] - b[15];
  1475. return out;
  1476. }
  1477. /**
  1478. * Multiply each element of the matrix by a scalar.
  1479. *
  1480. * @param {mat4} out the receiving matrix
  1481. * @param {mat4} a the matrix to scale
  1482. * @param {Number} b amount to scale the matrix's elements by
  1483. * @returns {mat4} out
  1484. */
  1485. export function multiplyScalar(out, a, b) {
  1486. out[0] = a[0] * b;
  1487. out[1] = a[1] * b;
  1488. out[2] = a[2] * b;
  1489. out[3] = a[3] * b;
  1490. out[4] = a[4] * b;
  1491. out[5] = a[5] * b;
  1492. out[6] = a[6] * b;
  1493. out[7] = a[7] * b;
  1494. out[8] = a[8] * b;
  1495. out[9] = a[9] * b;
  1496. out[10] = a[10] * b;
  1497. out[11] = a[11] * b;
  1498. out[12] = a[12] * b;
  1499. out[13] = a[13] * b;
  1500. out[14] = a[14] * b;
  1501. out[15] = a[15] * b;
  1502. return out;
  1503. }
  1504. /**
  1505. * Adds two mat4's after multiplying each element of the second operand by a scalar value.
  1506. *
  1507. * @param {mat4} out the receiving vector
  1508. * @param {mat4} a the first operand
  1509. * @param {mat4} b the second operand
  1510. * @param {Number} scale the amount to scale b's elements by before adding
  1511. * @returns {mat4} out
  1512. */
  1513. export function multiplyScalarAndAdd(out, a, b, scale) {
  1514. out[0] = a[0] + (b[0] * scale);
  1515. out[1] = a[1] + (b[1] * scale);
  1516. out[2] = a[2] + (b[2] * scale);
  1517. out[3] = a[3] + (b[3] * scale);
  1518. out[4] = a[4] + (b[4] * scale);
  1519. out[5] = a[5] + (b[5] * scale);
  1520. out[6] = a[6] + (b[6] * scale);
  1521. out[7] = a[7] + (b[7] * scale);
  1522. out[8] = a[8] + (b[8] * scale);
  1523. out[9] = a[9] + (b[9] * scale);
  1524. out[10] = a[10] + (b[10] * scale);
  1525. out[11] = a[11] + (b[11] * scale);
  1526. out[12] = a[12] + (b[12] * scale);
  1527. out[13] = a[13] + (b[13] * scale);
  1528. out[14] = a[14] + (b[14] * scale);
  1529. out[15] = a[15] + (b[15] * scale);
  1530. return out;
  1531. }
  1532. /**
  1533. * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
  1534. *
  1535. * @param {mat4} a The first matrix.
  1536. * @param {mat4} b The second matrix.
  1537. * @returns {Boolean} True if the matrices are equal, false otherwise.
  1538. */
  1539. export function exactEquals(a, b) {
  1540. return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] &&
  1541. a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] &&
  1542. a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] &&
  1543. a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
  1544. }
  1545. /**
  1546. * Returns whether or not the matrices have approximately the same elements in the same position.
  1547. *
  1548. * @param {mat4} a The first matrix.
  1549. * @param {mat4} b The second matrix.
  1550. * @returns {Boolean} True if the matrices are equal, false otherwise.
  1551. */
  1552. export function equals(a, b) {
  1553. let a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
  1554. let a4 = a[4], a5 = a[5], a6 = a[6], a7 = a[7];
  1555. let a8 = a[8], a9 = a[9], a10 = a[10], a11 = a[11];
  1556. let a12 = a[12], a13 = a[13], a14 = a[14], a15 = a[15];
  1557. let b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
  1558. let b4 = b[4], b5 = b[5], b6 = b[6], b7 = b[7];
  1559. let b8 = b[8], b9 = b[9], b10 = b[10], b11 = b[11];
  1560. let b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15];
  1561. return (Math.abs(a0 - b0) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
  1562. Math.abs(a1 - b1) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
  1563. Math.abs(a2 - b2) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
  1564. Math.abs(a3 - b3) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a3), Math.abs(b3)) &&
  1565. Math.abs(a4 - b4) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a4), Math.abs(b4)) &&
  1566. Math.abs(a5 - b5) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a5), Math.abs(b5)) &&
  1567. Math.abs(a6 - b6) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a6), Math.abs(b6)) &&
  1568. Math.abs(a7 - b7) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a7), Math.abs(b7)) &&
  1569. Math.abs(a8 - b8) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a8), Math.abs(b8)) &&
  1570. Math.abs(a9 - b9) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a9), Math.abs(b9)) &&
  1571. Math.abs(a10 - b10) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a10), Math.abs(b10)) &&
  1572. Math.abs(a11 - b11) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a11), Math.abs(b11)) &&
  1573. Math.abs(a12 - b12) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a12), Math.abs(b12)) &&
  1574. Math.abs(a13 - b13) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a13), Math.abs(b13)) &&
  1575. Math.abs(a14 - b14) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a14), Math.abs(b14)) &&
  1576. Math.abs(a15 - b15) <= glMatrix.EPSILON*Math.max(1.0, Math.abs(a15), Math.abs(b15)));
  1577. }
  1578. /**
  1579. * Alias for {@link mat4.multiply}
  1580. * @function
  1581. */
  1582. export const mul = multiply;
  1583. /**
  1584. * Alias for {@link mat4.subtract}
  1585. * @function
  1586. */
  1587. export const sub = subtract;