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>Matrix3f</code> defines a 3x3 matrix. Matrix data is maintained
     43  * internally and is accessible via the get and set methods. Convenience methods
     44  * are used for matrix operations as well as generating a matrix from a given
     45  * set of values.
     46  *
     47  * @author Mark Powell
     48  * @author Joshua Slack
     49  */
     50 public final class Matrix3f implements Savable, Cloneable, java.io.Serializable {
     51 
     52     static final long serialVersionUID = 1;
     53 
     54     private static final Logger logger = Logger.getLogger(Matrix3f.class.getName());
     55     protected float m00, m01, m02;
     56     protected float m10, m11, m12;
     57     protected float m20, m21, m22;
     58     public static final Matrix3f ZERO = new Matrix3f(0, 0, 0, 0, 0, 0, 0, 0, 0);
     59     public static final Matrix3f IDENTITY = new Matrix3f();
     60 
     61     /**
     62      * Constructor instantiates a new <code>Matrix3f</code> object. The
     63      * initial values for the matrix is that of the identity matrix.
     64      *
     65      */
     66     public Matrix3f() {
     67         loadIdentity();
     68     }
     69 
     70     /**
     71      * constructs a matrix with the given values.
     72      *
     73      * @param m00
     74      *            0x0 in the matrix.
     75      * @param m01
     76      *            0x1 in the matrix.
     77      * @param m02
     78      *            0x2 in the matrix.
     79      * @param m10
     80      *            1x0 in the matrix.
     81      * @param m11
     82      *            1x1 in the matrix.
     83      * @param m12
     84      *            1x2 in the matrix.
     85      * @param m20
     86      *            2x0 in the matrix.
     87      * @param m21
     88      *            2x1 in the matrix.
     89      * @param m22
     90      *            2x2 in the matrix.
     91      */
     92     public Matrix3f(float m00, float m01, float m02, float m10, float m11,
     93             float m12, float m20, float m21, float m22) {
     94 
     95         this.m00 = m00;
     96         this.m01 = m01;
     97         this.m02 = m02;
     98         this.m10 = m10;
     99         this.m11 = m11;
    100         this.m12 = m12;
    101         this.m20 = m20;
    102         this.m21 = m21;
    103         this.m22 = m22;
    104     }
    105 
    106     /**
    107      * Copy constructor that creates a new <code>Matrix3f</code> object that
    108      * is the same as the provided matrix.
    109      *
    110      * @param mat
    111      *            the matrix to copy.
    112      */
    113     public Matrix3f(Matrix3f mat) {
    114         set(mat);
    115     }
    116 
    117     /**
    118      * Takes the absolute value of all matrix fields locally.
    119      */
    120     public void absoluteLocal() {
    121         m00 = FastMath.abs(m00);
    122         m01 = FastMath.abs(m01);
    123         m02 = FastMath.abs(m02);
    124         m10 = FastMath.abs(m10);
    125         m11 = FastMath.abs(m11);
    126         m12 = FastMath.abs(m12);
    127         m20 = FastMath.abs(m20);
    128         m21 = FastMath.abs(m21);
    129         m22 = FastMath.abs(m22);
    130     }
    131 
    132     /**
    133      * <code>copy</code> transfers the contents of a given matrix to this
    134      * matrix. If a null matrix is supplied, this matrix is set to the identity
    135      * matrix.
    136      *
    137      * @param matrix
    138      *            the matrix to copy.
    139      * @return this
    140      */
    141     public Matrix3f set(Matrix3f matrix) {
    142         if (null == matrix) {
    143             loadIdentity();
    144         } else {
    145             m00 = matrix.m00;
    146             m01 = matrix.m01;
    147             m02 = matrix.m02;
    148             m10 = matrix.m10;
    149             m11 = matrix.m11;
    150             m12 = matrix.m12;
    151             m20 = matrix.m20;
    152             m21 = matrix.m21;
    153             m22 = matrix.m22;
    154         }
    155         return this;
    156     }
    157 
    158     /**
    159      * <code>get</code> retrieves a value from the matrix at the given
    160      * position. If the position is invalid a <code>JmeException</code> is
    161      * thrown.
    162      *
    163      * @param i
    164      *            the row index.
    165      * @param j
    166      *            the colum index.
    167      * @return the value at (i, j).
    168      */
    169     @SuppressWarnings("fallthrough")
    170     public float get(int i, int j) {
    171         switch (i) {
    172             case 0:
    173                 switch (j) {
    174                     case 0:
    175                         return m00;
    176                     case 1:
    177                         return m01;
    178                     case 2:
    179                         return m02;
    180                 }
    181             case 1:
    182                 switch (j) {
    183                     case 0:
    184                         return m10;
    185                     case 1:
    186                         return m11;
    187                     case 2:
    188                         return m12;
    189                 }
    190             case 2:
    191                 switch (j) {
    192                     case 0:
    193                         return m20;
    194                     case 1:
    195                         return m21;
    196                     case 2:
    197                         return m22;
    198                 }
    199         }
    200 
    201         logger.warning("Invalid matrix index.");
    202         throw new IllegalArgumentException("Invalid indices into matrix.");
    203     }
    204 
    205     /**
    206      * <code>get(float[])</code> returns the matrix in row-major or column-major order.
    207      *
    208      * @param data
    209      *      The array to return the data into. This array can be 9 or 16 floats in size.
    210      *      Only the upper 3x3 are assigned to in the case of a 16 element array.
    211      * @param rowMajor
    212      *      True for row major storage in the array (translation in elements 3, 7, 11 for a 4x4),
    213      *      false for column major (translation in elements 12, 13, 14 for a 4x4).
    214      */
    215     public void get(float[] data, boolean rowMajor) {
    216         if (data.length == 9) {
    217             if (rowMajor) {
    218                 data[0] = m00;
    219                 data[1] = m01;
    220                 data[2] = m02;
    221                 data[3] = m10;
    222                 data[4] = m11;
    223                 data[5] = m12;
    224                 data[6] = m20;
    225                 data[7] = m21;
    226                 data[8] = m22;
    227             } else {
    228                 data[0] = m00;
    229                 data[1] = m10;
    230                 data[2] = m20;
    231                 data[3] = m01;
    232                 data[4] = m11;
    233                 data[5] = m21;
    234                 data[6] = m02;
    235                 data[7] = m12;
    236                 data[8] = m22;
    237             }
    238         } else if (data.length == 16) {
    239             if (rowMajor) {
    240                 data[0] = m00;
    241                 data[1] = m01;
    242                 data[2] = m02;
    243                 data[4] = m10;
    244                 data[5] = m11;
    245                 data[6] = m12;
    246                 data[8] = m20;
    247                 data[9] = m21;
    248                 data[10] = m22;
    249             } else {
    250                 data[0] = m00;
    251                 data[1] = m10;
    252                 data[2] = m20;
    253                 data[4] = m01;
    254                 data[5] = m11;
    255                 data[6] = m21;
    256                 data[8] = m02;
    257                 data[9] = m12;
    258                 data[10] = m22;
    259             }
    260         } else {
    261             throw new IndexOutOfBoundsException("Array size must be 9 or 16 in Matrix3f.get().");
    262         }
    263     }
    264 
    265     /**
    266      * <code>getColumn</code> returns one of three columns specified by the
    267      * parameter. This column is returned as a <code>Vector3f</code> object.
    268      *
    269      * @param i
    270      *            the column to retrieve. Must be between 0 and 2.
    271      * @return the column specified by the index.
    272      */
    273     public Vector3f getColumn(int i) {
    274         return getColumn(i, null);
    275     }
    276 
    277     /**
    278      * <code>getColumn</code> returns one of three columns specified by the
    279      * parameter. This column is returned as a <code>Vector3f</code> object.
    280      *
    281      * @param i
    282      *            the column to retrieve. Must be between 0 and 2.
    283      * @param store
    284      *            the vector object to store the result in. if null, a new one
    285      *            is created.
    286      * @return the column specified by the index.
    287      */
    288     public Vector3f getColumn(int i, Vector3f store) {
    289         if (store == null) {
    290             store = new Vector3f();
    291         }
    292         switch (i) {
    293             case 0:
    294                 store.x = m00;
    295                 store.y = m10;
    296                 store.z = m20;
    297                 break;
    298             case 1:
    299                 store.x = m01;
    300                 store.y = m11;
    301                 store.z = m21;
    302                 break;
    303             case 2:
    304                 store.x = m02;
    305                 store.y = m12;
    306                 store.z = m22;
    307                 break;
    308             default:
    309                 logger.warning("Invalid column index.");
    310                 throw new IllegalArgumentException("Invalid column index. " + i);
    311         }
    312         return store;
    313     }
    314 
    315     /**
    316      * <code>getColumn</code> returns one of three rows as specified by the
    317      * parameter. This row is returned as a <code>Vector3f</code> object.
    318      *
    319      * @param i
    320      *            the row to retrieve. Must be between 0 and 2.
    321      * @return the row specified by the index.
    322      */
    323     public Vector3f getRow(int i) {
    324         return getRow(i, null);
    325     }
    326 
    327     /**
    328      * <code>getRow</code> returns one of three rows as specified by the
    329      * parameter. This row is returned as a <code>Vector3f</code> object.
    330      *
    331      * @param i
    332      *            the row to retrieve. Must be between 0 and 2.
    333      * @param store
    334      *            the vector object to store the result in. if null, a new one
    335      *            is created.
    336      * @return the row specified by the index.
    337      */
    338     public Vector3f getRow(int i, Vector3f store) {
    339         if (store == null) {
    340             store = new Vector3f();
    341         }
    342         switch (i) {
    343             case 0:
    344                 store.x = m00;
    345                 store.y = m01;
    346                 store.z = m02;
    347                 break;
    348             case 1:
    349                 store.x = m10;
    350                 store.y = m11;
    351                 store.z = m12;
    352                 break;
    353             case 2:
    354                 store.x = m20;
    355                 store.y = m21;
    356                 store.z = m22;
    357                 break;
    358             default:
    359                 logger.warning("Invalid row index.");
    360                 throw new IllegalArgumentException("Invalid row index. " + i);
    361         }
    362         return store;
    363     }
    364 
    365     /**
    366      * <code>toFloatBuffer</code> returns a FloatBuffer object that contains
    367      * the matrix data.
    368      *
    369      * @return matrix data as a FloatBuffer.
    370      */
    371     public FloatBuffer toFloatBuffer() {
    372         FloatBuffer fb = BufferUtils.createFloatBuffer(9);
    373 
    374         fb.put(m00).put(m01).put(m02);
    375         fb.put(m10).put(m11).put(m12);
    376         fb.put(m20).put(m21).put(m22);
    377         fb.rewind();
    378         return fb;
    379     }
    380 
    381     /**
    382      * <code>fillFloatBuffer</code> fills a FloatBuffer object with the matrix
    383      * data.
    384      *
    385      * @param fb
    386      *            the buffer to fill, starting at current position. Must have
    387      *            room for 9 more floats.
    388      * @return matrix data as a FloatBuffer. (position is advanced by 9 and any
    389      *         limit set is not changed).
    390      */
    391     public FloatBuffer fillFloatBuffer(FloatBuffer fb, boolean columnMajor) {
    392 //        if (columnMajor){
    393 //            fb.put(m00).put(m10).put(m20);
    394 //            fb.put(m01).put(m11).put(m21);
    395 //            fb.put(m02).put(m12).put(m22);
    396 //        }else{
    397 //            fb.put(m00).put(m01).put(m02);
    398 //            fb.put(m10).put(m11).put(m12);
    399 //            fb.put(m20).put(m21).put(m22);
    400 //        }
    401 
    402         TempVars vars = TempVars.get();
    403 
    404 
    405         fillFloatArray(vars.matrixWrite, columnMajor);
    406         fb.put(vars.matrixWrite, 0, 9);
    407 
    408         vars.release();
    409 
    410         return fb;
    411     }
    412 
    413     public void fillFloatArray(float[] f, boolean columnMajor) {
    414         if (columnMajor) {
    415             f[ 0] = m00;
    416             f[ 1] = m10;
    417             f[ 2] = m20;
    418             f[ 3] = m01;
    419             f[ 4] = m11;
    420             f[ 5] = m21;
    421             f[ 6] = m02;
    422             f[ 7] = m12;
    423             f[ 8] = m22;
    424         } else {
    425             f[ 0] = m00;
    426             f[ 1] = m01;
    427             f[ 2] = m02;
    428             f[ 3] = m10;
    429             f[ 4] = m11;
    430             f[ 5] = m12;
    431             f[ 6] = m20;
    432             f[ 7] = m21;
    433             f[ 8] = m22;
    434         }
    435     }
    436 
    437     /**
    438      *
    439      * <code>setColumn</code> sets a particular column of this matrix to that
    440      * represented by the provided vector.
    441      *
    442      * @param i
    443      *            the column to set.
    444      * @param column
    445      *            the data to set.
    446      * @return this
    447      */
    448     public Matrix3f setColumn(int i, Vector3f column) {
    449 
    450         if (column == null) {
    451             logger.warning("Column is null. Ignoring.");
    452             return this;
    453         }
    454         switch (i) {
    455             case 0:
    456                 m00 = column.x;
    457                 m10 = column.y;
    458                 m20 = column.z;
    459                 break;
    460             case 1:
    461                 m01 = column.x;
    462                 m11 = column.y;
    463                 m21 = column.z;
    464                 break;
    465             case 2:
    466                 m02 = column.x;
    467                 m12 = column.y;
    468                 m22 = column.z;
    469                 break;
    470             default:
    471                 logger.warning("Invalid column index.");
    472                 throw new IllegalArgumentException("Invalid column index. " + i);
    473         }
    474         return this;
    475     }
    476 
    477     /**
    478      *
    479      * <code>setRow</code> sets a particular row of this matrix to that
    480      * represented by the provided vector.
    481      *
    482      * @param i
    483      *            the row to set.
    484      * @param row
    485      *            the data to set.
    486      * @return this
    487      */
    488     public Matrix3f setRow(int i, Vector3f row) {
    489 
    490         if (row == null) {
    491             logger.warning("Row is null. Ignoring.");
    492             return this;
    493         }
    494         switch (i) {
    495             case 0:
    496                 m00 = row.x;
    497                 m01 = row.y;
    498                 m02 = row.z;
    499                 break;
    500             case 1:
    501                 m10 = row.x;
    502                 m11 = row.y;
    503                 m12 = row.z;
    504                 break;
    505             case 2:
    506                 m20 = row.x;
    507                 m21 = row.y;
    508                 m22 = row.z;
    509                 break;
    510             default:
    511                 logger.warning("Invalid row index.");
    512                 throw new IllegalArgumentException("Invalid row index. " + i);
    513         }
    514         return this;
    515     }
    516 
    517     /**
    518      * <code>set</code> places a given value into the matrix at the given
    519      * position. If the position is invalid a <code>JmeException</code> is
    520      * thrown.
    521      *
    522      * @param i
    523      *            the row index.
    524      * @param j
    525      *            the colum index.
    526      * @param value
    527      *            the value for (i, j).
    528      * @return this
    529      */
    530     @SuppressWarnings("fallthrough")
    531     public Matrix3f set(int i, int j, float value) {
    532         switch (i) {
    533             case 0:
    534                 switch (j) {
    535                     case 0:
    536                         m00 = value;
    537                         return this;
    538                     case 1:
    539                         m01 = value;
    540                         return this;
    541                     case 2:
    542                         m02 = value;
    543                         return this;
    544                 }
    545             case 1:
    546                 switch (j) {
    547                     case 0:
    548                         m10 = value;
    549                         return this;
    550                     case 1:
    551                         m11 = value;
    552                         return this;
    553                     case 2:
    554                         m12 = value;
    555                         return this;
    556                 }
    557             case 2:
    558                 switch (j) {
    559                     case 0:
    560                         m20 = value;
    561                         return this;
    562                     case 1:
    563                         m21 = value;
    564                         return this;
    565                     case 2:
    566                         m22 = value;
    567                         return this;
    568                 }
    569         }
    570 
    571         logger.warning("Invalid matrix index.");
    572         throw new IllegalArgumentException("Invalid indices into matrix.");
    573     }
    574 
    575     /**
    576      *
    577      * <code>set</code> sets the values of the matrix to those supplied by the
    578      * 3x3 two dimenion array.
    579      *
    580      * @param matrix
    581      *            the new values of the matrix.
    582      * @throws JmeException
    583      *             if the array is not of size 9.
    584      * @return this
    585      */
    586     public Matrix3f set(float[][] matrix) {
    587         if (matrix.length != 3 || matrix[0].length != 3) {
    588             throw new IllegalArgumentException(
    589                     "Array must be of size 9.");
    590         }
    591 
    592         m00 = matrix[0][0];
    593         m01 = matrix[0][1];
    594         m02 = matrix[0][2];
    595         m10 = matrix[1][0];
    596         m11 = matrix[1][1];
    597         m12 = matrix[1][2];
    598         m20 = matrix[2][0];
    599         m21 = matrix[2][1];
    600         m22 = matrix[2][2];
    601 
    602         return this;
    603     }
    604 
    605     /**
    606      * Recreate Matrix using the provided axis.
    607      *
    608      * @param uAxis
    609      *            Vector3f
    610      * @param vAxis
    611      *            Vector3f
    612      * @param wAxis
    613      *            Vector3f
    614      */
    615     public void fromAxes(Vector3f uAxis, Vector3f vAxis, Vector3f wAxis) {
    616         m00 = uAxis.x;
    617         m10 = uAxis.y;
    618         m20 = uAxis.z;
    619 
    620         m01 = vAxis.x;
    621         m11 = vAxis.y;
    622         m21 = vAxis.z;
    623 
    624         m02 = wAxis.x;
    625         m12 = wAxis.y;
    626         m22 = wAxis.z;
    627     }
    628 
    629     /**
    630      * <code>set</code> sets the values of this matrix from an array of
    631      * values assuming that the data is rowMajor order;
    632      *
    633      * @param matrix
    634      *            the matrix to set the value to.
    635      * @return this
    636      */
    637     public Matrix3f set(float[] matrix) {
    638         return set(matrix, true);
    639     }
    640 
    641     /**
    642      * <code>set</code> sets the values of this matrix from an array of
    643      * values;
    644      *
    645      * @param matrix
    646      *            the matrix to set the value to.
    647      * @param rowMajor
    648      *            whether the incoming data is in row or column major order.
    649      * @return this
    650      */
    651     public Matrix3f set(float[] matrix, boolean rowMajor) {
    652         if (matrix.length != 9) {
    653             throw new IllegalArgumentException(
    654                     "Array must be of size 9.");
    655         }
    656 
    657         if (rowMajor) {
    658             m00 = matrix[0];
    659             m01 = matrix[1];
    660             m02 = matrix[2];
    661             m10 = matrix[3];
    662             m11 = matrix[4];
    663             m12 = matrix[5];
    664             m20 = matrix[6];
    665             m21 = matrix[7];
    666             m22 = matrix[8];
    667         } else {
    668             m00 = matrix[0];
    669             m01 = matrix[3];
    670             m02 = matrix[6];
    671             m10 = matrix[1];
    672             m11 = matrix[4];
    673             m12 = matrix[7];
    674             m20 = matrix[2];
    675             m21 = matrix[5];
    676             m22 = matrix[8];
    677         }
    678         return this;
    679     }
    680 
    681     /**
    682      *
    683      * <code>set</code> defines the values of the matrix based on a supplied
    684      * <code>Quaternion</code>. It should be noted that all previous values
    685      * will be overridden.
    686      *
    687      * @param quaternion
    688      *            the quaternion to create a rotational matrix from.
    689      * @return this
    690      */
    691     public Matrix3f set(Quaternion quaternion) {
    692         return quaternion.toRotationMatrix(this);
    693     }
    694 
    695     /**
    696      * <code>loadIdentity</code> sets this matrix to the identity matrix.
    697      * Where all values are zero except those along the diagonal which are one.
    698      *
    699      */
    700     public void loadIdentity() {
    701         m01 = m02 = m10 = m12 = m20 = m21 = 0;
    702         m00 = m11 = m22 = 1;
    703     }
    704 
    705     /**
    706      * @return true if this matrix is identity
    707      */
    708     public boolean isIdentity() {
    709         return (m00 == 1 && m01 == 0 && m02 == 0)
    710                 && (m10 == 0 && m11 == 1 && m12 == 0)
    711                 && (m20 == 0 && m21 == 0 && m22 == 1);
    712     }
    713 
    714     /**
    715      * <code>fromAngleAxis</code> sets this matrix4f to the values specified
    716      * by an angle and an axis of rotation.  This method creates an object, so
    717      * use fromAngleNormalAxis if your axis is already normalized.
    718      *
    719      * @param angle
    720      *            the angle to rotate (in radians).
    721      * @param axis
    722      *            the axis of rotation.
    723      */
    724     public void fromAngleAxis(float angle, Vector3f axis) {
    725         Vector3f normAxis = axis.normalize();
    726         fromAngleNormalAxis(angle, normAxis);
    727     }
    728 
    729     /**
    730      * <code>fromAngleNormalAxis</code> sets this matrix4f to the values
    731      * specified by an angle and a normalized axis of rotation.
    732      *
    733      * @param angle
    734      *            the angle to rotate (in radians).
    735      * @param axis
    736      *            the axis of rotation (already normalized).
    737      */
    738     public void fromAngleNormalAxis(float angle, Vector3f axis) {
    739         float fCos = FastMath.cos(angle);
    740         float fSin = FastMath.sin(angle);
    741         float fOneMinusCos = ((float) 1.0) - fCos;
    742         float fX2 = axis.x * axis.x;
    743         float fY2 = axis.y * axis.y;
    744         float fZ2 = axis.z * axis.z;
    745         float fXYM = axis.x * axis.y * fOneMinusCos;
    746         float fXZM = axis.x * axis.z * fOneMinusCos;
    747         float fYZM = axis.y * axis.z * fOneMinusCos;
    748         float fXSin = axis.x * fSin;
    749         float fYSin = axis.y * fSin;
    750         float fZSin = axis.z * fSin;
    751 
    752         m00 = fX2 * fOneMinusCos + fCos;
    753         m01 = fXYM - fZSin;
    754         m02 = fXZM + fYSin;
    755         m10 = fXYM + fZSin;
    756         m11 = fY2 * fOneMinusCos + fCos;
    757         m12 = fYZM - fXSin;
    758         m20 = fXZM - fYSin;
    759         m21 = fYZM + fXSin;
    760         m22 = fZ2 * fOneMinusCos + fCos;
    761     }
    762 
    763     /**
    764      * <code>mult</code> multiplies this matrix by a given matrix. The result
    765      * matrix is returned as a new object. If the given matrix is null, a null
    766      * matrix is returned.
    767      *
    768      * @param mat
    769      *            the matrix to multiply this matrix by.
    770      * @return the result matrix.
    771      */
    772     public Matrix3f mult(Matrix3f mat) {
    773         return mult(mat, null);
    774     }
    775 
    776     /**
    777      * <code>mult</code> multiplies this matrix by a given matrix. The result
    778      * matrix is returned as a new object.
    779      *
    780      * @param mat
    781      *            the matrix to multiply this matrix by.
    782      * @param product
    783      *            the matrix to store the result in. if null, a new matrix3f is
    784      *            created.  It is safe for mat and product to be the same object.
    785      * @return a matrix3f object containing the result of this operation
    786      */
    787     public Matrix3f mult(Matrix3f mat, Matrix3f product) {
    788 
    789         float temp00, temp01, temp02;
    790         float temp10, temp11, temp12;
    791         float temp20, temp21, temp22;
    792 
    793         if (product == null) {
    794             product = new Matrix3f();
    795         }
    796         temp00 = m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20;
    797         temp01 = m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21;
    798         temp02 = m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22;
    799         temp10 = m10 * mat.m00 + m11 * mat.m10 + m12 * mat.m20;
    800         temp11 = m10 * mat.m01 + m11 * mat.m11 + m12 * mat.m21;
    801         temp12 = m10 * mat.m02 + m11 * mat.m12 + m12 * mat.m22;
    802         temp20 = m20 * mat.m00 + m21 * mat.m10 + m22 * mat.m20;
    803         temp21 = m20 * mat.m01 + m21 * mat.m11 + m22 * mat.m21;
    804         temp22 = m20 * mat.m02 + m21 * mat.m12 + m22 * mat.m22;
    805 
    806         product.m00 = temp00;
    807         product.m01 = temp01;
    808         product.m02 = temp02;
    809         product.m10 = temp10;
    810         product.m11 = temp11;
    811         product.m12 = temp12;
    812         product.m20 = temp20;
    813         product.m21 = temp21;
    814         product.m22 = temp22;
    815 
    816         return product;
    817     }
    818 
    819     /**
    820      * <code>mult</code> multiplies this matrix by a given
    821      * <code>Vector3f</code> object. The result vector is returned. If the
    822      * given vector is null, null will be returned.
    823      *
    824      * @param vec
    825      *            the vector to multiply this matrix by.
    826      * @return the result vector.
    827      */
    828     public Vector3f mult(Vector3f vec) {
    829         return mult(vec, null);
    830     }
    831 
    832     /**
    833      * Multiplies this 3x3 matrix by the 1x3 Vector vec and stores the result in
    834      * product.
    835      *
    836      * @param vec
    837      *            The Vector3f to multiply.
    838      * @param product
    839      *            The Vector3f to store the result, it is safe for this to be
    840      *            the same as vec.
    841      * @return The given product vector.
    842      */
    843     public Vector3f mult(Vector3f vec, Vector3f product) {
    844 
    845         if (null == product) {
    846             product = new Vector3f();
    847         }
    848 
    849         float x = vec.x;
    850         float y = vec.y;
    851         float z = vec.z;
    852 
    853         product.x = m00 * x + m01 * y + m02 * z;
    854         product.y = m10 * x + m11 * y + m12 * z;
    855         product.z = m20 * x + m21 * y + m22 * z;
    856         return product;
    857     }
    858 
    859     /**
    860      * <code>multLocal</code> multiplies this matrix internally by
    861      * a given float scale factor.
    862      *
    863      * @param scale
    864      *            the value to scale by.
    865      * @return this Matrix3f
    866      */
    867     public Matrix3f multLocal(float scale) {
    868         m00 *= scale;
    869         m01 *= scale;
    870         m02 *= scale;
    871         m10 *= scale;
    872         m11 *= scale;
    873         m12 *= scale;
    874         m20 *= scale;
    875         m21 *= scale;
    876         m22 *= scale;
    877         return this;
    878     }
    879 
    880     /**
    881      * <code>multLocal</code> multiplies this matrix by a given
    882      * <code>Vector3f</code> object. The result vector is stored inside the
    883      * passed vector, then returned . If the given vector is null, null will be
    884      * returned.
    885      *
    886      * @param vec
    887      *            the vector to multiply this matrix by.
    888      * @return The passed vector after multiplication
    889      */
    890     public Vector3f multLocal(Vector3f vec) {
    891         if (vec == null) {
    892             return null;
    893         }
    894         float x = vec.x;
    895         float y = vec.y;
    896         vec.x = m00 * x + m01 * y + m02 * vec.z;
    897         vec.y = m10 * x + m11 * y + m12 * vec.z;
    898         vec.z = m20 * x + m21 * y + m22 * vec.z;
    899         return vec;
    900     }
    901 
    902     /**
    903      * <code>mult</code> multiplies this matrix by a given matrix. The result
    904      * matrix is saved in the current matrix. If the given matrix is null,
    905      * nothing happens. The current matrix is returned. This is equivalent to
    906      * this*=mat
    907      *
    908      * @param mat
    909      *            the matrix to multiply this matrix by.
    910      * @return This matrix, after the multiplication
    911      */
    912     public Matrix3f multLocal(Matrix3f mat) {
    913         return mult(mat, this);
    914     }
    915 
    916     /**
    917      * Transposes this matrix in place. Returns this matrix for chaining
    918      *
    919      * @return This matrix after transpose
    920      */
    921     public Matrix3f transposeLocal() {
    922 //        float[] tmp = new float[9];
    923 //        get(tmp, false);
    924 //        set(tmp, true);
    925 
    926         float tmp = m01;
    927         m01 = m10;
    928         m10 = tmp;
    929 
    930         tmp = m02;
    931         m02 = m20;
    932         m20 = tmp;
    933 
    934         tmp = m12;
    935         m12 = m21;
    936         m21 = tmp;
    937 
    938         return this;
    939     }
    940 
    941     /**
    942      * Inverts this matrix as a new Matrix3f.
    943      *
    944      * @return The new inverse matrix
    945      */
    946     public Matrix3f invert() {
    947         return invert(null);
    948     }
    949 
    950     /**
    951      * Inverts this matrix and stores it in the given store.
    952      *
    953      * @return The store
    954      */
    955     public Matrix3f invert(Matrix3f store) {
    956         if (store == null) {
    957             store = new Matrix3f();
    958         }
    959 
    960         float det = determinant();
    961         if (FastMath.abs(det) <= FastMath.FLT_EPSILON) {
    962             return store.zero();
    963         }
    964 
    965         store.m00 = m11 * m22 - m12 * m21;
    966         store.m01 = m02 * m21 - m01 * m22;
    967         store.m02 = m01 * m12 - m02 * m11;
    968         store.m10 = m12 * m20 - m10 * m22;
    969         store.m11 = m00 * m22 - m02 * m20;
    970         store.m12 = m02 * m10 - m00 * m12;
    971         store.m20 = m10 * m21 - m11 * m20;
    972         store.m21 = m01 * m20 - m00 * m21;
    973         store.m22 = m00 * m11 - m01 * m10;
    974 
    975         store.multLocal(1f / det);
    976         return store;
    977     }
    978 
    979     /**
    980      * Inverts this matrix locally.
    981      *
    982      * @return this
    983      */
    984     public Matrix3f invertLocal() {
    985         float det = determinant();
    986         if (FastMath.abs(det) <= 0f) {
    987             return zero();
    988         }
    989 
    990         float f00 = m11 * m22 - m12 * m21;
    991         float f01 = m02 * m21 - m01 * m22;
    992         float f02 = m01 * m12 - m02 * m11;
    993         float f10 = m12 * m20 - m10 * m22;
    994         float f11 = m00 * m22 - m02 * m20;
    995         float f12 = m02 * m10 - m00 * m12;
    996         float f20 = m10 * m21 - m11 * m20;
    997         float f21 = m01 * m20 - m00 * m21;
    998         float f22 = m00 * m11 - m01 * m10;
    999 
   1000         m00 = f00;
   1001         m01 = f01;
   1002         m02 = f02;
   1003         m10 = f10;
   1004         m11 = f11;
   1005         m12 = f12;
   1006         m20 = f20;
   1007         m21 = f21;
   1008         m22 = f22;
   1009 
   1010         multLocal(1f / det);
   1011         return this;
   1012     }
   1013 
   1014     /**
   1015      * Returns a new matrix representing the adjoint of this matrix.
   1016      *
   1017      * @return The adjoint matrix
   1018      */
   1019     public Matrix3f adjoint() {
   1020         return adjoint(null);
   1021     }
   1022 
   1023     /**
   1024      * Places the adjoint of this matrix in store (creates store if null.)
   1025      *
   1026      * @param store
   1027      *            The matrix to store the result in.  If null, a new matrix is created.
   1028      * @return store
   1029      */
   1030     public Matrix3f adjoint(Matrix3f store) {
   1031         if (store == null) {
   1032             store = new Matrix3f();
   1033         }
   1034 
   1035         store.m00 = m11 * m22 - m12 * m21;
   1036         store.m01 = m02 * m21 - m01 * m22;
   1037         store.m02 = m01 * m12 - m02 * m11;
   1038         store.m10 = m12 * m20 - m10 * m22;
   1039         store.m11 = m00 * m22 - m02 * m20;
   1040         store.m12 = m02 * m10 - m00 * m12;
   1041         store.m20 = m10 * m21 - m11 * m20;
   1042         store.m21 = m01 * m20 - m00 * m21;
   1043         store.m22 = m00 * m11 - m01 * m10;
   1044 
   1045         return store;
   1046     }
   1047 
   1048     /**
   1049      * <code>determinant</code> generates the determinant of this matrix.
   1050      *
   1051      * @return the determinant
   1052      */
   1053     public float determinant() {
   1054         float fCo00 = m11 * m22 - m12 * m21;
   1055         float fCo10 = m12 * m20 - m10 * m22;
   1056         float fCo20 = m10 * m21 - m11 * m20;
   1057         float fDet = m00 * fCo00 + m01 * fCo10 + m02 * fCo20;
   1058         return fDet;
   1059     }
   1060 
   1061     /**
   1062      * Sets all of the values in this matrix to zero.
   1063      *
   1064      * @return this matrix
   1065      */
   1066     public Matrix3f zero() {
   1067         m00 = m01 = m02 = m10 = m11 = m12 = m20 = m21 = m22 = 0.0f;
   1068         return this;
   1069     }
   1070 
   1071     /**
   1072      * <code>transpose</code> <b>locally</b> transposes this Matrix.
   1073      * This is inconsistent with general value vs local semantics, but is
   1074      * preserved for backwards compatibility. Use transposeNew() to transpose
   1075      * to a new object (value).
   1076      *
   1077      * @return this object for chaining.
   1078      */
   1079     public Matrix3f transpose() {
   1080         return transposeLocal();
   1081     }
   1082 
   1083     /**
   1084      * <code>transposeNew</code> returns a transposed version of this matrix.
   1085      *
   1086      * @return The new Matrix3f object.
   1087      */
   1088     public Matrix3f transposeNew() {
   1089         Matrix3f ret = new Matrix3f(m00, m10, m20, m01, m11, m21, m02, m12, m22);
   1090         return ret;
   1091     }
   1092 
   1093     /**
   1094      * <code>toString</code> returns the string representation of this object.
   1095      * It is in a format of a 3x3 matrix. For example, an identity matrix would
   1096      * be represented by the following string. com.jme.math.Matrix3f <br>[<br>
   1097      * 1.0  0.0  0.0 <br>
   1098      * 0.0  1.0  0.0 <br>
   1099      * 0.0  0.0  1.0 <br>]<br>
   1100      *
   1101      * @return the string representation of this object.
   1102      */
   1103     @Override
   1104     public String toString() {
   1105         StringBuilder result = new StringBuilder("Matrix3f\n[\n");
   1106         result.append(" ");
   1107         result.append(m00);
   1108         result.append("  ");
   1109         result.append(m01);
   1110         result.append("  ");
   1111         result.append(m02);
   1112         result.append(" \n");
   1113         result.append(" ");
   1114         result.append(m10);
   1115         result.append("  ");
   1116         result.append(m11);
   1117         result.append("  ");
   1118         result.append(m12);
   1119         result.append(" \n");
   1120         result.append(" ");
   1121         result.append(m20);
   1122         result.append("  ");
   1123         result.append(m21);
   1124         result.append("  ");
   1125         result.append(m22);
   1126         result.append(" \n]");
   1127         return result.toString();
   1128     }
   1129 
   1130     /**
   1131      *
   1132      * <code>hashCode</code> returns the hash code value as an integer and is
   1133      * supported for the benefit of hashing based collection classes such as
   1134      * Hashtable, HashMap, HashSet etc.
   1135      *
   1136      * @return the hashcode for this instance of Matrix4f.
   1137      * @see java.lang.Object#hashCode()
   1138      */
   1139     @Override
   1140     public int hashCode() {
   1141         int hash = 37;
   1142         hash = 37 * hash + Float.floatToIntBits(m00);
   1143         hash = 37 * hash + Float.floatToIntBits(m01);
   1144         hash = 37 * hash + Float.floatToIntBits(m02);
   1145 
   1146         hash = 37 * hash + Float.floatToIntBits(m10);
   1147         hash = 37 * hash + Float.floatToIntBits(m11);
   1148         hash = 37 * hash + Float.floatToIntBits(m12);
   1149 
   1150         hash = 37 * hash + Float.floatToIntBits(m20);
   1151         hash = 37 * hash + Float.floatToIntBits(m21);
   1152         hash = 37 * hash + Float.floatToIntBits(m22);
   1153 
   1154         return hash;
   1155     }
   1156 
   1157     /**
   1158      * are these two matrices the same? they are is they both have the same mXX values.
   1159      *
   1160      * @param o
   1161      *            the object to compare for equality
   1162      * @return true if they are equal
   1163      */
   1164     @Override
   1165     public boolean equals(Object o) {
   1166         if (!(o instanceof Matrix3f) || o == null) {
   1167             return false;
   1168         }
   1169 
   1170         if (this == o) {
   1171             return true;
   1172         }
   1173 
   1174         Matrix3f comp = (Matrix3f) o;
   1175         if (Float.compare(m00, comp.m00) != 0) {
   1176             return false;
   1177         }
   1178         if (Float.compare(m01, comp.m01) != 0) {
   1179             return false;
   1180         }
   1181         if (Float.compare(m02, comp.m02) != 0) {
   1182             return false;
   1183         }
   1184 
   1185         if (Float.compare(m10, comp.m10) != 0) {
   1186             return false;
   1187         }
   1188         if (Float.compare(m11, comp.m11) != 0) {
   1189             return false;
   1190         }
   1191         if (Float.compare(m12, comp.m12) != 0) {
   1192             return false;
   1193         }
   1194 
   1195         if (Float.compare(m20, comp.m20) != 0) {
   1196             return false;
   1197         }
   1198         if (Float.compare(m21, comp.m21) != 0) {
   1199             return false;
   1200         }
   1201         if (Float.compare(m22, comp.m22) != 0) {
   1202             return false;
   1203         }
   1204 
   1205         return true;
   1206     }
   1207 
   1208     public void write(JmeExporter e) throws IOException {
   1209         OutputCapsule cap = e.getCapsule(this);
   1210         cap.write(m00, "m00", 1);
   1211         cap.write(m01, "m01", 0);
   1212         cap.write(m02, "m02", 0);
   1213         cap.write(m10, "m10", 0);
   1214         cap.write(m11, "m11", 1);
   1215         cap.write(m12, "m12", 0);
   1216         cap.write(m20, "m20", 0);
   1217         cap.write(m21, "m21", 0);
   1218         cap.write(m22, "m22", 1);
   1219     }
   1220 
   1221     public void read(JmeImporter e) throws IOException {
   1222         InputCapsule cap = e.getCapsule(this);
   1223         m00 = cap.readFloat("m00", 1);
   1224         m01 = cap.readFloat("m01", 0);
   1225         m02 = cap.readFloat("m02", 0);
   1226         m10 = cap.readFloat("m10", 0);
   1227         m11 = cap.readFloat("m11", 1);
   1228         m12 = cap.readFloat("m12", 0);
   1229         m20 = cap.readFloat("m20", 0);
   1230         m21 = cap.readFloat("m21", 0);
   1231         m22 = cap.readFloat("m22", 1);
   1232     }
   1233 
   1234     /**
   1235      * A function for creating a rotation matrix that rotates a vector called
   1236      * "start" into another vector called "end".
   1237      *
   1238      * @param start
   1239      *            normalized non-zero starting vector
   1240      * @param end
   1241      *            normalized non-zero ending vector
   1242      * @see "Tomas Mller, John Hughes \"Efficiently Building a Matrix to Rotate \
   1243      *      One Vector to Another\" Journal of Graphics Tools, 4(4):1-4, 1999"
   1244      */
   1245     public void fromStartEndVectors(Vector3f start, Vector3f end) {
   1246         Vector3f v = new Vector3f();
   1247         float e, h, f;
   1248 
   1249         start.cross(end, v);
   1250         e = start.dot(end);
   1251         f = (e < 0) ? -e : e;
   1252 
   1253         // if "from" and "to" vectors are nearly parallel
   1254         if (f > 1.0f - FastMath.ZERO_TOLERANCE) {
   1255             Vector3f u = new Vector3f();
   1256             Vector3f x = new Vector3f();
   1257             float c1, c2, c3; /* coefficients for later use */
   1258             int i, j;
   1259 
   1260             x.x = (start.x > 0.0) ? start.x : -start.x;
   1261             x.y = (start.y > 0.0) ? start.y : -start.y;
   1262             x.z = (start.z > 0.0) ? start.z : -start.z;
   1263 
   1264             if (x.x < x.y) {
   1265                 if (x.x < x.z) {
   1266                     x.x = 1.0f;
   1267                     x.y = x.z = 0.0f;
   1268                 } else {
   1269                     x.z = 1.0f;
   1270                     x.x = x.y = 0.0f;
   1271                 }
   1272             } else {
   1273                 if (x.y < x.z) {
   1274                     x.y = 1.0f;
   1275                     x.x = x.z = 0.0f;
   1276                 } else {
   1277                     x.z = 1.0f;
   1278                     x.x = x.y = 0.0f;
   1279                 }
   1280             }
   1281 
   1282             u.x = x.x - start.x;
   1283             u.y = x.y - start.y;
   1284             u.z = x.z - start.z;
   1285             v.x = x.x - end.x;
   1286             v.y = x.y - end.y;
   1287             v.z = x.z - end.z;
   1288 
   1289             c1 = 2.0f / u.dot(u);
   1290             c2 = 2.0f / v.dot(v);
   1291             c3 = c1 * c2 * u.dot(v);
   1292 
   1293             for (i = 0; i < 3; i++) {
   1294                 for (j = 0; j < 3; j++) {
   1295                     float val = -c1 * u.get(i) * u.get(j) - c2 * v.get(i)
   1296                             * v.get(j) + c3 * v.get(i) * u.get(j);
   1297                     set(i, j, val);
   1298                 }
   1299                 float val = get(i, i);
   1300                 set(i, i, val + 1.0f);
   1301             }
   1302         } else {
   1303             // the most common case, unless "start"="end", or "start"=-"end"
   1304             float hvx, hvz, hvxy, hvxz, hvyz;
   1305             h = 1.0f / (1.0f + e);
   1306             hvx = h * v.x;
   1307             hvz = h * v.z;
   1308             hvxy = hvx * v.y;
   1309             hvxz = hvx * v.z;
   1310             hvyz = hvz * v.y;
   1311             set(0, 0, e + hvx * v.x);
   1312             set(0, 1, hvxy - v.z);
   1313             set(0, 2, hvxz + v.y);
   1314 
   1315             set(1, 0, hvxy + v.z);
   1316             set(1, 1, e + h * v.y * v.y);
   1317             set(1, 2, hvyz - v.x);
   1318 
   1319             set(2, 0, hvxz - v.y);
   1320             set(2, 1, hvyz + v.x);
   1321             set(2, 2, e + hvz * v.z);
   1322         }
   1323     }
   1324 
   1325     /**
   1326      * <code>scale</code> scales the operation performed by this matrix on a
   1327      * per-component basis.
   1328      *
   1329      * @param scale
   1330      *         The scale applied to each of the X, Y and Z output values.
   1331      */
   1332     public void scale(Vector3f scale) {
   1333         m00 *= scale.x;
   1334         m10 *= scale.x;
   1335         m20 *= scale.x;
   1336         m01 *= scale.y;
   1337         m11 *= scale.y;
   1338         m21 *= scale.y;
   1339         m02 *= scale.z;
   1340         m12 *= scale.z;
   1341         m22 *= scale.z;
   1342     }
   1343 
   1344     static boolean equalIdentity(Matrix3f mat) {
   1345         if (Math.abs(mat.m00 - 1) > 1e-4) {
   1346             return false;
   1347         }
   1348         if (Math.abs(mat.m11 - 1) > 1e-4) {
   1349             return false;
   1350         }
   1351         if (Math.abs(mat.m22 - 1) > 1e-4) {
   1352             return false;
   1353         }
   1354 
   1355         if (Math.abs(mat.m01) > 1e-4) {
   1356             return false;
   1357         }
   1358         if (Math.abs(mat.m02) > 1e-4) {
   1359             return false;
   1360         }
   1361 
   1362         if (Math.abs(mat.m10) > 1e-4) {
   1363             return false;
   1364         }
   1365         if (Math.abs(mat.m12) > 1e-4) {
   1366             return false;
   1367         }
   1368 
   1369         if (Math.abs(mat.m20) > 1e-4) {
   1370             return false;
   1371         }
   1372         if (Math.abs(mat.m21) > 1e-4) {
   1373             return false;
   1374         }
   1375 
   1376         return true;
   1377     }
   1378 
   1379     @Override
   1380     public Matrix3f clone() {
   1381         try {
   1382             return (Matrix3f) super.clone();
   1383         } catch (CloneNotSupportedException e) {
   1384             throw new AssertionError(); // can not happen
   1385         }
   1386     }
   1387 }
   1388