/* | |
* Copyright (C) 2015 The Android Open Source Project | |
* | |
* 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 copy 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. | |
*/ | |
package com.example.android.rs.vr.engine; | |
import android.util.Log; | |
import java.text.*; | |
import java.util.*; | |
/** | |
* Generic matrix code | |
* Written for maximum portability between desktop and Android | |
* Not in performance critical sections | |
*/ | |
public class Matrix { | |
private static final String LOGTAG = "Matrix"; | |
public double[] m; | |
public void makeRotation() { | |
{ | |
double[] v = {m[0], m[4], m[8]}; | |
VectorUtil.normalize(v); | |
m[0] = v[0]; | |
m[4] = v[1]; | |
m[8] = v[2]; | |
} | |
{ | |
double[] v = {m[1], m[5], m[9]}; | |
VectorUtil.normalize(v); | |
m[1] = v[0]; | |
m[5] = v[1]; | |
m[9] = v[2]; | |
} | |
{ | |
double[] v = {m[2], m[6], m[10]}; | |
VectorUtil.normalize(v); | |
m[2] = v[0]; | |
m[6] = v[1]; | |
m[10] = v[2]; | |
} | |
} | |
private static String trim(String s) { | |
return s.substring(s.length() - 7); | |
} | |
public void print() { | |
DecimalFormat df = new DecimalFormat(" ##0.000"); | |
for (int i = 0; i < 4; i++) { | |
String s=""; | |
for (int j = 0; j < 4; j++) { | |
s+= ((j == 0) ? "[ " : " , ") + trim(" "+df.format(m[i * 4 + j])); | |
} | |
Log.v(LOGTAG, s+"]"); | |
} | |
} | |
public Matrix() { | |
m = new double[4 * 4]; | |
setToUnit(); | |
} | |
public Matrix(Matrix matrix) { | |
this(Arrays.copyOf(matrix.m, matrix.m.length)); | |
} | |
protected Matrix(double[] m) { | |
this.m = m; | |
} | |
public void setToUnit() { | |
for (int i = 1; i < m.length; i++) { | |
m[i] = 0; | |
} | |
m[0] = 1; | |
m[5] = 1; | |
m[10] = 1; | |
m[15] = 1; | |
} | |
public void mult4(float[] src, float[] dest) { | |
for (int i = 0; i < 4; i++) { | |
int col = i * 4; | |
double sum = 0; | |
for (int j = 0; j < 4; j++) { | |
sum += m[col + j] * src[j]; | |
} | |
dest[i] = (float) sum; | |
} | |
} | |
public void mult3(float[] src, float[] dest) { | |
for (int i = 0; i < 3; i++) { | |
int col = i * 4; | |
double sum = m[col + 3]; | |
for (int j = 0; j < 3; j++) { | |
sum += m[col + j] * src[j]; | |
} | |
dest[i] = (float) sum; | |
} | |
} | |
public void mult3v(float[] src, float[] dest) { | |
for (int i = 0; i < 3; i++) { | |
int col = i * 4; | |
double sum = 0; | |
for (int j = 0; j < 3; j++) { | |
sum += m[col + j] * src[j]; | |
} | |
dest[i] = (float) sum; | |
} | |
} | |
public void mult4(double[] src, double[] dest) { | |
for (int i = 0; i < 4; i++) { | |
int col = i * 4; | |
double sum = 0; | |
for (int j = 0; j < 4; j++) { | |
sum += m[col + j] * src[j]; | |
} | |
dest[i] = (float) sum; | |
} | |
} | |
public void mult3(double[] src, double[] dest) { | |
for (int i = 0; i < 3; i++) { | |
int col = i * 4; | |
double sum = m[col + 3]; | |
for (int j = 0; j < 3; j++) { | |
sum += m[col + j] * src[j]; | |
} | |
dest[i] = (float) sum; | |
} | |
} | |
public void mult3v(double[] src, double[] dest) { | |
for (int i = 0; i < 3; i++) { | |
int col = i * 4; | |
double sum = 0; | |
for (int j = 0; j < 3; j++) { | |
sum += m[col + j] * src[j]; | |
} | |
dest[i] = (float) sum; | |
} | |
} | |
public double[] vecmult(double[] src) { | |
double[] ret = new double[3]; | |
mult3v(src, ret); | |
return ret; | |
} | |
public void mult3(float[] src, int off1, float[] dest, int off2) { | |
int col = 0 * 4; | |
double sum = m[col + 3]; | |
for (int j = 0; j < 3; j++) { | |
sum += m[col + j] * src[j + off1]; | |
} | |
float v0 = (float) sum; | |
col = 1 * 4; | |
sum = m[col + 3]; | |
for (int j = 0; j < 3; j++) { | |
sum += m[col + j] * src[j + off1]; | |
} | |
float v1 = (float) sum; | |
col = 2 * 4; | |
sum = m[col + 3]; | |
for (int j = 0; j < 3; j++) { | |
sum += m[col + j] * src[j + off1]; | |
} | |
float v2 = (float) sum; | |
dest[off2] = v0; | |
dest[1 + off2] = v1; | |
dest[2 + off2] = v2; | |
} | |
public Matrix invers() { | |
double[] inv = new double[16]; | |
inv[0] = m[5] * m[10] * m[15] - | |
m[5] * m[11] * m[14] - | |
m[9] * m[6] * m[15] + | |
m[9] * m[7] * m[14] + | |
m[13] * m[6] * m[11] - | |
m[13] * m[7] * m[10]; | |
inv[4] = -m[4] * m[10] * m[15] + | |
m[4] * m[11] * m[14] + | |
m[8] * m[6] * m[15] - | |
m[8] * m[7] * m[14] - | |
m[12] * m[6] * m[11] + | |
m[12] * m[7] * m[10]; | |
inv[8] = m[4] * m[9] * m[15] - | |
m[4] * m[11] * m[13] - | |
m[8] * m[5] * m[15] + | |
m[8] * m[7] * m[13] + | |
m[12] * m[5] * m[11] - | |
m[12] * m[7] * m[9]; | |
inv[12] = -m[4] * m[9] * m[14] + | |
m[4] * m[10] * m[13] + | |
m[8] * m[5] * m[14] - | |
m[8] * m[6] * m[13] - | |
m[12] * m[5] * m[10] + | |
m[12] * m[6] * m[9]; | |
inv[1] = -m[1] * m[10] * m[15] + | |
m[1] * m[11] * m[14] + | |
m[9] * m[2] * m[15] - | |
m[9] * m[3] * m[14] - | |
m[13] * m[2] * m[11] + | |
m[13] * m[3] * m[10]; | |
inv[5] = m[0] * m[10] * m[15] - | |
m[0] * m[11] * m[14] - | |
m[8] * m[2] * m[15] + | |
m[8] * m[3] * m[14] + | |
m[12] * m[2] * m[11] - | |
m[12] * m[3] * m[10]; | |
inv[9] = -m[0] * m[9] * m[15] + | |
m[0] * m[11] * m[13] + | |
m[8] * m[1] * m[15] - | |
m[8] * m[3] * m[13] - | |
m[12] * m[1] * m[11] + | |
m[12] * m[3] * m[9]; | |
inv[13] = m[0] * m[9] * m[14] - | |
m[0] * m[10] * m[13] - | |
m[8] * m[1] * m[14] + | |
m[8] * m[2] * m[13] + | |
m[12] * m[1] * m[10] - | |
m[12] * m[2] * m[9]; | |
inv[2] = m[1] * m[6] * m[15] - | |
m[1] * m[7] * m[14] - | |
m[5] * m[2] * m[15] + | |
m[5] * m[3] * m[14] + | |
m[13] * m[2] * m[7] - | |
m[13] * m[3] * m[6]; | |
inv[6] = -m[0] * m[6] * m[15] + | |
m[0] * m[7] * m[14] + | |
m[4] * m[2] * m[15] - | |
m[4] * m[3] * m[14] - | |
m[12] * m[2] * m[7] + | |
m[12] * m[3] * m[6]; | |
inv[10] = m[0] * m[5] * m[15] - | |
m[0] * m[7] * m[13] - | |
m[4] * m[1] * m[15] + | |
m[4] * m[3] * m[13] + | |
m[12] * m[1] * m[7] - | |
m[12] * m[3] * m[5]; | |
inv[14] = -m[0] * m[5] * m[14] + | |
m[0] * m[6] * m[13] + | |
m[4] * m[1] * m[14] - | |
m[4] * m[2] * m[13] - | |
m[12] * m[1] * m[6] + | |
m[12] * m[2] * m[5]; | |
inv[3] = -m[1] * m[6] * m[11] + | |
m[1] * m[7] * m[10] + | |
m[5] * m[2] * m[11] - | |
m[5] * m[3] * m[10] - | |
m[9] * m[2] * m[7] + | |
m[9] * m[3] * m[6]; | |
inv[7] = m[0] * m[6] * m[11] - | |
m[0] * m[7] * m[10] - | |
m[4] * m[2] * m[11] + | |
m[4] * m[3] * m[10] + | |
m[8] * m[2] * m[7] - | |
m[8] * m[3] * m[6]; | |
inv[11] = -m[0] * m[5] * m[11] + | |
m[0] * m[7] * m[9] + | |
m[4] * m[1] * m[11] - | |
m[4] * m[3] * m[9] - | |
m[8] * m[1] * m[7] + | |
m[8] * m[3] * m[5]; | |
inv[15] = m[0] * m[5] * m[10] - | |
m[0] * m[6] * m[9] - | |
m[4] * m[1] * m[10] + | |
m[4] * m[2] * m[9] + | |
m[8] * m[1] * m[6] - | |
m[8] * m[2] * m[5]; | |
double det; | |
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]; | |
if (det == 0) { | |
return null; | |
} | |
det = 1.0 / det; | |
double[] out = new double[16]; | |
for (int i = 0; i < 16; i++) { | |
out[i] = inv[i] * det; | |
} | |
Matrix ret = new Matrix(out); | |
return ret; | |
} | |
public void getAsFloats(float[] fm) { | |
for (int y = 0; y < 4; y++) { | |
int col = y * 4; | |
for (int x = 0; x < 4; x++) | |
fm[y + x * 4] = (float) m[x + y * 4]; | |
} | |
} | |
Matrix mult(Matrix b) { | |
return new Matrix(multiply(this.m, b.m)); | |
} | |
Matrix premult(Matrix b) { | |
return new Matrix(multiply(b.m, this.m)); | |
} | |
private static double[] multiply(double a[], double b[]) { | |
double[] resultant = new double[16]; | |
for (int i = 0; i < 4; i++) { | |
for (int j = 0; j < 4; j++) { | |
for (int k = 0; k < 4; k++) { | |
resultant[i + 4 * j] += a[i + 4 * k] * b[k + 4 * j]; | |
} | |
} | |
} | |
return resultant; | |
} | |
public void clone(Matrix src) { | |
System.arraycopy(src.m, 0, m, 0, m.length); | |
} | |
} |