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>Matrix4f</code> defines and maintains a 4x4 matrix in row major order. 43 * This matrix is intended for use in a translation and rotational capacity. 44 * It provides convenience methods for creating the matrix from a multitude 45 * of sources. 46 * 47 * Matrices are stored assuming column vectors on the right, with the translation 48 * in the rightmost column. Element numbering is row,column, so m03 is the zeroth 49 * row, third column, which is the "x" translation part. This means that the implicit 50 * storage order is column major. However, the get() and set() functions on float 51 * arrays default to row major order! 52 * 53 * @author Mark Powell 54 * @author Joshua Slack 55 */ 56 public final class Matrix4f implements Savable, Cloneable, java.io.Serializable { 57 58 static final long serialVersionUID = 1; 59 60 private static final Logger logger = Logger.getLogger(Matrix4f.class.getName()); 61 public float m00, m01, m02, m03; 62 public float m10, m11, m12, m13; 63 public float m20, m21, m22, m23; 64 public float m30, m31, m32, m33; 65 public static final Matrix4f ZERO = new Matrix4f(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 66 public static final Matrix4f IDENTITY = new Matrix4f(); 67 68 /** 69 * Constructor instantiates a new <code>Matrix</code> that is set to the 70 * identity matrix. 71 * 72 */ Matrix4f()73 public Matrix4f() { 74 loadIdentity(); 75 } 76 77 /** 78 * constructs a matrix with the given values. 79 */ Matrix4f(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23, float m30, float m31, float m32, float m33)80 public Matrix4f(float m00, float m01, float m02, float m03, 81 float m10, float m11, float m12, float m13, 82 float m20, float m21, float m22, float m23, 83 float m30, float m31, float m32, float m33) { 84 85 this.m00 = m00; 86 this.m01 = m01; 87 this.m02 = m02; 88 this.m03 = m03; 89 this.m10 = m10; 90 this.m11 = m11; 91 this.m12 = m12; 92 this.m13 = m13; 93 this.m20 = m20; 94 this.m21 = m21; 95 this.m22 = m22; 96 this.m23 = m23; 97 this.m30 = m30; 98 this.m31 = m31; 99 this.m32 = m32; 100 this.m33 = m33; 101 } 102 103 /** 104 * Create a new Matrix4f, given data in column-major format. 105 * 106 * @param array 107 * An array of 16 floats in column-major format (translation in elements 12, 13 and 14). 108 */ Matrix4f(float[] array)109 public Matrix4f(float[] array) { 110 set(array, false); 111 } 112 113 /** 114 * Constructor instantiates a new <code>Matrix</code> that is set to the 115 * provided matrix. This constructor copies a given Matrix. If the provided 116 * matrix is null, the constructor sets the matrix to the identity. 117 * 118 * @param mat 119 * the matrix to copy. 120 */ Matrix4f(Matrix4f mat)121 public Matrix4f(Matrix4f mat) { 122 copy(mat); 123 } 124 125 /** 126 * <code>copy</code> transfers the contents of a given matrix to this 127 * matrix. If a null matrix is supplied, this matrix is set to the identity 128 * matrix. 129 * 130 * @param matrix 131 * the matrix to copy. 132 */ copy(Matrix4f matrix)133 public void copy(Matrix4f matrix) { 134 if (null == matrix) { 135 loadIdentity(); 136 } else { 137 m00 = matrix.m00; 138 m01 = matrix.m01; 139 m02 = matrix.m02; 140 m03 = matrix.m03; 141 m10 = matrix.m10; 142 m11 = matrix.m11; 143 m12 = matrix.m12; 144 m13 = matrix.m13; 145 m20 = matrix.m20; 146 m21 = matrix.m21; 147 m22 = matrix.m22; 148 m23 = matrix.m23; 149 m30 = matrix.m30; 150 m31 = matrix.m31; 151 m32 = matrix.m32; 152 m33 = matrix.m33; 153 } 154 } 155 fromFrame(Vector3f location, Vector3f direction, Vector3f up, Vector3f left)156 public void fromFrame(Vector3f location, Vector3f direction, Vector3f up, Vector3f left) { 157 loadIdentity(); 158 159 TempVars vars = TempVars.get(); 160 161 Vector3f f = vars.vect1.set(direction); 162 Vector3f s = vars.vect2.set(f).crossLocal(up); 163 Vector3f u = vars.vect3.set(s).crossLocal(f); 164 // s.normalizeLocal(); 165 // u.normalizeLocal(); 166 167 m00 = s.x; 168 m01 = s.y; 169 m02 = s.z; 170 171 m10 = u.x; 172 m11 = u.y; 173 m12 = u.z; 174 175 m20 = -f.x; 176 m21 = -f.y; 177 m22 = -f.z; 178 179 // m00 = -left.x; 180 // m10 = -left.y; 181 // m20 = -left.z; 182 // 183 // m01 = up.x; 184 // m11 = up.y; 185 // m21 = up.z; 186 // 187 // m02 = -direction.x; 188 // m12 = -direction.y; 189 // m22 = -direction.z; 190 // 191 192 Matrix4f transMatrix = vars.tempMat4; 193 transMatrix.loadIdentity(); 194 transMatrix.m03 = -location.x; 195 transMatrix.m13 = -location.y; 196 transMatrix.m23 = -location.z; 197 this.multLocal(transMatrix); 198 199 vars.release(); 200 201 // transMatrix.multLocal(this); 202 203 // set(transMatrix); 204 } 205 206 /** 207 * <code>get</code> retrieves the values of this object into 208 * a float array in row-major order. 209 * 210 * @param matrix 211 * the matrix to set the values into. 212 */ get(float[] matrix)213 public void get(float[] matrix) { 214 get(matrix, true); 215 } 216 217 /** 218 * <code>set</code> retrieves the values of this object into 219 * a float array. 220 * 221 * @param matrix 222 * the matrix to set the values into. 223 * @param rowMajor 224 * whether the outgoing data is in row or column major order. 225 */ get(float[] matrix, boolean rowMajor)226 public void get(float[] matrix, boolean rowMajor) { 227 if (matrix.length != 16) { 228 throw new IllegalArgumentException( 229 "Array must be of size 16."); 230 } 231 232 if (rowMajor) { 233 matrix[0] = m00; 234 matrix[1] = m01; 235 matrix[2] = m02; 236 matrix[3] = m03; 237 matrix[4] = m10; 238 matrix[5] = m11; 239 matrix[6] = m12; 240 matrix[7] = m13; 241 matrix[8] = m20; 242 matrix[9] = m21; 243 matrix[10] = m22; 244 matrix[11] = m23; 245 matrix[12] = m30; 246 matrix[13] = m31; 247 matrix[14] = m32; 248 matrix[15] = m33; 249 } else { 250 matrix[0] = m00; 251 matrix[4] = m01; 252 matrix[8] = m02; 253 matrix[12] = m03; 254 matrix[1] = m10; 255 matrix[5] = m11; 256 matrix[9] = m12; 257 matrix[13] = m13; 258 matrix[2] = m20; 259 matrix[6] = m21; 260 matrix[10] = m22; 261 matrix[14] = m23; 262 matrix[3] = m30; 263 matrix[7] = m31; 264 matrix[11] = m32; 265 matrix[15] = m33; 266 } 267 } 268 269 /** 270 * <code>get</code> retrieves a value from the matrix at the given 271 * position. If the position is invalid a <code>JmeException</code> is 272 * thrown. 273 * 274 * @param i 275 * the row index. 276 * @param j 277 * the colum index. 278 * @return the value at (i, j). 279 */ 280 @SuppressWarnings("fallthrough") get(int i, int j)281 public float get(int i, int j) { 282 switch (i) { 283 case 0: 284 switch (j) { 285 case 0: 286 return m00; 287 case 1: 288 return m01; 289 case 2: 290 return m02; 291 case 3: 292 return m03; 293 } 294 case 1: 295 switch (j) { 296 case 0: 297 return m10; 298 case 1: 299 return m11; 300 case 2: 301 return m12; 302 case 3: 303 return m13; 304 } 305 case 2: 306 switch (j) { 307 case 0: 308 return m20; 309 case 1: 310 return m21; 311 case 2: 312 return m22; 313 case 3: 314 return m23; 315 } 316 case 3: 317 switch (j) { 318 case 0: 319 return m30; 320 case 1: 321 return m31; 322 case 2: 323 return m32; 324 case 3: 325 return m33; 326 } 327 } 328 329 logger.warning("Invalid matrix index."); 330 throw new IllegalArgumentException("Invalid indices into matrix."); 331 } 332 333 /** 334 * <code>getColumn</code> returns one of three columns specified by the 335 * parameter. This column is returned as a float array of length 4. 336 * 337 * @param i 338 * the column to retrieve. Must be between 0 and 3. 339 * @return the column specified by the index. 340 */ getColumn(int i)341 public float[] getColumn(int i) { 342 return getColumn(i, null); 343 } 344 345 /** 346 * <code>getColumn</code> returns one of three columns specified by the 347 * parameter. This column is returned as a float[4]. 348 * 349 * @param i 350 * the column to retrieve. Must be between 0 and 3. 351 * @param store 352 * the float array to store the result in. if null, a new one 353 * is created. 354 * @return the column specified by the index. 355 */ getColumn(int i, float[] store)356 public float[] getColumn(int i, float[] store) { 357 if (store == null) { 358 store = new float[4]; 359 } 360 switch (i) { 361 case 0: 362 store[0] = m00; 363 store[1] = m10; 364 store[2] = m20; 365 store[3] = m30; 366 break; 367 case 1: 368 store[0] = m01; 369 store[1] = m11; 370 store[2] = m21; 371 store[3] = m31; 372 break; 373 case 2: 374 store[0] = m02; 375 store[1] = m12; 376 store[2] = m22; 377 store[3] = m32; 378 break; 379 case 3: 380 store[0] = m03; 381 store[1] = m13; 382 store[2] = m23; 383 store[3] = m33; 384 break; 385 default: 386 logger.warning("Invalid column index."); 387 throw new IllegalArgumentException("Invalid column index. " + i); 388 } 389 return store; 390 } 391 392 /** 393 * 394 * <code>setColumn</code> sets a particular column of this matrix to that 395 * represented by the provided vector. 396 * 397 * @param i 398 * the column to set. 399 * @param column 400 * the data to set. 401 */ setColumn(int i, float[] column)402 public void setColumn(int i, float[] column) { 403 404 if (column == null) { 405 logger.warning("Column is null. Ignoring."); 406 return; 407 } 408 switch (i) { 409 case 0: 410 m00 = column[0]; 411 m10 = column[1]; 412 m20 = column[2]; 413 m30 = column[3]; 414 break; 415 case 1: 416 m01 = column[0]; 417 m11 = column[1]; 418 m21 = column[2]; 419 m31 = column[3]; 420 break; 421 case 2: 422 m02 = column[0]; 423 m12 = column[1]; 424 m22 = column[2]; 425 m32 = column[3]; 426 break; 427 case 3: 428 m03 = column[0]; 429 m13 = column[1]; 430 m23 = column[2]; 431 m33 = column[3]; 432 break; 433 default: 434 logger.warning("Invalid column index."); 435 throw new IllegalArgumentException("Invalid column index. " + i); 436 } 437 } 438 439 /** 440 * <code>set</code> places a given value into the matrix at the given 441 * position. If the position is invalid a <code>JmeException</code> is 442 * thrown. 443 * 444 * @param i 445 * the row index. 446 * @param j 447 * the colum index. 448 * @param value 449 * the value for (i, j). 450 */ 451 @SuppressWarnings("fallthrough") set(int i, int j, float value)452 public void set(int i, int j, float value) { 453 switch (i) { 454 case 0: 455 switch (j) { 456 case 0: 457 m00 = value; 458 return; 459 case 1: 460 m01 = value; 461 return; 462 case 2: 463 m02 = value; 464 return; 465 case 3: 466 m03 = value; 467 return; 468 } 469 case 1: 470 switch (j) { 471 case 0: 472 m10 = value; 473 return; 474 case 1: 475 m11 = value; 476 return; 477 case 2: 478 m12 = value; 479 return; 480 case 3: 481 m13 = value; 482 return; 483 } 484 case 2: 485 switch (j) { 486 case 0: 487 m20 = value; 488 return; 489 case 1: 490 m21 = value; 491 return; 492 case 2: 493 m22 = value; 494 return; 495 case 3: 496 m23 = value; 497 return; 498 } 499 case 3: 500 switch (j) { 501 case 0: 502 m30 = value; 503 return; 504 case 1: 505 m31 = value; 506 return; 507 case 2: 508 m32 = value; 509 return; 510 case 3: 511 m33 = value; 512 return; 513 } 514 } 515 516 logger.warning("Invalid matrix index."); 517 throw new IllegalArgumentException("Invalid indices into matrix."); 518 } 519 520 /** 521 * <code>set</code> sets the values of this matrix from an array of 522 * values. 523 * 524 * @param matrix 525 * the matrix to set the value to. 526 * @throws JmeException 527 * if the array is not of size 16. 528 */ set(float[][] matrix)529 public void set(float[][] matrix) { 530 if (matrix.length != 4 || matrix[0].length != 4) { 531 throw new IllegalArgumentException( 532 "Array must be of size 16."); 533 } 534 535 m00 = matrix[0][0]; 536 m01 = matrix[0][1]; 537 m02 = matrix[0][2]; 538 m03 = matrix[0][3]; 539 m10 = matrix[1][0]; 540 m11 = matrix[1][1]; 541 m12 = matrix[1][2]; 542 m13 = matrix[1][3]; 543 m20 = matrix[2][0]; 544 m21 = matrix[2][1]; 545 m22 = matrix[2][2]; 546 m23 = matrix[2][3]; 547 m30 = matrix[3][0]; 548 m31 = matrix[3][1]; 549 m32 = matrix[3][2]; 550 m33 = matrix[3][3]; 551 } 552 553 /** 554 * <code>set</code> sets the values of this matrix from another matrix. 555 * 556 * @param matrix 557 * the matrix to read the value from. 558 */ set(Matrix4f matrix)559 public Matrix4f set(Matrix4f matrix) { 560 m00 = matrix.m00; 561 m01 = matrix.m01; 562 m02 = matrix.m02; 563 m03 = matrix.m03; 564 m10 = matrix.m10; 565 m11 = matrix.m11; 566 m12 = matrix.m12; 567 m13 = matrix.m13; 568 m20 = matrix.m20; 569 m21 = matrix.m21; 570 m22 = matrix.m22; 571 m23 = matrix.m23; 572 m30 = matrix.m30; 573 m31 = matrix.m31; 574 m32 = matrix.m32; 575 m33 = matrix.m33; 576 return this; 577 } 578 579 /** 580 * <code>set</code> sets the values of this matrix from an array of 581 * values assuming that the data is rowMajor order; 582 * 583 * @param matrix 584 * the matrix to set the value to. 585 */ set(float[] matrix)586 public void set(float[] matrix) { 587 set(matrix, true); 588 } 589 590 /** 591 * <code>set</code> sets the values of this matrix from an array of 592 * values; 593 * 594 * @param matrix 595 * the matrix to set the value to. 596 * @param rowMajor 597 * whether the incoming data is in row or column major order. 598 */ set(float[] matrix, boolean rowMajor)599 public void set(float[] matrix, boolean rowMajor) { 600 if (matrix.length != 16) { 601 throw new IllegalArgumentException( 602 "Array must be of size 16."); 603 } 604 605 if (rowMajor) { 606 m00 = matrix[0]; 607 m01 = matrix[1]; 608 m02 = matrix[2]; 609 m03 = matrix[3]; 610 m10 = matrix[4]; 611 m11 = matrix[5]; 612 m12 = matrix[6]; 613 m13 = matrix[7]; 614 m20 = matrix[8]; 615 m21 = matrix[9]; 616 m22 = matrix[10]; 617 m23 = matrix[11]; 618 m30 = matrix[12]; 619 m31 = matrix[13]; 620 m32 = matrix[14]; 621 m33 = matrix[15]; 622 } else { 623 m00 = matrix[0]; 624 m01 = matrix[4]; 625 m02 = matrix[8]; 626 m03 = matrix[12]; 627 m10 = matrix[1]; 628 m11 = matrix[5]; 629 m12 = matrix[9]; 630 m13 = matrix[13]; 631 m20 = matrix[2]; 632 m21 = matrix[6]; 633 m22 = matrix[10]; 634 m23 = matrix[14]; 635 m30 = matrix[3]; 636 m31 = matrix[7]; 637 m32 = matrix[11]; 638 m33 = matrix[15]; 639 } 640 } 641 transpose()642 public Matrix4f transpose() { 643 float[] tmp = new float[16]; 644 get(tmp, true); 645 Matrix4f mat = new Matrix4f(tmp); 646 return mat; 647 } 648 649 /** 650 * <code>transpose</code> locally transposes this Matrix. 651 * 652 * @return this object for chaining. 653 */ transposeLocal()654 public Matrix4f transposeLocal() { 655 float tmp = m01; 656 m01 = m10; 657 m10 = tmp; 658 659 tmp = m02; 660 m02 = m20; 661 m20 = tmp; 662 663 tmp = m03; 664 m03 = m30; 665 m30 = tmp; 666 667 tmp = m12; 668 m12 = m21; 669 m21 = tmp; 670 671 tmp = m13; 672 m13 = m31; 673 m31 = tmp; 674 675 tmp = m23; 676 m23 = m32; 677 m32 = tmp; 678 679 return this; 680 } 681 682 /** 683 * <code>toFloatBuffer</code> returns a FloatBuffer object that contains 684 * the matrix data. 685 * 686 * @return matrix data as a FloatBuffer. 687 */ toFloatBuffer()688 public FloatBuffer toFloatBuffer() { 689 return toFloatBuffer(false); 690 } 691 692 /** 693 * <code>toFloatBuffer</code> returns a FloatBuffer object that contains the 694 * matrix data. 695 * 696 * @param columnMajor 697 * if true, this buffer should be filled with column major data, 698 * otherwise it will be filled row major. 699 * @return matrix data as a FloatBuffer. The position is set to 0 for 700 * convenience. 701 */ toFloatBuffer(boolean columnMajor)702 public FloatBuffer toFloatBuffer(boolean columnMajor) { 703 FloatBuffer fb = BufferUtils.createFloatBuffer(16); 704 fillFloatBuffer(fb, columnMajor); 705 fb.rewind(); 706 return fb; 707 } 708 709 /** 710 * <code>fillFloatBuffer</code> fills a FloatBuffer object with 711 * the matrix data. 712 * @param fb the buffer to fill, must be correct size 713 * @return matrix data as a FloatBuffer. 714 */ fillFloatBuffer(FloatBuffer fb)715 public FloatBuffer fillFloatBuffer(FloatBuffer fb) { 716 return fillFloatBuffer(fb, false); 717 } 718 719 /** 720 * <code>fillFloatBuffer</code> fills a FloatBuffer object with the matrix 721 * data. 722 * 723 * @param fb 724 * the buffer to fill, starting at current position. Must have 725 * room for 16 more floats. 726 * @param columnMajor 727 * if true, this buffer should be filled with column major data, 728 * otherwise it will be filled row major. 729 * @return matrix data as a FloatBuffer. (position is advanced by 16 and any 730 * limit set is not changed). 731 */ fillFloatBuffer(FloatBuffer fb, boolean columnMajor)732 public FloatBuffer fillFloatBuffer(FloatBuffer fb, boolean columnMajor) { 733 // if (columnMajor) { 734 // fb.put(m00).put(m10).put(m20).put(m30); 735 // fb.put(m01).put(m11).put(m21).put(m31); 736 // fb.put(m02).put(m12).put(m22).put(m32); 737 // fb.put(m03).put(m13).put(m23).put(m33); 738 // } else { 739 // fb.put(m00).put(m01).put(m02).put(m03); 740 // fb.put(m10).put(m11).put(m12).put(m13); 741 // fb.put(m20).put(m21).put(m22).put(m23); 742 // fb.put(m30).put(m31).put(m32).put(m33); 743 // } 744 745 TempVars vars = TempVars.get(); 746 747 748 fillFloatArray(vars.matrixWrite, columnMajor); 749 fb.put(vars.matrixWrite, 0, 16); 750 751 vars.release(); 752 753 return fb; 754 } 755 fillFloatArray(float[] f, boolean columnMajor)756 public void fillFloatArray(float[] f, boolean columnMajor) { 757 if (columnMajor) { 758 f[ 0] = m00; 759 f[ 1] = m10; 760 f[ 2] = m20; 761 f[ 3] = m30; 762 f[ 4] = m01; 763 f[ 5] = m11; 764 f[ 6] = m21; 765 f[ 7] = m31; 766 f[ 8] = m02; 767 f[ 9] = m12; 768 f[10] = m22; 769 f[11] = m32; 770 f[12] = m03; 771 f[13] = m13; 772 f[14] = m23; 773 f[15] = m33; 774 } else { 775 f[ 0] = m00; 776 f[ 1] = m01; 777 f[ 2] = m02; 778 f[ 3] = m03; 779 f[ 4] = m10; 780 f[ 5] = m11; 781 f[ 6] = m12; 782 f[ 7] = m13; 783 f[ 8] = m20; 784 f[ 9] = m21; 785 f[10] = m22; 786 f[11] = m23; 787 f[12] = m30; 788 f[13] = m31; 789 f[14] = m32; 790 f[15] = m33; 791 } 792 } 793 794 /** 795 * <code>readFloatBuffer</code> reads value for this matrix from a FloatBuffer. 796 * @param fb the buffer to read from, must be correct size 797 * @return this data as a FloatBuffer. 798 */ readFloatBuffer(FloatBuffer fb)799 public Matrix4f readFloatBuffer(FloatBuffer fb) { 800 return readFloatBuffer(fb, false); 801 } 802 803 /** 804 * <code>readFloatBuffer</code> reads value for this matrix from a FloatBuffer. 805 * @param fb the buffer to read from, must be correct size 806 * @param columnMajor if true, this buffer should be filled with column 807 * major data, otherwise it will be filled row major. 808 * @return this data as a FloatBuffer. 809 */ readFloatBuffer(FloatBuffer fb, boolean columnMajor)810 public Matrix4f readFloatBuffer(FloatBuffer fb, boolean columnMajor) { 811 812 if (columnMajor) { 813 m00 = fb.get(); 814 m10 = fb.get(); 815 m20 = fb.get(); 816 m30 = fb.get(); 817 m01 = fb.get(); 818 m11 = fb.get(); 819 m21 = fb.get(); 820 m31 = fb.get(); 821 m02 = fb.get(); 822 m12 = fb.get(); 823 m22 = fb.get(); 824 m32 = fb.get(); 825 m03 = fb.get(); 826 m13 = fb.get(); 827 m23 = fb.get(); 828 m33 = fb.get(); 829 } else { 830 m00 = fb.get(); 831 m01 = fb.get(); 832 m02 = fb.get(); 833 m03 = fb.get(); 834 m10 = fb.get(); 835 m11 = fb.get(); 836 m12 = fb.get(); 837 m13 = fb.get(); 838 m20 = fb.get(); 839 m21 = fb.get(); 840 m22 = fb.get(); 841 m23 = fb.get(); 842 m30 = fb.get(); 843 m31 = fb.get(); 844 m32 = fb.get(); 845 m33 = fb.get(); 846 } 847 return this; 848 } 849 850 /** 851 * <code>loadIdentity</code> sets this matrix to the identity matrix, 852 * namely all zeros with ones along the diagonal. 853 * 854 */ loadIdentity()855 public void loadIdentity() { 856 m01 = m02 = m03 = 0.0f; 857 m10 = m12 = m13 = 0.0f; 858 m20 = m21 = m23 = 0.0f; 859 m30 = m31 = m32 = 0.0f; 860 m00 = m11 = m22 = m33 = 1.0f; 861 } 862 fromFrustum(float near, float far, float left, float right, float top, float bottom, boolean parallel)863 public void fromFrustum(float near, float far, float left, float right, float top, float bottom, boolean parallel) { 864 loadIdentity(); 865 if (parallel) { 866 // scale 867 m00 = 2.0f / (right - left); 868 //m11 = 2.0f / (bottom - top); 869 m11 = 2.0f / (top - bottom); 870 m22 = -2.0f / (far - near); 871 m33 = 1f; 872 873 // translation 874 m03 = -(right + left) / (right - left); 875 //m31 = -(bottom + top) / (bottom - top); 876 m13 = -(top + bottom) / (top - bottom); 877 m23 = -(far + near) / (far - near); 878 } else { 879 m00 = (2.0f * near) / (right - left); 880 m11 = (2.0f * near) / (top - bottom); 881 m32 = -1.0f; 882 m33 = -0.0f; 883 884 // A 885 m02 = (right + left) / (right - left); 886 887 // B 888 m12 = (top + bottom) / (top - bottom); 889 890 // C 891 m22 = -(far + near) / (far - near); 892 893 // D 894 m23 = -(2.0f * far * near) / (far - near); 895 } 896 } 897 898 /** 899 * <code>fromAngleAxis</code> sets this matrix4f to the values specified 900 * by an angle and an axis of rotation. This method creates an object, so 901 * use fromAngleNormalAxis if your axis is already normalized. 902 * 903 * @param angle 904 * the angle to rotate (in radians). 905 * @param axis 906 * the axis of rotation. 907 */ fromAngleAxis(float angle, Vector3f axis)908 public void fromAngleAxis(float angle, Vector3f axis) { 909 Vector3f normAxis = axis.normalize(); 910 fromAngleNormalAxis(angle, normAxis); 911 } 912 913 /** 914 * <code>fromAngleNormalAxis</code> sets this matrix4f to the values 915 * specified by an angle and a normalized axis of rotation. 916 * 917 * @param angle 918 * the angle to rotate (in radians). 919 * @param axis 920 * the axis of rotation (already normalized). 921 */ fromAngleNormalAxis(float angle, Vector3f axis)922 public void fromAngleNormalAxis(float angle, Vector3f axis) { 923 zero(); 924 m33 = 1; 925 926 float fCos = FastMath.cos(angle); 927 float fSin = FastMath.sin(angle); 928 float fOneMinusCos = ((float) 1.0) - fCos; 929 float fX2 = axis.x * axis.x; 930 float fY2 = axis.y * axis.y; 931 float fZ2 = axis.z * axis.z; 932 float fXYM = axis.x * axis.y * fOneMinusCos; 933 float fXZM = axis.x * axis.z * fOneMinusCos; 934 float fYZM = axis.y * axis.z * fOneMinusCos; 935 float fXSin = axis.x * fSin; 936 float fYSin = axis.y * fSin; 937 float fZSin = axis.z * fSin; 938 939 m00 = fX2 * fOneMinusCos + fCos; 940 m01 = fXYM - fZSin; 941 m02 = fXZM + fYSin; 942 m10 = fXYM + fZSin; 943 m11 = fY2 * fOneMinusCos + fCos; 944 m12 = fYZM - fXSin; 945 m20 = fXZM - fYSin; 946 m21 = fYZM + fXSin; 947 m22 = fZ2 * fOneMinusCos + fCos; 948 } 949 950 /** 951 * <code>mult</code> multiplies this matrix by a scalar. 952 * 953 * @param scalar 954 * the scalar to multiply this matrix by. 955 */ multLocal(float scalar)956 public void multLocal(float scalar) { 957 m00 *= scalar; 958 m01 *= scalar; 959 m02 *= scalar; 960 m03 *= scalar; 961 m10 *= scalar; 962 m11 *= scalar; 963 m12 *= scalar; 964 m13 *= scalar; 965 m20 *= scalar; 966 m21 *= scalar; 967 m22 *= scalar; 968 m23 *= scalar; 969 m30 *= scalar; 970 m31 *= scalar; 971 m32 *= scalar; 972 m33 *= scalar; 973 } 974 mult(float scalar)975 public Matrix4f mult(float scalar) { 976 Matrix4f out = new Matrix4f(); 977 out.set(this); 978 out.multLocal(scalar); 979 return out; 980 } 981 mult(float scalar, Matrix4f store)982 public Matrix4f mult(float scalar, Matrix4f store) { 983 store.set(this); 984 store.multLocal(scalar); 985 return store; 986 } 987 988 /** 989 * <code>mult</code> multiplies this matrix with another matrix. The 990 * result matrix will then be returned. This matrix will be on the left hand 991 * side, while the parameter matrix will be on the right. 992 * 993 * @param in2 994 * the matrix to multiply this matrix by. 995 * @return the resultant matrix 996 */ mult(Matrix4f in2)997 public Matrix4f mult(Matrix4f in2) { 998 return mult(in2, null); 999 } 1000 1001 /** 1002 * <code>mult</code> multiplies this matrix with another matrix. The 1003 * result matrix will then be returned. This matrix will be on the left hand 1004 * side, while the parameter matrix will be on the right. 1005 * 1006 * @param in2 1007 * the matrix to multiply this matrix by. 1008 * @param store 1009 * where to store the result. It is safe for in2 and store to be 1010 * the same object. 1011 * @return the resultant matrix 1012 */ mult(Matrix4f in2, Matrix4f store)1013 public Matrix4f mult(Matrix4f in2, Matrix4f store) { 1014 if (store == null) { 1015 store = new Matrix4f(); 1016 } 1017 1018 float temp00, temp01, temp02, temp03; 1019 float temp10, temp11, temp12, temp13; 1020 float temp20, temp21, temp22, temp23; 1021 float temp30, temp31, temp32, temp33; 1022 1023 temp00 = m00 * in2.m00 1024 + m01 * in2.m10 1025 + m02 * in2.m20 1026 + m03 * in2.m30; 1027 temp01 = m00 * in2.m01 1028 + m01 * in2.m11 1029 + m02 * in2.m21 1030 + m03 * in2.m31; 1031 temp02 = m00 * in2.m02 1032 + m01 * in2.m12 1033 + m02 * in2.m22 1034 + m03 * in2.m32; 1035 temp03 = m00 * in2.m03 1036 + m01 * in2.m13 1037 + m02 * in2.m23 1038 + m03 * in2.m33; 1039 1040 temp10 = m10 * in2.m00 1041 + m11 * in2.m10 1042 + m12 * in2.m20 1043 + m13 * in2.m30; 1044 temp11 = m10 * in2.m01 1045 + m11 * in2.m11 1046 + m12 * in2.m21 1047 + m13 * in2.m31; 1048 temp12 = m10 * in2.m02 1049 + m11 * in2.m12 1050 + m12 * in2.m22 1051 + m13 * in2.m32; 1052 temp13 = m10 * in2.m03 1053 + m11 * in2.m13 1054 + m12 * in2.m23 1055 + m13 * in2.m33; 1056 1057 temp20 = m20 * in2.m00 1058 + m21 * in2.m10 1059 + m22 * in2.m20 1060 + m23 * in2.m30; 1061 temp21 = m20 * in2.m01 1062 + m21 * in2.m11 1063 + m22 * in2.m21 1064 + m23 * in2.m31; 1065 temp22 = m20 * in2.m02 1066 + m21 * in2.m12 1067 + m22 * in2.m22 1068 + m23 * in2.m32; 1069 temp23 = m20 * in2.m03 1070 + m21 * in2.m13 1071 + m22 * in2.m23 1072 + m23 * in2.m33; 1073 1074 temp30 = m30 * in2.m00 1075 + m31 * in2.m10 1076 + m32 * in2.m20 1077 + m33 * in2.m30; 1078 temp31 = m30 * in2.m01 1079 + m31 * in2.m11 1080 + m32 * in2.m21 1081 + m33 * in2.m31; 1082 temp32 = m30 * in2.m02 1083 + m31 * in2.m12 1084 + m32 * in2.m22 1085 + m33 * in2.m32; 1086 temp33 = m30 * in2.m03 1087 + m31 * in2.m13 1088 + m32 * in2.m23 1089 + m33 * in2.m33; 1090 1091 store.m00 = temp00; 1092 store.m01 = temp01; 1093 store.m02 = temp02; 1094 store.m03 = temp03; 1095 store.m10 = temp10; 1096 store.m11 = temp11; 1097 store.m12 = temp12; 1098 store.m13 = temp13; 1099 store.m20 = temp20; 1100 store.m21 = temp21; 1101 store.m22 = temp22; 1102 store.m23 = temp23; 1103 store.m30 = temp30; 1104 store.m31 = temp31; 1105 store.m32 = temp32; 1106 store.m33 = temp33; 1107 1108 return store; 1109 } 1110 1111 /** 1112 * <code>mult</code> multiplies this matrix with another matrix. The 1113 * results are stored internally and a handle to this matrix will 1114 * then be returned. This matrix will be on the left hand 1115 * side, while the parameter matrix will be on the right. 1116 * 1117 * @param in2 1118 * the matrix to multiply this matrix by. 1119 * @return the resultant matrix 1120 */ multLocal(Matrix4f in2)1121 public Matrix4f multLocal(Matrix4f in2) { 1122 return mult(in2, this); 1123 } 1124 1125 /** 1126 * <code>mult</code> multiplies a vector about a rotation matrix. The 1127 * resulting vector is returned as a new Vector3f. 1128 * 1129 * @param vec 1130 * vec to multiply against. 1131 * @return the rotated vector. 1132 */ mult(Vector3f vec)1133 public Vector3f mult(Vector3f vec) { 1134 return mult(vec, null); 1135 } 1136 1137 /** 1138 * <code>mult</code> multiplies a vector about a rotation matrix and adds 1139 * translation. The resulting vector is returned. 1140 * 1141 * @param vec 1142 * vec to multiply against. 1143 * @param store 1144 * a vector to store the result in. Created if null is passed. 1145 * @return the rotated vector. 1146 */ mult(Vector3f vec, Vector3f store)1147 public Vector3f mult(Vector3f vec, Vector3f store) { 1148 if (store == null) { 1149 store = new Vector3f(); 1150 } 1151 1152 float vx = vec.x, vy = vec.y, vz = vec.z; 1153 store.x = m00 * vx + m01 * vy + m02 * vz + m03; 1154 store.y = m10 * vx + m11 * vy + m12 * vz + m13; 1155 store.z = m20 * vx + m21 * vy + m22 * vz + m23; 1156 1157 return store; 1158 } 1159 1160 /** 1161 * <code>mult</code> multiplies a <code>Vector4f</code> about a rotation 1162 * matrix. The resulting vector is returned as a new <code>Vector4f</code>. 1163 * 1164 * @param vec 1165 * vec to multiply against. 1166 * @return the rotated vector. 1167 */ mult(Vector4f vec)1168 public Vector4f mult(Vector4f vec) { 1169 return mult(vec, null); 1170 } 1171 1172 /** 1173 * <code>mult</code> multiplies a <code>Vector4f</code> about a rotation 1174 * matrix. The resulting vector is returned. 1175 * 1176 * @param vec 1177 * vec to multiply against. 1178 * @param store 1179 * a vector to store the result in. Created if null is passed. 1180 * @return the rotated vector. 1181 */ mult(Vector4f vec, Vector4f store)1182 public Vector4f mult(Vector4f vec, Vector4f store) { 1183 if (null == vec) { 1184 logger.info("Source vector is null, null result returned."); 1185 return null; 1186 } 1187 if (store == null) { 1188 store = new Vector4f(); 1189 } 1190 1191 float vx = vec.x, vy = vec.y, vz = vec.z, vw = vec.w; 1192 store.x = m00 * vx + m01 * vy + m02 * vz + m03 * vw; 1193 store.y = m10 * vx + m11 * vy + m12 * vz + m13 * vw; 1194 store.z = m20 * vx + m21 * vy + m22 * vz + m23 * vw; 1195 store.w = m30 * vx + m31 * vy + m32 * vz + m33 * vw; 1196 1197 return store; 1198 } 1199 1200 /** 1201 * <code>mult</code> multiplies a vector about a rotation matrix. The 1202 * resulting vector is returned. 1203 * 1204 * @param vec 1205 * vec to multiply against. 1206 * 1207 * @return the rotated vector. 1208 */ multAcross(Vector4f vec)1209 public Vector4f multAcross(Vector4f vec) { 1210 return multAcross(vec, null); 1211 } 1212 1213 /** 1214 * <code>mult</code> multiplies a vector about a rotation matrix. The 1215 * resulting vector is returned. 1216 * 1217 * @param vec 1218 * vec to multiply against. 1219 * @param store 1220 * a vector to store the result in. created if null is passed. 1221 * @return the rotated vector. 1222 */ multAcross(Vector4f vec, Vector4f store)1223 public Vector4f multAcross(Vector4f vec, Vector4f store) { 1224 if (null == vec) { 1225 logger.info("Source vector is null, null result returned."); 1226 return null; 1227 } 1228 if (store == null) { 1229 store = new Vector4f(); 1230 } 1231 1232 float vx = vec.x, vy = vec.y, vz = vec.z, vw = vec.w; 1233 store.x = m00 * vx + m10 * vy + m20 * vz + m30 * vw; 1234 store.y = m01 * vx + m11 * vy + m21 * vz + m31 * vw; 1235 store.z = m02 * vx + m12 * vy + m22 * vz + m32 * vw; 1236 store.z = m03 * vx + m13 * vy + m23 * vz + m33 * vw; 1237 1238 return store; 1239 } 1240 1241 /** 1242 * <code>multNormal</code> multiplies a vector about a rotation matrix, but 1243 * does not add translation. The resulting vector is returned. 1244 * 1245 * @param vec 1246 * vec to multiply against. 1247 * @param store 1248 * a vector to store the result in. Created if null is passed. 1249 * @return the rotated vector. 1250 */ multNormal(Vector3f vec, Vector3f store)1251 public Vector3f multNormal(Vector3f vec, Vector3f store) { 1252 if (store == null) { 1253 store = new Vector3f(); 1254 } 1255 1256 float vx = vec.x, vy = vec.y, vz = vec.z; 1257 store.x = m00 * vx + m01 * vy + m02 * vz; 1258 store.y = m10 * vx + m11 * vy + m12 * vz; 1259 store.z = m20 * vx + m21 * vy + m22 * vz; 1260 1261 return store; 1262 } 1263 1264 /** 1265 * <code>multNormal</code> multiplies a vector about a rotation matrix, but 1266 * does not add translation. The resulting vector is returned. 1267 * 1268 * @param vec 1269 * vec to multiply against. 1270 * @param store 1271 * a vector to store the result in. Created if null is passed. 1272 * @return the rotated vector. 1273 */ multNormalAcross(Vector3f vec, Vector3f store)1274 public Vector3f multNormalAcross(Vector3f vec, Vector3f store) { 1275 if (store == null) { 1276 store = new Vector3f(); 1277 } 1278 1279 float vx = vec.x, vy = vec.y, vz = vec.z; 1280 store.x = m00 * vx + m10 * vy + m20 * vz; 1281 store.y = m01 * vx + m11 * vy + m21 * vz; 1282 store.z = m02 * vx + m12 * vy + m22 * vz; 1283 1284 return store; 1285 } 1286 1287 /** 1288 * <code>mult</code> multiplies a vector about a rotation matrix and adds 1289 * translation. The w value is returned as a result of 1290 * multiplying the last column of the matrix by 1.0 1291 * 1292 * @param vec 1293 * vec to multiply against. 1294 * @param store 1295 * a vector to store the result in. 1296 * @return the W value 1297 */ multProj(Vector3f vec, Vector3f store)1298 public float multProj(Vector3f vec, Vector3f store) { 1299 float vx = vec.x, vy = vec.y, vz = vec.z; 1300 store.x = m00 * vx + m01 * vy + m02 * vz + m03; 1301 store.y = m10 * vx + m11 * vy + m12 * vz + m13; 1302 store.z = m20 * vx + m21 * vy + m22 * vz + m23; 1303 return m30 * vx + m31 * vy + m32 * vz + m33; 1304 } 1305 1306 /** 1307 * <code>mult</code> multiplies a vector about a rotation matrix. The 1308 * resulting vector is returned. 1309 * 1310 * @param vec 1311 * vec to multiply against. 1312 * @param store 1313 * a vector to store the result in. created if null is passed. 1314 * @return the rotated vector. 1315 */ multAcross(Vector3f vec, Vector3f store)1316 public Vector3f multAcross(Vector3f vec, Vector3f store) { 1317 if (null == vec) { 1318 logger.info("Source vector is null, null result returned."); 1319 return null; 1320 } 1321 if (store == null) { 1322 store = new Vector3f(); 1323 } 1324 1325 float vx = vec.x, vy = vec.y, vz = vec.z; 1326 store.x = m00 * vx + m10 * vy + m20 * vz + m30 * 1; 1327 store.y = m01 * vx + m11 * vy + m21 * vz + m31 * 1; 1328 store.z = m02 * vx + m12 * vy + m22 * vz + m32 * 1; 1329 1330 return store; 1331 } 1332 1333 /** 1334 * <code>mult</code> multiplies a quaternion about a matrix. The 1335 * resulting vector is returned. 1336 * 1337 * @param vec 1338 * vec to multiply against. 1339 * @param store 1340 * a quaternion to store the result in. created if null is passed. 1341 * @return store = this * vec 1342 */ mult(Quaternion vec, Quaternion store)1343 public Quaternion mult(Quaternion vec, Quaternion store) { 1344 1345 if (null == vec) { 1346 logger.warning("Source vector is null, null result returned."); 1347 return null; 1348 } 1349 if (store == null) { 1350 store = new Quaternion(); 1351 } 1352 1353 float x = m00 * vec.x + m10 * vec.y + m20 * vec.z + m30 * vec.w; 1354 float y = m01 * vec.x + m11 * vec.y + m21 * vec.z + m31 * vec.w; 1355 float z = m02 * vec.x + m12 * vec.y + m22 * vec.z + m32 * vec.w; 1356 float w = m03 * vec.x + m13 * vec.y + m23 * vec.z + m33 * vec.w; 1357 store.x = x; 1358 store.y = y; 1359 store.z = z; 1360 store.w = w; 1361 1362 return store; 1363 } 1364 1365 /** 1366 * <code>mult</code> multiplies an array of 4 floats against this rotation 1367 * matrix. The results are stored directly in the array. (vec4f x mat4f) 1368 * 1369 * @param vec4f 1370 * float array (size 4) to multiply against the matrix. 1371 * @return the vec4f for chaining. 1372 */ mult(float[] vec4f)1373 public float[] mult(float[] vec4f) { 1374 if (null == vec4f || vec4f.length != 4) { 1375 logger.warning("invalid array given, must be nonnull and length 4"); 1376 return null; 1377 } 1378 1379 float x = vec4f[0], y = vec4f[1], z = vec4f[2], w = vec4f[3]; 1380 1381 vec4f[0] = m00 * x + m01 * y + m02 * z + m03 * w; 1382 vec4f[1] = m10 * x + m11 * y + m12 * z + m13 * w; 1383 vec4f[2] = m20 * x + m21 * y + m22 * z + m23 * w; 1384 vec4f[3] = m30 * x + m31 * y + m32 * z + m33 * w; 1385 1386 return vec4f; 1387 } 1388 1389 /** 1390 * <code>mult</code> multiplies an array of 4 floats against this rotation 1391 * matrix. The results are stored directly in the array. (vec4f x mat4f) 1392 * 1393 * @param vec4f 1394 * float array (size 4) to multiply against the matrix. 1395 * @return the vec4f for chaining. 1396 */ multAcross(float[] vec4f)1397 public float[] multAcross(float[] vec4f) { 1398 if (null == vec4f || vec4f.length != 4) { 1399 logger.warning("invalid array given, must be nonnull and length 4"); 1400 return null; 1401 } 1402 1403 float x = vec4f[0], y = vec4f[1], z = vec4f[2], w = vec4f[3]; 1404 1405 vec4f[0] = m00 * x + m10 * y + m20 * z + m30 * w; 1406 vec4f[1] = m01 * x + m11 * y + m21 * z + m31 * w; 1407 vec4f[2] = m02 * x + m12 * y + m22 * z + m32 * w; 1408 vec4f[3] = m03 * x + m13 * y + m23 * z + m33 * w; 1409 1410 return vec4f; 1411 } 1412 1413 /** 1414 * Inverts this matrix as a new Matrix4f. 1415 * 1416 * @return The new inverse matrix 1417 */ invert()1418 public Matrix4f invert() { 1419 return invert(null); 1420 } 1421 1422 /** 1423 * Inverts this matrix and stores it in the given store. 1424 * 1425 * @return The store 1426 */ invert(Matrix4f store)1427 public Matrix4f invert(Matrix4f store) { 1428 if (store == null) { 1429 store = new Matrix4f(); 1430 } 1431 1432 float fA0 = m00 * m11 - m01 * m10; 1433 float fA1 = m00 * m12 - m02 * m10; 1434 float fA2 = m00 * m13 - m03 * m10; 1435 float fA3 = m01 * m12 - m02 * m11; 1436 float fA4 = m01 * m13 - m03 * m11; 1437 float fA5 = m02 * m13 - m03 * m12; 1438 float fB0 = m20 * m31 - m21 * m30; 1439 float fB1 = m20 * m32 - m22 * m30; 1440 float fB2 = m20 * m33 - m23 * m30; 1441 float fB3 = m21 * m32 - m22 * m31; 1442 float fB4 = m21 * m33 - m23 * m31; 1443 float fB5 = m22 * m33 - m23 * m32; 1444 float fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0; 1445 1446 if (FastMath.abs(fDet) <= 0f) { 1447 throw new ArithmeticException("This matrix cannot be inverted"); 1448 } 1449 1450 store.m00 = +m11 * fB5 - m12 * fB4 + m13 * fB3; 1451 store.m10 = -m10 * fB5 + m12 * fB2 - m13 * fB1; 1452 store.m20 = +m10 * fB4 - m11 * fB2 + m13 * fB0; 1453 store.m30 = -m10 * fB3 + m11 * fB1 - m12 * fB0; 1454 store.m01 = -m01 * fB5 + m02 * fB4 - m03 * fB3; 1455 store.m11 = +m00 * fB5 - m02 * fB2 + m03 * fB1; 1456 store.m21 = -m00 * fB4 + m01 * fB2 - m03 * fB0; 1457 store.m31 = +m00 * fB3 - m01 * fB1 + m02 * fB0; 1458 store.m02 = +m31 * fA5 - m32 * fA4 + m33 * fA3; 1459 store.m12 = -m30 * fA5 + m32 * fA2 - m33 * fA1; 1460 store.m22 = +m30 * fA4 - m31 * fA2 + m33 * fA0; 1461 store.m32 = -m30 * fA3 + m31 * fA1 - m32 * fA0; 1462 store.m03 = -m21 * fA5 + m22 * fA4 - m23 * fA3; 1463 store.m13 = +m20 * fA5 - m22 * fA2 + m23 * fA1; 1464 store.m23 = -m20 * fA4 + m21 * fA2 - m23 * fA0; 1465 store.m33 = +m20 * fA3 - m21 * fA1 + m22 * fA0; 1466 1467 float fInvDet = 1.0f / fDet; 1468 store.multLocal(fInvDet); 1469 1470 return store; 1471 } 1472 1473 /** 1474 * Inverts this matrix locally. 1475 * 1476 * @return this 1477 */ invertLocal()1478 public Matrix4f invertLocal() { 1479 1480 float fA0 = m00 * m11 - m01 * m10; 1481 float fA1 = m00 * m12 - m02 * m10; 1482 float fA2 = m00 * m13 - m03 * m10; 1483 float fA3 = m01 * m12 - m02 * m11; 1484 float fA4 = m01 * m13 - m03 * m11; 1485 float fA5 = m02 * m13 - m03 * m12; 1486 float fB0 = m20 * m31 - m21 * m30; 1487 float fB1 = m20 * m32 - m22 * m30; 1488 float fB2 = m20 * m33 - m23 * m30; 1489 float fB3 = m21 * m32 - m22 * m31; 1490 float fB4 = m21 * m33 - m23 * m31; 1491 float fB5 = m22 * m33 - m23 * m32; 1492 float fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0; 1493 1494 if (FastMath.abs(fDet) <= 0f) { 1495 return zero(); 1496 } 1497 1498 float f00 = +m11 * fB5 - m12 * fB4 + m13 * fB3; 1499 float f10 = -m10 * fB5 + m12 * fB2 - m13 * fB1; 1500 float f20 = +m10 * fB4 - m11 * fB2 + m13 * fB0; 1501 float f30 = -m10 * fB3 + m11 * fB1 - m12 * fB0; 1502 float f01 = -m01 * fB5 + m02 * fB4 - m03 * fB3; 1503 float f11 = +m00 * fB5 - m02 * fB2 + m03 * fB1; 1504 float f21 = -m00 * fB4 + m01 * fB2 - m03 * fB0; 1505 float f31 = +m00 * fB3 - m01 * fB1 + m02 * fB0; 1506 float f02 = +m31 * fA5 - m32 * fA4 + m33 * fA3; 1507 float f12 = -m30 * fA5 + m32 * fA2 - m33 * fA1; 1508 float f22 = +m30 * fA4 - m31 * fA2 + m33 * fA0; 1509 float f32 = -m30 * fA3 + m31 * fA1 - m32 * fA0; 1510 float f03 = -m21 * fA5 + m22 * fA4 - m23 * fA3; 1511 float f13 = +m20 * fA5 - m22 * fA2 + m23 * fA1; 1512 float f23 = -m20 * fA4 + m21 * fA2 - m23 * fA0; 1513 float f33 = +m20 * fA3 - m21 * fA1 + m22 * fA0; 1514 1515 m00 = f00; 1516 m01 = f01; 1517 m02 = f02; 1518 m03 = f03; 1519 m10 = f10; 1520 m11 = f11; 1521 m12 = f12; 1522 m13 = f13; 1523 m20 = f20; 1524 m21 = f21; 1525 m22 = f22; 1526 m23 = f23; 1527 m30 = f30; 1528 m31 = f31; 1529 m32 = f32; 1530 m33 = f33; 1531 1532 float fInvDet = 1.0f / fDet; 1533 multLocal(fInvDet); 1534 1535 return this; 1536 } 1537 1538 /** 1539 * Returns a new matrix representing the adjoint of this matrix. 1540 * 1541 * @return The adjoint matrix 1542 */ adjoint()1543 public Matrix4f adjoint() { 1544 return adjoint(null); 1545 } 1546 setTransform(Vector3f position, Vector3f scale, Matrix3f rotMat)1547 public void setTransform(Vector3f position, Vector3f scale, Matrix3f rotMat) { 1548 // Ordering: 1549 // 1. Scale 1550 // 2. Rotate 1551 // 3. Translate 1552 1553 // Set up final matrix with scale, rotation and translation 1554 m00 = scale.x * rotMat.m00; 1555 m01 = scale.y * rotMat.m01; 1556 m02 = scale.z * rotMat.m02; 1557 m03 = position.x; 1558 m10 = scale.x * rotMat.m10; 1559 m11 = scale.y * rotMat.m11; 1560 m12 = scale.z * rotMat.m12; 1561 m13 = position.y; 1562 m20 = scale.x * rotMat.m20; 1563 m21 = scale.y * rotMat.m21; 1564 m22 = scale.z * rotMat.m22; 1565 m23 = position.z; 1566 1567 // No projection term 1568 m30 = 0; 1569 m31 = 0; 1570 m32 = 0; 1571 m33 = 1; 1572 } 1573 1574 /** 1575 * Places the adjoint of this matrix in store (creates store if null.) 1576 * 1577 * @param store 1578 * The matrix to store the result in. If null, a new matrix is created. 1579 * @return store 1580 */ adjoint(Matrix4f store)1581 public Matrix4f adjoint(Matrix4f store) { 1582 if (store == null) { 1583 store = new Matrix4f(); 1584 } 1585 1586 float fA0 = m00 * m11 - m01 * m10; 1587 float fA1 = m00 * m12 - m02 * m10; 1588 float fA2 = m00 * m13 - m03 * m10; 1589 float fA3 = m01 * m12 - m02 * m11; 1590 float fA4 = m01 * m13 - m03 * m11; 1591 float fA5 = m02 * m13 - m03 * m12; 1592 float fB0 = m20 * m31 - m21 * m30; 1593 float fB1 = m20 * m32 - m22 * m30; 1594 float fB2 = m20 * m33 - m23 * m30; 1595 float fB3 = m21 * m32 - m22 * m31; 1596 float fB4 = m21 * m33 - m23 * m31; 1597 float fB5 = m22 * m33 - m23 * m32; 1598 1599 store.m00 = +m11 * fB5 - m12 * fB4 + m13 * fB3; 1600 store.m10 = -m10 * fB5 + m12 * fB2 - m13 * fB1; 1601 store.m20 = +m10 * fB4 - m11 * fB2 + m13 * fB0; 1602 store.m30 = -m10 * fB3 + m11 * fB1 - m12 * fB0; 1603 store.m01 = -m01 * fB5 + m02 * fB4 - m03 * fB3; 1604 store.m11 = +m00 * fB5 - m02 * fB2 + m03 * fB1; 1605 store.m21 = -m00 * fB4 + m01 * fB2 - m03 * fB0; 1606 store.m31 = +m00 * fB3 - m01 * fB1 + m02 * fB0; 1607 store.m02 = +m31 * fA5 - m32 * fA4 + m33 * fA3; 1608 store.m12 = -m30 * fA5 + m32 * fA2 - m33 * fA1; 1609 store.m22 = +m30 * fA4 - m31 * fA2 + m33 * fA0; 1610 store.m32 = -m30 * fA3 + m31 * fA1 - m32 * fA0; 1611 store.m03 = -m21 * fA5 + m22 * fA4 - m23 * fA3; 1612 store.m13 = +m20 * fA5 - m22 * fA2 + m23 * fA1; 1613 store.m23 = -m20 * fA4 + m21 * fA2 - m23 * fA0; 1614 store.m33 = +m20 * fA3 - m21 * fA1 + m22 * fA0; 1615 1616 return store; 1617 } 1618 1619 /** 1620 * <code>determinant</code> generates the determinate of this matrix. 1621 * 1622 * @return the determinate 1623 */ determinant()1624 public float determinant() { 1625 float fA0 = m00 * m11 - m01 * m10; 1626 float fA1 = m00 * m12 - m02 * m10; 1627 float fA2 = m00 * m13 - m03 * m10; 1628 float fA3 = m01 * m12 - m02 * m11; 1629 float fA4 = m01 * m13 - m03 * m11; 1630 float fA5 = m02 * m13 - m03 * m12; 1631 float fB0 = m20 * m31 - m21 * m30; 1632 float fB1 = m20 * m32 - m22 * m30; 1633 float fB2 = m20 * m33 - m23 * m30; 1634 float fB3 = m21 * m32 - m22 * m31; 1635 float fB4 = m21 * m33 - m23 * m31; 1636 float fB5 = m22 * m33 - m23 * m32; 1637 float fDet = fA0 * fB5 - fA1 * fB4 + fA2 * fB3 + fA3 * fB2 - fA4 * fB1 + fA5 * fB0; 1638 return fDet; 1639 } 1640 1641 /** 1642 * Sets all of the values in this matrix to zero. 1643 * 1644 * @return this matrix 1645 */ zero()1646 public Matrix4f zero() { 1647 m00 = m01 = m02 = m03 = 0.0f; 1648 m10 = m11 = m12 = m13 = 0.0f; 1649 m20 = m21 = m22 = m23 = 0.0f; 1650 m30 = m31 = m32 = m33 = 0.0f; 1651 return this; 1652 } 1653 add(Matrix4f mat)1654 public Matrix4f add(Matrix4f mat) { 1655 Matrix4f result = new Matrix4f(); 1656 result.m00 = this.m00 + mat.m00; 1657 result.m01 = this.m01 + mat.m01; 1658 result.m02 = this.m02 + mat.m02; 1659 result.m03 = this.m03 + mat.m03; 1660 result.m10 = this.m10 + mat.m10; 1661 result.m11 = this.m11 + mat.m11; 1662 result.m12 = this.m12 + mat.m12; 1663 result.m13 = this.m13 + mat.m13; 1664 result.m20 = this.m20 + mat.m20; 1665 result.m21 = this.m21 + mat.m21; 1666 result.m22 = this.m22 + mat.m22; 1667 result.m23 = this.m23 + mat.m23; 1668 result.m30 = this.m30 + mat.m30; 1669 result.m31 = this.m31 + mat.m31; 1670 result.m32 = this.m32 + mat.m32; 1671 result.m33 = this.m33 + mat.m33; 1672 return result; 1673 } 1674 1675 /** 1676 * <code>add</code> adds the values of a parameter matrix to this matrix. 1677 * 1678 * @param mat 1679 * the matrix to add to this. 1680 */ addLocal(Matrix4f mat)1681 public void addLocal(Matrix4f mat) { 1682 m00 += mat.m00; 1683 m01 += mat.m01; 1684 m02 += mat.m02; 1685 m03 += mat.m03; 1686 m10 += mat.m10; 1687 m11 += mat.m11; 1688 m12 += mat.m12; 1689 m13 += mat.m13; 1690 m20 += mat.m20; 1691 m21 += mat.m21; 1692 m22 += mat.m22; 1693 m23 += mat.m23; 1694 m30 += mat.m30; 1695 m31 += mat.m31; 1696 m32 += mat.m32; 1697 m33 += mat.m33; 1698 } 1699 toTranslationVector()1700 public Vector3f toTranslationVector() { 1701 return new Vector3f(m03, m13, m23); 1702 } 1703 toTranslationVector(Vector3f vector)1704 public void toTranslationVector(Vector3f vector) { 1705 vector.set(m03, m13, m23); 1706 } 1707 toRotationQuat()1708 public Quaternion toRotationQuat() { 1709 Quaternion quat = new Quaternion(); 1710 quat.fromRotationMatrix(toRotationMatrix()); 1711 return quat; 1712 } 1713 toRotationQuat(Quaternion q)1714 public void toRotationQuat(Quaternion q) { 1715 q.fromRotationMatrix(toRotationMatrix()); 1716 } 1717 toRotationMatrix()1718 public Matrix3f toRotationMatrix() { 1719 return new Matrix3f(m00, m01, m02, m10, m11, m12, m20, m21, m22); 1720 1721 } 1722 toRotationMatrix(Matrix3f mat)1723 public void toRotationMatrix(Matrix3f mat) { 1724 mat.m00 = m00; 1725 mat.m01 = m01; 1726 mat.m02 = m02; 1727 mat.m10 = m10; 1728 mat.m11 = m11; 1729 mat.m12 = m12; 1730 mat.m20 = m20; 1731 mat.m21 = m21; 1732 mat.m22 = m22; 1733 1734 } 1735 setScale(float x, float y, float z)1736 public void setScale(float x, float y, float z) { 1737 m00 *= x; 1738 m11 *= y; 1739 m22 *= z; 1740 } 1741 setScale(Vector3f scale)1742 public void setScale(Vector3f scale) { 1743 m00 *= scale.x; 1744 m11 *= scale.y; 1745 m22 *= scale.z; 1746 } 1747 1748 /** 1749 * <code>setTranslation</code> will set the matrix's translation values. 1750 * 1751 * @param translation 1752 * the new values for the translation. 1753 * @throws JmeException 1754 * if translation is not size 3. 1755 */ setTranslation(float[] translation)1756 public void setTranslation(float[] translation) { 1757 if (translation.length != 3) { 1758 throw new IllegalArgumentException( 1759 "Translation size must be 3."); 1760 } 1761 m03 = translation[0]; 1762 m13 = translation[1]; 1763 m23 = translation[2]; 1764 } 1765 1766 /** 1767 * <code>setTranslation</code> will set the matrix's translation values. 1768 * 1769 * @param x 1770 * value of the translation on the x axis 1771 * @param y 1772 * value of the translation on the y axis 1773 * @param z 1774 * value of the translation on the z axis 1775 */ setTranslation(float x, float y, float z)1776 public void setTranslation(float x, float y, float z) { 1777 m03 = x; 1778 m13 = y; 1779 m23 = z; 1780 } 1781 1782 /** 1783 * <code>setTranslation</code> will set the matrix's translation values. 1784 * 1785 * @param translation 1786 * the new values for the translation. 1787 */ setTranslation(Vector3f translation)1788 public void setTranslation(Vector3f translation) { 1789 m03 = translation.x; 1790 m13 = translation.y; 1791 m23 = translation.z; 1792 } 1793 1794 /** 1795 * <code>setInverseTranslation</code> will set the matrix's inverse 1796 * translation values. 1797 * 1798 * @param translation 1799 * the new values for the inverse translation. 1800 * @throws JmeException 1801 * if translation is not size 3. 1802 */ setInverseTranslation(float[] translation)1803 public void setInverseTranslation(float[] translation) { 1804 if (translation.length != 3) { 1805 throw new IllegalArgumentException( 1806 "Translation size must be 3."); 1807 } 1808 m03 = -translation[0]; 1809 m13 = -translation[1]; 1810 m23 = -translation[2]; 1811 } 1812 1813 /** 1814 * <code>angleRotation</code> sets this matrix to that of a rotation about 1815 * three axes (x, y, z). Where each axis has a specified rotation in 1816 * degrees. These rotations are expressed in a single <code>Vector3f</code> 1817 * object. 1818 * 1819 * @param angles 1820 * the angles to rotate. 1821 */ angleRotation(Vector3f angles)1822 public void angleRotation(Vector3f angles) { 1823 float angle; 1824 float sr, sp, sy, cr, cp, cy; 1825 1826 angle = (angles.z * FastMath.DEG_TO_RAD); 1827 sy = FastMath.sin(angle); 1828 cy = FastMath.cos(angle); 1829 angle = (angles.y * FastMath.DEG_TO_RAD); 1830 sp = FastMath.sin(angle); 1831 cp = FastMath.cos(angle); 1832 angle = (angles.x * FastMath.DEG_TO_RAD); 1833 sr = FastMath.sin(angle); 1834 cr = FastMath.cos(angle); 1835 1836 // matrix = (Z * Y) * X 1837 m00 = cp * cy; 1838 m10 = cp * sy; 1839 m20 = -sp; 1840 m01 = sr * sp * cy + cr * -sy; 1841 m11 = sr * sp * sy + cr * cy; 1842 m21 = sr * cp; 1843 m02 = (cr * sp * cy + -sr * -sy); 1844 m12 = (cr * sp * sy + -sr * cy); 1845 m22 = cr * cp; 1846 m03 = 0.0f; 1847 m13 = 0.0f; 1848 m23 = 0.0f; 1849 } 1850 1851 /** 1852 * <code>setRotationQuaternion</code> builds a rotation from a 1853 * <code>Quaternion</code>. 1854 * 1855 * @param quat 1856 * the quaternion to build the rotation from. 1857 * @throws NullPointerException 1858 * if quat is null. 1859 */ setRotationQuaternion(Quaternion quat)1860 public void setRotationQuaternion(Quaternion quat) { 1861 quat.toRotationMatrix(this); 1862 } 1863 1864 /** 1865 * <code>setInverseRotationRadians</code> builds an inverted rotation from 1866 * Euler angles that are in radians. 1867 * 1868 * @param angles 1869 * the Euler angles in radians. 1870 * @throws JmeException 1871 * if angles is not size 3. 1872 */ setInverseRotationRadians(float[] angles)1873 public void setInverseRotationRadians(float[] angles) { 1874 if (angles.length != 3) { 1875 throw new IllegalArgumentException( 1876 "Angles must be of size 3."); 1877 } 1878 double cr = FastMath.cos(angles[0]); 1879 double sr = FastMath.sin(angles[0]); 1880 double cp = FastMath.cos(angles[1]); 1881 double sp = FastMath.sin(angles[1]); 1882 double cy = FastMath.cos(angles[2]); 1883 double sy = FastMath.sin(angles[2]); 1884 1885 m00 = (float) (cp * cy); 1886 m10 = (float) (cp * sy); 1887 m20 = (float) (-sp); 1888 1889 double srsp = sr * sp; 1890 double crsp = cr * sp; 1891 1892 m01 = (float) (srsp * cy - cr * sy); 1893 m11 = (float) (srsp * sy + cr * cy); 1894 m21 = (float) (sr * cp); 1895 1896 m02 = (float) (crsp * cy + sr * sy); 1897 m12 = (float) (crsp * sy - sr * cy); 1898 m22 = (float) (cr * cp); 1899 } 1900 1901 /** 1902 * <code>setInverseRotationDegrees</code> builds an inverted rotation from 1903 * Euler angles that are in degrees. 1904 * 1905 * @param angles 1906 * the Euler angles in degrees. 1907 * @throws JmeException 1908 * if angles is not size 3. 1909 */ setInverseRotationDegrees(float[] angles)1910 public void setInverseRotationDegrees(float[] angles) { 1911 if (angles.length != 3) { 1912 throw new IllegalArgumentException( 1913 "Angles must be of size 3."); 1914 } 1915 float vec[] = new float[3]; 1916 vec[0] = (angles[0] * FastMath.RAD_TO_DEG); 1917 vec[1] = (angles[1] * FastMath.RAD_TO_DEG); 1918 vec[2] = (angles[2] * FastMath.RAD_TO_DEG); 1919 setInverseRotationRadians(vec); 1920 } 1921 1922 /** 1923 * 1924 * <code>inverseTranslateVect</code> translates a given Vector3f by the 1925 * translation part of this matrix. 1926 * 1927 * @param vec 1928 * the Vector3f data to be translated. 1929 * @throws JmeException 1930 * if the size of the Vector3f is not 3. 1931 */ inverseTranslateVect(float[] vec)1932 public void inverseTranslateVect(float[] vec) { 1933 if (vec.length != 3) { 1934 throw new IllegalArgumentException( 1935 "vec must be of size 3."); 1936 } 1937 1938 vec[0] = vec[0] - m03; 1939 vec[1] = vec[1] - m13; 1940 vec[2] = vec[2] - m23; 1941 } 1942 1943 /** 1944 * 1945 * <code>inverseTranslateVect</code> translates a given Vector3f by the 1946 * translation part of this matrix. 1947 * 1948 * @param data 1949 * the Vector3f to be translated. 1950 * @throws JmeException 1951 * if the size of the Vector3f is not 3. 1952 */ inverseTranslateVect(Vector3f data)1953 public void inverseTranslateVect(Vector3f data) { 1954 data.x -= m03; 1955 data.y -= m13; 1956 data.z -= m23; 1957 } 1958 1959 /** 1960 * 1961 * <code>inverseTranslateVect</code> translates a given Vector3f by the 1962 * translation part of this matrix. 1963 * 1964 * @param data 1965 * the Vector3f to be translated. 1966 * @throws JmeException 1967 * if the size of the Vector3f is not 3. 1968 */ translateVect(Vector3f data)1969 public void translateVect(Vector3f data) { 1970 data.x += m03; 1971 data.y += m13; 1972 data.z += m23; 1973 } 1974 1975 /** 1976 * 1977 * <code>inverseRotateVect</code> rotates a given Vector3f by the rotation 1978 * part of this matrix. 1979 * 1980 * @param vec 1981 * the Vector3f to be rotated. 1982 */ inverseRotateVect(Vector3f vec)1983 public void inverseRotateVect(Vector3f vec) { 1984 float vx = vec.x, vy = vec.y, vz = vec.z; 1985 1986 vec.x = vx * m00 + vy * m10 + vz * m20; 1987 vec.y = vx * m01 + vy * m11 + vz * m21; 1988 vec.z = vx * m02 + vy * m12 + vz * m22; 1989 } 1990 rotateVect(Vector3f vec)1991 public void rotateVect(Vector3f vec) { 1992 float vx = vec.x, vy = vec.y, vz = vec.z; 1993 1994 vec.x = vx * m00 + vy * m01 + vz * m02; 1995 vec.y = vx * m10 + vy * m11 + vz * m12; 1996 vec.z = vx * m20 + vy * m21 + vz * m22; 1997 } 1998 1999 /** 2000 * <code>toString</code> returns the string representation of this object. 2001 * It is in a format of a 4x4 matrix. For example, an identity matrix would 2002 * be represented by the following string. com.jme.math.Matrix3f <br>[<br> 2003 * 1.0 0.0 0.0 0.0 <br> 2004 * 0.0 1.0 0.0 0.0 <br> 2005 * 0.0 0.0 1.0 0.0 <br> 2006 * 0.0 0.0 0.0 1.0 <br>]<br> 2007 * 2008 * @return the string representation of this object. 2009 */ 2010 @Override toString()2011 public String toString() { 2012 StringBuilder result = new StringBuilder("Matrix4f\n[\n"); 2013 result.append(" "); 2014 result.append(m00); 2015 result.append(" "); 2016 result.append(m01); 2017 result.append(" "); 2018 result.append(m02); 2019 result.append(" "); 2020 result.append(m03); 2021 result.append(" \n"); 2022 result.append(" "); 2023 result.append(m10); 2024 result.append(" "); 2025 result.append(m11); 2026 result.append(" "); 2027 result.append(m12); 2028 result.append(" "); 2029 result.append(m13); 2030 result.append(" \n"); 2031 result.append(" "); 2032 result.append(m20); 2033 result.append(" "); 2034 result.append(m21); 2035 result.append(" "); 2036 result.append(m22); 2037 result.append(" "); 2038 result.append(m23); 2039 result.append(" \n"); 2040 result.append(" "); 2041 result.append(m30); 2042 result.append(" "); 2043 result.append(m31); 2044 result.append(" "); 2045 result.append(m32); 2046 result.append(" "); 2047 result.append(m33); 2048 result.append(" \n]"); 2049 return result.toString(); 2050 } 2051 2052 /** 2053 * 2054 * <code>hashCode</code> returns the hash code value as an integer and is 2055 * supported for the benefit of hashing based collection classes such as 2056 * Hashtable, HashMap, HashSet etc. 2057 * 2058 * @return the hashcode for this instance of Matrix4f. 2059 * @see java.lang.Object#hashCode() 2060 */ 2061 @Override hashCode()2062 public int hashCode() { 2063 int hash = 37; 2064 hash = 37 * hash + Float.floatToIntBits(m00); 2065 hash = 37 * hash + Float.floatToIntBits(m01); 2066 hash = 37 * hash + Float.floatToIntBits(m02); 2067 hash = 37 * hash + Float.floatToIntBits(m03); 2068 2069 hash = 37 * hash + Float.floatToIntBits(m10); 2070 hash = 37 * hash + Float.floatToIntBits(m11); 2071 hash = 37 * hash + Float.floatToIntBits(m12); 2072 hash = 37 * hash + Float.floatToIntBits(m13); 2073 2074 hash = 37 * hash + Float.floatToIntBits(m20); 2075 hash = 37 * hash + Float.floatToIntBits(m21); 2076 hash = 37 * hash + Float.floatToIntBits(m22); 2077 hash = 37 * hash + Float.floatToIntBits(m23); 2078 2079 hash = 37 * hash + Float.floatToIntBits(m30); 2080 hash = 37 * hash + Float.floatToIntBits(m31); 2081 hash = 37 * hash + Float.floatToIntBits(m32); 2082 hash = 37 * hash + Float.floatToIntBits(m33); 2083 2084 return hash; 2085 } 2086 2087 /** 2088 * are these two matrices the same? they are is they both have the same mXX values. 2089 * 2090 * @param o 2091 * the object to compare for equality 2092 * @return true if they are equal 2093 */ 2094 @Override equals(Object o)2095 public boolean equals(Object o) { 2096 if (!(o instanceof Matrix4f) || o == null) { 2097 return false; 2098 } 2099 2100 if (this == o) { 2101 return true; 2102 } 2103 2104 Matrix4f comp = (Matrix4f) o; 2105 if (Float.compare(m00, comp.m00) != 0) { 2106 return false; 2107 } 2108 if (Float.compare(m01, comp.m01) != 0) { 2109 return false; 2110 } 2111 if (Float.compare(m02, comp.m02) != 0) { 2112 return false; 2113 } 2114 if (Float.compare(m03, comp.m03) != 0) { 2115 return false; 2116 } 2117 2118 if (Float.compare(m10, comp.m10) != 0) { 2119 return false; 2120 } 2121 if (Float.compare(m11, comp.m11) != 0) { 2122 return false; 2123 } 2124 if (Float.compare(m12, comp.m12) != 0) { 2125 return false; 2126 } 2127 if (Float.compare(m13, comp.m13) != 0) { 2128 return false; 2129 } 2130 2131 if (Float.compare(m20, comp.m20) != 0) { 2132 return false; 2133 } 2134 if (Float.compare(m21, comp.m21) != 0) { 2135 return false; 2136 } 2137 if (Float.compare(m22, comp.m22) != 0) { 2138 return false; 2139 } 2140 if (Float.compare(m23, comp.m23) != 0) { 2141 return false; 2142 } 2143 2144 if (Float.compare(m30, comp.m30) != 0) { 2145 return false; 2146 } 2147 if (Float.compare(m31, comp.m31) != 0) { 2148 return false; 2149 } 2150 if (Float.compare(m32, comp.m32) != 0) { 2151 return false; 2152 } 2153 if (Float.compare(m33, comp.m33) != 0) { 2154 return false; 2155 } 2156 2157 return true; 2158 } 2159 write(JmeExporter e)2160 public void write(JmeExporter e) throws IOException { 2161 OutputCapsule cap = e.getCapsule(this); 2162 cap.write(m00, "m00", 1); 2163 cap.write(m01, "m01", 0); 2164 cap.write(m02, "m02", 0); 2165 cap.write(m03, "m03", 0); 2166 cap.write(m10, "m10", 0); 2167 cap.write(m11, "m11", 1); 2168 cap.write(m12, "m12", 0); 2169 cap.write(m13, "m13", 0); 2170 cap.write(m20, "m20", 0); 2171 cap.write(m21, "m21", 0); 2172 cap.write(m22, "m22", 1); 2173 cap.write(m23, "m23", 0); 2174 cap.write(m30, "m30", 0); 2175 cap.write(m31, "m31", 0); 2176 cap.write(m32, "m32", 0); 2177 cap.write(m33, "m33", 1); 2178 } 2179 read(JmeImporter e)2180 public void read(JmeImporter e) throws IOException { 2181 InputCapsule cap = e.getCapsule(this); 2182 m00 = cap.readFloat("m00", 1); 2183 m01 = cap.readFloat("m01", 0); 2184 m02 = cap.readFloat("m02", 0); 2185 m03 = cap.readFloat("m03", 0); 2186 m10 = cap.readFloat("m10", 0); 2187 m11 = cap.readFloat("m11", 1); 2188 m12 = cap.readFloat("m12", 0); 2189 m13 = cap.readFloat("m13", 0); 2190 m20 = cap.readFloat("m20", 0); 2191 m21 = cap.readFloat("m21", 0); 2192 m22 = cap.readFloat("m22", 1); 2193 m23 = cap.readFloat("m23", 0); 2194 m30 = cap.readFloat("m30", 0); 2195 m31 = cap.readFloat("m31", 0); 2196 m32 = cap.readFloat("m32", 0); 2197 m33 = cap.readFloat("m33", 1); 2198 } 2199 2200 /** 2201 * @return true if this matrix is identity 2202 */ isIdentity()2203 public boolean isIdentity() { 2204 return (m00 == 1 && m01 == 0 && m02 == 0 && m03 == 0) 2205 && (m10 == 0 && m11 == 1 && m12 == 0 && m13 == 0) 2206 && (m20 == 0 && m21 == 0 && m22 == 1 && m23 == 0) 2207 && (m30 == 0 && m31 == 0 && m32 == 0 && m33 == 1); 2208 } 2209 2210 /** 2211 * Apply a scale to this matrix. 2212 * 2213 * @param scale 2214 * the scale to apply 2215 */ scale(Vector3f scale)2216 public void scale(Vector3f scale) { 2217 m00 *= scale.getX(); 2218 m10 *= scale.getX(); 2219 m20 *= scale.getX(); 2220 m30 *= scale.getX(); 2221 m01 *= scale.getY(); 2222 m11 *= scale.getY(); 2223 m21 *= scale.getY(); 2224 m31 *= scale.getY(); 2225 m02 *= scale.getZ(); 2226 m12 *= scale.getZ(); 2227 m22 *= scale.getZ(); 2228 m32 *= scale.getZ(); 2229 } 2230 equalIdentity(Matrix4f mat)2231 static boolean equalIdentity(Matrix4f mat) { 2232 if (Math.abs(mat.m00 - 1) > 1e-4) { 2233 return false; 2234 } 2235 if (Math.abs(mat.m11 - 1) > 1e-4) { 2236 return false; 2237 } 2238 if (Math.abs(mat.m22 - 1) > 1e-4) { 2239 return false; 2240 } 2241 if (Math.abs(mat.m33 - 1) > 1e-4) { 2242 return false; 2243 } 2244 2245 if (Math.abs(mat.m01) > 1e-4) { 2246 return false; 2247 } 2248 if (Math.abs(mat.m02) > 1e-4) { 2249 return false; 2250 } 2251 if (Math.abs(mat.m03) > 1e-4) { 2252 return false; 2253 } 2254 2255 if (Math.abs(mat.m10) > 1e-4) { 2256 return false; 2257 } 2258 if (Math.abs(mat.m12) > 1e-4) { 2259 return false; 2260 } 2261 if (Math.abs(mat.m13) > 1e-4) { 2262 return false; 2263 } 2264 2265 if (Math.abs(mat.m20) > 1e-4) { 2266 return false; 2267 } 2268 if (Math.abs(mat.m21) > 1e-4) { 2269 return false; 2270 } 2271 if (Math.abs(mat.m23) > 1e-4) { 2272 return false; 2273 } 2274 2275 if (Math.abs(mat.m30) > 1e-4) { 2276 return false; 2277 } 2278 if (Math.abs(mat.m31) > 1e-4) { 2279 return false; 2280 } 2281 if (Math.abs(mat.m32) > 1e-4) { 2282 return false; 2283 } 2284 2285 return true; 2286 } 2287 2288 // XXX: This tests more solid than converting the q to a matrix and multiplying... why? multLocal(Quaternion rotation)2289 public void multLocal(Quaternion rotation) { 2290 Vector3f axis = new Vector3f(); 2291 float angle = rotation.toAngleAxis(axis); 2292 Matrix4f matrix4f = new Matrix4f(); 2293 matrix4f.fromAngleAxis(angle, axis); 2294 multLocal(matrix4f); 2295 } 2296 2297 @Override clone()2298 public Matrix4f clone() { 2299 try { 2300 return (Matrix4f) super.clone(); 2301 } catch (CloneNotSupportedException e) { 2302 throw new AssertionError(); // can not happen 2303 } 2304 } 2305 } 2306