• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package com.jme3.math;
33 
34 import com.jme3.export.*;
35 import com.jme3.util.BufferUtils;
36 import com.jme3.util.TempVars;
37 import java.io.IOException;
38 import java.nio.FloatBuffer;
39 import java.util.logging.Logger;
40 
41 /**
42  * <code>Matrix4f</code> defines and maintains a 4x4 matrix in row major order.
43  * This matrix is intended for use in a translation and rotational capacity.
44  * It provides convenience methods for creating the matrix from a multitude
45  * of sources.
46  *
47  * Matrices are stored assuming column vectors on the right, with the translation
48  * in the rightmost column. Element numbering is row,column, so m03 is the zeroth
49  * row, third column, which is the "x" translation part. This means that the implicit
50  * storage order is column major. However, the get() and set() functions on float
51  * arrays default to row major order!
52  *
53  * @author Mark Powell
54  * @author Joshua Slack
55  */
56 public final class Matrix4f implements Savable, Cloneable, java.io.Serializable {
57 
58     static final long serialVersionUID = 1;
59 
60     private static final Logger logger = Logger.getLogger(Matrix4f.class.getName());
61     public float m00, m01, m02, m03;
62     public float m10, m11, m12, m13;
63     public float m20, m21, m22, m23;
64     public float m30, m31, m32, m33;
65     public static final Matrix4f ZERO = new Matrix4f(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
66     public static final Matrix4f IDENTITY = new Matrix4f();
67 
68     /**
69      * Constructor instantiates a new <code>Matrix</code> that is set to the
70      * identity matrix.
71      *
72      */
Matrix4f()73     public Matrix4f() {
74         loadIdentity();
75     }
76 
77     /**
78      * constructs a matrix with the given values.
79      */
Matrix4f(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33)80     public Matrix4f(float m00, float m01, float m02, float m03,
81             float m10, float m11, float m12, float m13,
82             float m20, float m21, float m22, float m23,
83             float m30, float m31, float m32, float m33) {
84 
85         this.m00 = m00;
86         this.m01 = m01;
87         this.m02 = m02;
88         this.m03 = m03;
89         this.m10 = m10;
90         this.m11 = m11;
91         this.m12 = m12;
92         this.m13 = m13;
93         this.m20 = m20;
94         this.m21 = m21;
95         this.m22 = m22;
96         this.m23 = m23;
97         this.m30 = m30;
98         this.m31 = m31;
99         this.m32 = m32;
100         this.m33 = m33;
101     }
102 
103     /**
104      * Create a new Matrix4f, given data in column-major format.
105      *
106      * @param array
107      *		An array of 16 floats in column-major format (translation in elements 12, 13 and 14).
108      */
Matrix4f(float[] array)109     public Matrix4f(float[] array) {
110         set(array, false);
111     }
112 
113     /**
114      * Constructor instantiates a new <code>Matrix</code> that is set to the
115      * provided matrix. This constructor copies a given Matrix. If the provided
116      * matrix is null, the constructor sets the matrix to the identity.
117      *
118      * @param mat
119      *            the matrix to copy.
120      */
Matrix4f(Matrix4f mat)121     public Matrix4f(Matrix4f mat) {
122         copy(mat);
123     }
124 
125     /**
126      * <code>copy</code> transfers the contents of a given matrix to this
127      * matrix. If a null matrix is supplied, this matrix is set to the identity
128      * matrix.
129      *
130      * @param matrix
131      *            the matrix to copy.
132      */
copy(Matrix4f matrix)133     public void copy(Matrix4f matrix) {
134         if (null == matrix) {
135             loadIdentity();
136         } else {
137             m00 = matrix.m00;
138             m01 = matrix.m01;
139             m02 = matrix.m02;
140             m03 = matrix.m03;
141             m10 = matrix.m10;
142             m11 = matrix.m11;
143             m12 = matrix.m12;
144             m13 = matrix.m13;
145             m20 = matrix.m20;
146             m21 = matrix.m21;
147             m22 = matrix.m22;
148             m23 = matrix.m23;
149             m30 = matrix.m30;
150             m31 = matrix.m31;
151             m32 = matrix.m32;
152             m33 = matrix.m33;
153         }
154     }
155 
fromFrame(Vector3f location, Vector3f direction, Vector3f up, Vector3f left)156     public void fromFrame(Vector3f location, Vector3f direction, Vector3f up, Vector3f left) {
157         loadIdentity();
158 
159         TempVars vars = TempVars.get();
160 
161         Vector3f f = vars.vect1.set(direction);
162         Vector3f s = vars.vect2.set(f).crossLocal(up);
163         Vector3f u = vars.vect3.set(s).crossLocal(f);
164 //        s.normalizeLocal();
165 //        u.normalizeLocal();
166 
167         m00 = s.x;
168         m01 = s.y;
169         m02 = s.z;
170 
171         m10 = u.x;
172         m11 = u.y;
173         m12 = u.z;
174 
175         m20 = -f.x;
176         m21 = -f.y;
177         m22 = -f.z;
178 
179 //        m00 = -left.x;
180 //        m10 = -left.y;
181 //        m20 = -left.z;
182 //
183 //        m01 = up.x;
184 //        m11 = up.y;
185 //        m21 = up.z;
186 //
187 //        m02 = -direction.x;
188 //        m12 = -direction.y;
189 //        m22 = -direction.z;
190 //
191 
192         Matrix4f transMatrix = vars.tempMat4;
193         transMatrix.loadIdentity();
194         transMatrix.m03 = -location.x;
195         transMatrix.m13 = -location.y;
196         transMatrix.m23 = -location.z;
197         this.multLocal(transMatrix);
198 
199         vars.release();
200 
201 //        transMatrix.multLocal(this);
202 
203 //        set(transMatrix);
204     }
205 
206     /**
207      * <code>get</code> retrieves the values of this object into
208      * a float array in row-major order.
209      *
210      * @param matrix
211      *            the matrix to set the values into.
212      */
get(float[] matrix)213     public void get(float[] matrix) {
214         get(matrix, true);
215     }
216 
217     /**
218      * <code>set</code> retrieves the values of this object into
219      * a float array.
220      *
221      * @param matrix
222      *            the matrix to set the values into.
223      * @param rowMajor
224      *            whether the outgoing data is in row or column major order.
225      */
get(float[] matrix, boolean rowMajor)226     public void get(float[] matrix, boolean rowMajor) {
227         if (matrix.length != 16) {
228             throw new IllegalArgumentException(
229                     "Array must be of size 16.");
230         }
231 
232         if (rowMajor) {
233             matrix[0] = m00;
234             matrix[1] = m01;
235             matrix[2] = m02;
236             matrix[3] = m03;
237             matrix[4] = m10;
238             matrix[5] = m11;
239             matrix[6] = m12;
240             matrix[7] = m13;
241             matrix[8] = m20;
242             matrix[9] = m21;
243             matrix[10] = m22;
244             matrix[11] = m23;
245             matrix[12] = m30;
246             matrix[13] = m31;
247             matrix[14] = m32;
248             matrix[15] = m33;
249         } else {
250             matrix[0] = m00;
251             matrix[4] = m01;
252             matrix[8] = m02;
253             matrix[12] = m03;
254             matrix[1] = m10;
255             matrix[5] = m11;
256             matrix[9] = m12;
257             matrix[13] = m13;
258             matrix[2] = m20;
259             matrix[6] = m21;
260             matrix[10] = m22;
261             matrix[14] = m23;
262             matrix[3] = m30;
263             matrix[7] = m31;
264             matrix[11] = m32;
265             matrix[15] = m33;
266         }
267     }
268 
269     /**
270      * <code>get</code> retrieves a value from the matrix at the given
271      * position. If the position is invalid a <code>JmeException</code> is
272      * thrown.
273      *
274      * @param i
275      *            the row index.
276      * @param j
277      *            the colum index.
278      * @return the value at (i, j).
279      */
280     @SuppressWarnings("fallthrough")
get(int i, int j)281     public float get(int i, int j) {
282         switch (i) {
283             case 0:
284                 switch (j) {
285                     case 0:
286                         return m00;
287                     case 1:
288                         return m01;
289                     case 2:
290                         return m02;
291                     case 3:
292                         return m03;
293                 }
294             case 1:
295                 switch (j) {
296                     case 0:
297                         return m10;
298                     case 1:
299                         return m11;
300                     case 2:
301                         return m12;
302                     case 3:
303                         return m13;
304                 }
305             case 2:
306                 switch (j) {
307                     case 0:
308                         return m20;
309                     case 1:
310                         return m21;
311                     case 2:
312                         return m22;
313                     case 3:
314                         return m23;
315                 }
316             case 3:
317                 switch (j) {
318                     case 0:
319                         return m30;
320                     case 1:
321                         return m31;
322                     case 2:
323                         return m32;
324                     case 3:
325                         return m33;
326                 }
327         }
328 
329         logger.warning("Invalid matrix index.");
330         throw new IllegalArgumentException("Invalid indices into matrix.");
331     }
332 
333     /**
334      * <code>getColumn</code> returns one of three columns specified by the
335      * parameter. This column is returned as a float array of length 4.
336      *
337      * @param i
338      *            the column to retrieve. Must be between 0 and 3.
339      * @return the column specified by the index.
340      */
getColumn(int i)341     public float[] getColumn(int i) {
342         return getColumn(i, null);
343     }
344 
345     /**
346      * <code>getColumn</code> returns one of three columns specified by the
347      * parameter. This column is returned as a float[4].
348      *
349      * @param i
350      *            the column to retrieve. Must be between 0 and 3.
351      * @param store
352      *            the float array to store the result in. if null, a new one
353      *            is created.
354      * @return the column specified by the index.
355      */
getColumn(int i, float[] store)356     public float[] getColumn(int i, float[] store) {
357         if (store == null) {
358             store = new float[4];
359         }
360         switch (i) {
361             case 0:
362                 store[0] = m00;
363                 store[1] = m10;
364                 store[2] = m20;
365                 store[3] = m30;
366                 break;
367             case 1:
368                 store[0] = m01;
369                 store[1] = m11;
370                 store[2] = m21;
371                 store[3] = m31;
372                 break;
373             case 2:
374                 store[0] = m02;
375                 store[1] = m12;
376                 store[2] = m22;
377                 store[3] = m32;
378                 break;
379             case 3:
380                 store[0] = m03;
381                 store[1] = m13;
382                 store[2] = m23;
383                 store[3] = m33;
384                 break;
385             default:
386                 logger.warning("Invalid column index.");
387                 throw new IllegalArgumentException("Invalid column index. " + i);
388         }
389         return store;
390     }
391 
392     /**
393      *
394      * <code>setColumn</code> sets a particular column of this matrix to that
395      * represented by the provided vector.
396      *
397      * @param i
398      *            the column to set.
399      * @param column
400      *            the data to set.
401      */
setColumn(int i, float[] column)402     public void setColumn(int i, float[] column) {
403 
404         if (column == null) {
405             logger.warning("Column is null. Ignoring.");
406             return;
407         }
408         switch (i) {
409             case 0:
410                 m00 = column[0];
411                 m10 = column[1];
412                 m20 = column[2];
413                 m30 = column[3];
414                 break;
415             case 1:
416                 m01 = column[0];
417                 m11 = column[1];
418                 m21 = column[2];
419                 m31 = column[3];
420                 break;
421             case 2:
422                 m02 = column[0];
423                 m12 = column[1];
424                 m22 = column[2];
425                 m32 = column[3];
426                 break;
427             case 3:
428                 m03 = column[0];
429                 m13 = column[1];
430                 m23 = column[2];
431                 m33 = column[3];
432                 break;
433             default:
434                 logger.warning("Invalid column index.");
435                 throw new IllegalArgumentException("Invalid column index. " + i);
436         }
437     }
438 
439     /**
440      * <code>set</code> places a given value into the matrix at the given
441      * position. If the position is invalid a <code>JmeException</code> is
442      * thrown.
443      *
444      * @param i
445      *            the row index.
446      * @param j
447      *            the colum index.
448      * @param value
449      *            the value for (i, j).
450      */
451     @SuppressWarnings("fallthrough")
set(int i, int j, float value)452     public void set(int i, int j, float value) {
453         switch (i) {
454             case 0:
455                 switch (j) {
456                     case 0:
457                         m00 = value;
458                         return;
459                     case 1:
460                         m01 = value;
461                         return;
462                     case 2:
463                         m02 = value;
464                         return;
465                     case 3:
466                         m03 = value;
467                         return;
468                 }
469             case 1:
470                 switch (j) {
471                     case 0:
472                         m10 = value;
473                         return;
474                     case 1:
475                         m11 = value;
476                         return;
477                     case 2:
478                         m12 = value;
479                         return;
480                     case 3:
481                         m13 = value;
482                         return;
483                 }
484             case 2:
485                 switch (j) {
486                     case 0:
487                         m20 = value;
488                         return;
489                     case 1:
490                         m21 = value;
491                         return;
492                     case 2:
493                         m22 = value;
494                         return;
495                     case 3:
496                         m23 = value;
497                         return;
498                 }
499             case 3:
500                 switch (j) {
501                     case 0:
502                         m30 = value;
503                         return;
504                     case 1:
505                         m31 = value;
506                         return;
507                     case 2:
508                         m32 = value;
509                         return;
510                     case 3:
511                         m33 = value;
512                         return;
513                 }
514         }
515 
516         logger.warning("Invalid matrix index.");
517         throw new IllegalArgumentException("Invalid indices into matrix.");
518     }
519 
520     /**
521      * <code>set</code> sets the values of this matrix from an array of
522      * values.
523      *
524      * @param matrix
525      *            the matrix to set the value to.
526      * @throws JmeException
527      *             if the array is not of size 16.
528      */
set(float[][] matrix)529     public void set(float[][] matrix) {
530         if (matrix.length != 4 || matrix[0].length != 4) {
531             throw new IllegalArgumentException(
532                     "Array must be of size 16.");
533         }
534 
535         m00 = matrix[0][0];
536         m01 = matrix[0][1];
537         m02 = matrix[0][2];
538         m03 = matrix[0][3];
539         m10 = matrix[1][0];
540         m11 = matrix[1][1];
541         m12 = matrix[1][2];
542         m13 = matrix[1][3];
543         m20 = matrix[2][0];
544         m21 = matrix[2][1];
545         m22 = matrix[2][2];
546         m23 = matrix[2][3];
547         m30 = matrix[3][0];
548         m31 = matrix[3][1];
549         m32 = matrix[3][2];
550         m33 = matrix[3][3];
551     }
552 
553     /**
554      * <code>set</code> sets the values of this matrix from another matrix.
555      *
556      * @param matrix
557      *            the matrix to read the value from.
558      */
set(Matrix4f matrix)559     public Matrix4f set(Matrix4f matrix) {
560         m00 = matrix.m00;
561         m01 = matrix.m01;
562         m02 = matrix.m02;
563         m03 = matrix.m03;
564         m10 = matrix.m10;
565         m11 = matrix.m11;
566         m12 = matrix.m12;
567         m13 = matrix.m13;
568         m20 = matrix.m20;
569         m21 = matrix.m21;
570         m22 = matrix.m22;
571         m23 = matrix.m23;
572         m30 = matrix.m30;
573         m31 = matrix.m31;
574         m32 = matrix.m32;
575         m33 = matrix.m33;
576         return this;
577     }
578 
579     /**
580      * <code>set</code> sets the values of this matrix from an array of
581      * values assuming that the data is rowMajor order;
582      *
583      * @param matrix
584      *            the matrix to set the value to.
585      */
set(float[] matrix)586     public void set(float[] matrix) {
587         set(matrix, true);
588     }
589 
590     /**
591      * <code>set</code> sets the values of this matrix from an array of
592      * values;
593      *
594      * @param matrix
595      *            the matrix to set the value to.
596      * @param rowMajor
597      *            whether the incoming data is in row or column major order.
598      */
set(float[] matrix, boolean rowMajor)599     public void set(float[] matrix, boolean rowMajor) {
600         if (matrix.length != 16) {
601             throw new IllegalArgumentException(
602                     "Array must be of size 16.");
603         }
604 
605         if (rowMajor) {
606             m00 = matrix[0];
607             m01 = matrix[1];
608             m02 = matrix[2];
609             m03 = matrix[3];
610             m10 = matrix[4];
611             m11 = matrix[5];
612             m12 = matrix[6];
613             m13 = matrix[7];
614             m20 = matrix[8];
615             m21 = matrix[9];
616             m22 = matrix[10];
617             m23 = matrix[11];
618             m30 = matrix[12];
619             m31 = matrix[13];
620             m32 = matrix[14];
621             m33 = matrix[15];
622         } else {
623             m00 = matrix[0];
624             m01 = matrix[4];
625             m02 = matrix[8];
626             m03 = matrix[12];
627             m10 = matrix[1];
628             m11 = matrix[5];
629             m12 = matrix[9];
630             m13 = matrix[13];
631             m20 = matrix[2];
632             m21 = matrix[6];
633             m22 = matrix[10];
634             m23 = matrix[14];
635             m30 = matrix[3];
636             m31 = matrix[7];
637             m32 = matrix[11];
638             m33 = matrix[15];
639         }
640     }
641 
transpose()642     public Matrix4f transpose() {
643         float[] tmp = new float[16];
644         get(tmp, true);
645         Matrix4f mat = new Matrix4f(tmp);
646         return mat;
647     }
648 
649     /**
650      * <code>transpose</code> locally transposes this Matrix.
651      *
652      * @return this object for chaining.
653      */
transposeLocal()654     public Matrix4f transposeLocal() {
655         float tmp = m01;
656         m01 = m10;
657         m10 = tmp;
658 
659         tmp = m02;
660         m02 = m20;
661         m20 = tmp;
662 
663         tmp = m03;
664         m03 = m30;
665         m30 = tmp;
666 
667         tmp = m12;
668         m12 = m21;
669         m21 = tmp;
670 
671         tmp = m13;
672         m13 = m31;
673         m31 = tmp;
674 
675         tmp = m23;
676         m23 = m32;
677         m32 = tmp;
678 
679         return this;
680     }
681 
682     /**
683      * <code>toFloatBuffer</code> returns a FloatBuffer object that contains
684      * the matrix data.
685      *
686      * @return matrix data as a FloatBuffer.
687      */
toFloatBuffer()688     public FloatBuffer toFloatBuffer() {
689         return toFloatBuffer(false);
690     }
691 
692     /**
693      * <code>toFloatBuffer</code> returns a FloatBuffer object that contains the
694      * matrix data.
695      *
696      * @param columnMajor
697      *            if true, this buffer should be filled with column major data,
698      *            otherwise it will be filled row major.
699      * @return matrix data as a FloatBuffer. The position is set to 0 for
700      *         convenience.
701      */
toFloatBuffer(boolean columnMajor)702     public FloatBuffer toFloatBuffer(boolean columnMajor) {
703         FloatBuffer fb = BufferUtils.createFloatBuffer(16);
704         fillFloatBuffer(fb, columnMajor);
705         fb.rewind();
706         return fb;
707     }
708 
709     /**
710      * <code>fillFloatBuffer</code> fills a FloatBuffer object with
711      * the matrix data.
712      * @param fb the buffer to fill, must be correct size
713      * @return matrix data as a FloatBuffer.
714      */
fillFloatBuffer(FloatBuffer fb)715     public FloatBuffer fillFloatBuffer(FloatBuffer fb) {
716         return fillFloatBuffer(fb, false);
717     }
718 
719     /**
720      * <code>fillFloatBuffer</code> fills a FloatBuffer object with the matrix
721      * data.
722      *
723      * @param fb
724      *            the buffer to fill, starting at current position. Must have
725      *            room for 16 more floats.
726      * @param columnMajor
727      *            if true, this buffer should be filled with column major data,
728      *            otherwise it will be filled row major.
729      * @return matrix data as a FloatBuffer. (position is advanced by 16 and any
730      *         limit set is not changed).
731      */
fillFloatBuffer(FloatBuffer fb, boolean columnMajor)732     public FloatBuffer fillFloatBuffer(FloatBuffer fb, boolean columnMajor) {
733 //        if (columnMajor) {
734 //            fb.put(m00).put(m10).put(m20).put(m30);
735 //            fb.put(m01).put(m11).put(m21).put(m31);
736 //            fb.put(m02).put(m12).put(m22).put(m32);
737 //            fb.put(m03).put(m13).put(m23).put(m33);
738 //        } else {
739 //            fb.put(m00).put(m01).put(m02).put(m03);
740 //            fb.put(m10).put(m11).put(m12).put(m13);
741 //            fb.put(m20).put(m21).put(m22).put(m23);
742 //            fb.put(m30).put(m31).put(m32).put(m33);
743 //        }
744 
745         TempVars vars = TempVars.get();
746 
747 
748         fillFloatArray(vars.matrixWrite, columnMajor);
749         fb.put(vars.matrixWrite, 0, 16);
750 
751         vars.release();
752 
753         return fb;
754     }
755 
fillFloatArray(float[] f, boolean columnMajor)756     public void fillFloatArray(float[] f, boolean columnMajor) {
757         if (columnMajor) {
758             f[ 0] = m00;
759             f[ 1] = m10;
760             f[ 2] = m20;
761             f[ 3] = m30;
762             f[ 4] = m01;
763             f[ 5] = m11;
764             f[ 6] = m21;
765             f[ 7] = m31;
766             f[ 8] = m02;
767             f[ 9] = m12;
768             f[10] = m22;
769             f[11] = m32;
770             f[12] = m03;
771             f[13] = m13;
772             f[14] = m23;
773             f[15] = m33;
774         } else {
775             f[ 0] = m00;
776             f[ 1] = m01;
777             f[ 2] = m02;
778             f[ 3] = m03;
779             f[ 4] = m10;
780             f[ 5] = m11;
781             f[ 6] = m12;
782             f[ 7] = m13;
783             f[ 8] = m20;
784             f[ 9] = m21;
785             f[10] = m22;
786             f[11] = m23;
787             f[12] = m30;
788             f[13] = m31;
789             f[14] = m32;
790             f[15] = m33;
791         }
792     }
793 
794     /**
795      * <code>readFloatBuffer</code> reads value for this matrix from a FloatBuffer.
796      * @param fb the buffer to read from, must be correct size
797      * @return this data as a FloatBuffer.
798      */
readFloatBuffer(FloatBuffer fb)799     public Matrix4f readFloatBuffer(FloatBuffer fb) {
800         return readFloatBuffer(fb, false);
801     }
802 
803     /**
804      * <code>readFloatBuffer</code> reads value for this matrix from a FloatBuffer.
805      * @param fb the buffer to read from, must be correct size
806      * @param columnMajor if true, this buffer should be filled with column
807      * 		major data, otherwise it will be filled row major.
808      * @return this data as a FloatBuffer.
809      */
readFloatBuffer(FloatBuffer fb, boolean columnMajor)810     public Matrix4f readFloatBuffer(FloatBuffer fb, boolean columnMajor) {
811 
812         if (columnMajor) {
813             m00 = fb.get();
814             m10 = fb.get();
815             m20 = fb.get();
816             m30 = fb.get();
817             m01 = fb.get();
818             m11 = fb.get();
819             m21 = fb.get();
820             m31 = fb.get();
821             m02 = fb.get();
822             m12 = fb.get();
823             m22 = fb.get();
824             m32 = fb.get();
825             m03 = fb.get();
826             m13 = fb.get();
827             m23 = fb.get();
828             m33 = fb.get();
829         } else {
830             m00 = fb.get();
831             m01 = fb.get();
832             m02 = fb.get();
833             m03 = fb.get();
834             m10 = fb.get();
835             m11 = fb.get();
836             m12 = fb.get();
837             m13 = fb.get();
838             m20 = fb.get();
839             m21 = fb.get();
840             m22 = fb.get();
841             m23 = fb.get();
842             m30 = fb.get();
843             m31 = fb.get();
844             m32 = fb.get();
845             m33 = fb.get();
846         }
847         return this;
848     }
849 
850     /**
851      * <code>loadIdentity</code> sets this matrix to the identity matrix,
852      * namely all zeros with ones along the diagonal.
853      *
854      */
loadIdentity()855     public void loadIdentity() {
856         m01 = m02 = m03 = 0.0f;
857         m10 = m12 = m13 = 0.0f;
858         m20 = m21 = m23 = 0.0f;
859         m30 = m31 = m32 = 0.0f;
860         m00 = m11 = m22 = m33 = 1.0f;
861     }
862 
fromFrustum(float near, float far, float left, float right, float top, float bottom, boolean parallel)863     public void fromFrustum(float near, float far, float left, float right, float top, float bottom, boolean parallel) {
864         loadIdentity();
865         if (parallel) {
866             // scale
867             m00 = 2.0f / (right - left);
868             //m11 = 2.0f / (bottom - top);
869             m11 = 2.0f / (top - bottom);
870             m22 = -2.0f / (far - near);
871             m33 = 1f;
872 
873             // translation
874             m03 = -(right + left) / (right - left);
875             //m31 = -(bottom + top) / (bottom - top);
876             m13 = -(top + bottom) / (top - bottom);
877             m23 = -(far + near) / (far - near);
878         } else {
879             m00 = (2.0f * near) / (right - left);
880             m11 = (2.0f * near) / (top - bottom);
881             m32 = -1.0f;
882             m33 = -0.0f;
883 
884             // A
885             m02 = (right + left) / (right - left);
886 
887             // B
888             m12 = (top + bottom) / (top - bottom);
889 
890             // C
891             m22 = -(far + near) / (far - near);
892 
893             // D
894             m23 = -(2.0f * far * near) / (far - near);
895         }
896     }
897 
898     /**
899      * <code>fromAngleAxis</code> sets this matrix4f to the values specified
900      * by an angle and an axis of rotation.  This method creates an object, so
901      * use fromAngleNormalAxis if your axis is already normalized.
902      *
903      * @param angle
904      *            the angle to rotate (in radians).
905      * @param axis
906      *            the axis of rotation.
907      */
fromAngleAxis(float angle, Vector3f axis)908     public void fromAngleAxis(float angle, Vector3f axis) {
909         Vector3f normAxis = axis.normalize();
910         fromAngleNormalAxis(angle, normAxis);
911     }
912 
913     /**
914      * <code>fromAngleNormalAxis</code> sets this matrix4f to the values
915      * specified by an angle and a normalized axis of rotation.
916      *
917      * @param angle
918      *            the angle to rotate (in radians).
919      * @param axis
920      *            the axis of rotation (already normalized).
921      */
fromAngleNormalAxis(float angle, Vector3f axis)922     public void fromAngleNormalAxis(float angle, Vector3f axis) {
923         zero();
924         m33 = 1;
925 
926         float fCos = FastMath.cos(angle);
927         float fSin = FastMath.sin(angle);
928         float fOneMinusCos = ((float) 1.0) - fCos;
929         float fX2 = axis.x * axis.x;
930         float fY2 = axis.y * axis.y;
931         float fZ2 = axis.z * axis.z;
932         float fXYM = axis.x * axis.y * fOneMinusCos;
933         float fXZM = axis.x * axis.z * fOneMinusCos;
934         float fYZM = axis.y * axis.z * fOneMinusCos;
935         float fXSin = axis.x * fSin;
936         float fYSin = axis.y * fSin;
937         float fZSin = axis.z * fSin;
938 
939         m00 = fX2 * fOneMinusCos + fCos;
940         m01 = fXYM - fZSin;
941         m02 = fXZM + fYSin;
942         m10 = fXYM + fZSin;
943         m11 = fY2 * fOneMinusCos + fCos;
944         m12 = fYZM - fXSin;
945         m20 = fXZM - fYSin;
946         m21 = fYZM + fXSin;
947         m22 = fZ2 * fOneMinusCos + fCos;
948     }
949 
950     /**
951      * <code>mult</code> multiplies this matrix by a scalar.
952      *
953      * @param scalar
954      *            the scalar to multiply this matrix by.
955      */
multLocal(float scalar)956     public void multLocal(float scalar) {
957         m00 *= scalar;
958         m01 *= scalar;
959         m02 *= scalar;
960         m03 *= scalar;
961         m10 *= scalar;
962         m11 *= scalar;
963         m12 *= scalar;
964         m13 *= scalar;
965         m20 *= scalar;
966         m21 *= scalar;
967         m22 *= scalar;
968         m23 *= scalar;
969         m30 *= scalar;
970         m31 *= scalar;
971         m32 *= scalar;
972         m33 *= scalar;
973     }
974 
mult(float scalar)975     public Matrix4f mult(float scalar) {
976         Matrix4f out = new Matrix4f();
977         out.set(this);
978         out.multLocal(scalar);
979         return out;
980     }
981 
mult(float scalar, Matrix4f store)982     public Matrix4f mult(float scalar, Matrix4f store) {
983         store.set(this);
984         store.multLocal(scalar);
985         return store;
986     }
987 
988     /**
989      * <code>mult</code> multiplies this matrix with another matrix. The
990      * result matrix will then be returned. This matrix will be on the left hand
991      * side, while the parameter matrix will be on the right.
992      *
993      * @param in2
994      *            the matrix to multiply this matrix by.
995      * @return the resultant matrix
996      */
mult(Matrix4f in2)997     public Matrix4f mult(Matrix4f in2) {
998         return mult(in2, null);
999     }
1000 
1001     /**
1002      * <code>mult</code> multiplies this matrix with another matrix. The
1003      * result matrix will then be returned. This matrix will be on the left hand
1004      * side, while the parameter matrix will be on the right.
1005      *
1006      * @param in2
1007      *            the matrix to multiply this matrix by.
1008      * @param store
1009      *            where to store the result. It is safe for in2 and store to be
1010      *            the same object.
1011      * @return the resultant matrix
1012      */
mult(Matrix4f in2, Matrix4f store)1013     public Matrix4f mult(Matrix4f in2, Matrix4f store) {
1014         if (store == null) {
1015             store = new Matrix4f();
1016         }
1017 
1018         float temp00, temp01, temp02, temp03;
1019         float temp10, temp11, temp12, temp13;
1020         float temp20, temp21, temp22, temp23;
1021         float temp30, temp31, temp32, temp33;
1022 
1023         temp00 = m00 * in2.m00
1024                 + m01 * in2.m10
1025                 + m02 * in2.m20
1026                 + m03 * in2.m30;
1027         temp01 = m00 * in2.m01
1028                 + m01 * in2.m11
1029                 + m02 * in2.m21
1030                 + m03 * in2.m31;
1031         temp02 = m00 * in2.m02
1032                 + m01 * in2.m12
1033                 + m02 * in2.m22
1034                 + m03 * in2.m32;
1035         temp03 = m00 * in2.m03
1036                 + m01 * in2.m13
1037                 + m02 * in2.m23
1038                 + m03 * in2.m33;
1039 
1040         temp10 = m10 * in2.m00
1041                 + m11 * in2.m10
1042                 + m12 * in2.m20
1043                 + m13 * in2.m30;
1044         temp11 = m10 * in2.m01
1045                 + m11 * in2.m11
1046                 + m12 * in2.m21
1047                 + m13 * in2.m31;
1048         temp12 = m10 * in2.m02
1049                 + m11 * in2.m12
1050                 + m12 * in2.m22
1051                 + m13 * in2.m32;
1052         temp13 = m10 * in2.m03
1053                 + m11 * in2.m13
1054                 + m12 * in2.m23
1055                 + m13 * in2.m33;
1056 
1057         temp20 = m20 * in2.m00
1058                 + m21 * in2.m10
1059                 + m22 * in2.m20
1060                 + m23 * in2.m30;
1061         temp21 = m20 * in2.m01
1062                 + m21 * in2.m11
1063                 + m22 * in2.m21
1064                 + m23 * in2.m31;
1065         temp22 = m20 * in2.m02
1066                 + m21 * in2.m12
1067                 + m22 * in2.m22
1068                 + m23 * in2.m32;
1069         temp23 = m20 * in2.m03
1070                 + m21 * in2.m13
1071                 + m22 * in2.m23
1072                 + m23 * in2.m33;
1073 
1074         temp30 = m30 * in2.m00
1075                 + m31 * in2.m10
1076                 + m32 * in2.m20
1077                 + m33 * in2.m30;
1078         temp31 = m30 * in2.m01
1079                 + m31 * in2.m11
1080                 + m32 * in2.m21
1081                 + m33 * in2.m31;
1082         temp32 = m30 * in2.m02
1083                 + m31 * in2.m12
1084                 + m32 * in2.m22
1085                 + m33 * in2.m32;
1086         temp33 = m30 * in2.m03
1087                 + m31 * in2.m13
1088                 + m32 * in2.m23
1089                 + m33 * in2.m33;
1090 
1091         store.m00 = temp00;
1092         store.m01 = temp01;
1093         store.m02 = temp02;
1094         store.m03 = temp03;
1095         store.m10 = temp10;
1096         store.m11 = temp11;
1097         store.m12 = temp12;
1098         store.m13 = temp13;
1099         store.m20 = temp20;
1100         store.m21 = temp21;
1101         store.m22 = temp22;
1102         store.m23 = temp23;
1103         store.m30 = temp30;
1104         store.m31 = temp31;
1105         store.m32 = temp32;
1106         store.m33 = temp33;
1107 
1108         return store;
1109     }
1110 
1111     /**
1112      * <code>mult</code> multiplies this matrix with another matrix. The
1113      * results are stored internally and a handle to this matrix will
1114      * then be returned. This matrix will be on the left hand
1115      * side, while the parameter matrix will be on the right.
1116      *
1117      * @param in2
1118      *            the matrix to multiply this matrix by.
1119      * @return the resultant matrix
1120      */
multLocal(Matrix4f in2)1121     public Matrix4f multLocal(Matrix4f in2) {
1122         return mult(in2, this);
1123     }
1124 
1125     /**
1126      * <code>mult</code> multiplies a vector about a rotation matrix. The
1127      * resulting vector is returned as a new Vector3f.
1128      *
1129      * @param vec
1130      *            vec to multiply against.
1131      * @return the rotated vector.
1132      */
mult(Vector3f vec)1133     public Vector3f mult(Vector3f vec) {
1134         return mult(vec, null);
1135     }
1136 
1137     /**
1138      * <code>mult</code> multiplies a vector about a rotation matrix and adds
1139      * translation. The resulting vector is returned.
1140      *
1141      * @param vec
1142      *            vec to multiply against.
1143      * @param store
1144      *            a vector to store the result in. Created if null is passed.
1145      * @return the rotated vector.
1146      */
mult(Vector3f vec, Vector3f store)1147     public Vector3f mult(Vector3f vec, Vector3f store) {
1148         if (store == null) {
1149             store = new Vector3f();
1150         }
1151 
1152         float vx = vec.x, vy = vec.y, vz = vec.z;
1153         store.x = m00 * vx + m01 * vy + m02 * vz + m03;
1154         store.y = m10 * vx + m11 * vy + m12 * vz + m13;
1155         store.z = m20 * vx + m21 * vy + m22 * vz + m23;
1156 
1157         return store;
1158     }
1159 
1160     /**
1161      * <code>mult</code> multiplies a <code>Vector4f</code> about a rotation
1162      * matrix. The resulting vector is returned as a new <code>Vector4f</code>.
1163      *
1164      * @param vec
1165      *            vec to multiply against.
1166      * @return the rotated vector.
1167      */
mult(Vector4f vec)1168     public Vector4f mult(Vector4f vec) {
1169         return mult(vec, null);
1170     }
1171 
1172     /**
1173      * <code>mult</code> multiplies a <code>Vector4f</code> about a rotation
1174      * matrix. The resulting vector is returned.
1175      *
1176      * @param vec
1177      *            vec to multiply against.
1178      * @param store
1179      *            a vector to store the result in. Created if null is passed.
1180      * @return the rotated vector.
1181      */
mult(Vector4f vec, Vector4f store)1182     public Vector4f mult(Vector4f vec, Vector4f store) {
1183         if (null == vec) {
1184             logger.info("Source vector is null, null result returned.");
1185             return null;
1186         }
1187         if (store == null) {
1188             store = new Vector4f();
1189         }
1190 
1191         float vx = vec.x, vy = vec.y, vz = vec.z, vw = vec.w;
1192         store.x = m00 * vx + m01 * vy + m02 * vz + m03 * vw;
1193         store.y = m10 * vx + m11 * vy + m12 * vz + m13 * vw;
1194         store.z = m20 * vx + m21 * vy + m22 * vz + m23 * vw;
1195         store.w = m30 * vx + m31 * vy + m32 * vz + m33 * vw;
1196 
1197         return store;
1198     }
1199 
1200     /**
1201      * <code>mult</code> multiplies a vector about a rotation matrix. The
1202      * resulting vector is returned.
1203      *
1204      * @param vec
1205      *            vec to multiply against.
1206      *
1207      * @return the rotated vector.
1208      */
multAcross(Vector4f vec)1209     public Vector4f multAcross(Vector4f vec) {
1210         return multAcross(vec, null);
1211     }
1212 
1213     /**
1214      * <code>mult</code> multiplies a vector about a rotation matrix. The
1215      * resulting vector is returned.
1216      *
1217      * @param vec
1218      *            vec to multiply against.
1219      * @param store
1220      *            a vector to store the result in.  created if null is passed.
1221      * @return the rotated vector.
1222      */
multAcross(Vector4f vec, Vector4f store)1223     public Vector4f multAcross(Vector4f vec, Vector4f store) {
1224         if (null == vec) {
1225             logger.info("Source vector is null, null result returned.");
1226             return null;
1227         }
1228         if (store == null) {
1229             store = new Vector4f();
1230         }
1231 
1232         float vx = vec.x, vy = vec.y, vz = vec.z, vw = vec.w;
1233         store.x = m00 * vx + m10 * vy + m20 * vz + m30 * vw;
1234         store.y = m01 * vx + m11 * vy + m21 * vz + m31 * vw;
1235         store.z = m02 * vx + m12 * vy + m22 * vz + m32 * vw;
1236         store.z = m03 * vx + m13 * vy + m23 * vz + m33 * vw;
1237 
1238         return store;
1239     }
1240 
1241     /**
1242      * <code>multNormal</code> multiplies a vector about a rotation matrix, but
1243      * does not add translation. The resulting vector is returned.
1244      *
1245      * @param vec
1246      *            vec to multiply against.
1247      * @param store
1248      *            a vector to store the result in. Created if null is passed.
1249      * @return the rotated vector.
1250      */
multNormal(Vector3f vec, Vector3f store)1251     public Vector3f multNormal(Vector3f vec, Vector3f store) {
1252         if (store == null) {
1253             store = new Vector3f();
1254         }
1255 
1256         float vx = vec.x, vy = vec.y, vz = vec.z;
1257         store.x = m00 * vx + m01 * vy + m02 * vz;
1258         store.y = m10 * vx + m11 * vy + m12 * vz;
1259         store.z = m20 * vx + m21 * vy + m22 * vz;
1260 
1261         return store;
1262     }
1263 
1264     /**
1265      * <code>multNormal</code> multiplies a vector about a rotation matrix, but
1266      * does not add translation. The resulting vector is returned.
1267      *
1268      * @param vec
1269      *            vec to multiply against.
1270      * @param store
1271      *            a vector to store the result in. Created if null is passed.
1272      * @return the rotated vector.
1273      */
multNormalAcross(Vector3f vec, Vector3f store)1274     public Vector3f multNormalAcross(Vector3f vec, Vector3f store) {
1275         if (store == null) {
1276             store = new Vector3f();
1277         }
1278 
1279         float vx = vec.x, vy = vec.y, vz = vec.z;
1280         store.x = m00 * vx + m10 * vy + m20 * vz;
1281         store.y = m01 * vx + m11 * vy + m21 * vz;
1282         store.z = m02 * vx + m12 * vy + m22 * vz;
1283 
1284         return store;
1285     }
1286 
1287     /**
1288      * <code>mult</code> multiplies a vector about a rotation matrix and adds
1289      * translation. The w value is returned as a result of
1290      * multiplying the last column of the matrix by 1.0
1291      *
1292      * @param vec
1293      *            vec to multiply against.
1294      * @param store
1295      *            a vector to store the result in.
1296      * @return the W value
1297      */
multProj(Vector3f vec, Vector3f store)1298     public float multProj(Vector3f vec, Vector3f store) {
1299         float vx = vec.x, vy = vec.y, vz = vec.z;
1300         store.x = m00 * vx + m01 * vy + m02 * vz + m03;
1301         store.y = m10 * vx + m11 * vy + m12 * vz + m13;
1302         store.z = m20 * vx + m21 * vy + m22 * vz + m23;
1303         return m30 * vx + m31 * vy + m32 * vz + m33;
1304     }
1305 
1306     /**
1307      * <code>mult</code> multiplies a vector about a rotation matrix. The
1308      * resulting vector is returned.
1309      *
1310      * @param vec
1311      *            vec to multiply against.
1312      * @param store
1313      *            a vector to store the result in.  created if null is passed.
1314      * @return the rotated vector.
1315      */
multAcross(Vector3f vec, Vector3f store)1316     public Vector3f multAcross(Vector3f vec, Vector3f store) {
1317         if (null == vec) {
1318             logger.info("Source vector is null, null result returned.");
1319             return null;
1320         }
1321         if (store == null) {
1322             store = new Vector3f();
1323         }
1324 
1325         float vx = vec.x, vy = vec.y, vz = vec.z;
1326         store.x = m00 * vx + m10 * vy + m20 * vz + m30 * 1;
1327         store.y = m01 * vx + m11 * vy + m21 * vz + m31 * 1;
1328         store.z = m02 * vx + m12 * vy + m22 * vz + m32 * 1;
1329 
1330         return store;
1331     }
1332 
1333     /**
1334      * <code>mult</code> multiplies a quaternion about a matrix. The
1335      * resulting vector is returned.
1336      *
1337      * @param vec
1338      *            vec to multiply against.
1339      * @param store
1340      *            a quaternion to store the result in.  created if null is passed.
1341      * @return store = this * vec
1342      */
mult(Quaternion vec, Quaternion store)1343     public Quaternion mult(Quaternion vec, Quaternion store) {
1344 
1345         if (null == vec) {
1346             logger.warning("Source vector is null, null result returned.");
1347             return null;
1348         }
1349         if (store == null) {
1350             store = new Quaternion();
1351         }
1352 
1353         float x = m00 * vec.x + m10 * vec.y + m20 * vec.z + m30 * vec.w;
1354         float y = m01 * vec.x + m11 * vec.y + m21 * vec.z + m31 * vec.w;
1355         float z = m02 * vec.x + m12 * vec.y + m22 * vec.z + m32 * vec.w;
1356         float w = m03 * vec.x + m13 * vec.y + m23 * vec.z + m33 * vec.w;
1357         store.x = x;
1358         store.y = y;
1359         store.z = z;
1360         store.w = w;
1361 
1362         return store;
1363     }
1364 
1365     /**
1366      * <code>mult</code> multiplies an array of 4 floats against this rotation
1367      * matrix. The results are stored directly in the array. (vec4f x mat4f)
1368      *
1369      * @param vec4f
1370      *            float array (size 4) to multiply against the matrix.
1371      * @return the vec4f for chaining.
1372      */
mult(float[] vec4f)1373     public float[] mult(float[] vec4f) {
1374         if (null == vec4f || vec4f.length != 4) {
1375             logger.warning("invalid array given, must be nonnull and length 4");
1376             return null;
1377         }
1378 
1379         float x = vec4f[0], y = vec4f[1], z = vec4f[2], w = vec4f[3];
1380 
1381         vec4f[0] = m00 * x + m01 * y + m02 * z + m03 * w;
1382         vec4f[1] = m10 * x + m11 * y + m12 * z + m13 * w;
1383         vec4f[2] = m20 * x + m21 * y + m22 * z + m23 * w;
1384         vec4f[3] = m30 * x + m31 * y + m32 * z + m33 * w;
1385 
1386         return vec4f;
1387     }
1388 
1389     /**
1390      * <code>mult</code> multiplies an array of 4 floats against this rotation
1391      * matrix. The results are stored directly in the array. (vec4f x mat4f)
1392      *
1393      * @param vec4f
1394      *            float array (size 4) to multiply against the matrix.
1395      * @return the vec4f for chaining.
1396      */
multAcross(float[] vec4f)1397     public float[] multAcross(float[] vec4f) {
1398         if (null == vec4f || vec4f.length != 4) {
1399             logger.warning("invalid array given, must be nonnull and length 4");
1400             return null;
1401         }
1402 
1403         float x = vec4f[0], y = vec4f[1], z = vec4f[2], w = vec4f[3];
1404 
1405         vec4f[0] = m00 * x + m10 * y + m20 * z + m30 * w;
1406         vec4f[1] = m01 * x + m11 * y + m21 * z + m31 * w;
1407         vec4f[2] = m02 * x + m12 * y + m22 * z + m32 * w;
1408         vec4f[3] = m03 * x + m13 * y + m23 * z + m33 * w;
1409 
1410         return vec4f;
1411     }
1412 
1413     /**
1414      * Inverts this matrix as a new Matrix4f.
1415      *
1416      * @return The new inverse matrix
1417      */
invert()1418     public Matrix4f invert() {
1419         return invert(null);
1420     }
1421 
1422     /**
1423      * Inverts this matrix and stores it in the given store.
1424      *
1425      * @return The store
1426      */
invert(Matrix4f store)1427     public Matrix4f invert(Matrix4f store) {
1428         if (store == null) {
1429             store = new Matrix4f();
1430         }
1431 
1432         float fA0 = m00 * m11 - m01 * m10;
1433         float fA1 = m00 * m12 - m02 * m10;
1434         float fA2 = m00 * m13 - m03 * m10;
1435         float fA3 = m01 * m12 - m02 * m11;
1436         float fA4 = m01 * m13 - m03 * m11;
1437         float fA5 = m02 * m13 - m03 * m12;
1438         float fB0 = m20 * m31 - m21 * m30;
1439         float fB1 = m20 * m32 - m22 * m30;
1440         float fB2 = m20 * m33 - m23 * m30;
1441         float fB3 = m21 * m32 - m22 * m31;
1442         float fB4 = m21 * m33 - m23 * m31;
1443         float fB5 = m22 * m33 - m23 * m32;
1444         float fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0;
1445 
1446         if (FastMath.abs(fDet) <= 0f) {
1447             throw new ArithmeticException("This matrix cannot be inverted");
1448         }
1449 
1450         store.m00 = +m11 * fB5 - m12 * fB4 + m13 * fB3;
1451         store.m10 = -m10 * fB5 + m12 * fB2 - m13 * fB1;
1452         store.m20 = +m10 * fB4 - m11 * fB2 + m13 * fB0;
1453         store.m30 = -m10 * fB3 + m11 * fB1 - m12 * fB0;
1454         store.m01 = -m01 * fB5 + m02 * fB4 - m03 * fB3;
1455         store.m11 = +m00 * fB5 - m02 * fB2 + m03 * fB1;
1456         store.m21 = -m00 * fB4 + m01 * fB2 - m03 * fB0;
1457         store.m31 = +m00 * fB3 - m01 * fB1 + m02 * fB0;
1458         store.m02 = +m31 * fA5 - m32 * fA4 + m33 * fA3;
1459         store.m12 = -m30 * fA5 + m32 * fA2 - m33 * fA1;
1460         store.m22 = +m30 * fA4 - m31 * fA2 + m33 * fA0;
1461         store.m32 = -m30 * fA3 + m31 * fA1 - m32 * fA0;
1462         store.m03 = -m21 * fA5 + m22 * fA4 - m23 * fA3;
1463         store.m13 = +m20 * fA5 - m22 * fA2 + m23 * fA1;
1464         store.m23 = -m20 * fA4 + m21 * fA2 - m23 * fA0;
1465         store.m33 = +m20 * fA3 - m21 * fA1 + m22 * fA0;
1466 
1467         float fInvDet = 1.0f / fDet;
1468         store.multLocal(fInvDet);
1469 
1470         return store;
1471     }
1472 
1473     /**
1474      * Inverts this matrix locally.
1475      *
1476      * @return this
1477      */
invertLocal()1478     public Matrix4f invertLocal() {
1479 
1480         float fA0 = m00 * m11 - m01 * m10;
1481         float fA1 = m00 * m12 - m02 * m10;
1482         float fA2 = m00 * m13 - m03 * m10;
1483         float fA3 = m01 * m12 - m02 * m11;
1484         float fA4 = m01 * m13 - m03 * m11;
1485         float fA5 = m02 * m13 - m03 * m12;
1486         float fB0 = m20 * m31 - m21 * m30;
1487         float fB1 = m20 * m32 - m22 * m30;
1488         float fB2 = m20 * m33 - m23 * m30;
1489         float fB3 = m21 * m32 - m22 * m31;
1490         float fB4 = m21 * m33 - m23 * m31;
1491         float fB5 = m22 * m33 - m23 * m32;
1492         float fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0;
1493 
1494         if (FastMath.abs(fDet) <= 0f) {
1495             return zero();
1496         }
1497 
1498         float f00 = +m11 * fB5 - m12 * fB4 + m13 * fB3;
1499         float f10 = -m10 * fB5 + m12 * fB2 - m13 * fB1;
1500         float f20 = +m10 * fB4 - m11 * fB2 + m13 * fB0;
1501         float f30 = -m10 * fB3 + m11 * fB1 - m12 * fB0;
1502         float f01 = -m01 * fB5 + m02 * fB4 - m03 * fB3;
1503         float f11 = +m00 * fB5 - m02 * fB2 + m03 * fB1;
1504         float f21 = -m00 * fB4 + m01 * fB2 - m03 * fB0;
1505         float f31 = +m00 * fB3 - m01 * fB1 + m02 * fB0;
1506         float f02 = +m31 * fA5 - m32 * fA4 + m33 * fA3;
1507         float f12 = -m30 * fA5 + m32 * fA2 - m33 * fA1;
1508         float f22 = +m30 * fA4 - m31 * fA2 + m33 * fA0;
1509         float f32 = -m30 * fA3 + m31 * fA1 - m32 * fA0;
1510         float f03 = -m21 * fA5 + m22 * fA4 - m23 * fA3;
1511         float f13 = +m20 * fA5 - m22 * fA2 + m23 * fA1;
1512         float f23 = -m20 * fA4 + m21 * fA2 - m23 * fA0;
1513         float f33 = +m20 * fA3 - m21 * fA1 + m22 * fA0;
1514 
1515         m00 = f00;
1516         m01 = f01;
1517         m02 = f02;
1518         m03 = f03;
1519         m10 = f10;
1520         m11 = f11;
1521         m12 = f12;
1522         m13 = f13;
1523         m20 = f20;
1524         m21 = f21;
1525         m22 = f22;
1526         m23 = f23;
1527         m30 = f30;
1528         m31 = f31;
1529         m32 = f32;
1530         m33 = f33;
1531 
1532         float fInvDet = 1.0f / fDet;
1533         multLocal(fInvDet);
1534 
1535         return this;
1536     }
1537 
1538     /**
1539      * Returns a new matrix representing the adjoint of this matrix.
1540      *
1541      * @return The adjoint matrix
1542      */
adjoint()1543     public Matrix4f adjoint() {
1544         return adjoint(null);
1545     }
1546 
setTransform(Vector3f position, Vector3f scale, Matrix3f rotMat)1547     public void setTransform(Vector3f position, Vector3f scale, Matrix3f rotMat) {
1548         // Ordering:
1549         //    1. Scale
1550         //    2. Rotate
1551         //    3. Translate
1552 
1553         // Set up final matrix with scale, rotation and translation
1554         m00 = scale.x * rotMat.m00;
1555         m01 = scale.y * rotMat.m01;
1556         m02 = scale.z * rotMat.m02;
1557         m03 = position.x;
1558         m10 = scale.x * rotMat.m10;
1559         m11 = scale.y * rotMat.m11;
1560         m12 = scale.z * rotMat.m12;
1561         m13 = position.y;
1562         m20 = scale.x * rotMat.m20;
1563         m21 = scale.y * rotMat.m21;
1564         m22 = scale.z * rotMat.m22;
1565         m23 = position.z;
1566 
1567         // No projection term
1568         m30 = 0;
1569         m31 = 0;
1570         m32 = 0;
1571         m33 = 1;
1572     }
1573 
1574     /**
1575      * Places the adjoint of this matrix in store (creates store if null.)
1576      *
1577      * @param store
1578      *            The matrix to store the result in.  If null, a new matrix is created.
1579      * @return store
1580      */
adjoint(Matrix4f store)1581     public Matrix4f adjoint(Matrix4f store) {
1582         if (store == null) {
1583             store = new Matrix4f();
1584         }
1585 
1586         float fA0 = m00 * m11 - m01 * m10;
1587         float fA1 = m00 * m12 - m02 * m10;
1588         float fA2 = m00 * m13 - m03 * m10;
1589         float fA3 = m01 * m12 - m02 * m11;
1590         float fA4 = m01 * m13 - m03 * m11;
1591         float fA5 = m02 * m13 - m03 * m12;
1592         float fB0 = m20 * m31 - m21 * m30;
1593         float fB1 = m20 * m32 - m22 * m30;
1594         float fB2 = m20 * m33 - m23 * m30;
1595         float fB3 = m21 * m32 - m22 * m31;
1596         float fB4 = m21 * m33 - m23 * m31;
1597         float fB5 = m22 * m33 - m23 * m32;
1598 
1599         store.m00 = +m11 * fB5 - m12 * fB4 + m13 * fB3;
1600         store.m10 = -m10 * fB5 + m12 * fB2 - m13 * fB1;
1601         store.m20 = +m10 * fB4 - m11 * fB2 + m13 * fB0;
1602         store.m30 = -m10 * fB3 + m11 * fB1 - m12 * fB0;
1603         store.m01 = -m01 * fB5 + m02 * fB4 - m03 * fB3;
1604         store.m11 = +m00 * fB5 - m02 * fB2 + m03 * fB1;
1605         store.m21 = -m00 * fB4 + m01 * fB2 - m03 * fB0;
1606         store.m31 = +m00 * fB3 - m01 * fB1 + m02 * fB0;
1607         store.m02 = +m31 * fA5 - m32 * fA4 + m33 * fA3;
1608         store.m12 = -m30 * fA5 + m32 * fA2 - m33 * fA1;
1609         store.m22 = +m30 * fA4 - m31 * fA2 + m33 * fA0;
1610         store.m32 = -m30 * fA3 + m31 * fA1 - m32 * fA0;
1611         store.m03 = -m21 * fA5 + m22 * fA4 - m23 * fA3;
1612         store.m13 = +m20 * fA5 - m22 * fA2 + m23 * fA1;
1613         store.m23 = -m20 * fA4 + m21 * fA2 - m23 * fA0;
1614         store.m33 = +m20 * fA3 - m21 * fA1 + m22 * fA0;
1615 
1616         return store;
1617     }
1618 
1619     /**
1620      * <code>determinant</code> generates the determinate of this matrix.
1621      *
1622      * @return the determinate
1623      */
determinant()1624     public float determinant() {
1625         float fA0 = m00 * m11 - m01 * m10;
1626         float fA1 = m00 * m12 - m02 * m10;
1627         float fA2 = m00 * m13 - m03 * m10;
1628         float fA3 = m01 * m12 - m02 * m11;
1629         float fA4 = m01 * m13 - m03 * m11;
1630         float fA5 = m02 * m13 - m03 * m12;
1631         float fB0 = m20 * m31 - m21 * m30;
1632         float fB1 = m20 * m32 - m22 * m30;
1633         float fB2 = m20 * m33 - m23 * m30;
1634         float fB3 = m21 * m32 - m22 * m31;
1635         float fB4 = m21 * m33 - m23 * m31;
1636         float fB5 = m22 * m33 - m23 * m32;
1637         float fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0;
1638         return fDet;
1639     }
1640 
1641     /**
1642      * Sets all of the values in this matrix to zero.
1643      *
1644      * @return this matrix
1645      */
zero()1646     public Matrix4f zero() {
1647         m00 = m01 = m02 = m03 = 0.0f;
1648         m10 = m11 = m12 = m13 = 0.0f;
1649         m20 = m21 = m22 = m23 = 0.0f;
1650         m30 = m31 = m32 = m33 = 0.0f;
1651         return this;
1652     }
1653 
add(Matrix4f mat)1654     public Matrix4f add(Matrix4f mat) {
1655         Matrix4f result = new Matrix4f();
1656         result.m00 = this.m00 + mat.m00;
1657         result.m01 = this.m01 + mat.m01;
1658         result.m02 = this.m02 + mat.m02;
1659         result.m03 = this.m03 + mat.m03;
1660         result.m10 = this.m10 + mat.m10;
1661         result.m11 = this.m11 + mat.m11;
1662         result.m12 = this.m12 + mat.m12;
1663         result.m13 = this.m13 + mat.m13;
1664         result.m20 = this.m20 + mat.m20;
1665         result.m21 = this.m21 + mat.m21;
1666         result.m22 = this.m22 + mat.m22;
1667         result.m23 = this.m23 + mat.m23;
1668         result.m30 = this.m30 + mat.m30;
1669         result.m31 = this.m31 + mat.m31;
1670         result.m32 = this.m32 + mat.m32;
1671         result.m33 = this.m33 + mat.m33;
1672         return result;
1673     }
1674 
1675     /**
1676      * <code>add</code> adds the values of a parameter matrix to this matrix.
1677      *
1678      * @param mat
1679      *            the matrix to add to this.
1680      */
addLocal(Matrix4f mat)1681     public void addLocal(Matrix4f mat) {
1682         m00 += mat.m00;
1683         m01 += mat.m01;
1684         m02 += mat.m02;
1685         m03 += mat.m03;
1686         m10 += mat.m10;
1687         m11 += mat.m11;
1688         m12 += mat.m12;
1689         m13 += mat.m13;
1690         m20 += mat.m20;
1691         m21 += mat.m21;
1692         m22 += mat.m22;
1693         m23 += mat.m23;
1694         m30 += mat.m30;
1695         m31 += mat.m31;
1696         m32 += mat.m32;
1697         m33 += mat.m33;
1698     }
1699 
toTranslationVector()1700     public Vector3f toTranslationVector() {
1701         return new Vector3f(m03, m13, m23);
1702     }
1703 
toTranslationVector(Vector3f vector)1704     public void toTranslationVector(Vector3f vector) {
1705         vector.set(m03, m13, m23);
1706     }
1707 
toRotationQuat()1708     public Quaternion toRotationQuat() {
1709         Quaternion quat = new Quaternion();
1710         quat.fromRotationMatrix(toRotationMatrix());
1711         return quat;
1712     }
1713 
toRotationQuat(Quaternion q)1714     public void toRotationQuat(Quaternion q) {
1715         q.fromRotationMatrix(toRotationMatrix());
1716     }
1717 
toRotationMatrix()1718     public Matrix3f toRotationMatrix() {
1719         return new Matrix3f(m00, m01, m02, m10, m11, m12, m20, m21, m22);
1720 
1721     }
1722 
toRotationMatrix(Matrix3f mat)1723     public void toRotationMatrix(Matrix3f mat) {
1724         mat.m00 = m00;
1725         mat.m01 = m01;
1726         mat.m02 = m02;
1727         mat.m10 = m10;
1728         mat.m11 = m11;
1729         mat.m12 = m12;
1730         mat.m20 = m20;
1731         mat.m21 = m21;
1732         mat.m22 = m22;
1733 
1734     }
1735 
setScale(float x, float y, float z)1736     public void setScale(float x, float y, float z) {
1737         m00 *= x;
1738         m11 *= y;
1739         m22 *= z;
1740     }
1741 
setScale(Vector3f scale)1742     public void setScale(Vector3f scale) {
1743         m00 *= scale.x;
1744         m11 *= scale.y;
1745         m22 *= scale.z;
1746     }
1747 
1748     /**
1749      * <code>setTranslation</code> will set the matrix's translation values.
1750      *
1751      * @param translation
1752      *            the new values for the translation.
1753      * @throws JmeException
1754      *             if translation is not size 3.
1755      */
setTranslation(float[] translation)1756     public void setTranslation(float[] translation) {
1757         if (translation.length != 3) {
1758             throw new IllegalArgumentException(
1759                     "Translation size must be 3.");
1760         }
1761         m03 = translation[0];
1762         m13 = translation[1];
1763         m23 = translation[2];
1764     }
1765 
1766     /**
1767      * <code>setTranslation</code> will set the matrix's translation values.
1768      *
1769      * @param x
1770      *            value of the translation on the x axis
1771      * @param y
1772      *            value of the translation on the y axis
1773      * @param z
1774      *            value of the translation on the z axis
1775      */
setTranslation(float x, float y, float z)1776     public void setTranslation(float x, float y, float z) {
1777         m03 = x;
1778         m13 = y;
1779         m23 = z;
1780     }
1781 
1782     /**
1783      * <code>setTranslation</code> will set the matrix's translation values.
1784      *
1785      * @param translation
1786      *            the new values for the translation.
1787      */
setTranslation(Vector3f translation)1788     public void setTranslation(Vector3f translation) {
1789         m03 = translation.x;
1790         m13 = translation.y;
1791         m23 = translation.z;
1792     }
1793 
1794     /**
1795      * <code>setInverseTranslation</code> will set the matrix's inverse
1796      * translation values.
1797      *
1798      * @param translation
1799      *            the new values for the inverse translation.
1800      * @throws JmeException
1801      *             if translation is not size 3.
1802      */
setInverseTranslation(float[] translation)1803     public void setInverseTranslation(float[] translation) {
1804         if (translation.length != 3) {
1805             throw new IllegalArgumentException(
1806                     "Translation size must be 3.");
1807         }
1808         m03 = -translation[0];
1809         m13 = -translation[1];
1810         m23 = -translation[2];
1811     }
1812 
1813     /**
1814      * <code>angleRotation</code> sets this matrix to that of a rotation about
1815      * three axes (x, y, z). Where each axis has a specified rotation in
1816      * degrees. These rotations are expressed in a single <code>Vector3f</code>
1817      * object.
1818      *
1819      * @param angles
1820      *            the angles to rotate.
1821      */
angleRotation(Vector3f angles)1822     public void angleRotation(Vector3f angles) {
1823         float angle;
1824         float sr, sp, sy, cr, cp, cy;
1825 
1826         angle = (angles.z * FastMath.DEG_TO_RAD);
1827         sy = FastMath.sin(angle);
1828         cy = FastMath.cos(angle);
1829         angle = (angles.y * FastMath.DEG_TO_RAD);
1830         sp = FastMath.sin(angle);
1831         cp = FastMath.cos(angle);
1832         angle = (angles.x * FastMath.DEG_TO_RAD);
1833         sr = FastMath.sin(angle);
1834         cr = FastMath.cos(angle);
1835 
1836         // matrix = (Z * Y) * X
1837         m00 = cp * cy;
1838         m10 = cp * sy;
1839         m20 = -sp;
1840         m01 = sr * sp * cy + cr * -sy;
1841         m11 = sr * sp * sy + cr * cy;
1842         m21 = sr * cp;
1843         m02 = (cr * sp * cy + -sr * -sy);
1844         m12 = (cr * sp * sy + -sr * cy);
1845         m22 = cr * cp;
1846         m03 = 0.0f;
1847         m13 = 0.0f;
1848         m23 = 0.0f;
1849     }
1850 
1851     /**
1852      * <code>setRotationQuaternion</code> builds a rotation from a
1853      * <code>Quaternion</code>.
1854      *
1855      * @param quat
1856      *            the quaternion to build the rotation from.
1857      * @throws NullPointerException
1858      *             if quat is null.
1859      */
setRotationQuaternion(Quaternion quat)1860     public void setRotationQuaternion(Quaternion quat) {
1861         quat.toRotationMatrix(this);
1862     }
1863 
1864     /**
1865      * <code>setInverseRotationRadians</code> builds an inverted rotation from
1866      * Euler angles that are in radians.
1867      *
1868      * @param angles
1869      *            the Euler angles in radians.
1870      * @throws JmeException
1871      *             if angles is not size 3.
1872      */
setInverseRotationRadians(float[] angles)1873     public void setInverseRotationRadians(float[] angles) {
1874         if (angles.length != 3) {
1875             throw new IllegalArgumentException(
1876                     "Angles must be of size 3.");
1877         }
1878         double cr = FastMath.cos(angles[0]);
1879         double sr = FastMath.sin(angles[0]);
1880         double cp = FastMath.cos(angles[1]);
1881         double sp = FastMath.sin(angles[1]);
1882         double cy = FastMath.cos(angles[2]);
1883         double sy = FastMath.sin(angles[2]);
1884 
1885         m00 = (float) (cp * cy);
1886         m10 = (float) (cp * sy);
1887         m20 = (float) (-sp);
1888 
1889         double srsp = sr * sp;
1890         double crsp = cr * sp;
1891 
1892         m01 = (float) (srsp * cy - cr * sy);
1893         m11 = (float) (srsp * sy + cr * cy);
1894         m21 = (float) (sr * cp);
1895 
1896         m02 = (float) (crsp * cy + sr * sy);
1897         m12 = (float) (crsp * sy - sr * cy);
1898         m22 = (float) (cr * cp);
1899     }
1900 
1901     /**
1902      * <code>setInverseRotationDegrees</code> builds an inverted rotation from
1903      * Euler angles that are in degrees.
1904      *
1905      * @param angles
1906      *            the Euler angles in degrees.
1907      * @throws JmeException
1908      *             if angles is not size 3.
1909      */
setInverseRotationDegrees(float[] angles)1910     public void setInverseRotationDegrees(float[] angles) {
1911         if (angles.length != 3) {
1912             throw new IllegalArgumentException(
1913                     "Angles must be of size 3.");
1914         }
1915         float vec[] = new float[3];
1916         vec[0] = (angles[0] * FastMath.RAD_TO_DEG);
1917         vec[1] = (angles[1] * FastMath.RAD_TO_DEG);
1918         vec[2] = (angles[2] * FastMath.RAD_TO_DEG);
1919         setInverseRotationRadians(vec);
1920     }
1921 
1922     /**
1923      *
1924      * <code>inverseTranslateVect</code> translates a given Vector3f by the
1925      * translation part of this matrix.
1926      *
1927      * @param vec
1928      *            the Vector3f data to be translated.
1929      * @throws JmeException
1930      *             if the size of the Vector3f is not 3.
1931      */
inverseTranslateVect(float[] vec)1932     public void inverseTranslateVect(float[] vec) {
1933         if (vec.length != 3) {
1934             throw new IllegalArgumentException(
1935                     "vec must be of size 3.");
1936         }
1937 
1938         vec[0] = vec[0] - m03;
1939         vec[1] = vec[1] - m13;
1940         vec[2] = vec[2] - m23;
1941     }
1942 
1943     /**
1944      *
1945      * <code>inverseTranslateVect</code> translates a given Vector3f by the
1946      * translation part of this matrix.
1947      *
1948      * @param data
1949      *            the Vector3f to be translated.
1950      * @throws JmeException
1951      *             if the size of the Vector3f is not 3.
1952      */
inverseTranslateVect(Vector3f data)1953     public void inverseTranslateVect(Vector3f data) {
1954         data.x -= m03;
1955         data.y -= m13;
1956         data.z -= m23;
1957     }
1958 
1959     /**
1960      *
1961      * <code>inverseTranslateVect</code> translates a given Vector3f by the
1962      * translation part of this matrix.
1963      *
1964      * @param data
1965      *            the Vector3f to be translated.
1966      * @throws JmeException
1967      *             if the size of the Vector3f is not 3.
1968      */
translateVect(Vector3f data)1969     public void translateVect(Vector3f data) {
1970         data.x += m03;
1971         data.y += m13;
1972         data.z += m23;
1973     }
1974 
1975     /**
1976      *
1977      * <code>inverseRotateVect</code> rotates a given Vector3f by the rotation
1978      * part of this matrix.
1979      *
1980      * @param vec
1981      *            the Vector3f to be rotated.
1982      */
inverseRotateVect(Vector3f vec)1983     public void inverseRotateVect(Vector3f vec) {
1984         float vx = vec.x, vy = vec.y, vz = vec.z;
1985 
1986         vec.x = vx * m00 + vy * m10 + vz * m20;
1987         vec.y = vx * m01 + vy * m11 + vz * m21;
1988         vec.z = vx * m02 + vy * m12 + vz * m22;
1989     }
1990 
rotateVect(Vector3f vec)1991     public void rotateVect(Vector3f vec) {
1992         float vx = vec.x, vy = vec.y, vz = vec.z;
1993 
1994         vec.x = vx * m00 + vy * m01 + vz * m02;
1995         vec.y = vx * m10 + vy * m11 + vz * m12;
1996         vec.z = vx * m20 + vy * m21 + vz * m22;
1997     }
1998 
1999     /**
2000      * <code>toString</code> returns the string representation of this object.
2001      * It is in a format of a 4x4 matrix. For example, an identity matrix would
2002      * be represented by the following string. com.jme.math.Matrix3f <br>[<br>
2003      * 1.0  0.0  0.0  0.0 <br>
2004      * 0.0  1.0  0.0  0.0 <br>
2005      * 0.0  0.0  1.0  0.0 <br>
2006      * 0.0  0.0  0.0  1.0 <br>]<br>
2007      *
2008      * @return the string representation of this object.
2009      */
2010     @Override
toString()2011     public String toString() {
2012         StringBuilder result = new StringBuilder("Matrix4f\n[\n");
2013         result.append(" ");
2014         result.append(m00);
2015         result.append("  ");
2016         result.append(m01);
2017         result.append("  ");
2018         result.append(m02);
2019         result.append("  ");
2020         result.append(m03);
2021         result.append(" \n");
2022         result.append(" ");
2023         result.append(m10);
2024         result.append("  ");
2025         result.append(m11);
2026         result.append("  ");
2027         result.append(m12);
2028         result.append("  ");
2029         result.append(m13);
2030         result.append(" \n");
2031         result.append(" ");
2032         result.append(m20);
2033         result.append("  ");
2034         result.append(m21);
2035         result.append("  ");
2036         result.append(m22);
2037         result.append("  ");
2038         result.append(m23);
2039         result.append(" \n");
2040         result.append(" ");
2041         result.append(m30);
2042         result.append("  ");
2043         result.append(m31);
2044         result.append("  ");
2045         result.append(m32);
2046         result.append("  ");
2047         result.append(m33);
2048         result.append(" \n]");
2049         return result.toString();
2050     }
2051 
2052     /**
2053      *
2054      * <code>hashCode</code> returns the hash code value as an integer and is
2055      * supported for the benefit of hashing based collection classes such as
2056      * Hashtable, HashMap, HashSet etc.
2057      *
2058      * @return the hashcode for this instance of Matrix4f.
2059      * @see java.lang.Object#hashCode()
2060      */
2061     @Override
hashCode()2062     public int hashCode() {
2063         int hash = 37;
2064         hash = 37 * hash + Float.floatToIntBits(m00);
2065         hash = 37 * hash + Float.floatToIntBits(m01);
2066         hash = 37 * hash + Float.floatToIntBits(m02);
2067         hash = 37 * hash + Float.floatToIntBits(m03);
2068 
2069         hash = 37 * hash + Float.floatToIntBits(m10);
2070         hash = 37 * hash + Float.floatToIntBits(m11);
2071         hash = 37 * hash + Float.floatToIntBits(m12);
2072         hash = 37 * hash + Float.floatToIntBits(m13);
2073 
2074         hash = 37 * hash + Float.floatToIntBits(m20);
2075         hash = 37 * hash + Float.floatToIntBits(m21);
2076         hash = 37 * hash + Float.floatToIntBits(m22);
2077         hash = 37 * hash + Float.floatToIntBits(m23);
2078 
2079         hash = 37 * hash + Float.floatToIntBits(m30);
2080         hash = 37 * hash + Float.floatToIntBits(m31);
2081         hash = 37 * hash + Float.floatToIntBits(m32);
2082         hash = 37 * hash + Float.floatToIntBits(m33);
2083 
2084         return hash;
2085     }
2086 
2087     /**
2088      * are these two matrices the same? they are is they both have the same mXX values.
2089      *
2090      * @param o
2091      *            the object to compare for equality
2092      * @return true if they are equal
2093      */
2094     @Override
equals(Object o)2095     public boolean equals(Object o) {
2096         if (!(o instanceof Matrix4f) || o == null) {
2097             return false;
2098         }
2099 
2100         if (this == o) {
2101             return true;
2102         }
2103 
2104         Matrix4f comp = (Matrix4f) o;
2105         if (Float.compare(m00, comp.m00) != 0) {
2106             return false;
2107         }
2108         if (Float.compare(m01, comp.m01) != 0) {
2109             return false;
2110         }
2111         if (Float.compare(m02, comp.m02) != 0) {
2112             return false;
2113         }
2114         if (Float.compare(m03, comp.m03) != 0) {
2115             return false;
2116         }
2117 
2118         if (Float.compare(m10, comp.m10) != 0) {
2119             return false;
2120         }
2121         if (Float.compare(m11, comp.m11) != 0) {
2122             return false;
2123         }
2124         if (Float.compare(m12, comp.m12) != 0) {
2125             return false;
2126         }
2127         if (Float.compare(m13, comp.m13) != 0) {
2128             return false;
2129         }
2130 
2131         if (Float.compare(m20, comp.m20) != 0) {
2132             return false;
2133         }
2134         if (Float.compare(m21, comp.m21) != 0) {
2135             return false;
2136         }
2137         if (Float.compare(m22, comp.m22) != 0) {
2138             return false;
2139         }
2140         if (Float.compare(m23, comp.m23) != 0) {
2141             return false;
2142         }
2143 
2144         if (Float.compare(m30, comp.m30) != 0) {
2145             return false;
2146         }
2147         if (Float.compare(m31, comp.m31) != 0) {
2148             return false;
2149         }
2150         if (Float.compare(m32, comp.m32) != 0) {
2151             return false;
2152         }
2153         if (Float.compare(m33, comp.m33) != 0) {
2154             return false;
2155         }
2156 
2157         return true;
2158     }
2159 
write(JmeExporter e)2160     public void write(JmeExporter e) throws IOException {
2161         OutputCapsule cap = e.getCapsule(this);
2162         cap.write(m00, "m00", 1);
2163         cap.write(m01, "m01", 0);
2164         cap.write(m02, "m02", 0);
2165         cap.write(m03, "m03", 0);
2166         cap.write(m10, "m10", 0);
2167         cap.write(m11, "m11", 1);
2168         cap.write(m12, "m12", 0);
2169         cap.write(m13, "m13", 0);
2170         cap.write(m20, "m20", 0);
2171         cap.write(m21, "m21", 0);
2172         cap.write(m22, "m22", 1);
2173         cap.write(m23, "m23", 0);
2174         cap.write(m30, "m30", 0);
2175         cap.write(m31, "m31", 0);
2176         cap.write(m32, "m32", 0);
2177         cap.write(m33, "m33", 1);
2178     }
2179 
read(JmeImporter e)2180     public void read(JmeImporter e) throws IOException {
2181         InputCapsule cap = e.getCapsule(this);
2182         m00 = cap.readFloat("m00", 1);
2183         m01 = cap.readFloat("m01", 0);
2184         m02 = cap.readFloat("m02", 0);
2185         m03 = cap.readFloat("m03", 0);
2186         m10 = cap.readFloat("m10", 0);
2187         m11 = cap.readFloat("m11", 1);
2188         m12 = cap.readFloat("m12", 0);
2189         m13 = cap.readFloat("m13", 0);
2190         m20 = cap.readFloat("m20", 0);
2191         m21 = cap.readFloat("m21", 0);
2192         m22 = cap.readFloat("m22", 1);
2193         m23 = cap.readFloat("m23", 0);
2194         m30 = cap.readFloat("m30", 0);
2195         m31 = cap.readFloat("m31", 0);
2196         m32 = cap.readFloat("m32", 0);
2197         m33 = cap.readFloat("m33", 1);
2198     }
2199 
2200     /**
2201      * @return true if this matrix is identity
2202      */
isIdentity()2203     public boolean isIdentity() {
2204         return (m00 == 1 && m01 == 0 && m02 == 0 && m03 == 0)
2205                 && (m10 == 0 && m11 == 1 && m12 == 0 && m13 == 0)
2206                 && (m20 == 0 && m21 == 0 && m22 == 1 && m23 == 0)
2207                 && (m30 == 0 && m31 == 0 && m32 == 0 && m33 == 1);
2208     }
2209 
2210     /**
2211      * Apply a scale to this matrix.
2212      *
2213      * @param scale
2214      *            the scale to apply
2215      */
scale(Vector3f scale)2216     public void scale(Vector3f scale) {
2217         m00 *= scale.getX();
2218         m10 *= scale.getX();
2219         m20 *= scale.getX();
2220         m30 *= scale.getX();
2221         m01 *= scale.getY();
2222         m11 *= scale.getY();
2223         m21 *= scale.getY();
2224         m31 *= scale.getY();
2225         m02 *= scale.getZ();
2226         m12 *= scale.getZ();
2227         m22 *= scale.getZ();
2228         m32 *= scale.getZ();
2229     }
2230 
equalIdentity(Matrix4f mat)2231     static boolean equalIdentity(Matrix4f mat) {
2232         if (Math.abs(mat.m00 - 1) > 1e-4) {
2233             return false;
2234         }
2235         if (Math.abs(mat.m11 - 1) > 1e-4) {
2236             return false;
2237         }
2238         if (Math.abs(mat.m22 - 1) > 1e-4) {
2239             return false;
2240         }
2241         if (Math.abs(mat.m33 - 1) > 1e-4) {
2242             return false;
2243         }
2244 
2245         if (Math.abs(mat.m01) > 1e-4) {
2246             return false;
2247         }
2248         if (Math.abs(mat.m02) > 1e-4) {
2249             return false;
2250         }
2251         if (Math.abs(mat.m03) > 1e-4) {
2252             return false;
2253         }
2254 
2255         if (Math.abs(mat.m10) > 1e-4) {
2256             return false;
2257         }
2258         if (Math.abs(mat.m12) > 1e-4) {
2259             return false;
2260         }
2261         if (Math.abs(mat.m13) > 1e-4) {
2262             return false;
2263         }
2264 
2265         if (Math.abs(mat.m20) > 1e-4) {
2266             return false;
2267         }
2268         if (Math.abs(mat.m21) > 1e-4) {
2269             return false;
2270         }
2271         if (Math.abs(mat.m23) > 1e-4) {
2272             return false;
2273         }
2274 
2275         if (Math.abs(mat.m30) > 1e-4) {
2276             return false;
2277         }
2278         if (Math.abs(mat.m31) > 1e-4) {
2279             return false;
2280         }
2281         if (Math.abs(mat.m32) > 1e-4) {
2282             return false;
2283         }
2284 
2285         return true;
2286     }
2287 
2288     // XXX: This tests more solid than converting the q to a matrix and multiplying... why?
multLocal(Quaternion rotation)2289     public void multLocal(Quaternion rotation) {
2290         Vector3f axis = new Vector3f();
2291         float angle = rotation.toAngleAxis(axis);
2292         Matrix4f matrix4f = new Matrix4f();
2293         matrix4f.fromAngleAxis(angle, axis);
2294         multLocal(matrix4f);
2295     }
2296 
2297     @Override
clone()2298     public Matrix4f clone() {
2299         try {
2300             return (Matrix4f) super.clone();
2301         } catch (CloneNotSupportedException e) {
2302             throw new AssertionError(); // can not happen
2303         }
2304     }
2305 }
2306