/** * Copyright 2008 - 2015 The Loon Game Engine Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a cpy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.5 */ package loon.geom; import java.io.Serializable; import java.nio.FloatBuffer; import java.util.Collection; import loon.LSystem; import loon.utils.MathUtils; import loon.utils.NumberUtils; public class Matrix3 implements Serializable, XY { /** * */ private static final long serialVersionUID = 3501619461925966551L; public final static Matrix3 TMP() { return new Matrix3(); } public final static Matrix3 ZERO() { return new Matrix3(); } public static final int M00 = 0; public static final int M01 = 3; public static final int M02 = 6; public static final int M10 = 1; public static final int M11 = 4; public static final int M12 = 7; public static final int M20 = 2; public static final int M21 = 5; public static final int M22 = 8; public float[] val = new float[9]; private float[] tmp = new float[9]; public Matrix3() { idt(); } public Matrix3(Matrix3 matrix) { set(matrix); } public Matrix3(float[] values) { this.set(values); } public Matrix3(float mat[], int offset) { this.val = new float[9]; for (int i = 0; i < 9; i++) { this.val[i] = mat[i + offset]; } } public Matrix3(Matrix3 t1, Matrix3 t2) { this(t1); concatenate(t2); } public Matrix3 set(Affine2f affine) { float[] val = this.val; val[M00] = affine.m00; val[M10] = affine.m10; val[M20] = 0; val[M01] = affine.m01; val[M11] = affine.m11; val[M21] = 0; val[M02] = affine.tx; val[M12] = affine.ty; val[M22] = 1; return this; } public Matrix3 idt() { val[M00] = 1; val[M10] = 0; val[M20] = 0; val[M01] = 0; val[M11] = 1; val[M21] = 0; val[M02] = 0; val[M12] = 0; val[M22] = 1; return this; } public Matrix3 mul(Matrix3 m) { float v00 = val[M00] * m.val[M00] + val[M01] * m.val[M10] + val[M02] * m.val[M20]; float v01 = val[M00] * m.val[M01] + val[M01] * m.val[M11] + val[M02] * m.val[M21]; float v02 = val[M00] * m.val[M02] + val[M01] * m.val[M12] + val[M02] * m.val[M22]; float v10 = val[M10] * m.val[M00] + val[M11] * m.val[M10] + val[M12] * m.val[M20]; float v11 = val[M10] * m.val[M01] + val[M11] * m.val[M11] + val[M12] * m.val[M21]; float v12 = val[M10] * m.val[M02] + val[M11] * m.val[M12] + val[M12] * m.val[M22]; float v20 = val[M20] * m.val[M00] + val[M21] * m.val[M10] + val[M22] * m.val[M20]; float v21 = val[M20] * m.val[M01] + val[M21] * m.val[M11] + val[M22] * m.val[M21]; float v22 = val[M20] * m.val[M02] + val[M21] * m.val[M12] + val[M22] * m.val[M22]; val[M00] = v00; val[M10] = v10; val[M20] = v20; val[M01] = v01; val[M11] = v11; val[M21] = v21; val[M02] = v02; val[M12] = v12; val[M22] = v22; return this; } public Matrix3 mulLeft(Matrix3 m) { float v00 = m.val[M00] * val[M00] + m.val[M01] * val[M10] + m.val[M02] * val[M20]; float v01 = m.val[M00] * val[M01] + m.val[M01] * val[M11] + m.val[M02] * val[M21]; float v02 = m.val[M00] * val[M02] + m.val[M01] * val[M12] + m.val[M02] * val[M22]; float v10 = m.val[M10] * val[M00] + m.val[M11] * val[M10] + m.val[M12] * val[M20]; float v11 = m.val[M10] * val[M01] + m.val[M11] * val[M11] + m.val[M12] * val[M21]; float v12 = m.val[M10] * val[M02] + m.val[M11] * val[M12] + m.val[M12] * val[M22]; float v20 = m.val[M20] * val[M00] + m.val[M21] * val[M10] + m.val[M22] * val[M20]; float v21 = m.val[M20] * val[M01] + m.val[M21] * val[M11] + m.val[M22] * val[M21]; float v22 = m.val[M20] * val[M02] + m.val[M21] * val[M12] + m.val[M22] * val[M22]; val[M00] = v00; val[M10] = v10; val[M20] = v20; val[M01] = v01; val[M11] = v11; val[M21] = v21; val[M02] = v02; val[M12] = v12; val[M22] = v22; return this; } public Matrix3 setToRotation(float degrees) { return setToRotationRad(MathUtils.DEG_TO_RAD * degrees); } public Matrix3 setToRotationRad(float radians) { float cos = MathUtils.cos(radians); float sin = MathUtils.sin(radians); this.val[M00] = cos; this.val[M10] = sin; this.val[M20] = 0; this.val[M01] = -sin; this.val[M11] = cos; this.val[M21] = 0; this.val[M02] = 0; this.val[M12] = 0; this.val[M22] = 1; return this; } public Matrix3 setToRotation(Vector3f axis, float degrees) { return setToRotation(axis, MathUtils.cosDeg(degrees), MathUtils.sinDeg(degrees)); } public Matrix3 setToRotation(Vector3f axis, float cos, float sin) { float oc = 1.0f - cos; val[M00] = oc * axis.x * axis.x + cos; val[M10] = oc * axis.x * axis.y - axis.z * sin; val[M20] = oc * axis.z * axis.x + axis.y * sin; val[M01] = oc * axis.x * axis.y + axis.z * sin; val[M11] = oc * axis.y * axis.y + cos; val[M21] = oc * axis.y * axis.z - axis.x * sin; val[M02] = oc * axis.z * axis.x - axis.y * sin; val[M12] = oc * axis.y * axis.z + axis.x * sin; val[M22] = oc * axis.z * axis.z + cos; return this; } public Matrix3 setToTranslation(float x, float y) { this.val[M00] = 1; this.val[M10] = 0; this.val[M20] = 0; this.val[M01] = 0; this.val[M11] = 1; this.val[M21] = 0; this.val[M02] = x; this.val[M12] = y; this.val[M22] = 1; return this; } public Matrix3 setToTranslation(Vector2f translation) { this.val[M00] = 1; this.val[M10] = 0; this.val[M20] = 0; this.val[M01] = 0; this.val[M11] = 1; this.val[M21] = 0; this.val[M02] = translation.x; this.val[M12] = translation.y; this.val[M22] = 1; return this; } public Matrix3 setToScaling(float scaleX, float scaleY) { val[M00] = scaleX; val[M10] = 0; val[M20] = 0; val[M01] = 0; val[M11] = scaleY; val[M21] = 0; val[M02] = 0; val[M12] = 0; val[M22] = 1; return this; } public Matrix3 setToScaling(Vector2f scale) { val[M00] = scale.x; val[M10] = 0; val[M20] = 0; val[M01] = 0; val[M11] = scale.y; val[M21] = 0; val[M02] = 0; val[M12] = 0; val[M22] = 1; return this; } public String toString() { return "[" + val[0] + "|" + val[3] + "|" + val[6] + "]\n" + "[" + val[1] + "|" + val[4] + "|" + val[7] + "]\n" + "[" + val[2] + "|" + val[5] + "|" + val[8] + "]"; } public float det() { return val[M00] * val[M11] * val[M22] + val[M01] * val[M12] * val[M20] + val[M02] * val[M10] * val[M21] - val[M00] * val[M12] * val[M21] - val[M01] * val[M10] * val[M22] - val[M02] * val[M11] * val[M20]; } public Matrix3 inv() { float det = det(); if (det == 0) { throw LSystem.runThrow("Can't invert a singular matrix"); } float inv_det = 1.0f / det; tmp[M00] = val[M11] * val[M22] - val[M21] * val[M12]; tmp[M10] = val[M20] * val[M12] - val[M10] * val[M22]; tmp[M20] = val[M10] * val[M21] - val[M20] * val[M11]; tmp[M01] = val[M21] * val[M02] - val[M01] * val[M22]; tmp[M11] = val[M00] * val[M22] - val[M20] * val[M02]; tmp[M21] = val[M20] * val[M01] - val[M00] * val[M21]; tmp[M02] = val[M01] * val[M12] - val[M11] * val[M02]; tmp[M12] = val[M10] * val[M02] - val[M00] * val[M12]; tmp[M22] = val[M00] * val[M11] - val[M10] * val[M01]; val[M00] = inv_det * tmp[M00]; val[M10] = inv_det * tmp[M10]; val[M20] = inv_det * tmp[M20]; val[M01] = inv_det * tmp[M01]; val[M11] = inv_det * tmp[M11]; val[M21] = inv_det * tmp[M21]; val[M02] = inv_det * tmp[M02]; val[M12] = inv_det * tmp[M12]; val[M22] = inv_det * tmp[M22]; return this; } public Matrix3 set(Matrix3 mat) { System.arraycopy(mat.val, 0, val, 0, val.length); return this; } public Matrix3 set(Matrix4 mat) { val[M00] = mat.val[Matrix4.M00]; val[M10] = mat.val[Matrix4.M10]; val[M20] = mat.val[Matrix4.M20]; val[M01] = mat.val[Matrix4.M01]; val[M11] = mat.val[Matrix4.M11]; val[M21] = mat.val[Matrix4.M21]; val[M02] = mat.val[Matrix4.M02]; val[M12] = mat.val[Matrix4.M12]; val[M22] = mat.val[Matrix4.M22]; return this; } public Matrix3 set(float[] values) { System.arraycopy(values, 0, val, 0, val.length); return this; } public Matrix3 set(int x, int y, float v) { val[y + x * 3] = v; return this; } public float get(int x, int y) { return val[y + x * 3]; } public Matrix3 izero() { val[M00] = 0; val[M01] = 0; val[M02] = 0; val[M10] = 0; val[M11] = 0; val[M12] = 0; val[M20] = 0; val[M21] = 0; val[M22] = 0; return this; } public Matrix3 trn(Vector2f vector) { val[M02] += vector.x; val[M12] += vector.y; return this; } public Matrix3 trn(float x, float y) { val[M02] += x; val[M12] += y; return this; } public Matrix3 trn(Vector3f vector) { val[M02] += vector.x; val[M12] += vector.y; return this; } public Matrix3 translate(float x, float y) { tmp[M00] = 1; tmp[M10] = 0; tmp[M20] = 0; tmp[M01] = 0; tmp[M11] = 1; tmp[M21] = 0; tmp[M02] = x; tmp[M12] = y; tmp[M22] = 1; mul(val, tmp); return this; } public Matrix3 translate(Vector2f translation) { tmp[M00] = 1; tmp[M10] = 0; tmp[M20] = 0; tmp[M01] = 0; tmp[M11] = 1; tmp[M21] = 0; tmp[M02] = translation.x; tmp[M12] = translation.y; tmp[M22] = 1; mul(val, tmp); return this; } public Matrix3 rotate(float degrees) { return rotateRad(MathUtils.DEG_TO_RAD * degrees); } public Matrix3 rotateRad(float radians) { if (radians == 0) { return this; } float cos = MathUtils.cos(radians); float sin = MathUtils.sin(radians); tmp[M00] = cos; tmp[M10] = sin; tmp[M20] = 0; tmp[M01] = -sin; tmp[M11] = cos; tmp[M21] = 0; tmp[M02] = 0; tmp[M12] = 0; tmp[M22] = 1; mul(val, tmp); return this; } public Matrix3 scale(float scaleX, float scaleY) { tmp[M00] = scaleX; tmp[M10] = 0; tmp[M20] = 0; tmp[M01] = 0; tmp[M11] = scaleY; tmp[M21] = 0; tmp[M02] = 0; tmp[M12] = 0; tmp[M22] = 1; mul(val, tmp); return this; } public Matrix3 scale(Vector2f scale) { tmp[M00] = scale.x; tmp[M10] = 0; tmp[M20] = 0; tmp[M01] = 0; tmp[M11] = scale.y; tmp[M21] = 0; tmp[M02] = 0; tmp[M12] = 0; tmp[M22] = 1; mul(val, tmp); return this; } public float[] getValues() { return val; } public Vector2f getTranslation(Vector2f position) { position.x = val[M02]; position.y = val[M12]; return position; } public Vector2f getScale(Vector2f scale) { scale.x = MathUtils.sqrt(val[M00] * val[M00] + val[M01] * val[M01]); scale.y = MathUtils.sqrt(val[M10] * val[M10] + val[M11] * val[M11]); return scale; } public float getRotation() { return MathUtils.DEG_TO_RAD * MathUtils.atan2(val[M10], val[M00]); } public float getRotationRad() { return MathUtils.atan2(val[M10], val[M00]); } public Matrix3 scl(float scale) { val[M00] *= scale; val[M11] *= scale; return this; } public Matrix3 scl(Vector2f scale) { val[M00] *= scale.x; val[M11] *= scale.y; return this; } public Matrix3 scl(Vector3f scale) { val[M00] *= scale.x; val[M11] *= scale.y; return this; } public Matrix3 transpose() { float v01 = val[M10]; float v02 = val[M20]; float v10 = val[M01]; float v12 = val[M21]; float v20 = val[M02]; float v21 = val[M12]; val[M01] = v01; val[M02] = v02; val[M10] = v10; val[M12] = v12; val[M20] = v20; val[M21] = v21; return this; } private static void mul(float[] mata, float[] matb) { float v00 = mata[M00] * matb[M00] + mata[M01] * matb[M10] + mata[M02] * matb[M20]; float v01 = mata[M00] * matb[M01] + mata[M01] * matb[M11] + mata[M02] * matb[M21]; float v02 = mata[M00] * matb[M02] + mata[M01] * matb[M12] + mata[M02] * matb[M22]; float v10 = mata[M10] * matb[M00] + mata[M11] * matb[M10] + mata[M12] * matb[M20]; float v11 = mata[M10] * matb[M01] + mata[M11] * matb[M11] + mata[M12] * matb[M21]; float v12 = mata[M10] * matb[M02] + mata[M11] * matb[M12] + mata[M12] * matb[M22]; float v20 = mata[M20] * matb[M00] + mata[M21] * matb[M10] + mata[M22] * matb[M20]; float v21 = mata[M20] * matb[M01] + mata[M21] * matb[M11] + mata[M22] * matb[M21]; float v22 = mata[M20] * matb[M02] + mata[M21] * matb[M12] + mata[M22] * matb[M22]; mata[M00] = v00; mata[M10] = v10; mata[M20] = v20; mata[M01] = v01; mata[M11] = v11; mata[M21] = v21; mata[M02] = v02; mata[M12] = v12; mata[M22] = v22; } public FloatBuffer getAsFloatBuffer() { return LSystem.base().support().newFloatBuffer(val, 0, val.length); } public void set(float x1, float y1, float x2, float y2) { set(x1, y1, 1, x2, y2, 1); } public Matrix3(float a1, float a2, float a3, float b1, float b2, float b3) { set(a1, a2, a3, b1, b2, b3); } public void set(float a1, float a2, float a3, float b1, float b2, float b3) { set(a1, a2, a3, b1, b2, b3, 0, 0, 1); } public void set(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3) { this.val = new float[] { a1, a2, a3, b1, b2, b3, c1, c2, c3 }; } public void transform(float[] source, int sourceOffset, float[] destination, int destOffset, int numberOfPoints) { float result[] = source == destination ? new float[numberOfPoints * 2] : destination; for (int i = 0; i < numberOfPoints * 2; i += 2) { for (int j = 0; j < 6; j += 3) { result[i + (j / 3)] = source[i + sourceOffset] * this.val[j] + source[i + sourceOffset + 1] * this.val[j + 1] + 1 * this.val[j + 2]; } } if (source == destination) { for (int i = 0; i < numberOfPoints * 2; i += 2) { destination[i + destOffset] = result[i]; destination[i + destOffset + 1] = result[i + 1]; } } } public Matrix3 concatenate(Matrix3 m) { float[] mp = new float[9]; float n00 = this.val[0] * m.val[0] + this.val[1] * m.val[3]; float n01 = this.val[0] * m.val[1] + this.val[1] * m.val[4]; float n02 = this.val[0] * m.val[2] + this.val[1] * m.val[5] + this.val[2]; float n10 = this.val[3] * m.val[0] + this.val[4] * m.val[3]; float n11 = this.val[3] * m.val[1] + this.val[4] * m.val[4]; float n12 = this.val[3] * m.val[2] + this.val[4] * m.val[5] + this.val[5]; mp[0] = n00; mp[1] = n01; mp[2] = n02; mp[3] = n10; mp[4] = n11; mp[5] = n12; this.val = mp; return this; } public static Matrix3 createRotateTransform(float angle) { return new Matrix3(MathUtils.cos(angle), -MathUtils.sin(angle), 0, MathUtils.sin(angle), MathUtils.cos(angle), 0); } public static Matrix3 createRotateTransform(float angle, float x, float y) { Matrix3 temp = Matrix3.createRotateTransform(angle); float sinAngle = temp.val[3]; float oneMinusCosAngle = 1.0f - temp.val[4]; temp.val[2] = x * oneMinusCosAngle + y * sinAngle; temp.val[5] = y * oneMinusCosAngle - x * sinAngle; return temp; } public static Matrix3 createTranslateTransform(float xOffset, float yOffset) { return new Matrix3(1, 0, xOffset, 0, 1, yOffset); } public static Matrix3 createScaleTransform(float scalex, float scaley) { return new Matrix3(scalex, 0, 0, 0, scaley, 0); } public float get(int i) { return this.val[i]; } public Matrix3 from(float[] source, boolean rowMajor) { Matrix3 m = new Matrix3(); if (rowMajor) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { m.set(i, j, source[i * 3 + j]); } } } else { for (int j = 0; j < 3; j++) { for (int i = 0; i < 3; i++) { m.set(i, j, source[j * 3 + i]); } } } return this; } public float getTranslationX() { return this.val[6]; } public float getTranslationY() { return this.val[7]; } public void translation(float x, float y) { this.val[0] = 1; this.val[1] = 0; this.val[2] = 0; this.val[3] = 0; this.val[4] = 1; this.val[5] = 0; this.val[6] = x; this.val[7] = y; this.val[8] = 1; } public void rotation(float angle) { angle = MathUtils.DEG_TO_RAD * angle; float cos = MathUtils.cos(angle); float sin = MathUtils.sin(angle); this.val[0] = cos; this.val[1] = sin; this.val[2] = 0; this.val[3] = -sin; this.val[4] = cos; this.val[5] = 0; this.val[6] = 0; this.val[7] = 0; this.val[8] = 1; } private float[] result = new float[16]; public float[] get() { result[0] = this.val[0]; result[1] = this.val[1]; result[2] = this.val[2]; result[3] = 0; result[4] = this.val[3]; result[5] = this.val[4]; result[6] = this.val[5]; result[7] = 0; result[8] = 0; result[9] = 0; result[10] = 1; result[11] = 0; result[12] = this.val[6]; result[13] = this.val[7]; result[14] = 0; result[15] = this.val[8]; return result; } public void rotationX(float angleX) { angleX = MathUtils.PI / 180 * angleX; set(1f, 0f, 0f, 0f, MathUtils.cos(angleX), -MathUtils.sin(angleX), 0f, MathUtils.sin(angleX), MathUtils.cos(angleX)); } public void rotationY(float angleY) { angleY = MathUtils.PI / 180 * angleY; set(MathUtils.cos(angleY), 0f, MathUtils.sin(angleY), 0f, 1f, 0f, -MathUtils.sin(angleY), 0f, MathUtils.cos(angleY)); } public void rotationZ(float angleZ) { angleZ = MathUtils.PI / 180 * angleZ; set(MathUtils.cos(angleZ), -MathUtils.sin(angleZ), 0f, MathUtils.sin(angleZ), MathUtils.cos(angleZ), 0f, 0f, 0f, 1f); } public boolean isIdt() { return (this.val[0] == 1 && this.val[1] == 0 && this.val[2] == 0) && (this.val[3] == 0 && this.val[4] == 1 && this.val[5] == 0) && (this.val[6] == 0 && this.val[7] == 0 && this.val[8] == 1); } private final static float detd(float a, float b, float c, float d) { return (a * d) - (b * c); } public void adj() { float a11 = this.val[0]; float a12 = this.val[1]; float a13 = this.val[2]; float a21 = this.val[3]; float a22 = this.val[4]; float a23 = this.val[5]; float a31 = this.val[6]; float a32 = this.val[7]; float a33 = this.val[8]; this.val[0] = detd(a22, a23, a32, a33); this.val[1] = detd(a13, a12, a33, a32); this.val[2] = detd(a12, a13, a22, a23); this.val[3] = detd(a23, a21, a33, a31); this.val[4] = detd(a11, a13, a31, a33); this.val[5] = detd(a13, a11, a23, a21); this.val[6] = detd(a21, a22, a31, a32); this.val[7] = detd(a12, a11, a32, a31); this.val[8] = detd(a11, a12, a21, a22); } public void add(Matrix3 m) { float a1 = this.val[0]; float a2 = this.val[1]; float a3 = this.val[2]; float b1 = this.val[3]; float b2 = this.val[4]; float b3 = this.val[5]; float c1 = this.val[6]; float c2 = this.val[7]; float c3 = this.val[8]; a1 += m.val[0]; a2 += m.val[1]; a3 += m.val[2]; b1 += m.val[3]; b2 += m.val[4]; b3 += m.val[5]; c1 += m.val[6]; c2 += m.val[7]; c3 += m.val[8]; this.val[0] = a1; this.val[1] = a2; this.val[2] = a3; this.val[3] = b1; this.val[4] = b2; this.val[5] = b3; this.val[6] = c1; this.val[7] = c2; this.val[8] = c3; } public Matrix3 addEqual(Matrix3 m) { Matrix3 newMatrix = new Matrix3(this.val); newMatrix.add(m); return newMatrix; } public void mul(float c) { float a1 = this.val[0]; float a2 = this.val[1]; float a3 = this.val[2]; float b1 = this.val[3]; float b2 = this.val[4]; float b3 = this.val[5]; float c1 = this.val[6]; float c2 = this.val[7]; float c3 = this.val[8]; this.val[0] = a1 * c; this.val[1] = a2 * c; this.val[2] = a3 * c; this.val[3] = b1 * c; this.val[4] = b2 * c; this.val[5] = b3 * c; this.val[6] = c1 * c; this.val[7] = c2 * c; this.val[8] = c3 * c; } public Matrix3 mulEqual(Matrix3 m) { if (m == null) { m = new Matrix3(); } Matrix3 result = new Matrix3(this.val); result.mul(m); return result; } public Matrix3 invert(Matrix3 m) { Matrix3 result = m; if (result == null) { result = new Matrix3(); } final float det = det(); if (MathUtils.abs(det) <= MathUtils.EPSILON) { throw new ArithmeticException("This matrix cannot be inverted !"); } final float temp00 = this.val[4] * this.val[8] - this.val[5] * this.val[7]; final float temp01 = this.val[2] * this.val[7] - this.val[1] * this.val[8]; final float temp02 = this.val[1] * this.val[5] - this.val[2] * this.val[4]; final float temp10 = this.val[5] * this.val[6] - this.val[3] * this.val[8]; final float temp11 = this.val[0] * this.val[8] - this.val[2] * this.val[6]; final float temp12 = this.val[2] * this.val[3] - this.val[0] * this.val[5]; final float temp20 = this.val[3] * this.val[7] - this.val[4] * this.val[6]; final float temp21 = this.val[1] * this.val[6] - this.val[0] * this.val[7]; final float temp22 = this.val[0] * this.val[4] - this.val[1] * this.val[3]; result.set(temp00, temp01, temp02, temp10, temp11, temp12, temp20, temp21, temp22); result.mul(1.0f / det); return result; } public boolean isFloatValid() { boolean valid = true; valid &= !Float.isNaN(this.val[0]); valid &= !Float.isNaN(this.val[1]); valid &= !Float.isNaN(this.val[2]); valid &= !Float.isNaN(this.val[3]); valid &= !Float.isNaN(this.val[4]); valid &= !Float.isNaN(this.val[5]); valid &= !Float.isNaN(this.val[6]); valid &= !Float.isNaN(this.val[7]); valid &= !Float.isNaN(this.val[8]); return valid; } public final static Matrix3 avg(Collection<Matrix3> set) { Matrix3 average = new Matrix3(); average.set(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f); float hist = 0; for (Matrix3 matrix3d : set) { if (matrix3d.isFloatValid()) { average.add(matrix3d); hist++; } } average.mul(1f / hist); return average; } public void cpy(Matrix3 m) { if (m == null) { idt(); } else { set(m); } } public Vector2f transform(Vector2f pt) { float[] in = new float[] { pt.x, pt.y }; float[] out = new float[2]; transform(in, 0, out, 0, 1); return new Vector2f(out[0], out[1]); } public Matrix3 cpy() { return new Matrix3(this.val); } public void set(int i, float value) { this.val[i] = value; } public static void add(Matrix3 result, Matrix3 m1, Matrix3 m2) { for (int i = 0; i < 9; i++) { result.set(i, m1.get(i) + m2.get(i)); } } public static void sub(Matrix3 result, Matrix3 m1, Matrix3 m2) { for (int i = 0; i < 9; i++) { result.set(i, m1.get(i) - m2.get(i)); } } public static void mul(Matrix3 result, Matrix3 m1, Matrix3 m2) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { result.set(i, j, m1.get(i, 0) * m2.get(0, j) + m1.get(i, 1) * m2.get(1, j) + m1.get(i, 2) * m2.get(2, j)); } } } public static void mul(float result[], Matrix3 m, float v[]) { float a, b, c; a = m.get(0, 0) * v[0] + m.get(1, 0) * v[1] + m.get(2, 0) * v[2]; b = m.get(0, 1) * v[0] + m.get(1, 1) * v[1] + m.get(2, 1) * v[2]; c = m.get(0, 2) * v[0] + m.get(1, 2) * v[1] + m.get(2, 2) * v[2]; result[0] = a; result[1] = b; result[2] = c; } public static Matrix3 getRotationMatrixExact(float ax, float ay, float az) { float cosax = MathUtils.cos(MathUtils.toRadians(ax)); float sinax = MathUtils.sin(MathUtils.toRadians(ax)); float cosay = MathUtils.cos(MathUtils.toRadians(ay)); float sinay = MathUtils.sin(MathUtils.toRadians(ay)); float cosaz = MathUtils.cos(MathUtils.toRadians(az)); float sinaz = MathUtils.sin(MathUtils.toRadians(az)); float tx[] = { 1, 0, 0, 0, cosax, -sinax, 0, sinax, cosax }; float ty[] = { cosay, 0, sinay, 0, 1.f, 0.f, -sinay, 0, cosay }; float tz[] = { cosaz, -sinaz, 0, sinaz, cosaz, 0, 0, 0, 1 }; Matrix3 Rx = new Matrix3(tx); Matrix3 Ry = new Matrix3(ty); Matrix3 Rz = new Matrix3(tz); Matrix3 result = new Matrix3(); Matrix3 tmpresult = new Matrix3(); Matrix3.mul(tmpresult, Rx, Ry); Matrix3.mul(result, tmpresult, Rz); return result; } public static float distance2d(float x1, float y1, float x2, float y2) { return distance(x1, y1, 0.f, x2, y2, 0.f); } public static float distance(float x1, float y1, float z1, float x2, float y2, float z2) { return MathUtils.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1)); } public static boolean isOnTriange(float x1, float y1, float x2, float y2, float x3, float y3, float x, float y) { float a; float b; boolean s; boolean s2; if (x2 - x1 != 0.f) { a = (y2 - y1) / (x2 - x1); b = y1 - a * x1; if (a * x3 + b > y3) { s = true; } else { s = false; } if (a * x + b > y) { s2 = true; } else { s2 = false; } if ((s != s2) && (a * x + b != y)) { return false; } } else { if (x1 > x3) { s = true; } else { s = false; } if (x1 > x) { s2 = true; } else { s2 = false; } if ((s != s2) && (x1 != x)) { return false; } } if (x3 - x2 != 0.f) { a = (y3 - y2) / (x3 - x2); b = y2 - a * x2; if (a * x1 + b > y1) { s = true; } else { s = false; } if (a * x + b > y) { s2 = true; } else { s2 = false; } if ((s != s2) && (a * x + b != y)) { return false; } } else { if (x2 > x1) { s = true; } else { s = false; } if (x2 > x) { s2 = true; } else { s2 = false; } if ((s != s2) && (x1 != x)) { return false; } } if (x1 - x3 != 0.f) { a = (y1 - y3) / (x1 - x3); b = y3 - a * x3; if (a * x2 + b > y2) { s = true; } else { s = false; } if (a * x + b > y) { s2 = true; } else { s2 = false; } if ((s != s2) && (a * x + b != y)) { return false; } } else { if (x1 > x2) { s = true; } else { s = false; } if (x1 > x) { s2 = true; } else { s2 = false; } if ((s != s2) && (x1 != x)) { return false; } } return true; } public static float[] convert33to44(float m33[], int offset) { float m44[] = new float[16]; m44[0] = m33[0 + offset]; m44[1] = m33[1 + offset]; m44[2] = m33[2 + offset]; m44[4] = m33[3 + offset]; m44[5] = m33[4 + offset]; m44[6] = m33[5 + offset]; m44[8] = m33[6 + offset]; m44[9] = m33[7 + offset]; m44[10] = m33[8 + offset]; m44[15] = 1.0f; return m44; } public static void setRotateEulerM(float[] rm, int rmOffset, float x, float y, float z) { x = x * 0.01745329f; y = y * 0.01745329f; z = z * 0.01745329f; float sx = MathUtils.sin(x); float sy = MathUtils.sin(y); float sz = MathUtils.sin(z); float cx = MathUtils.cos(x); float cy = MathUtils.cos(y); float cz = MathUtils.cos(z); float cxsy = cx * sy; float sxsy = sx * sy; rm[rmOffset + 0] = cy * cz; rm[rmOffset + 1] = -cy * sz; rm[rmOffset + 2] = sy; rm[rmOffset + 3] = 0.0f; rm[rmOffset + 4] = sxsy * cz + cx * sz; rm[rmOffset + 5] = -sxsy * sz + cx * cz; rm[rmOffset + 6] = -sx * cy; rm[rmOffset + 7] = 0.0f; rm[rmOffset + 8] = -cxsy * cz + sx * sz; rm[rmOffset + 9] = cxsy * sz + sx * cz; rm[rmOffset + 10] = cx * cy; rm[rmOffset + 11] = 0.0f; rm[rmOffset + 12] = 0.0f; rm[rmOffset + 13] = 0.0f; rm[rmOffset + 14] = 0.0f; rm[rmOffset + 15] = 1.0f; } @Override public boolean equals(Object o) { if (!(o instanceof Matrix3) || o == null) { return false; } if (this == o) { return true; } Matrix3 comp = (Matrix3) o; for (int i = 0; i < 9; i++) { if (NumberUtils.compare(this.val[i], comp.val[i]) != 0) { return false; } } return true; } @Override public float getX() { return tmp[M02]; } @Override public float getY() { return tmp[M12]; } @Override public int hashCode() { int result = 17; for (int j = 0; j < 9; j++) { final long val = NumberUtils.floatToIntBits(this.val[j]); result += 31 * result + (int) (val ^ (val >>> 32)); } return result; } }