/** * Copyright (c) 2013, Mattias Andrée * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package v; /** * Orthonormalised vector maths */ public class VMaths { public static final float[][] UNIT = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; public static float[] createRotation(String side) { return createRotation(side, UNIT); } public static float[] createRotation(String side, float[][] proj) { switch (side.toLowerCase()) { case "x": case "xz": case "zx": return mul(-1, proj[1]); case "y": case "yz": case "zy": return mul(-1, proj[0]); case "xy": case "yx": return proj[2]; } return null; } public static float[][] createRotation(String side, float thetaDegrees) { switch (side.toLowerCase()) { case "x": case "xz": case "zx": return createRotation( 0f, -1f, 0f, thetaDegrees); case "y": case "yz": case "zy": return createRotation(-1f, 0f, 0f, thetaDegrees); case "xy": case "yx": return createRotation( 0f, 0f, +1f, thetaDegrees); } return null; } public static float[][] createRotation(float x, float y, float z, float thetaDegrees) { float theta = thetaDegrees * (float)(Math.PI) / 180f; float[][] m = new float[3][3]; float cos = (float)(Math.cos(theta)); float sin = (float)(Math.sin(theta)); float _cos = 1f - cos; m[0][0] = x * x * _cos + cos; m[1][0] = x * y * _cos + z * sin; m[2][0] = x * z * _cos - y * sin; m[0][1] = y * x * _cos - z * sin; m[1][1] = y * y * _cos + cos; m[2][1] = y * z * _cos + x * sin; m[0][2] = z * x * _cos + y * sin; m[1][2] = z * y * _cos - x * sin; m[2][2] = z * z * _cos + cos; return m; } public static float[][] createRotation(float[] v, float thetaDegrees) { return createRotation(v[0], v[1], v[2], thetaDegrees); } public static float[] mul(float[][] m, float[] v) { int n, k = v.length; float[] rc = new float[n = m.length]; for (int r = 0; r < n; r++) for (int i = 0; i < k; i++) rc[r] += m[r][i] * v[i]; return rc; } public static float[] mul(float[][] m, float x, float y, float z) { int n; float[] rc = new float[n = m.length]; for (int i = 0; i < n; i++) rc[i] = m[i][0] * x + m[i][1] * y + m[i][2] * z; return rc; } public static float[][] mul(float[][] a, float[][] b) { int n, m, k = b.length; float[][] rc = new float[n = a.length][m = b[0].length]; for (int r = 0; r < n; r++) for (int c = 0; c < m; c++) for (int i = 0; i < k; i++) rc[r][c] += a[i][r] * b[c][i]; return rc; } public static float[][] mul(float a, float[][] b) { int n, m; float[][] rc = new float[n = b.length][m = b[0].length]; for (int r = 0; r < n; r++) for (int c = 0; c < m; c++) rc[r][c] = a * b[r][c]; return rc; } public static float[] mul(float a, float[] b) { int n; float[] rc = new float[n = b.length]; for (int r = 0; r < n; r++) rc[r] = a * b[r]; return rc; } public static float[][] add(float[][] a, float[][] b) { int n, m; float[][] rc = new float[n = a.length][m = b[0].length]; for (int r = 0; r < n; r++) for (int c = 0; c < m; c++) rc[r][c] = a[r][c] + b[r][c]; return rc; } public static float[] add(float[] a, float[] b) { int n; float[] rc = new float[n = a.length]; for (int r = 0; r < n; r++) rc[r] = a[r] + b[r]; return rc; } public static float length(float[] v) { int n = v.length; float length = 0; for (int r = 0; r < n; r++) length += v[r] * v[r]; length = (float)Math.sqrt(length); return length; } public static float[] normalise(float[] v) { int n; float[] rc = new float[n = v.length]; float length = length(v); if (length * length == 0f) { for (int r = 0; r < n; r++) rc[r] = 0; rc[0] = 1; } else for (int r = 0; r < n; r++) rc[r] = v[r] / length; return rc; } public static float[][] on_inv(float[][] m) { return trans(m); } public static float[][] inv(float[][] m) { return mul(1f / det(m), trans(m)); } public static float[][] trans(float[][] m) { int x, y; float[][] rc = new float[y = m[0].length][x = m.length]; for (int r = 0; r < y; r++) for (int c = 0; c < x; c++) rc[r][c] = m[c][r]; return rc; } public static float det(float[][] m) { float rc = 0; int mul = 1; int n = m.length; if (n == 0) return 1; if (n == 1) return m[0][0]; for (int i = 0; i < n; i++) { float[][] sub = new float[n - 1][n - 1]; for (int y = 0; y < n - 1; y++) for (int x = 0; x < n - 1; x++) sub[y][x] = m[y + 1][x < i ? x : x + 1]; rc += mul * det(sub); mul *= -1; } return rc; } }