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