/* *EERT = EERT enhanced rendering technology * *Copyright (C) [2008] [Robert "BuRnEr" Schadek] *This program is free software; you can redistribute it and/or modify it under *the terms of the GNU General Public License as published by the Free Software *Foundation; either version 3 of the License, *or (at your option) any later version. *This program is distributed in the hope that it will be useful, but WITHOUT *ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. *You should have received a copy of the GNU General Public License along with *this program; if not, see <http://www.gnu.org/licenses/>. */ package Util.Geometrie; import Types.Geometrie.Vector4; import Types.Geometrie.Face; import Types.Geometrie.TexCoor; import Types.Geometrie.Vector; public class VectorUtil { public static float dotProduct(Vector v1, Vector v2) { return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); } public static float angleVec(Vector v1, Vector v2) { return (float) Math.acos((v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z)); } public static float angle(Face f1, Vector v1) { /* * acos(dotProduct(faceNormal, dirPointToFaceMiddle) * -------------------------------------------- * lenght(faceNormal) * length(dir)) */ //make middle of triangle float xF = (f1.v1.x / 3) + (f1.v2.x / 3) + (f1.v3.x / 3); float yF = (f1.v1.y / 3) + (f1.v2.y / 3) + (f1.v3.y / 3); float zF = (f1.v1.z / 3) + (f1.v2.z / 3) + (f1.v3.z / 3); //make vector from v1 to faceMiddle Vector dir = new Vector(xF - v1.x, yF - v1.y, zF - v1.z); float x = (float) Math.sqrt((f1.faceNormal.x * f1.faceNormal.x) + (f1.faceNormal.y * f1.faceNormal.y) + (f1.faceNormal.z * f1.faceNormal.z)); float dot = (xF * dir.x) + (yF * dir.y) + (zF * dir.z); float y = (float) Math.sqrt((dir.x * dir.x) + (dir.y * dir.y) + (dir.z * dir.z)); return (float) Math.acos(dot / (x * y)); } public static Vector sub(Vector v1, Vector v2) { return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); } public static Vector mult(Vector v, float scalar) { return new Vector(v.x * scalar, v.y * scalar, v.z * scalar); } public static Vector add(Vector v1, Vector v2) { return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } public static Vector add(Vector v1, Vector v2, Vector v3) { return new Vector(v1.x + v2.x + v3.x, v1.y + v2.y + v3.y, v1.z + v2.z + v3.z); } public static Vector crossProduct(Vector vector1, Vector vector2) { return new Vector( vector1.y * vector2.z - vector1.z * vector2.y, vector1.z * vector2.x - vector1.x * vector2.z, vector1.x * vector2.y - vector1.y * vector2.x); } public static Vector abs(Vector vec) { return new Vector(Math.abs(vec.x), Math.abs(vec.y), Math.abs(vec.z)); } public static Vector threePlaneIntersec(Vector n1, float d1, Vector n2, float d2, Vector n3, float d3) { /* d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) P = ------------------------------------------------------------------------- N1 . ( N2 * N3 ) */ n1.normalize(); n2.normalize(); n3.normalize(); Vector n2n3C = crossProduct(n2, n3); Vector n3n1C = crossProduct(n3, n1); Vector n1n2C = crossProduct(n1, n2); Vector copyN2N3C = new Vector(n2n3C); n2n3C.mult(d1); n3n1C.mult(d2); n1n2C.mult(d3); Vector divisor = add(n2n3C, n3n1C); divisor.add(n1n2C); float divident = dotProduct(n1, copyN2N3C); divisor.div(divident); return divisor; } public static float distance(Vector x, Vector y) { return (float) Math.sqrt(Math.pow((x.x - y.x), 2) + Math.pow((x.y - y.y), 2) + Math.pow((x.z - y.z), 2)); } public static float determinant4f(float m[]) { return m[12] * m[9] * m[6] * m[3] - m[8] * m[13] * m[6] * m[3] - m[12] * m[5] * m[10] * m[3] + m[4] * m[13] * m[10] * m[3] + m[8] * m[5] * m[14] * m[3] - m[4] * m[9] * m[14] * m[3] - m[12] * m[9] * m[2] * m[7] + m[8] * m[13] * m[2] * m[7] + m[12] * m[1] * m[10] * m[7] - m[0] * m[13] * m[10] * m[7] - m[8] * m[1] * m[14] * m[7] + m[0] * m[9] * m[14] * m[7] + m[12] * m[5] * m[2] * m[11] - m[4] * m[13] * m[2] * m[11] - m[12] * m[1] * m[6] * m[11] + m[0] * m[13] * m[6] * m[11] + m[4] * m[1] * m[14] * m[11] - m[0] * m[5] * m[14] * m[11] - m[8] * m[5] * m[2] * m[15] + m[4] * m[9] * m[2] * m[15] + m[8] * m[1] * m[6] * m[15] - m[0] * m[9] * m[6] * m[15] - m[4] * m[1] * m[10] * m[15] + m[0] * m[5] * m[10] * m[15]; } public static float[] invertFFMatrix(float[] m) { float x = determinant4f(m); float[] i = new float[16]; i[0] = (-m[13] * m[10] * m[7] + m[9] * m[14] * m[7] + m[13] * m[6] * m[11] - m[5] * m[14] * m[11] - m[9] * m[6] * m[15] + m[5] * m[10] * m[15]) / x; i[4] = (m[12] * m[10] * m[7] - m[8] * m[14] * m[7] - m[12] * m[6] * m[11] + m[4] * m[14] * m[11] + m[8] * m[6] * m[15] - m[4] * m[10] * m[15]) / x; i[8] = (-m[12] * m[9] * m[7] + m[8] * m[13] * m[7] + m[12] * m[5] * m[11] - m[4] * m[13] * m[11] - m[8] * m[5] * m[15] + m[4] * m[9] * m[15]) / x; i[12] = (m[12] * m[9] * m[6] - m[8] * m[13] * m[6] - m[12] * m[5] * m[10] + m[4] * m[13] * m[10] + m[8] * m[5] * m[14] - m[4] * m[9] * m[14]) / x; i[1] = (m[13] * m[10] * m[3] - m[9] * m[14] * m[3] - m[13] * m[2] * m[11] + m[1] * m[14] * m[11] + m[9] * m[2] * m[15] - m[1] * m[10] * m[15]) / x; i[5] = (-m[12] * m[10] * m[3] + m[8] * m[14] * m[3] + m[12] * m[2] * m[11] - m[0] * m[14] * m[11] - m[8] * m[2] * m[15] + m[0] * m[10] * m[15]) / x; i[9] = (m[12] * m[9] * m[3] - m[8] * m[13] * m[3] - m[12] * m[1] * m[11] + m[0] * m[13] * m[11] + m[8] * m[1] * m[15] - m[0] * m[9] * m[15]) / x; i[13] = (-m[12] * m[9] * m[2] + m[8] * m[13] * m[2] + m[12] * m[1] * m[10] - m[0] * m[13] * m[10] - m[8] * m[1] * m[14] + m[0] * m[9] * m[14]) / x; i[2] = (-m[13] * m[6] * m[3] + m[5] * m[14] * m[3] + m[13] * m[2] * m[7] - m[1] * m[14] * m[7] - m[5] * m[2] * m[15] + m[1] * m[6] * m[15]) / x; i[6] = (m[12] * m[6] * m[3] - m[4] * m[14] * m[3] - m[12] * m[2] * m[7] + m[0] * m[14] * m[7] + m[4] * m[2] * m[15] - m[0] * m[6] * m[15]) / x; i[10] = (-m[12] * m[5] * m[3] + m[4] * m[13] * m[3] + m[12] * m[1] * m[7] - m[0] * m[13] * m[7] - m[4] * m[1] * m[15] + m[0] * m[5] * m[15]) / x; i[14] = (m[12] * m[5] * m[2] - m[4] * m[13] * m[2] - m[12] * m[1] * m[6] + m[0] * m[13] * m[6] + m[4] * m[1] * m[14] - m[0] * m[5] * m[14]) / x; i[3] = (m[9] * m[6] * m[3] - m[5] * m[10] * m[3] - m[9] * m[2] * m[7] + m[1] * m[10] * m[7] + m[5] * m[2] * m[11] - m[1] * m[6] * m[11]) / x; i[7] = (-m[8] * m[6] * m[3] + m[4] * m[10] * m[3] + m[8] * m[2] * m[7] - m[0] * m[10] * m[7] - m[4] * m[2] * m[11] + m[0] * m[6] * m[11]) / x; i[11] = (m[8] * m[5] * m[3] - m[4] * m[9] * m[3] - m[8] * m[1] * m[7] + m[0] * m[9] * m[7] + m[4] * m[1] * m[11] - m[0] * m[5] * m[11]) / x; i[15] = (-m[8] * m[5] * m[2] + m[4] * m[9] * m[2] + m[8] * m[1] * m[6] - m[0] * m[9] * m[6] - m[4] * m[1] * m[10] + m[0] * m[5] * m[10]) / x; return i; } public static Vector4 vecMultMatrix(Vector4 in, float[] mIn) { Vector4 ret = new Vector4(); ret.x = in.x * mIn[0] + in.x * mIn[1] + in.x * mIn[2] + in.x * mIn[3]; ret.y = in.y * mIn[4] + in.y * mIn[5] + in.y * mIn[6] + in.y * mIn[7]; ret.z = in.z * mIn[8] + in.z * mIn[9] + in.z * mIn[10] + in.z * mIn[11]; ret.w = in.w * mIn[12] + in.w * mIn[13] + in.w * mIn[14] + in.w * mIn[15]; return ret; } public static float[] invertModelView(float[] in) { float[] tmp = new float[16]; //Rotation tmp[1] = in[4]; tmp[2] = in[8]; tmp[4] = in[1]; tmp[6] = in[9]; tmp[8] = in[2]; tmp[9] = in[6]; //Translation tmp[12] = -tmp[12]; tmp[13] = -tmp[14]; tmp[14] = -tmp[15]; return tmp; } public static Vector multWithGLMatrix(float[] m, Vector in) { Vector tmp = new Vector(); tmp.x = m[0] * in.x + m[1] * in.x + m[2] * in.x; tmp.y = m[4] * in.y + m[5] * in.y + m[6] * in.y; tmp.z = m[8] * in.x + m[9] * in.x + m[10] * in.x; tmp.x += m[12]; tmp.y += m[13]; tmp.z += m[14]; return tmp; } public static Vector[] calcTBN(Face foo) { Vector v2v1 = VectorUtil.sub(foo.v2, foo.v1); Vector v3v1 = VectorUtil.sub(foo.v3, foo.v1); TexCoor uv21 = TexCoorUtil.sub(foo.vt2, foo.vt1); TexCoor uv31 = TexCoorUtil.sub(foo.vt3, foo.vt1); Vector[] ret = new Vector[3]; //tangent ret[0] = VectorUtil.sub(VectorUtil.mult(v2v1, uv31.t), VectorUtil.mult(v3v1, uv21.t)); ret[0].normalize(); //binormal ret[1] = VectorUtil.sub(VectorUtil.mult(v3v1, uv21.s), VectorUtil.mult(v2v1, uv31.s)); ret[1].normalize(); //normal ret[2] = VectorUtil.crossProduct(ret[0], ret[1]); ret[2].normalize(); //Gram-Schmidt orthogonalization ret[0].sub(VectorUtil.mult(ret[2], VectorUtil.dotProduct(ret[2], ret[0]))); ret[0].normalize(); //check if right handed TBN boolean right = VectorUtil.dotProduct(VectorUtil.crossProduct(ret[0], ret[1]), ret[2]) >= 0; ret[1] = VectorUtil.crossProduct(ret[2], ret[0]); if (!right) { ret[1].mult(-1); } return ret; } }