1f16335ef4aa91df906c42287c84606b26134260
[jalview.git] / src / javajs / util / M4.java
1 /*
2    Copyright (C) 1997,1998,1999
3    Kenji Hiranabe, Eiwa System Management, Inc.
4
5    This program is free software.
6    Implemented by Kenji Hiranabe(hiranabe@esm.co.jp),
7    conforming to the Java(TM) 3D API specification by Sun Microsystems.
8
9    Permission to use, copy, modify, distribute and sell this software
10    and its documentation for any purpose is hereby granted without fee,
11    provided that the above copyright notice appear in all copies and
12    that both that copyright notice and this permission notice appear
13    in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc.
14    makes no representations about the suitability of this software for any
15    purpose.  It is provided "AS IS" with NO WARRANTY.
16 */
17 package javajs.util;
18
19 /**
20  * A single precision floating point 4 by 4 matrix.
21  * 
22  * @author Kenji hiranabe
23  * 
24  *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
25  *         constructor and method names for the optimization of compiled
26  *         JavaScript using Java2Script.
27  *
28  */
29 public class M4 extends M34 {
30
31   /**
32    * The fourth element of the first row.
33    */
34   public float m03;
35
36   /**
37    * The fourth element of the second row.
38    */
39   public float m13;
40
41   /**
42    * The fourth element of the third row.
43    */
44   public float m23;
45
46   /**
47    * The first element of the fourth row.
48    */
49   public float m30;
50
51   /**
52    * The second element of the fourth row.
53    */
54   public float m31;
55
56   /**
57    * The third element of the fourth row.
58    */
59   public float m32;
60
61   /**
62    * The fourth element of the fourth row.
63    */
64   public float m33 = 0;
65
66   public M4() {
67   }
68   /**
69    * Constructs and initializes a Matrix4f from the specified 16 element array.
70    * this.m00 =v[0], this.m01=v[1], etc.
71    * 
72    * @param v
73    *        the array of length 16 containing in order
74    * @return m
75    */
76   public static M4 newA16(float[] v) {
77     M4 m = new M4();
78     m.m00 = v[0];
79     m.m01 = v[1];
80     m.m02 = v[2];
81     m.m03 = v[3];
82
83     m.m10 = v[4];
84     m.m11 = v[5];
85     m.m12 = v[6];
86     m.m13 = v[7];
87
88     m.m20 = v[8];
89     m.m21 = v[9];
90     m.m22 = v[10];
91     m.m23 = v[11];
92
93     m.m30 = v[12];
94     m.m31 = v[13];
95     m.m32 = v[14];
96     m.m33 = v[15];
97
98     return m;
99   }
100
101   /**
102    * Constructs a new matrix with the same values as the Matrix4f parameter.
103    * 
104    * @param m1
105    *        the source matrix
106    * @return m
107    */
108   public static M4 newM4(M4 m1) {
109     M4 m = new M4();
110     if (m1 == null) {
111       m.setIdentity();
112       return m;
113     }
114     m.setToM3(m1);
115     m.m03 = m1.m03;
116     m.m13 = m1.m13;
117     m.m23 = m1.m23;
118     m.m30 = m1.m30;
119     m.m31 = m1.m31;
120     m.m32 = m1.m32;
121     m.m33 = m1.m33;
122     return m;
123   }
124
125   /**
126    * Constructs and initializes a Matrix4f from the rotation matrix and
127    * translation.
128    * 
129    * @param m1
130    *        The rotation matrix representing the rotational components
131    * @param t
132    *        The translational components of the matrix
133    * @return m
134    */
135   public static M4 newMV(M3 m1, T3 t) {
136     M4 m = new M4();
137     m.setMV(m1, t);
138     return m;
139   }
140
141   /**
142    * Sets this matrix to all zeros.
143    */
144   public void setZero() {
145     clear33();
146     m03 = m13 = m23 = m30 = m31 = m32 = m33 = 0.0f;
147   }
148
149   /**
150    * Sets this Matrix4f to identity.
151    */
152   public void setIdentity() {
153     setZero();
154     m00 = m11 = m22 = m33 = 1.0f;
155   }
156
157   /**
158    * Sets the value of this matrix to a copy of the passed matrix m1.
159    * 
160    * @param m1
161    *        the matrix to be copied
162    * @return this
163    */
164   public M4 setM4(M4 m1) {
165     setM33(m1);
166     m03 = m1.m03;
167     m13 = m1.m13;
168     m23 = m1.m23;
169     m30 = m1.m30;
170     m31 = m1.m31;
171     m32 = m1.m32;
172     m33 = m1.m33;
173     return this;
174   }
175
176   /**
177    * Initializes a Matrix4f from the rotation matrix and translation.
178    * 
179    * @param m1
180    *        The rotation matrix representing the rotational components
181    * @param t
182    *        The translational components of the matrix
183    */
184   public void setMV(M3 m1, T3 t) {
185     setM33(m1);
186     setTranslation(t);
187     m33 = 1;
188   }
189
190   /**
191    * Sets the rotational component (upper 3x3) of this matrix to the matrix
192    * values in the single precision Matrix3f argument; the other elements of
193    * this matrix are initialized as if this were an identity matrix (ie, affine
194    * matrix with no translational component).
195    * 
196    * @param m1
197    *        the 3x3 matrix
198    */
199   public void setToM3(M34 m1) {
200     setM33(m1);
201     m03 = m13 = m23 = m30 = m31 = m32 = 0.0f;
202     m33 = 1.0f;
203   }
204
205   /**
206    * Sets the rotational component (upper 3x3) of this matrix 
207    * to a rotation given by an axis angle
208    * 
209    * @param a
210    *        the axis and angle to be converted
211    */
212   public void setToAA(A4 a) {
213     setIdentity();
214     setAA33(a);
215   }
216
217   /**
218    * Sets the values in this Matrix4f equal to the row-major array parameter
219    * (ie, the first four elements of the array will be copied into the first row
220    * of this matrix, etc.).
221    * 
222    * @param m
223    */
224   public void setA(float m[]) {
225     m00 = m[0];
226     m01 = m[1];
227     m02 = m[2];
228     m03 = m[3];
229     m10 = m[4];
230     m11 = m[5];
231     m12 = m[6];
232     m13 = m[7];
233     m20 = m[8];
234     m21 = m[9];
235     m22 = m[10];
236     m23 = m[11];
237     m30 = m[12];
238     m31 = m[13];
239     m32 = m[14];
240     m33 = m[15];
241   }
242
243   /**
244    * Modifies the translational components of this matrix to the values of the
245    * Vector3f argument; the other values of this matrix are not modified.
246    * 
247    * @param trans
248    *        the translational component
249    */
250   public void setTranslation(T3 trans) {
251     m03 = trans.x;
252     m13 = trans.y;
253     m23 = trans.z;
254   }
255
256   /**
257    * Sets the specified element of this matrix4f to the value provided.
258    * 
259    * @param row
260    *        the row number to be modified (zero indexed)
261    * @param col
262    *        the column number to be modified (zero indexed)
263    * @param v
264    *        the new value
265    */
266   public void setElement(int row, int col, float v) {
267     if (row < 3 && col < 3) {
268       set33(row, col, v);
269       return;
270     }
271     if (row > 3 || col > 3)
272       err();
273     switch (row) {
274     case 0:
275       m03 = v;
276       return;
277     case 1:
278       m13 = v;
279       return;
280     case 2:
281       m23 = v;
282       return;
283     }
284     switch (col) {
285     case 0:
286       m30 = v;
287       return;
288     case 1:
289       m31 = v;
290       return;
291     case 2:
292       m32 = v;
293       return;
294     case 3:
295       m33 = v;
296       return;
297     }
298   }
299
300   /**
301    * Retrieves the value at the specified row and column of this matrix.
302    * 
303    * @param row
304    *        the row number to be retrieved (zero indexed)
305    * @param col
306    *        the column number to be retrieved (zero indexed)
307    * @return the value at the indexed element
308    */
309   public float getElement(int row, int col) {
310     if (row < 3 && col < 3)
311       return get33(row, col);
312     if (row > 3 || col > 3) {
313       err();
314       return 0;
315     }
316     switch (row) {
317     case 0:
318       return m03;
319     case 1:
320       return m13;
321     case 2:
322       return m23;
323     default:
324       switch (col) {
325       case 0:
326         return m30;
327       case 1:
328         return m31;
329       case 2:
330         return m32;
331       default:
332         return m33;
333       }
334     }
335   }
336
337   /**
338    * Retrieves the translational components of this matrix.
339    * 
340    * @param trans
341    *        the vector that will receive the translational component
342    */
343   public void getTranslation(T3 trans) {
344     trans.x = m03;
345     trans.y = m13;
346     trans.z = m23;
347   }
348
349   /**
350    * Gets the upper 3x3 values of this matrix and places them into the matrix
351    * m1.
352    * 
353    * @param m1
354    *        The matrix that will hold the values
355    */
356   public void getRotationScale(M3 m1) {
357     m1.m00 = m00;
358     m1.m01 = m01;
359     m1.m02 = m02;
360     m1.m10 = m10;
361     m1.m11 = m11;
362     m1.m12 = m12;
363     m1.m20 = m20;
364     m1.m21 = m21;
365     m1.m22 = m22;
366   }
367
368   /**
369    * Replaces the upper 3x3 matrix values of this matrix with the values in the
370    * matrix m1.
371    * 
372    * @param m1
373    *        The matrix that will be the new upper 3x3
374    */
375   public void setRotationScale(M3 m1) {
376     m00 = m1.m00;
377     m01 = m1.m01;
378     m02 = m1.m02;
379     m10 = m1.m10;
380     m11 = m1.m11;
381     m12 = m1.m12;
382     m20 = m1.m20;
383     m21 = m1.m21;
384     m22 = m1.m22;
385   }
386
387   /**
388    * Sets the specified row of this matrix4f to the four values provided.
389    * 
390    * @param row
391    *        the row number to be modified (zero indexed)
392    * @param v
393    *        the replacement row
394    */
395   public void setRowA(int row, float v[]) {
396     if (row < 3)
397       setRow33(row, v);
398     switch (row) {
399     case 0:
400       m03 = v[3];
401       return;
402     case 1:
403       m13 = v[3];
404       return;
405     case 2:
406       m23 = v[3];
407       return;
408     case 3:
409       m30 = v[0];
410       m31 = v[1];
411       m32 = v[2];
412       m33 = v[3];
413       return;
414     }
415     err();
416   }
417
418   /**
419    * Copies the matrix values in the specified row into the array parameter.
420    * 
421    * @param row
422    *        the matrix row
423    * @param v
424    *        The array into which the matrix row values will be copied
425    */
426   @Override
427   public void getRow(int row, float v[]) {
428     if (row < 3)
429       getRow33(row, v);
430     switch (row) {
431     case 0:
432       v[3] = m03;
433       return;
434     case 1:
435       v[3] = m13;
436       return;
437     case 2:
438       v[3] = m23;
439       return;
440     case 3:
441       v[0] = m30;
442       v[1] = m31;
443       v[2] = m32;
444       v[3] = m33;
445       return;
446     }
447     err();
448   }
449
450   /**
451    * Sets the specified column of this matrix4f to the four values provided.
452    * 
453    * @param column
454    *        the column number to be modified (zero indexed)
455    * @param x
456    *        the first row element
457    * @param y
458    *        the second row element
459    * @param z
460    *        the third row element
461    * @param w
462    *        the fourth row element
463    */
464   public void setColumn4(int column, float x, float y, float z, float w) {
465     if (column == 0) {
466       m00 = x;
467       m10 = y;
468       m20 = z;
469       m30 = w;
470     } else if (column == 1) {
471       m01 = x;
472       m11 = y;
473       m21 = z;
474       m31 = w;
475     } else if (column == 2) {
476       m02 = x;
477       m12 = y;
478       m22 = z;
479       m32 = w;
480     } else if (column == 3) {
481       m03 = x;
482       m13 = y;
483       m23 = z;
484       m33 = w;
485     } else {
486       err();
487     }
488   }
489
490   /**
491    * Sets the specified column of this matrix4f to the four values provided.
492    * 
493    * @param column
494    *        the column number to be modified (zero indexed)
495    * @param v
496    *        the replacement column
497    */
498   public void setColumnA(int column, float v[]) {
499     if (column < 3)
500       setColumn33(column, v);
501     switch (column) {
502     case 0:
503       m30 = v[3];
504       return;
505     case 1:
506       m31 = v[3];
507       return;
508     case 2:
509       m32 = v[3];
510       return;
511     case 3:
512       m03 = v[0];
513       m13 = v[1];
514       m23 = v[2];
515       m33 = v[3];
516       return;
517     default:
518       err();
519     }
520   }
521
522   /**
523    * Copies the matrix values in the specified column into the array parameter.
524    * 
525    * @param column
526    *        the matrix column
527    * @param v
528    *        The array into which the matrix column values will be copied
529    */
530   public void getColumn(int column, float v[]) {
531     if (column < 3)
532       getColumn33(column, v);
533     switch (column) {
534     case 0:
535       v[3] = m30;
536       return;
537     case 1:
538       v[3] = m31;
539       return;
540     case 2:
541       v[3] = m32;
542       return;
543     case 3:
544       v[0] = m03;
545       v[1] = m13;
546       v[2] = m23;
547       v[3] = m33;
548       return;
549     default:
550       err();
551     }
552   }
553
554   /**
555    * Sets the value of this matrix to the matrix difference of itself and matrix
556    * m1 (this = this - m1).
557    * 
558    * @param m1
559    *        the other matrix
560    */
561   public void sub(M4 m1) {
562     sub33(m1);
563     m03 -= m1.m03;
564     m13 -= m1.m13;
565     m23 -= m1.m23;
566     m30 -= m1.m30;
567     m31 -= m1.m31;
568     m32 -= m1.m32;
569     m33 -= m1.m33;
570   }
571
572   /**
573    * Sets the value of this matrix to its transpose.
574    */
575   public void transpose() {
576     transpose33();
577     float tmp = m03;
578     m03 = m30;
579     m30 = tmp;
580
581     tmp = m13;
582     m13 = m31;
583     m31 = tmp;
584
585     tmp = m23;
586     m23 = m32;
587     m32 = tmp;
588   }
589
590   /**
591    * Sets the value of this matrix to its inverse.
592    * @return this
593    */
594   public M4 invert() {
595     float s = determinant4();
596     if (s == 0.0)
597       return this;
598     s = 1 / s;
599     // alias-safe way.
600     // less *,+,- calculation than expanded expression.
601     set(m11 * (m22 * m33 - m23 * m32) + m12 * (m23 * m31 - m21 * m33) + m13
602         * (m21 * m32 - m22 * m31), m21 * (m02 * m33 - m03 * m32) + m22
603         * (m03 * m31 - m01 * m33) + m23 * (m01 * m32 - m02 * m31), m31
604         * (m02 * m13 - m03 * m12) + m32 * (m03 * m11 - m01 * m13) + m33
605         * (m01 * m12 - m02 * m11), m01 * (m13 * m22 - m12 * m23) + m02
606         * (m11 * m23 - m13 * m21) + m03 * (m12 * m21 - m11 * m22),
607
608     m12 * (m20 * m33 - m23 * m30) + m13 * (m22 * m30 - m20 * m32) + m10
609         * (m23 * m32 - m22 * m33), m22 * (m00 * m33 - m03 * m30) + m23
610         * (m02 * m30 - m00 * m32) + m20 * (m03 * m32 - m02 * m33), m32
611         * (m00 * m13 - m03 * m10) + m33 * (m02 * m10 - m00 * m12) + m30
612         * (m03 * m12 - m02 * m13), m02 * (m13 * m20 - m10 * m23) + m03
613         * (m10 * m22 - m12 * m20) + m00 * (m12 * m23 - m13 * m22),
614
615     m13 * (m20 * m31 - m21 * m30) + m10 * (m21 * m33 - m23 * m31) + m11
616         * (m23 * m30 - m20 * m33), m23 * (m00 * m31 - m01 * m30) + m20
617         * (m01 * m33 - m03 * m31) + m21 * (m03 * m30 - m00 * m33), m33
618         * (m00 * m11 - m01 * m10) + m30 * (m01 * m13 - m03 * m11) + m31
619         * (m03 * m10 - m00 * m13), m03 * (m11 * m20 - m10 * m21) + m00
620         * (m13 * m21 - m11 * m23) + m01 * (m10 * m23 - m13 * m20),
621
622     m10 * (m22 * m31 - m21 * m32) + m11 * (m20 * m32 - m22 * m30) + m12
623         * (m21 * m30 - m20 * m31), m20 * (m02 * m31 - m01 * m32) + m21
624         * (m00 * m32 - m02 * m30) + m22 * (m01 * m30 - m00 * m31), m30
625         * (m02 * m11 - m01 * m12) + m31 * (m00 * m12 - m02 * m10) + m32
626         * (m01 * m10 - m00 * m11), m00 * (m11 * m22 - m12 * m21) + m01
627         * (m12 * m20 - m10 * m22) + m02 * (m10 * m21 - m11 * m20));
628     scale(s);
629     return this;
630   }
631
632   /**
633    * Sets 16 values
634    * 
635    * @param m00
636    * @param m01
637    * @param m02
638    * @param m03
639    * @param m10
640    * @param m11
641    * @param m12
642    * @param m13
643    * @param m20
644    * @param m21
645    * @param m22
646    * @param m23
647    * @param m30
648    * @param m31
649    * @param m32
650    * @param m33
651    */
652   private void set(float m00, float m01, float m02, float m03, float m10,
653                    float m11, float m12, float m13, float m20, float m21,
654                    float m22, float m23, float m30, float m31, float m32,
655                    float m33) {
656     this.m00 = m00;
657     this.m01 = m01;
658     this.m02 = m02;
659     this.m03 = m03;
660     this.m10 = m10;
661     this.m11 = m11;
662     this.m12 = m12;
663     this.m13 = m13;
664     this.m20 = m20;
665     this.m21 = m21;
666     this.m22 = m22;
667     this.m23 = m23;
668     this.m30 = m30;
669     this.m31 = m31;
670     this.m32 = m32;
671     this.m33 = m33;
672   }
673   /**
674    * Computes the determinant of this matrix.
675    * 
676    * @return the determinant of the matrix
677    */
678   public float determinant4() {
679     // less *,+,- calculation than expanded expression.
680     return (m00 * m11 - m01 * m10) * (m22 * m33 - m23 * m32)
681         - (m00 * m12 - m02 * m10) * (m21 * m33 - m23 * m31)
682         + (m00 * m13 - m03 * m10) * (m21 * m32 - m22 * m31)
683         + (m01 * m12 - m02 * m11) * (m20 * m33 - m23 * m30)
684         - (m01 * m13 - m03 * m11) * (m20 * m32 - m22 * m30)
685         + (m02 * m13 - m03 * m12) * (m20 * m31 - m21 * m30);
686
687   }
688
689   /**
690    * Multiplies each element of this matrix by a scalar.
691    * 
692    * @param scalar
693    *        The scalar multiplier.
694    */
695   public void scale(float scalar) {
696     mul33(scalar);
697     m03 *= scalar;
698     m13 *= scalar;
699     m23 *= scalar;
700     m30 *= scalar;
701     m31 *= scalar;
702     m32 *= scalar;
703     m33 *= scalar;
704   }
705
706   /**
707    * Sets the value of this matrix to the result of multiplying itself with
708    * matrix m1.
709    * 
710    * @param m1
711    *        the other matrix
712    */
713   public void mul(M4 m1) {
714     mul2(this, m1);
715   }
716
717   /**
718    * Sets the value of this matrix to the result of multiplying the two argument
719    * matrices together.
720    * 
721    * @param m1
722    *        the first matrix
723    * @param m2
724    *        the second matrix
725    */
726   public void mul2(M4 m1, M4 m2) {
727     // alias-safe way.
728     set(m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30,
729         m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31,
730         m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32,
731         m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33,
732
733         m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30,
734         m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31,
735         m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32,
736         m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33,
737
738         m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30,
739         m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31,
740         m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32,
741         m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33,
742
743         m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30,
744         m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31,
745         m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32,
746         m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33);
747   }
748
749   /**
750    * Transform the vector vec using this Matrix4f and place the result back into
751    * vec.
752    * 
753    * @param vec
754    *        the single precision vector to be transformed
755    */
756   public void transform(T4 vec) {
757     transform2(vec, vec);
758   }
759
760   /**
761    * Transform the vector vec using this Matrix4f and place the result into
762    * vecOut.
763    * 
764    * @param vec
765    *        the single precision vector to be transformed
766    * @param vecOut
767    *        the vector into which the transformed values are placed
768    */
769   public void transform2(T4 vec, T4 vecOut) {
770     // alias-safe
771     vecOut.set4(m00 * vec.x + m01 * vec.y + m02 * vec.z + m03 * vec.w, m10
772         * vec.x + m11 * vec.y + m12 * vec.z + m13 * vec.w, m20 * vec.x + m21
773         * vec.y + m22 * vec.z + m23 * vec.w, m30 * vec.x + m31 * vec.y + m32
774         * vec.z + m33 * vec.w);
775   }
776
777   /**
778    * Transforms the point parameter with this Matrix4f and places the result
779    * back into point. The fourth element of the point input parameter is assumed
780    * to be one.
781    * 
782    * @param point
783    *        the input point to be transformed.
784    */
785   public void rotTrans(T3 point) {
786     rotTrans2(point, point);
787   }
788
789   /**
790    * Transforms the point parameter with this Matrix4f and places the result
791    * into pointOut. The fourth element of the point input parameter is assumed to
792    * be one. point may be pointOut
793    * 
794    * @param point
795    *        the input point to be transformed.
796    * @param pointOut
797    *        the transformed point
798    * @return pointOut
799    */
800   public T3 rotTrans2(T3 point, T3 pointOut) {
801       pointOut.set(
802           m00 * point.x + m01 * point.y + m02 * point.z + m03, 
803           m10 * point.x + m11 * point.y + m12 * point.z + m13, 
804           m20 * point.x + m21 * point.y + m22 * point.z + m23);
805       return pointOut;
806   }
807
808   /**
809    * Sets the value of this matrix to a rotation matrix about the w axis by the
810    * passed angle.
811    * 
812    * @param angle
813    *        the angle to rotate about the W axis in radians
814    * @return this
815    */
816   public M4 setAsXYRotation(float angle) {
817     setIdentity();
818     double c = Math.cos(angle);
819     double s = Math.sin(angle);
820     m22 = (float) c;
821     m23 = (float) -s;
822     m32 = (float) s;
823     m33 = (float) c;
824     return this;
825   }
826
827   /**
828    * Sets the value of this matrix to a rotation matrix about the w axis by the
829    * passed angle.
830    * 
831    * @param angle
832    *        the angle to rotate about the W axis in radians
833    * @return this
834    */
835   public M4 setAsYZRotation(float angle) {
836     setIdentity();
837     double c = Math.cos(angle);
838     double s = Math.sin(angle);
839     m00 = (float) c;
840     m03 = (float) -s;
841     m30 = (float) s;
842     m33 = (float) c;
843     return this;
844   }
845
846   /**
847    * Sets the value of this matrix to a rotation matrix about the w axis by the
848    * passed angle.
849    * 
850    * @param angle
851    *        the angle to rotate about the W axis in radians
852    * @return this
853    */
854   public M4 setAsXZRotation(float angle) {
855     setIdentity();
856     double c = Math.cos(angle);
857     double s = Math.sin(angle);
858     m11 = (float) c;
859     m13 = (float) -s;
860     m31 = (float) s;
861     m33 = (float) c;
862     return this;
863   }
864
865   /**
866    * Returns true if the Object o is of type Matrix4f and all of the data
867    * members of t1 are equal to the corresponding data members in this Matrix4f.
868    * 
869    * @param o
870    *        the object with which the comparison is made.
871    */
872   @Override
873   public boolean equals(Object o) {
874     if (!(o instanceof M4))
875       return false;
876     M4 m = (M4) o;
877     return (this.m00 == m.m00 && this.m01 == m.m01 && this.m02 == m.m02
878         && this.m03 == m.m03 && this.m10 == m.m10 && this.m11 == m.m11
879         && this.m12 == m.m12 && this.m13 == m.m13 && this.m20 == m.m20
880         && this.m21 == m.m21 && this.m22 == m.m22 && this.m23 == m.m23
881         && this.m30 == m.m30 && this.m31 == m.m31 && this.m32 == m.m32 && this.m33 == m.m33);
882   }
883
884   /**
885    * Returns a hash number based on the data values in this object. Two
886    * different Matrix4f objects with identical data values (ie, returns true for
887    * equals(Matrix4f) ) will return the same hash number. Two objects with
888    * different data members may return the same hash value, although this is not
889    * likely.
890    * 
891    * @return the integer hash value
892    */
893   @Override
894   public int hashCode() {
895     return T3.floatToIntBits(m00) ^ T3.floatToIntBits(m01)
896         ^ T3.floatToIntBits(m02) ^ T3.floatToIntBits(m03)
897         ^ T3.floatToIntBits(m10) ^ T3.floatToIntBits(m11)
898         ^ T3.floatToIntBits(m12) ^ T3.floatToIntBits(m13)
899         ^ T3.floatToIntBits(m20) ^ T3.floatToIntBits(m21)
900         ^ T3.floatToIntBits(m22) ^ T3.floatToIntBits(m23)
901         ^ T3.floatToIntBits(m30) ^ T3.floatToIntBits(m31)
902         ^ T3.floatToIntBits(m32) ^ T3.floatToIntBits(m33);
903   }
904
905   /**
906    * Returns a string that contains the values of this Matrix4f.
907    * 
908    * @return the String representation
909    */
910   @Override
911   public String toString() {
912     return "[\n  [" + m00 + "\t" + m01 + "\t" + m02 + "\t" + m03 + "]"
913         + "\n  [" + m10 + "\t" + m11 + "\t" + m12 + "\t" + m13 + "]" + "\n  ["
914         + m20 + "\t" + m21 + "\t" + m22 + "\t" + m23 + "]" + "\n  [" + m30
915         + "\t" + m31 + "\t" + m32 + "\t" + m33 + "] ]";
916   }
917   public M4 round(float f) {
918     m00 = rnd(m00, f);
919     m01 = rnd(m01, f);
920     m02 = rnd(m02, f);
921     m03 = rnd(m03, f);
922     m10 = rnd(m10, f);
923     m11 = rnd(m11, f);
924     m12 = rnd(m12, f);
925     m13 = rnd(m13, f);
926     m20 = rnd(m20, f);
927     m21 = rnd(m21, f);
928     m22 = rnd(m22, f);
929     m23 = rnd(m23, f);
930     m30 = rnd(m30, f);
931     m31 = rnd(m31, f);
932     m32 = rnd(m32, f);
933     m33 = rnd(m33, f);
934     return this;
935   }
936
937   private float rnd(float n, float f) {
938     return (Math.abs(n) < f ? 0 : n);
939   }
940 }