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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 } 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 */ 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 */ 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 */ 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