1/*
2 * Copyright (c) 2009-2010 jMonkeyEngine
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32package com.jme3.math;
33
34import com.jme3.export.*;
35import com.jme3.util.BufferUtils;
36import com.jme3.util.TempVars;
37import java.io.IOException;
38import java.nio.FloatBuffer;
39import java.util.logging.Logger;
40
41/**
42 * <code>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 */
50public 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 M�ller, 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