1 /**
  2  * Copyright (C) 2009-2012 Klaus Reimer <k@ailis.de>
  3  * See LICENSE.txt for licensing information
  4  * 
  5  * @require threedee.js
  6  */
  7 
  8 /**
  9  * @constructor
 10  * Constructs a new matrix initialized as an identity matrix.
 11  *            
 12  * @class
 13  * A matrix with 4x4 entries.
 14  */
 15 threedee.Matrix = function()
 16 {
 17     threedee.Matrix.counter++;
 18 };
 19 
 20 /** 
 21  * Instance counter. 
 22  * @private 
 23  * @type {number} 
 24  */
 25 threedee.Matrix.counter = 0;
 26 
 27 /** 
 28  * A temporary matrix for internal operations. 
 29  * @private 
 30  * @type {!threedee.Matrix} 
 31  */
 32 threedee.Matrix.TMP = new threedee.Matrix();
 33 
 34 /** 
 35  * The matrix entry 0;0. 
 36  * @type {number} 
 37  */
 38 threedee.Matrix.prototype.m00 = 1;
 39 
 40 /** 
 41  * The matrix entry 0;1.
 42  * @type {number} 
 43  */
 44 threedee.Matrix.prototype.m01 = 0;
 45 
 46 /** 
 47  * The matrix entry 0;2. 
 48  * @type {number} 
 49  */
 50 threedee.Matrix.prototype.m02 = 0;
 51 
 52 /** 
 53  * The matrix entry 0;3. 
 54  * @type {number} 
 55  */
 56 threedee.Matrix.prototype.m03 = 0;
 57 
 58 /** 
 59  * The matrix entry 1;0. 
 60  * @type {number} 
 61  */
 62 threedee.Matrix.prototype.m10 = 0;
 63 
 64 /** 
 65  * The matrix entry 1;1. 
 66  * @type {number} 
 67  */
 68 threedee.Matrix.prototype.m11 = 1;
 69 
 70 /** 
 71  * The matrix entry 1;2. 
 72  * @type {number} 
 73  */
 74 threedee.Matrix.prototype.m12 = 0;
 75 
 76 /** 
 77  * The matrix entry 1;3. 
 78  * @type {number} 
 79  */
 80 threedee.Matrix.prototype.m13 = 0;
 81 
 82 /** 
 83  * The matrix entry 2;0.
 84  * @type {number} 
 85  */
 86 threedee.Matrix.prototype.m20 = 0;
 87 
 88 /** 
 89  * The matrix entry 2;1. 
 90  * @type {number} 
 91  */
 92 threedee.Matrix.prototype.m21 = 0;
 93 
 94 /** 
 95  * The matrix entry 2;2. 
 96  * @type {number} *
 97  */
 98 threedee.Matrix.prototype.m22 = 1;
 99 
