// This is a package containing the guts of the matrix math

//package graphics;

import java.awt.*;

public class Matrix3D {

    /////////////////
    // the data
    /////////////////

    double A[][] = new double[4][4];

    /////////////////
    // the utilities
    /////////////////

    public void set (int i, int j, double x) {
	A[i][j] = x;
    }

    public double get (int i, int j) {
	return A[i][j];
    }

    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 Identity() {
	for (int i = 0; i < 4; i++)
	    for (int j = 0; j < 4; j++)
		set(i,j,0);
	for (int i = 0; i < 4; i++)
	    set(i,i,1);
	System.out.println("in Identity \n");
    }

    public void printout() {
	System.out.print("( ");
	for (int i = 0; i < 4; i++) {
	    System.out.print("(");
	    for (int j = 0; j < 4; j++)
		{
		    System.out.print(" " + A[i][j] + " "); 
		};
	    System.out.println(")");
	}
	System.out.print(" )");
	System.out.println();
    }

    /////////////////
    // the matrix and vector arithmetic
    /////////////////

    public double[] vectorMult (double v[]) {

	double temp = 0;
	double answer[] = new double[4];

	for (int i = 0; i < 4; i++) {
	    temp = 0;
	    for (int j = 0; j < 4; j++) {
		temp = temp + (A[i][j] * v[j]);
	    }
	    answer[i] = temp;
	}
	return answer;
    }

    public double[] rowof (int row) {
	double temp[] = new double[4];
	for (int i = 0; i < 4; i++)
	    {
		temp[i] = A[row][i];
	    }
	return temp;
    }

    public Matrix3D matrixMult(Matrix3D src)
    {
	Matrix3D temp = new Matrix3D();
	temp.copy(this);

	for (int i = 0; i < 4; i++)
	    for (int j = 0; j < 4; j++) {
		double sum = 0.0;
		for (int k = 0; k < 4; k++)
		    sum += temp.get(i,k) * src.get(k,j);
		A[i][j] = sum; 
	    }

	return this;
    }

    /*
    public void matrixMult (Matrix3D B) {
	Matrix3D temp = new Matrix3D();
	temp.copy(this); // the matrix we're accessing this method from

	for (int i = 0; i < 4; i++)
	    for (int j = 0; j < 4; j++)
		{
		    double sum = 0;
		    for (int k = 0; k < 4; k++)
			sum = sum + temp.get(i,k) * B.get(k,j);
		    A[i][j] = sum;
		}
    }
    */

    /////////////////
    // the geometric transforms
    /////////////////

    public void translationMatrix (double a, double b, double c) {
	Identity();
	set(0,3,a);
	set(1,3,b);
	set(2,3,c);
    }

    public void translate (double a, double b, double c) {
	Matrix3D temp = new Matrix3D();
	temp.translationMatrix(a,b,c);
	matrixMult(temp);
    }
    /*
    public void xRotationMatrix (double alpha) {
	Identity();
	double c = Math.cos(alpha);
	double s = Math.sin(alpha);
	set(1,1,c);
	set(1,2,-s);
	set(2,1,s);
	set(2,2,c);
    }

    public void xRotate (double alpha) {
	Matrix3D temp = new Matrix3D();
	temp.xRotationMatrix(alpha);
	matrixMult(temp);
    }

    public void yRotationMatrix (double beta) {
	Identity();
	double c = Math.cos(beta);
	double s = Math.sin(beta);
	set(0,0,c);
	set(0,2,s);
	set(2,0,-s);
	set(2,2,c);
    }

    public void yRotate (double beta) {
	Matrix3D temp = new Matrix3D();
	temp.yRotationMatrix(beta);
	matrixMult(temp);
    }
    */


    public void zRotationMatrix (double gamma) {
	Identity();
	double c = Math.cos(gamma);
	double s = Math.sin(gamma);
	set(0,0,c);
	set(0,1,-s);
	set(1,0,s);
	set(1,1,c);
    }

    public void zRotate (double gamma) {
	Matrix3D temp = new Matrix3D();
	temp.zRotationMatrix(gamma);
	matrixMult(temp);
    }

    public void yRotationMatrix (double gamma) {
	Identity();
	double c = Math.cos(gamma);
	double s = Math.sin(gamma);
	set(0,0,c);
	set(0,2,s);
	set(2,0,-s);
	set(2,2,c);
    }

    public void yRotate (double gamma) {
	Matrix3D temp = new Matrix3D();
	temp.yRotationMatrix(gamma);
	matrixMult(temp);
    }

    public void xRotationMatrix (double gamma) {
	Identity();
	double c = Math.cos(gamma);
	double s = Math.sin(gamma);
	set(1,1,c);
	set(1,2,-s);
	set(2,1,s);
	set(2,2,c);
    }

    public void xRotate (double gamma) {
	Matrix3D temp = new Matrix3D();
	temp.xRotationMatrix(gamma);
	matrixMult(temp);
    }

    public void scaleMatrix (double a, double b, double c) {
	Identity();
	set(0,0,a);
	set(1,1,b);
	set(2,2,c);
    }

    public void Scale (double a, double b, double c) {
	Matrix3D temp = new Matrix3D();
	temp.scaleMatrix(a,b,c);
	matrixMult(temp);
    }


    public void transform (double src[], double dst[]) {
	for (int i = 0; i < 3; i++)
	    dst[i] = A[i][0] * src[0] +
		     A[i][1] * src[1] +
		     A[i][2] * src[2] +
		     A[i][3];
    }
    
}

