2 * $RCSfile: Matrix3d.java,v $
4 * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7 * This code is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 only, as
9 * published by the Free Software Foundation. Sun designates this
10 * particular file as subject to the "Classpath" exception as provided
11 * by Sun in the LICENSE file that accompanied this code.
13 * This code is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * version 2 for more details (a copy is included in the LICENSE file that
17 * accompanied this code).
19 * You should have received a copy of the GNU General Public License version
20 * 2 along with this work; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
24 * CA 95054 USA or visit www.sun.com if you need additional information or
28 * $Date: 2008/02/28 20:18:50 $
32 package javax.vecmath;
34 import java.lang.Math;
37 * A double precision floating point 3 by 3 matrix.
38 * Primarily to support 3D rotations.
41 public class Matrix3d implements java.io.Serializable, Cloneable {
43 // Compatible with 1.1
44 static final long serialVersionUID = 6837536777072402710L;
47 * The first matrix element in the first row.
52 * The second matrix element in the first row.
57 * The third matrix element in the first row.
62 * The first matrix element in the second row.
67 * The second matrix element in the second row.
72 * The third matrix element in the second row.
77 * The first matrix element in the third row.
82 * The second matrix element in the third row.
87 * The third matrix element in the third row.
91 //double[] tmp = new double[9]; // scratch matrix
92 //double[] tmp_rot = new double[9]; // scratch matrix
93 //double[] tmp_scale = new double[3]; // scratch matrix
94 private static final double EPS = 1.110223024E-16;
95 private static final double ERR_EPS = 1.0E-8;
96 private static double xin,yin,zin,xout,yout,zout;
99 * Constructs and initializes a Matrix3d from the specified nine values.
100 * @param m00 the [0][0] element
101 * @param m01 the [0][1] element
102 * @param m02 the [0][2] element
103 * @param m10 the [1][0] element
104 * @param m11 the [1][1] element
105 * @param m12 the [1][2] element
106 * @param m20 the [2][0] element
107 * @param m21 the [2][1] element
108 * @param m22 the [2][2] element
110 public Matrix3d(double m00, double m01, double m02,
111 double m10, double m11, double m12,
112 double m20, double m21, double m22)
129 * Constructs and initializes a Matrix3d from the specified nine-
131 * @param v the array of length 9 containing in order
133 public Matrix3d(double[] v)
150 * Constructs a new matrix with the same values as the
151 * Matrix3d parameter.
152 * @param m1 the source matrix
154 public Matrix3d(Matrix3d m1)
171 * Constructs a new matrix with the same values as the
172 * Matrix3f parameter.
173 * @param m1 the source matrix
175 public Matrix3d(Matrix3f m1)
192 * Constructs and initializes a Matrix3d to all zeros.
211 * Returns a string that contains the values of this Matrix3d.
212 * @return the String representation
214 public String toString() {
216 this.m00 + ", " + this.m01 + ", " + this.m02 + "\n" +
217 this.m10 + ", " + this.m11 + ", " + this.m12 + "\n" +
218 this.m20 + ", " + this.m21 + ", " + this.m22 + "\n";
222 * Sets this Matrix3d to identity.
224 public final void setIdentity()
240 * Sets the scale component of the current matrix by factoring
241 * out the current scale (by doing an SVD) and multiplying by
243 * @param scale the new scale amount
245 public final void setScale(double scale)
248 double[] tmp_rot = new double[9]; // scratch matrix
249 double[] tmp_scale = new double[3]; // scratch matrix
251 getScaleRotate(tmp_scale, tmp_rot);
253 this.m00 = tmp_rot[0] * scale;
254 this.m01 = tmp_rot[1] * scale;
255 this.m02 = tmp_rot[2] * scale;
257 this.m10 = tmp_rot[3] * scale;
258 this.m11 = tmp_rot[4] * scale;
259 this.m12 = tmp_rot[5] * scale;
261 this.m20 = tmp_rot[6] * scale;
262 this.m21 = tmp_rot[7] * scale;
263 this.m22 = tmp_rot[8] * scale;
267 * Sets the specified element of this matrix3f to the value provided.
268 * @param row the row number to be modified (zero indexed)
269 * @param column the column number to be modified (zero indexed)
270 * @param value the new value
272 public final void setElement(int row, int column, double value)
289 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
306 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
324 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
329 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d0"));
334 * Retrieves the value at the specified row and column of the specified
336 * @param row the row number to be retrieved (zero indexed)
337 * @param column the column number to be retrieved (zero indexed)
338 * @return the value at the indexed element.
340 public final double getElement(int row, int column)
389 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d1"));
393 * Copies the matrix values in the specified row into the vector parameter.
394 * @param row the matrix row
395 * @param v the vector into which the matrix row values will be copied
397 public final void getRow(int row, Vector3d v) {
402 } else if(row == 1) {
406 } else if(row == 2) {
411 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d2"));
417 * Copies the matrix values in the specified row into the array parameter.
418 * @param row the matrix row
419 * @param v the array into which the matrix row values will be copied
421 public final void getRow(int row, double v[]) {
426 } else if(row == 1) {
430 } else if(row == 2) {
435 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d2"));
441 * Copies the matrix values in the specified column into the vector
443 * @param column the matrix column
444 * @param v the vector into which the matrix row values will be copied
446 public final void getColumn(int column, Vector3d v) {
451 } else if(column == 1) {
455 }else if(column == 2){
460 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d4"));
466 * Copies the matrix values in the specified column into the array
468 * @param column the matrix column
469 * @param v the array into which the matrix row values will be copied
471 public final void getColumn(int column, double v[]) {
476 } else if(column == 1) {
480 }else if(column == 2) {
485 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d4"));
492 * Sets the specified row of this matrix3d to the 4 values provided.
493 * @param row the row number to be modified (zero indexed)
494 * @param x the first column element
495 * @param y the second column element
496 * @param z the third column element
498 public final void setRow(int row, double x, double y, double z)
520 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6"));
525 * Sets the specified row of this matrix3d to the Vector provided.
526 * @param row the row number to be modified (zero indexed)
527 * @param v the replacement row
529 public final void setRow(int row, Vector3d v)
551 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6"));
556 * Sets the specified row of this matrix3d to the three values provided.
557 * @param row the row number to be modified (zero indexed)
558 * @param v the replacement row
560 public final void setRow(int row, double v[])
582 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d6"));
587 * Sets the specified column of this matrix3d to the three values provided.
588 * @param column the column number to be modified (zero indexed)
589 * @param x the first row element
590 * @param y the second row element
591 * @param z the third row element
593 public final void setColumn(int column, double x, double y, double z)
615 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9"));
620 * Sets the specified column of this matrix3d to the vector provided.
621 * @param column the column number to be modified (zero indexed)
622 * @param v the replacement column
624 public final void setColumn(int column, Vector3d v)
646 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9"));
651 * Sets the specified column of this matrix3d to the three values provided.
652 * @param column the column number to be modified (zero indexed)
653 * @param v the replacement column
655 public final void setColumn(int column, double v[])
677 throw new ArrayIndexOutOfBoundsException(VecMathI18N.getString("Matrix3d9"));
682 * Performs an SVD normalization of this matrix to calculate
683 * and return the uniform scale factor. If the matrix has non-uniform
684 * scale factors, the largest of the x, y, and z scale factors will
685 * be returned. This matrix is not modified.
686 * @return the scale factor of this matrix
688 public final double getScale()
691 double[] tmp_scale = new double[3]; // scratch matrix
692 double[] tmp_rot = new double[9]; // scratch matrix
693 getScaleRotate(tmp_scale, tmp_rot);
695 return( max3(tmp_scale) );
700 * Adds a scalar to each component of this matrix.
701 * @param scalar the scalar adder
703 public final void add(double scalar)
720 * Adds a scalar to each component of the matrix m1 and places
721 * the result into this. Matrix m1 is not modified.
722 * @param scalar the scalar adder
723 * @param m1 the original matrix values
725 public final void add(double scalar, Matrix3d m1)
727 this.m00 = m1.m00 + scalar;
728 this.m01 = m1.m01 + scalar;
729 this.m02 = m1.m02 + scalar;
731 this.m10 = m1.m10 + scalar;
732 this.m11 = m1.m11 + scalar;
733 this.m12 = m1.m12 + scalar;
735 this.m20 = m1.m20 + scalar;
736 this.m21 = m1.m21 + scalar;
737 this.m22 = m1.m22 + scalar;
741 * Sets the value of this matrix to the matrix sum of matrices m1 and m2.
742 * @param m1 the first matrix
743 * @param m2 the second matrix
745 public final void add(Matrix3d m1, Matrix3d m2)
747 this.m00 = m1.m00 + m2.m00;
748 this.m01 = m1.m01 + m2.m01;
749 this.m02 = m1.m02 + m2.m02;
751 this.m10 = m1.m10 + m2.m10;
752 this.m11 = m1.m11 + m2.m11;
753 this.m12 = m1.m12 + m2.m12;
755 this.m20 = m1.m20 + m2.m20;
756 this.m21 = m1.m21 + m2.m21;
757 this.m22 = m1.m22 + m2.m22;
761 * Sets the value of this matrix to the sum of itself and matrix m1.
762 * @param m1 the other matrix
764 public final void add(Matrix3d m1)
780 * Sets the value of this matrix to the matrix difference
781 * of matrices m1 and m2.
782 * @param m1 the first matrix
783 * @param m2 the second matrix
785 public final void sub(Matrix3d m1, Matrix3d m2)
787 this.m00 = m1.m00 - m2.m00;
788 this.m01 = m1.m01 - m2.m01;
789 this.m02 = m1.m02 - m2.m02;
791 this.m10 = m1.m10 - m2.m10;
792 this.m11 = m1.m11 - m2.m11;
793 this.m12 = m1.m12 - m2.m12;
795 this.m20 = m1.m20 - m2.m20;
796 this.m21 = m1.m21 - m2.m21;
797 this.m22 = m1.m22 - m2.m22;
801 * Sets the value of this matrix to the matrix difference of itself and
802 * matrix m1 (this = this - m1).
803 * @param m1 the other matrix
805 public final void sub(Matrix3d m1)
821 * Sets the value of this matrix to its transpose.
823 public final void transpose()
841 * Sets the value of this matrix to the transpose of the argument matrix.
842 * @param m1 the matrix to be transposed
844 public final void transpose(Matrix3d m1)
863 * Sets the value of this matrix to the matrix conversion of the
864 * double precision quaternion argument.
865 * @param q1 the quaternion to be converted
867 public final void set(Quat4d q1)
869 this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
870 this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z));
871 this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y));
873 this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z));
874 this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
875 this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x));
877 this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y));
878 this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x));
879 this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
883 * Sets the value of this matrix to the matrix conversion of the
884 * double precision axis and angle argument.
885 * @param a1 the axis and angle to be converted
887 public final void set(AxisAngle4d a1)
889 double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
905 double ax = a1.x*mag;
906 double ay = a1.y*mag;
907 double az = a1.z*mag;
909 double sinTheta = Math.sin(a1.angle);
910 double cosTheta = Math.cos(a1.angle);
911 double t = 1.0 - cosTheta;
917 m00 = t * ax * ax + cosTheta;
918 m01 = t * xy - sinTheta * az;
919 m02 = t * xz + sinTheta * ay;
921 m10 = t * xy + sinTheta * az;
922 m11 = t * ay * ay + cosTheta;
923 m12 = t * yz - sinTheta * ax;
925 m20 = t * xz - sinTheta * ay;
926 m21 = t * yz + sinTheta * ax;
927 m22 = t * az * az + cosTheta;
932 * Sets the value of this matrix to the matrix conversion of the
933 * single precision quaternion argument.
934 * @param q1 the quaternion to be converted
936 public final void set(Quat4f q1)
938 this.m00 = (1.0 - 2.0*q1.y*q1.y - 2.0*q1.z*q1.z);
939 this.m10 = (2.0*(q1.x*q1.y + q1.w*q1.z));
940 this.m20 = (2.0*(q1.x*q1.z - q1.w*q1.y));
942 this.m01 = (2.0*(q1.x*q1.y - q1.w*q1.z));
943 this.m11 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.z*q1.z);
944 this.m21 = (2.0*(q1.y*q1.z + q1.w*q1.x));
946 this.m02 = (2.0*(q1.x*q1.z + q1.w*q1.y));
947 this.m12 = (2.0*(q1.y*q1.z - q1.w*q1.x));
948 this.m22 = (1.0 - 2.0*q1.x*q1.x - 2.0*q1.y*q1.y);
952 * Sets the value of this matrix to the matrix conversion of the
953 * single precision axis and angle argument.
954 * @param a1 the axis and angle to be converted
956 public final void set(AxisAngle4f a1)
958 double mag = Math.sqrt( a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
973 double ax = a1.x*mag;
974 double ay = a1.y*mag;
975 double az = a1.z*mag;
976 double sinTheta = Math.sin(a1.angle);
977 double cosTheta = Math.cos(a1.angle);
978 double t = 1.0 - cosTheta;
984 m00 = t * ax * ax + cosTheta;
985 m01 = t * xy - sinTheta * az;
986 m02 = t * xz + sinTheta * ay;
988 m10 = t * xy + sinTheta * az;
989 m11 = t * ay * ay + cosTheta;
990 m12 = t * yz - sinTheta * ax;
992 m20 = t * xz - sinTheta * ay;
993 m21 = t * yz + sinTheta * ax;
994 m22 = t * az * az + cosTheta;
999 * Sets the value of this matrix to the double value of the Matrix3f
1001 * @param m1 the matrix3d to be converted to double
1003 public final void set(Matrix3f m1)
1019 * Sets the value of this matrix to the value of the Matrix3d
1021 * @param m1 the source matrix3d
1023 public final void set(Matrix3d m1)
1039 * Sets the values in this Matrix3d equal to the row-major
1040 * array parameter (ie, the first three elements of the
1041 * array will be copied into the first row of this matrix, etc.).
1042 * @param m the double precision array of length 9
1044 public final void set(double[] m)
1061 * Sets the value of this matrix to the matrix inverse
1062 * of the passed matrix m1.
1063 * @param m1 the matrix to be inverted
1065 public final void invert(Matrix3d m1)
1067 invertGeneral( m1 );
1071 * Inverts this matrix in place.
1073 public final void invert()
1075 invertGeneral( this );
1079 * General invert routine. Inverts m1 and places the result in "this".
1080 * Note that this routine handles both the "this" version and the
1081 * non-"this" version.
1083 * Also note that since this routine is slow anyway, we won't worry
1084 * about allocating a little bit of garbage.
1086 private final void invertGeneral(Matrix3d m1) {
1087 double result[] = new double[9];
1088 int row_perm[] = new int[3];
1090 double[] tmp = new double[9]; // scratch matrix
1092 // Use LU decomposition and backsubstitution code specifically
1093 // for floating-point 3x3 matrices.
1095 // Copy source matrix to t1tmp
1109 // Calculate LU decomposition: Is the matrix singular?
1110 if (!luDecomposition(tmp, row_perm)) {
1111 // Matrix has no inverse
1112 throw new SingularMatrixException(VecMathI18N.getString("Matrix3d12"));
1115 // Perform back substitution on the identity matrix
1116 for(i=0;i<9;i++) result[i] = 0.0;
1117 result[0] = 1.0; result[4] = 1.0; result[8] = 1.0;
1118 luBacksubstitution(tmp, row_perm, result);
1120 this.m00 = result[0];
1121 this.m01 = result[1];
1122 this.m02 = result[2];
1124 this.m10 = result[3];
1125 this.m11 = result[4];
1126 this.m12 = result[5];
1128 this.m20 = result[6];
1129 this.m21 = result[7];
1130 this.m22 = result[8];
1135 * Given a 3x3 array "matrix0", this function replaces it with the
1136 * LU decomposition of a row-wise permutation of itself. The input
1137 * parameters are "matrix0" and "dimen". The array "matrix0" is also
1138 * an output parameter. The vector "row_perm[3]" is an output
1139 * parameter that contains the row permutations resulting from partial
1140 * pivoting. The output parameter "even_row_xchg" is 1 when the
1141 * number of row exchanges is even, or -1 otherwise. Assumes data
1142 * type is always double.
1144 * This function is similar to luDecomposition, except that it
1145 * is tuned specifically for 3x3 matrices.
1147 * @return true if the matrix is nonsingular, or false otherwise.
1150 // Reference: Press, Flannery, Teukolsky, Vetterling,
1151 // _Numerical_Recipes_in_C_, Cambridge University Press,
1154 static boolean luDecomposition(double[] matrix0,
1157 double row_scale[] = new double[3];
1159 // Determine implicit scaling information by looping over rows
1173 // For each column, find the largest element in the row
1176 temp = matrix0[ptr++];
1177 temp = Math.abs(temp);
1183 // Is the matrix singular?
1187 row_scale[rs++] = 1.0 / big;
1197 // For all columns, execute Crout's method
1198 for (j = 0; j < 3; j++) {
1201 double sum, big, temp;
1203 // Determine elements of upper diagonal matrix U
1204 for (i = 0; i < j; i++) {
1205 target = mtx + (3*i) + j;
1206 sum = matrix0[target];
1211 sum -= matrix0[p1] * matrix0[p2];
1215 matrix0[target] = sum;
1218 // Search for largest pivot element and calculate
1219 // intermediate elements of lower diagonal matrix L.
1222 for (i = j; i < 3; i++) {
1223 target = mtx + (3*i) + j;
1224 sum = matrix0[target];
1229 sum -= matrix0[p1] * matrix0[p2];
1233 matrix0[target] = sum;
1235 // Is this the best pivot so far?
1236 if ((temp = row_scale[i] * Math.abs(sum)) >= big) {
1243 throw new RuntimeException(VecMathI18N.getString("Matrix3d13"));
1246 // Is a row exchange necessary?
1248 // Yes: exchange rows
1250 p1 = mtx + (3*imax);
1254 matrix0[p1++] = matrix0[p2];
1255 matrix0[p2++] = temp;
1258 // Record change in scale factor
1259 row_scale[imax] = row_scale[j];
1262 // Record row permutation
1265 // Is the matrix singular
1266 if (matrix0[(mtx + (3*j) + j)] == 0.0) {
1270 // Divide elements of lower diagonal matrix L by pivot
1272 temp = 1.0 / (matrix0[(mtx + (3*j) + j)]);
1273 target = mtx + (3*(j+1)) + j;
1276 matrix0[target] *= temp;
1287 * Solves a set of linear equations. The input parameters "matrix1",
1288 * and "row_perm" come from luDecompostionD3x3 and do not change
1289 * here. The parameter "matrix2" is a set of column vectors assembled
1290 * into a 3x3 matrix of floating-point values. The procedure takes each
1291 * column of "matrix2" in turn and treats it as the right-hand side of the
1292 * matrix equation Ax = LUx = b. The solution vector replaces the
1293 * original column of the matrix.
1295 * If "matrix2" is the identity matrix, the procedure replaces its contents
1296 * with the inverse of the matrix from which "matrix1" was originally
1300 // Reference: Press, Flannery, Teukolsky, Vetterling,
1301 // _Numerical_Recipes_in_C_, Cambridge University Press,
1304 static void luBacksubstitution(double[] matrix1,
1308 int i, ii, ip, j, k;
1315 // For each column vector of matrix2 ...
1316 for (k = 0; k < 3; k++) {
1317 // cv = &(matrix2[0][k]);
1321 // Forward substitution
1322 for (i = 0; i < 3; i++) {
1325 ip = row_perm[rp+i];
1326 sum = matrix2[cv+3*ip];
1327 matrix2[cv+3*ip] = matrix2[cv+3*i];
1329 // rv = &(matrix1[i][0]);
1331 for (j = ii; j <= i-1; j++) {
1332 sum -= matrix1[rv+j] * matrix2[cv+3*j];
1335 else if (sum != 0.0) {
1338 matrix2[cv+3*i] = sum;
1342 // rv = &(matrix1[3][0]);
1344 matrix2[cv+3*2] /= matrix1[rv+2];
1347 matrix2[cv+3*1] = (matrix2[cv+3*1] -
1348 matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+1];
1351 matrix2[cv+4*0] = (matrix2[cv+3*0] -
1352 matrix1[rv+1] * matrix2[cv+3*1] -
1353 matrix1[rv+2] * matrix2[cv+3*2]) / matrix1[rv+0];
1359 * Computes the determinant of this matrix.
1360 * @return the determinant of the matrix
1362 public final double determinant()
1366 total = this.m00*(this.m11*this.m22 - this.m12*this.m21)
1367 + this.m01*(this.m12*this.m20 - this.m10*this.m22)
1368 + this.m02*(this.m10*this.m21 - this.m11*this.m20);
1373 * Sets the value of this matrix to a scale matrix with
1374 * the passed scale amount.
1375 * @param scale the scale factor for the matrix
1377 public final void set(double scale)
1393 * Sets the value of this matrix to a counter clockwise rotation
1395 * @param angle the angle to rotate about the X axis in radians
1397 public final void rotX(double angle)
1399 double sinAngle, cosAngle;
1401 sinAngle = Math.sin(angle);
1402 cosAngle = Math.cos(angle);
1409 this.m11 = cosAngle;
1410 this.m12 = -sinAngle;
1413 this.m21 = sinAngle;
1414 this.m22 = cosAngle;
1418 * Sets the value of this matrix to a counter clockwise rotation
1420 * @param angle the angle to rotate about the Y axis in radians
1422 public final void rotY(double angle)
1424 double sinAngle, cosAngle;
1426 sinAngle = Math.sin(angle);
1427 cosAngle = Math.cos(angle);
1429 this.m00 = cosAngle;
1431 this.m02 = sinAngle;
1437 this.m20 = -sinAngle;
1439 this.m22 = cosAngle;
1443 * Sets the value of this matrix to a counter clockwise rotation
1445 * @param angle the angle to rotate about the Z axis in radians
1447 public final void rotZ(double angle)
1449 double sinAngle, cosAngle;
1451 sinAngle = Math.sin(angle);
1452 cosAngle = Math.cos(angle);
1454 this.m00 = cosAngle;
1455 this.m01 = -sinAngle;
1458 this.m10 = sinAngle;
1459 this.m11 = cosAngle;
1468 * Multiplies each element of this matrix by a scalar.
1469 * @param scalar The scalar multiplier.
1471 public final void mul(double scalar)
1488 * Multiplies each element of matrix m1 by a scalar and places
1489 * the result into this. Matrix m1 is not modified.
1490 * @param scalar the scalar multiplier
1491 * @param m1 the original matrix
1493 public final void mul(double scalar, Matrix3d m1)
1495 this.m00 = scalar * m1.m00;
1496 this.m01 = scalar * m1.m01;
1497 this.m02 = scalar * m1.m02;
1499 this.m10 = scalar * m1.m10;
1500 this.m11 = scalar * m1.m11;
1501 this.m12 = scalar * m1.m12;
1503 this.m20 = scalar * m1.m20;
1504 this.m21 = scalar * m1.m21;
1505 this.m22 = scalar * m1.m22;
1510 * Sets the value of this matrix to the result of multiplying itself
1512 * @param m1 the other matrix
1514 public final void mul(Matrix3d m1)
1516 double m00, m01, m02,
1520 m00 = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20;
1521 m01 = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21;
1522 m02 = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22;
1524 m10 = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20;
1525 m11 = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21;
1526 m12 = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22;
1528 m20 = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20;
1529 m21 = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21;
1530 m22 = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22;
1532 this.m00 = m00; this.m01 = m01; this.m02 = m02;
1533 this.m10 = m10; this.m11 = m11; this.m12 = m12;
1534 this.m20 = m20; this.m21 = m21; this.m22 = m22;
1538 * Sets the value of this matrix to the result of multiplying
1539 * the two argument matrices together.
1540 * @param m1 the first matrix
1541 * @param m2 the second matrix
1543 public final void mul(Matrix3d m1, Matrix3d m2)
1545 if (this != m1 && this != m2) {
1546 this.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
1547 this.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
1548 this.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
1550 this.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
1551 this.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
1552 this.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
1554 this.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
1555 this.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
1556 this.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
1558 double m00, m01, m02,
1560 m20, m21, m22; // vars for temp result matrix
1562 m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
1563 m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
1564 m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
1566 m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
1567 m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
1568 m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
1570 m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
1571 m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
1572 m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
1574 this.m00 = m00; this.m01 = m01; this.m02 = m02;
1575 this.m10 = m10; this.m11 = m11; this.m12 = m12;
1576 this.m20 = m20; this.m21 = m21; this.m22 = m22;
1581 * Multiplies this matrix by matrix m1, does an SVD normalization
1582 * of the result, and places the result back into this matrix
1583 * this = SVDnorm(this*m1).
1584 * @param m1 the matrix on the right hand side of the multiplication
1586 public final void mulNormalize(Matrix3d m1){
1588 double[] tmp = new double[9]; // scratch matrix
1589 double[] tmp_rot = new double[9]; // scratch matrix
1590 double[] tmp_scale = new double[3]; // scratch matrix
1592 tmp[0] = this.m00*m1.m00 + this.m01*m1.m10 + this.m02*m1.m20;
1593 tmp[1] = this.m00*m1.m01 + this.m01*m1.m11 + this.m02*m1.m21;
1594 tmp[2] = this.m00*m1.m02 + this.m01*m1.m12 + this.m02*m1.m22;
1596 tmp[3] = this.m10*m1.m00 + this.m11*m1.m10 + this.m12*m1.m20;
1597 tmp[4] = this.m10*m1.m01 + this.m11*m1.m11 + this.m12*m1.m21;
1598 tmp[5] = this.m10*m1.m02 + this.m11*m1.m12 + this.m12*m1.m22;
1600 tmp[6] = this.m20*m1.m00 + this.m21*m1.m10 + this.m22*m1.m20;
1601 tmp[7] = this.m20*m1.m01 + this.m21*m1.m11 + this.m22*m1.m21;
1602 tmp[8] = this.m20*m1.m02 + this.m21*m1.m12 + this.m22*m1.m22;
1604 compute_svd( tmp, tmp_scale, tmp_rot);
1606 this.m00 = tmp_rot[0];
1607 this.m01 = tmp_rot[1];
1608 this.m02 = tmp_rot[2];
1610 this.m10 = tmp_rot[3];
1611 this.m11 = tmp_rot[4];
1612 this.m12 = tmp_rot[5];
1614 this.m20 = tmp_rot[6];
1615 this.m21 = tmp_rot[7];
1616 this.m22 = tmp_rot[8];
1622 * Multiplies matrix m1 by matrix m2, does an SVD normalization
1623 * of the result, and places the result into this matrix
1624 * this = SVDnorm(m1*m2).
1625 * @param m1 the matrix on the left hand side of the multiplication
1626 * @param m2 the matrix on the right hand side of the multiplication
1628 public final void mulNormalize(Matrix3d m1, Matrix3d m2){
1630 double[] tmp = new double[9]; // scratch matrix
1631 double[] tmp_rot = new double[9]; // scratch matrix
1632 double[] tmp_scale = new double[3]; // scratch matrix
1634 tmp[0] = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
1635 tmp[1] = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
1636 tmp[2] = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
1638 tmp[3] = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
1639 tmp[4] = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
1640 tmp[5] = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
1642 tmp[6] = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
1643 tmp[7] = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
1644 tmp[8] = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
1646 compute_svd( tmp, tmp_scale, tmp_rot);
1648 this.m00 = tmp_rot[0];
1649 this.m01 = tmp_rot[1];
1650 this.m02 = tmp_rot[2];
1652 this.m10 = tmp_rot[3];
1653 this.m11 = tmp_rot[4];
1654 this.m12 = tmp_rot[5];
1656 this.m20 = tmp_rot[6];
1657 this.m21 = tmp_rot[7];
1658 this.m22 = tmp_rot[8];
1663 * Multiplies the transpose of matrix m1 times the transpose of matrix
1664 * m2, and places the result into this.
1665 * @param m1 the matrix on the left hand side of the multiplication
1666 * @param m2 the matrix on the right hand side of the multiplication
1668 public final void mulTransposeBoth(Matrix3d m1, Matrix3d m2)
1670 if (this != m1 && this != m2) {
1671 this.m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02;
1672 this.m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12;
1673 this.m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22;
1675 this.m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02;
1676 this.m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12;
1677 this.m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22;
1679 this.m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02;
1680 this.m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12;
1681 this.m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22;
1683 double m00, m01, m02,
1685 m20, m21, m22; // vars for temp result matrix
1687 m00 = m1.m00*m2.m00 + m1.m10*m2.m01 + m1.m20*m2.m02;
1688 m01 = m1.m00*m2.m10 + m1.m10*m2.m11 + m1.m20*m2.m12;
1689 m02 = m1.m00*m2.m20 + m1.m10*m2.m21 + m1.m20*m2.m22;
1691 m10 = m1.m01*m2.m00 + m1.m11*m2.m01 + m1.m21*m2.m02;
1692 m11 = m1.m01*m2.m10 + m1.m11*m2.m11 + m1.m21*m2.m12;
1693 m12 = m1.m01*m2.m20 + m1.m11*m2.m21 + m1.m21*m2.m22;
1695 m20 = m1.m02*m2.m00 + m1.m12*m2.m01 + m1.m22*m2.m02;
1696 m21 = m1.m02*m2.m10 + m1.m12*m2.m11 + m1.m22*m2.m12;
1697 m22 = m1.m02*m2.m20 + m1.m12*m2.m21 + m1.m22*m2.m22;
1699 this.m00 = m00; this.m01 = m01; this.m02 = m02;
1700 this.m10 = m10; this.m11 = m11; this.m12 = m12;
1701 this.m20 = m20; this.m21 = m21; this.m22 = m22;
1707 * Multiplies matrix m1 times the transpose of matrix m2, and
1708 * places the result into this.
1709 * @param m1 the matrix on the left hand side of the multiplication
1710 * @param m2 the matrix on the right hand side of the multiplication
1712 public final void mulTransposeRight(Matrix3d m1, Matrix3d m2)
1714 if (this != m1 && this != m2) {
1715 this.m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02;
1716 this.m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12;
1717 this.m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22;
1719 this.m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02;
1720 this.m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12;
1721 this.m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22;
1723 this.m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02;
1724 this.m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12;
1725 this.m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22;
1727 double m00, m01, m02,
1729 m20, m21, m22; // vars for temp result matrix
1731 m00 = m1.m00*m2.m00 + m1.m01*m2.m01 + m1.m02*m2.m02;
1732 m01 = m1.m00*m2.m10 + m1.m01*m2.m11 + m1.m02*m2.m12;
1733 m02 = m1.m00*m2.m20 + m1.m01*m2.m21 + m1.m02*m2.m22;
1735 m10 = m1.m10*m2.m00 + m1.m11*m2.m01 + m1.m12*m2.m02;
1736 m11 = m1.m10*m2.m10 + m1.m11*m2.m11 + m1.m12*m2.m12;
1737 m12 = m1.m10*m2.m20 + m1.m11*m2.m21 + m1.m12*m2.m22;
1739 m20 = m1.m20*m2.m00 + m1.m21*m2.m01 + m1.m22*m2.m02;
1740 m21 = m1.m20*m2.m10 + m1.m21*m2.m11 + m1.m22*m2.m12;
1741 m22 = m1.m20*m2.m20 + m1.m21*m2.m21 + m1.m22*m2.m22;
1743 this.m00 = m00; this.m01 = m01; this.m02 = m02;
1744 this.m10 = m10; this.m11 = m11; this.m12 = m12;
1745 this.m20 = m20; this.m21 = m21; this.m22 = m22;
1751 * Multiplies the transpose of matrix m1 times matrix m2, and
1752 * places the result into this.
1753 * @param m1 the matrix on the left hand side of the multiplication
1754 * @param m2 the matrix on the right hand side of the multiplication
1756 public final void mulTransposeLeft(Matrix3d m1, Matrix3d m2) {
1757 if (this != m1 && this != m2) {
1758 this.m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20;
1759 this.m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21;
1760 this.m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22;
1762 this.m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20;
1763 this.m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21;
1764 this.m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22;
1766 this.m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20;
1767 this.m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21;
1768 this.m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22;
1770 double m00, m01, m02,
1772 m20, m21, m22; // vars for temp result matrix
1774 m00 = m1.m00*m2.m00 + m1.m10*m2.m10 + m1.m20*m2.m20;
1775 m01 = m1.m00*m2.m01 + m1.m10*m2.m11 + m1.m20*m2.m21;
1776 m02 = m1.m00*m2.m02 + m1.m10*m2.m12 + m1.m20*m2.m22;
1778 m10 = m1.m01*m2.m00 + m1.m11*m2.m10 + m1.m21*m2.m20;
1779 m11 = m1.m01*m2.m01 + m1.m11*m2.m11 + m1.m21*m2.m21;
1780 m12 = m1.m01*m2.m02 + m1.m11*m2.m12 + m1.m21*m2.m22;
1782 m20 = m1.m02*m2.m00 + m1.m12*m2.m10 + m1.m22*m2.m20;
1783 m21 = m1.m02*m2.m01 + m1.m12*m2.m11 + m1.m22*m2.m21;
1784 m22 = m1.m02*m2.m02 + m1.m12*m2.m12 + m1.m22*m2.m22;
1786 this.m00 = m00; this.m01 = m01; this.m02 = m02;
1787 this.m10 = m10; this.m11 = m11; this.m12 = m12;
1788 this.m20 = m20; this.m21 = m21; this.m22 = m22;
1795 * Performs singular value decomposition normalization of this matrix.
1797 public final void normalize(){
1798 double[] tmp_rot = new double[9]; // scratch matrix
1799 double[] tmp_scale = new double[3]; // scratch matrix
1801 getScaleRotate( tmp_scale, tmp_rot );
1803 this.m00 = tmp_rot[0];
1804 this.m01 = tmp_rot[1];
1805 this.m02 = tmp_rot[2];
1807 this.m10 = tmp_rot[3];
1808 this.m11 = tmp_rot[4];
1809 this.m12 = tmp_rot[5];
1811 this.m20 = tmp_rot[6];
1812 this.m21 = tmp_rot[7];
1813 this.m22 = tmp_rot[8];
1819 * Perform singular value decomposition normalization of matrix m1 and
1820 * place the normalized values into this.
1821 * @param m1 Provides the matrix values to be normalized
1823 public final void normalize(Matrix3d m1){
1825 double[] tmp = new double[9]; // scratch matrix
1826 double[] tmp_rot = new double[9]; // scratch matrix
1827 double[] tmp_scale = new double[3]; // scratch matrix
1841 compute_svd( tmp, tmp_scale, tmp_rot);
1843 this.m00 = tmp_rot[0];
1844 this.m01 = tmp_rot[1];
1845 this.m02 = tmp_rot[2];
1847 this.m10 = tmp_rot[3];
1848 this.m11 = tmp_rot[4];
1849 this.m12 = tmp_rot[5];
1851 this.m20 = tmp_rot[6];
1852 this.m21 = tmp_rot[7];
1853 this.m22 = tmp_rot[8];
1858 * Perform cross product normalization of this matrix.
1861 public final void normalizeCP()
1863 double mag = 1.0/Math.sqrt(m00*m00 + m10*m10 + m20*m20);
1868 mag = 1.0/Math.sqrt(m01*m01 + m11*m11 + m21*m21);
1873 m02 = m10*m21 - m11*m20;
1874 m12 = m01*m20 - m00*m21;
1875 m22 = m00*m11 - m01*m10;
1880 * Perform cross product normalization of matrix m1 and place the
1881 * normalized values into this.
1882 * @param m1 Provides the matrix values to be normalized
1884 public final void normalizeCP(Matrix3d m1)
1886 double mag = 1.0/Math.sqrt(m1.m00*m1.m00 + m1.m10*m1.m10 + m1.m20*m1.m20);
1891 mag = 1.0/Math.sqrt(m1.m01*m1.m01 + m1.m11*m1.m11 + m1.m21*m1.m21);
1896 m02 = m10*m21 - m11*m20;
1897 m12 = m01*m20 - m00*m21;
1898 m22 = m00*m11 - m01*m10;
1902 * Returns true if all of the data members of Matrix3d m1 are
1903 * equal to the corresponding data members in this Matrix3d.
1904 * @param m1 the matrix with which the comparison is made
1905 * @return true or false
1907 public boolean equals(Matrix3d m1)
1910 return(this.m00 == m1.m00 && this.m01 == m1.m01 && this.m02 == m1.m02
1911 && this.m10 == m1.m10 && this.m11 == m1.m11 && this.m12 == m1.m12
1912 && this.m20 == m1.m20 && this.m21 == m1.m21 && this.m22 == m1.m22);
1914 catch (NullPointerException e2) { return false; }
1919 * Returns true if the Object t1 is of type Matrix3d and all of the
1920 * data members of t1 are equal to the corresponding data members in
1922 * @param t1 the matrix with which the comparison is made
1923 * @return true or false
1925 public boolean equals(Object t1)
1928 Matrix3d m2 = (Matrix3d) t1;
1929 return(this.m00 == m2.m00 && this.m01 == m2.m01 && this.m02 == m2.m02
1930 && this.m10 == m2.m10 && this.m11 == m2.m11 && this.m12 == m2.m12
1931 && this.m20 == m2.m20 && this.m21 == m2.m21 && this.m22 == m2.m22);
1933 catch (ClassCastException e1) { return false; }
1934 catch (NullPointerException e2) { return false; }
1939 * Returns true if the L-infinite distance between this matrix
1940 * and matrix m1 is less than or equal to the epsilon parameter,
1941 * otherwise returns false. The L-infinite
1942 * distance is equal to
1943 * MAX[i=0,1,2 ; j=0,1,2 ; abs(this.m(i,j) - m1.m(i,j)]
1944 * @param m1 the matrix to be compared to this matrix
1945 * @param epsilon the threshold value
1947 public boolean epsilonEquals(Matrix3d m1, double epsilon)
1951 diff = m00 - m1.m00;
1952 if((diff<0?-diff:diff) > epsilon) return false;
1954 diff = m01 - m1.m01;
1955 if((diff<0?-diff:diff) > epsilon) return false;
1957 diff = m02 - m1.m02;
1958 if((diff<0?-diff:diff) > epsilon) return false;
1960 diff = m10 - m1.m10;
1961 if((diff<0?-diff:diff) > epsilon) return false;
1963 diff = m11 - m1.m11;
1964 if((diff<0?-diff:diff) > epsilon) return false;
1966 diff = m12 - m1.m12;
1967 if((diff<0?-diff:diff) > epsilon) return false;
1969 diff = m20 - m1.m20;
1970 if((diff<0?-diff:diff) > epsilon) return false;
1972 diff = m21 - m1.m21;
1973 if((diff<0?-diff:diff) > epsilon) return false;
1975 diff = m22 - m1.m22;
1976 if((diff<0?-diff:diff) > epsilon) return false;
1983 * Returns a hash code value based on the data values in this
1984 * object. Two different Matrix3d objects with identical data values
1985 * (i.e., Matrix3d.equals returns true) will return the same hash
1986 * code value. Two objects with different data members may return the
1987 * same hash value, although this is not likely.
1988 * @return the integer hash code value
1990 public int hashCode() {
1992 bits = 31L * bits + VecMathUtil.doubleToLongBits(m00);
1993 bits = 31L * bits + VecMathUtil.doubleToLongBits(m01);
1994 bits = 31L * bits + VecMathUtil.doubleToLongBits(m02);
1995 bits = 31L * bits + VecMathUtil.doubleToLongBits(m10);
1996 bits = 31L * bits + VecMathUtil.doubleToLongBits(m11);
1997 bits = 31L * bits + VecMathUtil.doubleToLongBits(m12);
1998 bits = 31L * bits + VecMathUtil.doubleToLongBits(m20);
1999 bits = 31L * bits + VecMathUtil.doubleToLongBits(m21);
2000 bits = 31L * bits + VecMathUtil.doubleToLongBits(m22);
2001 return (int) (bits ^ (bits >> 32));
2006 * Sets this matrix to all zeros.
2008 public final void setZero()
2025 * Negates the value of this matrix: this = -this.
2027 public final void negate()
2029 this.m00 = -this.m00;
2030 this.m01 = -this.m01;
2031 this.m02 = -this.m02;
2033 this.m10 = -this.m10;
2034 this.m11 = -this.m11;
2035 this.m12 = -this.m12;
2037 this.m20 = -this.m20;
2038 this.m21 = -this.m21;
2039 this.m22 = -this.m22;
2044 * Sets the value of this matrix equal to the negation of
2045 * of the Matrix3d parameter.
2046 * @param m1 the source matrix
2048 public final void negate(Matrix3d m1)
2065 * Multiply this matrix by the tuple t and place the result
2066 * back into the tuple (t = this*t).
2067 * @param t the tuple to be multiplied by this matrix and then replaced
2069 public final void transform(Tuple3d t) {
2071 x = m00* t.x + m01*t.y + m02*t.z;
2072 y = m10* t.x + m11*t.y + m12*t.z;
2073 z = m20* t.x + m21*t.y + m22*t.z;
2078 * Multiply this matrix by the tuple t and and place the result
2079 * into the tuple "result" (result = this*t).
2080 * @param t the tuple to be multiplied by this matrix
2081 * @param result the tuple into which the product is placed
2083 public final void transform(Tuple3d t, Tuple3d result) {
2085 x = m00* t.x + m01*t.y + m02*t.z;
2086 y = m10* t.x + m11*t.y + m12*t.z;
2087 result.z = m20* t.x + m21*t.y + m22*t.z;
2093 * perform SVD (if necessary to get rotational component
2095 final void getScaleRotate(double scales[], double rots[]) {
2097 double[] tmp = new double[9]; // scratch matrix
2110 compute_svd( tmp, scales, rots);
2115 static void compute_svd( double[] m, double[] outScale, double[] outRot) {
2118 double[] u1 = new double[9];
2119 double[] v1 = new double[9];
2120 double[] t1 = new double[9];
2121 double[] t2 = new double[9];
2124 double[] single_values = t2;
2126 double[] rot = new double[9];
2127 double[] e = new double[3];
2128 double[] scales = new double[3];
2130 int converged, negCnt=0;
2142 if( m[3]*m[3] < EPS ) {
2143 u1[0] = 1.0; u1[1] = 0.0; u1[2] = 0.0;
2144 u1[3] = 0.0; u1[4] = 1.0; u1[5] = 0.0;
2145 u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0;
2146 } else if( m[0]*m[0] < EPS ) {
2154 m[3] = -tmp[0]; // zero
2158 u1[0] = 0.0; u1[1] = 1.0; u1[2] = 0.0;
2159 u1[3] = -1.0; u1[4] = 0.0; u1[5] = 0.0;
2160 u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0;
2162 g = 1.0/Math.sqrt(m[0]*m[0] + m[3]*m[3]);
2165 tmp[0] = c1*m[0] + s1*m[3];
2166 tmp[1] = c1*m[1] + s1*m[4];
2167 tmp[2] = c1*m[2] + s1*m[5];
2169 m[3] = -s1*m[0] + c1*m[3]; // zero
2170 m[4] = -s1*m[1] + c1*m[4];
2171 m[5] = -s1*m[2] + c1*m[5];
2176 u1[0] = c1; u1[1] = s1; u1[2] = 0.0;
2177 u1[3] = -s1; u1[4] = c1; u1[5] = 0.0;
2178 u1[6] = 0.0; u1[7] = 0.0; u1[8] = 1.0;
2183 if( m[6]*m[6] < EPS ) {
2184 } else if( m[0]*m[0] < EPS ){
2192 m[6] = -tmp[0]; // zero
2203 u1[6] = -tmp[0]; // zero
2207 g = 1.0/Math.sqrt(m[0]*m[0] + m[6]*m[6]);
2210 tmp[0] = c2*m[0] + s2*m[6];
2211 tmp[1] = c2*m[1] + s2*m[7];
2212 tmp[2] = c2*m[2] + s2*m[8];
2214 m[6] = -s2*m[0] + c2*m[6];
2215 m[7] = -s2*m[1] + c2*m[7];
2216 m[8] = -s2*m[2] + c2*m[8];
2236 if( m[2]*m[2] < EPS ) {
2237 v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0;
2238 v1[3] = 0.0; v1[4] = 1.0; v1[5] = 0.0;
2239 v1[6] = 0.0; v1[7] = 0.0; v1[8] = 1.0;
2240 } else if( m[1]*m[1] < EPS ) {
2248 m[1] = tmp[2]; // zero
2252 v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0;
2253 v1[3] = 0.0; v1[4] = 0.0; v1[5] =-1.0;
2254 v1[6] = 0.0; v1[7] = 1.0; v1[8] = 0.0;
2256 g = 1.0/Math.sqrt(m[1]*m[1] + m[2]*m[2]);
2259 tmp[1] = c3*m[1] + s3*m[2]; // can assign to m[1]?
2260 m[2] =-s3*m[1] + c3*m[2]; // zero
2263 tmp[4] = c3*m[4] + s3*m[5];
2264 m[5] =-s3*m[4] + c3*m[5];
2267 tmp[7] = c3*m[7] + s3*m[8];
2268 m[8] =-s3*m[7] + c3*m[8];
2271 v1[0] = 1.0; v1[1] = 0.0; v1[2] = 0.0;
2272 v1[3] = 0.0; v1[4] = c3; v1[5] = -s3;
2273 v1[6] = 0.0; v1[7] = s3; v1[8] = c3;
2278 if( m[7]*m[7] < EPS ) {
2279 } else if( m[4]*m[4] < EPS ) {
2283 m[3] = m[6]; // zero
2287 m[6] = -tmp[3]; // zero
2288 m[7] = -tmp[4]; // zero
2298 u1[6] = -tmp[3]; // zero
2303 g = 1.0/Math.sqrt(m[4]*m[4] + m[7]*m[7]);
2306 tmp[3] = c4*m[3] + s4*m[6];
2307 m[6] =-s4*m[3] + c4*m[6]; // zero
2310 tmp[4] = c4*m[4] + s4*m[7];
2311 m[7] =-s4*m[4] + c4*m[7];
2314 tmp[5] = c4*m[5] + s4*m[8];
2315 m[8] =-s4*m[5] + c4*m[8];
2318 tmp[3] = c4*u1[3] + s4*u1[6];
2319 u1[6] =-s4*u1[3] + c4*u1[6];
2322 tmp[4] = c4*u1[4] + s4*u1[7];
2323 u1[7] =-s4*u1[4] + c4*u1[7];
2326 tmp[5] = c4*u1[5] + s4*u1[8];
2327 u1[8] =-s4*u1[5] + c4*u1[8];
2331 single_values[0] = m[0];
2332 single_values[1] = m[4];
2333 single_values[2] = m[8];
2337 if( e[0]*e[0]<EPS && e[1]*e[1]<EPS ) {
2340 compute_qr( single_values, e, u1, v1);
2343 scales[0] = single_values[0];
2344 scales[1] = single_values[1];
2345 scales[2] = single_values[2];
2348 // Do some optimization here. If scale is unity, simply return the rotation matric.
2349 if(almostEqual(Math.abs(scales[0]), 1.0) &&
2350 almostEqual(Math.abs(scales[1]), 1.0) &&
2351 almostEqual(Math.abs(scales[2]), 1.0)) {
2352 // System.out.println("Scale components almost to 1.0");
2358 if((negCnt==0)||(negCnt==2)) {
2359 //System.out.println("Optimize!!");
2360 outScale[0] = outScale[1] = outScale[2] = 1.0;
2369 transpose_mat(u1, t1);
2370 transpose_mat(v1, t2);
2373 System.out.println("t1 is \n" + t1);
2374 System.out.println("t1="+t1[0]+" "+t1[1]+" "+t1[2]);
2375 System.out.println("t1="+t1[3]+" "+t1[4]+" "+t1[5]);
2376 System.out.println("t1="+t1[6]+" "+t1[7]+" "+t1[8]);
2378 System.out.println("t2 is \n" + t2);
2379 System.out.println("t2="+t2[0]+" "+t2[1]+" "+t2[2]);
2380 System.out.println("t2="+t2[3]+" "+t2[4]+" "+t2[5]);
2381 System.out.println("t2="+t2[6]+" "+t2[7]+" "+t2[8]);
2384 svdReorder( m, t1, t2, scales, outRot, outScale);
2388 static void svdReorder( double[] m, double[] t1, double[] t2, double[] scales,
2389 double[] outRot, double[] outScale) {
2391 int[] out = new int[3];
2392 int[] in = new int[3];
2393 int in0, in1, in2, index, i;
2394 double[] mag = new double[3];
2395 double[] rot = new double[9];
2398 // check for rotation information in the scales
2399 if(scales[0] < 0.0 ) { // move the rotation info to rotation matrix
2400 scales[0] = -scales[0];
2405 if(scales[1] < 0.0 ) { // move the rotation info to rotation matrix
2406 scales[1] = -scales[1];
2411 if(scales[2] < 0.0 ) { // move the rotation info to rotation matrix
2412 scales[2] = -scales[2];
2420 // check for equal scales case and do not reorder
2421 if(almostEqual(Math.abs(scales[0]), Math.abs(scales[1])) &&
2422 almostEqual(Math.abs(scales[1]), Math.abs(scales[2])) ){
2427 outScale[i] = scales[i];
2432 // sort the order of the results of SVD
2433 if( scales[0] > scales[1]) {
2434 if( scales[0] > scales[2] ) {
2435 if( scales[2] > scales[1] ) {
2436 out[0] = 0; out[1] = 2; out[2] = 1; // xzy
2438 out[0] = 0; out[1] = 1; out[2] = 2; // xyz
2441 out[0] = 2; out[1] = 0; out[2] = 1; // zxy
2444 if( scales[1] > scales[2] ) {
2445 if( scales[2] > scales[0] ) {
2446 out[0] = 1; out[1] = 2; out[2] = 0; // yzx
2448 out[0] = 1; out[1] = 0; out[2] = 2; // yxz
2451 out[0] = 2; out[1] = 1; out[2] = 0; // zyx
2456 System.out.println("\nscales="+scales[0]+" "+scales[1]+" "+scales[2]);
2457 System.out.println("\nrot="+rot[0]+" "+rot[1]+" "+rot[2]);
2458 System.out.println("rot="+rot[3]+" "+rot[4]+" "+rot[5]);
2459 System.out.println("rot="+rot[6]+" "+rot[7]+" "+rot[8]);
2462 // sort the order of the input matrix
2463 mag[0] = (m[0]*m[0] + m[1]*m[1] + m[2]*m[2]);
2464 mag[1] = (m[3]*m[3] + m[4]*m[4] + m[5]*m[5]);
2465 mag[2] = (m[6]*m[6] + m[7]*m[7] + m[8]*m[8]);
2467 if( mag[0] > mag[1]) {
2468 if( mag[0] > mag[2] ) {
2469 if( mag[2] > mag[1] ) {
2471 in0 = 0; in2 = 1; in1 = 2;// xzy
2474 in0 = 0; in1 = 1; in2 = 2; // xyz
2478 in2 = 0; in0 = 1; in1 = 2; // zxy
2480 } else { // y > x 1>0
2481 if( mag[1] > mag[2] ) {
2482 if( mag[2] > mag[0] ) {
2484 in1 = 0; in2 = 1; in0 = 2; // yzx
2487 in1 = 0; in0 = 1; in2 = 2; // yxz
2491 in2 = 0; in1 = 1; in0 = 2; // zyx
2497 outScale[0] = scales[index];
2500 outScale[1] = scales[index];
2503 outScale[2] = scales[index];
2507 outRot[0] = rot[index];
2510 outRot[0+3] = rot[index];
2513 outRot[0+6] = rot[index];
2516 outRot[1] = rot[index];
2519 outRot[1+3] = rot[index];
2522 outRot[1+6] = rot[index];
2525 outRot[2] = rot[index];
2528 outRot[2+3] = rot[index];
2531 outRot[2+6] = rot[index];
2535 static int compute_qr( double[] s, double[] e, double[] u, double[] v) {
2539 double shift,ssmin,ssmax,r;
2540 double[] cosl = new double[2];
2541 double[] cosr = new double[2];
2542 double[] sinl = new double[2];
2543 double[] sinr = new double[2];
2544 double[] m = new double[9];
2549 final int MAX_INTERATIONS = 10;
2550 final double CONVERGE_TOL = 4.89E-15;
2560 if( Math.abs(e[1]) < CONVERGE_TOL || Math.abs(e[0]) < CONVERGE_TOL) converged = true;
2562 for(k=0;k<MAX_INTERATIONS && !converged;k++) {
2563 shift = compute_shift( s[1], e[1], s[2]);
2564 f = (Math.abs(s[0]) - shift) * (d_sign(c_b48, s[0]) + shift/s[0]);
2566 r = compute_rot(f, g, sinr, cosr, 0, first);
2567 f = cosr[0] * s[0] + sinr[0] * e[0];
2568 e[0] = cosr[0] * e[0] - sinr[0] * s[0];
2570 s[1] = cosr[0] * s[1];
2572 r = compute_rot(f, g, sinl, cosl, 0, first);
2575 f = cosl[0] * e[0] + sinl[0] * s[1];
2576 s[1] = cosl[0] * s[1] - sinl[0] * e[0];
2578 e[1] = cosl[0] * e[1];
2580 r = compute_rot(f, g, sinr, cosr, 1, first);
2582 f = cosr[1] * s[1] + sinr[1] * e[1];
2583 e[1] = cosr[1] * e[1] - sinr[1] * s[1];
2585 s[2] = cosr[1] * s[2];
2587 r = compute_rot(f, g, sinl, cosl, 1, first);
2589 f = cosl[1] * e[1] + sinl[1] * s[2];
2590 s[2] = cosl[1] * s[2] - sinl[1] * e[1];
2593 // update u matrices
2595 u[0] = cosl[0]*utemp + sinl[0]*u[3];
2596 u[3] = -sinl[0]*utemp + cosl[0]*u[3];
2598 u[1] = cosl[0]*utemp + sinl[0]*u[4];
2599 u[4] = -sinl[0]*utemp + cosl[0]*u[4];
2601 u[2] = cosl[0]*utemp + sinl[0]*u[5];
2602 u[5] = -sinl[0]*utemp + cosl[0]*u[5];
2605 u[3] = cosl[1]*utemp + sinl[1]*u[6];
2606 u[6] = -sinl[1]*utemp + cosl[1]*u[6];
2608 u[4] = cosl[1]*utemp + sinl[1]*u[7];
2609 u[7] = -sinl[1]*utemp + cosl[1]*u[7];
2611 u[5] = cosl[1]*utemp + sinl[1]*u[8];
2612 u[8] = -sinl[1]*utemp + cosl[1]*u[8];
2614 // update v matrices
2617 v[0] = cosr[0]*vtemp + sinr[0]*v[1];
2618 v[1] = -sinr[0]*vtemp + cosr[0]*v[1];
2620 v[3] = cosr[0]*vtemp + sinr[0]*v[4];
2621 v[4] = -sinr[0]*vtemp + cosr[0]*v[4];
2623 v[6] = cosr[0]*vtemp + sinr[0]*v[7];
2624 v[7] = -sinr[0]*vtemp + cosr[0]*v[7];
2627 v[1] = cosr[1]*vtemp + sinr[1]*v[2];
2628 v[2] = -sinr[1]*vtemp + cosr[1]*v[2];
2630 v[4] = cosr[1]*vtemp + sinr[1]*v[5];
2631 v[5] = -sinr[1]*vtemp + cosr[1]*v[5];
2633 v[7] = cosr[1]*vtemp + sinr[1]*v[8];
2634 v[8] = -sinr[1]*vtemp + cosr[1]*v[8];
2637 m[0] = s[0]; m[1] = e[0]; m[2] = 0.0;
2638 m[3] = 0.0; m[4] = s[1]; m[5] =e[1];
2639 m[6] = 0.0; m[7] = 0.0; m[8] =s[2];
2641 if( Math.abs(e[1]) < CONVERGE_TOL || Math.abs(e[0]) < CONVERGE_TOL) converged = true;
2644 if( Math.abs(e[1]) < CONVERGE_TOL ) {
2645 compute_2X2( s[0],e[0],s[1],s,sinl,cosl,sinr,cosr, 0);
2648 u[0] = cosl[0]*utemp + sinl[0]*u[3];
2649 u[3] = -sinl[0]*utemp + cosl[0]*u[3];
2651 u[1] = cosl[0]*utemp + sinl[0]*u[4];
2652 u[4] = -sinl[0]*utemp + cosl[0]*u[4];
2654 u[2] = cosl[0]*utemp + sinl[0]*u[5];
2655 u[5] = -sinl[0]*utemp + cosl[0]*u[5];
2657 // update v matrices
2660 v[0] = cosr[0]*vtemp + sinr[0]*v[1];
2661 v[1] = -sinr[0]*vtemp + cosr[0]*v[1];
2663 v[3] = cosr[0]*vtemp + sinr[0]*v[4];
2664 v[4] = -sinr[0]*vtemp + cosr[0]*v[4];
2666 v[6] = cosr[0]*vtemp + sinr[0]*v[7];
2667 v[7] = -sinr[0]*vtemp + cosr[0]*v[7];
2669 compute_2X2( s[1],e[1],s[2],s,sinl,cosl,sinr,cosr,1);
2672 u[3] = cosl[0]*utemp + sinl[0]*u[6];
2673 u[6] = -sinl[0]*utemp + cosl[0]*u[6];
2675 u[4] = cosl[0]*utemp + sinl[0]*u[7];
2676 u[7] = -sinl[0]*utemp + cosl[0]*u[7];
2678 u[5] = cosl[0]*utemp + sinl[0]*u[8];
2679 u[8] = -sinl[0]*utemp + cosl[0]*u[8];
2681 // update v matrices
2684 v[1] = cosr[0]*vtemp + sinr[0]*v[2];
2685 v[2] = -sinr[0]*vtemp + cosr[0]*v[2];
2687 v[4] = cosr[0]*vtemp + sinr[0]*v[5];
2688 v[5] = -sinr[0]*vtemp + cosr[0]*v[5];
2690 v[7] = cosr[0]*vtemp + sinr[0]*v[8];
2691 v[8] = -sinr[0]*vtemp + cosr[0]*v[8];
2696 static double max( double a, double b) {
2702 static double min( double a, double b) {
2708 static double d_sign(double a, double b) {
2710 x = (a >= 0 ? a : - a);
2711 return( b >= 0 ? x : -x);
2714 static double compute_shift( double f, double g, double h) {
2716 double fhmn, fhmx, c, fa, ga, ha, as, at, au;
2728 d__1 = min(fhmx,ga) / max(fhmx,ga);
2732 as = fhmn / fhmx + 1.;
2733 at = (fhmx - fhmn) / fhmx;
2736 c = 2. / (Math.sqrt(as * as + au) + Math.sqrt(at * at + au));
2741 ssmin = fhmn * fhmx / ga;
2743 as = fhmn / fhmx + 1.;
2744 at = (fhmx - fhmn) / fhmx;
2747 c = 1. / (Math.sqrt(d__1 * d__1 + 1.) + Math.sqrt(d__2 * d__2 + 1.));
2748 ssmin = fhmn * c * au;
2756 static int compute_2X2( double f, double g, double h, double[] single_values,
2757 double[] snl, double[] csl, double[] snr, double[] csr, int index) {
2766 double a, d, l, m, r, s, t, tsign, fa, ga, ha;
2767 double ft, gt, ht, mm;
2769 double tt, clt, crt, slt, srt;
2772 ssmax = single_values[0];
2773 ssmin = single_values[1];
2805 single_values[1] = ha;
2806 single_values[0] = fa;
2816 if (fa / ga < EPS) {
2821 ssmin = fa / (ga / ha);
2823 ssmin = fa / ga * ha;
2847 s = Math.sqrt(tt + mm);
2852 r = Math.sqrt(l * l + mm);
2859 if (fa / ga < EPS) {
2864 ssmin = fa / (ga / ha);
2866 ssmin = fa / ga * ha;
2890 s = Math.sqrt(tt + mm);
2895 r = Math.sqrt(l * l + mm);
2906 t = d_sign(c_b3, ft) * d_sign(c_b4, gt);
2908 t = gt / d_sign(d, ft) + m / t;
2911 t = (m / (s + t) + m / (r + l)) * (a + 1.);
2913 l = Math.sqrt(t * t + 4.);
2916 clt = (crt + srt * m) / a;
2917 slt = ht / ft * srt / a;
2933 tsign = d_sign(c_b4, csr[0]) * d_sign(c_b4, csl[0]) * d_sign(c_b4, f);
2936 tsign = d_sign(c_b4, snr[0]) * d_sign(c_b4, csl[0]) * d_sign(c_b4, g);
2939 tsign = d_sign(c_b4, snr[0]) * d_sign(c_b4, snl[0]) * d_sign(c_b4, h);
2941 single_values[index] = d_sign(ssmax, tsign);
2942 d__1 = tsign * d_sign(c_b4, f) * d_sign(c_b4, h);
2943 single_values[index+1] = d_sign(ssmin, d__1);
2949 static double compute_rot( double f, double g, double[] sin, double[] cos, int index, int first) {
2958 final double safmn2 = 2.002083095183101E-146;
2959 final double safmx2 = 4.994797680505588E+145;
2965 } else if (f == 0.) {
2972 scale = max(Math.abs(f1),Math.abs(g1));
2973 if (scale >= safmx2) {
2975 while(scale >= safmx2) {
2979 scale = max(Math.abs(f1),Math.abs(g1));
2981 r = Math.sqrt(f1*f1 + g1*g1);
2985 for (i = 1; i <= count; ++i) {
2988 } else if (scale <= safmn2) {
2990 while(scale <= safmn2) {
2994 scale = max(Math.abs(f1),Math.abs(g1));
2996 r = Math.sqrt(f1*f1 + g1*g1);
3000 for (i = 1; i <= count; ++i) {
3004 r = Math.sqrt(f1*f1 + g1*g1);
3008 if (Math.abs(f) > Math.abs(g) && cs < 0.) {
3019 static void print_mat( double[] mat) {
3022 System.out.println(mat[i*3+0]+" "+mat[i*3+1]+" "+mat[i*3+2]+"\n");
3026 static void print_det( double[] mat) {
3029 det = mat[0]*mat[4]*mat[8] +
3030 mat[1]*mat[5]*mat[6] +
3031 mat[2]*mat[3]*mat[7] -
3032 mat[2]*mat[4]*mat[6] -
3033 mat[0]*mat[5]*mat[7] -
3034 mat[1]*mat[3]*mat[8];
3035 System.out.println("det= "+det);
3037 static void mat_mul(double[] m1, double[] m2, double[] m3) {
3039 double[] tmp = new double[9];
3041 tmp[0] = m1[0]*m2[0] + m1[1]*m2[3] + m1[2]*m2[6];
3042 tmp[1] = m1[0]*m2[1] + m1[1]*m2[4] + m1[2]*m2[7];
3043 tmp[2] = m1[0]*m2[2] + m1[1]*m2[5] + m1[2]*m2[8];
3045 tmp[3] = m1[3]*m2[0] + m1[4]*m2[3] + m1[5]*m2[6];
3046 tmp[4] = m1[3]*m2[1] + m1[4]*m2[4] + m1[5]*m2[7];
3047 tmp[5] = m1[3]*m2[2] + m1[4]*m2[5] + m1[5]*m2[8];
3049 tmp[6] = m1[6]*m2[0] + m1[7]*m2[3] + m1[8]*m2[6];
3050 tmp[7] = m1[6]*m2[1] + m1[7]*m2[4] + m1[8]*m2[7];
3051 tmp[8] = m1[6]*m2[2] + m1[7]*m2[5] + m1[8]*m2[8];
3057 static void transpose_mat(double[] in, double[] out) {
3070 static double max3( double[] values) {
3071 if( values[0] > values[1] ) {
3072 if( values[0] > values[2] )
3077 if( values[1] > values[2] )
3084 private static final boolean almostEqual(double a, double b) {
3088 final double EPSILON_ABSOLUTE = 1.0e-6;
3089 final double EPSILON_RELATIVE = 1.0e-4;
3090 double diff = Math.abs(a-b);
3091 double absA = Math.abs(a);
3092 double absB = Math.abs(b);
3093 double max = (absA >= absB) ? absA : absB;
3095 if (diff < EPSILON_ABSOLUTE)
3098 if ((diff / max) < EPSILON_RELATIVE)
3105 * Creates a new object of the same class as this object.
3107 * @return a clone of this instance.
3108 * @exception OutOfMemoryError if there is not enough memory.
3109 * @see java.lang.Cloneable
3110 * @since vecmath 1.3
3112 public Object clone() {
3115 m1 = (Matrix3d)super.clone();
3116 } catch (CloneNotSupportedException e) {
3117 // this shouldn't happen, since we are Cloneable
3118 throw new InternalError();
3121 // Also need to create new tmp arrays (no need to actually clone them)
3126 * Get the first matrix element in the first row.
3127 * @return Returns the m00.
3128 * @since vecmath 1.5
3130 public final double getM00() {
3135 * Set the first matrix element in the first row.
3137 * @param m00 The m00 to set.
3139 * @since vecmath 1.5
3141 public final void setM00(double m00) {
3146 * Get the second matrix element in the first row.
3148 * @return Returns the m01.
3150 * @since vecmath 1.5
3152 public final double getM01() {
3157 * Set the second matrix element in the first row.
3159 * @param m01 The m01 to set.
3161 * @since vecmath 1.5
3163 public final void setM01(double m01) {
3168 * Get the third matrix element in the first row.
3170 * @return Returns the m02.
3172 * @since vecmath 1.5
3174 public final double getM02() {
3179 * Set the third matrix element in the first row.
3181 * @param m02 The m02 to set.
3183 * @since vecmath 1.5
3185 public final void setM02(double m02) {
3190 * Get first matrix element in the second row.
3192 * @return Returns the m10.
3194 * @since vecmath 1.5
3196 public final double getM10() {
3201 * Set first matrix element in the second row.
3203 * @param m10 The m10 to set.
3205 * @since vecmath 1.5
3207 public final void setM10(double m10) {
3212 * Get second matrix element in the second row.
3214 * @return Returns the m11.
3216 * @since vecmath 1.5
3218 public final double getM11() {
3223 * Set the second matrix element in the second row.
3225 * @param m11 The m11 to set.
3227 * @since vecmath 1.5
3229 public final void setM11(double m11) {
3234 * Get the third matrix element in the second row.
3236 * @return Returns the m12.
3238 * @since vecmath 1.5
3240 public final double getM12() {
3245 * Set the third matrix element in the second row.
3247 * @param m12 The m12 to set.
3249 * @since vecmath 1.5
3251 public final void setM12(double m12) {
3256 * Get the first matrix element in the third row.
3258 * @return Returns the m20.
3260 * @since vecmath 1.5
3262 public final double getM20() {
3267 * Set the first matrix element in the third row.
3269 * @param m20 The m20 to set.
3271 * @since vecmath 1.5
3273 public final void setM20(double m20) {
3278 * Get the second matrix element in the third row.
3280 * @return Returns the m21.
3282 * @since vecmath 1.5
3284 public final double getM21() {
3289 * Set the second matrix element in the third row.
3291 * @param m21 The m21 to set.
3293 * @since vecmath 1.5
3295 public final void setM21(double m21) {
3300 * Get the third matrix element in the third row .
3302 * @return Returns the m22.
3304 * @since vecmath 1.5
3306 public final double getM22() {
3311 * Set the third matrix element in the third row.
3313 * @param m22 The m22 to set.
3315 * @since vecmath 1.5
3317 public final void setM22(double m22) {