1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 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 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software 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 org.lwjgl.util.vector; 33 34 import java.io.Serializable; 35 import java.nio.FloatBuffer; 36 37 /** 38 * Holds a 4x4 float matrix. 39 * 40 * @author foo 41 */ 42 public class Matrix4f extends Matrix implements Serializable { 43 private static final long serialVersionUID = 1L; 44 45 public float m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33; 46 47 /** 48 * Construct a new matrix, initialized to the identity. 49 */ Matrix4f()50 public Matrix4f() { 51 super(); 52 setIdentity(); 53 } 54 Matrix4f(final Matrix4f src)55 public Matrix4f(final Matrix4f src) { 56 super(); 57 load(src); 58 } 59 60 /** 61 * Returns a string representation of this matrix 62 */ toString()63 public String toString() { 64 StringBuilder buf = new StringBuilder(); 65 buf.append(m00).append(' ').append(m10).append(' ').append(m20).append(' ').append(m30).append('\n'); 66 buf.append(m01).append(' ').append(m11).append(' ').append(m21).append(' ').append(m31).append('\n'); 67 buf.append(m02).append(' ').append(m12).append(' ').append(m22).append(' ').append(m32).append('\n'); 68 buf.append(m03).append(' ').append(m13).append(' ').append(m23).append(' ').append(m33).append('\n'); 69 return buf.toString(); 70 } 71 72 /** 73 * Set this matrix to be the identity matrix. 74 * @return this 75 */ setIdentity()76 public Matrix setIdentity() { 77 return setIdentity(this); 78 } 79 80 /** 81 * Set the given matrix to be the identity matrix. 82 * @param m The matrix to set to the identity 83 * @return m 84 */ setIdentity(Matrix4f m)85 public static Matrix4f setIdentity(Matrix4f m) { 86 m.m00 = 1.0f; 87 m.m01 = 0.0f; 88 m.m02 = 0.0f; 89 m.m03 = 0.0f; 90 m.m10 = 0.0f; 91 m.m11 = 1.0f; 92 m.m12 = 0.0f; 93 m.m13 = 0.0f; 94 m.m20 = 0.0f; 95 m.m21 = 0.0f; 96 m.m22 = 1.0f; 97 m.m23 = 0.0f; 98 m.m30 = 0.0f; 99 m.m31 = 0.0f; 100 m.m32 = 0.0f; 101 m.m33 = 1.0f; 102 103 return m; 104 } 105 106 /** 107 * Set this matrix to 0. 108 * @return this 109 */ setZero()110 public Matrix setZero() { 111 return setZero(this); 112 } 113 114 /** 115 * Set the given matrix to 0. 116 * @param m The matrix to set to 0 117 * @return m 118 */ setZero(Matrix4f m)119 public static Matrix4f setZero(Matrix4f m) { 120 m.m00 = 0.0f; 121 m.m01 = 0.0f; 122 m.m02 = 0.0f; 123 m.m03 = 0.0f; 124 m.m10 = 0.0f; 125 m.m11 = 0.0f; 126 m.m12 = 0.0f; 127 m.m13 = 0.0f; 128 m.m20 = 0.0f; 129 m.m21 = 0.0f; 130 m.m22 = 0.0f; 131 m.m23 = 0.0f; 132 m.m30 = 0.0f; 133 m.m31 = 0.0f; 134 m.m32 = 0.0f; 135 m.m33 = 0.0f; 136 137 return m; 138 } 139 140 /** 141 * Load from another matrix4f 142 * @param src The source matrix 143 * @return this 144 */ load(Matrix4f src)145 public Matrix4f load(Matrix4f src) { 146 return load(src, this); 147 } 148 149 /** 150 * Copy the source matrix to the destination matrix 151 * @param src The source matrix 152 * @param dest The destination matrix, or null of a new one is to be created 153 * @return The copied matrix 154 */ load(Matrix4f src, Matrix4f dest)155 public static Matrix4f load(Matrix4f src, Matrix4f dest) { 156 if (dest == null) 157 dest = new Matrix4f(); 158 dest.m00 = src.m00; 159 dest.m01 = src.m01; 160 dest.m02 = src.m02; 161 dest.m03 = src.m03; 162 dest.m10 = src.m10; 163 dest.m11 = src.m11; 164 dest.m12 = src.m12; 165 dest.m13 = src.m13; 166 dest.m20 = src.m20; 167 dest.m21 = src.m21; 168 dest.m22 = src.m22; 169 dest.m23 = src.m23; 170 dest.m30 = src.m30; 171 dest.m31 = src.m31; 172 dest.m32 = src.m32; 173 dest.m33 = src.m33; 174 175 return dest; 176 } 177 178 /** 179 * Load from a float buffer. The buffer stores the matrix in column major 180 * (OpenGL) order. 181 * 182 * @param buf A float buffer to read from 183 * @return this 184 */ load(FloatBuffer buf)185 public Matrix load(FloatBuffer buf) { 186 187 m00 = buf.get(); 188 m01 = buf.get(); 189 m02 = buf.get(); 190 m03 = buf.get(); 191 m10 = buf.get(); 192 m11 = buf.get(); 193 m12 = buf.get(); 194 m13 = buf.get(); 195 m20 = buf.get(); 196 m21 = buf.get(); 197 m22 = buf.get(); 198 m23 = buf.get(); 199 m30 = buf.get(); 200 m31 = buf.get(); 201 m32 = buf.get(); 202 m33 = buf.get(); 203 204 return this; 205 } 206 207 /** 208 * Load from a float buffer. The buffer stores the matrix in row major 209 * (maths) order. 210 * 211 * @param buf A float buffer to read from 212 * @return this 213 */ loadTranspose(FloatBuffer buf)214 public Matrix loadTranspose(FloatBuffer buf) { 215 216 m00 = buf.get(); 217 m10 = buf.get(); 218 m20 = buf.get(); 219 m30 = buf.get(); 220 m01 = buf.get(); 221 m11 = buf.get(); 222 m21 = buf.get(); 223 m31 = buf.get(); 224 m02 = buf.get(); 225 m12 = buf.get(); 226 m22 = buf.get(); 227 m32 = buf.get(); 228 m03 = buf.get(); 229 m13 = buf.get(); 230 m23 = buf.get(); 231 m33 = buf.get(); 232 233 return this; 234 } 235 236 /** 237 * Store this matrix in a float buffer. The matrix is stored in column 238 * major (openGL) order. 239 * @param buf The buffer to store this matrix in 240 */ store(FloatBuffer buf)241 public Matrix store(FloatBuffer buf) { 242 buf.put(m00); 243 buf.put(m01); 244 buf.put(m02); 245 buf.put(m03); 246 buf.put(m10); 247 buf.put(m11); 248 buf.put(m12); 249 buf.put(m13); 250 buf.put(m20); 251 buf.put(m21); 252 buf.put(m22); 253 buf.put(m23); 254 buf.put(m30); 255 buf.put(m31); 256 buf.put(m32); 257 buf.put(m33); 258 return this; 259 } 260 261 /** 262 * Store this matrix in a float buffer. The matrix is stored in row 263 * major (maths) order. 264 * @param buf The buffer to store this matrix in 265 */ storeTranspose(FloatBuffer buf)266 public Matrix storeTranspose(FloatBuffer buf) { 267 buf.put(m00); 268 buf.put(m10); 269 buf.put(m20); 270 buf.put(m30); 271 buf.put(m01); 272 buf.put(m11); 273 buf.put(m21); 274 buf.put(m31); 275 buf.put(m02); 276 buf.put(m12); 277 buf.put(m22); 278 buf.put(m32); 279 buf.put(m03); 280 buf.put(m13); 281 buf.put(m23); 282 buf.put(m33); 283 return this; 284 } 285 286 /** 287 * Store the rotation portion of this matrix in a float buffer. The matrix is stored in column 288 * major (openGL) order. 289 * @param buf The buffer to store this matrix in 290 */ store3f(FloatBuffer buf)291 public Matrix store3f(FloatBuffer buf) { 292 buf.put(m00); 293 buf.put(m01); 294 buf.put(m02); 295 buf.put(m10); 296 buf.put(m11); 297 buf.put(m12); 298 buf.put(m20); 299 buf.put(m21); 300 buf.put(m22); 301 return this; 302 } 303 304 /** 305 * Add two matrices together and place the result in a third matrix. 306 * @param left The left source matrix 307 * @param right The right source matrix 308 * @param dest The destination matrix, or null if a new one is to be created 309 * @return the destination matrix 310 */ add(Matrix4f left, Matrix4f right, Matrix4f dest)311 public static Matrix4f add(Matrix4f left, Matrix4f right, Matrix4f dest) { 312 if (dest == null) 313 dest = new Matrix4f(); 314 315 dest.m00 = left.m00 + right.m00; 316 dest.m01 = left.m01 + right.m01; 317 dest.m02 = left.m02 + right.m02; 318 dest.m03 = left.m03 + right.m03; 319 dest.m10 = left.m10 + right.m10; 320 dest.m11 = left.m11 + right.m11; 321 dest.m12 = left.m12 + right.m12; 322 dest.m13 = left.m13 + right.m13; 323 dest.m20 = left.m20 + right.m20; 324 dest.m21 = left.m21 + right.m21; 325 dest.m22 = left.m22 + right.m22; 326 dest.m23 = left.m23 + right.m23; 327 dest.m30 = left.m30 + right.m30; 328 dest.m31 = left.m31 + right.m31; 329 dest.m32 = left.m32 + right.m32; 330 dest.m33 = left.m33 + right.m33; 331 332 return dest; 333 } 334 335 /** 336 * Subtract the right matrix from the left and place the result in a third matrix. 337 * @param left The left source matrix 338 * @param right The right source matrix 339 * @param dest The destination matrix, or null if a new one is to be created 340 * @return the destination matrix 341 */ sub(Matrix4f left, Matrix4f right, Matrix4f dest)342 public static Matrix4f sub(Matrix4f left, Matrix4f right, Matrix4f dest) { 343 if (dest == null) 344 dest = new Matrix4f(); 345 346 dest.m00 = left.m00 - right.m00; 347 dest.m01 = left.m01 - right.m01; 348 dest.m02 = left.m02 - right.m02; 349 dest.m03 = left.m03 - right.m03; 350 dest.m10 = left.m10 - right.m10; 351 dest.m11 = left.m11 - right.m11; 352 dest.m12 = left.m12 - right.m12; 353 dest.m13 = left.m13 - right.m13; 354 dest.m20 = left.m20 - right.m20; 355 dest.m21 = left.m21 - right.m21; 356 dest.m22 = left.m22 - right.m22; 357 dest.m23 = left.m23 - right.m23; 358 dest.m30 = left.m30 - right.m30; 359 dest.m31 = left.m31 - right.m31; 360 dest.m32 = left.m32 - right.m32; 361 dest.m33 = left.m33 - right.m33; 362 363 return dest; 364 } 365 366 /** 367 * Multiply the right matrix by the left and place the result in a third matrix. 368 * @param left The left source matrix 369 * @param right The right source matrix 370 * @param dest The destination matrix, or null if a new one is to be created 371 * @return the destination matrix 372 */ mul(Matrix4f left, Matrix4f right, Matrix4f dest)373 public static Matrix4f mul(Matrix4f left, Matrix4f right, Matrix4f dest) { 374 if (dest == null) 375 dest = new Matrix4f(); 376 377 float m00 = left.m00 * right.m00 + left.m10 * right.m01 + left.m20 * right.m02 + left.m30 * right.m03; 378 float m01 = left.m01 * right.m00 + left.m11 * right.m01 + left.m21 * right.m02 + left.m31 * right.m03; 379 float m02 = left.m02 * right.m00 + left.m12 * right.m01 + left.m22 * right.m02 + left.m32 * right.m03; 380 float m03 = left.m03 * right.m00 + left.m13 * right.m01 + left.m23 * right.m02 + left.m33 * right.m03; 381 float m10 = left.m00 * right.m10 + left.m10 * right.m11 + left.m20 * right.m12 + left.m30 * right.m13; 382 float m11 = left.m01 * right.m10 + left.m11 * right.m11 + left.m21 * right.m12 + left.m31 * right.m13; 383 float m12 = left.m02 * right.m10 + left.m12 * right.m11 + left.m22 * right.m12 + left.m32 * right.m13; 384 float m13 = left.m03 * right.m10 + left.m13 * right.m11 + left.m23 * right.m12 + left.m33 * right.m13; 385 float m20 = left.m00 * right.m20 + left.m10 * right.m21 + left.m20 * right.m22 + left.m30 * right.m23; 386 float m21 = left.m01 * right.m20 + left.m11 * right.m21 + left.m21 * right.m22 + left.m31 * right.m23; 387 float m22 = left.m02 * right.m20 + left.m12 * right.m21 + left.m22 * right.m22 + left.m32 * right.m23; 388 float m23 = left.m03 * right.m20 + left.m13 * right.m21 + left.m23 * right.m22 + left.m33 * right.m23; 389 float m30 = left.m00 * right.m30 + left.m10 * right.m31 + left.m20 * right.m32 + left.m30 * right.m33; 390 float m31 = left.m01 * right.m30 + left.m11 * right.m31 + left.m21 * right.m32 + left.m31 * right.m33; 391 float m32 = left.m02 * right.m30 + left.m12 * right.m31 + left.m22 * right.m32 + left.m32 * right.m33; 392 float m33 = left.m03 * right.m30 + left.m13 * right.m31 + left.m23 * right.m32 + left.m33 * right.m33; 393 394 dest.m00 = m00; 395 dest.m01 = m01; 396 dest.m02 = m02; 397 dest.m03 = m03; 398 dest.m10 = m10; 399 dest.m11 = m11; 400 dest.m12 = m12; 401 dest.m13 = m13; 402 dest.m20 = m20; 403 dest.m21 = m21; 404 dest.m22 = m22; 405 dest.m23 = m23; 406 dest.m30 = m30; 407 dest.m31 = m31; 408 dest.m32 = m32; 409 dest.m33 = m33; 410 411 return dest; 412 } 413 414 /** 415 * Transform a Vector by a matrix and return the result in a destination 416 * vector. 417 * @param left The left matrix 418 * @param right The right vector 419 * @param dest The destination vector, or null if a new one is to be created 420 * @return the destination vector 421 */ transform(Matrix4f left, Vector4f right, Vector4f dest)422 public static Vector4f transform(Matrix4f left, Vector4f right, Vector4f dest) { 423 if (dest == null) 424 dest = new Vector4f(); 425 426 float x = left.m00 * right.x + left.m10 * right.y + left.m20 * right.z + left.m30 * right.w; 427 float y = left.m01 * right.x + left.m11 * right.y + left.m21 * right.z + left.m31 * right.w; 428 float z = left.m02 * right.x + left.m12 * right.y + left.m22 * right.z + left.m32 * right.w; 429 float w = left.m03 * right.x + left.m13 * right.y + left.m23 * right.z + left.m33 * right.w; 430 431 dest.x = x; 432 dest.y = y; 433 dest.z = z; 434 dest.w = w; 435 436 return dest; 437 } 438 439 /** 440 * Transpose this matrix 441 * @return this 442 */ transpose()443 public Matrix transpose() { 444 return transpose(this); 445 } 446 447 /** 448 * Translate this matrix 449 * @param vec The vector to translate by 450 * @return this 451 */ translate(Vector2f vec)452 public Matrix4f translate(Vector2f vec) { 453 return translate(vec, this); 454 } 455 456 /** 457 * Translate this matrix 458 * @param vec The vector to translate by 459 * @return this 460 */ translate(Vector3f vec)461 public Matrix4f translate(Vector3f vec) { 462 return translate(vec, this); 463 } 464 465 /** 466 * Scales this matrix 467 * @param vec The vector to scale by 468 * @return this 469 */ scale(Vector3f vec)470 public Matrix4f scale(Vector3f vec) { 471 return scale(vec, this, this); 472 } 473 474 /** 475 * Scales the source matrix and put the result in the destination matrix 476 * @param vec The vector to scale by 477 * @param src The source matrix 478 * @param dest The destination matrix, or null if a new matrix is to be created 479 * @return The scaled matrix 480 */ scale(Vector3f vec, Matrix4f src, Matrix4f dest)481 public static Matrix4f scale(Vector3f vec, Matrix4f src, Matrix4f dest) { 482 if (dest == null) 483 dest = new Matrix4f(); 484 dest.m00 = src.m00 * vec.x; 485 dest.m01 = src.m01 * vec.x; 486 dest.m02 = src.m02 * vec.x; 487 dest.m03 = src.m03 * vec.x; 488 dest.m10 = src.m10 * vec.y; 489 dest.m11 = src.m11 * vec.y; 490 dest.m12 = src.m12 * vec.y; 491 dest.m13 = src.m13 * vec.y; 492 dest.m20 = src.m20 * vec.z; 493 dest.m21 = src.m21 * vec.z; 494 dest.m22 = src.m22 * vec.z; 495 dest.m23 = src.m23 * vec.z; 496 return dest; 497 } 498 499 /** 500 * Rotates the matrix around the given axis the specified angle 501 * @param angle the angle, in radians. 502 * @param axis The vector representing the rotation axis. Must be normalized. 503 * @return this 504 */ rotate(float angle, Vector3f axis)505 public Matrix4f rotate(float angle, Vector3f axis) { 506 return rotate(angle, axis, this); 507 } 508 509 /** 510 * Rotates the matrix around the given axis the specified angle 511 * @param angle the angle, in radians. 512 * @param axis The vector representing the rotation axis. Must be normalized. 513 * @param dest The matrix to put the result, or null if a new matrix is to be created 514 * @return The rotated matrix 515 */ rotate(float angle, Vector3f axis, Matrix4f dest)516 public Matrix4f rotate(float angle, Vector3f axis, Matrix4f dest) { 517 return rotate(angle, axis, this, dest); 518 } 519 520 /** 521 * Rotates the source matrix around the given axis the specified angle and 522 * put the result in the destination matrix. 523 * @param angle the angle, in radians. 524 * @param axis The vector representing the rotation axis. Must be normalized. 525 * @param src The matrix to rotate 526 * @param dest The matrix to put the result, or null if a new matrix is to be created 527 * @return The rotated matrix 528 */ rotate(float angle, Vector3f axis, Matrix4f src, Matrix4f dest)529 public static Matrix4f rotate(float angle, Vector3f axis, Matrix4f src, Matrix4f dest) { 530 if (dest == null) 531 dest = new Matrix4f(); 532 float c = (float) Math.cos(angle); 533 float s = (float) Math.sin(angle); 534 float oneminusc = 1.0f - c; 535 float xy = axis.x*axis.y; 536 float yz = axis.y*axis.z; 537 float xz = axis.x*axis.z; 538 float xs = axis.x*s; 539 float ys = axis.y*s; 540 float zs = axis.z*s; 541 542 float f00 = axis.x*axis.x*oneminusc+c; 543 float f01 = xy*oneminusc+zs; 544 float f02 = xz*oneminusc-ys; 545 // n[3] not used 546 float f10 = xy*oneminusc-zs; 547 float f11 = axis.y*axis.y*oneminusc+c; 548 float f12 = yz*oneminusc+xs; 549 // n[7] not used 550 float f20 = xz*oneminusc+ys; 551 float f21 = yz*oneminusc-xs; 552 float f22 = axis.z*axis.z*oneminusc+c; 553 554 float t00 = src.m00 * f00 + src.m10 * f01 + src.m20 * f02; 555 float t01 = src.m01 * f00 + src.m11 * f01 + src.m21 * f02; 556 float t02 = src.m02 * f00 + src.m12 * f01 + src.m22 * f02; 557 float t03 = src.m03 * f00 + src.m13 * f01 + src.m23 * f02; 558 float t10 = src.m00 * f10 + src.m10 * f11 + src.m20 * f12; 559 float t11 = src.m01 * f10 + src.m11 * f11 + src.m21 * f12; 560 float t12 = src.m02 * f10 + src.m12 * f11 + src.m22 * f12; 561 float t13 = src.m03 * f10 + src.m13 * f11 + src.m23 * f12; 562 dest.m20 = src.m00 * f20 + src.m10 * f21 + src.m20 * f22; 563 dest.m21 = src.m01 * f20 + src.m11 * f21 + src.m21 * f22; 564 dest.m22 = src.m02 * f20 + src.m12 * f21 + src.m22 * f22; 565 dest.m23 = src.m03 * f20 + src.m13 * f21 + src.m23 * f22; 566 dest.m00 = t00; 567 dest.m01 = t01; 568 dest.m02 = t02; 569 dest.m03 = t03; 570 dest.m10 = t10; 571 dest.m11 = t11; 572 dest.m12 = t12; 573 dest.m13 = t13; 574 return dest; 575 } 576 577 /** 578 * Translate this matrix and stash the result in another matrix 579 * @param vec The vector to translate by 580 * @param dest The destination matrix or null if a new matrix is to be created 581 * @return the translated matrix 582 */ translate(Vector3f vec, Matrix4f dest)583 public Matrix4f translate(Vector3f vec, Matrix4f dest) { 584 return translate(vec, this, dest); 585 } 586 587 /** 588 * Translate the source matrix and stash the result in the destination matrix 589 * @param vec The vector to translate by 590 * @param src The source matrix 591 * @param dest The destination matrix or null if a new matrix is to be created 592 * @return The translated matrix 593 */ translate(Vector3f vec, Matrix4f src, Matrix4f dest)594 public static Matrix4f translate(Vector3f vec, Matrix4f src, Matrix4f dest) { 595 if (dest == null) 596 dest = new Matrix4f(); 597 598 dest.m30 += src.m00 * vec.x + src.m10 * vec.y + src.m20 * vec.z; 599 dest.m31 += src.m01 * vec.x + src.m11 * vec.y + src.m21 * vec.z; 600 dest.m32 += src.m02 * vec.x + src.m12 * vec.y + src.m22 * vec.z; 601 dest.m33 += src.m03 * vec.x + src.m13 * vec.y + src.m23 * vec.z; 602 603 return dest; 604 } 605 606 /** 607 * Translate this matrix and stash the result in another matrix 608 * @param vec The vector to translate by 609 * @param dest The destination matrix or null if a new matrix is to be created 610 * @return the translated matrix 611 */ translate(Vector2f vec, Matrix4f dest)612 public Matrix4f translate(Vector2f vec, Matrix4f dest) { 613 return translate(vec, this, dest); 614 } 615 616 /** 617 * Translate the source matrix and stash the result in the destination matrix 618 * @param vec The vector to translate by 619 * @param src The source matrix 620 * @param dest The destination matrix or null if a new matrix is to be created 621 * @return The translated matrix 622 */ translate(Vector2f vec, Matrix4f src, Matrix4f dest)623 public static Matrix4f translate(Vector2f vec, Matrix4f src, Matrix4f dest) { 624 if (dest == null) 625 dest = new Matrix4f(); 626 627 dest.m30 += src.m00 * vec.x + src.m10 * vec.y; 628 dest.m31 += src.m01 * vec.x + src.m11 * vec.y; 629 dest.m32 += src.m02 * vec.x + src.m12 * vec.y; 630 dest.m33 += src.m03 * vec.x + src.m13 * vec.y; 631 632 return dest; 633 } 634 635 /** 636 * Transpose this matrix and place the result in another matrix 637 * @param dest The destination matrix or null if a new matrix is to be created 638 * @return the transposed matrix 639 */ transpose(Matrix4f dest)640 public Matrix4f transpose(Matrix4f dest) { 641 return transpose(this, dest); 642 } 643 644 /** 645 * Transpose the source matrix and place the result in the destination matrix 646 * @param src The source matrix 647 * @param dest The destination matrix or null if a new matrix is to be created 648 * @return the transposed matrix 649 */ transpose(Matrix4f src, Matrix4f dest)650 public static Matrix4f transpose(Matrix4f src, Matrix4f dest) { 651 if (dest == null) 652 dest = new Matrix4f(); 653 float m00 = src.m00; 654 float m01 = src.m10; 655 float m02 = src.m20; 656 float m03 = src.m30; 657 float m10 = src.m01; 658 float m11 = src.m11; 659 float m12 = src.m21; 660 float m13 = src.m31; 661 float m20 = src.m02; 662 float m21 = src.m12; 663 float m22 = src.m22; 664 float m23 = src.m32; 665 float m30 = src.m03; 666 float m31 = src.m13; 667 float m32 = src.m23; 668 float m33 = src.m33; 669 670 dest.m00 = m00; 671 dest.m01 = m01; 672 dest.m02 = m02; 673 dest.m03 = m03; 674 dest.m10 = m10; 675 dest.m11 = m11; 676 dest.m12 = m12; 677 dest.m13 = m13; 678 dest.m20 = m20; 679 dest.m21 = m21; 680 dest.m22 = m22; 681 dest.m23 = m23; 682 dest.m30 = m30; 683 dest.m31 = m31; 684 dest.m32 = m32; 685 dest.m33 = m33; 686 687 return dest; 688 } 689 690 /** 691 * @return the determinant of the matrix 692 */ determinant()693 public float determinant() { 694 float f = 695 m00 696 * ((m11 * m22 * m33 + m12 * m23 * m31 + m13 * m21 * m32) 697 - m13 * m22 * m31 698 - m11 * m23 * m32 699 - m12 * m21 * m33); 700 f -= m01 701 * ((m10 * m22 * m33 + m12 * m23 * m30 + m13 * m20 * m32) 702 - m13 * m22 * m30 703 - m10 * m23 * m32 704 - m12 * m20 * m33); 705 f += m02 706 * ((m10 * m21 * m33 + m11 * m23 * m30 + m13 * m20 * m31) 707 - m13 * m21 * m30 708 - m10 * m23 * m31 709 - m11 * m20 * m33); 710 f -= m03 711 * ((m10 * m21 * m32 + m11 * m22 * m30 + m12 * m20 * m31) 712 - m12 * m21 * m30 713 - m10 * m22 * m31 714 - m11 * m20 * m32); 715 return f; 716 } 717 718 /** 719 * Calculate the determinant of a 3x3 matrix 720 * @return result 721 */ 722 determinant3x3(float t00, float t01, float t02, float t10, float t11, float t12, float t20, float t21, float t22)723 private static float determinant3x3(float t00, float t01, float t02, 724 float t10, float t11, float t12, 725 float t20, float t21, float t22) 726 { 727 return t00 * (t11 * t22 - t12 * t21) 728 + t01 * (t12 * t20 - t10 * t22) 729 + t02 * (t10 * t21 - t11 * t20); 730 } 731 732 /** 733 * Invert this matrix 734 * @return this if successful, null otherwise 735 */ invert()736 public Matrix invert() { 737 return invert(this, this); 738 } 739 740 /** 741 * Invert the source matrix and put the result in the destination 742 * @param src The source matrix 743 * @param dest The destination matrix, or null if a new matrix is to be created 744 * @return The inverted matrix if successful, null otherwise 745 */ invert(Matrix4f src, Matrix4f dest)746 public static Matrix4f invert(Matrix4f src, Matrix4f dest) { 747 float determinant = src.determinant(); 748 749 if (determinant != 0) { 750 /* 751 * m00 m01 m02 m03 752 * m10 m11 m12 m13 753 * m20 m21 m22 m23 754 * m30 m31 m32 m33 755 */ 756 if (dest == null) 757 dest = new Matrix4f(); 758 float determinant_inv = 1f/determinant; 759 760 // first row 761 float t00 = determinant3x3(src.m11, src.m12, src.m13, src.m21, src.m22, src.m23, src.m31, src.m32, src.m33); 762 float t01 = -determinant3x3(src.m10, src.m12, src.m13, src.m20, src.m22, src.m23, src.m30, src.m32, src.m33); 763 float t02 = determinant3x3(src.m10, src.m11, src.m13, src.m20, src.m21, src.m23, src.m30, src.m31, src.m33); 764 float t03 = -determinant3x3(src.m10, src.m11, src.m12, src.m20, src.m21, src.m22, src.m30, src.m31, src.m32); 765 // second row 766 float t10 = -determinant3x3(src.m01, src.m02, src.m03, src.m21, src.m22, src.m23, src.m31, src.m32, src.m33); 767 float t11 = determinant3x3(src.m00, src.m02, src.m03, src.m20, src.m22, src.m23, src.m30, src.m32, src.m33); 768 float t12 = -determinant3x3(src.m00, src.m01, src.m03, src.m20, src.m21, src.m23, src.m30, src.m31, src.m33); 769 float t13 = determinant3x3(src.m00, src.m01, src.m02, src.m20, src.m21, src.m22, src.m30, src.m31, src.m32); 770 // third row 771 float t20 = determinant3x3(src.m01, src.m02, src.m03, src.m11, src.m12, src.m13, src.m31, src.m32, src.m33); 772 float t21 = -determinant3x3(src.m00, src.m02, src.m03, src.m10, src.m12, src.m13, src.m30, src.m32, src.m33); 773 float t22 = determinant3x3(src.m00, src.m01, src.m03, src.m10, src.m11, src.m13, src.m30, src.m31, src.m33); 774 float t23 = -determinant3x3(src.m00, src.m01, src.m02, src.m10, src.m11, src.m12, src.m30, src.m31, src.m32); 775 // fourth row 776 float t30 = -determinant3x3(src.m01, src.m02, src.m03, src.m11, src.m12, src.m13, src.m21, src.m22, src.m23); 777 float t31 = determinant3x3(src.m00, src.m02, src.m03, src.m10, src.m12, src.m13, src.m20, src.m22, src.m23); 778 float t32 = -determinant3x3(src.m00, src.m01, src.m03, src.m10, src.m11, src.m13, src.m20, src.m21, src.m23); 779 float t33 = determinant3x3(src.m00, src.m01, src.m02, src.m10, src.m11, src.m12, src.m20, src.m21, src.m22); 780 781 // transpose and divide by the determinant 782 dest.m00 = t00*determinant_inv; 783 dest.m11 = t11*determinant_inv; 784 dest.m22 = t22*determinant_inv; 785 dest.m33 = t33*determinant_inv; 786 dest.m01 = t10*determinant_inv; 787 dest.m10 = t01*determinant_inv; 788 dest.m20 = t02*determinant_inv; 789 dest.m02 = t20*determinant_inv; 790 dest.m12 = t21*determinant_inv; 791 dest.m21 = t12*determinant_inv; 792 dest.m03 = t30*determinant_inv; 793 dest.m30 = t03*determinant_inv; 794 dest.m13 = t31*determinant_inv; 795 dest.m31 = t13*determinant_inv; 796 dest.m32 = t23*determinant_inv; 797 dest.m23 = t32*determinant_inv; 798 return dest; 799 } else 800 return null; 801 } 802 803 /** 804 * Negate this matrix 805 * @return this 806 */ negate()807 public Matrix negate() { 808 return negate(this); 809 } 810 811 /** 812 * Negate this matrix and place the result in a destination matrix. 813 * @param dest The destination matrix, or null if a new matrix is to be created 814 * @return the negated matrix 815 */ negate(Matrix4f dest)816 public Matrix4f negate(Matrix4f dest) { 817 return negate(this, dest); 818 } 819 820 /** 821 * Negate this matrix and place the result in a destination matrix. 822 * @param src The source matrix 823 * @param dest The destination matrix, or null if a new matrix is to be created 824 * @return The negated matrix 825 */ negate(Matrix4f src, Matrix4f dest)826 public static Matrix4f negate(Matrix4f src, Matrix4f dest) { 827 if (dest == null) 828 dest = new Matrix4f(); 829 830 dest.m00 = -src.m00; 831 dest.m01 = -src.m01; 832 dest.m02 = -src.m02; 833 dest.m03 = -src.m03; 834 dest.m10 = -src.m10; 835 dest.m11 = -src.m11; 836 dest.m12 = -src.m12; 837 dest.m13 = -src.m13; 838 dest.m20 = -src.m20; 839 dest.m21 = -src.m21; 840 dest.m22 = -src.m22; 841 dest.m23 = -src.m23; 842 dest.m30 = -src.m30; 843 dest.m31 = -src.m31; 844 dest.m32 = -src.m32; 845 dest.m33 = -src.m33; 846 847 return dest; 848 } 849 } 850