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      */
Matrix3f()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      */
Matrix3f(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)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      */
Matrix3f(Matrix3f mat)113     public Matrix3f(Matrix3f mat) {
114         set(mat);
115     }
116 
117     /**
118      * Takes the absolute value of all matrix fields locally.
119      */
absoluteLocal()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      */
set(Matrix3f matrix)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")
get(int i, int j)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      */
get(float[] data, boolean rowMajor)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      */
getColumn(int i)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      */
getColumn(int i, Vector3f store)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      */
getRow(int i)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      */
getRow(int i, Vector3f store)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      */
toFloatBuffer()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      */
fillFloatBuffer(FloatBuffer fb, boolean columnMajor)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 
fillFloatArray(float[] f, boolean columnMajor)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      */
setColumn(int i, Vector3f column)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      */
setRow(int i, Vector3f row)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")
set(int i, int j, float value)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      */
set(float[][] matrix)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      */
fromAxes(Vector3f uAxis, Vector3f vAxis, Vector3f wAxis)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      */
set(float[] matrix)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      */
set(float[] matrix, boolean rowMajor)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      */
set(Quaternion quaternion)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      */
loadIdentity()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      */
isIdentity()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      */
fromAngleAxis(float angle, Vector3f axis)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      */
fromAngleNormalAxis(float angle, Vector3f axis)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      */
mult(Matrix3f mat)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      */
mult(Matrix3f mat, Matrix3f product)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      */
mult(Vector3f vec)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      */
mult(Vector3f vec, Vector3f product)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      */
multLocal(float scale)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      */
multLocal(Vector3f vec)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      */
multLocal(Matrix3f mat)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      */
transposeLocal()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      */
invert()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      */
invert(Matrix3f store)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      */
invertLocal()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      */
adjoint()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      */
adjoint(Matrix3f store)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      */
determinant()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      */
zero()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      */
transpose()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      */
transposeNew()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
toString()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
hashCode()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
equals(Object o)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 
write(JmeExporter e)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 
read(JmeImporter e)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      */
fromStartEndVectors(Vector3f start, Vector3f end)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      */
scale(Vector3f scale)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 
equalIdentity(Matrix3f mat)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
clone()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