mat4_test.js 24 KB

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