mat3d.js 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  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 mat3f.js by running: //
  9. // swap_type.sh mat3d.js > mat3f.js //
  10. // //
  11. ////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
  12. /**
  13. * @fileoverview Provides functions for operating on 3x3 double (64bit)
  14. * matrices. The matrices are stored in column-major order.
  15. *
  16. * The last parameter will typically be the output object and an object
  17. * can be both an input and output parameter to all methods except where
  18. * noted.
  19. *
  20. * See the README for notes about the design and structure of the API
  21. * (especially related to performance).
  22. */
  23. goog.provide('goog.vec.mat3d');
  24. goog.provide('goog.vec.mat3d.Type');
  25. goog.require('goog.vec');
  26. goog.require('goog.vec.vec3d.Type');
  27. /** @typedef {!goog.vec.Float64} */ goog.vec.mat3d.Type;
  28. /**
  29. * Creates a mat3d with all elements initialized to zero.
  30. *
  31. * @return {!goog.vec.mat3d.Type} The new mat3d.
  32. */
  33. goog.vec.mat3d.create = function() {
  34. return new Float64Array(9);
  35. };
  36. /**
  37. * Creates a mat3d identity matrix.
  38. *
  39. * @return {!goog.vec.mat3d.Type} The new mat3d.
  40. */
  41. goog.vec.mat3d.createIdentity = function() {
  42. var mat = goog.vec.mat3d.create();
  43. mat[0] = mat[4] = mat[8] = 1;
  44. return mat;
  45. };
  46. /**
  47. * Initializes the matrix from the set of values. Note the values supplied are
  48. * in column major order.
  49. *
  50. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the
  51. * values.
  52. * @param {number} v00 The values at (0, 0).
  53. * @param {number} v10 The values at (1, 0).
  54. * @param {number} v20 The values at (2, 0).
  55. * @param {number} v01 The values at (0, 1).
  56. * @param {number} v11 The values at (1, 1).
  57. * @param {number} v21 The values at (2, 1).
  58. * @param {number} v02 The values at (0, 2).
  59. * @param {number} v12 The values at (1, 2).
  60. * @param {number} v22 The values at (2, 2).
  61. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  62. * chained together.
  63. */
  64. goog.vec.mat3d.setFromValues = function(
  65. mat, v00, v10, v20, v01, v11, v21, v02, v12, v22) {
  66. mat[0] = v00;
  67. mat[1] = v10;
  68. mat[2] = v20;
  69. mat[3] = v01;
  70. mat[4] = v11;
  71. mat[5] = v21;
  72. mat[6] = v02;
  73. mat[7] = v12;
  74. mat[8] = v22;
  75. return mat;
  76. };
  77. /**
  78. * Initializes mat3d mat from mat3d src.
  79. *
  80. * @param {!goog.vec.mat3d.Type} mat The destination matrix.
  81. * @param {!goog.vec.mat3d.Type} src The source matrix.
  82. * @return {!goog.vec.mat3d.Type} Return mat so that operations can be
  83. * chained together.
  84. */
  85. goog.vec.mat3d.setFromMat3d = function(mat, src) {
  86. mat[0] = src[0];
  87. mat[1] = src[1];
  88. mat[2] = src[2];
  89. mat[3] = src[3];
  90. mat[4] = src[4];
  91. mat[5] = src[5];
  92. mat[6] = src[6];
  93. mat[7] = src[7];
  94. mat[8] = src[8];
  95. return mat;
  96. };
  97. /**
  98. * Initializes mat3d mat from mat3f src (typed as a Float32Array to
  99. * avoid circular goog.requires).
  100. *
  101. * @param {!goog.vec.mat3d.Type} mat The destination matrix.
  102. * @param {Float32Array} src The source matrix.
  103. * @return {!goog.vec.mat3d.Type} Return mat so that operations can be
  104. * chained together.
  105. */
  106. goog.vec.mat3d.setFromMat3f = function(mat, src) {
  107. mat[0] = src[0];
  108. mat[1] = src[1];
  109. mat[2] = src[2];
  110. mat[3] = src[3];
  111. mat[4] = src[4];
  112. mat[5] = src[5];
  113. mat[6] = src[6];
  114. mat[7] = src[7];
  115. mat[8] = src[8];
  116. return mat;
  117. };
  118. /**
  119. * Initializes mat3d mat from Array src.
  120. *
  121. * @param {!goog.vec.mat3d.Type} mat The destination matrix.
  122. * @param {Array<number>} src The source matrix.
  123. * @return {!goog.vec.mat3d.Type} Return mat so that operations can be
  124. * chained together.
  125. */
  126. goog.vec.mat3d.setFromArray = function(mat, src) {
  127. mat[0] = src[0];
  128. mat[1] = src[1];
  129. mat[2] = src[2];
  130. mat[3] = src[3];
  131. mat[4] = src[4];
  132. mat[5] = src[5];
  133. mat[6] = src[6];
  134. mat[7] = src[7];
  135. mat[8] = src[8];
  136. return mat;
  137. };
  138. /**
  139. * Retrieves the element at the requested row and column.
  140. *
  141. * @param {!goog.vec.mat3d.Type} mat The matrix containing the value to
  142. * retrieve.
  143. * @param {number} row The row index.
  144. * @param {number} column The column index.
  145. * @return {number} The element value at the requested row, column indices.
  146. */
  147. goog.vec.mat3d.getElement = function(mat, row, column) {
  148. return mat[row + column * 3];
  149. };
  150. /**
  151. * Sets the element at the requested row and column.
  152. *
  153. * @param {!goog.vec.mat3d.Type} mat The matrix containing the value to
  154. * retrieve.
  155. * @param {number} row The row index.
  156. * @param {number} column The column index.
  157. * @param {number} value The value to set at the requested row, column.
  158. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  159. * chained together.
  160. */
  161. goog.vec.mat3d.setElement = function(mat, row, column, value) {
  162. mat[row + column * 3] = value;
  163. return mat;
  164. };
  165. /**
  166. * Sets the diagonal values of the matrix from the given values.
  167. *
  168. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the values.
  169. * @param {number} v00 The values for (0, 0).
  170. * @param {number} v11 The values for (1, 1).
  171. * @param {number} v22 The values for (2, 2).
  172. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  173. * chained together.
  174. */
  175. goog.vec.mat3d.setDiagonalValues = function(mat, v00, v11, v22) {
  176. mat[0] = v00;
  177. mat[4] = v11;
  178. mat[8] = v22;
  179. return mat;
  180. };
  181. /**
  182. * Sets the diagonal values of the matrix from the given vector.
  183. *
  184. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the values.
  185. * @param {!goog.vec.vec3d.Type} vec The vector containing the values.
  186. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  187. * chained together.
  188. */
  189. goog.vec.mat3d.setDiagonal = function(mat, vec) {
  190. mat[0] = vec[0];
  191. mat[4] = vec[1];
  192. mat[8] = vec[2];
  193. return mat;
  194. };
  195. /**
  196. * Sets the specified column with the supplied values.
  197. *
  198. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the values.
  199. * @param {number} column The column index to set the values on.
  200. * @param {number} v0 The value for row 0.
  201. * @param {number} v1 The value for row 1.
  202. * @param {number} v2 The value for row 2.
  203. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  204. * chained together.
  205. */
  206. goog.vec.mat3d.setColumnValues = function(mat, column, v0, v1, v2) {
  207. var i = column * 3;
  208. mat[i] = v0;
  209. mat[i + 1] = v1;
  210. mat[i + 2] = v2;
  211. return mat;
  212. };
  213. /**
  214. * Sets the specified column with the value from the supplied array.
  215. *
  216. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the values.
  217. * @param {number} column The column index to set the values on.
  218. * @param {!goog.vec.vec3d.Type} vec The vector elements for the column.
  219. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  220. * chained together.
  221. */
  222. goog.vec.mat3d.setColumn = function(mat, column, vec) {
  223. var i = column * 3;
  224. mat[i] = vec[0];
  225. mat[i + 1] = vec[1];
  226. mat[i + 2] = vec[2];
  227. return mat;
  228. };
  229. /**
  230. * Retrieves the specified column from the matrix into the given vector
  231. * array.
  232. *
  233. * @param {!goog.vec.mat3d.Type} mat The matrix supplying the values.
  234. * @param {number} column The column to get the values from.
  235. * @param {!goog.vec.vec3d.Type} vec The vector elements to receive the
  236. * column.
  237. * @return {!goog.vec.vec3d.Type} return vec so that operations can be
  238. * chained together.
  239. */
  240. goog.vec.mat3d.getColumn = function(mat, column, vec) {
  241. var i = column * 3;
  242. vec[0] = mat[i];
  243. vec[1] = mat[i + 1];
  244. vec[2] = mat[i + 2];
  245. return vec;
  246. };
  247. /**
  248. * Sets the columns of the matrix from the set of vector elements.
  249. *
  250. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the values.
  251. * @param {!goog.vec.vec3d.Type} vec0 The values for column 0.
  252. * @param {!goog.vec.vec3d.Type} vec1 The values for column 1.
  253. * @param {!goog.vec.vec3d.Type} vec2 The values for column 2.
  254. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  255. * chained together.
  256. */
  257. goog.vec.mat3d.setColumns = function(mat, vec0, vec1, vec2) {
  258. goog.vec.mat3d.setColumn(mat, 0, vec0);
  259. goog.vec.mat3d.setColumn(mat, 1, vec1);
  260. goog.vec.mat3d.setColumn(mat, 2, vec2);
  261. return /** @type {!goog.vec.mat3d.Type} */ (mat);
  262. };
  263. /**
  264. * Retrieves the column values from the given matrix into the given vector
  265. * elements.
  266. *
  267. * @param {!goog.vec.mat3d.Type} mat The matrix supplying the columns.
  268. * @param {!goog.vec.vec3d.Type} vec0 The vector to receive column 0.
  269. * @param {!goog.vec.vec3d.Type} vec1 The vector to receive column 1.
  270. * @param {!goog.vec.vec3d.Type} vec2 The vector to receive column 2.
  271. */
  272. goog.vec.mat3d.getColumns = function(mat, vec0, vec1, vec2) {
  273. goog.vec.mat3d.getColumn(mat, 0, vec0);
  274. goog.vec.mat3d.getColumn(mat, 1, vec1);
  275. goog.vec.mat3d.getColumn(mat, 2, vec2);
  276. };
  277. /**
  278. * Sets the row values from the supplied values.
  279. *
  280. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the values.
  281. * @param {number} row The index of the row to receive the values.
  282. * @param {number} v0 The value for column 0.
  283. * @param {number} v1 The value for column 1.
  284. * @param {number} v2 The value for column 2.
  285. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  286. * chained together.
  287. */
  288. goog.vec.mat3d.setRowValues = function(mat, row, v0, v1, v2) {
  289. mat[row] = v0;
  290. mat[row + 3] = v1;
  291. mat[row + 6] = v2;
  292. return mat;
  293. };
  294. /**
  295. * Sets the row values from the supplied vector.
  296. *
  297. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the row values.
  298. * @param {number} row The index of the row.
  299. * @param {!goog.vec.vec3d.Type} vec The vector containing the values.
  300. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  301. * chained together.
  302. */
  303. goog.vec.mat3d.setRow = function(mat, row, vec) {
  304. mat[row] = vec[0];
  305. mat[row + 3] = vec[1];
  306. mat[row + 6] = vec[2];
  307. return mat;
  308. };
  309. /**
  310. * Retrieves the row values into the given vector.
  311. *
  312. * @param {!goog.vec.mat3d.Type} mat The matrix supplying the values.
  313. * @param {number} row The index of the row supplying the values.
  314. * @param {!goog.vec.vec3d.Type} vec The vector to receive the row.
  315. * @return {!goog.vec.vec3d.Type} return vec so that operations can be
  316. * chained together.
  317. */
  318. goog.vec.mat3d.getRow = function(mat, row, vec) {
  319. vec[0] = mat[row];
  320. vec[1] = mat[row + 3];
  321. vec[2] = mat[row + 6];
  322. return vec;
  323. };
  324. /**
  325. * Sets the rows of the matrix from the supplied vectors.
  326. *
  327. * @param {!goog.vec.mat3d.Type} mat The matrix to receive the values.
  328. * @param {!goog.vec.vec3d.Type} vec0 The values for row 0.
  329. * @param {!goog.vec.vec3d.Type} vec1 The values for row 1.
  330. * @param {!goog.vec.vec3d.Type} vec2 The values for row 2.
  331. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  332. * chained together.
  333. */
  334. goog.vec.mat3d.setRows = function(mat, vec0, vec1, vec2) {
  335. goog.vec.mat3d.setRow(mat, 0, vec0);
  336. goog.vec.mat3d.setRow(mat, 1, vec1);
  337. goog.vec.mat3d.setRow(mat, 2, vec2);
  338. return /** @type {!goog.vec.mat3d.Type} */ (mat);
  339. };
  340. /**
  341. * Retrieves the rows of the matrix into the supplied vectors.
  342. *
  343. * @param {!goog.vec.mat3d.Type} mat The matrix to supplying the values.
  344. * @param {!goog.vec.vec3d.Type} vec0 The vector to receive row 0.
  345. * @param {!goog.vec.vec3d.Type} vec1 The vector to receive row 1.
  346. * @param {!goog.vec.vec3d.Type} vec2 The vector to receive row 2.
  347. */
  348. goog.vec.mat3d.getRows = function(mat, vec0, vec1, vec2) {
  349. goog.vec.mat3d.getRow(mat, 0, vec0);
  350. goog.vec.mat3d.getRow(mat, 1, vec1);
  351. goog.vec.mat3d.getRow(mat, 2, vec2);
  352. };
  353. /**
  354. * Makes the given 3x3 matrix the zero matrix.
  355. *
  356. * @param {!goog.vec.mat3d.Type} mat The matrix.
  357. * @return {!goog.vec.mat3d.Type} return mat so operations can be chained.
  358. */
  359. goog.vec.mat3d.makeZero = function(mat) {
  360. mat[0] = 0;
  361. mat[1] = 0;
  362. mat[2] = 0;
  363. mat[3] = 0;
  364. mat[4] = 0;
  365. mat[5] = 0;
  366. mat[6] = 0;
  367. mat[7] = 0;
  368. mat[8] = 0;
  369. return mat;
  370. };
  371. /**
  372. * Makes the given 3x3 matrix the identity matrix.
  373. *
  374. * @param {!goog.vec.mat3d.Type} mat The matrix.
  375. * @return {!goog.vec.mat3d.Type} return mat so operations can be chained.
  376. */
  377. goog.vec.mat3d.makeIdentity = function(mat) {
  378. mat[0] = 1;
  379. mat[1] = 0;
  380. mat[2] = 0;
  381. mat[3] = 0;
  382. mat[4] = 1;
  383. mat[5] = 0;
  384. mat[6] = 0;
  385. mat[7] = 0;
  386. mat[8] = 1;
  387. return mat;
  388. };
  389. /**
  390. * Performs a per-component addition of the matrices mat0 and mat1, storing
  391. * the result into resultMat.
  392. *
  393. * @param {!goog.vec.mat3d.Type} mat0 The first addend.
  394. * @param {!goog.vec.mat3d.Type} mat1 The second addend.
  395. * @param {!goog.vec.mat3d.Type} resultMat The matrix to
  396. * receive the results (may be either mat0 or mat1).
  397. * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
  398. * chained together.
  399. */
  400. goog.vec.mat3d.addMat = function(mat0, mat1, resultMat) {
  401. resultMat[0] = mat0[0] + mat1[0];
  402. resultMat[1] = mat0[1] + mat1[1];
  403. resultMat[2] = mat0[2] + mat1[2];
  404. resultMat[3] = mat0[3] + mat1[3];
  405. resultMat[4] = mat0[4] + mat1[4];
  406. resultMat[5] = mat0[5] + mat1[5];
  407. resultMat[6] = mat0[6] + mat1[6];
  408. resultMat[7] = mat0[7] + mat1[7];
  409. resultMat[8] = mat0[8] + mat1[8];
  410. return resultMat;
  411. };
  412. /**
  413. * Performs a per-component subtraction of the matrices mat0 and mat1,
  414. * storing the result into resultMat.
  415. *
  416. * @param {!goog.vec.mat3d.Type} mat0 The minuend.
  417. * @param {!goog.vec.mat3d.Type} mat1 The subtrahend.
  418. * @param {!goog.vec.mat3d.Type} resultMat The matrix to receive
  419. * the results (may be either mat0 or mat1).
  420. * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
  421. * chained together.
  422. */
  423. goog.vec.mat3d.subMat = function(mat0, mat1, resultMat) {
  424. resultMat[0] = mat0[0] - mat1[0];
  425. resultMat[1] = mat0[1] - mat1[1];
  426. resultMat[2] = mat0[2] - mat1[2];
  427. resultMat[3] = mat0[3] - mat1[3];
  428. resultMat[4] = mat0[4] - mat1[4];
  429. resultMat[5] = mat0[5] - mat1[5];
  430. resultMat[6] = mat0[6] - mat1[6];
  431. resultMat[7] = mat0[7] - mat1[7];
  432. resultMat[8] = mat0[8] - mat1[8];
  433. return resultMat;
  434. };
  435. /**
  436. * Multiplies matrix mat0 with the given scalar, storing the result
  437. * into resultMat.
  438. *
  439. * @param {!goog.vec.mat3d.Type} mat The matrix.
  440. * @param {number} scalar The scalar value to multiple to each element of mat.
  441. * @param {!goog.vec.mat3d.Type} resultMat The matrix to receive
  442. * the results (may be mat).
  443. * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
  444. * chained together.
  445. */
  446. goog.vec.mat3d.multScalar = function(mat, scalar, resultMat) {
  447. resultMat[0] = mat[0] * scalar;
  448. resultMat[1] = mat[1] * scalar;
  449. resultMat[2] = mat[2] * scalar;
  450. resultMat[3] = mat[3] * scalar;
  451. resultMat[4] = mat[4] * scalar;
  452. resultMat[5] = mat[5] * scalar;
  453. resultMat[6] = mat[6] * scalar;
  454. resultMat[7] = mat[7] * scalar;
  455. resultMat[8] = mat[8] * scalar;
  456. return resultMat;
  457. };
  458. /**
  459. * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
  460. * storing the result into resultMat.
  461. *
  462. * @param {!goog.vec.mat3d.Type} mat0 The first (left hand) matrix.
  463. * @param {!goog.vec.mat3d.Type} mat1 The second (right hand) matrix.
  464. * @param {!goog.vec.mat3d.Type} resultMat The matrix to receive
  465. * the results (may be either mat0 or mat1).
  466. * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
  467. * chained together.
  468. */
  469. goog.vec.mat3d.multMat = function(mat0, mat1, resultMat) {
  470. var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
  471. var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
  472. var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
  473. var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2];
  474. var b01 = mat1[3], b11 = mat1[4], b21 = mat1[5];
  475. var b02 = mat1[6], b12 = mat1[7], b22 = mat1[8];
  476. resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20;
  477. resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20;
  478. resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20;
  479. resultMat[3] = a00 * b01 + a01 * b11 + a02 * b21;
  480. resultMat[4] = a10 * b01 + a11 * b11 + a12 * b21;
  481. resultMat[5] = a20 * b01 + a21 * b11 + a22 * b21;
  482. resultMat[6] = a00 * b02 + a01 * b12 + a02 * b22;
  483. resultMat[7] = a10 * b02 + a11 * b12 + a12 * b22;
  484. resultMat[8] = a20 * b02 + a21 * b12 + a22 * b22;
  485. return resultMat;
  486. };
  487. /**
  488. * Transposes the given matrix mat storing the result into resultMat.
  489. *
  490. * @param {!goog.vec.mat3d.Type} mat The matrix to transpose.
  491. * @param {!goog.vec.mat3d.Type} resultMat The matrix to receive
  492. * the results (may be mat).
  493. * @return {!goog.vec.mat3d.Type} return resultMat so that operations can be
  494. * chained together.
  495. */
  496. goog.vec.mat3d.transpose = function(mat, resultMat) {
  497. if (resultMat == mat) {
  498. var a10 = mat[1], a20 = mat[2], a21 = mat[5];
  499. resultMat[1] = mat[3];
  500. resultMat[2] = mat[6];
  501. resultMat[3] = a10;
  502. resultMat[5] = mat[7];
  503. resultMat[6] = a20;
  504. resultMat[7] = a21;
  505. } else {
  506. resultMat[0] = mat[0];
  507. resultMat[1] = mat[3];
  508. resultMat[2] = mat[6];
  509. resultMat[3] = mat[1];
  510. resultMat[4] = mat[4];
  511. resultMat[5] = mat[7];
  512. resultMat[6] = mat[2];
  513. resultMat[7] = mat[5];
  514. resultMat[8] = mat[8];
  515. }
  516. return resultMat;
  517. };
  518. /**
  519. * Computes the inverse of mat0 storing the result into resultMat. If the
  520. * inverse is defined, this function returns true, false otherwise.
  521. *
  522. * @param {!goog.vec.mat3d.Type} mat0 The matrix to invert.
  523. * @param {!goog.vec.mat3d.Type} resultMat The matrix to receive
  524. * the result (may be mat0).
  525. * @return {boolean} True if the inverse is defined. If false is returned,
  526. * resultMat is not modified.
  527. */
  528. goog.vec.mat3d.invert = function(mat0, resultMat) {
  529. var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2];
  530. var a01 = mat0[3], a11 = mat0[4], a21 = mat0[5];
  531. var a02 = mat0[6], a12 = mat0[7], a22 = mat0[8];
  532. var t00 = a11 * a22 - a12 * a21;
  533. var t10 = a12 * a20 - a10 * a22;
  534. var t20 = a10 * a21 - a11 * a20;
  535. var det = a00 * t00 + a01 * t10 + a02 * t20;
  536. if (det == 0) {
  537. return false;
  538. }
  539. var idet = 1 / det;
  540. resultMat[0] = t00 * idet;
  541. resultMat[3] = (a02 * a21 - a01 * a22) * idet;
  542. resultMat[6] = (a01 * a12 - a02 * a11) * idet;
  543. resultMat[1] = t10 * idet;
  544. resultMat[4] = (a00 * a22 - a02 * a20) * idet;
  545. resultMat[7] = (a02 * a10 - a00 * a12) * idet;
  546. resultMat[2] = t20 * idet;
  547. resultMat[5] = (a01 * a20 - a00 * a21) * idet;
  548. resultMat[8] = (a00 * a11 - a01 * a10) * idet;
  549. return true;
  550. };
  551. /**
  552. * Returns true if the components of mat0 are equal to the components of mat1.
  553. *
  554. * @param {!goog.vec.mat3d.Type} mat0 The first matrix.
  555. * @param {!goog.vec.mat3d.Type} mat1 The second matrix.
  556. * @return {boolean} True if the the two matrices are equivalent.
  557. */
  558. goog.vec.mat3d.equals = function(mat0, mat1) {
  559. return mat0.length == mat1.length && mat0[0] == mat1[0] &&
  560. mat0[1] == mat1[1] && mat0[2] == mat1[2] && mat0[3] == mat1[3] &&
  561. mat0[4] == mat1[4] && mat0[5] == mat1[5] && mat0[6] == mat1[6] &&
  562. mat0[7] == mat1[7] && mat0[8] == mat1[8];
  563. };
  564. /**
  565. * Transforms the given vector with the given matrix storing the resulting,
  566. * transformed matrix into resultVec.
  567. *
  568. * @param {!goog.vec.mat3d.Type} mat The matrix supplying the transformation.
  569. * @param {!goog.vec.vec3d.Type} vec The vector to transform.
  570. * @param {!goog.vec.vec3d.Type} resultVec The vector to
  571. * receive the results (may be vec).
  572. * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
  573. * chained together.
  574. */
  575. goog.vec.mat3d.multVec3 = function(mat, vec, resultVec) {
  576. var x = vec[0], y = vec[1], z = vec[2];
  577. resultVec[0] = x * mat[0] + y * mat[3] + z * mat[6];
  578. resultVec[1] = x * mat[1] + y * mat[4] + z * mat[7];
  579. resultVec[2] = x * mat[2] + y * mat[5] + z * mat[8];
  580. return resultVec;
  581. };
  582. /**
  583. * Makes the given 3x3 matrix a translation matrix with x and y
  584. * translation values.
  585. *
  586. * @param {!goog.vec.mat3d.Type} mat The matrix.
  587. * @param {number} x The translation along the x axis.
  588. * @param {number} y The translation along the y axis.
  589. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  590. * chained.
  591. */
  592. goog.vec.mat3d.makeTranslate = function(mat, x, y) {
  593. mat[0] = 1;
  594. mat[1] = 0;
  595. mat[2] = 0;
  596. mat[3] = 0;
  597. mat[4] = 1;
  598. mat[5] = 0;
  599. mat[6] = x;
  600. mat[7] = y;
  601. mat[8] = 1;
  602. return mat;
  603. };
  604. /**
  605. * Makes the given 3x3 matrix a scale matrix with x, y, and z scale factors.
  606. *
  607. * @param {!goog.vec.mat3d.Type} mat The 3x3 (9-element) matrix
  608. * array to receive the new scale matrix.
  609. * @param {number} x The scale along the x axis.
  610. * @param {number} y The scale along the y axis.
  611. * @param {number} z The scale along the z axis.
  612. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  613. * chained.
  614. */
  615. goog.vec.mat3d.makeScale = function(mat, x, y, z) {
  616. mat[0] = x;
  617. mat[1] = 0;
  618. mat[2] = 0;
  619. mat[3] = 0;
  620. mat[4] = y;
  621. mat[5] = 0;
  622. mat[6] = 0;
  623. mat[7] = 0;
  624. mat[8] = z;
  625. return mat;
  626. };
  627. /**
  628. * Makes the given 3x3 matrix a rotation matrix with the given rotation
  629. * angle about the axis defined by the vector (ax, ay, az).
  630. *
  631. * @param {!goog.vec.mat3d.Type} mat The matrix.
  632. * @param {number} angle The rotation angle in radians.
  633. * @param {number} ax The x component of the rotation axis.
  634. * @param {number} ay The y component of the rotation axis.
  635. * @param {number} az The z component of the rotation axis.
  636. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  637. * chained.
  638. */
  639. goog.vec.mat3d.makeRotate = function(mat, angle, ax, ay, az) {
  640. var c = Math.cos(angle);
  641. var d = 1 - c;
  642. var s = Math.sin(angle);
  643. mat[0] = ax * ax * d + c;
  644. mat[1] = ax * ay * d + az * s;
  645. mat[2] = ax * az * d - ay * s;
  646. mat[3] = ax * ay * d - az * s;
  647. mat[4] = ay * ay * d + c;
  648. mat[5] = ay * az * d + ax * s;
  649. mat[6] = ax * az * d + ay * s;
  650. mat[7] = ay * az * d - ax * s;
  651. mat[8] = az * az * d + c;
  652. return mat;
  653. };
  654. /**
  655. * Makes the given 3x3 matrix a rotation matrix with the given rotation
  656. * angle about the X axis.
  657. *
  658. * @param {!goog.vec.mat3d.Type} mat The matrix.
  659. * @param {number} angle The rotation angle in radians.
  660. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  661. * chained.
  662. */
  663. goog.vec.mat3d.makeRotateX = function(mat, angle) {
  664. var c = Math.cos(angle);
  665. var s = Math.sin(angle);
  666. mat[0] = 1;
  667. mat[1] = 0;
  668. mat[2] = 0;
  669. mat[3] = 0;
  670. mat[4] = c;
  671. mat[5] = s;
  672. mat[6] = 0;
  673. mat[7] = -s;
  674. mat[8] = c;
  675. return mat;
  676. };
  677. /**
  678. * Makes the given 3x3 matrix a rotation matrix with the given rotation
  679. * angle about the Y axis.
  680. *
  681. * @param {!goog.vec.mat3d.Type} mat The matrix.
  682. * @param {number} angle The rotation angle in radians.
  683. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  684. * chained.
  685. */
  686. goog.vec.mat3d.makeRotateY = function(mat, angle) {
  687. var c = Math.cos(angle);
  688. var s = Math.sin(angle);
  689. mat[0] = c;
  690. mat[1] = 0;
  691. mat[2] = -s;
  692. mat[3] = 0;
  693. mat[4] = 1;
  694. mat[5] = 0;
  695. mat[6] = s;
  696. mat[7] = 0;
  697. mat[8] = c;
  698. return mat;
  699. };
  700. /**
  701. * Makes the given 3x3 matrix a rotation matrix with the given rotation
  702. * angle about the Z axis.
  703. *
  704. * @param {!goog.vec.mat3d.Type} mat The matrix.
  705. * @param {number} angle The rotation angle in radians.
  706. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  707. * chained.
  708. */
  709. goog.vec.mat3d.makeRotateZ = function(mat, angle) {
  710. var c = Math.cos(angle);
  711. var s = Math.sin(angle);
  712. mat[0] = c;
  713. mat[1] = s;
  714. mat[2] = 0;
  715. mat[3] = -s;
  716. mat[4] = c;
  717. mat[5] = 0;
  718. mat[6] = 0;
  719. mat[7] = 0;
  720. mat[8] = 1;
  721. return mat;
  722. };
  723. /**
  724. * Rotate the given matrix by angle about the x,y,z axis. Equivalent to:
  725. * goog.vec.mat3d.multMat(
  726. * mat,
  727. * goog.vec.mat3d.makeRotate(goog.vec.mat3d.create(), angle, x, y, z),
  728. * mat);
  729. *
  730. * @param {!goog.vec.mat3d.Type} mat The matrix.
  731. * @param {number} angle The angle in radians.
  732. * @param {number} x The x component of the rotation axis.
  733. * @param {number} y The y component of the rotation axis.
  734. * @param {number} z The z component of the rotation axis.
  735. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  736. * chained.
  737. */
  738. goog.vec.mat3d.rotate = function(mat, angle, x, y, z) {
  739. var m00 = mat[0], m10 = mat[1], m20 = mat[2];
  740. var m01 = mat[3], m11 = mat[4], m21 = mat[5];
  741. var m02 = mat[6], m12 = mat[7], m22 = mat[8];
  742. var cosAngle = Math.cos(angle);
  743. var sinAngle = Math.sin(angle);
  744. var diffCosAngle = 1 - cosAngle;
  745. var r00 = x * x * diffCosAngle + cosAngle;
  746. var r10 = x * y * diffCosAngle + z * sinAngle;
  747. var r20 = x * z * diffCosAngle - y * sinAngle;
  748. var r01 = x * y * diffCosAngle - z * sinAngle;
  749. var r11 = y * y * diffCosAngle + cosAngle;
  750. var r21 = y * z * diffCosAngle + x * sinAngle;
  751. var r02 = x * z * diffCosAngle + y * sinAngle;
  752. var r12 = y * z * diffCosAngle - x * sinAngle;
  753. var r22 = z * z * diffCosAngle + cosAngle;
  754. mat[0] = m00 * r00 + m01 * r10 + m02 * r20;
  755. mat[1] = m10 * r00 + m11 * r10 + m12 * r20;
  756. mat[2] = m20 * r00 + m21 * r10 + m22 * r20;
  757. mat[3] = m00 * r01 + m01 * r11 + m02 * r21;
  758. mat[4] = m10 * r01 + m11 * r11 + m12 * r21;
  759. mat[5] = m20 * r01 + m21 * r11 + m22 * r21;
  760. mat[6] = m00 * r02 + m01 * r12 + m02 * r22;
  761. mat[7] = m10 * r02 + m11 * r12 + m12 * r22;
  762. mat[8] = m20 * r02 + m21 * r12 + m22 * r22;
  763. return mat;
  764. };
  765. /**
  766. * Rotate the given matrix by angle about the x axis. Equivalent to:
  767. * goog.vec.mat3d.multMat(
  768. * mat,
  769. * goog.vec.mat3d.makeRotateX(goog.vec.mat3d.create(), angle),
  770. * mat);
  771. *
  772. * @param {!goog.vec.mat3d.Type} mat The matrix.
  773. * @param {number} angle The angle in radians.
  774. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  775. * chained.
  776. */
  777. goog.vec.mat3d.rotateX = function(mat, angle) {
  778. var m01 = mat[3], m11 = mat[4], m21 = mat[5];
  779. var m02 = mat[6], m12 = mat[7], m22 = mat[8];
  780. var c = Math.cos(angle);
  781. var s = Math.sin(angle);
  782. mat[3] = m01 * c + m02 * s;
  783. mat[4] = m11 * c + m12 * s;
  784. mat[5] = m21 * c + m22 * s;
  785. mat[6] = m01 * -s + m02 * c;
  786. mat[7] = m11 * -s + m12 * c;
  787. mat[8] = m21 * -s + m22 * c;
  788. return mat;
  789. };
  790. /**
  791. * Rotate the given matrix by angle about the y axis. Equivalent to:
  792. * goog.vec.mat3d.multMat(
  793. * mat,
  794. * goog.vec.mat3d.makeRotateY(goog.vec.mat3d.create(), angle),
  795. * mat);
  796. *
  797. * @param {!goog.vec.mat3d.Type} mat The matrix.
  798. * @param {number} angle The angle in radians.
  799. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  800. * chained.
  801. */
  802. goog.vec.mat3d.rotateY = function(mat, angle) {
  803. var m00 = mat[0], m10 = mat[1], m20 = mat[2];
  804. var m02 = mat[6], m12 = mat[7], m22 = mat[8];
  805. var c = Math.cos(angle);
  806. var s = Math.sin(angle);
  807. mat[0] = m00 * c + m02 * -s;
  808. mat[1] = m10 * c + m12 * -s;
  809. mat[2] = m20 * c + m22 * -s;
  810. mat[6] = m00 * s + m02 * c;
  811. mat[7] = m10 * s + m12 * c;
  812. mat[8] = m20 * s + m22 * c;
  813. return mat;
  814. };
  815. /**
  816. * Rotate the given matrix by angle about the z axis. Equivalent to:
  817. * goog.vec.mat3d.multMat(
  818. * mat,
  819. * goog.vec.mat3d.makeRotateZ(goog.vec.mat3d.create(), angle),
  820. * mat);
  821. *
  822. * @param {!goog.vec.mat3d.Type} mat The matrix.
  823. * @param {number} angle The angle in radians.
  824. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  825. * chained.
  826. */
  827. goog.vec.mat3d.rotateZ = function(mat, angle) {
  828. var m00 = mat[0], m10 = mat[1], m20 = mat[2];
  829. var m01 = mat[3], m11 = mat[4], m21 = mat[5];
  830. var c = Math.cos(angle);
  831. var s = Math.sin(angle);
  832. mat[0] = m00 * c + m01 * s;
  833. mat[1] = m10 * c + m11 * s;
  834. mat[2] = m20 * c + m21 * s;
  835. mat[3] = m00 * -s + m01 * c;
  836. mat[4] = m10 * -s + m11 * c;
  837. mat[5] = m20 * -s + m21 * c;
  838. return mat;
  839. };
  840. /**
  841. * Makes the given 3x3 matrix a rotation matrix given Euler angles using
  842. * the ZXZ convention.
  843. * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
  844. * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
  845. * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
  846. * rotation_x(theta) means rotation around the X axis of theta radians.
  847. *
  848. * @param {!goog.vec.mat3d.Type} mat The matrix.
  849. * @param {number} theta1 The angle of rotation around the Z axis in radians.
  850. * @param {number} theta2 The angle of rotation around the X axis in radians.
  851. * @param {number} theta3 The angle of rotation around the Z axis in radians.
  852. * @return {!goog.vec.mat3d.Type} return mat so that operations can be
  853. * chained.
  854. */
  855. goog.vec.mat3d.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
  856. var c1 = Math.cos(theta1);
  857. var s1 = Math.sin(theta1);
  858. var c2 = Math.cos(theta2);
  859. var s2 = Math.sin(theta2);
  860. var c3 = Math.cos(theta3);
  861. var s3 = Math.sin(theta3);
  862. mat[0] = c1 * c3 - c2 * s1 * s3;
  863. mat[1] = c2 * c1 * s3 + c3 * s1;
  864. mat[2] = s3 * s2;
  865. mat[3] = -c1 * s3 - c3 * c2 * s1;
  866. mat[4] = c1 * c2 * c3 - s1 * s3;
  867. mat[5] = c3 * s2;
  868. mat[6] = s2 * s1;
  869. mat[7] = -c1 * s2;
  870. mat[8] = c2;
  871. return mat;
  872. };
  873. /**
  874. * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
  875. * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
  876. * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
  877. * rotation_x(theta) means rotation around the X axis of theta radians.
  878. *
  879. * @param {!goog.vec.mat3d.Type} mat The matrix.
  880. * @param {!goog.vec.vec3d.Type} euler The ZXZ Euler angles in
  881. * radians as [theta1, theta2, theta3].
  882. * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
  883. * of the default [0, pi].
  884. * @return {!goog.vec.vec3d.Type} return euler so that operations can be
  885. * chained together.
  886. */
  887. goog.vec.mat3d.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
  888. // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
  889. var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[5] * mat[5]);
  890. // By default we explicitely constrain theta2 to be in [0, pi],
  891. // so sinTheta2 is always positive. We can change the behavior and specify
  892. // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
  893. var signTheta2 = opt_theta2IsNegative ? -1 : 1;
  894. if (sinTheta2 > goog.vec.EPSILON) {
  895. euler[2] = Math.atan2(mat[2] * signTheta2, mat[5] * signTheta2);
  896. euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
  897. euler[0] = Math.atan2(mat[6] * signTheta2, -mat[7] * signTheta2);
  898. } else {
  899. // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
  900. // We assume theta1 = 0 as some applications do not allow the camera to roll
  901. // (i.e. have theta1 != 0).
  902. euler[0] = 0;
  903. euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[8]);
  904. euler[2] = Math.atan2(mat[1], mat[0]);
  905. }
  906. // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
  907. euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
  908. euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
  909. // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
  910. // signTheta2.
  911. euler[1] =
  912. ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) * signTheta2;
  913. return euler;
  914. };