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