1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.math; 33 34 import com.jme3.export.*; 35 import com.jme3.util.BufferUtils; 36 import com.jme3.util.TempVars; 37 import java.io.IOException; 38 import java.nio.FloatBuffer; 39 import java.util.logging.Logger; 40 41 /** 42 * <code>Matrix3f</code> defines a 3x3 matrix. Matrix data is maintained 43 * internally and is accessible via the get and set methods. Convenience methods 44 * are used for matrix operations as well as generating a matrix from a given 45 * set of values. 46 * 47 * @author Mark Powell 48 * @author Joshua Slack 49 */ 50 public final class Matrix3f implements Savable, Cloneable, java.io.Serializable { 51 52 static final long serialVersionUID = 1; 53 54 private static final Logger logger = Logger.getLogger(Matrix3f.class.getName()); 55 protected float m00, m01, m02; 56 protected float m10, m11, m12; 57 protected float m20, m21, m22; 58 public static final Matrix3f ZERO = new Matrix3f(0, 0, 0, 0, 0, 0, 0, 0, 0); 59 public static final Matrix3f IDENTITY = new Matrix3f(); 60 61 /** 62 * Constructor instantiates a new <code>Matrix3f</code> object. The 63 * initial values for the matrix is that of the identity matrix. 64 * 65 */ Matrix3f()66 public Matrix3f() { 67 loadIdentity(); 68 } 69 70 /** 71 * constructs a matrix with the given values. 72 * 73 * @param m00 74 * 0x0 in the matrix. 75 * @param m01 76 * 0x1 in the matrix. 77 * @param m02 78 * 0x2 in the matrix. 79 * @param m10 80 * 1x0 in the matrix. 81 * @param m11 82 * 1x1 in the matrix. 83 * @param m12 84 * 1x2 in the matrix. 85 * @param m20 86 * 2x0 in the matrix. 87 * @param m21 88 * 2x1 in the matrix. 89 * @param m22 90 * 2x2 in the matrix. 91 */ Matrix3f(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)92 public Matrix3f(float m00, float m01, float m02, float m10, float m11, 93 float m12, float m20, float m21, float m22) { 94 95 this.m00 = m00; 96 this.m01 = m01; 97 this.m02 = m02; 98 this.m10 = m10; 99 this.m11 = m11; 100 this.m12 = m12; 101 this.m20 = m20; 102 this.m21 = m21; 103 this.m22 = m22; 104 } 105 106 /** 107 * Copy constructor that creates a new <code>Matrix3f</code> object that 108 * is the same as the provided matrix. 109 * 110 * @param mat 111 * the matrix to copy. 112 */ Matrix3f(Matrix3f mat)113 public Matrix3f(Matrix3f mat) { 114 set(mat); 115 } 116 117 /** 118 * Takes the absolute value of all matrix fields locally. 119 */ absoluteLocal()120 public void absoluteLocal() { 121 m00 = FastMath.abs(m00); 122 m01 = FastMath.abs(m01); 123 m02 = FastMath.abs(m02); 124 m10 = FastMath.abs(m10); 125 m11 = FastMath.abs(m11); 126 m12 = FastMath.abs(m12); 127 m20 = FastMath.abs(m20); 128 m21 = FastMath.abs(m21); 129 m22 = FastMath.abs(m22); 130 } 131 132 /** 133 * <code>copy</code> transfers the contents of a given matrix to this 134 * matrix. If a null matrix is supplied, this matrix is set to the identity 135 * matrix. 136 * 137 * @param matrix 138 * the matrix to copy. 139 * @return this 140 */ set(Matrix3f matrix)141 public Matrix3f set(Matrix3f matrix) { 142 if (null == matrix) { 143 loadIdentity(); 144 } else { 145 m00 = matrix.m00; 146 m01 = matrix.m01; 147 m02 = matrix.m02; 148 m10 = matrix.m10; 149 m11 = matrix.m11; 150 m12 = matrix.m12; 151 m20 = matrix.m20; 152 m21 = matrix.m21; 153 m22 = matrix.m22; 154 } 155 return this; 156 } 157 158 /** 159 * <code>get</code> retrieves a value from the matrix at the given 160 * position. If the position is invalid a <code>JmeException</code> is 161 * thrown. 162 * 163 * @param i 164 * the row index. 165 * @param j 166 * the colum index. 167 * @return the value at (i, j). 168 */ 169 @SuppressWarnings("fallthrough") get(int i, int j)170 public float get(int i, int j) { 171 switch (i) { 172 case 0: 173 switch (j) { 174 case 0: 175 return m00; 176 case 1: 177 return m01; 178 case 2: 179 return m02; 180 } 181 case 1: 182 switch (j) { 183 case 0: 184 return m10; 185 case 1: 186 return m11; 187 case 2: 188 return m12; 189 } 190 case 2: 191 switch (j) { 192 case 0: 193 return m20; 194 case 1: 195 return m21; 196 case 2: 197 return m22; 198 } 199 } 200 201 logger.warning("Invalid matrix index."); 202 throw new IllegalArgumentException("Invalid indices into matrix."); 203 } 204 205 /** 206 * <code>get(float[])</code> returns the matrix in row-major or column-major order. 207 * 208 * @param data 209 * The array to return the data into. This array can be 9 or 16 floats in size. 210 * Only the upper 3x3 are assigned to in the case of a 16 element array. 211 * @param rowMajor 212 * True for row major storage in the array (translation in elements 3, 7, 11 for a 4x4), 213 * false for column major (translation in elements 12, 13, 14 for a 4x4). 214 */ get(float[] data, boolean rowMajor)215 public void get(float[] data, boolean rowMajor) { 216 if (data.length == 9) { 217 if (rowMajor) { 218 data[0] = m00; 219 data[1] = m01; 220 data[2] = m02; 221 data[3] = m10; 222 data[4] = m11; 223 data[5] = m12; 224 data[6] = m20; 225 data[7] = m21; 226 data[8] = m22; 227 } else { 228 data[0] = m00; 229 data[1] = m10; 230 data[2] = m20; 231 data[3] = m01; 232 data[4] = m11; 233 data[5] = m21; 234 data[6] = m02; 235 data[7] = m12; 236 data[8] = m22; 237 } 238 } else if (data.length == 16) { 239 if (rowMajor) { 240 data[0] = m00; 241 data[1] = m01; 242 data[2] = m02; 243 data[4] = m10; 244 data[5] = m11; 245 data[6] = m12; 246 data[8] = m20; 247 data[9] = m21; 248 data[10] = m22; 249 } else { 250 data[0] = m00; 251 data[1] = m10; 252 data[2] = m20; 253 data[4] = m01; 254 data[5] = m11; 255 data[6] = m21; 256 data[8] = m02; 257 data[9] = m12; 258 data[10] = m22; 259 } 260 } else { 261 throw new IndexOutOfBoundsException("Array size must be 9 or 16 in Matrix3f.get()."); 262 } 263 } 264 265 /** 266 * <code>getColumn</code> returns one of three columns specified by the 267 * parameter. This column is returned as a <code>Vector3f</code> object. 268 * 269 * @param i 270 * the column to retrieve. Must be between 0 and 2. 271 * @return the column specified by the index. 272 */ getColumn(int i)273 public Vector3f getColumn(int i) { 274 return getColumn(i, null); 275 } 276 277 /** 278 * <code>getColumn</code> returns one of three columns specified by the 279 * parameter. This column is returned as a <code>Vector3f</code> object. 280 * 281 * @param i 282 * the column to retrieve. Must be between 0 and 2. 283 * @param store 284 * the vector object to store the result in. if null, a new one 285 * is created. 286 * @return the column specified by the index. 287 */ getColumn(int i, Vector3f store)288 public Vector3f getColumn(int i, Vector3f store) { 289 if (store == null) { 290 store = new Vector3f(); 291 } 292 switch (i) { 293 case 0: 294 store.x = m00; 295 store.y = m10; 296 store.z = m20; 297 break; 298 case 1: 299 store.x = m01; 300 store.y = m11; 301 store.z = m21; 302 break; 303 case 2: 304 store.x = m02; 305 store.y = m12; 306 store.z = m22; 307 break; 308 default: 309 logger.warning("Invalid column index."); 310 throw new IllegalArgumentException("Invalid column index. " + i); 311 } 312 return store; 313 } 314 315 /** 316 * <code>getColumn</code> returns one of three rows as specified by the 317 * parameter. This row is returned as a <code>Vector3f</code> object. 318 * 319 * @param i 320 * the row to retrieve. Must be between 0 and 2. 321 * @return the row specified by the index. 322 */ getRow(int i)323 public Vector3f getRow(int i) { 324 return getRow(i, null); 325 } 326 327 /** 328 * <code>getRow</code> returns one of three rows as specified by the 329 * parameter. This row is returned as a <code>Vector3f</code> object. 330 * 331 * @param i 332 * the row to retrieve. Must be between 0 and 2. 333 * @param store 334 * the vector object to store the result in. if null, a new one 335 * is created. 336 * @return the row specified by the index. 337 */ getRow(int i, Vector3f store)338 public Vector3f getRow(int i, Vector3f store) { 339 if (store == null) { 340 store = new Vector3f(); 341 } 342 switch (i) { 343 case 0: 344 store.x = m00; 345 store.y = m01; 346 store.z = m02; 347 break; 348 case 1: 349 store.x = m10; 350 store.y = m11; 351 store.z = m12; 352 break; 353 case 2: 354 store.x = m20; 355 store.y = m21; 356 store.z = m22; 357 break; 358 default: 359 logger.warning("Invalid row index."); 360 throw new IllegalArgumentException("Invalid row index. " + i); 361 } 362 return store; 363 } 364 365 /** 366 * <code>toFloatBuffer</code> returns a FloatBuffer object that contains 367 * the matrix data. 368 * 369 * @return matrix data as a FloatBuffer. 370 */ toFloatBuffer()371 public FloatBuffer toFloatBuffer() { 372 FloatBuffer fb = BufferUtils.createFloatBuffer(9); 373 374 fb.put(m00).put(m01).put(m02); 375 fb.put(m10).put(m11).put(m12); 376 fb.put(m20).put(m21).put(m22); 377 fb.rewind(); 378 return fb; 379 } 380 381 /** 382 * <code>fillFloatBuffer</code> fills a FloatBuffer object with the matrix 383 * data. 384 * 385 * @param fb 386 * the buffer to fill, starting at current position. Must have 387 * room for 9 more floats. 388 * @return matrix data as a FloatBuffer. (position is advanced by 9 and any 389 * limit set is not changed). 390 */ fillFloatBuffer(FloatBuffer fb, boolean columnMajor)391 public FloatBuffer fillFloatBuffer(FloatBuffer fb, boolean columnMajor) { 392 // if (columnMajor){ 393 // fb.put(m00).put(m10).put(m20); 394 // fb.put(m01).put(m11).put(m21); 395 // fb.put(m02).put(m12).put(m22); 396 // }else{ 397 // fb.put(m00).put(m01).put(m02); 398 // fb.put(m10).put(m11).put(m12); 399 // fb.put(m20).put(m21).put(m22); 400 // } 401 402 TempVars vars = TempVars.get(); 403 404 405 fillFloatArray(vars.matrixWrite, columnMajor); 406 fb.put(vars.matrixWrite, 0, 9); 407 408 vars.release(); 409 410 return fb; 411 } 412 fillFloatArray(float[] f, boolean columnMajor)413 public void fillFloatArray(float[] f, boolean columnMajor) { 414 if (columnMajor) { 415 f[ 0] = m00; 416 f[ 1] = m10; 417 f[ 2] = m20; 418 f[ 3] = m01; 419 f[ 4] = m11; 420 f[ 5] = m21; 421 f[ 6] = m02; 422 f[ 7] = m12; 423 f[ 8] = m22; 424 } else { 425 f[ 0] = m00; 426 f[ 1] = m01; 427 f[ 2] = m02; 428 f[ 3] = m10; 429 f[ 4] = m11; 430 f[ 5] = m12; 431 f[ 6] = m20; 432 f[ 7] = m21; 433 f[ 8] = m22; 434 } 435 } 436 437 /** 438 * 439 * <code>setColumn</code> sets a particular column of this matrix to that 440 * represented by the provided vector. 441 * 442 * @param i 443 * the column to set. 444 * @param column 445 * the data to set. 446 * @return this 447 */ setColumn(int i, Vector3f column)448 public Matrix3f setColumn(int i, Vector3f column) { 449 450 if (column == null) { 451 logger.warning("Column is null. Ignoring."); 452 return this; 453 } 454 switch (i) { 455 case 0: 456 m00 = column.x; 457 m10 = column.y; 458 m20 = column.z; 459 break; 460 case 1: 461 m01 = column.x; 462 m11 = column.y; 463 m21 = column.z; 464 break; 465 case 2: 466 m02 = column.x; 467 m12 = column.y; 468 m22 = column.z; 469 break; 470 default: 471 logger.warning("Invalid column index."); 472 throw new IllegalArgumentException("Invalid column index. " + i); 473 } 474 return this; 475 } 476 477 /** 478 * 479 * <code>setRow</code> sets a particular row of this matrix to that 480 * represented by the provided vector. 481 * 482 * @param i 483 * the row to set. 484 * @param row 485 * the data to set. 486 * @return this 487 */ setRow(int i, Vector3f row)488 public Matrix3f setRow(int i, Vector3f row) { 489 490 if (row == null) { 491 logger.warning("Row is null. Ignoring."); 492 return this; 493 } 494 switch (i) { 495 case 0: 496 m00 = row.x; 497 m01 = row.y; 498 m02 = row.z; 499 break; 500 case 1: 501 m10 = row.x; 502 m11 = row.y; 503 m12 = row.z; 504 break; 505 case 2: 506 m20 = row.x; 507 m21 = row.y; 508 m22 = row.z; 509 break; 510 default: 511 logger.warning("Invalid row index."); 512 throw new IllegalArgumentException("Invalid row index. " + i); 513 } 514 return this; 515 } 516 517 /** 518 * <code>set</code> places a given value into the matrix at the given 519 * position. If the position is invalid a <code>JmeException</code> is 520 * thrown. 521 * 522 * @param i 523 * the row index. 524 * @param j 525 * the colum index. 526 * @param value 527 * the value for (i, j). 528 * @return this 529 */ 530 @SuppressWarnings("fallthrough") set(int i, int j, float value)531 public Matrix3f set(int i, int j, float value) { 532 switch (i) { 533 case 0: 534 switch (j) { 535 case 0: 536 m00 = value; 537 return this; 538 case 1: 539 m01 = value; 540 return this; 541 case 2: 542 m02 = value; 543 return this; 544 } 545 case 1: 546 switch (j) { 547 case 0: 548 m10 = value; 549 return this; 550 case 1: 551 m11 = value; 552 return this; 553 case 2: 554 m12 = value; 555 return this; 556 } 557 case 2: 558 switch (j) { 559 case 0: 560 m20 = value; 561 return this; 562 case 1: 563 m21 = value; 564 return this; 565 case 2: 566 m22 = value; 567 return this; 568 } 569 } 570 571 logger.warning("Invalid matrix index."); 572 throw new IllegalArgumentException("Invalid indices into matrix."); 573 } 574 575 /** 576 * 577 * <code>set</code> sets the values of the matrix to those supplied by the 578 * 3x3 two dimenion array. 579 * 580 * @param matrix 581 * the new values of the matrix. 582 * @throws JmeException 583 * if the array is not of size 9. 584 * @return this 585 */ set(float[][] matrix)586 public Matrix3f set(float[][] matrix) { 587 if (matrix.length != 3 || matrix[0].length != 3) { 588 throw new IllegalArgumentException( 589 "Array must be of size 9."); 590 } 591 592 m00 = matrix[0][0]; 593 m01 = matrix[0][1]; 594 m02 = matrix[0][2]; 595 m10 = matrix[1][0]; 596 m11 = matrix[1][1]; 597 m12 = matrix[1][2]; 598 m20 = matrix[2][0]; 599 m21 = matrix[2][1]; 600 m22 = matrix[2][2]; 601 602 return this; 603 } 604 605 /** 606 * Recreate Matrix using the provided axis. 607 * 608 * @param uAxis 609 * Vector3f 610 * @param vAxis 611 * Vector3f 612 * @param wAxis 613 * Vector3f 614 */ fromAxes(Vector3f uAxis, Vector3f vAxis, Vector3f wAxis)615 public void fromAxes(Vector3f uAxis, Vector3f vAxis, Vector3f wAxis) { 616 m00 = uAxis.x; 617 m10 = uAxis.y; 618 m20 = uAxis.z; 619 620 m01 = vAxis.x; 621 m11 = vAxis.y; 622 m21 = vAxis.z; 623 624 m02 = wAxis.x; 625 m12 = wAxis.y; 626 m22 = wAxis.z; 627 } 628 629 /** 630 * <code>set</code> sets the values of this matrix from an array of 631 * values assuming that the data is rowMajor order; 632 * 633 * @param matrix 634 * the matrix to set the value to. 635 * @return this 636 */ set(float[] matrix)637 public Matrix3f set(float[] matrix) { 638 return set(matrix, true); 639 } 640 641 /** 642 * <code>set</code> sets the values of this matrix from an array of 643 * values; 644 * 645 * @param matrix 646 * the matrix to set the value to. 647 * @param rowMajor 648 * whether the incoming data is in row or column major order. 649 * @return this 650 */ set(float[] matrix, boolean rowMajor)651 public Matrix3f set(float[] matrix, boolean rowMajor) { 652 if (matrix.length != 9) { 653 throw new IllegalArgumentException( 654 "Array must be of size 9."); 655 } 656 657 if (rowMajor) { 658 m00 = matrix[0]; 659 m01 = matrix[1]; 660 m02 = matrix[2]; 661 m10 = matrix[3]; 662 m11 = matrix[4]; 663 m12 = matrix[5]; 664 m20 = matrix[6]; 665 m21 = matrix[7]; 666 m22 = matrix[8]; 667 } else { 668 m00 = matrix[0]; 669 m01 = matrix[3]; 670 m02 = matrix[6]; 671 m10 = matrix[1]; 672 m11 = matrix[4]; 673 m12 = matrix[7]; 674 m20 = matrix[2]; 675 m21 = matrix[5]; 676 m22 = matrix[8]; 677 } 678 return this; 679 } 680 681 /** 682 * 683 * <code>set</code> defines the values of the matrix based on a supplied 684 * <code>Quaternion</code>. It should be noted that all previous values 685 * will be overridden. 686 * 687 * @param quaternion 688 * the quaternion to create a rotational matrix from. 689 * @return this 690 */ set(Quaternion quaternion)691 public Matrix3f set(Quaternion quaternion) { 692 return quaternion.toRotationMatrix(this); 693 } 694 695 /** 696 * <code>loadIdentity</code> sets this matrix to the identity matrix. 697 * Where all values are zero except those along the diagonal which are one. 698 * 699 */ loadIdentity()700 public void loadIdentity() { 701 m01 = m02 = m10 = m12 = m20 = m21 = 0; 702 m00 = m11 = m22 = 1; 703 } 704 705 /** 706 * @return true if this matrix is identity 707 */ isIdentity()708 public boolean isIdentity() { 709 return (m00 == 1 && m01 == 0 && m02 == 0) 710 && (m10 == 0 && m11 == 1 && m12 == 0) 711 && (m20 == 0 && m21 == 0 && m22 == 1); 712 } 713 714 /** 715 * <code>fromAngleAxis</code> sets this matrix4f to the values specified 716 * by an angle and an axis of rotation. This method creates an object, so 717 * use fromAngleNormalAxis if your axis is already normalized. 718 * 719 * @param angle 720 * the angle to rotate (in radians). 721 * @param axis 722 * the axis of rotation. 723 */ fromAngleAxis(float angle, Vector3f axis)724 public void fromAngleAxis(float angle, Vector3f axis) { 725 Vector3f normAxis = axis.normalize(); 726 fromAngleNormalAxis(angle, normAxis); 727 } 728 729 /** 730 * <code>fromAngleNormalAxis</code> sets this matrix4f to the values 731 * specified by an angle and a normalized axis of rotation. 732 * 733 * @param angle 734 * the angle to rotate (in radians). 735 * @param axis 736 * the axis of rotation (already normalized). 737 */ fromAngleNormalAxis(float angle, Vector3f axis)738 public void fromAngleNormalAxis(float angle, Vector3f axis) { 739 float fCos = FastMath.cos(angle); 740 float fSin = FastMath.sin(angle); 741 float fOneMinusCos = ((float) 1.0) - fCos; 742 float fX2 = axis.x * axis.x; 743 float fY2 = axis.y * axis.y; 744 float fZ2 = axis.z * axis.z; 745 float fXYM = axis.x * axis.y * fOneMinusCos; 746 float fXZM = axis.x * axis.z * fOneMinusCos; 747 float fYZM = axis.y * axis.z * fOneMinusCos; 748 float fXSin = axis.x * fSin; 749 float fYSin = axis.y * fSin; 750 float fZSin = axis.z * fSin; 751 752 m00 = fX2 * fOneMinusCos + fCos; 753 m01 = fXYM - fZSin; 754 m02 = fXZM + fYSin; 755 m10 = fXYM + fZSin; 756 m11 = fY2 * fOneMinusCos + fCos; 757 m12 = fYZM - fXSin; 758 m20 = fXZM - fYSin; 759 m21 = fYZM + fXSin; 760 m22 = fZ2 * fOneMinusCos + fCos; 761 } 762 763 /** 764 * <code>mult</code> multiplies this matrix by a given matrix. The result 765 * matrix is returned as a new object. If the given matrix is null, a null 766 * matrix is returned. 767 * 768 * @param mat 769 * the matrix to multiply this matrix by. 770 * @return the result matrix. 771 */ mult(Matrix3f mat)772 public Matrix3f mult(Matrix3f mat) { 773 return mult(mat, null); 774 } 775 776 /** 777 * <code>mult</code> multiplies this matrix by a given matrix. The result 778 * matrix is returned as a new object. 779 * 780 * @param mat 781 * the matrix to multiply this matrix by. 782 * @param product 783 * the matrix to store the result in. if null, a new matrix3f is 784 * created. It is safe for mat and product to be the same object. 785 * @return a matrix3f object containing the result of this operation 786 */ mult(Matrix3f mat, Matrix3f product)787 public Matrix3f mult(Matrix3f mat, Matrix3f product) { 788 789 float temp00, temp01, temp02; 790 float temp10, temp11, temp12; 791 float temp20, temp21, temp22; 792 793 if (product == null) { 794 product = new Matrix3f(); 795 } 796 temp00 = m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20; 797 temp01 = m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21; 798 temp02 = m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22; 799 temp10 = m10 * mat.m00 + m11 * mat.m10 + m12 * mat.m20; 800 temp11 = m10 * mat.m01 + m11 * mat.m11 + m12 * mat.m21; 801 temp12 = m10 * mat.m02 + m11 * mat.m12 + m12 * mat.m22; 802 temp20 = m20 * mat.m00 + m21 * mat.m10 + m22 * mat.m20; 803 temp21 = m20 * mat.m01 + m21 * mat.m11 + m22 * mat.m21; 804 temp22 = m20 * mat.m02 + m21 * mat.m12 + m22 * mat.m22; 805 806 product.m00 = temp00; 807 product.m01 = temp01; 808 product.m02 = temp02; 809 product.m10 = temp10; 810 product.m11 = temp11; 811 product.m12 = temp12; 812 product.m20 = temp20; 813 product.m21 = temp21; 814 product.m22 = temp22; 815 816 return product; 817 } 818 819 /** 820 * <code>mult</code> multiplies this matrix by a given 821 * <code>Vector3f</code> object. The result vector is returned. If the 822 * given vector is null, null will be returned. 823 * 824 * @param vec 825 * the vector to multiply this matrix by. 826 * @return the result vector. 827 */ mult(Vector3f vec)828 public Vector3f mult(Vector3f vec) { 829 return mult(vec, null); 830 } 831 832 /** 833 * Multiplies this 3x3 matrix by the 1x3 Vector vec and stores the result in 834 * product. 835 * 836 * @param vec 837 * The Vector3f to multiply. 838 * @param product 839 * The Vector3f to store the result, it is safe for this to be 840 * the same as vec. 841 * @return The given product vector. 842 */ mult(Vector3f vec, Vector3f product)843 public Vector3f mult(Vector3f vec, Vector3f product) { 844 845 if (null == product) { 846 product = new Vector3f(); 847 } 848 849 float x = vec.x; 850 float y = vec.y; 851 float z = vec.z; 852 853 product.x = m00 * x + m01 * y + m02 * z; 854 product.y = m10 * x + m11 * y + m12 * z; 855 product.z = m20 * x + m21 * y + m22 * z; 856 return product; 857 } 858 859 /** 860 * <code>multLocal</code> multiplies this matrix internally by 861 * a given float scale factor. 862 * 863 * @param scale 864 * the value to scale by. 865 * @return this Matrix3f 866 */ multLocal(float scale)867 public Matrix3f multLocal(float scale) { 868 m00 *= scale; 869 m01 *= scale; 870 m02 *= scale; 871 m10 *= scale; 872 m11 *= scale; 873 m12 *= scale; 874 m20 *= scale; 875 m21 *= scale; 876 m22 *= scale; 877 return this; 878 } 879 880 /** 881 * <code>multLocal</code> multiplies this matrix by a given 882 * <code>Vector3f</code> object. The result vector is stored inside the 883 * passed vector, then returned . If the given vector is null, null will be 884 * returned. 885 * 886 * @param vec 887 * the vector to multiply this matrix by. 888 * @return The passed vector after multiplication 889 */ multLocal(Vector3f vec)890 public Vector3f multLocal(Vector3f vec) { 891 if (vec == null) { 892 return null; 893 } 894 float x = vec.x; 895 float y = vec.y; 896 vec.x = m00 * x + m01 * y + m02 * vec.z; 897 vec.y = m10 * x + m11 * y + m12 * vec.z; 898 vec.z = m20 * x + m21 * y + m22 * vec.z; 899 return vec; 900 } 901 902 /** 903 * <code>mult</code> multiplies this matrix by a given matrix. The result 904 * matrix is saved in the current matrix. If the given matrix is null, 905 * nothing happens. The current matrix is returned. This is equivalent to 906 * this*=mat 907 * 908 * @param mat 909 * the matrix to multiply this matrix by. 910 * @return This matrix, after the multiplication 911 */ multLocal(Matrix3f mat)912 public Matrix3f multLocal(Matrix3f mat) { 913 return mult(mat, this); 914 } 915 916 /** 917 * Transposes this matrix in place. Returns this matrix for chaining 918 * 919 * @return This matrix after transpose 920 */ transposeLocal()921 public Matrix3f transposeLocal() { 922 // float[] tmp = new float[9]; 923 // get(tmp, false); 924 // set(tmp, true); 925 926 float tmp = m01; 927 m01 = m10; 928 m10 = tmp; 929 930 tmp = m02; 931 m02 = m20; 932 m20 = tmp; 933 934 tmp = m12; 935 m12 = m21; 936 m21 = tmp; 937 938 return this; 939 } 940 941 /** 942 * Inverts this matrix as a new Matrix3f. 943 * 944 * @return The new inverse matrix 945 */ invert()946 public Matrix3f invert() { 947 return invert(null); 948 } 949 950 /** 951 * Inverts this matrix and stores it in the given store. 952 * 953 * @return The store 954 */ invert(Matrix3f store)955 public Matrix3f invert(Matrix3f store) { 956 if (store == null) { 957 store = new Matrix3f(); 958 } 959 960 float det = determinant(); 961 if (FastMath.abs(det) <= FastMath.FLT_EPSILON) { 962 return store.zero(); 963 } 964 965 store.m00 = m11 * m22 - m12 * m21; 966 store.m01 = m02 * m21 - m01 * m22; 967 store.m02 = m01 * m12 - m02 * m11; 968 store.m10 = m12 * m20 - m10 * m22; 969 store.m11 = m00 * m22 - m02 * m20; 970 store.m12 = m02 * m10 - m00 * m12; 971 store.m20 = m10 * m21 - m11 * m20; 972 store.m21 = m01 * m20 - m00 * m21; 973 store.m22 = m00 * m11 - m01 * m10; 974 975 store.multLocal(1f / det); 976 return store; 977 } 978 979 /** 980 * Inverts this matrix locally. 981 * 982 * @return this 983 */ invertLocal()984 public Matrix3f invertLocal() { 985 float det = determinant(); 986 if (FastMath.abs(det) <= 0f) { 987 return zero(); 988 } 989 990 float f00 = m11 * m22 - m12 * m21; 991 float f01 = m02 * m21 - m01 * m22; 992 float f02 = m01 * m12 - m02 * m11; 993 float f10 = m12 * m20 - m10 * m22; 994 float f11 = m00 * m22 - m02 * m20; 995 float f12 = m02 * m10 - m00 * m12; 996 float f20 = m10 * m21 - m11 * m20; 997 float f21 = m01 * m20 - m00 * m21; 998 float f22 = m00 * m11 - m01 * m10; 999 1000 m00 = f00; 1001 m01 = f01; 1002 m02 = f02; 1003 m10 = f10; 1004 m11 = f11; 1005 m12 = f12; 1006 m20 = f20; 1007 m21 = f21; 1008 m22 = f22; 1009 1010 multLocal(1f / det); 1011 return this; 1012 } 1013 1014 /** 1015 * Returns a new matrix representing the adjoint of this matrix. 1016 * 1017 * @return The adjoint matrix 1018 */ adjoint()1019 public Matrix3f adjoint() { 1020 return adjoint(null); 1021 } 1022 1023 /** 1024 * Places the adjoint of this matrix in store (creates store if null.) 1025 * 1026 * @param store 1027 * The matrix to store the result in. If null, a new matrix is created. 1028 * @return store 1029 */ adjoint(Matrix3f store)1030 public Matrix3f adjoint(Matrix3f store) { 1031 if (store == null) { 1032 store = new Matrix3f(); 1033 } 1034 1035 store.m00 = m11 * m22 - m12 * m21; 1036 store.m01 = m02 * m21 - m01 * m22; 1037 store.m02 = m01 * m12 - m02 * m11; 1038 store.m10 = m12 * m20 - m10 * m22; 1039 store.m11 = m00 * m22 - m02 * m20; 1040 store.m12 = m02 * m10 - m00 * m12; 1041 store.m20 = m10 * m21 - m11 * m20; 1042 store.m21 = m01 * m20 - m00 * m21; 1043 store.m22 = m00 * m11 - m01 * m10; 1044 1045 return store; 1046 } 1047 1048 /** 1049 * <code>determinant</code> generates the determinant of this matrix. 1050 * 1051 * @return the determinant 1052 */ determinant()1053 public float determinant() { 1054 float fCo00 = m11 * m22 - m12 * m21; 1055 float fCo10 = m12 * m20 - m10 * m22; 1056 float fCo20 = m10 * m21 - m11 * m20; 1057 float fDet = m00 * fCo00 + m01 * fCo10 + m02 * fCo20; 1058 return fDet; 1059 } 1060 1061 /** 1062 * Sets all of the values in this matrix to zero. 1063 * 1064 * @return this matrix 1065 */ zero()1066 public Matrix3f zero() { 1067 m00 = m01 = m02 = m10 = m11 = m12 = m20 = m21 = m22 = 0.0f; 1068 return this; 1069 } 1070 1071 /** 1072 * <code>transpose</code> <b>locally</b> transposes this Matrix. 1073 * This is inconsistent with general value vs local semantics, but is 1074 * preserved for backwards compatibility. Use transposeNew() to transpose 1075 * to a new object (value). 1076 * 1077 * @return this object for chaining. 1078 */ transpose()1079 public Matrix3f transpose() { 1080 return transposeLocal(); 1081 } 1082 1083 /** 1084 * <code>transposeNew</code> returns a transposed version of this matrix. 1085 * 1086 * @return The new Matrix3f object. 1087 */ transposeNew()1088 public Matrix3f transposeNew() { 1089 Matrix3f ret = new Matrix3f(m00, m10, m20, m01, m11, m21, m02, m12, m22); 1090 return ret; 1091 } 1092 1093 /** 1094 * <code>toString</code> returns the string representation of this object. 1095 * It is in a format of a 3x3 matrix. For example, an identity matrix would 1096 * be represented by the following string. com.jme.math.Matrix3f <br>[<br> 1097 * 1.0 0.0 0.0 <br> 1098 * 0.0 1.0 0.0 <br> 1099 * 0.0 0.0 1.0 <br>]<br> 1100 * 1101 * @return the string representation of this object. 1102 */ 1103 @Override toString()1104 public String toString() { 1105 StringBuilder result = new StringBuilder("Matrix3f\n[\n"); 1106 result.append(" "); 1107 result.append(m00); 1108 result.append(" "); 1109 result.append(m01); 1110 result.append(" "); 1111 result.append(m02); 1112 result.append(" \n"); 1113 result.append(" "); 1114 result.append(m10); 1115 result.append(" "); 1116 result.append(m11); 1117 result.append(" "); 1118 result.append(m12); 1119 result.append(" \n"); 1120 result.append(" "); 1121 result.append(m20); 1122 result.append(" "); 1123 result.append(m21); 1124 result.append(" "); 1125 result.append(m22); 1126 result.append(" \n]"); 1127 return result.toString(); 1128 } 1129 1130 /** 1131 * 1132 * <code>hashCode</code> returns the hash code value as an integer and is 1133 * supported for the benefit of hashing based collection classes such as 1134 * Hashtable, HashMap, HashSet etc. 1135 * 1136 * @return the hashcode for this instance of Matrix4f. 1137 * @see java.lang.Object#hashCode() 1138 */ 1139 @Override hashCode()1140 public int hashCode() { 1141 int hash = 37; 1142 hash = 37 * hash + Float.floatToIntBits(m00); 1143 hash = 37 * hash + Float.floatToIntBits(m01); 1144 hash = 37 * hash + Float.floatToIntBits(m02); 1145 1146 hash = 37 * hash + Float.floatToIntBits(m10); 1147 hash = 37 * hash + Float.floatToIntBits(m11); 1148 hash = 37 * hash + Float.floatToIntBits(m12); 1149 1150 hash = 37 * hash + Float.floatToIntBits(m20); 1151 hash = 37 * hash + Float.floatToIntBits(m21); 1152 hash = 37 * hash + Float.floatToIntBits(m22); 1153 1154 return hash; 1155 } 1156 1157 /** 1158 * are these two matrices the same? they are is they both have the same mXX values. 1159 * 1160 * @param o 1161 * the object to compare for equality 1162 * @return true if they are equal 1163 */ 1164 @Override equals(Object o)1165 public boolean equals(Object o) { 1166 if (!(o instanceof Matrix3f) || o == null) { 1167 return false; 1168 } 1169 1170 if (this == o) { 1171 return true; 1172 } 1173 1174 Matrix3f comp = (Matrix3f) o; 1175 if (Float.compare(m00, comp.m00) != 0) { 1176 return false; 1177 } 1178 if (Float.compare(m01, comp.m01) != 0) { 1179 return false; 1180 } 1181 if (Float.compare(m02, comp.m02) != 0) { 1182 return false; 1183 } 1184 1185 if (Float.compare(m10, comp.m10) != 0) { 1186 return false; 1187 } 1188 if (Float.compare(m11, comp.m11) != 0) { 1189 return false; 1190 } 1191 if (Float.compare(m12, comp.m12) != 0) { 1192 return false; 1193 } 1194 1195 if (Float.compare(m20, comp.m20) != 0) { 1196 return false; 1197 } 1198 if (Float.compare(m21, comp.m21) != 0) { 1199 return false; 1200 } 1201 if (Float.compare(m22, comp.m22) != 0) { 1202 return false; 1203 } 1204 1205 return true; 1206 } 1207 write(JmeExporter e)1208 public void write(JmeExporter e) throws IOException { 1209 OutputCapsule cap = e.getCapsule(this); 1210 cap.write(m00, "m00", 1); 1211 cap.write(m01, "m01", 0); 1212 cap.write(m02, "m02", 0); 1213 cap.write(m10, "m10", 0); 1214 cap.write(m11, "m11", 1); 1215 cap.write(m12, "m12", 0); 1216 cap.write(m20, "m20", 0); 1217 cap.write(m21, "m21", 0); 1218 cap.write(m22, "m22", 1); 1219 } 1220 read(JmeImporter e)1221 public void read(JmeImporter e) throws IOException { 1222 InputCapsule cap = e.getCapsule(this); 1223 m00 = cap.readFloat("m00", 1); 1224 m01 = cap.readFloat("m01", 0); 1225 m02 = cap.readFloat("m02", 0); 1226 m10 = cap.readFloat("m10", 0); 1227 m11 = cap.readFloat("m11", 1); 1228 m12 = cap.readFloat("m12", 0); 1229 m20 = cap.readFloat("m20", 0); 1230 m21 = cap.readFloat("m21", 0); 1231 m22 = cap.readFloat("m22", 1); 1232 } 1233 1234 /** 1235 * A function for creating a rotation matrix that rotates a vector called 1236 * "start" into another vector called "end". 1237 * 1238 * @param start 1239 * normalized non-zero starting vector 1240 * @param end 1241 * normalized non-zero ending vector 1242 * @see "Tomas M�ller, John Hughes \"Efficiently Building a Matrix to Rotate \ 1243 * One Vector to Another\" Journal of Graphics Tools, 4(4):1-4, 1999" 1244 */ fromStartEndVectors(Vector3f start, Vector3f end)1245 public void fromStartEndVectors(Vector3f start, Vector3f end) { 1246 Vector3f v = new Vector3f(); 1247 float e, h, f; 1248 1249 start.cross(end, v); 1250 e = start.dot(end); 1251 f = (e < 0) ? -e : e; 1252 1253 // if "from" and "to" vectors are nearly parallel 1254 if (f > 1.0f - FastMath.ZERO_TOLERANCE) { 1255 Vector3f u = new Vector3f(); 1256 Vector3f x = new Vector3f(); 1257 float c1, c2, c3; /* coefficients for later use */ 1258 int i, j; 1259 1260 x.x = (start.x > 0.0) ? start.x : -start.x; 1261 x.y = (start.y > 0.0) ? start.y : -start.y; 1262 x.z = (start.z > 0.0) ? start.z : -start.z; 1263 1264 if (x.x < x.y) { 1265 if (x.x < x.z) { 1266 x.x = 1.0f; 1267 x.y = x.z = 0.0f; 1268 } else { 1269 x.z = 1.0f; 1270 x.x = x.y = 0.0f; 1271 } 1272 } else { 1273 if (x.y < x.z) { 1274 x.y = 1.0f; 1275 x.x = x.z = 0.0f; 1276 } else { 1277 x.z = 1.0f; 1278 x.x = x.y = 0.0f; 1279 } 1280 } 1281 1282 u.x = x.x - start.x; 1283 u.y = x.y - start.y; 1284 u.z = x.z - start.z; 1285 v.x = x.x - end.x; 1286 v.y = x.y - end.y; 1287 v.z = x.z - end.z; 1288 1289 c1 = 2.0f / u.dot(u); 1290 c2 = 2.0f / v.dot(v); 1291 c3 = c1 * c2 * u.dot(v); 1292 1293 for (i = 0; i < 3; i++) { 1294 for (j = 0; j < 3; j++) { 1295 float val = -c1 * u.get(i) * u.get(j) - c2 * v.get(i) 1296 * v.get(j) + c3 * v.get(i) * u.get(j); 1297 set(i, j, val); 1298 } 1299 float val = get(i, i); 1300 set(i, i, val + 1.0f); 1301 } 1302 } else { 1303 // the most common case, unless "start"="end", or "start"=-"end" 1304 float hvx, hvz, hvxy, hvxz, hvyz; 1305 h = 1.0f / (1.0f + e); 1306 hvx = h * v.x; 1307 hvz = h * v.z; 1308 hvxy = hvx * v.y; 1309 hvxz = hvx * v.z; 1310 hvyz = hvz * v.y; 1311 set(0, 0, e + hvx * v.x); 1312 set(0, 1, hvxy - v.z); 1313 set(0, 2, hvxz + v.y); 1314 1315 set(1, 0, hvxy + v.z); 1316 set(1, 1, e + h * v.y * v.y); 1317 set(1, 2, hvyz - v.x); 1318 1319 set(2, 0, hvxz - v.y); 1320 set(2, 1, hvyz + v.x); 1321 set(2, 2, e + hvz * v.z); 1322 } 1323 } 1324 1325 /** 1326 * <code>scale</code> scales the operation performed by this matrix on a 1327 * per-component basis. 1328 * 1329 * @param scale 1330 * The scale applied to each of the X, Y and Z output values. 1331 */ scale(Vector3f scale)1332 public void scale(Vector3f scale) { 1333 m00 *= scale.x; 1334 m10 *= scale.x; 1335 m20 *= scale.x; 1336 m01 *= scale.y; 1337 m11 *= scale.y; 1338 m21 *= scale.y; 1339 m02 *= scale.z; 1340 m12 *= scale.z; 1341 m22 *= scale.z; 1342 } 1343 equalIdentity(Matrix3f mat)1344 static boolean equalIdentity(Matrix3f mat) { 1345 if (Math.abs(mat.m00 - 1) > 1e-4) { 1346 return false; 1347 } 1348 if (Math.abs(mat.m11 - 1) > 1e-4) { 1349 return false; 1350 } 1351 if (Math.abs(mat.m22 - 1) > 1e-4) { 1352 return false; 1353 } 1354 1355 if (Math.abs(mat.m01) > 1e-4) { 1356 return false; 1357 } 1358 if (Math.abs(mat.m02) > 1e-4) { 1359 return false; 1360 } 1361 1362 if (Math.abs(mat.m10) > 1e-4) { 1363 return false; 1364 } 1365 if (Math.abs(mat.m12) > 1e-4) { 1366 return false; 1367 } 1368 1369 if (Math.abs(mat.m20) > 1e-4) { 1370 return false; 1371 } 1372 if (Math.abs(mat.m21) > 1e-4) { 1373 return false; 1374 } 1375 1376 return true; 1377 } 1378 1379 @Override clone()1380 public Matrix3f clone() { 1381 try { 1382 return (Matrix3f) super.clone(); 1383 } catch (CloneNotSupportedException e) { 1384 throw new AssertionError(); // can not happen 1385 } 1386 } 1387 } 1388