parent
e2d8fe8293
commit
f7a4fe9f25
@ -0,0 +1,214 @@ |
||||
package com.jme3.scene.plugins.blender.math; |
||||
|
||||
import java.text.DecimalFormat; |
||||
|
||||
import org.ejml.ops.CommonOps; |
||||
import org.ejml.simple.SimpleMatrix; |
||||
import org.ejml.simple.SimpleSVD; |
||||
|
||||
import com.jme3.math.FastMath; |
||||
|
||||
/** |
||||
* Encapsulates a 4x4 matrix |
||||
* |
||||
* |
||||
*/ |
||||
public class Matrix extends SimpleMatrix { |
||||
private static final long serialVersionUID = 2396600537315902559L; |
||||
|
||||
public Matrix(int rows, int cols) { |
||||
super(rows, cols); |
||||
} |
||||
|
||||
/** |
||||
* Copy constructor |
||||
*/ |
||||
public Matrix(SimpleMatrix m) { |
||||
super(m); |
||||
} |
||||
|
||||
public Matrix(double[][] data) { |
||||
super(data); |
||||
} |
||||
|
||||
public static Matrix identity(int size) { |
||||
Matrix result = new Matrix(size, size); |
||||
CommonOps.setIdentity(result.mat); |
||||
return result; |
||||
} |
||||
|
||||
public Matrix pseudoinverse() { |
||||
return this.pseudoinverse(1); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public Matrix pseudoinverse(double lambda) { |
||||
SimpleSVD<SimpleMatrix> simpleSVD = this.svd(); |
||||
|
||||
SimpleMatrix U = simpleSVD.getU(); |
||||
SimpleMatrix S = simpleSVD.getW(); |
||||
SimpleMatrix V = simpleSVD.getV(); |
||||
|
||||
int N = Math.min(this.numRows(),this.numCols()); |
||||
double maxSingular = 0; |
||||
for( int i = 0; i < N; i++ ) { |
||||
if( S.get(i, i) > maxSingular ) { |
||||
maxSingular = S.get(i, i); |
||||
} |
||||
} |
||||
|
||||
double tolerance = FastMath.DBL_EPSILON * Math.max(this.numRows(),this.numCols()) * maxSingular; |
||||
for(int i=0;i<Math.min(S.numRows(), S.numCols());++i) { |
||||
double a = S.get(i, i); |
||||
if(a <= tolerance) { |
||||
a = 0; |
||||
} else { |
||||
a = a/(a * a + lambda * lambda); |
||||
} |
||||
S.set(i, i, a); |
||||
} |
||||
return new Matrix(V.mult(S.transpose()).mult(U.transpose())); |
||||
} |
||||
|
||||
public void setColumn(Vector3d col, int column) { |
||||
this.setColumn(column, 0, col.x, col.y, col.z); |
||||
} |
||||
|
||||
/** |
||||
* Just for some debug informations in order to compare the results with the scilab computation program. |
||||
* @param name the name of the matrix |
||||
* @param m the matrix to print out |
||||
* @return the String format of the matrix to easily input it to Scilab |
||||
*/ |
||||
public String toScilabString(String name, SimpleMatrix m) { |
||||
String result = name + " = ["; |
||||
|
||||
for(int i=0;i<m.numRows();++i) { |
||||
for(int j=0;j<m.numCols();++j) { |
||||
result += m.get(i, j) + " "; |
||||
} |
||||
result += ";"; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* @return a String representation of the matrix |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
DecimalFormat df = new DecimalFormat("#.0000"); |
||||
StringBuilder buf = new StringBuilder(); |
||||
for (int r = 0; r < this.numRows(); ++r) { |
||||
buf.append("\n| "); |
||||
for (int c = 0; c < this.numCols(); ++c) { |
||||
buf.append(df.format(this.get(r, c))).append(' '); |
||||
} |
||||
buf.append('|'); |
||||
} |
||||
return buf.toString(); |
||||
} |
||||
|
||||
public void setTranslation(Vector3d translation) { |
||||
this.setColumn(translation, 3); |
||||
} |
||||
|
||||
/** |
||||
* Sets the scale. |
||||
* |
||||
* @param scale |
||||
* the scale vector to set |
||||
*/ |
||||
public void setScale(Vector3d scale) { |
||||
this.setScale(scale.x, scale.y, scale.z); |
||||
} |
||||
|
||||
/** |
||||
* Sets the scale. |
||||
* |
||||
* @param x |
||||
* the X scale |
||||
* @param y |
||||
* the Y scale |
||||
* @param z |
||||
* the Z scale |
||||
*/ |
||||
public void setScale(double x, double y, double z) { |
||||
Vector3d vect1 = new Vector3d(this.get(0, 0), this.get(1, 0), this.get(2, 0)); |
||||
vect1.normalizeLocal().multLocal(x); |
||||
this.set(0, 0, vect1.x); |
||||
this.set(1, 0, vect1.y); |
||||
this.set(2, 0, vect1.z); |
||||
|
||||
vect1.set(this.get(0, 1), this.get(1, 1), this.get(2, 1)); |
||||
vect1.normalizeLocal().multLocal(y); |
||||
this.set(0, 1, vect1.x); |
||||
this.set(1, 1, vect1.y); |
||||
this.set(2, 1, vect1.z); |
||||
|
||||
vect1.set(this.get(0, 2), this.get(1, 2), this.get(2, 2)); |
||||
vect1.normalizeLocal().multLocal(z); |
||||
this.set(0, 2, vect1.x); |
||||
this.set(1, 2, vect1.y); |
||||
this.set(2, 2, vect1.z); |
||||
} |
||||
|
||||
/** |
||||
* <code>setRotationQuaternion</code> builds a rotation from a |
||||
* <code>Quaternion</code>. |
||||
* |
||||
* @param quat |
||||
* the quaternion to build the rotation from. |
||||
* @throws NullPointerException |
||||
* if quat is null. |
||||
*/ |
||||
public void setRotationQuaternion(DQuaternion quat) { |
||||
quat.toRotationMatrix(this); |
||||
} |
||||
|
||||
public DTransform toTransform() { |
||||
DTransform result = new DTransform(); |
||||
result.setTranslation(this.toTranslationVector()); |
||||
result.setRotation(this.toRotationQuat()); |
||||
result.setScale(this.toScaleVector()); |
||||
return result; |
||||
} |
||||
|
||||
public Vector3d toTranslationVector() { |
||||
return new Vector3d(this.get(0, 3), this.get(1, 3), this.get(2, 3)); |
||||
} |
||||
|
||||
public DQuaternion toRotationQuat() { |
||||
DQuaternion quat = new DQuaternion(); |
||||
quat.fromRotationMatrix(this.get(0, 0), this.get(0, 1), this.get(0, 2), this.get(1, 0), this.get(1, 1), this.get(1, 2), this.get(2, 0), this.get(2, 1), this.get(2, 2)); |
||||
return quat; |
||||
} |
||||
|
||||
/** |
||||
* Retreives the scale vector from the matrix and stores it into a given |
||||
* vector. |
||||
* |
||||
* @param the |
||||
* vector where the scale will be stored |
||||
*/ |
||||
public Vector3d toScaleVector() { |
||||
Vector3d result = new Vector3d(); |
||||
this.toScaleVector(result); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Retreives the scale vector from the matrix and stores it into a given |
||||
* vector. |
||||
* |
||||
* @param the |
||||
* vector where the scale will be stored |
||||
*/ |
||||
public void toScaleVector(Vector3d vector) { |
||||
double scaleX = Math.sqrt(this.get(0, 0) * this.get(0, 0) + this.get(1, 0) * this.get(1, 0) + this.get(2, 0) * this.get(2, 0)); |
||||
double scaleY = Math.sqrt(this.get(0, 1) * this.get(0, 1) + this.get(1, 1) * this.get(1, 1) + this.get(2, 1) * this.get(2, 1)); |
||||
double scaleZ = Math.sqrt(this.get(0, 2) * this.get(0, 2) + this.get(1, 2) * this.get(1, 2) + this.get(2, 2) * this.get(2, 2)); |
||||
vector.set(scaleX, scaleY, scaleZ); |
||||
} |
||||
} |
Loading…
Reference in new issue