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