1 module matrix_4x3d; 2 3 import Math = math; 4 import MemUtil = mem_util; 5 6 import matrix_3d; 7 import matrix_4d; 8 9 import vector_3d; 10 import vector_4d; 11 12 import axis_angle_4d; 13 import quaternion_d; 14 15 /* 16 * The MIT License 17 * 18 * Copyright (c) 2015-2021 Richard Greenlees 19 @$!@$# Translated by jordan4ibanez 20 * 21 * Permission is hereby granted, free of charge, to any person obtaining a copy 22 * of this software and associated documentation files (the "Software"), to deal 23 * in the Software without restriction, including without limitation the rights 24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 * copies of the Software, and to permit persons to whom the Software is 26 * furnished to do so, subject to the following conditions: 27 * 28 * The above copyright notice and this permission notice shall be included in 29 * all copies or substantial portions of the Software. 30 * 31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 * THE SOFTWARE. 38 */ 39 40 /** 41 * Contains the definition of an affine 4x3 matrix (4 columns, 3 rows) of doubles, and associated functions to transform 42 * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this: 43 * <p> 44 * m00 m10 m20 m30<br> 45 * m01 m11 m21 m31<br> 46 * m02 m12 m22 m32<br> 47 * 48 * @author Richard Greenlees 49 * @author Kai Burjack 50 */ 51 struct Matrix4x3d { 52 53 double m00 = 1.0; 54 double m01 = 0.0; 55 double m02 = 0.0; 56 57 double m10 = 0.0; 58 double m11 = 1.0; 59 double m12 = 0.0; 60 61 double m20 = 0.0; 62 double m21 = 0.0; 63 double m22 = 1.0; 64 65 double m30 = 0.0; 66 double m31 = 0.0; 67 double m32 = 0.0; 68 69 /** 70 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 71 * identifying the plane with equation <code>x=-1</code> when using the identity matrix. 72 */ 73 immutable static int PLANE_NX = 0; 74 /** 75 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 76 * identifying the plane with equation <code>x=1</code> when using the identity matrix. 77 */ 78 immutable static int PLANE_PX = 1; 79 /** 80 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 81 * identifying the plane with equation <code>y=-1</code> when using the identity matrix. 82 */ 83 immutable static int PLANE_NY = 2; 84 /** 85 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 86 * identifying the plane with equation <code>y=1</code> when using the identity matrix. 87 */ 88 immutable static int PLANE_PY = 3; 89 /** 90 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 91 * identifying the plane with equation <code>z=-1</code> when using the identity matrix. 92 */ 93 immutable static int PLANE_NZ = 4; 94 /** 95 * Argument to the first parameter of {@link #frustumPlane(int, Vector4d)} 96 * identifying the plane with equation <code>z=1</code> when using the identity matrix. 97 */ 98 immutable static int PLANE_PZ = 5; 99 100 /** 101 * Bit returned by {@link #properties()} to indicate that the matrix represents the identity transformation. 102 */ 103 immutable static byte PROPERTY_IDENTITY = 1<<2; 104 /** 105 * Bit returned by {@link #properties()} to indicate that the matrix represents a pure translation transformation. 106 */ 107 immutable static byte PROPERTY_TRANSLATION = 1<<3; 108 /** 109 * Bit returned by {@link #properties()} to indicate that the left 3x3 submatrix represents an orthogonal 110 * matrix (i.e. orthonormal basis). 111 */ 112 immutable static byte PROPERTY_ORTHONORMAL = 1<<4; 113 114 115 int properties = PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 116 117 /** 118 * Create a new {@link Matrix4x3d} and make it a copy of the given matrix. 119 * 120 * @param mat 121 * the {@link Matrix4x3d} to copy the values from 122 */ 123 this(Matrix4x3d mat) { 124 set(mat); 125 } 126 127 128 /** 129 * Create a new {@link Matrix4x3d} by setting its left 3x3 submatrix to the values of the given {@link Matrix3d} 130 * and the rest to identity. 131 * 132 * @param mat 133 * the {@link Matrix3d} 134 */ 135 this(Matrix3d mat) { 136 set(mat); 137 } 138 139 /** 140 * Create a new 4x4 matrix using the supplied double values. 141 * 142 * @param m00 143 * the value of m00 144 * @param m01 145 * the value of m01 146 * @param m02 147 * the value of m02 148 * @param m10 149 * the value of m10 150 * @param m11 151 * the value of m11 152 * @param m12 153 * the value of m12 154 * @param m20 155 * the value of m20 156 * @param m21 157 * the value of m21 158 * @param m22 159 * the value of m22 160 * @param m30 161 * the value of m30 162 * @param m31 163 * the value of m31 164 * @param m32 165 * the value of m32 166 */ 167 this(double m00, double m01, double m02, 168 double m10, double m11, double m12, 169 double m20, double m21, double m22, 170 double m30, double m31, double m32) { 171 this.m00 = m00; 172 this.m01 = m01; 173 this.m02 = m02; 174 this.m10 = m10; 175 this.m11 = m11; 176 this.m12 = m12; 177 this.m20 = m20; 178 this.m21 = m21; 179 this.m22 = m22; 180 this.m30 = m30; 181 this.m31 = m31; 182 this.m32 = m32; 183 determineProperties(); 184 } 185 186 /** 187 * Assume the given properties about this matrix. 188 * <p> 189 * Use one or multiple of 0, {@link Matrix4x3d#PROPERTY_IDENTITY}, 190 * {@link Matrix4x3d#PROPERTY_TRANSLATION}, {@link Matrix4x3d#PROPERTY_ORTHONORMAL}. 191 * 192 * @param properties 193 * bitset of the properties to assume about this matrix 194 * @return this 195 */ 196 ref public Matrix4x3d assume(int properties) return { 197 this.properties = properties; 198 return this; 199 } 200 201 /** 202 * Compute and set the matrix properties returned by {@link #properties()} based 203 * on the current matrix element values. 204 * 205 * @return this 206 */ 207 ref public Matrix4x3d determineProperties() return { 208 int __properties = 0; 209 if (m00 == 1.0 && m01 == 0.0 && m02 == 0.0 && m10 == 0.0 && m11 == 1.0 && m12 == 0.0 210 && m20 == 0.0 && m21 == 0.0 && m22 == 1.0) { 211 __properties |= PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 212 if (m30 == 0.0 && m31 == 0.0 && m32 == 0.0) 213 __properties |= PROPERTY_IDENTITY; 214 } 215 /* 216 * We do not determine orthogonality, since it would require arbitrary epsilons 217 * and is rather expensive (6 dot products) in the worst case. 218 */ 219 this.properties = __properties; 220 return this; 221 } 222 223 public int getproperties() { 224 return properties; 225 } 226 227 ref Matrix4x3d _properties(int properties) return { 228 this.properties = properties; 229 return this; 230 } 231 232 /** 233 * Set the value of the matrix element at column 0 and row 0 without updating the properties of the matrix. 234 * 235 * @param m00 236 * the new value 237 * @return this 238 */ 239 ref Matrix4x3d _m00(double m00) return { 240 this.m00 = m00; 241 return this; 242 } 243 /** 244 * Set the value of the matrix element at column 0 and row 1 without updating the properties of the matrix. 245 * 246 * @param m01 247 * the new value 248 * @return this 249 */ 250 ref Matrix4x3d _m01(double m01) return { 251 this.m01 = m01; 252 return this; 253 } 254 /** 255 * Set the value of the matrix element at column 0 and row 2 without updating the properties of the matrix. 256 * 257 * @param m02 258 * the new value 259 * @return this 260 */ 261 ref Matrix4x3d _m02(double m02) return { 262 this.m02 = m02; 263 return this; 264 } 265 /** 266 * Set the value of the matrix element at column 1 and row 0 without updating the properties of the matrix. 267 * 268 * @param m10 269 * the new value 270 * @return this 271 */ 272 ref Matrix4x3d _m10(double m10) return { 273 this.m10 = m10; 274 return this; 275 } 276 /** 277 * Set the value of the matrix element at column 1 and row 1 without updating the properties of the matrix. 278 * 279 * @param m11 280 * the new value 281 * @return this 282 */ 283 ref Matrix4x3d _m11(double m11) return { 284 this.m11 = m11; 285 return this; 286 } 287 /** 288 * Set the value of the matrix element at column 1 and row 2 without updating the properties of the matrix. 289 * 290 * @param m12 291 * the new value 292 * @return this 293 */ 294 ref Matrix4x3d _m12(double m12) return { 295 this.m12 = m12; 296 return this; 297 } 298 /** 299 * Set the value of the matrix element at column 2 and row 0 without updating the properties of the matrix. 300 * 301 * @param m20 302 * the new value 303 * @return this 304 */ 305 ref Matrix4x3d _m20(double m20) return { 306 this.m20 = m20; 307 return this; 308 } 309 /** 310 * Set the value of the matrix element at column 2 and row 1 without updating the properties of the matrix. 311 * 312 * @param m21 313 * the new value 314 * @return this 315 */ 316 ref Matrix4x3d _m21(double m21) return { 317 this.m21 = m21; 318 return this; 319 } 320 /** 321 * Set the value of the matrix element at column 2 and row 2 without updating the properties of the matrix. 322 * 323 * @param m22 324 * the new value 325 * @return this 326 */ 327 ref Matrix4x3d _m22(double m22) return { 328 this.m22 = m22; 329 return this; 330 } 331 /** 332 * Set the value of the matrix element at column 3 and row 0 without updating the properties of the matrix. 333 * 334 * @param m30 335 * the new value 336 * @return this 337 */ 338 ref Matrix4x3d _m30(double m30) return { 339 this.m30 = m30; 340 return this; 341 } 342 /** 343 * Set the value of the matrix element at column 3 and row 1 without updating the properties of the matrix. 344 * 345 * @param m31 346 * the new value 347 * @return this 348 */ 349 ref Matrix4x3d _m31(double m31) return { 350 this.m31 = m31; 351 return this; 352 } 353 /** 354 * Set the value of the matrix element at column 3 and row 2 without updating the properties of the matrix. 355 * 356 * @param m32 357 * the new value 358 * @return this 359 */ 360 ref Matrix4x3d _m32(double m32) return { 361 this.m32 = m32; 362 return this; 363 } 364 365 /** 366 * Set the value of the matrix element at column 0 and row 0. 367 * 368 * @param m00 369 * the new value 370 * @return this 371 */ 372 ref public Matrix4x3d setm00(double m00) return { 373 this.m00 = m00; 374 properties &= ~PROPERTY_ORTHONORMAL; 375 if (m00 != 1.0) 376 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 377 return this; 378 } 379 /** 380 * Set the value of the matrix element at column 0 and row 1. 381 * 382 * @param m01 383 * the new value 384 * @return this 385 */ 386 ref public Matrix4x3d setm01(double m01) return { 387 this.m01 = m01; 388 properties &= ~PROPERTY_ORTHONORMAL; 389 if (m01 != 0.0) 390 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 391 return this; 392 } 393 /** 394 * Set the value of the matrix element at column 0 and row 2. 395 * 396 * @param m02 397 * the new value 398 * @return this 399 */ 400 ref public Matrix4x3d setm02(double m02) return { 401 this.m02 = m02; 402 properties &= ~PROPERTY_ORTHONORMAL; 403 if (m02 != 0.0) 404 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 405 return this; 406 } 407 /** 408 * Set the value of the matrix element at column 1 and row 0. 409 * 410 * @param m10 411 * the new value 412 * @return this 413 */ 414 ref public Matrix4x3d setm10(double m10) return { 415 this.m10 = m10; 416 properties &= ~PROPERTY_ORTHONORMAL; 417 if (m10 != 0.0) 418 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 419 return this; 420 } 421 /** 422 * Set the value of the matrix element at column 1 and row 1. 423 * 424 * @param m11 425 * the new value 426 * @return this 427 */ 428 ref public Matrix4x3d setm11(double m11) return { 429 this.m11 = m11; 430 properties &= ~PROPERTY_ORTHONORMAL; 431 if (m11 != 1.0) 432 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 433 return this; 434 } 435 /** 436 * Set the value of the matrix element at column 1 and row 2. 437 * 438 * @param m12 439 * the new value 440 * @return this 441 */ 442 ref public Matrix4x3d setm12(double m12) return { 443 this.m12 = m12; 444 properties &= ~PROPERTY_ORTHONORMAL; 445 if (m12 != 0.0) 446 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 447 return this; 448 } 449 /** 450 * Set the value of the matrix element at column 2 and row 0. 451 * 452 * @param m20 453 * the new value 454 * @return this 455 */ 456 ref public Matrix4x3d setm20(double m20) return { 457 this.m20 = m20; 458 properties &= ~PROPERTY_ORTHONORMAL; 459 if (m20 != 0.0) 460 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 461 return this; 462 } 463 /** 464 * Set the value of the matrix element at column 2 and row 1. 465 * 466 * @param m21 467 * the new value 468 * @return this 469 */ 470 ref public Matrix4x3d setm21(double m21) return { 471 this.m21 = m21; 472 properties &= ~PROPERTY_ORTHONORMAL; 473 if (m21 != 0.0) 474 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 475 return this; 476 } 477 /** 478 * Set the value of the matrix element at column 2 and row 2. 479 * 480 * @param m22 481 * the new value 482 * @return this 483 */ 484 ref public Matrix4x3d setm22(double m22) return { 485 this.m22 = m22; 486 properties &= ~PROPERTY_ORTHONORMAL; 487 if (m22 != 1.0) 488 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 489 return this; 490 } 491 /** 492 * Set the value of the matrix element at column 3 and row 0. 493 * 494 * @param m30 495 * the new value 496 * @return this 497 */ 498 ref public Matrix4x3d setm30(double m30) return { 499 this.m30 = m30; 500 if (m30 != 0.0) 501 properties &= ~PROPERTY_IDENTITY; 502 return this; 503 } 504 /** 505 * Set the value of the matrix element at column 3 and row 1. 506 * 507 * @param m31 508 * the new value 509 * @return this 510 */ 511 ref public Matrix4x3d setm31(double m31) return { 512 this.m31 = m31; 513 if (m31 != 0.0) 514 properties &= ~PROPERTY_IDENTITY; 515 return this; 516 } 517 /** 518 * Set the value of the matrix element at column 3 and row 2. 519 * 520 * @param m32 521 * the new value 522 * @return this 523 */ 524 ref public Matrix4x3d setm32(double m32) return { 525 this.m32 = m32; 526 if (m32 != 0.0) 527 properties &= ~PROPERTY_IDENTITY; 528 return this; 529 } 530 531 /** 532 * Reset this matrix to the identity. 533 * <p> 534 * Please note that if a call to {@link #identity()} is immediately followed by a call to: 535 * {@link #translate(double, double, double) translate}, 536 * {@link #rotate(double, double, double, double) rotate}, 537 * {@link #scale(double, double, double) scale}, 538 * {@link #ortho(double, double, double, double, double, double) ortho}, 539 * {@link #ortho2D(double, double, double, double) ortho2D}, 540 * {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt}, 541 * {@link #lookAlong(double, double, double, double, double, double) lookAlong}, 542 * or any of their overloads, then the call to {@link #identity()} can be omitted and the subsequent call replaced with: 543 * {@link #translation(double, double, double) translation}, 544 * {@link #rotation(double, double, double, double) rotation}, 545 * {@link #scaling(double, double, double) scaling}, 546 * {@link #setOrtho(double, double, double, double, double, double) setOrtho}, 547 * {@link #setOrtho2D(double, double, double, double) setOrtho2D}, 548 * {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt}, 549 * {@link #setLookAlong(double, double, double, double, double, double) setLookAlong}, 550 * or any of their overloads. 551 * 552 * @return this 553 */ 554 ref public Matrix4x3d identity() return { 555 if ((properties & PROPERTY_IDENTITY) != 0) 556 return this; 557 m00 = 1.0; 558 m01 = 0.0; 559 m02 = 0.0; 560 m10 = 0.0; 561 m11 = 1.0; 562 m12 = 0.0; 563 m20 = 0.0; 564 m21 = 0.0; 565 m22 = 1.0; 566 m30 = 0.0; 567 m31 = 0.0; 568 m32 = 0.0; 569 properties = PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 570 return this; 571 } 572 573 /** 574 * Store the values of the given matrix <code>m</code> into <code>this</code> matrix. 575 * 576 * @param m 577 * the matrix to copy the values from 578 * @return this 579 */ 580 ref public Matrix4x3d set(Matrix4x3d m) return { 581 m00 = m.m00; 582 m01 = m.m01; 583 m02 = m.m02; 584 m10 = m.m10; 585 m11 = m.m11; 586 m12 = m.m12; 587 m20 = m.m20; 588 m21 = m.m21; 589 m22 = m.m22; 590 m30 = m.m30; 591 m31 = m.m31; 592 m32 = m.m32; 593 properties = m.properties; 594 return this; 595 } 596 597 598 /** 599 * Store the values of the upper 4x3 submatrix of <code>m</code> into <code>this</code> matrix. 600 * 601 * @see Matrix4d#get4x3(Matrix4x3d) 602 * 603 * @param m 604 * the matrix to copy the values from 605 * @return this 606 */ 607 ref public Matrix4x3d set(Matrix4d m) return { 608 m00 = m.m00; 609 m01 = m.m01; 610 m02 = m.m02; 611 m10 = m.m10; 612 m11 = m.m11; 613 m12 = m.m12; 614 m20 = m.m20; 615 m21 = m.m21; 616 m22 = m.m22; 617 m30 = m.m30; 618 m31 = m.m31; 619 m32 = m.m32; 620 properties = m.properties & (PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 621 return this; 622 } 623 624 public Matrix4d get(ref Matrix4d dest) { 625 return dest.set4x3(this); 626 } 627 628 /** 629 * Set the left 3x3 submatrix of this {@link Matrix4x3d} to the given {@link Matrix3d} 630 * and the rest to identity. 631 * 632 * @see #Matrix4x3d(Matrix3d) 633 * 634 * @param mat 635 * the {@link Matrix3d} 636 * @return this 637 */ 638 ref public Matrix4x3d set(Matrix3d mat) return { 639 m00 = mat.m00; 640 m01 = mat.m01; 641 m02 = mat.m02; 642 m10 = mat.m10; 643 m11 = mat.m11; 644 m12 = mat.m12; 645 m20 = mat.m20; 646 m21 = mat.m21; 647 m22 = mat.m22; 648 m30 = 0.0; 649 m31 = 0.0; 650 m32 = 0.0; 651 return determineProperties(); 652 } 653 654 655 /** 656 * Set the four columns of this matrix to the supplied vectors, respectively. 657 * 658 * @param col0 659 * the first column 660 * @param col1 661 * the second column 662 * @param col2 663 * the third column 664 * @param col3 665 * the fourth column 666 * @return this 667 */ 668 ref public Matrix4x3d set(Vector3d col0, 669 Vector3d col1, 670 Vector3d col2, 671 Vector3d col3) return { 672 this.m00 = col0.x; 673 this.m01 = col0.y; 674 this.m02 = col0.z; 675 this.m10 = col1.x; 676 this.m11 = col1.y; 677 this.m12 = col1.z; 678 this.m20 = col2.x; 679 this.m21 = col2.y; 680 this.m22 = col2.z; 681 this.m30 = col3.x; 682 this.m31 = col3.y; 683 this.m32 = col3.z; 684 return determineProperties(); 685 } 686 687 /** 688 * Set the left 3x3 submatrix of this {@link Matrix4x3d} to that of the given {@link Matrix4x3d} 689 * and don't change the other elements. 690 * 691 * @param mat 692 * the {@link Matrix4x3d} 693 * @return this 694 */ 695 ref public Matrix4x3d set3x3(Matrix4x3d mat) return { 696 m00 = mat.m00; 697 m01 = mat.m01; 698 m02 = mat.m02; 699 m10 = mat.m10; 700 m11 = mat.m11; 701 m12 = mat.m12; 702 m20 = mat.m20; 703 m21 = mat.m21; 704 m22 = mat.m22; 705 properties &= mat.properties; 706 return this; 707 } 708 709 /** 710 * Set this matrix to be equivalent to the rotation specified by the given {@link AxisAngle4d}. 711 * 712 * @param axisAngle 713 * the {@link AxisAngle4d} 714 * @return this 715 */ 716 ref public Matrix4x3d set(AxisAngle4d axisAngle) return { 717 double x = axisAngle.x; 718 double y = axisAngle.y; 719 double z = axisAngle.z; 720 double angle = axisAngle.angle; 721 double invLength = Math.invsqrt(x*x + y*y + z*z); 722 x *= invLength; 723 y *= invLength; 724 z *= invLength; 725 double s = Math.sin(angle); 726 double c = Math.cosFromSin(s, angle); 727 double omc = 1.0 - c; 728 m00 = c + x*x*omc; 729 m11 = c + y*y*omc; 730 m22 = c + z*z*omc; 731 double tmp1 = x*y*omc; 732 double tmp2 = z*s; 733 m10 = tmp1 - tmp2; 734 m01 = tmp1 + tmp2; 735 tmp1 = x*z*omc; 736 tmp2 = y*s; 737 m20 = tmp1 + tmp2; 738 m02 = tmp1 - tmp2; 739 tmp1 = y*z*omc; 740 tmp2 = x*s; 741 m21 = tmp1 - tmp2; 742 m12 = tmp1 + tmp2; 743 m30 = 0.0; 744 m31 = 0.0; 745 m32 = 0.0; 746 properties = PROPERTY_ORTHONORMAL; 747 return this; 748 } 749 750 751 /** 752 * Set this matrix to be equivalent to the rotation - and possibly scaling - specified by the given {@link Quaterniond}. 753 * <p> 754 * This method is equivalent to calling: <code>rotation(q)</code> 755 * 756 * @param q 757 * the {@link Quaterniond} 758 * @return this 759 */ 760 ref public Matrix4x3d set(Quaterniond q) return { 761 return rotation(q); 762 } 763 764 /** 765 * Multiply this matrix by the supplied <code>right</code> matrix. 766 * <p> 767 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix, 768 * then the new matrix will be <code>M * R</code>. So when transforming a 769 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 770 * transformation of the right matrix will be applied first! 771 * 772 * @param right 773 * the right operand of the multiplication 774 * @return this 775 */ 776 ref public Matrix4x3d mul(Matrix4x3d right) return { 777 mul(right, this); 778 return this; 779 } 780 781 public Matrix4x3d mul(Matrix4x3d right, ref Matrix4x3d dest) { 782 if ((properties & PROPERTY_IDENTITY) != 0) 783 return dest.set(right); 784 else if ((right.properties & PROPERTY_IDENTITY) != 0) 785 return dest.set(this); 786 else if ((properties & PROPERTY_TRANSLATION) != 0) 787 return mulTranslation(right, dest); 788 return mulGeneric(right, dest); 789 } 790 private Matrix4x3d mulGeneric(Matrix4x3d right, ref Matrix4x3d dest) { 791 double __m00 = this.m00, __m01 = this.m01, __m02 = this.m02; 792 double __m10 = this.m10, __m11 = this.m11, __m12 = this.m12; 793 double __m20 = this.m20, __m21 = this.m21, __m22 = this.m22; 794 double rm00 = right.m00, rm01 = right.m01, rm02 = right.m02; 795 double rm10 = right.m10, rm11 = right.m11, rm12 = right.m12; 796 double rm20 = right.m20, rm21 = right.m21, rm22 = right.m22; 797 double rm30 = right.m30, rm31 = right.m31, rm32 = right.m32; 798 return dest 799 ._m00(Math.fma(__m00, rm00, Math.fma(__m10, rm01, __m20 * rm02))) 800 ._m01(Math.fma(__m01, rm00, Math.fma(__m11, rm01, __m21 * rm02))) 801 ._m02(Math.fma(__m02, rm00, Math.fma(__m12, rm01, __m22 * rm02))) 802 ._m10(Math.fma(__m00, rm10, Math.fma(__m10, rm11, __m20 * rm12))) 803 ._m11(Math.fma(__m01, rm10, Math.fma(__m11, rm11, __m21 * rm12))) 804 ._m12(Math.fma(__m02, rm10, Math.fma(__m12, rm11, __m22 * rm12))) 805 ._m20(Math.fma(__m00, rm20, Math.fma(__m10, rm21, __m20 * rm22))) 806 ._m21(Math.fma(__m01, rm20, Math.fma(__m11, rm21, __m21 * rm22))) 807 ._m22(Math.fma(__m02, rm20, Math.fma(__m12, rm21, __m22 * rm22))) 808 ._m30(Math.fma(__m00, rm30, Math.fma(__m10, rm31, Math.fma(__m20, rm32, m30)))) 809 ._m31(Math.fma(__m01, rm30, Math.fma(__m11, rm31, Math.fma(__m21, rm32, m31)))) 810 ._m32(Math.fma(__m02, rm30, Math.fma(__m12, rm31, Math.fma(__m22, rm32, m32)))) 811 ._properties(properties & right.properties & PROPERTY_ORTHONORMAL); 812 } 813 814 815 public Matrix4x3d mulTranslation(Matrix4x3d right, ref Matrix4x3d dest) { 816 return dest 817 ._m00(right.m00) 818 ._m01(right.m01) 819 ._m02(right.m02) 820 ._m10(right.m10) 821 ._m11(right.m11) 822 ._m12(right.m12) 823 ._m20(right.m20) 824 ._m21(right.m21) 825 ._m22(right.m22) 826 ._m30(right.m30 + m30) 827 ._m31(right.m31 + m31) 828 ._m32(right.m32 + m32) 829 ._properties(right.properties & PROPERTY_ORTHONORMAL); 830 } 831 832 /** 833 * Multiply <code>this</code> orthographic projection matrix by the supplied <code>view</code> matrix. 834 * <p> 835 * If <code>M</code> is <code>this</code> matrix and <code>V</code> the <code>view</code> matrix, 836 * then the new matrix will be <code>M * V</code>. So when transforming a 837 * vector <code>v</code> with the new matrix by using <code>M * V * v</code>, the 838 * transformation of the <code>view</code> matrix will be applied first! 839 * 840 * @param view 841 * the matrix which to multiply <code>this</code> with 842 * @return this 843 */ 844 ref public Matrix4x3d mulOrtho(Matrix4x3d view) return { 845 mulOrtho(view, this); 846 return this; 847 } 848 849 public Matrix4x3d mulOrtho(Matrix4x3d view, ref Matrix4x3d dest) { 850 double nm00 = m00 * view.m00; 851 double nm01 = m11 * view.m01; 852 double nm02 = m22 * view.m02; 853 double nm10 = m00 * view.m10; 854 double nm11 = m11 * view.m11; 855 double nm12 = m22 * view.m12; 856 double nm20 = m00 * view.m20; 857 double nm21 = m11 * view.m21; 858 double nm22 = m22 * view.m22; 859 double nm30 = m00 * view.m30 + m30; 860 double nm31 = m11 * view.m31 + m31; 861 double nm32 = m22 * view.m32 + m32; 862 dest.m00 = nm00; 863 dest.m01 = nm01; 864 dest.m02 = nm02; 865 dest.m10 = nm10; 866 dest.m11 = nm11; 867 dest.m12 = nm12; 868 dest.m20 = nm20; 869 dest.m21 = nm21; 870 dest.m22 = nm22; 871 dest.m30 = nm30; 872 dest.m31 = nm31; 873 dest.m32 = nm32; 874 dest.properties = (this.properties & view.properties & PROPERTY_ORTHONORMAL); 875 return dest; 876 } 877 878 /** 879 * Multiply <code>this</code> by the 4x3 matrix with the column vectors <code>(rm00, rm01, rm02)</code>, 880 * <code>(rm10, rm11, rm12)</code>, <code>(rm20, rm21, rm22)</code> and <code>(0, 0, 0)</code>. 881 * <p> 882 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the specified matrix, 883 * then the new matrix will be <code>M * R</code>. So when transforming a 884 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 885 * transformation of the <code>R</code> matrix will be applied first! 886 * 887 * @param rm00 888 * the value of the m00 element 889 * @param rm01 890 * the value of the m01 element 891 * @param rm02 892 * the value of the m02 element 893 * @param rm10 894 * the value of the m10 element 895 * @param rm11 896 * the value of the m11 element 897 * @param rm12 898 * the value of the m12 element 899 * @param rm20 900 * the value of the m20 element 901 * @param rm21 902 * the value of the m21 element 903 * @param rm22 904 * the value of the m22 element 905 * @return this 906 */ 907 ref public Matrix4x3d mul3x3( 908 double rm00, double rm01, double rm02, 909 double rm10, double rm11, double rm12, 910 double rm20, double rm21, double rm22) return { 911 mul3x3(rm00, rm01, rm02, rm10, rm11, rm12, rm20, rm21, rm22, this); 912 return this; 913 } 914 public Matrix4x3d mul3x3( 915 double rm00, double rm01, double rm02, 916 double rm10, double rm11, double rm12, 917 double rm20, double rm21, double rm22, 918 ref Matrix4x3d dest) { 919 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 920 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 921 double m20 = this.m20, m21 = this.m21, m22 = this.m22; 922 return dest 923 ._m00(Math.fma(m00, rm00, Math.fma(m10, rm01, m20 * rm02))) 924 ._m01(Math.fma(m01, rm00, Math.fma(m11, rm01, m21 * rm02))) 925 ._m02(Math.fma(m02, rm00, Math.fma(m12, rm01, m22 * rm02))) 926 ._m10(Math.fma(m00, rm10, Math.fma(m10, rm11, m20 * rm12))) 927 ._m11(Math.fma(m01, rm10, Math.fma(m11, rm11, m21 * rm12))) 928 ._m12(Math.fma(m02, rm10, Math.fma(m12, rm11, m22 * rm12))) 929 ._m20(Math.fma(m00, rm20, Math.fma(m10, rm21, m20 * rm22))) 930 ._m21(Math.fma(m01, rm20, Math.fma(m11, rm21, m21 * rm22))) 931 ._m22(Math.fma(m02, rm20, Math.fma(m12, rm21, m22 * rm22))) 932 ._m30(m30) 933 ._m31(m31) 934 ._m32(m32) 935 ._properties(0); 936 } 937 938 /** 939 * Component-wise add <code>this</code> and <code>other</code> 940 * by first multiplying each component of <code>other</code> by <code>otherFactor</code> and 941 * adding that result to <code>this</code>. 942 * <p> 943 * The matrix <code>other</code> will not be changed. 944 * 945 * @param other 946 * the other matrix 947 * @param otherFactor 948 * the factor to multiply each of the other matrix's components 949 * @return this 950 */ 951 ref public Matrix4x3d fma(Matrix4x3d other, double otherFactor) return { 952 fma(other, otherFactor, this); 953 return this; 954 } 955 956 public Matrix4x3d fma(Matrix4x3d other, double otherFactor, ref Matrix4x3d dest) { 957 dest 958 ._m00(Math.fma(other.m00, otherFactor, m00)) 959 ._m01(Math.fma(other.m01, otherFactor, m01)) 960 ._m02(Math.fma(other.m02, otherFactor, m02)) 961 ._m10(Math.fma(other.m10, otherFactor, m10)) 962 ._m11(Math.fma(other.m11, otherFactor, m11)) 963 ._m12(Math.fma(other.m12, otherFactor, m12)) 964 ._m20(Math.fma(other.m20, otherFactor, m20)) 965 ._m21(Math.fma(other.m21, otherFactor, m21)) 966 ._m22(Math.fma(other.m22, otherFactor, m22)) 967 ._m30(Math.fma(other.m30, otherFactor, m30)) 968 ._m31(Math.fma(other.m31, otherFactor, m31)) 969 ._m32(Math.fma(other.m32, otherFactor, m32)) 970 ._properties(0); 971 return dest; 972 } 973 974 /** 975 * Component-wise add <code>this</code> and <code>other</code>. 976 * 977 * @param other 978 * the other addend 979 * @return this 980 */ 981 ref public Matrix4x3d add(Matrix4x3d other) return { 982 add(other, this); 983 return this; 984 } 985 986 public Matrix4x3d add(Matrix4x3d other, ref Matrix4x3d dest) { 987 dest.m00 = m00 + other.m00; 988 dest.m01 = m01 + other.m01; 989 dest.m02 = m02 + other.m02; 990 dest.m10 = m10 + other.m10; 991 dest.m11 = m11 + other.m11; 992 dest.m12 = m12 + other.m12; 993 dest.m20 = m20 + other.m20; 994 dest.m21 = m21 + other.m21; 995 dest.m22 = m22 + other.m22; 996 dest.m30 = m30 + other.m30; 997 dest.m31 = m31 + other.m31; 998 dest.m32 = m32 + other.m32; 999 dest.properties = 0; 1000 return dest; 1001 } 1002 1003 1004 /** 1005 * Component-wise subtract <code>subtrahend</code> from <code>this</code>. 1006 * 1007 * @param subtrahend 1008 * the subtrahend 1009 * @return this 1010 */ 1011 ref public Matrix4x3d sub(Matrix4x3d subtrahend) return { 1012 sub(subtrahend, this); 1013 return this; 1014 } 1015 1016 public Matrix4x3d sub(Matrix4x3d subtrahend, ref Matrix4x3d dest) { 1017 dest.m00 = m00 - subtrahend.m00; 1018 dest.m01 = m01 - subtrahend.m01; 1019 dest.m02 = m02 - subtrahend.m02; 1020 dest.m10 = m10 - subtrahend.m10; 1021 dest.m11 = m11 - subtrahend.m11; 1022 dest.m12 = m12 - subtrahend.m12; 1023 dest.m20 = m20 - subtrahend.m20; 1024 dest.m21 = m21 - subtrahend.m21; 1025 dest.m22 = m22 - subtrahend.m22; 1026 dest.m30 = m30 - subtrahend.m30; 1027 dest.m31 = m31 - subtrahend.m31; 1028 dest.m32 = m32 - subtrahend.m32; 1029 dest.properties = 0; 1030 return dest; 1031 } 1032 1033 /** 1034 * Component-wise multiply <code>this</code> by <code>other</code>. 1035 * 1036 * @param other 1037 * the other matrix 1038 * @return this 1039 */ 1040 ref public Matrix4x3d mulComponentWise(Matrix4x3d other) return { 1041 mulComponentWise(other, this); 1042 return this; 1043 } 1044 1045 public Matrix4x3d mulComponentWise(Matrix4x3d other, ref Matrix4x3d dest) { 1046 dest.m00 = m00 * other.m00; 1047 dest.m01 = m01 * other.m01; 1048 dest.m02 = m02 * other.m02; 1049 dest.m10 = m10 * other.m10; 1050 dest.m11 = m11 * other.m11; 1051 dest.m12 = m12 * other.m12; 1052 dest.m20 = m20 * other.m20; 1053 dest.m21 = m21 * other.m21; 1054 dest.m22 = m22 * other.m22; 1055 dest.m30 = m30 * other.m30; 1056 dest.m31 = m31 * other.m31; 1057 dest.m32 = m32 * other.m32; 1058 dest.properties = 0; 1059 return dest; 1060 } 1061 1062 /** 1063 * Set the values within this matrix to the supplied double values. The matrix will look like this:<br><br> 1064 * 1065 * m00, m10, m20, m30<br> 1066 * m01, m11, m21, m31<br> 1067 * m02, m12, m22, m32<br> 1068 * 1069 * @param m00 1070 * the new value of m00 1071 * @param m01 1072 * the new value of m01 1073 * @param m02 1074 * the new value of m02 1075 * @param m10 1076 * the new value of m10 1077 * @param m11 1078 * the new value of m11 1079 * @param m12 1080 * the new value of m12 1081 * @param m20 1082 * the new value of m20 1083 * @param m21 1084 * the new value of m21 1085 * @param m22 1086 * the new value of m22 1087 * @param m30 1088 * the new value of m30 1089 * @param m31 1090 * the new value of m31 1091 * @param m32 1092 * the new value of m32 1093 * @return this 1094 */ 1095 ref public Matrix4x3d set(double m00, double m01, double m02, 1096 double m10, double m11, double m12, 1097 double m20, double m21, double m22, 1098 double m30, double m31, double m32) return { 1099 this.m00 = m00; 1100 this.m10 = m10; 1101 this.m20 = m20; 1102 this.m30 = m30; 1103 this.m01 = m01; 1104 this.m11 = m11; 1105 this.m21 = m21; 1106 this.m31 = m31; 1107 this.m02 = m02; 1108 this.m12 = m12; 1109 this.m22 = m22; 1110 this.m32 = m32; 1111 return determineProperties(); 1112 } 1113 1114 /** 1115 * Set the values in the matrix using a double array that contains the matrix elements in column-major order. 1116 * <p> 1117 * The results will look like this:<br><br> 1118 * 1119 * 0, 3, 6, 9<br> 1120 * 1, 4, 7, 10<br> 1121 * 2, 5, 8, 11<br> 1122 * 1123 * @see #set(double[]) 1124 * 1125 * @param m 1126 * the array to read the matrix values from 1127 * @param off 1128 * the offset into the array 1129 * @return this 1130 */ 1131 ref public Matrix4x3d set(double[] m, int off) return { 1132 m00 = m[off+0]; 1133 m01 = m[off+1]; 1134 m02 = m[off+2]; 1135 m10 = m[off+3]; 1136 m11 = m[off+4]; 1137 m12 = m[off+5]; 1138 m20 = m[off+6]; 1139 m21 = m[off+7]; 1140 m22 = m[off+8]; 1141 m30 = m[off+9]; 1142 m31 = m[off+10]; 1143 m32 = m[off+11]; 1144 return determineProperties(); 1145 } 1146 1147 /** 1148 * Set the values in the matrix using a double array that contains the matrix elements in column-major order. 1149 * <p> 1150 * The results will look like this:<br><br> 1151 * 1152 * 0, 3, 6, 9<br> 1153 * 1, 4, 7, 10<br> 1154 * 2, 5, 8, 11<br> 1155 * 1156 * @see #set(double[], int) 1157 * 1158 * @param m 1159 * the array to read the matrix values from 1160 * @return this 1161 */ 1162 ref public Matrix4x3d set(double[] m) return { 1163 return set(m, 0); 1164 } 1165 1166 /** 1167 * Set the values in the matrix using a float array that contains the matrix elements in column-major order. 1168 * <p> 1169 * The results will look like this:<br><br> 1170 * 1171 * 0, 3, 6, 9<br> 1172 * 1, 4, 7, 10<br> 1173 * 2, 5, 8, 11<br> 1174 * 1175 * @see #set(float[]) 1176 * 1177 * @param m 1178 * the array to read the matrix values from 1179 * @param off 1180 * the offset into the array 1181 * @return this 1182 */ 1183 ref public Matrix4x3d set(float[] m, int off) return { 1184 m00 = m[off+0]; 1185 m01 = m[off+1]; 1186 m02 = m[off+2]; 1187 m10 = m[off+3]; 1188 m11 = m[off+4]; 1189 m12 = m[off+5]; 1190 m20 = m[off+6]; 1191 m21 = m[off+7]; 1192 m22 = m[off+8]; 1193 m30 = m[off+9]; 1194 m31 = m[off+10]; 1195 m32 = m[off+11]; 1196 return determineProperties(); 1197 } 1198 1199 /** 1200 * Set the values in the matrix using a float array that contains the matrix elements in column-major order. 1201 * <p> 1202 * The results will look like this:<br><br> 1203 * 1204 * 0, 3, 6, 9<br> 1205 * 1, 4, 7, 10<br> 1206 * 2, 5, 8, 11<br> 1207 * 1208 * @see #set(float[], int) 1209 * 1210 * @param m 1211 * the array to read the matrix values from 1212 * @return this 1213 */ 1214 ref public Matrix4x3d set(float[] m) return { 1215 return set(m, 0); 1216 } 1217 1218 1219 1220 public double determinant() { 1221 return (m00 * m11 - m01 * m10) * m22 1222 + (m02 * m10 - m00 * m12) * m21 1223 + (m01 * m12 - m02 * m11) * m20; 1224 } 1225 1226 /** 1227 * Invert this matrix. 1228 * 1229 * @return this 1230 */ 1231 ref public Matrix4x3d invert() return { 1232 invert(this); 1233 return this; 1234 } 1235 1236 public Matrix4x3d invert(ref Matrix4x3d dest) { 1237 if ((properties & PROPERTY_IDENTITY) != 0) 1238 return dest.identity(); 1239 else if ((properties & PROPERTY_ORTHONORMAL) != 0) 1240 return invertOrthonormal(dest); 1241 return invertGeneric(dest); 1242 } 1243 private Matrix4x3d invertGeneric(ref Matrix4x3d dest) { 1244 double m11m00 = m00 * m11, m10m01 = m01 * m10, m10m02 = m02 * m10; 1245 double m12m00 = m00 * m12, m12m01 = m01 * m12, m11m02 = m02 * m11; 1246 double s = 1.0 / ((m11m00 - m10m01) * m22 + (m10m02 - m12m00) * m21 + (m12m01 - m11m02) * m20); 1247 double m10m22 = m10 * m22, m10m21 = m10 * m21, m11m22 = m11 * m22; 1248 double m11m20 = m11 * m20, m12m21 = m12 * m21, m12m20 = m12 * m20; 1249 double m20m02 = m20 * m02, m20m01 = m20 * m01, m21m02 = m21 * m02; 1250 double m21m00 = m21 * m00, m22m01 = m22 * m01, m22m00 = m22 * m00; 1251 double nm00 = (m11m22 - m12m21) * s; 1252 double nm01 = (m21m02 - m22m01) * s; 1253 double nm02 = (m12m01 - m11m02) * s; 1254 double nm10 = (m12m20 - m10m22) * s; 1255 double nm11 = (m22m00 - m20m02) * s; 1256 double nm12 = (m10m02 - m12m00) * s; 1257 double nm20 = (m10m21 - m11m20) * s; 1258 double nm21 = (m20m01 - m21m00) * s; 1259 double nm22 = (m11m00 - m10m01) * s; 1260 double nm30 = (m10m22 * m31 - m10m21 * m32 + m11m20 * m32 - m11m22 * m30 + m12m21 * m30 - m12m20 * m31) * s; 1261 double nm31 = (m20m02 * m31 - m20m01 * m32 + m21m00 * m32 - m21m02 * m30 + m22m01 * m30 - m22m00 * m31) * s; 1262 double nm32 = (m11m02 * m30 - m12m01 * m30 + m12m00 * m31 - m10m02 * m31 + m10m01 * m32 - m11m00 * m32) * s; 1263 dest.m00 = nm00; 1264 dest.m01 = nm01; 1265 dest.m02 = nm02; 1266 dest.m10 = nm10; 1267 dest.m11 = nm11; 1268 dest.m12 = nm12; 1269 dest.m20 = nm20; 1270 dest.m21 = nm21; 1271 dest.m22 = nm22; 1272 dest.m30 = nm30; 1273 dest.m31 = nm31; 1274 dest.m32 = nm32; 1275 dest.properties = 0; 1276 return dest; 1277 } 1278 private Matrix4x3d invertOrthonormal(ref Matrix4x3d dest) { 1279 double nm30 = -(m00 * m30 + m01 * m31 + m02 * m32); 1280 double nm31 = -(m10 * m30 + m11 * m31 + m12 * m32); 1281 double nm32 = -(m20 * m30 + m21 * m31 + m22 * m32); 1282 double m01 = this.m01; 1283 double m02 = this.m02; 1284 double m12 = this.m12; 1285 dest.m00 = m00; 1286 dest.m01 = m10; 1287 dest.m02 = m20; 1288 dest.m10 = m01; 1289 dest.m11 = m11; 1290 dest.m12 = m21; 1291 dest.m20 = m02; 1292 dest.m21 = m12; 1293 dest.m22 = m22; 1294 dest.m30 = nm30; 1295 dest.m31 = nm31; 1296 dest.m32 = nm32; 1297 dest.properties = PROPERTY_ORTHONORMAL; 1298 return dest; 1299 } 1300 1301 public Matrix4x3d invertOrtho(ref Matrix4x3d dest) { 1302 double invM00 = 1.0 / m00; 1303 double invM11 = 1.0 / m11; 1304 double invM22 = 1.0 / m22; 1305 dest.set(invM00, 0, 0, 1306 0, invM11, 0, 1307 0, 0, invM22, 1308 -m30 * invM00, -m31 * invM11, -m32 * invM22); 1309 dest.properties = 0; 1310 return dest; 1311 } 1312 1313 /** 1314 * Invert <code>this</code> orthographic projection matrix. 1315 * <p> 1316 * This method can be used to quickly obtain the inverse of an orthographic projection matrix. 1317 * 1318 * @return this 1319 */ 1320 ref public Matrix4x3d invertOrtho() return { 1321 invertOrtho(this); 1322 return this; 1323 } 1324 1325 /** 1326 * Transpose only the left 3x3 submatrix of this matrix and set the rest of the matrix elements to identity. 1327 * 1328 * @return this 1329 */ 1330 ref public Matrix4x3d transpose3x3() return { 1331 transpose3x3(this); 1332 return this; 1333 } 1334 1335 public Matrix4x3d transpose3x3(ref Matrix4x3d dest) { 1336 double nm00 = m00; 1337 double nm01 = m10; 1338 double nm02 = m20; 1339 double nm10 = m01; 1340 double nm11 = m11; 1341 double nm12 = m21; 1342 double nm20 = m02; 1343 double nm21 = m12; 1344 double nm22 = m22; 1345 dest.m00 = nm00; 1346 dest.m01 = nm01; 1347 dest.m02 = nm02; 1348 dest.m10 = nm10; 1349 dest.m11 = nm11; 1350 dest.m12 = nm12; 1351 dest.m20 = nm20; 1352 dest.m21 = nm21; 1353 dest.m22 = nm22; 1354 dest.properties = properties; 1355 return dest; 1356 } 1357 1358 public Matrix3d transpose3x3(Matrix3d dest) { 1359 dest.m00 = (m00); 1360 dest.m01 = (m10); 1361 dest.m02 = (m20); 1362 dest.m10 = (m01); 1363 dest.m11 = (m11); 1364 dest.m12 = (m21); 1365 dest.m20 = (m02); 1366 dest.m21 = (m12); 1367 dest.m22 = (m22); 1368 return dest; 1369 } 1370 1371 /** 1372 * Set this matrix to be a simple translation matrix. 1373 * <p> 1374 * The resulting matrix can be multiplied against another transformation 1375 * matrix to obtain an additional translation. 1376 * 1377 * @param x 1378 * the offset to translate in x 1379 * @param y 1380 * the offset to translate in y 1381 * @param z 1382 * the offset to translate in z 1383 * @return this 1384 */ 1385 ref public Matrix4x3d translation(double x, double y, double z) return { 1386 if ((properties & PROPERTY_IDENTITY) == 0) 1387 this.identity(); 1388 m30 = x; 1389 m31 = y; 1390 m32 = z; 1391 properties = PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL; 1392 return this; 1393 } 1394 1395 1396 /** 1397 * Set this matrix to be a simple translation matrix. 1398 * <p> 1399 * The resulting matrix can be multiplied against another transformation 1400 * matrix to obtain an additional translation. 1401 * 1402 * @param offset 1403 * the offsets in x, y and z to translate 1404 * @return this 1405 */ 1406 ref public Matrix4x3d translation(Vector3d offset) return { 1407 return translation(offset.x, offset.y, offset.z); 1408 } 1409 1410 /** 1411 * Set only the translation components <code>(m30, m31, m32)</code> of this matrix to the given values <code>(x, y, z)</code>. 1412 * <p> 1413 * To build a translation matrix instead, use {@link #translation(double, double, double)}. 1414 * To apply a translation, use {@link #translate(double, double, double)}. 1415 * 1416 * @see #translation(double, double, double) 1417 * @see #translate(double, double, double) 1418 * 1419 * @param x 1420 * the units to translate in x 1421 * @param y 1422 * the units to translate in y 1423 * @param z 1424 * the units to translate in z 1425 * @return this 1426 */ 1427 ref public Matrix4x3d setTranslation(double x, double y, double z) return { 1428 m30 = x; 1429 m31 = y; 1430 m32 = z; 1431 properties &= ~(PROPERTY_IDENTITY); 1432 return this; 1433 } 1434 1435 /** 1436 * Set only the translation components <code>(m30, m31, m32)</code> of this matrix to the given values <code>(xyz.x, xyz.y, xyz.z)</code>. 1437 * <p> 1438 * To build a translation matrix instead, use {@link #translation(Vector3d)}. 1439 * To apply a translation, use {@link #translate(Vector3d)}. 1440 * 1441 * @see #translation(Vector3d) 1442 * @see #translate(Vector3d) 1443 * 1444 * @param xyz 1445 * the units to translate in <code>(x, y, z)</code> 1446 * @return this 1447 */ 1448 ref public Matrix4x3d setTranslation(Vector3d xyz) return { 1449 return setTranslation(xyz.x, xyz.y, xyz.z); 1450 } 1451 1452 public Vector3d getTranslation(ref Vector3d dest) { 1453 dest.x = m30; 1454 dest.y = m31; 1455 dest.z = m32; 1456 return dest; 1457 } 1458 1459 public Vector3d getScale(ref Vector3d dest) { 1460 dest.x = Math.sqrt(m00 * m00 + m01 * m01 + m02 * m02); 1461 dest.y = Math.sqrt(m10 * m10 + m11 * m11 + m12 * m12); 1462 dest.z = Math.sqrt(m20 * m20 + m21 * m21 + m22 * m22); 1463 return dest; 1464 } 1465 1466 /** 1467 * Get the current values of <code>this</code> matrix and store them into 1468 * <code>dest</code>. 1469 * <p> 1470 * This is the reverse method of {@link #set(Matrix4x3d)} and allows to obtain 1471 * intermediate calculation results when chaining multiple transformations. 1472 * 1473 * @see #set(Matrix4x3d) 1474 * 1475 * @param dest 1476 * the destination matrix 1477 * @return the passed in destination 1478 */ 1479 public Matrix4x3d get(ref Matrix4x3d dest) { 1480 return dest.set(this); 1481 } 1482 1483 public Quaterniond getUnnormalizedRotation(Quaterniond dest) { 1484 return dest.setFromUnnormalized(this); 1485 } 1486 1487 public Quaterniond getNormalizedRotation(Quaterniond dest) { 1488 return dest.setFromNormalized(this); 1489 } 1490 1491 public double[] get(double[] arr, int offset) { 1492 arr[offset+0] = m00; 1493 arr[offset+1] = m01; 1494 arr[offset+2] = m02; 1495 arr[offset+3] = m10; 1496 arr[offset+4] = m11; 1497 arr[offset+5] = m12; 1498 arr[offset+6] = m20; 1499 arr[offset+7] = m21; 1500 arr[offset+8] = m22; 1501 arr[offset+9] = m30; 1502 arr[offset+10] = m31; 1503 arr[offset+11] = m32; 1504 return arr; 1505 } 1506 1507 public double[] get(double[] arr) { 1508 return get(arr, 0); 1509 } 1510 1511 public float[] get(float[] arr, int offset) { 1512 arr[offset+0] = cast(float)m00; 1513 arr[offset+1] = cast(float)m01; 1514 arr[offset+2] = cast(float)m02; 1515 arr[offset+3] = cast(float)m10; 1516 arr[offset+4] = cast(float)m11; 1517 arr[offset+5] = cast(float)m12; 1518 arr[offset+6] = cast(float)m20; 1519 arr[offset+7] = cast(float)m21; 1520 arr[offset+8] = cast(float)m22; 1521 arr[offset+9] = cast(float)m30; 1522 arr[offset+10] = cast(float)m31; 1523 arr[offset+11] = cast(float)m32; 1524 return arr; 1525 } 1526 1527 public float[] get(float[] arr) { 1528 return get(arr, 0); 1529 } 1530 1531 1532 public double[] get4x4(double[] arr, int offset) { 1533 MemUtil.copy4x4(this, arr, offset); 1534 return arr; 1535 } 1536 1537 public double[] get4x4(double[] arr) { 1538 return get4x4(arr, 0); 1539 } 1540 1541 1542 public double[] getTransposed(double[] arr, int offset) { 1543 arr[offset+0] = m00; 1544 arr[offset+1] = m10; 1545 arr[offset+2] = m20; 1546 arr[offset+3] = m30; 1547 arr[offset+4] = m01; 1548 arr[offset+5] = m11; 1549 arr[offset+6] = m21; 1550 arr[offset+7] = m31; 1551 arr[offset+8] = m02; 1552 arr[offset+9] = m12; 1553 arr[offset+10] = m22; 1554 arr[offset+11] = m32; 1555 return arr; 1556 } 1557 1558 public double[] getTransposed(double[] arr) { 1559 return getTransposed(arr, 0); 1560 } 1561 1562 /** 1563 * Set all the values within this matrix to 0. 1564 * 1565 * @return this 1566 */ 1567 ref public Matrix4x3d zero() return { 1568 m00 = 0.0; 1569 m01 = 0.0; 1570 m02 = 0.0; 1571 m10 = 0.0; 1572 m11 = 0.0; 1573 m12 = 0.0; 1574 m20 = 0.0; 1575 m21 = 0.0; 1576 m22 = 0.0; 1577 m30 = 0.0; 1578 m31 = 0.0; 1579 m32 = 0.0; 1580 properties = 0; 1581 return this; 1582 } 1583 1584 /** 1585 * Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor. 1586 * <p> 1587 * The resulting matrix can be multiplied against another transformation 1588 * matrix to obtain an additional scaling. 1589 * <p> 1590 * In order to post-multiply a scaling transformation directly to a 1591 * matrix, use {@link #scale(double) scale()} instead. 1592 * 1593 * @see #scale(double) 1594 * 1595 * @param factor 1596 * the scale factor in x, y and z 1597 * @return this 1598 */ 1599 ref public Matrix4x3d scaling(double factor) return { 1600 return scaling(factor, factor, factor); 1601 } 1602 1603 /** 1604 * Set this matrix to be a simple scale matrix. 1605 * 1606 * @param x 1607 * the scale in x 1608 * @param y 1609 * the scale in y 1610 * @param z 1611 * the scale in z 1612 * @return this 1613 */ 1614 ref public Matrix4x3d scaling(double x, double y, double z) return { 1615 if ((properties & PROPERTY_IDENTITY) == 0) 1616 this.identity(); 1617 m00 = x; 1618 m11 = y; 1619 m22 = z; 1620 bool one = Math.absEqualsOne(x) && Math.absEqualsOne(y) && Math.absEqualsOne(z); 1621 properties = one ? PROPERTY_ORTHONORMAL : 0; 1622 return this; 1623 } 1624 1625 /** 1626 * Set this matrix to be a simple scale matrix which scales the base axes by 1627 * <code>xyz.x</code>, <code>xyz.y</code> and <code>xyz.z</code>, respectively. 1628 * <p> 1629 * The resulting matrix can be multiplied against another transformation 1630 * matrix to obtain an additional scaling. 1631 * <p> 1632 * In order to post-multiply a scaling transformation directly to a 1633 * matrix use {@link #scale(Vector3d) scale()} instead. 1634 * 1635 * @see #scale(Vector3d) 1636 * 1637 * @param xyz 1638 * the scale in x, y and z, respectively 1639 * @return this 1640 */ 1641 ref public Matrix4x3d scaling(Vector3d xyz) return { 1642 return scaling(xyz.x, xyz.y, xyz.z); 1643 } 1644 1645 /** 1646 * Set this matrix to a rotation matrix which rotates the given radians about a given axis. 1647 * <p> 1648 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1649 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1650 * When used with a left-handed coordinate system, the rotation is clockwise. 1651 * <p> 1652 * From <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">Wikipedia</a> 1653 * 1654 * @param angle 1655 * the angle in radians 1656 * @param x 1657 * the x-coordinate of the axis to rotate about 1658 * @param y 1659 * the y-coordinate of the axis to rotate about 1660 * @param z 1661 * the z-coordinate of the axis to rotate about 1662 * @return this 1663 */ 1664 ref public Matrix4x3d rotation(double angle, double x, double y, double z) return { 1665 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 1666 rotationX(x * angle); 1667 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 1668 rotationY(y * angle); 1669 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 1670 rotationZ(z * angle); 1671 else 1672 rotationInternal(angle, x, y, z); 1673 return this; 1674 } 1675 private Matrix4x3d rotationInternal(double angle, double x, double y, double z) { 1676 double sin = Math.sin(angle); 1677 double cos = Math.cosFromSin(sin, angle); 1678 double C = 1.0 - cos; 1679 double xy = x * y, xz = x * z, yz = y * z; 1680 m00 = cos + x * x * C; 1681 m01 = xy * C + z * sin; 1682 m02 = xz * C - y * sin; 1683 m10 = xy * C - z * sin; 1684 m11 = cos + y * y * C; 1685 m12 = yz * C + x * sin; 1686 m20 = xz * C + y * sin; 1687 m21 = yz * C - x * sin; 1688 m22 = cos + z * z * C; 1689 m30 = 0.0; 1690 m31 = 0.0; 1691 m32 = 0.0; 1692 properties = PROPERTY_ORTHONORMAL; 1693 return this; 1694 } 1695 1696 /** 1697 * Set this matrix to a rotation transformation about the X axis. 1698 * <p> 1699 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1700 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1701 * When used with a left-handed coordinate system, the rotation is clockwise. 1702 * <p> 1703 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1704 * 1705 * @param ang 1706 * the angle in radians 1707 * @return this 1708 */ 1709 ref public Matrix4x3d rotationX(double ang) return { 1710 double sin, cos; 1711 sin = Math.sin(ang); 1712 cos = Math.cosFromSin(sin, ang); 1713 m00 = 1.0; 1714 m01 = 0.0; 1715 m02 = 0.0; 1716 m10 = 0.0; 1717 m11 = cos; 1718 m12 = sin; 1719 m20 = 0.0; 1720 m21 = -sin; 1721 m22 = cos; 1722 m30 = 0.0; 1723 m31 = 0.0; 1724 m32 = 0.0; 1725 properties = PROPERTY_ORTHONORMAL; 1726 return this; 1727 } 1728 1729 /** 1730 * Set this matrix to a rotation transformation about the Y axis. 1731 * <p> 1732 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1733 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1734 * When used with a left-handed coordinate system, the rotation is clockwise. 1735 * <p> 1736 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1737 * 1738 * @param ang 1739 * the angle in radians 1740 * @return this 1741 */ 1742 ref public Matrix4x3d rotationY(double ang) return { 1743 double sin, cos; 1744 sin = Math.sin(ang); 1745 cos = Math.cosFromSin(sin, ang); 1746 m00 = cos; 1747 m01 = 0.0; 1748 m02 = -sin; 1749 m10 = 0.0; 1750 m11 = 1.0; 1751 m12 = 0.0; 1752 m20 = sin; 1753 m21 = 0.0; 1754 m22 = cos; 1755 m30 = 0.0; 1756 m31 = 0.0; 1757 m32 = 0.0; 1758 properties = PROPERTY_ORTHONORMAL; 1759 return this; 1760 } 1761 1762 /** 1763 * Set this matrix to a rotation transformation about the Z axis. 1764 * <p> 1765 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1766 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1767 * When used with a left-handed coordinate system, the rotation is clockwise. 1768 * <p> 1769 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 1770 * 1771 * @param ang 1772 * the angle in radians 1773 * @return this 1774 */ 1775 ref public Matrix4x3d rotationZ(double ang) return { 1776 double sin, cos; 1777 sin = Math.sin(ang); 1778 cos = Math.cosFromSin(sin, ang); 1779 m00 = cos; 1780 m01 = sin; 1781 m02 = 0.0; 1782 m10 = -sin; 1783 m11 = cos; 1784 m12 = 0.0; 1785 m20 = 0.0; 1786 m21 = 0.0; 1787 m22 = 1.0; 1788 m30 = 0.0; 1789 m31 = 0.0; 1790 m32 = 0.0; 1791 properties = PROPERTY_ORTHONORMAL; 1792 return this; 1793 } 1794 1795 /** 1796 * Set this matrix to a rotation of <code>angleX</code> radians about the X axis, followed by a rotation 1797 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1798 * <p> 1799 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1800 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1801 * When used with a left-handed coordinate system, the rotation is clockwise. 1802 * <p> 1803 * This method is equivalent to calling: <code>rotationX(angleX).rotateY(angleY).rotateZ(angleZ)</code> 1804 * 1805 * @param angleX 1806 * the angle to rotate about X 1807 * @param angleY 1808 * the angle to rotate about Y 1809 * @param angleZ 1810 * the angle to rotate about Z 1811 * @return this 1812 */ 1813 ref public Matrix4x3d rotationXYZ(double angleX, double angleY, double angleZ) return { 1814 double sinX = Math.sin(angleX); 1815 double cosX = Math.cosFromSin(sinX, angleX); 1816 double sinY = Math.sin(angleY); 1817 double cosY = Math.cosFromSin(sinY, angleY); 1818 double sinZ = Math.sin(angleZ); 1819 double cosZ = Math.cosFromSin(sinZ, angleZ); 1820 double m_sinX = -sinX; 1821 double m_sinY = -sinY; 1822 double m_sinZ = -sinZ; 1823 1824 // rotateX 1825 double nm11 = cosX; 1826 double nm12 = sinX; 1827 double nm21 = m_sinX; 1828 double nm22 = cosX; 1829 // rotateY 1830 double nm00 = cosY; 1831 double nm01 = nm21 * m_sinY; 1832 double nm02 = nm22 * m_sinY; 1833 m20 = sinY; 1834 m21 = nm21 * cosY; 1835 m22 = nm22 * cosY; 1836 // rotateZ 1837 m00 = nm00 * cosZ; 1838 m01 = nm01 * cosZ + nm11 * sinZ; 1839 m02 = nm02 * cosZ + nm12 * sinZ; 1840 m10 = nm00 * m_sinZ; 1841 m11 = nm01 * m_sinZ + nm11 * cosZ; 1842 m12 = nm02 * m_sinZ + nm12 * cosZ; 1843 // set last column to identity 1844 m30 = 0.0; 1845 m31 = 0.0; 1846 m32 = 0.0; 1847 properties = PROPERTY_ORTHONORMAL; 1848 return this; 1849 } 1850 1851 /** 1852 * Set this matrix to a rotation of <code>angleZ</code> radians about the Z axis, followed by a rotation 1853 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleX</code> radians about the X axis. 1854 * <p> 1855 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1856 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1857 * When used with a left-handed coordinate system, the rotation is clockwise. 1858 * <p> 1859 * This method is equivalent to calling: <code>rotationZ(angleZ).rotateY(angleY).rotateX(angleX)</code> 1860 * 1861 * @param angleZ 1862 * the angle to rotate about Z 1863 * @param angleY 1864 * the angle to rotate about Y 1865 * @param angleX 1866 * the angle to rotate about X 1867 * @return this 1868 */ 1869 ref public Matrix4x3d rotationZYX(double angleZ, double angleY, double angleX) return { 1870 double sinX = Math.sin(angleX); 1871 double cosX = Math.cosFromSin(sinX, angleX); 1872 double sinY = Math.sin(angleY); 1873 double cosY = Math.cosFromSin(sinY, angleY); 1874 double sinZ = Math.sin(angleZ); 1875 double cosZ = Math.cosFromSin(sinZ, angleZ); 1876 double m_sinZ = -sinZ; 1877 double m_sinY = -sinY; 1878 double m_sinX = -sinX; 1879 1880 // rotateZ 1881 double nm00 = cosZ; 1882 double nm01 = sinZ; 1883 double nm10 = m_sinZ; 1884 double nm11 = cosZ; 1885 // rotateY 1886 double nm20 = nm00 * sinY; 1887 double nm21 = nm01 * sinY; 1888 double nm22 = cosY; 1889 m00 = nm00 * cosY; 1890 m01 = nm01 * cosY; 1891 m02 = m_sinY; 1892 // rotateX 1893 m10 = nm10 * cosX + nm20 * sinX; 1894 m11 = nm11 * cosX + nm21 * sinX; 1895 m12 = nm22 * sinX; 1896 m20 = nm10 * m_sinX + nm20 * cosX; 1897 m21 = nm11 * m_sinX + nm21 * cosX; 1898 m22 = nm22 * cosX; 1899 // set last column to identity 1900 m30 = 0.0; 1901 m31 = 0.0; 1902 m32 = 0.0; 1903 properties = PROPERTY_ORTHONORMAL; 1904 return this; 1905 } 1906 1907 /** 1908 * Set this matrix to a rotation of <code>angleY</code> radians about the Y axis, followed by a rotation 1909 * of <code>angleX</code> radians about the X axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1910 * <p> 1911 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1912 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1913 * When used with a left-handed coordinate system, the rotation is clockwise. 1914 * <p> 1915 * This method is equivalent to calling: <code>rotationY(angleY).rotateX(angleX).rotateZ(angleZ)</code> 1916 * 1917 * @param angleY 1918 * the angle to rotate about Y 1919 * @param angleX 1920 * the angle to rotate about X 1921 * @param angleZ 1922 * the angle to rotate about Z 1923 * @return this 1924 */ 1925 ref public Matrix4x3d rotationYXZ(double angleY, double angleX, double angleZ) return { 1926 double sinX = Math.sin(angleX); 1927 double cosX = Math.cosFromSin(sinX, angleX); 1928 double sinY = Math.sin(angleY); 1929 double cosY = Math.cosFromSin(sinY, angleY); 1930 double sinZ = Math.sin(angleZ); 1931 double cosZ = Math.cosFromSin(sinZ, angleZ); 1932 double m_sinY = -sinY; 1933 double m_sinX = -sinX; 1934 double m_sinZ = -sinZ; 1935 1936 // rotateY 1937 double nm00 = cosY; 1938 double nm02 = m_sinY; 1939 double nm20 = sinY; 1940 double nm22 = cosY; 1941 // rotateX 1942 double nm10 = nm20 * sinX; 1943 double nm11 = cosX; 1944 double nm12 = nm22 * sinX; 1945 m20 = nm20 * cosX; 1946 m21 = m_sinX; 1947 m22 = nm22 * cosX; 1948 // rotateZ 1949 m00 = nm00 * cosZ + nm10 * sinZ; 1950 m01 = nm11 * sinZ; 1951 m02 = nm02 * cosZ + nm12 * sinZ; 1952 m10 = nm00 * m_sinZ + nm10 * cosZ; 1953 m11 = nm11 * cosZ; 1954 m12 = nm02 * m_sinZ + nm12 * cosZ; 1955 // set last column to identity 1956 m30 = 0.0; 1957 m31 = 0.0; 1958 m32 = 0.0; 1959 properties = PROPERTY_ORTHONORMAL; 1960 return this; 1961 } 1962 1963 /** 1964 * Set only the left 3x3 submatrix of this matrix to a rotation of <code>angleX</code> radians about the X axis, followed by a rotation 1965 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 1966 * <p> 1967 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 1968 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 1969 * When used with a left-handed coordinate system, the rotation is clockwise. 1970 * 1971 * @param angleX 1972 * the angle to rotate about X 1973 * @param angleY 1974 * the angle to rotate about Y 1975 * @param angleZ 1976 * the angle to rotate about Z 1977 * @return this 1978 */ 1979 ref public Matrix4x3d setRotationXYZ(double angleX, double angleY, double angleZ) return { 1980 double sinX = Math.sin(angleX); 1981 double cosX = Math.cosFromSin(sinX, angleX); 1982 double sinY = Math.sin(angleY); 1983 double cosY = Math.cosFromSin(sinY, angleY); 1984 double sinZ = Math.sin(angleZ); 1985 double cosZ = Math.cosFromSin(sinZ, angleZ); 1986 double m_sinX = -sinX; 1987 double m_sinY = -sinY; 1988 double m_sinZ = -sinZ; 1989 1990 // rotateX 1991 double nm11 = cosX; 1992 double nm12 = sinX; 1993 double nm21 = m_sinX; 1994 double nm22 = cosX; 1995 // rotateY 1996 double nm00 = cosY; 1997 double nm01 = nm21 * m_sinY; 1998 double nm02 = nm22 * m_sinY; 1999 m20 = sinY; 2000 m21 = nm21 * cosY; 2001 m22 = nm22 * cosY; 2002 // rotateZ 2003 m00 = nm00 * cosZ; 2004 m01 = nm01 * cosZ + nm11 * sinZ; 2005 m02 = nm02 * cosZ + nm12 * sinZ; 2006 m10 = nm00 * m_sinZ; 2007 m11 = nm01 * m_sinZ + nm11 * cosZ; 2008 m12 = nm02 * m_sinZ + nm12 * cosZ; 2009 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2010 return this; 2011 } 2012 2013 /** 2014 * Set only the left 3x3 submatrix of this matrix to a rotation of <code>angleZ</code> radians about the Z axis, followed by a rotation 2015 * of <code>angleY</code> radians about the Y axis and followed by a rotation of <code>angleX</code> radians about the X axis. 2016 * <p> 2017 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2018 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2019 * When used with a left-handed coordinate system, the rotation is clockwise. 2020 * 2021 * @param angleZ 2022 * the angle to rotate about Z 2023 * @param angleY 2024 * the angle to rotate about Y 2025 * @param angleX 2026 * the angle to rotate about X 2027 * @return this 2028 */ 2029 ref public Matrix4x3d setRotationZYX(double angleZ, double angleY, double angleX) return { 2030 double sinX = Math.sin(angleX); 2031 double cosX = Math.cosFromSin(sinX, angleX); 2032 double sinY = Math.sin(angleY); 2033 double cosY = Math.cosFromSin(sinY, angleY); 2034 double sinZ = Math.sin(angleZ); 2035 double cosZ = Math.cosFromSin(sinZ, angleZ); 2036 double m_sinZ = -sinZ; 2037 double m_sinY = -sinY; 2038 double m_sinX = -sinX; 2039 2040 // rotateZ 2041 double nm00 = cosZ; 2042 double nm01 = sinZ; 2043 double nm10 = m_sinZ; 2044 double nm11 = cosZ; 2045 // rotateY 2046 double nm20 = nm00 * sinY; 2047 double nm21 = nm01 * sinY; 2048 double nm22 = cosY; 2049 m00 = nm00 * cosY; 2050 m01 = nm01 * cosY; 2051 m02 = m_sinY; 2052 // rotateX 2053 m10 = nm10 * cosX + nm20 * sinX; 2054 m11 = nm11 * cosX + nm21 * sinX; 2055 m12 = nm22 * sinX; 2056 m20 = nm10 * m_sinX + nm20 * cosX; 2057 m21 = nm11 * m_sinX + nm21 * cosX; 2058 m22 = nm22 * cosX; 2059 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2060 return this; 2061 } 2062 2063 /** 2064 * Set only the left 3x3 submatrix of this matrix to a rotation of <code>angleY</code> radians about the Y axis, followed by a rotation 2065 * of <code>angleX</code> radians about the X axis and followed by a rotation of <code>angleZ</code> radians about the Z axis. 2066 * <p> 2067 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2068 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2069 * When used with a left-handed coordinate system, the rotation is clockwise. 2070 * 2071 * @param angleY 2072 * the angle to rotate about Y 2073 * @param angleX 2074 * the angle to rotate about X 2075 * @param angleZ 2076 * the angle to rotate about Z 2077 * @return this 2078 */ 2079 ref public Matrix4x3d setRotationYXZ(double angleY, double angleX, double angleZ) return { 2080 double sinX = Math.sin(angleX); 2081 double cosX = Math.cosFromSin(sinX, angleX); 2082 double sinY = Math.sin(angleY); 2083 double cosY = Math.cosFromSin(sinY, angleY); 2084 double sinZ = Math.sin(angleZ); 2085 double cosZ = Math.cosFromSin(sinZ, angleZ); 2086 double m_sinY = -sinY; 2087 double m_sinX = -sinX; 2088 double m_sinZ = -sinZ; 2089 2090 // rotateY 2091 double nm00 = cosY; 2092 double nm02 = m_sinY; 2093 double nm20 = sinY; 2094 double nm22 = cosY; 2095 // rotateX 2096 double nm10 = nm20 * sinX; 2097 double nm11 = cosX; 2098 double nm12 = nm22 * sinX; 2099 m20 = nm20 * cosX; 2100 m21 = m_sinX; 2101 m22 = nm22 * cosX; 2102 // rotateZ 2103 m00 = nm00 * cosZ + nm10 * sinZ; 2104 m01 = nm11 * sinZ; 2105 m02 = nm02 * cosZ + nm12 * sinZ; 2106 m10 = nm00 * m_sinZ + nm10 * cosZ; 2107 m11 = nm11 * cosZ; 2108 m12 = nm02 * m_sinZ + nm12 * cosZ; 2109 properties &= ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2110 return this; 2111 } 2112 2113 /** 2114 * Set this matrix to a rotation matrix which rotates the given radians about a given axis. 2115 * <p> 2116 * The axis described by the <code>axis</code> vector needs to be a unit vector. 2117 * <p> 2118 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2119 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2120 * When used with a left-handed coordinate system, the rotation is clockwise. 2121 * 2122 * @param angle 2123 * the angle in radians 2124 * @param axis 2125 * the axis to rotate about 2126 * @return this 2127 */ 2128 ref public Matrix4x3d rotation(double angle, Vector3d axis) return { 2129 return rotation(angle, axis.x, axis.y, axis.z); 2130 } 2131 2132 public Vector4d transform(Vector4d v) { 2133 return v.mul(this); 2134 } 2135 2136 public Vector4d transform(Vector4d v, Vector4d dest) { 2137 return v.mul(this, dest); 2138 } 2139 2140 public Vector3d transformPosition(ref Vector3d v) { 2141 v.set(m00 * v.x + m10 * v.y + m20 * v.z + m30, 2142 m01 * v.x + m11 * v.y + m21 * v.z + m31, 2143 m02 * v.x + m12 * v.y + m22 * v.z + m32); 2144 return v; 2145 } 2146 2147 public Vector3d transformPosition(ref Vector3d v, ref Vector3d dest) { 2148 dest.set(m00 * v.x + m10 * v.y + m20 * v.z + m30, 2149 m01 * v.x + m11 * v.y + m21 * v.z + m31, 2150 m02 * v.x + m12 * v.y + m22 * v.z + m32); 2151 return dest; 2152 } 2153 2154 public Vector3d transformDirection(ref Vector3d v) { 2155 v.set(m00 * v.x + m10 * v.y + m20 * v.z, 2156 m01 * v.x + m11 * v.y + m21 * v.z, 2157 m02 * v.x + m12 * v.y + m22 * v.z); 2158 return v; 2159 } 2160 2161 public Vector3d transformDirection(ref Vector3d v, ref Vector3d dest) { 2162 dest.set(m00 * v.x + m10 * v.y + m20 * v.z, 2163 m01 * v.x + m11 * v.y + m21 * v.z, 2164 m02 * v.x + m12 * v.y + m22 * v.z); 2165 return dest; 2166 } 2167 2168 /** 2169 * Set the left 3x3 submatrix of this {@link Matrix4x3d} to the given {@link Matrix3d} and don't change the other elements. 2170 * 2171 * @param mat 2172 * the 3x3 matrix 2173 * @return this 2174 */ 2175 ref public Matrix4x3d set3x3(Matrix3d mat) return { 2176 m00 = mat.m00; 2177 m01 = mat.m01; 2178 m02 = mat.m02; 2179 m10 = mat.m10; 2180 m11 = mat.m11; 2181 m12 = mat.m12; 2182 m20 = mat.m20; 2183 m21 = mat.m21; 2184 m22 = mat.m22; 2185 properties = 0; 2186 return this; 2187 } 2188 2189 2190 public Matrix4x3d scale(Vector3d xyz, ref Matrix4x3d dest) { 2191 return scale(xyz.x, xyz.y, xyz.z, dest); 2192 } 2193 2194 /** 2195 * Apply scaling to this matrix by scaling the base axes by the given <code>xyz.x</code>, 2196 * <code>xyz.y</code> and <code>xyz.z</code> factors, respectively. 2197 * <p> 2198 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2199 * then the new matrix will be <code>M * S</code>. So when transforming a 2200 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2201 * scaling will be applied first! 2202 * 2203 * @param xyz 2204 * the factors of the x, y and z component, respectively 2205 * @return this 2206 */ 2207 ref public Matrix4x3d scale(Vector3d xyz) return { 2208 scale(xyz.x, xyz.y, xyz.z, this); 2209 return this; 2210 } 2211 2212 public Matrix4x3d scale(double x, double y, double z, ref Matrix4x3d dest) { 2213 if ((properties & PROPERTY_IDENTITY) != 0) 2214 return dest.scaling(x, y, z); 2215 return scaleGeneric(x, y, z, dest); 2216 } 2217 private Matrix4x3d scaleGeneric(double x, double y, double z, ref Matrix4x3d dest) { 2218 dest.m00 = m00 * x; 2219 dest.m01 = m01 * x; 2220 dest.m02 = m02 * x; 2221 dest.m10 = m10 * y; 2222 dest.m11 = m11 * y; 2223 dest.m12 = m12 * y; 2224 dest.m20 = m20 * z; 2225 dest.m21 = m21 * z; 2226 dest.m22 = m22 * z; 2227 dest.m30 = m30; 2228 dest.m31 = m31; 2229 dest.m32 = m32; 2230 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 2231 return dest; 2232 } 2233 2234 /** 2235 * Apply scaling to <code>this</code> matrix by scaling the base axes by the given x, 2236 * y and z factors. 2237 * <p> 2238 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2239 * then the new matrix will be <code>M * S</code>. So when transforming a 2240 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 2241 * , the scaling will be applied first! 2242 * 2243 * @param x 2244 * the factor of the x component 2245 * @param y 2246 * the factor of the y component 2247 * @param z 2248 * the factor of the z component 2249 * @return this 2250 */ 2251 ref public Matrix4x3d scale(double x, double y, double z) return { 2252 scale(x, y, z, this); 2253 return this; 2254 } 2255 2256 public Matrix4x3d scale(double xyz, ref Matrix4x3d dest) { 2257 return scale(xyz, xyz, xyz, dest); 2258 } 2259 2260 /** 2261 * Apply scaling to this matrix by uniformly scaling all base axes by the given xyz factor. 2262 * <p> 2263 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2264 * then the new matrix will be <code>M * S</code>. So when transforming a 2265 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 2266 * , the scaling will be applied first! 2267 * 2268 * @see #scale(double, double, double) 2269 * 2270 * @param xyz 2271 * the factor for all components 2272 * @return this 2273 */ 2274 ref public Matrix4x3d scale(double xyz) return { 2275 return scale(xyz, xyz, xyz); 2276 } 2277 2278 public Matrix4x3d scaleXY(double x, double y, ref Matrix4x3d dest) { 2279 return scale(x, y, 1.0, dest); 2280 } 2281 2282 /** 2283 * Apply scaling to this matrix by scaling the X axis by <code>x</code> and the Y axis by <code>y</code>. 2284 * <p> 2285 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2286 * then the new matrix will be <code>M * S</code>. So when transforming a 2287 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2288 * scaling will be applied first! 2289 * 2290 * @param x 2291 * the factor of the x component 2292 * @param y 2293 * the factor of the y component 2294 * @return this 2295 */ 2296 ref public Matrix4x3d scaleXY(double x, double y) return { 2297 return scale(x, y, 1.0); 2298 } 2299 2300 public Matrix4x3d scaleAround(double sx, double sy, double sz, double ox, double oy, double oz, ref Matrix4x3d dest) { 2301 double nm30 = m00 * ox + m10 * oy + m20 * oz + m30; 2302 double nm31 = m01 * ox + m11 * oy + m21 * oz + m31; 2303 double nm32 = m02 * ox + m12 * oy + m22 * oz + m32; 2304 bool one = Math.absEqualsOne(sx) && Math.absEqualsOne(sy) && Math.absEqualsOne(sz); 2305 return dest 2306 ._m00(m00 * sx) 2307 ._m01(m01 * sx) 2308 ._m02(m02 * sx) 2309 ._m10(m10 * sy) 2310 ._m11(m11 * sy) 2311 ._m12(m12 * sy) 2312 ._m20(m20 * sz) 2313 ._m21(m21 * sz) 2314 ._m22(m22 * sz) 2315 ._m30(-dest.m00 * ox - dest.m10 * oy - dest.m20 * oz + nm30) 2316 ._m31(-dest.m01 * ox - dest.m11 * oy - dest.m21 * oz + nm31) 2317 ._m32(-dest.m02 * ox - dest.m12 * oy - dest.m22 * oz + nm32) 2318 ._properties(properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | (one ? 0 : PROPERTY_ORTHONORMAL))); 2319 } 2320 2321 /** 2322 * Apply scaling to this matrix by scaling the base axes by the given sx, 2323 * sy and sz factors while using <code>(ox, oy, oz)</code> as the scaling origin. 2324 * <p> 2325 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2326 * then the new matrix will be <code>M * S</code>. So when transforming a 2327 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2328 * scaling will be applied first! 2329 * <p> 2330 * This method is equivalent to calling: <code>translate(ox, oy, oz).scale(sx, sy, sz).translate(-ox, -oy, -oz)</code> 2331 * 2332 * @param sx 2333 * the scaling factor of the x component 2334 * @param sy 2335 * the scaling factor of the y component 2336 * @param sz 2337 * the scaling factor of the z component 2338 * @param ox 2339 * the x coordinate of the scaling origin 2340 * @param oy 2341 * the y coordinate of the scaling origin 2342 * @param oz 2343 * the z coordinate of the scaling origin 2344 * @return this 2345 */ 2346 ref public Matrix4x3d scaleAround(double sx, double sy, double sz, double ox, double oy, double oz) return { 2347 scaleAround(sx, sy, sz, ox, oy, oz, this); 2348 return this; 2349 } 2350 2351 /** 2352 * Apply scaling to this matrix by scaling all three base axes by the given <code>factor</code> 2353 * while using <code>(ox, oy, oz)</code> as the scaling origin. 2354 * <p> 2355 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2356 * then the new matrix will be <code>M * S</code>. So when transforming a 2357 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 2358 * scaling will be applied first! 2359 * <p> 2360 * This method is equivalent to calling: <code>translate(ox, oy, oz).scale(factor).translate(-ox, -oy, -oz)</code> 2361 * 2362 * @param factor 2363 * the scaling factor for all three axes 2364 * @param ox 2365 * the x coordinate of the scaling origin 2366 * @param oy 2367 * the y coordinate of the scaling origin 2368 * @param oz 2369 * the z coordinate of the scaling origin 2370 * @return this 2371 */ 2372 ref public Matrix4x3d scaleAround(double factor, double ox, double oy, double oz) return { 2373 scaleAround(factor, factor, factor, ox, oy, oz, this); 2374 return this; 2375 } 2376 2377 public Matrix4x3d scaleAround(double factor, double ox, double oy, double oz, ref Matrix4x3d dest) { 2378 return scaleAround(factor, factor, factor, ox, oy, oz, dest); 2379 } 2380 2381 public Matrix4x3d scaleLocal(double x, double y, double z, ref Matrix4x3d dest) { 2382 if ((properties & PROPERTY_IDENTITY) != 0) 2383 return dest.scaling(x, y, z); 2384 2385 double nm00 = x * m00; 2386 double nm01 = y * m01; 2387 double nm02 = z * m02; 2388 double nm10 = x * m10; 2389 double nm11 = y * m11; 2390 double nm12 = z * m12; 2391 double nm20 = x * m20; 2392 double nm21 = y * m21; 2393 double nm22 = z * m22; 2394 double nm30 = x * m30; 2395 double nm31 = y * m31; 2396 double nm32 = z * m32; 2397 dest.m00 = nm00; 2398 dest.m01 = nm01; 2399 dest.m02 = nm02; 2400 dest.m10 = nm10; 2401 dest.m11 = nm11; 2402 dest.m12 = nm12; 2403 dest.m20 = nm20; 2404 dest.m21 = nm21; 2405 dest.m22 = nm22; 2406 dest.m30 = nm30; 2407 dest.m31 = nm31; 2408 dest.m32 = nm32; 2409 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 2410 return dest; 2411 } 2412 2413 /** 2414 * Pre-multiply scaling to this matrix by scaling the base axes by the given x, 2415 * y and z factors. 2416 * <p> 2417 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 2418 * then the new matrix will be <code>S * M</code>. So when transforming a 2419 * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the 2420 * scaling will be applied last! 2421 * 2422 * @param x 2423 * the factor of the x component 2424 * @param y 2425 * the factor of the y component 2426 * @param z 2427 * the factor of the z component 2428 * @return this 2429 */ 2430 ref public Matrix4x3d scaleLocal(double x, double y, double z) return { 2431 scaleLocal(x, y, z, this); 2432 return this; 2433 } 2434 2435 public Matrix4x3d rotate(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2436 if ((properties & PROPERTY_IDENTITY) != 0) 2437 return dest.rotation(ang, x, y, z); 2438 else if ((properties & PROPERTY_TRANSLATION) != 0) 2439 return rotateTranslation(ang, x, y, z, dest); 2440 return rotateGeneric(ang, x, y, z, dest); 2441 } 2442 private Matrix4x3d rotateGeneric(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2443 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 2444 return rotateX(x * ang, dest); 2445 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 2446 return rotateY(y * ang, dest); 2447 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 2448 return rotateZ(z * ang, dest); 2449 return rotateGenericInternal(ang, x, y, z, dest); 2450 } 2451 private Matrix4x3d rotateGenericInternal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2452 double s = Math.sin(ang); 2453 double c = Math.cosFromSin(s, ang); 2454 double C = 1.0 - c; 2455 double xx = x * x, xy = x * y, xz = x * z; 2456 double yy = y * y, yz = y * z; 2457 double zz = z * z; 2458 double rm00 = xx * C + c; 2459 double rm01 = xy * C + z * s; 2460 double rm02 = xz * C - y * s; 2461 double rm10 = xy * C - z * s; 2462 double rm11 = yy * C + c; 2463 double rm12 = yz * C + x * s; 2464 double rm20 = xz * C + y * s; 2465 double rm21 = yz * C - x * s; 2466 double rm22 = zz * C + c; 2467 // add temporaries for dependent values 2468 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 2469 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 2470 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 2471 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 2472 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 2473 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 2474 // set non-dependent values directly 2475 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 2476 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 2477 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 2478 // set other values 2479 dest.m00 = nm00; 2480 dest.m01 = nm01; 2481 dest.m02 = nm02; 2482 dest.m10 = nm10; 2483 dest.m11 = nm11; 2484 dest.m12 = nm12; 2485 dest.m30 = m30; 2486 dest.m31 = m31; 2487 dest.m32 = m32; 2488 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2489 return dest; 2490 } 2491 2492 /** 2493 * Apply rotation to this matrix by rotating the given amount of radians 2494 * about the given axis specified as x, y and z components. 2495 * <p> 2496 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2497 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2498 * When used with a left-handed coordinate system, the rotation is clockwise. 2499 * <p> 2500 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2501 * then the new matrix will be <code>M * R</code>. So when transforming a 2502 * vector <code>v</code> with the new matrix by using <code>M * R * v</code> 2503 * , the rotation will be applied first! 2504 * <p> 2505 * In order to set the matrix to a rotation matrix without post-multiplying the rotation 2506 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2507 * 2508 * @see #rotation(double, double, double, double) 2509 * 2510 * @param ang 2511 * the angle is in radians 2512 * @param x 2513 * the x component of the axis 2514 * @param y 2515 * the y component of the axis 2516 * @param z 2517 * the z component of the axis 2518 * @return this 2519 */ 2520 ref public Matrix4x3d rotate(double ang, double x, double y, double z) return { 2521 rotate(ang, x, y, z, this); 2522 return this; 2523 } 2524 2525 /** 2526 * Apply rotation to this matrix, which is assumed to only contain a translation, by rotating the given amount of radians 2527 * about the specified <code>(x, y, z)</code> axis and store the result in <code>dest</code>. 2528 * <p> 2529 * This method assumes <code>this</code> to only contain a translation. 2530 * <p> 2531 * The axis described by the three components needs to be a unit vector. 2532 * <p> 2533 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2534 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2535 * When used with a left-handed coordinate system, the rotation is clockwise. 2536 * <p> 2537 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2538 * then the new matrix will be <code>M * R</code>. So when transforming a 2539 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 2540 * rotation will be applied first! 2541 * <p> 2542 * In order to set the matrix to a rotation matrix without post-multiplying the rotation 2543 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2544 * <p> 2545 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2546 * 2547 * @see #rotation(double, double, double, double) 2548 * 2549 * @param ang 2550 * the angle in radians 2551 * @param x 2552 * the x component of the axis 2553 * @param y 2554 * the y component of the axis 2555 * @param z 2556 * the z component of the axis 2557 * @param dest 2558 * will hold the result 2559 * @return dest 2560 */ 2561 public Matrix4x3d rotateTranslation(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2562 double tx = m30, ty = m31, tz = m32; 2563 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 2564 return dest.rotationX(x * ang).setTranslation(tx, ty, tz); 2565 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 2566 return dest.rotationY(y * ang).setTranslation(tx, ty, tz); 2567 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 2568 return dest.rotationZ(z * ang).setTranslation(tx, ty, tz); 2569 return rotateTranslationInternal(ang, x, y, z, dest); 2570 } 2571 private Matrix4x3d rotateTranslationInternal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2572 double s = Math.sin(ang); 2573 double c = Math.cosFromSin(s, ang); 2574 double C = 1.0 - c; 2575 double xx = x * x, xy = x * y, xz = x * z; 2576 double yy = y * y, yz = y * z; 2577 double zz = z * z; 2578 double rm00 = xx * C + c; 2579 double rm01 = xy * C + z * s; 2580 double rm02 = xz * C - y * s; 2581 double rm10 = xy * C - z * s; 2582 double rm11 = yy * C + c; 2583 double rm12 = yz * C + x * s; 2584 double rm20 = xz * C + y * s; 2585 double rm21 = yz * C - x * s; 2586 double rm22 = zz * C + c; 2587 dest.m20 = rm20; 2588 dest.m21 = rm21; 2589 dest.m22 = rm22; 2590 dest.m00 = rm00; 2591 dest.m01 = rm01; 2592 dest.m02 = rm02; 2593 dest.m10 = rm10; 2594 dest.m11 = rm11; 2595 dest.m12 = rm12; 2596 dest.m30 = m30; 2597 dest.m31 = m31; 2598 dest.m32 = m32; 2599 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2600 return dest; 2601 } 2602 2603 /** 2604 * Apply the rotation transformation of the given {@link Quaterniond} to this matrix while using <code>(ox, oy, oz)</code> as the rotation origin. 2605 * <p> 2606 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2607 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2608 * When used with a left-handed coordinate system, the rotation is clockwise. 2609 * <p> 2610 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 2611 * then the new matrix will be <code>M * Q</code>. So when transforming a 2612 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 2613 * the quaternion rotation will be applied first! 2614 * <p> 2615 * This method is equivalent to calling: <code>translate(ox, oy, oz).rotate(quat).translate(-ox, -oy, -oz)</code> 2616 * <p> 2617 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2618 * 2619 * @param quat 2620 * the {@link Quaterniond} 2621 * @param ox 2622 * the x coordinate of the rotation origin 2623 * @param oy 2624 * the y coordinate of the rotation origin 2625 * @param oz 2626 * the z coordinate of the rotation origin 2627 * @return this 2628 */ 2629 ref public Matrix4x3d rotateAround(Quaterniond quat, double ox, double oy, double oz) return { 2630 rotateAround(quat, ox, oy, oz, this); 2631 return this; 2632 } 2633 2634 private Matrix4x3d rotateAroundAffine(Quaterniond quat, double ox, double oy, double oz, ref Matrix4x3d dest) { 2635 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 2636 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 2637 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 2638 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 2639 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 2640 double rm00 = w2 + x2 - z2 - y2; 2641 double rm01 = dxy + dzw; 2642 double rm02 = dxz - dyw; 2643 double rm10 = dxy - dzw; 2644 double rm11 = y2 - z2 + w2 - x2; 2645 double rm12 = dyz + dxw; 2646 double rm20 = dyw + dxz; 2647 double rm21 = dyz - dxw; 2648 double rm22 = z2 - y2 - x2 + w2; 2649 double tm30 = m00 * ox + m10 * oy + m20 * oz + m30; 2650 double tm31 = m01 * ox + m11 * oy + m21 * oz + m31; 2651 double tm32 = m02 * ox + m12 * oy + m22 * oz + m32; 2652 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 2653 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 2654 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 2655 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 2656 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 2657 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 2658 dest 2659 ._m20(m00 * rm20 + m10 * rm21 + m20 * rm22) 2660 ._m21(m01 * rm20 + m11 * rm21 + m21 * rm22) 2661 ._m22(m02 * rm20 + m12 * rm21 + m22 * rm22) 2662 ._m00(nm00) 2663 ._m01(nm01) 2664 ._m02(nm02) 2665 ._m10(nm10) 2666 ._m11(nm11) 2667 ._m12(nm12) 2668 ._m30(-nm00 * ox - nm10 * oy - m20 * oz + tm30) 2669 ._m31(-nm01 * ox - nm11 * oy - m21 * oz + tm31) 2670 ._m32(-nm02 * ox - nm12 * oy - m22 * oz + tm32) 2671 ._properties(properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION)); 2672 return dest; 2673 } 2674 2675 public Matrix4x3d rotateAround(Quaterniond quat, double ox, double oy, double oz, ref Matrix4x3d dest) { 2676 if ((properties & PROPERTY_IDENTITY) != 0) 2677 return rotationAround(quat, ox, oy, oz); 2678 return rotateAroundAffine(quat, ox, oy, oz, dest); 2679 } 2680 2681 /** 2682 * Set this matrix to a transformation composed of a rotation of the specified {@link Quaterniond} while using <code>(ox, oy, oz)</code> as the rotation origin. 2683 * <p> 2684 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2685 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2686 * When used with a left-handed coordinate system, the rotation is clockwise. 2687 * <p> 2688 * This method is equivalent to calling: <code>translation(ox, oy, oz).rotate(quat).translate(-ox, -oy, -oz)</code> 2689 * <p> 2690 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 2691 * 2692 * @param quat 2693 * the {@link Quaterniond} 2694 * @param ox 2695 * the x coordinate of the rotation origin 2696 * @param oy 2697 * the y coordinate of the rotation origin 2698 * @param oz 2699 * the z coordinate of the rotation origin 2700 * @return this 2701 */ 2702 ref public Matrix4x3d rotationAround(Quaterniond quat, double ox, double oy, double oz) return { 2703 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 2704 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 2705 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 2706 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 2707 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 2708 this._m20(dyw + dxz); 2709 this._m21(dyz - dxw); 2710 this._m22(z2 - y2 - x2 + w2); 2711 this._m00(w2 + x2 - z2 - y2); 2712 this._m01(dxy + dzw); 2713 this._m02(dxz - dyw); 2714 this._m10(dxy - dzw); 2715 this._m11(y2 - z2 + w2 - x2); 2716 this._m12(dyz + dxw); 2717 this._m30(-m00 * ox - m10 * oy - m20 * oz + ox); 2718 this._m31(-m01 * ox - m11 * oy - m21 * oz + oy); 2719 this._m32(-m02 * ox - m12 * oy - m22 * oz + oz); 2720 this.properties = PROPERTY_ORTHONORMAL; 2721 return this; 2722 } 2723 2724 /** 2725 * Pre-multiply a rotation to this matrix by rotating the given amount of radians 2726 * about the specified <code>(x, y, z)</code> axis and store the result in <code>dest</code>. 2727 * <p> 2728 * The axis described by the three components needs to be a unit vector. 2729 * <p> 2730 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2731 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2732 * When used with a left-handed coordinate system, the rotation is clockwise. 2733 * <p> 2734 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2735 * then the new matrix will be <code>R * M</code>. So when transforming a 2736 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2737 * rotation will be applied last! 2738 * <p> 2739 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2740 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2741 * <p> 2742 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2743 * 2744 * @see #rotation(double, double, double, double) 2745 * 2746 * @param ang 2747 * the angle in radians 2748 * @param x 2749 * the x component of the axis 2750 * @param y 2751 * the y component of the axis 2752 * @param z 2753 * the z component of the axis 2754 * @param dest 2755 * will hold the result 2756 * @return dest 2757 */ 2758 public Matrix4x3d rotateLocal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2759 if (y == 0.0 && z == 0.0 && Math.absEqualsOne(x)) 2760 return rotateLocalX(x * ang, dest); 2761 else if (x == 0.0 && z == 0.0 && Math.absEqualsOne(y)) 2762 return rotateLocalY(y * ang, dest); 2763 else if (x == 0.0 && y == 0.0 && Math.absEqualsOne(z)) 2764 return rotateLocalZ(z * ang, dest); 2765 return rotateLocalInternal(ang, x, y, z, dest); 2766 } 2767 private Matrix4x3d rotateLocalInternal(double ang, double x, double y, double z, ref Matrix4x3d dest) { 2768 double s = Math.sin(ang); 2769 double c = Math.cosFromSin(s, ang); 2770 double C = 1.0 - c; 2771 double xx = x * x, xy = x * y, xz = x * z; 2772 double yy = y * y, yz = y * z; 2773 double zz = z * z; 2774 double lm00 = xx * C + c; 2775 double lm01 = xy * C + z * s; 2776 double lm02 = xz * C - y * s; 2777 double lm10 = xy * C - z * s; 2778 double lm11 = yy * C + c; 2779 double lm12 = yz * C + x * s; 2780 double lm20 = xz * C + y * s; 2781 double lm21 = yz * C - x * s; 2782 double lm22 = zz * C + c; 2783 double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; 2784 double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; 2785 double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; 2786 double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; 2787 double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; 2788 double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; 2789 double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; 2790 double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; 2791 double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; 2792 double nm30 = lm00 * m30 + lm10 * m31 + lm20 * m32; 2793 double nm31 = lm01 * m30 + lm11 * m31 + lm21 * m32; 2794 double nm32 = lm02 * m30 + lm12 * m31 + lm22 * m32; 2795 dest.m00 = nm00; 2796 dest.m01 = nm01; 2797 dest.m02 = nm02; 2798 dest.m10 = nm10; 2799 dest.m11 = nm11; 2800 dest.m12 = nm12; 2801 dest.m20 = nm20; 2802 dest.m21 = nm21; 2803 dest.m22 = nm22; 2804 dest.m30 = nm30; 2805 dest.m31 = nm31; 2806 dest.m32 = nm32; 2807 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2808 return dest; 2809 } 2810 2811 /** 2812 * Pre-multiply a rotation to this matrix by rotating the given amount of radians 2813 * about the specified <code>(x, y, z)</code> axis. 2814 * <p> 2815 * The axis described by the three components needs to be a unit vector. 2816 * <p> 2817 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2818 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2819 * When used with a left-handed coordinate system, the rotation is clockwise. 2820 * <p> 2821 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2822 * then the new matrix will be <code>R * M</code>. So when transforming a 2823 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2824 * rotation will be applied last! 2825 * <p> 2826 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2827 * transformation, use {@link #rotation(double, double, double, double) rotation()}. 2828 * <p> 2829 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2830 * 2831 * @see #rotation(double, double, double, double) 2832 * 2833 * @param ang 2834 * the angle in radians 2835 * @param x 2836 * the x component of the axis 2837 * @param y 2838 * the y component of the axis 2839 * @param z 2840 * the z component of the axis 2841 * @return this 2842 */ 2843 ref public Matrix4x3d rotateLocal(double ang, double x, double y, double z) return { 2844 rotateLocal(ang, x, y, z, this); 2845 return this; 2846 } 2847 2848 /** 2849 * Pre-multiply a rotation around the X axis to this matrix by rotating the given amount of radians 2850 * about the X axis and store the result in <code>dest</code>. 2851 * <p> 2852 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2853 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2854 * When used with a left-handed coordinate system, the rotation is clockwise. 2855 * <p> 2856 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2857 * then the new matrix will be <code>R * M</code>. So when transforming a 2858 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2859 * rotation will be applied last! 2860 * <p> 2861 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2862 * transformation, use {@link #rotationX(double) rotationX()}. 2863 * <p> 2864 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2865 * 2866 * @see #rotationX(double) 2867 * 2868 * @param ang 2869 * the angle in radians to rotate about the X axis 2870 * @param dest 2871 * will hold the result 2872 * @return dest 2873 */ 2874 public Matrix4x3d rotateLocalX(double ang, ref Matrix4x3d dest) { 2875 double sin = Math.sin(ang); 2876 double cos = Math.cosFromSin(sin, ang); 2877 double nm01 = cos * m01 - sin * m02; 2878 double nm02 = sin * m01 + cos * m02; 2879 double nm11 = cos * m11 - sin * m12; 2880 double nm12 = sin * m11 + cos * m12; 2881 double nm21 = cos * m21 - sin * m22; 2882 double nm22 = sin * m21 + cos * m22; 2883 double nm31 = cos * m31 - sin * m32; 2884 double nm32 = sin * m31 + cos * m32; 2885 dest.m00 = m00; 2886 dest.m01 = nm01; 2887 dest.m02 = nm02; 2888 dest.m10 = m10; 2889 dest.m11 = nm11; 2890 dest.m12 = nm12; 2891 dest.m20 = m20; 2892 dest.m21 = nm21; 2893 dest.m22 = nm22; 2894 dest.m30 = m30; 2895 dest.m31 = nm31; 2896 dest.m32 = nm32; 2897 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2898 return dest; 2899 } 2900 2901 /** 2902 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the X axis. 2903 * <p> 2904 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2905 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2906 * When used with a left-handed coordinate system, the rotation is clockwise. 2907 * <p> 2908 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2909 * then the new matrix will be <code>R * M</code>. So when transforming a 2910 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2911 * rotation will be applied last! 2912 * <p> 2913 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2914 * transformation, use {@link #rotationX(double) rotationX()}. 2915 * <p> 2916 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2917 * 2918 * @see #rotationX(double) 2919 * 2920 * @param ang 2921 * the angle in radians to rotate about the X axis 2922 * @return this 2923 */ 2924 ref public Matrix4x3d rotateLocalX(double ang) return { 2925 rotateLocalX(ang, this); 2926 return this; 2927 } 2928 2929 /** 2930 * Pre-multiply a rotation around the Y axis to this matrix by rotating the given amount of radians 2931 * about the Y axis and store the result in <code>dest</code>. 2932 * <p> 2933 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2934 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2935 * When used with a left-handed coordinate system, the rotation is clockwise. 2936 * <p> 2937 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2938 * then the new matrix will be <code>R * M</code>. So when transforming a 2939 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2940 * rotation will be applied last! 2941 * <p> 2942 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2943 * transformation, use {@link #rotationY(double) rotationY()}. 2944 * <p> 2945 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2946 * 2947 * @see #rotationY(double) 2948 * 2949 * @param ang 2950 * the angle in radians to rotate about the Y axis 2951 * @param dest 2952 * will hold the result 2953 * @return dest 2954 */ 2955 public Matrix4x3d rotateLocalY(double ang, ref Matrix4x3d dest) { 2956 double sin = Math.sin(ang); 2957 double cos = Math.cosFromSin(sin, ang); 2958 double nm00 = cos * m00 + sin * m02; 2959 double nm02 = -sin * m00 + cos * m02; 2960 double nm10 = cos * m10 + sin * m12; 2961 double nm12 = -sin * m10 + cos * m12; 2962 double nm20 = cos * m20 + sin * m22; 2963 double nm22 = -sin * m20 + cos * m22; 2964 double nm30 = cos * m30 + sin * m32; 2965 double nm32 = -sin * m30 + cos * m32; 2966 dest.m00 = nm00; 2967 dest.m01 = m01; 2968 dest.m02 = nm02; 2969 dest.m10 = nm10; 2970 dest.m11 = m11; 2971 dest.m12 = nm12; 2972 dest.m20 = nm20; 2973 dest.m21 = m21; 2974 dest.m22 = nm22; 2975 dest.m30 = nm30; 2976 dest.m31 = m31; 2977 dest.m32 = nm32; 2978 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 2979 return dest; 2980 } 2981 2982 /** 2983 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Y axis. 2984 * <p> 2985 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 2986 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 2987 * When used with a left-handed coordinate system, the rotation is clockwise. 2988 * <p> 2989 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 2990 * then the new matrix will be <code>R * M</code>. So when transforming a 2991 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 2992 * rotation will be applied last! 2993 * <p> 2994 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 2995 * transformation, use {@link #rotationY(double) rotationY()}. 2996 * <p> 2997 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 2998 * 2999 * @see #rotationY(double) 3000 * 3001 * @param ang 3002 * the angle in radians to rotate about the Y axis 3003 * @return this 3004 */ 3005 ref public Matrix4x3d rotateLocalY(double ang) return { 3006 rotateLocalY(ang, this); 3007 return this; 3008 } 3009 3010 /** 3011 * Pre-multiply a rotation around the Z axis to this matrix by rotating the given amount of radians 3012 * about the Z axis and store the result in <code>dest</code>. 3013 * <p> 3014 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3015 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3016 * When used with a left-handed coordinate system, the rotation is clockwise. 3017 * <p> 3018 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3019 * then the new matrix will be <code>R * M</code>. So when transforming a 3020 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 3021 * rotation will be applied last! 3022 * <p> 3023 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 3024 * transformation, use {@link #rotationZ(double) rotationZ()}. 3025 * <p> 3026 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 3027 * 3028 * @see #rotationZ(double) 3029 * 3030 * @param ang 3031 * the angle in radians to rotate about the Z axis 3032 * @param dest 3033 * will hold the result 3034 * @return dest 3035 */ 3036 public Matrix4x3d rotateLocalZ(double ang, ref Matrix4x3d dest) { 3037 double sin = Math.sin(ang); 3038 double cos = Math.cosFromSin(sin, ang); 3039 double nm00 = cos * m00 - sin * m01; 3040 double nm01 = sin * m00 + cos * m01; 3041 double nm10 = cos * m10 - sin * m11; 3042 double nm11 = sin * m10 + cos * m11; 3043 double nm20 = cos * m20 - sin * m21; 3044 double nm21 = sin * m20 + cos * m21; 3045 double nm30 = cos * m30 - sin * m31; 3046 double nm31 = sin * m30 + cos * m31; 3047 dest.m00 = nm00; 3048 dest.m01 = nm01; 3049 dest.m02 = m02; 3050 dest.m10 = nm10; 3051 dest.m11 = nm11; 3052 dest.m12 = m12; 3053 dest.m20 = nm20; 3054 dest.m21 = nm21; 3055 dest.m22 = m22; 3056 dest.m30 = nm30; 3057 dest.m31 = nm31; 3058 dest.m32 = m32; 3059 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3060 return dest; 3061 } 3062 3063 /** 3064 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the Z axis. 3065 * <p> 3066 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3067 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3068 * When used with a left-handed coordinate system, the rotation is clockwise. 3069 * <p> 3070 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3071 * then the new matrix will be <code>R * M</code>. So when transforming a 3072 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 3073 * rotation will be applied last! 3074 * <p> 3075 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 3076 * transformation, use {@link #rotationZ(double) rotationY()}. 3077 * <p> 3078 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a> 3079 * 3080 * @see #rotationY(double) 3081 * 3082 * @param ang 3083 * the angle in radians to rotate about the Z axis 3084 * @return this 3085 */ 3086 ref public Matrix4x3d rotateLocalZ(double ang) return { 3087 rotateLocalZ(ang, this); 3088 return this; 3089 } 3090 3091 /** 3092 * Apply a translation to this matrix by translating by the given number of 3093 * units in x, y and z. 3094 * <p> 3095 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3096 * matrix, then the new matrix will be <code>M * T</code>. So when 3097 * transforming a vector <code>v</code> with the new matrix by using 3098 * <code>M * T * v</code>, the translation will be applied first! 3099 * <p> 3100 * In order to set the matrix to a translation transformation without post-multiplying 3101 * it, use {@link #translation(Vector3d)}. 3102 * 3103 * @see #translation(Vector3d) 3104 * 3105 * @param offset 3106 * the number of units in x, y and z by which to translate 3107 * @return this 3108 */ 3109 ref public Matrix4x3d translate(Vector3d offset) return { 3110 return translate(offset.x, offset.y, offset.z); 3111 } 3112 3113 /** 3114 * Apply a translation to this matrix by translating by the given number of 3115 * units in x, y and z and store the result in <code>dest</code>. 3116 * <p> 3117 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3118 * matrix, then the new matrix will be <code>M * T</code>. So when 3119 * transforming a vector <code>v</code> with the new matrix by using 3120 * <code>M * T * v</code>, the translation will be applied first! 3121 * <p> 3122 * In order to set the matrix to a translation transformation without post-multiplying 3123 * it, use {@link #translation(Vector3d)}. 3124 * 3125 * @see #translation(Vector3d) 3126 * 3127 * @param offset 3128 * the number of units in x, y and z by which to translate 3129 * @param dest 3130 * will hold the result 3131 * @return dest 3132 */ 3133 public Matrix4x3d translate(Vector3d offset, ref Matrix4x3d dest) { 3134 return translate(offset.x, offset.y, offset.z, dest); 3135 } 3136 3137 /** 3138 * Apply a translation to this matrix by translating by the given number of 3139 * units in x, y and z and store the result in <code>dest</code>. 3140 * <p> 3141 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3142 * matrix, then the new matrix will be <code>M * T</code>. So when 3143 * transforming a vector <code>v</code> with the new matrix by using 3144 * <code>M * T * v</code>, the translation will be applied first! 3145 * <p> 3146 * In order to set the matrix to a translation transformation without post-multiplying 3147 * it, use {@link #translation(double, double, double)}. 3148 * 3149 * @see #translation(double, double, double) 3150 * 3151 * @param x 3152 * the offset to translate in x 3153 * @param y 3154 * the offset to translate in y 3155 * @param z 3156 * the offset to translate in z 3157 * @param dest 3158 * will hold the result 3159 * @return dest 3160 */ 3161 public Matrix4x3d translate(double x, double y, double z, ref Matrix4x3d dest) { 3162 if ((properties & PROPERTY_IDENTITY) != 0) 3163 return dest.translation(x, y, z); 3164 return translateGeneric(x, y, z, dest); 3165 } 3166 private Matrix4x3d translateGeneric(double x, double y, double z, ref Matrix4x3d dest) { 3167 dest.m00 = m00; 3168 dest.m01 = m01; 3169 dest.m02 = m02; 3170 dest.m10 = m10; 3171 dest.m11 = m11; 3172 dest.m12 = m12; 3173 dest.m20 = m20; 3174 dest.m21 = m21; 3175 dest.m22 = m22; 3176 dest.m30 = m00 * x + m10 * y + m20 * z + m30; 3177 dest.m31 = m01 * x + m11 * y + m21 * z + m31; 3178 dest.m32 = m02 * x + m12 * y + m22 * z + m32; 3179 dest.properties = properties & ~(PROPERTY_IDENTITY); 3180 return dest; 3181 } 3182 3183 /** 3184 * Apply a translation to this matrix by translating by the given number of 3185 * units in x, y and z. 3186 * <p> 3187 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3188 * matrix, then the new matrix will be <code>M * T</code>. So when 3189 * transforming a vector <code>v</code> with the new matrix by using 3190 * <code>M * T * v</code>, the translation will be applied first! 3191 * <p> 3192 * In order to set the matrix to a translation transformation without post-multiplying 3193 * it, use {@link #translation(double, double, double)}. 3194 * 3195 * @see #translation(double, double, double) 3196 * 3197 * @param x 3198 * the offset to translate in x 3199 * @param y 3200 * the offset to translate in y 3201 * @param z 3202 * the offset to translate in z 3203 * @return this 3204 */ 3205 ref public Matrix4x3d translate(double x, double y, double z) return { 3206 if ((properties & PROPERTY_IDENTITY) != 0) 3207 return translation(x, y, z); 3208 Matrix4x3d c = this; 3209 c.m30 = c.m00 * x + c.m10 * y + c.m20 * z + c.m30; 3210 c.m31 = c.m01 * x + c.m11 * y + c.m21 * z + c.m31; 3211 c.m32 = c.m02 * x + c.m12 * y + c.m22 * z + c.m32; 3212 c.properties &= ~(PROPERTY_IDENTITY); 3213 return this; 3214 } 3215 3216 3217 /** 3218 * Pre-multiply a translation to this matrix by translating by the given number of 3219 * units in x, y and z. 3220 * <p> 3221 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3222 * matrix, then the new matrix will be <code>T * M</code>. So when 3223 * transforming a vector <code>v</code> with the new matrix by using 3224 * <code>T * M * v</code>, the translation will be applied last! 3225 * <p> 3226 * In order to set the matrix to a translation transformation without pre-multiplying 3227 * it, use {@link #translation(Vector3d)}. 3228 * 3229 * @see #translation(Vector3d) 3230 * 3231 * @param offset 3232 * the number of units in x, y and z by which to translate 3233 * @return this 3234 */ 3235 ref public Matrix4x3d translateLocal(Vector3d offset) return { 3236 return translateLocal(offset.x, offset.y, offset.z); 3237 } 3238 3239 /** 3240 * Pre-multiply a translation to this matrix by translating by the given number of 3241 * units in x, y and z and store the result in <code>dest</code>. 3242 * <p> 3243 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3244 * matrix, then the new matrix will be <code>T * M</code>. So when 3245 * transforming a vector <code>v</code> with the new matrix by using 3246 * <code>T * M * v</code>, the translation will be applied last! 3247 * <p> 3248 * In order to set the matrix to a translation transformation without pre-multiplying 3249 * it, use {@link #translation(Vector3d)}. 3250 * 3251 * @see #translation(Vector3d) 3252 * 3253 * @param offset 3254 * the number of units in x, y and z by which to translate 3255 * @param dest 3256 * will hold the result 3257 * @return dest 3258 */ 3259 public Matrix4x3d translateLocal(Vector3d offset, ref Matrix4x3d dest) { 3260 return translateLocal(offset.x, offset.y, offset.z, dest); 3261 } 3262 3263 /** 3264 * Pre-multiply a translation to this matrix by translating by the given number of 3265 * units in x, y and z and store the result in <code>dest</code>. 3266 * <p> 3267 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3268 * matrix, then the new matrix will be <code>T * M</code>. So when 3269 * transforming a vector <code>v</code> with the new matrix by using 3270 * <code>T * M * v</code>, the translation will be applied last! 3271 * <p> 3272 * In order to set the matrix to a translation transformation without pre-multiplying 3273 * it, use {@link #translation(double, double, double)}. 3274 * 3275 * @see #translation(double, double, double) 3276 * 3277 * @param x 3278 * the offset to translate in x 3279 * @param y 3280 * the offset to translate in y 3281 * @param z 3282 * the offset to translate in z 3283 * @param dest 3284 * will hold the result 3285 * @return dest 3286 */ 3287 public Matrix4x3d translateLocal(double x, double y, double z, ref Matrix4x3d dest) { 3288 dest.m00 = m00; 3289 dest.m01 = m01; 3290 dest.m02 = m02; 3291 dest.m10 = m10; 3292 dest.m11 = m11; 3293 dest.m12 = m12; 3294 dest.m20 = m20; 3295 dest.m21 = m21; 3296 dest.m22 = m22; 3297 dest.m30 = m30 + x; 3298 dest.m31 = m31 + y; 3299 dest.m32 = m32 + z; 3300 dest.properties = properties & ~(PROPERTY_IDENTITY); 3301 return dest; 3302 } 3303 3304 /** 3305 * Pre-multiply a translation to this matrix by translating by the given number of 3306 * units in x, y and z. 3307 * <p> 3308 * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation 3309 * matrix, then the new matrix will be <code>T * M</code>. So when 3310 * transforming a vector <code>v</code> with the new matrix by using 3311 * <code>T * M * v</code>, the translation will be applied last! 3312 * <p> 3313 * In order to set the matrix to a translation transformation without pre-multiplying 3314 * it, use {@link #translation(double, double, double)}. 3315 * 3316 * @see #translation(double, double, double) 3317 * 3318 * @param x 3319 * the offset to translate in x 3320 * @param y 3321 * the offset to translate in y 3322 * @param z 3323 * the offset to translate in z 3324 * @return this 3325 */ 3326 ref public Matrix4x3d translateLocal(double x, double y, double z) return { 3327 translateLocal(x, y, z, this); 3328 return this; 3329 } 3330 3331 public Matrix4x3d rotateX(double ang, ref Matrix4x3d dest) { 3332 if ((properties & PROPERTY_IDENTITY) != 0) 3333 return dest.rotationX(ang); 3334 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3335 double x = m30, y = m31, z = m32; 3336 return dest.rotationX(ang).setTranslation(x, y, z); 3337 } 3338 return rotateXInternal(ang, dest); 3339 } 3340 private Matrix4x3d rotateXInternal(double ang, ref Matrix4x3d dest) { 3341 double sin, cos; 3342 sin = Math.sin(ang); 3343 cos = Math.cosFromSin(sin, ang); 3344 double rm11 = cos; 3345 double rm12 = sin; 3346 double rm21 = -sin; 3347 double rm22 = cos; 3348 3349 // add temporaries for dependent values 3350 double nm10 = m10 * rm11 + m20 * rm12; 3351 double nm11 = m11 * rm11 + m21 * rm12; 3352 double nm12 = m12 * rm11 + m22 * rm12; 3353 // set non-dependent values directly 3354 dest.m20 = m10 * rm21 + m20 * rm22; 3355 dest.m21 = m11 * rm21 + m21 * rm22; 3356 dest.m22 = m12 * rm21 + m22 * rm22; 3357 // set other values 3358 dest.m10 = nm10; 3359 dest.m11 = nm11; 3360 dest.m12 = nm12; 3361 dest.m00 = m00; 3362 dest.m01 = m01; 3363 dest.m02 = m02; 3364 dest.m30 = m30; 3365 dest.m31 = m31; 3366 dest.m32 = m32; 3367 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3368 return dest; 3369 } 3370 3371 /** 3372 * Apply rotation about the X axis to this matrix by rotating the given amount of radians. 3373 * <p> 3374 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3375 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3376 * When used with a left-handed coordinate system, the rotation is clockwise. 3377 * <p> 3378 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3379 * then the new matrix will be <code>M * R</code>. So when transforming a 3380 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3381 * rotation will be applied first! 3382 * <p> 3383 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 3384 * 3385 * @param ang 3386 * the angle in radians 3387 * @return this 3388 */ 3389 ref public Matrix4x3d rotateX(double ang) return { 3390 rotateX(ang, this); 3391 return this; 3392 } 3393 3394 public Matrix4x3d rotateY(double ang, ref Matrix4x3d dest) { 3395 if ((properties & PROPERTY_IDENTITY) != 0) 3396 return dest.rotationY(ang); 3397 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3398 double x = m30, y = m31, z = m32; 3399 return dest.rotationY(ang).setTranslation(x, y, z); 3400 } 3401 return rotateYInternal(ang, dest); 3402 } 3403 private Matrix4x3d rotateYInternal(double ang, ref Matrix4x3d dest) { 3404 double sin, cos; 3405 sin = Math.sin(ang); 3406 cos = Math.cosFromSin(sin, ang); 3407 double rm00 = cos; 3408 double rm02 = -sin; 3409 double rm20 = sin; 3410 double rm22 = cos; 3411 3412 // add temporaries for dependent values 3413 double nm00 = m00 * rm00 + m20 * rm02; 3414 double nm01 = m01 * rm00 + m21 * rm02; 3415 double nm02 = m02 * rm00 + m22 * rm02; 3416 // set non-dependent values directly 3417 dest.m20 = m00 * rm20 + m20 * rm22; 3418 dest.m21 = m01 * rm20 + m21 * rm22; 3419 dest.m22 = m02 * rm20 + m22 * rm22; 3420 // set other values 3421 dest.m00 = nm00; 3422 dest.m01 = nm01; 3423 dest.m02 = nm02; 3424 dest.m10 = m10; 3425 dest.m11 = m11; 3426 dest.m12 = m12; 3427 dest.m30 = m30; 3428 dest.m31 = m31; 3429 dest.m32 = m32; 3430 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3431 return dest; 3432 } 3433 3434 /** 3435 * Apply rotation about the Y axis to this matrix by rotating the given amount of radians. 3436 * <p> 3437 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3438 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3439 * When used with a left-handed coordinate system, the rotation is clockwise. 3440 * <p> 3441 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3442 * then the new matrix will be <code>M * R</code>. So when transforming a 3443 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3444 * rotation will be applied first! 3445 * <p> 3446 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 3447 * 3448 * @param ang 3449 * the angle in radians 3450 * @return this 3451 */ 3452 ref public Matrix4x3d rotateY(double ang) return { 3453 rotateY(ang, this); 3454 return this; 3455 } 3456 3457 public Matrix4x3d rotateZ(double ang, ref Matrix4x3d dest) { 3458 if ((properties & PROPERTY_IDENTITY) != 0) 3459 return dest.rotationZ(ang); 3460 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3461 double x = m30, y = m31, z = m32; 3462 return dest.rotationZ(ang).setTranslation(x, y, z); 3463 } 3464 return rotateZInternal(ang, dest); 3465 } 3466 private Matrix4x3d rotateZInternal(double ang, ref Matrix4x3d dest) { 3467 double sin, cos; 3468 sin = Math.sin(ang); 3469 cos = Math.cosFromSin(sin, ang); 3470 double rm00 = cos; 3471 double rm01 = sin; 3472 double rm10 = -sin; 3473 double rm11 = cos; 3474 3475 // add temporaries for dependent values 3476 double nm00 = m00 * rm00 + m10 * rm01; 3477 double nm01 = m01 * rm00 + m11 * rm01; 3478 double nm02 = m02 * rm00 + m12 * rm01; 3479 // set non-dependent values directly 3480 dest.m10 = m00 * rm10 + m10 * rm11; 3481 dest.m11 = m01 * rm10 + m11 * rm11; 3482 dest.m12 = m02 * rm10 + m12 * rm11; 3483 // set other values 3484 dest.m00 = nm00; 3485 dest.m01 = nm01; 3486 dest.m02 = nm02; 3487 dest.m20 = m20; 3488 dest.m21 = m21; 3489 dest.m22 = m22; 3490 dest.m30 = m30; 3491 dest.m31 = m31; 3492 dest.m32 = m32; 3493 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3494 return dest; 3495 } 3496 3497 /** 3498 * Apply rotation about the Z axis to this matrix by rotating the given amount of radians. 3499 * <p> 3500 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3501 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3502 * When used with a left-handed coordinate system, the rotation is clockwise. 3503 * <p> 3504 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3505 * then the new matrix will be <code>M * R</code>. So when transforming a 3506 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3507 * rotation will be applied first! 3508 * <p> 3509 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations">http://en.wikipedia.org</a> 3510 * 3511 * @param ang 3512 * the angle in radians 3513 * @return this 3514 */ 3515 ref public Matrix4x3d rotateZ(double ang) return { 3516 rotateZ(ang, this); 3517 return this; 3518 } 3519 3520 /** 3521 * Apply rotation of <code>angles.x</code> radians about the X axis, followed by a rotation of <code>angles.y</code> radians about the Y axis and 3522 * followed by a rotation of <code>angles.z</code> radians about the Z axis. 3523 * <p> 3524 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3525 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3526 * When used with a left-handed coordinate system, the rotation is clockwise. 3527 * <p> 3528 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3529 * then the new matrix will be <code>M * R</code>. So when transforming a 3530 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3531 * rotation will be applied first! 3532 * <p> 3533 * This method is equivalent to calling: <code>rotateX(angles.x).rotateY(angles.y).rotateZ(angles.z)</code> 3534 * 3535 * @param angles 3536 * the Euler angles 3537 * @return this 3538 */ 3539 ref public Matrix4x3d rotateXYZ(Vector3d angles) return { 3540 return rotateXYZ(angles.x, angles.y, angles.z); 3541 } 3542 3543 /** 3544 * Apply rotation of <code>angleX</code> radians about the X axis, followed by a rotation of <code>angleY</code> radians about the Y axis and 3545 * followed by a rotation of <code>angleZ</code> radians about the Z axis. 3546 * <p> 3547 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3548 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3549 * When used with a left-handed coordinate system, the rotation is clockwise. 3550 * <p> 3551 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3552 * then the new matrix will be <code>M * R</code>. So when transforming a 3553 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3554 * rotation will be applied first! 3555 * <p> 3556 * This method is equivalent to calling: <code>rotateX(angleX).rotateY(angleY).rotateZ(angleZ)</code> 3557 * 3558 * @param angleX 3559 * the angle to rotate about X 3560 * @param angleY 3561 * the angle to rotate about Y 3562 * @param angleZ 3563 * the angle to rotate about Z 3564 * @return this 3565 */ 3566 ref public Matrix4x3d rotateXYZ(double angleX, double angleY, double angleZ) return { 3567 rotateXYZ(angleX, angleY, angleZ, this); 3568 return this; 3569 } 3570 3571 public Matrix4x3d rotateXYZ(double angleX, double angleY, double angleZ, ref Matrix4x3d dest) { 3572 if ((properties & PROPERTY_IDENTITY) != 0) 3573 return dest.rotationXYZ(angleX, angleY, angleZ); 3574 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3575 double tx = m30, ty = m31, tz = m32; 3576 return dest.rotationXYZ(angleX, angleY, angleZ).setTranslation(tx, ty, tz); 3577 } 3578 return rotateXYZInternal(angleX, angleY, angleZ, dest); 3579 } 3580 private Matrix4x3d rotateXYZInternal(double angleX, double angleY, double angleZ, ref Matrix4x3d dest) { 3581 double sinX = Math.sin(angleX); 3582 double cosX = Math.cosFromSin(sinX, angleX); 3583 double sinY = Math.sin(angleY); 3584 double cosY = Math.cosFromSin(sinY, angleY); 3585 double sinZ = Math.sin(angleZ); 3586 double cosZ = Math.cosFromSin(sinZ, angleZ); 3587 double m_sinX = -sinX; 3588 double m_sinY = -sinY; 3589 double m_sinZ = -sinZ; 3590 3591 // rotateX 3592 double nm10 = m10 * cosX + m20 * sinX; 3593 double nm11 = m11 * cosX + m21 * sinX; 3594 double nm12 = m12 * cosX + m22 * sinX; 3595 double nm20 = m10 * m_sinX + m20 * cosX; 3596 double nm21 = m11 * m_sinX + m21 * cosX; 3597 double nm22 = m12 * m_sinX + m22 * cosX; 3598 // rotateY 3599 double nm00 = m00 * cosY + nm20 * m_sinY; 3600 double nm01 = m01 * cosY + nm21 * m_sinY; 3601 double nm02 = m02 * cosY + nm22 * m_sinY; 3602 dest.m20 = m00 * sinY + nm20 * cosY; 3603 dest.m21 = m01 * sinY + nm21 * cosY; 3604 dest.m22 = m02 * sinY + nm22 * cosY; 3605 // rotateZ 3606 dest.m00 = nm00 * cosZ + nm10 * sinZ; 3607 dest.m01 = nm01 * cosZ + nm11 * sinZ; 3608 dest.m02 = nm02 * cosZ + nm12 * sinZ; 3609 dest.m10 = nm00 * m_sinZ + nm10 * cosZ; 3610 dest.m11 = nm01 * m_sinZ + nm11 * cosZ; 3611 dest.m12 = nm02 * m_sinZ + nm12 * cosZ; 3612 // copy last column from 'this' 3613 dest.m30 = m30; 3614 dest.m31 = m31; 3615 dest.m32 = m32; 3616 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3617 return dest; 3618 } 3619 3620 /** 3621 * Apply rotation of <code>angles.z</code> radians about the Z axis, followed by a rotation of <code>angles.y</code> radians about the Y axis and 3622 * followed by a rotation of <code>angles.x</code> radians about the X axis. 3623 * <p> 3624 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3625 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3626 * When used with a left-handed coordinate system, the rotation is clockwise. 3627 * <p> 3628 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3629 * then the new matrix will be <code>M * R</code>. So when transforming a 3630 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3631 * rotation will be applied first! 3632 * <p> 3633 * This method is equivalent to calling: <code>rotateZ(angles.z).rotateY(angles.y).rotateX(angles.x)</code> 3634 * 3635 * @param angles 3636 * the Euler angles 3637 * @return this 3638 */ 3639 ref public Matrix4x3d rotateZYX(Vector3d angles) return { 3640 return rotateZYX(angles.z, angles.y, angles.x); 3641 } 3642 3643 /** 3644 * Apply rotation of <code>angleZ</code> radians about the Z axis, followed by a rotation of <code>angleY</code> radians about the Y axis and 3645 * followed by a rotation of <code>angleX</code> radians about the X axis. 3646 * <p> 3647 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3648 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3649 * When used with a left-handed coordinate system, the rotation is clockwise. 3650 * <p> 3651 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3652 * then the new matrix will be <code>M * R</code>. So when transforming a 3653 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3654 * rotation will be applied first! 3655 * <p> 3656 * This method is equivalent to calling: <code>rotateZ(angleZ).rotateY(angleY).rotateX(angleX)</code> 3657 * 3658 * @param angleZ 3659 * the angle to rotate about Z 3660 * @param angleY 3661 * the angle to rotate about Y 3662 * @param angleX 3663 * the angle to rotate about X 3664 * @return this 3665 */ 3666 ref public Matrix4x3d rotateZYX(double angleZ, double angleY, double angleX) return { 3667 rotateZYX(angleZ, angleY, angleX, this); 3668 return this; 3669 } 3670 3671 public Matrix4x3d rotateZYX(double angleZ, double angleY, double angleX, ref Matrix4x3d dest) { 3672 if ((properties & PROPERTY_IDENTITY) != 0) 3673 return dest.rotationZYX(angleZ, angleY, angleX); 3674 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3675 double tx = m30, ty = m31, tz = m32; 3676 return dest.rotationZYX(angleZ, angleY, angleX).setTranslation(tx, ty, tz); 3677 } 3678 return rotateZYXInternal(angleZ, angleY, angleX, dest); 3679 } 3680 private Matrix4x3d rotateZYXInternal(double angleZ, double angleY, double angleX, ref Matrix4x3d dest) { 3681 double sinX = Math.sin(angleX); 3682 double cosX = Math.cosFromSin(sinX, angleX); 3683 double sinY = Math.sin(angleY); 3684 double cosY = Math.cosFromSin(sinY, angleY); 3685 double sinZ = Math.sin(angleZ); 3686 double cosZ = Math.cosFromSin(sinZ, angleZ); 3687 double m_sinZ = -sinZ; 3688 double m_sinY = -sinY; 3689 double m_sinX = -sinX; 3690 3691 // rotateZ 3692 double nm00 = m00 * cosZ + m10 * sinZ; 3693 double nm01 = m01 * cosZ + m11 * sinZ; 3694 double nm02 = m02 * cosZ + m12 * sinZ; 3695 double nm10 = m00 * m_sinZ + m10 * cosZ; 3696 double nm11 = m01 * m_sinZ + m11 * cosZ; 3697 double nm12 = m02 * m_sinZ + m12 * cosZ; 3698 // rotateY 3699 double nm20 = nm00 * sinY + m20 * cosY; 3700 double nm21 = nm01 * sinY + m21 * cosY; 3701 double nm22 = nm02 * sinY + m22 * cosY; 3702 dest.m00 = nm00 * cosY + m20 * m_sinY; 3703 dest.m01 = nm01 * cosY + m21 * m_sinY; 3704 dest.m02 = nm02 * cosY + m22 * m_sinY; 3705 // rotateX 3706 dest.m10 = nm10 * cosX + nm20 * sinX; 3707 dest.m11 = nm11 * cosX + nm21 * sinX; 3708 dest.m12 = nm12 * cosX + nm22 * sinX; 3709 dest.m20 = nm10 * m_sinX + nm20 * cosX; 3710 dest.m21 = nm11 * m_sinX + nm21 * cosX; 3711 dest.m22 = nm12 * m_sinX + nm22 * cosX; 3712 // copy last column from 'this' 3713 dest.m30 = m30; 3714 dest.m31 = m31; 3715 dest.m32 = m32; 3716 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3717 return dest; 3718 } 3719 3720 /** 3721 * Apply rotation of <code>angles.y</code> radians about the Y axis, followed by a rotation of <code>angles.x</code> radians about the X axis and 3722 * followed by a rotation of <code>angles.z</code> radians about the Z axis. 3723 * <p> 3724 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3725 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3726 * When used with a left-handed coordinate system, the rotation is clockwise. 3727 * <p> 3728 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3729 * then the new matrix will be <code>M * R</code>. So when transforming a 3730 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3731 * rotation will be applied first! 3732 * <p> 3733 * This method is equivalent to calling: <code>rotateY(angles.y).rotateX(angles.x).rotateZ(angles.z)</code> 3734 * 3735 * @param angles 3736 * the Euler angles 3737 * @return this 3738 */ 3739 ref public Matrix4x3d rotateYXZ(Vector3d angles) return { 3740 return rotateYXZ(angles.y, angles.x, angles.z); 3741 } 3742 3743 /** 3744 * Apply rotation of <code>angleY</code> radians about the Y axis, followed by a rotation of <code>angleX</code> radians about the X axis and 3745 * followed by a rotation of <code>angleZ</code> radians about the Z axis. 3746 * <p> 3747 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3748 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3749 * When used with a left-handed coordinate system, the rotation is clockwise. 3750 * <p> 3751 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 3752 * then the new matrix will be <code>M * R</code>. So when transforming a 3753 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 3754 * rotation will be applied first! 3755 * <p> 3756 * This method is equivalent to calling: <code>rotateY(angleY).rotateX(angleX).rotateZ(angleZ)</code> 3757 * 3758 * @param angleY 3759 * the angle to rotate about Y 3760 * @param angleX 3761 * the angle to rotate about X 3762 * @param angleZ 3763 * the angle to rotate about Z 3764 * @return this 3765 */ 3766 ref public Matrix4x3d rotateYXZ(double angleY, double angleX, double angleZ) return { 3767 rotateYXZ(angleY, angleX, angleZ, this); 3768 return this; 3769 } 3770 3771 public Matrix4x3d rotateYXZ(double angleY, double angleX, double angleZ, ref Matrix4x3d dest) { 3772 if ((properties & PROPERTY_IDENTITY) != 0) 3773 return dest.rotationYXZ(angleY, angleX, angleZ); 3774 else if ((properties & PROPERTY_TRANSLATION) != 0) { 3775 double tx = m30, ty = m31, tz = m32; 3776 return dest.rotationYXZ(angleY, angleX, angleZ).setTranslation(tx, ty, tz); 3777 } 3778 return rotateYXZInternal(angleY, angleX, angleZ, dest); 3779 } 3780 private Matrix4x3d rotateYXZInternal(double angleY, double angleX, double angleZ, ref Matrix4x3d dest) { 3781 double sinX = Math.sin(angleX); 3782 double cosX = Math.cosFromSin(sinX, angleX); 3783 double sinY = Math.sin(angleY); 3784 double cosY = Math.cosFromSin(sinY, angleY); 3785 double sinZ = Math.sin(angleZ); 3786 double cosZ = Math.cosFromSin(sinZ, angleZ); 3787 double m_sinY = -sinY; 3788 double m_sinX = -sinX; 3789 double m_sinZ = -sinZ; 3790 3791 // rotateY 3792 double nm20 = m00 * sinY + m20 * cosY; 3793 double nm21 = m01 * sinY + m21 * cosY; 3794 double nm22 = m02 * sinY + m22 * cosY; 3795 double nm00 = m00 * cosY + m20 * m_sinY; 3796 double nm01 = m01 * cosY + m21 * m_sinY; 3797 double nm02 = m02 * cosY + m22 * m_sinY; 3798 // rotateX 3799 double nm10 = m10 * cosX + nm20 * sinX; 3800 double nm11 = m11 * cosX + nm21 * sinX; 3801 double nm12 = m12 * cosX + nm22 * sinX; 3802 dest.m20 = m10 * m_sinX + nm20 * cosX; 3803 dest.m21 = m11 * m_sinX + nm21 * cosX; 3804 dest.m22 = m12 * m_sinX + nm22 * cosX; 3805 // rotateZ 3806 dest.m00 = nm00 * cosZ + nm10 * sinZ; 3807 dest.m01 = nm01 * cosZ + nm11 * sinZ; 3808 dest.m02 = nm02 * cosZ + nm12 * sinZ; 3809 dest.m10 = nm00 * m_sinZ + nm10 * cosZ; 3810 dest.m11 = nm01 * m_sinZ + nm11 * cosZ; 3811 dest.m12 = nm02 * m_sinZ + nm12 * cosZ; 3812 // copy last column from 'this' 3813 dest.m30 = m30; 3814 dest.m31 = m31; 3815 dest.m32 = m32; 3816 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 3817 return dest; 3818 } 3819 3820 3821 /** 3822 * Set this matrix to a rotation transformation using the given {@link AxisAngle4d}. 3823 * <p> 3824 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3825 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3826 * When used with a left-handed coordinate system, the rotation is clockwise. 3827 * <p> 3828 * The resulting matrix can be multiplied against another transformation 3829 * matrix to obtain an additional rotation. 3830 * <p> 3831 * In order to apply the rotation transformation to an existing transformation, 3832 * use {@link #rotate(AxisAngle4d) rotate()} instead. 3833 * <p> 3834 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 3835 * 3836 * @see #rotate(AxisAngle4d) 3837 * 3838 * @param angleAxis 3839 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 3840 * @return this 3841 */ 3842 ref public Matrix4x3d rotation(AxisAngle4d angleAxis) return { 3843 return rotation(angleAxis.angle, angleAxis.x, angleAxis.y, angleAxis.z); 3844 } 3845 3846 /** 3847 * Set this matrix to the rotation - and possibly scaling - transformation of the given {@link Quaterniond}. 3848 * <p> 3849 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3850 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3851 * When used with a left-handed coordinate system, the rotation is clockwise. 3852 * <p> 3853 * The resulting matrix can be multiplied against another transformation 3854 * matrix to obtain an additional rotation. 3855 * <p> 3856 * In order to apply the rotation transformation to an existing transformation, 3857 * use {@link #rotate(Quaterniond) rotate()} instead. 3858 * <p> 3859 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 3860 * 3861 * @see #rotate(Quaterniond) 3862 * 3863 * @param quat 3864 * the {@link Quaterniond} 3865 * @return this 3866 */ 3867 ref public Matrix4x3d rotation(Quaterniond quat) return { 3868 double w2 = quat.w * quat.w; 3869 double x2 = quat.x * quat.x; 3870 double y2 = quat.y * quat.y; 3871 double z2 = quat.z * quat.z; 3872 double zw = quat.z * quat.w, dzw = zw + zw; 3873 double xy = quat.x * quat.y, dxy = xy + xy; 3874 double xz = quat.x * quat.z, dxz = xz + xz; 3875 double yw = quat.y * quat.w, dyw = yw + yw; 3876 double yz = quat.y * quat.z, dyz = yz + yz; 3877 double xw = quat.x * quat.w, dxw = xw + xw; 3878 _m00(w2 + x2 - z2 - y2); 3879 _m01(dxy + dzw); 3880 _m02(dxz - dyw); 3881 _m10(dxy - dzw); 3882 _m11(y2 - z2 + w2 - x2); 3883 _m12(dyz + dxw); 3884 _m20(dyw + dxz); 3885 _m21(dyz - dxw); 3886 _m22(z2 - y2 - x2 + w2); 3887 _m30(0.0); 3888 _m31(0.0); 3889 _m32(0.0); 3890 properties = PROPERTY_ORTHONORMAL; 3891 return this; 3892 } 3893 3894 3895 /** 3896 * Set <code>this</code> matrix to <code>T * R * S</code>, where <code>T</code> is a translation by the given <code>(tx, ty, tz)</code>, 3897 * <code>R</code> is a rotation transformation specified by the quaternion <code>(qx, qy, qz, qw)</code>, and <code>S</code> is a scaling transformation 3898 * which scales the three axes x, y and z by <code>(sx, sy, sz)</code>. 3899 * <p> 3900 * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and 3901 * at last the translation. 3902 * <p> 3903 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3904 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3905 * When used with a left-handed coordinate system, the rotation is clockwise. 3906 * <p> 3907 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat).scale(sx, sy, sz)</code> 3908 * 3909 * @see #translation(double, double, double) 3910 * @see #rotate(Quaterniond) 3911 * @see #scale(double, double, double) 3912 * 3913 * @param tx 3914 * the number of units by which to translate the x-component 3915 * @param ty 3916 * the number of units by which to translate the y-component 3917 * @param tz 3918 * the number of units by which to translate the z-component 3919 * @param qx 3920 * the x-coordinate of the vector part of the quaternion 3921 * @param qy 3922 * the y-coordinate of the vector part of the quaternion 3923 * @param qz 3924 * the z-coordinate of the vector part of the quaternion 3925 * @param qw 3926 * the scalar part of the quaternion 3927 * @param sx 3928 * the scaling factor for the x-axis 3929 * @param sy 3930 * the scaling factor for the y-axis 3931 * @param sz 3932 * the scaling factor for the z-axis 3933 * @return this 3934 */ 3935 ref public Matrix4x3d translationRotateScale(double tx, double ty, double tz, 3936 double qx, double qy, double qz, double qw, 3937 double sx, double sy, double sz) return { 3938 double dqx = qx + qx, dqy = qy + qy, dqz = qz + qz; 3939 double q00 = dqx * qx; 3940 double q11 = dqy * qy; 3941 double q22 = dqz * qz; 3942 double q01 = dqx * qy; 3943 double q02 = dqx * qz; 3944 double q03 = dqx * qw; 3945 double q12 = dqy * qz; 3946 double q13 = dqy * qw; 3947 double q23 = dqz * qw; 3948 m00 = sx - (q11 + q22) * sx; 3949 m01 = (q01 + q23) * sx; 3950 m02 = (q02 - q13) * sx; 3951 m10 = (q01 - q23) * sy; 3952 m11 = sy - (q22 + q00) * sy; 3953 m12 = (q12 + q03) * sy; 3954 m20 = (q02 + q13) * sz; 3955 m21 = (q12 - q03) * sz; 3956 m22 = sz - (q11 + q00) * sz; 3957 m30 = tx; 3958 m31 = ty; 3959 m32 = tz; 3960 properties = 0; 3961 return this; 3962 } 3963 3964 /** 3965 * Set <code>this</code> matrix to <code>T * R * S</code>, where <code>T</code> is the given <code>translation</code>, 3966 * <code>R</code> is a rotation transformation specified by the given quaternion, and <code>S</code> is a scaling transformation 3967 * which scales the axes by <code>scale</code>. 3968 * <p> 3969 * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and 3970 * at last the translation. 3971 * <p> 3972 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 3973 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 3974 * When used with a left-handed coordinate system, the rotation is clockwise. 3975 * <p> 3976 * This method is equivalent to calling: <code>translation(translation).rotate(quat).scale(scale)</code> 3977 * 3978 * @see #translation(Vector3d) 3979 * @see #rotate(Quaterniond) 3980 * 3981 * @param translation 3982 * the translation 3983 * @param quat 3984 * the quaternion representing a rotation 3985 * @param scale 3986 * the scaling factors 3987 * @return this 3988 */ 3989 ref public Matrix4x3d translationRotateScale(Vector3d translation, 3990 Quaterniond quat, 3991 Vector3d scale) return { 3992 return translationRotateScale(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z, 3993 quat.w, scale.x, scale.y, scale.z); 3994 } 3995 3996 /** 3997 * Set <code>this</code> matrix to <code>T * R * S * M</code>, where <code>T</code> is a translation by the given <code>(tx, ty, tz)</code>, 3998 * <code>R</code> is a rotation transformation specified by the quaternion <code>(qx, qy, qz, qw)</code>, <code>S</code> is a scaling transformation 3999 * which scales the three axes x, y and z by <code>(sx, sy, sz)</code>. 4000 * <p> 4001 * When transforming a vector by the resulting matrix the transformation described by <code>M</code> will be applied first, then the scaling, then rotation and 4002 * at last the translation. 4003 * <p> 4004 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4005 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4006 * When used with a left-handed coordinate system, the rotation is clockwise. 4007 * <p> 4008 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat).scale(sx, sy, sz).mul(m)</code> 4009 * 4010 * @see #translation(double, double, double) 4011 * @see #rotate(Quaterniond) 4012 * @see #scale(double, double, double) 4013 * @see #mul(Matrix4x3d) 4014 * 4015 * @param tx 4016 * the number of units by which to translate the x-component 4017 * @param ty 4018 * the number of units by which to translate the y-component 4019 * @param tz 4020 * the number of units by which to translate the z-component 4021 * @param qx 4022 * the x-coordinate of the vector part of the quaternion 4023 * @param qy 4024 * the y-coordinate of the vector part of the quaternion 4025 * @param qz 4026 * the z-coordinate of the vector part of the quaternion 4027 * @param qw 4028 * the scalar part of the quaternion 4029 * @param sx 4030 * the scaling factor for the x-axis 4031 * @param sy 4032 * the scaling factor for the y-axis 4033 * @param sz 4034 * the scaling factor for the z-axis 4035 * @param m 4036 * the matrix to multiply by 4037 * @return this 4038 */ 4039 ref public Matrix4x3d translationRotateScaleMul( 4040 double tx, double ty, double tz, 4041 double qx, double qy, double qz, double qw, 4042 double sx, double sy, double sz, 4043 Matrix4x3d m) return { 4044 double dqx = qx + qx; 4045 double dqy = qy + qy; 4046 double dqz = qz + qz; 4047 double q00 = dqx * qx; 4048 double q11 = dqy * qy; 4049 double q22 = dqz * qz; 4050 double q01 = dqx * qy; 4051 double q02 = dqx * qz; 4052 double q03 = dqx * qw; 4053 double q12 = dqy * qz; 4054 double q13 = dqy * qw; 4055 double q23 = dqz * qw; 4056 double nm00 = sx - (q11 + q22) * sx; 4057 double nm01 = (q01 + q23) * sx; 4058 double nm02 = (q02 - q13) * sx; 4059 double nm10 = (q01 - q23) * sy; 4060 double nm11 = sy - (q22 + q00) * sy; 4061 double nm12 = (q12 + q03) * sy; 4062 double nm20 = (q02 + q13) * sz; 4063 double nm21 = (q12 - q03) * sz; 4064 double nm22 = sz - (q11 + q00) * sz; 4065 double __m00 = nm00 * m.m00 + nm10 * m.m01 + nm20 * m.m02; 4066 double __m01 = nm01 * m.m00 + nm11 * m.m01 + nm21 * m.m02; 4067 m02 = nm02 * m.m00 + nm12 * m.m01 + nm22 * m.m02; 4068 this.m00 = __m00; 4069 this.m01 = __m01; 4070 double __m10 = nm00 * m.m10 + nm10 * m.m11 + nm20 * m.m12; 4071 double __m11 = nm01 * m.m10 + nm11 * m.m11 + nm21 * m.m12; 4072 m12 = nm02 * m.m10 + nm12 * m.m11 + nm22 * m.m12; 4073 this.m10 = __m10; 4074 this.m11 = __m11; 4075 double __m20 = nm00 * m.m20 + nm10 * m.m21 + nm20 * m.m22; 4076 double __m21 = nm01 * m.m20 + nm11 * m.m21 + nm21 * m.m22; 4077 m22 = nm02 * m.m20 + nm12 * m.m21 + nm22 * m.m22; 4078 this.m20 = __m20; 4079 this.m21 = __m21; 4080 double __m30 = nm00 * m.m30 + nm10 * m.m31 + nm20 * m.m32 + tx; 4081 double __m31 = nm01 * m.m30 + nm11 * m.m31 + nm21 * m.m32 + ty; 4082 m32 = nm02 * m.m30 + nm12 * m.m31 + nm22 * m.m32 + tz; 4083 this.m30 = __m30; 4084 this.m31 = __m31; 4085 properties = 0; 4086 return this; 4087 } 4088 4089 /** 4090 * Set <code>this</code> matrix to <code>T * R * S * M</code>, where <code>T</code> is the given <code>translation</code>, 4091 * <code>R</code> is a rotation transformation specified by the given quaternion, <code>S</code> is a scaling transformation 4092 * which scales the axes by <code>scale</code>. 4093 * <p> 4094 * When transforming a vector by the resulting matrix the transformation described by <code>M</code> will be applied first, then the scaling, then rotation and 4095 * at last the translation. 4096 * <p> 4097 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4098 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4099 * When used with a left-handed coordinate system, the rotation is clockwise. 4100 * <p> 4101 * This method is equivalent to calling: <code>translation(translation).rotate(quat).scale(scale).mul(m)</code> 4102 * 4103 * @see #translation(Vector3d) 4104 * @see #rotate(Quaterniond) 4105 * @see #mul(Matrix4x3d) 4106 * 4107 * @param translation 4108 * the translation 4109 * @param quat 4110 * the quaternion representing a rotation 4111 * @param scale 4112 * the scaling factors 4113 * @param m 4114 * the matrix to multiply by 4115 * @return this 4116 */ 4117 ref public Matrix4x3d translationRotateScaleMul(Vector3d translation, Quaterniond quat, Vector3d scale, Matrix4x3d m) return { 4118 return translationRotateScaleMul(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z 4119 , quat.w, scale.x, scale.y, scale.z, m); 4120 } 4121 4122 /** 4123 * Set <code>this</code> matrix to <code>T * R</code>, where <code>T</code> is a translation by the given <code>(tx, ty, tz)</code> and 4124 * <code>R</code> is a rotation transformation specified by the given quaternion. 4125 * <p> 4126 * When transforming a vector by the resulting matrix the rotation transformation will be applied first and then the translation. 4127 * <p> 4128 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4129 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4130 * When used with a left-handed coordinate system, the rotation is clockwise. 4131 * <p> 4132 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat)</code> 4133 * 4134 * @see #translation(double, double, double) 4135 * @see #rotate(Quaterniond) 4136 * 4137 * @param tx 4138 * the number of units by which to translate the x-component 4139 * @param ty 4140 * the number of units by which to translate the y-component 4141 * @param tz 4142 * the number of units by which to translate the z-component 4143 * @param quat 4144 * the quaternion representing a rotation 4145 * @return this 4146 */ 4147 ref public Matrix4x3d translationRotate(double tx, double ty, double tz, Quaterniond quat) return { 4148 double dqx = quat.x + quat.x, dqy = quat.y + quat.y, dqz = quat.z + quat.z; 4149 double q00 = dqx * quat.x; 4150 double q11 = dqy * quat.y; 4151 double q22 = dqz * quat.z; 4152 double q01 = dqx * quat.y; 4153 double q02 = dqx * quat.z; 4154 double q03 = dqx * quat.w; 4155 double q12 = dqy * quat.z; 4156 double q13 = dqy * quat.w; 4157 double q23 = dqz * quat.w; 4158 m00 = 1.0 - (q11 + q22); 4159 m01 = q01 + q23; 4160 m02 = q02 - q13; 4161 m10 = q01 - q23; 4162 m11 = 1.0 - (q22 + q00); 4163 m12 = q12 + q03; 4164 m20 = q02 + q13; 4165 m21 = q12 - q03; 4166 m22 = 1.0 - (q11 + q00); 4167 m30 = tx; 4168 m31 = ty; 4169 m32 = tz; 4170 properties = PROPERTY_ORTHONORMAL; 4171 return this; 4172 } 4173 4174 /** 4175 * Set <code>this</code> matrix to <code>T * R</code>, where <code>T</code> is a translation by the given <code>(tx, ty, tz)</code> and 4176 * <code>R</code> is a rotation - and possibly scaling - transformation specified by the quaternion <code>(qx, qy, qz, qw)</code>. 4177 * <p> 4178 * When transforming a vector by the resulting matrix the rotation - and possibly scaling - transformation will be applied first and then the translation. 4179 * <p> 4180 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4181 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4182 * When used with a left-handed coordinate system, the rotation is clockwise. 4183 * <p> 4184 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat)</code> 4185 * 4186 * @see #translation(double, double, double) 4187 * @see #rotate(Quaterniond) 4188 * 4189 * @param tx 4190 * the number of units by which to translate the x-component 4191 * @param ty 4192 * the number of units by which to translate the y-component 4193 * @param tz 4194 * the number of units by which to translate the z-component 4195 * @param qx 4196 * the x-coordinate of the vector part of the quaternion 4197 * @param qy 4198 * the y-coordinate of the vector part of the quaternion 4199 * @param qz 4200 * the z-coordinate of the vector part of the quaternion 4201 * @param qw 4202 * the scalar part of the quaternion 4203 * @return this 4204 */ 4205 ref public Matrix4x3d translationRotate(double tx, double ty, double tz, double qx, double qy, double qz, double qw) return { 4206 double w2 = qw * qw; 4207 double x2 = qx * qx; 4208 double y2 = qy * qy; 4209 double z2 = qz * qz; 4210 double zw = qz * qw; 4211 double xy = qx * qy; 4212 double xz = qx * qz; 4213 double yw = qy * qw; 4214 double yz = qy * qz; 4215 double xw = qx * qw; 4216 this.m00 = w2 + x2 - z2 - y2; 4217 this.m01 = xy + zw + zw + xy; 4218 this.m02 = xz - yw + xz - yw; 4219 this.m10 = -zw + xy - zw + xy; 4220 this.m11 = y2 - z2 + w2 - x2; 4221 this.m12 = yz + yz + xw + xw; 4222 this.m20 = yw + xz + xz + yw; 4223 this.m21 = yz + yz - xw - xw; 4224 this.m22 = z2 - y2 - x2 + w2; 4225 this.m30 = tx; 4226 this.m31 = ty; 4227 this.m32 = tz; 4228 this.properties = PROPERTY_ORTHONORMAL; 4229 return this; 4230 } 4231 4232 /** 4233 * Set <code>this</code> matrix to <code>T * R</code>, where <code>T</code> is the given <code>translation</code> and 4234 * <code>R</code> is a rotation transformation specified by the given quaternion. 4235 * <p> 4236 * When transforming a vector by the resulting matrix the scaling transformation will be applied first, then the rotation and 4237 * at last the translation. 4238 * <p> 4239 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4240 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4241 * When used with a left-handed coordinate system, the rotation is clockwise. 4242 * <p> 4243 * This method is equivalent to calling: <code>translation(translation).rotate(quat)</code> 4244 * 4245 * @see #translation(Vector3d) 4246 * @see #rotate(Quaterniond) 4247 * 4248 * @param translation 4249 * the translation 4250 * @param quat 4251 * the quaternion representing a rotation 4252 * @return this 4253 */ 4254 ref public Matrix4x3d translationRotate(Vector3d translation, 4255 Quaterniond quat) return { 4256 return translationRotate(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z, quat.w); 4257 } 4258 4259 /** 4260 * Set <code>this</code> matrix to <code>T * R * M</code>, where <code>T</code> is a translation by the given <code>(tx, ty, tz)</code>, 4261 * <code>R</code> is a rotation - and possibly scaling - transformation specified by the quaternion <code>(qx, qy, qz, qw)</code> and <code>M</code> is the given matrix <code>mat</code> 4262 * <p> 4263 * When transforming a vector by the resulting matrix the transformation described by <code>M</code> will be applied first, then the scaling, then rotation and 4264 * at last the translation. 4265 * <p> 4266 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4267 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4268 * When used with a left-handed coordinate system, the rotation is clockwise. 4269 * <p> 4270 * This method is equivalent to calling: <code>translation(tx, ty, tz).rotate(quat).mul(mat)</code> 4271 * 4272 * @see #translation(double, double, double) 4273 * @see #rotate(Quaternionfc) 4274 * @see #mul(Matrix4x3d) 4275 * 4276 * @param tx 4277 * the number of units by which to translate the x-component 4278 * @param ty 4279 * the number of units by which to translate the y-component 4280 * @param tz 4281 * the number of units by which to translate the z-component 4282 * @param qx 4283 * the x-coordinate of the vector part of the quaternion 4284 * @param qy 4285 * the y-coordinate of the vector part of the quaternion 4286 * @param qz 4287 * the z-coordinate of the vector part of the quaternion 4288 * @param qw 4289 * the scalar part of the quaternion 4290 * @param mat 4291 * the matrix to multiply with 4292 * @return this 4293 */ 4294 ref public Matrix4x3d translationRotateMul(double tx, double ty, double tz, double qx, double qy, double qz, double qw, Matrix4x3d mat) return { 4295 double w2 = qw * qw; 4296 double x2 = qx * qx; 4297 double y2 = qy * qy; 4298 double z2 = qz * qz; 4299 double zw = qz * qw; 4300 double xy = qx * qy; 4301 double xz = qx * qz; 4302 double yw = qy * qw; 4303 double yz = qy * qz; 4304 double xw = qx * qw; 4305 double nm00 = w2 + x2 - z2 - y2; 4306 double nm01 = xy + zw + zw + xy; 4307 double nm02 = xz - yw + xz - yw; 4308 double nm10 = -zw + xy - zw + xy; 4309 double nm11 = y2 - z2 + w2 - x2; 4310 double nm12 = yz + yz + xw + xw; 4311 double nm20 = yw + xz + xz + yw; 4312 double nm21 = yz + yz - xw - xw; 4313 double nm22 = z2 - y2 - x2 + w2; 4314 m00 = nm00 * mat.m00 + nm10 * mat.m01 + nm20 * mat.m02; 4315 m01 = nm01 * mat.m00 + nm11 * mat.m01 + nm21 * mat.m02; 4316 m02 = nm02 * mat.m00 + nm12 * mat.m01 + nm22 * mat.m02; 4317 m10 = nm00 * mat.m10 + nm10 * mat.m11 + nm20 * mat.m12; 4318 m11 = nm01 * mat.m10 + nm11 * mat.m11 + nm21 * mat.m12; 4319 m12 = nm02 * mat.m10 + nm12 * mat.m11 + nm22 * mat.m12; 4320 m20 = nm00 * mat.m20 + nm10 * mat.m21 + nm20 * mat.m22; 4321 m21 = nm01 * mat.m20 + nm11 * mat.m21 + nm21 * mat.m22; 4322 m22 = nm02 * mat.m20 + nm12 * mat.m21 + nm22 * mat.m22; 4323 m30 = nm00 * mat.m30 + nm10 * mat.m31 + nm20 * mat.m32 + tx; 4324 m31 = nm01 * mat.m30 + nm11 * mat.m31 + nm21 * mat.m32 + ty; 4325 m32 = nm02 * mat.m30 + nm12 * mat.m31 + nm22 * mat.m32 + tz; 4326 this.properties = 0; 4327 return this; 4328 } 4329 4330 /** 4331 * Set <code>this</code> matrix to <code>(T * R)<sup>-1</sup></code>, where <code>T</code> is a translation by the given <code>(tx, ty, tz)</code> and 4332 * <code>R</code> is a rotation transformation specified by the quaternion <code>(qx, qy, qz, qw)</code>. 4333 * <p> 4334 * This method is equivalent to calling: <code>translationRotate(...).invert()</code> 4335 * 4336 * @see #translationRotate(double, double, double, double, double, double, double) 4337 * @see #invert() 4338 * 4339 * @param tx 4340 * the number of units by which to translate the x-component 4341 * @param ty 4342 * the number of units by which to translate the y-component 4343 * @param tz 4344 * the number of units by which to translate the z-component 4345 * @param qx 4346 * the x-coordinate of the vector part of the quaternion 4347 * @param qy 4348 * the y-coordinate of the vector part of the quaternion 4349 * @param qz 4350 * the z-coordinate of the vector part of the quaternion 4351 * @param qw 4352 * the scalar part of the quaternion 4353 * @return this 4354 */ 4355 ref public Matrix4x3d translationRotateInvert(double tx, double ty, double tz, double qx, double qy, double qz, 4356 double qw) return { 4357 double nqx = -qx, nqy = -qy, nqz = -qz; 4358 double dqx = nqx + nqx; 4359 double dqy = nqy + nqy; 4360 double dqz = nqz + nqz; 4361 double q00 = dqx * nqx; 4362 double q11 = dqy * nqy; 4363 double q22 = dqz * nqz; 4364 double q01 = dqx * nqy; 4365 double q02 = dqx * nqz; 4366 double q03 = dqx * qw; 4367 double q12 = dqy * nqz; 4368 double q13 = dqy * qw; 4369 double q23 = dqz * qw; 4370 return this 4371 ._m00(1.0 - q11 - q22) 4372 ._m01(q01 + q23) 4373 ._m02(q02 - q13) 4374 ._m10(q01 - q23) 4375 ._m11(1.0 - q22 - q00) 4376 ._m12(q12 + q03) 4377 ._m20(q02 + q13) 4378 ._m21(q12 - q03) 4379 ._m22(1.0 - q11 - q00) 4380 ._m30(-m00 * tx - m10 * ty - m20 * tz) 4381 ._m31(-m01 * tx - m11 * ty - m21 * tz) 4382 ._m32(-m02 * tx - m12 * ty - m22 * tz) 4383 ._properties(PROPERTY_ORTHONORMAL); 4384 } 4385 4386 /** 4387 * Set <code>this</code> matrix to <code>(T * R)<sup>-1</sup></code>, where <code>T</code> is the given <code>translation</code> and 4388 * <code>R</code> is a rotation transformation specified by the given quaternion. 4389 * <p> 4390 * This method is equivalent to calling: <code>translationRotate(...).invert()</code> 4391 * 4392 * @see #translationRotate(Vector3d, Quaterniond) 4393 * @see #invert() 4394 * 4395 * @param translation 4396 * the translation 4397 * @param quat 4398 * the quaternion representing a rotation 4399 * @return this 4400 */ 4401 ref public Matrix4x3d translationRotateInvert(Vector3d translation, 4402 Quaterniond quat) return { 4403 return translationRotateInvert(translation.x, translation.y, translation.z, quat.x, quat.y, quat.z, 4404 quat.w); 4405 } 4406 4407 /** 4408 * Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix and store 4409 * the result in <code>dest</code>. 4410 * <p> 4411 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4412 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4413 * When used with a left-handed coordinate system, the rotation is clockwise. 4414 * <p> 4415 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4416 * then the new matrix will be <code>M * Q</code>. So when transforming a 4417 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 4418 * the quaternion rotation will be applied first! 4419 * <p> 4420 * In order to set the matrix to a rotation transformation without post-multiplying, 4421 * use {@link #rotation(Quaterniond)}. 4422 * <p> 4423 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4424 * 4425 * @see #rotation(Quaterniond) 4426 * 4427 * @param quat 4428 * the {@link Quaterniond} 4429 * @param dest 4430 * will hold the result 4431 * @return dest 4432 */ 4433 public Matrix4x3d rotate(Quaterniond quat, ref Matrix4x3d dest) { 4434 if ((properties & PROPERTY_IDENTITY) != 0) 4435 return dest.rotation(quat); 4436 else if ((properties & PROPERTY_TRANSLATION) != 0) 4437 return rotateTranslation(quat, dest); 4438 return rotateGeneric(quat, dest); 4439 } 4440 private Matrix4x3d rotateGeneric(Quaterniond quat, ref Matrix4x3d dest) { 4441 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 4442 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 4443 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 4444 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 4445 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 4446 double rm00 = w2 + x2 - z2 - y2; 4447 double rm01 = dxy + dzw; 4448 double rm02 = dxz - dyw; 4449 double rm10 = dxy - dzw; 4450 double rm11 = y2 - z2 + w2 - x2; 4451 double rm12 = dyz + dxw; 4452 double rm20 = dyw + dxz; 4453 double rm21 = dyz - dxw; 4454 double rm22 = z2 - y2 - x2 + w2; 4455 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 4456 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 4457 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 4458 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 4459 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 4460 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 4461 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 4462 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 4463 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 4464 dest.m00 = nm00; 4465 dest.m01 = nm01; 4466 dest.m02 = nm02; 4467 dest.m10 = nm10; 4468 dest.m11 = nm11; 4469 dest.m12 = nm12; 4470 dest.m30 = m30; 4471 dest.m31 = m31; 4472 dest.m32 = m32; 4473 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 4474 return dest; 4475 } 4476 4477 4478 /** 4479 * Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix. 4480 * <p> 4481 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4482 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4483 * When used with a left-handed coordinate system, the rotation is clockwise. 4484 * <p> 4485 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4486 * then the new matrix will be <code>M * Q</code>. So when transforming a 4487 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 4488 * the quaternion rotation will be applied first! 4489 * <p> 4490 * In order to set the matrix to a rotation transformation without post-multiplying, 4491 * use {@link #rotation(Quaterniond)}. 4492 * <p> 4493 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4494 * 4495 * @see #rotation(Quaterniond) 4496 * 4497 * @param quat 4498 * the {@link Quaterniond} 4499 * @return this 4500 */ 4501 ref public Matrix4x3d rotate(Quaterniond quat) return { 4502 rotate(quat, this); 4503 return this; 4504 } 4505 4506 4507 /** 4508 * Apply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix, which is assumed to only contain a translation, and store 4509 * the result in <code>dest</code>. 4510 * <p> 4511 * This method assumes <code>this</code> to only contain a translation. 4512 * <p> 4513 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4514 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4515 * When used with a left-handed coordinate system, the rotation is clockwise. 4516 * <p> 4517 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4518 * then the new matrix will be <code>M * Q</code>. So when transforming a 4519 * vector <code>v</code> with the new matrix by using <code>M * Q * v</code>, 4520 * the quaternion rotation will be applied first! 4521 * <p> 4522 * In order to set the matrix to a rotation transformation without post-multiplying, 4523 * use {@link #rotation(Quaterniond)}. 4524 * <p> 4525 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4526 * 4527 * @see #rotation(Quaterniond) 4528 * 4529 * @param quat 4530 * the {@link Quaterniond} 4531 * @param dest 4532 * will hold the result 4533 * @return dest 4534 */ 4535 public Matrix4x3d rotateTranslation(Quaterniond quat, ref Matrix4x3d dest) { 4536 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 4537 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 4538 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 4539 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 4540 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 4541 double rm00 = w2 + x2 - z2 - y2; 4542 double rm01 = dxy + dzw; 4543 double rm02 = dxz - dyw; 4544 double rm10 = dxy - dzw; 4545 double rm11 = y2 - z2 + w2 - x2; 4546 double rm12 = dyz + dxw; 4547 double rm20 = dyw + dxz; 4548 double rm21 = dyz - dxw; 4549 double rm22 = z2 - y2 - x2 + w2; 4550 dest.m20 = rm20; 4551 dest.m21 = rm21; 4552 dest.m22 = rm22; 4553 dest.m00 = rm00; 4554 dest.m01 = rm01; 4555 dest.m02 = rm02; 4556 dest.m10 = rm10; 4557 dest.m11 = rm11; 4558 dest.m12 = rm12; 4559 dest.m30 = m30; 4560 dest.m31 = m31; 4561 dest.m32 = m32; 4562 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 4563 return dest; 4564 } 4565 4566 4567 /** 4568 * Pre-multiply the rotation - and possibly scaling - transformation of the given {@link Quaterniond} to this matrix and store 4569 * the result in <code>dest</code>. 4570 * <p> 4571 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4572 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4573 * When used with a left-handed coordinate system, the rotation is clockwise. 4574 * <p> 4575 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4576 * then the new matrix will be <code>Q * M</code>. So when transforming a 4577 * vector <code>v</code> with the new matrix by using <code>Q * M * v</code>, 4578 * the quaternion rotation will be applied last! 4579 * <p> 4580 * In order to set the matrix to a rotation transformation without pre-multiplying, 4581 * use {@link #rotation(Quaterniond)}. 4582 * <p> 4583 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4584 * 4585 * @see #rotation(Quaterniond) 4586 * 4587 * @param quat 4588 * the {@link Quaterniond} 4589 * @param dest 4590 * will hold the result 4591 * @return dest 4592 */ 4593 public Matrix4x3d rotateLocal(Quaterniond quat, ref Matrix4x3d dest) { 4594 double w2 = quat.w * quat.w, x2 = quat.x * quat.x; 4595 double y2 = quat.y * quat.y, z2 = quat.z * quat.z; 4596 double zw = quat.z * quat.w, dzw = zw + zw, xy = quat.x * quat.y, dxy = xy + xy; 4597 double xz = quat.x * quat.z, dxz = xz + xz, yw = quat.y * quat.w, dyw = yw + yw; 4598 double yz = quat.y * quat.z, dyz = yz + yz, xw = quat.x * quat.w, dxw = xw + xw; 4599 double lm00 = w2 + x2 - z2 - y2; 4600 double lm01 = dxy + dzw; 4601 double lm02 = dxz - dyw; 4602 double lm10 = dxy - dzw; 4603 double lm11 = y2 - z2 + w2 - x2; 4604 double lm12 = dyz + dxw; 4605 double lm20 = dyw + dxz; 4606 double lm21 = dyz - dxw; 4607 double lm22 = z2 - y2 - x2 + w2; 4608 double nm00 = lm00 * m00 + lm10 * m01 + lm20 * m02; 4609 double nm01 = lm01 * m00 + lm11 * m01 + lm21 * m02; 4610 double nm02 = lm02 * m00 + lm12 * m01 + lm22 * m02; 4611 double nm10 = lm00 * m10 + lm10 * m11 + lm20 * m12; 4612 double nm11 = lm01 * m10 + lm11 * m11 + lm21 * m12; 4613 double nm12 = lm02 * m10 + lm12 * m11 + lm22 * m12; 4614 double nm20 = lm00 * m20 + lm10 * m21 + lm20 * m22; 4615 double nm21 = lm01 * m20 + lm11 * m21 + lm21 * m22; 4616 double nm22 = lm02 * m20 + lm12 * m21 + lm22 * m22; 4617 double nm30 = lm00 * m30 + lm10 * m31 + lm20 * m32; 4618 double nm31 = lm01 * m30 + lm11 * m31 + lm21 * m32; 4619 double nm32 = lm02 * m30 + lm12 * m31 + lm22 * m32; 4620 dest.m00 = nm00; 4621 dest.m01 = nm01; 4622 dest.m02 = nm02; 4623 dest.m10 = nm10; 4624 dest.m11 = nm11; 4625 dest.m12 = nm12; 4626 dest.m20 = nm20; 4627 dest.m21 = nm21; 4628 dest.m22 = nm22; 4629 dest.m30 = nm30; 4630 dest.m31 = nm31; 4631 dest.m32 = nm32; 4632 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 4633 return dest; 4634 } 4635 4636 /** 4637 * Pre-multiply the rotation transformation of the given {@link Quaterniond} to this matrix. 4638 * <p> 4639 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4640 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4641 * When used with a left-handed coordinate system, the rotation is clockwise. 4642 * <p> 4643 * If <code>M</code> is <code>this</code> matrix and <code>Q</code> the rotation matrix obtained from the given quaternion, 4644 * then the new matrix will be <code>Q * M</code>. So when transforming a 4645 * vector <code>v</code> with the new matrix by using <code>Q * M * v</code>, 4646 * the quaternion rotation will be applied last! 4647 * <p> 4648 * In order to set the matrix to a rotation transformation without pre-multiplying, 4649 * use {@link #rotation(Quaterniond)}. 4650 * <p> 4651 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion">http://en.wikipedia.org</a> 4652 * 4653 * @see #rotation(Quaterniond) 4654 * 4655 * @param quat 4656 * the {@link Quaterniond} 4657 * @return this 4658 */ 4659 ref public Matrix4x3d rotateLocal(Quaterniond quat) return { 4660 rotateLocal(quat, this); 4661 return this; 4662 } 4663 4664 /** 4665 * Apply a rotation transformation, rotating about the given {@link AxisAngle4d}, to this matrix. 4666 * <p> 4667 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4668 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4669 * When used with a left-handed coordinate system, the rotation is clockwise. 4670 * <p> 4671 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d}, 4672 * then the new matrix will be <code>M * A</code>. So when transforming a 4673 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4674 * the {@link AxisAngle4d} rotation will be applied first! 4675 * <p> 4676 * In order to set the matrix to a rotation transformation without post-multiplying, 4677 * use {@link #rotation(AxisAngle4d)}. 4678 * <p> 4679 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4680 * 4681 * @see #rotate(double, double, double, double) 4682 * @see #rotation(AxisAngle4d) 4683 * 4684 * @param axisAngle 4685 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 4686 * @return this 4687 */ 4688 ref public Matrix4x3d rotate(AxisAngle4d axisAngle) return { 4689 return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z); 4690 } 4691 4692 /** 4693 * Apply a rotation transformation, rotating about the given {@link AxisAngle4d} and store the result in <code>dest</code>. 4694 * <p> 4695 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4696 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4697 * When used with a left-handed coordinate system, the rotation is clockwise. 4698 * <p> 4699 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given {@link AxisAngle4d}, 4700 * then the new matrix will be <code>M * A</code>. So when transforming a 4701 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4702 * the {@link AxisAngle4d} rotation will be applied first! 4703 * <p> 4704 * In order to set the matrix to a rotation transformation without post-multiplying, 4705 * use {@link #rotation(AxisAngle4d)}. 4706 * <p> 4707 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4708 * 4709 * @see #rotate(double, double, double, double) 4710 * @see #rotation(AxisAngle4d) 4711 * 4712 * @param axisAngle 4713 * the {@link AxisAngle4d} (needs to be {@link AxisAngle4d#normalize() normalized}) 4714 * @param dest 4715 * will hold the result 4716 * @return dest 4717 */ 4718 public Matrix4x3d rotate(AxisAngle4d axisAngle, ref Matrix4x3d dest) { 4719 return rotate(axisAngle.angle, axisAngle.x, axisAngle.y, axisAngle.z, dest); 4720 } 4721 4722 /** 4723 * Apply a rotation transformation, rotating the given radians about the specified axis, to this matrix. 4724 * <p> 4725 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4726 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4727 * When used with a left-handed coordinate system, the rotation is clockwise. 4728 * <p> 4729 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given angle and axis, 4730 * then the new matrix will be <code>M * A</code>. So when transforming a 4731 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4732 * the axis-angle rotation will be applied first! 4733 * <p> 4734 * In order to set the matrix to a rotation transformation without post-multiplying, 4735 * use {@link #rotation(double, Vector3d)}. 4736 * <p> 4737 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4738 * 4739 * @see #rotate(double, double, double, double) 4740 * @see #rotation(double, Vector3d) 4741 * 4742 * @param angle 4743 * the angle in radians 4744 * @param axis 4745 * the rotation axis (needs to be {@link Vector3d#normalize() normalized}) 4746 * @return this 4747 */ 4748 ref public Matrix4x3d rotate(double angle, Vector3d axis) return { 4749 return rotate(angle, axis.x, axis.y, axis.z); 4750 } 4751 4752 /** 4753 * Apply a rotation transformation, rotating the given radians about the specified axis and store the result in <code>dest</code>. 4754 * <p> 4755 * When used with a right-handed coordinate system, the produced rotation will rotate a vector 4756 * counter-clockwise around the rotation axis, when viewing along the negative axis direction towards the origin. 4757 * When used with a left-handed coordinate system, the rotation is clockwise. 4758 * <p> 4759 * If <code>M</code> is <code>this</code> matrix and <code>A</code> the rotation matrix obtained from the given angle and axis, 4760 * then the new matrix will be <code>M * A</code>. So when transforming a 4761 * vector <code>v</code> with the new matrix by using <code>M * A * v</code>, 4762 * the axis-angle rotation will be applied first! 4763 * <p> 4764 * In order to set the matrix to a rotation transformation without post-multiplying, 4765 * use {@link #rotation(double, Vector3d)}. 4766 * <p> 4767 * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle">http://en.wikipedia.org</a> 4768 * 4769 * @see #rotate(double, double, double, double) 4770 * @see #rotation(double, Vector3d) 4771 * 4772 * @param angle 4773 * the angle in radians 4774 * @param axis 4775 * the rotation axis (needs to be {@link Vector3d#normalize() normalized}) 4776 * @param dest 4777 * will hold the result 4778 * @return dest 4779 */ 4780 public Matrix4x3d rotate(double angle, Vector3d axis, ref Matrix4x3d dest) { 4781 return rotate(angle, axis.x, axis.y, axis.z, dest); 4782 } 4783 4784 4785 public Vector4d getRow(int row, Vector4d dest) { 4786 switch (row) { 4787 case 0: 4788 dest.x = m00; 4789 dest.y = m10; 4790 dest.z = m20; 4791 dest.w = m30; 4792 break; 4793 case 1: 4794 dest.x = m01; 4795 dest.y = m11; 4796 dest.z = m21; 4797 dest.w = m31; 4798 break; 4799 case 2: 4800 dest.x = m02; 4801 dest.y = m12; 4802 dest.z = m22; 4803 dest.w = m32; 4804 break; 4805 default: {} 4806 } 4807 return dest; 4808 } 4809 4810 /** 4811 * Set the row at the given <code>row</code> index, starting with <code>0</code>. 4812 * 4813 * @param row 4814 * the row index in <code>[0..2]</code> 4815 * @param src 4816 * the row components to set 4817 * @return this 4818 * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..2]</code> 4819 */ 4820 ref public Matrix4x3d setRow(int row, Vector4d src) return { 4821 switch (row) { 4822 case 0: 4823 this.m00 = src.x; 4824 this.m10 = src.y; 4825 this.m20 = src.z; 4826 this.m30 = src.w; 4827 break; 4828 case 1: 4829 this.m01 = src.x; 4830 this.m11 = src.y; 4831 this.m21 = src.z; 4832 this.m31 = src.w; 4833 break; 4834 case 2: 4835 this.m02 = src.x; 4836 this.m12 = src.y; 4837 this.m22 = src.z; 4838 this.m32 = src.w; 4839 break; 4840 default: {} 4841 } 4842 properties = 0; 4843 return this; 4844 } 4845 4846 public Vector3d getColumn(int column, ref Vector3d dest) { 4847 switch (column) { 4848 case 0: 4849 dest.x = m00; 4850 dest.y = m01; 4851 dest.z = m02; 4852 break; 4853 case 1: 4854 dest.x = m10; 4855 dest.y = m11; 4856 dest.z = m12; 4857 break; 4858 case 2: 4859 dest.x = m20; 4860 dest.y = m21; 4861 dest.z = m22; 4862 break; 4863 case 3: 4864 dest.x = m30; 4865 dest.y = m31; 4866 dest.z = m32; 4867 break; 4868 default: {} 4869 } 4870 return dest; 4871 } 4872 4873 /** 4874 * Set the column at the given <code>column</code> index, starting with <code>0</code>. 4875 * 4876 * @param column 4877 * the column index in <code>[0..3]</code> 4878 * @param src 4879 * the column components to set 4880 * @return this 4881 * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..3]</code> 4882 */ 4883 ref public Matrix4x3d setColumn(int column, Vector3d src) return { 4884 switch (column) { 4885 case 0: 4886 this.m00 = src.x; 4887 this.m01 = src.y; 4888 this.m02 = src.z; 4889 break; 4890 case 1: 4891 this.m10 = src.x; 4892 this.m11 = src.y; 4893 this.m12 = src.z; 4894 break; 4895 case 2: 4896 this.m20 = src.x; 4897 this.m21 = src.y; 4898 this.m22 = src.z; 4899 break; 4900 case 3: 4901 this.m30 = src.x; 4902 this.m31 = src.y; 4903 this.m32 = src.z; 4904 break; 4905 default: {} 4906 } 4907 properties = 0; 4908 return this; 4909 } 4910 4911 /** 4912 * Compute a normal matrix from the left 3x3 submatrix of <code>this</code> 4913 * and store it into the left 3x3 submatrix of <code>this</code>. 4914 * All other values of <code>this</code> will be set to {@link #identity() identity}. 4915 * <p> 4916 * The normal matrix of <code>m</code> is the transpose of the inverse of <code>m</code>. 4917 * <p> 4918 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 4919 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 4920 * In that case, use {@link #set3x3(Matrix4x3d)} to set a given Matrix4x3d to only the left 3x3 submatrix 4921 * of this matrix. 4922 * 4923 * @see #set3x3(Matrix4x3d) 4924 * 4925 * @return this 4926 */ 4927 ref public Matrix4x3d normal() return { 4928 normal(this); 4929 return this; 4930 } 4931 4932 /** 4933 * Compute a normal matrix from the left 3x3 submatrix of <code>this</code> 4934 * and store it into the left 3x3 submatrix of <code>dest</code>. 4935 * All other values of <code>dest</code> will be set to {@link #identity() identity}. 4936 * <p> 4937 * The normal matrix of <code>m</code> is the transpose of the inverse of <code>m</code>. 4938 * <p> 4939 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 4940 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 4941 * In that case, use {@link #set3x3(Matrix4x3d)} to set a given Matrix4x3d to only the left 3x3 submatrix 4942 * of a given matrix. 4943 * 4944 * @see #set3x3(Matrix4x3d) 4945 * 4946 * @param dest 4947 * will hold the result 4948 * @return dest 4949 */ 4950 public Matrix4x3d normal(ref Matrix4x3d dest) { 4951 if ((properties & PROPERTY_IDENTITY) != 0) 4952 return dest.identity(); 4953 else if ((properties & PROPERTY_ORTHONORMAL) != 0) 4954 return normalOrthonormal(dest); 4955 return normalGeneric(dest); 4956 } 4957 private Matrix4x3d normalOrthonormal(ref Matrix4x3d dest) { 4958 if (dest != this) 4959 dest.set(this); 4960 return dest._properties(PROPERTY_ORTHONORMAL); 4961 } 4962 private Matrix4x3d normalGeneric(ref Matrix4x3d dest) { 4963 double m00m11 = m00 * m11; 4964 double m01m10 = m01 * m10; 4965 double m02m10 = m02 * m10; 4966 double m00m12 = m00 * m12; 4967 double m01m12 = m01 * m12; 4968 double m02m11 = m02 * m11; 4969 double det = (m00m11 - m01m10) * m22 + (m02m10 - m00m12) * m21 + (m01m12 - m02m11) * m20; 4970 double s = 1.0 / det; 4971 /* Invert and transpose in one go */ 4972 double nm00 = (m11 * m22 - m21 * m12) * s; 4973 double nm01 = (m20 * m12 - m10 * m22) * s; 4974 double nm02 = (m10 * m21 - m20 * m11) * s; 4975 double nm10 = (m21 * m02 - m01 * m22) * s; 4976 double nm11 = (m00 * m22 - m20 * m02) * s; 4977 double nm12 = (m20 * m01 - m00 * m21) * s; 4978 double nm20 = (m01m12 - m02m11) * s; 4979 double nm21 = (m02m10 - m00m12) * s; 4980 double nm22 = (m00m11 - m01m10) * s; 4981 dest.m00 = nm00; 4982 dest.m01 = nm01; 4983 dest.m02 = nm02; 4984 dest.m10 = nm10; 4985 dest.m11 = nm11; 4986 dest.m12 = nm12; 4987 dest.m20 = nm20; 4988 dest.m21 = nm21; 4989 dest.m22 = nm22; 4990 dest.m30 = 0.0; 4991 dest.m31 = 0.0; 4992 dest.m32 = 0.0; 4993 dest.properties = properties & ~PROPERTY_TRANSLATION; 4994 return dest; 4995 } 4996 4997 public Matrix3d normal(Matrix3d dest) { 4998 if ((properties & PROPERTY_ORTHONORMAL) != 0) 4999 return normalOrthonormal(dest); 5000 return normalGeneric(dest); 5001 } 5002 private Matrix3d normalOrthonormal(Matrix3d dest) { 5003 return dest.set(this); 5004 } 5005 private Matrix3d normalGeneric(Matrix3d dest) { 5006 double m00m11 = m00 * m11; 5007 double m01m10 = m01 * m10; 5008 double m02m10 = m02 * m10; 5009 double m00m12 = m00 * m12; 5010 double m01m12 = m01 * m12; 5011 double m02m11 = m02 * m11; 5012 double det = (m00m11 - m01m10) * m22 + (m02m10 - m00m12) * m21 + (m01m12 - m02m11) * m20; 5013 double s = 1.0 / det; 5014 /* Invert and transpose in one go */ 5015 dest.m00 = ((m11 * m22 - m21 * m12) * s); 5016 dest.m01 = ((m20 * m12 - m10 * m22) * s); 5017 dest.m02 = ((m10 * m21 - m20 * m11) * s); 5018 dest.m10 = ((m21 * m02 - m01 * m22) * s); 5019 dest.m11 = ((m00 * m22 - m20 * m02) * s); 5020 dest.m12 = ((m20 * m01 - m00 * m21) * s); 5021 dest.m20 = ((m01m12 - m02m11) * s); 5022 dest.m21 = ((m02m10 - m00m12) * s); 5023 dest.m22 = ((m00m11 - m01m10) * s); 5024 return dest; 5025 } 5026 5027 /** 5028 * Compute the cofactor matrix of the left 3x3 submatrix of <code>this</code>. 5029 * <p> 5030 * The cofactor matrix can be used instead of {@link #normal()} to transform normals 5031 * when the orientation of the normals with respect to the surface should be preserved. 5032 * 5033 * @return this 5034 */ 5035 ref public Matrix4x3d cofactor3x3() return { 5036 cofactor3x3(this); 5037 return this; 5038 } 5039 5040 /** 5041 * Compute the cofactor matrix of the left 3x3 submatrix of <code>this</code> 5042 * and store it into <code>dest</code>. 5043 * <p> 5044 * The cofactor matrix can be used instead of {@link #normal(Matrix3d)} to transform normals 5045 * when the orientation of the normals with respect to the surface should be preserved. 5046 * 5047 * @param dest 5048 * will hold the result 5049 * @return dest 5050 */ 5051 public Matrix3d cofactor3x3(Matrix3d dest) { 5052 dest.m00 = m11 * m22 - m21 * m12; 5053 dest.m01 = m20 * m12 - m10 * m22; 5054 dest.m02 = m10 * m21 - m20 * m11; 5055 dest.m10 = m21 * m02 - m01 * m22; 5056 dest.m11 = m00 * m22 - m20 * m02; 5057 dest.m12 = m20 * m01 - m00 * m21; 5058 dest.m20 = m01 * m12 - m02 * m11; 5059 dest.m21 = m02 * m10 - m00 * m12; 5060 dest.m22 = m00 * m11 - m01 * m10; 5061 return dest; 5062 } 5063 5064 /** 5065 * Compute the cofactor matrix of the left 3x3 submatrix of <code>this</code> 5066 * and store it into <code>dest</code>. 5067 * All other values of <code>dest</code> will be set to {@link #identity() identity}. 5068 * <p> 5069 * The cofactor matrix can be used instead of {@link #normal(Matrix4x3d)} to transform normals 5070 * when the orientation of the normals with respect to the surface should be preserved. 5071 * 5072 * @param dest 5073 * will hold the result 5074 * @return dest 5075 */ 5076 public Matrix4x3d cofactor3x3(ref Matrix4x3d dest) { 5077 double nm00 = m11 * m22 - m21 * m12; 5078 double nm01 = m20 * m12 - m10 * m22; 5079 double nm02 = m10 * m21 - m20 * m11; 5080 double nm10 = m21 * m02 - m01 * m22; 5081 double nm11 = m00 * m22 - m20 * m02; 5082 double nm12 = m20 * m01 - m00 * m21; 5083 double nm20 = m01 * m12 - m11 * m02; 5084 double nm21 = m02 * m10 - m12 * m00; 5085 double nm22 = m00 * m11 - m10 * m01; 5086 dest.m00 = nm00; 5087 dest.m01 = nm01; 5088 dest.m02 = nm02; 5089 dest.m10 = nm10; 5090 dest.m11 = nm11; 5091 dest.m12 = nm12; 5092 dest.m20 = nm20; 5093 dest.m21 = nm21; 5094 dest.m22 = nm22; 5095 dest.m30 = 0.0; 5096 dest.m31 = 0.0; 5097 dest.m32 = 0.0; 5098 dest.properties = properties & ~PROPERTY_TRANSLATION; 5099 return dest; 5100 } 5101 5102 /** 5103 * Normalize the left 3x3 submatrix of this matrix. 5104 * <p> 5105 * The resulting matrix will map unit vectors to unit vectors, though a pair of orthogonal input unit 5106 * vectors need not be mapped to a pair of orthogonal output vectors if the original matrix was not orthogonal itself 5107 * (i.e. had <i>skewing</i>). 5108 * 5109 * @return this 5110 */ 5111 ref public Matrix4x3d normalize3x3() return { 5112 normalize3x3(this); 5113 return this; 5114 } 5115 5116 public Matrix4x3d normalize3x3(ref Matrix4x3d dest) { 5117 double invXlen = Math.invsqrt(m00 * m00 + m01 * m01 + m02 * m02); 5118 double invYlen = Math.invsqrt(m10 * m10 + m11 * m11 + m12 * m12); 5119 double invZlen = Math.invsqrt(m20 * m20 + m21 * m21 + m22 * m22); 5120 dest.m00 = m00 * invXlen; dest.m01 = m01 * invXlen; dest.m02 = m02 * invXlen; 5121 dest.m10 = m10 * invYlen; dest.m11 = m11 * invYlen; dest.m12 = m12 * invYlen; 5122 dest.m20 = m20 * invZlen; dest.m21 = m21 * invZlen; dest.m22 = m22 * invZlen; 5123 return dest; 5124 } 5125 5126 public Matrix3d normalize3x3(Matrix3d dest) { 5127 double invXlen = Math.invsqrt(m00 * m00 + m01 * m01 + m02 * m02); 5128 double invYlen = Math.invsqrt(m10 * m10 + m11 * m11 + m12 * m12); 5129 double invZlen = Math.invsqrt(m20 * m20 + m21 * m21 + m22 * m22); 5130 dest.m00 = (m00 * invXlen); dest.m01 = (m01 * invXlen); dest.m02 = (m02 * invXlen); 5131 dest.m10 = (m10 * invYlen); dest.m11 = (m11 * invYlen); dest.m12 = (m12 * invYlen); 5132 dest.m20 = (m20 * invZlen); dest.m21 = (m21 * invZlen); dest.m22 = (m22 * invZlen); 5133 return dest; 5134 } 5135 5136 public Matrix4x3d reflect(double a, double b, double c, double d, ref Matrix4x3d dest) { 5137 if ((properties & PROPERTY_IDENTITY) != 0) 5138 return dest.reflection(a, b, c, d); 5139 5140 double da = a + a, db = b + b, dc = c + c, dd = d + d; 5141 double rm00 = 1.0 - da * a; 5142 double rm01 = -da * b; 5143 double rm02 = -da * c; 5144 double rm10 = -db * a; 5145 double rm11 = 1.0 - db * b; 5146 double rm12 = -db * c; 5147 double rm20 = -dc * a; 5148 double rm21 = -dc * b; 5149 double rm22 = 1.0 - dc * c; 5150 double rm30 = -dd * a; 5151 double rm31 = -dd * b; 5152 double rm32 = -dd * c; 5153 5154 // matrix multiplication 5155 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 5156 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 5157 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 5158 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 5159 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 5160 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 5161 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 5162 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 5163 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 5164 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 5165 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 5166 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 5167 dest.m00 = nm00; 5168 dest.m01 = nm01; 5169 dest.m02 = nm02; 5170 dest.m10 = nm10; 5171 dest.m11 = nm11; 5172 dest.m12 = nm12; 5173 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 5174 5175 return dest; 5176 } 5177 5178 /** 5179 * Apply a mirror/reflection transformation to this matrix that reflects about the given plane 5180 * specified via the equation <code>x*a + y*b + z*c + d = 0</code>. 5181 * <p> 5182 * The vector <code>(a, b, c)</code> must be a unit vector. 5183 * <p> 5184 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5185 * then the new matrix will be <code>M * R</code>. So when transforming a 5186 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5187 * reflection will be applied first! 5188 * <p> 5189 * Reference: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb281733(v=vs.85).aspx">msdn.microsoft.com</a> 5190 * 5191 * @param a 5192 * the x factor in the plane equation 5193 * @param b 5194 * the y factor in the plane equation 5195 * @param c 5196 * the z factor in the plane equation 5197 * @param d 5198 * the constant in the plane equation 5199 * @return this 5200 */ 5201 ref public Matrix4x3d reflect(double a, double b, double c, double d) return { 5202 reflect(a, b, c, d, this); 5203 return this; 5204 } 5205 5206 /** 5207 * Apply a mirror/reflection transformation to this matrix that reflects about the given plane 5208 * specified via the plane normal and a point on the plane. 5209 * <p> 5210 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5211 * then the new matrix will be <code>M * R</code>. So when transforming a 5212 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5213 * reflection will be applied first! 5214 * 5215 * @param nx 5216 * the x-coordinate of the plane normal 5217 * @param ny 5218 * the y-coordinate of the plane normal 5219 * @param nz 5220 * the z-coordinate of the plane normal 5221 * @param px 5222 * the x-coordinate of a point on the plane 5223 * @param py 5224 * the y-coordinate of a point on the plane 5225 * @param pz 5226 * the z-coordinate of a point on the plane 5227 * @return this 5228 */ 5229 ref public Matrix4x3d reflect(double nx, double ny, double nz, double px, double py, double pz) return { 5230 reflect(nx, ny, nz, px, py, pz, this); 5231 return this; 5232 } 5233 5234 public Matrix4x3d reflect(double nx, double ny, double nz, double px, double py, double pz, ref Matrix4x3d dest) { 5235 double invLength = Math.invsqrt(nx * nx + ny * ny + nz * nz); 5236 double nnx = nx * invLength; 5237 double nny = ny * invLength; 5238 double nnz = nz * invLength; 5239 /* See: http://mathworld.wolfram.com/Plane.html */ 5240 return reflect(nnx, nny, nnz, -nnx * px - nny * py - nnz * pz, dest); 5241 } 5242 5243 /** 5244 * Apply a mirror/reflection transformation to this matrix that reflects about the given plane 5245 * specified via the plane normal and a point on the plane. 5246 * <p> 5247 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5248 * then the new matrix will be <code>M * R</code>. So when transforming a 5249 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5250 * reflection will be applied first! 5251 * 5252 * @param normal 5253 * the plane normal 5254 * @param point 5255 * a point on the plane 5256 * @return this 5257 */ 5258 ref public Matrix4x3d reflect(Vector3d normal, Vector3d point) return { 5259 return reflect(normal.x, normal.y, normal.z, point.x, point.y, point.z); 5260 } 5261 5262 /** 5263 * Apply a mirror/reflection transformation to this matrix that reflects about a plane 5264 * specified via the plane orientation and a point on the plane. 5265 * <p> 5266 * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. 5267 * It is assumed that the default mirror plane's normal is <code>(0, 0, 1)</code>. So, if the given {@link Quaterniond} is 5268 * the identity (does not apply any additional rotation), the reflection plane will be <code>z=0</code>, offset by the given <code>point</code>. 5269 * <p> 5270 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the reflection matrix, 5271 * then the new matrix will be <code>M * R</code>. So when transforming a 5272 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 5273 * reflection will be applied first! 5274 * 5275 * @param orientation 5276 * the plane orientation relative to an implied normal vector of <code>(0, 0, 1)</code> 5277 * @param point 5278 * a point on the plane 5279 * @return this 5280 */ 5281 ref public Matrix4x3d reflect(Quaterniond orientation, Vector3d point) return { 5282 reflect(orientation, point, this); 5283 return this; 5284 } 5285 5286 public Matrix4x3d reflect(Quaterniond orientation, Vector3d point, ref Matrix4x3d dest) { 5287 double num1 = orientation.x + orientation.x; 5288 double num2 = orientation.y + orientation.y; 5289 double num3 = orientation.z + orientation.z; 5290 double normalX = orientation.x * num3 + orientation.w * num2; 5291 double normalY = orientation.y * num3 - orientation.w * num1; 5292 double normalZ = 1.0 - (orientation.x * num1 + orientation.y * num2); 5293 return reflect(normalX, normalY, normalZ, point.x, point.y, point.z, dest); 5294 } 5295 5296 public Matrix4x3d reflect(Vector3d normal, Vector3d point, ref Matrix4x3d dest) { 5297 return reflect(normal.x, normal.y, normal.z, point.x, point.y, point.z, dest); 5298 } 5299 5300 /** 5301 * Set this matrix to a mirror/reflection transformation that reflects about the given plane 5302 * specified via the equation <code>x*a + y*b + z*c + d = 0</code>. 5303 * <p> 5304 * The vector <code>(a, b, c)</code> must be a unit vector. 5305 * <p> 5306 * Reference: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb281733(v=vs.85).aspx">msdn.microsoft.com</a> 5307 * 5308 * @param a 5309 * the x factor in the plane equation 5310 * @param b 5311 * the y factor in the plane equation 5312 * @param c 5313 * the z factor in the plane equation 5314 * @param d 5315 * the constant in the plane equation 5316 * @return this 5317 */ 5318 ref public Matrix4x3d reflection(double a, double b, double c, double d) return { 5319 double da = a + a, db = b + b, dc = c + c, dd = d + d; 5320 m00 = 1.0 - da * a; 5321 m01 = -da * b; 5322 m02 = -da * c; 5323 m10 = -db * a; 5324 m11 = 1.0 - db * b; 5325 m12 = -db * c; 5326 m20 = -dc * a; 5327 m21 = -dc * b; 5328 m22 = 1.0 - dc * c; 5329 m30 = -dd * a; 5330 m31 = -dd * b; 5331 m32 = -dd * c; 5332 properties = PROPERTY_ORTHONORMAL; 5333 return this; 5334 } 5335 5336 /** 5337 * Set this matrix to a mirror/reflection transformation that reflects about the given plane 5338 * specified via the plane normal and a point on the plane. 5339 * 5340 * @param nx 5341 * the x-coordinate of the plane normal 5342 * @param ny 5343 * the y-coordinate of the plane normal 5344 * @param nz 5345 * the z-coordinate of the plane normal 5346 * @param px 5347 * the x-coordinate of a point on the plane 5348 * @param py 5349 * the y-coordinate of a point on the plane 5350 * @param pz 5351 * the z-coordinate of a point on the plane 5352 * @return this 5353 */ 5354 ref public Matrix4x3d reflection(double nx, double ny, double nz, double px, double py, double pz) return { 5355 double invLength = Math.invsqrt(nx * nx + ny * ny + nz * nz); 5356 double nnx = nx * invLength; 5357 double nny = ny * invLength; 5358 double nnz = nz * invLength; 5359 /* See: http://mathworld.wolfram.com/Plane.html */ 5360 return reflection(nnx, nny, nnz, -nnx * px - nny * py - nnz * pz); 5361 } 5362 5363 /** 5364 * Set this matrix to a mirror/reflection transformation that reflects about the given plane 5365 * specified via the plane normal and a point on the plane. 5366 * 5367 * @param normal 5368 * the plane normal 5369 * @param point 5370 * a point on the plane 5371 * @return this 5372 */ 5373 ref public Matrix4x3d reflection(Vector3d normal, Vector3d point) return { 5374 return reflection(normal.x, normal.y, normal.z, point.x, point.y, point.z); 5375 } 5376 5377 /** 5378 * Set this matrix to a mirror/reflection transformation that reflects about a plane 5379 * specified via the plane orientation and a point on the plane. 5380 * <p> 5381 * This method can be used to build a reflection transformation based on the orientation of a mirror object in the scene. 5382 * It is assumed that the default mirror plane's normal is <code>(0, 0, 1)</code>. So, if the given {@link Quaterniond} is 5383 * the identity (does not apply any additional rotation), the reflection plane will be <code>z=0</code>, offset by the given <code>point</code>. 5384 * 5385 * @param orientation 5386 * the plane orientation 5387 * @param point 5388 * a point on the plane 5389 * @return this 5390 */ 5391 ref public Matrix4x3d reflection(Quaterniond orientation, Vector3d point) return { 5392 double num1 = orientation.x + orientation.x; 5393 double num2 = orientation.y + orientation.y; 5394 double num3 = orientation.z + orientation.z; 5395 double normalX = orientation.x * num3 + orientation.w * num2; 5396 double normalY = orientation.y * num3 - orientation.w * num1; 5397 double normalZ = 1.0 - (orientation.x * num1 + orientation.y * num2); 5398 return reflection(normalX, normalY, normalZ, point.x, point.y, point.z); 5399 } 5400 5401 /** 5402 * Apply an orthographic projection transformation for a right-handed coordinate system 5403 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 5404 * <p> 5405 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5406 * then the new matrix will be <code>M * O</code>. So when transforming a 5407 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5408 * orthographic projection transformation will be applied first! 5409 * <p> 5410 * In order to set the matrix to an orthographic projection without post-multiplying it, 5411 * use {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()}. 5412 * <p> 5413 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5414 * 5415 * @see #setOrtho(double, double, double, double, double, double, bool) 5416 * 5417 * @param left 5418 * the distance from the center to the left frustum edge 5419 * @param right 5420 * the distance from the center to the right frustum edge 5421 * @param bottom 5422 * the distance from the center to the bottom frustum edge 5423 * @param top 5424 * the distance from the center to the top frustum edge 5425 * @param zNear 5426 * near clipping plane distance 5427 * @param zFar 5428 * far clipping plane distance 5429 * @param zZeroToOne 5430 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5431 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5432 * @param dest 5433 * will hold the result 5434 * @return dest 5435 */ 5436 public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 5437 // calculate right matrix elements 5438 double rm00 = 2.0 / (right - left); 5439 double rm11 = 2.0 / (top - bottom); 5440 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 5441 double rm30 = (left + right) / (left - right); 5442 double rm31 = (top + bottom) / (bottom - top); 5443 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5444 5445 // perform optimized multiplication 5446 // compute the last column first, because other columns do not depend on it 5447 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 5448 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 5449 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 5450 dest.m00 = m00 * rm00; 5451 dest.m01 = m01 * rm00; 5452 dest.m02 = m02 * rm00; 5453 dest.m10 = m10 * rm11; 5454 dest.m11 = m11 * rm11; 5455 dest.m12 = m12 * rm11; 5456 dest.m20 = m20 * rm22; 5457 dest.m21 = m21 * rm22; 5458 dest.m22 = m22 * rm22; 5459 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 5460 5461 return dest; 5462 } 5463 5464 /** 5465 * Apply an orthographic projection transformation for a right-handed coordinate system 5466 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 5467 * <p> 5468 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5469 * then the new matrix will be <code>M * O</code>. So when transforming a 5470 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5471 * orthographic projection transformation will be applied first! 5472 * <p> 5473 * In order to set the matrix to an orthographic projection without post-multiplying it, 5474 * use {@link #setOrtho(double, double, double, double, double, double) setOrtho()}. 5475 * <p> 5476 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5477 * 5478 * @see #setOrtho(double, double, double, double, double, double) 5479 * 5480 * @param left 5481 * the distance from the center to the left frustum edge 5482 * @param right 5483 * the distance from the center to the right frustum edge 5484 * @param bottom 5485 * the distance from the center to the bottom frustum edge 5486 * @param top 5487 * the distance from the center to the top frustum edge 5488 * @param zNear 5489 * near clipping plane distance 5490 * @param zFar 5491 * far clipping plane distance 5492 * @param dest 5493 * will hold the result 5494 * @return dest 5495 */ 5496 public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar, ref Matrix4x3d dest) { 5497 return ortho(left, right, bottom, top, zNear, zFar, false, dest); 5498 } 5499 5500 /** 5501 * Apply an orthographic projection transformation for a right-handed coordinate system 5502 * using the given NDC z range to this matrix. 5503 * <p> 5504 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5505 * then the new matrix will be <code>M * O</code>. So when transforming a 5506 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5507 * orthographic projection transformation will be applied first! 5508 * <p> 5509 * In order to set the matrix to an orthographic projection without post-multiplying it, 5510 * use {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()}. 5511 * <p> 5512 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5513 * 5514 * @see #setOrtho(double, double, double, double, double, double, bool) 5515 * 5516 * @param left 5517 * the distance from the center to the left frustum edge 5518 * @param right 5519 * the distance from the center to the right frustum edge 5520 * @param bottom 5521 * the distance from the center to the bottom frustum edge 5522 * @param top 5523 * the distance from the center to the top frustum edge 5524 * @param zNear 5525 * near clipping plane distance 5526 * @param zFar 5527 * far clipping plane distance 5528 * @param zZeroToOne 5529 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5530 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5531 * @return this 5532 */ 5533 ref public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5534 ortho(left, right, bottom, top, zNear, zFar, zZeroToOne, this); 5535 return this; 5536 } 5537 5538 /** 5539 * Apply an orthographic projection transformation for a right-handed coordinate system 5540 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 5541 * <p> 5542 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5543 * then the new matrix will be <code>M * O</code>. So when transforming a 5544 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5545 * orthographic projection transformation will be applied first! 5546 * <p> 5547 * In order to set the matrix to an orthographic projection without post-multiplying it, 5548 * use {@link #setOrtho(double, double, double, double, double, double) setOrtho()}. 5549 * <p> 5550 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5551 * 5552 * @see #setOrtho(double, double, double, double, double, double) 5553 * 5554 * @param left 5555 * the distance from the center to the left frustum edge 5556 * @param right 5557 * the distance from the center to the right frustum edge 5558 * @param bottom 5559 * the distance from the center to the bottom frustum edge 5560 * @param top 5561 * the distance from the center to the top frustum edge 5562 * @param zNear 5563 * near clipping plane distance 5564 * @param zFar 5565 * far clipping plane distance 5566 * @return this 5567 */ 5568 ref public Matrix4x3d ortho(double left, double right, double bottom, double top, double zNear, double zFar) return { 5569 return ortho(left, right, bottom, top, zNear, zFar, false); 5570 } 5571 5572 /** 5573 * Apply an orthographic projection transformation for a left-handed coordiante system 5574 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 5575 * <p> 5576 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5577 * then the new matrix will be <code>M * O</code>. So when transforming a 5578 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5579 * orthographic projection transformation will be applied first! 5580 * <p> 5581 * In order to set the matrix to an orthographic projection without post-multiplying it, 5582 * use {@link #setOrthoLH(double, double, double, double, double, double, bool) setOrthoLH()}. 5583 * <p> 5584 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5585 * 5586 * @see #setOrthoLH(double, double, double, double, double, double, bool) 5587 * 5588 * @param left 5589 * the distance from the center to the left frustum edge 5590 * @param right 5591 * the distance from the center to the right frustum edge 5592 * @param bottom 5593 * the distance from the center to the bottom frustum edge 5594 * @param top 5595 * the distance from the center to the top frustum edge 5596 * @param zNear 5597 * near clipping plane distance 5598 * @param zFar 5599 * far clipping plane distance 5600 * @param zZeroToOne 5601 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5602 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5603 * @param dest 5604 * will hold the result 5605 * @return dest 5606 */ 5607 public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 5608 // calculate right matrix elements 5609 double rm00 = 2.0 / (right - left); 5610 double rm11 = 2.0 / (top - bottom); 5611 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 5612 double rm30 = (left + right) / (left - right); 5613 double rm31 = (top + bottom) / (bottom - top); 5614 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5615 5616 // perform optimized multiplication 5617 // compute the last column first, because other columns do not depend on it 5618 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 5619 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 5620 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 5621 dest.m00 = m00 * rm00; 5622 dest.m01 = m01 * rm00; 5623 dest.m02 = m02 * rm00; 5624 dest.m10 = m10 * rm11; 5625 dest.m11 = m11 * rm11; 5626 dest.m12 = m12 * rm11; 5627 dest.m20 = m20 * rm22; 5628 dest.m21 = m21 * rm22; 5629 dest.m22 = m22 * rm22; 5630 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 5631 5632 return dest; 5633 } 5634 5635 /** 5636 * Apply an orthographic projection transformation for a left-handed coordiante system 5637 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 5638 * <p> 5639 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5640 * then the new matrix will be <code>M * O</code>. So when transforming a 5641 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5642 * orthographic projection transformation will be applied first! 5643 * <p> 5644 * In order to set the matrix to an orthographic projection without post-multiplying it, 5645 * use {@link #setOrthoLH(double, double, double, double, double, double) setOrthoLH()}. 5646 * <p> 5647 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5648 * 5649 * @see #setOrthoLH(double, double, double, double, double, double) 5650 * 5651 * @param left 5652 * the distance from the center to the left frustum edge 5653 * @param right 5654 * the distance from the center to the right frustum edge 5655 * @param bottom 5656 * the distance from the center to the bottom frustum edge 5657 * @param top 5658 * the distance from the center to the top frustum edge 5659 * @param zNear 5660 * near clipping plane distance 5661 * @param zFar 5662 * far clipping plane distance 5663 * @param dest 5664 * will hold the result 5665 * @return dest 5666 */ 5667 public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar, ref Matrix4x3d dest) { 5668 return orthoLH(left, right, bottom, top, zNear, zFar, false, dest); 5669 } 5670 5671 /** 5672 * Apply an orthographic projection transformation for a left-handed coordiante system 5673 * using the given NDC z range to this matrix. 5674 * <p> 5675 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5676 * then the new matrix will be <code>M * O</code>. So when transforming a 5677 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5678 * orthographic projection transformation will be applied first! 5679 * <p> 5680 * In order to set the matrix to an orthographic projection without post-multiplying it, 5681 * use {@link #setOrthoLH(double, double, double, double, double, double, bool) setOrthoLH()}. 5682 * <p> 5683 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5684 * 5685 * @see #setOrthoLH(double, double, double, double, double, double, bool) 5686 * 5687 * @param left 5688 * the distance from the center to the left frustum edge 5689 * @param right 5690 * the distance from the center to the right frustum edge 5691 * @param bottom 5692 * the distance from the center to the bottom frustum edge 5693 * @param top 5694 * the distance from the center to the top frustum edge 5695 * @param zNear 5696 * near clipping plane distance 5697 * @param zFar 5698 * far clipping plane distance 5699 * @param zZeroToOne 5700 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5701 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5702 * @return this 5703 */ 5704 ref public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5705 orthoLH(left, right, bottom, top, zNear, zFar, zZeroToOne, this); 5706 return this; 5707 } 5708 5709 /** 5710 * Apply an orthographic projection transformation for a left-handed coordiante system 5711 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 5712 * <p> 5713 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5714 * then the new matrix will be <code>M * O</code>. So when transforming a 5715 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5716 * orthographic projection transformation will be applied first! 5717 * <p> 5718 * In order to set the matrix to an orthographic projection without post-multiplying it, 5719 * use {@link #setOrthoLH(double, double, double, double, double, double) setOrthoLH()}. 5720 * <p> 5721 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5722 * 5723 * @see #setOrthoLH(double, double, double, double, double, double) 5724 * 5725 * @param left 5726 * the distance from the center to the left frustum edge 5727 * @param right 5728 * the distance from the center to the right frustum edge 5729 * @param bottom 5730 * the distance from the center to the bottom frustum edge 5731 * @param top 5732 * the distance from the center to the top frustum edge 5733 * @param zNear 5734 * near clipping plane distance 5735 * @param zFar 5736 * far clipping plane distance 5737 * @return this 5738 */ 5739 ref public Matrix4x3d orthoLH(double left, double right, double bottom, double top, double zNear, double zFar) return { 5740 return orthoLH(left, right, bottom, top, zNear, zFar, false); 5741 } 5742 5743 /** 5744 * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system 5745 * using the given NDC z range. 5746 * <p> 5747 * In order to apply the orthographic projection to an already existing transformation, 5748 * use {@link #ortho(double, double, double, double, double, double, bool) ortho()}. 5749 * <p> 5750 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5751 * 5752 * @see #ortho(double, double, double, double, double, double, bool) 5753 * 5754 * @param left 5755 * the distance from the center to the left frustum edge 5756 * @param right 5757 * the distance from the center to the right frustum edge 5758 * @param bottom 5759 * the distance from the center to the bottom frustum edge 5760 * @param top 5761 * the distance from the center to the top frustum edge 5762 * @param zNear 5763 * near clipping plane distance 5764 * @param zFar 5765 * far clipping plane distance 5766 * @param zZeroToOne 5767 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5768 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5769 * @return this 5770 */ 5771 ref public Matrix4x3d setOrtho(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5772 m00 = 2.0 / (right - left); 5773 m01 = 0.0; 5774 m02 = 0.0; 5775 m10 = 0.0; 5776 m11 = 2.0 / (top - bottom); 5777 m12 = 0.0; 5778 m20 = 0.0; 5779 m21 = 0.0; 5780 m22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 5781 m30 = (right + left) / (left - right); 5782 m31 = (top + bottom) / (bottom - top); 5783 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5784 properties = 0; 5785 return this; 5786 } 5787 5788 /** 5789 * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system 5790 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 5791 * <p> 5792 * In order to apply the orthographic projection to an already existing transformation, 5793 * use {@link #ortho(double, double, double, double, double, double) ortho()}. 5794 * <p> 5795 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5796 * 5797 * @see #ortho(double, double, double, double, double, double) 5798 * 5799 * @param left 5800 * the distance from the center to the left frustum edge 5801 * @param right 5802 * the distance from the center to the right frustum edge 5803 * @param bottom 5804 * the distance from the center to the bottom frustum edge 5805 * @param top 5806 * the distance from the center to the top frustum edge 5807 * @param zNear 5808 * near clipping plane distance 5809 * @param zFar 5810 * far clipping plane distance 5811 * @return this 5812 */ 5813 ref public Matrix4x3d setOrtho(double left, double right, double bottom, double top, double zNear, double zFar) return { 5814 return setOrtho(left, right, bottom, top, zNear, zFar, false); 5815 } 5816 5817 /** 5818 * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system 5819 * using the given NDC z range. 5820 * <p> 5821 * In order to apply the orthographic projection to an already existing transformation, 5822 * use {@link #orthoLH(double, double, double, double, double, double, bool) orthoLH()}. 5823 * <p> 5824 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5825 * 5826 * @see #orthoLH(double, double, double, double, double, double, bool) 5827 * 5828 * @param left 5829 * the distance from the center to the left frustum edge 5830 * @param right 5831 * the distance from the center to the right frustum edge 5832 * @param bottom 5833 * the distance from the center to the bottom frustum edge 5834 * @param top 5835 * the distance from the center to the top frustum edge 5836 * @param zNear 5837 * near clipping plane distance 5838 * @param zFar 5839 * far clipping plane distance 5840 * @param zZeroToOne 5841 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5842 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5843 * @return this 5844 */ 5845 ref public Matrix4x3d setOrthoLH(double left, double right, double bottom, double top, double zNear, double zFar, bool zZeroToOne) return { 5846 m00 = 2.0 / (right - left); 5847 m01 = 0.0; 5848 m02 = 0.0; 5849 m10 = 0.0; 5850 m11 = 2.0 / (top - bottom); 5851 m12 = 0.0; 5852 m20 = 0.0; 5853 m21 = 0.0; 5854 m22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 5855 m30 = (right + left) / (left - right); 5856 m31 = (top + bottom) / (bottom - top); 5857 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5858 properties = 0; 5859 return this; 5860 } 5861 5862 /** 5863 * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system 5864 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 5865 * <p> 5866 * In order to apply the orthographic projection to an already existing transformation, 5867 * use {@link #orthoLH(double, double, double, double, double, double) orthoLH()}. 5868 * <p> 5869 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5870 * 5871 * @see #orthoLH(double, double, double, double, double, double) 5872 * 5873 * @param left 5874 * the distance from the center to the left frustum edge 5875 * @param right 5876 * the distance from the center to the right frustum edge 5877 * @param bottom 5878 * the distance from the center to the bottom frustum edge 5879 * @param top 5880 * the distance from the center to the top frustum edge 5881 * @param zNear 5882 * near clipping plane distance 5883 * @param zFar 5884 * far clipping plane distance 5885 * @return this 5886 */ 5887 ref public Matrix4x3d setOrthoLH(double left, double right, double bottom, double top, double zNear, double zFar) return { 5888 return setOrthoLH(left, right, bottom, top, zNear, zFar, false); 5889 } 5890 5891 /** 5892 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 5893 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 5894 * <p> 5895 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, bool, Matrix4x3d) ortho()} with 5896 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 5897 * <p> 5898 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5899 * then the new matrix will be <code>M * O</code>. So when transforming a 5900 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5901 * orthographic projection transformation will be applied first! 5902 * <p> 5903 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 5904 * use {@link #setOrthoSymmetric(double, double, double, double, bool) setOrthoSymmetric()}. 5905 * <p> 5906 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5907 * 5908 * @see #setOrthoSymmetric(double, double, double, double, bool) 5909 * 5910 * @param width 5911 * the distance between the right and left frustum edges 5912 * @param height 5913 * the distance between the top and bottom frustum edges 5914 * @param zNear 5915 * near clipping plane distance 5916 * @param zFar 5917 * far clipping plane distance 5918 * @param dest 5919 * will hold the result 5920 * @param zZeroToOne 5921 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 5922 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 5923 * @return dest 5924 */ 5925 public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 5926 // calculate right matrix elements 5927 double rm00 = 2.0 / width; 5928 double rm11 = 2.0 / height; 5929 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 5930 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 5931 5932 // perform optimized multiplication 5933 // compute the last column first, because other columns do not depend on it 5934 dest.m30 = m20 * rm32 + m30; 5935 dest.m31 = m21 * rm32 + m31; 5936 dest.m32 = m22 * rm32 + m32; 5937 dest.m00 = m00 * rm00; 5938 dest.m01 = m01 * rm00; 5939 dest.m02 = m02 * rm00; 5940 dest.m10 = m10 * rm11; 5941 dest.m11 = m11 * rm11; 5942 dest.m12 = m12 * rm11; 5943 dest.m20 = m20 * rm22; 5944 dest.m21 = m21 * rm22; 5945 dest.m22 = m22 * rm22; 5946 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 5947 5948 return dest; 5949 } 5950 5951 /** 5952 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 5953 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 5954 * <p> 5955 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, Matrix4x3d) ortho()} with 5956 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 5957 * <p> 5958 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5959 * then the new matrix will be <code>M * O</code>. So when transforming a 5960 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5961 * orthographic projection transformation will be applied first! 5962 * <p> 5963 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 5964 * use {@link #setOrthoSymmetric(double, double, double, double) setOrthoSymmetric()}. 5965 * <p> 5966 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 5967 * 5968 * @see #setOrthoSymmetric(double, double, double, double) 5969 * 5970 * @param width 5971 * the distance between the right and left frustum edges 5972 * @param height 5973 * the distance between the top and bottom frustum edges 5974 * @param zNear 5975 * near clipping plane distance 5976 * @param zFar 5977 * far clipping plane distance 5978 * @param dest 5979 * will hold the result 5980 * @return dest 5981 */ 5982 public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar, ref Matrix4x3d dest) { 5983 return orthoSymmetric(width, height, zNear, zFar, false, dest); 5984 } 5985 5986 /** 5987 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 5988 * using the given NDC z range to this matrix. 5989 * <p> 5990 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, bool) ortho()} with 5991 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 5992 * <p> 5993 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 5994 * then the new matrix will be <code>M * O</code>. So when transforming a 5995 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 5996 * orthographic projection transformation will be applied first! 5997 * <p> 5998 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 5999 * use {@link #setOrthoSymmetric(double, double, double, double, bool) setOrthoSymmetric()}. 6000 * <p> 6001 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6002 * 6003 * @see #setOrthoSymmetric(double, double, double, double, bool) 6004 * 6005 * @param width 6006 * the distance between the right and left frustum edges 6007 * @param height 6008 * the distance between the top and bottom frustum edges 6009 * @param zNear 6010 * near clipping plane distance 6011 * @param zFar 6012 * far clipping plane distance 6013 * @param zZeroToOne 6014 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6015 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6016 * @return this 6017 */ 6018 ref public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 6019 orthoSymmetric(width, height, zNear, zFar, zZeroToOne, this); 6020 return this; 6021 } 6022 6023 /** 6024 * Apply a symmetric orthographic projection transformation for a right-handed coordinate system 6025 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 6026 * <p> 6027 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double) ortho()} with 6028 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6029 * <p> 6030 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6031 * then the new matrix will be <code>M * O</code>. So when transforming a 6032 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6033 * orthographic projection transformation will be applied first! 6034 * <p> 6035 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6036 * use {@link #setOrthoSymmetric(double, double, double, double) setOrthoSymmetric()}. 6037 * <p> 6038 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6039 * 6040 * @see #setOrthoSymmetric(double, double, double, double) 6041 * 6042 * @param width 6043 * the distance between the right and left frustum edges 6044 * @param height 6045 * the distance between the top and bottom frustum edges 6046 * @param zNear 6047 * near clipping plane distance 6048 * @param zFar 6049 * far clipping plane distance 6050 * @return this 6051 */ 6052 ref public Matrix4x3d orthoSymmetric(double width, double height, double zNear, double zFar) return { 6053 orthoSymmetric(width, height, zNear, zFar, false, this); 6054 return this; 6055 } 6056 6057 /** 6058 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 6059 * using the given NDC z range to this matrix and store the result in <code>dest</code>. 6060 * <p> 6061 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, bool, Matrix4x3d) orthoLH()} with 6062 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6063 * <p> 6064 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6065 * then the new matrix will be <code>M * O</code>. So when transforming a 6066 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6067 * orthographic projection transformation will be applied first! 6068 * <p> 6069 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6070 * use {@link #setOrthoSymmetricLH(double, double, double, double, bool) setOrthoSymmetricLH()}. 6071 * <p> 6072 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6073 * 6074 * @see #setOrthoSymmetricLH(double, double, double, double, bool) 6075 * 6076 * @param width 6077 * the distance between the right and left frustum edges 6078 * @param height 6079 * the distance between the top and bottom frustum edges 6080 * @param zNear 6081 * near clipping plane distance 6082 * @param zFar 6083 * far clipping plane distance 6084 * @param dest 6085 * will hold the result 6086 * @param zZeroToOne 6087 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6088 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6089 * @return dest 6090 */ 6091 public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar, bool zZeroToOne, ref Matrix4x3d dest) { 6092 // calculate right matrix elements 6093 double rm00 = 2.0 / width; 6094 double rm11 = 2.0 / height; 6095 double rm22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 6096 double rm32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 6097 6098 // perform optimized multiplication 6099 // compute the last column first, because other columns do not depend on it 6100 dest.m30 = m20 * rm32 + m30; 6101 dest.m31 = m21 * rm32 + m31; 6102 dest.m32 = m22 * rm32 + m32; 6103 dest.m00 = m00 * rm00; 6104 dest.m01 = m01 * rm00; 6105 dest.m02 = m02 * rm00; 6106 dest.m10 = m10 * rm11; 6107 dest.m11 = m11 * rm11; 6108 dest.m12 = m12 * rm11; 6109 dest.m20 = m20 * rm22; 6110 dest.m21 = m21 * rm22; 6111 dest.m22 = m22 * rm22; 6112 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 6113 6114 return dest; 6115 } 6116 6117 /** 6118 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 6119 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix and store the result in <code>dest</code>. 6120 * <p> 6121 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, Matrix4x3d) orthoLH()} with 6122 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6123 * <p> 6124 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6125 * then the new matrix will be <code>M * O</code>. So when transforming a 6126 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6127 * orthographic projection transformation will be applied first! 6128 * <p> 6129 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6130 * use {@link #setOrthoSymmetricLH(double, double, double, double) setOrthoSymmetricLH()}. 6131 * <p> 6132 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6133 * 6134 * @see #setOrthoSymmetricLH(double, double, double, double) 6135 * 6136 * @param width 6137 * the distance between the right and left frustum edges 6138 * @param height 6139 * the distance between the top and bottom frustum edges 6140 * @param zNear 6141 * near clipping plane distance 6142 * @param zFar 6143 * far clipping plane distance 6144 * @param dest 6145 * will hold the result 6146 * @return dest 6147 */ 6148 public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar, ref Matrix4x3d dest) { 6149 return orthoSymmetricLH(width, height, zNear, zFar, false, dest); 6150 } 6151 6152 /** 6153 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 6154 * using the given NDC z range to this matrix. 6155 * <p> 6156 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, bool) orthoLH()} with 6157 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6158 * <p> 6159 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6160 * then the new matrix will be <code>M * O</code>. So when transforming a 6161 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6162 * orthographic projection transformation will be applied first! 6163 * <p> 6164 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6165 * use {@link #setOrthoSymmetricLH(double, double, double, double, bool) setOrthoSymmetricLH()}. 6166 * <p> 6167 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6168 * 6169 * @see #setOrthoSymmetricLH(double, double, double, double, bool) 6170 * 6171 * @param width 6172 * the distance between the right and left frustum edges 6173 * @param height 6174 * the distance between the top and bottom frustum edges 6175 * @param zNear 6176 * near clipping plane distance 6177 * @param zFar 6178 * far clipping plane distance 6179 * @param zZeroToOne 6180 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6181 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6182 * @return this 6183 */ 6184 ref public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 6185 orthoSymmetricLH(width, height, zNear, zFar, zZeroToOne, this); 6186 return this; 6187 } 6188 6189 /** 6190 * Apply a symmetric orthographic projection transformation for a left-handed coordinate system 6191 * using OpenGL's NDC z range of <code>[-1..+1]</code> to this matrix. 6192 * <p> 6193 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double) orthoLH()} with 6194 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6195 * <p> 6196 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6197 * then the new matrix will be <code>M * O</code>. So when transforming a 6198 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6199 * orthographic projection transformation will be applied first! 6200 * <p> 6201 * In order to set the matrix to a symmetric orthographic projection without post-multiplying it, 6202 * use {@link #setOrthoSymmetricLH(double, double, double, double) setOrthoSymmetricLH()}. 6203 * <p> 6204 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6205 * 6206 * @see #setOrthoSymmetricLH(double, double, double, double) 6207 * 6208 * @param width 6209 * the distance between the right and left frustum edges 6210 * @param height 6211 * the distance between the top and bottom frustum edges 6212 * @param zNear 6213 * near clipping plane distance 6214 * @param zFar 6215 * far clipping plane distance 6216 * @return this 6217 */ 6218 ref public Matrix4x3d orthoSymmetricLH(double width, double height, double zNear, double zFar) return { 6219 orthoSymmetricLH(width, height, zNear, zFar, false, this); 6220 return this; 6221 } 6222 6223 /** 6224 * Set this matrix to be a symmetric orthographic projection transformation for a right-handed coordinate system 6225 * using the given NDC z range. 6226 * <p> 6227 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()} with 6228 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6229 * <p> 6230 * In order to apply the symmetric orthographic projection to an already existing transformation, 6231 * use {@link #orthoSymmetric(double, double, double, double, bool) orthoSymmetric()}. 6232 * <p> 6233 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6234 * 6235 * @see #orthoSymmetric(double, double, double, double, bool) 6236 * 6237 * @param width 6238 * the distance between the right and left frustum edges 6239 * @param height 6240 * the distance between the top and bottom frustum edges 6241 * @param zNear 6242 * near clipping plane distance 6243 * @param zFar 6244 * far clipping plane distance 6245 * @param zZeroToOne 6246 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6247 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6248 * @return this 6249 */ 6250 ref public Matrix4x3d setOrthoSymmetric(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 6251 m00 = 2.0 / width; 6252 m01 = 0.0; 6253 m02 = 0.0; 6254 m10 = 0.0; 6255 m11 = 2.0 / height; 6256 m12 = 0.0; 6257 m20 = 0.0; 6258 m21 = 0.0; 6259 m22 = (zZeroToOne ? 1.0 : 2.0) / (zNear - zFar); 6260 m30 = 0.0; 6261 m31 = 0.0; 6262 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 6263 properties = 0; 6264 return this; 6265 } 6266 6267 /** 6268 * Set this matrix to be a symmetric orthographic projection transformation for a right-handed coordinate system 6269 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 6270 * <p> 6271 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double) setOrtho()} with 6272 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6273 * <p> 6274 * In order to apply the symmetric orthographic projection to an already existing transformation, 6275 * use {@link #orthoSymmetric(double, double, double, double) orthoSymmetric()}. 6276 * <p> 6277 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6278 * 6279 * @see #orthoSymmetric(double, double, double, double) 6280 * 6281 * @param width 6282 * the distance between the right and left frustum edges 6283 * @param height 6284 * the distance between the top and bottom frustum edges 6285 * @param zNear 6286 * near clipping plane distance 6287 * @param zFar 6288 * far clipping plane distance 6289 * @return this 6290 */ 6291 ref public Matrix4x3d setOrthoSymmetric(double width, double height, double zNear, double zFar) return { 6292 return setOrthoSymmetric(width, height, zNear, zFar, false); 6293 } 6294 6295 /** 6296 * Set this matrix to be a symmetric orthographic projection transformation for a left-handed coordinate system using the given NDC z range. 6297 * <p> 6298 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double, bool) setOrtho()} with 6299 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6300 * <p> 6301 * In order to apply the symmetric orthographic projection to an already existing transformation, 6302 * use {@link #orthoSymmetricLH(double, double, double, double, bool) orthoSymmetricLH()}. 6303 * <p> 6304 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6305 * 6306 * @see #orthoSymmetricLH(double, double, double, double, bool) 6307 * 6308 * @param width 6309 * the distance between the right and left frustum edges 6310 * @param height 6311 * the distance between the top and bottom frustum edges 6312 * @param zNear 6313 * near clipping plane distance 6314 * @param zFar 6315 * far clipping plane distance 6316 * @param zZeroToOne 6317 * whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code> 6318 * or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code> 6319 * @return this 6320 */ 6321 ref public Matrix4x3d setOrthoSymmetricLH(double width, double height, double zNear, double zFar, bool zZeroToOne) return { 6322 m00 = 2.0 / width; 6323 m01 = 0.0; 6324 m02 = 0.0; 6325 m10 = 0.0; 6326 m11 = 2.0 / height; 6327 m12 = 0.0; 6328 m20 = 0.0; 6329 m21 = 0.0; 6330 m22 = (zZeroToOne ? 1.0 : 2.0) / (zFar - zNear); 6331 m30 = 0.0; 6332 m31 = 0.0; 6333 m32 = (zZeroToOne ? zNear : (zFar + zNear)) / (zNear - zFar); 6334 properties = 0; 6335 return this; 6336 } 6337 6338 /** 6339 * Set this matrix to be a symmetric orthographic projection transformation for a left-handed coordinate system 6340 * using OpenGL's NDC z range of <code>[-1..+1]</code>. 6341 * <p> 6342 * This method is equivalent to calling {@link #setOrthoLH(double, double, double, double, double, double) setOrthoLH()} with 6343 * <code>left=-width/2</code>, <code>right=+width/2</code>, <code>bottom=-height/2</code> and <code>top=+height/2</code>. 6344 * <p> 6345 * In order to apply the symmetric orthographic projection to an already existing transformation, 6346 * use {@link #orthoSymmetricLH(double, double, double, double) orthoSymmetricLH()}. 6347 * <p> 6348 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6349 * 6350 * @see #orthoSymmetricLH(double, double, double, double) 6351 * 6352 * @param width 6353 * the distance between the right and left frustum edges 6354 * @param height 6355 * the distance between the top and bottom frustum edges 6356 * @param zNear 6357 * near clipping plane distance 6358 * @param zFar 6359 * far clipping plane distance 6360 * @return this 6361 */ 6362 ref public Matrix4x3d setOrthoSymmetricLH(double width, double height, double zNear, double zFar) return { 6363 return setOrthoSymmetricLH(width, height, zNear, zFar, false); 6364 } 6365 6366 /** 6367 * Apply an orthographic projection transformation for a right-handed coordinate system 6368 * to this matrix and store the result in <code>dest</code>. 6369 * <p> 6370 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double, Matrix4x3d) ortho()} with 6371 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6372 * <p> 6373 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6374 * then the new matrix will be <code>M * O</code>. So when transforming a 6375 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6376 * orthographic projection transformation will be applied first! 6377 * <p> 6378 * In order to set the matrix to an orthographic projection without post-multiplying it, 6379 * use {@link #setOrtho2D(double, double, double, double) setOrtho()}. 6380 * <p> 6381 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6382 * 6383 * @see #ortho(double, double, double, double, double, double, Matrix4x3d) 6384 * @see #setOrtho2D(double, double, double, double) 6385 * 6386 * @param left 6387 * the distance from the center to the left frustum edge 6388 * @param right 6389 * the distance from the center to the right frustum edge 6390 * @param bottom 6391 * the distance from the center to the bottom frustum edge 6392 * @param top 6393 * the distance from the center to the top frustum edge 6394 * @param dest 6395 * will hold the result 6396 * @return dest 6397 */ 6398 public Matrix4x3d ortho2D(double left, double right, double bottom, double top, ref Matrix4x3d dest) { 6399 // calculate right matrix elements 6400 double rm00 = 2.0 / (right - left); 6401 double rm11 = 2.0 / (top - bottom); 6402 double rm30 = -(right + left) / (right - left); 6403 double rm31 = -(top + bottom) / (top - bottom); 6404 6405 // perform optimized multiplication 6406 // compute the last column first, because other columns do not depend on it 6407 dest.m30 = m00 * rm30 + m10 * rm31 + m30; 6408 dest.m31 = m01 * rm30 + m11 * rm31 + m31; 6409 dest.m32 = m02 * rm30 + m12 * rm31 + m32; 6410 dest.m00 = m00 * rm00; 6411 dest.m01 = m01 * rm00; 6412 dest.m02 = m02 * rm00; 6413 dest.m10 = m10 * rm11; 6414 dest.m11 = m11 * rm11; 6415 dest.m12 = m12 * rm11; 6416 dest.m20 = -m20; 6417 dest.m21 = -m21; 6418 dest.m22 = -m22; 6419 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 6420 6421 return dest; 6422 } 6423 6424 /** 6425 * Apply an orthographic projection transformation for a right-handed coordinate system to this matrix. 6426 * <p> 6427 * This method is equivalent to calling {@link #ortho(double, double, double, double, double, double) ortho()} with 6428 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6429 * <p> 6430 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6431 * then the new matrix will be <code>M * O</code>. So when transforming a 6432 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6433 * orthographic projection transformation will be applied first! 6434 * <p> 6435 * In order to set the matrix to an orthographic projection without post-multiplying it, 6436 * use {@link #setOrtho2D(double, double, double, double) setOrtho2D()}. 6437 * <p> 6438 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6439 * 6440 * @see #ortho(double, double, double, double, double, double) 6441 * @see #setOrtho2D(double, double, double, double) 6442 * 6443 * @param left 6444 * the distance from the center to the left frustum edge 6445 * @param right 6446 * the distance from the center to the right frustum edge 6447 * @param bottom 6448 * the distance from the center to the bottom frustum edge 6449 * @param top 6450 * the distance from the center to the top frustum edge 6451 * @return this 6452 */ 6453 ref public Matrix4x3d ortho2D(double left, double right, double bottom, double top) return { 6454 ortho2D(left, right, bottom, top, this); 6455 return this; 6456 } 6457 6458 /** 6459 * Apply an orthographic projection transformation for a left-handed coordinate system to this matrix and store the result in <code>dest</code>. 6460 * <p> 6461 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double, Matrix4x3d) orthoLH()} with 6462 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6463 * <p> 6464 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6465 * then the new matrix will be <code>M * O</code>. So when transforming a 6466 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6467 * orthographic projection transformation will be applied first! 6468 * <p> 6469 * In order to set the matrix to an orthographic projection without post-multiplying it, 6470 * use {@link #setOrtho2DLH(double, double, double, double) setOrthoLH()}. 6471 * <p> 6472 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6473 * 6474 * @see #orthoLH(double, double, double, double, double, double, Matrix4x3d) 6475 * @see #setOrtho2DLH(double, double, double, double) 6476 * 6477 * @param left 6478 * the distance from the center to the left frustum edge 6479 * @param right 6480 * the distance from the center to the right frustum edge 6481 * @param bottom 6482 * the distance from the center to the bottom frustum edge 6483 * @param top 6484 * the distance from the center to the top frustum edge 6485 * @param dest 6486 * will hold the result 6487 * @return dest 6488 */ 6489 public Matrix4x3d ortho2DLH(double left, double right, double bottom, double top, ref Matrix4x3d dest) { 6490 // calculate right matrix elements 6491 double rm00 = 2.0 / (right - left); 6492 double rm11 = 2.0 / (top - bottom); 6493 double rm30 = -(right + left) / (right - left); 6494 double rm31 = -(top + bottom) / (top - bottom); 6495 6496 // perform optimized multiplication 6497 // compute the last column first, because other columns do not depend on it 6498 dest.m30 = m00 * rm30 + m10 * rm31 + m30; 6499 dest.m31 = m01 * rm30 + m11 * rm31 + m31; 6500 dest.m32 = m02 * rm30 + m12 * rm31 + m32; 6501 dest.m00 = m00 * rm00; 6502 dest.m01 = m01 * rm00; 6503 dest.m02 = m02 * rm00; 6504 dest.m10 = m10 * rm11; 6505 dest.m11 = m11 * rm11; 6506 dest.m12 = m12 * rm11; 6507 dest.m20 = m20; 6508 dest.m21 = m21; 6509 dest.m22 = m22; 6510 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 6511 6512 return dest; 6513 } 6514 6515 /** 6516 * Apply an orthographic projection transformation for a left-handed coordinate system to this matrix. 6517 * <p> 6518 * This method is equivalent to calling {@link #orthoLH(double, double, double, double, double, double) orthoLH()} with 6519 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6520 * <p> 6521 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix, 6522 * then the new matrix will be <code>M * O</code>. So when transforming a 6523 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 6524 * orthographic projection transformation will be applied first! 6525 * <p> 6526 * In order to set the matrix to an orthographic projection without post-multiplying it, 6527 * use {@link #setOrtho2DLH(double, double, double, double) setOrtho2DLH()}. 6528 * <p> 6529 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6530 * 6531 * @see #orthoLH(double, double, double, double, double, double) 6532 * @see #setOrtho2DLH(double, double, double, double) 6533 * 6534 * @param left 6535 * the distance from the center to the left frustum edge 6536 * @param right 6537 * the distance from the center to the right frustum edge 6538 * @param bottom 6539 * the distance from the center to the bottom frustum edge 6540 * @param top 6541 * the distance from the center to the top frustum edge 6542 * @return this 6543 */ 6544 ref public Matrix4x3d ortho2DLH(double left, double right, double bottom, double top) return { 6545 ortho2DLH(left, right, bottom, top, this); 6546 return this; 6547 } 6548 6549 /** 6550 * Set this matrix to be an orthographic projection transformation for a right-handed coordinate system. 6551 * <p> 6552 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double) setOrtho()} with 6553 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6554 * <p> 6555 * In order to apply the orthographic projection to an already existing transformation, 6556 * use {@link #ortho2D(double, double, double, double) ortho2D()}. 6557 * <p> 6558 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6559 * 6560 * @see #setOrtho(double, double, double, double, double, double) 6561 * @see #ortho2D(double, double, double, double) 6562 * 6563 * @param left 6564 * the distance from the center to the left frustum edge 6565 * @param right 6566 * the distance from the center to the right frustum edge 6567 * @param bottom 6568 * the distance from the center to the bottom frustum edge 6569 * @param top 6570 * the distance from the center to the top frustum edge 6571 * @return this 6572 */ 6573 ref public Matrix4x3d setOrtho2D(double left, double right, double bottom, double top) return { 6574 m00 = 2.0 / (right - left); 6575 m01 = 0.0; 6576 m02 = 0.0; 6577 m10 = 0.0; 6578 m11 = 2.0 / (top - bottom); 6579 m12 = 0.0; 6580 m20 = 0.0; 6581 m21 = 0.0; 6582 m22 = -1.0; 6583 m30 = -(right + left) / (right - left); 6584 m31 = -(top + bottom) / (top - bottom); 6585 m32 = 0.0; 6586 properties = 0; 6587 return this; 6588 } 6589 6590 /** 6591 * Set this matrix to be an orthographic projection transformation for a left-handed coordinate system. 6592 * <p> 6593 * This method is equivalent to calling {@link #setOrtho(double, double, double, double, double, double) setOrthoLH()} with 6594 * <code>zNear=-1</code> and <code>zFar=+1</code>. 6595 * <p> 6596 * In order to apply the orthographic projection to an already existing transformation, 6597 * use {@link #ortho2DLH(double, double, double, double) ortho2DLH()}. 6598 * <p> 6599 * Reference: <a href="http://www.songho.ca/opengl/gl_projectionmatrix.html#ortho">http://www.songho.ca</a> 6600 * 6601 * @see #setOrthoLH(double, double, double, double, double, double) 6602 * @see #ortho2DLH(double, double, double, double) 6603 * 6604 * @param left 6605 * the distance from the center to the left frustum edge 6606 * @param right 6607 * the distance from the center to the right frustum edge 6608 * @param bottom 6609 * the distance from the center to the bottom frustum edge 6610 * @param top 6611 * the distance from the center to the top frustum edge 6612 * @return this 6613 */ 6614 ref public Matrix4x3d setOrtho2DLH(double left, double right, double bottom, double top) return { 6615 m00 = 2.0 / (right - left); 6616 m01 = 0.0; 6617 m02 = 0.0; 6618 m10 = 0.0; 6619 m11 = 2.0 / (top - bottom); 6620 m12 = 0.0; 6621 m20 = 0.0; 6622 m21 = 0.0; 6623 m22 = 1.0; 6624 m30 = -(right + left) / (right - left); 6625 m31 = -(top + bottom) / (top - bottom); 6626 m32 = 0.0; 6627 properties = 0; 6628 return this; 6629 } 6630 6631 /** 6632 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>. 6633 * <p> 6634 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6635 * then the new matrix will be <code>M * L</code>. So when transforming a 6636 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6637 * lookalong rotation transformation will be applied first! 6638 * <p> 6639 * This is equivalent to calling 6640 * {@link #lookAt(Vector3d, Vector3d, Vector3d) lookAt} 6641 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6642 * <p> 6643 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6644 * use {@link #setLookAlong(Vector3d, Vector3d) setLookAlong()}. 6645 * 6646 * @see #lookAlong(double, double, double, double, double, double) 6647 * @see #lookAt(Vector3d, Vector3d, Vector3d) 6648 * @see #setLookAlong(Vector3d, Vector3d) 6649 * 6650 * @param dir 6651 * the direction in space to look along 6652 * @param up 6653 * the direction of 'up' 6654 * @return this 6655 */ 6656 ref public Matrix4x3d lookAlong(ref Vector3d dir, Vector3d up) return { 6657 lookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z, this); 6658 return this; 6659 } 6660 6661 /** 6662 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code> 6663 * and store the result in <code>dest</code>. 6664 * <p> 6665 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6666 * then the new matrix will be <code>M * L</code>. So when transforming a 6667 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6668 * lookalong rotation transformation will be applied first! 6669 * <p> 6670 * This is equivalent to calling 6671 * {@link #lookAt(Vector3d, Vector3d, Vector3d) lookAt} 6672 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6673 * <p> 6674 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6675 * use {@link #setLookAlong(Vector3d, Vector3d) setLookAlong()}. 6676 * 6677 * @see #lookAlong(double, double, double, double, double, double) 6678 * @see #lookAt(Vector3d, Vector3d, Vector3d) 6679 * @see #setLookAlong(Vector3d, Vector3d) 6680 * 6681 * @param dir 6682 * the direction in space to look along 6683 * @param up 6684 * the direction of 'up' 6685 * @param dest 6686 * will hold the result 6687 * @return dest 6688 */ 6689 public Matrix4x3d lookAlong(ref Vector3d dir, Vector3d up, ref Matrix4x3d dest) { 6690 return lookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z, dest); 6691 } 6692 6693 /** 6694 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code> 6695 * and store the result in <code>dest</code>. 6696 * <p> 6697 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6698 * then the new matrix will be <code>M * L</code>. So when transforming a 6699 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6700 * lookalong rotation transformation will be applied first! 6701 * <p> 6702 * This is equivalent to calling 6703 * {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt()} 6704 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6705 * <p> 6706 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6707 * use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()} 6708 * 6709 * @see #lookAt(double, double, double, double, double, double, double, double, double) 6710 * @see #setLookAlong(double, double, double, double, double, double) 6711 * 6712 * @param dirX 6713 * the x-coordinate of the direction to look along 6714 * @param dirY 6715 * the y-coordinate of the direction to look along 6716 * @param dirZ 6717 * the z-coordinate of the direction to look along 6718 * @param upX 6719 * the x-coordinate of the up vector 6720 * @param upY 6721 * the y-coordinate of the up vector 6722 * @param upZ 6723 * the z-coordinate of the up vector 6724 * @param dest 6725 * will hold the result 6726 * @return dest 6727 */ 6728 public Matrix4x3d lookAlong(double dirX, double dirY, double dirZ, 6729 double upX, double upY, double upZ, ref Matrix4x3d dest) { 6730 if ((properties & PROPERTY_IDENTITY) != 0) 6731 return setLookAlong(dirX, dirY, dirZ, upX, upY, upZ); 6732 6733 // Normalize direction 6734 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 6735 dirX *= -invDirLength; 6736 dirY *= -invDirLength; 6737 dirZ *= -invDirLength; 6738 // left = up x direction 6739 double leftX, leftY, leftZ; 6740 leftX = upY * dirZ - upZ * dirY; 6741 leftY = upZ * dirX - upX * dirZ; 6742 leftZ = upX * dirY - upY * dirX; 6743 // normalize left 6744 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 6745 leftX *= invLeftLength; 6746 leftY *= invLeftLength; 6747 leftZ *= invLeftLength; 6748 // up = direction x left 6749 double upnX = dirY * leftZ - dirZ * leftY; 6750 double upnY = dirZ * leftX - dirX * leftZ; 6751 double upnZ = dirX * leftY - dirY * leftX; 6752 6753 // calculate right matrix elements 6754 double rm00 = leftX; 6755 double rm01 = upnX; 6756 double rm02 = dirX; 6757 double rm10 = leftY; 6758 double rm11 = upnY; 6759 double rm12 = dirY; 6760 double rm20 = leftZ; 6761 double rm21 = upnZ; 6762 double rm22 = dirZ; 6763 6764 // perform optimized matrix multiplication 6765 // introduce temporaries for dependent results 6766 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 6767 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 6768 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 6769 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 6770 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 6771 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 6772 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 6773 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 6774 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 6775 // set the rest of the matrix elements 6776 dest.m00 = nm00; 6777 dest.m01 = nm01; 6778 dest.m02 = nm02; 6779 dest.m10 = nm10; 6780 dest.m11 = nm11; 6781 dest.m12 = nm12; 6782 dest.m30 = m30; 6783 dest.m31 = m31; 6784 dest.m32 = m32; 6785 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 6786 6787 return dest; 6788 } 6789 6790 /** 6791 * Apply a rotation transformation to this matrix to make <code>-z</code> point along <code>dir</code>. 6792 * <p> 6793 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookalong rotation matrix, 6794 * then the new matrix will be <code>M * L</code>. So when transforming a 6795 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, the 6796 * lookalong rotation transformation will be applied first! 6797 * <p> 6798 * This is equivalent to calling 6799 * {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt()} 6800 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6801 * <p> 6802 * In order to set the matrix to a lookalong transformation without post-multiplying it, 6803 * use {@link #setLookAlong(double, double, double, double, double, double) setLookAlong()} 6804 * 6805 * @see #lookAt(double, double, double, double, double, double, double, double, double) 6806 * @see #setLookAlong(double, double, double, double, double, double) 6807 * 6808 * @param dirX 6809 * the x-coordinate of the direction to look along 6810 * @param dirY 6811 * the y-coordinate of the direction to look along 6812 * @param dirZ 6813 * the z-coordinate of the direction to look along 6814 * @param upX 6815 * the x-coordinate of the up vector 6816 * @param upY 6817 * the y-coordinate of the up vector 6818 * @param upZ 6819 * the z-coordinate of the up vector 6820 * @return this 6821 */ 6822 ref public Matrix4x3d lookAlong(double dirX, double dirY, double dirZ, 6823 double upX, double upY, double upZ) return { 6824 lookAlong(dirX, dirY, dirZ, upX, upY, upZ, this); 6825 return this; 6826 } 6827 6828 /** 6829 * Set this matrix to a rotation transformation to make <code>-z</code> 6830 * point along <code>dir</code>. 6831 * <p> 6832 * This is equivalent to calling 6833 * {@link #setLookAt(Vector3d, Vector3d, Vector3d) setLookAt()} 6834 * with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6835 * <p> 6836 * In order to apply the lookalong transformation to any previous existing transformation, 6837 * use {@link #lookAlong(Vector3d, Vector3d)}. 6838 * 6839 * @see #setLookAlong(Vector3d, Vector3d) 6840 * @see #lookAlong(Vector3d, Vector3d) 6841 * 6842 * @param dir 6843 * the direction in space to look along 6844 * @param up 6845 * the direction of 'up' 6846 * @return this 6847 */ 6848 ref public Matrix4x3d setLookAlong(ref Vector3d dir, Vector3d up) return { 6849 return setLookAlong(dir.x, dir.y, dir.z, up.x, up.y, up.z); 6850 } 6851 6852 /** 6853 * Set this matrix to a rotation transformation to make <code>-z</code> 6854 * point along <code>dir</code>. 6855 * <p> 6856 * This is equivalent to calling 6857 * {@link #setLookAt(double, double, double, double, double, double, double, double, double) 6858 * setLookAt()} with <code>eye = (0, 0, 0)</code> and <code>center = dir</code>. 6859 * <p> 6860 * In order to apply the lookalong transformation to any previous existing transformation, 6861 * use {@link #lookAlong(double, double, double, double, double, double) lookAlong()} 6862 * 6863 * @see #setLookAlong(double, double, double, double, double, double) 6864 * @see #lookAlong(double, double, double, double, double, double) 6865 * 6866 * @param dirX 6867 * the x-coordinate of the direction to look along 6868 * @param dirY 6869 * the y-coordinate of the direction to look along 6870 * @param dirZ 6871 * the z-coordinate of the direction to look along 6872 * @param upX 6873 * the x-coordinate of the up vector 6874 * @param upY 6875 * the y-coordinate of the up vector 6876 * @param upZ 6877 * the z-coordinate of the up vector 6878 * @return this 6879 */ 6880 ref public Matrix4x3d setLookAlong(double dirX, double dirY, double dirZ, 6881 double upX, double upY, double upZ) return { 6882 // Normalize direction 6883 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 6884 dirX *= -invDirLength; 6885 dirY *= -invDirLength; 6886 dirZ *= -invDirLength; 6887 // left = up x direction 6888 double leftX, leftY, leftZ; 6889 leftX = upY * dirZ - upZ * dirY; 6890 leftY = upZ * dirX - upX * dirZ; 6891 leftZ = upX * dirY - upY * dirX; 6892 // normalize left 6893 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 6894 leftX *= invLeftLength; 6895 leftY *= invLeftLength; 6896 leftZ *= invLeftLength; 6897 // up = direction x left 6898 double upnX = dirY * leftZ - dirZ * leftY; 6899 double upnY = dirZ * leftX - dirX * leftZ; 6900 double upnZ = dirX * leftY - dirY * leftX; 6901 6902 m00 = leftX; 6903 m01 = upnX; 6904 m02 = dirX; 6905 m10 = leftY; 6906 m11 = upnY; 6907 m12 = dirY; 6908 m20 = leftZ; 6909 m21 = upnZ; 6910 m22 = dirZ; 6911 m30 = 0.0; 6912 m31 = 0.0; 6913 m32 = 0.0; 6914 properties = PROPERTY_ORTHONORMAL; 6915 6916 return this; 6917 } 6918 6919 /** 6920 * Set this matrix to be a "lookat" transformation for a right-handed coordinate system, that aligns 6921 * <code>-z</code> with <code>center - eye</code>. 6922 * <p> 6923 * In order to not make use of vectors to specify <code>eye</code>, <code>center</code> and <code>up</code> but use primitives, 6924 * like in the GLU function, use {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt()} 6925 * instead. 6926 * <p> 6927 * In order to apply the lookat transformation to a previous existing transformation, 6928 * use {@link #lookAt(Vector3d, Vector3d, Vector3d) lookAt()}. 6929 * 6930 * @see #setLookAt(double, double, double, double, double, double, double, double, double) 6931 * @see #lookAt(Vector3d, Vector3d, Vector3d) 6932 * 6933 * @param eye 6934 * the position of the camera 6935 * @param center 6936 * the point in space to look at 6937 * @param up 6938 * the direction of 'up' 6939 * @return this 6940 */ 6941 ref public Matrix4x3d setLookAt(Vector3d eye, Vector3d center, Vector3d up) return { 6942 return setLookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z); 6943 } 6944 6945 /** 6946 * Set this matrix to be a "lookat" transformation for a right-handed coordinate system, 6947 * that aligns <code>-z</code> with <code>center - eye</code>. 6948 * <p> 6949 * In order to apply the lookat transformation to a previous existing transformation, 6950 * use {@link #lookAt(double, double, double, double, double, double, double, double, double) lookAt}. 6951 * 6952 * @see #setLookAt(Vector3d, Vector3d, Vector3d) 6953 * @see #lookAt(double, double, double, double, double, double, double, double, double) 6954 * 6955 * @param eyeX 6956 * the x-coordinate of the eye/camera location 6957 * @param eyeY 6958 * the y-coordinate of the eye/camera location 6959 * @param eyeZ 6960 * the z-coordinate of the eye/camera location 6961 * @param centerX 6962 * the x-coordinate of the point to look at 6963 * @param centerY 6964 * the y-coordinate of the point to look at 6965 * @param centerZ 6966 * the z-coordinate of the point to look at 6967 * @param upX 6968 * the x-coordinate of the up vector 6969 * @param upY 6970 * the y-coordinate of the up vector 6971 * @param upZ 6972 * the z-coordinate of the up vector 6973 * @return this 6974 */ 6975 ref public Matrix4x3d setLookAt(double eyeX, double eyeY, double eyeZ, 6976 double centerX, double centerY, double centerZ, 6977 double upX, double upY, double upZ) return { 6978 // Compute direction from position to lookAt 6979 double dirX, dirY, dirZ; 6980 dirX = eyeX - centerX; 6981 dirY = eyeY - centerY; 6982 dirZ = eyeZ - centerZ; 6983 // Normalize direction 6984 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 6985 dirX *= invDirLength; 6986 dirY *= invDirLength; 6987 dirZ *= invDirLength; 6988 // left = up x direction 6989 double leftX, leftY, leftZ; 6990 leftX = upY * dirZ - upZ * dirY; 6991 leftY = upZ * dirX - upX * dirZ; 6992 leftZ = upX * dirY - upY * dirX; 6993 // normalize left 6994 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 6995 leftX *= invLeftLength; 6996 leftY *= invLeftLength; 6997 leftZ *= invLeftLength; 6998 // up = direction x left 6999 double upnX = dirY * leftZ - dirZ * leftY; 7000 double upnY = dirZ * leftX - dirX * leftZ; 7001 double upnZ = dirX * leftY - dirY * leftX; 7002 7003 m00 = leftX; 7004 m01 = upnX; 7005 m02 = dirX; 7006 m10 = leftY; 7007 m11 = upnY; 7008 m12 = dirY; 7009 m20 = leftZ; 7010 m21 = upnZ; 7011 m22 = dirZ; 7012 m30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 7013 m31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 7014 m32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 7015 properties = PROPERTY_ORTHONORMAL; 7016 7017 return this; 7018 } 7019 7020 /** 7021 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 7022 * that aligns <code>-z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 7023 * <p> 7024 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7025 * then the new matrix will be <code>M * L</code>. So when transforming a 7026 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7027 * the lookat transformation will be applied first! 7028 * <p> 7029 * In order to set the matrix to a lookat transformation without post-multiplying it, 7030 * use {@link #setLookAt(Vector3d, Vector3d, Vector3d)}. 7031 * 7032 * @see #lookAt(double, double, double, double, double, double, double, double, double) 7033 * @see #setLookAlong(Vector3d, Vector3d) 7034 * 7035 * @param eye 7036 * the position of the camera 7037 * @param center 7038 * the point in space to look at 7039 * @param up 7040 * the direction of 'up' 7041 * @param dest 7042 * will hold the result 7043 * @return dest 7044 */ 7045 public Matrix4x3d lookAt(Vector3d eye, Vector3d center, Vector3d up, ref Matrix4x3d dest) { 7046 return lookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, dest); 7047 } 7048 7049 /** 7050 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 7051 * that aligns <code>-z</code> with <code>center - eye</code>. 7052 * <p> 7053 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7054 * then the new matrix will be <code>M * L</code>. So when transforming a 7055 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7056 * the lookat transformation will be applied first! 7057 * <p> 7058 * In order to set the matrix to a lookat transformation without post-multiplying it, 7059 * use {@link #setLookAt(Vector3d, Vector3d, Vector3d)}. 7060 * 7061 * @see #lookAt(double, double, double, double, double, double, double, double, double) 7062 * @see #setLookAlong(Vector3d, Vector3d) 7063 * 7064 * @param eye 7065 * the position of the camera 7066 * @param center 7067 * the point in space to look at 7068 * @param up 7069 * the direction of 'up' 7070 * @return this 7071 */ 7072 ref public Matrix4x3d lookAt(Vector3d eye, Vector3d center, Vector3d up) return { 7073 lookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, this); 7074 return this; 7075 } 7076 7077 /** 7078 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 7079 * that aligns <code>-z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 7080 * <p> 7081 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7082 * then the new matrix will be <code>M * L</code>. So when transforming a 7083 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7084 * the lookat transformation will be applied first! 7085 * <p> 7086 * In order to set the matrix to a lookat transformation without post-multiplying it, 7087 * use {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt()}. 7088 * 7089 * @see #lookAt(Vector3d, Vector3d, Vector3d) 7090 * @see #setLookAt(double, double, double, double, double, double, double, double, double) 7091 * 7092 * @param eyeX 7093 * the x-coordinate of the eye/camera location 7094 * @param eyeY 7095 * the y-coordinate of the eye/camera location 7096 * @param eyeZ 7097 * the z-coordinate of the eye/camera location 7098 * @param centerX 7099 * the x-coordinate of the point to look at 7100 * @param centerY 7101 * the y-coordinate of the point to look at 7102 * @param centerZ 7103 * the z-coordinate of the point to look at 7104 * @param upX 7105 * the x-coordinate of the up vector 7106 * @param upY 7107 * the y-coordinate of the up vector 7108 * @param upZ 7109 * the z-coordinate of the up vector 7110 * @param dest 7111 * will hold the result 7112 * @return dest 7113 */ 7114 public Matrix4x3d lookAt(double eyeX, double eyeY, double eyeZ, 7115 double centerX, double centerY, double centerZ, 7116 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7117 if ((properties & PROPERTY_IDENTITY) != 0) 7118 return dest.setLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); 7119 return lookAtGeneric(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); 7120 } 7121 private Matrix4x3d lookAtGeneric(double eyeX, double eyeY, double eyeZ, 7122 double centerX, double centerY, double centerZ, 7123 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7124 // Compute direction from position to lookAt 7125 double dirX, dirY, dirZ; 7126 dirX = eyeX - centerX; 7127 dirY = eyeY - centerY; 7128 dirZ = eyeZ - centerZ; 7129 // Normalize direction 7130 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7131 dirX *= invDirLength; 7132 dirY *= invDirLength; 7133 dirZ *= invDirLength; 7134 // left = up x direction 7135 double leftX, leftY, leftZ; 7136 leftX = upY * dirZ - upZ * dirY; 7137 leftY = upZ * dirX - upX * dirZ; 7138 leftZ = upX * dirY - upY * dirX; 7139 // normalize left 7140 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7141 leftX *= invLeftLength; 7142 leftY *= invLeftLength; 7143 leftZ *= invLeftLength; 7144 // up = direction x left 7145 double upnX = dirY * leftZ - dirZ * leftY; 7146 double upnY = dirZ * leftX - dirX * leftZ; 7147 double upnZ = dirX * leftY - dirY * leftX; 7148 7149 // calculate right matrix elements 7150 double rm00 = leftX; 7151 double rm01 = upnX; 7152 double rm02 = dirX; 7153 double rm10 = leftY; 7154 double rm11 = upnY; 7155 double rm12 = dirY; 7156 double rm20 = leftZ; 7157 double rm21 = upnZ; 7158 double rm22 = dirZ; 7159 double rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 7160 double rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 7161 double rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 7162 7163 // perform optimized matrix multiplication 7164 // compute last column first, because others do not depend on it 7165 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 7166 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 7167 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 7168 // introduce temporaries for dependent results 7169 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 7170 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 7171 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 7172 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 7173 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 7174 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 7175 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 7176 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 7177 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 7178 // set the rest of the matrix elements 7179 dest.m00 = nm00; 7180 dest.m01 = nm01; 7181 dest.m02 = nm02; 7182 dest.m10 = nm10; 7183 dest.m11 = nm11; 7184 dest.m12 = nm12; 7185 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 7186 7187 return dest; 7188 } 7189 7190 /** 7191 * Apply a "lookat" transformation to this matrix for a right-handed coordinate system, 7192 * that aligns <code>-z</code> with <code>center - eye</code>. 7193 * <p> 7194 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7195 * then the new matrix will be <code>M * L</code>. So when transforming a 7196 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7197 * the lookat transformation will be applied first! 7198 * <p> 7199 * In order to set the matrix to a lookat transformation without post-multiplying it, 7200 * use {@link #setLookAt(double, double, double, double, double, double, double, double, double) setLookAt()}. 7201 * 7202 * @see #lookAt(Vector3d, Vector3d, Vector3d) 7203 * @see #setLookAt(double, double, double, double, double, double, double, double, double) 7204 * 7205 * @param eyeX 7206 * the x-coordinate of the eye/camera location 7207 * @param eyeY 7208 * the y-coordinate of the eye/camera location 7209 * @param eyeZ 7210 * the z-coordinate of the eye/camera location 7211 * @param centerX 7212 * the x-coordinate of the point to look at 7213 * @param centerY 7214 * the y-coordinate of the point to look at 7215 * @param centerZ 7216 * the z-coordinate of the point to look at 7217 * @param upX 7218 * the x-coordinate of the up vector 7219 * @param upY 7220 * the y-coordinate of the up vector 7221 * @param upZ 7222 * the z-coordinate of the up vector 7223 * @return this 7224 */ 7225 ref public Matrix4x3d lookAt(double eyeX, double eyeY, double eyeZ, 7226 double centerX, double centerY, double centerZ, 7227 double upX, double upY, double upZ) return { 7228 lookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, this); 7229 return this; 7230 } 7231 7232 /** 7233 * Set this matrix to be a "lookat" transformation for a left-handed coordinate system, that aligns 7234 * <code>+z</code> with <code>center - eye</code>. 7235 * <p> 7236 * In order to not make use of vectors to specify <code>eye</code>, <code>center</code> and <code>up</code> but use primitives, 7237 * like in the GLU function, use {@link #setLookAtLH(double, double, double, double, double, double, double, double, double) setLookAtLH()} 7238 * instead. 7239 * <p> 7240 * In order to apply the lookat transformation to a previous existing transformation, 7241 * use {@link #lookAtLH(Vector3d, Vector3d, Vector3d) lookAt()}. 7242 * 7243 * @see #setLookAtLH(double, double, double, double, double, double, double, double, double) 7244 * @see #lookAtLH(Vector3d, Vector3d, Vector3d) 7245 * 7246 * @param eye 7247 * the position of the camera 7248 * @param center 7249 * the point in space to look at 7250 * @param up 7251 * the direction of 'up' 7252 * @return this 7253 */ 7254 ref public Matrix4x3d setLookAtLH(Vector3d eye, Vector3d center, Vector3d up) return { 7255 return setLookAtLH(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z); 7256 } 7257 7258 /** 7259 * Set this matrix to be a "lookat" transformation for a left-handed coordinate system, 7260 * that aligns <code>+z</code> with <code>center - eye</code>. 7261 * <p> 7262 * In order to apply the lookat transformation to a previous existing transformation, 7263 * use {@link #lookAtLH(double, double, double, double, double, double, double, double, double) lookAtLH}. 7264 * 7265 * @see #setLookAtLH(Vector3d, Vector3d, Vector3d) 7266 * @see #lookAtLH(double, double, double, double, double, double, double, double, double) 7267 * 7268 * @param eyeX 7269 * the x-coordinate of the eye/camera location 7270 * @param eyeY 7271 * the y-coordinate of the eye/camera location 7272 * @param eyeZ 7273 * the z-coordinate of the eye/camera location 7274 * @param centerX 7275 * the x-coordinate of the point to look at 7276 * @param centerY 7277 * the y-coordinate of the point to look at 7278 * @param centerZ 7279 * the z-coordinate of the point to look at 7280 * @param upX 7281 * the x-coordinate of the up vector 7282 * @param upY 7283 * the y-coordinate of the up vector 7284 * @param upZ 7285 * the z-coordinate of the up vector 7286 * @return this 7287 */ 7288 ref public Matrix4x3d setLookAtLH(double eyeX, double eyeY, double eyeZ, 7289 double centerX, double centerY, double centerZ, 7290 double upX, double upY, double upZ) return { 7291 // Compute direction from position to lookAt 7292 double dirX, dirY, dirZ; 7293 dirX = centerX - eyeX; 7294 dirY = centerY - eyeY; 7295 dirZ = centerZ - eyeZ; 7296 // Normalize direction 7297 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7298 dirX *= invDirLength; 7299 dirY *= invDirLength; 7300 dirZ *= invDirLength; 7301 // left = up x direction 7302 double leftX, leftY, leftZ; 7303 leftX = upY * dirZ - upZ * dirY; 7304 leftY = upZ * dirX - upX * dirZ; 7305 leftZ = upX * dirY - upY * dirX; 7306 // normalize left 7307 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7308 leftX *= invLeftLength; 7309 leftY *= invLeftLength; 7310 leftZ *= invLeftLength; 7311 // up = direction x left 7312 double upnX = dirY * leftZ - dirZ * leftY; 7313 double upnY = dirZ * leftX - dirX * leftZ; 7314 double upnZ = dirX * leftY - dirY * leftX; 7315 7316 m00 = leftX; 7317 m01 = upnX; 7318 m02 = dirX; 7319 m10 = leftY; 7320 m11 = upnY; 7321 m12 = dirY; 7322 m20 = leftZ; 7323 m21 = upnZ; 7324 m22 = dirZ; 7325 m30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 7326 m31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 7327 m32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 7328 properties = PROPERTY_ORTHONORMAL; 7329 7330 return this; 7331 } 7332 7333 /** 7334 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7335 * that aligns <code>+z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 7336 * <p> 7337 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7338 * then the new matrix will be <code>M * L</code>. So when transforming a 7339 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7340 * the lookat transformation will be applied first! 7341 * <p> 7342 * In order to set the matrix to a lookat transformation without post-multiplying it, 7343 * use {@link #setLookAtLH(Vector3d, Vector3d, Vector3d)}. 7344 * 7345 * @see #lookAtLH(double, double, double, double, double, double, double, double, double) 7346 * 7347 * @param eye 7348 * the position of the camera 7349 * @param center 7350 * the point in space to look at 7351 * @param up 7352 * the direction of 'up' 7353 * @param dest 7354 * will hold the result 7355 * @return dest 7356 */ 7357 public Matrix4x3d lookAtLH(Vector3d eye, Vector3d center, Vector3d up, ref Matrix4x3d dest) { 7358 return lookAtLH(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, dest); 7359 } 7360 7361 /** 7362 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7363 * that aligns <code>+z</code> with <code>center - eye</code>. 7364 * <p> 7365 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7366 * then the new matrix will be <code>M * L</code>. So when transforming a 7367 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7368 * the lookat transformation will be applied first! 7369 * <p> 7370 * In order to set the matrix to a lookat transformation without post-multiplying it, 7371 * use {@link #setLookAtLH(Vector3d, Vector3d, Vector3d)}. 7372 * 7373 * @see #lookAtLH(double, double, double, double, double, double, double, double, double) 7374 * 7375 * @param eye 7376 * the position of the camera 7377 * @param center 7378 * the point in space to look at 7379 * @param up 7380 * the direction of 'up' 7381 * @return this 7382 */ 7383 ref public Matrix4x3d lookAtLH(Vector3d eye, Vector3d center, Vector3d up) return { 7384 lookAtLH(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z, this); 7385 return this; 7386 } 7387 7388 /** 7389 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7390 * that aligns <code>+z</code> with <code>center - eye</code> and store the result in <code>dest</code>. 7391 * <p> 7392 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7393 * then the new matrix will be <code>M * L</code>. So when transforming a 7394 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7395 * the lookat transformation will be applied first! 7396 * <p> 7397 * In order to set the matrix to a lookat transformation without post-multiplying it, 7398 * use {@link #setLookAtLH(double, double, double, double, double, double, double, double, double) setLookAtLH()}. 7399 * 7400 * @see #lookAtLH(Vector3d, Vector3d, Vector3d) 7401 * @see #setLookAtLH(double, double, double, double, double, double, double, double, double) 7402 * 7403 * @param eyeX 7404 * the x-coordinate of the eye/camera location 7405 * @param eyeY 7406 * the y-coordinate of the eye/camera location 7407 * @param eyeZ 7408 * the z-coordinate of the eye/camera location 7409 * @param centerX 7410 * the x-coordinate of the point to look at 7411 * @param centerY 7412 * the y-coordinate of the point to look at 7413 * @param centerZ 7414 * the z-coordinate of the point to look at 7415 * @param upX 7416 * the x-coordinate of the up vector 7417 * @param upY 7418 * the y-coordinate of the up vector 7419 * @param upZ 7420 * the z-coordinate of the up vector 7421 * @param dest 7422 * will hold the result 7423 * @return dest 7424 */ 7425 public Matrix4x3d lookAtLH(double eyeX, double eyeY, double eyeZ, 7426 double centerX, double centerY, double centerZ, 7427 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7428 if ((properties & PROPERTY_IDENTITY) != 0) 7429 return dest.setLookAtLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); 7430 return lookAtLHGeneric(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, dest); 7431 } 7432 private Matrix4x3d lookAtLHGeneric(double eyeX, double eyeY, double eyeZ, 7433 double centerX, double centerY, double centerZ, 7434 double upX, double upY, double upZ, ref Matrix4x3d dest) { 7435 // Compute direction from position to lookAt 7436 double dirX, dirY, dirZ; 7437 dirX = centerX - eyeX; 7438 dirY = centerY - eyeY; 7439 dirZ = centerZ - eyeZ; 7440 // Normalize direction 7441 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7442 dirX *= invDirLength; 7443 dirY *= invDirLength; 7444 dirZ *= invDirLength; 7445 // left = up x direction 7446 double leftX, leftY, leftZ; 7447 leftX = upY * dirZ - upZ * dirY; 7448 leftY = upZ * dirX - upX * dirZ; 7449 leftZ = upX * dirY - upY * dirX; 7450 // normalize left 7451 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7452 leftX *= invLeftLength; 7453 leftY *= invLeftLength; 7454 leftZ *= invLeftLength; 7455 // up = direction x left 7456 double upnX = dirY * leftZ - dirZ * leftY; 7457 double upnY = dirZ * leftX - dirX * leftZ; 7458 double upnZ = dirX * leftY - dirY * leftX; 7459 7460 // calculate right matrix elements 7461 double rm00 = leftX; 7462 double rm01 = upnX; 7463 double rm02 = dirX; 7464 double rm10 = leftY; 7465 double rm11 = upnY; 7466 double rm12 = dirY; 7467 double rm20 = leftZ; 7468 double rm21 = upnZ; 7469 double rm22 = dirZ; 7470 double rm30 = -(leftX * eyeX + leftY * eyeY + leftZ * eyeZ); 7471 double rm31 = -(upnX * eyeX + upnY * eyeY + upnZ * eyeZ); 7472 double rm32 = -(dirX * eyeX + dirY * eyeY + dirZ * eyeZ); 7473 7474 // perform optimized matrix multiplication 7475 // compute last column first, because others do not depend on it 7476 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30; 7477 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31; 7478 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32; 7479 // introduce temporaries for dependent results 7480 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 7481 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 7482 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 7483 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 7484 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 7485 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 7486 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 7487 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 7488 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 7489 // set the rest of the matrix elements 7490 dest.m00 = nm00; 7491 dest.m01 = nm01; 7492 dest.m02 = nm02; 7493 dest.m10 = nm10; 7494 dest.m11 = nm11; 7495 dest.m12 = nm12; 7496 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 7497 7498 return dest; 7499 } 7500 7501 /** 7502 * Apply a "lookat" transformation to this matrix for a left-handed coordinate system, 7503 * that aligns <code>+z</code> with <code>center - eye</code>. 7504 * <p> 7505 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 7506 * then the new matrix will be <code>M * L</code>. So when transforming a 7507 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 7508 * the lookat transformation will be applied first! 7509 * <p> 7510 * In order to set the matrix to a lookat transformation without post-multiplying it, 7511 * use {@link #setLookAtLH(double, double, double, double, double, double, double, double, double) setLookAtLH()}. 7512 * 7513 * @see #lookAtLH(Vector3d, Vector3d, Vector3d) 7514 * @see #setLookAtLH(double, double, double, double, double, double, double, double, double) 7515 * 7516 * @param eyeX 7517 * the x-coordinate of the eye/camera location 7518 * @param eyeY 7519 * the y-coordinate of the eye/camera location 7520 * @param eyeZ 7521 * the z-coordinate of the eye/camera location 7522 * @param centerX 7523 * the x-coordinate of the point to look at 7524 * @param centerY 7525 * the y-coordinate of the point to look at 7526 * @param centerZ 7527 * the z-coordinate of the point to look at 7528 * @param upX 7529 * the x-coordinate of the up vector 7530 * @param upY 7531 * the y-coordinate of the up vector 7532 * @param upZ 7533 * the z-coordinate of the up vector 7534 * @return this 7535 */ 7536 ref public Matrix4x3d lookAtLH(double eyeX, double eyeY, double eyeZ, 7537 double centerX, double centerY, double centerZ, 7538 double upX, double upY, double upZ) return { 7539 lookAtLH(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ, this); 7540 return this; 7541 } 7542 7543 public Vector4d frustumPlane(int which, Vector4d dest) { 7544 switch (which) { 7545 case PLANE_NX: 7546 dest.set(m00, m10, m20, 1.0 + m30).normalize(); 7547 break; 7548 case PLANE_PX: 7549 dest.set(-m00, -m10, -m20, 1.0 - m30).normalize(); 7550 break; 7551 case PLANE_NY: 7552 dest.set(m01, m11, m21, 1.0 + m31).normalize(); 7553 break; 7554 case PLANE_PY: 7555 dest.set(-m01, -m11, -m21, 1.0 - m31).normalize(); 7556 break; 7557 case PLANE_NZ: 7558 dest.set(m02, m12, m22, 1.0 + m32).normalize(); 7559 break; 7560 case PLANE_PZ: 7561 dest.set(-m02, -m12, -m22, 1.0 - m32).normalize(); 7562 break; 7563 default: 7564 // do nothing 7565 } 7566 return dest; 7567 } 7568 7569 public Vector3d positiveZ(ref Vector3d dir) { 7570 dir.x = m10 * m21 - m11 * m20; 7571 dir.y = m20 * m01 - m21 * m00; 7572 dir.z = m00 * m11 - m01 * m10; 7573 return dir.normalize(dir); 7574 } 7575 7576 public Vector3d normalizedPositiveZ(ref Vector3d dir) { 7577 dir.x = m02; 7578 dir.y = m12; 7579 dir.z = m22; 7580 return dir; 7581 } 7582 7583 public Vector3d positiveX(ref Vector3d dir) { 7584 dir.x = m11 * m22 - m12 * m21; 7585 dir.y = m02 * m21 - m01 * m22; 7586 dir.z = m01 * m12 - m02 * m11; 7587 return dir.normalize(dir); 7588 } 7589 7590 public Vector3d normalizedPositiveX(ref Vector3d dir) { 7591 dir.x = m00; 7592 dir.y = m10; 7593 dir.z = m20; 7594 return dir; 7595 } 7596 7597 public Vector3d positiveY(ref Vector3d dir) { 7598 dir.x = m12 * m20 - m10 * m22; 7599 dir.y = m00 * m22 - m02 * m20; 7600 dir.z = m02 * m10 - m00 * m12; 7601 return dir.normalize(dir); 7602 } 7603 7604 public Vector3d normalizedPositiveY(ref Vector3d dir) { 7605 dir.x = m01; 7606 dir.y = m11; 7607 dir.z = m21; 7608 return dir; 7609 } 7610 7611 public Vector3d origin(Vector3d origin) { 7612 double a = m00 * m11 - m01 * m10; 7613 double b = m00 * m12 - m02 * m10; 7614 double d = m01 * m12 - m02 * m11; 7615 double g = m20 * m31 - m21 * m30; 7616 double h = m20 * m32 - m22 * m30; 7617 double j = m21 * m32 - m22 * m31; 7618 origin.x = -m10 * j + m11 * h - m12 * g; 7619 origin.y = m00 * j - m01 * h + m02 * g; 7620 origin.z = -m30 * d + m31 * b - m32 * a; 7621 return origin; 7622 } 7623 7624 /** 7625 * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation 7626 * <code>x*a + y*b + z*c + d = 0</code> as if casting a shadow from a given light position/direction <code>light</code>. 7627 * <p> 7628 * If <code>light.w</code> is <code>0.0</code> the light is being treated as a directional light; if it is <code>1.0</code> it is a point light. 7629 * <p> 7630 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7631 * then the new matrix will be <code>M * S</code>. So when transforming a 7632 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7633 * shadow projection will be applied first! 7634 * <p> 7635 * Reference: <a href="ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node192.html">ftp.sgi.com</a> 7636 * 7637 * @param light 7638 * the light's vector 7639 * @param a 7640 * the x factor in the plane equation 7641 * @param b 7642 * the y factor in the plane equation 7643 * @param c 7644 * the z factor in the plane equation 7645 * @param d 7646 * the constant in the plane equation 7647 * @return this 7648 */ 7649 ref public Matrix4x3d shadow(Vector4d light, double a, double b, double c, double d) return { 7650 shadow(light.x, light.y, light.z, light.w, a, b, c, d, this); 7651 return this; 7652 } 7653 7654 public Matrix4x3d shadow(Vector4d light, double a, double b, double c, double d, ref Matrix4x3d dest) { 7655 return shadow(light.x, light.y, light.z, light.w, a, b, c, d, dest); 7656 } 7657 7658 /** 7659 * Apply a projection transformation to this matrix that projects onto the plane specified via the general plane equation 7660 * <code>x*a + y*b + z*c + d = 0</code> as if casting a shadow from a given light position/direction <code>(lightX, lightY, lightZ, lightW)</code>. 7661 * <p> 7662 * If <code>lightW</code> is <code>0.0</code> the light is being treated as a directional light; if it is <code>1.0</code> it is a point light. 7663 * <p> 7664 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7665 * then the new matrix will be <code>M * S</code>. So when transforming a 7666 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7667 * shadow projection will be applied first! 7668 * <p> 7669 * Reference: <a href="ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node192.html">ftp.sgi.com</a> 7670 * 7671 * @param lightX 7672 * the x-component of the light's vector 7673 * @param lightY 7674 * the y-component of the light's vector 7675 * @param lightZ 7676 * the z-component of the light's vector 7677 * @param lightW 7678 * the w-component of the light's vector 7679 * @param a 7680 * the x factor in the plane equation 7681 * @param b 7682 * the y factor in the plane equation 7683 * @param c 7684 * the z factor in the plane equation 7685 * @param d 7686 * the constant in the plane equation 7687 * @return this 7688 */ 7689 ref public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, double a, double b, double c, double d) return { 7690 shadow(lightX, lightY, lightZ, lightW, a, b, c, d, this); 7691 return this; 7692 } 7693 7694 public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, double a, double b, double c, double d, ref Matrix4x3d dest) { 7695 // normalize plane 7696 double invPlaneLen = Math.invsqrt(a*a + b*b + c*c); 7697 double an = a * invPlaneLen; 7698 double bn = b * invPlaneLen; 7699 double cn = c * invPlaneLen; 7700 double dn = d * invPlaneLen; 7701 7702 double dot = an * lightX + bn * lightY + cn * lightZ + dn * lightW; 7703 7704 // compute right matrix elements 7705 double rm00 = dot - an * lightX; 7706 double rm01 = -an * lightY; 7707 double rm02 = -an * lightZ; 7708 double rm03 = -an * lightW; 7709 double rm10 = -bn * lightX; 7710 double rm11 = dot - bn * lightY; 7711 double rm12 = -bn * lightZ; 7712 double rm13 = -bn * lightW; 7713 double rm20 = -cn * lightX; 7714 double rm21 = -cn * lightY; 7715 double rm22 = dot - cn * lightZ; 7716 double rm23 = -cn * lightW; 7717 double rm30 = -dn * lightX; 7718 double rm31 = -dn * lightY; 7719 double rm32 = -dn * lightZ; 7720 double rm33 = dot - dn * lightW; 7721 7722 // matrix multiplication 7723 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02 + m30 * rm03; 7724 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02 + m31 * rm03; 7725 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02 + m32 * rm03; 7726 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12 + m30 * rm13; 7727 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12 + m31 * rm13; 7728 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12 + m32 * rm13; 7729 double nm20 = m00 * rm20 + m10 * rm21 + m20 * rm22 + m30 * rm23; 7730 double nm21 = m01 * rm20 + m11 * rm21 + m21 * rm22 + m31 * rm23; 7731 double nm22 = m02 * rm20 + m12 * rm21 + m22 * rm22 + m32 * rm23; 7732 dest.m30 = m00 * rm30 + m10 * rm31 + m20 * rm32 + m30 * rm33; 7733 dest.m31 = m01 * rm30 + m11 * rm31 + m21 * rm32 + m31 * rm33; 7734 dest.m32 = m02 * rm30 + m12 * rm31 + m22 * rm32 + m32 * rm33; 7735 dest.m00 = nm00; 7736 dest.m01 = nm01; 7737 dest.m02 = nm02; 7738 dest.m10 = nm10; 7739 dest.m11 = nm11; 7740 dest.m12 = nm12; 7741 dest.m20 = nm20; 7742 dest.m21 = nm21; 7743 dest.m22 = nm22; 7744 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION | PROPERTY_ORTHONORMAL); 7745 7746 return dest; 7747 } 7748 7749 public Matrix4x3d shadow(Vector4d light, Matrix4x3d planeTransform, ref Matrix4x3d dest) { 7750 // compute plane equation by transforming (y = 0) 7751 double a = planeTransform.m10; 7752 double b = planeTransform.m11; 7753 double c = planeTransform.m12; 7754 double d = -a * planeTransform.m30 - b * planeTransform.m31 - c * planeTransform.m32; 7755 return shadow(light.x, light.y, light.z, light.w, a, b, c, d, dest); 7756 } 7757 7758 /** 7759 * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation 7760 * <code>y = 0</code> as if casting a shadow from a given light position/direction <code>light</code>. 7761 * <p> 7762 * Before the shadow projection is applied, the plane is transformed via the specified <code>planeTransformation</code>. 7763 * <p> 7764 * If <code>light.w</code> is <code>0.0</code> the light is being treated as a directional light; if it is <code>1.0</code> it is a point light. 7765 * <p> 7766 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7767 * then the new matrix will be <code>M * S</code>. So when transforming a 7768 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7769 * shadow projection will be applied first! 7770 * 7771 * @param light 7772 * the light's vector 7773 * @param planeTransform 7774 * the transformation to transform the implied plane <code>y = 0</code> before applying the projection 7775 * @return this 7776 */ 7777 ref public Matrix4x3d shadow(Vector4d light, Matrix4x3d planeTransform) return { 7778 shadow(light, planeTransform, this); 7779 return this; 7780 } 7781 7782 public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, Matrix4x3d planeTransform, ref Matrix4x3d dest) { 7783 // compute plane equation by transforming (y = 0) 7784 double a = planeTransform.m10; 7785 double b = planeTransform.m11; 7786 double c = planeTransform.m12; 7787 double d = -a * planeTransform.m30 - b * planeTransform.m31 - c * planeTransform.m32; 7788 return shadow(lightX, lightY, lightZ, lightW, a, b, c, d, dest); 7789 } 7790 7791 /** 7792 * Apply a projection transformation to this matrix that projects onto the plane with the general plane equation 7793 * <code>y = 0</code> as if casting a shadow from a given light position/direction <code>(lightX, lightY, lightZ, lightW)</code>. 7794 * <p> 7795 * Before the shadow projection is applied, the plane is transformed via the specified <code>planeTransformation</code>. 7796 * <p> 7797 * If <code>lightW</code> is <code>0.0</code> the light is being treated as a directional light; if it is <code>1.0</code> it is a point light. 7798 * <p> 7799 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the shadow matrix, 7800 * then the new matrix will be <code>M * S</code>. So when transforming a 7801 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 7802 * shadow projection will be applied first! 7803 * 7804 * @param lightX 7805 * the x-component of the light vector 7806 * @param lightY 7807 * the y-component of the light vector 7808 * @param lightZ 7809 * the z-component of the light vector 7810 * @param lightW 7811 * the w-component of the light vector 7812 * @param planeTransform 7813 * the transformation to transform the implied plane <code>y = 0</code> before applying the projection 7814 * @return this 7815 */ 7816 ref public Matrix4x3d shadow(double lightX, double lightY, double lightZ, double lightW, Matrix4x3d planeTransform) return { 7817 shadow(lightX, lightY, lightZ, lightW, planeTransform, this); 7818 return this; 7819 } 7820 7821 /** 7822 * Set this matrix to a cylindrical billboard transformation that rotates the local +Z axis of a given object with position <code>objPos</code> towards 7823 * a target position at <code>targetPos</code> while constraining a cylindrical rotation around the given <code>up</code> vector. 7824 * <p> 7825 * This method can be used to create the complete model transformation for a given object, including the translation of the object to 7826 * its position <code>objPos</code>. 7827 * 7828 * @param objPos 7829 * the position of the object to rotate towards <code>targetPos</code> 7830 * @param targetPos 7831 * the position of the target (for example the camera) towards which to rotate the object 7832 * @param up 7833 * the rotation axis (must be {@link Vector3d#normalize() normalized}) 7834 * @return this 7835 */ 7836 ref public Matrix4x3d billboardCylindrical(Vector3d objPos, Vector3d targetPos, Vector3d up) return { 7837 double dirX = targetPos.x - objPos.x; 7838 double dirY = targetPos.y - objPos.y; 7839 double dirZ = targetPos.z - objPos.z; 7840 // left = up x dir 7841 double leftX = up.y * dirZ - up.z * dirY; 7842 double leftY = up.z * dirX - up.x * dirZ; 7843 double leftZ = up.x * dirY - up.y * dirX; 7844 // normalize left 7845 double invLeftLen = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7846 leftX *= invLeftLen; 7847 leftY *= invLeftLen; 7848 leftZ *= invLeftLen; 7849 // recompute dir by constraining rotation around 'up' 7850 // dir = left x up 7851 dirX = leftY * up.z - leftZ * up.y; 7852 dirY = leftZ * up.x - leftX * up.z; 7853 dirZ = leftX * up.y - leftY * up.x; 7854 // normalize dir 7855 double invDirLen = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7856 dirX *= invDirLen; 7857 dirY *= invDirLen; 7858 dirZ *= invDirLen; 7859 // set matrix elements 7860 m00 = leftX; 7861 m01 = leftY; 7862 m02 = leftZ; 7863 m10 = up.x; 7864 m11 = up.y; 7865 m12 = up.z; 7866 m20 = dirX; 7867 m21 = dirY; 7868 m22 = dirZ; 7869 m30 = objPos.x; 7870 m31 = objPos.y; 7871 m32 = objPos.z; 7872 properties = PROPERTY_ORTHONORMAL; 7873 return this; 7874 } 7875 7876 /** 7877 * Set this matrix to a spherical billboard transformation that rotates the local +Z axis of a given object with position <code>objPos</code> towards 7878 * a target position at <code>targetPos</code>. 7879 * <p> 7880 * This method can be used to create the complete model transformation for a given object, including the translation of the object to 7881 * its position <code>objPos</code>. 7882 * <p> 7883 * If preserving an <i>up</i> vector is not necessary when rotating the +Z axis, then a shortest arc rotation can be obtained 7884 * using {@link #billboardSpherical(Vector3d, Vector3d)}. 7885 * 7886 * @see #billboardSpherical(Vector3d, Vector3d) 7887 * 7888 * @param objPos 7889 * the position of the object to rotate towards <code>targetPos</code> 7890 * @param targetPos 7891 * the position of the target (for example the camera) towards which to rotate the object 7892 * @param up 7893 * the up axis used to orient the object 7894 * @return this 7895 */ 7896 ref public Matrix4x3d billboardSpherical(Vector3d objPos, Vector3d targetPos, Vector3d up) return { 7897 double dirX = targetPos.x - objPos.x; 7898 double dirY = targetPos.y - objPos.y; 7899 double dirZ = targetPos.z - objPos.z; 7900 // normalize dir 7901 double invDirLen = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 7902 dirX *= invDirLen; 7903 dirY *= invDirLen; 7904 dirZ *= invDirLen; 7905 // left = up x dir 7906 double leftX = up.y * dirZ - up.z * dirY; 7907 double leftY = up.z * dirX - up.x * dirZ; 7908 double leftZ = up.x * dirY - up.y * dirX; 7909 // normalize left 7910 double invLeftLen = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 7911 leftX *= invLeftLen; 7912 leftY *= invLeftLen; 7913 leftZ *= invLeftLen; 7914 // up = dir x left 7915 double upX = dirY * leftZ - dirZ * leftY; 7916 double upY = dirZ * leftX - dirX * leftZ; 7917 double upZ = dirX * leftY - dirY * leftX; 7918 // set matrix elements 7919 m00 = leftX; 7920 m01 = leftY; 7921 m02 = leftZ; 7922 m10 = upX; 7923 m11 = upY; 7924 m12 = upZ; 7925 m20 = dirX; 7926 m21 = dirY; 7927 m22 = dirZ; 7928 m30 = objPos.x; 7929 m31 = objPos.y; 7930 m32 = objPos.z; 7931 properties = PROPERTY_ORTHONORMAL; 7932 return this; 7933 } 7934 7935 /** 7936 * Set this matrix to a spherical billboard transformation that rotates the local +Z axis of a given object with position <code>objPos</code> towards 7937 * a target position at <code>targetPos</code> using a shortest arc rotation by not preserving any <i>up</i> vector of the object. 7938 * <p> 7939 * This method can be used to create the complete model transformation for a given object, including the translation of the object to 7940 * its position <code>objPos</code>. 7941 * <p> 7942 * In order to specify an <i>up</i> vector which needs to be maintained when rotating the +Z axis of the object, 7943 * use {@link #billboardSpherical(Vector3d, Vector3d, Vector3d)}. 7944 * 7945 * @see #billboardSpherical(Vector3d, Vector3d, Vector3d) 7946 * 7947 * @param objPos 7948 * the position of the object to rotate towards <code>targetPos</code> 7949 * @param targetPos 7950 * the position of the target (for example the camera) towards which to rotate the object 7951 * @return this 7952 */ 7953 ref public Matrix4x3d billboardSpherical(Vector3d objPos, Vector3d targetPos) return { 7954 double toDirX = targetPos.x - objPos.x; 7955 double toDirY = targetPos.y - objPos.y; 7956 double toDirZ = targetPos.z - objPos.z; 7957 double x = -toDirY; 7958 double y = toDirX; 7959 double w = Math.sqrt(toDirX * toDirX + toDirY * toDirY + toDirZ * toDirZ) + toDirZ; 7960 double invNorm = Math.invsqrt(x * x + y * y + w * w); 7961 x *= invNorm; 7962 y *= invNorm; 7963 w *= invNorm; 7964 double q00 = (x + x) * x; 7965 double q11 = (y + y) * y; 7966 double q01 = (x + x) * y; 7967 double q03 = (x + x) * w; 7968 double q13 = (y + y) * w; 7969 m00 = 1.0 - q11; 7970 m01 = q01; 7971 m02 = -q13; 7972 m10 = q01; 7973 m11 = 1.0 - q00; 7974 m12 = q03; 7975 m20 = q13; 7976 m21 = -q03; 7977 m22 = 1.0 - q11 - q00; 7978 m30 = objPos.x; 7979 m31 = objPos.y; 7980 m32 = objPos.z; 7981 properties = PROPERTY_ORTHONORMAL; 7982 return this; 7983 } 7984 7985 public int hashCode() { 7986 immutable int prime = 31; 7987 int result = 1; 7988 long temp; 7989 temp = Math.doubleToLongBits(m00); 7990 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7991 temp = Math.doubleToLongBits(m01); 7992 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7993 temp = Math.doubleToLongBits(m02); 7994 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7995 temp = Math.doubleToLongBits(m10); 7996 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7997 temp = Math.doubleToLongBits(m11); 7998 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 7999 temp = Math.doubleToLongBits(m12); 8000 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 8001 temp = Math.doubleToLongBits(m20); 8002 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 8003 temp = Math.doubleToLongBits(m21); 8004 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 8005 temp = Math.doubleToLongBits(m22); 8006 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 8007 temp = Math.doubleToLongBits(m30); 8008 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 8009 temp = Math.doubleToLongBits(m31); 8010 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 8011 temp = Math.doubleToLongBits(m32); 8012 result = prime * result + cast(int) (temp ^ (temp >>> 32)); 8013 return result; 8014 } 8015 8016 public bool equals(Matrix4x3d m, double delta) { 8017 if (this == m) 8018 return true; 8019 if (!Math.equals(m00, m.m00, delta)) 8020 return false; 8021 if (!Math.equals(m01, m.m01, delta)) 8022 return false; 8023 if (!Math.equals(m02, m.m02, delta)) 8024 return false; 8025 if (!Math.equals(m10, m.m10, delta)) 8026 return false; 8027 if (!Math.equals(m11, m.m11, delta)) 8028 return false; 8029 if (!Math.equals(m12, m.m12, delta)) 8030 return false; 8031 if (!Math.equals(m20, m.m20, delta)) 8032 return false; 8033 if (!Math.equals(m21, m.m21, delta)) 8034 return false; 8035 if (!Math.equals(m22, m.m22, delta)) 8036 return false; 8037 if (!Math.equals(m30, m.m30, delta)) 8038 return false; 8039 if (!Math.equals(m31, m.m31, delta)) 8040 return false; 8041 if (!Math.equals(m32, m.m32, delta)) 8042 return false; 8043 return true; 8044 } 8045 8046 public Matrix4x3d pick(double x, double y, double width, double height, int[] viewport, ref Matrix4x3d dest) { 8047 double sx = viewport[2] / width; 8048 double sy = viewport[3] / height; 8049 double tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width; 8050 double ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height; 8051 dest.m30 = m00 * tx + m10 * ty + m30; 8052 dest.m31 = m01 * tx + m11 * ty + m31; 8053 dest.m32 = m02 * tx + m12 * ty + m32; 8054 dest.m00 = m00 * sx; 8055 dest.m01 = m01 * sx; 8056 dest.m02 = m02 * sx; 8057 dest.m10 = m10 * sy; 8058 dest.m11 = m11 * sy; 8059 dest.m12 = m12 * sy; 8060 dest.properties = 0; 8061 return dest; 8062 } 8063 8064 /** 8065 * Apply a picking transformation to this matrix using the given window coordinates <code>(x, y)</code> as the pick center 8066 * and the given <code>(width, height)</code> as the size of the picking region in window coordinates. 8067 * 8068 * @param x 8069 * the x coordinate of the picking region center in window coordinates 8070 * @param y 8071 * the y coordinate of the picking region center in window coordinates 8072 * @param width 8073 * the width of the picking region in window coordinates 8074 * @param height 8075 * the height of the picking region in window coordinates 8076 * @param viewport 8077 * the viewport described by <code>[x, y, width, height]</code> 8078 * @return this 8079 */ 8080 ref public Matrix4x3d pick(double x, double y, double width, double height, int[] viewport) return { 8081 pick(x, y, width, height, viewport, this); 8082 return this; 8083 } 8084 8085 /** 8086 * Exchange the values of <code>this</code> matrix with the given <code>other</code> matrix. 8087 * 8088 * @param other 8089 * the other matrix to exchange the values with 8090 * @return this 8091 */ 8092 ref public Matrix4x3d swap(ref Matrix4x3d other) return { 8093 double tmp; 8094 tmp = m00; m00 = other.m00; other.m00 = tmp; 8095 tmp = m01; m01 = other.m01; other.m01 = tmp; 8096 tmp = m02; m02 = other.m02; other.m02 = tmp; 8097 tmp = m10; m10 = other.m10; other.m10 = tmp; 8098 tmp = m11; m11 = other.m11; other.m11 = tmp; 8099 tmp = m12; m12 = other.m12; other.m12 = tmp; 8100 tmp = m20; m20 = other.m20; other.m20 = tmp; 8101 tmp = m21; m21 = other.m21; other.m21 = tmp; 8102 tmp = m22; m22 = other.m22; other.m22 = tmp; 8103 tmp = m30; m30 = other.m30; other.m30 = tmp; 8104 tmp = m31; m31 = other.m31; other.m31 = tmp; 8105 tmp = m32; m32 = other.m32; other.m32 = tmp; 8106 int props = properties; 8107 this.properties = other.properties; 8108 other.properties = props; 8109 return this; 8110 } 8111 8112 public Matrix4x3d arcball(double radius, double centerX, double centerY, double centerZ, double angleX, double angleY, ref Matrix4x3d dest) { 8113 double m30 = m20 * -radius + this.m30; 8114 double m31 = m21 * -radius + this.m31; 8115 double m32 = m22 * -radius + this.m32; 8116 double sin = Math.sin(angleX); 8117 double cos = Math.cosFromSin(sin, angleX); 8118 double nm10 = m10 * cos + m20 * sin; 8119 double nm11 = m11 * cos + m21 * sin; 8120 double nm12 = m12 * cos + m22 * sin; 8121 double m20 = this.m20 * cos - m10 * sin; 8122 double m21 = this.m21 * cos - m11 * sin; 8123 double m22 = this.m22 * cos - m12 * sin; 8124 sin = Math.sin(angleY); 8125 cos = Math.cosFromSin(sin, angleY); 8126 double nm00 = m00 * cos - m20 * sin; 8127 double nm01 = m01 * cos - m21 * sin; 8128 double nm02 = m02 * cos - m22 * sin; 8129 double nm20 = m00 * sin + m20 * cos; 8130 double nm21 = m01 * sin + m21 * cos; 8131 double nm22 = m02 * sin + m22 * cos; 8132 dest.m30 = -nm00 * centerX - nm10 * centerY - nm20 * centerZ + m30; 8133 dest.m31 = -nm01 * centerX - nm11 * centerY - nm21 * centerZ + m31; 8134 dest.m32 = -nm02 * centerX - nm12 * centerY - nm22 * centerZ + m32; 8135 dest.m20 = nm20; 8136 dest.m21 = nm21; 8137 dest.m22 = nm22; 8138 dest.m10 = nm10; 8139 dest.m11 = nm11; 8140 dest.m12 = nm12; 8141 dest.m00 = nm00; 8142 dest.m01 = nm01; 8143 dest.m02 = nm02; 8144 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 8145 return dest; 8146 } 8147 8148 public Matrix4x3d arcball(double radius, Vector3d center, double angleX, double angleY, ref Matrix4x3d dest) { 8149 return arcball(radius, center.x, center.y, center.z, angleX, angleY, dest); 8150 } 8151 8152 /** 8153 * Apply an arcball view transformation to this matrix with the given <code>radius</code> and center <code>(centerX, centerY, centerZ)</code> 8154 * position of the arcball and the specified X and Y rotation angles. 8155 * <p> 8156 * This method is equivalent to calling: <code>translate(0, 0, -radius).rotateX(angleX).rotateY(angleY).translate(-centerX, -centerY, -centerZ)</code> 8157 * 8158 * @param radius 8159 * the arcball radius 8160 * @param centerX 8161 * the x coordinate of the center position of the arcball 8162 * @param centerY 8163 * the y coordinate of the center position of the arcball 8164 * @param centerZ 8165 * the z coordinate of the center position of the arcball 8166 * @param angleX 8167 * the rotation angle around the X axis in radians 8168 * @param angleY 8169 * the rotation angle around the Y axis in radians 8170 * @return this 8171 */ 8172 ref public Matrix4x3d arcball(double radius, double centerX, double centerY, double centerZ, double angleX, double angleY) return { 8173 arcball(radius, centerX, centerY, centerZ, angleX, angleY, this); 8174 return this; 8175 } 8176 8177 /** 8178 * Apply an arcball view transformation to this matrix with the given <code>radius</code> and <code>center</code> 8179 * position of the arcball and the specified X and Y rotation angles. 8180 * <p> 8181 * This method is equivalent to calling: <code>translate(0, 0, -radius).rotateX(angleX).rotateY(angleY).translate(-center.x, -center.y, -center.z)</code> 8182 * 8183 * @param radius 8184 * the arcball radius 8185 * @param center 8186 * the center position of the arcball 8187 * @param angleX 8188 * the rotation angle around the X axis in radians 8189 * @param angleY 8190 * the rotation angle around the Y axis in radians 8191 * @return this 8192 */ 8193 ref public Matrix4x3d arcball(double radius, Vector3d center, double angleX, double angleY) return { 8194 arcball(radius, center.x, center.y, center.z, angleX, angleY, this); 8195 return this; 8196 } 8197 8198 public Matrix4x3d transformAab(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, Vector3d outMin, Vector3d outMax) { 8199 double xax = m00 * minX, xay = m01 * minX, xaz = m02 * minX; 8200 double xbx = m00 * maxX, xby = m01 * maxX, xbz = m02 * maxX; 8201 double yax = m10 * minY, yay = m11 * minY, yaz = m12 * minY; 8202 double ybx = m10 * maxY, yby = m11 * maxY, ybz = m12 * maxY; 8203 double zax = m20 * minZ, zay = m21 * minZ, zaz = m22 * minZ; 8204 double zbx = m20 * maxZ, zby = m21 * maxZ, zbz = m22 * maxZ; 8205 double xminx, xminy, xminz, yminx, yminy, yminz, zminx, zminy, zminz; 8206 double xmaxx, xmaxy, xmaxz, ymaxx, ymaxy, ymaxz, zmaxx, zmaxy, zmaxz; 8207 if (xax < xbx) { 8208 xminx = xax; 8209 xmaxx = xbx; 8210 } else { 8211 xminx = xbx; 8212 xmaxx = xax; 8213 } 8214 if (xay < xby) { 8215 xminy = xay; 8216 xmaxy = xby; 8217 } else { 8218 xminy = xby; 8219 xmaxy = xay; 8220 } 8221 if (xaz < xbz) { 8222 xminz = xaz; 8223 xmaxz = xbz; 8224 } else { 8225 xminz = xbz; 8226 xmaxz = xaz; 8227 } 8228 if (yax < ybx) { 8229 yminx = yax; 8230 ymaxx = ybx; 8231 } else { 8232 yminx = ybx; 8233 ymaxx = yax; 8234 } 8235 if (yay < yby) { 8236 yminy = yay; 8237 ymaxy = yby; 8238 } else { 8239 yminy = yby; 8240 ymaxy = yay; 8241 } 8242 if (yaz < ybz) { 8243 yminz = yaz; 8244 ymaxz = ybz; 8245 } else { 8246 yminz = ybz; 8247 ymaxz = yaz; 8248 } 8249 if (zax < zbx) { 8250 zminx = zax; 8251 zmaxx = zbx; 8252 } else { 8253 zminx = zbx; 8254 zmaxx = zax; 8255 } 8256 if (zay < zby) { 8257 zminy = zay; 8258 zmaxy = zby; 8259 } else { 8260 zminy = zby; 8261 zmaxy = zay; 8262 } 8263 if (zaz < zbz) { 8264 zminz = zaz; 8265 zmaxz = zbz; 8266 } else { 8267 zminz = zbz; 8268 zmaxz = zaz; 8269 } 8270 outMin.x = xminx + yminx + zminx + m30; 8271 outMin.y = xminy + yminy + zminy + m31; 8272 outMin.z = xminz + yminz + zminz + m32; 8273 outMax.x = xmaxx + ymaxx + zmaxx + m30; 8274 outMax.y = xmaxy + ymaxy + zmaxy + m31; 8275 outMax.z = xmaxz + ymaxz + zmaxz + m32; 8276 return this; 8277 } 8278 8279 public Matrix4x3d transformAab(Vector3d min, Vector3d max, Vector3d outMin, Vector3d outMax) { 8280 return transformAab(min.x, min.y, min.z, max.x, max.y, max.z, outMin, outMax); 8281 } 8282 8283 /** 8284 * Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code> 8285 * and store the result in <code>this</code>. 8286 * <p> 8287 * If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code> 8288 * then the result is <code>other</code>. 8289 * 8290 * @param other 8291 * the other matrix 8292 * @param t 8293 * the interpolation factor between 0.0 and 1.0 8294 * @return this 8295 */ 8296 ref public Matrix4x3d lerp(Matrix4x3d other, double t) return { 8297 lerp(other, t, this); 8298 return this; 8299 } 8300 8301 public Matrix4x3d lerp(Matrix4x3d other, double t, ref Matrix4x3d dest) { 8302 dest.m00 = Math.fma(other.m00 - m00, t, m00); 8303 dest.m01 = Math.fma(other.m01 - m01, t, m01); 8304 dest.m02 = Math.fma(other.m02 - m02, t, m02); 8305 dest.m10 = Math.fma(other.m10 - m10, t, m10); 8306 dest.m11 = Math.fma(other.m11 - m11, t, m11); 8307 dest.m12 = Math.fma(other.m12 - m12, t, m12); 8308 dest.m20 = Math.fma(other.m20 - m20, t, m20); 8309 dest.m21 = Math.fma(other.m21 - m21, t, m21); 8310 dest.m22 = Math.fma(other.m22 - m22, t, m22); 8311 dest.m30 = Math.fma(other.m30 - m30, t, m30); 8312 dest.m31 = Math.fma(other.m31 - m31, t, m31); 8313 dest.m32 = Math.fma(other.m32 - m32, t, m32); 8314 dest.properties = properties & other.properties; 8315 return dest; 8316 } 8317 8318 /** 8319 * Apply a model transformation to this matrix for a right-handed coordinate system, 8320 * that aligns the local <code>+Z</code> axis with <code>dir</code> 8321 * and store the result in <code>dest</code>. 8322 * <p> 8323 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8324 * then the new matrix will be <code>M * L</code>. So when transforming a 8325 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8326 * the lookat transformation will be applied first! 8327 * <p> 8328 * In order to set the matrix to a rotation transformation without post-multiplying it, 8329 * use {@link #rotationTowards(Vector3d, Vector3d) rotationTowards()}. 8330 * <p> 8331 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(new Vector3d(), new Vector3d(dir).negate(), up).invert(), dest)</code> 8332 * 8333 * @see #rotateTowards(double, double, double, double, double, double, Matrix4x3d) 8334 * @see #rotationTowards(Vector3d, Vector3d) 8335 * 8336 * @param dir 8337 * the direction to rotate towards 8338 * @param up 8339 * the up vector 8340 * @param dest 8341 * will hold the result 8342 * @return dest 8343 */ 8344 public Matrix4x3d rotateTowards(ref Vector3d dir, Vector3d up, ref Matrix4x3d dest) { 8345 return rotateTowards(dir.x, dir.y, dir.z, up.x, up.y, up.z, dest); 8346 } 8347 8348 /** 8349 * Apply a model transformation to this matrix for a right-handed coordinate system, 8350 * that aligns the local <code>+Z</code> axis with <code>dir</code>. 8351 * <p> 8352 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8353 * then the new matrix will be <code>M * L</code>. So when transforming a 8354 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8355 * the lookat transformation will be applied first! 8356 * <p> 8357 * In order to set the matrix to a rotation transformation without post-multiplying it, 8358 * use {@link #rotationTowards(Vector3d, Vector3d) rotationTowards()}. 8359 * <p> 8360 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(new Vector3d(), new Vector3d(dir).negate(), up).invert())</code> 8361 * 8362 * @see #rotateTowards(double, double, double, double, double, double) 8363 * @see #rotationTowards(Vector3d, Vector3d) 8364 * 8365 * @param dir 8366 * the direction to orient towards 8367 * @param up 8368 * the up vector 8369 * @return this 8370 */ 8371 ref public Matrix4x3d rotateTowards(ref Vector3d dir, Vector3d up) return { 8372 rotateTowards(dir.x, dir.y, dir.z, up.x, up.y, up.z, this); 8373 return this; 8374 } 8375 8376 /** 8377 * Apply a model transformation to this matrix for a right-handed coordinate system, 8378 * that aligns the local <code>+Z</code> axis with <code>(dirX, dirY, dirZ)</code>. 8379 * <p> 8380 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8381 * then the new matrix will be <code>M * L</code>. So when transforming a 8382 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8383 * the lookat transformation will be applied first! 8384 * <p> 8385 * In order to set the matrix to a rotation transformation without post-multiplying it, 8386 * use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}. 8387 * <p> 8388 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invert())</code> 8389 * 8390 * @see #rotateTowards(Vector3d, Vector3d) 8391 * @see #rotationTowards(double, double, double, double, double, double) 8392 * 8393 * @param dirX 8394 * the x-coordinate of the direction to rotate towards 8395 * @param dirY 8396 * the y-coordinate of the direction to rotate towards 8397 * @param dirZ 8398 * the z-coordinate of the direction to rotate towards 8399 * @param upX 8400 * the x-coordinate of the up vector 8401 * @param upY 8402 * the y-coordinate of the up vector 8403 * @param upZ 8404 * the z-coordinate of the up vector 8405 * @return this 8406 */ 8407 ref public Matrix4x3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 8408 rotateTowards(dirX, dirY, dirZ, upX, upY, upZ, this); 8409 return this; 8410 } 8411 8412 /** 8413 * Apply a model transformation to this matrix for a right-handed coordinate system, 8414 * that aligns the local <code>+Z</code> axis with <code>(dirX, dirY, dirZ)</code> 8415 * and store the result in <code>dest</code>. 8416 * <p> 8417 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the lookat matrix, 8418 * then the new matrix will be <code>M * L</code>. So when transforming a 8419 * vector <code>v</code> with the new matrix by using <code>M * L * v</code>, 8420 * the lookat transformation will be applied first! 8421 * <p> 8422 * In order to set the matrix to a rotation transformation without post-multiplying it, 8423 * use {@link #rotationTowards(double, double, double, double, double, double) rotationTowards()}. 8424 * <p> 8425 * This method is equivalent to calling: <code>mul(new Matrix4x3d().lookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invert(), dest)</code> 8426 * 8427 * @see #rotateTowards(Vector3d, Vector3d) 8428 * @see #rotationTowards(double, double, double, double, double, double) 8429 * 8430 * @param dirX 8431 * the x-coordinate of the direction to rotate towards 8432 * @param dirY 8433 * the y-coordinate of the direction to rotate towards 8434 * @param dirZ 8435 * the z-coordinate of the direction to rotate towards 8436 * @param upX 8437 * the x-coordinate of the up vector 8438 * @param upY 8439 * the y-coordinate of the up vector 8440 * @param upZ 8441 * the z-coordinate of the up vector 8442 * @param dest 8443 * will hold the result 8444 * @return dest 8445 */ 8446 public Matrix4x3d rotateTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ, ref Matrix4x3d dest) { 8447 // Normalize direction 8448 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 8449 double ndirX = dirX * invDirLength; 8450 double ndirY = dirY * invDirLength; 8451 double ndirZ = dirZ * invDirLength; 8452 // left = up x direction 8453 double leftX, leftY, leftZ; 8454 leftX = upY * ndirZ - upZ * ndirY; 8455 leftY = upZ * ndirX - upX * ndirZ; 8456 leftZ = upX * ndirY - upY * ndirX; 8457 // normalize left 8458 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 8459 leftX *= invLeftLength; 8460 leftY *= invLeftLength; 8461 leftZ *= invLeftLength; 8462 // up = direction x left 8463 double upnX = ndirY * leftZ - ndirZ * leftY; 8464 double upnY = ndirZ * leftX - ndirX * leftZ; 8465 double upnZ = ndirX * leftY - ndirY * leftX; 8466 double rm00 = leftX; 8467 double rm01 = leftY; 8468 double rm02 = leftZ; 8469 double rm10 = upnX; 8470 double rm11 = upnY; 8471 double rm12 = upnZ; 8472 double rm20 = ndirX; 8473 double rm21 = ndirY; 8474 double rm22 = ndirZ; 8475 dest.m30 = m30; 8476 dest.m31 = m31; 8477 dest.m32 = m32; 8478 double nm00 = m00 * rm00 + m10 * rm01 + m20 * rm02; 8479 double nm01 = m01 * rm00 + m11 * rm01 + m21 * rm02; 8480 double nm02 = m02 * rm00 + m12 * rm01 + m22 * rm02; 8481 double nm10 = m00 * rm10 + m10 * rm11 + m20 * rm12; 8482 double nm11 = m01 * rm10 + m11 * rm11 + m21 * rm12; 8483 double nm12 = m02 * rm10 + m12 * rm11 + m22 * rm12; 8484 dest.m20 = m00 * rm20 + m10 * rm21 + m20 * rm22; 8485 dest.m21 = m01 * rm20 + m11 * rm21 + m21 * rm22; 8486 dest.m22 = m02 * rm20 + m12 * rm21 + m22 * rm22; 8487 dest.m00 = nm00; 8488 dest.m01 = nm01; 8489 dest.m02 = nm02; 8490 dest.m10 = nm10; 8491 dest.m11 = nm11; 8492 dest.m12 = nm12; 8493 dest.properties = properties & ~(PROPERTY_IDENTITY | PROPERTY_TRANSLATION); 8494 return dest; 8495 } 8496 8497 /** 8498 * Set this matrix to a model transformation for a right-handed coordinate system, 8499 * that aligns the local <code>-z</code> axis with <code>dir</code>. 8500 * <p> 8501 * In order to apply the rotation transformation to a previous existing transformation, 8502 * use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}. 8503 * <p> 8504 * This method is equivalent to calling: <code>setLookAt(new Vector3d(), new Vector3d(dir).negate(), up).invert()</code> 8505 * 8506 * @see #rotationTowards(Vector3d, Vector3d) 8507 * @see #rotateTowards(double, double, double, double, double, double) 8508 * 8509 * @param dir 8510 * the direction to orient the local -z axis towards 8511 * @param up 8512 * the up vector 8513 * @return this 8514 */ 8515 ref public Matrix4x3d rotationTowards(ref Vector3d dir, Vector3d up) return { 8516 return rotationTowards(dir.x, dir.y, dir.z, up.x, up.y, up.z); 8517 } 8518 8519 /** 8520 * Set this matrix to a model transformation for a right-handed coordinate system, 8521 * that aligns the local <code>-z</code> axis with <code>(dirX, dirY, dirZ)</code>. 8522 * <p> 8523 * In order to apply the rotation transformation to a previous existing transformation, 8524 * use {@link #rotateTowards(double, double, double, double, double, double) rotateTowards}. 8525 * <p> 8526 * This method is equivalent to calling: <code>setLookAt(0, 0, 0, -dirX, -dirY, -dirZ, upX, upY, upZ).invert()</code> 8527 * 8528 * @see #rotateTowards(Vector3d, Vector3d) 8529 * @see #rotationTowards(double, double, double, double, double, double) 8530 * 8531 * @param dirX 8532 * the x-coordinate of the direction to rotate towards 8533 * @param dirY 8534 * the y-coordinate of the direction to rotate towards 8535 * @param dirZ 8536 * the z-coordinate of the direction to rotate towards 8537 * @param upX 8538 * the x-coordinate of the up vector 8539 * @param upY 8540 * the y-coordinate of the up vector 8541 * @param upZ 8542 * the z-coordinate of the up vector 8543 * @return this 8544 */ 8545 ref public Matrix4x3d rotationTowards(double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 8546 // Normalize direction 8547 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 8548 double ndirX = dirX * invDirLength; 8549 double ndirY = dirY * invDirLength; 8550 double ndirZ = dirZ * invDirLength; 8551 // left = up x direction 8552 double leftX, leftY, leftZ; 8553 leftX = upY * ndirZ - upZ * ndirY; 8554 leftY = upZ * ndirX - upX * ndirZ; 8555 leftZ = upX * ndirY - upY * ndirX; 8556 // normalize left 8557 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 8558 leftX *= invLeftLength; 8559 leftY *= invLeftLength; 8560 leftZ *= invLeftLength; 8561 // up = direction x left 8562 double upnX = ndirY * leftZ - ndirZ * leftY; 8563 double upnY = ndirZ * leftX - ndirX * leftZ; 8564 double upnZ = ndirX * leftY - ndirY * leftX; 8565 this.m00 = leftX; 8566 this.m01 = leftY; 8567 this.m02 = leftZ; 8568 this.m10 = upnX; 8569 this.m11 = upnY; 8570 this.m12 = upnZ; 8571 this.m20 = ndirX; 8572 this.m21 = ndirY; 8573 this.m22 = ndirZ; 8574 this.m30 = 0.0; 8575 this.m31 = 0.0; 8576 this.m32 = 0.0; 8577 properties = PROPERTY_ORTHONORMAL; 8578 return this; 8579 } 8580 8581 /** 8582 * Set this matrix to a model transformation for a right-handed coordinate system, 8583 * that translates to the given <code>pos</code> and aligns the local <code>-z</code> 8584 * axis with <code>dir</code>. 8585 * <p> 8586 * This method is equivalent to calling: <code>translation(pos).rotateTowards(dir, up)</code> 8587 * 8588 * @see #translation(Vector3d) 8589 * @see #rotateTowards(Vector3d, Vector3d) 8590 * 8591 * @param pos 8592 * the position to translate to 8593 * @param dir 8594 * the direction to rotate towards 8595 * @param up 8596 * the up vector 8597 * @return this 8598 */ 8599 ref public Matrix4x3d translationRotateTowards(Vector3d pos, ref Vector3d dir, Vector3d up) return { 8600 return translationRotateTowards(pos.x, pos.y, pos.z, dir.x, dir.y, dir.z, up.x, up.y, up.z); 8601 } 8602 8603 /** 8604 * Set this matrix to a model transformation for a right-handed coordinate system, 8605 * that translates to the given <code>(posX, posY, posZ)</code> and aligns the local <code>-z</code> 8606 * axis with <code>(dirX, dirY, dirZ)</code>. 8607 * <p> 8608 * This method is equivalent to calling: <code>translation(posX, posY, posZ).rotateTowards(dirX, dirY, dirZ, upX, upY, upZ)</code> 8609 * 8610 * @see #translation(double, double, double) 8611 * @see #rotateTowards(double, double, double, double, double, double) 8612 * 8613 * @param posX 8614 * the x-coordinate of the position to translate to 8615 * @param posY 8616 * the y-coordinate of the position to translate to 8617 * @param posZ 8618 * the z-coordinate of the position to translate to 8619 * @param dirX 8620 * the x-coordinate of the direction to rotate towards 8621 * @param dirY 8622 * the y-coordinate of the direction to rotate towards 8623 * @param dirZ 8624 * the z-coordinate of the direction to rotate towards 8625 * @param upX 8626 * the x-coordinate of the up vector 8627 * @param upY 8628 * the y-coordinate of the up vector 8629 * @param upZ 8630 * the z-coordinate of the up vector 8631 * @return this 8632 */ 8633 ref public Matrix4x3d translationRotateTowards(double posX, double posY, double posZ, double dirX, double dirY, double dirZ, double upX, double upY, double upZ) return { 8634 // Normalize direction 8635 double invDirLength = Math.invsqrt(dirX * dirX + dirY * dirY + dirZ * dirZ); 8636 double ndirX = dirX * invDirLength; 8637 double ndirY = dirY * invDirLength; 8638 double ndirZ = dirZ * invDirLength; 8639 // left = up x direction 8640 double leftX, leftY, leftZ; 8641 leftX = upY * ndirZ - upZ * ndirY; 8642 leftY = upZ * ndirX - upX * ndirZ; 8643 leftZ = upX * ndirY - upY * ndirX; 8644 // normalize left 8645 double invLeftLength = Math.invsqrt(leftX * leftX + leftY * leftY + leftZ * leftZ); 8646 leftX *= invLeftLength; 8647 leftY *= invLeftLength; 8648 leftZ *= invLeftLength; 8649 // up = direction x left 8650 double upnX = ndirY * leftZ - ndirZ * leftY; 8651 double upnY = ndirZ * leftX - ndirX * leftZ; 8652 double upnZ = ndirX * leftY - ndirY * leftX; 8653 this.m00 = leftX; 8654 this.m01 = leftY; 8655 this.m02 = leftZ; 8656 this.m10 = upnX; 8657 this.m11 = upnY; 8658 this.m12 = upnZ; 8659 this.m20 = ndirX; 8660 this.m21 = ndirY; 8661 this.m22 = ndirZ; 8662 this.m30 = posX; 8663 this.m31 = posY; 8664 this.m32 = posZ; 8665 properties = PROPERTY_ORTHONORMAL; 8666 return this; 8667 } 8668 8669 public Vector3d getEulerAnglesZYX(ref Vector3d dest) { 8670 dest.x = Math.atan2(m12, m22); 8671 dest.y = Math.atan2(-m02, Math.sqrt(1.0 - m02 * m02)); 8672 dest.z = Math.atan2(m01, m00); 8673 return dest; 8674 } 8675 8676 public Vector3d getEulerAnglesXYZ(ref Vector3d dest) { 8677 dest.x = Math.atan2(-m21, m22); 8678 dest.y = Math.atan2(m20, Math.sqrt(1.0 - m20 * m20)); 8679 dest.z = Math.atan2(-m10, m00); 8680 return dest; 8681 } 8682 8683 /** 8684 * Apply an oblique projection transformation to this matrix with the given values for <code>a</code> and 8685 * <code>b</code>. 8686 * <p> 8687 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the oblique transformation matrix, 8688 * then the new matrix will be <code>M * O</code>. So when transforming a 8689 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 8690 * oblique transformation will be applied first! 8691 * <p> 8692 * The oblique transformation is defined as: 8693 * <pre> 8694 * x' = x + a*z 8695 * y' = y + a*z 8696 * z' = z 8697 * </pre> 8698 * or in matrix form: 8699 * <pre> 8700 * 1 0 a 0 8701 * 0 1 b 0 8702 * 0 0 1 0 8703 * </pre> 8704 * 8705 * @param a 8706 * the value for the z factor that applies to x 8707 * @param b 8708 * the value for the z factor that applies to y 8709 * @return this 8710 */ 8711 ref public Matrix4x3d obliqueZ(double a, double b) return { 8712 this.m20 = m00 * a + m10 * b + m20; 8713 this.m21 = m01 * a + m11 * b + m21; 8714 this.m22 = m02 * a + m12 * b + m22; 8715 this.properties = 0; 8716 return this; 8717 } 8718 8719 /** 8720 * Apply an oblique projection transformation to this matrix with the given values for <code>a</code> and 8721 * <code>b</code> and store the result in <code>dest</code>. 8722 * <p> 8723 * If <code>M</code> is <code>this</code> matrix and <code>O</code> the oblique transformation matrix, 8724 * then the new matrix will be <code>M * O</code>. So when transforming a 8725 * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the 8726 * oblique transformation will be applied first! 8727 * <p> 8728 * The oblique transformation is defined as: 8729 * <pre> 8730 * x' = x + a*z 8731 * y' = y + a*z 8732 * z' = z 8733 * </pre> 8734 * or in matrix form: 8735 * <pre> 8736 * 1 0 a 0 8737 * 0 1 b 0 8738 * 0 0 1 0 8739 * </pre> 8740 * 8741 * @param a 8742 * the value for the z factor that applies to x 8743 * @param b 8744 * the value for the z factor that applies to y 8745 * @param dest 8746 * will hold the result 8747 * @return dest 8748 */ 8749 public Matrix4x3d obliqueZ(double a, double b, ref Matrix4x3d dest) { 8750 dest.m00 = m00; 8751 dest.m01 = m01; 8752 dest.m02 = m02; 8753 dest.m10 = m10; 8754 dest.m11 = m11; 8755 dest.m12 = m12; 8756 dest.m20 = m00 * a + m10 * b + m20; 8757 dest.m21 = m01 * a + m11 * b + m21; 8758 dest.m22 = m02 * a + m12 * b + m22; 8759 dest.m30 = m30; 8760 dest.m31 = m31; 8761 dest.m32 = m32; 8762 dest.properties = 0; 8763 return dest; 8764 } 8765 8766 /** 8767 * Multiply <code>this</code> by the matrix 8768 * <pre> 8769 * 1 0 0 0 8770 * 0 0 1 0 8771 * 0 1 0 0 8772 * </pre> 8773 * 8774 * @return this 8775 */ 8776 ref public Matrix4x3d mapXZY() return { 8777 mapXZY(this); 8778 return this; 8779 } 8780 public Matrix4x3d mapXZY(ref Matrix4x3d dest) { 8781 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8782 return dest._m00(m00)._m01(m01)._m02(m02)._m10(m20)._m11(m21)._m12(m22)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8783 } 8784 /** 8785 * Multiply <code>this</code> by the matrix 8786 * <pre> 8787 * 1 0 0 0 8788 * 0 0 -1 0 8789 * 0 1 0 0 8790 * </pre> 8791 * 8792 * @return this 8793 */ 8794 ref public Matrix4x3d mapXZnY() return { 8795 mapXZnY(this); 8796 return this; 8797 } 8798 public Matrix4x3d mapXZnY(ref Matrix4x3d dest) { 8799 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8800 return dest._m00(m00)._m01(m01)._m02(m02)._m10(m20)._m11(m21)._m12(m22)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8801 } 8802 /** 8803 * Multiply <code>this</code> by the matrix 8804 * <pre> 8805 * 1 0 0 0 8806 * 0 -1 0 0 8807 * 0 0 -1 0 8808 * </pre> 8809 * 8810 * @return this 8811 */ 8812 ref public Matrix4x3d mapXnYnZ() return { 8813 mapXnYnZ(this); 8814 return this; 8815 } 8816 public Matrix4x3d mapXnYnZ(ref Matrix4x3d dest) { 8817 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8818 } 8819 /** 8820 * Multiply <code>this</code> by the matrix 8821 * <pre> 8822 * 1 0 0 0 8823 * 0 0 1 0 8824 * 0 -1 0 0 8825 * </pre> 8826 * 8827 * @return this 8828 */ 8829 ref public Matrix4x3d mapXnZY() return { 8830 mapXnZY(this); 8831 return this; 8832 } 8833 public Matrix4x3d mapXnZY(ref Matrix4x3d dest) { 8834 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8835 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8836 } 8837 /** 8838 * Multiply <code>this</code> by the matrix 8839 * <pre> 8840 * 1 0 0 0 8841 * 0 0 -1 0 8842 * 0 -1 0 0 8843 * </pre> 8844 * 8845 * @return this 8846 */ 8847 ref public Matrix4x3d mapXnZnY() return { 8848 mapXnZnY(this); 8849 return this; 8850 } 8851 public Matrix4x3d mapXnZnY(ref Matrix4x3d dest) { 8852 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 8853 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8854 } 8855 /** 8856 * Multiply <code>this</code> by the matrix 8857 * <pre> 8858 * 0 1 0 0 8859 * 1 0 0 0 8860 * 0 0 1 0 8861 * </pre> 8862 * 8863 * @return this 8864 */ 8865 ref public Matrix4x3d mapYXZ() return { 8866 mapYXZ(this); 8867 return this; 8868 } 8869 public Matrix4x3d mapYXZ(ref Matrix4x3d dest) { 8870 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8871 return dest._m00(m10)._m01(m11)._m02(m12)._m10(m00)._m11(m01)._m12(m02)._m20(m20)._m21(m21)._m22(m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8872 } 8873 /** 8874 * Multiply <code>this</code> by the matrix 8875 * <pre> 8876 * 0 1 0 0 8877 * 1 0 0 0 8878 * 0 0 -1 0 8879 * </pre> 8880 * 8881 * @return this 8882 */ 8883 ref public Matrix4x3d mapYXnZ() return { 8884 mapYXnZ(this); 8885 return this; 8886 } 8887 public Matrix4x3d mapYXnZ(ref Matrix4x3d dest) { 8888 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8889 return dest._m00(m10)._m01(m11)._m02(m12)._m10(m00)._m11(m01)._m12(m02)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8890 } 8891 /** 8892 * Multiply <code>this</code> by the matrix 8893 * <pre> 8894 * 0 0 1 0 8895 * 1 0 0 0 8896 * 0 1 0 0 8897 * </pre> 8898 * 8899 * @return this 8900 */ 8901 ref public Matrix4x3d mapYZX() return { 8902 mapYZX(this); 8903 return this; 8904 } 8905 public Matrix4x3d mapYZX(ref Matrix4x3d dest) { 8906 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8907 return dest._m00(m10)._m01(m11)._m02(m12)._m10(m20)._m11(m21)._m12(m22)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8908 } 8909 /** 8910 * Multiply <code>this</code> by the matrix 8911 * <pre> 8912 * 0 0 -1 0 8913 * 1 0 0 0 8914 * 0 1 0 0 8915 * </pre> 8916 * 8917 * @return this 8918 */ 8919 ref public Matrix4x3d mapYZnX() return { 8920 mapYZnX(this); 8921 return this; 8922 } 8923 public Matrix4x3d mapYZnX(ref Matrix4x3d dest) { 8924 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8925 return dest._m00(m10)._m01(m11)._m02(m12)._m10(m20)._m11(m21)._m12(m22)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8926 } 8927 /** 8928 * Multiply <code>this</code> by the matrix 8929 * <pre> 8930 * 0 -1 0 0 8931 * 1 0 0 0 8932 * 0 0 1 0 8933 * </pre> 8934 * 8935 * @return this 8936 */ 8937 ref public Matrix4x3d mapYnXZ() return { 8938 mapYnXZ(this); 8939 return this; 8940 } 8941 public Matrix4x3d mapYnXZ(ref Matrix4x3d dest) { 8942 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8943 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m20)._m21(m21)._m22(m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8944 } 8945 /** 8946 * Multiply <code>this</code> by the matrix 8947 * <pre> 8948 * 0 -1 0 0 8949 * 1 0 0 0 8950 * 0 0 -1 0 8951 * </pre> 8952 * 8953 * @return this 8954 */ 8955 ref public Matrix4x3d mapYnXnZ() return { 8956 mapYnXnZ(this); 8957 return this; 8958 } 8959 public Matrix4x3d mapYnXnZ(ref Matrix4x3d dest) { 8960 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8961 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8962 } 8963 /** 8964 * Multiply <code>this</code> by the matrix 8965 * <pre> 8966 * 0 0 1 0 8967 * 1 0 0 0 8968 * 0 -1 0 0 8969 * </pre> 8970 * 8971 * @return this 8972 */ 8973 ref public Matrix4x3d mapYnZX() return { 8974 mapYnZX(this); 8975 return this; 8976 } 8977 public Matrix4x3d mapYnZX(ref Matrix4x3d dest) { 8978 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8979 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8980 } 8981 /** 8982 * Multiply <code>this</code> by the matrix 8983 * <pre> 8984 * 0 0 -1 0 8985 * 1 0 0 0 8986 * 0 -1 0 0 8987 * </pre> 8988 * 8989 * @return this 8990 */ 8991 ref public Matrix4x3d mapYnZnX() return { 8992 mapYnZnX(this); 8993 return this; 8994 } 8995 public Matrix4x3d mapYnZnX(ref Matrix4x3d dest) { 8996 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 8997 return dest._m00(m10)._m01(m11)._m02(m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 8998 } 8999 /** 9000 * Multiply <code>this</code> by the matrix 9001 * <pre> 9002 * 0 1 0 0 9003 * 0 0 1 0 9004 * 1 0 0 0 9005 * </pre> 9006 * 9007 * @return this 9008 */ 9009 ref public Matrix4x3d mapZXY() return { 9010 mapZXY(this); 9011 return this; 9012 } 9013 public Matrix4x3d mapZXY(ref Matrix4x3d dest) { 9014 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9015 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9016 return dest._m00(m20)._m01(m21)._m02(m22)._m10(m00)._m11(m01)._m12(m02)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9017 } 9018 /** 9019 * Multiply <code>this</code> by the matrix 9020 * <pre> 9021 * 0 1 0 0 9022 * 0 0 -1 0 9023 * 1 0 0 0 9024 * </pre> 9025 * 9026 * @return this 9027 */ 9028 ref public Matrix4x3d mapZXnY() return { 9029 mapZXnY(this); 9030 return this; 9031 } 9032 public Matrix4x3d mapZXnY(ref Matrix4x3d dest) { 9033 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9034 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9035 return dest._m00(m20)._m01(m21)._m02(m22)._m10(m00)._m11(m01)._m12(m02)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9036 } 9037 /** 9038 * Multiply <code>this</code> by the matrix 9039 * <pre> 9040 * 0 0 1 0 9041 * 0 1 0 0 9042 * 1 0 0 0 9043 * </pre> 9044 * 9045 * @return this 9046 */ 9047 ref public Matrix4x3d mapZYX() return { 9048 mapZYX(this); 9049 return this; 9050 } 9051 public Matrix4x3d mapZYX(ref Matrix4x3d dest) { 9052 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9053 return dest._m00(m20)._m01(m21)._m02(m22)._m10(m10)._m11(m11)._m12(m12)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9054 } 9055 /** 9056 * Multiply <code>this</code> by the matrix 9057 * <pre> 9058 * 0 0 -1 0 9059 * 0 1 0 0 9060 * 1 0 0 0 9061 * </pre> 9062 * 9063 * @return this 9064 */ 9065 ref public Matrix4x3d mapZYnX() return { 9066 mapZYnX(this); 9067 return this; 9068 } 9069 public Matrix4x3d mapZYnX(ref Matrix4x3d dest) { 9070 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9071 return dest._m00(m20)._m01(m21)._m02(m22)._m10(m10)._m11(m11)._m12(m12)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9072 } 9073 /** 9074 * Multiply <code>this</code> by the matrix 9075 * <pre> 9076 * 0 -1 0 0 9077 * 0 0 1 0 9078 * 1 0 0 0 9079 * </pre> 9080 * 9081 * @return this 9082 */ 9083 ref public Matrix4x3d mapZnXY() return { 9084 mapZnXY(this); 9085 return this; 9086 } 9087 public Matrix4x3d mapZnXY(ref Matrix4x3d dest) { 9088 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9089 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9090 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9091 } 9092 /** 9093 * Multiply <code>this</code> by the matrix 9094 * <pre> 9095 * 0 -1 0 0 9096 * 0 0 -1 0 9097 * 1 0 0 0 9098 * </pre> 9099 * 9100 * @return this 9101 */ 9102 ref public Matrix4x3d mapZnXnY() return { 9103 mapZnXnY(this); 9104 return this; 9105 } 9106 public Matrix4x3d mapZnXnY(ref Matrix4x3d dest) { 9107 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9108 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9109 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9110 } 9111 /** 9112 * Multiply <code>this</code> by the matrix 9113 * <pre> 9114 * 0 0 1 0 9115 * 0 -1 0 0 9116 * 1 0 0 0 9117 * </pre> 9118 * 9119 * @return this 9120 */ 9121 ref public Matrix4x3d mapZnYX() return { 9122 mapZnYX(this); 9123 return this; 9124 } 9125 public Matrix4x3d mapZnYX(ref Matrix4x3d dest) { 9126 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9127 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9128 } 9129 /** 9130 * Multiply <code>this</code> by the matrix 9131 * <pre> 9132 * 0 0 -1 0 9133 * 0 -1 0 0 9134 * 1 0 0 0 9135 * </pre> 9136 * 9137 * @return this 9138 */ 9139 ref public Matrix4x3d mapZnYnX() return { 9140 mapZnYnX(this); 9141 return this; 9142 } 9143 public Matrix4x3d mapZnYnX(ref Matrix4x3d dest) { 9144 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9145 return dest._m00(m20)._m01(m21)._m02(m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9146 } 9147 /** 9148 * Multiply <code>this</code> by the matrix 9149 * <pre> 9150 * -1 0 0 0 9151 * 0 1 0 0 9152 * 0 0 -1 0 9153 * </pre> 9154 * 9155 * @return this 9156 */ 9157 ref public Matrix4x3d mapnXYnZ() return { 9158 mapnXYnZ(this); 9159 return this; 9160 } 9161 public Matrix4x3d mapnXYnZ(ref Matrix4x3d dest) { 9162 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m10)._m11(m11)._m12(m12)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9163 } 9164 /** 9165 * Multiply <code>this</code> by the matrix 9166 * <pre> 9167 * -1 0 0 0 9168 * 0 0 1 0 9169 * 0 1 0 0 9170 * </pre> 9171 * 9172 * @return this 9173 */ 9174 ref public Matrix4x3d mapnXZY() return { 9175 mapnXZY(this); 9176 return this; 9177 } 9178 public Matrix4x3d mapnXZY(ref Matrix4x3d dest) { 9179 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9180 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m20)._m11(m21)._m12(m22)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9181 } 9182 /** 9183 * Multiply <code>this</code> by the matrix 9184 * <pre> 9185 * -1 0 0 0 9186 * 0 0 -1 0 9187 * 0 1 0 0 9188 * </pre> 9189 * 9190 * @return this 9191 */ 9192 ref public Matrix4x3d mapnXZnY() return { 9193 mapnXZnY(this); 9194 return this; 9195 } 9196 public Matrix4x3d mapnXZnY(ref Matrix4x3d dest) { 9197 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9198 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m20)._m11(m21)._m12(m22)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9199 } 9200 /** 9201 * Multiply <code>this</code> by the matrix 9202 * <pre> 9203 * -1 0 0 0 9204 * 0 -1 0 0 9205 * 0 0 1 0 9206 * </pre> 9207 * 9208 * @return this 9209 */ 9210 ref public Matrix4x3d mapnXnYZ() return { 9211 mapnXnYZ(this); 9212 return this; 9213 } 9214 public Matrix4x3d mapnXnYZ(ref Matrix4x3d dest) { 9215 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m20)._m21(m21)._m22(m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9216 } 9217 /** 9218 * Multiply <code>this</code> by the matrix 9219 * <pre> 9220 * -1 0 0 0 9221 * 0 -1 0 0 9222 * 0 0 -1 0 9223 * </pre> 9224 * 9225 * @return this 9226 */ 9227 ref public Matrix4x3d mapnXnYnZ() return { 9228 mapnXnYnZ(this); 9229 return this; 9230 } 9231 public Matrix4x3d mapnXnYnZ(ref Matrix4x3d dest) { 9232 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9233 } 9234 /** 9235 * Multiply <code>this</code> by the matrix 9236 * <pre> 9237 * -1 0 0 0 9238 * 0 0 1 0 9239 * 0 -1 0 0 9240 * </pre> 9241 * 9242 * @return this 9243 */ 9244 ref public Matrix4x3d mapnXnZY() return { 9245 mapnXnZY(this); 9246 return this; 9247 } 9248 public Matrix4x3d mapnXnZY(ref Matrix4x3d dest) { 9249 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9250 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9251 } 9252 /** 9253 * Multiply <code>this</code> by the matrix 9254 * <pre> 9255 * -1 0 0 0 9256 * 0 0 -1 0 9257 * 0 -1 0 0 9258 * </pre> 9259 * 9260 * @return this 9261 */ 9262 ref public Matrix4x3d mapnXnZnY() return { 9263 mapnXnZnY(this); 9264 return this; 9265 } 9266 public Matrix4x3d mapnXnZnY(ref Matrix4x3d dest) { 9267 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9268 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9269 } 9270 /** 9271 * Multiply <code>this</code> by the matrix 9272 * <pre> 9273 * 0 1 0 0 9274 * -1 0 0 0 9275 * 0 0 1 0 9276 * </pre> 9277 * 9278 * @return this 9279 */ 9280 ref public Matrix4x3d mapnYXZ() return { 9281 mapnYXZ(this); 9282 return this; 9283 } 9284 public Matrix4x3d mapnYXZ(ref Matrix4x3d dest) { 9285 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9286 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m00)._m11(m01)._m12(m02)._m20(m20)._m21(m21)._m22(m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9287 } 9288 /** 9289 * Multiply <code>this</code> by the matrix 9290 * <pre> 9291 * 0 1 0 0 9292 * -1 0 0 0 9293 * 0 0 -1 0 9294 * </pre> 9295 * 9296 * @return this 9297 */ 9298 ref public Matrix4x3d mapnYXnZ() return { 9299 mapnYXnZ(this); 9300 return this; 9301 } 9302 public Matrix4x3d mapnYXnZ(ref Matrix4x3d dest) { 9303 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9304 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m00)._m11(m01)._m12(m02)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9305 } 9306 /** 9307 * Multiply <code>this</code> by the matrix 9308 * <pre> 9309 * 0 0 1 0 9310 * -1 0 0 0 9311 * 0 1 0 0 9312 * </pre> 9313 * 9314 * @return this 9315 */ 9316 ref public Matrix4x3d mapnYZX() return { 9317 mapnYZX(this); 9318 return this; 9319 } 9320 public Matrix4x3d mapnYZX(ref Matrix4x3d dest) { 9321 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9322 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m20)._m11(m21)._m12(m22)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9323 } 9324 /** 9325 * Multiply <code>this</code> by the matrix 9326 * <pre> 9327 * 0 0 -1 0 9328 * -1 0 0 0 9329 * 0 1 0 0 9330 * </pre> 9331 * 9332 * @return this 9333 */ 9334 ref public Matrix4x3d mapnYZnX() return { 9335 mapnYZnX(this); 9336 return this; 9337 } 9338 public Matrix4x3d mapnYZnX(ref Matrix4x3d dest) { 9339 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9340 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(m20)._m11(m21)._m12(m22)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9341 } 9342 /** 9343 * Multiply <code>this</code> by the matrix 9344 * <pre> 9345 * 0 -1 0 0 9346 * -1 0 0 0 9347 * 0 0 1 0 9348 * </pre> 9349 * 9350 * @return this 9351 */ 9352 ref public Matrix4x3d mapnYnXZ() return { 9353 mapnYnXZ(this); 9354 return this; 9355 } 9356 public Matrix4x3d mapnYnXZ(ref Matrix4x3d dest) { 9357 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9358 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m20)._m21(m21)._m22(m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9359 } 9360 /** 9361 * Multiply <code>this</code> by the matrix 9362 * <pre> 9363 * 0 -1 0 0 9364 * -1 0 0 0 9365 * 0 0 -1 0 9366 * </pre> 9367 * 9368 * @return this 9369 */ 9370 ref public Matrix4x3d mapnYnXnZ() return { 9371 mapnYnXnZ(this); 9372 return this; 9373 } 9374 public Matrix4x3d mapnYnXnZ(ref Matrix4x3d dest) { 9375 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9376 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9377 } 9378 /** 9379 * Multiply <code>this</code> by the matrix 9380 * <pre> 9381 * 0 0 1 0 9382 * -1 0 0 0 9383 * 0 -1 0 0 9384 * </pre> 9385 * 9386 * @return this 9387 */ 9388 ref public Matrix4x3d mapnYnZX() return { 9389 mapnYnZX(this); 9390 return this; 9391 } 9392 public Matrix4x3d mapnYnZX(ref Matrix4x3d dest) { 9393 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9394 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9395 } 9396 /** 9397 * Multiply <code>this</code> by the matrix 9398 * <pre> 9399 * 0 0 -1 0 9400 * -1 0 0 0 9401 * 0 -1 0 0 9402 * </pre> 9403 * 9404 * @return this 9405 */ 9406 ref public Matrix4x3d mapnYnZnX() return { 9407 mapnYnZnX(this); 9408 return this; 9409 } 9410 public Matrix4x3d mapnYnZnX(ref Matrix4x3d dest) { 9411 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9412 return dest._m00(-m10)._m01(-m11)._m02(-m12)._m10(-m20)._m11(-m21)._m12(-m22)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9413 } 9414 /** 9415 * Multiply <code>this</code> by the matrix 9416 * <pre> 9417 * 0 1 0 0 9418 * 0 0 1 0 9419 * -1 0 0 0 9420 * </pre> 9421 * 9422 * @return this 9423 */ 9424 ref public Matrix4x3d mapnZXY() return { 9425 mapnZXY(this); 9426 return this; 9427 } 9428 public Matrix4x3d mapnZXY(ref Matrix4x3d dest) { 9429 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9430 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9431 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m00)._m11(m01)._m12(m02)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9432 } 9433 /** 9434 * Multiply <code>this</code> by the matrix 9435 * <pre> 9436 * 0 1 0 0 9437 * 0 0 -1 0 9438 * -1 0 0 0 9439 * </pre> 9440 * 9441 * @return this 9442 */ 9443 ref public Matrix4x3d mapnZXnY() return { 9444 mapnZXnY(this); 9445 return this; 9446 } 9447 public Matrix4x3d mapnZXnY(ref Matrix4x3d dest) { 9448 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9449 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9450 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m00)._m11(m01)._m12(m02)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9451 } 9452 /** 9453 * Multiply <code>this</code> by the matrix 9454 * <pre> 9455 * 0 0 1 0 9456 * 0 1 0 0 9457 * -1 0 0 0 9458 * </pre> 9459 * 9460 * @return this 9461 */ 9462 ref public Matrix4x3d mapnZYX() return { 9463 mapnZYX(this); 9464 return this; 9465 } 9466 public Matrix4x3d mapnZYX(ref Matrix4x3d dest) { 9467 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9468 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m10)._m11(m11)._m12(m12)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9469 } 9470 /** 9471 * Multiply <code>this</code> by the matrix 9472 * <pre> 9473 * 0 0 -1 0 9474 * 0 1 0 0 9475 * -1 0 0 0 9476 * </pre> 9477 * 9478 * @return this 9479 */ 9480 ref public Matrix4x3d mapnZYnX() return { 9481 mapnZYnX(this); 9482 return this; 9483 } 9484 public Matrix4x3d mapnZYnX(ref Matrix4x3d dest) { 9485 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9486 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(m10)._m11(m11)._m12(m12)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9487 } 9488 /** 9489 * Multiply <code>this</code> by the matrix 9490 * <pre> 9491 * 0 -1 0 0 9492 * 0 0 1 0 9493 * -1 0 0 0 9494 * </pre> 9495 * 9496 * @return this 9497 */ 9498 ref public Matrix4x3d mapnZnXY() return { 9499 mapnZnXY(this); 9500 return this; 9501 } 9502 public Matrix4x3d mapnZnXY(ref Matrix4x3d dest) { 9503 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9504 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9505 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(m10)._m21(m11)._m22(m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9506 } 9507 /** 9508 * Multiply <code>this</code> by the matrix 9509 * <pre> 9510 * 0 -1 0 0 9511 * 0 0 -1 0 9512 * -1 0 0 0 9513 * </pre> 9514 * 9515 * @return this 9516 */ 9517 ref public Matrix4x3d mapnZnXnY() return { 9518 mapnZnXnY(this); 9519 return this; 9520 } 9521 public Matrix4x3d mapnZnXnY(ref Matrix4x3d dest) { 9522 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9523 double m10 = this.m10, m11 = this.m11, m12 = this.m12; 9524 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m00)._m11(-m01)._m12(-m02)._m20(-m10)._m21(-m11)._m22(-m12)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9525 } 9526 /** 9527 * Multiply <code>this</code> by the matrix 9528 * <pre> 9529 * 0 0 1 0 9530 * 0 -1 0 0 9531 * -1 0 0 0 9532 * </pre> 9533 * 9534 * @return this 9535 */ 9536 ref public Matrix4x3d mapnZnYX() return { 9537 mapnZnYX(this); 9538 return this; 9539 } 9540 public Matrix4x3d mapnZnYX(ref Matrix4x3d dest) { 9541 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9542 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m00)._m21(m01)._m22(m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9543 } 9544 /** 9545 * Multiply <code>this</code> by the matrix 9546 * <pre> 9547 * 0 0 -1 0 9548 * 0 -1 0 0 9549 * -1 0 0 0 9550 * </pre> 9551 * 9552 * @return this 9553 */ 9554 ref public Matrix4x3d mapnZnYnX() return { 9555 mapnZnYnX(this); 9556 return this; 9557 } 9558 public Matrix4x3d mapnZnYnX(ref Matrix4x3d dest) { 9559 double m00 = this.m00, m01 = this.m01, m02 = this.m02; 9560 return dest._m00(-m20)._m01(-m21)._m02(-m22)._m10(-m10)._m11(-m11)._m12(-m12)._m20(-m00)._m21(-m01)._m22(-m02)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9561 } 9562 9563 /** 9564 * Multiply <code>this</code> by the matrix 9565 * <pre> 9566 * -1 0 0 0 9567 * 0 1 0 0 9568 * 0 0 1 0 9569 * </pre> 9570 * 9571 * @return this 9572 */ 9573 ref public Matrix4x3d negateX() return { 9574 return _m00(-m00)._m01(-m01)._m02(-m02)._properties(properties & PROPERTY_ORTHONORMAL); 9575 } 9576 public Matrix4x3d negateX(ref Matrix4x3d dest) { 9577 return dest._m00(-m00)._m01(-m01)._m02(-m02)._m10(m10)._m11(m11)._m12(m12)._m20(m20)._m21(m21)._m22(m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9578 } 9579 9580 /** 9581 * Multiply <code>this</code> by the matrix 9582 * <pre> 9583 * 1 0 0 0 9584 * 0 -1 0 0 9585 * 0 0 1 0 9586 * </pre> 9587 * 9588 * @return this 9589 */ 9590 ref public Matrix4x3d negateY() return { 9591 return _m10(-m10)._m11(-m11)._m12(-m12)._properties(properties & PROPERTY_ORTHONORMAL); 9592 } 9593 public Matrix4x3d negateY(ref Matrix4x3d dest) { 9594 return dest._m00(m00)._m01(m01)._m02(m02)._m10(-m10)._m11(-m11)._m12(-m12)._m20(m20)._m21(m21)._m22(m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9595 } 9596 9597 /** 9598 * Multiply <code>this</code> by the matrix 9599 * <pre> 9600 * 1 0 0 0 9601 * 0 1 0 0 9602 * 0 0 -1 0 9603 * </pre> 9604 * 9605 * @return this 9606 */ 9607 ref public Matrix4x3d negateZ() return { 9608 return _m20(-m20)._m21(-m21)._m22(-m22)._properties(properties & PROPERTY_ORTHONORMAL); 9609 } 9610 public Matrix4x3d negateZ(ref Matrix4x3d dest) { 9611 return dest._m00(m00)._m01(m01)._m02(m02)._m10(m10)._m11(m11)._m12(m12)._m20(-m20)._m21(-m21)._m22(-m22)._m30(m30)._m31(m31)._m32(m32)._properties(properties & PROPERTY_ORTHONORMAL); 9612 } 9613 9614 public bool isFinite() { 9615 return Math.isFinite(m00) && Math.isFinite(m01) && Math.isFinite(m02) && 9616 Math.isFinite(m10) && Math.isFinite(m11) && Math.isFinite(m12) && 9617 Math.isFinite(m20) && Math.isFinite(m21) && Math.isFinite(m22) && 9618 Math.isFinite(m30) && Math.isFinite(m31) && Math.isFinite(m32); 9619 } 9620 }