507 lines
16 KiB
Java
507 lines
16 KiB
Java
package org.atriaSoft.etk.math;
|
|
|
|
import java.nio.FloatBuffer;
|
|
|
|
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;
|
|
}
|
|
this.mat[0] = 1.0f;
|
|
this.mat[5] = 1.0f;
|
|
this.mat[10] = 1.0f;
|
|
this.mat[15] = 1.0f;
|
|
}
|
|
public static Matrix4f identity() {
|
|
Matrix4f tmp = new Matrix4f();
|
|
tmp.setIdentity();
|
|
return tmp;
|
|
}
|
|
/**
|
|
* @brief Constructor that load identity
|
|
*/
|
|
public Matrix4f() {
|
|
setIdentity();
|
|
}
|
|
/**
|
|
* @brief Configuration constructor.
|
|
* @param[in] a1 1st colomn, 1 line value
|
|
* @param[in] b1 2nd colomn, 1 line value
|
|
* @param[in] c1 3rd colomn, 1 line value
|
|
* @param[in] d1 4th colomn, 1 line value
|
|
* @param[in] a2 1st colomn, 2 line value
|
|
* @param[in] b2 2nd colomn, 2 line value
|
|
* @param[in] c2 3rd colomn, 2 line value
|
|
* @param[in] d2 4th colomn, 2 line value
|
|
* @param[in] a3 1st colomn, 3 line value
|
|
* @param[in] b3 2nd colomn, 3 line value
|
|
* @param[in] c3 3rd colomn, 3 line value
|
|
* @param[in] d3 4th colomn, 3 line value
|
|
* @param[in] a4 1st colomn, 4 line value
|
|
* @param[in] b4 2nd colomn, 4 line value
|
|
* @param[in] c4 3rd colomn, 4 line value
|
|
* @param[in] 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) {
|
|
this.mat[0] = a1;
|
|
this.mat[1] = b1;
|
|
this.mat[2] = c1;
|
|
this.mat[3] = d1;
|
|
this.mat[4] = a2;
|
|
this.mat[5] = b2;
|
|
this.mat[6] = c2;
|
|
this.mat[7] = d2;
|
|
this.mat[8] = a3;
|
|
this.mat[9] = b3;
|
|
this.mat[10] = c3;
|
|
this.mat[11] = d3;
|
|
this.mat[12] = a4;
|
|
this.mat[13] = b4;
|
|
this.mat[14] = c4;
|
|
this.mat[15] = d4;
|
|
}
|
|
/**
|
|
* @brief Configuration constructor.
|
|
* @param[in] values vector of values
|
|
*/
|
|
public Matrix4f(float[] values) {
|
|
if (values == null) {
|
|
setIdentity();
|
|
return;
|
|
}
|
|
for(int iii=0; iii<16 ; ++iii) {
|
|
this.mat[iii] = values[iii];
|
|
}
|
|
}
|
|
/**
|
|
* @brief Operator= Asign the current object with an other object
|
|
* @param[in] obj Reference on the external object
|
|
*/
|
|
public void set(Matrix4f obj) {
|
|
for(int iii=0; iii<16 ; iii++) {
|
|
this.mat[iii] = obj.mat[iii];
|
|
}
|
|
}
|
|
/**
|
|
* @brief Equality compare operator with an other object.
|
|
* @param[in] obj Reference on the comparing object
|
|
* @return true The Objects are identical
|
|
* @return false The Objects are NOT identical
|
|
*/
|
|
public boolean isEqual(Matrix4f obj) {
|
|
for(int iii=0; iii<4*4 ; ++iii) {
|
|
if(this.mat[iii] != obj.mat[iii]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* @brief In-Equality compare operator with an other object.
|
|
* @param[in] 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]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* @brief Operator+= Addition an other matrix with this one
|
|
* @param[in] obj Reference on the external object
|
|
*/
|
|
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[in] 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];
|
|
}
|
|
}
|
|
/**
|
|
* @brief Operator*= Multiplication an other matrix with this one
|
|
* @param[in] obj Reference on the external object
|
|
*/
|
|
public Matrix4f multiply(Matrix4f obj) {
|
|
// output Matrix
|
|
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];
|
|
}
|
|
matrixOut[yyy*4+xxx] = value;
|
|
}
|
|
}
|
|
// set it at the output
|
|
for(int iii=0; iii<4*4 ; iii++) {
|
|
this.mat[iii] = matrixOut[iii];
|
|
}
|
|
return this;
|
|
}
|
|
public Matrix4f multiply_new(Matrix4f obj) {
|
|
return this.clone().multiply(obj);
|
|
}
|
|
/**
|
|
* @brief Operator* apply matrix on a vector
|
|
* @param[in] 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] );
|
|
}
|
|
/**
|
|
* @brief Transpose the current matix (usefull for OpenGL display)
|
|
*/
|
|
public Matrix4f transpose() {
|
|
float tmpVal = this.mat[1];
|
|
this.mat[1] = this.mat[4];
|
|
this.mat[4] = tmpVal;
|
|
|
|
tmpVal = this.mat[2];
|
|
this.mat[2] = this.mat[8];
|
|
this.mat[8] = tmpVal;
|
|
|
|
tmpVal = this.mat[6];
|
|
this.mat[6] = this.mat[9];
|
|
this.mat[9] = tmpVal;
|
|
|
|
tmpVal = this.mat[3];
|
|
this.mat[3] = this.mat[12];
|
|
this.mat[12] = tmpVal;
|
|
|
|
tmpVal = this.mat[7];
|
|
this.mat[7] = this.mat[13];
|
|
this.mat[13] = tmpVal;
|
|
|
|
tmpVal = this.mat[11];
|
|
this.mat[11] = this.mat[14];
|
|
this.mat[14] = tmpVal;
|
|
return this;
|
|
}
|
|
public Matrix4f transpose_new() {
|
|
return this.clone().transpose();
|
|
}
|
|
/**
|
|
* @brief Scale the current Matrix.
|
|
* @param[in] vect Scale vector to apply.
|
|
*/
|
|
public Matrix4f scale(Vector3f vect) {
|
|
return scale(vect.x, vect.y, vect.z);
|
|
}
|
|
public Matrix4f scale_new(Vector3f vect) {
|
|
return this.clone().scale(vect.x, vect.y, vect.z);
|
|
}
|
|
/**
|
|
* @brief Scale the current Matrix.
|
|
* @param[in] sx Scale X value to apply.
|
|
* @param[in] sy Scale Y value to apply.
|
|
* @param[in] 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 scale_new(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[in] scale Scale XYZ value to apply.
|
|
*/
|
|
public Matrix4f scale(float scale) {
|
|
return scale(scale, scale, scale);
|
|
}
|
|
public Matrix4f scale_new(float scale) {
|
|
return this.clone().scale(scale, scale, scale);
|
|
}
|
|
/**
|
|
* @brief Makes a rotation matrix about an arbitrary axis.
|
|
* @param[in] vect vector to apply the angle.
|
|
* @param[in] angleRad angle to apply.
|
|
*/
|
|
public Matrix4f rotate(Vector3f vect, float angleRad) {
|
|
Matrix4f tmpMat = createMatrixRotate(vect, angleRad);
|
|
return this.multiply(tmpMat);
|
|
}
|
|
public Matrix4f rotate_new(Vector3f vect, float angleRad) {
|
|
Matrix4f tmpMat = createMatrixRotate(vect, angleRad);
|
|
return this.multiply_new(tmpMat);
|
|
}
|
|
/**
|
|
* @brief Makes a translation of the matrix
|
|
* @param[in] vect Translation to apply.
|
|
*/
|
|
public Matrix4f translate(Vector3f vect) {
|
|
Matrix4f tmpMat = createMatrixTranslate(vect);
|
|
return this.multiply(tmpMat);
|
|
}
|
|
public Matrix4f translate_new(Vector3f vect) {
|
|
Matrix4f tmpMat = createMatrixTranslate(vect);
|
|
return this.multiply_new(tmpMat);
|
|
}
|
|
/**
|
|
* @brief Computes a cofactor. Used for matrix inversion.
|
|
* @param[in] row Id of raw.
|
|
* @param[in] 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 invert_new() {
|
|
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[in] 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[in] xmin X minimum size of the frustum
|
|
* @param[in] xmax X maximum size of the frustum
|
|
* @param[in] ymin Y minimum size of the frustum
|
|
* @param[in] ymax Y maximum size of the frustum
|
|
* @param[in] zNear Z minimum size of the frustum
|
|
* @param[in] 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[in] foxy Focal in radian of the camera
|
|
* @param[in] aspect aspect ratio of the camera
|
|
* @param[in] zNear Z near size of the camera
|
|
* @param[in] 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[in] left left size of the camera
|
|
* @param[in] right Right size of the camera
|
|
* @param[in] bottom Buttom size of the camera
|
|
* @param[in] top Top Size of the camera
|
|
* @param[in] nearVal Z near size of the camera
|
|
* @param[in] 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[in] 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[in] 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[in] normal vector aroud witch apply the rotation
|
|
* @param[in] 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[in] eye Optical center of the camera
|
|
* @param[in] target Point of where the camera is showing
|
|
* @param[in] 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.normalize_new());
|
|
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;
|
|
}
|
|
|
|
}
|