// Matrix class --
// matrices for 3D transformations
// (c) Lars Huttar  2000

class Matrix {
	// order of members: xx xy xz xo; yx yy yz yo; zx zy zz zo;
	//   four more for "scratch work"
	double m[][] = new double[4][4];

	public Matrix() {
		unit();
	}

	// Initialize this mx to unit mx
	public void unit() {
		int i, j;
		for (i = 0; i < 4; i++)
			for (j = 0; j < 4; j++)
				m[i][j] = (i == j) ? 1 : 0;
	}

	// Initialize this mx to a mx of rotation about vector v by a radians.
	// Assuming left-handed coord system (I think).
	public void rotateAboutV(double v[], double a) {
		unit(); // initialize the last column

		double cosa = Math.cos(a);
		double sina = Math.sin(a);

		double x = v[0], y = v[1], z = v[2];
		double xyc = x * y * (1 - cosa);
		double xzc = x * z * (1 - cosa);
		double yzc = y * z * (1 - cosa);

		m[0][0] = (x*x * (1 - cosa) + cosa);
		m[0][1] = (xyc + z*sina);
		m[0][2] = (xzc - y*sina);

		m[1][0] = (xyc - z*sina);
		m[1][1] = (y*y * (1 - cosa) + cosa);
		m[1][2] = (yzc + x*sina);

		m[2][0] = (xzc + y*sina);
		m[2][1] = (yzc - x*sina);
		m[2][2] = (z*z * (1 - cosa) + cosa);
	}

	// Transform vector v1 by this mx, putting result in v2.
	// v1 and v2 cannot be the same vector.
	public void transform(double v1[], double v2[]) {
		for (int i = 0; i < 3; i++)
			v2[i] = v1[0] * m[0][i] + v1[1] * m[1][i] + v1[2] * m[2][i] +
				m[3][i];
	}
}