100 /** 
101  * The matrix entry 2;3. 
102  * @type {number} 
103  */
104 threedee.Matrix.prototype.m23 = 0;
105 
106 /** 
107  * The matrix entry 3;0. 
108  * @type {number} 
109  */
110 threedee.Matrix.prototype.m30 = 0;
111 
112 /** 
113  * The matrix entry 3;1. 
114  * @type {number} 
115  */
116 threedee.Matrix.prototype.m31 = 0;
117 
118 /** 
119  * The matrix entry 3;2. 
120  * @type {number} 
121  */
122 threedee.Matrix.prototype.m32 = 0;
123 
124 /** 
125  * The matrix entry 3;3. 
126  * @type {number} 
127  */
128 threedee.Matrix.prototype.m33 = 1;
129 
130 /**
131  * Returns and resets the current instance counter.
132  * 
133  * @return {number} 
134  *             The number of created instances since the last call.
135  */
136 threedee.Matrix.count = function()
137 {
138     var value = threedee.Matrix.counter;
139     threedee.Matrix.counter = 0;
140     return value;
141 };
142 
143 /**
144  * Returns a copy of this matrix.
145  * 
146  * @return {!threedee.Matrix} 
147  *            A copy of this matrix
148  */
149 threedee.Matrix.prototype.copy = function()
150 {
151     return new threedee.Matrix().set(
152         this.m00, this.m01, this.m02, this.m03,
153         this.m10, this.m11, this.m12, this.m13,
154         this.m20, this.m21, this.m22, this.m23,
155         this.m30, this.m31, this.m32, this.m33);
156 };
157 
158 /**
159  * Sets the matrix entries.
160  * 
161  * @param {number} m00
162  *            The matrix entry 0;0
163  * @param {number} m01
164  *            The matrix entry 0;1
165  * @param {number} m02
166  *            The matrix entry 0;2
167  * @param {number} m03
168  *            The matrix entry 0;3
169  * @param {number} m10
170  *            The matrix entry 1;0
171  * @param {number} m11
172  *            The matrix entry 1;1
173  * @param {number} m12
174  *            The matrix entry 1;2
175  * @param {number} m13
176  *            The matrix entry 1;3
177  * @param {number} m20
178  *            The matrix entry 2;0
179  * @param {number} m21
180  *            The matrix entry 2;1
181  * @param {number} m22
182  *            The matrix entry 2;2
183  * @param {number} m23
184  *            The matrix entry 2;3
185  * @param {number} m30
186  *            The matrix entry 3;0
187  * @param {number} m31
188  *            The matrix entry 3;1
189  * @param {number} m32
190  *            The matrix entry 3;2
191  * @param {number} m33
192  *            The matrix entry 3;3
193  * @return {!threedee.Matrix}
194  *            This matrix
195  */
196 threedee.Matrix.prototype.set = function(m00, m01, m02, m03,
197     m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33)
198 {
199     this.m00 = m00;
200     this.m01 = m01;
201     this.m02 = m02;
202     this.m03 = m03;
203     this.m10 = m10;
204     this.m11 = m11;
205     this.m12 = m12;
206     this.m13 = m13;
207     this.m20 = m20;
208     this.m21 = m21;
209     this.m22 = m22;
210     this.m23 = m23;
211     this.m30 = m30;
212     this.m31 = m31;
213     this.m32 = m32;
214     this.m33 = m33;
215     return this;
216 };
217 
218 /**
219  * Sets the entries of this matrix to an identity matrix.
220  * 
221  * @return {!threedee.Matrix}
222  *             The matrix
223  */
224 threedee.Matrix.prototype.setIdentity = function()
225 {
226     return this.set(
227         1, 0, 0, 0,
228         0, 1, 0, 0,
229         0, 0, 1, 0,
230         0, 0, 0, 1);
231 };
232 
233 /**
234  * Sets the entries of this matrix to an X rotation matrix.
235  * 
236  * @param {number} angle
237  *            The rotation angle in clock-wise RAD
238  * @return {!threedee.Matrix}
239  *            This matrix
240  */
241 threedee.Matrix.prototype.setRotateX = function(angle)
242 {
243     var s, c;
244     
245     s = Math.sin(angle);
246     c = Math.cos(angle);
247     return this.set(
248         1, 0, 0, 0,
249         0, c, -s, 0,
250         0, s, c, 0,
251         0, 0, 0, 1);
252 };
253 
254 /**
255  * Sets the entries of this matrix to an Y rotation matrix.
256  * 
257  * @param {number} angle
258  *            The rotation angle in anti-clock-wise RAD
259  * @return {!threedee.Matrix}
260  *            This matrix
261  */
262 threedee.Matrix.prototype.setRotateY = function(angle)
263 {
264     var s, c;
265     
266     s = Math.sin(angle);
267     c = Math.cos(angle);
268     return this.set(
269         c, 0, s, 0,
270         0, 1, 0, 0,
271         -s, 0, c, 0,
272         0, 0, 0, 1);
273 };
274 
275 /**
276  * Sets the entries of this matrix to an Z rotation matrix.
277  * 
278  * @param {number} angle
279  *            The rotation angle in anti-clock-wise RAD
280  * @return {!threedee.Matrix}
281  *            This matrix
282  */
283 threedee.Matrix.prototype.setRotateZ = function(angle)
284 {
285     var s, c;
286     
287     s = Math.sin(angle);
288     c = Math.cos(angle);
289     return this.set(
290         c, -s, 0, 0,
291         s, c, 0, 0,
292         0, 0, 1, 0,
293         0, 0, 0, 1);
294 };
295 
296 /**
297  * Sets the entries of this matrix to a scaling matrix.
298  * 
299  * @param {number} fx
300  *            The X scale factor
301  * @param {number} fy
302  *            The Y scale factor. Optional. Defaults to fx.
303  * @param {number} fz
304  *            The Z scale factor. Optional. Defaults to fx.
305  * @return {!threedee.Matrix}
306  *            This matrix
307  */
308 threedee.Matrix.prototype.setScale = function(fx, fy, fz)
309 {
310     return this.set(
311         fx, 0, 0, 0,
312         0, fy === undefined ? fx : fy, 0, 0,
313         0, 0, fz === undefined ? fx : fz, 0,
314         0, 0, 0, 1);
315 };
316 
317 /**
318  * Sets the entries of this matrix to a X scaling matrix.
319  * 
320  * @param {number} f
321  *            The scale factor
322  * @return {!threedee.Matrix}
323  *            This matrix
324  */
325 threedee.Matrix.prototype.setScaleX = function(f)
326 {
327     return this.set(
328         f, 0, 0, 0,
329         0, 1, 0, 0,
330         0, 0, 1, 0,
331         0, 0, 0, 1);
332 };
333 
334 /**
335  * Sets the entries of this matrix to a Y scaling matrix.
336  * 
337  * @param {number} f
338  *            The scale factor
339  * @return {!threedee.Matrix}
340  *            This matrix
341  */
342 threedee.Matrix.prototype.setScaleY = function(f)
343 {
344     return this.set(
345         1, 0, 0, 0,
346         0, f, 0, 0,
347         0, 0, 1, 0,
348         0, 0, 0, 1);
349 };
350 
351 /**
352  * Sets the entries of this matrix to a Z scaling matrix.
353  * 
354  * @param {number} f
355  *            The scale factor
356  * @return {!threedee.Matrix}
357  *            This matrix
358  */
359 threedee.Matrix.prototype.setScaleZ = function(f)
360 {
361     return this.set(
362         1, 0, 0, 0,
363         0, 1, 0, 0,
364         0, 0, f, 0,
365         0, 0, 0, 1);
366 };
367 
368 /**
369  * Sets the entries of this matrix to a translation matrix.
370  * 
371  * @param {number} dx
372  *            The X delta
373  * @param {number} dy
374  *            The Y delta.
375  * @param {number} dz
376  *            The Z delta.
377  * @return {!threedee.Matrix}
378  *            This matrix
379  */
380 threedee.Matrix.prototype.setTranslate = function(dx, dy, dz)
381 {
382     return this.set(
383         1, 0, 0, dx,
384         0, 1, 0, dy,
385         0, 0, 1, dz,
386         0, 0, 0, 1);
387 };
388 
389 /**
390  * Sets the entries of this matrix to a X translation matrix.
391  * 
392  * @param {number} d
393  *            The delta
394  * @return {!threedee.Matrix}
395  *            This matrix
396  */
397 threedee.Matrix.prototype.setTranslateX = function(d)
398 {
399     return this.set(
400         1, 0, 0, d,
401         0, 1, 0, 0,
402         0, 0, 1, 0,
403         0, 0, 0, 1);
404 };
405 
406 /**
407  * Sets the entries of this matrix to a Y translation matrix.
408  * 
409  * @param {number} d
410  *            The delta
411  * @return {!threedee.Matrix}
412  *            This matrix
413  */
414 threedee.Matrix.prototype.setTranslateY = function(d)
415 {
416     return this.set(
417         1, 0, 0, 0,
418         0, 1, 0, d,
419         0, 0, 1, 0,
420         0, 0, 0, 1);
421 };
422 
423 /**
424  * Sets the entries of this matrix to a Z translation matrix.
425  * 
426  * @param {number} d
427  *            The delta
428  * @return {!threedee.Matrix}
429  *            This matrix
430  */
431 threedee.Matrix.prototype.setTranslateZ = function(d)
432 {
433     return this.set(
434         1, 0, 0, 0,
435         0, 1, 0, 0,
436         0, 0, 1, d,
437         0, 0, 0, 1);
438 };
439 
440 /**
441  * Multiplies this matrix with the specified matrix. The result is written
442  * to this matrix.
443  * 
444  * @param {!threedee.Matrix} m
445  *            The other matrix
446  * @return {!threedee.Matrix}
447  *            This matrix
448  */
449 threedee.Matrix.prototype.transform = function(m)
450 {
451     return this.set(this.m00 * m.m00 + this.m01 * m.m10 + this.m02
452         * m.m20 + this.m03 * m.m30, this.m00 * m.m01 + this.m01 * m.m11
453         + this.m02 * m.m21 + this.m03 * m.m31, this.m00 * m.m02 + this.m01
454         * m.m12 + this.m02 * m.m22 + this.m03 * m.m32, this.m00 * m.m03
455         + this.m01 * m.m13 + this.m02 * m.m23 + this.m03 * m.m33,
456 
457     this.m10 * m.m00 + this.m11 * m.m10 + this.m12 * m.m20 + this.m13
458         * m.m30, this.m10 * m.m01 + this.m11 * m.m11 + this.m12 * m.m21
459         + this.m13 * m.m31, this.m10 * m.m02 + this.m11 * m.m12 + this.m12
460         * m.m22 + this.m13 * m.m32, this.m10 * m.m03 + this.m11 * m.m13
461         + this.m12 * m.m23 + this.m13 * m.m33,
462 
463     this.m20 * m.m00 + this.m21 * m.m10 + this.m22 * m.m20 + this.m23
464         * m.m30, this.m20 * m.m01 + this.m21 * m.m11 + this.m22 * m.m21
465         + this.m23 * m.m31, this.m20 * m.m02 + this.m21 * m.m12 + this.m22
466         * m.m22 + this.m23 * m.m32, this.m20 * m.m03 + this.m21 * m.m13
467         + this.m22 * m.m23 + this.m23 * m.m33,
468 
469     this.m30 * m.m00 + this.m31 * m.m10 + this.m32 * m.m20 + this.m33
470         * m.m30, this.m30 * m.m01 + this.m31 * m.m11 + this.m32 * m.m21
471         + this.m33 * m.m31, this.m30 * m.m02 + this.m31 * m.m12 + this.m32
472         * m.m22 + this.m33 * m.m32, this.m30 * m.m03 + this.m31 * m.m13
473         + this.m32 * m.m23 + this.m33 * m.m33);
474 };
475 
476 /**
477  * Multiplies this matrix with the specified factor.
478  * 
479  * @param {number} f
480  *            The factor
481  * @return {!threedee.Matrix}
482  *            This matrix
483  */
484 threedee.Matrix.prototype.multiply = function(f)
485 {
486     this.m00 *= f;
487     this.m01 *= f;
488     this.m02 *= f;
489     this.m03 *= f;
490     this.m10 *= f;
491     this.m11 *= f;
492     this.m12 *= f;
493     this.m13 *= f;
494     this.m20 *= f;
495     this.m21 *= f;
496     this.m22 *= f;
497     this.m23 *= f;
498     this.m30 *= f;
499     this.m31 *= f;
500     this.m32 *= f;
501     this.m33 *= f;
502     return this;
503 };
504 
505 /**
506  * Divides this matrix by the specified factor.
507  * 
508  * @param {number} f
509  *            The factor
510  * @return {!threedee.Matrix}
511  *            This matrix
512  */
513 threedee.Matrix.prototype.divide = function(f)
514 {
515     this.m00 /= f;
516     this.m01 /= f;
517     this.m02 /= f;
518     this.m03 /= f;
519     this.m10 /= f;
520     this.m11 /= f;
521     this.m12 /= f;
522     this.m13 /= f;
523     this.m20 /= f;
524     this.m21 /= f;
525     this.m22 /= f;
526     this.m23 /= f;
527     this.m30 /= f;
528     this.m31 /= f;
529     this.m32 /= f;
530     this.m33 /= f;
531     return this;
532 };
533 
534 /**
535  * Translates this matrix by the specified deltas
536  * 
537  * @param {number} dx
538  *            The X delta
539  * @param {number} dy
540  *            The Y delta
541  * @param {number} dz
542  *            The Z delta
543  * @return {!threedee.Matrix}
544  *            This matrix
545  */
546 threedee.Matrix.prototype.translate = function(dx, dy, dz)
547 {
548     return this.transform(threedee.Matrix.TMP.setTranslate(dx, dy, dz));
549 };
550 
551 /**
552  * X-Translates this matrix by the specified delta
553  * 
554  * @param {number} d
555  *            The delta
556  * @return {!threedee.Matrix}
557  *            This matrix
558  */
559 threedee.Matrix.prototype.translateX = function(d)
560 {
561     return this.transform(threedee.Matrix.TMP.setTranslateX(d));
562 };
563 
564 /**
565  * Y-Translates this matrix by the specified delta
566  * 
567  * @param {number} d
568  *            The delta
569  * @return {!threedee.Matrix}
570  *            This matrix
571  */
572 threedee.Matrix.prototype.translateY = function(d)
573 {
574     return this.transform(threedee.Matrix.TMP.setTranslateY(d));
575 };
576 
577 /**
578  * Z-Translates this matrix by the specified delta
579  * 
580  * @param {number} d
581  *            The delta
582  * @return {!threedee.Matrix}
583  *            This matrix
584  */
585 threedee.Matrix.prototype.translateZ = function(d)
586 {
587     return this.transform(threedee.Matrix.TMP.setTranslateZ(d));
588 };
589 
590 /**
591  * Scales this matrix by the specified factors
592  * 
593  * @param {number} fx
594  *            The X factor
595  * @param {number} fy
596  *            The Y factor. Optional. Defaults to fx.
597  * @param {number} fz
598  *            The Z factor. Optional. Defaults to fx.
599  * @return {!threedee.Matrix}
600  *            This matrix
601  */
602 threedee.Matrix.prototype.scale = function(fx, fy, fz)
603 {
604     return this.transform(threedee.Matrix.TMP.setScale(fx,
605         fy === undefined ? fx : fy, fz === undefined ? fx : fz));
606 };
607 
608 /**
609  * X-Scales this matrix by the specified factor
610  * 
611  * @param {number} f
612  *            The factor
613  * @return {!threedee.Matrix}
614  *            This matrix
615  */
616 threedee.Matrix.prototype.scaleX = function(f)
617 {
618     return this.transform(threedee.Matrix.TMP.setScaleX(f));
619 };
620 
621 /**
622  * Y-Scales this matrix by the specified factor
623  * 
624  * @param {number} f
625  *            The factor
626  * @return {!threedee.Matrix}
627  *            This matrix
628  */
629 threedee.Matrix.prototype.scaleY = function(f)
630 {
631     return this.transform(threedee.Matrix.TMP.setScaleY(f));
632 };
633 
634 /**
635  * Z-Scales this matrix by the specified factor
636  * 
637  * @param {number} f
638  *            The factor
639  * @return {!threedee.Matrix}
640  *            This matrix
641  */
642 threedee.Matrix.prototype.scaleZ = function(f)
643 {
644     return this.transform(threedee.Matrix.TMP.setScaleZ(f));
645 };
646 
647 /**
648  * X-Rotates this matrix by the specified angle
649  * 
650  * @param {number} r
651  *            The angle in clock-wise RAD
652  * @return {!threedee.Matrix}
653  *            This matrix
654  */
655 threedee.Matrix.prototype.rotateX = function(r)
656 {
657     return this.transform(threedee.Matrix.TMP.setRotateX(r));
658 };
659 
660 /**
661  * Y-Rotates this matrix by the specified angle
662  * 
663  * @param {number} r
664  *            The angle in clock-wise RAD
665  * @return {!threedee.Matrix}
666  *            This matrix
667  */
668 threedee.Matrix.prototype.rotateY = function(r)
669 {
670     return this.transform(threedee.Matrix.TMP.setRotateY(r));
671 };
672 
673 /**
674  * Z-Rotates this matrix by the specified angle
675  * 
676  * @param {number} r
677  *            The angle in clock-wise RAD
678  * @return {!threedee.Matrix}
679  *            This matrix
680  */
681 threedee.Matrix.prototype.rotateZ = function(r)
682 {
683     return this.transform(threedee.Matrix.TMP.setRotateZ(r));
684 };
685 
686 /**
687  * Returns the determinant of the matrix.
688  * 
689  * @return {number} The determinant of the matrix
690  */
691 threedee.Matrix.prototype.getDeterminant = function()
692 {
693     return this.m03 * this.m12 * this.m21 * this.m30 - this.m02
694          * this.m13 * this.m21 * this.m30 - this.m03 * this.m11
695          * this.m22 * this.m30 + this.m01 * this.m13 * this.m22
696          * this.m30 + this.m02 * this.m11 * this.m23 * this.m30
697          - this.m01 * this.m12 * this.m23 * this.m30 - this.m03
698          * this.m12 * this.m20 * this.m31 + this.m02 * this.m13
699          * this.m20 * this.m31 + this.m03 * this.m10 * this.m22
700          * this.m31 - this.m00 * this.m13 * this.m22 * this.m31
701          - this.m02 * this.m10 * this.m23 * this.m31 + this.m00
702          * this.m12 * this.m23 * this.m31 + this.m03 * this.m11
703          * this.m20 * this.m32 - this.m01 * this.m13 * this.m20
704          * this.m32 - this.m03 * this.m10 * this.m21 * this.m32
705          + this.m00 * this.m13 * this.m21 * this.m32 + this.m01
706          * this.m10 * this.m23 * this.m32 - this.m00 * this.m11
707          * this.m23 * this.m32 - this.m02 * this.m11 * this.m20
708          * this.m33 + this.m01 * this.m12 * this.m20 * this.m33
709          + this.m02 * this.m10 * this.m21 * this.m33 - this.m00
710          * this.m12 * this.m21 * this.m33 - this.m01 * this.m10
711          * this.m22 * this.m33 + this.m00 * this.m11 * this.m22
712          * this.m33;
713 };
714 
715 /**
716  * Inverts this matrix.
717  * 
718  * @return {!threedee.Matrix}
719  *            This matrix
720  */
721 threedee.Matrix.prototype.invert = function()
722 {
723     return this.set(
724         this.m12 * this.m23 * this.m31 - this.m13
725             * this.m22 * this.m31 + this.m13 * this.m21 * this.m32
726             - this.m11 * this.m23 * this.m32 - this.m12 * this.m21
727             * this.m33 + this.m11 * this.m22 * this.m33,
728     
729         this.m03 * this.m22 * this.m31 - this.m02 * this.m23
730             * this.m31 - this.m03 * this.m21 * this.m32 + this.m01
731             * this.m23 * this.m32 + this.m02 * this.m21 * this.m33
732             - this.m01 * this.m22 * this.m33,
733     
734         this.m02 * this.m13 * this.m31 - this.m03 * this.m12
735             * this.m31 + this.m03 * this.m11 * this.m32 - this.m01
736             * this.m13 * this.m32 - this.m02 * this.m11 * this.m33
737             + this.m01 * this.m12 * this.m33,
738     
739         this.m03 * this.m12 * this.m21 - this.m02 * this.m13
740             * this.m21 - this.m03 * this.m11 * this.m22 + this.m01
741             * this.m13 * this.m22 + this.m02 * this.m11 * this.m23
742             - this.m01 * this.m12 * this.m23,
743     
744         this.m13 * this.m22 * this.m30 - this.m12 * this.m23
745             * this.m30 - this.m13 * this.m20 * this.m32 + this.m10
746             * this.m23 * this.m32 + this.m12 * this.m20 * this.m33
747             - this.m10 * this.m22 * this.m33,
748     
749         this.m02 * this.m23 * this.m30 - this.m03 * this.m22
750             * this.m30 + this.m03 * this.m20 * this.m32 - this.m00
751             * this.m23 * this.m32 - this.m02 * this.m20 * this.m33
752             + this.m00 * this.m22 * this.m33,
753     
754         this.m03 * this.m12 * this.m30 - this.m02 * this.m13
755             * this.m30 - this.m03 * this.m10 * this.m32 + this.m00
756             * this.m13 * this.m32 + this.m02 * this.m10 * this.m33
757             - this.m00 * this.m12 * this.m33,
758     
759         this.m02 * this.m13 * this.m20 - this.m03 * this.m12
760             * this.m20 + this.m03 * this.m10 * this.m22 - this.m00
761             * this.m13 * this.m22 - this.m02 * this.m10 * this.m23
762             + this.m00 * this.m12 * this.m23,
763     
764         this.m11 * this.m23 * this.m30 - this.m13 * this.m21
765             * this.m30 + this.m13 * this.m20 * this.m31 - this.m10
766             * this.m23 * this.m31 - this.m11 * this.m20 * this.m33
767             + this.m10 * this.m21 * this.m33,
768     
769         this.m03 * this.m21 * this.m30 - this.m01 * this.m23
770             * this.m30 - this.m03 * this.m20 * this.m31 + this.m00
771             * this.m23 * this.m31 + this.m01 * this.m20 * this.m33
772             - this.m00 * this.m21 * this.m33,
773     
774         this.m01 * this.m13 * this.m30 - this.m03 * this.m11
775             * this.m30 + this.m03 * this.m10 * this.m31 - this.m00
776             * this.m13 * this.m31 - this.m01 * this.m10 * this.m33
777             + this.m00 * this.m11 * this.m33,
778     
779         this.m03 * this.m11 * this.m20 - this.m01 * this.m13
780             * this.m20 - this.m03 * this.m10 * this.m21 + this.m00
781             * this.m13 * this.m21 + this.m01 * this.m10 * this.m23
782             - this.m00 * this.m11 * this.m23,
783     
784         this.m12 * this.m21 * this.m30 - this.m11 * this.m22
785             * this.m30 - this.m12 * this.m20 * this.m31 + this.m10
786             * this.m22 * this.m31 + this.m11 * this.m20 * this.m32
787             - this.m10 * this.m21 * this.m32,
788     
789         this.m01 * this.m22 * this.m30 - this.m02 * this.m21
790             * this.m30 + this.m02 * this.m20 * this.m31 - this.m00
791             * this.m22 * this.m31 - this.m01 * this.m20 * this.m32
792             + this.m00 * this.m21 * this.m32,
793     
794         this.m02 * this.m11 * this.m30 - this.m01 * this.m12
795             * this.m30 - this.m02 * this.m10 * this.m31 + this.m00
796             * this.m12 * this.m31 + this.m01 * this.m10 * this.m32
797             - this.m00 * this.m11 * this.m32,
798     
799         this.m01 * this.m12 * this.m20 - this.m02 * this.m11
800             * this.m20 + this.m02 * this.m10 * this.m21 - this.m00
801             * this.m12 * this.m21 - this.m01 * this.m10 * this.m22
802             + this.m00 * this.m11 * this.m22).divide(this.getDeterminant());
803 };
804