From ea862edd8c644f270a85067d823338c673e8f533 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Mon, 18 Jan 2021 21:19:59 +0100 Subject: [PATCH] [DEV] add some tools --- CleanUp.xml | 110 ++- Formatter.xml | 416 +++++---- src/org/atriasoft/etk/internal/Log.java | 2 +- src/org/atriasoft/etk/math/Constant.java | 14 + src/org/atriasoft/etk/math/FMath.java | 131 +++ src/org/atriasoft/etk/math/Matrix3f.java | 124 ++- src/org/atriasoft/etk/math/Matrix4f.java | 800 +++++++++-------- src/org/atriasoft/etk/math/Quaternion.java | 125 ++- src/org/atriasoft/etk/math/Transform3D.java | 115 ++- src/org/atriasoft/etk/math/Vector2f.java | 682 ++++++++------ src/org/atriasoft/etk/math/Vector3f.java | 943 ++++++++++++-------- 11 files changed, 2135 insertions(+), 1327 deletions(-) create mode 100644 src/org/atriasoft/etk/math/Constant.java create mode 100644 src/org/atriasoft/etk/math/FMath.java diff --git a/CleanUp.xml b/CleanUp.xml index 9df98d2..6cf4cba 100644 --- a/CleanUp.xml +++ b/CleanUp.xml @@ -1,66 +1,106 @@ - - + - - - - + - - + + + + + - - + + - + + - - - + + - - - - - - - - - + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + - - - + + + - + diff --git a/Formatter.xml b/Formatter.xml index 79dcbb8..14a5d6c 100644 --- a/Formatter.xml +++ b/Formatter.xml @@ -1,77 +1,237 @@ - - - + + - - - - - + + - - - - - + - - - - - - - - - - - + - - + - - + - - - - - - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -81,284 +241,148 @@ - + - - - - - - - - - - - - - - - - - - + - - - - - + - - - - - - - - - + - - + - - - - - - - - - - + + - - - - - - - - - - - - - - - - + + + - - - - - - + - - + - - - - - - - - - + - - - - - - - - - + + - - - - - - - - - - + - - - - + + - - - + - - - + - - - - - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - diff --git a/src/org/atriasoft/etk/internal/Log.java b/src/org/atriasoft/etk/internal/Log.java index 123a89a..65d29ef 100644 --- a/src/org/atriasoft/etk/internal/Log.java +++ b/src/org/atriasoft/etk/internal/Log.java @@ -3,7 +3,7 @@ package org.atriasoft.etk.internal; import io.scenarium.logger.LogLevel; import io.scenarium.logger.Logger; -public class Log { +class Log { private static final String LIB_NAME = "etk"; private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); diff --git a/src/org/atriasoft/etk/math/Constant.java b/src/org/atriasoft/etk/math/Constant.java new file mode 100644 index 0000000..839ca8c --- /dev/null +++ b/src/org/atriasoft/etk/math/Constant.java @@ -0,0 +1,14 @@ +package org.atriasoft.etk.math; + +public class Constant { + + private Constant() { + } + + // Machine epsilon + public static final float MACHINE_EPSILON = 0.000001f; + // Pi constant + public static final float PI = 3.14159265f; + // 2*Pi constant + public static final float PI_2 = 6.28318530f; +} diff --git a/src/org/atriasoft/etk/math/FMath.java b/src/org/atriasoft/etk/math/FMath.java new file mode 100644 index 0000000..325ff01 --- /dev/null +++ b/src/org/atriasoft/etk/math/FMath.java @@ -0,0 +1,131 @@ +package org.atriasoft.etk.math; + +public class FMath { + public static float abs(final float a) { + if (a < 0.0f) { + return -a; + } + return a; + } + + /** + * Test if the value id in the correct range + * @param a fist value + * @param b second value (a-b) + * @return true if it is in the range + */ + public static boolean approxEqual(final float a, final float b) { + return approxEqual(a, b, Constant.MACHINE_EPSILON); + } + + /** + * Test if the value id in the correct range + * @param a fist value + * @param b second value (a-b) + * @param epsilon delta to check + * @return true if it is in the range + */ + public static boolean approxEqual(final float a, final float b, final float epsilon) { + final float difference = a - b; + return (abs(difference) < epsilon); + } + + public static float atan2(final float sinHalfAngleAbs, final float cosHalfAngle) { + return (float) Math.atan2(sinHalfAngleAbs, cosHalfAngle); + } + + public static float avg(final float min, final float value, final float max) { + return Math.max(min, Math.min(value, max)); + } + + /// Function that returns the result of the "value" clamped by + /// two others values "lowerLimit" and "upperLimit" + public static float clamp(final float value, final float lowerLimit, final float upperLimit) { + assert (lowerLimit <= upperLimit); + return FMath.min(FMath.max(value, lowerLimit), upperLimit); + } + + public static int clamp(final int value, final int lowerLimit, final int upperLimit) { + assert (lowerLimit <= upperLimit); + return FMath.min(FMath.max(value, lowerLimit), upperLimit); + } + + /// Function that returns the result of the "value" clamped by + /// two others values "lowerLimit" and "upperLimit" + public static long clamp(final long value, final long lowerLimit, final long upperLimit) { + assert (lowerLimit <= upperLimit); + return FMath.min(FMath.max(value, lowerLimit), upperLimit); + } + + // TODO check this basic function ... + public static int floor(final float f) { + return (int) Math.floor(f); + } + + public static float max(final float a, final float b) { + return Math.max(a, b); + } + + public static float max(final float a, final float b, final float c) { + return Math.max(Math.max(a, b), c); + } + + public static float max(final float a, final float b, final float c, final float d) { + return Math.max(Math.max(Math.max(a, b), c), d); + } + + public static int max(final int a, final int b) { + return Math.max(a, b); + } + + public static long max(final long a, final long b) { + return Math.max(a, b); + } + + public static Vector3f max(final Vector3f a, final Vector3f b) { + return new Vector3f(Math.max(a.x, b.x), Math.max(a.y, b.y), Math.max(a.z, b.z)); + } + + public static float min(final float a, final float b) { + return Math.min(a, b); + } + + public static float min(final float a, final float b, final float c) { + return Math.min(Math.min(a, b), c); + } + + public static float min(final float a, final float b, final float c, final float d) { + return Math.min(Math.min(Math.min(a, b), c), d); + } + + public static int min(final int a, final int b) { + return Math.min(a, b); + } + + public static long min(final long a, final long b) { + return Math.min(a, b); + } + + public static Vector3f min(final Vector3f a, final Vector3f b) { + return new Vector3f(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z)); + } + + public static float mod(final float value, final float modulo) { + // TODO Auto-generated method stub + return value % modulo; + } + + public static float pow(final float value, final float exponent) { + // TODO Auto-generated method stub + return (float) Math.pow(value, exponent); + } + + /// Return true if two values have the same sign + public static boolean sameSign(final float a, final float b) { + return a * b >= 0.0f; + } + + public static float sqrt(final float value) { + return (float) Math.sqrt(value); + } +} diff --git a/src/org/atriasoft/etk/math/Matrix3f.java b/src/org/atriasoft/etk/math/Matrix3f.java index 4491614..dcbd560 100644 --- a/src/org/atriasoft/etk/math/Matrix3f.java +++ b/src/org/atriasoft/etk/math/Matrix3f.java @@ -79,17 +79,18 @@ public class Matrix3f { * @param c2 element 2x1 * @param c3 element 2x2 */ - public void set(float a1, float a2, float a3, + public Matrix3f set(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) { this.mat[0] = a1; this.mat[1] = a2; this.mat[2] = a3; this.mat[3] = b1; this.mat[4] = b2; this.mat[5] = b3; this.mat[6] = c1; this.mat[7] = c2; this.mat[8] = c3; + return this; } /** * @brief Load Zero matrix */ - public void setZero() { + public Matrix3f setZero() { this.mat[0] = 0.0f; this.mat[1] = 0.0f; this.mat[2] = 0.0f; @@ -99,6 +100,7 @@ public class Matrix3f { this.mat[6] = 0.0f; this.mat[7] = 0.0f; this.mat[8] = 0.0f; + return this; } /** @@ -106,7 +108,7 @@ public class Matrix3f { * @param iii Id of the colomn * @return Vector 3D vith the values */ - Vector3f getColumn(int iii) { + public Vector3f getColumn(int iii) { if (iii == 0) { return new Vector3f(this.mat[0], this.mat[3], this.mat[6]); } else if (iii == 1) { @@ -134,16 +136,16 @@ public class Matrix3f { * @brief get a transpose matrix of this one. * @return the transpose matrix */ - public Matrix3f getTranspose() { + public Matrix3f transposeNew() { return new Matrix3f(this.mat[0], this.mat[3], this.mat[6], - this.mat[1], this.mat[4], this.mat[7], - this.mat[2], this.mat[5], this.mat[8]); + this.mat[1], this.mat[4], this.mat[7], + this.mat[2], this.mat[5], this.mat[8]); } /** * @brief Transpose the current matrix. */ - public void transpose() { + public Matrix3f transpose() { float tmp = this.mat[1]; this.mat[1] = this.mat[3]; this.mat[3] = tmp; @@ -153,6 +155,7 @@ public class Matrix3f { tmp = this.mat[5]; this.mat[5] = this.mat[7]; this.mat[7] = tmp; + return this; } /** * @brief Computes the determinant of the matrix. @@ -171,7 +174,7 @@ public class Matrix3f { return (this.mat[0] + this.mat[4] + this.mat[8]); } /** - * @brief Inverts the matrix. + * @brief Inverse the matrix. * @note The determinant must be != 0, otherwithe the matrix can't be inverted. * @return The inverted matrix. */ @@ -190,17 +193,30 @@ public class Matrix3f { //assert(Math.abs(det) > MACHINEEPSILON); float invDet = 1.0f / det; this.set( (this.mat[4] * this.mat[8]-this.mat[7] * this.mat[5]), - -(this.mat[1] * this.mat[8]-this.mat[7] * this.mat[2]), - (this.mat[1] * this.mat[5]-this.mat[2] * this.mat[4]), - -(this.mat[3] * this.mat[8]-this.mat[6] * this.mat[5]), - (this.mat[0] * this.mat[8]-this.mat[6] * this.mat[2]), - -(this.mat[0] * this.mat[5]-this.mat[3] * this.mat[2]), - (this.mat[3] * this.mat[7]-this.mat[6] * this.mat[4]), - -(this.mat[0] * this.mat[7]-this.mat[6] * this.mat[1]), - (this.mat[0] * this.mat[4]-this.mat[1] * this.mat[3])); + -(this.mat[1] * this.mat[8]-this.mat[7] * this.mat[2]), + (this.mat[1] * this.mat[5]-this.mat[2] * this.mat[4]), + -(this.mat[3] * this.mat[8]-this.mat[6] * this.mat[5]), + (this.mat[0] * this.mat[8]-this.mat[6] * this.mat[2]), + -(this.mat[0] * this.mat[5]-this.mat[3] * this.mat[2]), + (this.mat[3] * this.mat[7]-this.mat[6] * this.mat[4]), + -(this.mat[0] * this.mat[7]-this.mat[6] * this.mat[1]), + (this.mat[0] * this.mat[4]-this.mat[1] * this.mat[3])); this.multiply(invDet); return this; } + // Overloaded operator for the negative of the matrix + public Matrix3f invert() { + this.mat[0] = -this.mat[0]; + this.mat[1] = -this.mat[1]; + this.mat[2] = -this.mat[2]; + this.mat[3] = -this.mat[3]; + this.mat[4] = -this.mat[4]; + this.mat[5] = -this.mat[5]; + this.mat[6] = -this.mat[6]; + this.mat[7] = -this.mat[7]; + this.mat[8] = -this.mat[8]; + return this; + } /** * @brief get the matrix with the absolute value * @return matix in absolute @@ -213,6 +229,19 @@ public class Matrix3f { /** * @brief absolutise the matrix */ + public Matrix3f abs(){ + this.mat[0] = Math.abs(this.mat[0]); + this.mat[1] = Math.abs(this.mat[1]); + this.mat[2] = Math.abs(this.mat[2]); + this.mat[3] = Math.abs(this.mat[3]); + this.mat[4] = Math.abs(this.mat[4]); + this.mat[5] = Math.abs(this.mat[5]); + this.mat[6] = Math.abs(this.mat[6]); + this.mat[7] = Math.abs(this.mat[7]); + this.mat[8] = Math.abs(this.mat[8]); + return this; + } + @Deprecated public void absolute(){ this.mat[0] = Math.abs(this.mat[0]); this.mat[1] = Math.abs(this.mat[1]); @@ -227,10 +256,11 @@ public class Matrix3f { /** * @brief Load Identity matrix */ - public void setIdentity(){ + public Matrix3f setIdentity(){ this.mat[0] = 1.0f; this.mat[1] = 0.0f; this.mat[2] = 0.0f; this.mat[3] = 0.0f; this.mat[4] = 1.0f; this.mat[5] = 0.0f; this.mat[6] = 0.0f; this.mat[7] = 0.0f; this.mat[8] = 1.0f; + return this; } /** * @brief create a Identity matrix @@ -360,6 +390,22 @@ public class Matrix3f { this.mat[7] = c2; return this; } + /** + * @brief Operator*= Multiplication an other matrix with this one + * @param obj Reference on the external object + * @return Local reference of the vector multiplicated + */ + public void multiplyTo(Matrix3f obj, Matrix3f out) { + out.mat[2] = this.mat[0]*obj.mat[2] + this.mat[1]*obj.mat[5] + this.mat[2]*obj.mat[8]; + out.mat[5] = this.mat[3]*obj.mat[2] + this.mat[4]*obj.mat[5] + this.mat[5]*obj.mat[8]; + out.mat[8] = this.mat[6]*obj.mat[2] + this.mat[7]*obj.mat[5] + this.mat[8]*obj.mat[8]; + out.mat[0] = this.mat[0]*obj.mat[0] + this.mat[1]*obj.mat[3] + this.mat[2]*obj.mat[6]; + out.mat[3] = this.mat[3]*obj.mat[0] + this.mat[4]*obj.mat[3] + this.mat[5]*obj.mat[6]; + out.mat[6] = this.mat[6]*obj.mat[0] + this.mat[7]*obj.mat[3] + this.mat[8]*obj.mat[6]; + out.mat[1] = this.mat[0]*obj.mat[1] + this.mat[1]*obj.mat[4] + this.mat[2]*obj.mat[7]; + out.mat[4] = this.mat[3]*obj.mat[1] + this.mat[4]*obj.mat[4] + this.mat[5]*obj.mat[7]; + out.mat[7] = this.mat[6]*obj.mat[1] + this.mat[7]*obj.mat[4] + this.mat[8]*obj.mat[7]; + } /** * @brief Operator* Multiplication an other matrix with this one * @param obj Reference on the external object @@ -402,11 +448,16 @@ public class Matrix3f { * @param point Point value to apply the matrix * @return New vector containing the value */ - public Vector3f multiply(Vector3f point) { + public Vector3f multiplyNew(Vector3f point) { return new Vector3f(point.x * this.mat[0] + point.y * this.mat[1] + point.z * this.mat[2], point.x * this.mat[3] + point.y * this.mat[4] + point.z * this.mat[5], point.x * this.mat[6] + point.y * this.mat[7] + point.z * this.mat[8]); } + public void multiplyTo(Vector3f point, Vector3f out) { + out.set(point.x * this.mat[0] + point.y * this.mat[1] + point.z * this.mat[2], + point.x * this.mat[3] + point.y * this.mat[4] + point.z * this.mat[5], + point.x * this.mat[6] + point.y * this.mat[7] + point.z * this.mat[8]); + } /** * @brief Create a matrix 3D with a simple rotation * @param normal vector aroud witch apply the rotation @@ -432,4 +483,41 @@ public class Matrix3f { tmp.mat[8] = normal.z * normal.z * invVal + cosVal; return tmp; } + @Override + public int hashCode() { + int hash = 1542; + hash += Float.floatToIntBits(this.mat[0]); + hash += Float.floatToIntBits(this.mat[1]); + hash += Float.floatToIntBits(this.mat[2]); + hash += Float.floatToIntBits(this.mat[3]); + hash += Float.floatToIntBits(this.mat[4]); + hash += Float.floatToIntBits(this.mat[5]); + hash += Float.floatToIntBits(this.mat[6]); + hash += Float.floatToIntBits(this.mat[7]); + hash += Float.floatToIntBits(this.mat[8]); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Matrix3f other = (Matrix3f) obj; + for(int iii=0; iii<3*3 ; ++iii) { + if (Float.floatToIntBits(this.mat[iii]) != Float.floatToIntBits(other.mat[iii])) { + return false; + } + } + return true; + } + + // Return a skew-symmetric matrix using a given vector that can be used + // to compute cross product with another vector using matrix multiplication + public Matrix3f computeSkewSymmetricMatrixForCrossProductNew(Vector3f vector) { + return new Matrix3f(0.0f, -vector.z, vector.y, vector.z, 0, -vector.x, -vector.y, vector.x, 0.0f); + } } diff --git a/src/org/atriasoft/etk/math/Matrix4f.java b/src/org/atriasoft/etk/math/Matrix4f.java index 88f4866..9974e7f 100644 --- a/src/org/atriasoft/etk/math/Matrix4f.java +++ b/src/org/atriasoft/etk/math/Matrix4f.java @@ -1,30 +1,190 @@ package org.atriasoft.etk.math; public class Matrix4f { - public float[] mat = new float[4*4]; //!< matrix data /** - * @brief configure identity of the matrix - */ - public void setIdentity() { - for(int iii=0; iii<4*4 ; iii++) { - this.mat[iii] = 0; + * @brief Create projection matrix with the box parameter (camera view in -z axis) + * @param xmin X minimum size of the frustum + * @param xmax X maximum size of the frustum + * @param ymin Y minimum size of the frustum + * @param ymax Y maximum size of the frustum + * @param zNear Z minimum size of the frustum + * @param zFar Z maximum size of the frustum + * @return New matrix of the transformation requested + */ + public static Matrix4f createMatrixFrustum(final float xmin, final float xmax, final float ymin, final float ymax, final float zNear, final float zFar) { + final Matrix4f tmp = new Matrix4f(); + for (int iii = 0; iii < 4 * 4; iii++) { + tmp.mat[iii] = 0; } - this.mat[0] = 1.0f; - this.mat[5] = 1.0f; - this.mat[10] = 1.0f; - this.mat[15] = 1.0f; + // 0 1 2 3 + // 4 5 6 7 + // 8 9 10 11 + // 12 13 14 15 + tmp.mat[0] = (2.0f * zNear) / (xmax - xmin); + tmp.mat[5] = (2.0f * zNear) / (ymax - ymin); + tmp.mat[10] = -(zFar + zNear) / (zFar - zNear); + tmp.mat[2] = (xmax + xmin) / (xmax - xmin); + tmp.mat[6] = (ymax + ymin) / (ymax - ymin); + tmp.mat[14] = -1.0f; + tmp.mat[11] = -(2.0f * zFar * zNear) / (zFar - zNear); + return tmp; } - public static Matrix4f identity() { - Matrix4f tmp = new Matrix4f(); + + /** + * @brief Create projection matrix with camera property (camera view in -z axis) + * @param eye Optical center of the camera + * @param target Point of where the camera is showing + * @param up Up vector of the camera + * @return New matrix of the transformation requested + */ + public static Matrix4f createMatrixLookAt(final Vector3f eye, final Vector3f target, final Vector3f up) { + final Matrix4f tmp = new Matrix4f(); + + final Vector3f forward = eye; + forward.less(target); + forward.safeNormalize(); + final Vector3f xaxis = target.cross(up.normalizeNew()); + xaxis.safeNormalize(); + final Vector3f up2 = xaxis.cross(forward); + xaxis.safeNormalize(); + + tmp.mat[0] = xaxis.x; + tmp.mat[1] = up2.x; + tmp.mat[2] = forward.x; + tmp.mat[3] = eye.x; + + tmp.mat[4] = xaxis.y; + tmp.mat[5] = up2.y; + tmp.mat[6] = forward.y; + tmp.mat[7] = eye.y; + + tmp.mat[8] = xaxis.z; + tmp.mat[9] = up2.z; + tmp.mat[10] = forward.z; + tmp.mat[11] = eye.z; + + tmp.mat[12] = 0.0f; + tmp.mat[13] = 0.0f; + tmp.mat[14] = 0.0f; + tmp.mat[15] = 1.0f; + return tmp; + } + + /** + * @brief Create orthogonal projection matrix with the box parameter (camera view in -z axis) + * @param left left size of the camera + * @param right Right size of the camera + * @param bottom Buttom size of the camera + * @param top Top Size of the camera + * @param nearVal Z near size of the camera + * @param farVal Z far size of the camera + * @return New matrix of the transformation requested + */ + public static Matrix4f createMatrixOrtho(final float left, final float right, final float bottom, final float top, final float nearVal, final float farVal) { + final Matrix4f tmp = new Matrix4f(); + for (int iii = 0; iii < 4 * 4; iii++) { + tmp.mat[iii] = 0; + } + tmp.mat[0] = 2.0f / (right - left); + tmp.mat[5] = 2.0f / (top - bottom); + tmp.mat[10] = -2.0f / (farVal - nearVal); + tmp.mat[3] = -1 * (right + left) / (right - left); + tmp.mat[7] = -1 * (top + bottom) / (top - bottom); + tmp.mat[11] = -1 * (farVal + nearVal) / (farVal - nearVal); + tmp.mat[15] = 1; + return tmp; + } + + /** + * @brief Create projection matrix with human repensentation view (camera view in -z axis) + * @param foxy Focal in radian of the camera + * @param aspect aspect ratio of the camera + * @param zNear Z near size of the camera + * @param zFar Z far size of the camera + * @return New matrix of the transformation requested + */ + public static Matrix4f createMatrixPerspective(final float foxy, final float aspect, final float zNear, final float zFar) { + //TKDEBUG("drax perspective: foxy=" << foxy << "->" << aspect << " " << zNear << "->" << zFar); + final float xmax = zNear * (float) Math.tan(foxy / 2.0); + final float xmin = -xmax; + + final float ymin = xmin / aspect; + final float ymax = xmax / aspect; + //TKDEBUG("drax perspective: " << xmin << "->" << xmax << " & " << ymin << "->" << ymax << " " << zNear << "->" << zFar); + return createMatrixFrustum(xmin, xmax, ymin, ymax, zNear, zFar); + } + + /** + * @brief Create a matrix 3D with a simple rotation + * @param normal vector aroud witch apply the rotation + * @param angleRad Radian angle to set at the matrix + * @return New matrix of the transformation requested + */ + public static Matrix4f createMatrixRotate(final Vector3f normal, final float angleRad) { + final Matrix4f tmp = new Matrix4f(); + final float cosVal = (float) Math.cos(angleRad); + final float sinVal = (float) Math.sin(angleRad); + final float invVal = 1.0f - cosVal; + // set rotation : + tmp.mat[0] = normal.x * normal.x * invVal + cosVal; + tmp.mat[1] = normal.x * normal.y * invVal - normal.z * sinVal; + tmp.mat[2] = normal.x * normal.z * invVal + normal.y * sinVal; + + tmp.mat[4] = normal.y * normal.x * invVal + normal.z * sinVal; + tmp.mat[5] = normal.y * normal.y * invVal + cosVal; + tmp.mat[6] = normal.y * normal.z * invVal - normal.x * sinVal; + + tmp.mat[8] = normal.z * normal.x * invVal - normal.y * sinVal; + tmp.mat[9] = normal.z * normal.y * invVal + normal.x * sinVal; + tmp.mat[10] = normal.z * normal.z * invVal + cosVal; + return tmp; + } + + //! @notindoc + public static Matrix4f createMatrixRotate2(final Vector3f vect) { + return createMatrixLookAt(vect, new Vector3f(0, 0, 0), new Vector3f(0, 1, 0)); + } + + /** + * @brief Create a matrix 3D with a simple scale + * @param scale 3 dimention scale + * @return New matrix of the transformation requested + */ + public static Matrix4f createMatrixScale(final Vector3f scale) { + final Matrix4f tmp = new Matrix4f(); + tmp.scale(scale); + return tmp; + } + + /** + * @brief Create a matrix 3D with a simple translation + * @param translate 3 dimention translation + * @return New matrix of the transformation requested + */ + public static Matrix4f createMatrixTranslate(final Vector3f translate) { + final Matrix4f tmp = new Matrix4f(); + // set translation : + tmp.mat[3] = translate.x; + tmp.mat[7] = translate.y; + tmp.mat[11] = translate.z; + return tmp; + } + + public static Matrix4f identity() { + final Matrix4f tmp = new Matrix4f(); tmp.setIdentity(); return tmp; } + + public float[] mat = new float[4 * 4]; //!< matrix data + /** * @brief Constructor that load identity */ public Matrix4f() { setIdentity(); } + /** * @brief Configuration constructor. * @param a1 1st colomn, 1 line value @@ -44,10 +204,8 @@ public class Matrix4f { * @param c4 3rd colomn, 4 line value * @param d4 4th colomn, 4 line value */ - public Matrix4f(float a1, float b1, float c1, float d1, - float a2, float b2, float c2, float d2, - float a3, float b3, float c3, float d3, - float a4, float b4, float c4, float d4) { + public Matrix4f(final float a1, final float b1, final float c1, final float d1, final float a2, final float b2, final float c2, final float d2, final float a3, final float b3, final float c3, + final float d3, final float a4, final float b4, final float c4, final float d4) { this.mat[0] = a1; this.mat[1] = b1; this.mat[2] = c1; @@ -65,20 +223,22 @@ public class Matrix4f { this.mat[14] = c4; this.mat[15] = d4; } + /** * @brief Configuration constructor. * @param values vector of values */ - public Matrix4f(float[] values) { + public Matrix4f(final float[] values) { if (values == null) { setIdentity(); return; } - for(int iii=0; iii<16 ; ++iii) { + for (int iii = 0; iii < 16; ++iii) { this.mat[iii] = values[iii]; } } - public Matrix4f(Matrix3f matrix) { + + public Matrix4f(final Matrix3f matrix) { this.mat[0] = matrix.mat[0]; this.mat[1] = matrix.mat[1]; this.mat[2] = matrix.mat[2]; @@ -95,113 +255,286 @@ public class Matrix4f { this.mat[13] = 0; this.mat[14] = 0; this.mat[15] = 1; -// this.mat[0] = matrix.mat[0]; -// this.mat[1] = matrix.mat[3]; -// this.mat[2] = matrix.mat[6]; -// this.mat[3] = 0; -// this.mat[4] = matrix.mat[1]; -// this.mat[5] = matrix.mat[4]; -// this.mat[6] = matrix.mat[7]; -// this.mat[7] = 0; -// this.mat[8] = matrix.mat[2]; -// this.mat[9] = matrix.mat[5]; -// this.mat[10] = matrix.mat[8]; -// this.mat[11] = 0; -// this.mat[12] = 0; -// this.mat[13] = 0; -// this.mat[14] = 0; -// this.mat[15] = 1; + // this.mat[0] = matrix.mat[0]; + // this.mat[1] = matrix.mat[3]; + // this.mat[2] = matrix.mat[6]; + // this.mat[3] = 0; + // this.mat[4] = matrix.mat[1]; + // this.mat[5] = matrix.mat[4]; + // this.mat[6] = matrix.mat[7]; + // this.mat[7] = 0; + // this.mat[8] = matrix.mat[2]; + // this.mat[9] = matrix.mat[5]; + // this.mat[10] = matrix.mat[8]; + // this.mat[11] = 0; + // this.mat[12] = 0; + // this.mat[13] = 0; + // this.mat[14] = 0; + // this.mat[15] = 1; } + + // copy contructor: + public Matrix4f(final Matrix4f matrix) { + for (int iii = 0; iii < 16; ++iii) { + this.mat[iii] = matrix.mat[iii]; + } + } + + /** + * @brief Operator+= Addition an other matrix with this one + * @param obj Reference on the external object + */ + public void add(final Matrix4f obj) { + for (int iii = 0; iii < 4 * 4; ++iii) { + this.mat[iii] += obj.mat[iii]; + } + } + /** * @brief Operator= Asign the current object with an other object * @param obj Reference on the external object */ - public void set(Matrix4f obj) { - for(int iii=0; iii<16 ; iii++) { - this.mat[iii] = obj.mat[iii]; - } + @Override + public Matrix4f clone() { + return new Matrix4f(this); } + /** - * @brief Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are identical - * @return false The Objects are NOT identical + * @brief Computes a cofactor. Used for matrix inversion. + * @param row Id of raw. + * @param col Id of colomn. + * @return the coFactorValue. */ - public boolean isEqual(Matrix4f obj) { - for(int iii=0; iii<4*4 ; ++iii) { - if(this.mat[iii] != obj.mat[iii]) { - return false; - } - } - return true; + public float coFactor(final int row, final int col) { + return ((this.mat[((row + 1) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 3) & 3) * 4 + ((col + 3) & 3)] + + this.mat[((row + 1) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 3) & 3) * 4 + ((col + 1) & 3)] + + this.mat[((row + 1) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 3) & 3) * 4 + ((col + 2) & 3)]) + - (this.mat[((row + 3) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 1) & 3) * 4 + ((col + 3) & 3)] + + this.mat[((row + 3) & 3) * 4 + ((col + 2) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 1) & 3) * 4 + ((col + 1) & 3)] + + this.mat[((row + 3) & 3) * 4 + ((col + 3) & 3)] * this.mat[((row + 2) & 3) * 4 + ((col + 1) & 3)] * this.mat[((row + 1) & 3) * 4 + ((col + 2) & 3)])) + * (((row + col) & 1) == 1 ? -1.0f : +1.0f); } + + /** + * @brief Operator-= Decrement an other matrix with this one + * @param obj Reference on the external object + */ + public void decrement(final Matrix4f obj) { + for (int iii = 0; iii < 4 * 4; ++iii) { + this.mat[iii] -= obj.mat[iii]; + } + } + + /** + * @brief Computes the determinant of the matrix. + * @return The determinent Value. + */ + public float determinant() { + return this.mat[0] * coFactor(0, 0) + this.mat[1] * coFactor(0, 1) + this.mat[2] * coFactor(0, 2) + this.mat[3] * coFactor(0, 3); + } + + public float[] getTable() { + return this.mat; + } + + /** + * @brief Inverts the matrix. + * @note The determinant must be != 0, otherwithe the matrix can't be inverted. + * @return The inverted matrix. + */ + public Matrix4f invertNew() { + final float det = determinant(); + if (Math.abs(det) < (1.0e-7f)) { + // The matrix is not invertible! Singular case! + return clone(); + } + final Matrix4f temp = new Matrix4f(); + final float iDet = 1.0f / det; + temp.mat[0] = coFactor(0, 0) * iDet; + temp.mat[1] = coFactor(0, 1) * iDet; + temp.mat[2] = coFactor(0, 2) * iDet; + temp.mat[3] = coFactor(0, 3) * iDet; + temp.mat[4] = coFactor(1, 0) * iDet; + temp.mat[5] = coFactor(1, 1) * iDet; + temp.mat[6] = coFactor(1, 2) * iDet; + temp.mat[7] = coFactor(1, 3) * iDet; + temp.mat[8] = coFactor(2, 0) * iDet; + temp.mat[9] = coFactor(2, 1) * iDet; + temp.mat[10] = coFactor(2, 2) * iDet; + temp.mat[11] = coFactor(2, 3) * iDet; + temp.mat[12] = coFactor(3, 0) * iDet; + temp.mat[13] = coFactor(3, 1) * iDet; + temp.mat[14] = coFactor(3, 2) * iDet; + temp.mat[15] = coFactor(3, 3) * iDet; + return temp; + } + /** * @brief In-Equality compare operator with an other object. * @param obj Reference on the comparing object * @return true The Objects are NOT identical * @return false The Objects are identical */ - public boolean isDifferent(Matrix4f obj) { - for(int iii=0; iii<4*4 ; ++iii) { - if(this.mat[iii] != obj.mat[iii]) { + public boolean isDifferent(final Matrix4f obj) { + for (int iii = 0; iii < 4 * 4; ++iii) { + if (this.mat[iii] != obj.mat[iii]) { return true; } } return false; } + /** - * @brief Operator+= Addition an other matrix with this one - * @param obj Reference on the external object + * @brief Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical */ - public void add(Matrix4f obj) { - for(int iii=0; iii<4*4 ; ++iii) { - this.mat[iii] += obj.mat[iii]; - } - } - /** - * @brief Operator-= Decrement an other matrix with this one - * @param obj Reference on the external object - */ - public void decrement(Matrix4f obj) { - for(int iii=0; iii<4*4 ; ++iii) { - this.mat[iii] -= obj.mat[iii]; + public boolean isEqual(final Matrix4f obj) { + for (int iii = 0; iii < 4 * 4; ++iii) { + if (this.mat[iii] != obj.mat[iii]) { + return false; + } } + return true; } + /** * @brief Operator*= Multiplication an other matrix with this one * @param obj Reference on the external object */ - public Matrix4f multiply(Matrix4f obj) { + public Matrix4f multiply(final Matrix4f obj) { // output Matrix - float[] matrixOut = new float[16]; - for(int xxx=0; xxx<4 ; xxx++) { - for(int yyy=0; yyy<4 ; yyy++) { + final float[] matrixOut = new float[16]; + for (int xxx = 0; xxx < 4; xxx++) { + for (int yyy = 0; yyy < 4; yyy++) { float value = 0; - for(int kkk=0; kkk<4 ; kkk++) { - value += this.mat[yyy*4+kkk] * obj.mat[kkk*4+xxx]; + for (int kkk = 0; kkk < 4; kkk++) { + value += this.mat[yyy * 4 + kkk] * obj.mat[kkk * 4 + xxx]; } - matrixOut[yyy*4+xxx] = value; + matrixOut[yyy * 4 + xxx] = value; } } // set it at the output - for(int iii=0; iii<4*4 ; iii++) { + for (int iii = 0; iii < 4 * 4; iii++) { this.mat[iii] = matrixOut[iii]; } return this; } - public Matrix4f multiplyNew(Matrix4f obj) { - return this.clone().multiply(obj); - } + /** * @brief Operator* apply matrix on a vector * @param point Point value to apply the matrix * @return New vector containing the value */ - public Vector3f multiply(Vector3f point) { - return new Vector3f( this.mat[0]*point.x + this.mat[1]*point.y + this.mat[2]*point.z + this.mat[3], - this.mat[4]*point.x + this.mat[5]*point.y + this.mat[6]*point.z + this.mat[7], - this.mat[8]*point.x + this.mat[9]*point.y + this.mat[10]*point.z + this.mat[11] ); + public Vector3f multiply(final Vector3f point) { + return new Vector3f(this.mat[0] * point.x + this.mat[1] * point.y + this.mat[2] * point.z + this.mat[3], this.mat[4] * point.x + this.mat[5] * point.y + this.mat[6] * point.z + this.mat[7], + this.mat[8] * point.x + this.mat[9] * point.y + this.mat[10] * point.z + this.mat[11]); } + + public Matrix4f multiplyNew(final Matrix4f obj) { + return clone().multiply(obj); + } + + /** + * @brief Makes a rotation matrix about an arbitrary axis. + * @param vect vector to apply the angle. + * @param angleRad angle to apply. + */ + public Matrix4f rotate(final Vector3f vect, final float angleRad) { + final Matrix4f tmpMat = createMatrixRotate(vect, angleRad); + return this.multiply(tmpMat); + } + + public Matrix4f rotateNew(final Vector3f vect, final float angleRad) { + final Matrix4f tmpMat = createMatrixRotate(vect, angleRad); + return multiplyNew(tmpMat); + } + + /** + * @brief Scale the current Matrix in all direction with 1 value. + * @param scale Scale XYZ value to apply. + */ + public Matrix4f scale(final float scale) { + return scale(scale, scale, scale); + } + + /** + * @brief Scale the current Matrix. + * @param sx Scale X value to apply. + * @param sy Scale Y value to apply. + * @param sz Scale Z value to apply. + */ + public Matrix4f scale(final float sx, final float sy, final float sz) { + this.mat[0] *= sx; + this.mat[1] *= sy; + this.mat[2] *= sz; + this.mat[4] *= sx; + this.mat[5] *= sy; + this.mat[6] *= sz; + this.mat[8] *= sx; + this.mat[9] *= sy; + this.mat[10] *= sz; + return this; + } + + /** + * @brief Scale the current Matrix. + * @param vect Scale vector to apply. + */ + public Matrix4f scale(final Vector3f vect) { + return scale(vect.x, vect.y, vect.z); + } + + public Matrix4f scaleNew(final float scale) { + return clone().scale(scale, scale, scale); + } + + public Matrix4f scaleNew(final float sx, final float sy, final float sz) { + return clone().scale(sx, sy, sz); + } + + public Matrix4f scaleNew(final Vector3f vect) { + return clone().scale(vect.x, vect.y, vect.z); + } + + /** + * @brief Operator= Asign the current object with an other object + * @param obj Reference on the external object + */ + public void set(final Matrix4f obj) { + for (int iii = 0; iii < 16; iii++) { + this.mat[iii] = obj.mat[iii]; + } + } + + /** + * @brief configure identity of the matrix + */ + public void setIdentity() { + for (int iii = 0; iii < 4 * 4; iii++) { + this.mat[iii] = 0; + } + this.mat[0] = 1.0f; + this.mat[5] = 1.0f; + this.mat[10] = 1.0f; + this.mat[15] = 1.0f; + } + + /** + * @brief Makes a translation of the matrix + * @param vect Translation to apply. + */ + public Matrix4f translate(final Vector3f vect) { + final Matrix4f tmpMat = createMatrixTranslate(vect); + return this.multiply(tmpMat); + } + + public Matrix4f translateNew(final Vector3f vect) { + final Matrix4f tmpMat = createMatrixTranslate(vect); + return multiplyNew(tmpMat); + } + /** * @brief Transpose the current matix (usefull for OpenGL display) */ @@ -231,308 +564,9 @@ public class Matrix4f { this.mat[14] = tmpVal; return this; } + public Matrix4f transposeNew() { - return this.clone().transpose(); - } - /** - * @brief Scale the current Matrix. - * @param vect Scale vector to apply. - */ - public Matrix4f scale(Vector3f vect) { - return scale(vect.x, vect.y, vect.z); - } - public Matrix4f scaleNew(Vector3f vect) { - return this.clone().scale(vect.x, vect.y, vect.z); - } - /** - * @brief Scale the current Matrix. - * @param sx Scale X value to apply. - * @param sy Scale Y value to apply. - * @param sz Scale Z value to apply. - */ - public Matrix4f scale(float sx, float sy, float sz) { - this.mat[0] *= sx; this.mat[1] *= sy; this.mat[2] *= sz; - this.mat[4] *= sx; this.mat[5] *= sy; this.mat[6] *= sz; - this.mat[8] *= sx; this.mat[9] *= sy; this.mat[10] *= sz; - return this; - } - public Matrix4f scaleNew(float sx, float sy, float sz) { - return this.clone().scale(sx, sy, sz); - } - /** - * @brief Scale the current Matrix in all direction with 1 value. - * @param scale Scale XYZ value to apply. - */ - public Matrix4f scale(float scale) { - return scale(scale, scale, scale); - } - public Matrix4f scaleNew(float scale) { - return this.clone().scale(scale, scale, scale); - } - /** - * @brief Makes a rotation matrix about an arbitrary axis. - * @param vect vector to apply the angle. - * @param angleRad angle to apply. - */ - public Matrix4f rotate(Vector3f vect, float angleRad) { - Matrix4f tmpMat = createMatrixRotate(vect, angleRad); - return this.multiply(tmpMat); - } - public Matrix4f rotateNew(Vector3f vect, float angleRad) { - Matrix4f tmpMat = createMatrixRotate(vect, angleRad); - return this.multiplyNew(tmpMat); - } - /** - * @brief Makes a translation of the matrix - * @param vect Translation to apply. - */ - public Matrix4f translate(Vector3f vect) { - Matrix4f tmpMat = createMatrixTranslate(vect); - return this.multiply(tmpMat); - } - public Matrix4f translateNew(Vector3f vect) { - Matrix4f tmpMat = createMatrixTranslate(vect); - return this.multiplyNew(tmpMat); - } - /** - * @brief Computes a cofactor. Used for matrix inversion. - * @param row Id of raw. - * @param col Id of colomn. - * @return the coFactorValue. - */ - public float coFactor(int row, int col) { - return ( ( this.mat[((row+1)&3)*4 + ((col+1)&3)] * this.mat[((row+2)&3)*4 + ((col+2)&3)] * this.mat[((row+3)&3)*4 + ((col+3)&3)] - + this.mat[((row+1)&3)*4 + ((col+2)&3)] * this.mat[((row+2)&3)*4 + ((col+3)&3)] * this.mat[((row+3)&3)*4 + ((col+1)&3)] - + this.mat[((row+1)&3)*4 + ((col+3)&3)] * this.mat[((row+2)&3)*4 + ((col+1)&3)] * this.mat[((row+3)&3)*4 + ((col+2)&3)] ) - - ( this.mat[((row+3)&3)*4 + ((col+1)&3)] * this.mat[((row+2)&3)*4 + ((col+2)&3)] * this.mat[((row+1)&3)*4 + ((col+3)&3)] - + this.mat[((row+3)&3)*4 + ((col+2)&3)] * this.mat[((row+2)&3)*4 + ((col+3)&3)] * this.mat[((row+1)&3)*4 + ((col+1)&3)] - + this.mat[((row+3)&3)*4 + ((col+3)&3)] * this.mat[((row+2)&3)*4 + ((col+1)&3)] * this.mat[((row+1)&3)*4 + ((col+2)&3)] ) - ) * (((row + col) & 1)== 1? -1.0f : +1.0f); -} - /** - * @brief Computes the determinant of the matrix. - * @return The determinent Value. - */ - public float determinant() { - return this.mat[0] * coFactor(0, 0) + - this.mat[1] * coFactor(0, 1) + - this.mat[2] * coFactor(0, 2) + - this.mat[3] * coFactor(0, 3); - } - - /** - * @brief Inverts the matrix. - * @note The determinant must be != 0, otherwithe the matrix can't be inverted. - * @return The inverted matrix. - */ - public Matrix4f invertNew() { - float det = determinant(); - if(Math.abs(det) < (1.0e-7f)) { - // The matrix is not invertible! Singular case! - return clone(); - } - Matrix4f temp = new Matrix4f(); - float iDet = 1.0f / det; - temp.mat[0] = coFactor(0,0) * iDet; - temp.mat[1] = coFactor(0,1) * iDet; - temp.mat[2] = coFactor(0,2) * iDet; - temp.mat[3] = coFactor(0,3) * iDet; - temp.mat[4] = coFactor(1,0) * iDet; - temp.mat[5] = coFactor(1,1) * iDet; - temp.mat[6] = coFactor(1,2) * iDet; - temp.mat[7] = coFactor(1,3) * iDet; - temp.mat[8] = coFactor(2,0) * iDet; - temp.mat[9] = coFactor(2,1) * iDet; - temp.mat[10] = coFactor(2,2) * iDet; - temp.mat[11] = coFactor(2,3) * iDet; - temp.mat[12] = coFactor(3,0) * iDet; - temp.mat[13] = coFactor(3,1) * iDet; - temp.mat[14] = coFactor(3,2) * iDet; - temp.mat[15] = coFactor(3,3) * iDet; - return temp; - } - - /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object - */ - public Matrix4f clone() { - Matrix4f out = new Matrix4f(); - for(int iii=0; iii<16 ; iii++) { - out.mat[iii] = this.mat[iii]; - } - return out; - } - - /** - * @brief Create projection matrix with the box parameter (camera view in -z axis) - * @param xmin X minimum size of the frustum - * @param xmax X maximum size of the frustum - * @param ymin Y minimum size of the frustum - * @param ymax Y maximum size of the frustum - * @param zNear Z minimum size of the frustum - * @param zFar Z maximum size of the frustum - * @return New matrix of the transformation requested - */ - public static Matrix4f createMatrixFrustum(float xmin, float xmax, float ymin, float ymax, float zNear, float zFar) { - Matrix4f tmp = new Matrix4f(); - for(int iii=0; iii<4*4 ; iii++) { - tmp.mat[iii] = 0; - } - // 0 1 2 3 - // 4 5 6 7 - // 8 9 10 11 - // 12 13 14 15 - tmp.mat[0] = (2.0f * zNear) / (xmax - xmin); - tmp.mat[5] = (2.0f * zNear) / (ymax - ymin); - tmp.mat[10] = -(zFar + zNear) / (zFar - zNear); - tmp.mat[2] = (xmax + xmin) / (xmax - xmin); - tmp.mat[6] = (ymax + ymin) / (ymax - ymin); - tmp.mat[14] = -1.0f; - tmp.mat[11] = -(2.0f * zFar * zNear) / (zFar - zNear); - return tmp; - } - - /** - * @brief Create projection matrix with human repensentation view (camera view in -z axis) - * @param foxy Focal in radian of the camera - * @param aspect aspect ratio of the camera - * @param zNear Z near size of the camera - * @param zFar Z far size of the camera - * @return New matrix of the transformation requested - */ - public static Matrix4f createMatrixPerspective(float foxy, float aspect, float zNear, float zFar) { - //TKDEBUG("drax perspective: foxy=" << foxy << "->" << aspect << " " << zNear << "->" << zFar); - float xmax = zNear * (float)Math.tan(foxy/2.0); - float xmin = -xmax; - - float ymin = xmin / aspect; - float ymax = xmax / aspect; - //TKDEBUG("drax perspective: " << xmin << "->" << xmax << " & " << ymin << "->" << ymax << " " << zNear << "->" << zFar); - return createMatrixFrustum(xmin, xmax, ymin, ymax, zNear, zFar); - } - /** - * @brief Create orthogonal projection matrix with the box parameter (camera view in -z axis) - * @param left left size of the camera - * @param right Right size of the camera - * @param bottom Buttom size of the camera - * @param top Top Size of the camera - * @param nearVal Z near size of the camera - * @param farVal Z far size of the camera - * @return New matrix of the transformation requested - */ - public static Matrix4f createMatrixOrtho(float left, float right, float bottom, float top, float nearVal, float farVal) { - Matrix4f tmp = new Matrix4f(); - for(int iii=0; iii<4*4 ; iii++) { - tmp.mat[iii] = 0; - } - tmp.mat[0] = 2.0f / (right - left); - tmp.mat[5] = 2.0f / (top - bottom); - tmp.mat[10] = -2.0f / (farVal - nearVal); - tmp.mat[3] = -1*(right + left) / (right - left); - tmp.mat[7] = -1*(top + bottom) / (top - bottom); - tmp.mat[11] = -1*(farVal + nearVal) / (farVal - nearVal); - tmp.mat[15] = 1; - return tmp; - } - /** - * @brief Create a matrix 3D with a simple translation - * @param translate 3 dimention translation - * @return New matrix of the transformation requested - */ - public static Matrix4f createMatrixTranslate(Vector3f translate) { - Matrix4f tmp = new Matrix4f(); - // set translation : - tmp.mat[3] = translate.x; - tmp.mat[7] = translate.y; - tmp.mat[11] = translate.z; - return tmp; - } - /** - * @brief Create a matrix 3D with a simple scale - * @param scale 3 dimention scale - * @return New matrix of the transformation requested - */ - public static Matrix4f createMatrixScale(Vector3f scale){ - Matrix4f tmp = new Matrix4f(); - tmp.scale(scale); - return tmp; - } - - /** - * @brief Create a matrix 3D with a simple rotation - * @param normal vector aroud witch apply the rotation - * @param angleRad Radian angle to set at the matrix - * @return New matrix of the transformation requested - */ - public static Matrix4f createMatrixRotate(Vector3f normal, float angleRad) { - Matrix4f tmp = new Matrix4f(); - float cosVal = (float)Math.cos(angleRad); - float sinVal = (float)Math.sin(angleRad); - float invVal = 1.0f-cosVal; - // set rotation : - tmp.mat[0] = normal.x * normal.x * invVal + cosVal; - tmp.mat[1] = normal.x * normal.y * invVal - normal.z * sinVal; - tmp.mat[2] = normal.x * normal.z * invVal + normal.y * sinVal; - - tmp.mat[4] = normal.y * normal.x * invVal + normal.z * sinVal; - tmp.mat[5] = normal.y * normal.y * invVal + cosVal; - tmp.mat[6] = normal.y * normal.z * invVal - normal.x * sinVal; - - tmp.mat[8] = normal.z * normal.x * invVal - normal.y * sinVal; - tmp.mat[9] = normal.z * normal.y * invVal + normal.x * sinVal; - tmp.mat[10] = normal.z * normal.z * invVal + cosVal; - return tmp; - } - //! @notindoc - public static Matrix4f createMatrixRotate2(Vector3f vect) { - return createMatrixLookAt(vect, new Vector3f(0,0,0), new Vector3f(0,1,0)); - } - - /** - * @brief Create projection matrix with camera property (camera view in -z axis) - * @param eye Optical center of the camera - * @param target Point of where the camera is showing - * @param up Up vector of the camera - * @return New matrix of the transformation requested - */ - public static Matrix4f createMatrixLookAt(Vector3f eye, - Vector3f target, - Vector3f up) { - Matrix4f tmp = new Matrix4f(); - - Vector3f forward = eye; - forward.less(target); - forward.safeNormalize(); - Vector3f xaxis = target.cross(up.normalizeNew()); - xaxis.safeNormalize(); - Vector3f up2 = xaxis.cross(forward); - xaxis.safeNormalize(); - - tmp.mat[0] = xaxis.x; - tmp.mat[1] = up2.x; - tmp.mat[2] = forward.x; - tmp.mat[3] = eye.x; - - tmp.mat[4] = xaxis.y; - tmp.mat[5] = up2.y; - tmp.mat[6] = forward.y; - tmp.mat[7] = eye.y; - - tmp.mat[8] = xaxis.z; - tmp.mat[9] = up2.z; - tmp.mat[10] = forward.z; - tmp.mat[11] = eye.z; - - tmp.mat[12] = 0.0f; - tmp.mat[13] = 0.0f; - tmp.mat[14] = 0.0f; - tmp.mat[15] = 1.0f; - return tmp; - } - - public float[] getTable() { - return this.mat; + return clone().transpose(); } } diff --git a/src/org/atriasoft/etk/math/Quaternion.java b/src/org/atriasoft/etk/math/Quaternion.java index 76a8328..8c42c29 100644 --- a/src/org/atriasoft/etk/math/Quaternion.java +++ b/src/org/atriasoft/etk/math/Quaternion.java @@ -307,6 +307,40 @@ public class Quaternion { this.w = w; return this; } + /** + * @brief Constructor from scalars. + * @param xxx X value + * @param yyy Y value + * @param zzz Z value + * @param www W value */ + public Quaternion set(float xxx, float yyy, float zzz, float www) { + this.x = xxx; + this.y = yyy; + this.z = zzz; + this.w = www; + return this; + } + + public Quaternion set(Quaternion obj) { + x = obj.x; + y = obj.y; + z = obj.z; + w = obj.w; + return this; + } + + /** + * @brief Constructor with the component w and a vector 3D. + * @param www W value + * @param vec 3D vector value + */ + public Quaternion set(float www, Vector3f obj) { + x = obj.x; + y = obj.y; + z = obj.z; + this.w = www; + return this; + } /** @brief Equality compare operator with an other object. * @param obj Reference on the comparing object @@ -434,12 +468,13 @@ public class Quaternion { } /** @brief Inverse the quaternion */ - public void inverse() { + public Quaternion inverse() { float invLengthSquare = 1.0f / length2(); this.x *= -invLengthSquare; this.y *= -invLengthSquare; this.z *= -invLengthSquare; this.w *= invLengthSquare; + return this; } /** @brief Return the inverse of the quaternion @@ -457,10 +492,11 @@ public class Quaternion { } /** @brief Conjugate the quaternion */ - public void conjugate() { + public Quaternion conjugate() { this.x *= -1.0f; this.y *= -1.0f; this.z *= -1.0f; + return this; } /** @brief Return the conjugate of the quaternion @@ -504,6 +540,26 @@ public class Quaternion { float zzs = this.z * zs; return new Matrix3f(1.0f - yys - zzs, xys - wzs, xzs + wys, xys + wzs, 1.0f - xxs - zzs, yzs - wxs, xzs - wys, yzs + wxs, 1.0f - xxs - yys); } + public void getMatrixTo(Matrix3f out) { + float nQ = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; + float sss = 0.0f; + if (nQ > 0.0f) { + sss = 2.0f / nQ; + } + float xs = this.x * sss; + float ys = this.y * sss; + float zs = this.z * sss; + float wxs = this.w * xs; + float wys = this.w * ys; + float wzs = this.w * zs; + float xxs = this.x * xs; + float xys = this.x * ys; + float xzs = this.x * zs; + float yys = this.y * ys; + float yzs = this.y * zs; + float zzs = this.z * zs; + out.set(1.0f - yys - zzs, xys - wzs, xzs + wys, xys + wzs, 1.0f - xxs - zzs, yzs - wxs, xzs - wys, yzs + wxs, 1.0f - xxs - yys); + } public Matrix4f getMatrix4() { @@ -531,22 +587,22 @@ public class Quaternion { * @param obj1 First quaternion * @param obj2 Second quaternion * @param ttt linar coefficient interpolation to be such that [0..1] */ - public static Quaternion slerp(Quaternion obj1, Quaternion obj2, float ttt) { + public Quaternion slerp(Quaternion obj2, float ttt) { // TKASSERT(ttt >= 0.0f ttt <= 1.0f, "wrong intermolation"); float invert = 1.0f; - float cosineTheta = obj1.dot(obj2); + float cosineTheta = this.dot(obj2); if (cosineTheta < 0.0f) { cosineTheta = -cosineTheta; invert = -1.0f; } if (1 - cosineTheta < 0.00001f) { - return obj1.multiplyNew(1.0f - ttt).add(obj2.multiplyNew(ttt * invert)); + return this.multiplyNew(1.0f - ttt).add(obj2.multiplyNew(ttt * invert)); } float theta = (float) Math.acos(cosineTheta); float sineTheta = (float) Math.sin(theta); float coeff1 = (float) Math.sin((1.0f - ttt) * theta) / sineTheta; float coeff2 = (float) Math.sin(ttt * theta) / sineTheta * invert; - return obj1.multiplyNew(coeff1).add(obj2.multiplyNew(coeff2)); + return this.multiplyNew(coeff1).add(obj2.multiplyNew(coeff2)); } /** @brief Configure the quaternion with euler angles. @@ -572,6 +628,33 @@ public class Quaternion { normalize(); } + + // Compute the rotation angle (in radians) and the rotation axis + // This method is used to get the rotation angle (in radian) and the unit + // rotation axis of an orientation quaternion. + /* + public Vector3f getRotationAngleAxis(Vector3f axis, float[] angle) { + Quaternion quaternion; + // If the quaternion is unit + if (length() == 1.0) { + quaternion = this; + } else { + // We compute the unit quaternion + quaternion = new Quaternion(this).normalize(); + } + // Compute the roation angle + angle[0] = Mathematics.ArcCos(quaternion.w) * 2.0f; + // Compute the 3D rotation axis + Vector3f rotationAxis = new Vector3f(quaternion.x, quaternion.y, quaternion.z); + // Normalize the rotation axis + rotationAxis.normalize(); + // Set the rotation axis values + return axis.set(rotationAxis); + } + */ + + + /** @brief Clone the current Quaternion. * @return New Quaternion containing the value */ @Override @@ -590,4 +673,34 @@ public class Quaternion { Quaternion inv = a.inverseNew(); return inv.multiply(b); } + @Override + public int hashCode() { + int hash = 7564; + hash += Float.floatToIntBits(this.x); + hash += Float.floatToIntBits(this.y); + hash += Float.floatToIntBits(this.z); + hash += Float.floatToIntBits(this.w); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Quaternion other = (Quaternion) obj; + if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) { + return false; + } + if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) { + return false; + } + if (Float.floatToIntBits(this.z) != Float.floatToIntBits(other.z)) { + return false; + } + return Float.floatToIntBits(this.w) == Float.floatToIntBits(other.w); + } } diff --git a/src/org/atriasoft/etk/math/Transform3D.java b/src/org/atriasoft/etk/math/Transform3D.java index 1983bce..98964bc 100644 --- a/src/org/atriasoft/etk/math/Transform3D.java +++ b/src/org/atriasoft/etk/math/Transform3D.java @@ -2,18 +2,6 @@ package org.atriasoft.etk.math; public class Transform3D { protected Vector3f position; //! Position - public Vector3f getPosition() { - return position; - } - public void setPosition(Vector3f position) { - this.position = position; - } - public Quaternion getOrientation() { - return orientation; - } - public void setOrientation(Quaternion orientation) { - this.orientation = orientation; - } protected Quaternion orientation; //!< Orientation public Transform3D() { this.position = Vector3f.zero(); @@ -35,6 +23,19 @@ public class Transform3D { this.position = transform3d.position.clone(); this.orientation = transform3d.orientation.clone(); } + + public Vector3f getPosition() { + return position; + } + public void setPosition(Vector3f position) { + this.position = position; + } + public Quaternion getOrientation() { + return orientation; + } + public void setOrientation(Quaternion orientation) { + this.orientation = orientation; + } /** * @brief Get the identity of the transformation */ @@ -58,23 +59,6 @@ public class Transform3D { public Matrix4f getOpenGLMatrix() { Matrix4f out = new Matrix4f(); Matrix3f tmpMatrix = this.orientation.getMatrix(); - // version transposer... -// out.mat[0] = tmpMatrix.mat[0]; -// out.mat[1] = tmpMatrix.mat[3]; -// out.mat[2] = tmpMatrix.mat[6]; -// out.mat[3] = 0.0f; -// out.mat[4] = tmpMatrix.mat[1]; -// out.mat[5] = tmpMatrix.mat[4]; -// out.mat[6] = tmpMatrix.mat[7]; -// out.mat[7] = 0.0f; -// out.mat[8] = tmpMatrix.mat[2]; -// out.mat[9] = tmpMatrix.mat[5]; -// out.mat[10] = tmpMatrix.mat[8]; -// out.mat[11] = 0.0f; -// out.mat[12] = this.position.x; -// out.mat[13] = this.position.y; -// out.mat[14] = this.position.z; -// out.mat[15] = 1.0f; out.mat[0] = tmpMatrix.mat[0]; out.mat[1] = tmpMatrix.mat[1]; out.mat[2] = tmpMatrix.mat[2]; @@ -93,29 +77,59 @@ public class Transform3D { out.mat[15] = 1.0f; return out; } + /// Get the OpenGL matrix of the transform + public Matrix4f getOpenGLMatrixTransposed() { + Matrix4f out = new Matrix4f(); + Matrix3f tmpMatrix = this.orientation.getMatrix(); + // version transposer... + out.mat[0] = tmpMatrix.mat[0]; + out.mat[1] = tmpMatrix.mat[3]; + out.mat[2] = tmpMatrix.mat[6]; + out.mat[3] = 0.0f; + out.mat[4] = tmpMatrix.mat[1]; + out.mat[5] = tmpMatrix.mat[4]; + out.mat[6] = tmpMatrix.mat[7]; + out.mat[7] = 0.0f; + out.mat[8] = tmpMatrix.mat[2]; + out.mat[9] = tmpMatrix.mat[5]; + out.mat[10] = tmpMatrix.mat[8]; + out.mat[11] = 0.0f; + out.mat[12] = this.position.x; + out.mat[13] = this.position.y; + out.mat[14] = this.position.z; + out.mat[15] = 1.0f; + return out; + } /// Return the inverse of the transform public Transform3D inverseNew() { Quaternion invQuaternion = this.orientation.inverseNew(); Matrix3f invMatrix = invQuaternion.getMatrix(); - return new Transform3D(invMatrix.multiply(this.position.multiplyNew(-1)), invQuaternion); + return new Transform3D(invMatrix.multiplyNew(this.position.multiplyNew(-1)), invQuaternion); } /// Return an interpolated transform - public Transform3D interpolateTransforms(Transform3D old, - Transform3D newOne, - float interpolationFactor) { - Vector3f interPosition = old.position.multiplyNew(1.0f - interpolationFactor) - .add(newOne.position.multiplyNew(interpolationFactor)); - Quaternion interOrientation = Quaternion.slerp(old.orientation, - newOne.orientation, interpolationFactor); + public Transform3D interpolateTransforms(Transform3D newOne, float interpolationFactor) { + Vector3f interPosition = this.position.multiplyNew(1.0f - interpolationFactor).add(newOne.position.multiplyNew(interpolationFactor)); + Quaternion interOrientation = this.orientation.slerp(newOne.orientation, interpolationFactor); return new Transform3D(interPosition, interOrientation); } /// Return the transformed vector public Vector3f multiply(Vector3f vector) { - return this.orientation.getMatrix().multiply(vector).add(this.position); + return this.orientation.getMatrix().multiplyNew(vector).add(this.position); + } + /// Return the transformed vector + public Vector3f multiplyNew(Vector3f vector) { + return new Matrix3f(this.orientation.getMatrix()).multiplyNew(vector).add(this.position); } /// Operator of multiplication of a transform with another one + /* + public Transform3D multiply(Transform3D transform2) { + this.position = this.orientation.getMatrix().multiply(transform2.position).add(this.position); + this.orientation.multiply(transform2.orientation); + } + */ + /// Operator of multiplication of a transform with another one public Transform3D multiplyNew(Transform3D transform2) { - return new Transform3D(this.orientation.getMatrix().multiply(transform2.position).add(this.position), + return new Transform3D(this.orientation.getMatrix().multiplyNew(transform2.position).add(this.position), this.orientation.multiplyNew(transform2.orientation)); } /// Return true if the two transforms are equal @@ -146,4 +160,27 @@ public class Transform3D { public void applyRotation(Quaternion rotation) { this.orientation = this.orientation.multiply(rotation); } + + @Override + public int hashCode() { + int hash = 38542; + hash += this.position.hashCode(); + hash += this.orientation.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Transform3D other = (Transform3D) obj; + if (!this.position.equals(position)) { + return false; + } + return this.orientation.equals(other.orientation); + } } diff --git a/src/org/atriasoft/etk/math/Vector2f.java b/src/org/atriasoft/etk/math/Vector2f.java index bd8d3fb..59b2fb3 100644 --- a/src/org/atriasoft/etk/math/Vector2f.java +++ b/src/org/atriasoft/etk/math/Vector2f.java @@ -1,8 +1,13 @@ package org.atriasoft.etk.math; public class Vector2f { + public static Vector2f zero() { + return new Vector2f(0, 0); + } + public float x = 0; public float y = 0; + /* **************************************************** * Constructor *****************************************************/ @@ -10,274 +15,65 @@ public class Vector2f { this.x = 0; this.y = 0; } - public static Vector2f zero() { - return new Vector2f(0,0); - } + /** * @brief Constructor from scalars * @param xxx X value * @param yyy Y value */ - public Vector2f(float xxx, float yyy) { + public Vector2f(final float xxx, final float yyy) { this.x = xxx; this.y = yyy; } + /** * @brief Constructor with external vector * @param obj The vector to add to this one */ - public Vector2f(Vector2f obj) { + public Vector2f(final Vector2f obj) { this.x = obj.x; this.y = obj.y; } - /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object - */ - public void set(Vector2f obj) { - this.x = obj.x; - this.y = obj.y; - } - /** - * @brief Operator= Asign the current object with a value - * @param val Value to assign on the object - */ - public void set(float val) { - this.x = val; - this.y = val; - } - /** - * @brief Operator= Asign the current object with a value - * @param xxx X value - * @param yyy Y value - */ - public void set(float xxx, float yyy) { - this.x = xxx; - this.y = yyy; - } - /** - * @brief Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are identical - * @return false The Objects are NOT identical - */ - public boolean isEqual(Vector2f obj) { - return ( obj.x == this.x - && obj.y == this.y); - } - /** - * @brief In-Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are NOT identical - * @return false The Objects are identical - */ - public boolean isDifferent(Vector2f obj) { - return ( obj.x != this.x - || obj.y != this.y); - } - public boolean isLowerOrEqual(Vector2f obj) { - return ( this.x <= obj.x - && this.y <= obj.y); - } - public boolean isLower(Vector2f obj) { - return ( this.x < obj.x - && this.y < obj.y); - } - public boolean isGreaterOrEqual(Vector2f obj) { - return ( this.x >= obj.x - && this.y >= obj.y); - } - public boolean isGreater(Vector2f obj) { - return ( this.x > obj.x - && this.y > obj.y); - } - /** - * @brief Operator+= Addition an other vertor with this one - * @param obj Reference on the external object - */ - void add(Vector2f obj) { - this.x += obj.x; - this.y += obj.y; - } - /** - * @brief Operator+= Addition an other vertor with this one - * @param val Value to addition at x/y - */ - public void add(float val) { - this.x += val; - this.y += val; - } - /** - * @brief Operator-= Decrement an other vertor with this one - * @param obj Reference on the external object - */ - public void less(Vector2f obj) { - this.x -= obj.x; - this.y -= obj.y; - } - /** - * @brief Operator-= Decrement an other vertor with this one - * @param val Value to addition at x/y - */ - public void less(float val) { - this.x -= val; - this.y -= val; - } - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param obj Reference on the external object - */ - public void multiply(Vector2f obj) { - this.x *= obj.x; - this.y *= obj.y; - } - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param val Value to addition at x/y - */ - public void multiply(float val) { - this.x *= val; - this.y *= val; - } - /** - * @brief Operator/ Dividing an other vertor with this one - * @param obj Reference on the external object - */ - public void devide(Vector2f obj) { - this.x /= obj.x; - this.y /= obj.y; - } - /** - * @brief Operator/ Dividing an other vertor with this one - * @param val Value to addition at x/y - */ - public void devide(float val) { - this.x /= val; - this.y /= val; - } - /** - * @brief Incrementation of this vector (+1 of 2 elements) - */ - public void increment() { - this.x++; - this.y++; - } - /** - * @brief Decrementation of this vector (-1 of 2 elements) - */ - public void decrement() { - this.x--; - this.y--; - } - /** - * @brief Return the cross product / determinant - * @param obj The other vector in the cross product - * @return cross product value - */ - public float cross(Vector2f obj) { - return this.x * obj.y - - this.y * obj.x; - } - /** - * @brief Return the dot product - * @param obj The other vector in the dot product - * @return Dot product value - */ - public float dot(Vector2f obj) { - return this.x * obj.x - + this.y * obj.y; - } - /** - * @brief Get the length of the vector squared - * @return Squared length value. - */ - public float length2() { - return dot(this); - } - /** - * @brief Get the length of the vector - * @return Length value - */ - public float length() { - return (float) Math.sqrt(length2()); - } - /** - * @brief Return the distance squared between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the square distance of the 2 points - */ - public float distance2(Vector2f obj) { - float deltaX = obj.x - this.x; - float deltaY = obj.y - this.y; - return deltaX*deltaX + deltaY*deltaY; - } - /** - * @brief Return the distance between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the distance of the 2 points - */ - public float distance(Vector2f obj) { - return (float)Math.sqrt(this.distance2(obj)); - } - /** - * @brief Normalize this vector x^2 + y^2 = 1 - */ - public void normalize() { - this.devide(length()); - } - /** - * @brief Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0)) - * @return Local reference of the vector normalized - */ - public void safeNormalize() { - float tmp = length(); - if (tmp != 0) { - this.devide(length()); - return; - } - setValue(1,0); - return; - } - /** - * @brief Return a normalized version of this vector - * @return New vector containing the value - */ - public Vector2f normalized() { - Vector2f tmp = this.clone(); - tmp.normalize(); - return tmp; - } + /** * @brief Return a vector will the absolute values of each element * @return New vector containing the value */ + public Vector2f abs() { + this.x = Math.abs(this.x); + this.y = Math.abs(this.y); + return this; + } + public Vector2f absolute() { - return new Vector2f( Math.abs(this.x), - Math.abs(this.y)); + return new Vector2f(Math.abs(this.x), Math.abs(this.y)); } + /** - * @brief Return the axis with the smallest value - * @return values are 0,1 for x or y + * @brief Operator+= Addition an other vertor with this one + * @param val Value to addition at x/y */ - public int minAxis() { - return this.x < this.y ? 0 : 1; + public Vector2f add(final float val) { + this.x += val; + this.y += val; + return this; } + /** - * @brief Return the axis with the largest value - * @return values are 0,1 for x or y + * @brief Operator+= Addition an other vertor with this one + * @param obj Reference on the external object */ - public int maxAxis() { - return this.x < this.y ? 1 : 0; + public Vector2f add(final Vector2f obj) { + this.x += obj.x; + this.y += obj.y; + return this; } - /** - * @brief Return the axis with the smallest ABSOLUTE value - * @return values 0,1 for x, or z - */ - public int furthestAxis() { - return absolute().minAxis(); + + @Override + public Vector2f clone() { + return new Vector2f(this); } + /** * @brief Return the axis with the largest ABSOLUTE value * @return values 0,1 for x or y @@ -285,20 +81,116 @@ public class Vector2f { public int closestAxis() { return absolute().maxAxis(); } + /** - * @brief Set the x value - * @param xxx New value + * @brief Return the cross product / determinant + * @param obj The other vector in the cross product + * @return cross product value */ - public void setX(float xxx) { - this.x = xxx; - }; + public float cross(final Vector2f obj) { + return this.x * obj.y - this.y * obj.x; + } + /** - * @brief Set the y value - * @param yyy New value + * @brief Decrementation of this vector (-1 of 2 elements) */ - public void setY(float yyy) { - this.y = yyy; - }; + public Vector2f decrement() { + this.x--; + this.y--; + return this; + } + + /** + * @brief Operator/ Dividing an other vertor with this one + * @param val Value to addition at x/y + */ + public Vector2f devide(final float val) { + this.x /= val; + this.y /= val; + return this; + } + + /** + * @brief Operator/ Dividing an other vertor with this one + * @param obj Reference on the external object + */ + public Vector2f devide(final Vector2f obj) { + this.x /= obj.x; + this.y /= obj.y; + return this; + } + + /** + * @brief Return the distance between the ends of this and another vector + * This is semantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the distance of the 2 points + */ + public float distance(final Vector2f obj) { + return (float) Math.sqrt(distance2(obj)); + } + + /** + * @brief Return the distance squared between the ends of this and another vector + * This is semantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the square distance of the 2 points + */ + public float distance2(final Vector2f obj) { + final float deltaX = obj.x - this.x; + final float deltaY = obj.y - this.y; + return deltaX * deltaX + deltaY * deltaY; + } + + /** + * @brief Return the dot product + * @param obj The other vector in the dot product + * @return Dot product value + */ + public float dot(final Vector2f obj) { + return this.x * obj.x + this.y * obj.y; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + // check type + if (getClass() != obj.getClass()) { + return false; + } + // cast object + final Vector2f other = (Vector2f) obj; + // checks values + if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) { + return false; + } + return Float.floatToIntBits(this.y) == Float.floatToIntBits(other.y); + } + + /** + * @brief Return the axis with the smallest ABSOLUTE value + * @return values 0,1 for x, or z + */ + public int furthestAxis() { + return absolute().minAxis(); + } + + /** + * @brief get the value with his index + * @param index Index of the value (0: x, 1: y) + * @return The value associated + */ + public float get(final int index) { + if (index == 0) { + return this.x; + } else if (index == 1) { + return this.y; + } + throw new IllegalArgumentException("Unknown index: " + index); + } + /** * @brief Get X value * @return the x value @@ -306,6 +198,7 @@ public class Vector2f { public float getX() { return this.x; } + /** * @brief Get Y value * @return the y value @@ -313,53 +206,290 @@ public class Vector2f { public float getY() { return this.y; } - /** - * @brief Set each element to the max of the current values and the values of another vector - * @param other The other vector to compare with - */ - public void setMax(Vector2f other) { - this.x = Math.max(this.x, other.x); - this.y = Math.max(this.y, other.y); + + @Override + public int hashCode() { + int hash = 38521; + hash += hash + Float.floatToIntBits(this.x); + hash += hash + Float.floatToIntBits(this.y); + return hash; } + /** - * @brief Set each element to the min of the current values and the values of another vector - * @param other The other vector to compare with + * @brief Incrementation of this vector (+1 of 2 elements) */ - public void setMin(Vector2f other) { - this.x = Math.min(this.x, other.x); - this.y = Math.min(this.y, other.y); + public Vector2f increment() { + this.x++; + this.y++; + return this; } + + // Overloaded operator for the negative of a vector + public Vector2f invert() { + this.x = -this.x; + this.y = -this.y; + return this; + } + /** - * @brief Set Value on the vector - * @param xxx X value. - * @param yyy Y value. + * @brief In-Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical */ - public void setValue(float xxx, float yyy) { - this.x = xxx; - this.y = yyy; + public boolean isDifferent(final Vector2f obj) { + return (obj.x != this.x || obj.y != this.y); } + /** - * @brief Set 0 value on all the vector + * @brief Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical */ - public void setZero() { - this.x = 0; - this.y = 0; + public boolean isEqual(final Vector2f obj) { + return (obj.x == this.x && obj.y == this.y); } + + public boolean isGreater(final Vector2f obj) { + return (this.x > obj.x && this.y > obj.y); + } + + public boolean isGreaterOrEqual(final Vector2f obj) { + return (this.x >= obj.x && this.y >= obj.y); + } + + public boolean isLower(final Vector2f obj) { + return (this.x < obj.x && this.y < obj.y); + } + + public boolean isLowerOrEqual(final Vector2f obj) { + return (this.x <= obj.x && this.y <= obj.y); + } + + /** + * @brief Check if the vector is unitary (langth = 10f=) + * @return true if unit , false otherwise + */ + public boolean isUnit() { + return FMath.approxEqual(length2(), 1.0f, Constant.MACHINE_EPSILON); + } + /** * @brief Check if the vector is equal to (0,0) * @return true The value is equal to (0,0) * @return false The value is NOT equal to (0,0) */ public boolean isZero() { - return this.x == 0 - && this.y == 0; + return FMath.approxEqual(length2(), 0.0f, Constant.MACHINE_EPSILON); } - public Vector2f clone() { - return new Vector2f(this); + /** + * @brief Get the length of the vector + * @return Length value + */ + public float length() { + return (float) Math.sqrt(length2()); } + + /** + * @brief Get the length of the vector squared + * @return Squared length value. + */ + public float length2() { + return dot(this); + } + + /** + * @brief Operator-= Decrement an other vertor with this one + * @param val Value to addition at x/y + */ + public Vector2f less(final float val) { + this.x -= val; + this.y -= val; + return this; + } + + /** + * @brief Operator-= Decrement an other vertor with this one + * @param obj Reference on the external object + */ + public Vector2f less(final Vector2f obj) { + this.x -= obj.x; + this.y -= obj.y; + return this; + } + + /** + * @brief Return the axis with the largest value + * @return values are 0,1 for x or y + */ + public int maxAxis() { + return this.x < this.y ? 1 : 0; + } + + /** + * @brief Return the axis with the smallest value + * @return values are 0,1 for x or y + */ + public int minAxis() { + return this.x < this.y ? 0 : 1; + } + + /** + * @brief Operator*= Multiplication an other vertor with this one + * @param val Value to addition at x/y + */ + public Vector2f multiply(final float val) { + this.x *= val; + this.y *= val; + return this; + } + + /** + * @brief Operator*= Multiplication an other vertor with this one + * @param obj Reference on the external object + */ + public Vector2f multiply(final Vector2f obj) { + this.x *= obj.x; + this.y *= obj.y; + return this; + } + + public Vector2f multiplyNew(final float val) { + return new Vector2f(this.x * val, this.y * val); + }; + + /** + * @brief Normalize this vector x^2 + y^2 = 1 + */ + public Vector2f normalize() { + this.devide(length()); + return this; + }; + + /** + * @brief Return a normalized version of this vector + * @return New vector containing the value + */ + public Vector2f normalized() { + final Vector2f tmp = clone(); + tmp.normalize(); + return tmp; + } + + /** + * @brief Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0)) + * @return Local reference of the vector normalized + */ + public Vector2f safeNormalize() { + final float tmp = length(); + if (tmp != 0) { + this.devide(length()); + return this; + } + setValue(1, 0); + return this; + } + + /** + * @brief Operator= Asign the current object with a value + * @param val Value to assign on the object + */ + public Vector2f set(final float val) { + this.x = val; + this.y = val; + return this; + } + + /** + * @brief Operator= Asign the current object with a value + * @param xxx X value + * @param yyy Y value + */ + public Vector2f set(final float xxx, final float yyy) { + this.x = xxx; + this.y = yyy; + return this; + } + + /** + * @brief Operator= Asign the current object with an other object + * @param obj Reference on the external object + */ + public Vector2f set(final Vector2f obj) { + this.x = obj.x; + this.y = obj.y; + return this; + } + + /** + * @brief Set each element to the max of the current values and the values of another vector + * @param other The other vector to compare with + */ + public Vector2f setMax(final Vector2f other) { + this.x = Math.max(this.x, other.x); + this.y = Math.max(this.y, other.y); + return this; + } + + /** + * @brief Set each element to the min of the current values and the values of another vector + * @param other The other vector to compare with + */ + public Vector2f setMin(final Vector2f other) { + this.x = Math.min(this.x, other.x); + this.y = Math.min(this.y, other.y); + return this; + } + + // Return one unit orthogonal vector of the current vector + public Vector2f setUnitOrthogonal() { + this.y = -this.y; + return safeNormalize(); + } + + /** + * @brief Set Value on the vector + * @param xxx X value. + * @param yyy Y value. + */ + public Vector2f setValue(final float xxx, final float yyy) { + this.x = xxx; + this.y = yyy; + return this; + } + + /** + * @brief Set the x value + * @param xxx New value + */ + public Vector2f setX(final float xxx) { + this.x = xxx; + return this; + } + + /** + * @brief Set the y value + * @param yyy New value + */ + public Vector2f setY(final float yyy) { + this.y = yyy; + return this; + } + + /** + * @brief Set 0 value on all the vector + */ + public Vector2f setZero() { + this.x = 0; + this.y = 0; + return this; + } + @Override public String toString() { return "Vector2f(" + this.x + "," + this.y + ")"; } + } diff --git a/src/org/atriasoft/etk/math/Vector3f.java b/src/org/atriasoft/etk/math/Vector3f.java index b15a43c..8c91192 100644 --- a/src/org/atriasoft/etk/math/Vector3f.java +++ b/src/org/atriasoft/etk/math/Vector3f.java @@ -1,9 +1,27 @@ package org.atriasoft.etk.math; public class Vector3f { + /** + * @brief Get the length square between the 2 vectors + * @param start First vector + * @param stop second vector + * @return Length value + */ + public static float length2(final Vector3f start, final Vector3f stop) { + final float x = stop.x - start.x; + final float y = stop.y - start.y; + final float z = stop.z - start.z; + return x * x + y * y + z * z; + } + + public static Vector3f zero() { + return new Vector3f(0, 0, 0); + } + public float x; public float y; public float z; + /** * @brief Default contructor */ @@ -12,120 +30,402 @@ public class Vector3f { this.y = 0; this.z = 0; } + + /** + * @brief Constructor from scalars + * @param value unique value for X,Y and Z value + */ + public Vector3f(final float value) { + this.x = value; + this.y = value; + this.z = value; + } + /** * @brief Constructor from scalars * @param xxx X value * @param yyy Y value * @param zzz Z value */ - public Vector3f(float xxx, float yyy, float zzz) { + public Vector3f(final float xxx, final float yyy, final float zzz) { this.x = xxx; this.y = yyy; this.z = zzz; } - /** - * @brief Constructor from scalars - * @param value unique value for X,Y and Z value - */ - public Vector3f(float value) { - this.x = value; - this.y = value; - this.z = value; - } + /** * @brief Constructor from other vector (copy) * @param obj The vector to add to this one */ - public Vector3f(Vector3f obj) { + public Vector3f(final Vector3f obj) { this.x += obj.x; this.y += obj.y; this.z += obj.z; } + + /** + * @brief Return a vector will the absolute values of each element + * @return the curent reference + */ + public Vector3f abs() { + this.x = Math.abs(this.x); + this.y = Math.abs(this.y); + this.z = Math.abs(this.z); + return this; + } + + @Deprecated + public Vector3f absolute() { + this.x = Math.abs(this.x); + this.y = Math.abs(this.y); + this.z = Math.abs(this.z); + return this; + } + + /** + * @brief Return a vector will the absolute values of each element + * @return New vector containing the value + */ + public Vector3f absoluteNew() { + return new Vector3f(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); + } + + public Vector3f add(final float value) { + this.x += value; + this.y += value; + this.z += value; + return this; + } + /** * @brief Add a vector to this one * @param obj The vector to add to this one */ - public Vector3f add(Vector3f obj) { + public Vector3f add(final Vector3f obj) { this.x += obj.x; this.y += obj.y; this.z += obj.z; return this; } + + public Vector3f addNew(final float value) { + return new Vector3f(this.x + value, this.y + value, this.z + value); + } + /** * @brief Add a vector to this one * @param obj The vector to add to this one */ - public Vector3f addNew(Vector3f obj) { - return new Vector3f(this.x + obj.x, - this.y + obj.y, - this.z + obj.z); + public Vector3f addNew(final Vector3f obj) { + return new Vector3f(this.x + obj.x, this.y + obj.y, this.z + obj.z); } + /** - * @brief Subtract a vector from this one - * @param obj The vector to subtract + * @brief Calculate the angle between this and another vector + * @param obj The other vector + * @return Angle in radian */ - public Vector3f less(Vector3f obj) { - this.x -= obj.x; - this.y -= obj.y; - this.z -= obj.z; - return this; + public float angle(final Vector3f obj) { + final float s = (float) Math.sqrt(length2() * obj.length2()); + if (0 != s) { + return (float) Math.acos(dot(obj) / s); + } + return 0; } + + public Vector3f clampNew(final float maxLength) { + if (length2() > maxLength * maxLength) { + return safeNormalizeNew().multiply(maxLength); + } + return clone(); + } + /** - * @brief Subtract a vector from this one - * @param obj The vector to subtract - * @return A new vector with the data + * @brief Clone the current vector. + * @return New vector containing the value */ - public Vector3f lessNew(Vector3f obj) { - return new Vector3f(this.x - obj.x, this.y - obj.y, this.z - obj.z); + @Override + public Vector3f clone() { + return new Vector3f(this); } + /** - * @brief Scale the vector - * @param val Scale factor + * @brief Return the axis with the largest ABSOLUTE value + * @return values 0,1,2 for x, y, or z */ - public Vector3f multiply(float val) { - this.x *= val; - this.y *= val; - this.z *= val; - return this; + public int closestAxis() { + return absoluteNew().maxAxis(); } + /** - * @brief Scale the vector - * @param val Scale factor - * @return A new vector with the data + * @brief Return the cross product between this and another vector + * @param obj The other vector + * @return Vector with the result of the cross product */ - public Vector3f multiplyNew(float val) { - return new Vector3f(this.x * val, this.y * val, this.z * val); + public Vector3f cross(final Vector3f obj) { + return new Vector3f(this.y * obj.z - this.z * obj.y, this.z * obj.x - this.x * obj.z, this.x * obj.y - this.y * obj.x); } + + /** + * @brief Return the distance between the ends of this and another vector + * This is symantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the distance of the 2 points + */ + public float distance(final Vector3f obj) { + return (float) Math.sqrt(distance2(obj)); + } + + /** + * @brief Return the distance squared between the ends of this and another vector + * This is symantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the square distance of the 2 points + */ + public float distance2(final Vector3f obj) { + final float deltaX = obj.x - this.x; + final float deltaY = obj.y - this.y; + final float deltaZ = obj.z - this.z; + return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ; + } + /** * @brief Inversely scale the vector * @param val Scale factor to divide by */ - public void devide(float val) { + public Vector3f divide(final float val) { if (val != 0.0f) { - float tmpVal = 1.0f / val; + final float tmpVal = 1.0f / val; this.x *= tmpVal; this.y *= tmpVal; this.z *= tmpVal; + return this; } - // TODO maybe throw ... + throw new IllegalArgumentException("divice by 0 (vector3f)"); } + + /** + * @brief Inversely scale the vector + * @param val Scale factor to divide by + */ + public Vector3f divide(final Vector3f val) { + this.x /= val.x; + this.y /= val.y; + this.z /= val.z; + return this; + } + + /** + * @brief Inversely scale the vector + * @param val Scale factor to divide by + */ + public Vector3f divideNew(final float val) { + if (val != 0.0f) { + final float tmpVal = 1.0f / val; + return new Vector3f(this.x * tmpVal, this.y * tmpVal, this.z * tmpVal); + } + throw new IllegalArgumentException("divice by 0 (vector3f)"); + } + + /** + * @brief Inversely scale the vector + * @param val Scale factor to divide by + */ + public Vector3f divideNew(final Vector3f val) { + return new Vector3f(this.x / val.x, this.y / val.y, this.z / val.z); + } + /** * @brief Return the dot product * @param obj The other vector in the dot product * @return Dot product value */ - public float dot(Vector3f obj) { - return this.x * obj.x - + this.y * obj.y - + this.z * obj.z; + public float dot(final Vector3f obj) { + return this.x * obj.x + this.y * obj.y + this.z * obj.z; } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Vector3f other = (Vector3f) obj; + if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) { + return false; + } + if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) { + return false; + } + return Float.floatToIntBits(this.z) == Float.floatToIntBits(other.z); + } + /** - * @brief Get the length of the vector squared - * @return Squared length value. + * @brief Return the axis with the smallest ABSOLUTE value + * @return values 0,1,2 for x, y, or z */ - public float length2() { - return dot(this); + public int furthestAxis() { + return absoluteNew().minAxis(); } + + /** + * @brief get the value with his index + * @param index Index of the value (0: x, 1: y, 2: z) + * @return The value associated + */ + public float get(final int index) { + if (index == 0) { + return this.x; + } else if (index == 1) { + return this.y; + } else if (index == 2) { + return this.z; + } + throw new IllegalArgumentException("Unknown index: " + index); + } + + /** + * @brief Get the maximum value of the vector (x, y, z) + * @return The max value + */ + public float getMax() { + return Math.max(Math.max(this.x, this.y), this.z); + } + + /** + * @brief Get the Axis id with the maximum value + * @return Axis ID 0,1,2 + */ + public int getMaxAxis() { + return (this.x < this.y ? (this.y < this.z ? 2 : 1) : (this.x < this.z ? 2 : 0)); + } + + /** + * @brief Get the minimum value of the vector (x, y, z) + * @return The min value + */ + public float getMin() { + return Math.min(Math.min(this.x, this.y), this.z); + } + + /** + * @brief Get the Axis id with the minimum value + * @return Axis ID 0,1,2 + */ + public int getMinAxis() { + return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); + } + + /** + * @breif Get the orthogonal vector of the current vector + * @return The ortho vector + */ + public Vector3f getOrthoVector() { + final Vector3f vectorAbs = new Vector3f(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); + final int minElement = vectorAbs.getMinAxis(); + if (minElement == 0) { + final float devider = 1.0f / (float) Math.sqrt(this.y * this.y + this.z * this.z); + return new Vector3f(0.0f, -this.z * devider, this.y * devider); + } else if (minElement == 1) { + final float devider = 1.0f / (float) Math.sqrt(this.x * this.x + this.z * this.z); + return new Vector3f(-this.z * devider, 0.0f, this.x * devider); + } + final float devider = 1.0f / (float) Math.sqrt(this.x * this.x + this.y * this.y); + return new Vector3f(-this.y * devider, this.x * devider, 0.0f); + } + + /** + * @brief Create a skew matrix of the object + * @param obj0 Vector matric first line + * @param obj1 Vector matric second line + * @param obj2 Vector matric third line + */ + public void getSkewSymmetricMatrix(final Vector3f obj0, final Vector3f obj1, final Vector3f obj2) { + obj0.setValue(0, -this.z, this.y); + obj1.setValue(this.z, 0, -this.x); + obj2.setValue(-this.y, this.x, 0); + } + + /** + * @brief Get X value + * @return the x value + */ + public float getX() { + return this.x; + } + + /** + * @brief Get Y value + * @return the y value + */ + public float getY() { + return this.y; + } + + /** + * @brief Get Z value + * @return the z value + */ + public float getZ() { + return this.z; + } + + @Override + public int hashCode() { + int hash = 5; + hash += Float.floatToIntBits(this.x); + hash += Float.floatToIntBits(this.y); + hash += Float.floatToIntBits(this.z); + return hash; + } + + // Overloaded operator for the negative of a vector + public Vector3f invert() { + this.x = -this.x; + this.y = -this.y; + this.z = -this.z; + return this; + } + + /** + * @brief In-Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical + */ + public boolean isDifferent(final Vector3f obj) { + return ((this.z != obj.z) || (this.y != obj.y) || (this.x != obj.x)); + } + + /** + * @brief Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical + */ + public boolean isEqual(final Vector3f obj) { + return ((this.z == obj.z) && (this.y == obj.y) && (this.x == obj.x)); + } + + /** + * @brief Check if the vector is unitary (langth = 10f=) + * @return true if unit , false otherwise + */ + public boolean isUnit() { + return FMath.approxEqual(length2(), 1.0f, Constant.MACHINE_EPSILON); + } + + /** + * @brief Check if the vector is equal to (0,0,0) + * @return true The value is equal to (0,0,0) + * @return false The value is NOT equal to (0,0,0) + */ + public boolean isZero() { + return FMath.approxEqual(length2(), 0.0f, Constant.MACHINE_EPSILON); + } + /** * @brief Get the length of the vector * @return Length value @@ -133,146 +433,66 @@ public class Vector3f { public float length() { return (float) Math.sqrt(length2()); } + /** - * @brief Return the distance squared between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the square distance of the 2 points + * @brief Get the length between the 2 vectors + * @param start First vector + * @param stop second vector + * @return Length value */ - public float distance2(Vector3f obj) { - float deltaX = obj.x - this.x; - float deltaY = obj.y - this.y; - float deltaZ = obj.z - this.z; - return deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + public float length(final Vector3f start, final Vector3f stop) { + return (float) Math.sqrt(length2(start, stop)); } + /** - * @brief Return the distance between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the distance of the 2 points + * @brief Get the length of the vector squared + * @return Squared length value. */ - public float distance(Vector3f obj) { - return (float)Math.sqrt(this.distance2(obj)); + public float length2() { + return dot(this); } + /** - * @brief Normalize this vector x^2 + y^2 + z^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0,0)) - * @return the current vector + * @brief Return the linear interpolation between this and another vector + * @param obj The other vector + * @param ratio The ratio of this to obj (ratio = 0 => return copy of this, ratio=1 => return other) + * @return New vector containing the value */ - public Vector3f safeNormalize() { - float length = length(); - if (length != 0.0f) { - this.devide(length); - return this; - } - this.setValue(1,0,0); + public Vector3f lerp(final Vector3f obj, final float ratio) { + return new Vector3f(this.x + (obj.x - this.x) * ratio, this.y + (obj.y - this.y) * ratio, this.z + (obj.z - this.z) * ratio); + } + + public Vector3f less(final float value) { + this.x -= value; + this.y -= value; + this.z -= value; return this; } + /** - * @brief Normalize this vector x^2 + y^2 + z^2 = 1 - * @return the current vector + * @brief Subtract a vector from this one + * @param obj The vector to subtract */ - public Vector3f normalize() { - this.devide(this.length()); + public Vector3f less(final Vector3f obj) { + this.x -= obj.x; + this.y -= obj.y; + this.z -= obj.z; return this; } - /** - * @brief Return a normalized version of this vector - * @return New vector containing the value - */ - public Vector3f normalizeNew() { - Vector3f out = new Vector3f(this); - out.normalize(); - return out; + + public Vector3f lessNew(final float value) { + return new Vector3f(this.x - value, this.y - value, this.z - value); } + /** - * @brief Return a normalized version of this vector (check if not deviding by 0, if it is the case ==> return (1,0,0)) - * @return New vector containing the value + * @brief Subtract a vector from this one + * @param obj The vector to subtract + * @return A new vector with the data */ - public Vector3f safeNormalizeNew() { - Vector3f out = new Vector3f(this); - out.safeNormalize(); - return out; - } - /** - * @brief Return a rotated version of this vector - * @param wAxis The axis to rotate about - * @param angle The angle to rotate by - * @return New vector containing the value - */ - public Vector3f rotateNew( Vector3f wAxis, float angle ) { - Vector3f out = wAxis.clone(); - out.multiply( wAxis.dot( this ) ); - Vector3f x = this.clone(); - x.less(out); - Vector3f y = wAxis.cross( this ); - x.multiply((float)Math.cos(angle)); - y.multiply((float)Math.sin(angle)); - out.add(x); - out.add(y); - return out; - } - /** - * @brief Calculate the angle between this and another vector - * @param obj The other vector - * @return Angle in radian - */ - public float angle(Vector3f obj) { - float s = (float) Math.sqrt(length2() * obj.length2()); - if (0!=s) { - return (float) Math.acos(this.dot(obj) / s); - } - return 0; - } - /** - * @brief Return a vector will the absolute values of each element - * @return the curent reference - */ - public Vector3f absolute() { - this.x = Math.abs(this.x); - this.y = Math.abs(this.y); - this.z = Math.abs(this.z); - return this; - } - /** - * @brief Return a vector will the absolute values of each element - * @return New vector containing the value - */ - public Vector3f absoluteNew() { - return new Vector3f( Math.abs(this.x), - Math.abs(this.y), - Math.abs(this.z)); - } - /** - * @brief Return the cross product between this and another vector - * @param obj The other vector - * @return Vector with the result of the cross product - */ - public Vector3f cross(Vector3f obj) { - return new Vector3f(this.y * obj.z - this.z * obj.y, - this.z * obj.x - this.x * obj.z, - this.x * obj.y - this.y * obj.x); - } - /** - * @brief Return the triple product between this and another vector and another - * @param obj1 The other vector 1 - * @param obj2 The other vector 2 - * @return Value with the result of the triple product - */ - public float triple(Vector3f obj1, Vector3f obj2) { - return this.x * (obj1.y * obj2.z - obj1.z * obj2.y) - + this.y * (obj1.z * obj2.x - obj1.x * obj2.z) - + this.z * (obj1.x * obj2.y - obj1.y * obj2.x); - } - /** - * @brief Return the axis with the smallest value - * @return values 0,1,2 for x, y, or z - */ - public int minAxis() { - if (this.x < this.y) { - return this.x < this.z ? 0 : 2; - } - return this.y < this.z ? 1 : 2; + public Vector3f lessNew(final Vector3f obj) { + return new Vector3f(this.x - obj.x, this.y - obj.y, this.z - obj.z); } + /** * @brief Return the axis with the largest value * @return values 0,1,2 for x, y, or z @@ -283,265 +503,242 @@ public class Vector3f { } return this.x < this.z ? 2 : 0; } + /** - * @brief Return the axis with the smallest ABSOLUTE value + * @brief Return the axis with the smallest value * @return values 0,1,2 for x, y, or z */ - public int furthestAxis() { - return absoluteNew().minAxis(); + public int minAxis() { + if (this.x < this.y) { + return this.x < this.z ? 0 : 2; + } + return this.y < this.z ? 1 : 2; } + /** - * @brief Return the axis with the largest ABSOLUTE value - * @return values 0,1,2 for x, y, or z + * @brief Scale the vector + * @param val Scale factor */ - public int closestAxis() { - return absoluteNew().maxAxis(); + public Vector3f multiply(final float val) { + this.x *= val; + this.y *= val; + this.z *= val; + return this; } + + /** + * @brief Elementwise multiply this vector by the other + * @param obj The other vector + * @return the current reference + */ + public Vector3f multiply(final Vector3f obj) { + this.x *= obj.x; + this.y *= obj.y; + this.z *= obj.z; + return this; + } + + /** + * @brief Scale the vector + * @param val Scale factor + * @return A new vector with the data + */ + public Vector3f multiplyNew(final float val) { + return new Vector3f(this.x * val, this.y * val, this.z * val); + } + + /** + * @brief Elementwise multiply this vector by the other + * @param obj The other vector + */ + public Vector3f multiplyNew(final Vector3f obj) { + return new Vector3f(this.x * obj.x, this.y * obj.y, this.z * obj.z); + } + + public void multiplyTo(final Vector3f obj, final Vector3f out) { + out.set(this.x * obj.x, this.y * obj.y, this.z * obj.z); + } + + /** + * @brief Normalize this vector x^2 + y^2 + z^2 = 1 + * @return the current vector + */ + public Vector3f normalize() { + this.divide(this.length()); + return this; + } + + /** + * @brief Return a normalized version of this vector + * @return New vector containing the value + */ + public Vector3f normalizeNew() { + final Vector3f out = new Vector3f(this); + out.normalize(); + return out; + } + + /** + * @brief Return a rotated version of this vector + * @param wAxis The axis to rotate about + * @param angle The angle to rotate by + * @return New vector containing the value + */ + public Vector3f rotateNew(final Vector3f wAxis, final float angle) { + final Vector3f out = wAxis.clone(); + out.multiply(wAxis.dot(this)); + final Vector3f x = clone(); + x.less(out); + final Vector3f y = wAxis.cross(this); + x.multiply((float) Math.cos(angle)); + y.multiply((float) Math.sin(angle)); + out.add(x); + out.add(y); + return out; + } + + /** + * @brief Normalize this vector x^2 + y^2 + z^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0,0)) + * @return the current vector + */ + public Vector3f safeNormalize() { + final float length = length(); + if (length != 0.0f) { + this.divide(length); + return this; + } + setValue(1, 0, 0); + return this; + } + + /** + * @brief Return a normalized version of this vector (check if not deviding by 0, if it is the case ==> return (1,0,0)) + * @return New vector containing the value + */ + public Vector3f safeNormalizeNew() { + final Vector3f out = new Vector3f(this); + out.safeNormalize(); + return out; + } + + /** + * @brief Set scalar values + * @param xxx X value + * @param yyy Y value + * @param zzz Z value + */ + public Vector3f set(final float xxx, final float yyy, final float zzz) { + this.x = xxx; + this.y = yyy; + this.z = zzz; + return this; + } + + /** + * @brief Copy an other object + * @param obj The vector to add to this one + */ + public Vector3f set(final Vector3f obj) { + this.x += obj.x; + this.y += obj.y; + this.z += obj.z; + return this; + } + /** * @brief Interpolate the vector with a ration between 2 others * @param obj0 First vector * @param obj1 Second vector * @param ratio Ratio between obj0 and obj1 */ - public void setInterpolate3(Vector3f obj0, Vector3f obj1, float ratio) { - float inverse = 1.0f - ratio; + public void setInterpolate3(final Vector3f obj0, final Vector3f obj1, final float ratio) { + final float inverse = 1.0f - ratio; this.x = inverse * obj0.x + ratio * obj1.x; this.y = inverse * obj0.y + ratio * obj1.y; this.z = inverse * obj0.z + ratio * obj1.z; // this.co[3] = s * v0[3] + rt * v1[3]; } - /** - * @brief Return the linear interpolation between this and another vector - * @param obj The other vector - * @param ratio The ratio of this to obj (ratio = 0 => return copy of this, ratio=1 => return other) - * @return New vector containing the value - */ - public Vector3f lerp(Vector3f obj, float ratio) { - return new Vector3f(this.x + (obj.x - this.x) * ratio, - this.y + (obj.y - this.y) * ratio, - this.z + (obj.z - this.z) * ratio); - } - /** - * @brief Elementwise multiply this vector by the other - * @param obj The other vector - * @return the current reference - */ - public Vector3f multiply(Vector3f obj) { - this.x *= obj.x; - this.y *= obj.y; - this.z *= obj.z; - return this; - } - /** - * @brief Elementwise multiply this vector by the other - * @param obj The other vector - */ - public Vector3f multiplyNew(Vector3f obj) { - return new Vector3f(this.x * obj.x, this.y * obj.y, this.z * obj.z); - } - /** - * @brief Set the x value - * @param x New value - */ - public void setX(float x) { - this.x = x; - } - /** - * @brief Set the y value - * @param y New value - */ - public void setY(float y) { - this.y = y; - } - /** - * @brief Set the z value - * @param z New value - */ - public void setZ(float z) { - this.z = z; - } - /** - * @brief Get X value - * @return the x value - */ - public float getX() { - return this.x; - } - /** - * @brief Get Y value - * @return the y value - */ - public float getY() { - return this.y; - } - /** - * @brief Get Z value - * @return the z value - */ - public float getZ() { - return this.z; - } - /** - * @brief Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are identical - * @return false The Objects are NOT identical - */ - public boolean isEqual(Vector3f obj) { - return ( (this.z == obj.z) - && (this.y == obj.y) - && (this.x == obj.x)); - } - /** - * @brief In-Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are NOT identical - * @return false The Objects are identical - */ - public boolean isDifferent(Vector3f obj) { - return ( (this.z != obj.z) - || (this.y != obj.y) - || (this.x != obj.x)); - } + /** * @brief Set each element to the max of the current values and the values of another Vector3f * @param obj The other Vector3f to compare with */ - public void setMax(Vector3f obj) { + public void setMax(final Vector3f obj) { this.x = Math.max(this.x, obj.x); this.y = Math.max(this.y, obj.y); this.z = Math.max(this.z, obj.z); } + /** * @brief Set each element to the min of the current values and the values of another Vector3f * @param obj The other Vector3f to compare with */ - public void setMin(Vector3f obj) { + public void setMin(final Vector3f obj) { this.x = Math.min(this.x, obj.x); this.y = Math.min(this.y, obj.y); this.z = Math.min(this.z, obj.z); } - /** - * @brief Get the minimum value of the vector (x, y, z) - * @return The min value - */ - public float getMin() { - return Math.min(Math.min(this.x, this.y), this.z); - } - /** - * @brief Get the maximum value of the vector (x, y, z) - * @return The max value - */ - public float getMax() { - return Math.max(Math.max(this.x, this.y), this.z); - } + /** * @brief Set Value on the vector * @param xxx X value. * @param yyy Y value. * @param zzz Z value. */ - public void setValue(float xxx, float yyy, float zzz) { + public void setValue(final float xxx, final float yyy, final float zzz) { this.x = xxx; this.y = yyy; this.z = zzz; } + /** - * @brief Create a skew matrix of the object - * @param obj0 Vector matric first line - * @param obj1 Vector matric second line - * @param obj2 Vector matric third line + * @brief Set the x value + * @param x New value */ - public void getSkewSymmetricMatrix(Vector3f obj0,Vector3f obj1,Vector3f obj2) { - obj0.setValue(0 ,-z ,y); - obj1.setValue(z ,0 ,-x); - obj2.setValue(-y ,x ,0); + public void setX(final float x) { + this.x = x; } + + /** + * @brief Set the y value + * @param y New value + */ + public void setY(final float y) { + this.y = y; + } + + /** + * @brief Set the z value + * @param z New value + */ + public void setZ(final float z) { + this.z = z; + } + /** * @brief Set 0 value on all the vector */ public void setZero() { - setValue(0,0,0); + setValue(0, 0, 0); } - /** - * @brief Check if the vector is equal to (0,0,0) - * @return true The value is equal to (0,0,0) - * @return false The value is NOT equal to (0,0,0) - */ - public boolean isZero() { - return this.x == 0 - && this.y == 0 - && this.z == 0; - } - /** - * @brief Get the Axis id with the minimum value - * @return Axis ID 0,1,2 - */ - public int getMinAxis() { - return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); - } - /** - * @brief Get the Axis id with the maximum value - * @return Axis ID 0,1,2 - */ - public int getMaxAxis() { - return (this.x < this.y ? (this.y < this.z ? 2 : 1) : (this.x < this.z ? 2 : 0)); - } - /** - * @breif Get the orthogonal vector of the current vector - * @return The ortho vector - */ - public Vector3f getOrthoVector() { - Vector3f vectorAbs = new Vector3f(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); - int minElement = vectorAbs.getMinAxis(); - if (minElement == 0) { - float devider = 1.0f / (float)Math.sqrt(this.y*this.y + this.z*this.z); - return new Vector3f(0.0f, -this.z*devider, this.y*devider); - } else if (minElement == 1) { - float devider = 1.0f / (float)Math.sqrt(this.x*this.x + this.z*this.z); - return new Vector3f(-this.z*devider, 0.0f, this.x*devider); - } - float devider = 1.0f / (float)Math.sqrt(this.x*this.x + this.y*this.y); - return new Vector3f(-this.y*devider, this.x*devider, 0.0f); - } - /** - * @brief Clone the current vector. - * @return New vector containing the value - */ - public Vector3f clone() { - return new Vector3f(this); - } - public static Vector3f zero() { - return new Vector3f(0,0,0); + + public void to(final Vector3f out) { + out.set(this.x, this.y, this.z); } + @Override public String toString() { return "Vector3f(" + this.x + "," + this.y + "," + this.z + ")"; } - - - - /** - * @brief Get the length square between the 2 vectors - * @param start First vector - * @param stop second vector - * @return Length value + * @brief Return the triple product between this and another vector and another + * @param obj1 The other vector 1 + * @param obj2 The other vector 2 + * @return Value with the result of the triple product */ - public static float length2(Vector3f start, Vector3f stop) { - float x = stop.x - start.x; - float y = stop.y - start.y; - float z = stop.z - start.z; - return x * x + y * y + z * z; - } - /** - * @brief Get the length between the 2 vectors - * @param start First vector - * @param stop second vector - * @return Length value - */ - public float length(Vector3f start, Vector3f stop) { - return (float) Math.sqrt(length2(start, stop)); + public float triple(final Vector3f obj1, final Vector3f obj2) { + return this.x * (obj1.y * obj2.z - obj1.z * obj2.y) + this.y * (obj1.z * obj2.x - obj1.x * obj2.z) + this.z * (obj1.x * obj2.y - obj1.y * obj2.x); } + }