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 */ 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 */ 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 */ 113 public Matrix3f(Matrix3f mat) { 114 set(mat); 115 } 116 117 /** 118 * Takes the absolute value of all matrix fields locally. 119 */ 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 */ 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") 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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") 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 Mller, John Hughes \"Efficiently Building a Matrix to Rotate \ 1243 * One Vector to Another\" Journal of Graphics Tools, 4(4):1-4, 1999" 1244 */ 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 */ 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 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 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