package jo.vecmath.logic;
import java.nio.FloatBuffer;
import jo.sm.logic.utils.BufferLogic;
import jo.vecmath.AxisAngle4f;
import jo.vecmath.Matrix3f;
import jo.vecmath.Matrix4f;
import jo.vecmath.Point3f;
import jo.vecmath.Tuple3f;
import jo.vecmath.Vector3f;
public class Matrix4fLogic extends MathUtils {
public static void rotateEuler(Matrix4f m, Tuple3f angles) {
m.mul(makeRotateEulerMatrix(angles), m);
}
public static void rotateEuler(Matrix4f m, float x, float y, float z) {
m.mul(makeRotateEulerMatrix(x, y, z), m);
}
public static void rotateEulerPre(Matrix4f m, Tuple3f angles) {
m.mul(m, makeRotateEulerMatrix(angles));
}
public static void rotateEulerPre(Matrix4f m, float x, float y, float z) {
m.mul(m, makeRotateEulerMatrix(x, y, z));
}
// angles in degrees
public static Matrix4f makeRotateEulerMatrix(Tuple3f angles) {
return makeRotateEulerMatrix(angles.x, angles.y, angles.z);
}
// angles in degrees
public static Matrix4f makeRotateEulerMatrix(float x, float y, float z) {
Matrix4f m = new Matrix4f();
m.setIdentity();
rotX(m, x * DEG_TO_RAD);
rotY(m, y * DEG_TO_RAD);
rotZ(m, z * DEG_TO_RAD);
return m;
}
public static void rotate(Matrix4f m, Tuple3f angles) {
m.mul(makeRotateMatrix(angles), m);
}
// angles in degrees
public static Matrix4f makeRotateMatrix(Tuple3f angles) {
return makeRotateMatrix(angles.x, angles.y, angles.z);
}
// angles in degrees
public static Matrix4f makeRotateMatrix(float x, float y, float z) {
Matrix4f m = new Matrix4f();
m.setIdentity();
rotX(m, x);
rotY(m, y);
rotZ(m, z);
return m;
}
public static void rotate(Matrix4f m, float x, float y, float z, float a) {
m.mul(makeRotateMatrix(x, y, z, a), m);
}
public static void rotate(Matrix4f m, AxisAngle4f angles) {
m.mul(makeRotateMatrix(angles), m);
}
public static Matrix4f makeRotateMatrix(float x, float y, float z, float a) {
return makeRotateMatrix(new AxisAngle4f(x, y, z, a));
}
public static Matrix4f makeRotateMatrix(AxisAngle4f axis) {
Matrix4f m = new Matrix4f();
m.setIdentity();
m.set(axis);
return m;
}
public static Matrix4f makeRotateMatrix(Matrix3f rot) {
Matrix4f m = new Matrix4f();
m.m00 = rot.m00;
m.m01 = rot.m01;
m.m02 = rot.m02;
m.m03 = 0f;
m.m10 = rot.m10;
m.m11 = rot.m11;
m.m12 = rot.m12;
m.m13 = 0f;
m.m20 = rot.m20;
m.m21 = rot.m21;
m.m22 = rot.m22;
m.m23 = 0f;
m.m30 = 0.0f;
m.m31 = 0.0f;
m.m32 = 0.0f;
m.m33 = 1.0f;
return m;
}
public static void rotX(Matrix4f m, float radians) {
m.mul(makeRotXMatrix(radians), m);
}
public static Matrix4f makeRotXMatrix(float radians) {
Matrix4f m = new Matrix4f();
m.rotX(radians);
return m;
}
public static void rotY(Matrix4f m, float radians) {
m.mul(makeRotYMatrix(radians), m);
}
public static Matrix4f makeRotYMatrix(float radians) {
Matrix4f m = new Matrix4f();
m.rotY(radians);
return m;
}
public static void rotZ(Matrix4f m, float radians) {
m.mul(makeRotZMatrix(radians), m);
}
public static Matrix4f makeRotZMatrix(float radians) {
Matrix4f m = new Matrix4f();
m.rotZ(radians);
return m;
}
public static void scale(Matrix4f m, float scale) {
scale(m, new Point3f(scale, scale, scale));
}
public static void scale(Matrix4f m, Tuple3f scale) {
m.mul(makeScaleMatrix(scale), m);
}
public static Matrix4f makeScaleMatrix(Tuple3f scale) {
return makeScaleMatrix(scale.x, scale.y, scale.z);
}
public static Matrix4f makeScaleMatrix(float s) {
return makeScaleMatrix(s, s, s);
}
public static Matrix4f makeScaleMatrix(float x, float y, float z) {
Matrix4f m = new Matrix4f();
m.m00 = x;
m.m01 = (float) 0.0;
m.m02 = (float) 0.0;
m.m03 = (float) 0.0;
m.m10 = (float) 0.0;
m.m11 = y;
m.m12 = (float) 0.0;
m.m13 = (float) 0.0;
m.m20 = (float) 0.0;
m.m21 = (float) 0.0;
m.m22 = z;
m.m23 = (float) 0.0;
m.m30 = (float) 0.0;
m.m31 = (float) 0.0;
m.m32 = (float) 0.0;
m.m33 = (float) 1.0;
return m;
}
public static void translate(Matrix4f m, float x, float y, float z) {
translate(m, new Point3f(x, y, z));
}
public static void translate(Matrix4f m, Tuple3f scale) {
m.mul(makeTranslateMatrix(scale), m);
}
public static Matrix4f makeTranslateMatrix(Tuple3f translate) {
Matrix4f m = new Matrix4f();
m.m00 = (float) 1.0;
m.m01 = (float) 0.0;
m.m02 = (float) 0.0;
m.m03 = translate.x;
m.m10 = (float) 0.0;
m.m11 = (float) 1.0;
m.m12 = (float) 0.0;
m.m13 = translate.y;
m.m20 = (float) 0.0;
m.m21 = (float) 0.0;
m.m22 = (float) 1.0;
m.m23 = translate.z;
m.m30 = (float) 0.0;
m.m31 = (float) 0.0;
m.m32 = (float) 0.0;
m.m33 = (float) 1.0;
return m;
}
public static void orientateTo(Matrix4f m, Tuple3f lookAt) {
m.mul(makeOrientateToMatrix(lookAt), m);
}
// return transform that will rotate (1,0,0) to the direction vector given
public static Matrix4f makeOrientateToMatrix(Tuple3f lookAt) {
Matrix4f m = new Matrix4f();
m.setIdentity();
boolean xZero = epsilonEquals(lookAt.x, 0);
boolean yZero = epsilonEquals(lookAt.y, 0);
boolean zZero = epsilonEquals(lookAt.z, 0);
// evaluate trivial options
if (xZero) {
if (yZero) {
if (zZero)
; // no op
else if (lookAt.z < 0) {
rotY(m, Euler90);
} else {
rotY(m, -Euler90);
}
} else if (zZero) {
if (lookAt.y < 0) {
rotZ(m, -Euler90);
} else {
rotZ(m, Euler90);
}
} else { // YZ plane
float a = atan2(lookAt.y, lookAt.z);
rotX(m, a);
if (Math.signum(lookAt.y) == Math.signum(lookAt.z)) {
rotZ(m, Euler90);
} else {
rotZ(m, -Euler90);
}
}
} else if (yZero) {
if (zZero) {
if (lookAt.x < 0) {
rotY(m, Euler180);
} else
;
} else { // XZ plane
float a = atan2(lookAt.z, lookAt.x);
rotY(m, -a);
}
} else if (zZero) { // XY plane
float a = atan2(lookAt.y, lookAt.x);
rotZ(m, a);
} else {
float xy = (float) Math.sqrt(lookAt.x * lookAt.x + lookAt.y * lookAt.y);
rotZ(m, atan2(lookAt.y, lookAt.x));
rotY(m, -atan2(lookAt.z, xy));
}
return m;
}
public static float[] toFloatArray(Matrix4f m) {
float[] v = new float[16];
v[ 0] = m.m00;
v[ 1] = m.m10;
v[ 2] = m.m20;
v[ 3] = m.m30;
v[ 4] = m.m01;
v[ 5] = m.m11;
v[ 6] = m.m21;
v[ 7] = m.m31;
v[ 8] = m.m02;
v[ 9] = m.m12;
v[10] = m.m22;
v[11] = m.m32;
v[12] = m.m03;
v[13] = m.m13;
v[14] = m.m23;
v[15] = m.m33;
return v;
}
public static FloatBuffer toFloatBuffer(Matrix4f m) {
return BufferLogic.create(toFloatArray(m));
}
public static void lookAt(Matrix4f transform, Point3f standHere, Point3f lookAtThis) {
// assume +z is the direction we are looking
Vector3f zaxis = new Vector3f(lookAtThis);
zaxis.sub(standHere);
zaxis.normalize();
Vector3f provisionalUp;
// if we're not looking along +y make that up, otherwise make it +z
if (!MathUtils.equals(zaxis.x, 0) || !MathUtils.equals(zaxis.z, 0)) {
provisionalUp = new Vector3f(0, 1, 0);
} else {
provisionalUp = new Vector3f(0, 0, 1);
}
Vector3f xaxis = new Vector3f();
xaxis.cross(zaxis, provisionalUp); // +x is left
xaxis.normalize();
Vector3f yaxis = new Vector3f();
yaxis.cross(xaxis, zaxis); // +y is the real up
yaxis.normalize();
transform.m00 = xaxis.x;
transform.m01 = yaxis.x;
transform.m02 = zaxis.x;
transform.m03 = standHere.x;
transform.m10 = xaxis.y;
transform.m11 = yaxis.y;
transform.m12 = zaxis.y;
transform.m13 = standHere.y;
transform.m20 = xaxis.z;
transform.m21 = yaxis.z;
transform.m22 = zaxis.z;
transform.m23 = standHere.z;
transform.m30 = 0;
transform.m31 = 0;
transform.m32 = 0;
transform.m33 = 1;
}
}