OSDN Git Service

e4c5adbfabf647c1c119e970bc4d1a42eb3bc971
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / math / Matrix4f.java
1 /*
2  * Copyright (c) 2003-2009 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
33 package com.jme.math;
34
35 import java.io.IOException;
36 import java.io.Serializable;
37 import java.nio.FloatBuffer;
38 import java.util.logging.Logger;
39
40 import com.jme.system.JmeException;
41 import com.jme.util.export.InputCapsule;
42 import com.jme.util.export.JMEExporter;
43 import com.jme.util.export.JMEImporter;
44 import com.jme.util.export.OutputCapsule;
45 import com.jme.util.export.Savable;
46 import com.jme.util.geom.BufferUtils;
47
48 /**
49  * <code>Matrix4f</code> defines and maintains a 4x4 matrix in row major order.
50  * This matrix is intended for use in a translation and rotational capacity. 
51  * It provides convenience methods for creating the matrix from a multitude 
52  * of sources.
53  * 
54  * Matrices are stored assuming column vectors on the right, with the translation
55  * in the rightmost column. Element numbering is row,column, so m03 is the zeroth
56  * row, third column, which is the "x" translation part. This means that the implicit
57  * storage order is column major. However, the get() and set() functions on float
58  * arrays default to row major order!
59  *
60  * @author Mark Powell
61  * @author Joshua Slack
62  */
63 public class Matrix4f  implements Serializable, Savable, Cloneable {
64     private static final Logger logger = Logger.getLogger(Matrix4f.class.getName());
65
66     private static final long serialVersionUID = 1L;
67
68     public float m00, m01, m02, m03;
69
70     public float m10, m11, m12, m13;
71
72     public float m20, m21, m22, m23;
73
74     public float m30, m31, m32, m33;
75
76     /**
77      * Constructor instantiates a new <code>Matrix</code> that is set to the
78      * identity matrix.
79      *  
80      */
81     public Matrix4f() {
82         loadIdentity();
83     }
84
85     /**
86      * constructs a matrix with the given values.
87      */
88     public Matrix4f(float m00, float m01, float m02, float m03, 
89             float m10, float m11, float m12, float m13,
90             float m20, float m21, float m22, float m23,
91             float m30, float m31, float m32, float m33) {
92
93         this.m00 = m00;
94         this.m01 = m01;
95         this.m02 = m02;
96         this.m03 = m03;
97         this.m10 = m10;
98         this.m11 = m11;
99         this.m12 = m12;
100         this.m13 = m13;
101         this.m20 = m20;
102         this.m21 = m21;
103         this.m22 = m22;
104         this.m23 = m23;
105         this.m30 = m30;
106         this.m31 = m31;
107         this.m32 = m32;
108         this.m33 = m33;
109     }
110
111     /**
112      * Create a new Matrix4f, given data in column-major format.
113      *
114      * @param array
115          *              An array of 16 floats in column-major format (translation in elements 12, 13 and 14).
116      */
117     public Matrix4f(float[] array) {
118         set(array, false);
119     }
120
121     /**
122      * Constructor instantiates a new <code>Matrix</code> that is set to the
123      * provided matrix. This constructor copies a given Matrix. If the provided
124      * matrix is null, the constructor sets the matrix to the identity.
125      * 
126      * @param mat
127      *            the matrix to copy.
128      */
129     public Matrix4f(Matrix4f mat) {
130         copy(mat);
131     }
132
133     /**
134      * <code>copy</code> transfers the contents of a given matrix to this
135      * matrix. If a null matrix is supplied, this matrix is set to the identity
136      * matrix.
137      * 
138      * @param matrix
139      *            the matrix to copy.
140      */
141     public void copy(Matrix4f matrix) {
142         if (null == matrix) {
143             loadIdentity();
144         } else {
145             m00 = matrix.m00;
146             m01 = matrix.m01;
147             m02 = matrix.m02;
148             m03 = matrix.m03;
149             m10 = matrix.m10;
150             m11 = matrix.m11;
151             m12 = matrix.m12;
152             m13 = matrix.m13;
153             m20 = matrix.m20;
154             m21 = matrix.m21;
155             m22 = matrix.m22;
156             m23 = matrix.m23;
157             m30 = matrix.m30;
158             m31 = matrix.m31;
159             m32 = matrix.m32;
160             m33 = matrix.m33;
161         }
162     }
163
164     /**
165      * <code>get</code> retrieves the values of this object into
166      * a float array in row-major order.
167      * 
168      * @param matrix
169      *            the matrix to set the values into.
170      */
171     public void get(float[] matrix) {
172         get(matrix, true);
173     }
174
175     /**
176      * <code>set</code> retrieves the values of this object into
177      * a float array.
178      * 
179      * @param matrix
180      *            the matrix to set the values into.
181      * @param rowMajor
182      *            whether the outgoing data is in row or column major order.
183      */
184     public void get(float[] matrix, boolean rowMajor) {
185         if (matrix.length != 16) throw new JmeException(
186                 "Array must be of size 16.");
187
188         if (rowMajor) {
189             matrix[0] = m00;
190             matrix[1] = m01;
191             matrix[2] = m02;
192             matrix[3] = m03;
193             matrix[4] = m10;
194             matrix[5] = m11;
195             matrix[6] = m12;
196             matrix[7] = m13;
197             matrix[8] = m20;
198             matrix[9] = m21;
199             matrix[10] = m22;
200             matrix[11] = m23;
201             matrix[12] = m30;
202             matrix[13] = m31;
203             matrix[14] = m32;
204             matrix[15] = m33;
205         } else {
206             matrix[0] = m00;
207             matrix[4] = m01;
208             matrix[8] = m02;
209             matrix[12] = m03;
210             matrix[1] = m10;
211             matrix[5] = m11;
212             matrix[9] = m12;
213             matrix[13] = m13;
214             matrix[2] = m20;
215             matrix[6] = m21;
216             matrix[10] = m22;
217             matrix[14] = m23;
218             matrix[3] = m30;
219             matrix[7] = m31;
220             matrix[11] = m32;
221             matrix[15] = m33;
222         }
223     }
224
225     /**
226      * <code>get</code> retrieves a value from the matrix at the given
227      * position. If the position is invalid a <code>JmeException</code> is
228      * thrown.
229      * 
230      * @param i
231      *            the row index.
232      * @param j
233      *            the colum index.
234      * @return the value at (i, j).
235      */
236     public float get(int i, int j) {
237         switch (i) {
238         case 0:
239             switch (j) {
240             case 0: return m00;
241             case 1: return m01;
242             case 2: return m02;
243             case 3: return m03;
244             }
245         case 1:
246             switch (j) {
247             case 0: return m10;
248             case 1: return m11;
249             case 2: return m12;
250             case 3: return m13;
251             }
252         case 2:
253             switch (j) {
254             case 0: return m20;
255             case 1: return m21;
256             case 2: return m22;
257             case 3: return m23;
258             }
259         case 3:
260             switch (j) {
261             case 0: return m30;
262             case 1: return m31;
263             case 2: return m32;
264             case 3: return m33;
265             }
266         }
267
268         logger.warning("Invalid matrix index.");
269         throw new JmeException("Invalid indices into matrix.");
270     }
271
272     /**
273      * <code>getColumn</code> returns one of three columns specified by the
274      * parameter. This column is returned as a float array of length 4.
275      * 
276      * @param i
277      *            the column to retrieve. Must be between 0 and 3.
278      * @return the column specified by the index.
279      */
280     public float[] getColumn(int i) {
281         return getColumn(i, null);
282     }
283
284     /**
285      * <code>getColumn</code> returns one of three columns specified by the
286      * parameter. This column is returned as a float[4].
287      * 
288      * @param i
289      *            the column to retrieve. Must be between 0 and 3.
290      * @param store
291      *            the float array to store the result in. if null, a new one
292      *            is created.
293      * @return the column specified by the index.
294      */
295     public float[] getColumn(int i, float[] store) {
296         if (store == null) store = new float[4];
297         switch (i) {
298         case 0:
299             store[0] = m00;
300             store[1] = m10;
301             store[2] = m20;
302             store[3] = m30;
303             break;
304         case 1:
305             store[0] = m01;
306             store[1] = m11;
307             store[2] = m21;
308             store[3] = m31;
309             break;
310         case 2:
311             store[0] = m02;
312             store[1] = m12;
313             store[2] = m22;
314             store[3] = m32;
315             break;
316         case 3:
317             store[0] = m03;
318             store[1] = m13;
319             store[2] = m23;
320             store[3] = m33;
321             break;
322         default:
323             logger.warning("Invalid column index.");
324             throw new JmeException("Invalid column index. " + i);
325         }
326         return store;
327     }
328
329     /**
330      * 
331      * <code>setColumn</code> sets a particular column of this matrix to that
332      * represented by the provided vector.
333      * 
334      * @param i
335      *            the column to set.
336      * @param column
337      *            the data to set.
338      */
339     public void setColumn(int i, float[] column) {
340
341         if (column == null) {
342             logger.warning("Column is null. Ignoring.");
343             return;
344         }
345         switch (i) {
346         case 0:
347             m00 = column[0];
348             m10 = column[1];
349             m20 = column[2];
350             m30 = column[3];
351             break;
352         case 1:
353             m01 = column[0];
354             m11 = column[1];
355             m21 = column[2];
356             m31 = column[3];
357             break;
358         case 2:
359             m02 = column[0];
360             m12 = column[1];
361             m22 = column[2];
362             m32 = column[3];
363             break;
364         case 3:
365             m03 = column[0];
366             m13 = column[1];
367             m23 = column[2];
368             m33 = column[3];
369             break;
370         default:
371             logger.warning("Invalid column index.");
372             throw new JmeException("Invalid column index. " + i);
373         }    }
374
375     /**
376      * <code>set</code> places a given value into the matrix at the given
377      * position. If the position is invalid a <code>JmeException</code> is
378      * thrown.
379      * 
380      * @param i
381      *            the row index.
382      * @param j
383      *            the colum index.
384      * @param value
385      *            the value for (i, j).
386      */
387     public void set(int i, int j, float value) {
388         switch (i) {
389         case 0:
390             switch (j) {
391             case 0: m00 = value; return;
392             case 1: m01 = value; return;
393             case 2: m02 = value; return;
394             case 3: m03 = value; return;
395             }
396         case 1:
397             switch (j) {
398             case 0: m10 = value; return;
399             case 1: m11 = value; return;
400             case 2: m12 = value; return;
401             case 3: m13 = value; return;
402             }
403         case 2:
404             switch (j) {
405             case 0: m20 = value; return;
406             case 1: m21 = value; return;
407             case 2: m22 = value; return;
408             case 3: m23 = value; return;
409             }
410         case 3:
411             switch (j) {
412             case 0: m30 = value; return;
413             case 1: m31 = value; return;
414             case 2: m32 = value; return;
415             case 3: m33 = value; return;
416             }
417         }
418
419         logger.warning("Invalid matrix index.");
420         throw new JmeException("Invalid indices into matrix.");
421     }
422
423     /**
424      * <code>set</code> sets the values of this matrix from an array of
425      * values.
426      * 
427      * @param matrix
428      *            the matrix to set the value to.
429      * @throws JmeException
430      *             if the array is not of size 16.
431      */
432     public void set(float[][] matrix) {
433         if (matrix.length != 4 || matrix[0].length != 4) { throw new JmeException(
434                 "Array must be of size 16."); }
435
436         m00 = matrix[0][0];
437         m01 = matrix[0][1];
438         m02 = matrix[0][2];
439         m03 = matrix[0][3];
440         m10 = matrix[1][0];
441         m11 = matrix[1][1];
442         m12 = matrix[1][2];
443         m13 = matrix[1][3];
444         m20 = matrix[2][0];
445         m21 = matrix[2][1];
446         m22 = matrix[2][2];
447         m23 = matrix[2][3];
448         m30 = matrix[3][0];
449         m31 = matrix[3][1];
450         m32 = matrix[3][2];
451         m33 = matrix[3][3];
452     }
453
454     /**
455      * <code>set</code> sets the values of this matrix from another matrix.
456      *
457      * @param matrix
458      *            the matrix to read the value from.
459      */
460     public Matrix4f set(Matrix4f matrix) {
461         m00 = matrix.m00; m01 = matrix.m01; m02 = matrix.m02; m03 = matrix.m03;
462         m10 = matrix.m10; m11 = matrix.m11; m12 = matrix.m12; m13 = matrix.m13;
463         m20 = matrix.m20; m21 = matrix.m21; m22 = matrix.m22; m23 = matrix.m23;
464         m30 = matrix.m30; m31 = matrix.m31; m32 = matrix.m32; m33 = matrix.m33;
465         return this;
466     }
467
468     /**
469      * <code>set</code> sets the values of this matrix from an array of
470      * values assuming that the data is rowMajor order;
471      * 
472      * @param matrix
473      *            the matrix to set the value to.
474      */
475     public void set(float[] matrix) {
476         set(matrix, true);
477     }
478
479     /**
480      * <code>set</code> sets the values of this matrix from an array of
481      * values;
482      * 
483      * @param matrix
484      *            the matrix to set the value to.
485      * @param rowMajor
486      *            whether the incoming data is in row or column major order.
487      */
488     public void set(float[] matrix, boolean rowMajor) {
489         if (matrix.length != 16) throw new JmeException(
490                 "Array must be of size 16.");
491
492         if (rowMajor) {
493             m00 = matrix[0];
494             m01 = matrix[1];
495             m02 = matrix[2];
496             m03 = matrix[3];
497             m10 = matrix[4];
498             m11 = matrix[5];
499             m12 = matrix[6];
500             m13 = matrix[7];
501             m20 = matrix[8];
502             m21 = matrix[9];
503             m22 = matrix[10];
504             m23 = matrix[11];
505             m30 = matrix[12];
506             m31 = matrix[13];
507             m32 = matrix[14];
508             m33 = matrix[15];
509         } else {
510             m00 = matrix[0];
511             m01 = matrix[4];
512             m02 = matrix[8];
513             m03 = matrix[12];
514             m10 = matrix[1];
515             m11 = matrix[5];
516             m12 = matrix[9];
517             m13 = matrix[13];
518             m20 = matrix[2];
519             m21 = matrix[6];
520             m22 = matrix[10];
521             m23 = matrix[14];
522             m30 = matrix[3];
523             m31 = matrix[7];
524             m32 = matrix[11];
525             m33 = matrix[15];
526         }
527     }
528
529     public Matrix4f transpose() {
530         float[] tmp = new float[16];
531         get(tmp, true);
532         Matrix4f mat = new Matrix4f(tmp);
533         return mat;
534     }
535
536     /**
537      * <code>transpose</code> locally transposes this Matrix.
538      * 
539      * @return this object for chaining.
540      */
541     public Matrix4f transposeLocal() {
542         float[] tmp = new float[16];
543         get(tmp, true);
544         set(tmp, false);
545         return this;
546     }
547     
548     
549     /**
550      * <code>toFloatBuffer</code> returns a FloatBuffer object that contains
551      * the matrix data.
552      * 
553      * @return matrix data as a FloatBuffer.
554      */
555     public FloatBuffer toFloatBuffer() {
556         return toFloatBuffer(false);
557     }
558
559     /**
560      * <code>toFloatBuffer</code> returns a FloatBuffer object that contains the
561      * matrix data.
562      * 
563      * @param columnMajor
564      *            if true, this buffer should be filled with column major data,
565      *            otherwise it will be filled row major.
566      * @return matrix data as a FloatBuffer. The position is set to 0 for
567      *         convenience.
568      */
569     public FloatBuffer toFloatBuffer(boolean columnMajor) {
570         FloatBuffer fb = BufferUtils.createFloatBuffer(16);
571         fillFloatBuffer(fb, columnMajor);
572         fb.rewind();
573         return fb;
574     }
575     
576     /**
577      * <code>fillFloatBuffer</code> fills a FloatBuffer object with
578      * the matrix data.
579      * @param fb the buffer to fill, must be correct size
580      * @return matrix data as a FloatBuffer.
581      */
582     public FloatBuffer fillFloatBuffer(FloatBuffer fb) {
583         return fillFloatBuffer(fb, false);
584     }
585
586     /**
587      * <code>fillFloatBuffer</code> fills a FloatBuffer object with the matrix
588      * data.
589      * 
590      * @param fb
591      *            the buffer to fill, starting at current position. Must have
592      *            room for 16 more floats.
593      * @param columnMajor
594      *            if true, this buffer should be filled with column major data,
595      *            otherwise it will be filled row major.
596      * @return matrix data as a FloatBuffer. (position is advanced by 16 and any
597      *         limit set is not changed).
598      */
599     public FloatBuffer fillFloatBuffer(FloatBuffer fb, boolean columnMajor) {
600         if(columnMajor) {
601             fb.put(m00).put(m10).put(m20).put(m30);
602                 fb.put(m01).put(m11).put(m21).put(m31);
603                 fb.put(m02).put(m12).put(m22).put(m32);
604                 fb.put(m03).put(m13).put(m23).put(m33);
605             } else {
606                 fb.put(m00).put(m01).put(m02).put(m03);
607                 fb.put(m10).put(m11).put(m12).put(m13);
608                 fb.put(m20).put(m21).put(m22).put(m23);
609                 fb.put(m30).put(m31).put(m32).put(m33);
610             }
611         return fb;
612     }
613     
614     /**
615      * <code>readFloatBuffer</code> reads value for this matrix from a FloatBuffer.
616      * @param fb the buffer to read from, must be correct size
617      * @return this data as a FloatBuffer.
618      */
619     public Matrix4f readFloatBuffer(FloatBuffer fb) {
620         return readFloatBuffer(fb, false);
621     }
622
623     /**
624      * <code>readFloatBuffer</code> reads value for this matrix from a FloatBuffer.
625      * @param fb the buffer to read from, must be correct size
626      * @param columnMajor if true, this buffer should be filled with column
627      *          major data, otherwise it will be filled row major.
628      * @return this data as a FloatBuffer.
629      */
630     public Matrix4f readFloatBuffer(FloatBuffer fb, boolean columnMajor) {
631         
632         if(columnMajor) {
633                 m00 = fb.get(); m10 = fb.get(); m20 = fb.get(); m30 = fb.get();
634                 m01 = fb.get(); m11 = fb.get(); m21 = fb.get(); m31 = fb.get();
635                 m02 = fb.get(); m12 = fb.get(); m22 = fb.get(); m32 = fb.get();
636                 m03 = fb.get(); m13 = fb.get(); m23 = fb.get(); m33 = fb.get();
637         } else {
638                 m00 = fb.get(); m01 = fb.get(); m02 = fb.get(); m03 = fb.get();
639                 m10 = fb.get(); m11 = fb.get(); m12 = fb.get(); m13 = fb.get();
640                 m20 = fb.get(); m21 = fb.get(); m22 = fb.get(); m23 = fb.get();
641                 m30 = fb.get(); m31 = fb.get(); m32 = fb.get(); m33 = fb.get();
642         }
643         return this;
644     }
645
646     /**
647      * <code>loadIdentity</code> sets this matrix to the identity matrix,
648      * namely all zeros with ones along the diagonal.
649      *  
650      */
651     public void loadIdentity() {
652         m01 = m02 = m03 = 0.0f;
653         m10 = m12 = m13 = 0.0f;
654         m20 = m21 = m23 = 0.0f;
655         m30 = m31 = m32 = 0.0f;
656         m00 = m11 = m22 = m33 = 1.0f;
657     }
658
659     /**
660      * <code>fromAngleAxis</code> sets this matrix4f to the values specified
661      * by an angle and an axis of rotation.  This method creates an object, so
662      * use fromAngleNormalAxis if your axis is already normalized.
663      * 
664      * @param angle
665      *            the angle to rotate (in radians).
666      * @param axis
667      *            the axis of rotation.
668      */
669     public void fromAngleAxis(float angle, Vector3f axis) {
670         Vector3f normAxis = axis.normalize();
671         fromAngleNormalAxis(angle, normAxis);
672     }
673
674     /**
675      * <code>fromAngleNormalAxis</code> sets this matrix4f to the values
676      * specified by an angle and a normalized axis of rotation.
677      * 
678      * @param angle
679      *            the angle to rotate (in radians).
680      * @param axis
681      *            the axis of rotation (already normalized).
682      */
683     public void fromAngleNormalAxis(float angle, Vector3f axis) {
684         zero();
685         m33 = 1;
686
687         float fCos = FastMath.cos(angle);
688         float fSin = FastMath.sin(angle);
689         float fOneMinusCos = ((float)1.0)-fCos;
690         float fX2 = axis.x*axis.x;
691         float fY2 = axis.y*axis.y;
692         float fZ2 = axis.z*axis.z;
693         float fXYM = axis.x*axis.y*fOneMinusCos;
694         float fXZM = axis.x*axis.z*fOneMinusCos;
695         float fYZM = axis.y*axis.z*fOneMinusCos;
696         float fXSin = axis.x*fSin;
697         float fYSin = axis.y*fSin;
698         float fZSin = axis.z*fSin;
699         
700         m00 = fX2*fOneMinusCos+fCos;
701         m01 = fXYM-fZSin;
702         m02 = fXZM+fYSin;
703         m10 = fXYM+fZSin;
704         m11 = fY2*fOneMinusCos+fCos;
705         m12 = fYZM-fXSin;
706         m20 = fXZM-fYSin;
707         m21 = fYZM+fXSin;
708         m22 = fZ2*fOneMinusCos+fCos;
709     }
710
711     /**
712      * <code>mult</code> multiplies this matrix by a scalar.
713      * 
714      * @param scalar
715      *            the scalar to multiply this matrix by.
716      */
717     public void multLocal(float scalar) {
718         m00 *= scalar;
719         m01 *= scalar;
720         m02 *= scalar;
721         m03 *= scalar;
722         m10 *= scalar;
723         m11 *= scalar;
724         m12 *= scalar;
725         m13 *= scalar;
726         m20 *= scalar;
727         m21 *= scalar;
728         m22 *= scalar;
729         m23 *= scalar;
730         m30 *= scalar;
731         m31 *= scalar;
732         m32 *= scalar;
733         m33 *= scalar;
734     }
735     
736     public Matrix4f mult(float scalar) {
737         Matrix4f out = new Matrix4f();
738         out.set(this);
739         out.multLocal(scalar);
740         return out;
741     }
742     
743     public Matrix4f mult(float scalar, Matrix4f store) {
744         store.set(this);
745         store.multLocal(scalar);
746         return store;
747     }
748
749     /**
750      * <code>mult</code> multiplies this matrix with another matrix. The
751      * result matrix will then be returned. This matrix will be on the left hand
752      * side, while the parameter matrix will be on the right.
753      * 
754      * @param in2
755      *            the matrix to multiply this matrix by.
756      * @return the resultant matrix
757      */
758     public Matrix4f mult(Matrix4f in2) {
759         return mult(in2, null);
760     }
761
762     /**
763      * <code>mult</code> multiplies this matrix with another matrix. The
764      * result matrix will then be returned. This matrix will be on the left hand
765      * side, while the parameter matrix will be on the right.
766      * 
767      * @param in2
768      *            the matrix to multiply this matrix by.
769      * @param store
770      *            where to store the result. It is safe for in2 and store to be
771      *            the same object.
772      * @return the resultant matrix
773      */
774     public Matrix4f mult(Matrix4f in2, Matrix4f store) {
775         if (store == null) store = new Matrix4f();
776
777         float temp00, temp01, temp02, temp03;
778         float temp10, temp11, temp12, temp13;
779         float temp20, temp21, temp22, temp23;
780         float temp30, temp31, temp32, temp33;
781
782         temp00 = m00 * in2.m00 + 
783                 m01 * in2.m10 + 
784                 m02 * in2.m20 + 
785                 m03 * in2.m30;
786         temp01 = m00 * in2.m01 + 
787                 m01 * in2.m11 + 
788                 m02 * in2.m21 +
789                 m03 * in2.m31;
790         temp02 = m00 * in2.m02 + 
791                 m01 * in2.m12 + 
792                 m02 * in2.m22 +
793                 m03 * in2.m32;
794         temp03 = m00 * in2.m03 + 
795                 m01 * in2.m13 + 
796                 m02 * in2.m23 + 
797                 m03 * in2.m33;
798         
799         temp10 = m10 * in2.m00 + 
800                 m11 * in2.m10 + 
801                 m12 * in2.m20 +
802                 m13 * in2.m30;
803         temp11 = m10 * in2.m01 +
804                 m11 * in2.m11 +
805                 m12 * in2.m21 +
806                 m13 * in2.m31;
807         temp12 = m10 * in2.m02 +
808                 m11 * in2.m12 + 
809                 m12 * in2.m22 +
810                 m13 * in2.m32;
811         temp13 = m10 * in2.m03 +
812                 m11 * in2.m13 +
813                 m12 * in2.m23 + 
814                 m13 * in2.m33;
815
816         temp20 = m20 * in2.m00 + 
817                 m21 * in2.m10 + 
818                 m22 * in2.m20 +
819                 m23 * in2.m30;
820         temp21 = m20 * in2.m01 + 
821                 m21 * in2.m11 + 
822                 m22 * in2.m21 +
823                 m23 * in2.m31;
824         temp22 = m20 * in2.m02 + 
825                 m21 * in2.m12 + 
826                 m22 * in2.m22 +
827                 m23 * in2.m32;
828         temp23 = m20 * in2.m03 + 
829                 m21 * in2.m13 + 
830                 m22 * in2.m23 +
831                 m23 * in2.m33;
832
833         temp30 = m30 * in2.m00 + 
834                 m31 * in2.m10 + 
835                 m32 * in2.m20 +
836                 m33 * in2.m30;
837         temp31 = m30 * in2.m01 + 
838                 m31 * in2.m11 + 
839                 m32 * in2.m21 +
840                 m33 * in2.m31;
841         temp32 = m30 * in2.m02 + 
842                 m31 * in2.m12 + 
843                 m32 * in2.m22 +
844                 m33 * in2.m32;
845         temp33 = m30 * in2.m03 + 
846                 m31 * in2.m13 + 
847                 m32 * in2.m23 +
848                 m33 * in2.m33;
849         
850         store.m00 = temp00;  store.m01 = temp01;  store.m02 = temp02;  store.m03 = temp03;
851         store.m10 = temp10;  store.m11 = temp11;  store.m12 = temp12;  store.m13 = temp13;
852         store.m20 = temp20;  store.m21 = temp21;  store.m22 = temp22;  store.m23 = temp23;
853         store.m30 = temp30;  store.m31 = temp31;  store.m32 = temp32;  store.m33 = temp33;
854         
855         return store;
856     }
857
858     /**
859      * <code>mult</code> multiplies this matrix with another matrix. The
860      * results are stored internally and a handle to this matrix will 
861      * then be returned. This matrix will be on the left hand
862      * side, while the parameter matrix will be on the right.
863      * 
864      * @param in2
865      *            the matrix to multiply this matrix by.
866      * @return the resultant matrix
867      */
868     public Matrix4f multLocal(Matrix4f in2) {
869         
870         return mult(in2, this);
871     }
872
873     /**
874      * <code>mult</code> multiplies a vector about a rotation matrix. The
875      * resulting vector is returned as a new Vector3f.
876      * 
877      * @param vec
878      *            vec to multiply against.
879      * @return the rotated vector.
880      */
881     public Vector3f mult(Vector3f vec) {
882         return mult(vec, null);
883     }
884
885     /**
886      * <code>mult</code> multiplies a vector about a rotation matrix and adds
887      * translation. The resulting vector is returned.
888      * 
889      * @param vec
890      *            vec to multiply against.
891      * @param store
892      *            a vector to store the result in. Created if null is passed.
893      * @return the rotated vector.
894      */
895     public Vector3f mult(Vector3f vec, Vector3f store) {
896         if (store == null) store = new Vector3f();
897         
898         float vx = vec.x, vy = vec.y, vz = vec.z;
899         store.x = m00 * vx + m01 * vy + m02 * vz + m03;
900         store.y = m10 * vx + m11 * vy + m12 * vz + m13;
901         store.z = m20 * vx + m21 * vy + m22 * vz + m23;
902
903         return store;
904     }
905
906     /**
907      * <code>mult</code> multiplies a vector about a rotation matrix. The
908      * resulting vector is returned.
909      * 
910      * @param vec
911      *            vec to multiply against.
912      * @param store
913      *            a vector to store the result in.  created if null is passed.
914      * @return the rotated vector.
915      */
916     public Vector3f multAcross(Vector3f vec, Vector3f store) {
917         if (null == vec) {
918             logger.info("Source vector is null, null result returned.");
919             return null;
920         }
921         if (store == null) store = new Vector3f();
922         
923         float vx = vec.x, vy = vec.y, vz = vec.z;
924         store.x = m00 * vx + m10 * vy + m20 * vz + m30 * 1;
925         store.y = m01 * vx + m11 * vy + m21 * vz + m31 * 1;
926         store.z = m02 * vx + m12 * vy + m22 * vz + m32 * 1;
927
928         return store;
929     }
930
931     /**
932      * <code>mult</code> multiplies a quaternion about a matrix. The
933      * resulting vector is returned.
934      *
935      * @param vec
936      *            vec to multiply against.
937      * @param store
938      *            a quaternion to store the result in.  created if null is passed.
939      * @return store = this * vec
940      */
941     public Quaternion mult(Quaternion vec, Quaternion store) {
942
943         if (null == vec) {
944             logger.warning("Source vector is null, null result returned.");
945             return null;
946         }
947         if (store == null) store = new Quaternion();
948
949         float x = m00 * vec.x + m10 * vec.y + m20 * vec.z + m30 * vec.w;
950         float y = m01 * vec.x + m11 * vec.y + m21 * vec.z + m31 * vec.w;
951         float z = m02 * vec.x + m12 * vec.y + m22 * vec.z + m32 * vec.w;
952         float w = m03 * vec.x + m13 * vec.y + m23 * vec.z + m33 * vec.w;
953         store.x = x;
954         store.y = y;
955         store.z = z;
956         store.w = w;
957
958         return store;
959     }
960     
961     /**
962      * <code>mult</code> multiplies an array of 4 floats against this rotation 
963      * matrix. The results are stored directly in the array. (vec4f x mat4f)
964      * 
965      * @param vec4f
966      *            float array (size 4) to multiply against the matrix.
967      * @return the vec4f for chaining.
968      */
969     public float[] mult(float[] vec4f) {
970         if (null == vec4f || vec4f.length != 4) {
971             logger.warning("invalid array given, must be nonnull and length 4");
972             return null;
973         }
974
975         float x = vec4f[0], y = vec4f[1], z = vec4f[2], w = vec4f[3];
976         
977         vec4f[0] = m00 * x + m01 * y + m02 * z + m03 * w;
978         vec4f[1] = m10 * x + m11 * y + m12 * z + m13 * w;
979         vec4f[2] = m20 * x + m21 * y + m22 * z + m23 * w;
980         vec4f[3] = m30 * x + m31 * y + m32 * z + m33 * w;
981
982         return vec4f;
983     }
984
985     /**
986      * <code>mult</code> multiplies an array of 4 floats against this rotation 
987      * matrix. The results are stored directly in the array. (vec4f x mat4f)
988      * 
989      * @param vec4f
990      *            float array (size 4) to multiply against the matrix.
991      * @return the vec4f for chaining.
992      */
993     public float[] multAcross(float[] vec4f) {
994         if (null == vec4f || vec4f.length != 4) {
995             logger.warning("invalid array given, must be nonnull and length 4");
996             return null;
997         }
998
999         float x = vec4f[0], y = vec4f[1], z = vec4f[2], w = vec4f[3];
1000         
1001         vec4f[0] = m00 * x + m10 * y + m20 * z + m30 * w;
1002         vec4f[1] = m01 * x + m11 * y + m21 * z + m31 * w;
1003         vec4f[2] = m02 * x + m12 * y + m22 * z + m32 * w;
1004         vec4f[3] = m03 * x + m13 * y + m23 * z + m33 * w;
1005
1006         return vec4f;
1007     }
1008
1009     /**
1010      * Inverts this matrix as a new Matrix4f.
1011      * 
1012      * @return The new inverse matrix
1013      */
1014     public Matrix4f invert() {
1015         return invert(null);
1016     }
1017
1018     /**
1019      * Inverts this matrix and stores it in the given store.
1020      * 
1021      * @return The store
1022      */
1023     public Matrix4f invert(Matrix4f store) {
1024         if (store == null) store = new Matrix4f();
1025
1026         float fA0 = m00*m11 - m01*m10;
1027         float fA1 = m00*m12 - m02*m10;
1028         float fA2 = m00*m13 - m03*m10;
1029         float fA3 = m01*m12 - m02*m11;
1030         float fA4 = m01*m13 - m03*m11;
1031         float fA5 = m02*m13 - m03*m12;
1032         float fB0 = m20*m31 - m21*m30;
1033         float fB1 = m20*m32 - m22*m30;
1034         float fB2 = m20*m33 - m23*m30;
1035         float fB3 = m21*m32 - m22*m31;
1036         float fB4 = m21*m33 - m23*m31;
1037         float fB5 = m22*m33 - m23*m32;
1038         float fDet = fA0*fB5-fA1*fB4+fA2*fB3+fA3*fB2-fA4*fB1+fA5*fB0;
1039
1040         if ( FastMath.abs(fDet) <= FastMath.FLT_EPSILON )
1041             throw new ArithmeticException("This matrix cannot be inverted");
1042
1043         store.m00 = + m11*fB5 - m12*fB4 + m13*fB3;
1044         store.m10 = - m10*fB5 + m12*fB2 - m13*fB1;
1045         store.m20 = + m10*fB4 - m11*fB2 + m13*fB0;
1046         store.m30 = - m10*fB3 + m11*fB1 - m12*fB0;
1047         store.m01 = - m01*fB5 + m02*fB4 - m03*fB3;
1048         store.m11 = + m00*fB5 - m02*fB2 + m03*fB1;
1049         store.m21 = - m00*fB4 + m01*fB2 - m03*fB0;
1050         store.m31 = + m00*fB3 - m01*fB1 + m02*fB0;
1051         store.m02 = + m31*fA5 - m32*fA4 + m33*fA3;
1052         store.m12 = - m30*fA5 + m32*fA2 - m33*fA1;
1053         store.m22 = + m30*fA4 - m31*fA2 + m33*fA0;
1054         store.m32 = - m30*fA3 + m31*fA1 - m32*fA0;
1055         store.m03 = - m21*fA5 + m22*fA4 - m23*fA3;
1056         store.m13 = + m20*fA5 - m22*fA2 + m23*fA1;
1057         store.m23 = - m20*fA4 + m21*fA2 - m23*fA0;
1058         store.m33 = + m20*fA3 - m21*fA1 + m22*fA0;
1059
1060         float fInvDet = 1.0f/fDet;
1061         store.multLocal(fInvDet);
1062
1063         return store;
1064     }
1065
1066     /**
1067      * Inverts this matrix locally.
1068      * 
1069      * @return this
1070      */
1071     public Matrix4f invertLocal() {
1072
1073         float fA0 = m00*m11 - m01*m10;
1074         float fA1 = m00*m12 - m02*m10;
1075         float fA2 = m00*m13 - m03*m10;
1076         float fA3 = m01*m12 - m02*m11;
1077         float fA4 = m01*m13 - m03*m11;
1078         float fA5 = m02*m13 - m03*m12;
1079         float fB0 = m20*m31 - m21*m30;
1080         float fB1 = m20*m32 - m22*m30;
1081         float fB2 = m20*m33 - m23*m30;
1082         float fB3 = m21*m32 - m22*m31;
1083         float fB4 = m21*m33 - m23*m31;
1084         float fB5 = m22*m33 - m23*m32;
1085         float fDet = fA0*fB5-fA1*fB4+fA2*fB3+fA3*fB2-fA4*fB1+fA5*fB0;
1086
1087         if ( FastMath.abs(fDet) <= FastMath.FLT_EPSILON )
1088             return zero();
1089
1090         float f00 = + m11*fB5 - m12*fB4 + m13*fB3;
1091         float f10 = - m10*fB5 + m12*fB2 - m13*fB1;
1092         float f20 = + m10*fB4 - m11*fB2 + m13*fB0;
1093         float f30 = - m10*fB3 + m11*fB1 - m12*fB0;
1094         float f01 = - m01*fB5 + m02*fB4 - m03*fB3;
1095         float f11 = + m00*fB5 - m02*fB2 + m03*fB1;
1096         float f21 = - m00*fB4 + m01*fB2 - m03*fB0;
1097         float f31 = + m00*fB3 - m01*fB1 + m02*fB0;
1098         float f02 = + m31*fA5 - m32*fA4 + m33*fA3;
1099         float f12 = - m30*fA5 + m32*fA2 - m33*fA1;
1100         float f22 = + m30*fA4 - m31*fA2 + m33*fA0;
1101         float f32 = - m30*fA3 + m31*fA1 - m32*fA0;
1102         float f03 = - m21*fA5 + m22*fA4 - m23*fA3;
1103         float f13 = + m20*fA5 - m22*fA2 + m23*fA1;
1104         float f23 = - m20*fA4 + m21*fA2 - m23*fA0;
1105         float f33 = + m20*fA3 - m21*fA1 + m22*fA0;
1106         
1107         m00 = f00;
1108         m01 = f01;
1109         m02 = f02;
1110         m03 = f03;
1111         m10 = f10;
1112         m11 = f11;
1113         m12 = f12;
1114         m13 = f13;
1115         m20 = f20;
1116         m21 = f21;
1117         m22 = f22;
1118         m23 = f23;
1119         m30 = f30;
1120         m31 = f31;
1121         m32 = f32;
1122         m33 = f33;
1123
1124         float fInvDet = 1.0f/fDet;
1125         multLocal(fInvDet);
1126
1127         return this;
1128     }
1129     
1130     /**
1131      * Returns a new matrix representing the adjoint of this matrix.
1132      * 
1133      * @return The adjoint matrix
1134      */
1135     public Matrix4f adjoint() {
1136         return adjoint(null);
1137     }
1138      
1139     
1140     /**
1141      * Places the adjoint of this matrix in store (creates store if null.)
1142      * 
1143      * @param store
1144      *            The matrix to store the result in.  If null, a new matrix is created.
1145      * @return store
1146      */
1147     public Matrix4f adjoint(Matrix4f store) {
1148         if (store == null) store = new Matrix4f();
1149
1150         float fA0 = m00*m11 - m01*m10;
1151         float fA1 = m00*m12 - m02*m10;
1152         float fA2 = m00*m13 - m03*m10;
1153         float fA3 = m01*m12 - m02*m11;
1154         float fA4 = m01*m13 - m03*m11;
1155         float fA5 = m02*m13 - m03*m12;
1156         float fB0 = m20*m31 - m21*m30;
1157         float fB1 = m20*m32 - m22*m30;
1158         float fB2 = m20*m33 - m23*m30;
1159         float fB3 = m21*m32 - m22*m31;
1160         float fB4 = m21*m33 - m23*m31;
1161         float fB5 = m22*m33 - m23*m32;
1162
1163         store.m00 = + m11*fB5 - m12*fB4 + m13*fB3;
1164         store.m10 = - m10*fB5 + m12*fB2 - m13*fB1;
1165         store.m20 = + m10*fB4 - m11*fB2 + m13*fB0;
1166         store.m30 = - m10*fB3 + m11*fB1 - m12*fB0;
1167         store.m01 = - m01*fB5 + m02*fB4 - m03*fB3;
1168         store.m11 = + m00*fB5 - m02*fB2 + m03*fB1;
1169         store.m21 = - m00*fB4 + m01*fB2 - m03*fB0;
1170         store.m31 = + m00*fB3 - m01*fB1 + m02*fB0;
1171         store.m02 = + m31*fA5 - m32*fA4 + m33*fA3;
1172         store.m12 = - m30*fA5 + m32*fA2 - m33*fA1;
1173         store.m22 = + m30*fA4 - m31*fA2 + m33*fA0;
1174         store.m32 = - m30*fA3 + m31*fA1 - m32*fA0;
1175         store.m03 = - m21*fA5 + m22*fA4 - m23*fA3;
1176         store.m13 = + m20*fA5 - m22*fA2 + m23*fA1;
1177         store.m23 = - m20*fA4 + m21*fA2 - m23*fA0;
1178         store.m33 = + m20*fA3 - m21*fA1 + m22*fA0;
1179
1180         return store;
1181     }
1182
1183     /**
1184      * <code>determinant</code> generates the determinate of this matrix.
1185      * 
1186      * @return the determinate
1187      */
1188     public float determinant() {
1189         float fA0 = m00*m11 - m01*m10;
1190         float fA1 = m00*m12 - m02*m10;
1191         float fA2 = m00*m13 - m03*m10;
1192         float fA3 = m01*m12 - m02*m11;
1193         float fA4 = m01*m13 - m03*m11;
1194         float fA5 = m02*m13 - m03*m12;
1195         float fB0 = m20*m31 - m21*m30;
1196         float fB1 = m20*m32 - m22*m30;
1197         float fB2 = m20*m33 - m23*m30;
1198         float fB3 = m21*m32 - m22*m31;
1199         float fB4 = m21*m33 - m23*m31;
1200         float fB5 = m22*m33 - m23*m32;
1201         float fDet = fA0*fB5-fA1*fB4+fA2*fB3+fA3*fB2-fA4*fB1+fA5*fB0;
1202         return fDet;
1203     }
1204
1205     /**
1206      * Sets all of the values in this matrix to zero.
1207      * 
1208      * @return this matrix
1209      */
1210     public Matrix4f zero() {
1211         m00 = m01 = m02 = m03 = 0.0f;
1212         m10 = m11 = m12 = m13 = 0.0f;
1213         m20 = m21 = m22 = m23 = 0.0f;
1214         m30 = m31 = m32 = m33 = 0.0f;
1215         return this;
1216     }
1217     
1218     public Matrix4f add(Matrix4f mat) {
1219         Matrix4f result = new Matrix4f();
1220         result.m00 = this.m00 + mat.m00;
1221         result.m01 = this.m01 + mat.m01;
1222         result.m02 = this.m02 + mat.m02;
1223         result.m03 = this.m03 + mat.m03;
1224         result.m10 = this.m10 + mat.m10;
1225         result.m11 = this.m11 + mat.m11;
1226         result.m12 = this.m12 + mat.m12;
1227         result.m13 = this.m13 + mat.m13;
1228         result.m20 = this.m20 + mat.m20;
1229         result.m21 = this.m21 + mat.m21;
1230         result.m22 = this.m22 + mat.m22;
1231         result.m23 = this.m23 + mat.m23;
1232         result.m30 = this.m30 + mat.m30;
1233         result.m31 = this.m31 + mat.m31;
1234         result.m32 = this.m32 + mat.m32;
1235         result.m33 = this.m33 + mat.m33;
1236         return result;
1237     }
1238
1239     /**
1240      * <code>add</code> adds the values of a parameter matrix to this matrix.
1241      * 
1242      * @param mat
1243      *            the matrix to add to this.
1244      */
1245     public void addLocal(Matrix4f mat) {
1246         m00 += mat.m00;
1247         m01 += mat.m01;
1248         m02 += mat.m02;
1249         m03 += mat.m03;
1250         m10 += mat.m10;
1251         m11 += mat.m11;
1252         m12 += mat.m12;
1253         m13 += mat.m13;
1254         m20 += mat.m20;
1255         m21 += mat.m21;
1256         m22 += mat.m22;
1257         m23 += mat.m23;
1258         m30 += mat.m30;
1259         m31 += mat.m31;
1260         m32 += mat.m32;
1261         m33 += mat.m33;
1262     }
1263     
1264     public Vector3f toTranslationVector() {
1265         return new Vector3f(m03, m13, m23);
1266     }
1267     
1268     public void toTranslationVector(Vector3f vector) {
1269         vector.set(m03, m13, m23);
1270     }
1271     
1272     public Quaternion toRotationQuat() {
1273         Quaternion quat = new Quaternion();
1274         quat.fromRotationMatrix(toRotationMatrix());
1275         return quat;
1276     }
1277     
1278     public void toRotationQuat(Quaternion q) {
1279         q.fromRotationMatrix(toRotationMatrix());
1280     }
1281     
1282     public Matrix3f toRotationMatrix() {
1283         return new Matrix3f(m00, m01, m02, m10, m11, m12, m20, m21, m22);
1284         
1285     }
1286     
1287     public void toRotationMatrix(Matrix3f mat) {
1288         mat.m00 = m00;
1289         mat.m01 = m01;
1290         mat.m02 = m02;
1291         mat.m10 = m10;
1292         mat.m11 = m11;
1293         mat.m12 = m12;
1294         mat.m20 = m20;
1295         mat.m21 = m21;
1296         mat.m22 = m22;
1297         
1298     }
1299
1300     /**
1301      * <code>setTranslation</code> will set the matrix's translation values.
1302      * 
1303      * @param translation
1304      *            the new values for the translation.
1305      * @throws JmeException
1306      *             if translation is not size 3.
1307      */
1308     public void setTranslation(float[] translation) {
1309         if (translation.length != 3) { throw new JmeException(
1310                 "Translation size must be 3."); }
1311         m03 = translation[0];
1312         m13 = translation[1];
1313         m23 = translation[2];
1314     }
1315
1316     /**
1317      * <code>setTranslation</code> will set the matrix's translation values.
1318      * 
1319      * @param x
1320      *            value of the translation on the x axis
1321      * @param y
1322      *            value of the translation on the y axis
1323      * @param z
1324      *            value of the translation on the z axis
1325      */
1326     public void setTranslation(float x, float y, float z) {
1327         m03 = x;
1328         m13 = y;
1329         m23 = z;
1330     }
1331
1332     /**
1333      * <code>setTranslation</code> will set the matrix's translation values.
1334      *
1335      * @param translation
1336      *            the new values for the translation.
1337      */
1338     public void setTranslation(Vector3f translation) {
1339         m03 = translation.x;
1340         m13 = translation.y;
1341         m23 = translation.z;
1342     }
1343
1344     /**
1345      * <code>setInverseTranslation</code> will set the matrix's inverse
1346      * translation values.
1347      * 
1348      * @param translation
1349      *            the new values for the inverse translation.
1350      * @throws JmeException
1351      *             if translation is not size 3.
1352      */
1353     public void setInverseTranslation(float[] translation) {
1354         if (translation.length != 3) { throw new JmeException(
1355                 "Translation size must be 3."); }
1356         m03 = -translation[0];
1357         m13 = -translation[1];
1358         m23 = -translation[2];
1359     }
1360
1361     /**
1362      * <code>angleRotation</code> sets this matrix to that of a rotation about
1363      * three axes (x, y, z). Where each axis has a specified rotation in
1364      * degrees. These rotations are expressed in a single <code>Vector3f</code>
1365      * object.
1366      * 
1367      * @param angles
1368      *            the angles to rotate.
1369      */
1370     public void angleRotation(Vector3f angles) {
1371         float angle;
1372         float sr, sp, sy, cr, cp, cy;
1373
1374         angle = (angles.z * FastMath.DEG_TO_RAD);
1375         sy = FastMath.sin(angle);
1376         cy = FastMath.cos(angle);
1377         angle = (angles.y * FastMath.DEG_TO_RAD);
1378         sp = FastMath.sin(angle);
1379         cp = FastMath.cos(angle);
1380         angle = (angles.x * FastMath.DEG_TO_RAD);
1381         sr = FastMath.sin(angle);
1382         cr = FastMath.cos(angle);
1383
1384         // matrix = (Z * Y) * X
1385         m00 = cp * cy;
1386         m10 = cp * sy;
1387         m20 = -sp;
1388         m01 = sr * sp * cy + cr * -sy;
1389         m11 = sr * sp * sy + cr * cy;
1390         m21 = sr * cp;
1391         m02 = (cr * sp * cy + -sr * -sy);
1392         m12 = (cr * sp * sy + -sr * cy);
1393         m22 = cr * cp;
1394         m03 = 0.0f;
1395         m13 = 0.0f;
1396         m23 = 0.0f;
1397     }
1398
1399     /**
1400      * <code>setRotationQuaternion</code> builds a rotation from a
1401      * <code>Quaternion</code>.
1402      * 
1403      * @param quat
1404      *            the quaternion to build the rotation from.
1405      * @throws NullPointerException
1406      *             if quat is null.
1407      */
1408     public void setRotationQuaternion(Quaternion quat) {
1409         quat.toRotationMatrix(this);
1410     }
1411
1412     /**
1413      * <code>setInverseRotationRadians</code> builds an inverted rotation from
1414      * Euler angles that are in radians.
1415      * 
1416      * @param angles
1417      *            the Euler angles in radians.
1418      * @throws JmeException
1419      *             if angles is not size 3.
1420      */
1421     public void setInverseRotationRadians(float[] angles) {
1422         if (angles.length != 3) { throw new JmeException(
1423                 "Angles must be of size 3."); }
1424         double cr = FastMath.cos(angles[0]);
1425         double sr = FastMath.sin(angles[0]);
1426         double cp = FastMath.cos(angles[1]);
1427         double sp = FastMath.sin(angles[1]);
1428         double cy = FastMath.cos(angles[2]);
1429         double sy = FastMath.sin(angles[2]);
1430
1431         m00 = (float) (cp * cy);
1432         m10 = (float) (cp * sy);
1433         m20 = (float) (-sp);
1434
1435         double srsp = sr * sp;
1436         double crsp = cr * sp;
1437
1438         m01 = (float) (srsp * cy - cr * sy);
1439         m11 = (float) (srsp * sy + cr * cy);
1440         m21 = (float) (sr * cp);
1441
1442         m02 = (float) (crsp * cy + sr * sy);
1443         m12 = (float) (crsp * sy - sr * cy);
1444         m22 = (float) (cr * cp);
1445     }
1446
1447     /**
1448      * <code>setInverseRotationDegrees</code> builds an inverted rotation from
1449      * Euler angles that are in degrees.
1450      * 
1451      * @param angles
1452      *            the Euler angles in degrees.
1453      * @throws JmeException
1454      *             if angles is not size 3.
1455      */
1456     public void setInverseRotationDegrees(float[] angles) {
1457         if (angles.length != 3) { throw new JmeException(
1458                 "Angles must be of size 3."); }
1459         float vec[] = new float[3];
1460         vec[0] = (angles[0] * FastMath.RAD_TO_DEG);
1461         vec[1] = (angles[1] * FastMath.RAD_TO_DEG);
1462         vec[2] = (angles[2] * FastMath.RAD_TO_DEG);
1463         setInverseRotationRadians(vec);
1464     }
1465
1466     /**
1467      * 
1468      * <code>inverseTranslateVect</code> translates a given Vector3f by the
1469      * translation part of this matrix.
1470      * 
1471      * @param vec
1472      *            the Vector3f data to be translated.
1473      * @throws JmeException
1474      *             if the size of the Vector3f is not 3.
1475      */
1476     public void inverseTranslateVect(float[] vec) {
1477         if (vec.length != 3) { throw new JmeException(
1478                 "vec must be of size 3."); }
1479
1480         vec[0] = vec[0] - m03;
1481         vec[1] = vec[1] - m13;
1482         vec[2] = vec[2] - m23;
1483     }
1484
1485     /**
1486      * 
1487      * <code>inverseTranslateVect</code> translates a given Vector3f by the
1488      * translation part of this matrix.
1489      * 
1490      * @param data
1491      *            the Vector3f to be translated.
1492      * @throws JmeException
1493      *             if the size of the Vector3f is not 3.
1494      */
1495     public void inverseTranslateVect(Vector3f data) {
1496         data.x -= m03;
1497         data.y -= m13;
1498         data.z -= m23;
1499     }
1500
1501     /**
1502      * 
1503      * <code>inverseTranslateVect</code> translates a given Vector3f by the
1504      * translation part of this matrix.
1505      * 
1506      * @param data
1507      *            the Vector3f to be translated.
1508      * @throws JmeException
1509      *             if the size of the Vector3f is not 3.
1510      */
1511     public void translateVect(Vector3f data) {
1512         data.x += m03;
1513         data.y += m13;
1514         data.z += m23;
1515     }
1516
1517     /**
1518      * 
1519      * <code>inverseRotateVect</code> rotates a given Vector3f by the rotation
1520      * part of this matrix.
1521      * 
1522      * @param vec
1523      *            the Vector3f to be rotated.
1524      */
1525     public void inverseRotateVect(Vector3f vec) {
1526         float vx = vec.x, vy = vec.y, vz = vec.z;
1527
1528         vec.x = vx * m00 + vy * m10 + vz * m20;
1529         vec.y = vx * m01 + vy * m11 + vz * m21;
1530         vec.z = vx * m02 + vy * m12 + vz * m22;
1531     }
1532     
1533     public void rotateVect(Vector3f vec) {
1534         float vx = vec.x, vy = vec.y, vz = vec.z;
1535
1536         vec.x = vx * m00 + vy * m01 + vz * m02;
1537         vec.y = vx * m10 + vy * m11 + vz * m12;
1538         vec.z = vx * m20 + vy * m21 + vz * m22;
1539     }
1540
1541     /**
1542      * <code>toString</code> returns the string representation of this object.
1543      * It is in a format of a 4x4 matrix. For example, an identity matrix would
1544      * be represented by the following string. com.jme.math.Matrix3f <br>[<br>
1545      * 1.0  0.0  0.0  0.0 <br>
1546      * 0.0  1.0  0.0  0.0 <br>
1547      * 0.0  0.0  1.0  0.0 <br>
1548      * 0.0  0.0  0.0  1.0 <br>]<br>
1549      * 
1550      * @return the string representation of this object.
1551      */
1552     public String toString() {
1553         StringBuffer result = new StringBuffer("com.jme.math.Matrix4f\n[\n");
1554         result.append(" ");
1555         result.append(m00);
1556         result.append("  ");
1557         result.append(m01);
1558         result.append("  ");
1559         result.append(m02);
1560         result.append("  ");
1561         result.append(m03);
1562         result.append(" \n");
1563         result.append(" ");
1564         result.append(m10);
1565         result.append("  ");
1566         result.append(m11);
1567         result.append("  ");
1568         result.append(m12);
1569         result.append("  ");
1570         result.append(m13);
1571         result.append(" \n");
1572         result.append(" ");
1573         result.append(m20);
1574         result.append("  ");
1575         result.append(m21);
1576         result.append("  ");
1577         result.append(m22);
1578         result.append("  ");
1579         result.append(m23);
1580         result.append(" \n");
1581         result.append(" ");
1582         result.append(m30);
1583         result.append("  ");
1584         result.append(m31);
1585         result.append("  ");
1586         result.append(m32);
1587         result.append("  ");
1588         result.append(m33);
1589         result.append(" \n]");
1590         return result.toString();
1591     }
1592
1593     /**
1594      * 
1595      * <code>hashCode</code> returns the hash code value as an integer and is
1596      * supported for the benefit of hashing based collection classes such as
1597      * Hashtable, HashMap, HashSet etc.
1598      * 
1599      * @return the hashcode for this instance of Matrix4f.
1600      * @see java.lang.Object#hashCode()
1601      */
1602     public int hashCode() {
1603         int hash = 37;
1604         hash = 37 * hash + Float.floatToIntBits(m00);
1605         hash = 37 * hash + Float.floatToIntBits(m01);
1606         hash = 37 * hash + Float.floatToIntBits(m02);
1607         hash = 37 * hash + Float.floatToIntBits(m03);
1608
1609         hash = 37 * hash + Float.floatToIntBits(m10);
1610         hash = 37 * hash + Float.floatToIntBits(m11);
1611         hash = 37 * hash + Float.floatToIntBits(m12);
1612         hash = 37 * hash + Float.floatToIntBits(m13);
1613
1614         hash = 37 * hash + Float.floatToIntBits(m20);
1615         hash = 37 * hash + Float.floatToIntBits(m21);
1616         hash = 37 * hash + Float.floatToIntBits(m22);
1617         hash = 37 * hash + Float.floatToIntBits(m23);
1618
1619         hash = 37 * hash + Float.floatToIntBits(m30);
1620         hash = 37 * hash + Float.floatToIntBits(m31);
1621         hash = 37 * hash + Float.floatToIntBits(m32);
1622         hash = 37 * hash + Float.floatToIntBits(m33);
1623
1624         return hash;
1625     }
1626     
1627     /**
1628      * are these two matrices the same? they are is they both have the same mXX values.
1629      *
1630      * @param o
1631      *            the object to compare for equality
1632      * @return true if they are equal
1633      */
1634     public boolean equals(Object o) {
1635         if (!(o instanceof Matrix4f) || o == null) {
1636             return false;
1637         }
1638
1639         if (this == o) {
1640             return true;
1641         }
1642
1643         Matrix4f comp = (Matrix4f) o;
1644         if (Float.compare(m00,comp.m00) != 0) return false;
1645         if (Float.compare(m01,comp.m01) != 0) return false;
1646         if (Float.compare(m02,comp.m02) != 0) return false;
1647         if (Float.compare(m03,comp.m03) != 0) return false;
1648
1649         if (Float.compare(m10,comp.m10) != 0) return false;
1650         if (Float.compare(m11,comp.m11) != 0) return false;
1651         if (Float.compare(m12,comp.m12) != 0) return false;
1652         if (Float.compare(m13,comp.m13) != 0) return false;
1653
1654         if (Float.compare(m20,comp.m20) != 0) return false;
1655         if (Float.compare(m21,comp.m21) != 0) return false;
1656         if (Float.compare(m22,comp.m22) != 0) return false;
1657         if (Float.compare(m23,comp.m23) != 0) return false;
1658
1659         if (Float.compare(m30,comp.m30) != 0) return false;
1660         if (Float.compare(m31,comp.m31) != 0) return false;
1661         if (Float.compare(m32,comp.m32) != 0) return false;
1662         if (Float.compare(m33,comp.m33) != 0) return false;
1663
1664         return true;
1665     }
1666
1667     public void write(JMEExporter e) throws IOException {
1668         OutputCapsule cap = e.getCapsule(this);
1669         cap.write(m00, "m00", 1);
1670         cap.write(m01, "m01", 0);
1671         cap.write(m02, "m02", 0);
1672         cap.write(m03, "m03", 0);
1673         cap.write(m10, "m10", 0);
1674         cap.write(m11, "m11", 1);
1675         cap.write(m12, "m12", 0);
1676         cap.write(m13, "m13", 0);
1677         cap.write(m20, "m20", 0);
1678         cap.write(m21, "m21", 0);
1679         cap.write(m22, "m22", 1);
1680         cap.write(m23, "m23", 0);
1681         cap.write(m30, "m30", 0);
1682         cap.write(m31, "m31", 0);
1683         cap.write(m32, "m32", 0);
1684         cap.write(m33, "m33", 1);
1685     }
1686
1687     public void read(JMEImporter e) throws IOException {
1688         InputCapsule cap = e.getCapsule(this);
1689         m00 = cap.readFloat("m00", 1);
1690         m01 = cap.readFloat("m01", 0);
1691         m02 = cap.readFloat("m02", 0);
1692         m03 = cap.readFloat("m03", 0);
1693         m10 = cap.readFloat("m10", 0);
1694         m11 = cap.readFloat("m11", 1);
1695         m12 = cap.readFloat("m12", 0);
1696         m13 = cap.readFloat("m13", 0);
1697         m20 = cap.readFloat("m20", 0);
1698         m21 = cap.readFloat("m21", 0);
1699         m22 = cap.readFloat("m22", 1);
1700         m23 = cap.readFloat("m23", 0);
1701         m30 = cap.readFloat("m30", 0);
1702         m31 = cap.readFloat("m31", 0);
1703         m32 = cap.readFloat("m32", 0);
1704         m33 = cap.readFloat("m33", 1);
1705     }
1706     
1707     public Class<? extends Matrix4f> getClassTag() {
1708         return this.getClass();
1709     }
1710
1711     /**
1712      * @return true if this matrix is identity
1713      */
1714     public boolean isIdentity() {
1715         return 
1716         (m00 == 1 && m01 == 0 && m02 == 0 && m03 == 0) &&
1717         (m10 == 0 && m11 == 1 && m12 == 0 && m13 == 0) &&
1718         (m20 == 0 && m21 == 0 && m22 == 1 && m23 == 0) &&
1719         (m30 == 0 && m31 == 0 && m32 == 0 && m33 == 1);
1720     }
1721
1722     /**
1723      * Apply a scale to this matrix.
1724      * 
1725      * @param scale
1726      *            the scale to apply
1727      */
1728     public void scale(Vector3f scale) {
1729         m00 *= scale.getX();
1730         m10 *= scale.getX();
1731         m20 *= scale.getX();
1732         m30 *= scale.getX();
1733         m01 *= scale.getY();
1734         m11 *= scale.getY();
1735         m21 *= scale.getY();
1736         m31 *= scale.getY();
1737         m02 *= scale.getZ();
1738         m12 *= scale.getZ();
1739         m22 *= scale.getZ();
1740         m32 *= scale.getZ();
1741     }
1742
1743     static final boolean equalIdentity(Matrix4f mat) {
1744                 if (Math.abs(mat.m00 - 1) > 1e-4) return false;
1745                 if (Math.abs(mat.m11 - 1) > 1e-4) return false;
1746                 if (Math.abs(mat.m22 - 1) > 1e-4) return false;
1747                 if (Math.abs(mat.m33 - 1) > 1e-4) return false;
1748
1749                 if (Math.abs(mat.m01) > 1e-4) return false;
1750                 if (Math.abs(mat.m02) > 1e-4) return false;
1751                 if (Math.abs(mat.m03) > 1e-4) return false;
1752
1753                 if (Math.abs(mat.m10) > 1e-4) return false;
1754                 if (Math.abs(mat.m12) > 1e-4) return false;
1755                 if (Math.abs(mat.m13) > 1e-4) return false;
1756
1757                 if (Math.abs(mat.m20) > 1e-4) return false;
1758                 if (Math.abs(mat.m21) > 1e-4) return false;
1759                 if (Math.abs(mat.m23) > 1e-4) return false;
1760
1761                 if (Math.abs(mat.m30) > 1e-4) return false;
1762                 if (Math.abs(mat.m31) > 1e-4) return false;
1763                 if (Math.abs(mat.m32) > 1e-4) return false;
1764
1765                 return true;
1766     }
1767
1768     // XXX: This tests more solid than converting the q to a matrix and multiplying... why?
1769     public void multLocal(Quaternion rotation) {
1770         Vector3f axis = new Vector3f();
1771         float angle = rotation.toAngleAxis(axis);
1772         Matrix4f matrix4f = new Matrix4f();
1773         matrix4f.fromAngleAxis(angle, axis);
1774         multLocal(matrix4f);
1775     }
1776     
1777     @Override
1778     public Matrix4f clone() {
1779         try {
1780             return (Matrix4f) super.clone();
1781         } catch (CloneNotSupportedException e) {
1782             throw new AssertionError(); // can not happen
1783         }
1784     }
1785 }
1786