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 */
32package com.jme3.math;
33
34import com.jme3.export.*;
35import com.jme3.util.BufferUtils;
36import com.jme3.util.TempVars;
37import java.io.IOException;
38import java.nio.FloatBuffer;
39import 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 */
56public 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     */
73    public Matrix4f() {
74        loadIdentity();
75    }
76
77    /**
78     * constructs a matrix with the given values.
79     */
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     */
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     */
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     */
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
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     */
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     */
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")
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     */
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     */
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     */
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")
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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
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     */
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     */
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     */
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
975    public Matrix4f mult(float scalar) {
976        Matrix4f out = new Matrix4f();
977        out.set(this);
978        out.multLocal(scalar);
979        return out;
980    }
981
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
1543    public Matrix4f adjoint() {
1544        return adjoint(null);
1545    }
1546
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     */
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     */
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     */
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
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     */
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
1700    public Vector3f toTranslationVector() {
1701        return new Vector3f(m03, m13, m23);
1702    }
1703
1704    public void toTranslationVector(Vector3f vector) {
1705        vector.set(m03, m13, m23);
1706    }
1707
1708    public Quaternion toRotationQuat() {
1709        Quaternion quat = new Quaternion();
1710        quat.fromRotationMatrix(toRotationMatrix());
1711        return quat;
1712    }
1713
1714    public void toRotationQuat(Quaternion q) {
1715        q.fromRotationMatrix(toRotationMatrix());
1716    }
1717
1718    public Matrix3f toRotationMatrix() {
1719        return new Matrix3f(m00, m01, m02, m10, m11, m12, m20, m21, m22);
1720
1721    }
1722
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
1736    public void setScale(float x, float y, float z) {
1737        m00 *= x;
1738        m11 *= y;
1739        m22 *= z;
1740    }
1741
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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
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
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
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
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
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     */
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     */
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
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?
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
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