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