mat3d.js 31 KB

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