package graphics; import graphics.MatrixInverter; public class Matrix3D { private double[][] data = new double[4][4]; public Matrix3D() { zero(); } public Matrix3D(double[][] startData) { for (int i=0 ; i<4 ; i++) for (int j=0 ; j<4 ; j++) data[i][j] = startData[i][j]; } //copies data from existing matrix public Matrix3D(Matrix3D src) { copy(src); } public void zero() { for (int i=0 ; i<4 ; i++) for (int j=0 ; j<4 ; j++) data[i][j] = 0.0; } public void identity() { zero(); data[0][0] = 1.0; data[1][1] = 1.0; data[2][2] = 1.0; data[3][3] = 1.0; } public void translationMatrix(double a, double b, double c) { identity(); data[0][3] = a; data[1][3] = b; data[2][3] = c; } public void xRotationMatrix(double theta) { double cos = Math.cos(theta); double sin = Math.sin(theta); identity(); data[1][1] = cos; data[2][2] = cos; data[2][1] = sin; data[1][2] = -sin; } public void yRotationMatrix(double theta) { double cos = Math.cos(theta); double sin = Math.sin(theta); identity(); data[0][0] = cos; data[2][2] = cos; data[0][2] = sin; data[2][0] = -sin; } public void zRotationMatrix(double theta) { double cos = Math.cos(theta); double sin = Math.sin(theta); identity(); data[0][0] = cos; data[1][1] = cos; data[0][1] = -sin; data[1][0] = sin; } public void scaleMatrix(double x, double y, double z) { identity(); data[0][0] = x; data[1][1] = y; data[2][2] = z; } public void perspectiveMatrix(double f) { zero(); data[0][0] = f; data[1][1] = f; data[2][3] = f; data[3][2] = 1; } public void set(int i, int j, double value) { data[i][j] = value; } public double get(int i, int j) { return data[i][j]; } public Vector4 getRowVector(int row) { return new Vector4(data[row][0], data[row][1], data[row][2], data[row][3]); } public Vector4 getColumnVector(int col) { return new Vector4(data[0][col], data[1][col], data[2][col], data[3][col]); } public void copy(Matrix3D src) { for (int i=0 ; i<4 ; i++) for (int j=0 ; j<4 ; j++) set(i,j, src.get(i,j)); } public void multiply(Matrix3D m) { Matrix3D result = new Matrix3D(); for (int i=0 ; i<4 ; i++) for (int j=0 ; j<4 ; j++) //result.set(i,j, m.getRowVector(i).dotProduct(this.getColumnVector(j))); result.set(i,j, this.getRowVector(i).dotProduct(m.getColumnVector(j))); copy(result); } public void transpose() { Matrix3D result = new Matrix3D(); for (int i=0 ; i<4 ; i++) for (int j=0 ; j<4 ; j++) result.set(j,i, get(i,j)); copy(result); } public void inverse() { double[][] invData = new double[4][4]; MatrixInverter.invert(data, invData); Matrix3D result = new Matrix3D(invData); copy(result); } public void invert() {inverse();} //alias for inverse public void translate(double a, double b, double c) { Matrix3D t = new Matrix3D(); t.translationMatrix(a, b, c); multiply(t); } public void rotateX(double theta) { Matrix3D r = new Matrix3D(); r.xRotationMatrix(theta); multiply(r); } public void rotateY(double theta) { Matrix3D r = new Matrix3D(); r.yRotationMatrix(theta); multiply(r); } public void rotateZ(double theta) { Matrix3D r = new Matrix3D(); r.zRotationMatrix(theta); multiply(r); } public void scale(double x, double y, double z) { Matrix3D s = new Matrix3D(); s.scaleMatrix(x, y, z); multiply(s); } public void transform(double[] src, double[] dst) { //if it's a 3D point, (or vertex with 3D pt + 3D normal + uv), //use transform3 if (src.length == 3 || src.length == 8) { transform3(src, dst); } else { Vector4 pt = new Vector4(src[0], src[1], src[2], src[3]); Vector4 result = transform4(pt); for (int i = 0 ; i < 4 ; i++) dst[i] = result.get(i); //for (int i = 0 ; i < 4 ; i++) // dst[i] = pt.dotProduct( getRowVector(i) ); } } public Vector4 transform4(Vector4 src) { double[] dst = new double[4]; for (int i = 0 ; i < 4 ; i++) dst[i] = src.dotProduct( getRowVector(i) ); return new Vector4(dst); } //for 3D points (loses perspective) public void transform3(double[] src, double[] dst) { Vector4 pt = new Vector4(src[0], src[1], src[2], 1); for (int i = 0 ; i < 3 ; i++) dst[i] = pt.dotProduct( getRowVector(i) ); } public String toString() { StringBuilder sb = new StringBuilder(); for (int i=0 ; i<4 ; i++) sb.append(getRowVector(i)+"\n"); return sb.toString(); } }