Home | History | Annotate | Download | only in math
      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      */
     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