public final class Matrix implements Cloneable {
double[] mx;
public Matrix() {
mx = new double[16];
identity();
}
public Matrix(double[] mx) {
if (mx.length != 16) {
throw new IllegalArgumentException("mx.length != 16");
}
this.mx = mx;
}
public double[] getMatrix() {
return mx;
}
public void multiplicate(double[] nm) {
int x, a, b;
double[] tm = new double[16];
for (x = 0; x < 16; x++) {
a = x % 4;
b = (x / 4) * 4;
tm[ x] = nm[ a] * mx[ b]
+ nm[ a + 4] * mx[ b + 1]
+ nm[ a + 8] * mx[ b + 2]
+ nm[ a + 12] * mx[ b + 3];
}
for (x = 0; x < 16; x++) {
mx[ x] = tm[ x];
}
}
public void multiplicate(Matrix matrix) {
multiplicate(matrix.mx);
}
public void rotate(double alpha, Vector3f dir) {
double[] rm = new double[16];
if (dir.length() < 0.0001) {
return;
}
dir = dir.mul(1.0 / dir.length());
double x = dir.x, y = dir.y, z = dir.z;
double s = Math.sin(Math.toRadians(alpha));
double c = Math.cos(Math.toRadians(alpha));
rm[ 0] = x * x * (1 - c) + c;
rm[ 4] = x * y * (1 - c) - z * s;
rm[ 8] = x * z * (1 - c) + y * s;
rm[ 12] = 0;
rm[ 1] = x * y * (1 - c) + z * s;
rm[ 5] = y * y * (1 - c) + c;
rm[ 9] = y * z * (1 - c) - x * s;
rm[ 13] = 0;
rm[ 2] = x * z * (1 - c) - y * s;
rm[ 6] = y * z * (1 - c) + x * s;
rm[ 10] = z * z * (1 - c) + c;
rm[ 14] = 0;
rm[ 3] = 0;
rm[ 7] = 0;
rm[ 11] = 0;
rm[ 15] = 1;
multiplicate(rm);
}
public void rotate_x(double alpha) {
rotate(alpha, new Vector3f(1, 0, 0));
}
public void rotate_y(double alpha) {
rotate(alpha, new Vector3f(0, 1, 0));
}
public void rotate_z(double alpha) {
rotate(alpha, new Vector3f(0, 0, 1));
}
public void rotate(double alpha) {
rotate_z(alpha);
}
public void rotate(double x, double y, double alpha) {
rotate(alpha, new Vector3f(x, y, 0));
}
public void translate(double xt, double yt, double zt) {
double[] tm = new double[16];
tm[ 0] = 1;
tm[ 4] = 0;
tm[ 8] = 0;
tm[ 12] = xt;
tm[ 1] = 0;
tm[ 5] = 1;
tm[ 9] = 0;
tm[ 13] = yt;
tm[ 2] = 0;
tm[ 6] = 0;
tm[ 10] = 1;
tm[ 14] = zt;
tm[ 3] = 0;
tm[ 7] = 0;
tm[ 11] = 0;
tm[ 15] = 1;
multiplicate(tm);
}
public void translate(double tx, double ty) {
translate(tx, ty, 0);
}
public void scale(double xs, double ys, double zs) {
double[] sm = new double[16];
sm[ 0] = xs;
sm[ 4] = 0;
sm[ 8] = 0;
sm[ 12] = 0;
sm[ 1] = 0;
sm[ 5] = ys;
sm[ 9] = 0;
sm[ 13] = 0;
sm[ 2] = 0;
sm[ 6] = 0;
sm[ 10] = zs;
sm[ 14] = 0;
sm[ 3] = 0;
sm[ 7] = 0;
sm[ 11] = 0;
sm[ 15] = 1;
multiplicate(sm);
}
public void scale(double sx, double sy) {
scale(sx, sy, 0);
}
public Point3d transform(Point3d p) {
double wx = p.x * mx[ 0] + p.y * mx[ 4] + p.z * mx[ 8] + mx[ 12];
double wy = p.x * mx[ 1] + p.y * mx[ 5] + p.z * mx[ 9] + mx[ 13];
double wz = p.x * mx[ 2] + p.y * mx[ 6] + p.z * mx[ 10] + mx[ 14];
return new Point3d(wx, wy, wz);
}
public Vector3f transform(Vector3f v) {
double x = v.x * mx[ 0] + v.y * mx[ 4] + v.z * mx[ 8];
double y = v.x * mx[ 1] + v.y * mx[ 5] + v.z * mx[ 9];
double z = v.x * mx[ 2] + v.y * mx[ 6] + v.z * mx[ 10];
return new Vector3f(x, y, z);
}
public void identity() {
mx[ 0] = 1;
mx[ 4] = 0;
mx[ 8] = 0;
mx[ 12] = 0;
mx[ 1] = 0;
mx[ 5] = 1;
mx[ 9] = 0;
mx[ 13] = 0;
mx[ 2] = 0;
mx[ 6] = 0;
mx[ 10] = 1;
mx[ 14] = 0;
mx[ 3] = 0;
mx[ 7] = 0;
mx[ 11] = 0;
mx[ 15] = 1;
}
public void rows(Vector3f a, Vector3f b, Vector3f c) {
double[] rm = new double[16];
rm[ 0] = a.x;
rm[ 4] = a.y;
rm[ 8] = a.z;
rm[ 12] = 0;
rm[ 1] = b.x;
rm[ 5] = b.y;
rm[ 9] = b.z;
rm[ 13] = 0;
rm[ 2] = c.x;
rm[ 6] = c.y;
rm[ 10] = c.z;
rm[ 14] = 0;
rm[ 3] = 0;
rm[ 7] = 0;
rm[ 11] = 0;
rm[ 15] = 1;
multiplicate(rm);
}
public void columns(Vector3f a, Vector3f b, Vector3f c) {
double[] cm = new double[16];
cm[ 0] = a.x;
cm[ 4] = b.x;
cm[ 8] = c.x;
cm[ 12] = 0;
cm[ 1] = a.y;
cm[ 5] = b.y;
cm[ 9] = c.y;
cm[ 13] = 0;
cm[ 2] = a.z;
cm[ 6] = b.z;
cm[ 10] = c.z;
cm[ 14] = 0;
cm[ 3] = 0;
cm[ 7] = 0;
cm[ 11] = 0;
cm[ 15] = 1;
multiplicate(cm);
}
public double determinant() {
return mx[12] * mx[9] * mx[6] * mx[3]
- mx[8] * mx[13] * mx[6] * mx[3]
- mx[12] * mx[5] * mx[10] * mx[3]
+ mx[4] * mx[13] * mx[10] * mx[3]
+ mx[8] * mx[5] * mx[14] * mx[3]
- mx[4] * mx[9] * mx[14] * mx[3]
- mx[12] * mx[9] * mx[2] * mx[7]
+ mx[8] * mx[13] * mx[2] * mx[7]
+ mx[12] * mx[1] * mx[10] * mx[7]
- mx[0] * mx[13] * mx[10] * mx[7]
- mx[8] * mx[1] * mx[14] * mx[7]
+ mx[0] * mx[9] * mx[14] * mx[7]
+ mx[12] * mx[5] * mx[2] * mx[11]
- mx[4] * mx[13] * mx[2] * mx[11]
- mx[12] * mx[1] * mx[6] * mx[11]
+ mx[0] * mx[13] * mx[6] * mx[11]
+ mx[4] * mx[1] * mx[14] * mx[11]
- mx[0] * mx[5] * mx[14] * mx[11]
- mx[8] * mx[5] * mx[2] * mx[15]
+ mx[4] * mx[9] * mx[2] * mx[15]
+ mx[8] * mx[1] * mx[6] * mx[15]
- mx[0] * mx[9] * mx[6] * mx[15]
- mx[4] * mx[1] * mx[10] * mx[15]
+ mx[0] * mx[5] * mx[10] * mx[15];
}
public void invert() {
double[] inverse = new double[16];
generateInverseMatrix(inverse, mx);
mx = inverse;
}
private boolean generateInverseMatrix(double[] i, double[] m) {
double x = determinant();
if (x == 0) {
return false;
}
i[0] = (-m[13] * m[10] * m[7] + m[9] * m[14] * m[7] + m[13] * m[6] * m[11]
- m[5] * m[14] * m[11] - m[9] * m[6] * m[15] + m[5] * m[10] * m[15]) / x;
i[4] = (m[12] * m[10] * m[7] - m[8] * m[14] * m[7] - m[12] * m[6] * m[11]
+ m[4] * m[14] * m[11] + m[8] * m[6] * m[15] - m[4] * m[10] * m[15]) / x;
i[8] = (-m[12] * m[9] * m[7] + m[8] * m[13] * m[7] + m[12] * m[5] * m[11]
- m[4] * m[13] * m[11] - m[8] * m[5] * m[15] + m[4] * m[9] * m[15]) / x;
i[12] = (m[12] * m[9] * m[6] - m[8] * m[13] * m[6] - m[12] * m[5] * m[10]
+ m[4] * m[13] * m[10] + m[8] * m[5] * m[14] - m[4] * m[9] * m[14]) / x;
i[1] = (m[13] * m[10] * m[3] - m[9] * m[14] * m[3] - m[13] * m[2] * m[11]
+ m[1] * m[14] * m[11] + m[9] * m[2] * m[15] - m[1] * m[10] * m[15]) / x;
i[5] = (-m[12] * m[10] * m[3] + m[8] * m[14] * m[3] + m[12] * m[2] * m[11]
- m[0] * m[14] * m[11] - m[8] * m[2] * m[15] + m[0] * m[10] * m[15]) / x;
i[9] = (m[12] * m[9] * m[3] - m[8] * m[13] * m[3] - m[12] * m[1] * m[11]
+ m[0] * m[13] * m[11] + m[8] * m[1] * m[15] - m[0] * m[9] * m[15]) / x;
i[13] = (-m[12] * m[9] * m[2] + m[8] * m[13] * m[2] + m[12] * m[1] * m[10]
- m[0] * m[13] * m[10] - m[8] * m[1] * m[14] + m[0] * m[9] * m[14]) / x;
i[2] = (-m[13] * m[6] * m[3] + m[5] * m[14] * m[3] + m[13] * m[2] * m[7]
- m[1] * m[14] * m[7] - m[5] * m[2] * m[15] + m[1] * m[6] * m[15]) / x;
i[6] = (m[12] * m[6] * m[3] - m[4] * m[14] * m[3] - m[12] * m[2] * m[7]
+ m[0] * m[14] * m[7] + m[4] * m[2] * m[15] - m[0] * m[6] * m[15]) / x;
i[10] = (-m[12] * m[5] * m[3] + m[4] * m[13] * m[3] + m[12] * m[1] * m[7]
- m[0] * m[13] * m[7] - m[4] * m[1] * m[15] + m[0] * m[5] * m[15]) / x;
i[14] = (m[12] * m[5] * m[2] - m[4] * m[13] * m[2] - m[12] * m[1] * m[6]
+ m[0] * m[13] * m[6] + m[4] * m[1] * m[14] - m[0] * m[5] * m[14]) / x;
i[3] = (m[9] * m[6] * m[3] - m[5] * m[10] * m[3] - m[9] * m[2] * m[7]
+ m[1] * m[10] * m[7] + m[5] * m[2] * m[11] - m[1] * m[6] * m[11]) / x;
i[7] = (-m[8] * m[6] * m[3] + m[4] * m[10] * m[3] + m[8] * m[2] * m[7]
- m[0] * m[10] * m[7] - m[4] * m[2] * m[11] + m[0] * m[6] * m[11]) / x;
i[11] = (m[8] * m[5] * m[3] - m[4] * m[9] * m[3] - m[8] * m[1] * m[7]
+ m[0] * m[9] * m[7] + m[4] * m[1] * m[11] - m[0] * m[5] * m[11]) / x;
i[15] = (-m[8] * m[5] * m[2] + m[4] * m[9] * m[2] + m[8] * m[1] * m[6]
- m[0] * m[9] * m[6] - m[4] * m[1] * m[10] + m[0] * m[5] * m[10]) / x;
return true;
}
@Override
public Matrix clone() {
double[] matrix = new double[mx.length];
System.arraycopy(mx, 0, matrix, 0, mx.length);
return new Matrix(matrix);
}
}