1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.example.android.rs.vr.engine;
17
18import android.util.Log;
19
20import java.text.*;
21import java.util.*;
22
23/**
24 * Generic matrix code
25 * Written for maximum portability between desktop and Android
26 * Not in performance critical sections
27 */
28public class Matrix {
29
30    private static final String LOGTAG = "Matrix";
31    public double[] m;
32
33    public void makeRotation() {
34        {
35            double[] v = {m[0], m[4], m[8]};
36            VectorUtil.normalize(v);
37            m[0] = v[0];
38            m[4] = v[1];
39            m[8] = v[2];
40        }
41        {
42            double[] v = {m[1], m[5], m[9]};
43            VectorUtil.normalize(v);
44            m[1] = v[0];
45            m[5] = v[1];
46            m[9] = v[2];
47        }
48        {
49            double[] v = {m[2], m[6], m[10]};
50            VectorUtil.normalize(v);
51            m[2] = v[0];
52            m[6] = v[1];
53            m[10] = v[2];
54        }
55
56    }
57
58    private static String trim(String s) {
59        return s.substring(s.length() - 7);
60    }
61
62    public void print() {
63        DecimalFormat df = new DecimalFormat("      ##0.000");
64        for (int i = 0; i < 4; i++) {
65            String s="";
66            for (int j = 0; j < 4; j++) {
67               s+= ((j == 0) ? "[ " : " , ") + trim("       "+df.format(m[i * 4 + j]));
68            }
69            Log.v(LOGTAG, s+"]");
70        }
71    }
72
73    public Matrix() {
74        m = new double[4 * 4];
75        setToUnit();
76    }
77
78    public Matrix(Matrix matrix) {
79        this(Arrays.copyOf(matrix.m, matrix.m.length));
80    }
81
82    protected Matrix(double[] m) {
83        this.m = m;
84    }
85
86    public void setToUnit() {
87        for (int i = 1; i < m.length; i++) {
88            m[i] = 0;
89        }
90        m[0] = 1;
91        m[5] = 1;
92        m[10] = 1;
93        m[15] = 1;
94    }
95
96    public void mult4(float[] src, float[] dest) {
97        for (int i = 0; i < 4; i++) {
98            int col = i * 4;
99            double sum = 0;
100            for (int j = 0; j < 4; j++) {
101                sum += m[col + j] * src[j];
102            }
103            dest[i] = (float) sum;
104        }
105    }
106
107    public void mult3(float[] src, float[] dest) {
108        for (int i = 0; i < 3; i++) {
109            int col = i * 4;
110            double sum = m[col + 3];
111            for (int j = 0; j < 3; j++) {
112                sum += m[col + j] * src[j];
113            }
114            dest[i] = (float) sum;
115        }
116    }
117
118    public void mult3v(float[] src, float[] dest) {
119        for (int i = 0; i < 3; i++) {
120            int col = i * 4;
121            double sum = 0;
122            for (int j = 0; j < 3; j++) {
123                sum += m[col + j] * src[j];
124            }
125            dest[i] = (float) sum;
126        }
127    }
128
129    public void mult4(double[] src, double[] dest) {
130        for (int i = 0; i < 4; i++) {
131            int col = i * 4;
132            double sum = 0;
133            for (int j = 0; j < 4; j++) {
134                sum += m[col + j] * src[j];
135            }
136            dest[i] = (float) sum;
137        }
138    }
139
140    public void mult3(double[] src, double[] dest) {
141        for (int i = 0; i < 3; i++) {
142            int col = i * 4;
143            double sum = m[col + 3];
144            for (int j = 0; j < 3; j++) {
145                sum += m[col + j] * src[j];
146            }
147            dest[i] = (float) sum;
148        }
149    }
150
151    public void mult3v(double[] src, double[] dest) {
152        for (int i = 0; i < 3; i++) {
153            int col = i * 4;
154            double sum = 0;
155            for (int j = 0; j < 3; j++) {
156                sum += m[col + j] * src[j];
157            }
158            dest[i] = (float) sum;
159        }
160    }
161
162    public double[] vecmult(double[] src) {
163        double[] ret = new double[3];
164        mult3v(src, ret);
165        return ret;
166    }
167
168    public void mult3(float[] src, int off1, float[] dest, int off2) {
169
170        int col = 0 * 4;
171        double sum = m[col + 3];
172        for (int j = 0; j < 3; j++) {
173            sum += m[col + j] * src[j + off1];
174        }
175        float v0 = (float) sum;
176
177
178        col = 1 * 4;
179        sum = m[col + 3];
180        for (int j = 0; j < 3; j++) {
181            sum += m[col + j] * src[j + off1];
182        }
183
184        float v1 = (float) sum;
185
186
187        col = 2 * 4;
188        sum = m[col + 3];
189        for (int j = 0; j < 3; j++) {
190            sum += m[col + j] * src[j + off1];
191        }
192        float v2 = (float) sum;
193
194        dest[off2] = v0;
195        dest[1 + off2] = v1;
196        dest[2 + off2] = v2;
197
198    }
199
200    public Matrix invers() {
201        double[] inv = new double[16];
202
203        inv[0] = m[5] * m[10] * m[15] -
204                m[5] * m[11] * m[14] -
205                m[9] * m[6] * m[15] +
206                m[9] * m[7] * m[14] +
207                m[13] * m[6] * m[11] -
208                m[13] * m[7] * m[10];
209
210        inv[4] = -m[4] * m[10] * m[15] +
211                m[4] * m[11] * m[14] +
212                m[8] * m[6] * m[15] -
213                m[8] * m[7] * m[14] -
214                m[12] * m[6] * m[11] +
215                m[12] * m[7] * m[10];
216
217        inv[8] = m[4] * m[9] * m[15] -
218                m[4] * m[11] * m[13] -
219                m[8] * m[5] * m[15] +
220                m[8] * m[7] * m[13] +
221                m[12] * m[5] * m[11] -
222                m[12] * m[7] * m[9];
223
224        inv[12] = -m[4] * m[9] * m[14] +
225                m[4] * m[10] * m[13] +
226                m[8] * m[5] * m[14] -
227                m[8] * m[6] * m[13] -
228                m[12] * m[5] * m[10] +
229                m[12] * m[6] * m[9];
230
231        inv[1] = -m[1] * m[10] * m[15] +
232                m[1] * m[11] * m[14] +
233                m[9] * m[2] * m[15] -
234                m[9] * m[3] * m[14] -
235                m[13] * m[2] * m[11] +
236                m[13] * m[3] * m[10];
237
238        inv[5] = m[0] * m[10] * m[15] -
239                m[0] * m[11] * m[14] -
240                m[8] * m[2] * m[15] +
241                m[8] * m[3] * m[14] +
242                m[12] * m[2] * m[11] -
243                m[12] * m[3] * m[10];
244
245        inv[9] = -m[0] * m[9] * m[15] +
246                m[0] * m[11] * m[13] +
247                m[8] * m[1] * m[15] -
248                m[8] * m[3] * m[13] -
249                m[12] * m[1] * m[11] +
250                m[12] * m[3] * m[9];
251
252        inv[13] = m[0] * m[9] * m[14] -
253                m[0] * m[10] * m[13] -
254                m[8] * m[1] * m[14] +
255                m[8] * m[2] * m[13] +
256                m[12] * m[1] * m[10] -
257                m[12] * m[2] * m[9];
258
259        inv[2] = m[1] * m[6] * m[15] -
260                m[1] * m[7] * m[14] -
261                m[5] * m[2] * m[15] +
262                m[5] * m[3] * m[14] +
263                m[13] * m[2] * m[7] -
264                m[13] * m[3] * m[6];
265
266        inv[6] = -m[0] * m[6] * m[15] +
267                m[0] * m[7] * m[14] +
268                m[4] * m[2] * m[15] -
269                m[4] * m[3] * m[14] -
270                m[12] * m[2] * m[7] +
271                m[12] * m[3] * m[6];
272
273        inv[10] = m[0] * m[5] * m[15] -
274                m[0] * m[7] * m[13] -
275                m[4] * m[1] * m[15] +
276                m[4] * m[3] * m[13] +
277                m[12] * m[1] * m[7] -
278                m[12] * m[3] * m[5];
279
280        inv[14] = -m[0] * m[5] * m[14] +
281                m[0] * m[6] * m[13] +
282                m[4] * m[1] * m[14] -
283                m[4] * m[2] * m[13] -
284                m[12] * m[1] * m[6] +
285                m[12] * m[2] * m[5];
286
287        inv[3] = -m[1] * m[6] * m[11] +
288                m[1] * m[7] * m[10] +
289                m[5] * m[2] * m[11] -
290                m[5] * m[3] * m[10] -
291                m[9] * m[2] * m[7] +
292                m[9] * m[3] * m[6];
293
294        inv[7] = m[0] * m[6] * m[11] -
295                m[0] * m[7] * m[10] -
296                m[4] * m[2] * m[11] +
297                m[4] * m[3] * m[10] +
298                m[8] * m[2] * m[7] -
299                m[8] * m[3] * m[6];
300
301        inv[11] = -m[0] * m[5] * m[11] +
302                m[0] * m[7] * m[9] +
303                m[4] * m[1] * m[11] -
304                m[4] * m[3] * m[9] -
305                m[8] * m[1] * m[7] +
306                m[8] * m[3] * m[5];
307
308        inv[15] = m[0] * m[5] * m[10] -
309                m[0] * m[6] * m[9] -
310                m[4] * m[1] * m[10] +
311                m[4] * m[2] * m[9] +
312                m[8] * m[1] * m[6] -
313                m[8] * m[2] * m[5];
314
315
316        double det;
317        det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
318
319        if (det == 0) {
320            return null;
321        }
322
323        det = 1.0 / det;
324
325        double[] out = new double[16];
326
327        for (int i = 0; i < 16; i++) {
328            out[i] = inv[i] * det;
329        }
330
331        Matrix ret = new Matrix(out);
332        return ret;
333    }
334
335    public void getAsFloats(float[] fm) {
336        for (int y = 0; y < 4; y++) {
337            int col = y * 4;
338
339            for (int x = 0; x < 4; x++)
340                fm[y + x * 4] = (float) m[x + y * 4];
341        }
342    }
343
344    Matrix mult(Matrix b) {
345        return new Matrix(multiply(this.m, b.m));
346    }
347
348    Matrix premult(Matrix b) {
349        return new Matrix(multiply(b.m, this.m));
350    }
351
352    private static double[] multiply(double a[], double b[]) {
353        double[] resultant = new double[16];
354        for (int i = 0; i < 4; i++) {
355            for (int j = 0; j < 4; j++) {
356                for (int k = 0; k < 4; k++) {
357                    resultant[i + 4 * j] += a[i + 4 * k] * b[k + 4 * j];
358                }
359            }
360        }
361
362        return resultant;
363    }
364
365    public void clone(Matrix src) {
366        System.arraycopy(src.m, 0, m, 0, m.length);
367    }
368}
369