// Matrix3D.java
// This class implements the basic matrix operations for 3D graphics
// Much of this code is based on code or hints provided by Prof. Ken Perlin (NYU)

/*	// constructors
	Matrix3D();
	
	// canonical matrices
	identityMatrix();
	translationMatrix(double a, double b, double c);
	xRotationMatrix(double theta);
	yRotationMatrix(double theta);
	zRotationMatrix(double theta);
	scaleMatrix(double a, double b, double c);
	perspectiveMatrix(double f);
	zeroMatrix();
	
	// transformation matrices
	translate(double a, double b, double c);
	rotateX(double theta);
	rotateY(double theta);
	rotateZ(double theta);
	scale(double a, double b, double c);
	
	// additional operations
	double get(int i, int j);
	set(int i, int j, double a);
	copy(Matrix3D src);
	add(Matrix3D src);
	multiply(Matrix3D src);
	inverse();
	random();
	
	print();
	
	// variables
	double data[4][4];
	Matrix3D temp;
*/
package wonderlab.graphics.geometry;

public class Matrix3D extends Matrix {
	
	Matrix3D temp;
	
	public static void main (String argv[]) {

		Matrix3D A = new Matrix3D();
		Matrix3D B = new Matrix3D();
		
		System.out.println("xRotation");
		//A.scale(0.2,0.3,0.4);
		A.xRotationMatrix(1);
		A.print();
		
		System.out.println("yRotation");
		A.yRotationMatrix(1);
		A.print();

		System.out.println("zRotation");
		A.zRotationMatrix(1);
		A.print();

		System.out.println("scale");
		A.scaleMatrix(1,2,3);
		A.print();

		System.out.println("translation");
		A.translationMatrix(1, 2, 3);
		A.print();

		System.out.println("Matrix Multiply Identity * translation");
		B.identityMatrix();
		B.multiply(A);
		B.print();		
		
		System.out.println("zRotationMatrix * translation");
		A.zRotationMatrix(.1);
		B.translationMatrix(1, 2, 3);
		B.multiply(A);
		B.print();	
		
		System.out.println("Testing inverse...");
		System.out.println("Inverse of identity ");
		A.identity();
		A.inverse();
		A.print();
		A.identity();
		System.out.println("A Rotation Matrix...");
		A.rotateX(2);
		A.print();
		System.out.println("It's Inverse...(Should be same as transpose)");
		A.inverse();
		A.print();
		System.out.println("Inverse again...Should be same as orig.");
		A.inverse();
		A.print();
		System.out.println("A Random matrix");
		A.random();
		A.print();
		System.out.println("It's Inverse...");
		A.inverse();
		A.print();
		System.out.println("Inverse again...Should be same as orig.");
		A.inverse();
		A.print();
	}

	public Matrix3D( ) {
		super(4,4);
		identityMatrix();
	}
			
	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) {
		identityMatrix();
		data[1][1] = Math.cos(theta);
		data[1][2] = Math.sin(theta);
		data[2][2] = data[1][1];
		data[2][1] = -1*data[1][2];
	}
	
	public void yRotationMatrix(double theta) {
		identityMatrix();
		data[0][0] = Math.cos(theta);
		data[0][2] = Math.sin(theta);
		data[2][2] = data[0][0];
		data[2][0] = -1*data[0][2];
	}

	public void zRotationMatrix(double theta) {
		identityMatrix();
		data[0][0] = Math.cos(theta);
		data[0][1] = Math.sin(theta);
		data[1][1] = data[0][0];
		data[1][0] = -1*data[0][1];
	}
	
	public void scaleMatrix(double a, double b, double c) {
		identityMatrix();
		data[0][0] = a;
		data[1][1] = b;
		data[2][2] = c;
	}

	public Vector3D transform(Vector3D src) {
		double x = src.get(0);
		double y = src.get(1);
		double z = src.get(2);
		double w = src.get(3);
		
		//System.out.println("w is " + w);
		
		Vector3D temp = new Vector3D(4);
		
		for (int i = 0 ; i < 4 ; i++) {
         	temp.set(i,data[i][0]*x + data[i][1]*y + data[i][2]*z + data[i][3]);
   		}
   		return temp;
   	}

	public void translate(double a, double b, double c) {
		temp = new Matrix3D();
		temp.translationMatrix(a, b, c);
		this.multiply(temp);
//		this.print();
	}
	
	public void rotateX(double theta) {
		temp = new Matrix3D();
		temp.xRotationMatrix(theta);
		this.multiply(temp);
	}

	public void rotateY(double theta) {
		temp = new Matrix3D();
		temp.yRotationMatrix(theta);
		this.multiply(temp);
	}

	public void rotateZ(double theta) {
		temp = new Matrix3D();
		temp.zRotationMatrix(theta);
		this.multiply(temp);
	}

	public void scale(double a, double b, double c) {
		temp = new Matrix3D();
		temp.scaleMatrix(a, b, c);
		this.multiply(temp);
	}
	
}

