• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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  */
16 
17 package android.renderscript;
18 
19 import java.lang.Math;
20 import android.util.Log;
21 
22 
23 /**
24  * Class for exposing the native Renderscript rs_matrix4x4 type back to the Android system.
25  *
26  **/
27 public class Matrix4f {
28 
29     /**
30     * Creates a new identity 4x4 matrix
31     */
Matrix4f()32     public Matrix4f() {
33         mMat = new float[16];
34         loadIdentity();
35     }
36 
37     /**
38     * Creates a new matrix and sets its values from the given
39     * parameter
40     *
41     * @param dataArray values to set the matrix to, must be 16
42     *                  floats long
43     */
Matrix4f(float[] dataArray)44     public Matrix4f(float[] dataArray) {
45         mMat = new float[16];
46         System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
47     }
48 
49     /**
50     * Return a reference to the internal array representing matrix
51     * values. Modifying this array will also change the matrix
52     *
53     * @return internal array representing the matrix
54     */
getArray()55     public float[] getArray() {
56         return mMat;
57     }
58 
59     /**
60     * Returns the value for a given row and column
61     *
62     * @param i row of the value to return
63     * @param j column of the value to return
64     *
65     * @return value in the ith row and jth column
66     */
get(int i, int j)67     public float get(int i, int j) {
68         return mMat[i*4 + j];
69     }
70 
71     /**
72     * Sets the value for a given row and column
73     *
74     * @param i row of the value to set
75     * @param j column of the value to set
76     */
set(int i, int j, float v)77     public void set(int i, int j, float v) {
78         mMat[i*4 + j] = v;
79     }
80 
81     /**
82     * Sets the matrix values to identity
83     */
loadIdentity()84     public void loadIdentity() {
85         mMat[0] = 1;
86         mMat[1] = 0;
87         mMat[2] = 0;
88         mMat[3] = 0;
89 
90         mMat[4] = 0;
91         mMat[5] = 1;
92         mMat[6] = 0;
93         mMat[7] = 0;
94 
95         mMat[8] = 0;
96         mMat[9] = 0;
97         mMat[10] = 1;
98         mMat[11] = 0;
99 
100         mMat[12] = 0;
101         mMat[13] = 0;
102         mMat[14] = 0;
103         mMat[15] = 1;
104     }
105 
106     /**
107     * Sets the values of the matrix to those of the parameter
108     *
109     * @param src matrix to load the values from
110     */
load(Matrix4f src)111     public void load(Matrix4f src) {
112         System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
113     }
114 
115     /**
116     * Sets current values to be a rotation matrix of certain angle
117     * about a given axis
118     *
119     * @param rot angle of rotation
120     * @param x rotation axis x
121     * @param y rotation axis y
122     * @param z rotation axis z
123     */
loadRotate(float rot, float x, float y, float z)124     public void loadRotate(float rot, float x, float y, float z) {
125         float c, s;
126         mMat[3] = 0;
127         mMat[7] = 0;
128         mMat[11]= 0;
129         mMat[12]= 0;
130         mMat[13]= 0;
131         mMat[14]= 0;
132         mMat[15]= 1;
133         rot *= (float)(java.lang.Math.PI / 180.0f);
134         c = (float)java.lang.Math.cos(rot);
135         s = (float)java.lang.Math.sin(rot);
136 
137         float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z);
138         if (!(len != 1)) {
139             float recipLen = 1.f / len;
140             x *= recipLen;
141             y *= recipLen;
142             z *= recipLen;
143         }
144         float nc = 1.0f - c;
145         float xy = x * y;
146         float yz = y * z;
147         float zx = z * x;
148         float xs = x * s;
149         float ys = y * s;
150         float zs = z * s;
151         mMat[ 0] = x*x*nc +  c;
152         mMat[ 4] =  xy*nc - zs;
153         mMat[ 8] =  zx*nc + ys;
154         mMat[ 1] =  xy*nc + zs;
155         mMat[ 5] = y*y*nc +  c;
156         mMat[ 9] =  yz*nc - xs;
157         mMat[ 2] =  zx*nc - ys;
158         mMat[ 6] =  yz*nc + xs;
159         mMat[10] = z*z*nc +  c;
160     }
161 
162     /**
163     * Sets current values to be a scale matrix of given dimensions
164     *
165     * @param x scale component x
166     * @param y scale component y
167     * @param z scale component z
168     */
loadScale(float x, float y, float z)169     public void loadScale(float x, float y, float z) {
170         loadIdentity();
171         mMat[0] = x;
172         mMat[5] = y;
173         mMat[10] = z;
174     }
175 
176     /**
177     * Sets current values to be a translation matrix of given
178     * dimensions
179     *
180     * @param x translation component x
181     * @param y translation component y
182     * @param z translation component z
183     */
loadTranslate(float x, float y, float z)184     public void loadTranslate(float x, float y, float z) {
185         loadIdentity();
186         mMat[12] = x;
187         mMat[13] = y;
188         mMat[14] = z;
189     }
190 
191     /**
192     * Sets current values to be the result of multiplying two given
193     * matrices
194     *
195     * @param lhs left hand side matrix
196     * @param rhs right hand side matrix
197     */
loadMultiply(Matrix4f lhs, Matrix4f rhs)198     public void loadMultiply(Matrix4f lhs, Matrix4f rhs) {
199         for (int i=0 ; i<4 ; i++) {
200             float ri0 = 0;
201             float ri1 = 0;
202             float ri2 = 0;
203             float ri3 = 0;
204             for (int j=0 ; j<4 ; j++) {
205                 float rhs_ij = rhs.get(i,j);
206                 ri0 += lhs.get(j,0) * rhs_ij;
207                 ri1 += lhs.get(j,1) * rhs_ij;
208                 ri2 += lhs.get(j,2) * rhs_ij;
209                 ri3 += lhs.get(j,3) * rhs_ij;
210             }
211             set(i,0, ri0);
212             set(i,1, ri1);
213             set(i,2, ri2);
214             set(i,3, ri3);
215         }
216     }
217 
218     /**
219     * Set current values to be an orthographic projection matrix
220     *
221     * @param l location of the left vertical clipping plane
222     * @param r location of the right vertical clipping plane
223     * @param b location of the bottom horizontal clipping plane
224     * @param t location of the top horizontal clipping plane
225     * @param n location of the near clipping plane
226     * @param f location of the far clipping plane
227     */
loadOrtho(float l, float r, float b, float t, float n, float f)228     public void loadOrtho(float l, float r, float b, float t, float n, float f) {
229         loadIdentity();
230         mMat[0] = 2 / (r - l);
231         mMat[5] = 2 / (t - b);
232         mMat[10]= -2 / (f - n);
233         mMat[12]= -(r + l) / (r - l);
234         mMat[13]= -(t + b) / (t - b);
235         mMat[14]= -(f + n) / (f - n);
236     }
237 
238     /**
239     * Set current values to be an orthographic projection matrix
240     * with the right and bottom clipping planes set to the given
241     * values. Left and top clipping planes are set to 0. Near and
242     * far are set to -1, 1 respectively
243     *
244     * @param w location of the right vertical clipping plane
245     * @param h location of the bottom horizontal clipping plane
246     *
247     */
loadOrthoWindow(int w, int h)248     public void loadOrthoWindow(int w, int h) {
249         loadOrtho(0,w, h,0, -1,1);
250     }
251 
252     /**
253     * Sets current values to be a perspective projection matrix
254     *
255     * @param l location of the left vertical clipping plane
256     * @param r location of the right vertical clipping plane
257     * @param b location of the bottom horizontal clipping plane
258     * @param t location of the top horizontal clipping plane
259     * @param n location of the near clipping plane, must be positive
260     * @param f location of the far clipping plane, must be positive
261     *
262     */
loadFrustum(float l, float r, float b, float t, float n, float f)263     public void loadFrustum(float l, float r, float b, float t, float n, float f) {
264         loadIdentity();
265         mMat[0] = 2 * n / (r - l);
266         mMat[5] = 2 * n / (t - b);
267         mMat[8] = (r + l) / (r - l);
268         mMat[9] = (t + b) / (t - b);
269         mMat[10]= -(f + n) / (f - n);
270         mMat[11]= -1;
271         mMat[14]= -2*f*n / (f - n);
272         mMat[15]= 0;
273     }
274 
275     /**
276     * Sets current values to be a perspective projection matrix
277     *
278     * @param fovy vertical field of view angle in degrees
279     * @param aspect aspect ratio of the screen
280     * @param near near cliping plane, must be positive
281     * @param far far clipping plane, must be positive
282     */
loadPerspective(float fovy, float aspect, float near, float far)283     public void loadPerspective(float fovy, float aspect, float near, float far) {
284         float top = near * (float)Math.tan((float) (fovy * Math.PI / 360.0f));
285         float bottom = -top;
286         float left = bottom * aspect;
287         float right = top * aspect;
288         loadFrustum(left, right, bottom, top, near, far);
289     }
290 
291     /**
292     * Helper function to set the current values to a perspective
293     * projection matrix with aspect ratio defined by the parameters
294     * and (near, far), (bottom, top) mapping to (-1, 1) at z = 0
295     *
296     * @param w screen width
297     * @param h screen height
298     */
loadProjectionNormalized(int w, int h)299     public void loadProjectionNormalized(int w, int h) {
300         // range -1,1 in the narrow axis at z = 0.
301         Matrix4f m1 = new Matrix4f();
302         Matrix4f m2 = new Matrix4f();
303 
304         if(w > h) {
305             float aspect = ((float)w) / h;
306             m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
307         } else {
308             float aspect = ((float)h) / w;
309             m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
310         }
311 
312         m2.loadRotate(180, 0, 1, 0);
313         m1.loadMultiply(m1, m2);
314 
315         m2.loadScale(-2, 2, 1);
316         m1.loadMultiply(m1, m2);
317 
318         m2.loadTranslate(0, 0, 2);
319         m1.loadMultiply(m1, m2);
320 
321         load(m1);
322     }
323 
324     /**
325     * Post-multiplies the current matrix by a given parameter
326     *
327     * @param rhs right hand side to multiply by
328     */
multiply(Matrix4f rhs)329     public void multiply(Matrix4f rhs) {
330         Matrix4f tmp = new Matrix4f();
331         tmp.loadMultiply(this, rhs);
332         load(tmp);
333     }
334     /**
335     * Modifies the current matrix by post-multiplying it with a
336     * rotation matrix of certain angle about a given axis
337     *
338     * @param rot angle of rotation
339     * @param x rotation axis x
340     * @param y rotation axis y
341     * @param z rotation axis z
342     */
rotate(float rot, float x, float y, float z)343     public void rotate(float rot, float x, float y, float z) {
344         Matrix4f tmp = new Matrix4f();
345         tmp.loadRotate(rot, x, y, z);
346         multiply(tmp);
347     }
348 
349     /**
350     * Modifies the current matrix by post-multiplying it with a
351     * scale matrix of given dimensions
352     *
353     * @param x scale component x
354     * @param y scale component y
355     * @param z scale component z
356     */
scale(float x, float y, float z)357     public void scale(float x, float y, float z) {
358         Matrix4f tmp = new Matrix4f();
359         tmp.loadScale(x, y, z);
360         multiply(tmp);
361     }
362 
363     /**
364     * Modifies the current matrix by post-multiplying it with a
365     * translation matrix of given dimensions
366     *
367     * @param x translation component x
368     * @param y translation component y
369     * @param z translation component z
370     */
translate(float x, float y, float z)371     public void translate(float x, float y, float z) {
372         Matrix4f tmp = new Matrix4f();
373         tmp.loadTranslate(x, y, z);
374         multiply(tmp);
375     }
computeCofactor(int i, int j)376     private float computeCofactor(int i, int j) {
377         int c0 = (i+1) % 4;
378         int c1 = (i+2) % 4;
379         int c2 = (i+3) % 4;
380         int r0 = (j+1) % 4;
381         int r1 = (j+2) % 4;
382         int r2 = (j+3) % 4;
383 
384         float minor = (mMat[c0 + 4*r0] * (mMat[c1 + 4*r1] * mMat[c2 + 4*r2] -
385                                             mMat[c1 + 4*r2] * mMat[c2 + 4*r1]))
386                      - (mMat[c0 + 4*r1] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r2] -
387                                             mMat[c1 + 4*r2] * mMat[c2 + 4*r0]))
388                      + (mMat[c0 + 4*r2] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r1] -
389                                             mMat[c1 + 4*r1] * mMat[c2 + 4*r0]));
390 
391         float cofactor = ((i+j) & 1) != 0 ? -minor : minor;
392         return cofactor;
393     }
394 
395     /**
396     * Sets the current matrix to its inverse
397     */
inverse()398     public boolean inverse() {
399 
400         Matrix4f result = new Matrix4f();
401 
402         for (int i = 0; i < 4; ++i) {
403             for (int j = 0; j < 4; ++j) {
404                 result.mMat[4*i + j] = computeCofactor(i, j);
405             }
406         }
407 
408         // Dot product of 0th column of source and 0th row of result
409         float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[1] +
410                      mMat[8]*result.mMat[2] + mMat[12]*result.mMat[3];
411 
412         if (Math.abs(det) < 1e-6) {
413             return false;
414         }
415 
416         det = 1.0f / det;
417         for (int i = 0; i < 16; ++i) {
418             mMat[i] = result.mMat[i] * det;
419         }
420 
421         return true;
422     }
423 
424     /**
425     * Sets the current matrix to its inverse transpose
426     */
inverseTranspose()427     public boolean inverseTranspose() {
428 
429         Matrix4f result = new Matrix4f();
430 
431         for (int i = 0; i < 4; ++i) {
432             for (int j = 0; j < 4; ++j) {
433                 result.mMat[4*j + i] = computeCofactor(i, j);
434             }
435         }
436 
437         float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[4] +
438                      mMat[8]*result.mMat[8] + mMat[12]*result.mMat[12];
439 
440         if (Math.abs(det) < 1e-6) {
441             return false;
442         }
443 
444         det = 1.0f / det;
445         for (int i = 0; i < 16; ++i) {
446             mMat[i] = result.mMat[i] * det;
447         }
448 
449         return true;
450     }
451 
452     /**
453     * Sets the current matrix to its transpose
454     */
transpose()455     public void transpose() {
456         for(int i = 0; i < 3; ++i) {
457             for(int j = i + 1; j < 4; ++j) {
458                 float temp = mMat[i*4 + j];
459                 mMat[i*4 + j] = mMat[j*4 + i];
460                 mMat[j*4 + i] = temp;
461             }
462         }
463     }
464 
465     final float[] mMat;
466 }
467