public Matrix4x4 multiply(double value) { if (flagBits == Mathematics.mat_type_Identity) { // dummy matrix Matrix4x4 new_mat = new Matrix4x4(0); new_mat.set_value(0, value); new_mat.set_value(5, value); new_mat.set_value(10, value); new_mat.set_value(15, value); return new_mat; } return new Matrix4x4( this.mat4[0] * value, this.mat4[1] * value, this.mat4[2] * value, this.mat4[3] * value, this.mat4[4] * value, this.mat4[5] * value, this.mat4[6] * value, this.mat4[7] * value, this.mat4[8] * value, this.mat4[9] * value, this.mat4[10] * value, this.mat4[11] * value, this.mat4[12] * value, this.mat4[13] * value, this.mat4[14] * value, this.mat4[15] * value); }
public Matrix4x4 divide(double value) { if (flagBits == Mathematics.mat_type_Identity) { // dummy matrix Matrix4x4 new_mat = new Matrix4x4(0); new_mat.set_value(0, 1.0 / value); new_mat.set_value(5, 1.0 / value); new_mat.set_value(10, 1.0 / value); new_mat.set_value(15, 1.0 / value); return new_mat; } return new Matrix4x4( this.mat4[0] / value, this.mat4[1] / value, this.mat4[2] / value, this.mat4[3] / value, this.mat4[4] / value, this.mat4[5] / value, this.mat4[6] / value, this.mat4[7] / value, this.mat4[8] / value, this.mat4[9] / value, this.mat4[10] / value, this.mat4[11] / value, this.mat4[12] / value, this.mat4[13] / value, this.mat4[14] / value, this.mat4[15] / value); }
public Matrix4x4 transposed() { Matrix4x4 result = new Matrix4x4(1); // The "1" says to not load the identity. for (int row = 0; row < 4; ++row) { for (int col = 0; col < 4; ++col) { result.set_value(col + row * 4, mat4[4 * row + col]); } } return result; }
// cpp would have a boolean as input(pointer so output) to check if inversion was successful... // returns identity matrix if not invertible... public Matrix4x4 inverted() { // Handle some of the easy cases first. if (flagBits == Mathematics.mat_type_Identity) { return new Matrix4x4(); } else if (flagBits == Mathematics.mat_type_Translation) { Matrix4x4 inv = new Matrix4x4(); inv.mat4[12] = -mat4[12]; inv.mat4[13] = -mat4[13]; inv.mat4[14] = -mat4[14]; inv.flagBits = Mathematics.mat_type_Translation; return inv; } else if (flagBits == Mathematics.mat_type_Rotation || flagBits == (Mathematics.mat_type_Rotation | Mathematics.mat_type_Translation)) { return orthonormalInverse(); } double det = matrixDet4(mat4); if (det == 0.0f) { return new Matrix4x4(); } det = 1.0f / det; return new Matrix4x4( matrixDet3(mat4, 1, 2, 3, 1, 2, 3) * det, -matrixDet3(mat4, 0, 2, 3, 1, 2, 3) * det, matrixDet3(mat4, 0, 1, 3, 1, 2, 3) * det, -matrixDet3(mat4, 0, 1, 2, 1, 2, 3) * det, -matrixDet3(mat4, 1, 2, 3, 0, 2, 3) * det, matrixDet3(mat4, 0, 2, 3, 0, 2, 3) * det, -matrixDet3(mat4, 0, 1, 3, 0, 2, 3) * det, matrixDet3(mat4, 0, 1, 2, 0, 2, 3) * det, matrixDet3(mat4, 1, 2, 3, 0, 1, 3) * det, -matrixDet3(mat4, 0, 2, 3, 0, 1, 3) * det, matrixDet3(mat4, 0, 1, 3, 0, 1, 3) * det, -matrixDet3(mat4, 0, 1, 2, 0, 1, 3) * det, -matrixDet3(mat4, 1, 2, 3, 0, 1, 2) * det, matrixDet3(mat4, 0, 2, 3, 0, 1, 2) * det, -matrixDet3(mat4, 0, 1, 3, 0, 1, 2) * det, matrixDet3(mat4, 0, 1, 2, 0, 1, 2) * det); }
public Matrix4x4 subtract(Matrix4x4 other) { return new Matrix4x4( this.mat4[0] - other.get_value(0), this.mat4[1] - other.get_value(1), this.mat4[2] - other.get_value(2), this.mat4[3] - other.get_value(3), this.mat4[4] - other.get_value(4), this.mat4[5] - other.get_value(5), this.mat4[6] - other.get_value(6), this.mat4[7] - other.get_value(7), this.mat4[8] - other.get_value(8), this.mat4[9] - other.get_value(9), this.mat4[10] - other.get_value(10), this.mat4[11] - other.get_value(11), this.mat4[12] - other.get_value(12), this.mat4[13] - other.get_value(13), this.mat4[14] - other.get_value(14), this.mat4[15] - other.get_value(15)); }
public Matrix4x4 add(Matrix4x4 other) { return new Matrix4x4( this.mat4[0] + other.get_value(0), this.mat4[1] + other.get_value(1), this.mat4[2] + other.get_value(2), this.mat4[3] + other.get_value(3), this.mat4[4] + other.get_value(4), this.mat4[5] + other.get_value(5), this.mat4[6] + other.get_value(6), this.mat4[7] + other.get_value(7), this.mat4[8] + other.get_value(8), this.mat4[9] + other.get_value(9), this.mat4[10] + other.get_value(10), this.mat4[11] + other.get_value(11), this.mat4[12] + other.get_value(12), this.mat4[13] + other.get_value(13), this.mat4[14] + other.get_value(14), this.mat4[15] + other.get_value(15)); }
// copy constructor public Matrix4x4(Matrix4x4 mat) { this.mat4[0] = mat.get_value(0); this.mat4[1] = mat.get_value(1); this.mat4[2] = mat.get_value(2); this.mat4[3] = mat.get_value(3); this.mat4[4] = mat.get_value(4); this.mat4[5] = mat.get_value(5); this.mat4[6] = mat.get_value(6); this.mat4[7] = mat.get_value(7); this.mat4[8] = mat.get_value(8); this.mat4[9] = mat.get_value(9); this.mat4[10] = mat.get_value(10); this.mat4[11] = mat.get_value(11); this.mat4[12] = mat.get_value(12); this.mat4[13] = mat.get_value(13); this.mat4[14] = mat.get_value(14); this.mat4[15] = mat.get_value(15); flagBits = Mathematics.mat_type_General; }
public Matrix4x4 multiply(Matrix4x4 other) { if (this.flagBits == Mathematics.mat_type_Identity) return new Matrix4x4(other); else if (other.getType() == Mathematics.mat_type_Identity) return new Matrix4x4(this); return new Matrix4x4( // Fisrt Column mat4[0] * other.get_value(0) + mat4[4] * other.get_value(1) + mat4[8] * other.get_value(2) + mat4[12] * other.get_value(3), mat4[1] * other.get_value(0) + mat4[5] * other.get_value(1) + mat4[9] * other.get_value(2) + mat4[13] * other.get_value(3), mat4[2] * other.get_value(0) + mat4[6] * other.get_value(1) + mat4[10] * other.get_value(2) + mat4[14] * other.get_value(3), mat4[3] * other.get_value(0) + mat4[7] * other.get_value(1) + mat4[11] * other.get_value(2) + mat4[15] * other.get_value(3), // Second Column mat4[0] * other.get_value(4) + mat4[4] * other.get_value(5) + mat4[8] * other.get_value(6) + mat4[12] * other.get_value(7), mat4[1] * other.get_value(4) + mat4[5] * other.get_value(5) + mat4[9] * other.get_value(6) + mat4[13] * other.get_value(7), mat4[2] * other.get_value(4) + mat4[6] * other.get_value(5) + mat4[10] * other.get_value(6) + mat4[14] * other.get_value(7), mat4[3] * other.get_value(4) + mat4[7] * other.get_value(5) + mat4[11] * other.get_value(6) + mat4[15] * other.get_value(7), // Third Column mat4[0] * other.get_value(8) + mat4[4] * other.get_value(9) + mat4[8] * other.get_value(10) + mat4[12] * other.get_value(11), mat4[1] * other.get_value(8) + mat4[5] * other.get_value(9) + mat4[9] * other.get_value(10) + mat4[13] * other.get_value(11), mat4[2] * other.get_value(8) + mat4[6] * other.get_value(9) + mat4[10] * other.get_value(10) + mat4[14] * other.get_value(11), mat4[3] * other.get_value(8) + mat4[7] * other.get_value(9) + mat4[11] * other.get_value(10) + mat4[15] * other.get_value(11), // Fourth Column mat4[0] * other.get_value(12) + mat4[4] * other.get_value(13) + mat4[8] * other.get_value(14) + mat4[12] * other.get_value(15), mat4[1] * other.get_value(12) + mat4[5] * other.get_value(13) + mat4[9] * other.get_value(14) + mat4[13] * other.get_value(15), mat4[2] * other.get_value(12) + mat4[6] * other.get_value(13) + mat4[10] * other.get_value(14) + mat4[14] * other.get_value(15), mat4[3] * other.get_value(12) + mat4[7] * other.get_value(13) + mat4[11] * other.get_value(14) + mat4[15] * other.get_value(15) // is General matrix... ); }
public Matrix4x4 lookAt(Vector3 eye, Vector3 center, Vector3 up) { Vector3 forward = (center.subtract(eye)).normalized(); Vector3 side = Vector3.crossProduct(forward, up).normalized(); Vector3 upVector = Vector3.crossProduct(side, forward); Matrix4x4 m = new Matrix4x4(1); m.set_value(0, 0, side.x()); m.set_value(1, 0, side.y()); m.set_value(2, 0, side.z()); m.set_value(3, 0, 0.0f); m.set_value(0, 1, upVector.x()); m.set_value(1, 1, upVector.y()); m.set_value(2, 1, upVector.z()); m.set_value(3, 1, 0.0f); m.set_value(0, 2, -forward.x()); m.set_value(1, 2, -forward.y()); m.set_value(2, 2, -forward.z()); m.set_value(3, 2, 0.0f); m.set_value(0, 3, 0.0f); m.set_value(1, 3, 0.0f); m.set_value(2, 3, 0.0f); m.set_value(3, 3, 1.0f); Matrix4x4 m2 = this.multiply(m); m2.translate(-eye.x(), -eye.y(), -eye.z()); return m2; }
public Matrix4x4 perspective(double angle, double aspect, double nearPlane, double farPlane) { // Bail out if the projection volume is zero-sized. if (nearPlane == farPlane || aspect == 0.0) return this; // Construct the projection. Matrix4x4 m = new Matrix4x4(1); double radians = (angle / 2.0) * Mathematics.M_PI / 180.0; double sine = Math.sin(radians); if (sine == 0.0) return this; double cotan = Math.cos(radians) / sine; double clip = farPlane - nearPlane; m.set_value(0, 0, cotan / aspect); m.set_value(1, 0, 0.0); m.set_value(2, 0, 0.0); m.set_value(3, 0, 0.0); m.set_value(0, 1, 0.0); m.set_value(1, 1, cotan); m.set_value(2, 1, 0.0); m.set_value(3, 1, 0.0); m.set_value(0, 2, 0.0); m.set_value(1, 2, 0.0); m.set_value(2, 2, -(nearPlane + farPlane) / clip); m.set_value(3, 2, -(2.0 * nearPlane * farPlane) / clip); m.set_value(0, 3, 0.0); m.set_value(1, 3, 0.0); m.set_value(2, 3, -1.0); m.set_value(3, 3, 0.0); // Apply the projection. return this.multiply(m); }
public Matrix4x4 frustum( double left, double right, double bottom, double top, double nearPlane, double farPlane) { // Bail out if the projection volume is zero-sized. if (left == right || bottom == top || nearPlane == farPlane) return this; // Construct the projection. Matrix4x4 m = new Matrix4x4(1); double width = right - left; double invheight = top - bottom; double clip = farPlane - nearPlane; m.set_value(0, 0, 2.0 * nearPlane / width); m.set_value(1, 0, 0.0); m.set_value(2, 0, (left + right) / width); m.set_value(3, 0, 0.0); m.set_value(0, 1, 0.0); m.set_value(1, 1, 2.0 * nearPlane / invheight); m.set_value(2, 1, (top + bottom) / invheight); m.set_value(3, 1, 0.0); m.set_value(0, 2, 0.0); m.set_value(1, 2, 0.0); m.set_value(2, 2, -(nearPlane + farPlane) / clip); m.set_value(3, 2, -2.0 * nearPlane * farPlane / clip); m.set_value(0, 3, 0.0); m.set_value(1, 3, 0.0); m.set_value(2, 3, -1.0); m.set_value(3, 3, 0.0); // Apply the projection. return this.multiply(m); }
public Matrix4x4 ortho( double left, double right, double bottom, double top, double nearPlane, double farPlane) { // Bail out if the projection volume is zero-sized. if (left == right || bottom == top || nearPlane == farPlane) return this; // Construct the projection. double width = right - left; double invheight = top - bottom; double clip = farPlane - nearPlane; // Vector class is incomplete and thus functions are missing... // A more efficient way of ortho projection... /* if (clip == 2.0f && (nearPlane + farPlane) == 0.0f) { // We can express this projection as a translate and scale // which will be more efficient to modify with further // transformations than producing a "General" matrix. translate(Vector3 (-(left + right) / width, -(top + bottom) / invheight, 0.0f)); scale(Vector3 (2.0f / width, 2.0f / invheight, -1.0f)); return; } */ Matrix4x4 m = new Matrix4x4(1); m.set_value(0, 0, 2.0 / width); m.set_value(1, 0, 0.0); m.set_value(2, 0, 0.0); m.set_value(3, 0, -(left + right) / width); m.set_value(0, 1, 0.0); m.set_value(1, 1, 2.0 / invheight); m.set_value(2, 1, 0.0); m.set_value(3, 1, -(top + bottom) / invheight); m.set_value(0, 2, 0.0); m.set_value(1, 2, 0.0); m.set_value(2, 2, -2.0 / clip); m.set_value(3, 2, -(nearPlane + farPlane) / clip); m.set_value(0, 3, 0.0); m.set_value(1, 3, 0.0); m.set_value(2, 3, 0.0); m.set_value(3, 3, 1.0); // Apply the projection. return this.multiply(m); }
private Matrix4x4 orthonormalInverse() { Matrix4x4 result = new Matrix4x4(1); // The '1' says not to load identity result.set_value(0, mat4[0]); result.set_value(4, mat4[1]); result.set_value(8, mat4[2]); result.set_value(1, mat4[4]); result.set_value(5, mat4[5]); result.set_value(9, mat4[6]); result.set_value(2, mat4[8]); result.set_value(6, mat4[9]); result.set_value(10, mat4[10]); result.set_value(3, 0.0); result.set_value(7, 0.0); result.set_value(11, 0.0); // might have wrong values result.set_value( 12, -(result.get_value(0) * mat4[12] + result.get_value(4) * mat4[13] + result.get_value(8) * mat4[14])); result.set_value( 13, -(result.get_value(1) * mat4[12] + result.get_value(5) * mat4[13] + result.get_value(9) * mat4[14])); result.set_value( 14, -(result.get_value(2) * mat4[12] + result.get_value(6) * mat4[13] + result.get_value(10) * mat4[14])); result.set_value(15, 1.0); return result; }
public void rotate(double angle, double x, double y, double z) { if (angle == 0.0f) return; Matrix4x4 m = new Matrix4x4(1); // The "1" says to not load the identity. double c, s, ic; if (angle == 90.0 || angle == -270.0) { s = 1.0; c = 0.0; } else if (angle == -90.0 || angle == 270.0) { s = -1.0; c = 0.0; } else if (angle == 180.0 || angle == -180.0) { s = 0.0; c = -1.0; } else { double a = angle * Mathematics.M_PI / 180.0; c = Math.cos(a); s = Math.sin(a); } boolean quick = false; if (x == 0.0) { if (y == 0.0) { if (z != 0.0) { // Rotate around the Z axis. m.set_to_identity(); m.mat4[0] = c; m.mat4[5] = c; if (z < 0.0) { m.mat4[4] = s; m.mat4[1] = -s; } else { m.mat4[4] = -s; m.mat4[1] = s; } m.setType(Mathematics.mat_type_General); quick = true; } } else if (z == 0.0) { // Rotate around the Y axis. m.set_to_identity(); m.mat4[0] = c; m.mat4[10] = c; if (y < 0.0) { m.mat4[8] = -s; m.mat4[2] = s; } else { m.mat4[8] = s; m.mat4[2] = -s; } m.setType(Mathematics.mat_type_General); quick = true; } } else if (y == 0.0 && z == 0.0) { // Rotate around the X axis. m.set_to_identity(); m.mat4[5] = c; m.mat4[10] = c; if (x < 0.0) { m.mat4[9] = s; m.mat4[6] = -s; } else { m.mat4[9] = -s; m.mat4[6] = s; } m.setType(Mathematics.mat_type_General); quick = true; } if (!quick) { double len = x * x + y * y + z * z; if (!Mathematics.fuzzyIsNull(len - 1.0) && Mathematics.fuzzyIsNull(len)) { len = Math.sqrt(len); x /= len; y /= len; z /= len; } ic = 1.0 - c; m.mat4[0] = x * x * ic + c; m.mat4[4] = x * y * ic - z * s; m.mat4[8] = x * z * ic + y * s; m.mat4[12] = 0.0; m.mat4[1] = y * x * ic + z * s; m.mat4[5] = y * y * ic + c; m.mat4[9] = y * z * ic - x * s; m.mat4[13] = 0.0; m.mat4[2] = x * z * ic - y * s; m.mat4[6] = y * z * ic + x * s; m.mat4[10] = z * z * ic + c; m.mat4[14] = 0.0; m.mat4[3] = 0.0; m.mat4[7] = 0.0; m.mat4[11] = 0.0; m.mat4[15] = 1.0; } int flags = flagBits; // cpp style // *this *= m; // java... this.set_array(this.multiply(m).get_array()); if (flags != Mathematics.mat_type_Identity) flagBits = flags | Mathematics.mat_type_Rotation; else flagBits = Mathematics.mat_type_Rotation; }