package android.opengl.OpenGLES10;
import android.util.Log;
import java.util.Arrays;
public class OpenGLESMath
{
public static Matrix4x4f scale(Matrix4x4f result, float sx, float sy, float sz)
{
result.m[0] *= sx;
result.m[1] *= sx;
result.m[2] *= sx;
result.m[3] *= sx;
result.m[4] *= sy;
result.m[5] *= sy;
result.m[6] *= sy;
result.m[7] *= sy;
result.m[8] *= sz;
result.m[9] *= sz;
result.m[10] *= sz;
result.m[11] *= sz;
return result;
}
public static Matrix4x4f translate(Matrix4x4f result, float tx, float ty, float tz)
{
result.m[12] += (result.m[0] * tx + result.m[4] * ty + result.m[8] * tz);
result.m[13] += (result.m[1] * tx + result.m[5] * ty + result.m[9] * tz);
result.m[14] += (result.m[2] * tx + result.m[6] * ty + result.m[10] * tz);
result.m[15] += (result.m[3] * tx + result.m[7] * ty + result.m[11] * tz);
return result;
}
public static Matrix4x4f rotate(Matrix4x4f result, float angle, float x, float y, float z)
{
float sinAngle = (float) Math.sin(angle * Math.PI / 180.0f);
float cosAngle = (float) Math.cos(angle * Math.PI / 180.0f);
float oneMinusCos = 1.0f - cosAngle;
float mag = (float) Math.sqrt(x * x + y * y + z * z);
if (mag != 0.0f && mag != 1.0f)
{
x /= mag;
y /= mag;
z /= mag;
}
float xx = x * x;
float yy = y * y;
float zz = z * z;
float xy = x * y;
float yz = y * z;
float zx = z * x;
float xs = x * sinAngle;
float ys = y * sinAngle;
float zs = z * sinAngle;
Matrix4x4f rotationMatrix = new Matrix4x4f();
rotationMatrix.m[0] = (oneMinusCos * xx) + cosAngle;
rotationMatrix.m[1] = (oneMinusCos * xy) - zs;
rotationMatrix.m[2] = (oneMinusCos * zx) + ys;
rotationMatrix.m[3] = 0.0f;
rotationMatrix.m[4] = (oneMinusCos * xy) + zs;
rotationMatrix.m[5] = (oneMinusCos * yy) + cosAngle;
rotationMatrix.m[6] = (oneMinusCos * yz) - xs;
rotationMatrix.m[7] = 0.0f;
rotationMatrix.m[8] = (oneMinusCos * zx) - ys;
rotationMatrix.m[9] = (oneMinusCos * yz) + xs;
rotationMatrix.m[10] = (oneMinusCos * zz) + cosAngle;
rotationMatrix.m[11] = 0.0f;
rotationMatrix.m[12] = 0.0f;
rotationMatrix.m[13] = 0.0f;
rotationMatrix.m[14] = 0.0f;
rotationMatrix.m[15] = 1.0f;
result = multiply(rotationMatrix, result);
return result;
}
public static Matrix4x4f frustum(Matrix4x4f result, float left, float right, float bottom, float top, float nearZ, float farZ)
{
float deltaX = right - left;
float deltaY = top - bottom;
float deltaZ = farZ - nearZ;
Matrix4x4f frust = new Matrix4x4f();
if ((nearZ <= 0.0f) || (farZ <= 0.0f) || (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f))
{
Log.e("OpenGLESMath", "Invalid frustrum");
return null;
}
frust.m[0] = 2.0f * nearZ / deltaX;
frust.m[1] = frust.m[2] = frust.m[3] = 0.0f;
frust.m[5] = 2.0f * nearZ / deltaY;
frust.m[4] = frust.m[6] = frust.m[7] = 0.0f;
frust.m[8] = (right + left) / deltaX;
frust.m[9] = (top + bottom) / deltaY;
frust.m[10] = -(nearZ + farZ) / deltaZ;
frust.m[11] = -1.0f;
frust.m[14] = -2.0f * nearZ * farZ / deltaZ;
frust.m[12] = frust.m[13] = frust.m[15] = 0.0f;
result = multiply(frust, result);
return result;
}
public static Matrix4x4f perspective(Matrix4x4f result, float fovy, float aspect, float nearZ, float farZ)
{
float frustumHeight = (float) (Math.tan(fovy / 360 * Math.PI) * nearZ);
float frustumWidth = frustumHeight * aspect;
result = frustum(result, -frustumWidth, frustumWidth, -frustumHeight, frustumHeight, nearZ, farZ);
return result;
}
public static Matrix4x4f ortho(Matrix4x4f result, float left, float right, float bottom, float top, float nearZ, float farZ)
{
float deltaX = right - left;
float deltaY = top - bottom;
float deltaZ = farZ - nearZ;
Matrix4x4f ortho = new Matrix4x4f();
if ((deltaX == 0) || (deltaY == 0) || (deltaZ == 0))
{
Log.e("OpenGLESMath", "Invalid ortho");
return null;
}
ortho = loadIdentity(ortho);
ortho.m[0] = 2 / deltaX;
ortho.m[12] = -(right + left) / deltaX;
ortho.m[5] = 2 / deltaY;
ortho.m[13] = -(top + bottom) / deltaY;
ortho.m[10] = -2 / deltaZ;
ortho.m[14] = -(nearZ + farZ) / deltaZ;
result = multiply(ortho, result);
return result;
}
public static Matrix4x4f multiply(Matrix4x4f srcA, final Matrix4x4f srcB)
{
Matrix4x4f tmp = new Matrix4x4f();
for (int i = 0; i < 4; i++)
{
int a = 4 * i;
int b = a + 1;
int c = a + 2;
int d = a + 3;
tmp.m[a] = srcA.m[a] * srcB.m[0] + srcA.m[b] * srcB.m[4] + srcA.m[c] * srcB.m[8] + srcA.m[d] * srcB.m[12];
tmp.m[b] = srcA.m[a] * srcB.m[1] + srcA.m[b] * srcB.m[5] + srcA.m[c] * srcB.m[9] + srcA.m[d] * srcB.m[13];
tmp.m[c] = srcA.m[a] * srcB.m[2] + srcA.m[b] * srcB.m[6] + srcA.m[c] * srcB.m[10] + srcA.m[d] * srcB.m[14];
tmp.m[d] = srcA.m[a] * srcB.m[3] + srcA.m[b] * srcB.m[7] + srcA.m[c] * srcB.m[11] + srcA.m[d] * srcB.m[15];
}
return tmp;
}
public static Matrix4x4f multiply(Matrix4x4f srcA, float[] srcB)
{
Matrix4x4f result = new Matrix4x4f();
for (int i = 0; i < 4; i++)
{
int a = 4 * i;
int b = a + 1;
int c = a + 2;
int d = a + 3;
result.m[a] = srcA.m[a] * srcB[0] + srcA.m[b] * srcB[4] + srcA.m[c] * srcB[8] + srcA.m[d] * srcB[12];
result.m[b] = srcA.m[a] * srcB[1] + srcA.m[b] * srcB[5] + srcA.m[c] * srcB[9] + srcA.m[d] * srcB[13];
result.m[c] = srcA.m[a] * srcB[2] + srcA.m[b] * srcB[6] + srcA.m[c] * srcB[10] + srcA.m[d] * srcB[14];
result.m[d] = srcA.m[a] * srcB[3] + srcA.m[b] * srcB[7] + srcA.m[c] * srcB[11] + srcA.m[d] * srcB[15];
}
return result;
}
public static Matrix3x3f multiply(Matrix3x3f srcA, Matrix3x3f srcB)
{
Matrix3x3f result = new Matrix3x3f();
for (int i = 0; i < 3; i++)
{
int a = 3 * i;
int b = a + 1;
int c = a + 2;
result.m[a] = srcA.m[a] * srcB.m[0] + srcA.m[b] * srcB.m[3] + srcA.m[c] * srcB.m[6];
result.m[b] = srcA.m[a] * srcB.m[1] + srcA.m[b] * srcB.m[4] + srcA.m[c] * srcB.m[7];
result.m[c] = srcA.m[a] * srcB.m[2] + srcA.m[b] * srcB.m[5] + srcA.m[c] * srcB.m[8];
}
return result;
}
public static Vector3f multiply(Matrix3x3f srcA, Vector3f srcB)
{
Vector3f tmp = new Vector3f();
for (int i = 0; i < 3; i++)
{
tmp.v[i] = srcA.m[i] * srcB.v[0] + srcA.m[i + 3] * srcB.v[1] + srcA.m[i + 6] * srcB.v[2];
}
return tmp;
}
public static Vector4f multiply(Matrix4x4f srcA, Vector4f srcB)
{
Vector4f tmp = new Vector4f();
for (int i = 0; i < 4; i++)
{
tmp.v[i] = srcA.m[i] * srcB.v[0] + srcA.m[i + 4] * srcB.v[1] + srcA.m[i + 8] * srcB.v[2] + srcA.m[i + 12] * srcB.v[3];
}
return tmp;
}
public static Matrix3x3f loadIdentity(Matrix3x3f src)
{
Matrix3x3f result = new Matrix3x3f();
result.m[0] = 1;
result.m[4] = 1;
result.m[8] = 1;
return result;
}
public static Matrix4x4f loadIdentity(Matrix4x4f src)
{
Matrix4x4f result = new Matrix4x4f();
result.m[0] = 1;
result.m[5] = 1;
result.m[10] = 1;
result.m[15] = 1;
return result;
}
public static Matrix3x3f transpose(Matrix3x3f result)
{
Matrix3x3f tmp = new Matrix3x3f();
tmp.m[0] = result.m[0];
tmp.m[1] = result.m[3];
tmp.m[2] = result.m[6];
tmp.m[3] = result.m[1];
tmp.m[4] = result.m[4];
tmp.m[5] = result.m[7];
tmp.m[6] = result.m[2];
tmp.m[7] = result.m[5];
tmp.m[8] = result.m[8];
return tmp;
}
public static Matrix4x4f transpose(Matrix4x4f result)
{
Matrix4x4f tmp = new Matrix4x4f();
tmp.m[0] = result.m[0];
tmp.m[1] = result.m[4];
tmp.m[2] = result.m[8];
tmp.m[3] = result.m[12];
tmp.m[4] = result.m[1];
tmp.m[5] = result.m[5];
tmp.m[6] = result.m[9];
tmp.m[7] = result.m[13];
tmp.m[8] = result.m[2];
tmp.m[9] = result.m[6];
tmp.m[10] = result.m[10];
tmp.m[11] = result.m[14];
tmp.m[12] = result.m[3];
tmp.m[13] = result.m[7];
tmp.m[14] = result.m[11];
tmp.m[15] = result.m[15];
return tmp;
}
public static Matrix3x3f adjoint(Matrix3x3f src)
{
Matrix3x3f result = new Matrix3x3f();
float a1 = src.m[0];
float a2 = src.m[3];
float a3 = src.m[6];
float b1 = src.m[1];
float b2 = src.m[4];
float b3 = src.m[7];
float c1 = src.m[2];
float c2 = src.m[5];
float c3 = src.m[8];
result.m[0] = (b2 * c3 - b3 * c2);
result.m[3] = (a3 * c2 - a2 * c3);
result.m[6] = (a2 * b3 - a3 * b2);
result.m[1] = (b3 * c1 - b1 * c3);
result.m[4] = (a1 * c3 - a3 * c1);
result.m[7] = (a3 * b1 - a1 * b3);
result.m[2] = (b1 * c2 - b2 * c1);
result.m[5] = (a2 * c1 - a1 * c2);
result.m[8] = (a1 * b2 - a2 * b1);
return result;
}
public static Matrix3x3f inverse(Matrix3x3f src)
{
Matrix3x3f result = new Matrix3x3f();
float a1 = src.m[0];
float a2 = src.m[3];
float a3 = src.m[6];
float b1 = src.m[1];
float b2 = src.m[4];
float b3 = src.m[7];
float c1 = src.m[2];
float c2 = src.m[5];
float c3 = src.m[8];
float det = (a1 * (b2 * c3 - b3 * c2) + a2 * (b3 * c1 - b1 * c3) + a3 * (b1 * c2 - b2 * c1));
result.m[0] = (b2 * c3 - b3 * c2) / det;
result.m[3] = (a3 * c2 - a2 * c3) / det;
result.m[6] = (a2 * b3 - a3 * b2) / det;
result.m[1] = (b3 * c1 - b1 * c3) / det;
result.m[4] = (a1 * c3 - a3 * c1) / det;
result.m[7] = (a3 * b1 - a1 * b3) / det;
result.m[2] = (b1 * c2 - b2 * c1) / det;
result.m[5] = (a2 * c1 - a1 * c2) / det;
result.m[8] = (a1 * b2 - a2 * b1) / det;
return result;
}
public static Matrix4x4f inverse(Matrix4x4f src)
{
int swap;
float t = 0;
float[][] temp = new float[4][4];
Matrix4x4f result = new Matrix4x4f();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
temp[i][j] = src.getItem(i, j);
}
}
result = loadIdentity(result);
for (int i = 0; i < 4; i++)
{
swap = i;
for (int j = i + 1; j < 4; j++)
{
if (Math.abs(temp[j][i]) > Math.abs(temp[i][i]))
{
swap = j;
}
}
if (swap != i)
{
for (int k = 0; k < 4; k++)
{
t = temp[i][k];
temp[i][k] = temp[swap][k];
temp[swap][k] = t;
t = result.getItem(i, k);
result.setItem(i, k, result.getItem(swap, k));
result.setItem(swap, k, t);
}
}
if (temp[i][i] == 0)
{
Log.d("OpenGLESMath", "ERROR: Matrix is singular, cannot invert.");
return null;
}
t = temp[i][i];
for (int k = 0; k < 4; k++)
{
temp[i][k] /= t;
result.setItem(i, k, result.getItem(i, k)/t);
}
for (int j = 0; j < 4; j++)
{
if (j != i)
{
t = temp[j][i];
for (int k = 0; k < 4; k++)
{
temp[j][k] -= temp[i][k] * t;
float tmp = result.getItem(j, k) - result.getItem(i, k) * t;
result.setItem(j, k, tmp);
}
}
}
}
return result;
}
public static Matrix3x3f copyMatrix4x4UpperLeftToMatrix3x3(Matrix4x4f mat)
{
Matrix3x3f result = new Matrix3x3f();
result.m[0] = mat.m[0];
result.m[1] = mat.m[1];
result.m[2] = mat.m[2];
result.m[3] = mat.m[4];
result.m[4] = mat.m[5];
result.m[5] = mat.m[6];
result.m[6] = mat.m[8];
result.m[7] = mat.m[9];
result.m[8] = mat.m[10];
return result;
}
public static boolean isUnitVector(Vector4f vec)
{
double length = Math.sqrt(vec.v[0] * vec.v[0] + vec.v[1] * vec.v[1] + vec.v[2] * vec.v[2] + vec.v[3] * vec.v[3]);
float epsilon = 0.01f;
return 1.0f - epsilon <= length && length <= 1.0f + epsilon;
}
public static float clamp(float t, float minV, float maxV)
{
return Math.max(Math.min(maxV, t), minV);
}
}