mat4d.js 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943
  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 mat4f.js by running: //
  17. // swap_type.sh mat4d.js > mat4f.js //
  18. // //
  19. ////////////////////////// NOTE ABOUT EDITING THIS FILE ///////////////////////
  20. /**
  21. * @fileoverview Provides functions for operating on 4x4 double (64bit)
  22. * matrices. The matrices are stored in column-major order.
  23. *
  24. * The last parameter will typically be the output matrix and an
  25. * object can be both an input and output parameter to all methods except
  26. * where 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.mat4d');
  33. goog.provide('goog.vec.mat4d.Type');
  34. goog.require('goog.vec');
  35. /** @suppress {extraRequire} */
  36. goog.require('goog.vec.Quaternion');
  37. goog.require('goog.vec.vec3d');
  38. goog.require('goog.vec.vec4d');
  39. /** @typedef {goog.vec.Float64} */ goog.vec.mat4d.Type;
  40. /**
  41. * Creates a mat4d with all elements initialized to zero.
  42. *
  43. * @return {!goog.vec.mat4d.Type} The new mat4d.
  44. */
  45. goog.vec.mat4d.create = function() {
  46. return new Float64Array(16);
  47. };
  48. /**
  49. * Creates a mat4d identity matrix.
  50. *
  51. * @return {!goog.vec.mat4d.Type} The new mat4d.
  52. */
  53. goog.vec.mat4d.createIdentity = function() {
  54. var mat = goog.vec.mat4d.create();
  55. mat[0] = mat[5] = mat[10] = mat[15] = 1;
  56. return mat;
  57. };
  58. /**
  59. * Initializes the matrix from the set of values. Note the values supplied are
  60. * in column major order.
  61. *
  62. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the
  63. * values.
  64. * @param {number} v00 The values at (0, 0).
  65. * @param {number} v10 The values at (1, 0).
  66. * @param {number} v20 The values at (2, 0).
  67. * @param {number} v30 The values at (3, 0).
  68. * @param {number} v01 The values at (0, 1).
  69. * @param {number} v11 The values at (1, 1).
  70. * @param {number} v21 The values at (2, 1).
  71. * @param {number} v31 The values at (3, 1).
  72. * @param {number} v02 The values at (0, 2).
  73. * @param {number} v12 The values at (1, 2).
  74. * @param {number} v22 The values at (2, 2).
  75. * @param {number} v32 The values at (3, 2).
  76. * @param {number} v03 The values at (0, 3).
  77. * @param {number} v13 The values at (1, 3).
  78. * @param {number} v23 The values at (2, 3).
  79. * @param {number} v33 The values at (3, 3).
  80. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  81. * chained together.
  82. */
  83. goog.vec.mat4d.setFromValues = function(
  84. mat, v00, v10, v20, v30, v01, v11, v21, v31, v02, v12, v22, v32, v03, v13,
  85. v23, v33) {
  86. mat[0] = v00;
  87. mat[1] = v10;
  88. mat[2] = v20;
  89. mat[3] = v30;
  90. mat[4] = v01;
  91. mat[5] = v11;
  92. mat[6] = v21;
  93. mat[7] = v31;
  94. mat[8] = v02;
  95. mat[9] = v12;
  96. mat[10] = v22;
  97. mat[11] = v32;
  98. mat[12] = v03;
  99. mat[13] = v13;
  100. mat[14] = v23;
  101. mat[15] = v33;
  102. return mat;
  103. };
  104. /**
  105. * Initializes mat4d mat from mat4d src.
  106. *
  107. * @param {!goog.vec.mat4d.Type} mat The destination matrix.
  108. * @param {!goog.vec.mat4d.Type} src The source matrix.
  109. * @return {!goog.vec.mat4d.Type} Return mat so that operations can be
  110. * chained together.
  111. */
  112. goog.vec.mat4d.setFromMat4d = function(mat, src) {
  113. mat[0] = src[0];
  114. mat[1] = src[1];
  115. mat[2] = src[2];
  116. mat[3] = src[3];
  117. mat[4] = src[4];
  118. mat[5] = src[5];
  119. mat[6] = src[6];
  120. mat[7] = src[7];
  121. mat[8] = src[8];
  122. mat[9] = src[9];
  123. mat[10] = src[10];
  124. mat[11] = src[11];
  125. mat[12] = src[12];
  126. mat[13] = src[13];
  127. mat[14] = src[14];
  128. mat[15] = src[15];
  129. return mat;
  130. };
  131. /**
  132. * Initializes mat4d mat from mat4f src (typed as a Float32Array to
  133. * avoid circular goog.requires).
  134. *
  135. * @param {!goog.vec.mat4d.Type} mat The destination matrix.
  136. * @param {Float32Array} src The source matrix.
  137. * @return {!goog.vec.mat4d.Type} Return mat so that operations can be
  138. * chained together.
  139. */
  140. goog.vec.mat4d.setFromMat4f = function(mat, src) {
  141. mat[0] = src[0];
  142. mat[1] = src[1];
  143. mat[2] = src[2];
  144. mat[3] = src[3];
  145. mat[4] = src[4];
  146. mat[5] = src[5];
  147. mat[6] = src[6];
  148. mat[7] = src[7];
  149. mat[8] = src[8];
  150. mat[9] = src[9];
  151. mat[10] = src[10];
  152. mat[11] = src[11];
  153. mat[12] = src[12];
  154. mat[13] = src[13];
  155. mat[14] = src[14];
  156. mat[15] = src[15];
  157. return mat;
  158. };
  159. /**
  160. * Initializes mat4d mat from Array src.
  161. *
  162. * @param {!goog.vec.mat4d.Type} mat The destination matrix.
  163. * @param {Array<number>} src The source matrix.
  164. * @return {!goog.vec.mat4d.Type} Return mat so that operations can be
  165. * chained together.
  166. */
  167. goog.vec.mat4d.setFromArray = function(mat, src) {
  168. mat[0] = src[0];
  169. mat[1] = src[1];
  170. mat[2] = src[2];
  171. mat[3] = src[3];
  172. mat[4] = src[4];
  173. mat[5] = src[5];
  174. mat[6] = src[6];
  175. mat[7] = src[7];
  176. mat[8] = src[8];
  177. mat[9] = src[9];
  178. mat[10] = src[10];
  179. mat[11] = src[11];
  180. mat[12] = src[12];
  181. mat[13] = src[13];
  182. mat[14] = src[14];
  183. mat[15] = src[15];
  184. return mat;
  185. };
  186. /**
  187. * Retrieves the element at the requested row and column.
  188. *
  189. * @param {!goog.vec.mat4d.Type} mat The matrix containing the value to
  190. * retrieve.
  191. * @param {number} row The row index.
  192. * @param {number} column The column index.
  193. * @return {number} The element value at the requested row, column indices.
  194. */
  195. goog.vec.mat4d.getElement = function(mat, row, column) {
  196. return mat[row + column * 4];
  197. };
  198. /**
  199. * Sets the element at the requested row and column.
  200. *
  201. * @param {!goog.vec.mat4d.Type} mat The matrix containing the value to
  202. * retrieve.
  203. * @param {number} row The row index.
  204. * @param {number} column The column index.
  205. * @param {number} value The value to set at the requested row, column.
  206. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  207. * chained together.
  208. */
  209. goog.vec.mat4d.setElement = function(mat, row, column, value) {
  210. mat[row + column * 4] = value;
  211. return mat;
  212. };
  213. /**
  214. * Sets the diagonal values of the matrix from the given values.
  215. *
  216. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the values.
  217. * @param {number} v00 The values for (0, 0).
  218. * @param {number} v11 The values for (1, 1).
  219. * @param {number} v22 The values for (2, 2).
  220. * @param {number} v33 The values for (3, 3).
  221. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  222. * chained together.
  223. */
  224. goog.vec.mat4d.setDiagonalValues = function(mat, v00, v11, v22, v33) {
  225. mat[0] = v00;
  226. mat[5] = v11;
  227. mat[10] = v22;
  228. mat[15] = v33;
  229. return mat;
  230. };
  231. /**
  232. * Sets the diagonal values of the matrix from the given vector.
  233. *
  234. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the values.
  235. * @param {!goog.vec.vec4d.Type} vec The vector containing the values.
  236. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  237. * chained together.
  238. */
  239. goog.vec.mat4d.setDiagonal = function(mat, vec) {
  240. mat[0] = vec[0];
  241. mat[5] = vec[1];
  242. mat[10] = vec[2];
  243. mat[15] = vec[3];
  244. return mat;
  245. };
  246. /**
  247. * Gets the diagonal values of the matrix into the given vector.
  248. *
  249. * @param {!goog.vec.mat4d.Type} mat The matrix containing the values.
  250. * @param {!goog.vec.vec4d.Type} vec The vector to receive the values.
  251. * @param {number=} opt_diagonal Which diagonal to get. A value of 0 selects the
  252. * main diagonal, a positive number selects a super diagonal and a negative
  253. * number selects a sub diagonal.
  254. * @return {!goog.vec.vec4d.Type} return vec so that operations can be
  255. * chained together.
  256. */
  257. goog.vec.mat4d.getDiagonal = function(mat, vec, opt_diagonal) {
  258. if (!opt_diagonal) {
  259. // This is the most common case, so we avoid the for loop.
  260. vec[0] = mat[0];
  261. vec[1] = mat[5];
  262. vec[2] = mat[10];
  263. vec[3] = mat[15];
  264. } else {
  265. var offset = opt_diagonal > 0 ? 4 * opt_diagonal : -opt_diagonal;
  266. for (var i = 0; i < 4 - Math.abs(opt_diagonal); i++) {
  267. vec[i] = mat[offset + 5 * i];
  268. }
  269. }
  270. return vec;
  271. };
  272. /**
  273. * Sets the specified column with the supplied values.
  274. *
  275. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the values.
  276. * @param {number} column The column index to set the values on.
  277. * @param {number} v0 The value for row 0.
  278. * @param {number} v1 The value for row 1.
  279. * @param {number} v2 The value for row 2.
  280. * @param {number} v3 The value for row 3.
  281. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  282. * chained together.
  283. */
  284. goog.vec.mat4d.setColumnValues = function(mat, column, v0, v1, v2, v3) {
  285. var i = column * 4;
  286. mat[i] = v0;
  287. mat[i + 1] = v1;
  288. mat[i + 2] = v2;
  289. mat[i + 3] = v3;
  290. return mat;
  291. };
  292. /**
  293. * Sets the specified column with the value from the supplied vector.
  294. *
  295. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the values.
  296. * @param {number} column The column index to set the values on.
  297. * @param {!goog.vec.vec4d.Type} vec The vector of elements for the column.
  298. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  299. * chained together.
  300. */
  301. goog.vec.mat4d.setColumn = function(mat, column, vec) {
  302. var i = column * 4;
  303. mat[i] = vec[0];
  304. mat[i + 1] = vec[1];
  305. mat[i + 2] = vec[2];
  306. mat[i + 3] = vec[3];
  307. return mat;
  308. };
  309. /**
  310. * Retrieves the specified column from the matrix into the given vector.
  311. *
  312. * @param {!goog.vec.mat4d.Type} mat The matrix supplying the values.
  313. * @param {number} column The column to get the values from.
  314. * @param {!goog.vec.vec4d.Type} vec The vector of elements to
  315. * receive the column.
  316. * @return {!goog.vec.vec4d.Type} return vec so that operations can be
  317. * chained together.
  318. */
  319. goog.vec.mat4d.getColumn = function(mat, column, vec) {
  320. var i = column * 4;
  321. vec[0] = mat[i];
  322. vec[1] = mat[i + 1];
  323. vec[2] = mat[i + 2];
  324. vec[3] = mat[i + 3];
  325. return vec;
  326. };
  327. /**
  328. * Sets the columns of the matrix from the given vectors.
  329. *
  330. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the values.
  331. * @param {!goog.vec.vec4d.Type} vec0 The values for column 0.
  332. * @param {!goog.vec.vec4d.Type} vec1 The values for column 1.
  333. * @param {!goog.vec.vec4d.Type} vec2 The values for column 2.
  334. * @param {!goog.vec.vec4d.Type} vec3 The values for column 3.
  335. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  336. * chained together.
  337. */
  338. goog.vec.mat4d.setColumns = function(mat, vec0, vec1, vec2, vec3) {
  339. mat[0] = vec0[0];
  340. mat[1] = vec0[1];
  341. mat[2] = vec0[2];
  342. mat[3] = vec0[3];
  343. mat[4] = vec1[0];
  344. mat[5] = vec1[1];
  345. mat[6] = vec1[2];
  346. mat[7] = vec1[3];
  347. mat[8] = vec2[0];
  348. mat[9] = vec2[1];
  349. mat[10] = vec2[2];
  350. mat[11] = vec2[3];
  351. mat[12] = vec3[0];
  352. mat[13] = vec3[1];
  353. mat[14] = vec3[2];
  354. mat[15] = vec3[3];
  355. return mat;
  356. };
  357. /**
  358. * Retrieves the column values from the given matrix into the given vectors.
  359. *
  360. * @param {!goog.vec.mat4d.Type} mat The matrix supplying the columns.
  361. * @param {!goog.vec.vec4d.Type} vec0 The vector to receive column 0.
  362. * @param {!goog.vec.vec4d.Type} vec1 The vector to receive column 1.
  363. * @param {!goog.vec.vec4d.Type} vec2 The vector to receive column 2.
  364. * @param {!goog.vec.vec4d.Type} vec3 The vector to receive column 3.
  365. */
  366. goog.vec.mat4d.getColumns = function(mat, vec0, vec1, vec2, vec3) {
  367. vec0[0] = mat[0];
  368. vec0[1] = mat[1];
  369. vec0[2] = mat[2];
  370. vec0[3] = mat[3];
  371. vec1[0] = mat[4];
  372. vec1[1] = mat[5];
  373. vec1[2] = mat[6];
  374. vec1[3] = mat[7];
  375. vec2[0] = mat[8];
  376. vec2[1] = mat[9];
  377. vec2[2] = mat[10];
  378. vec2[3] = mat[11];
  379. vec3[0] = mat[12];
  380. vec3[1] = mat[13];
  381. vec3[2] = mat[14];
  382. vec3[3] = mat[15];
  383. };
  384. /**
  385. * Sets the row values from the supplied values.
  386. *
  387. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the values.
  388. * @param {number} row The index of the row to receive the values.
  389. * @param {number} v0 The value for column 0.
  390. * @param {number} v1 The value for column 1.
  391. * @param {number} v2 The value for column 2.
  392. * @param {number} v3 The value for column 3.
  393. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  394. * chained together.
  395. */
  396. goog.vec.mat4d.setRowValues = function(mat, row, v0, v1, v2, v3) {
  397. mat[row] = v0;
  398. mat[row + 4] = v1;
  399. mat[row + 8] = v2;
  400. mat[row + 12] = v3;
  401. return mat;
  402. };
  403. /**
  404. * Sets the row values from the supplied vector.
  405. *
  406. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the row values.
  407. * @param {number} row The index of the row.
  408. * @param {!goog.vec.vec4d.Type} vec The vector containing the values.
  409. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  410. * chained together.
  411. */
  412. goog.vec.mat4d.setRow = function(mat, row, vec) {
  413. mat[row] = vec[0];
  414. mat[row + 4] = vec[1];
  415. mat[row + 8] = vec[2];
  416. mat[row + 12] = vec[3];
  417. return mat;
  418. };
  419. /**
  420. * Retrieves the row values into the given vector.
  421. *
  422. * @param {!goog.vec.mat4d.Type} mat The matrix supplying the values.
  423. * @param {number} row The index of the row supplying the values.
  424. * @param {!goog.vec.vec4d.Type} vec The vector to receive the row.
  425. * @return {!goog.vec.vec4d.Type} return vec so that operations can be
  426. * chained together.
  427. */
  428. goog.vec.mat4d.getRow = function(mat, row, vec) {
  429. vec[0] = mat[row];
  430. vec[1] = mat[row + 4];
  431. vec[2] = mat[row + 8];
  432. vec[3] = mat[row + 12];
  433. return vec;
  434. };
  435. /**
  436. * Sets the rows of the matrix from the supplied vectors.
  437. *
  438. * @param {!goog.vec.mat4d.Type} mat The matrix to receive the values.
  439. * @param {!goog.vec.vec4d.Type} vec0 The values for row 0.
  440. * @param {!goog.vec.vec4d.Type} vec1 The values for row 1.
  441. * @param {!goog.vec.vec4d.Type} vec2 The values for row 2.
  442. * @param {!goog.vec.vec4d.Type} vec3 The values for row 3.
  443. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  444. * chained together.
  445. */
  446. goog.vec.mat4d.setRows = function(mat, vec0, vec1, vec2, vec3) {
  447. mat[0] = vec0[0];
  448. mat[1] = vec1[0];
  449. mat[2] = vec2[0];
  450. mat[3] = vec3[0];
  451. mat[4] = vec0[1];
  452. mat[5] = vec1[1];
  453. mat[6] = vec2[1];
  454. mat[7] = vec3[1];
  455. mat[8] = vec0[2];
  456. mat[9] = vec1[2];
  457. mat[10] = vec2[2];
  458. mat[11] = vec3[2];
  459. mat[12] = vec0[3];
  460. mat[13] = vec1[3];
  461. mat[14] = vec2[3];
  462. mat[15] = vec3[3];
  463. return mat;
  464. };
  465. /**
  466. * Retrieves the rows of the matrix into the supplied vectors.
  467. *
  468. * @param {!goog.vec.mat4d.Type} mat The matrix to supply the values.
  469. * @param {!goog.vec.vec4d.Type} vec0 The vector to receive row 0.
  470. * @param {!goog.vec.vec4d.Type} vec1 The vector to receive row 1.
  471. * @param {!goog.vec.vec4d.Type} vec2 The vector to receive row 2.
  472. * @param {!goog.vec.vec4d.Type} vec3 The vector to receive row 3.
  473. */
  474. goog.vec.mat4d.getRows = function(mat, vec0, vec1, vec2, vec3) {
  475. vec0[0] = mat[0];
  476. vec1[0] = mat[1];
  477. vec2[0] = mat[2];
  478. vec3[0] = mat[3];
  479. vec0[1] = mat[4];
  480. vec1[1] = mat[5];
  481. vec2[1] = mat[6];
  482. vec3[1] = mat[7];
  483. vec0[2] = mat[8];
  484. vec1[2] = mat[9];
  485. vec2[2] = mat[10];
  486. vec3[2] = mat[11];
  487. vec0[3] = mat[12];
  488. vec1[3] = mat[13];
  489. vec2[3] = mat[14];
  490. vec3[3] = mat[15];
  491. };
  492. /**
  493. * Makes the given 4x4 matrix the zero matrix.
  494. *
  495. * @param {!goog.vec.mat4d.Type} mat The matrix.
  496. * @return {!goog.vec.mat4d.Type} return mat so operations can be chained.
  497. */
  498. goog.vec.mat4d.makeZero = function(mat) {
  499. mat[0] = 0;
  500. mat[1] = 0;
  501. mat[2] = 0;
  502. mat[3] = 0;
  503. mat[4] = 0;
  504. mat[5] = 0;
  505. mat[6] = 0;
  506. mat[7] = 0;
  507. mat[8] = 0;
  508. mat[9] = 0;
  509. mat[10] = 0;
  510. mat[11] = 0;
  511. mat[12] = 0;
  512. mat[13] = 0;
  513. mat[14] = 0;
  514. mat[15] = 0;
  515. return mat;
  516. };
  517. /**
  518. * Makes the given 4x4 matrix the identity matrix.
  519. *
  520. * @param {!goog.vec.mat4d.Type} mat The matrix.
  521. * @return {!goog.vec.mat4d.Type} return mat so operations can be chained.
  522. */
  523. goog.vec.mat4d.makeIdentity = function(mat) {
  524. mat[0] = 1;
  525. mat[1] = 0;
  526. mat[2] = 0;
  527. mat[3] = 0;
  528. mat[4] = 0;
  529. mat[5] = 1;
  530. mat[6] = 0;
  531. mat[7] = 0;
  532. mat[8] = 0;
  533. mat[9] = 0;
  534. mat[10] = 1;
  535. mat[11] = 0;
  536. mat[12] = 0;
  537. mat[13] = 0;
  538. mat[14] = 0;
  539. mat[15] = 1;
  540. return mat;
  541. };
  542. /**
  543. * Performs a per-component addition of the matrix mat0 and mat1, storing
  544. * the result into resultMat.
  545. *
  546. * @param {!goog.vec.mat4d.Type} mat0 The first addend.
  547. * @param {!goog.vec.mat4d.Type} mat1 The second addend.
  548. * @param {!goog.vec.mat4d.Type} resultMat The matrix to
  549. * receive the results (may be either mat0 or mat1).
  550. * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
  551. * chained together.
  552. */
  553. goog.vec.mat4d.addMat = function(mat0, mat1, resultMat) {
  554. resultMat[0] = mat0[0] + mat1[0];
  555. resultMat[1] = mat0[1] + mat1[1];
  556. resultMat[2] = mat0[2] + mat1[2];
  557. resultMat[3] = mat0[3] + mat1[3];
  558. resultMat[4] = mat0[4] + mat1[4];
  559. resultMat[5] = mat0[5] + mat1[5];
  560. resultMat[6] = mat0[6] + mat1[6];
  561. resultMat[7] = mat0[7] + mat1[7];
  562. resultMat[8] = mat0[8] + mat1[8];
  563. resultMat[9] = mat0[9] + mat1[9];
  564. resultMat[10] = mat0[10] + mat1[10];
  565. resultMat[11] = mat0[11] + mat1[11];
  566. resultMat[12] = mat0[12] + mat1[12];
  567. resultMat[13] = mat0[13] + mat1[13];
  568. resultMat[14] = mat0[14] + mat1[14];
  569. resultMat[15] = mat0[15] + mat1[15];
  570. return resultMat;
  571. };
  572. /**
  573. * Performs a per-component subtraction of the matrix mat0 and mat1,
  574. * storing the result into resultMat.
  575. *
  576. * @param {!goog.vec.mat4d.Type} mat0 The minuend.
  577. * @param {!goog.vec.mat4d.Type} mat1 The subtrahend.
  578. * @param {!goog.vec.mat4d.Type} resultMat The matrix to receive
  579. * the results (may be either mat0 or mat1).
  580. * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
  581. * chained together.
  582. */
  583. goog.vec.mat4d.subMat = function(mat0, mat1, resultMat) {
  584. resultMat[0] = mat0[0] - mat1[0];
  585. resultMat[1] = mat0[1] - mat1[1];
  586. resultMat[2] = mat0[2] - mat1[2];
  587. resultMat[3] = mat0[3] - mat1[3];
  588. resultMat[4] = mat0[4] - mat1[4];
  589. resultMat[5] = mat0[5] - mat1[5];
  590. resultMat[6] = mat0[6] - mat1[6];
  591. resultMat[7] = mat0[7] - mat1[7];
  592. resultMat[8] = mat0[8] - mat1[8];
  593. resultMat[9] = mat0[9] - mat1[9];
  594. resultMat[10] = mat0[10] - mat1[10];
  595. resultMat[11] = mat0[11] - mat1[11];
  596. resultMat[12] = mat0[12] - mat1[12];
  597. resultMat[13] = mat0[13] - mat1[13];
  598. resultMat[14] = mat0[14] - mat1[14];
  599. resultMat[15] = mat0[15] - mat1[15];
  600. return resultMat;
  601. };
  602. /**
  603. * Multiplies matrix mat with the given scalar, storing the result
  604. * into resultMat.
  605. *
  606. * @param {!goog.vec.mat4d.Type} mat The matrix.
  607. * @param {number} scalar The scalar value to multiply to each element of mat.
  608. * @param {!goog.vec.mat4d.Type} resultMat The matrix to receive
  609. * the results (may be mat).
  610. * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
  611. * chained together.
  612. */
  613. goog.vec.mat4d.multScalar = function(mat, scalar, resultMat) {
  614. resultMat[0] = mat[0] * scalar;
  615. resultMat[1] = mat[1] * scalar;
  616. resultMat[2] = mat[2] * scalar;
  617. resultMat[3] = mat[3] * scalar;
  618. resultMat[4] = mat[4] * scalar;
  619. resultMat[5] = mat[5] * scalar;
  620. resultMat[6] = mat[6] * scalar;
  621. resultMat[7] = mat[7] * scalar;
  622. resultMat[8] = mat[8] * scalar;
  623. resultMat[9] = mat[9] * scalar;
  624. resultMat[10] = mat[10] * scalar;
  625. resultMat[11] = mat[11] * scalar;
  626. resultMat[12] = mat[12] * scalar;
  627. resultMat[13] = mat[13] * scalar;
  628. resultMat[14] = mat[14] * scalar;
  629. resultMat[15] = mat[15] * scalar;
  630. return resultMat;
  631. };
  632. /**
  633. * Multiplies the two matrices mat0 and mat1 using matrix multiplication,
  634. * storing the result into resultMat.
  635. *
  636. * @param {!goog.vec.mat4d.Type} mat0 The first (left hand) matrix.
  637. * @param {!goog.vec.mat4d.Type} mat1 The second (right hand) matrix.
  638. * @param {!goog.vec.mat4d.Type} resultMat The matrix to receive
  639. * the results (may be either mat0 or mat1).
  640. * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
  641. * chained together.
  642. */
  643. goog.vec.mat4d.multMat = function(mat0, mat1, resultMat) {
  644. var a00 = mat0[0], a10 = mat0[1], a20 = mat0[2], a30 = mat0[3];
  645. var a01 = mat0[4], a11 = mat0[5], a21 = mat0[6], a31 = mat0[7];
  646. var a02 = mat0[8], a12 = mat0[9], a22 = mat0[10], a32 = mat0[11];
  647. var a03 = mat0[12], a13 = mat0[13], a23 = mat0[14], a33 = mat0[15];
  648. var b00 = mat1[0], b10 = mat1[1], b20 = mat1[2], b30 = mat1[3];
  649. var b01 = mat1[4], b11 = mat1[5], b21 = mat1[6], b31 = mat1[7];
  650. var b02 = mat1[8], b12 = mat1[9], b22 = mat1[10], b32 = mat1[11];
  651. var b03 = mat1[12], b13 = mat1[13], b23 = mat1[14], b33 = mat1[15];
  652. resultMat[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
  653. resultMat[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
  654. resultMat[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
  655. resultMat[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
  656. resultMat[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
  657. resultMat[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
  658. resultMat[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
  659. resultMat[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
  660. resultMat[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
  661. resultMat[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
  662. resultMat[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
  663. resultMat[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
  664. resultMat[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
  665. resultMat[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
  666. resultMat[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
  667. resultMat[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
  668. return resultMat;
  669. };
  670. /**
  671. * Transposes the given matrix mat storing the result into resultMat.
  672. *
  673. * @param {!goog.vec.mat4d.Type} mat The matrix to transpose.
  674. * @param {!goog.vec.mat4d.Type} resultMat The matrix to receive
  675. * the results (may be mat).
  676. * @return {!goog.vec.mat4d.Type} return resultMat so that operations can be
  677. * chained together.
  678. */
  679. goog.vec.mat4d.transpose = function(mat, resultMat) {
  680. if (resultMat == mat) {
  681. var a10 = mat[1], a20 = mat[2], a30 = mat[3];
  682. var a21 = mat[6], a31 = mat[7];
  683. var a32 = mat[11];
  684. resultMat[1] = mat[4];
  685. resultMat[2] = mat[8];
  686. resultMat[3] = mat[12];
  687. resultMat[4] = a10;
  688. resultMat[6] = mat[9];
  689. resultMat[7] = mat[13];
  690. resultMat[8] = a20;
  691. resultMat[9] = a21;
  692. resultMat[11] = mat[14];
  693. resultMat[12] = a30;
  694. resultMat[13] = a31;
  695. resultMat[14] = a32;
  696. } else {
  697. resultMat[0] = mat[0];
  698. resultMat[1] = mat[4];
  699. resultMat[2] = mat[8];
  700. resultMat[3] = mat[12];
  701. resultMat[4] = mat[1];
  702. resultMat[5] = mat[5];
  703. resultMat[6] = mat[9];
  704. resultMat[7] = mat[13];
  705. resultMat[8] = mat[2];
  706. resultMat[9] = mat[6];
  707. resultMat[10] = mat[10];
  708. resultMat[11] = mat[14];
  709. resultMat[12] = mat[3];
  710. resultMat[13] = mat[7];
  711. resultMat[14] = mat[11];
  712. resultMat[15] = mat[15];
  713. }
  714. return resultMat;
  715. };
  716. /**
  717. * Computes the determinant of the matrix.
  718. *
  719. * @param {!goog.vec.mat4d.Type} mat The matrix to compute the matrix for.
  720. * @return {number} The determinant of the matrix.
  721. */
  722. goog.vec.mat4d.determinant = function(mat) {
  723. var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
  724. var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
  725. var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
  726. var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
  727. var a0 = m00 * m11 - m10 * m01;
  728. var a1 = m00 * m21 - m20 * m01;
  729. var a2 = m00 * m31 - m30 * m01;
  730. var a3 = m10 * m21 - m20 * m11;
  731. var a4 = m10 * m31 - m30 * m11;
  732. var a5 = m20 * m31 - m30 * m21;
  733. var b0 = m02 * m13 - m12 * m03;
  734. var b1 = m02 * m23 - m22 * m03;
  735. var b2 = m02 * m33 - m32 * m03;
  736. var b3 = m12 * m23 - m22 * m13;
  737. var b4 = m12 * m33 - m32 * m13;
  738. var b5 = m22 * m33 - m32 * m23;
  739. return a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
  740. };
  741. /**
  742. * Computes the inverse of mat storing the result into resultMat. If the
  743. * inverse is defined, this function returns true, false otherwise.
  744. *
  745. * @param {!goog.vec.mat4d.Type} mat The matrix to invert.
  746. * @param {!goog.vec.mat4d.Type} resultMat The matrix to receive
  747. * the result (may be mat).
  748. * @return {boolean} True if the inverse is defined. If false is returned,
  749. * resultMat is not modified.
  750. */
  751. goog.vec.mat4d.invert = function(mat, resultMat) {
  752. var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
  753. var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
  754. var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
  755. var m03 = mat[12], m13 = mat[13], m23 = mat[14], m33 = mat[15];
  756. var a0 = m00 * m11 - m10 * m01;
  757. var a1 = m00 * m21 - m20 * m01;
  758. var a2 = m00 * m31 - m30 * m01;
  759. var a3 = m10 * m21 - m20 * m11;
  760. var a4 = m10 * m31 - m30 * m11;
  761. var a5 = m20 * m31 - m30 * m21;
  762. var b0 = m02 * m13 - m12 * m03;
  763. var b1 = m02 * m23 - m22 * m03;
  764. var b2 = m02 * m33 - m32 * m03;
  765. var b3 = m12 * m23 - m22 * m13;
  766. var b4 = m12 * m33 - m32 * m13;
  767. var b5 = m22 * m33 - m32 * m23;
  768. var det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
  769. if (det == 0) {
  770. return false;
  771. }
  772. var idet = 1.0 / det;
  773. resultMat[0] = (m11 * b5 - m21 * b4 + m31 * b3) * idet;
  774. resultMat[1] = (-m10 * b5 + m20 * b4 - m30 * b3) * idet;
  775. resultMat[2] = (m13 * a5 - m23 * a4 + m33 * a3) * idet;
  776. resultMat[3] = (-m12 * a5 + m22 * a4 - m32 * a3) * idet;
  777. resultMat[4] = (-m01 * b5 + m21 * b2 - m31 * b1) * idet;
  778. resultMat[5] = (m00 * b5 - m20 * b2 + m30 * b1) * idet;
  779. resultMat[6] = (-m03 * a5 + m23 * a2 - m33 * a1) * idet;
  780. resultMat[7] = (m02 * a5 - m22 * a2 + m32 * a1) * idet;
  781. resultMat[8] = (m01 * b4 - m11 * b2 + m31 * b0) * idet;
  782. resultMat[9] = (-m00 * b4 + m10 * b2 - m30 * b0) * idet;
  783. resultMat[10] = (m03 * a4 - m13 * a2 + m33 * a0) * idet;
  784. resultMat[11] = (-m02 * a4 + m12 * a2 - m32 * a0) * idet;
  785. resultMat[12] = (-m01 * b3 + m11 * b1 - m21 * b0) * idet;
  786. resultMat[13] = (m00 * b3 - m10 * b1 + m20 * b0) * idet;
  787. resultMat[14] = (-m03 * a3 + m13 * a1 - m23 * a0) * idet;
  788. resultMat[15] = (m02 * a3 - m12 * a1 + m22 * a0) * idet;
  789. return true;
  790. };
  791. /**
  792. * Returns true if the components of mat0 are equal to the components of mat1.
  793. *
  794. * @param {!goog.vec.mat4d.Type} mat0 The first matrix.
  795. * @param {!goog.vec.mat4d.Type} mat1 The second matrix.
  796. * @return {boolean} True if the the two matrices are equivalent.
  797. */
  798. goog.vec.mat4d.equals = function(mat0, mat1) {
  799. return mat0.length == mat1.length && mat0[0] == mat1[0] &&
  800. mat0[1] == mat1[1] && mat0[2] == mat1[2] && mat0[3] == mat1[3] &&
  801. mat0[4] == mat1[4] && mat0[5] == mat1[5] && mat0[6] == mat1[6] &&
  802. mat0[7] == mat1[7] && mat0[8] == mat1[8] && mat0[9] == mat1[9] &&
  803. mat0[10] == mat1[10] && mat0[11] == mat1[11] && mat0[12] == mat1[12] &&
  804. mat0[13] == mat1[13] && mat0[14] == mat1[14] && mat0[15] == mat1[15];
  805. };
  806. /**
  807. * Transforms the given vector with the given matrix storing the resulting,
  808. * transformed vector into resultVec. The input vector is multiplied against the
  809. * upper 3x4 matrix omitting the projective component.
  810. *
  811. * @param {!goog.vec.mat4d.Type} mat The matrix supplying the transformation.
  812. * @param {!goog.vec.vec3d.Type} vec The 3 element vector to transform.
  813. * @param {!goog.vec.vec3d.Type} resultVec The 3 element vector to
  814. * receive the results (may be vec).
  815. * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
  816. * chained together.
  817. */
  818. goog.vec.mat4d.multVec3 = function(mat, vec, resultVec) {
  819. var x = vec[0], y = vec[1], z = vec[2];
  820. resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + mat[12];
  821. resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + mat[13];
  822. resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + mat[14];
  823. return resultVec;
  824. };
  825. /**
  826. * Transforms the given vector with the given matrix storing the resulting,
  827. * transformed vector into resultVec. The input vector is multiplied against the
  828. * upper 3x3 matrix omitting the projective component and translation
  829. * components.
  830. *
  831. * @param {!goog.vec.mat4d.Type} mat The matrix supplying the transformation.
  832. * @param {!goog.vec.vec3d.Type} vec The 3 element vector to transform.
  833. * @param {!goog.vec.vec3d.Type} resultVec The 3 element vector to
  834. * receive the results (may be vec).
  835. * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
  836. * chained together.
  837. */
  838. goog.vec.mat4d.multVec3NoTranslate = function(mat, vec, resultVec) {
  839. var x = vec[0], y = vec[1], z = vec[2];
  840. resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8];
  841. resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9];
  842. resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10];
  843. return resultVec;
  844. };
  845. /**
  846. * Transforms the given vector with the given matrix storing the resulting,
  847. * transformed vector into resultVec. The input vector is multiplied against the
  848. * full 4x4 matrix with the homogeneous divide applied to reduce the 4 element
  849. * vector to a 3 element vector.
  850. *
  851. * @param {!goog.vec.mat4d.Type} mat The matrix supplying the transformation.
  852. * @param {!goog.vec.vec3d.Type} vec The 3 element vector to transform.
  853. * @param {!goog.vec.vec3d.Type} resultVec The 3 element vector
  854. * to receive the results (may be vec).
  855. * @return {!goog.vec.vec3d.Type} return resultVec so that operations can be
  856. * chained together.
  857. */
  858. goog.vec.mat4d.multVec3Projective = function(mat, vec, resultVec) {
  859. var x = vec[0], y = vec[1], z = vec[2];
  860. var invw = 1 / (x * mat[3] + y * mat[7] + z * mat[11] + mat[15]);
  861. resultVec[0] = (x * mat[0] + y * mat[4] + z * mat[8] + mat[12]) * invw;
  862. resultVec[1] = (x * mat[1] + y * mat[5] + z * mat[9] + mat[13]) * invw;
  863. resultVec[2] = (x * mat[2] + y * mat[6] + z * mat[10] + mat[14]) * invw;
  864. return resultVec;
  865. };
  866. /**
  867. * Transforms the given vector with the given matrix storing the resulting,
  868. * transformed vector into resultVec.
  869. *
  870. * @param {!goog.vec.mat4d.Type} mat The matrix supplying the transformation.
  871. * @param {!goog.vec.vec4d.Type} vec The vector to transform.
  872. * @param {!goog.vec.vec4d.Type} resultVec The vector to
  873. * receive the results (may be vec).
  874. * @return {!goog.vec.vec4d.Type} return resultVec so that operations can be
  875. * chained together.
  876. */
  877. goog.vec.mat4d.multVec4 = function(mat, vec, resultVec) {
  878. var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
  879. resultVec[0] = x * mat[0] + y * mat[4] + z * mat[8] + w * mat[12];
  880. resultVec[1] = x * mat[1] + y * mat[5] + z * mat[9] + w * mat[13];
  881. resultVec[2] = x * mat[2] + y * mat[6] + z * mat[10] + w * mat[14];
  882. resultVec[3] = x * mat[3] + y * mat[7] + z * mat[11] + w * mat[15];
  883. return resultVec;
  884. };
  885. /**
  886. * Makes the given 4x4 matrix a translation matrix with x, y and z
  887. * translation factors.
  888. *
  889. * @param {!goog.vec.mat4d.Type} mat The matrix.
  890. * @param {number} x The translation along the x axis.
  891. * @param {number} y The translation along the y axis.
  892. * @param {number} z The translation along the z axis.
  893. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  894. * chained.
  895. */
  896. goog.vec.mat4d.makeTranslate = function(mat, x, y, z) {
  897. mat[0] = 1;
  898. mat[1] = 0;
  899. mat[2] = 0;
  900. mat[3] = 0;
  901. mat[4] = 0;
  902. mat[5] = 1;
  903. mat[6] = 0;
  904. mat[7] = 0;
  905. mat[8] = 0;
  906. mat[9] = 0;
  907. mat[10] = 1;
  908. mat[11] = 0;
  909. mat[12] = x;
  910. mat[13] = y;
  911. mat[14] = z;
  912. mat[15] = 1;
  913. return mat;
  914. };
  915. /**
  916. * Makes the given 4x4 matrix as a scale matrix with x, y and z scale factors.
  917. *
  918. * @param {!goog.vec.mat4d.Type} mat The matrix.
  919. * @param {number} x The scale along the x axis.
  920. * @param {number} y The scale along the y axis.
  921. * @param {number} z The scale along the z axis.
  922. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  923. * chained.
  924. */
  925. goog.vec.mat4d.makeScale = function(mat, x, y, z) {
  926. mat[0] = x;
  927. mat[1] = 0;
  928. mat[2] = 0;
  929. mat[3] = 0;
  930. mat[4] = 0;
  931. mat[5] = y;
  932. mat[6] = 0;
  933. mat[7] = 0;
  934. mat[8] = 0;
  935. mat[9] = 0;
  936. mat[10] = z;
  937. mat[11] = 0;
  938. mat[12] = 0;
  939. mat[13] = 0;
  940. mat[14] = 0;
  941. mat[15] = 1;
  942. return mat;
  943. };
  944. /**
  945. * Makes the given 4x4 matrix a rotation matrix with the given rotation
  946. * angle about the axis defined by the vector (ax, ay, az).
  947. *
  948. * @param {!goog.vec.mat4d.Type} mat The matrix.
  949. * @param {number} angle The rotation angle in radians.
  950. * @param {number} ax The x component of the rotation axis.
  951. * @param {number} ay The y component of the rotation axis.
  952. * @param {number} az The z component of the rotation axis.
  953. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  954. * chained.
  955. */
  956. goog.vec.mat4d.makeRotate = function(mat, angle, ax, ay, az) {
  957. var c = Math.cos(angle);
  958. var d = 1 - c;
  959. var s = Math.sin(angle);
  960. mat[0] = ax * ax * d + c;
  961. mat[1] = ax * ay * d + az * s;
  962. mat[2] = ax * az * d - ay * s;
  963. mat[3] = 0;
  964. mat[4] = ax * ay * d - az * s;
  965. mat[5] = ay * ay * d + c;
  966. mat[6] = ay * az * d + ax * s;
  967. mat[7] = 0;
  968. mat[8] = ax * az * d + ay * s;
  969. mat[9] = ay * az * d - ax * s;
  970. mat[10] = az * az * d + c;
  971. mat[11] = 0;
  972. mat[12] = 0;
  973. mat[13] = 0;
  974. mat[14] = 0;
  975. mat[15] = 1;
  976. return mat;
  977. };
  978. /**
  979. * Makes the given 4x4 matrix a rotation matrix with the given rotation
  980. * angle about the X axis.
  981. *
  982. * @param {!goog.vec.mat4d.Type} mat The matrix.
  983. * @param {number} angle The rotation angle in radians.
  984. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  985. * chained.
  986. */
  987. goog.vec.mat4d.makeRotateX = function(mat, angle) {
  988. var c = Math.cos(angle);
  989. var s = Math.sin(angle);
  990. mat[0] = 1;
  991. mat[1] = 0;
  992. mat[2] = 0;
  993. mat[3] = 0;
  994. mat[4] = 0;
  995. mat[5] = c;
  996. mat[6] = s;
  997. mat[7] = 0;
  998. mat[8] = 0;
  999. mat[9] = -s;
  1000. mat[10] = c;
  1001. mat[11] = 0;
  1002. mat[12] = 0;
  1003. mat[13] = 0;
  1004. mat[14] = 0;
  1005. mat[15] = 1;
  1006. return mat;
  1007. };
  1008. /**
  1009. * Makes the given 4x4 matrix a rotation matrix with the given rotation
  1010. * angle about the Y axis.
  1011. *
  1012. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1013. * @param {number} angle The rotation angle in radians.
  1014. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1015. * chained.
  1016. */
  1017. goog.vec.mat4d.makeRotateY = function(mat, angle) {
  1018. var c = Math.cos(angle);
  1019. var s = Math.sin(angle);
  1020. mat[0] = c;
  1021. mat[1] = 0;
  1022. mat[2] = -s;
  1023. mat[3] = 0;
  1024. mat[4] = 0;
  1025. mat[5] = 1;
  1026. mat[6] = 0;
  1027. mat[7] = 0;
  1028. mat[8] = s;
  1029. mat[9] = 0;
  1030. mat[10] = c;
  1031. mat[11] = 0;
  1032. mat[12] = 0;
  1033. mat[13] = 0;
  1034. mat[14] = 0;
  1035. mat[15] = 1;
  1036. return mat;
  1037. };
  1038. /**
  1039. * Makes the given 4x4 matrix a rotation matrix with the given rotation
  1040. * angle about the Z axis.
  1041. *
  1042. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1043. * @param {number} angle The rotation angle in radians.
  1044. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1045. * chained.
  1046. */
  1047. goog.vec.mat4d.makeRotateZ = function(mat, angle) {
  1048. var c = Math.cos(angle);
  1049. var s = Math.sin(angle);
  1050. mat[0] = c;
  1051. mat[1] = s;
  1052. mat[2] = 0;
  1053. mat[3] = 0;
  1054. mat[4] = -s;
  1055. mat[5] = c;
  1056. mat[6] = 0;
  1057. mat[7] = 0;
  1058. mat[8] = 0;
  1059. mat[9] = 0;
  1060. mat[10] = 1;
  1061. mat[11] = 0;
  1062. mat[12] = 0;
  1063. mat[13] = 0;
  1064. mat[14] = 0;
  1065. mat[15] = 1;
  1066. return mat;
  1067. };
  1068. /**
  1069. * Creates a matrix from a quaternion rotation and vector translation.
  1070. *
  1071. * This is a specialization of makeRotationTranslationScaleOrigin.
  1072. *
  1073. * This is equivalent to, but faster than:
  1074. * goog.vec.mat4d.makeIdentity(m);
  1075. * goog.vec.mat4d.translate(m, tx, ty, tz);
  1076. * goog.vec.mat4d.rotate(m, theta, rx, ry, rz);
  1077. * and:
  1078. * goog.vec.Quaternion.toRotationMatrix4(rotation, mat);
  1079. * mat[12] = translation[0];
  1080. * mat[13] = translation[1];
  1081. * mat[14] = translation[2];
  1082. * See http://jsperf.com/goog-vec-makerotationtranslation2 .
  1083. *
  1084. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1085. * @param {!goog.vec.Quaternion.AnyType} rotation The quaternion rotation.
  1086. * Note: this quaternion is assumed to already be normalized.
  1087. * @param {!goog.vec.vec3d.Type} translation The vector translation.
  1088. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1089. * chained.
  1090. */
  1091. goog.vec.mat4d.makeRotationTranslation = function(mat, rotation, translation) {
  1092. // Quaternion math
  1093. var x = rotation[0], y = rotation[1], z = rotation[2], w = rotation[3];
  1094. var x2 = 2 * x, y2 = 2 * y, z2 = 2 * z;
  1095. var xx = x * x2;
  1096. var xy = x * y2;
  1097. var xz = x * z2;
  1098. var yy = y * y2;
  1099. var yz = y * z2;
  1100. var zz = z * z2;
  1101. var wx = w * x2;
  1102. var wy = w * y2;
  1103. var wz = w * z2;
  1104. mat[0] = 1 - (yy + zz);
  1105. mat[1] = xy + wz;
  1106. mat[2] = xz - wy;
  1107. mat[3] = 0;
  1108. mat[4] = xy - wz;
  1109. mat[5] = 1 - (xx + zz);
  1110. mat[6] = yz + wx;
  1111. mat[7] = 0;
  1112. mat[8] = xz + wy;
  1113. mat[9] = yz - wx;
  1114. mat[10] = 1 - (xx + yy);
  1115. mat[11] = 0;
  1116. mat[12] = translation[0];
  1117. mat[13] = translation[1];
  1118. mat[14] = translation[2];
  1119. mat[15] = 1;
  1120. return mat;
  1121. };
  1122. /**
  1123. * Creates a matrix from a quaternion rotation, vector translation, and
  1124. * vector scale.
  1125. *
  1126. * This is a specialization of makeRotationTranslationScaleOrigin.
  1127. *
  1128. * This is equivalent to, but faster than:
  1129. * goog.vec.mat4d.makeIdentity(m);
  1130. * goog.vec.mat4d.translate(m, tx, ty, tz);
  1131. * goog.vec.mat4d.rotate(m, theta, rx, ry, rz);
  1132. * goog.vec.mat4d.scale(m, sx, sy, sz);
  1133. *
  1134. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1135. * @param {!goog.vec.Quaternion.AnyType} rotation The quaternion rotation.
  1136. * Note: this quaternion is assumed to already be normalized.
  1137. * @param {!goog.vec.vec3d.Type} translation The vector translation.
  1138. * @param {!goog.vec.vec3d.Type} scale The vector scale.
  1139. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1140. * chained.
  1141. */
  1142. goog.vec.mat4d.makeRotationTranslationScale = function(
  1143. mat, rotation, translation, scale) {
  1144. // Quaternion math
  1145. var x = rotation[0], y = rotation[1], z = rotation[2], w = rotation[3];
  1146. var x2 = 2 * x, y2 = 2 * y, z2 = 2 * z;
  1147. var xx = x * x2;
  1148. var xy = x * y2;
  1149. var xz = x * z2;
  1150. var yy = y * y2;
  1151. var yz = y * z2;
  1152. var zz = z * z2;
  1153. var wx = w * x2;
  1154. var wy = w * y2;
  1155. var wz = w * z2;
  1156. var sx = scale[0];
  1157. var sy = scale[1];
  1158. var sz = scale[2];
  1159. mat[0] = (1 - (yy + zz)) * sx;
  1160. mat[1] = (xy + wz) * sx;
  1161. mat[2] = (xz - wy) * sx;
  1162. mat[3] = 0;
  1163. mat[4] = (xy - wz) * sy;
  1164. mat[5] = (1 - (xx + zz)) * sy;
  1165. mat[6] = (yz + wx) * sy;
  1166. mat[7] = 0;
  1167. mat[8] = (xz + wy) * sz;
  1168. mat[9] = (yz - wx) * sz;
  1169. mat[10] = (1 - (xx + yy)) * sz;
  1170. mat[11] = 0;
  1171. mat[12] = translation[0];
  1172. mat[13] = translation[1];
  1173. mat[14] = translation[2];
  1174. mat[15] = 1;
  1175. return mat;
  1176. };
  1177. /**
  1178. * Creates a matrix from a quaternion rotation, vector translation, and
  1179. * vector scale, rotating and scaling about the given origin.
  1180. *
  1181. * This is equivalent to, but faster than:
  1182. * goog.vec.mat4d.makeIdentity(m);
  1183. * goog.vec.mat4d.translate(m, tx, ty, tz);
  1184. * goog.vec.mat4d.translate(m, ox, oy, oz);
  1185. * goog.vec.mat4d.rotate(m, theta, rx, ry, rz);
  1186. * goog.vec.mat4d.scale(m, sx, sy, sz);
  1187. * goog.vec.mat4d.translate(m, -ox, -oy, -oz);
  1188. * See http://jsperf.com/glmatrix-matrix-variant-test/3 for performance
  1189. * results of a similar function in the glmatrix library.
  1190. *
  1191. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1192. * @param {!goog.vec.Quaternion.AnyType} rotation The quaternion rotation.
  1193. * Note: this quaternion is assumed to already be normalized.
  1194. * @param {!goog.vec.vec3d.Type} translation The vector translation.
  1195. * @param {!goog.vec.vec3d.Type} scale The vector scale.
  1196. * @param {!goog.vec.vec3d.Type} origin The origin about which to scale and
  1197. * rotate.
  1198. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1199. * chained.
  1200. */
  1201. goog.vec.mat4d.makeRotationTranslationScaleOrigin = function(
  1202. mat, rotation, translation, scale, origin) {
  1203. // Quaternion math
  1204. var x = rotation[0], y = rotation[1], z = rotation[2], w = rotation[3];
  1205. var x2 = 2 * x, y2 = 2 * y, z2 = 2 * z;
  1206. var xx = x * x2;
  1207. var xy = x * y2;
  1208. var xz = x * z2;
  1209. var yy = y * y2;
  1210. var yz = y * z2;
  1211. var zz = z * z2;
  1212. var wx = w * x2;
  1213. var wy = w * y2;
  1214. var wz = w * z2;
  1215. var sx = scale[0];
  1216. var sy = scale[1];
  1217. var sz = scale[2];
  1218. var ox = origin[0];
  1219. var oy = origin[1];
  1220. var oz = origin[2];
  1221. mat[0] = (1 - (yy + zz)) * sx;
  1222. mat[1] = (xy + wz) * sx;
  1223. mat[2] = (xz - wy) * sx;
  1224. mat[3] = 0;
  1225. mat[4] = (xy - wz) * sy;
  1226. mat[5] = (1 - (xx + zz)) * sy;
  1227. mat[6] = (yz + wx) * sy;
  1228. mat[7] = 0;
  1229. mat[8] = (xz + wy) * sz;
  1230. mat[9] = (yz - wx) * sz;
  1231. mat[10] = (1 - (xx + yy)) * sz;
  1232. mat[11] = 0;
  1233. mat[12] = translation[0] + ox - (mat[0] * ox + mat[4] * oy + mat[8] * oz);
  1234. mat[13] = translation[1] + oy - (mat[1] * ox + mat[5] * oy + mat[9] * oz);
  1235. mat[14] = translation[2] + oz - (mat[2] * ox + mat[6] * oy + mat[10] * oz);
  1236. mat[15] = 1;
  1237. return mat;
  1238. };
  1239. /**
  1240. * Makes the given 4x4 matrix a perspective projection matrix.
  1241. *
  1242. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1243. * @param {number} left The coordinate of the left clipping plane.
  1244. * @param {number} right The coordinate of the right clipping plane.
  1245. * @param {number} bottom The coordinate of the bottom clipping plane.
  1246. * @param {number} top The coordinate of the top clipping plane.
  1247. * @param {number} near The distance to the near clipping plane.
  1248. * @param {number} far The distance to the far clipping plane.
  1249. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1250. * chained.
  1251. */
  1252. goog.vec.mat4d.makeFrustum = function(
  1253. mat, left, right, bottom, top, near, far) {
  1254. var x = (2 * near) / (right - left);
  1255. var y = (2 * near) / (top - bottom);
  1256. var a = (right + left) / (right - left);
  1257. var b = (top + bottom) / (top - bottom);
  1258. var c = -(far + near) / (far - near);
  1259. var d = -(2 * far * near) / (far - near);
  1260. mat[0] = x;
  1261. mat[1] = 0;
  1262. mat[2] = 0;
  1263. mat[3] = 0;
  1264. mat[4] = 0;
  1265. mat[5] = y;
  1266. mat[6] = 0;
  1267. mat[7] = 0;
  1268. mat[8] = a;
  1269. mat[9] = b;
  1270. mat[10] = c;
  1271. mat[11] = -1;
  1272. mat[12] = 0;
  1273. mat[13] = 0;
  1274. mat[14] = d;
  1275. mat[15] = 0;
  1276. return mat;
  1277. };
  1278. /**
  1279. * Makes the given 4x4 matrix perspective projection matrix given a
  1280. * field of view and aspect ratio.
  1281. *
  1282. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1283. * @param {number} fovy The field of view along the y (vertical) axis in
  1284. * radians.
  1285. * @param {number} aspect The x (width) to y (height) aspect ratio.
  1286. * @param {number} near The distance to the near clipping plane.
  1287. * @param {number} far The distance to the far clipping plane.
  1288. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1289. * chained.
  1290. */
  1291. goog.vec.mat4d.makePerspective = function(mat, fovy, aspect, near, far) {
  1292. var angle = fovy / 2;
  1293. var dz = far - near;
  1294. var sinAngle = Math.sin(angle);
  1295. if (dz == 0 || sinAngle == 0 || aspect == 0) {
  1296. return mat;
  1297. }
  1298. var cot = Math.cos(angle) / sinAngle;
  1299. mat[0] = cot / aspect;
  1300. mat[1] = 0;
  1301. mat[2] = 0;
  1302. mat[3] = 0;
  1303. mat[4] = 0;
  1304. mat[5] = cot;
  1305. mat[6] = 0;
  1306. mat[7] = 0;
  1307. mat[8] = 0;
  1308. mat[9] = 0;
  1309. mat[10] = -(far + near) / dz;
  1310. mat[11] = -1;
  1311. mat[12] = 0;
  1312. mat[13] = 0;
  1313. mat[14] = -(2 * near * far) / dz;
  1314. mat[15] = 0;
  1315. return mat;
  1316. };
  1317. /**
  1318. * Makes the given 4x4 matrix an orthographic projection matrix.
  1319. *
  1320. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1321. * @param {number} left The coordinate of the left clipping plane.
  1322. * @param {number} right The coordinate of the right clipping plane.
  1323. * @param {number} bottom The coordinate of the bottom clipping plane.
  1324. * @param {number} top The coordinate of the top clipping plane.
  1325. * @param {number} near The distance to the near clipping plane.
  1326. * @param {number} far The distance to the far clipping plane.
  1327. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1328. * chained.
  1329. */
  1330. goog.vec.mat4d.makeOrtho = function(mat, left, right, bottom, top, near, far) {
  1331. var x = 2 / (right - left);
  1332. var y = 2 / (top - bottom);
  1333. var z = -2 / (far - near);
  1334. var a = -(right + left) / (right - left);
  1335. var b = -(top + bottom) / (top - bottom);
  1336. var c = -(far + near) / (far - near);
  1337. mat[0] = x;
  1338. mat[1] = 0;
  1339. mat[2] = 0;
  1340. mat[3] = 0;
  1341. mat[4] = 0;
  1342. mat[5] = y;
  1343. mat[6] = 0;
  1344. mat[7] = 0;
  1345. mat[8] = 0;
  1346. mat[9] = 0;
  1347. mat[10] = z;
  1348. mat[11] = 0;
  1349. mat[12] = a;
  1350. mat[13] = b;
  1351. mat[14] = c;
  1352. mat[15] = 1;
  1353. return mat;
  1354. };
  1355. /**
  1356. * Makes the given 4x4 matrix a modelview matrix of a camera so that
  1357. * the camera is 'looking at' the given center point.
  1358. *
  1359. * Note that unlike most other goog.vec functions where we inline
  1360. * everything, this function does not inline various goog.vec
  1361. * functions. This makes the code more readable, but somewhat
  1362. * less efficient.
  1363. *
  1364. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1365. * @param {!goog.vec.vec3d.Type} eyePt The position of the eye point
  1366. * (camera origin).
  1367. * @param {!goog.vec.vec3d.Type} centerPt The point to aim the camera at.
  1368. * @param {!goog.vec.vec3d.Type} worldUpVec The vector that identifies
  1369. * the up direction for the camera.
  1370. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1371. * chained.
  1372. */
  1373. goog.vec.mat4d.makeLookAt = function(mat, eyePt, centerPt, worldUpVec) {
  1374. // Compute the direction vector from the eye point to the center point and
  1375. // normalize.
  1376. var fwdVec = goog.vec.mat4d.tmpvec4d_[0];
  1377. goog.vec.vec3d.subtract(centerPt, eyePt, fwdVec);
  1378. goog.vec.vec3d.normalize(fwdVec, fwdVec);
  1379. fwdVec[3] = 0;
  1380. // Compute the side vector from the forward vector and the input up vector.
  1381. var sideVec = goog.vec.mat4d.tmpvec4d_[1];
  1382. goog.vec.vec3d.cross(fwdVec, worldUpVec, sideVec);
  1383. goog.vec.vec3d.normalize(sideVec, sideVec);
  1384. sideVec[3] = 0;
  1385. // Now the up vector to form the orthonormal basis.
  1386. var upVec = goog.vec.mat4d.tmpvec4d_[2];
  1387. goog.vec.vec3d.cross(sideVec, fwdVec, upVec);
  1388. goog.vec.vec3d.normalize(upVec, upVec);
  1389. upVec[3] = 0;
  1390. // Update the view matrix with the new orthonormal basis and position the
  1391. // camera at the given eye point.
  1392. goog.vec.vec3d.negate(fwdVec, fwdVec);
  1393. goog.vec.mat4d.setRow(mat, 0, sideVec);
  1394. goog.vec.mat4d.setRow(mat, 1, upVec);
  1395. goog.vec.mat4d.setRow(mat, 2, fwdVec);
  1396. goog.vec.mat4d.setRowValues(mat, 3, 0, 0, 0, 1);
  1397. goog.vec.mat4d.translate(mat, -eyePt[0], -eyePt[1], -eyePt[2]);
  1398. return mat;
  1399. };
  1400. /**
  1401. * Decomposes a matrix into the lookAt vectors eyePt, fwdVec and worldUpVec.
  1402. * The matrix represents the modelview matrix of a camera. It is the inverse
  1403. * of lookAt except for the output of the fwdVec instead of centerPt.
  1404. * The centerPt itself cannot be recovered from a modelview matrix.
  1405. *
  1406. * Note that unlike most other goog.vec functions where we inline
  1407. * everything, this function does not inline various goog.vec
  1408. * functions. This makes the code more readable, but somewhat
  1409. * less efficient.
  1410. *
  1411. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1412. * @param {!goog.vec.vec3d.Type} eyePt The position of the eye point
  1413. * (camera origin).
  1414. * @param {!goog.vec.vec3d.Type} fwdVec The vector describing where
  1415. * the camera points to.
  1416. * @param {!goog.vec.vec3d.Type} worldUpVec The vector that
  1417. * identifies the up direction for the camera.
  1418. * @return {boolean} True if the method succeeds, false otherwise.
  1419. * The method can only fail if the inverse of viewMatrix is not defined.
  1420. */
  1421. goog.vec.mat4d.toLookAt = function(mat, eyePt, fwdVec, worldUpVec) {
  1422. // Get eye of the camera.
  1423. var matInverse = goog.vec.mat4d.tmpmat4d_[0];
  1424. if (!goog.vec.mat4d.invert(mat, matInverse)) {
  1425. // The input matrix does not have a valid inverse.
  1426. return false;
  1427. }
  1428. if (eyePt) {
  1429. eyePt[0] = matInverse[12];
  1430. eyePt[1] = matInverse[13];
  1431. eyePt[2] = matInverse[14];
  1432. }
  1433. // Get forward vector from the definition of lookAt.
  1434. if (fwdVec || worldUpVec) {
  1435. if (!fwdVec) {
  1436. fwdVec = goog.vec.mat4d.tmpvec3d_[0];
  1437. }
  1438. fwdVec[0] = -mat[2];
  1439. fwdVec[1] = -mat[6];
  1440. fwdVec[2] = -mat[10];
  1441. // Normalize forward vector.
  1442. goog.vec.vec3d.normalize(fwdVec, fwdVec);
  1443. }
  1444. if (worldUpVec) {
  1445. // Get side vector from the definition of gluLookAt.
  1446. var side = goog.vec.mat4d.tmpvec3d_[1];
  1447. side[0] = mat[0];
  1448. side[1] = mat[4];
  1449. side[2] = mat[8];
  1450. // Compute up vector as a up = side x forward.
  1451. goog.vec.vec3d.cross(side, fwdVec, worldUpVec);
  1452. // Normalize up vector.
  1453. goog.vec.vec3d.normalize(worldUpVec, worldUpVec);
  1454. }
  1455. return true;
  1456. };
  1457. /**
  1458. * Makes the given 4x4 matrix a rotation matrix given Euler angles using
  1459. * the ZXZ convention.
  1460. * Given the euler angles [theta1, theta2, theta3], the rotation is defined as
  1461. * rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
  1462. * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
  1463. * rotation_x(theta) means rotation around the X axis of theta radians,
  1464. *
  1465. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1466. * @param {number} theta1 The angle of rotation around the Z axis in radians.
  1467. * @param {number} theta2 The angle of rotation around the X axis in radians.
  1468. * @param {number} theta3 The angle of rotation around the Z axis in radians.
  1469. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1470. * chained.
  1471. */
  1472. goog.vec.mat4d.makeEulerZXZ = function(mat, theta1, theta2, theta3) {
  1473. var c1 = Math.cos(theta1);
  1474. var s1 = Math.sin(theta1);
  1475. var c2 = Math.cos(theta2);
  1476. var s2 = Math.sin(theta2);
  1477. var c3 = Math.cos(theta3);
  1478. var s3 = Math.sin(theta3);
  1479. mat[0] = c1 * c3 - c2 * s1 * s3;
  1480. mat[1] = c2 * c1 * s3 + c3 * s1;
  1481. mat[2] = s3 * s2;
  1482. mat[3] = 0;
  1483. mat[4] = -c1 * s3 - c3 * c2 * s1;
  1484. mat[5] = c1 * c2 * c3 - s1 * s3;
  1485. mat[6] = c3 * s2;
  1486. mat[7] = 0;
  1487. mat[8] = s2 * s1;
  1488. mat[9] = -c1 * s2;
  1489. mat[10] = c2;
  1490. mat[11] = 0;
  1491. mat[12] = 0;
  1492. mat[13] = 0;
  1493. mat[14] = 0;
  1494. mat[15] = 1;
  1495. return mat;
  1496. };
  1497. /**
  1498. * Decomposes a rotation matrix into Euler angles using the ZXZ convention so
  1499. * that rotation = rotation_z(theta1) * rotation_x(theta2) * rotation_z(theta3),
  1500. * with theta1 in [0, 2 * pi], theta2 in [0, pi] and theta3 in [0, 2 * pi].
  1501. * rotation_x(theta) means rotation around the X axis of theta radians.
  1502. *
  1503. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1504. * @param {!goog.vec.vec3d.Type} euler The ZXZ Euler angles in
  1505. * radians as [theta1, theta2, theta3].
  1506. * @param {boolean=} opt_theta2IsNegative Whether theta2 is in [-pi, 0] instead
  1507. * of the default [0, pi].
  1508. * @return {!goog.vec.vec4d.Type} return euler so that operations can be
  1509. * chained together.
  1510. */
  1511. goog.vec.mat4d.toEulerZXZ = function(mat, euler, opt_theta2IsNegative) {
  1512. // There is an ambiguity in the sign of sinTheta2 because of the sqrt.
  1513. var sinTheta2 = Math.sqrt(mat[2] * mat[2] + mat[6] * mat[6]);
  1514. // By default we explicitely constrain theta2 to be in [0, pi],
  1515. // so sinTheta2 is always positive. We can change the behavior and specify
  1516. // theta2 to be negative in [-pi, 0] with opt_Theta2IsNegative.
  1517. var signTheta2 = opt_theta2IsNegative ? -1 : 1;
  1518. if (sinTheta2 > goog.vec.EPSILON) {
  1519. euler[2] = Math.atan2(mat[2] * signTheta2, mat[6] * signTheta2);
  1520. euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
  1521. euler[0] = Math.atan2(mat[8] * signTheta2, -mat[9] * signTheta2);
  1522. } else {
  1523. // There is also an arbitrary choice for theta1 = 0 or theta2 = 0 here.
  1524. // We assume theta1 = 0 as some applications do not allow the camera to roll
  1525. // (i.e. have theta1 != 0).
  1526. euler[0] = 0;
  1527. euler[1] = Math.atan2(sinTheta2 * signTheta2, mat[10]);
  1528. euler[2] = Math.atan2(mat[1], mat[0]);
  1529. }
  1530. // Atan2 outputs angles in [-pi, pi] so we bring them back to [0, 2 * pi].
  1531. euler[0] = (euler[0] + Math.PI * 2) % (Math.PI * 2);
  1532. euler[2] = (euler[2] + Math.PI * 2) % (Math.PI * 2);
  1533. // For theta2 we want the angle to be in [0, pi] or [-pi, 0] depending on
  1534. // signTheta2.
  1535. euler[1] =
  1536. ((euler[1] * signTheta2 + Math.PI * 2) % (Math.PI * 2)) * signTheta2;
  1537. return euler;
  1538. };
  1539. /**
  1540. * Translates the given matrix by x,y,z. Equvialent to:
  1541. * goog.vec.mat4d.multMat(
  1542. * mat,
  1543. * goog.vec.mat4d.makeTranslate(goog.vec.mat4d.create(), x, y, z),
  1544. * mat);
  1545. *
  1546. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1547. * @param {number} x The translation along the x axis.
  1548. * @param {number} y The translation along the y axis.
  1549. * @param {number} z The translation along the z axis.
  1550. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1551. * chained.
  1552. */
  1553. goog.vec.mat4d.translate = function(mat, x, y, z) {
  1554. mat[12] += mat[0] * x + mat[4] * y + mat[8] * z;
  1555. mat[13] += mat[1] * x + mat[5] * y + mat[9] * z;
  1556. mat[14] += mat[2] * x + mat[6] * y + mat[10] * z;
  1557. mat[15] += mat[3] * x + mat[7] * y + mat[11] * z;
  1558. return mat;
  1559. };
  1560. /**
  1561. * Scales the given matrix by x,y,z. Equivalent to:
  1562. * goog.vec.mat4d.multMat(
  1563. * mat,
  1564. * goog.vec.mat4d.makeScale(goog.vec.mat4d.create(), x, y, z),
  1565. * mat);
  1566. *
  1567. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1568. * @param {number} x The x scale factor.
  1569. * @param {number} y The y scale factor.
  1570. * @param {number} z The z scale factor.
  1571. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1572. * chained.
  1573. */
  1574. goog.vec.mat4d.scale = function(mat, x, y, z) {
  1575. mat[0] = mat[0] * x;
  1576. mat[1] = mat[1] * x;
  1577. mat[2] = mat[2] * x;
  1578. mat[3] = mat[3] * x;
  1579. mat[4] = mat[4] * y;
  1580. mat[5] = mat[5] * y;
  1581. mat[6] = mat[6] * y;
  1582. mat[7] = mat[7] * y;
  1583. mat[8] = mat[8] * z;
  1584. mat[9] = mat[9] * z;
  1585. mat[10] = mat[10] * z;
  1586. mat[11] = mat[11] * z;
  1587. mat[12] = mat[12];
  1588. mat[13] = mat[13];
  1589. mat[14] = mat[14];
  1590. mat[15] = mat[15];
  1591. return mat;
  1592. };
  1593. /**
  1594. * Rotate the given matrix by angle about the x,y,z axis. Equivalent to:
  1595. * goog.vec.mat4d.multMat(
  1596. * mat,
  1597. * goog.vec.mat4d.makeRotate(goog.vec.mat4d.create(), angle, x, y, z),
  1598. * mat);
  1599. *
  1600. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1601. * @param {number} angle The angle in radians.
  1602. * @param {number} x The x component of the rotation axis.
  1603. * @param {number} y The y component of the rotation axis.
  1604. * @param {number} z The z component of the rotation axis.
  1605. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1606. * chained.
  1607. */
  1608. goog.vec.mat4d.rotate = function(mat, angle, x, y, z) {
  1609. var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
  1610. var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
  1611. var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
  1612. var cosAngle = Math.cos(angle);
  1613. var sinAngle = Math.sin(angle);
  1614. var diffCosAngle = 1 - cosAngle;
  1615. var r00 = x * x * diffCosAngle + cosAngle;
  1616. var r10 = x * y * diffCosAngle + z * sinAngle;
  1617. var r20 = x * z * diffCosAngle - y * sinAngle;
  1618. var r01 = x * y * diffCosAngle - z * sinAngle;
  1619. var r11 = y * y * diffCosAngle + cosAngle;
  1620. var r21 = y * z * diffCosAngle + x * sinAngle;
  1621. var r02 = x * z * diffCosAngle + y * sinAngle;
  1622. var r12 = y * z * diffCosAngle - x * sinAngle;
  1623. var r22 = z * z * diffCosAngle + cosAngle;
  1624. mat[0] = m00 * r00 + m01 * r10 + m02 * r20;
  1625. mat[1] = m10 * r00 + m11 * r10 + m12 * r20;
  1626. mat[2] = m20 * r00 + m21 * r10 + m22 * r20;
  1627. mat[3] = m30 * r00 + m31 * r10 + m32 * r20;
  1628. mat[4] = m00 * r01 + m01 * r11 + m02 * r21;
  1629. mat[5] = m10 * r01 + m11 * r11 + m12 * r21;
  1630. mat[6] = m20 * r01 + m21 * r11 + m22 * r21;
  1631. mat[7] = m30 * r01 + m31 * r11 + m32 * r21;
  1632. mat[8] = m00 * r02 + m01 * r12 + m02 * r22;
  1633. mat[9] = m10 * r02 + m11 * r12 + m12 * r22;
  1634. mat[10] = m20 * r02 + m21 * r12 + m22 * r22;
  1635. mat[11] = m30 * r02 + m31 * r12 + m32 * r22;
  1636. return mat;
  1637. };
  1638. /**
  1639. * Rotate the given matrix by angle about the x axis. Equivalent to:
  1640. * goog.vec.mat4d.multMat(
  1641. * mat,
  1642. * goog.vec.mat4d.makeRotateX(goog.vec.mat4d.create(), angle),
  1643. * mat);
  1644. *
  1645. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1646. * @param {number} angle The angle in radians.
  1647. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1648. * chained.
  1649. */
  1650. goog.vec.mat4d.rotateX = function(mat, angle) {
  1651. var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
  1652. var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
  1653. var c = Math.cos(angle);
  1654. var s = Math.sin(angle);
  1655. mat[4] = m01 * c + m02 * s;
  1656. mat[5] = m11 * c + m12 * s;
  1657. mat[6] = m21 * c + m22 * s;
  1658. mat[7] = m31 * c + m32 * s;
  1659. mat[8] = m01 * -s + m02 * c;
  1660. mat[9] = m11 * -s + m12 * c;
  1661. mat[10] = m21 * -s + m22 * c;
  1662. mat[11] = m31 * -s + m32 * c;
  1663. return mat;
  1664. };
  1665. /**
  1666. * Rotate the given matrix by angle about the y axis. Equivalent to:
  1667. * goog.vec.mat4d.multMat(
  1668. * mat,
  1669. * goog.vec.mat4d.makeRotateY(goog.vec.mat4d.create(), angle),
  1670. * mat);
  1671. *
  1672. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1673. * @param {number} angle The angle in radians.
  1674. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1675. * chained.
  1676. */
  1677. goog.vec.mat4d.rotateY = function(mat, angle) {
  1678. var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
  1679. var m02 = mat[8], m12 = mat[9], m22 = mat[10], m32 = mat[11];
  1680. var c = Math.cos(angle);
  1681. var s = Math.sin(angle);
  1682. mat[0] = m00 * c + m02 * -s;
  1683. mat[1] = m10 * c + m12 * -s;
  1684. mat[2] = m20 * c + m22 * -s;
  1685. mat[3] = m30 * c + m32 * -s;
  1686. mat[8] = m00 * s + m02 * c;
  1687. mat[9] = m10 * s + m12 * c;
  1688. mat[10] = m20 * s + m22 * c;
  1689. mat[11] = m30 * s + m32 * c;
  1690. return mat;
  1691. };
  1692. /**
  1693. * Rotate the given matrix by angle about the z axis. Equivalent to:
  1694. * goog.vec.mat4d.multMat(
  1695. * mat,
  1696. * goog.vec.mat4d.makeRotateZ(goog.vec.mat4d.create(), angle),
  1697. * mat);
  1698. *
  1699. * @param {!goog.vec.mat4d.Type} mat The matrix.
  1700. * @param {number} angle The angle in radians.
  1701. * @return {!goog.vec.mat4d.Type} return mat so that operations can be
  1702. * chained.
  1703. */
  1704. goog.vec.mat4d.rotateZ = function(mat, angle) {
  1705. var m00 = mat[0], m10 = mat[1], m20 = mat[2], m30 = mat[3];
  1706. var m01 = mat[4], m11 = mat[5], m21 = mat[6], m31 = mat[7];
  1707. var c = Math.cos(angle);
  1708. var s = Math.sin(angle);
  1709. mat[0] = m00 * c + m01 * s;
  1710. mat[1] = m10 * c + m11 * s;
  1711. mat[2] = m20 * c + m21 * s;
  1712. mat[3] = m30 * c + m31 * s;
  1713. mat[4] = m00 * -s + m01 * c;
  1714. mat[5] = m10 * -s + m11 * c;
  1715. mat[6] = m20 * -s + m21 * c;
  1716. mat[7] = m30 * -s + m31 * c;
  1717. return mat;
  1718. };
  1719. /**
  1720. * Retrieves the translation component of the transformation matrix.
  1721. *
  1722. * @param {!goog.vec.mat4d.Type} mat The transformation matrix.
  1723. * @param {!goog.vec.vec3d.Type} translation The vector for storing the
  1724. * result.
  1725. * @return {!goog.vec.vec3d.Type} return translation so that operations can be
  1726. * chained.
  1727. */
  1728. goog.vec.mat4d.getTranslation = function(mat, translation) {
  1729. translation[0] = mat[12];
  1730. translation[1] = mat[13];
  1731. translation[2] = mat[14];
  1732. return translation;
  1733. };
  1734. /**
  1735. * @type {Array<goog.vec.vec3d.Type>}
  1736. * @private
  1737. */
  1738. goog.vec.mat4d.tmpvec3d_ = [goog.vec.vec3d.create(), goog.vec.vec3d.create()];
  1739. /**
  1740. * @type {Array<goog.vec.vec4d.Type>}
  1741. * @private
  1742. */
  1743. goog.vec.mat4d.tmpvec4d_ =
  1744. [goog.vec.vec4d.create(), goog.vec.vec4d.create(), goog.vec.vec4d.create()];
  1745. /**
  1746. * @type {Array<goog.vec.mat4d.Type>}
  1747. * @private
  1748. */
  1749. goog.vec.mat4d.tmpmat4d_ = [goog.vec.mat4d.create()];