mat4d_test.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. /**
  2. * @license
  3. * Copyright The Closure Library Authors.
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. ////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
  7. // //
  8. // Any edits to this file must be applied to mat4f_test.js by running: //
  9. // swap_type.sh mat4d_test.js > mat4f_test.js //
  10. // //
  11. ////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
  12. goog.module('goog.vec.mat4dTest');
  13. goog.setTestOnly();
  14. const Quaternion = goog.require('goog.vec.Quaternion');
  15. const mat4d = goog.require('goog.vec.mat4d');
  16. const testSuite = goog.require('goog.testing.testSuite');
  17. const vec3d = goog.require('goog.vec.vec3d');
  18. const vec4d = goog.require('goog.vec.vec4d');
  19. const randommat4d = mat4d.setFromValues(
  20. mat4d.create(), 0.8025078773498535, 0.7559120655059814, 0.15274643898010254,
  21. 0.19196106493473053, 0.0890120416879654, 0.15422114729881287,
  22. 0.09754583984613419, 0.44862601161003113, 0.9196512699127197,
  23. 0.5310639142990112, 0.8962187170982361, 0.280601441860199,
  24. 0.594650387763977, 0.4134795069694519, 0.06632178276777267,
  25. 0.8837796449661255);
  26. testSuite({
  27. testCreate() {
  28. const m = mat4d.create();
  29. assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m);
  30. },
  31. testCreateIdentity() {
  32. const m = mat4d.createIdentity();
  33. assertElementsEquals([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m);
  34. },
  35. testSet() {
  36. const m0 = mat4d.create();
  37. const m1 = mat4d.setFromArray(
  38. mat4d.create(),
  39. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
  40. mat4d.setFromArray(m0, m1);
  41. assertElementsEquals(
  42. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  43. mat4d.setFromValues(
  44. m0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
  45. assertElementsEquals(
  46. [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], m0);
  47. },
  48. testSetDiagonal() {
  49. const m0 = mat4d.create();
  50. mat4d.setDiagonalValues(m0, 1, 2, 3, 4);
  51. assertElementsEquals([1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], m0);
  52. mat4d.setDiagonal(m0, [4, 5, 6, 7]);
  53. assertElementsEquals([4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7], m0);
  54. },
  55. testGetDiagonal() {
  56. const v0 = vec4d.create();
  57. const m0 = mat4d.create();
  58. mat4d.setFromArray(
  59. m0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
  60. mat4d.getDiagonal(m0, v0);
  61. assertElementsEquals([0, 5, 10, 15], v0);
  62. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  63. mat4d.getDiagonal(m0, v0, 1);
  64. assertElementsEquals([4, 9, 14, 0], v0);
  65. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  66. mat4d.getDiagonal(m0, v0, 2);
  67. assertElementsEquals([8, 13, 0, 0], v0);
  68. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  69. mat4d.getDiagonal(m0, v0, 3);
  70. assertElementsEquals([12, 0, 0, 0], v0);
  71. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  72. mat4d.getDiagonal(m0, v0, 4);
  73. assertElementsEquals([0, 0, 0, 0], v0);
  74. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  75. mat4d.getDiagonal(m0, v0, -1);
  76. assertElementsEquals([1, 6, 11, 0], v0);
  77. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  78. mat4d.getDiagonal(m0, v0, -2);
  79. assertElementsEquals([2, 7, 0, 0], v0);
  80. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  81. mat4d.getDiagonal(m0, v0, -3);
  82. assertElementsEquals([3, 0, 0, 0], v0);
  83. vec4d.setFromArray(v0, [0, 0, 0, 0]);
  84. mat4d.getDiagonal(m0, v0, -4);
  85. assertElementsEquals([0, 0, 0, 0], v0);
  86. },
  87. testSetGetColumn() {
  88. const m0 = mat4d.create();
  89. mat4d.setColumn(m0, 0, [1, 2, 3, 4]);
  90. mat4d.setColumn(m0, 1, [5, 6, 7, 8]);
  91. mat4d.setColumn(m0, 2, [9, 10, 11, 12]);
  92. mat4d.setColumn(m0, 3, [13, 14, 15, 16]);
  93. assertElementsEquals(
  94. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  95. const v0 = [0, 0, 0, 0];
  96. mat4d.getColumn(m0, 0, v0);
  97. assertElementsEquals([1, 2, 3, 4], v0);
  98. mat4d.getColumn(m0, 1, v0);
  99. assertElementsEquals([5, 6, 7, 8], v0);
  100. mat4d.getColumn(m0, 2, v0);
  101. assertElementsEquals([9, 10, 11, 12], v0);
  102. mat4d.getColumn(m0, 3, v0);
  103. assertElementsEquals([13, 14, 15, 16], v0);
  104. },
  105. testSetGetColumns() {
  106. const m0 = mat4d.create();
  107. mat4d.setColumns(
  108. m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
  109. assertElementsEquals(
  110. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  111. const v0 = [0, 0, 0, 0];
  112. const v1 = [0, 0, 0, 0];
  113. const v2 = [0, 0, 0, 0];
  114. const v3 = [0, 0, 0, 0];
  115. mat4d.getColumns(m0, v0, v1, v2, v3);
  116. assertElementsEquals([1, 2, 3, 4], v0);
  117. assertElementsEquals([5, 6, 7, 8], v1);
  118. assertElementsEquals([9, 10, 11, 12], v2);
  119. assertElementsEquals([13, 14, 15, 16], v3);
  120. },
  121. testSetGetRow() {
  122. const m0 = mat4d.create();
  123. mat4d.setRow(m0, 0, [1, 2, 3, 4]);
  124. mat4d.setRow(m0, 1, [5, 6, 7, 8]);
  125. mat4d.setRow(m0, 2, [9, 10, 11, 12]);
  126. mat4d.setRow(m0, 3, [13, 14, 15, 16]);
  127. assertElementsEquals(
  128. [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
  129. const v0 = [0, 0, 0, 0];
  130. mat4d.getRow(m0, 0, v0);
  131. assertElementsEquals([1, 2, 3, 4], v0);
  132. mat4d.getRow(m0, 1, v0);
  133. assertElementsEquals([5, 6, 7, 8], v0);
  134. mat4d.getRow(m0, 2, v0);
  135. assertElementsEquals([9, 10, 11, 12], v0);
  136. mat4d.getRow(m0, 3, v0);
  137. assertElementsEquals([13, 14, 15, 16], v0);
  138. },
  139. testSetGetRows() {
  140. const m0 = mat4d.create();
  141. mat4d.setRows(
  142. m0, [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]);
  143. assertElementsEquals(
  144. [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m0);
  145. const v0 = [0, 0, 0, 0];
  146. const v1 = [0, 0, 0, 0];
  147. const v2 = [0, 0, 0, 0];
  148. const v3 = [0, 0, 0, 0];
  149. mat4d.getRows(m0, v0, v1, v2, v3);
  150. assertElementsEquals([1, 2, 3, 4], v0);
  151. assertElementsEquals([5, 6, 7, 8], v1);
  152. assertElementsEquals([9, 10, 11, 12], v2);
  153. assertElementsEquals([13, 14, 15, 16], v3);
  154. },
  155. testMakeZero() {
  156. const m0 = mat4d.setFromArray(
  157. mat4d.create(),
  158. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
  159. assertElementsEquals(
  160. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  161. mat4d.makeZero(m0);
  162. assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m0);
  163. },
  164. testMakeIdentity() {
  165. const m0 = mat4d.create();
  166. mat4d.makeIdentity(m0);
  167. assertElementsEquals([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m0);
  168. },
  169. testSetGetElement() {
  170. const m0 = mat4d.create();
  171. for (let r = 0; r < 4; r++) {
  172. for (let c = 0; c < 4; c++) {
  173. const value = c * 4 + r + 1;
  174. mat4d.setElement(m0, r, c, value);
  175. assertEquals(value, mat4d.getElement(m0, r, c));
  176. }
  177. }
  178. assertElementsEquals(
  179. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  180. },
  181. testAddMat() {
  182. const m0 = mat4d.setFromValues(
  183. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  184. const m1 = mat4d.setFromValues(
  185. mat4d.create(), 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
  186. const m2 = mat4d.create();
  187. mat4d.addMat(m0, m1, m2);
  188. assertElementsEquals(
  189. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  190. assertElementsEquals(
  191. [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
  192. assertElementsEquals(
  193. [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m2);
  194. mat4d.addMat(m0, m1, m0);
  195. assertElementsEquals(
  196. [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
  197. assertElementsEquals(
  198. [10, 12, 14, 16, 18, 20, 22, 24, 10, 12, 14, 16, 18, 20, 22, 24], m0);
  199. },
  200. testSubMat() {
  201. const m0 = mat4d.setFromValues(
  202. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  203. const m1 = mat4d.setFromValues(
  204. mat4d.create(), 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8);
  205. const m2 = mat4d.create();
  206. mat4d.subMat(m0, m1, m2);
  207. assertElementsEquals(
  208. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  209. assertElementsEquals(
  210. [9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8], m1);
  211. assertElementsEquals(
  212. [-8, -8, -8, -8, -8, -8, -8, -8, 8, 8, 8, 8, 8, 8, 8, 8], m2);
  213. mat4d.subMat(m1, m0, m1);
  214. assertElementsEquals(
  215. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  216. assertElementsEquals(
  217. [8, 8, 8, 8, 8, 8, 8, 8, -8, -8, -8, -8, -8, -8, -8, -8], m1);
  218. },
  219. testMultScalar() {
  220. const m0 = mat4d.setFromValues(
  221. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  222. const m1 = mat4d.create();
  223. mat4d.multScalar(m0, 2, m1);
  224. assertElementsEquals(
  225. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m0);
  226. assertElementsEquals(
  227. [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32], m1);
  228. mat4d.multScalar(m0, 5, m0);
  229. assertElementsEquals(
  230. [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80], m0);
  231. },
  232. testMultMat() {
  233. const m0 = mat4d.setFromValues(
  234. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  235. const m1 = mat4d.setFromValues(
  236. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  237. const m2 = mat4d.create();
  238. mat4d.multMat(m0, m1, m2);
  239. assertElementsEquals(
  240. [
  241. 90, 100, 110, 120, 202, 228, 254, 280, 314, 356, 398, 440, 426, 484,
  242. 542, 600
  243. ],
  244. m2);
  245. mat4d.multScalar(m1, 2, m1);
  246. mat4d.multMat(m1, m0, m1);
  247. assertElementsEquals(
  248. [
  249. 180, 200, 220, 240, 404, 456, 508, 560, 628, 712, 796, 880, 852, 968,
  250. 1084, 1200
  251. ],
  252. m1);
  253. },
  254. testTranspose() {
  255. const m0 = mat4d.setFromValues(
  256. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  257. const m1 = mat4d.create();
  258. mat4d.transpose(m0, m1);
  259. assertElementsEquals(
  260. [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16], m1);
  261. mat4d.transpose(m1, m1);
  262. assertElementsEquals(
  263. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
  264. },
  265. testDeterminant() {
  266. const m0 = mat4d.setFromValues(
  267. mat4d.create(), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
  268. assertEquals(0, mat4d.determinant(m0));
  269. assertElementsEquals([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
  270. mat4d.setFromValues(m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
  271. assertEquals(160, mat4d.determinant(m0));
  272. assertElementsEquals([1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3], m0);
  273. },
  274. testInvert() {
  275. const m0 = mat4d.setFromValues(
  276. mat4d.create(), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
  277. assertFalse(mat4d.invert(m0, m0));
  278. assertElementsEquals([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], m0);
  279. mat4d.setFromValues(m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
  280. assertTrue(mat4d.invert(m0, m0));
  281. assertElementsRoughlyEqual(
  282. [
  283. -0.225, 0.025, 0.025, 0.275, 0.025, 0.025, 0.275, -0.225, 0.025,
  284. 0.275, -0.225, 0.025, 0.275, -0.225, 0.025, 0.025
  285. ],
  286. m0, goog.vec.EPSILON);
  287. mat4d.makeScale(m0, .01, .01, .01);
  288. assertTrue(mat4d.invert(m0, m0));
  289. const m1 = mat4d.create();
  290. mat4d.makeScale(m1, 100, 100, 100);
  291. assertElementsEquals(m1, m0);
  292. },
  293. testEquals() {
  294. const m0 = mat4d.setFromValues(
  295. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  296. const m1 = mat4d.setFromMat4d(mat4d.create(), m0);
  297. assertTrue(mat4d.equals(m0, m1));
  298. assertTrue(mat4d.equals(m1, m0));
  299. for (let i = 0; i < 16; i++) {
  300. m1[i] = 18;
  301. assertFalse(mat4d.equals(m0, m1));
  302. assertFalse(mat4d.equals(m1, m0));
  303. m1[i] = i + 1;
  304. }
  305. },
  306. testMultVec3() {
  307. const m0 = mat4d.setFromValues(
  308. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  309. const v0 = [1, 2, 3];
  310. const v1 = [0, 0, 0];
  311. mat4d.multVec3(m0, v0, v1);
  312. assertElementsEquals([1, 2, 3], v0);
  313. assertElementsEquals([51, 58, 65], v1);
  314. mat4d.multVec3(m0, v0, v0);
  315. assertElementsEquals([51, 58, 65], v0);
  316. },
  317. testMultVec3NoTranslate() {
  318. const m0 = mat4d.setFromValues(
  319. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  320. const v0 = [1, 2, 3];
  321. const v1 = [0, 0, 0];
  322. mat4d.multVec3NoTranslate(m0, v0, v1);
  323. assertElementsEquals([1, 2, 3], v0);
  324. assertElementsEquals([38, 44, 50], v1);
  325. mat4d.multVec3NoTranslate(m0, v0, v0);
  326. assertElementsEquals([38, 44, 50], v0);
  327. },
  328. testMultVec3Projective() {
  329. const m0 = mat4d.setFromValues(
  330. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  331. const v0 = [1, 2, 3];
  332. const v1 = [0, 0, 0];
  333. const invw = 1 / 72;
  334. mat4d.multVec3Projective(m0, v0, v1);
  335. assertElementsEquals([1, 2, 3], v0);
  336. assertElementsEquals([51 * invw, 58 * invw, 65 * invw], v1);
  337. mat4d.multVec3Projective(m0, v0, v0);
  338. assertElementsEquals([51 * invw, 58 * invw, 65 * invw], v0);
  339. },
  340. testMultVec4() {
  341. const m0 = mat4d.setFromValues(
  342. mat4d.create(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
  343. const v0 = [1, 2, 3, 4];
  344. const v1 = [0, 0, 0, 0];
  345. mat4d.multVec4(m0, v0, v1);
  346. assertElementsEquals([90, 100, 110, 120], v1);
  347. mat4d.multVec4(m0, v0, v0);
  348. assertElementsEquals([90, 100, 110, 120], v0);
  349. },
  350. testSetValues() {
  351. let a0 = mat4d.create();
  352. assertElementsEquals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], a0);
  353. a0 = mat4d.setFromArray(
  354. mat4d.create(),
  355. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
  356. assertElementsEquals(
  357. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a0);
  358. const a1 = mat4d.create();
  359. mat4d.setDiagonalValues(a1, 1, 2, 3, 4);
  360. assertElementsEquals([1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 4], a1);
  361. mat4d.setColumnValues(a1, 0, 2, 3, 4, 5);
  362. mat4d.setColumnValues(a1, 1, 6, 7, 8, 9);
  363. mat4d.setColumnValues(a1, 2, 10, 11, 12, 13);
  364. mat4d.setColumnValues(a1, 3, 14, 15, 16, 1);
  365. assertElementsEquals(
  366. [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1], a1);
  367. mat4d.setRowValues(a1, 0, 1, 5, 9, 13);
  368. mat4d.setRowValues(a1, 1, 2, 6, 10, 14);
  369. mat4d.setRowValues(a1, 2, 3, 7, 11, 15);
  370. mat4d.setRowValues(a1, 3, 4, 8, 12, 16);
  371. assertElementsEquals(
  372. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], a1);
  373. },
  374. testMakeTranslate() {
  375. const m0 = mat4d.create();
  376. mat4d.makeTranslate(m0, 3, 4, 5);
  377. assertElementsEquals([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
  378. },
  379. testMakeScale() {
  380. const m0 = mat4d.create();
  381. mat4d.makeScale(m0, 3, 4, 5);
  382. assertElementsEquals([3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
  383. },
  384. testMakeRotate() {
  385. const m0 = mat4d.create();
  386. mat4d.makeRotate(m0, Math.PI / 2, 0, 0, 1);
  387. assertElementsRoughlyEqual(
  388. [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m0,
  389. goog.vec.EPSILON);
  390. const m1 = mat4d.create();
  391. mat4d.makeRotate(m1, -Math.PI / 4, 0, 0, 1);
  392. mat4d.multMat(m0, m1, m1);
  393. assertElementsRoughlyEqual(
  394. [
  395. 0.7071068, 0.7071068, 0, 0, -0.7071068, 0.7071068, 0, 0, 0, 0, 1, 0,
  396. 0, 0, 0, 1
  397. ],
  398. m1, goog.vec.EPSILON);
  399. },
  400. testMakeRotateX() {
  401. const m0 = mat4d.create();
  402. const m1 = mat4d.create();
  403. mat4d.makeRotateX(m0, Math.PI / 7);
  404. mat4d.makeRotate(m1, Math.PI / 7, 1, 0, 0);
  405. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  406. },
  407. testMakeRotateY() {
  408. const m0 = mat4d.create();
  409. const m1 = mat4d.create();
  410. mat4d.makeRotateY(m0, Math.PI / 7);
  411. mat4d.makeRotate(m1, Math.PI / 7, 0, 1, 0);
  412. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  413. },
  414. testMakeRotateZ() {
  415. const m0 = mat4d.create();
  416. const m1 = mat4d.create();
  417. mat4d.makeRotateZ(m0, Math.PI / 7);
  418. mat4d.makeRotate(m1, Math.PI / 7, 0, 0, 1);
  419. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  420. },
  421. testTranslate() {
  422. const m0 = mat4d.makeIdentity(mat4d.create());
  423. mat4d.translate(m0, 3, 4, 5);
  424. assertElementsEquals([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 4, 5, 1], m0);
  425. mat4d.setFromValues(m0, 1, 2, 3, 4, 2, 3, 4, 1, 3, 4, 1, 2, 4, 1, 2, 3);
  426. const m1 = mat4d.create();
  427. mat4d.makeTranslate(m1, 5, 6, 7);
  428. const m2 = mat4d.create();
  429. mat4d.multMat(m0, m1, m2);
  430. mat4d.translate(m0, 5, 6, 7);
  431. assertElementsEquals(m2, m0);
  432. },
  433. testScale() {
  434. const m0 = mat4d.makeIdentity(mat4d.create());
  435. mat4d.scale(m0, 3, 4, 5);
  436. assertElementsEquals([3, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1], m0);
  437. },
  438. testRotate() {
  439. const m0 = mat4d.makeIdentity(mat4d.create());
  440. mat4d.rotate(m0, Math.PI / 2, 0, 0, 1);
  441. assertElementsRoughlyEqual(
  442. [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], m0,
  443. goog.vec.EPSILON);
  444. mat4d.rotate(m0, -Math.PI / 4, 0, 0, 1);
  445. assertElementsRoughlyEqual(
  446. [
  447. 0.7071068, 0.7071068, 0, 0, -0.7071068, 0.7071068, 0, 0, 0, 0, 1, 0,
  448. 0, 0, 0, 1
  449. ],
  450. m0, goog.vec.EPSILON);
  451. },
  452. testRotateX() {
  453. const m0 = mat4d.create();
  454. const m1 = mat4d.setFromArray(mat4d.create(), randommat4d);
  455. mat4d.makeRotateX(m0, Math.PI / 7);
  456. mat4d.multMat(m1, m0, m0);
  457. mat4d.rotateX(m1, Math.PI / 7);
  458. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  459. },
  460. testRotateY() {
  461. const m0 = mat4d.create();
  462. const m1 = mat4d.setFromArray(mat4d.create(), randommat4d);
  463. mat4d.makeRotateY(m0, Math.PI / 7);
  464. mat4d.multMat(m1, m0, m0);
  465. mat4d.rotateY(m1, Math.PI / 7);
  466. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  467. },
  468. testRotateZ() {
  469. const m0 = mat4d.create();
  470. const m1 = mat4d.setFromArray(mat4d.create(), randommat4d);
  471. mat4d.makeRotateZ(m0, Math.PI / 7);
  472. mat4d.multMat(m1, m0, m0);
  473. mat4d.rotateZ(m1, Math.PI / 7);
  474. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  475. },
  476. testMakeRotationTranslation() {
  477. // Create manually.
  478. const m0 = mat4d.makeIdentity(mat4d.create());
  479. mat4d.translate(m0, 3, 4, 5);
  480. mat4d.rotate(m0, Math.PI / 2, 3 / 13, 4 / 13, 12 / 13);
  481. // Create using makeRotationTranslation.
  482. const m1 = mat4d.create();
  483. const q = Quaternion.createFloat64();
  484. const axis = vec3d.createFromValues(3 / 13, 4 / 13, 12 / 13);
  485. Quaternion.fromAngleAxis(Math.PI / 2, axis, q);
  486. const v = vec3d.createFromValues(3, 4, 5);
  487. mat4d.makeRotationTranslation(m1, q, v);
  488. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  489. },
  490. testMakeRotationTranslationScale() {
  491. // Create manually.
  492. const m0 = mat4d.makeIdentity(mat4d.create());
  493. mat4d.translate(m0, 3, 4, 5);
  494. mat4d.rotate(m0, Math.PI / 2, 3 / 13, 4 / 13, 12 / 13);
  495. mat4d.scale(m0, 6, 7, 8);
  496. // Create using makeRotationTranslationScale.
  497. const m1 = mat4d.create();
  498. const q = Quaternion.createFloat64();
  499. const axis = vec3d.createFromValues(3 / 13, 4 / 13, 12 / 13);
  500. Quaternion.fromAngleAxis(Math.PI / 2, axis, q);
  501. const v = vec3d.createFromValues(3, 4, 5);
  502. const s = vec3d.createFromValues(6, 7, 8);
  503. mat4d.makeRotationTranslationScale(m1, q, v, s);
  504. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  505. },
  506. testMakeRotationTranslationScaleOrigin() {
  507. // Create manually.
  508. const m0 = mat4d.makeIdentity(mat4d.create());
  509. mat4d.translate(m0, 3, 4, 5);
  510. mat4d.translate(m0, 9, 10, -11); // Origin.
  511. mat4d.rotate(m0, Math.PI / 2, 3 / 13, 4 / 13, 12 / 13);
  512. mat4d.scale(m0, 6, 7, 8);
  513. mat4d.translate(m0, -9, -10, 11); // -Origin.
  514. // Create using makeRotationTranslationScaleOrigin.
  515. const m1 = mat4d.create();
  516. const q = Quaternion.createFloat64();
  517. const axis = vec3d.createFromValues(3 / 13, 4 / 13, 12 / 13);
  518. Quaternion.fromAngleAxis(Math.PI / 2, axis, q);
  519. const v = vec3d.createFromValues(3, 4, 5);
  520. const s = vec3d.createFromValues(6, 7, 8);
  521. const o = vec3d.createFromValues(9, 10, -11);
  522. mat4d.makeRotationTranslationScaleOrigin(m1, q, v, s, o);
  523. assertElementsRoughlyEqual(m0, m1, 0.00001); // Slightly larger epsilon.
  524. },
  525. testGetTranslation() {
  526. const mat = mat4d.setFromArray(mat4d.create(), randommat4d);
  527. const translation = vec3d.create();
  528. mat4d.getTranslation(mat, translation);
  529. assertElementsRoughlyEqual(
  530. [0.59465038776, 0.413479506969, 0.0663217827677], translation,
  531. goog.vec.EPSILON);
  532. },
  533. testMakeFrustum() {
  534. const m0 = mat4d.create();
  535. mat4d.makeFrustum(m0, -1, 2, -2, 1, .1, 1.1);
  536. assertElementsRoughlyEqual(
  537. [
  538. 0.06666666, 0, 0, 0, 0, 0.06666666, 0, 0, 0.33333333, -0.33333333,
  539. -1.2, -1, 0, 0, -0.22, 0
  540. ],
  541. m0, goog.vec.EPSILON);
  542. },
  543. testMakePerspective() {
  544. const m0 = mat4d.create();
  545. mat4d.makePerspective(m0, 90 * Math.PI / 180, 2, 0.1, 1.1);
  546. assertElementsRoughlyEqual(
  547. [0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1.2, -1, 0, 0, -0.22, 0], m0,
  548. goog.vec.EPSILON);
  549. },
  550. testMakeOrtho() {
  551. const m0 = mat4d.create();
  552. mat4d.makeOrtho(m0, -1, 2, -2, 1, 0.1, 1.1);
  553. assertElementsRoughlyEqual(
  554. [
  555. 0.6666666, 0, 0, 0, 0, 0.6666666, 0, 0, 0, 0, -2, 0, -0.333333,
  556. 0.3333333, -1.2, 1
  557. ],
  558. m0, goog.vec.EPSILON);
  559. },
  560. testMakeEulerZXZ() {
  561. const m0 = mat4d.create();
  562. const roll = 0.200982 * 2 * Math.PI;
  563. const tilt = 0.915833 * Math.PI;
  564. const yaw = 0.839392 * 2 * Math.PI;
  565. mat4d.makeRotate(m0, roll, 0, 0, 1);
  566. mat4d.rotate(m0, tilt, 1, 0, 0);
  567. mat4d.rotate(m0, yaw, 0, 0, 1);
  568. const m1 = mat4d.create();
  569. mat4d.makeEulerZXZ(m1, roll, tilt, yaw);
  570. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  571. let euler = [0, 0, 0];
  572. mat4d.toEulerZXZ(m0, euler);
  573. assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
  574. assertRoughlyEquals(tilt, euler[1], goog.vec.EPSILON);
  575. assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
  576. // Test negative tilt now.
  577. mat4d.makeRotate(m0, roll, 0, 0, 1);
  578. mat4d.rotate(m0, -tilt, 1, 0, 0);
  579. mat4d.rotate(m0, yaw, 0, 0, 1);
  580. mat4d.makeEulerZXZ(m1, roll, -tilt, yaw);
  581. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  582. euler = [0, 0, 0];
  583. mat4d.toEulerZXZ(m0, euler, true);
  584. assertRoughlyEquals(roll, euler[0], goog.vec.EPSILON);
  585. assertRoughlyEquals(-tilt, euler[1], goog.vec.EPSILON);
  586. assertRoughlyEquals(yaw, euler[2], goog.vec.EPSILON);
  587. },
  588. testEulerZXZExtrema() {
  589. const m0 = mat4d.setFromArray(
  590. mat4d.create(), [1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1]);
  591. const m1 = mat4d.setFromArray(
  592. mat4d.create(), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
  593. const euler = [0, 0, 0];
  594. mat4d.toEulerZXZ(m0, euler);
  595. assertElementsRoughlyEqual(
  596. [Math.PI, Math.PI / 2, Math.PI], euler, goog.vec.EPSILON);
  597. mat4d.makeEulerZXZ(m1, euler[0], euler[1], euler[2]);
  598. assertElementsRoughlyEqual(m0, m1, goog.vec.EPSILON);
  599. },
  600. testLookAt() {
  601. const viewMatrix = mat4d.create();
  602. mat4d.makeLookAt(viewMatrix, [0, 0, 0], [1, 0, 0], [0, 1, 0]);
  603. assertElementsRoughlyEqual(
  604. [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], viewMatrix,
  605. goog.vec.EPSILON);
  606. },
  607. testToLookAt() {
  608. // This test does not use the default precision goog.vec.EPSILON due to
  609. // precision issues in some browsers leading to flaky tests.
  610. const EPSILON = 1e-4;
  611. const eyeExp = [0, 0, 0];
  612. const fwdExp = [1, 0, 0];
  613. const upExp = [0, 1, 0];
  614. const centerExp = [0, 0, 0];
  615. vec3d.add(eyeExp, fwdExp, centerExp);
  616. const view = mat4d.create();
  617. mat4d.makeLookAt(view, eyeExp, centerExp, upExp);
  618. const eyeRes = [0, 0, 0];
  619. const fwdRes = [0, 0, 0];
  620. const upRes = [0, 0, 0];
  621. mat4d.toLookAt(view, eyeRes, fwdRes, upRes);
  622. assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
  623. assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
  624. assertElementsRoughlyEqual(upExp, upRes, EPSILON);
  625. },
  626. testLookAtDecomposition() {
  627. // This test does not use the default precision goog.vec.EPSILON due to
  628. // precision issues in some browsers leading to flaky tests.
  629. const EPSILON = 1e-4;
  630. const viewExp = mat4d.create();
  631. const viewRes = mat4d.create();
  632. // Get a valid set of random vectors eye, forward, up by decomposing
  633. // a random matrix into a set of lookAt vectors.
  634. const tmp = mat4d.setFromArray(mat4d.create(), randommat4d);
  635. const eyeExp = [0, 0, 0];
  636. const fwdExp = [0, 0, 0];
  637. const upExp = [0, 0, 0];
  638. const centerExp = [0, 0, 0];
  639. // Project the random matrix into a real modelview matrix.
  640. mat4d.toLookAt(tmp, eyeExp, fwdExp, upExp);
  641. vec3d.add(eyeExp, fwdExp, centerExp);
  642. // Compute the expected modelview matrix from a set of valid random vectors.
  643. mat4d.makeLookAt(viewExp, eyeExp, centerExp, upExp);
  644. const eyeRes = [0, 0, 0];
  645. const fwdRes = [0, 0, 0];
  646. const upRes = [0, 0, 0];
  647. const centerRes = [0, 0, 0];
  648. mat4d.toLookAt(viewExp, eyeRes, fwdRes, upRes);
  649. vec3d.add(eyeRes, fwdRes, centerRes);
  650. mat4d.makeLookAt(viewRes, eyeRes, centerRes, upRes);
  651. assertElementsRoughlyEqual(eyeExp, eyeRes, EPSILON);
  652. assertElementsRoughlyEqual(fwdExp, fwdRes, EPSILON);
  653. assertElementsRoughlyEqual(upExp, upRes, EPSILON);
  654. assertElementsRoughlyEqual(viewExp, viewRes, EPSILON);
  655. },
  656. });