Home Reference Source Repository

js/base/Matrix.js

  1. 'use strict'
  2.  
  3. import Vector3 from './Vector3'
  4. // import Vector4 from './Vector4'
  5.  
  6. /**
  7. * matrix class
  8. * @access public
  9. */
  10. export default class Matrix {
  11. /**
  12. * constructor
  13. * @access public
  14. * @constructor
  15. * @param {Matrix|array} matrix - a
  16. */
  17. constructor(matrix) {
  18. if(matrix instanceof Matrix){
  19. this.copyMatrix(matrix)
  20. }else if(typeof matrix === 'object') {
  21. if('length' in matrix && matrix.length >= 16){
  22. /** @type {float} */ this.m11 = matrix[ 0]
  23. /** @type {float} */ this.m12 = matrix[ 1]
  24. /** @type {float} */ this.m13 = matrix[ 2]
  25. /** @type {float} */ this.m14 = matrix[ 3]
  26. /** @type {float} */ this.m21 = matrix[ 4]
  27. /** @type {float} */ this.m22 = matrix[ 5]
  28. /** @type {float} */ this.m23 = matrix[ 6]
  29. /** @type {float} */ this.m24 = matrix[ 7]
  30. /** @type {float} */ this.m31 = matrix[ 8]
  31. /** @type {float} */ this.m32 = matrix[ 9]
  32. /** @type {float} */ this.m33 = matrix[10]
  33. /** @type {float} */ this.m34 = matrix[11]
  34. /** @type {float} */ this.m41 = matrix[12]
  35. /** @type {float} */ this.m42 = matrix[13]
  36. /** @type {float} */ this.m43 = matrix[14]
  37. /** @type {float} */ this.m44 = matrix[15]
  38. }
  39. }else{
  40. // default
  41. this.identity()
  42. }
  43. }
  44.  
  45. clone() {
  46. return new Matrix(this)
  47. }
  48.  
  49. /**
  50. * reset matrix
  51. * @access public
  52. * @returns {void}
  53. */
  54. identity() {
  55. this.m11 = 1
  56. this.m12 = 0
  57. this.m13 = 0
  58. this.m14 = 0
  59. this.m21 = 0
  60. this.m22 = 1
  61. this.m23 = 0
  62. this.m24 = 0
  63. this.m31 = 0
  64. this.m32 = 0
  65. this.m33 = 1
  66. this.m34 = 0
  67. this.m41 = 0
  68. this.m42 = 0
  69. this.m43 = 0
  70. this.m44 = 1
  71. }
  72.  
  73. /**
  74. * multiply matrix (src1 x src2), set result to this matrix
  75. * @access public
  76. * @param {Matrix} src1 -
  77. * @param {Matrix} src2 -
  78. * @returns {void}
  79. */
  80. multiplyMatrix(src1, src2) {
  81. const m11 = src1.m11 * src2.m11 + src1.m12 * src2.m21 + src1.m13 * src2.m31 + src1.m14 * src2.m41
  82. const m12 = src1.m11 * src2.m12 + src1.m12 * src2.m22 + src1.m13 * src2.m32 + src1.m14 * src2.m42
  83. const m13 = src1.m11 * src2.m13 + src1.m12 * src2.m23 + src1.m13 * src2.m33 + src1.m14 * src2.m43
  84. const m14 = src1.m11 * src2.m14 + src1.m12 * src2.m24 + src1.m13 * src2.m34 + src1.m14 * src2.m44
  85. const m21 = src1.m21 * src2.m11 + src1.m22 * src2.m21 + src1.m23 * src2.m31 + src1.m24 * src2.m41
  86. const m22 = src1.m21 * src2.m12 + src1.m22 * src2.m22 + src1.m23 * src2.m32 + src1.m24 * src2.m42
  87. const m23 = src1.m21 * src2.m13 + src1.m22 * src2.m23 + src1.m23 * src2.m33 + src1.m24 * src2.m43
  88. const m24 = src1.m21 * src2.m14 + src1.m22 * src2.m24 + src1.m23 * src2.m34 + src1.m24 * src2.m44
  89. const m31 = src1.m31 * src2.m11 + src1.m32 * src2.m21 + src1.m33 * src2.m31 + src1.m34 * src2.m41
  90. const m32 = src1.m31 * src2.m12 + src1.m32 * src2.m22 + src1.m33 * src2.m32 + src1.m34 * src2.m42
  91. const m33 = src1.m31 * src2.m13 + src1.m32 * src2.m23 + src1.m33 * src2.m33 + src1.m34 * src2.m43
  92. const m34 = src1.m31 * src2.m14 + src1.m32 * src2.m24 + src1.m33 * src2.m34 + src1.m34 * src2.m44
  93. const m41 = src1.m41 * src2.m11 + src1.m42 * src2.m21 + src1.m43 * src2.m31 + src1.m44 * src2.m41
  94. const m42 = src1.m41 * src2.m12 + src1.m42 * src2.m22 + src1.m43 * src2.m32 + src1.m44 * src2.m42
  95. const m43 = src1.m41 * src2.m13 + src1.m42 * src2.m23 + src1.m43 * src2.m33 + src1.m44 * src2.m43
  96. const m44 = src1.m41 * src2.m14 + src1.m42 * src2.m24 + src1.m43 * src2.m34 + src1.m44 * src2.m44
  97.  
  98. this.m11 = m11
  99. this.m12 = m12
  100. this.m13 = m13
  101. this.m14 = m14
  102. this.m21 = m21
  103. this.m22 = m22
  104. this.m23 = m23
  105. this.m24 = m24
  106. this.m31 = m31
  107. this.m32 = m32
  108. this.m33 = m33
  109. this.m34 = m34
  110. this.m41 = m41
  111. this.m42 = m42
  112. this.m43 = m43
  113. this.m44 = m44
  114. }
  115.  
  116. /**
  117. * blend 2 matrices.
  118. * if rate is 0, result is equal to src1.
  119. * if rate is 1, result is equal to src2.
  120. * @access public
  121. * @param {Matrix} src1 -
  122. * @param {Matrix} src2 -
  123. * @param {float} rate -
  124. * @returns {void}
  125. */
  126. lerp(src1, src2, rate) {
  127. this.m11 = src1.m11 + rate * (src1.m11 - src2.m11)
  128. this.m12 = src1.m12 + rate * (src1.m12 - src2.m12)
  129. this.m13 = src1.m13 + rate * (src1.m13 - src2.m13)
  130. this.m14 = src1.m14 + rate * (src1.m14 - src2.m14)
  131. this.m21 = src1.m21 + rate * (src1.m21 - src2.m21)
  132. this.m22 = src1.m22 + rate * (src1.m22 - src2.m22)
  133. this.m23 = src1.m23 + rate * (src1.m23 - src2.m23)
  134. this.m24 = src1.m24 + rate * (src1.m24 - src2.m24)
  135. this.m31 = src1.m31 + rate * (src1.m31 - src2.m31)
  136. this.m32 = src1.m32 + rate * (src1.m32 - src2.m32)
  137. this.m33 = src1.m33 + rate * (src1.m33 - src2.m33)
  138. this.m34 = src1.m34 + rate * (src1.m34 - src2.m34)
  139. this.m41 = src1.m41 + rate * (src1.m41 - src2.m41)
  140. this.m42 = src1.m42 + rate * (src1.m42 - src2.m42)
  141. this.m43 = src1.m43 + rate * (src1.m43 - src2.m43)
  142. this.m44 = src1.m44 + rate * (src1.m44 - src2.m44)
  143. }
  144.  
  145. /**
  146. * set rotation matrix from quaternion
  147. * @access public
  148. * @param {Vector4} quat - Quaternion
  149. * @returns {void}
  150. */
  151. matrixFromQuaternion(quat) {
  152. const x2 = quat.x * quat.x * 2.0
  153. const y2 = quat.y * quat.y * 2.0
  154. const z2 = quat.z * quat.z * 2.0
  155. const xy = quat.x * quat.y * 2.0
  156. const yz = quat.y * quat.z * 2.0
  157. const zx = quat.z * quat.x * 2.0
  158. const xw = quat.x * quat.w * 2.0
  159. const yw = quat.y * quat.w * 2.0
  160. const zw = quat.z * quat.w * 2.0
  161.  
  162. this.m11 = 1.0 - y2 - z2
  163. this.m12 = xy + zw
  164. this.m13 = zx - yw
  165. this.m14 = 0.0
  166. this.m21 = xy - zw
  167. this.m22 = 1.0 - z2 - x2
  168. this.m23 = yz + xw
  169. this.m24 = 0.0
  170. this.m31 = zx + yw
  171. this.m32 = yz - xw
  172. this.m33 = 1.0 - x2 - y2
  173. this.m34 = 0.0
  174. this.m41 = 0.0
  175. this.m42 = 0.0
  176. this.m43 = 0.0
  177. this.m44 = 1.0
  178. }
  179.  
  180. /**
  181. * copy matrix
  182. * @access public
  183. * @param {Matrix} src -
  184. * @returns {void}
  185. */
  186. copyMatrix(src) {
  187. this.m11 = src.m11
  188. this.m12 = src.m12
  189. this.m13 = src.m13
  190. this.m14 = src.m14
  191. this.m21 = src.m21
  192. this.m22 = src.m22
  193. this.m23 = src.m23
  194. this.m24 = src.m24
  195. this.m31 = src.m31
  196. this.m32 = src.m32
  197. this.m33 = src.m33
  198. this.m34 = src.m34
  199. this.m41 = src.m41
  200. this.m42 = src.m42
  201. this.m43 = src.m43
  202. this.m44 = src.m44
  203. }
  204.  
  205. /**
  206. * inverse matrix
  207. * @access public
  208. * @param {Matrix} src -
  209. * @returns {void}
  210. */
  211. inverseMatrix(src) {
  212. const temp = new Matrix(src)
  213. let buf = 0
  214. let w1 = Math.abs(temp.m11)
  215. let w2 = Math.abs(temp.m21)
  216. let w3 = Math.abs(temp.m31)
  217. let w4 = Math.abs(temp.m41)
  218. let max = w1 > w2 ? w1 : w2
  219. if(max < w3) max = w3
  220.  
  221. this.identity()
  222. // 1
  223. if(max < w4){
  224. buf = 1.0 / temp.m41
  225. w1 = temp.m11
  226. w2 = temp.m12
  227. w3 = temp.m13
  228. w4 = temp.m14
  229. temp.m12 = temp.m42 * buf
  230. temp.m13 = temp.m43 * buf
  231. temp.m14 = temp.m44 * buf
  232. temp.m41 = w1
  233. temp.m42 = w2
  234. temp.m43 = w3
  235. temp.m44 = w4
  236. this.m11 = 0.0
  237. this.m14 = buf
  238. this.m41 = 1.0
  239. this.m44 = 0.0
  240. }else if(max === w1){
  241. buf = 1.0 / temp.m11
  242. temp.m12 *= buf
  243. temp.m13 *= buf
  244. temp.m14 *= buf
  245. this.m11 = buf
  246. }else if(max === w2){
  247. buf = 1.0 / temp.m21
  248. w1 = temp.m11
  249. w2 = temp.m12
  250. w3 = temp.m13
  251. w4 = temp.m14
  252. temp.m12 = temp.m22 * buf
  253. temp.m13 = temp.m23 * buf
  254. temp.m14 = temp.m24 * buf
  255. temp.m21 = w1
  256. temp.m22 = w2
  257. temp.m23 = w3
  258. temp.m24 = w4
  259. this.m11 = 0.0
  260. this.m12 = buf
  261. this.m21 = 1.0
  262. this.m22 = 0.0
  263. }else{
  264. buf = 1.0 / temp.m31
  265. w1 = temp.m11
  266. w2 = temp.m12
  267. w3 = temp.m13
  268. w4 = temp.m14
  269. temp.m12 = temp.m32 * buf
  270. temp.m13 = temp.m33 * buf
  271. temp.m14 = temp.m34 * buf
  272. temp.m31 = w1
  273. temp.m32 = w2
  274. temp.m33 = w3
  275. temp.m34 = w4
  276. this.m11 = 0.0
  277. this.m13 = buf
  278. this.m31 = 1.0
  279. this.m33 = 0.0
  280. }
  281.  
  282. buf = temp.m21
  283. temp.m22 -= temp.m12 * buf
  284. temp.m23 -= temp.m13 * buf
  285. temp.m24 -= temp.m14 * buf
  286. this.m21 -= this.m11 * buf
  287. this.m22 -= this.m12 * buf
  288. this.m23 -= this.m13 * buf
  289. this.m24 -= this.m14 * buf
  290.  
  291. buf = temp.m31
  292. temp.m32 -= temp.m12 * buf
  293. temp.m33 -= temp.m13 * buf
  294. temp.m34 -= temp.m14 * buf
  295. this.m31 -= this.m11 * buf
  296. this.m32 -= this.m12 * buf
  297. this.m33 -= this.m13 * buf
  298. this.m34 -= this.m14 * buf
  299.  
  300. buf = temp.m41
  301. temp.m42 -= temp.m12 * buf
  302. temp.m43 -= temp.m13 * buf
  303. temp.m44 -= temp.m14 * buf
  304. this.m41 -= this.m11 * buf
  305. this.m42 -= this.m12 * buf
  306. this.m43 -= this.m13 * buf
  307. this.m44 -= this.m14 * buf
  308.  
  309. // 2
  310. w2 = Math.abs(temp.m22)
  311. w3 = Math.abs(temp.m32)
  312. w4 = Math.abs(temp.m42)
  313. max = w2 > w3 ? w2 : w3
  314. if(max < w4){
  315. buf = 1.0 / temp.m42
  316. w2 = temp.m22
  317. w3 = temp.m23
  318. w4 = temp.m24
  319. temp.m23 = temp.m43 * buf
  320. temp.m24 = temp.m44 * buf
  321. temp.m42 = w2
  322. temp.m43 = w3
  323. temp.m44 = w4
  324. w1 = this.m21
  325. w2 = this.m22
  326. w3 = this.m23
  327. w4 = this.m24
  328. this.m21 = this.m41 * buf
  329. this.m22 = this.m42 * buf
  330. this.m23 = this.m43 * buf
  331. this.m24 = this.m44 * buf
  332. this.m41 = w1
  333. this.m42 = w2
  334. this.m43 = w3
  335. this.m44 = w4
  336. }else if(w2 > w3){
  337. buf = 1.0 / temp.m22
  338. temp.m23 *= buf
  339. temp.m24 *= buf
  340. this.m21 *= buf
  341. this.m22 *= buf
  342. this.m23 *= buf
  343. this.m24 *= buf
  344. }else{
  345. buf = 1.0 / temp.m32
  346. w2 = temp.m22
  347. w3 = temp.m23
  348. w4 = temp.m24
  349. temp.m23 = temp.m33 * buf
  350. temp.m24 = temp.m34 * buf
  351. temp.m32 = w2
  352. temp.m33 = w3
  353. temp.m34 = w4
  354. w1 = this.m21
  355. w2 = this.m22
  356. w3 = this.m23
  357. w4 = this.m24
  358. this.m21 = this.m31 * buf
  359. this.m22 = this.m32 * buf
  360. this.m23 = this.m33 * buf
  361. this.m24 = this.m34 * buf
  362. this.m31 = w1
  363. this.m32 = w2
  364. this.m33 = w3
  365. this.m34 = w4
  366. }
  367.  
  368. buf = temp.m12
  369. temp.m13 -= temp.m23 * buf
  370. temp.m14 -= temp.m24 * buf
  371. this.m11 -= this.m21 * buf
  372. this.m12 -= this.m22 * buf
  373. this.m13 -= this.m23 * buf
  374. this.m14 -= this.m24 * buf
  375.  
  376. buf = temp.m32
  377. temp.m33 -= temp.m23 * buf
  378. temp.m34 -= temp.m24 * buf
  379. this.m31 -= this.m21 * buf
  380. this.m32 -= this.m22 * buf
  381. this.m33 -= this.m23 * buf
  382. this.m34 -= this.m24 * buf
  383.  
  384. buf = temp.m42
  385. temp.m43 -= temp.m23 * buf
  386. temp.m44 -= temp.m24 * buf
  387. this.m41 -= this.m21 * buf
  388. this.m42 -= this.m22 * buf
  389. this.m43 -= this.m23 * buf
  390. this.m44 -= this.m24 * buf
  391.  
  392. // 3
  393. if(Math.abs(temp.m33) > Math.abs(temp.m43)){
  394. buf = 1.0 / temp.m33
  395. temp.m34 *= buf
  396. this.m31 *= buf
  397. this.m32 *= buf
  398. this.m33 *= buf
  399. this.m34 *= buf
  400. }else{
  401. buf = 1.0 / temp.m43
  402. w3 = temp.m33
  403. w4 = temp.m34
  404. temp.m34 = temp.m44 * buf
  405. temp.m43 = w3
  406. temp.m44 = w4
  407. w1 = this.m31
  408. w2 = this.m32
  409. w3 = this.m33
  410. w4 = this.m34
  411. this.m31 = this.m41 * buf
  412. this.m32 = this.m42 * buf
  413. this.m33 = this.m43 * buf
  414. this.m34 = this.m44 * buf
  415. this.m41 = w1
  416. this.m42 = w2
  417. this.m43 = w3
  418. this.m44 = w4
  419. }
  420. buf = temp.m13
  421. temp.m14 -= temp.m34 * buf
  422. this.m11 -= this.m31 * buf
  423. this.m12 -= this.m32 * buf
  424. this.m13 -= this.m33 * buf
  425. this.m14 -= this.m34 * buf
  426.  
  427. buf = temp.m23
  428. temp.m24 -= temp.m34 * buf
  429. this.m21 -= this.m31 * buf
  430. this.m22 -= this.m32 * buf
  431. this.m23 -= this.m33 * buf
  432. this.m24 -= this.m34 * buf
  433.  
  434. buf = temp.m43
  435. temp.m44 -= temp.m34 * buf
  436. this.m41 -= this.m31 * buf
  437. this.m42 -= this.m32 * buf
  438. this.m43 -= this.m33 * buf
  439. this.m44 -= this.m34 * buf
  440.  
  441. // 4
  442. buf = 1.0 / temp.m44
  443. this.m41 *= buf
  444. this.m42 *= buf
  445. this.m43 *= buf
  446. this.m44 *= buf
  447.  
  448. buf = temp.m14
  449. this.m11 -= this.m41 * buf
  450. this.m12 -= this.m42 * buf
  451. this.m13 -= this.m43 * buf
  452. this.m14 -= this.m44 * buf
  453.  
  454. buf = temp.m24
  455. this.m21 -= this.m41 * buf
  456. this.m22 -= this.m42 * buf
  457. this.m23 -= this.m43 * buf
  458. this.m24 -= this.m44 * buf
  459.  
  460. buf = temp.m34
  461. this.m31 -= this.m41 * buf
  462. this.m32 -= this.m42 * buf
  463. this.m33 -= this.m43 * buf
  464. this.m34 -= this.m44 * buf
  465. }
  466.  
  467. /**
  468. * transpose matrix
  469. * @access public
  470. * @param {Matrix} src -
  471. * @returns {void}
  472. */
  473. transposeMatrix(src) {
  474. this.m11 = src.m11
  475. this.m12 = src.m21
  476. this.m13 = src.m31
  477. this.m14 = src.m41
  478. this.m21 = src.m12
  479. this.m22 = src.m22
  480. this.m23 = src.m32
  481. this.m24 = src.m42
  482. this.m31 = src.m13
  483. this.m32 = src.m23
  484. this.m33 = src.m33
  485. this.m34 = src.m43
  486. this.m41 = src.m14
  487. this.m42 = src.m24
  488. this.m43 = src.m34
  489. this.m44 = src.m44
  490. }
  491.  
  492. /**
  493. * scale matrix
  494. * @access public
  495. * @param {Matrix} mat -
  496. * @param {float} x -
  497. * @param {float} y -
  498. * @param {float} z -
  499. * @returns {void}
  500. */
  501. scale(mat, x, y, z) {
  502. const r = new Matrix()
  503. r.identity()
  504.  
  505. if(!(mat instanceof Object) && z === undefined){
  506. r.m11 = mat
  507. r.m22 = x
  508. r.m33 = y
  509.  
  510. this.multiplyMatrix(this, r)
  511. }else{
  512. r.m11 = x
  513. r.m22 = y
  514. r.m33 = z
  515.  
  516. this.multiplyMatrix(mat, r)
  517. }
  518. }
  519.  
  520. /**
  521. * translate matrix
  522. * @access public
  523. * @param {Matrix} mat -
  524. * @param {float} x -
  525. * @param {float} y -
  526. * @param {float} z -
  527. * @returns {void}
  528. */
  529. translate(mat, x, y, z) {
  530. const r = new Matrix()
  531. r.identity()
  532. r.m14 = x
  533. r.m24 = y
  534. r.m34 = z
  535.  
  536. this.multiplyMatrix(mat, r)
  537. }
  538.  
  539. /**
  540. * rotate matrix
  541. * @access public
  542. * @param {Matrix} mat -
  543. * @param {float} angle -
  544. * @param {float} x -
  545. * @param {float} y -
  546. * @param {float} z -
  547. * @returns {void}
  548. */
  549. rotate(mat, angle, x, y, z) {
  550. const c = Math.cos(angle)
  551. const s = Math.sin(angle)
  552. const v = new Vector3(x, y, z)
  553. const r = new Matrix()
  554.  
  555. v.normalize()
  556. const nx = v.x
  557. const ny = v.y
  558. const nz = v.z
  559.  
  560. r.m11 = nx * nx * (1.0-c) + c
  561. r.m12 = nx * ny * (1.0-c) - nz * s
  562. r.m13 = nx * nz * (1.0-c) + ny * s
  563. r.m14 = 0.0
  564. r.m21 = ny * nx * (1.0-c) + nz * s
  565. r.m22 = ny * ny * (1.0-c) + c
  566. r.m23 = ny * nz * (1.0-c) - nx * s
  567. r.m24 = 0.0
  568. r.m31 = nz * nx * (1.0-c) - ny * s
  569. r.m32 = nz * ny * (1.0-c) + nx * s
  570. r.m33 = nz * nz * (1.0-c) + c
  571. r.m34 = 0.0
  572. r.m41 = 0.0
  573. r.m42 = 0.0
  574. r.m43 = 0.0
  575. r.m44 = 1.0
  576.  
  577. this.multiplyMatrix(mat, r)
  578. }
  579.  
  580. /**
  581. * get Float32Array format value of matrix for WebGL
  582. * @access public
  583. * @returns {Float32Array} matrix value
  584. */
  585. getWebGLFloatArray() {
  586. return new Float32Array([
  587. this.m11, this.m12, this.m13, this.m14,
  588. this.m21, this.m22, this.m23, this.m24,
  589. this.m31, this.m32, this.m33, this.m34,
  590. this.m41, this.m42, this.m43, this.m44
  591. ])
  592. }
  593.  
  594. /**
  595. * get Float32Array format value of transposed matrix for WebGL
  596. * @access public
  597. * @returns {Float32Array} transposed matrix value
  598. */
  599. getWebGLFloatArrayTransposed() {
  600. return new Float32Array([
  601. this.m11, this.m21, this.m31, this.m41,
  602. this.m12, this.m22, this.m32, this.m42,
  603. this.m13, this.m23, this.m33, this.m43,
  604. this.m14, this.m24, this.m34, this.m44
  605. ])
  606. }
  607.  
  608. /**
  609. * get array format value of matrix for WebGL
  610. * @access public
  611. * @returns {array} matrix value
  612. */
  613. getArray() {
  614. return [
  615. this.m11, this.m12, this.m13, this.m14,
  616. this.m21, this.m22, this.m23, this.m24,
  617. this.m31, this.m32, this.m33, this.m34,
  618. this.m41, this.m42, this.m43, this.m44
  619. ]
  620. }
  621.  
  622. /**
  623. * show matrix value to console for debug
  624. * @access public
  625. * @returns {void}
  626. */
  627. showMatrix() {
  628. /*
  629. console.log('matrix:<br />\n'
  630. + this.m11 + ' ' + this.m12 + ' ' + this.m13 + ' ' + this.m14 + '<br />\n'
  631. + this.m21 + ' ' + this.m22 + ' ' + this.m23 + ' ' + this.m24 + '<br />\n'
  632. + this.m31 + ' ' + this.m32 + ' ' + this.m33 + ' ' + this.m34 + '<br />\n'
  633. + this.m41 + ' ' + this.m42 + ' ' + this.m43 + ' ' + this.m44 + '<br />\n'
  634. )
  635. */
  636. }
  637. }
  638.