package speiger.src.coreengine.math.vector.matrix; import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.util.Arrays; import speiger.src.coreengine.math.MathUtils; import speiger.src.coreengine.math.vector.VectorUtil; import speiger.src.coreengine.math.vector.floats.Vec2f; import speiger.src.coreengine.math.vector.floats.Vec3f; import speiger.src.coreengine.math.vector.floats.Vec4f; import speiger.src.coreengine.math.vector.quaternion.Quaternion; public class Matrix4f { static final Vec3f X_ROTATION = Vec3f.newVec(1F, 0F, 0F); static final Vec3f Y_ROTATION = Vec3f.newVec(0F, 1F, 0F); static final Vec3f Z_ROTATION = Vec3f.newVec(0F, 0F, 1F); float[] data = new float[16]; public Matrix4f() { setIdentity(); } public Matrix4f(float[] data) { System.arraycopy(data, 0, this.data, 0, 16); } public Matrix4f(Matrix4f other) { this(other.data); } public Matrix4f store(FloatBuffer buffer) { buffer.put(data); return this; } public Matrix4f store(ByteBuffer buffer) { for(int i = 0;i < 16;i++) { buffer.putFloat(data[i]); } return this; } public Matrix4f store(Matrix4f other) { System.arraycopy(data, 0, other.data, 0, 16); return this; } public Matrix4f load(FloatBuffer buffer) { buffer.get(data); return this; } public Matrix4f load(ByteBuffer buffer) { for(int i = 0;i < 16;i++) { data[i] = buffer.getFloat(); } return this; } public Matrix4f load(Matrix4f other) { System.arraycopy(other.data, 0, data, 0, 16); return this; } @Override public String toString() { StringBuilder buf = new StringBuilder().append("\n"); buf.append("x0=").append(data[0]).append(' ').append("y0=").append(data[4]).append(' ').append("z0=").append(data[8]).append(' ').append("w0=").append(data[12]).append('\n'); buf.append("x1=").append(data[1]).append(' ').append("y1=").append(data[5]).append(' ').append("z1=").append(data[9]).append(' ').append("w1=").append(data[13]).append('\n'); buf.append("x2=").append(data[2]).append(' ').append("y2=").append(data[6]).append(' ').append("z2=").append(data[10]).append(' ').append("w2=").append(data[14]).append('\n'); buf.append("x3=").append(data[3]).append(' ').append("y3=").append(data[7]).append(' ').append("z3=").append(data[11]).append(' ').append("w3=").append(data[15]).append('\n'); return buf.toString(); } @Override public boolean equals(Object obj) { if(obj instanceof Matrix4f) { return Arrays.equals(data, ((Matrix4f)obj).data); } return false; } public float[] getData() { return data; } public float get(int index) { return data[index]; } public float get(int column, int row) { return data[(column * 4) + row]; } public Matrix4f set(int column, int row, float value) { data[(column * 4) + row] = value; return this; } public Matrix4f set(int index, float value) { data[index] = value; return this; } public Matrix4f setIdentity() { Arrays.fill(data, 0F); data[0] = 1F; data[5] = 1F; data[10] = 1F; data[15] = 1F; return this; } public Matrix4f invert() { float determinant = determinant(); if(determinant != 0F) { float determinant_inv = 1F / determinant; float t00 = determinant3x3(data[5], data[6], data[7], data[9], data[10], data[11], data[13], data[14], data[15]); float t01 = -determinant3x3(data[4], data[6], data[7], data[8], data[10], data[11], data[12], data[14], data[15]); float t02 = determinant3x3(data[4], data[5], data[7], data[8], data[9], data[11], data[12], data[13], data[15]); float t03 = -determinant3x3(data[4], data[5], data[6], data[8], data[9], data[10], data[12], data[13], data[14]); float t10 = -determinant3x3(data[1], data[2], data[3], data[9], data[10], data[11], data[13], data[14], data[15]); float t11 = determinant3x3(data[0], data[2], data[3], data[8], data[10], data[11], data[12], data[14], data[15]); float t12 = -determinant3x3(data[0], data[1], data[3], data[8], data[9], data[11], data[12], data[13], data[15]); float t13 = determinant3x3(data[0], data[1], data[2], data[8], data[9], data[10], data[12], data[13], data[14]); float t20 = determinant3x3(data[1], data[2], data[3], data[5], data[6], data[7], data[13], data[14], data[15]); float t21 = -determinant3x3(data[0], data[2], data[3], data[4], data[6], data[7], data[12], data[14], data[15]); float t22 = determinant3x3(data[0], data[1], data[3], data[4], data[5], data[7], data[12], data[13], data[15]); float t23 = -determinant3x3(data[0], data[1], data[2], data[4], data[5], data[6], data[12], data[13], data[14]); float t30 = -determinant3x3(data[1], data[2], data[3], data[5], data[6], data[7], data[9], data[10], data[11]); float t31 = determinant3x3(data[0], data[2], data[3], data[4], data[6], data[7], data[8], data[10], data[11]); float t32 = -determinant3x3(data[0], data[1], data[3], data[4], data[5], data[7], data[8], data[9], data[11]); float t33 = determinant3x3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); data[0] = t00 * determinant_inv; data[5] = t11 * determinant_inv; data[10] = t22 * determinant_inv; data[15] = t33 * determinant_inv; data[1] = t10 * determinant_inv; data[4] = t01 * determinant_inv; data[8] = t02 * determinant_inv; data[2] = t20 * determinant_inv; data[6] = t21 * determinant_inv; data[9] = t12 * determinant_inv; data[3] = t30 * determinant_inv; data[12] = t03 * determinant_inv; data[7] = t31 * determinant_inv; data[13] = t13 * determinant_inv; data[14] = t23 * determinant_inv; data[11] = t32 * determinant_inv; } return this; } public Matrix4f flip() { data[0] = -data[0]; data[1] = -data[1]; data[2] = -data[2]; data[3] = -data[3]; data[4] = -data[4]; data[5] = -data[5]; data[6] = -data[6]; data[7] = -data[7]; data[8] = -data[8]; data[9] = -data[9]; data[10] = -data[10]; data[11] = -data[11]; data[12] = -data[12]; data[13] = -data[13]; data[14] = -data[14]; data[15] = -data[15]; return this; } public Matrix4f negate() { Arrays.fill(data, 0F); return this; } public Matrix4f add(Matrix4f other) { data[0] += other.data[0]; data[1] += other.data[1]; data[2] += other.data[2]; data[3] += other.data[3]; data[4] += other.data[4]; data[5] += other.data[5]; data[6] += other.data[6]; data[7] += other.data[7]; data[8] += other.data[8]; data[9] += other.data[9]; data[10] += other.data[10]; data[11] += other.data[11]; data[12] += other.data[12]; data[13] += other.data[13]; data[14] += other.data[14]; data[15] += other.data[15]; return this; } public Matrix4f sub(Matrix4f other) { data[0] -= other.data[0]; data[1] -= other.data[1]; data[2] -= other.data[2]; data[3] -= other.data[3]; data[4] -= other.data[4]; data[5] -= other.data[5]; data[6] -= other.data[6]; data[7] -= other.data[7]; data[8] -= other.data[8]; data[9] -= other.data[9]; data[10] -= other.data[10]; data[11] -= other.data[11]; data[12] -= other.data[12]; data[13] -= other.data[13]; data[14] -= other.data[14]; data[15] -= other.data[15]; return this; } public Matrix4f multiply(Matrix4f other) { float data0 = data[0] * other.data[0] + data[4] * other.data[1] + data[8] * other.data[2] + data[12] * other.data[3]; float data1 = data[1] * other.data[0] + data[5] * other.data[1] + data[9] * other.data[2] + data[13] * other.data[3]; float data2 = data[2] * other.data[0] + data[6] * other.data[1] + data[10] * other.data[2] + data[14] * other.data[3]; float data3 = data[3] * other.data[0] + data[7] * other.data[1] + data[11] * other.data[2] + data[15] * other.data[3]; float data4 = data[0] * other.data[4] + data[4] * other.data[5] + data[8] * other.data[6] + data[12] * other.data[7]; float data5 = data[1] * other.data[4] + data[5] * other.data[5] + data[9] * other.data[6] + data[13] * other.data[7]; float data6 = data[2] * other.data[4] + data[6] * other.data[5] + data[10] * other.data[6] + data[14] * other.data[7]; float data7 = data[3] * other.data[4] + data[7] * other.data[5] + data[11] * other.data[6] + data[15] * other.data[7]; float data8 = data[0] * other.data[8] + data[4] * other.data[9] + data[8] * other.data[10] + data[12] * other.data[11]; float data9 = data[1] * other.data[8] + data[5] * other.data[9] + data[9] * other.data[10] + data[13] * other.data[11]; float data10 = data[2] * other.data[8] + data[6] * other.data[9] + data[10] * other.data[10] + data[14] * other.data[11]; float data11 = data[3] * other.data[8] + data[7] * other.data[9] + data[11] * other.data[10] + data[15] * other.data[11]; float data12 = data[0] * other.data[12] + data[4] * other.data[13] + data[8] * other.data[14] + data[12] * other.data[15]; float data13 = data[1] * other.data[12] + data[5] * other.data[13] + data[9] * other.data[14] + data[13] * other.data[15]; float data14 = data[2] * other.data[12] + data[6] * other.data[13] + data[10] * other.data[14] + data[14] * other.data[15]; float data15 = data[3] * other.data[12] + data[7] * other.data[13] + data[11] * other.data[14] + data[15] * other.data[15]; data[0] = data0; data[1] = data1; data[2] = data2; data[3] = data3; data[4] = data4; data[5] = data5; data[6] = data6; data[7] = data7; data[8] = data8; data[9] = data9; data[10] = data10; data[11] = data11; data[12] = data12; data[13] = data13; data[14] = data14; data[15] = data15; return this; } public Matrix4f transpose() { float data0 = data[0]; float data1 = data[4]; float data2 = data[8]; float data3 = data[12]; float data4 = data[1]; float data5 = data[5]; float data6 = data[9]; float data7 = data[13]; float data8 = data[2]; float data9 = data[6]; float data10 = data[10]; float data11 = data[14]; float data12 = data[3]; float data13 = data[7]; float data14 = data[11]; float data15 = data[15]; data[0] = data0; data[1] = data1; data[2] = data2; data[3] = data3; data[4] = data4; data[5] = data5; data[6] = data6; data[7] = data7; data[8] = data8; data[9] = data9; data[10] = data10; data[11] = data11; data[12] = data12; data[13] = data13; data[14] = data14; data[15] = data15; return this; } public Matrix4f transpose3x3() { float nm00 = data[0]; float nm01 = data[4]; float nm02 = data[8]; float nm10 = data[1]; float nm11 = data[5]; float nm12 = data[9]; float nm20 = data[2]; float nm21 = data[6]; float nm22 = data[10]; data[0] = nm00; data[1] = nm01; data[2] = nm02; data[4] = nm10; data[5] = nm11; data[6] = nm12; data[8] = nm20; data[9] = nm21; data[10] = nm22; return this; } public Matrix4f decompose(Vec3f position, Quaternion rotation, Vec3f scale) { position.set(get(3, 0), get(3, 1), get(3, 2)); rotation.set(this); scale.set(get(0, 0), get(1, 1), get(2, 2)); return this; } public Matrix4f setTranslation(Vec3f vec) { data[12] = vec.getX(); data[13] = vec.getY(); data[14] = vec.getZ(); return this; } public Matrix4f translate(Vec2f vec) { return translate(vec.getX(), vec.getY()); } public Matrix4f translate(float x, float y) { data[12] += data[0] * x + data[4] * y; data[13] += data[1] * x + data[5] * y; data[14] += data[2] * x + data[6] * y; data[15] += data[3] * x + data[7] * y; return this; } public Matrix4f translate(Vec3f vec) { data[12] += data[0] * vec.getX() + data[4] * vec.getY() + data[8] * vec.getZ(); data[13] += data[1] * vec.getX() + data[5] * vec.getY() + data[9] * vec.getZ(); data[14] += data[2] * vec.getX() + data[6] * vec.getY() + data[10] * vec.getZ(); data[15] += data[3] * vec.getX() + data[7] * vec.getY() + data[11] * vec.getZ(); return this; } public Matrix4f translate(float x, float y, float z) { data[12] += data[0] * x + data[4] * y + data[8] * z; data[13] += data[1] * x + data[5] * y + data[9] * z; data[14] += data[2] * x + data[6] * y + data[10] * z; data[15] += data[3] * x + data[7] * y + data[11] * z; return this; } public Matrix4f rotateX(float angle) { return rotate((float)Math.toRadians(angle), X_ROTATION); } public Matrix4f rotateY(float angle) { return rotate((float)Math.toRadians(angle), Y_ROTATION); } public Matrix4f rotateZ(float angle) { return rotate((float)Math.toRadians(angle), Z_ROTATION); } public Matrix4f rotateRadX(float angle) { return rotate(angle, X_ROTATION); } public Matrix4f rotateRadY(float angle) { return rotate(angle, Y_ROTATION); } public Matrix4f rotateRadZ(float angle) { return rotate(angle, Z_ROTATION); } public Matrix4f rotate(float angle, Vec3f axis) { float c = MathUtils.cos(angle); float s = MathUtils.sin(angle); float oneminusc = 1.0f - c; float xy = axis.getX() * axis.getY(); float yz = axis.getY() * axis.getZ(); float xz = axis.getX() * axis.getZ(); float xs = axis.getX() * s; float ys = axis.getY() * s; float zs = axis.getZ() * s; float f00 = axis.getX() * axis.getX() * oneminusc + c; float f01 = xy * oneminusc + zs; float f02 = xz * oneminusc - ys; float f10 = xy * oneminusc - zs; float f11 = axis.getY() * axis.getY() * oneminusc + c; float f12 = yz * oneminusc + xs; float f20 = xz * oneminusc + ys; float f21 = yz * oneminusc - xs; float f22 = axis.getZ() * axis.getZ() * oneminusc + c; float t00 = data[0] * f00 + data[4] * f01 + data[8] * f02; float t01 = data[1] * f00 + data[5] * f01 + data[9] * f02; float t02 = data[2] * f00 + data[6] * f01 + data[10] * f02; float t03 = data[3] * f00 + data[7] * f01 + data[11] * f02; float t10 = data[0] * f10 + data[4] * f11 + data[8] * f12; float t11 = data[1] * f10 + data[5] * f11 + data[9] * f12; float t12 = data[2] * f10 + data[6] * f11 + data[10] * f12; float t13 = data[3] * f10 + data[7] * f11 + data[11] * f12; data[8] = data[0] * f20 + data[4] * f21 + data[8] * f22; data[9] = data[1] * f20 + data[5] * f21 + data[9] * f22; data[10] = data[2] * f20 + data[6] * f21 + data[10] * f22; data[11] = data[3] * f20 + data[7] * f21 + data[11] * f22; data[0] = t00; data[1] = t01; data[2] = t02; data[3] = t03; data[4] = t10; data[5] = t11; data[6] = t12; data[7] = t13; return this; } public Matrix4f rotate(Quaternion rotation) { float w2 = rotation.getW() * rotation.getW(); float x2 = rotation.getX() * rotation.getX(); float y2 = rotation.getY() * rotation.getY(); float z2 = rotation.getZ() * rotation.getZ(); float zw = rotation.getZ() * rotation.getW(); float dzw = zw + zw; float xy = rotation.getX() * rotation.getY(); float dxy = xy + xy; float xz = rotation.getX() * rotation.getZ(); float dxz = xz + xz; float yw = rotation.getY() * rotation.getW(); float dyw = yw + yw; float yz = rotation.getY() * rotation.getZ(); float dyz = yz + yz; float xw = rotation.getX() * rotation.getW(); float dxw = xw + xw; float rm00 = w2 + x2 - z2 - y2; float rm01 = dxy + dzw; float rm02 = dxz - dyw; float rm10 = -dzw + dxy; float rm11 = y2 - z2 + w2 - x2; float rm12 = dyz + dxw; float rm20 = dyw + dxz; float rm21 = dyz - dxw; float rm22 = z2 - y2 - x2 + w2; float nm00 = data[0] * rm00 + data[4] * rm01 + data[8] * rm02; float nm01 = data[1] * rm00 + data[5] * rm01 + data[9] * rm02; float nm02 = data[2] * rm00 + data[6] * rm01 + data[10] * rm02; float nm03 = data[3] * rm00 + data[7] * rm01 + data[11] * rm02; float nm10 = data[0] * rm10 + data[4] * rm11 + data[8] * rm12; float nm11 = data[1] * rm10 + data[5] * rm11 + data[9] * rm12; float nm12 = data[2] * rm10 + data[6] * rm11 + data[10] * rm12; float nm13 = data[3] * rm10 + data[7] * rm11 + data[11] * rm12; data[8] = data[0] * rm20 + data[4] * rm21 + data[8] * rm22; data[9] = data[1] * rm20 + data[5] * rm21 + data[9] * rm22; data[10] = data[2] * rm20 + data[6] * rm21 + data[10] * rm22; data[11] = data[3] * rm20 + data[7] * rm21 + data[11] * rm22; data[0] = nm00; data[1] = nm01; data[2] = nm02; data[3] = nm03; data[4] = nm10; data[5] = nm11; data[6] = nm12; data[7] = nm13; return this; } public Matrix4f setRotation(Matrix4f source) { data[0] = source.data[0]; data[1] = source.data[1]; data[2] = source.data[2]; data[4] = source.data[4]; data[5] = source.data[5]; data[6] = source.data[6]; data[8] = source.data[8]; data[9] = source.data[9]; data[10] = source.data[10]; return this; } public Matrix4f setBillboard(Matrix4f source) { data[0] = source.data[0]; data[1] = source.data[4]; data[2] = source.data[8]; data[4] = source.data[1]; data[5] = source.data[5]; data[6] = source.data[9]; data[8] = source.data[2]; data[9] = source.data[6]; data[10] = source.data[10]; return this; } public Matrix4f scale(Vec3f vec) { return scale(vec.getX(), vec.getY(), vec.getZ()); } public Matrix4f scale(float value) { return scale(value, value, value); } public Matrix4f scale(float x, float y, float z) { data[0] *= x; data[1] *= x; data[2] *= x; data[3] *= x; data[4] *= y; data[5] *= y; data[6] *= y; data[7] *= y; data[8] *= z; data[9] *= z; data[10] *= z; data[11] *= z; return this; } public Matrix4f unscale(Vec3f vec) { return unscale(vec.getX(), vec.getY(), vec.getZ()); } public Matrix4f unscale(float scale) { return unscale(scale, scale, scale); } public Matrix4f unscale(float x, float y, float z) { data[0] /= x; data[1] /= x; data[2] /= x; data[3] /= x; data[4] /= y; data[5] /= y; data[6] /= y; data[7] /= y; data[8] /= z; data[9] /= z; data[10] /= z; data[11] /= z; return this; } public Matrix4f setPerspective(float fovy, float aspect, float zNear, float zFar) { float h = (float)Math.tan(fovy * 0.5f); set(0, 0, 1F / (h * aspect)).set(1, 1, 1F / h); boolean farInf = zFar > 0 && Float.isInfinite(zFar); boolean nearInf = zNear > 0 && Float.isInfinite(zNear); if(farInf) { float e = 1E-6f; set(2, 2, e - 1F).set(3, 2, (e - 2F) * zNear); } else if(nearInf) { float e = 1E-6f; set(2, 2, 1F - e).set(3, 2, (2F - e) * zFar); } else { set(2, 2, (zFar + zNear) / (zNear - zFar)).set(3, 2, (zFar + zFar) * zNear / (zNear - zFar)); } return set(2, 3, -1.0f); } public Matrix4f getTranslation(Vec3f vec) { vec.set(data[12], data[13], data[14]); return this; } public Matrix4f getScale(Vec3f vec) { vec.setX((float)Math.sqrt(data[0] * data[0] + data[1] * data[1] + data[2] * data[2])); vec.setY((float)Math.sqrt(data[4] * data[4] + data[5] * data[5] + data[6] * data[6])); vec.setZ((float)Math.sqrt(data[8] * data[8] + data[9] * data[9] + data[10] * data[10])); return this; } public Vec4f transform(Vec4f input) { return transform(input, input); } public Vec4f transform(Vec4f input, Vec4f output) { float x = data[0] * input.getX() + data[4] * input.getY() + data[8] * input.getZ() + data[12] * input.getW(); float y = data[1] * input.getX() + data[5] * input.getY() + data[9] * input.getZ() + data[13] * input.getW(); float z = data[2] * input.getX() + data[6] * input.getY() + data[10] * input.getZ() + data[14] * input.getW(); float w = data[3] * input.getX() + data[7] * input.getY() + data[11] * input.getZ() + data[15] * input.getW(); return output.set(x, y, z, w); } public void transform(Vec4f input, FloatBuffer buffer) { buffer.put(data[0] * input.getX() + data[4] * input.getY() + data[8] * input.getZ() + data[12] * input.getW()); buffer.put(data[1] * input.getX() + data[5] * input.getY() + data[9] * input.getZ() + data[13] * input.getW()); buffer.put(data[2] * input.getX() + data[6] * input.getY() + data[10] * input.getZ() + data[14] * input.getW()); buffer.put(data[3] * input.getX() + data[7] * input.getY() + data[11] * input.getZ() + data[15] * input.getW()); } public Vec3f transform(Vec3f input, boolean position) { return transform(input, input, position); } public Vec3f transform(Vec3f input, Vec3f output, boolean position) { float pos = position ? 1F : 0F; return output.set(data[0] * input.getX() + data[4] * input.getY() + data[8] * input.getZ() + data[12] * pos, data[1] * input.getX() + data[5] * input.getY() + data[9] * input.getZ() + data[13] * pos, data[2] * input.getX() + data[6] * input.getY() + data[10] * input.getZ() + data[14] * pos); } public void transform(Vec3f input, FloatBuffer buffer, boolean position) { float pos = position ? 1F : 0F; buffer.put(data[0] * input.getX() + data[4] * input.getY() + data[8] * input.getZ() + data[12] * pos); buffer.put(data[1] * input.getX() + data[5] * input.getY() + data[9] * input.getZ() + data[13] * pos); buffer.put(data[2] * input.getX() + data[6] * input.getY() + data[10] * input.getZ() + data[14] * pos); } public float determinant() { float f = data[0] * ((data[5] * data[10] * data[15] + data[6] * data[11] * data[13] + data[7] * data[9] * data[14]) - data[7] * data[10] * data[13] - data[5] * data[11] * data[14] - data[6] * data[9] * data[15]); f -= data[1] * ((data[4] * data[10] * data[15] + data[6] * data[11] * data[12] + data[7] * data[8] * data[14]) - data[7] * data[10] * data[12] - data[4] * data[11] * data[14] - data[6] * data[8] * data[15]); f += data[2] * ((data[4] * data[9] * data[15] + data[5] * data[11] * data[12] + data[7] * data[8] * data[13]) - data[7] * data[9] * data[12] - data[4] * data[11] * data[13] - data[5] * data[8] * data[15]); f -= data[3] * ((data[4] * data[9] * data[14] + data[5] * data[10] * data[12] + data[6] * data[8] * data[13]) - data[6] * data[9] * data[12] - data[4] * data[10] * data[13] - data[5] * data[8] * data[14]); return f; } public float determinant3x3(float t00, float t01, float t02, float t10, float t11, float t12, float t20, float t21, float t22) { return t00 * (t11 * t22 - t12 * t21) + t01 * (t12 * t20 - t10 * t22) + t02 * (t10 * t21 - t11 * t20); } public Matrix4f setTransform(Vec3f position, Vec3f rotation, float scale) { setIdentity(); translate(position); rotate((float)Math.toRadians(rotation.getX()), X_ROTATION); rotate((float)Math.toRadians(rotation.getY()), Y_ROTATION); rotate((float)Math.toRadians(rotation.getZ()), Z_ROTATION); scale(scale, scale, scale); return this; } public Matrix4f setTransform(Vec3f position, Vec3f rotation, Vec3f scale) { setIdentity(); translate(position); rotate((float)Math.toRadians(rotation.getX()), X_ROTATION); rotate((float)Math.toRadians(rotation.getY()), Y_ROTATION); rotate((float)Math.toRadians(rotation.getZ()), Z_ROTATION); scale(scale); return this; } public Matrix4f setTransform(Vec3f position, Vec3f offset, Vec3f rotation, float scale) { setIdentity(); translate(position); translate(offset); rotate((float)Math.toRadians(rotation.getX()), X_ROTATION); rotate((float)Math.toRadians(rotation.getY()), Y_ROTATION); rotate((float)Math.toRadians(rotation.getZ()), Z_ROTATION); scale(scale, scale, scale); return this; } public Matrix4f setTransform(Vec3f position, Vec3f offset, Vec3f rotation, Vec3f scale) { setIdentity(); translate(position); translate(offset); rotate((float)Math.toRadians(rotation.getX()), X_ROTATION); rotate((float)Math.toRadians(rotation.getY()), Y_ROTATION); rotate((float)Math.toRadians(rotation.getZ()), Z_ROTATION); scale(scale); return this; } public Matrix4f setTransform(Vec3f position, Quaternion rotation, float scale) { setIdentity(); translate(position); rotate(rotation); scale(scale, scale, scale); return this; } public Matrix4f setTransform(Vec3f position, Quaternion rotation, Vec3f scale) { setIdentity(); translate(position); rotate(rotation); scale(scale); return this; } public Matrix4f setTransform(Vec3f position, Vec3f offset, Quaternion rotation, float scale) { setIdentity(); translate(position); translate(offset); rotate(rotation); scale(scale, scale, scale); return this; } public Matrix4f setTransform(Vec3f position, Vec3f offset, Quaternion rotation, Vec3f scale) { setIdentity(); translate(position); translate(offset); rotate(rotation); scale(scale); return this; } public Matrix4f setTransform(Vec3f position, Matrix4f billRotation, float scale) { setIdentity(); translate(position); setBillboard(billRotation); scale(scale, scale, scale); return this; } public Matrix4f setTransform(Vec3f position, Matrix4f billRotation, Vec3f scale) { setIdentity(); translate(position); setBillboard(billRotation); transpose3x3(); scale(scale); return this; } public Vec3f project(float x, float y, float z, int[] viewport, Vec3f winCoordsDest) { float invW = 1F / VectorUtil.fma(data[3], x, VectorUtil.fma(data[7], y, VectorUtil.fma(data[11], z, data[15]))); float nx = VectorUtil.fma(data[0], x, VectorUtil.fma(data[4], y, VectorUtil.fma(data[8], z, data[12]))) * invW; float ny = VectorUtil.fma(data[1], x, VectorUtil.fma(data[5], y, VectorUtil.fma(data[9], z, data[13]))) * invW; float nz = VectorUtil.fma(data[2], x, VectorUtil.fma(data[6], y, VectorUtil.fma(data[10], z, data[14]))) * invW; return winCoordsDest.set(VectorUtil.fma(VectorUtil.fma(nx, 0.5F, 0.5F), viewport[2], viewport[0]), VectorUtil.fma(VectorUtil.fma(ny, 0.5F, 0.5F), viewport[3], viewport[1]), VectorUtil.fma(0.5F, nz, 0.5F)); } public Vec3f unproject(float winX, float winY, float winZ, int[] viewport, Vec3f dest) { float a = data[0] * data[5] - data[1] * data[4]; float b = data[0] * data[6] - data[2] * data[4]; float c = data[0] * data[7] - data[3] * data[4]; float d = data[1] * data[6] - data[2] * data[5]; float e = data[1] * data[7] - data[3] * data[5]; float f = data[2] * data[7] - data[3] * data[6]; float g = data[8] * data[13] - data[9] * data[12]; float h = data[8] * data[14] - data[10] * data[12]; float i = data[8] * data[15] - data[11] * data[12]; float j = data[9] * data[14] - data[10] * data[13]; float k = data[9] * data[15] - data[11] * data[13]; float l = data[10] * data[15] - data[11] * data[14]; float det = a * l - b * k + c * j + d * i - e * h + f * g; det = 1.0f / det; float im00 = ( data[5] * l - data[6] * k + data[7] * j) * det; float im01 = (-data[1] * l + data[2] * k - data[3] * j) * det; float im02 = ( data[13] * f - data[14] * e + data[15] * d) * det; float im03 = (-data[9] * f + data[10] * e - data[11] * d) * det; float im10 = (-data[4] * l + data[6] * i - data[7] * h) * det; float im11 = ( data[0] * l - data[2] * i + data[3] * h) * det; float im12 = (-data[12] * f + data[14] * c - data[15] * b) * det; float im13 = ( data[8] * f - data[10] * c + data[11] * b) * det; float im20 = ( data[4] * k - data[5] * i + data[7] * g) * det; float im21 = (-data[0] * k + data[1] * i - data[3] * g) * det; float im22 = ( data[12] * e - data[13] * c + data[15] * a) * det; float im23 = (-data[8] * e + data[9] * c - data[11] * a) * det; float im30 = (-data[4] * j + data[5] * h - data[6] * g) * det; float im31 = ( data[0] * j - data[1] * h + data[2] * g) * det; float im32 = (-data[12] * d + data[13] * b - data[14] * a) * det; float im33 = ( data[8] * d - data[9] * b + data[10] * a) * det; float ndcX = (winX-viewport[0])/viewport[2]*2.0f-1.0f; float ndcY = (winY-viewport[1])/viewport[3]*2.0f-1.0f; float ndcZ = winZ+winZ-1.0f; float invW = 1.0f / (im03 * ndcX + im13 * ndcY + im23 * ndcZ + im33); return dest.set((im00 * ndcX + im10 * ndcY + im20 * ndcZ + im30) * invW, (im01 * ndcX + im11 * ndcY + im21 * ndcZ + im31) * invW, (im02 * ndcX + im12 * ndcY + im22 * ndcZ + im32) * invW); } public Matrix4f ortho(float x, float y, float width, float height, float zNear, float zFar) { return ortho(x, x+width, y+height, y, zNear, zFar, false); } public Matrix4f ortho(float left, float right, float bottom, float top, float zNear, float zFar, boolean zZeroToOne) { float rm00 = 2F / (right - left); float rm11 = 2F / (top - bottom); float rm22 = (zZeroToOne ? 1F : 2F) / (zFar - zNear); float rm30 = (left + right) / (left - right); float rm31 = (top + bottom) / (bottom - top); float rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); data[12] = data[0] * rm30 + data[4] * rm31 + data[8] * rm32 + data[12]; data[13] = data[1] * rm30 + data[5] * rm31 + data[9] * rm32 + data[13]; data[14] = data[2] * rm30 + data[6] * rm31 + data[10] * rm32 + data[14]; data[15] = data[3] * rm30 + data[7] * rm31 + data[11] * rm32 + data[15]; data[0] = data[0] * rm00; data[1] = data[1] * rm00; data[2] = data[2] * rm00; data[3] = data[3] * rm00; data[4] = data[4] * rm11; data[5] = data[5] * rm11; data[6] = data[6] * rm11; data[7] = data[7] * rm11; data[8] = data[8] * rm22; data[9] = data[9] * rm22; data[10] = data[10] * rm22; data[11] = data[11] * rm22; return this; } public Vec4f storeFrustrumPlane(int plane, Vec4f toStore) { switch(plane) { case 0: return toStore.set(data[3] + data[0], data[7] + data[4], data[11] + data[8], data[15] + data[12]).normalize3D(); case 1: return toStore.set(data[3] - data[0], data[7] - data[4], data[11] - data[8], data[15] - data[12]).normalize3D(); case 2: return toStore.set(data[3] + data[1], data[7] + data[5], data[11] + data[9], data[15] + data[13]).normalize3D(); case 3: return toStore.set(data[3] - data[1], data[7] - data[5], data[11] - data[9], data[15] - data[13]).normalize3D(); case 4: return toStore.set(data[3] + data[2], data[7] + data[6], data[11] + data[10], data[15] + data[14]).normalize3D(); case 5: return toStore.set(data[3] - data[2], data[7] - data[6], data[11] - data[10], data[15] - data[14]).normalize3D(); } return toStore; } }