/*
 * Matrix3D.java
 *
 * Created on September 24, 2006, 7:33 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

/**
 *
 * @author Alex
 */
public class Matrix3D {
    int SIZE = 4;
    // 3D matrix -- is 4 by 4, like all wheel drive
    double data [][] = new double[SIZE][SIZE];
    // lets make is official ii will be horizontal counter and
    // jj will be vertical
    
    /** Creates a new instance of Matrix3D */
    public Matrix3D() {
        identityMatrix();
    }
    
    private void init() {
        // least we can do is initialize ,,
        // i know , i know -- gotta kick this C habbit 
        for(int ii = 0; ii<SIZE; ii++)
            for(int jj = 0; jj < SIZE; jj++)
                data[ii][jj] = 0;
    }
    
    public void set(int ii, int jj, double value) {
        data[ii][jj] = value;
    } 
    
    public double get(int ii, int jj) {
        return data[ii][jj];       
    }
    
    // build an identity matrix -- fun fun fun
    public void identityMatrix(){
        init();
        data[0][0] = data[1][1] = data[2][2] = data[3][3] = 1;
    }
    
    public void translationMatrix(double a, double b, double c){
        identityMatrix();
        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] = (-1) * Math.sin(theta);
        data[2][1] = Math.sin(theta);
        data[2][2] = Math.cos(theta);
    }
    
    public void yRotationMatrix(double theta){
        identityMatrix();
        data[0][0] = Math.cos(theta);
        data[0][2] = Math.sin(theta);
        data[2][0] = (-1) * Math.sin(theta);
        data[2][2] = Math.cos(theta);
    }
    
    public void zRotationMatrix(double theta){
        identityMatrix();
        data[0][0] = Math.cos(theta);
        data[0][1] = (-1) * Math.sin(theta);
        data[1][0] = Math.sin(theta);
        data[1][1] = Math.cos(theta);
    }
    
    public void scaleMatrix(double a, double b, double c){
        identityMatrix();
        data[0][0] = a;
        data[1][1] = b;
        data[2][2] = c;
    }

    public void copy(Matrix3D src) {
	for(int ii = 0; ii<SIZE; ii++)
            for(int jj = 0; jj < SIZE; jj++)
                set(ii, jj, src.get(ii, jj));
    }

    void multiply (Matrix3D M) {
        Matrix3D temp = new Matrix3D(); // temp to store this 
        temp.copy(this); // copy this matrix into temp , else a big mess
        // now multiply 
        for(int ii = 0; ii<SIZE; ii++)
            for(int jj = 0; jj < SIZE; jj++) {
                double sum = 0;
                for(int kk = 0; kk < SIZE; kk++)
                    sum += temp.get(ii, kk) * M.get(kk, jj);
                data[ii][jj] = sum;
            }
    }

    public void translate(double a, double b, double c) {
        Matrix3D temp = new Matrix3D(); // temp to store this 
        temp.copy(this);
        temp.translationMatrix(a,b,c);
        multiply(temp);
    }
    
    public void rotateX(double theta) {
        Matrix3D temp = new Matrix3D(); // temp to store this 
        temp.copy(this);
        temp.xRotationMatrix(theta);
        multiply(temp);
    }
    
    public void rotateY(double theta) {
        Matrix3D temp = new Matrix3D(); // temp to store this 
        temp.copy(this);
        temp.yRotationMatrix(theta);
        multiply(temp);
    }
    
    public void rotateZ(double theta) {
        Matrix3D temp = new Matrix3D(); // temp to store this 
        temp.copy(this);
        temp.zRotationMatrix(theta);
        multiply(temp);    
    }

    public void scale(double a, double b, double c) {
        Matrix3D temp = new Matrix3D(); // temp to store this
        temp.copy(this);
        temp.scaleMatrix(a, b, c);
        multiply(temp);    
    }
    
    public void transform(double src[], double dst[]) {
        for(int ii = 0; ii < 3; ii++)
            dst[ii] = data[ii][0]*src[0] + data[ii][1]*src[1] + data[ii][2]*src[2] + data[ii][3];
    }
    
    
    public void printMatrix() {
        System.out.println("|" + data[0][0] + "|" + data[0][1] + "|" + data[0][2] + "|" + data[0][3] + "|" );
        System.out.println("|" + data[1][0] + "|" + data[1][1] + "|" + data[1][2] + "|" + data[1][3] + "|" );
        System.out.println("|" + data[2][0] + "|" + data[2][1] + "|" + data[2][2] + "|" + data[2][3] + "|" );
        System.out.println("|" + data[3][0] + "|" + data[3][1] + "|" + data[3][2] + "|" + data[3][3] + "|" );
    }
    
}






