blob: a9469c97949456ceda6b8d26eb30a0da634d9970 [file] [log] [blame]
Jason Sams0826a6f2009-06-15 19:04:56 -07001/*
Stephen Hinesec6f2002012-07-10 16:16:22 -07002 * Copyright (C) 2009-2012 The Android Open Source Project
Jason Sams0826a6f2009-06-15 19:04:56 -07003 *
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
17package android.renderscript;
18
Artur Satayev53ada2a2019-12-10 17:47:56 +000019import android.compat.annotation.UnsupportedAppUsage;
Jason Sams0826a6f2009-06-15 19:04:56 -070020
21
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -070022/**
Tim Murrayc11e25c2013-04-09 11:01:01 -070023 * Class for exposing the native RenderScript rs_matrix4x4 type back to the Android system.
Jason Samse29d4712009-07-23 15:19:03 -070024 *
25 **/
Jason Sams25430d02010-02-02 15:26:40 -080026public class Matrix4f {
Jason Sams0826a6f2009-06-15 19:04:56 -070027
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -070028 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080029 * Creates a new identity 4x4 matrix
30 */
Jason Sams25430d02010-02-02 15:26:40 -080031 public Matrix4f() {
Jason Sams0826a6f2009-06-15 19:04:56 -070032 mMat = new float[16];
33 loadIdentity();
34 }
35
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -070036 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080037 * Creates a new matrix and sets its values from the given
38 * parameter
39 *
40 * @param dataArray values to set the matrix to, must be 16
41 * floats long
42 */
Alex Sakhartchouke27cdee2010-12-17 11:41:08 -080043 public Matrix4f(float[] dataArray) {
44 mMat = new float[16];
45 System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
46 }
47
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -070048 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080049 * Return a reference to the internal array representing matrix
50 * values. Modifying this array will also change the matrix
51 *
52 * @return internal array representing the matrix
53 */
Alex Sakhartchouke27cdee2010-12-17 11:41:08 -080054 public float[] getArray() {
55 return mMat;
56 }
57
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -070058 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080059 * Returns the value for a given row and column
60 *
Stephen Hinesec6f2002012-07-10 16:16:22 -070061 * @param x column of the value to return
62 * @param y row of the value to return
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080063 *
Stephen Hinesec6f2002012-07-10 16:16:22 -070064 * @return value in the yth row and xth column
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080065 */
Stephen Hinesec6f2002012-07-10 16:16:22 -070066 public float get(int x, int y) {
67 return mMat[x*4 + y];
Jason Sams0826a6f2009-06-15 19:04:56 -070068 }
69
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -070070 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080071 * Sets the value for a given row and column
72 *
Stephen Hinesec6f2002012-07-10 16:16:22 -070073 * @param x column of the value to set
74 * @param y row of the value to set
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080075 */
Stephen Hinesec6f2002012-07-10 16:16:22 -070076 public void set(int x, int y, float v) {
77 mMat[x*4 + y] = v;
Jason Sams0826a6f2009-06-15 19:04:56 -070078 }
79
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -070080 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -080081 * Sets the matrix values to identity
82 */
Jason Sams0826a6f2009-06-15 19:04:56 -070083 public void loadIdentity() {
84 mMat[0] = 1;
85 mMat[1] = 0;
86 mMat[2] = 0;
87 mMat[3] = 0;
88
89 mMat[4] = 0;
90 mMat[5] = 1;
91 mMat[6] = 0;
92 mMat[7] = 0;
Jason Sams25430d02010-02-02 15:26:40 -080093
Jason Sams0826a6f2009-06-15 19:04:56 -070094 mMat[8] = 0;
95 mMat[9] = 0;
96 mMat[10] = 1;
97 mMat[11] = 0;
98
99 mMat[12] = 0;
100 mMat[13] = 0;
101 mMat[14] = 0;
102 mMat[15] = 1;
103 }
104
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700105 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800106 * Sets the values of the matrix to those of the parameter
107 *
108 * @param src matrix to load the values from
109 */
Jason Sams25430d02010-02-02 15:26:40 -0800110 public void load(Matrix4f src) {
Alex Sakhartchoukb3b89f62010-12-29 08:43:49 -0800111 System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
Jason Sams0826a6f2009-06-15 19:04:56 -0700112 }
113
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700114 /**
Jason Sams8fd58532012-09-05 15:30:18 -0700115 * Sets the values of the matrix to those of the parameter
116 *
117 * @param src matrix to load the values from
118 * @hide
119 */
120 public void load(Matrix3f src) {
121 mMat[0] = src.mMat[0];
122 mMat[1] = src.mMat[1];
123 mMat[2] = src.mMat[2];
124 mMat[3] = 0;
125
126 mMat[4] = src.mMat[3];
127 mMat[5] = src.mMat[4];
128 mMat[6] = src.mMat[5];
129 mMat[7] = 0;
130
131 mMat[8] = src.mMat[6];
132 mMat[9] = src.mMat[7];
133 mMat[10] = src.mMat[8];
134 mMat[11] = 0;
135
136 mMat[12] = 0;
137 mMat[13] = 0;
138 mMat[14] = 0;
139 mMat[15] = 1;
140 }
141
142 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800143 * Sets current values to be a rotation matrix of certain angle
144 * about a given axis
145 *
146 * @param rot angle of rotation
147 * @param x rotation axis x
148 * @param y rotation axis y
149 * @param z rotation axis z
150 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700151 public void loadRotate(float rot, float x, float y, float z) {
152 float c, s;
153 mMat[3] = 0;
154 mMat[7] = 0;
155 mMat[11]= 0;
156 mMat[12]= 0;
157 mMat[13]= 0;
158 mMat[14]= 0;
159 mMat[15]= 1;
160 rot *= (float)(java.lang.Math.PI / 180.0f);
161 c = (float)java.lang.Math.cos(rot);
162 s = (float)java.lang.Math.sin(rot);
Jason Sams25430d02010-02-02 15:26:40 -0800163
Jason Sams0826a6f2009-06-15 19:04:56 -0700164 float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z);
165 if (!(len != 1)) {
166 float recipLen = 1.f / len;
167 x *= recipLen;
168 y *= recipLen;
169 z *= recipLen;
170 }
171 float nc = 1.0f - c;
172 float xy = x * y;
173 float yz = y * z;
174 float zx = z * x;
175 float xs = x * s;
176 float ys = y * s;
Jason Sams25430d02010-02-02 15:26:40 -0800177 float zs = z * s;
Jason Sams0826a6f2009-06-15 19:04:56 -0700178 mMat[ 0] = x*x*nc + c;
179 mMat[ 4] = xy*nc - zs;
180 mMat[ 8] = zx*nc + ys;
181 mMat[ 1] = xy*nc + zs;
182 mMat[ 5] = y*y*nc + c;
183 mMat[ 9] = yz*nc - xs;
184 mMat[ 2] = zx*nc - ys;
185 mMat[ 6] = yz*nc + xs;
186 mMat[10] = z*z*nc + c;
187 }
188
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700189 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800190 * Sets current values to be a scale matrix of given dimensions
191 *
192 * @param x scale component x
193 * @param y scale component y
194 * @param z scale component z
195 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700196 public void loadScale(float x, float y, float z) {
197 loadIdentity();
198 mMat[0] = x;
199 mMat[5] = y;
200 mMat[10] = z;
201 }
Jason Sams25430d02010-02-02 15:26:40 -0800202
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700203 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800204 * Sets current values to be a translation matrix of given
205 * dimensions
206 *
207 * @param x translation component x
208 * @param y translation component y
209 * @param z translation component z
210 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700211 public void loadTranslate(float x, float y, float z) {
212 loadIdentity();
213 mMat[12] = x;
214 mMat[13] = y;
215 mMat[14] = z;
216 }
217
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700218 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800219 * Sets current values to be the result of multiplying two given
220 * matrices
221 *
222 * @param lhs left hand side matrix
223 * @param rhs right hand side matrix
224 */
Jason Sams25430d02010-02-02 15:26:40 -0800225 public void loadMultiply(Matrix4f lhs, Matrix4f rhs) {
Jason Sams0826a6f2009-06-15 19:04:56 -0700226 for (int i=0 ; i<4 ; i++) {
227 float ri0 = 0;
228 float ri1 = 0;
229 float ri2 = 0;
230 float ri3 = 0;
231 for (int j=0 ; j<4 ; j++) {
232 float rhs_ij = rhs.get(i,j);
233 ri0 += lhs.get(j,0) * rhs_ij;
234 ri1 += lhs.get(j,1) * rhs_ij;
235 ri2 += lhs.get(j,2) * rhs_ij;
236 ri3 += lhs.get(j,3) * rhs_ij;
237 }
238 set(i,0, ri0);
239 set(i,1, ri1);
240 set(i,2, ri2);
241 set(i,3, ri3);
242 }
243 }
244
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700245 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800246 * Set current values to be an orthographic projection matrix
247 *
248 * @param l location of the left vertical clipping plane
249 * @param r location of the right vertical clipping plane
250 * @param b location of the bottom horizontal clipping plane
251 * @param t location of the top horizontal clipping plane
252 * @param n location of the near clipping plane
253 * @param f location of the far clipping plane
254 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700255 public void loadOrtho(float l, float r, float b, float t, float n, float f) {
256 loadIdentity();
257 mMat[0] = 2 / (r - l);
258 mMat[5] = 2 / (t - b);
259 mMat[10]= -2 / (f - n);
260 mMat[12]= -(r + l) / (r - l);
Jason Samsb37c0a52009-06-16 17:49:58 -0700261 mMat[13]= -(t + b) / (t - b);
262 mMat[14]= -(f + n) / (f - n);
Jason Sams0826a6f2009-06-15 19:04:56 -0700263 }
264
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700265 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800266 * Set current values to be an orthographic projection matrix
267 * with the right and bottom clipping planes set to the given
268 * values. Left and top clipping planes are set to 0. Near and
269 * far are set to -1, 1 respectively
270 *
271 * @param w location of the right vertical clipping plane
272 * @param h location of the bottom horizontal clipping plane
273 *
274 */
Alex Sakhartchouke27cdee2010-12-17 11:41:08 -0800275 public void loadOrthoWindow(int w, int h) {
276 loadOrtho(0,w, h,0, -1,1);
277 }
278
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700279 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800280 * Sets current values to be a perspective projection matrix
281 *
282 * @param l location of the left vertical clipping plane
283 * @param r location of the right vertical clipping plane
284 * @param b location of the bottom horizontal clipping plane
285 * @param t location of the top horizontal clipping plane
286 * @param n location of the near clipping plane, must be positive
287 * @param f location of the far clipping plane, must be positive
288 *
289 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700290 public void loadFrustum(float l, float r, float b, float t, float n, float f) {
291 loadIdentity();
292 mMat[0] = 2 * n / (r - l);
293 mMat[5] = 2 * n / (t - b);
294 mMat[8] = (r + l) / (r - l);
295 mMat[9] = (t + b) / (t - b);
296 mMat[10]= -(f + n) / (f - n);
297 mMat[11]= -1;
298 mMat[14]= -2*f*n / (f - n);
299 mMat[15]= 0;
300 }
301
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700302 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800303 * Sets current values to be a perspective projection matrix
304 *
305 * @param fovy vertical field of view angle in degrees
306 * @param aspect aspect ratio of the screen
307 * @param near near cliping plane, must be positive
308 * @param far far clipping plane, must be positive
309 */
Alex Sakhartchouke27cdee2010-12-17 11:41:08 -0800310 public void loadPerspective(float fovy, float aspect, float near, float far) {
311 float top = near * (float)Math.tan((float) (fovy * Math.PI / 360.0f));
312 float bottom = -top;
313 float left = bottom * aspect;
314 float right = top * aspect;
315 loadFrustum(left, right, bottom, top, near, far);
316 }
317
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700318 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800319 * Helper function to set the current values to a perspective
320 * projection matrix with aspect ratio defined by the parameters
321 * and (near, far), (bottom, top) mapping to (-1, 1) at z = 0
322 *
323 * @param w screen width
324 * @param h screen height
325 */
Alex Sakhartchoukb4d7bb62010-12-21 14:42:26 -0800326 public void loadProjectionNormalized(int w, int h) {
327 // range -1,1 in the narrow axis at z = 0.
328 Matrix4f m1 = new Matrix4f();
329 Matrix4f m2 = new Matrix4f();
330
331 if(w > h) {
332 float aspect = ((float)w) / h;
333 m1.loadFrustum(-aspect,aspect, -1,1, 1,100);
334 } else {
335 float aspect = ((float)h) / w;
336 m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
337 }
338
339 m2.loadRotate(180, 0, 1, 0);
340 m1.loadMultiply(m1, m2);
341
342 m2.loadScale(-2, 2, 1);
343 m1.loadMultiply(m1, m2);
344
345 m2.loadTranslate(0, 0, 2);
346 m1.loadMultiply(m1, m2);
347
348 load(m1);
349 }
350
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700351 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800352 * Post-multiplies the current matrix by a given parameter
353 *
354 * @param rhs right hand side to multiply by
355 */
Jason Sams25430d02010-02-02 15:26:40 -0800356 public void multiply(Matrix4f rhs) {
357 Matrix4f tmp = new Matrix4f();
Jason Sams0826a6f2009-06-15 19:04:56 -0700358 tmp.loadMultiply(this, rhs);
359 load(tmp);
360 }
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700361 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800362 * Modifies the current matrix by post-multiplying it with a
363 * rotation matrix of certain angle about a given axis
364 *
365 * @param rot angle of rotation
366 * @param x rotation axis x
367 * @param y rotation axis y
368 * @param z rotation axis z
369 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700370 public void rotate(float rot, float x, float y, float z) {
Jason Sams25430d02010-02-02 15:26:40 -0800371 Matrix4f tmp = new Matrix4f();
Jason Sams0826a6f2009-06-15 19:04:56 -0700372 tmp.loadRotate(rot, x, y, z);
373 multiply(tmp);
374 }
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800375
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700376 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800377 * Modifies the current matrix by post-multiplying it with a
378 * scale matrix of given dimensions
379 *
380 * @param x scale component x
381 * @param y scale component y
382 * @param z scale component z
383 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700384 public void scale(float x, float y, float z) {
Jason Sams25430d02010-02-02 15:26:40 -0800385 Matrix4f tmp = new Matrix4f();
Jason Sams0826a6f2009-06-15 19:04:56 -0700386 tmp.loadScale(x, y, z);
387 multiply(tmp);
388 }
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800389
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700390 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800391 * Modifies the current matrix by post-multiplying it with a
392 * translation matrix of given dimensions
393 *
394 * @param x translation component x
395 * @param y translation component y
396 * @param z translation component z
397 */
Jason Sams0826a6f2009-06-15 19:04:56 -0700398 public void translate(float x, float y, float z) {
Jason Sams25430d02010-02-02 15:26:40 -0800399 Matrix4f tmp = new Matrix4f();
Jason Sams0826a6f2009-06-15 19:04:56 -0700400 tmp.loadTranslate(x, y, z);
401 multiply(tmp);
402 }
Alex Sakhartchoukfacd6fc2010-08-10 17:34:39 -0700403 private float computeCofactor(int i, int j) {
404 int c0 = (i+1) % 4;
405 int c1 = (i+2) % 4;
406 int c2 = (i+3) % 4;
407 int r0 = (j+1) % 4;
408 int r1 = (j+2) % 4;
409 int r2 = (j+3) % 4;
410
411 float minor = (mMat[c0 + 4*r0] * (mMat[c1 + 4*r1] * mMat[c2 + 4*r2] -
412 mMat[c1 + 4*r2] * mMat[c2 + 4*r1]))
413 - (mMat[c0 + 4*r1] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r2] -
414 mMat[c1 + 4*r2] * mMat[c2 + 4*r0]))
415 + (mMat[c0 + 4*r2] * (mMat[c1 + 4*r0] * mMat[c2 + 4*r1] -
416 mMat[c1 + 4*r1] * mMat[c2 + 4*r0]));
417
418 float cofactor = ((i+j) & 1) != 0 ? -minor : minor;
419 return cofactor;
420 }
421
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700422 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800423 * Sets the current matrix to its inverse
424 */
Alex Sakhartchoukfacd6fc2010-08-10 17:34:39 -0700425 public boolean inverse() {
426
427 Matrix4f result = new Matrix4f();
428
429 for (int i = 0; i < 4; ++i) {
430 for (int j = 0; j < 4; ++j) {
431 result.mMat[4*i + j] = computeCofactor(i, j);
432 }
433 }
434
435 // Dot product of 0th column of source and 0th row of result
436 float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[1] +
437 mMat[8]*result.mMat[2] + mMat[12]*result.mMat[3];
438
439 if (Math.abs(det) < 1e-6) {
440 return false;
441 }
442
443 det = 1.0f / det;
444 for (int i = 0; i < 16; ++i) {
445 mMat[i] = result.mMat[i] * det;
446 }
447
448 return true;
449 }
450
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700451 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800452 * Sets the current matrix to its inverse transpose
453 */
Alex Sakhartchoukfacd6fc2010-08-10 17:34:39 -0700454 public boolean inverseTranspose() {
455
456 Matrix4f result = new Matrix4f();
457
458 for (int i = 0; i < 4; ++i) {
459 for (int j = 0; j < 4; ++j) {
460 result.mMat[4*j + i] = computeCofactor(i, j);
461 }
462 }
463
464 float det = mMat[0]*result.mMat[0] + mMat[4]*result.mMat[4] +
465 mMat[8]*result.mMat[8] + mMat[12]*result.mMat[12];
466
467 if (Math.abs(det) < 1e-6) {
468 return false;
469 }
470
471 det = 1.0f / det;
472 for (int i = 0; i < 16; ++i) {
473 mMat[i] = result.mMat[i] * det;
474 }
475
476 return true;
477 }
478
Stephen Hines9c9ad3f8c22012-05-07 15:34:29 -0700479 /**
Alex Sakhartchoukec0d3352011-01-17 15:23:22 -0800480 * Sets the current matrix to its transpose
481 */
Alex Sakhartchouk518f0332010-08-05 10:28:43 -0700482 public void transpose() {
483 for(int i = 0; i < 3; ++i) {
484 for(int j = i + 1; j < 4; ++j) {
485 float temp = mMat[i*4 + j];
486 mMat[i*4 + j] = mMat[j*4 + i];
487 mMat[j*4 + i] = temp;
488 }
489 }
490 }
Jason Sams0826a6f2009-06-15 19:04:56 -0700491
Mathew Inwood15324472018-08-06 11:18:49 +0100492 @UnsupportedAppUsage
Jason Sams25430d02010-02-02 15:26:40 -0800493 final float[] mMat;
Jason Sams0826a6f2009-06-15 19:04:56 -0700494}