I think it is correct. Translated Matrix3f pretty much, but changed to 2D. Got all the stuff from Matrix3f in it, except for some methods:
- One of the fillFloatBuffer method that needed tempvars (would have to modify tempvars). Just commented it out.
- Replaced fromAngleAxis and fromAngleNormalAxis (they are now “fromAngle(float angle)”
- Removed everything involving quaternions and vector cross products (just two or three methods).
[java]
import com.jme3.export.*;
import com.jme3.math.FastMath;
import com.jme3.math.Vector2f;
import com.jme3.util.BufferUtils;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Logger;
/**
*
- Matrix2f converted from Matrix3f.
*
-
@author Androlo
*
******************************************************************************
*
- <code>Matrix3f</code> defines a 3x3 matrix. Matrix data is maintained
- internally and is accessible via the get and set methods. Convenience methods
- are used for matrix operations as well as generating a matrix from a given
- set of values.
*
-
@author Mark Powell
-
@author Joshua Slack
*/
public final class Matrix2f implements Savable, Cloneable, java.io.Serializable {
// TODO is there a system for this?
static final long serialVersionUID = 1;
private static final Logger logger = Logger.getLogger(Matrix2f.class.getName());
protected float m00, m01;
protected float m10, m11;
public static final Matrix2f ZERO = new Matrix2f(0, 0, 0, 0);
public static final Matrix2f IDENTITY = new Matrix2f();
/**
- Constructor instantiates a new <code>Matrix2f</code> object. The
- initial values for the matrix is that of the identity matrix.
*
*/
public Matrix2f() {
loadIdentity();
}
/**
- constructs a matrix with the given values.
*
-
@param m00
-
0x0 in the matrix.<br />
-
@param m01
-
0x1 in the matrix.<br />
-
@param m10
-
1x0 in the matrix.<br />
-
@param m11
*/
public Matrix2f(float m00, float m01, float m10, float m11) {
this.m00 = m00;
this.m01 = m01;
this.m10 = m10;
this.m11 = m11;
}
/**
- Copy constructor that creates a new <code>Matrix2f</code> object that
- is the same as the provided matrix.
*
-
@param mat
-
the matrix to copy.<br />
*/
public Matrix2f(Matrix2f mat) {
set(mat);
}
/**
- Takes the absolute value of all matrix fields locally.
*/
public void absoluteLocal() {
m00 = FastMath.abs(m00);
m01 = FastMath.abs(m01);
m10 = FastMath.abs(m10);
m11 = FastMath.abs(m11);
}
/**
- <code>copy</code> transfers the contents of a given matrix to this
- matrix. If a null matrix is supplied, this matrix is set to the identity
- matrix.
*
-
@param matrix
-
the matrix to copy.<br />
-
@return this
*/
public Matrix2f set(Matrix2f matrix) {
if (null == matrix) {
loadIdentity();
} else {
m00 = matrix.m00;
m01 = matrix.m01;
m10 = matrix.m10;
m11 = matrix.m11;
}
return this;
}
/**
- <code>get</code> retrieves a value from the matrix at the given
- position. If the position is invalid a <code>JmeException</code> is
- thrown.
*
-
@param i
-
the row index.<br />
-
@param j
-
the colum index.<br />
-
@return the value at (i, j).
*/
@SuppressWarnings("fallthrough")
public float get(int i, int j) {
switch (i) {
case 0:
switch (j) {
case 0:
return m00;
case 1:
return m01;
}
case 1:
switch (j) {
case 0:
return m10;
case 1:
return m11;
}
}
logger.warning("Invalid matrix index.");
throw new IllegalArgumentException("Invalid indices into matrix.");
}
/**
- <code>get(float[])</code> returns the matrix in row-major or column-major order.
*
-
@param data
-
The array to return the data into. This array can be 4, 9 or 16 floats in size.<br />
-
Only the upper 3x3 are assigned to in the case of a 16 element array.<br />
-
@param rowMajor
-
True for row major storage in the array (translation in elements 3, 7, 11 for a 4x4),<br />
-
false for column major (translation in elements 12, 13, 14 for a 4x4).<br />
*/
public void get(float[] data, boolean rowMajor) {
if (data.length == 4) {
if (rowMajor) {
data[0] = m00;
data[1] = m01;
data[3] = m10;
data[4] = m11;
} else {
data[0] = m00;
data[1] = m10;
data[3] = m01;
data[4] = m11;
}
if (data.length == 9) {
if (rowMajor) {
data[0] = m00;
data[1] = m01;
data[3] = m10;
data[4] = m11;
} else {
data[0] = m00;
data[1] = m10;
data[3] = m01;
data[4] = m11;
}
} else if (data.length == 16) {
if (rowMajor) {
data[0] = m00;
data[1] = m01;
data[4] = m10;
data[5] = m11;
} else {
data[0] = m00;
data[1] = m10;
data[4] = m01;
data[5] = m11;
}
} else {
throw new IndexOutOfBoundsException("Array size must be 4, 9 or 16 in Matrix3f.get().");
}
}
}
/**
- <code>getColumn</code> returns one of three columns specified by the
- parameter. This column is returned as a <code>Vector2f</code> object.
*
-
@param i
-
the column to retrieve. Must be 0 or 1.<br />
-
@return the column specified by the index.
*/
public Vector2f getColumn(int i) {
return getColumn(i, null);
}
/**
- <code>getColumn</code> returns one of three columns specified by the
- parameter. This column is returned as a <code>Vector2f</code> object.
*
-
@param i
-
the column to retrieve. Must be 0 or 1.<br />
-
@param store
-
the vector object to store the result in. if null, a new one<br />
-
is created.<br />
-
@return the column specified by the index.
*/
public Vector2f getColumn(int i, Vector2f store) {
if (store == null) {
store = new Vector2f();
}
switch (i) {
case 0:
store.x = m00;
store.y = m10;
break;
case 1:
store.x = m01;
store.y = m11;
break;
default:
logger.warning("Invalid column index.");
throw new IllegalArgumentException("Invalid column index. " + i);
}
return store;
}
/**
- <code>getRow</code> returns one of three rows as specified by the
- parameter. This row is returned as a <code>Vector2f</code> object.
*
-
@param i
-
the row to retrieve. Must be 0 or 1.<br />
-
@return the row specified by the index.
*/
public Vector2f getRow(int i) {
return getRow(i, null);
}
/**
- <code>getRow</code> returns one of three rows as specified by the
- parameter. This row is returned as a <code>Vector2f</code> object.
*
-
@param i
-
the row to retrieve. Must be 0 or 1.<br />
-
@param store
-
the vector object to store the result in. if null, a new one<br />
-
is created.<br />
-
@return the row specified by the index.
*/
public Vector2f getRow(int i, Vector2f store) {
if (store == null) {
store = new Vector2f();
}
switch (i) {
case 0:
store.x = m00;
store.y = m01;
break;
case 1:
store.x = m10;
store.y = m11;
break;
default:
logger.warning("Invalid row index.");
throw new IllegalArgumentException("Invalid row index. " + i);
}
return store;
}
/**
- <code>toFloatBuffer</code> returns a FloatBuffer object that contains
- the matrix data.
*
-
@return matrix data as a FloatBuffer.
*/
public FloatBuffer toFloatBuffer() {
FloatBuffer fb = BufferUtils.createFloatBuffer(4);
fb.put(m00).put(m01);
fb.put(m10).put(m11);
fb.rewind();
return fb;
}
/**
- <code>fillFloatBuffer</code> fills a FloatBuffer object with the matrix
- data.
*
-
@param fb
-
the buffer to fill, starting at current position. Must have<br />
-
room for 4 more floats.<br />
-
@return matrix data as a FloatBuffer. (position is advanced by 4 and any
-
limit set is not changed).<br />
*/
// public FloatBuffer fillFloatBuffer(FloatBuffer fb, boolean columnMajor) {
// TempVars vars = TempVars.get();
//
//
// fillFloatArray(vars.matrixWrite, columnMajor);
// fb.put(vars.matrixWrite, 0, 4);
//
// vars.release();
//
// return fb;
// }
public void fillFloatArray(float[] f, boolean columnMajor) {
if (columnMajor) {
f[0] = m00;
f[1] = m10;
f[2] = m01;
f[3] = m11;
} else {
f[0] = m00;
f[1] = m01;
f[3] = m10;
f[4] = m11;
}
}
/**
*
- <code>setColumn</code> sets a particular column of this matrix to that
- represented by the provided vector.
*
-
@param i
-
the column to set.<br />
-
@param column
-
the data to set.<br />
-
@return this
*/
public Matrix2f setColumn(int i, Vector2f column) {
if (column == null) {
logger.warning("Column is null. Ignoring.");
return this;
}
switch (i) {
case 0:
m00 = column.x;
m10 = column.y;
break;
case 1:
m01 = column.x;
m11 = column.y;
break;
default:
logger.warning("Invalid column index.");
throw new IllegalArgumentException("Invalid column index. " + i);
}
return this;
}
/**
*
- <code>setRow</code> sets a particular row of this matrix to that
- represented by the provided vector.
*
-
@param i
-
the row to set.<br />
-
@param row
-
the data to set.<br />
-
@return this
*/
public Matrix2f setRow(int i, Vector2f row) {
if (row == null) {
logger.warning("Row is null. Ignoring.");
return this;
}
switch (i) {
case 0:
m00 = row.x;
m01 = row.y;
break;
case 1:
m10 = row.x;
m11 = row.y;
break;
default:
logger.warning("Invalid row index.");
throw new IllegalArgumentException("Invalid row index. " + i);
}
return this;
}
/**
- <code>set</code> places a given value into the matrix at the given
- position. If the position is invalid a <code>JmeException</code> is
- thrown.
*
-
@param i
-
the row index.<br />
-
@param j
-
the colum index.<br />
-
@param value
-
the value for (i, j).<br />
-
@return this
*/
@SuppressWarnings("fallthrough")
public Matrix2f set(int i, int j, float value) {
switch (i) {
case 0:
switch (j) {
case 0:
m00 = value;
return this;
case 1:
m01 = value;
return this;
}
case 1:
switch (j) {
case 0:
m10 = value;
return this;
case 1:
m11 = value;
return this;
}
}
logger.warning("Invalid matrix index.");
throw new IllegalArgumentException("Invalid indices into matrix.");
}
/**
*
- <code>set</code> sets the values of the matrix to those supplied by the
- 2x2 two dimenion array.
*
-
@param matrix
-
the new values of the matrix.<br />
-
@throws JmeException
-
if the array is not of size 4.<br />
-
@return this
*/
public Matrix2f set(float[][] matrix) {
if (matrix.length != 2 || matrix[0].length != 2) {
throw new IllegalArgumentException(
"Array must be of size 9.");
}
m00 = matrix[0][0];
m01 = matrix[0][1];
m10 = matrix[1][0];
m11 = matrix[1][1];
return this;
}
/**
- Recreate Matrix using the provided axes.
*
-
@param uAxis
-
Vector3f<br />
-
@param vAxis
-
Vector3f<br />
*/
public void fromAxes(Vector2f uAxis, Vector2f vAxis) {
m00 = uAxis.x;
m10 = uAxis.y;
m01 = vAxis.x;
m11 = vAxis.y;
}
/**
- <code>set</code> sets the values of this matrix from an array of
- values assuming that the data is rowMajor order;
*
-
@param matrix
-
the matrix to set the value to.<br />
-
@return this
*/
public Matrix2f set(float[] matrix) {
return set(matrix, true);
}
/**
- <code>set</code> sets the values of this matrix from an array of
- values;
*
-
@param matrix
-
the matrix to set the value to.<br />
-
@param rowMajor
-
whether the incoming data is in row or column major order.<br />
-
@return this
*/
public Matrix2f set(float[] matrix, boolean rowMajor) {
if (matrix.length != 4) {
throw new IllegalArgumentException(
"Array must be of size 9.");
}
if (rowMajor) {
m00 = matrix[0];
m01 = matrix[1];
m10 = matrix[2];
m11 = matrix[3];
} else {
m00 = matrix[0];
m01 = matrix[2];
m10 = matrix[1];
m11 = matrix[4];
}
return this;
}
/**
- <code>loadIdentity</code> sets this matrix to the identity matrix.
- Where all values are zero except those along the diagonal which are one.
*
*/
public void loadIdentity() {
m01 = m10 = 0;
m00 = m11 = 1;
}
/**
-
@return true if this matrix is identity
*/
public boolean isIdentity() {
return (m00 == 1 && m01 == 0)
&& (m10 == 0 && m11 == 1);
}
/**
- <code>fromAngle</code> sets this matrix2f to the values
- specified by an angle of rotation.
*
-
@param angle
-
the angle to rotate (in radians).<br />
*/
public void fromAngle(float angle) {
float fCos = FastMath.cos(angle);
float fSin = FastMath.sin(angle);
m00 = fCos;
m01 = -fSin;
m10 = fSin;
m11 = fCos;
}
/**
- <code>mult</code> multiplies this matrix by a given matrix. The result
- matrix is returned as a new object. If the given matrix is null, a null
- matrix is returned.
*
-
@param mat
-
the matrix to multiply this matrix by.<br />
-
@return the result matrix.
*/
public Matrix2f mult(Matrix2f mat) {
return mult(mat, null);
}
/**
- <code>mult</code> multiplies this matrix by a given matrix. The result
- matrix is returned as a new object.
*
-
@param mat
-
the matrix to multiply this matrix by.<br />
-
@param product
-
the matrix to store the result in. if null, a new matrix3f is<br />
-
created. It is safe for mat and product to be the same object.<br />
-
@return a matrix2f object containing the result of this operation
*/
public Matrix2f mult(Matrix2f mat, Matrix2f product) {
float temp00, temp01;
float temp10, temp11;
if (product == null) {
product = new Matrix2f();
}
temp00 = m00 * mat.m00 + m01 * mat.m10;
temp01 = m00 * mat.m01 + m01 * mat.m11;
temp10 = m10 * mat.m00 + m11 * mat.m10;
temp11 = m10 * mat.m01 + m11 * mat.m11;
product.m00 = temp00;
product.m01 = temp01;
product.m10 = temp10;
product.m11 = temp11;
return product;
}
/**
- <code>mult</code> multiplies this matrix by a given
- <code>Vector2f</code> object. The result vector is returned. If the
- given vector is null, null will be returned.
*
-
@param vec
-
the vector to multiply this matrix by.<br />
-
@return the result vector.
*/
public Vector2f mult(Vector2f vec) {
return mult(vec, null);
}
/**
- Multiplies this 2x2 matrix by the 1x2 Vector vec and stores the result in
- product.
*
-
@param vec
-
The Vector2f to multiply.<br />
-
@param product
-
The Vector2f to store the result, it is safe for this to be<br />
-
the same as vec.<br />
-
@return The given product vector.
*/
public Vector2f mult(Vector2f vec, Vector2f product) {
if (null == product) {
product = new Vector2f();
}
float x = vec.x;
float y = vec.y;
product.x = m00 * x + m01 * y;
product.y = m10 * x + m11 * y;
return product;
}
/**
- <code>multLocal</code> multiplies this matrix internally by
- a given float scale factor.
*
-
@param scale
-
the value to scale by.<br />
-
@return this Matrix2f
*/
public Matrix2f multLocal(float scale) {
m00 *= scale;
m01 *= scale;
m10 *= scale;
m11 *= scale;
return this;
}
/**
- <code>multLocal</code> multiplies this matrix by a given
- <code>Vector2f</code> object. The result vector is stored inside the
- passed vector, then returned . If the given vector is null, null will be
- returned.
*
-
@param vec
-
the vector to multiply this matrix by.<br />
-
@return The passed vector after multiplication
*/
public Vector2f multLocal(Vector2f vec) {
if (vec == null) {
return null;
}
float x = vec.x;
float y = vec.y;
vec.x = m00 * x + m01 * y;
vec.y = m10 * x + m11 * y;
return vec;
}
/**
- <code>mult</code> multiplies this matrix by a given matrix. The result
- matrix is saved in the current matrix. If the given matrix is null,
- nothing happens. The current matrix is returned. This is equivalent to
- this*=mat
*
-
@param mat
-
the matrix to multiply this matrix by.<br />
-
@return This matrix, after the multiplication
*/
public Matrix2f multLocal(Matrix2f mat) {
return mult(mat, this);
}
/**
- Transposes this matrix in place. Returns this matrix for chaining
*
-
@return This matrix after transpose
*/
public Matrix2f transposeLocal() {
float tmp = m01;
m01 = m10;
m10 = tmp;
return this;
}
/**
- Inverts this matrix as a new Matrix2f.
*
-
@return The new inverse matrix
*/
public Matrix2f invert() {
return invert(null);
}
/**
- Inverts this matrix and stores it in the given store.
*
-
@return The store
*/
public Matrix2f invert(Matrix2f store) {
if (store == null) {
store = new Matrix2f();
}
float det = determinant();
if (FastMath.abs(det) <= FastMath.FLT_EPSILON) {
return store.zero();
}
store.m00 = m11;
store.m01 = -m01;
store.m10 = -m10;
store.m11 = m00;
store.multLocal(1f / det);
return store;
}
/**
- Inverts this matrix locally.
*
-
@return this
*/
public Matrix2f invertLocal() {
float det = determinant();
if (FastMath.abs(det) <= 0f) {
return zero();
}
float f00 = m11;
float f01 = -m01;
float f10 = -m10;
float f11 = m00;
m00 = f00;
m01 = f01;
m10 = f10;
m11 = f11;
multLocal(1f / det);
return this;
}
/**
- Returns a new matrix representing the adjoint of this matrix.
*
-
@return The adjoint matrix
*/
public Matrix2f adjoint() {
return adjoint(null);
}
/**
- Places the adjoint of this matrix in store (creates store if null.)
*
-
@param store
-
The matrix to store the result in. If null, a new matrix is created.<br />
-
@return store
*/
public Matrix2f adjoint(Matrix2f store) {
if (store == null) {
store = new Matrix2f();
}
store.m00 = m11;
store.m01 = -m01;
store.m10 = -m10;
store.m11 = m00;
return store;
}
/**
- <code>determinant</code> generates the determinant of this matrix.
*
-
@return the determinant
*/
public float determinant() {
float fDet = m00 * m11 - m01 * m10;
return fDet;
}
/**
- Sets all of the values in this matrix to zero.
*
-
@return this matrix
*/
public Matrix2f zero() {
m00 = m01 = m10 = m11 = 0.0f;
return this;
}
/**
- <code>transposeNew</code> returns a transposed version of this matrix.
*
-
@return The new Matrix2f object.
*/
public Matrix2f transpose() {
Matrix2f ret = new Matrix2f(m00, m10, m01, m11);
return ret;
}
/**
- <code>toString</code> returns the string representation of this object.
- It is in a format of a 2x2 matrix. For example, an identity matrix would
- be represented by the following string. com.jme.math.Matrix2f <br>[<br>
- 1.0 0.0<br>
- 0.0 1.0<br>]<br>
*
-
@return the string representation of this object.
*/
@Override
public String toString() {
StringBuilder result = new StringBuilder("Matrix3fn[n");
result.append(" ");
result.append(m00);
result.append(" ");
result.append(m01);
result.append(" n");
result.append(" ");
result.append(m10);
result.append(" ");
result.append(m11);
result.append(" n]");
return result.toString();
}
/**
*
- <code>hashCode</code> returns the hash code value as an integer and is
- supported for the benefit of hashing based collection classes such as
- Hashtable, HashMap, HashSet etc.
*
-
@return the hashcode for this instance of Matrix2f.
-
@see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int hash = 37;
hash = 37 * hash + Float.floatToIntBits(m00);
hash = 37 * hash + Float.floatToIntBits(m01);
hash = 37 * hash + Float.floatToIntBits(m10);
hash = 37 * hash + Float.floatToIntBits(m11);
return hash;
}
/**
- are these two matrices the same? they are is they both have the same mXX values.
*
-
@param o
-
the object to compare for equality<br />
-
@return true if they are equal
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof Matrix2f) || o == null) {
return false;
}
if (this == o) {
return true;
}
Matrix2f comp = (Matrix2f) o;
if (Float.compare(m00, comp.m00) != 0) {
return false;
}
if (Float.compare(m01, comp.m01) != 0) {
return false;
}
if (Float.compare(m10, comp.m10) != 0) {
return false;
}
if (Float.compare(m11, comp.m11) != 0) {
return false;
}
return true;
}
public void write(JmeExporter e) throws IOException {
OutputCapsule cap = e.getCapsule(this);
cap.write(m00, "m00", 1);
cap.write(m01, "m01", 0);
cap.write(m10, "m10", 0);
cap.write(m11, "m11", 1);
}
public void read(JmeImporter e) throws IOException {
InputCapsule cap = e.getCapsule(this);
m00 = cap.readFloat("m00", 1);
m01 = cap.readFloat("m01", 0);
m10 = cap.readFloat("m10", 0);
m11 = cap.readFloat("m11", 1);
}
/**
- <code>scale</code> scales the operation performed by this matrix on a
- per-component basis.
*
-
@param scale
-
The scale applied to the X and Y output values.<br />
*/
public void scale(Vector2f scale) {
m00 *= scale.x;
m10 *= scale.x;
m01 *= scale.y;
m11 *= scale.y;
}
static boolean equalIdentity(Matrix2f mat) {
if (Math.abs(mat.m00 - 1) > 1e-4) {
return false;
}
if (Math.abs(mat.m11 - 1) > 1e-4) {
return false;
}
if (Math.abs(mat.m01) > 1e-4) {
return false;
}
if (Math.abs(mat.m10) > 1e-4) {
return false;
}
return true;
}
@Override
public Matrix2f clone() {
try {
return (Matrix2f) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // can not happen
}
}
}
[/java]