//----- SIMPLE CLASS TO HANDLE BASIC 3D MATRIX OPERATIONS ----- public class Matrix { public static void identity(double matrix[][]) { for (int i = 0 ; i < 4 ; i++) for (int j = 0 ; j < 4 ; j++) matrix[i][j] = (i == j ? 1 : 0); } public static double[][] tmp = new double[4][4]; public static void copy(double src[][], double dst[][]) { for (int i = 0 ; i < 4 ; i++) for (int j = 0 ; j < 4 ; j++) dst[i][j] = src[i][j]; } public static void preMultiply(double dst[][], double b[][]) { copy(dst, tmp); for (int i = 0 ; i < 4 ; i++) for (int j = 0 ; j < 4 ; j++) { dst[i][j] = 0; for (int k = 0 ; k < 4 ; k++) dst[i][j] += tmp[i][k] * b[k][j]; } } public static void postMultiply(double dst[][], double b[][]) { copy(dst, tmp); for (int i = 0 ; i < 4 ; i++) for (int j = 0 ; j < 4 ; j++) { dst[i][j] = 0; for (int k = 0 ; k < 4 ; k++) dst[i][j] += b[i][k] * tmp[k][j]; } } //----- ROUTINES TO ROTATE AND TRANSLATE MATRICES ----- private static double[][] mat = new double[4][4]; public static void translate(double m[][], double x, double y, double z) { makeTranslationMatrix(mat, x,y,z); preMultiply(m, mat); } public static void rotateX(double m[][], double theta) { makeRotationMatrix(mat, 1,2, theta); preMultiply(m, mat); } public static void rotateY(double m[][], double theta) { makeRotationMatrix(mat, 2,0, theta); preMultiply(m, mat); } public static void rotateZ(double m[][], double theta) { makeRotationMatrix(mat, 0,1, theta); preMultiply(m, mat); } public static void scale(double m[][], double x, double y, double z) { makeScaleMatrix(mat, x,y,z); preMultiply(m, mat); } //----- INVERTING A 4x4 THAT WAS CREATED BY TRANSLATIONS+ROTATIONS+SCALES public static void invert(double src[][], double dst[][]) { // COMPUTE ADJOINT COFACTOR MATRIX FOR THE ROTATION+SCALE 3x3 for (int i = 0 ; i < 3 ; i++) for (int j = 0 ; j < 3 ; j++) { int i0 = (i+1) % 3; int i1 = (i+2) % 3; int j0 = (j+1) % 3; int j1 = (j+2) % 3; dst[j][i] = src[i0][j0] * src[i1][j1] - src[i0][j1] * src[i1][j0]; } // RENORMALIZE BY DETERMINANT TO GET ROTATION+SCALE 3x3 INVERSE double determinant = src[0][0] * dst[0][0] + src[1][0] * dst[0][1] + src[2][0] * dst[0][2] ; for (int i = 0 ; i < 3 ; i++) for (int j = 0 ; j < 3 ; j++) dst[i][j] /= determinant; // COMPUTE INVERSE TRANSLATION for (int i = 0 ; i < 3 ; i++) dst[i][3]= - dst[i][0] * src[0][3] - dst[i][1] * src[1][3] - dst[i][2] * src[2][3] ; } //----- FOR DEBUGGING ----- public static String toString(double m[][]) { String s = "{"; for (int i = 0 ; i < 4 ; i++) { s += "{"; for (int j = 0 ; j < 4 ; j++) { int n = (int)(100*m[i][j]); s += (n/100.) + (j==3 ? "" : ","); } s += "}" + (i==3 ? "" : ","); } return s + "}"; } //----- ROUTINES TO GENERATE TRANSFORMATION MATRICES ----- static void makeTranslationMatrix(double m[][], double x, double y, double z) { identity(m); m[0][3] = x; m[1][3] = y; m[2][3] = z; } static void makeRotationMatrix(double m[][], int i,int j,double theta) { identity(m); m[i][i] = m[j][j] = Math.cos(theta); m[i][j] = -Math.sin(theta); m[j][i] = -m[i][j]; } static void makeScaleMatrix(double m[][], double x,double y,double z) { identity(m); m[0][0] *= x; m[1][1] *= y; m[2][2] *= z; } //----- ROUTINE TO TRANSFORM A POINT ----- public static void transform(double m[][], double src[], double dst[]){ for (int j = 0 ; j < 3 ; j++) dst[j] = m[j][0]*src[0] + m[j][1]*src[1] + m[j][2]*src[2] + m[j][3]; } }