package org.dynmap.utils;
import org.json.simple.JSONArray;
/**
* Basic 3D matrix math class - prevent dependency on Java 3D for this
*/
public class Matrix3D {
private double m11, m12, m13, m21, m22, m23, m31, m32, m33;
/**
* Construct identity matrix
*/
public Matrix3D() {
m11 = m22 = m33 = 1.0;
m12 = m13 = m21 = m23 = m31 = m32 = 0.0;
}
/**
* Construct matrix with given parms
*
* @param m11 - first cell of first row
* @param m12 - second cell of first row
* @param m13 - third cell of first row
* @param m21 - first cell of second row
* @param m22 - second cell of second row
* @param m23 - third cell of second row
* @param m31 - first cell of third row
* @param m32 - second cell of third row
* @param m33 - third cell of third row
*/
public Matrix3D(double m11, double m12, double m13, double m21, double m22, double m23, double m31, double m32, double m33) {
this.m11 = m11; this.m12 = m12; this.m13 = m13;
this.m21 = m21; this.m22 = m22; this.m23 = m23;
this.m31 = m31; this.m32 = m32; this.m33 = m33;
}
/**
* Multiply matrix by another matrix (this = mat * this), and store result in self
* @param mat - matrix to multiply
*/
public void multiply(Matrix3D mat) {
double new_m11 = mat.m11*m11 + mat.m12*m21 + mat.m13*m31;
double new_m12 = mat.m11*m12 + mat.m12*m22 + mat.m13*m32;
double new_m13 = mat.m11*m13 + mat.m12*m23 + mat.m13*m33;
double new_m21 = mat.m21*m11 + mat.m22*m21 + mat.m23*m31;
double new_m22 = mat.m21*m12 + mat.m22*m22 + mat.m23*m32;
double new_m23 = mat.m21*m13 + mat.m22*m23 + mat.m23*m33;
double new_m31 = mat.m31*m11 + mat.m32*m21 + mat.m33*m31;
double new_m32 = mat.m31*m12 + mat.m32*m22 + mat.m33*m32;
double new_m33 = mat.m31*m13 + mat.m32*m23 + mat.m33*m33;
m11 = new_m11; m12 = new_m12; m13 = new_m13;
m21 = new_m21; m22 = new_m22; m23 = new_m23;
m31 = new_m31; m32 = new_m32; m33 = new_m33;
}
/**
* Scale each coordinate by given values
*
* @param s1 - X scale
* @param s2 - Y scale
* @param s3 - Z scale
*/
public void scale(double s1, double s2, double s3) {
Matrix3D scalemat = new Matrix3D(s1, 0, 0, 0, s2, 0, 0, 0, s3);
multiply(scalemat);
}
/**
* Rotate XY clockwise around +Z axis
* @param rot_deg - degrees of rotation
*/
public void rotateXY(double rot_deg) {
double rot_rad = Math.toRadians(rot_deg);
double sin_rot = Math.sin(rot_rad);
double cos_rot = Math.cos(rot_rad);
Matrix3D rotmat = new Matrix3D(cos_rot, sin_rot, 0, -sin_rot, cos_rot, 0, 0, 0, 1);
multiply(rotmat);
}
/**
* Rotate YZ clockwise around +X axis
* @param rot_deg - degrees of rotation
*/
public void rotateYZ(double rot_deg) {
double rot_rad = Math.toRadians(rot_deg);
double sin_rot = Math.sin(rot_rad);
double cos_rot = Math.cos(rot_rad);
Matrix3D rotmat = new Matrix3D(1, 0, 0, 0, cos_rot, sin_rot, 0, -sin_rot, cos_rot);
multiply(rotmat);
}
/**
* Shear along Z axis by factor of X and Y
* @param x_fact - X shear
* @param y_fact - Y shear
*/
public void shearZ(double x_fact, double y_fact) {
Matrix3D shearmat = new Matrix3D(1, 0, 0, 0, 1, 0, x_fact, y_fact, 1);
multiply(shearmat);
}
/**
* Transform a given vector using the matrix
* @param v - array[3] of vector coords (input, updated for output)
*/
public final void transform(double[] v) {
double v1 = m11*v[0] + m12*v[1] + m13*v[2];
double v2 = m21*v[0] + m22*v[1] + m23*v[2];
double v3 = m31*v[0] + m32*v[1] + m33*v[2];
v[0] = v1; v[1] = v2; v[2] = v3;
}
/**
* Transform a given vector using the matrix
* @param v - vector input (updated for output)
*/
public final void transform(Vector3D v) {
double v1 = m11*v.x + m12*v.y + m13*v.z;
double v2 = m21*v.x + m22*v.y + m23*v.z;
double v3 = m31*v.x + m32*v.y + m33*v.z;
v.x = v1; v.y = v2; v.z = v3;
}
/**
* Transform a given vector using the matrix - put result in provided output vector
* @param v - input vector
* @param outv - output vector
*/
public final void transform(Vector3D v, Vector3D outv) {
outv.x = m11*v.x + m12*v.y + m13*v.z;
outv.y = m21*v.x + m22*v.y + m23*v.z;
outv.z = m31*v.x + m32*v.y + m33*v.z;
}
public String toString() {
return "[ [" + m11 + " " + m12 + " " + m13 + "] [" + m21 + " " + m22 + " " + m23 + "] [" + m31 + " " + m32 + " " + m33 + "] ]";
}
@SuppressWarnings("unchecked")
public JSONArray toJSON() {
JSONArray array = new JSONArray();
array.add(m11);
array.add(m12);
array.add(m13);
array.add(m21);
array.add(m22);
array.add(m23);
array.add(m31);
array.add(m32);
array.add(m33);
return array;
}
}